diff options
Diffstat (limited to 'clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.cpp')
-rw-r--r-- | clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.cpp | 117 |
1 files changed, 75 insertions, 42 deletions
diff --git a/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.cpp b/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.cpp index 96bf992c9a5..629851ffbd3 100644 --- a/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.cpp +++ b/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.cpp @@ -154,64 +154,84 @@ void FindAllSymbols::registerMatchers(MatchFinder *MatchFinder) { // The float parameter of the function pointer has an empty name, and its // declaration context is an anonymous namespace; therefore, it won't be // filtered out by our matchers above. - MatchFinder->addMatcher(varDecl(CommonFilter, - anyOf(ExternCMatcher, CCMatcher), - unless(parmVarDecl())) - .bind("decl"), - this); + auto Vars = varDecl(CommonFilter, anyOf(ExternCMatcher, CCMatcher), + unless(parmVarDecl())); // Matchers for C-style record declarations in extern "C" {...}. - MatchFinder->addMatcher( - recordDecl(CommonFilter, ExternCMatcher, isDefinition()).bind("decl"), - this); - + auto CRecords = recordDecl(CommonFilter, ExternCMatcher, isDefinition()); // Matchers for C++ record declarations. - auto CxxRecordDecl = - cxxRecordDecl(CommonFilter, CCMatcher, isDefinition()); - MatchFinder->addMatcher(CxxRecordDecl.bind("decl"), this); + auto CXXRecords = cxxRecordDecl(CommonFilter, CCMatcher, isDefinition()); // Matchers for function declarations. // We want to exclude friend declaration, but the `DeclContext` of a friend // function declaration is not the class in which it is declared, so we need // to explicitly check if the parent is a `friendDecl`. - MatchFinder->addMatcher(functionDecl(CommonFilter, - unless(hasParent(friendDecl())), - anyOf(ExternCMatcher, CCMatcher)) - .bind("decl"), - this); + auto Functions = functionDecl(CommonFilter, unless(hasParent(friendDecl())), + anyOf(ExternCMatcher, CCMatcher)); // Matcher for typedef and type alias declarations. // - // typedef and type alias can come from C-style headers and C++ heaeders. - // For C-style header, `DeclContxet` can be either `TranslationUnitDecl` + // typedef and type alias can come from C-style headers and C++ headers. + // For C-style headers, `DeclContxet` can be either `TranslationUnitDecl` // or `LinkageSpecDecl`. - // For C++ header, `DeclContext ` can be one of `TranslationUnitDecl`, - // `NamespaceDecl`. + // For C++ headers, `DeclContext ` can be either `TranslationUnitDecl` + // or `NamespaceDecl`. // With the following context matcher, we can match `typedefNameDecl` from - // both C-style header and C++ header (except for those in classes). + // both C-style headers and C++ headers (except for those in classes). // "cc_matchers" are not included since template-related matchers are not // applicable on `TypedefNameDecl`. - MatchFinder->addMatcher( + auto Typedefs = typedefNameDecl(CommonFilter, anyOf(HasNSOrTUCtxMatcher, - hasDeclContext(linkageSpecDecl()))) - .bind("decl"), - this); + hasDeclContext(linkageSpecDecl()))); // Matchers for enum declarations. - MatchFinder->addMatcher(enumDecl(CommonFilter, isDefinition(), - anyOf(HasNSOrTUCtxMatcher, ExternCMatcher)) - .bind("decl"), - this); + auto Enums = enumDecl(CommonFilter, isDefinition(), + anyOf(HasNSOrTUCtxMatcher, ExternCMatcher)); // Matchers for enum constant declarations. // We only match the enum constants in non-scoped enum declarations which are // inside toplevel translation unit or a namespace. + auto EnumConstants = enumConstantDecl( + CommonFilter, unless(isInScopedEnum()), + anyOf(hasDeclContext(enumDecl(HasNSOrTUCtxMatcher)), ExternCMatcher)); + + // Most of the time we care about all matchable decls, or all types. + auto Types = namedDecl(anyOf(CRecords, CXXRecords, Enums, Typedefs)); + auto Decls = namedDecl(anyOf(CRecords, CXXRecords, Enums, Typedefs, Vars, + EnumConstants, Functions)); + + // We want eligible decls bound to "decl"... + MatchFinder->addMatcher(Decls.bind("decl"), this); + + // ... and all uses of them bound to "use". These have many cases: + // Uses of values/functions: these generate a declRefExpr. + MatchFinder->addMatcher( + declRefExpr(isExpansionInMainFile(), to(Decls.bind("use"))), this); + // Uses of function templates: + MatchFinder->addMatcher( + declRefExpr(isExpansionInMainFile(), + to(functionDecl(hasParent( + functionTemplateDecl(has(Functions.bind("use"))))))), + this); + + // Uses of most types: just look at what the typeLoc refers to. + MatchFinder->addMatcher( + typeLoc(isExpansionInMainFile(), + loc(qualType(hasDeclaration(Types.bind("use"))))), + this); + // Uses of typedefs: these are transparent to hasDeclaration, so we need to + // handle them explicitly. + MatchFinder->addMatcher( + typeLoc(isExpansionInMainFile(), + loc(typedefType(hasDeclaration(Typedefs.bind("use"))))), + this); + // Uses of class templates: + // The typeLoc names the templateSpecializationType. Its declaration is the + // ClassTemplateDecl, which contains the CXXRecordDecl we want. MatchFinder->addMatcher( - enumConstantDecl( - CommonFilter, - unless(isInScopedEnum()), - anyOf(hasDeclContext(enumDecl(HasNSOrTUCtxMatcher)), ExternCMatcher)) - .bind("decl"), + typeLoc(isExpansionInMainFile(), + loc(templateSpecializationType(hasDeclaration( + classTemplateDecl(has(CXXRecords.bind("use"))))))), this); } @@ -221,15 +241,28 @@ void FindAllSymbols::run(const MatchFinder::MatchResult &Result) { return; } - const auto *ND = Result.Nodes.getNodeAs<NamedDecl>("decl"); - assert(ND && "Matched declaration must be a NamedDecl!"); + SymbolInfo::Signals Signals; + const NamedDecl *ND; + if ((ND = Result.Nodes.getNodeAs<NamedDecl>("use"))) + Signals.Used = 1; + else if ((ND = Result.Nodes.getNodeAs<NamedDecl>("decl"))) + Signals.Seen = 1; + else + assert(false && "Must match a NamedDecl!"); + const SourceManager *SM = Result.SourceManager; + if (auto Symbol = CreateSymbolInfo(ND, *SM, Collector)) { + Filename = SM->getFileEntryForID(SM->getMainFileID())->getName(); + FileSymbols[*Symbol] += Signals; + } +} - llvm::Optional<SymbolInfo> Symbol = - CreateSymbolInfo(ND, *SM, Collector); - if (Symbol) - Reporter->reportSymbol( - SM->getFileEntryForID(SM->getMainFileID())->getName(), *Symbol); +void FindAllSymbols::onEndOfTranslationUnit() { + if (Filename != "") { + Reporter->reportSymbols(Filename, FileSymbols); + FileSymbols.clear(); + Filename = ""; + } } } // namespace find_all_symbols |