Skip to content

Commit

Permalink
[include-cleaner] Treat references to nested types implicit
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D149948
  • Loading branch information
kadircet committed May 23, 2023
1 parent 2938f9b commit cce7b81
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 7 deletions.
28 changes: 21 additions & 7 deletions clang-tools-extra/include-cleaner/lib/WalkAST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,31 +218,45 @@ class ASTWalker : public RecursiveASTVisitor<ASTWalker> {
}

// TypeLoc visitors.
void reportType(SourceLocation RefLoc, NamedDecl *ND) {
// Reporting explicit references to types nested inside classes can cause
// issues, e.g. a type accessed through a derived class shouldn't require
// inclusion of the base.
// Hence we report all such references as implicit. The code must spell the
// outer type-location somewhere, which will trigger an explicit reference
// and per IWYS, it's that spelling's responsibility to bring in necessary
// declarations.
RefType RT = llvm::isa<RecordDecl>(ND->getDeclContext())
? RefType::Implicit
: RefType::Explicit;
return report(RefLoc, ND, RT);
}

bool VisitUsingTypeLoc(UsingTypeLoc TL) {
report(TL.getNameLoc(), TL.getFoundDecl());
reportType(TL.getNameLoc(), TL.getFoundDecl());
return true;
}

bool VisitTagTypeLoc(TagTypeLoc TTL) {
report(TTL.getNameLoc(), TTL.getDecl());
reportType(TTL.getNameLoc(), TTL.getDecl());
return true;
}

bool VisitTypedefTypeLoc(TypedefTypeLoc TTL) {
report(TTL.getNameLoc(), TTL.getTypedefNameDecl());
reportType(TTL.getNameLoc(), TTL.getTypedefNameDecl());
return true;
}

bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
report(TL.getTemplateNameLoc(),
getMostRelevantTemplatePattern(TL.getTypePtr()));
reportType(TL.getTemplateNameLoc(),
getMostRelevantTemplatePattern(TL.getTypePtr()));
return true;
}

bool VisitDeducedTemplateSpecializationTypeLoc(
DeducedTemplateSpecializationTypeLoc TL) {
report(TL.getTemplateNameLoc(),
getMostRelevantTemplatePattern(TL.getTypePtr()));
reportType(TL.getTemplateNameLoc(),
getMostRelevantTemplatePattern(TL.getTypePtr()));
return true;
}

Expand Down
28 changes: 28 additions & 0 deletions clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,34 @@ TEST(WalkAST, TemplateNames) {
testWalk("template<typename T> struct $explicit^S { S(T); };", "^S s(42);");
}

TEST(WalkAST, NestedTypes) {
testWalk(R"cpp(
struct Base { typedef int $implicit^a; };
struct Derived : public Base {};)cpp",
"void fun() { Derived::^a x; }");
testWalk(R"cpp(
struct Base { using $implicit^a = int; };
struct Derived : public Base {};)cpp",
"void fun() { Derived::^a x; }");
testWalk(R"cpp(
struct ns { struct a {}; };
struct Base : public ns { using ns::$implicit^a; };
struct Derived : public Base {};)cpp",
"void fun() { Derived::^a x; }");
testWalk(R"cpp(
struct Base { struct $implicit^a {}; };
struct Derived : public Base {};)cpp",
"void fun() { Derived::^a x; }");
testWalk("struct Base { struct $implicit^a {}; };",
"struct Derived : public Base { ^a x; };");
testWalk(R"cpp(
struct Base { struct $implicit^a {}; };
struct Derived : public Base {};
struct SoDerived : public Derived {};
)cpp",
"void fun() { SoDerived::Derived::^a x; }");
}

TEST(WalkAST, MemberExprs) {
testWalk("struct $implicit^S { static int f; };", "void foo() { S::^f; }");
testWalk("struct B { static int f; }; struct $implicit^S : B {};",
Expand Down

0 comments on commit cce7b81

Please sign in to comment.