16499e9c6SDaniel Dunbar //===- PrintFunctionNames.cpp ---------------------------------------------===// 26499e9c6SDaniel Dunbar // 36499e9c6SDaniel Dunbar // The LLVM Compiler Infrastructure 46499e9c6SDaniel Dunbar // 56499e9c6SDaniel Dunbar // This file is distributed under the University of Illinois Open Source 66499e9c6SDaniel Dunbar // License. See LICENSE.TXT for details. 76499e9c6SDaniel Dunbar // 86499e9c6SDaniel Dunbar //===----------------------------------------------------------------------===// 96499e9c6SDaniel Dunbar // 10520d1e6cSDaniel Dunbar // Example clang plugin which simply prints the names of all the top-level decls 11520d1e6cSDaniel Dunbar // in the input file. 126499e9c6SDaniel Dunbar // 136499e9c6SDaniel Dunbar //===----------------------------------------------------------------------===// 146499e9c6SDaniel Dunbar 156499e9c6SDaniel Dunbar #include "clang/Frontend/FrontendPluginRegistry.h" 166499e9c6SDaniel Dunbar #include "clang/AST/AST.h" 178675b4afSChandler Carruth #include "clang/AST/ASTConsumer.h" 1828e0f243SNico Weber #include "clang/AST/RecursiveASTVisitor.h" 192be96746SDaniel Dunbar #include "clang/Frontend/CompilerInstance.h" 2028e0f243SNico Weber #include "clang/Sema/Sema.h" 216499e9c6SDaniel Dunbar #include "llvm/Support/raw_ostream.h" 226499e9c6SDaniel Dunbar using namespace clang; 236499e9c6SDaniel Dunbar 246499e9c6SDaniel Dunbar namespace { 256499e9c6SDaniel Dunbar 266499e9c6SDaniel Dunbar class PrintFunctionsConsumer : public ASTConsumer { 2728e0f243SNico Weber CompilerInstance &Instance; 2828e0f243SNico Weber std::set<std::string> ParsedTemplates; 2928e0f243SNico Weber 306499e9c6SDaniel Dunbar public: 3128e0f243SNico Weber PrintFunctionsConsumer(CompilerInstance &Instance, 3228e0f243SNico Weber std::set<std::string> ParsedTemplates) 3328e0f243SNico Weber : Instance(Instance), ParsedTemplates(ParsedTemplates) {} 3428e0f243SNico Weber 3534eb2072SAlexander Kornienko bool HandleTopLevelDecl(DeclGroupRef DG) override { 366499e9c6SDaniel Dunbar for (DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; ++i) { 376499e9c6SDaniel Dunbar const Decl *D = *i; 386499e9c6SDaniel Dunbar if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) 396499e9c6SDaniel Dunbar llvm::errs() << "top-level-decl: \"" << ND->getNameAsString() << "\"\n"; 406499e9c6SDaniel Dunbar } 419f39a765SDouglas Gregor 429f39a765SDouglas Gregor return true; 436499e9c6SDaniel Dunbar } 4428e0f243SNico Weber 4528e0f243SNico Weber void HandleTranslationUnit(ASTContext& context) override { 4628e0f243SNico Weber if (!Instance.getLangOpts().DelayedTemplateParsing) 4728e0f243SNico Weber return; 4828e0f243SNico Weber 4928e0f243SNico Weber // This demonstrates how to force instantiation of some templates in 5028e0f243SNico Weber // -fdelayed-template-parsing mode. (Note: Doing this unconditionally for 5128e0f243SNico Weber // all templates is similar to not using -fdelayed-template-parsig in the 5228e0f243SNico Weber // first place.) 5328e0f243SNico Weber // The advantage of doing this in HandleTranslationUnit() is that all 5428e0f243SNico Weber // codegen (when using -add-plugin) is completely finished and this can't 5528e0f243SNico Weber // affect the compiler output. 5628e0f243SNico Weber struct Visitor : public RecursiveASTVisitor<Visitor> { 5728e0f243SNico Weber const std::set<std::string> &ParsedTemplates; 5828e0f243SNico Weber Visitor(const std::set<std::string> &ParsedTemplates) 5928e0f243SNico Weber : ParsedTemplates(ParsedTemplates) {} 6028e0f243SNico Weber bool VisitFunctionDecl(FunctionDecl *FD) { 6128e0f243SNico Weber if (FD->isLateTemplateParsed() && 6228e0f243SNico Weber ParsedTemplates.count(FD->getNameAsString())) 6328e0f243SNico Weber LateParsedDecls.insert(FD); 6428e0f243SNico Weber return true; 6528e0f243SNico Weber } 6628e0f243SNico Weber 6728e0f243SNico Weber std::set<FunctionDecl*> LateParsedDecls; 6828e0f243SNico Weber } v(ParsedTemplates); 6928e0f243SNico Weber v.TraverseDecl(context.getTranslationUnitDecl()); 7028e0f243SNico Weber clang::Sema &sema = Instance.getSema(); 7128e0f243SNico Weber for (const FunctionDecl *FD : v.LateParsedDecls) { 72*b89d85feSJustin Lebar clang::LateParsedTemplate &LPT = 73*b89d85feSJustin Lebar *sema.LateParsedTemplateMap.find(FD)->second; 74*b89d85feSJustin Lebar sema.LateTemplateParser(sema.OpaqueParser, LPT); 7528e0f243SNico Weber llvm::errs() << "late-parsed-decl: \"" << FD->getNameAsString() << "\"\n"; 7628e0f243SNico Weber } 7728e0f243SNico Weber } 786499e9c6SDaniel Dunbar }; 796499e9c6SDaniel Dunbar 807c995e8fSDaniel Dunbar class PrintFunctionNamesAction : public PluginASTAction { 8128e0f243SNico Weber std::set<std::string> ParsedTemplates; 826499e9c6SDaniel Dunbar protected: 836beb6aa8SDavid Blaikie std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, 8434eb2072SAlexander Kornienko llvm::StringRef) override { 8528e0f243SNico Weber return llvm::make_unique<PrintFunctionsConsumer>(CI, ParsedTemplates); 866499e9c6SDaniel Dunbar } 877c995e8fSDaniel Dunbar 882be96746SDaniel Dunbar bool ParseArgs(const CompilerInstance &CI, 8934eb2072SAlexander Kornienko const std::vector<std::string> &args) override { 902be96746SDaniel Dunbar for (unsigned i = 0, e = args.size(); i != e; ++i) { 917c995e8fSDaniel Dunbar llvm::errs() << "PrintFunctionNames arg = " << args[i] << "\n"; 922be96746SDaniel Dunbar 932be96746SDaniel Dunbar // Example error handling. 94f42db7ceSEli Friedman DiagnosticsEngine &D = CI.getDiagnostics(); 9528e0f243SNico Weber if (args[i] == "-an-error") { 969477f9e5SAlp Toker unsigned DiagID = D.getCustomDiagID(DiagnosticsEngine::Error, 979477f9e5SAlp Toker "invalid argument '%0'"); 989477f9e5SAlp Toker D.Report(DiagID) << args[i]; 992be96746SDaniel Dunbar return false; 10028e0f243SNico Weber } else if (args[i] == "-parse-template") { 10128e0f243SNico Weber if (i + 1 >= e) { 10228e0f243SNico Weber D.Report(D.getCustomDiagID(DiagnosticsEngine::Error, 10328e0f243SNico Weber "missing -parse-template argument")); 10428e0f243SNico Weber return false; 10528e0f243SNico Weber } 10628e0f243SNico Weber ++i; 10728e0f243SNico Weber ParsedTemplates.insert(args[i]); 1082be96746SDaniel Dunbar } 1092be96746SDaniel Dunbar } 1106ee521c7SAlexander Kornienko if (!args.empty() && args[0] == "help") 1117c995e8fSDaniel Dunbar PrintHelp(llvm::errs()); 1127c995e8fSDaniel Dunbar 1137c995e8fSDaniel Dunbar return true; 1147c995e8fSDaniel Dunbar } 1157c995e8fSDaniel Dunbar void PrintHelp(llvm::raw_ostream& ros) { 1167c995e8fSDaniel Dunbar ros << "Help for PrintFunctionNames plugin goes here\n"; 1177c995e8fSDaniel Dunbar } 1187c995e8fSDaniel Dunbar 1196499e9c6SDaniel Dunbar }; 1206499e9c6SDaniel Dunbar 121ab9db510SAlexander Kornienko } 1226499e9c6SDaniel Dunbar 12334e0f6cbSManuel Klimek static FrontendPluginRegistry::Add<PrintFunctionNamesAction> 1246499e9c6SDaniel Dunbar X("print-fns", "print function names"); 125