PrintFunctionNames.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. //===- PrintFunctionNames.cpp ---------------------------------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // Example clang plugin which simply prints the names of all the top-level decls
  11. // in the input file.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "clang/Frontend/FrontendPluginRegistry.h"
  15. #include "clang/AST/AST.h"
  16. #include "clang/AST/ASTConsumer.h"
  17. #include "clang/AST/RecursiveASTVisitor.h"
  18. #include "clang/Frontend/CompilerInstance.h"
  19. #include "clang/Sema/Sema.h"
  20. #include "llvm/Support/raw_ostream.h"
  21. using namespace clang;
  22. namespace {
  23. class PrintFunctionsConsumer : public ASTConsumer {
  24. CompilerInstance &Instance;
  25. std::set<std::string> ParsedTemplates;
  26. public:
  27. PrintFunctionsConsumer(CompilerInstance &Instance,
  28. std::set<std::string> ParsedTemplates)
  29. : Instance(Instance), ParsedTemplates(ParsedTemplates) {}
  30. bool HandleTopLevelDecl(DeclGroupRef DG) override {
  31. for (DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; ++i) {
  32. const Decl *D = *i;
  33. if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
  34. llvm::errs() << "top-level-decl: \"" << ND->getNameAsString() << "\"\n";
  35. }
  36. return true;
  37. }
  38. void HandleTranslationUnit(ASTContext& context) override {
  39. if (!Instance.getLangOpts().DelayedTemplateParsing)
  40. return;
  41. // This demonstrates how to force instantiation of some templates in
  42. // -fdelayed-template-parsing mode. (Note: Doing this unconditionally for
  43. // all templates is similar to not using -fdelayed-template-parsig in the
  44. // first place.)
  45. // The advantage of doing this in HandleTranslationUnit() is that all
  46. // codegen (when using -add-plugin) is completely finished and this can't
  47. // affect the compiler output.
  48. struct Visitor : public RecursiveASTVisitor<Visitor> {
  49. const std::set<std::string> &ParsedTemplates;
  50. Visitor(const std::set<std::string> &ParsedTemplates)
  51. : ParsedTemplates(ParsedTemplates) {}
  52. bool VisitFunctionDecl(FunctionDecl *FD) {
  53. if (FD->isLateTemplateParsed() &&
  54. ParsedTemplates.count(FD->getNameAsString()))
  55. LateParsedDecls.insert(FD);
  56. return true;
  57. }
  58. std::set<FunctionDecl*> LateParsedDecls;
  59. } v(ParsedTemplates);
  60. v.TraverseDecl(context.getTranslationUnitDecl());
  61. clang::Sema &sema = Instance.getSema();
  62. for (const FunctionDecl *FD : v.LateParsedDecls) {
  63. clang::LateParsedTemplate* LPT = sema.LateParsedTemplateMap.lookup(FD);
  64. sema.LateTemplateParser(sema.OpaqueParser, *LPT);
  65. llvm::errs() << "late-parsed-decl: \"" << FD->getNameAsString() << "\"\n";
  66. }
  67. }
  68. };
  69. class PrintFunctionNamesAction : public PluginASTAction {
  70. std::set<std::string> ParsedTemplates;
  71. protected:
  72. std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
  73. llvm::StringRef) override {
  74. return llvm::make_unique<PrintFunctionsConsumer>(CI, ParsedTemplates);
  75. }
  76. bool ParseArgs(const CompilerInstance &CI,
  77. const std::vector<std::string> &args) override {
  78. for (unsigned i = 0, e = args.size(); i != e; ++i) {
  79. llvm::errs() << "PrintFunctionNames arg = " << args[i] << "\n";
  80. // Example error handling.
  81. DiagnosticsEngine &D = CI.getDiagnostics();
  82. if (args[i] == "-an-error") {
  83. unsigned DiagID = D.getCustomDiagID(DiagnosticsEngine::Error,
  84. "invalid argument '%0'");
  85. D.Report(DiagID) << args[i];
  86. return false;
  87. } else if (args[i] == "-parse-template") {
  88. if (i + 1 >= e) {
  89. D.Report(D.getCustomDiagID(DiagnosticsEngine::Error,
  90. "missing -parse-template argument"));
  91. return false;
  92. }
  93. ++i;
  94. ParsedTemplates.insert(args[i]);
  95. }
  96. }
  97. if (!args.empty() && args[0] == "help")
  98. PrintHelp(llvm::errs());
  99. return true;
  100. }
  101. void PrintHelp(llvm::raw_ostream& ros) {
  102. ros << "Help for PrintFunctionNames plugin goes here\n";
  103. }
  104. };
  105. }
  106. static FrontendPluginRegistry::Add<PrintFunctionNamesAction>
  107. X("print-fns", "print function names");