16499e9c6SDaniel Dunbar //===- PrintFunctionNames.cpp ---------------------------------------------===// 26499e9c6SDaniel Dunbar // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 66499e9c6SDaniel Dunbar // 76499e9c6SDaniel Dunbar //===----------------------------------------------------------------------===// 86499e9c6SDaniel Dunbar // 9520d1e6cSDaniel Dunbar // Example clang plugin which simply prints the names of all the top-level decls 10520d1e6cSDaniel Dunbar // in the input file. 116499e9c6SDaniel Dunbar // 126499e9c6SDaniel Dunbar //===----------------------------------------------------------------------===// 136499e9c6SDaniel Dunbar 146499e9c6SDaniel Dunbar #include "clang/Frontend/FrontendPluginRegistry.h" 156499e9c6SDaniel Dunbar #include "clang/AST/AST.h" 168675b4afSChandler Carruth #include "clang/AST/ASTConsumer.h" 1728e0f243SNico Weber #include "clang/AST/RecursiveASTVisitor.h" 182be96746SDaniel Dunbar #include "clang/Frontend/CompilerInstance.h" 1928e0f243SNico Weber #include "clang/Sema/Sema.h" 206499e9c6SDaniel Dunbar #include "llvm/Support/raw_ostream.h" 216499e9c6SDaniel Dunbar using namespace clang; 226499e9c6SDaniel Dunbar 236499e9c6SDaniel Dunbar namespace { 246499e9c6SDaniel Dunbar 256499e9c6SDaniel Dunbar class PrintFunctionsConsumer : public ASTConsumer { 2628e0f243SNico Weber CompilerInstance &Instance; 2728e0f243SNico Weber std::set<std::string> ParsedTemplates; 2828e0f243SNico Weber 296499e9c6SDaniel Dunbar public: PrintFunctionsConsumer(CompilerInstance & Instance,std::set<std::string> ParsedTemplates)3028e0f243SNico Weber PrintFunctionsConsumer(CompilerInstance &Instance, 3128e0f243SNico Weber std::set<std::string> ParsedTemplates) 3228e0f243SNico Weber : Instance(Instance), ParsedTemplates(ParsedTemplates) {} 3328e0f243SNico Weber HandleTopLevelDecl(DeclGroupRef DG)3434eb2072SAlexander Kornienko bool HandleTopLevelDecl(DeclGroupRef DG) override { 356499e9c6SDaniel Dunbar for (DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; ++i) { 366499e9c6SDaniel Dunbar const Decl *D = *i; 376499e9c6SDaniel Dunbar if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) 386499e9c6SDaniel Dunbar llvm::errs() << "top-level-decl: \"" << ND->getNameAsString() << "\"\n"; 396499e9c6SDaniel Dunbar } 409f39a765SDouglas Gregor 419f39a765SDouglas Gregor return true; 426499e9c6SDaniel Dunbar } 4328e0f243SNico Weber HandleTranslationUnit(ASTContext & context)4428e0f243SNico Weber void HandleTranslationUnit(ASTContext& context) override { 4528e0f243SNico Weber if (!Instance.getLangOpts().DelayedTemplateParsing) 4628e0f243SNico Weber return; 4728e0f243SNico Weber 4828e0f243SNico Weber // This demonstrates how to force instantiation of some templates in 4928e0f243SNico Weber // -fdelayed-template-parsing mode. (Note: Doing this unconditionally for 5028e0f243SNico Weber // all templates is similar to not using -fdelayed-template-parsig in the 5128e0f243SNico Weber // first place.) 5228e0f243SNico Weber // The advantage of doing this in HandleTranslationUnit() is that all 5328e0f243SNico Weber // codegen (when using -add-plugin) is completely finished and this can't 5428e0f243SNico Weber // affect the compiler output. 5528e0f243SNico Weber struct Visitor : public RecursiveASTVisitor<Visitor> { 5628e0f243SNico Weber const std::set<std::string> &ParsedTemplates; 5728e0f243SNico Weber Visitor(const std::set<std::string> &ParsedTemplates) 5828e0f243SNico Weber : ParsedTemplates(ParsedTemplates) {} 5928e0f243SNico Weber bool VisitFunctionDecl(FunctionDecl *FD) { 6028e0f243SNico Weber if (FD->isLateTemplateParsed() && 6128e0f243SNico Weber ParsedTemplates.count(FD->getNameAsString())) 6228e0f243SNico Weber LateParsedDecls.insert(FD); 6328e0f243SNico Weber return true; 6428e0f243SNico Weber } 6528e0f243SNico Weber 6628e0f243SNico Weber std::set<FunctionDecl*> LateParsedDecls; 6728e0f243SNico Weber } v(ParsedTemplates); 6828e0f243SNico Weber v.TraverseDecl(context.getTranslationUnitDecl()); 6928e0f243SNico Weber clang::Sema &sema = Instance.getSema(); 7028e0f243SNico Weber for (const FunctionDecl *FD : v.LateParsedDecls) { 71b89d85feSJustin Lebar clang::LateParsedTemplate &LPT = 72b89d85feSJustin Lebar *sema.LateParsedTemplateMap.find(FD)->second; 73b89d85feSJustin Lebar sema.LateTemplateParser(sema.OpaqueParser, LPT); 7428e0f243SNico Weber llvm::errs() << "late-parsed-decl: \"" << FD->getNameAsString() << "\"\n"; 7528e0f243SNico Weber } 7628e0f243SNico Weber } 776499e9c6SDaniel Dunbar }; 786499e9c6SDaniel Dunbar 797c995e8fSDaniel Dunbar class PrintFunctionNamesAction : public PluginASTAction { 8028e0f243SNico Weber std::set<std::string> ParsedTemplates; 816499e9c6SDaniel Dunbar protected: CreateASTConsumer(CompilerInstance & CI,llvm::StringRef)826beb6aa8SDavid Blaikie std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, 8334eb2072SAlexander Kornienko llvm::StringRef) override { 84*2b3d49b6SJonas Devlieghere return std::make_unique<PrintFunctionsConsumer>(CI, ParsedTemplates); 856499e9c6SDaniel Dunbar } 867c995e8fSDaniel Dunbar ParseArgs(const CompilerInstance & CI,const std::vector<std::string> & args)872be96746SDaniel Dunbar bool ParseArgs(const CompilerInstance &CI, 8834eb2072SAlexander Kornienko const std::vector<std::string> &args) override { 892be96746SDaniel Dunbar for (unsigned i = 0, e = args.size(); i != e; ++i) { 907c995e8fSDaniel Dunbar llvm::errs() << "PrintFunctionNames arg = " << args[i] << "\n"; 912be96746SDaniel Dunbar 922be96746SDaniel Dunbar // Example error handling. 93f42db7ceSEli Friedman DiagnosticsEngine &D = CI.getDiagnostics(); 9428e0f243SNico Weber if (args[i] == "-an-error") { 959477f9e5SAlp Toker unsigned DiagID = D.getCustomDiagID(DiagnosticsEngine::Error, 969477f9e5SAlp Toker "invalid argument '%0'"); 979477f9e5SAlp Toker D.Report(DiagID) << args[i]; 982be96746SDaniel Dunbar return false; 9928e0f243SNico Weber } else if (args[i] == "-parse-template") { 10028e0f243SNico Weber if (i + 1 >= e) { 10128e0f243SNico Weber D.Report(D.getCustomDiagID(DiagnosticsEngine::Error, 10228e0f243SNico Weber "missing -parse-template argument")); 10328e0f243SNico Weber return false; 10428e0f243SNico Weber } 10528e0f243SNico Weber ++i; 10628e0f243SNico Weber ParsedTemplates.insert(args[i]); 1072be96746SDaniel Dunbar } 1082be96746SDaniel Dunbar } 1096ee521c7SAlexander Kornienko if (!args.empty() && args[0] == "help") 1107c995e8fSDaniel Dunbar PrintHelp(llvm::errs()); 1117c995e8fSDaniel Dunbar 1127c995e8fSDaniel Dunbar return true; 1137c995e8fSDaniel Dunbar } PrintHelp(llvm::raw_ostream & ros)1147c995e8fSDaniel Dunbar void PrintHelp(llvm::raw_ostream& ros) { 1157c995e8fSDaniel Dunbar ros << "Help for PrintFunctionNames plugin goes here\n"; 1167c995e8fSDaniel Dunbar } 1177c995e8fSDaniel Dunbar 1186499e9c6SDaniel Dunbar }; 1196499e9c6SDaniel Dunbar 120ab9db510SAlexander Kornienko } 1216499e9c6SDaniel Dunbar 12234e0f6cbSManuel Klimek static FrontendPluginRegistry::Add<PrintFunctionNamesAction> 1236499e9c6SDaniel Dunbar X("print-fns", "print function names"); 124