Config.h 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. // This file defines the names used by GC infrastructure.
  5. // TODO: Restructure the name determination to use fully qualified names (ala,
  6. // blink::Foo) so that the plugin can be enabled for all of chromium. Doing so
  7. // would allow us to catch errors with structures outside of blink that might
  8. // have unsafe pointers to GC allocated blink structures.
  9. #ifndef TOOLS_BLINK_GC_PLUGIN_CONFIG_H_
  10. #define TOOLS_BLINK_GC_PLUGIN_CONFIG_H_
  11. #include <cassert>
  12. #include "RecordInfo.h"
  13. #include "clang/AST/AST.h"
  14. #include "clang/AST/Attr.h"
  15. extern const char kNewOperatorName[];
  16. extern const char kCreateName[];
  17. extern const char kTraceName[];
  18. extern const char kFinalizeName[];
  19. extern const char kTraceAfterDispatchName[];
  20. extern const char kRegisterWeakMembersName[];
  21. extern const char kHeapAllocatorName[];
  22. extern const char kTraceIfNeededName[];
  23. extern const char kVisitorDispatcherName[];
  24. extern const char kVisitorVarName[];
  25. extern const char kAdjustAndMarkName[];
  26. extern const char kIsHeapObjectAliveName[];
  27. extern const char kConstIteratorName[];
  28. extern const char kIteratorName[];
  29. extern const char kConstReverseIteratorName[];
  30. extern const char kReverseIteratorName[];
  31. class Config {
  32. private:
  33. // Checks that the namespace matches the expected namespace and that the type
  34. // takes at least |expected_minimum_arg_count| template arguments. If both
  35. // requirements are fulfilled, populates |args| with the first
  36. // |expected_minimum_arg_count| template arguments. Verifying only the minimum
  37. // expected argument keeps the plugin resistant to changes in the type
  38. // definitions (to some extent)
  39. static bool VerifyNamespaceAndArgCount(std::string expected_ns_name,
  40. int expected_minimum_arg_count,
  41. llvm::StringRef ns_name,
  42. RecordInfo* info,
  43. RecordInfo::TemplateArgs* args) {
  44. return (ns_name == expected_ns_name) &&
  45. info->GetTemplateArgs(expected_minimum_arg_count, args);
  46. }
  47. public:
  48. static bool IsMember(llvm::StringRef name,
  49. llvm::StringRef ns_name,
  50. RecordInfo* info,
  51. RecordInfo::TemplateArgs* args) {
  52. if (name == "Member") {
  53. return VerifyNamespaceAndArgCount("blink", 1, ns_name, info, args);
  54. }
  55. if (name == "BasicMember") {
  56. if (!VerifyNamespaceAndArgCount("cppgc", 2, ns_name, info, args))
  57. return false;
  58. return (*args)[1]->getAsRecordDecl()->getName() == "StrongMemberTag";
  59. }
  60. return false;
  61. }
  62. static bool IsWeakMember(llvm::StringRef name,
  63. llvm::StringRef ns_name,
  64. RecordInfo* info,
  65. RecordInfo::TemplateArgs* args) {
  66. if (name == "WeakMember") {
  67. return VerifyNamespaceAndArgCount("blink", 1, ns_name, info, args);
  68. }
  69. if (name == "BasicMember") {
  70. if (!VerifyNamespaceAndArgCount("cppgc", 2, ns_name, info, args))
  71. return false;
  72. return (*args)[1]->getAsRecordDecl()->getName() == "WeakMemberTag";
  73. }
  74. return false;
  75. }
  76. static bool IsPersistent(llvm::StringRef name,
  77. llvm::StringRef ns_name,
  78. RecordInfo* info,
  79. RecordInfo::TemplateArgs* args) {
  80. if ((name == "Persistent") || (name == "WeakPersistent")) {
  81. return VerifyNamespaceAndArgCount("blink", 1, ns_name, info, args);
  82. }
  83. if (name == "BasicPersistent") {
  84. return VerifyNamespaceAndArgCount("cppgc", 1, ns_name, info, args);
  85. }
  86. return false;
  87. }
  88. static bool IsCrossThreadPersistent(llvm::StringRef name,
  89. llvm::StringRef ns_name,
  90. RecordInfo* info,
  91. RecordInfo::TemplateArgs* args) {
  92. if ((name == "CrossThreadPersistent") ||
  93. (name == "CrossThreadWeakPersistent")) {
  94. return VerifyNamespaceAndArgCount("blink", 1, ns_name, info, args);
  95. }
  96. if (name == "BasicCrossThreadPersistent") {
  97. return VerifyNamespaceAndArgCount("cppgc", 1, ns_name, info, args);
  98. }
  99. return false;
  100. }
  101. static bool IsRefPtr(llvm::StringRef name) { return name == "scoped_refptr"; }
  102. static bool IsWeakPtr(llvm::StringRef name) { return name == "WeakPtr"; }
  103. static bool IsRefOrWeakPtr(llvm::StringRef name) {
  104. return IsRefPtr(name) || IsWeakPtr(name);
  105. }
  106. static bool IsUniquePtr(llvm::StringRef name) {
  107. return name == "unique_ptr";
  108. }
  109. static bool IsTraceWrapperV8Reference(llvm::StringRef name,
  110. llvm::StringRef ns_name,
  111. RecordInfo* info,
  112. RecordInfo::TemplateArgs* args) {
  113. return name == "TraceWrapperV8Reference" &&
  114. VerifyNamespaceAndArgCount("blink", 1, ns_name, info, args);
  115. }
  116. static bool IsWTFCollection(llvm::StringRef name) {
  117. return name == "Vector" ||
  118. name == "Deque" ||
  119. name == "HashSet" ||
  120. name == "LinkedHashSet" ||
  121. name == "HashCountedSet" ||
  122. name == "HashMap";
  123. }
  124. static bool IsGCCollection(llvm::StringRef name) {
  125. return name == "HeapVector" || name == "HeapDeque" ||
  126. name == "HeapHashSet" || name == "HeapLinkedHashSet" ||
  127. name == "HeapHashCountedSet" || name == "HeapHashMap";
  128. }
  129. static bool IsHashMap(llvm::StringRef name) {
  130. return name == "HashMap" || name == "HeapHashMap";
  131. }
  132. // Assumes name is a valid collection name.
  133. static size_t CollectionDimension(llvm::StringRef name) {
  134. return (IsHashMap(name) || name == "pair") ? 2 : 1;
  135. }
  136. static bool IsRefCountedBase(llvm::StringRef name) {
  137. return name == "RefCounted" ||
  138. name == "ThreadSafeRefCounted";
  139. }
  140. static bool IsGCSimpleBase(llvm::StringRef name) {
  141. return name == "GarbageCollected";
  142. }
  143. static bool IsGCMixinBase(llvm::StringRef name) {
  144. return name == "GarbageCollectedMixin";
  145. }
  146. static bool IsGCBase(llvm::StringRef name) {
  147. return IsGCSimpleBase(name) || IsGCMixinBase(name);
  148. }
  149. static bool IsIterator(llvm::StringRef name) {
  150. return name == kIteratorName || name == kConstIteratorName ||
  151. name == kReverseIteratorName || name == kConstReverseIteratorName;
  152. }
  153. // Returns true of the base classes that do not need a vtable entry for trace
  154. // because they cannot possibly initiate a GC during construction.
  155. static bool IsSafePolymorphicBase(llvm::StringRef name) {
  156. return IsGCBase(name) || IsRefCountedBase(name);
  157. }
  158. static bool IsAnnotated(const clang::Decl* decl, const std::string& anno) {
  159. clang::AnnotateAttr* attr = decl->getAttr<clang::AnnotateAttr>();
  160. return attr && (attr->getAnnotation() == anno);
  161. }
  162. static bool IsIgnoreAnnotated(const clang::Decl* decl) {
  163. return IsAnnotated(decl, "blink_gc_plugin_ignore");
  164. }
  165. static bool IsVisitor(llvm::StringRef name) { return name == "Visitor"; }
  166. static bool IsVisitorPtrType(const clang::QualType& formal_type) {
  167. if (!formal_type->isPointerType())
  168. return false;
  169. clang::CXXRecordDecl* pointee_type =
  170. formal_type->getPointeeType()->getAsCXXRecordDecl();
  171. if (!pointee_type)
  172. return false;
  173. if (!IsVisitor(pointee_type->getName()))
  174. return false;
  175. return true;
  176. }
  177. static bool IsVisitorDispatcherType(const clang::QualType& formal_type) {
  178. if (const clang::SubstTemplateTypeParmType* subst_type =
  179. clang::dyn_cast<clang::SubstTemplateTypeParmType>(
  180. formal_type.getTypePtr())) {
  181. if (IsVisitorPtrType(subst_type->getReplacementType())) {
  182. // VisitorDispatcher template parameter substituted to Visitor*.
  183. return true;
  184. }
  185. } else if (const clang::TemplateTypeParmType* parm_type =
  186. clang::dyn_cast<clang::TemplateTypeParmType>(
  187. formal_type.getTypePtr())) {
  188. if (parm_type->getDecl()->getName() == kVisitorDispatcherName) {
  189. // Unresolved, but its parameter name is VisitorDispatcher.
  190. return true;
  191. }
  192. }
  193. return IsVisitorPtrType(formal_type);
  194. }
  195. enum TraceMethodType {
  196. NOT_TRACE_METHOD,
  197. TRACE_METHOD,
  198. TRACE_AFTER_DISPATCH_METHOD,
  199. };
  200. static TraceMethodType GetTraceMethodType(const clang::FunctionDecl* method) {
  201. if (method->getNumParams() != 1)
  202. return NOT_TRACE_METHOD;
  203. const std::string& name = method->getNameAsString();
  204. if (name != kTraceName && name != kTraceAfterDispatchName)
  205. return NOT_TRACE_METHOD;
  206. const clang::QualType& formal_type = method->getParamDecl(0)->getType();
  207. if (!IsVisitorPtrType(formal_type)) {
  208. return NOT_TRACE_METHOD;
  209. }
  210. if (name == kTraceName)
  211. return TRACE_METHOD;
  212. if (name == kTraceAfterDispatchName)
  213. return TRACE_AFTER_DISPATCH_METHOD;
  214. assert(false && "Should not reach here");
  215. return NOT_TRACE_METHOD;
  216. }
  217. static bool IsTraceMethod(const clang::FunctionDecl* method) {
  218. return GetTraceMethodType(method) != NOT_TRACE_METHOD;
  219. }
  220. static bool IsTraceWrappersMethod(const clang::FunctionDecl* method);
  221. static bool StartsWith(const std::string& str, const std::string& prefix) {
  222. if (prefix.size() > str.size())
  223. return false;
  224. return str.compare(0, prefix.size(), prefix) == 0;
  225. }
  226. static bool EndsWith(const std::string& str, const std::string& suffix) {
  227. if (suffix.size() > str.size())
  228. return false;
  229. return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
  230. }
  231. // Test if a template specialization is an instantiation.
  232. static bool IsTemplateInstantiation(clang::CXXRecordDecl* record);
  233. };
  234. #endif // TOOLS_BLINK_GC_PLUGIN_CONFIG_H_