19a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar//===- PrintFunctionNames.cpp ---------------------------------------------===// 29a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar// 39a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar// The LLVM Compiler Infrastructure 49a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar// 59a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar// This file is distributed under the University of Illinois Open Source 69a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar// License. See LICENSE.TXT for details. 79a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar// 89a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar//===----------------------------------------------------------------------===// 99a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar// 10dd63b28107f21692b5065588f0e90b4534946f93Daniel Dunbar// Example clang plugin which simply prints the names of all the top-level decls 11dd63b28107f21692b5065588f0e90b4534946f93Daniel Dunbar// in the input file. 129a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar// 139a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar//===----------------------------------------------------------------------===// 149a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar 159a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar#include "clang/Frontend/FrontendPluginRegistry.h" 169a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar#include "clang/AST/AST.h" 17e0c6e93dddf4503d9b12ce09d7ab6ea5d523499fChandler Carruth#include "clang/AST/ASTConsumer.h" 18b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar#include "clang/AST/RecursiveASTVisitor.h" 19f56a488a6bdfe56ca814f37d384afa67c67f9dd5Daniel Dunbar#include "clang/Frontend/CompilerInstance.h" 20b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar#include "clang/Sema/Sema.h" 219a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar#include "llvm/Support/raw_ostream.h" 229a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbarusing namespace clang; 239a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar 249a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbarnamespace { 259a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar 269a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbarclass PrintFunctionsConsumer : public ASTConsumer { 27b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar CompilerInstance &Instance; 28b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar std::set<std::string> ParsedTemplates; 29b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar 309a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbarpublic: 31b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar PrintFunctionsConsumer(CompilerInstance &Instance, 32b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar std::set<std::string> ParsedTemplates) 33b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar : Instance(Instance), ParsedTemplates(ParsedTemplates) {} 34b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar 3558878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar bool HandleTopLevelDecl(DeclGroupRef DG) override { 369a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar for (DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; ++i) { 379a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar const Decl *D = *i; 389a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) 399a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar llvm::errs() << "top-level-decl: \"" << ND->getNameAsString() << "\"\n"; 409a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar } 411a026803b7886ed265fc63dfddaaa5d3712760e3Douglas Gregor 421a026803b7886ed265fc63dfddaaa5d3712760e3Douglas Gregor return true; 439a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar } 44b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar 45b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar void HandleTranslationUnit(ASTContext& context) override { 46b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if (!Instance.getLangOpts().DelayedTemplateParsing) 47b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar return; 48b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar 49b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar // This demonstrates how to force instantiation of some templates in 50b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar // -fdelayed-template-parsing mode. (Note: Doing this unconditionally for 51b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar // all templates is similar to not using -fdelayed-template-parsig in the 52b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar // first place.) 53b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar // The advantage of doing this in HandleTranslationUnit() is that all 54b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar // codegen (when using -add-plugin) is completely finished and this can't 55b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar // affect the compiler output. 56b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar struct Visitor : public RecursiveASTVisitor<Visitor> { 57b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar const std::set<std::string> &ParsedTemplates; 58b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar Visitor(const std::set<std::string> &ParsedTemplates) 59b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar : ParsedTemplates(ParsedTemplates) {} 60b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar bool VisitFunctionDecl(FunctionDecl *FD) { 61b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if (FD->isLateTemplateParsed() && 62b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar ParsedTemplates.count(FD->getNameAsString())) 63b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar LateParsedDecls.insert(FD); 64b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar return true; 65b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar } 66b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar 67b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar std::set<FunctionDecl*> LateParsedDecls; 68b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar } v(ParsedTemplates); 69b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar v.TraverseDecl(context.getTranslationUnitDecl()); 70b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar clang::Sema &sema = Instance.getSema(); 71b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar for (const FunctionDecl *FD : v.LateParsedDecls) { 72b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar clang::LateParsedTemplate* LPT = sema.LateParsedTemplateMap.lookup(FD); 73b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar sema.LateTemplateParser(sema.OpaqueParser, *LPT); 74b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar llvm::errs() << "late-parsed-decl: \"" << FD->getNameAsString() << "\"\n"; 75b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar } 76b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar } 77f56a488a6bdfe56ca814f37d384afa67c67f9dd5Daniel Dunbar}; 789a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar 793177aae51a21f61ab483c52f97124bdb707da7f1Daniel Dunbarclass PrintFunctionNamesAction : public PluginASTAction { 80b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar std::set<std::string> ParsedTemplates; 819a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbarprotected: 82176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, 8358878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar llvm::StringRef) override { 84b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar return llvm::make_unique<PrintFunctionsConsumer>(CI, ParsedTemplates); 859a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar } 863177aae51a21f61ab483c52f97124bdb707da7f1Daniel Dunbar 87f56a488a6bdfe56ca814f37d384afa67c67f9dd5Daniel Dunbar bool ParseArgs(const CompilerInstance &CI, 8858878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar const std::vector<std::string> &args) override { 89f56a488a6bdfe56ca814f37d384afa67c67f9dd5Daniel Dunbar for (unsigned i = 0, e = args.size(); i != e; ++i) { 903177aae51a21f61ab483c52f97124bdb707da7f1Daniel Dunbar llvm::errs() << "PrintFunctionNames arg = " << args[i] << "\n"; 91f56a488a6bdfe56ca814f37d384afa67c67f9dd5Daniel Dunbar 92f56a488a6bdfe56ca814f37d384afa67c67f9dd5Daniel Dunbar // Example error handling. 93b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar DiagnosticsEngine &D = CI.getDiagnostics(); 94f56a488a6bdfe56ca814f37d384afa67c67f9dd5Daniel Dunbar if (args[i] == "-an-error") { 95651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unsigned DiagID = D.getCustomDiagID(DiagnosticsEngine::Error, 96651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "invalid argument '%0'"); 97651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines D.Report(DiagID) << args[i]; 98f56a488a6bdfe56ca814f37d384afa67c67f9dd5Daniel Dunbar return false; 99b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar } else if (args[i] == "-parse-template") { 100b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if (i + 1 >= e) { 101b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar D.Report(D.getCustomDiagID(DiagnosticsEngine::Error, 102b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar "missing -parse-template argument")); 103b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar return false; 104b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar } 105b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar ++i; 106b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar ParsedTemplates.insert(args[i]); 107f56a488a6bdfe56ca814f37d384afa67c67f9dd5Daniel Dunbar } 108f56a488a6bdfe56ca814f37d384afa67c67f9dd5Daniel Dunbar } 1090e2c34f92f00628d48968dfea096d36381f494cbStephen Hines if (!args.empty() && args[0] == "help") 1103177aae51a21f61ab483c52f97124bdb707da7f1Daniel Dunbar PrintHelp(llvm::errs()); 1113177aae51a21f61ab483c52f97124bdb707da7f1Daniel Dunbar 1123177aae51a21f61ab483c52f97124bdb707da7f1Daniel Dunbar return true; 1133177aae51a21f61ab483c52f97124bdb707da7f1Daniel Dunbar } 114f56a488a6bdfe56ca814f37d384afa67c67f9dd5Daniel Dunbar void PrintHelp(llvm::raw_ostream& ros) { 1153177aae51a21f61ab483c52f97124bdb707da7f1Daniel Dunbar ros << "Help for PrintFunctionNames plugin goes here\n"; 1163177aae51a21f61ab483c52f97124bdb707da7f1Daniel Dunbar } 1173177aae51a21f61ab483c52f97124bdb707da7f1Daniel Dunbar 1189a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar}; 1199a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar 1209a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar} 1219a69387f5c88c73638ae5155a398477d9c7ac87fDaniel Dunbar 122981d1ec3fd2d33fbb1b47c9fdae9e5a0ea241bc4Manuel Klimekstatic FrontendPluginRegistry::Add<PrintFunctionNamesAction> 1239a69387f5c88c73638ae5155a398477d9c7ac87fDaniel DunbarX("print-fns", "print function names"); 124