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