AnnotateFunctions.cpp 2.6 KB

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