1 | //===- AnnotateFunctions.cpp ----------------------------------------------===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Example clang plugin which adds an annotation to every function in |
10 | // translation units that start with #pragma enable_annotate. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "clang/Frontend/FrontendPluginRegistry.h" |
15 | #include "clang/AST/AST.h" |
16 | #include "clang/AST/ASTConsumer.h" |
17 | #include "clang/AST/Attr.h" |
18 | #include "clang/Lex/Preprocessor.h" |
19 | #include "clang/Lex/LexDiagnostic.h" |
20 | using namespace clang; |
21 | |
22 | namespace { |
23 | |
24 | static bool EnableAnnotate = false; |
25 | static bool HandledDecl = false; |
26 | |
27 | class AnnotateFunctionsConsumer : public ASTConsumer { |
28 | public: |
29 | bool HandleTopLevelDecl(DeclGroupRef DG) override { |
30 | HandledDecl = true; |
31 | if (!EnableAnnotate) |
32 | return true; |
33 | for (auto D : DG) |
34 | if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: D)) |
35 | FD->addAttr(A: AnnotateAttr::CreateImplicit( |
36 | Ctx&: FD->getASTContext(), Annotation: "example_annotation" , Args: nullptr, ArgsSize: 0)); |
37 | return true; |
38 | } |
39 | }; |
40 | |
41 | class AnnotateFunctionsAction : public PluginASTAction { |
42 | public: |
43 | std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, |
44 | llvm::StringRef) override { |
45 | return std::make_unique<AnnotateFunctionsConsumer>(); |
46 | } |
47 | |
48 | bool ParseArgs(const CompilerInstance &CI, |
49 | const std::vector<std::string> &args) override { |
50 | return true; |
51 | } |
52 | |
53 | PluginASTAction::ActionType getActionType() override { |
54 | return AddBeforeMainAction; |
55 | } |
56 | }; |
57 | |
58 | class PragmaAnnotateHandler : public PragmaHandler { |
59 | public: |
60 | PragmaAnnotateHandler() : PragmaHandler("enable_annotate" ) { } |
61 | |
62 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
63 | Token &PragmaTok) override { |
64 | |
65 | Token Tok; |
66 | PP.LexUnexpandedToken(Result&: Tok); |
67 | if (Tok.isNot(K: tok::eod)) |
68 | PP.Diag(Tok, DiagID: diag::ext_pp_extra_tokens_at_eol) << "pragma" ; |
69 | |
70 | if (HandledDecl) { |
71 | DiagnosticsEngine &D = PP.getDiagnostics(); |
72 | unsigned ID = D.getCustomDiagID( |
73 | L: DiagnosticsEngine::Error, |
74 | FormatString: "#pragma enable_annotate not allowed after declarations" ); |
75 | D.Report(Loc: PragmaTok.getLocation(), DiagID: ID); |
76 | } |
77 | |
78 | EnableAnnotate = true; |
79 | } |
80 | }; |
81 | |
82 | } |
83 | |
84 | static FrontendPluginRegistry::Add<AnnotateFunctionsAction> |
85 | X("annotate-fns" , "annotate functions" ); |
86 | |
87 | static PragmaHandlerRegistry::Add<PragmaAnnotateHandler> |
88 | Y("enable_annotate" ,"enable annotation" ); |
89 | |