diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp --- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp +++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp @@ -27,16 +27,6 @@ class ASTWalker : public RecursiveASTVisitor { DeclCallback Callback; - bool handleTemplateName(SourceLocation Loc, TemplateName TN) { - // For using-templates, only mark the alias. - if (auto *USD = TN.getAsUsingShadowDecl()) { - report(Loc, USD); - return true; - } - report(Loc, TN.getAsTemplateDecl()); - return true; - } - void report(SourceLocation Loc, NamedDecl *ND, RefType RT = RefType::Explicit) { if (!ND || Loc.isInvalid()) @@ -44,9 +34,22 @@ Callback(Loc, *cast(ND->getCanonicalDecl()), RT); } + NamedDecl *resolveTemplateName(TemplateName TN) { + // For using-templates, only mark the alias. + if (auto *USD = TN.getAsUsingShadowDecl()) + return USD; + return TN.getAsTemplateDecl(); + } NamedDecl *resolveType(QualType Type) { if (Type->isPointerType()) Type = Type->getPointeeType(); + if (const auto *TT = Type->getAs()) + return TT->getDecl(); + if (const auto *UT = Type->getAs()) + return UT->getFoundDecl(); + if (const auto *TST = Type->getAs()) + return resolveTemplateName(TST->getTemplateName()); + return Type->getAsRecordDecl(); } @@ -126,15 +129,17 @@ bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) { // FIXME: Handle explicit specializations. - return handleTemplateName(TL.getTemplateNameLoc(), - TL.getTypePtr()->getTemplateName()); + report(TL.getTemplateNameLoc(), + resolveTemplateName(TL.getTypePtr()->getTemplateName())); + return true; } bool VisitDeducedTemplateSpecializationTypeLoc( DeducedTemplateSpecializationTypeLoc TL) { // FIXME: Handle specializations. - return handleTemplateName(TL.getTemplateNameLoc(), - TL.getTypePtr()->getTemplateName()); + report(TL.getTemplateNameLoc(), + resolveTemplateName(TL.getTypePtr()->getTemplateName())); + return true; } bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &TL) { @@ -142,9 +147,11 @@ // Template-template parameters require special attention, as there's no // TemplateNameLoc. if (Arg.getKind() == TemplateArgument::Template || - Arg.getKind() == TemplateArgument::TemplateExpansion) - return handleTemplateName(TL.getLocation(), - Arg.getAsTemplateOrTemplatePattern()); + Arg.getKind() == TemplateArgument::TemplateExpansion) { + report(TL.getLocation(), + resolveTemplateName(Arg.getAsTemplateOrTemplatePattern())); + return true; + } return RecursiveASTVisitor::TraverseTemplateArgumentLoc(TL); } }; diff --git a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp --- a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp +++ b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp @@ -210,6 +210,19 @@ }; struct Foo {};)cpp", "void test(unique_ptr &V) { V.^release(); }"); + // Respect the sugar type (typedef, using-type). + testWalk(R"cpp( + namespace ns { struct Foo { int a; }; } + using $explicit^Bar = ns::Foo;)cpp", + "void test(Bar b) { b.^a; }"); + testWalk(R"cpp( + namespace ns { struct Foo { int a; }; } + using ns::$explicit^Foo;)cpp", + "void test(Foo b) { b.^a; }"); + testWalk(R"cpp( + namespace ns { template struct Foo { int a; }; } + using ns::$explicit^Foo;)cpp", + "void k(Foo b) { b.^a; }"); } TEST(WalkAST, ConstructExprs) { diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2592,6 +2592,7 @@ /// This will check for a TypedefType by removing any existing sugar /// until it reaches a TypedefType or a non-sugared type. template <> const TypedefType *Type::getAs() const; +template <> const UsingType *Type::getAs() const; /// This will check for a TemplateSpecializationType by removing any /// existing sugar until it reaches a TemplateSpecializationType or a diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -524,6 +524,10 @@ return getAsSugar(this); } +template <> const UsingType *Type::getAs() const { + return getAsSugar(this); +} + template <> const TemplateSpecializationType *Type::getAs() const { return getAsSugar(this); }