| //===- AnnotateFunctions.cpp ----------------------------------------------===// | 
 | // | 
 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
 | // See https://llvm.org/LICENSE.txt for license information. | 
 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | // Example clang plugin which adds an annotation to every function in | 
 | // translation units that start with #pragma enable_annotate. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "clang/Frontend/FrontendPluginRegistry.h" | 
 | #include "clang/AST/AST.h" | 
 | #include "clang/AST/ASTConsumer.h" | 
 | #include "clang/AST/Attr.h" | 
 | #include "clang/Lex/Preprocessor.h" | 
 | #include "clang/Lex/LexDiagnostic.h" | 
 | using namespace clang; | 
 |  | 
 | namespace { | 
 |  | 
 | static bool EnableAnnotate = false; | 
 | static bool HandledDecl = false; | 
 |  | 
 | class AnnotateFunctionsConsumer : public ASTConsumer { | 
 | public: | 
 |   bool HandleTopLevelDecl(DeclGroupRef DG) override { | 
 |     HandledDecl = true; | 
 |     if (!EnableAnnotate) | 
 |       return true; | 
 |     for (auto D : DG) | 
 |       if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) | 
 |         FD->addAttr(AnnotateAttr::CreateImplicit( | 
 |             FD->getASTContext(), "example_annotation", nullptr, 0)); | 
 |     return true; | 
 |   } | 
 | }; | 
 |  | 
 | class AnnotateFunctionsAction : public PluginASTAction { | 
 | public: | 
 |   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, | 
 |                                                  llvm::StringRef) override { | 
 |     return std::make_unique<AnnotateFunctionsConsumer>(); | 
 |   } | 
 |  | 
 |   bool ParseArgs(const CompilerInstance &CI, | 
 |                  const std::vector<std::string> &args) override { | 
 |     return true; | 
 |   } | 
 |  | 
 |   PluginASTAction::ActionType getActionType() override { | 
 |     return AddBeforeMainAction; | 
 |   } | 
 | }; | 
 |  | 
 | class PragmaAnnotateHandler : public PragmaHandler { | 
 | public: | 
 |   PragmaAnnotateHandler() : PragmaHandler("enable_annotate") { } | 
 |  | 
 |   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, | 
 |                     Token &PragmaTok) override { | 
 |  | 
 |     Token Tok; | 
 |     PP.LexUnexpandedToken(Tok); | 
 |     if (Tok.isNot(tok::eod)) | 
 |       PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; | 
 |  | 
 |     if (HandledDecl) { | 
 |       DiagnosticsEngine &D = PP.getDiagnostics(); | 
 |       unsigned ID = D.getCustomDiagID( | 
 |         DiagnosticsEngine::Error, | 
 |         "#pragma enable_annotate not allowed after declarations"); | 
 |       D.Report(PragmaTok.getLocation(), ID); | 
 |     } | 
 |  | 
 |     EnableAnnotate = true; | 
 |   } | 
 | }; | 
 |  | 
 | } | 
 |  | 
 | static FrontendPluginRegistry::Add<AnnotateFunctionsAction> | 
 | X("annotate-fns", "annotate functions"); | 
 |  | 
 | static PragmaHandlerRegistry::Add<PragmaAnnotateHandler> | 
 | Y("enable_annotate","enable annotation"); |