xref: /netbsd-src/external/apache2/llvm/dist/clang/examples/AnnotateFunctions/AnnotateFunctions.cpp (revision 181254a7b1bdde6873432bffef2d2decc4b5c22f)
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/Lex/Preprocessor.h"
18 #include "clang/Lex/LexDiagnostic.h"
19 using namespace clang;
20 
21 namespace {
22 
23 static bool EnableAnnotate = false;
24 static bool HandledDecl = false;
25 
26 class AnnotateFunctionsConsumer : public ASTConsumer {
27 public:
28   bool HandleTopLevelDecl(DeclGroupRef DG) override {
29     HandledDecl = true;
30     if (!EnableAnnotate)
31       return true;
32     for (auto D : DG)
33       if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
34         FD->addAttr(AnnotateAttr::CreateImplicit(FD->getASTContext(),
35                                                  "example_annotation"));
36     return true;
37   }
38 };
39 
40 class AnnotateFunctionsAction : public PluginASTAction {
41 public:
42   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
43                                                  llvm::StringRef) override {
44     return std::make_unique<AnnotateFunctionsConsumer>();
45   }
46 
47   bool ParseArgs(const CompilerInstance &CI,
48                  const std::vector<std::string> &args) override {
49     return true;
50   }
51 
52   PluginASTAction::ActionType getActionType() override {
53     return AddBeforeMainAction;
54   }
55 };
56 
57 class PragmaAnnotateHandler : public PragmaHandler {
58 public:
59   PragmaAnnotateHandler() : PragmaHandler("enable_annotate") { }
60 
61   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
62                     Token &PragmaTok) override {
63 
64     Token Tok;
65     PP.LexUnexpandedToken(Tok);
66     if (Tok.isNot(tok::eod))
67       PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
68 
69     if (HandledDecl) {
70       DiagnosticsEngine &D = PP.getDiagnostics();
71       unsigned ID = D.getCustomDiagID(
72         DiagnosticsEngine::Error,
73         "#pragma enable_annotate not allowed after declarations");
74       D.Report(PragmaTok.getLocation(), ID);
75     }
76 
77     EnableAnnotate = true;
78   }
79 };
80 
81 }
82 
83 static FrontendPluginRegistry::Add<AnnotateFunctionsAction>
84 X("annotate-fns", "annotate functions");
85 
86 static PragmaHandlerRegistry::Add<PragmaAnnotateHandler>
87 Y("enable_annotate","enable annotation");
88