blob: 9f8f6e3f050a5650fadc268528b754b5bfafff58 [file] [log] [blame]
Daniel Dunbar6499e9c2009-11-15 00:27:43 +00001//===- 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//
Daniel Dunbar520d1e62009-12-11 23:04:35 +000010// Example clang plugin which simply prints the names of all the top-level decls
11// in the input file.
Daniel Dunbar6499e9c2009-11-15 00:27:43 +000012//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Frontend/FrontendPluginRegistry.h"
Daniel Dunbar6499e9c2009-11-15 00:27:43 +000016#include "clang/AST/AST.h"
Chandler Carruth8675b4a2012-12-04 09:37:22 +000017#include "clang/AST/ASTConsumer.h"
Nico Weber28e0f242015-05-17 01:07:16 +000018#include "clang/AST/RecursiveASTVisitor.h"
Daniel Dunbar2be96742010-08-02 15:31:28 +000019#include "clang/Frontend/CompilerInstance.h"
Nico Weber28e0f242015-05-17 01:07:16 +000020#include "clang/Sema/Sema.h"
Daniel Dunbar6499e9c2009-11-15 00:27:43 +000021#include "llvm/Support/raw_ostream.h"
22using namespace clang;
23
24namespace {
25
26class PrintFunctionsConsumer : public ASTConsumer {
Nico Weber28e0f242015-05-17 01:07:16 +000027 CompilerInstance &Instance;
28 std::set<std::string> ParsedTemplates;
29
Daniel Dunbar6499e9c2009-11-15 00:27:43 +000030public:
Nico Weber28e0f242015-05-17 01:07:16 +000031 PrintFunctionsConsumer(CompilerInstance &Instance,
32 std::set<std::string> ParsedTemplates)
33 : Instance(Instance), ParsedTemplates(ParsedTemplates) {}
34
Alexander Kornienko34eb2072015-04-11 02:00:23 +000035 bool HandleTopLevelDecl(DeclGroupRef DG) override {
Daniel Dunbar6499e9c2009-11-15 00:27:43 +000036 for (DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; ++i) {
37 const Decl *D = *i;
38 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
39 llvm::errs() << "top-level-decl: \"" << ND->getNameAsString() << "\"\n";
40 }
Douglas Gregor9f39a762011-11-19 19:22:13 +000041
42 return true;
Daniel Dunbar6499e9c2009-11-15 00:27:43 +000043 }
Nico Weber28e0f242015-05-17 01:07:16 +000044
45 void HandleTranslationUnit(ASTContext& context) override {
46 if (!Instance.getLangOpts().DelayedTemplateParsing)
47 return;
48
49 // This demonstrates how to force instantiation of some templates in
50 // -fdelayed-template-parsing mode. (Note: Doing this unconditionally for
51 // all templates is similar to not using -fdelayed-template-parsig in the
52 // first place.)
53 // The advantage of doing this in HandleTranslationUnit() is that all
54 // codegen (when using -add-plugin) is completely finished and this can't
55 // affect the compiler output.
56 struct Visitor : public RecursiveASTVisitor<Visitor> {
57 const std::set<std::string> &ParsedTemplates;
58 Visitor(const std::set<std::string> &ParsedTemplates)
59 : ParsedTemplates(ParsedTemplates) {}
60 bool VisitFunctionDecl(FunctionDecl *FD) {
61 if (FD->isLateTemplateParsed() &&
62 ParsedTemplates.count(FD->getNameAsString()))
63 LateParsedDecls.insert(FD);
64 return true;
65 }
66
67 std::set<FunctionDecl*> LateParsedDecls;
68 } v(ParsedTemplates);
69 v.TraverseDecl(context.getTranslationUnitDecl());
70 clang::Sema &sema = Instance.getSema();
71 for (const FunctionDecl *FD : v.LateParsedDecls) {
72 clang::LateParsedTemplate* LPT = sema.LateParsedTemplateMap.lookup(FD);
73 sema.LateTemplateParser(sema.OpaqueParser, *LPT);
74 llvm::errs() << "late-parsed-decl: \"" << FD->getNameAsString() << "\"\n";
75 }
76 }
Daniel Dunbar2be96742010-08-02 15:31:28 +000077};
Daniel Dunbar6499e9c2009-11-15 00:27:43 +000078
Daniel Dunbar7c995e82010-06-16 16:59:23 +000079class PrintFunctionNamesAction : public PluginASTAction {
Nico Weber28e0f242015-05-17 01:07:16 +000080 std::set<std::string> ParsedTemplates;
Daniel Dunbar6499e9c2009-11-15 00:27:43 +000081protected:
David Blaikie6beb6aa2014-08-10 19:56:51 +000082 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
Alexander Kornienko34eb2072015-04-11 02:00:23 +000083 llvm::StringRef) override {
Nico Weber28e0f242015-05-17 01:07:16 +000084 return llvm::make_unique<PrintFunctionsConsumer>(CI, ParsedTemplates);
Daniel Dunbar6499e9c2009-11-15 00:27:43 +000085 }
Daniel Dunbar7c995e82010-06-16 16:59:23 +000086
Daniel Dunbar2be96742010-08-02 15:31:28 +000087 bool ParseArgs(const CompilerInstance &CI,
Alexander Kornienko34eb2072015-04-11 02:00:23 +000088 const std::vector<std::string> &args) override {
Daniel Dunbar2be96742010-08-02 15:31:28 +000089 for (unsigned i = 0, e = args.size(); i != e; ++i) {
Daniel Dunbar7c995e82010-06-16 16:59:23 +000090 llvm::errs() << "PrintFunctionNames arg = " << args[i] << "\n";
Daniel Dunbar2be96742010-08-02 15:31:28 +000091
92 // Example error handling.
Nico Weber28e0f242015-05-17 01:07:16 +000093 DiagnosticsEngine &D = CI.getDiagnostics();
Daniel Dunbar2be96742010-08-02 15:31:28 +000094 if (args[i] == "-an-error") {
Alp Toker9477f9e52013-12-21 05:19:58 +000095 unsigned DiagID = D.getCustomDiagID(DiagnosticsEngine::Error,
96 "invalid argument '%0'");
97 D.Report(DiagID) << args[i];
Daniel Dunbar2be96742010-08-02 15:31:28 +000098 return false;
Nico Weber28e0f242015-05-17 01:07:16 +000099 } else if (args[i] == "-parse-template") {
100 if (i + 1 >= e) {
101 D.Report(D.getCustomDiagID(DiagnosticsEngine::Error,
102 "missing -parse-template argument"));
103 return false;
104 }
105 ++i;
106 ParsedTemplates.insert(args[i]);
Daniel Dunbar2be96742010-08-02 15:31:28 +0000107 }
108 }
Alexander Kornienko6ee521c2015-01-23 15:36:10 +0000109 if (!args.empty() && args[0] == "help")
Daniel Dunbar7c995e82010-06-16 16:59:23 +0000110 PrintHelp(llvm::errs());
111
112 return true;
113 }
Daniel Dunbar2be96742010-08-02 15:31:28 +0000114 void PrintHelp(llvm::raw_ostream& ros) {
Daniel Dunbar7c995e82010-06-16 16:59:23 +0000115 ros << "Help for PrintFunctionNames plugin goes here\n";
116 }
117
Daniel Dunbar6499e9c2009-11-15 00:27:43 +0000118};
119
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000120}
Daniel Dunbar6499e9c2009-11-15 00:27:43 +0000121
Manuel Klimek34e0f6c2012-04-26 08:46:12 +0000122static FrontendPluginRegistry::Add<PrintFunctionNamesAction>
Daniel Dunbar6499e9c2009-11-15 00:27:43 +0000123X("print-fns", "print function names");