xref: /openbsd-src/gnu/llvm/clang/examples/AnnotateFunctions/AnnotateFunctions.cpp (revision a9ac8606c53d55cee9c3a39778b249c51df111ef)
1e5dd7070Spatrick //===- AnnotateFunctions.cpp ----------------------------------------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // Example clang plugin which adds an annotation to every function in
10e5dd7070Spatrick // translation units that start with #pragma enable_annotate.
11e5dd7070Spatrick //
12e5dd7070Spatrick //===----------------------------------------------------------------------===//
13e5dd7070Spatrick 
14e5dd7070Spatrick #include "clang/Frontend/FrontendPluginRegistry.h"
15e5dd7070Spatrick #include "clang/AST/AST.h"
16e5dd7070Spatrick #include "clang/AST/ASTConsumer.h"
17e5dd7070Spatrick #include "clang/AST/Attr.h"
18e5dd7070Spatrick #include "clang/Lex/Preprocessor.h"
19e5dd7070Spatrick #include "clang/Lex/LexDiagnostic.h"
20e5dd7070Spatrick using namespace clang;
21e5dd7070Spatrick 
22e5dd7070Spatrick namespace {
23e5dd7070Spatrick 
24e5dd7070Spatrick static bool EnableAnnotate = false;
25e5dd7070Spatrick static bool HandledDecl = false;
26e5dd7070Spatrick 
27e5dd7070Spatrick class AnnotateFunctionsConsumer : public ASTConsumer {
28e5dd7070Spatrick public:
HandleTopLevelDecl(DeclGroupRef DG)29e5dd7070Spatrick   bool HandleTopLevelDecl(DeclGroupRef DG) override {
30e5dd7070Spatrick     HandledDecl = true;
31e5dd7070Spatrick     if (!EnableAnnotate)
32e5dd7070Spatrick       return true;
33e5dd7070Spatrick     for (auto D : DG)
34e5dd7070Spatrick       if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
35*a9ac8606Spatrick         FD->addAttr(AnnotateAttr::CreateImplicit(
36*a9ac8606Spatrick             FD->getASTContext(), "example_annotation", nullptr, 0));
37e5dd7070Spatrick     return true;
38e5dd7070Spatrick   }
39e5dd7070Spatrick };
40e5dd7070Spatrick 
41e5dd7070Spatrick class AnnotateFunctionsAction : public PluginASTAction {
42e5dd7070Spatrick public:
CreateASTConsumer(CompilerInstance & CI,llvm::StringRef)43e5dd7070Spatrick   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
44e5dd7070Spatrick                                                  llvm::StringRef) override {
45e5dd7070Spatrick     return std::make_unique<AnnotateFunctionsConsumer>();
46e5dd7070Spatrick   }
47e5dd7070Spatrick 
ParseArgs(const CompilerInstance & CI,const std::vector<std::string> & args)48e5dd7070Spatrick   bool ParseArgs(const CompilerInstance &CI,
49e5dd7070Spatrick                  const std::vector<std::string> &args) override {
50e5dd7070Spatrick     return true;
51e5dd7070Spatrick   }
52e5dd7070Spatrick 
getActionType()53e5dd7070Spatrick   PluginASTAction::ActionType getActionType() override {
54e5dd7070Spatrick     return AddBeforeMainAction;
55e5dd7070Spatrick   }
56e5dd7070Spatrick };
57e5dd7070Spatrick 
58e5dd7070Spatrick class PragmaAnnotateHandler : public PragmaHandler {
59e5dd7070Spatrick public:
PragmaAnnotateHandler()60e5dd7070Spatrick   PragmaAnnotateHandler() : PragmaHandler("enable_annotate") { }
61e5dd7070Spatrick 
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & PragmaTok)62e5dd7070Spatrick   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
63e5dd7070Spatrick                     Token &PragmaTok) override {
64e5dd7070Spatrick 
65e5dd7070Spatrick     Token Tok;
66e5dd7070Spatrick     PP.LexUnexpandedToken(Tok);
67e5dd7070Spatrick     if (Tok.isNot(tok::eod))
68e5dd7070Spatrick       PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
69e5dd7070Spatrick 
70e5dd7070Spatrick     if (HandledDecl) {
71e5dd7070Spatrick       DiagnosticsEngine &D = PP.getDiagnostics();
72e5dd7070Spatrick       unsigned ID = D.getCustomDiagID(
73e5dd7070Spatrick         DiagnosticsEngine::Error,
74e5dd7070Spatrick         "#pragma enable_annotate not allowed after declarations");
75e5dd7070Spatrick       D.Report(PragmaTok.getLocation(), ID);
76e5dd7070Spatrick     }
77e5dd7070Spatrick 
78e5dd7070Spatrick     EnableAnnotate = true;
79e5dd7070Spatrick   }
80e5dd7070Spatrick };
81e5dd7070Spatrick 
82e5dd7070Spatrick }
83e5dd7070Spatrick 
84e5dd7070Spatrick static FrontendPluginRegistry::Add<AnnotateFunctionsAction>
85e5dd7070Spatrick X("annotate-fns", "annotate functions");
86e5dd7070Spatrick 
87e5dd7070Spatrick static PragmaHandlerRegistry::Add<PragmaAnnotateHandler>
88e5dd7070Spatrick Y("enable_annotate","enable annotation");
89