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>(D))
35         FD->addAttr(AnnotateAttr::CreateImplicit(FD->getASTContext(),
36                                                  "example_annotation"));
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(Tok);
67     if (Tok.isNot(tok::eod))
68       PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
69 
70     if (HandledDecl) {
71       DiagnosticsEngine &D = PP.getDiagnostics();
72       unsigned ID = D.getCustomDiagID(
73         DiagnosticsEngine::Error,
74         "#pragma enable_annotate not allowed after declarations");
75       D.Report(PragmaTok.getLocation(), 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