1 //===- PrintFunctionNames.cpp ---------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Example clang plugin which simply prints the names of all the top-level decls
12 //===----------------------------------------------------------------------===//
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
;
25 class PrintFunctionsConsumer
: public ASTConsumer
{
26 CompilerInstance
&Instance
;
27 std::set
<std::string
> ParsedTemplates
;
30 PrintFunctionsConsumer(CompilerInstance
&Instance
,
31 std::set
<std::string
> ParsedTemplates
)
32 : Instance(Instance
), ParsedTemplates(ParsedTemplates
) {}
34 bool HandleTopLevelDecl(DeclGroupRef DG
) override
{
35 for (DeclGroupRef::iterator i
= DG
.begin(), e
= DG
.end(); i
!= e
; ++i
) {
37 if (const NamedDecl
*ND
= dyn_cast
<NamedDecl
>(D
))
38 llvm::errs() << "top-level-decl: \"" << ND
->getNameAsString() << "\"\n";
44 void HandleTranslationUnit(ASTContext
& context
) override
{
45 if (!Instance
.getLangOpts().DelayedTemplateParsing
)
48 // This demonstrates how to force instantiation of some templates in
49 // -fdelayed-template-parsing mode. (Note: Doing this unconditionally for
50 // all templates is similar to not using -fdelayed-template-parsig in the
52 // The advantage of doing this in HandleTranslationUnit() is that all
53 // codegen (when using -add-plugin) is completely finished and this can't
54 // affect the compiler output.
55 struct Visitor
: public RecursiveASTVisitor
<Visitor
> {
56 const std::set
<std::string
> &ParsedTemplates
;
57 Visitor(const std::set
<std::string
> &ParsedTemplates
)
58 : ParsedTemplates(ParsedTemplates
) {}
59 bool VisitFunctionDecl(FunctionDecl
*FD
) {
60 if (FD
->isLateTemplateParsed() &&
61 ParsedTemplates
.count(FD
->getNameAsString()))
62 LateParsedDecls
.insert(FD
);
66 std::set
<FunctionDecl
*> LateParsedDecls
;
68 v
.TraverseDecl(context
.getTranslationUnitDecl());
69 clang::Sema
&sema
= Instance
.getSema();
70 for (const FunctionDecl
*FD
: v
.LateParsedDecls
) {
71 clang::LateParsedTemplate
&LPT
=
72 *sema
.LateParsedTemplateMap
.find(FD
)->second
;
73 sema
.LateTemplateParser(sema
.OpaqueParser
, LPT
);
74 llvm::errs() << "late-parsed-decl: \"" << FD
->getNameAsString() << "\"\n";
79 class PrintFunctionNamesAction
: public PluginASTAction
{
80 std::set
<std::string
> ParsedTemplates
;
82 std::unique_ptr
<ASTConsumer
> CreateASTConsumer(CompilerInstance
&CI
,
83 llvm::StringRef
) override
{
84 return std::make_unique
<PrintFunctionsConsumer
>(CI
, ParsedTemplates
);
87 bool ParseArgs(const CompilerInstance
&CI
,
88 const std::vector
<std::string
> &args
) override
{
89 for (unsigned i
= 0, e
= args
.size(); i
!= e
; ++i
) {
90 llvm::errs() << "PrintFunctionNames arg = " << args
[i
] << "\n";
92 // Example error handling.
93 DiagnosticsEngine
&D
= CI
.getDiagnostics();
94 if (args
[i
] == "-an-error") {
95 unsigned DiagID
= D
.getCustomDiagID(DiagnosticsEngine::Error
,
96 "invalid argument '%0'");
97 D
.Report(DiagID
) << args
[i
];
99 } else if (args
[i
] == "-parse-template") {
101 D
.Report(D
.getCustomDiagID(DiagnosticsEngine::Error
,
102 "missing -parse-template argument"));
106 ParsedTemplates
.insert(args
[i
]);
109 if (!args
.empty() && args
[0] == "help")
110 PrintHelp(llvm::errs());
114 void PrintHelp(llvm::raw_ostream
& ros
) {
115 ros
<< "Help for PrintFunctionNames plugin goes here\n";
122 static FrontendPluginRegistry::Add
<PrintFunctionNamesAction
>
123 X("print-fns", "print function names");