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/AST/Attr.h"
18#include "clang/Lex/Preprocessor.h"
19#include "clang/Lex/LexDiagnostic.h"
20using namespace clang;
21
22namespace {
23
24static bool EnableAnnotate = false;
25static bool HandledDecl = false;
26
27class AnnotateFunctionsConsumer : public ASTConsumer {
28public:
29 bool HandleTopLevelDecl(DeclGroupRef DG) override {
30 HandledDecl = true;
31 if (!EnableAnnotate)
32 return true;
33 for (auto D : DG)
34 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: D))
35 FD->addAttr(A: AnnotateAttr::CreateImplicit(
36 Ctx&: FD->getASTContext(), Annotation: "example_annotation", Args: nullptr, ArgsSize: 0));
37 return true;
38 }
39};
40
41class AnnotateFunctionsAction : public PluginASTAction {
42public:
43 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
44 llvm::StringRef) override {
45 return std::make_unique<AnnotateFunctionsConsumer>();
46 }
47
48 bool ParseArgs(const CompilerInstance &CI,
49 const std::vector<std::string> &args) override {
50 return true;
51 }
52
53 PluginASTAction::ActionType getActionType() override {
54 return AddBeforeMainAction;
55 }
56};
57
58class PragmaAnnotateHandler : public PragmaHandler {
59public:
60 PragmaAnnotateHandler() : PragmaHandler("enable_annotate") { }
61
62 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
63 Token &PragmaTok) override {
64
65 Token Tok;
66 PP.LexUnexpandedToken(Result&: Tok);
67 if (Tok.isNot(K: tok::eod))
68 PP.Diag(Tok, DiagID: diag::ext_pp_extra_tokens_at_eol) << "pragma";
69
70 if (HandledDecl) {
71 DiagnosticsEngine &D = PP.getDiagnostics();
72 unsigned ID = D.getCustomDiagID(
73 L: DiagnosticsEngine::Error,
74 FormatString: "#pragma enable_annotate not allowed after declarations");
75 D.Report(Loc: PragmaTok.getLocation(), DiagID: ID);
76 }
77
78 EnableAnnotate = true;
79 }
80};
81
82}
83
84static FrontendPluginRegistry::Add<AnnotateFunctionsAction>
85X("annotate-fns", "annotate functions");
86
87static PragmaHandlerRegistry::Add<PragmaAnnotateHandler>
88Y("enable_annotate","enable annotation");
89