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