//===- 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(D)) FD->addAttr(AnnotateAttr::CreateImplicit( FD->getASTContext(), "example_annotation", nullptr, 0)); return true; } }; class AnnotateFunctionsAction : public PluginASTAction { public: std::unique_ptr CreateASTConsumer(CompilerInstance &CI, llvm::StringRef) override { return std::make_unique(); } bool ParseArgs(const CompilerInstance &CI, const std::vector &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 X("annotate-fns", "annotate functions"); static PragmaHandlerRegistry::Add Y("enable_annotate","enable annotation");