RecyclerChecker.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. #include <unordered_set>
  7. #include <queue>
  8. #include "clang/Frontend/FrontendPluginRegistry.h"
  9. #include "clang/AST/AST.h"
  10. #include "clang/AST/ASTConsumer.h"
  11. #include "clang/AST/RecursiveASTVisitor.h"
  12. #include "clang/Frontend/CompilerInstance.h"
  13. #include "clang/Rewrite/Core/Rewriter.h"
  14. #include "clang/Sema/Sema.h"
  15. #include "Helpers.h"
  16. using namespace std;
  17. using namespace clang;
  18. // To record seen allocators with a Type
  19. //
  20. enum AllocationTypes
  21. {
  22. Unknown = 0x0, // e.g. template dependent
  23. NonRecycler = 0x1, // Heap, Arena, JitArena, ...
  24. Recycler = 0x2, // Recycler
  25. WriteBarrier = 0x4, // Recycler write barrier
  26. RecyclerWriteBarrier = Recycler | WriteBarrier,
  27. };
  28. class MainVisitor:
  29. public RecursiveASTVisitor<MainVisitor>
  30. {
  31. private:
  32. CompilerInstance& _compilerInstance;
  33. ASTContext& _context;
  34. Rewriter _rewriter;
  35. bool _fix; // whether user requested to fix missing annotations
  36. bool _fixed; // whether this plugin committed any annotation fixes
  37. // For emitting checker errors
  38. DiagnosticsEngine& _diagEngine;
  39. unsigned _diagUnbarrieredField;
  40. unsigned _diagIllegalBarrierCast;
  41. bool _barrierTypeDefined;
  42. map<string, set<string>> _allocatorTypeMap;
  43. set<string> _pointerClasses;
  44. set<string> _barrieredClasses;
  45. map<const Type*, int> _allocationTypes; // {type -> AllocationTypes}
  46. public:
  47. MainVisitor(CompilerInstance& compilerInstance, ASTContext& context, bool fix);
  48. const ASTContext& getContext() const { return _context; }
  49. const CompilerInstance& getCompilerInstance() const { return _compilerInstance; }
  50. bool VisitCXXRecordDecl(CXXRecordDecl* recordDecl);
  51. bool VisitFunctionDecl(FunctionDecl* functionDecl);
  52. void RecordAllocation(QualType qtype, AllocationTypes allocationType);
  53. void RecordRecyclerAllocation(
  54. const string& allocationFunction, const string& type);
  55. void Inspect();
  56. bool ApplyFix();
  57. void ReportUnbarriedField(SourceLocation location);
  58. void ReportIllegalBarrierCast(SourceLocation location);
  59. private:
  60. template <class Set, class DumpItemFunc>
  61. void dump(const char* name, const Set& set, const DumpItemFunc& func);
  62. template <class Item>
  63. void dump(const char* name, const set<Item>& set);
  64. void dump(const char* name, const unordered_set<const Type*> set);
  65. template <class PushFieldType>
  66. void ProcessUnbarrieredFields(CXXRecordDecl* recordDecl, const PushFieldType& pushFieldType);
  67. bool MatchType(const string& type, const char* source, const char** pSourceEnd);
  68. const char* GetFieldTypeAnnotation(QualType qtype);
  69. void DiagReport(SourceLocation location, unsigned diagId);
  70. };
  71. class CheckAllocationsInFunctionVisitor:
  72. public RecursiveASTVisitor<CheckAllocationsInFunctionVisitor>
  73. {
  74. public:
  75. CheckAllocationsInFunctionVisitor(
  76. MainVisitor* mainVisitor, FunctionDecl* functionDecl)
  77. : _mainVisitor(mainVisitor), _functionDecl(functionDecl)
  78. {}
  79. bool VisitCXXNewExpr(CXXNewExpr* newExpression);
  80. bool VisitCallExpr(CallExpr* callExpr);
  81. #define IMPLEMENT_VISIT_CAST(Expr) \
  82. bool Visit##Expr(Expr *cast) { return CommonVisitCastExpr(cast); }
  83. IMPLEMENT_VISIT_CAST(CStyleCastExpr)
  84. IMPLEMENT_VISIT_CAST(CXXFunctionalCastExpr)
  85. IMPLEMENT_VISIT_CAST(CXXConstCastExpr)
  86. IMPLEMENT_VISIT_CAST(CXXDynamicCastExpr)
  87. IMPLEMENT_VISIT_CAST(CXXReinterpretCastExpr)
  88. IMPLEMENT_VISIT_CAST(CXXStaticCastExpr)
  89. #undef IMPLEMENT_VISIT_CAST
  90. private:
  91. MainVisitor* _mainVisitor;
  92. FunctionDecl* _functionDecl;
  93. template <class A0, class A1, class T>
  94. void VisitAllocate(const A0& getArg0, const A1& getArg1, const T& getAllocType);
  95. bool IsFieldPointer(const QualType& qtype, const char* alt = nullptr);
  96. bool CommonVisitCastExpr(CastExpr *cast);
  97. };
  98. class RecyclerCheckerConsumer: public ASTConsumer
  99. {
  100. private:
  101. CompilerInstance& _compilerInstance;
  102. bool _fix; // whether user requested to fix missing annotations
  103. public:
  104. RecyclerCheckerConsumer(CompilerInstance& compilerInstance, bool fix)
  105. : _compilerInstance(compilerInstance), _fix(fix)
  106. {}
  107. void HandleTranslationUnit(ASTContext& context);
  108. };
  109. class RecyclerCheckerAction: public PluginASTAction
  110. {
  111. private:
  112. bool _fix; // whether user requested to fix missing annotations
  113. public:
  114. RecyclerCheckerAction() : _fix(false) {}
  115. protected:
  116. std::unique_ptr<ASTConsumer> CreateASTConsumer(
  117. CompilerInstance& compilerInstance, llvm::StringRef) override;
  118. bool ParseArgs(
  119. const CompilerInstance& compilerInstance,
  120. const std::vector<std::string>& args) override;
  121. };