xref: /llvm-project/clang/examples/AnnotateFunctions/AnnotateFunctions.cpp (revision 2618247c61c25cf9bd4cb315ee51cff2b3ab3add)
16c78974bSJohn Brawn //===- AnnotateFunctions.cpp ----------------------------------------------===//
26c78974bSJohn Brawn //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66c78974bSJohn Brawn //
76c78974bSJohn Brawn //===----------------------------------------------------------------------===//
86c78974bSJohn Brawn //
98e62db32SJohn Brawn // Example clang plugin which adds an annotation to every function in
108e62db32SJohn Brawn // translation units that start with #pragma enable_annotate.
116c78974bSJohn Brawn //
126c78974bSJohn Brawn //===----------------------------------------------------------------------===//
136c78974bSJohn Brawn 
146c78974bSJohn Brawn #include "clang/Frontend/FrontendPluginRegistry.h"
156c78974bSJohn Brawn #include "clang/AST/AST.h"
166c78974bSJohn Brawn #include "clang/AST/ASTConsumer.h"
17f7e7a5f1SDavid Green #include "clang/AST/Attr.h"
188e62db32SJohn Brawn #include "clang/Lex/Preprocessor.h"
198e62db32SJohn Brawn #include "clang/Lex/LexDiagnostic.h"
206c78974bSJohn Brawn using namespace clang;
216c78974bSJohn Brawn 
226c78974bSJohn Brawn namespace {
236c78974bSJohn Brawn 
248e62db32SJohn Brawn static bool EnableAnnotate = false;
258e62db32SJohn Brawn static bool HandledDecl = false;
268e62db32SJohn Brawn 
276c78974bSJohn Brawn class AnnotateFunctionsConsumer : public ASTConsumer {
286c78974bSJohn Brawn public:
HandleTopLevelDecl(DeclGroupRef DG)296c78974bSJohn Brawn   bool HandleTopLevelDecl(DeclGroupRef DG) override {
308e62db32SJohn Brawn     HandledDecl = true;
318e62db32SJohn Brawn     if (!EnableAnnotate)
328e62db32SJohn Brawn       return true;
336c78974bSJohn Brawn     for (auto D : DG)
346c78974bSJohn Brawn       if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
35*2618247cSTyker         FD->addAttr(AnnotateAttr::CreateImplicit(
36*2618247cSTyker             FD->getASTContext(), "example_annotation", nullptr, 0));
376c78974bSJohn Brawn     return true;
386c78974bSJohn Brawn   }
396c78974bSJohn Brawn };
406c78974bSJohn Brawn 
416c78974bSJohn Brawn class AnnotateFunctionsAction : public PluginASTAction {
426c78974bSJohn Brawn public:
CreateASTConsumer(CompilerInstance & CI,llvm::StringRef)436c78974bSJohn Brawn   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
446c78974bSJohn Brawn                                                  llvm::StringRef) override {
452b3d49b6SJonas Devlieghere     return std::make_unique<AnnotateFunctionsConsumer>();
466c78974bSJohn Brawn   }
476c78974bSJohn Brawn 
ParseArgs(const CompilerInstance & CI,const std::vector<std::string> & args)486c78974bSJohn Brawn   bool ParseArgs(const CompilerInstance &CI,
496c78974bSJohn Brawn                  const std::vector<std::string> &args) override {
506c78974bSJohn Brawn     return true;
516c78974bSJohn Brawn   }
526c78974bSJohn Brawn 
getActionType()536c78974bSJohn Brawn   PluginASTAction::ActionType getActionType() override {
546c78974bSJohn Brawn     return AddBeforeMainAction;
556c78974bSJohn Brawn   }
566c78974bSJohn Brawn };
576c78974bSJohn Brawn 
588e62db32SJohn Brawn class PragmaAnnotateHandler : public PragmaHandler {
598e62db32SJohn Brawn public:
PragmaAnnotateHandler()608e62db32SJohn Brawn   PragmaAnnotateHandler() : PragmaHandler("enable_annotate") { }
618e62db32SJohn Brawn 
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & PragmaTok)62ddde0ec1SJoel E. Denny   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
638e62db32SJohn Brawn                     Token &PragmaTok) override {
648e62db32SJohn Brawn 
658e62db32SJohn Brawn     Token Tok;
668e62db32SJohn Brawn     PP.LexUnexpandedToken(Tok);
678e62db32SJohn Brawn     if (Tok.isNot(tok::eod))
688e62db32SJohn Brawn       PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
698e62db32SJohn Brawn 
708e62db32SJohn Brawn     if (HandledDecl) {
718e62db32SJohn Brawn       DiagnosticsEngine &D = PP.getDiagnostics();
728e62db32SJohn Brawn       unsigned ID = D.getCustomDiagID(
738e62db32SJohn Brawn         DiagnosticsEngine::Error,
748e62db32SJohn Brawn         "#pragma enable_annotate not allowed after declarations");
758e62db32SJohn Brawn       D.Report(PragmaTok.getLocation(), ID);
768e62db32SJohn Brawn     }
778e62db32SJohn Brawn 
788e62db32SJohn Brawn     EnableAnnotate = true;
798e62db32SJohn Brawn   }
808e62db32SJohn Brawn };
818e62db32SJohn Brawn 
826c78974bSJohn Brawn }
836c78974bSJohn Brawn 
846c78974bSJohn Brawn static FrontendPluginRegistry::Add<AnnotateFunctionsAction>
856c78974bSJohn Brawn X("annotate-fns", "annotate functions");
868e62db32SJohn Brawn 
878e62db32SJohn Brawn static PragmaHandlerRegistry::Add<PragmaAnnotateHandler>
888e62db32SJohn Brawn Y("enable_annotate","enable annotation");
89