Config.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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 "clang/AST/AST.h"
  13. #include "clang/AST/Attr.h"
  14. extern const char kNewOperatorName[];
  15. extern const char kCreateName[];
  16. extern const char kTraceName[];
  17. extern const char kFinalizeName[];
  18. extern const char kTraceAfterDispatchName[];
  19. extern const char kRegisterWeakMembersName[];
  20. extern const char kHeapAllocatorName[];
  21. extern const char kTraceIfNeededName[];
  22. extern const char kVisitorDispatcherName[];
  23. extern const char kVisitorVarName[];
  24. extern const char kAdjustAndMarkName[];
  25. extern const char kIsHeapObjectAliveName[];
  26. extern const char kConstIteratorName[];
  27. extern const char kIteratorName[];
  28. extern const char kConstReverseIteratorName[];
  29. extern const char kReverseIteratorName[];
  30. class Config {
  31. public:
  32. static bool IsMember(llvm::StringRef name) {
  33. return name == "Member";
  34. }
  35. static bool IsWeakMember(llvm::StringRef name) {
  36. return name == "WeakMember";
  37. }
  38. static bool IsMemberHandle(llvm::StringRef name) {
  39. return IsMember(name) ||
  40. IsWeakMember(name);
  41. }
  42. static bool IsPersistent(llvm::StringRef name) {
  43. return name == "Persistent" ||
  44. name == "WeakPersistent" ;
  45. }
  46. static bool IsCrossThreadPersistent(llvm::StringRef name) {
  47. return name == "CrossThreadPersistent" ||
  48. name == "CrossThreadWeakPersistent" ;
  49. }
  50. static bool IsRefPtr(llvm::StringRef name) { return name == "scoped_refptr"; }
  51. static bool IsWeakPtr(llvm::StringRef name) { return name == "WeakPtr"; }
  52. static bool IsRefOrWeakPtr(llvm::StringRef name) {
  53. return IsRefPtr(name) || IsWeakPtr(name);
  54. }
  55. static bool IsUniquePtr(llvm::StringRef name) {
  56. return name == "unique_ptr";
  57. }
  58. static bool IsTraceWrapperV8Reference(llvm::StringRef name) {
  59. return name == "TraceWrapperV8Reference";
  60. }
  61. static bool IsWTFCollection(llvm::StringRef name) {
  62. return name == "Vector" ||
  63. name == "Deque" ||
  64. name == "HashSet" ||
  65. name == "ListHashSet" ||
  66. name == "LinkedHashSet" ||
  67. name == "HashCountedSet" ||
  68. name == "HashMap";
  69. }
  70. static bool IsGCCollection(llvm::StringRef name) {
  71. return name == "HeapVector" || name == "HeapDeque" ||
  72. name == "HeapHashSet" || name == "HeapListHashSet" ||
  73. name == "HeapLinkedHashSet" || name == "HeapHashCountedSet" ||
  74. name == "HeapHashMap";
  75. }
  76. static bool IsGCCollectionWithUnsafeIterator(llvm::StringRef name) {
  77. if (!IsGCCollection(name))
  78. return false;
  79. // The list hash set iterators refer to the set, not the
  80. // backing store and are consequently safe.
  81. if (name == "HeapListHashSet" || name == "PersistentHeapListHashSet")
  82. return false;
  83. return true;
  84. }
  85. static bool IsHashMap(llvm::StringRef name) {
  86. return name == "HashMap" ||
  87. name == "HeapHashMap" ||
  88. name == "PersistentHeapHashMap";
  89. }
  90. // Assumes name is a valid collection name.
  91. static size_t CollectionDimension(llvm::StringRef name) {
  92. return (IsHashMap(name) || name == "pair") ? 2 : 1;
  93. }
  94. static bool IsRefCountedBase(llvm::StringRef name) {
  95. return name == "RefCounted" ||
  96. name == "ThreadSafeRefCounted";
  97. }
  98. static bool IsGCSimpleBase(llvm::StringRef name) {
  99. return name == "GarbageCollected";
  100. }
  101. static bool IsGCMixinBase(llvm::StringRef name) {
  102. return name == "GarbageCollectedMixin";
  103. }
  104. static bool IsGCBase(llvm::StringRef name) {
  105. return IsGCSimpleBase(name) || IsGCMixinBase(name);
  106. }
  107. static bool IsIterator(llvm::StringRef name) {
  108. return name == kIteratorName || name == kConstIteratorName ||
  109. name == kReverseIteratorName || name == kConstReverseIteratorName;
  110. }
  111. // Returns true of the base classes that do not need a vtable entry for trace
  112. // because they cannot possibly initiate a GC during construction.
  113. static bool IsSafePolymorphicBase(llvm::StringRef name) {
  114. return IsGCBase(name) || IsRefCountedBase(name);
  115. }
  116. static bool IsAnnotated(clang::Decl* decl, const std::string& anno) {
  117. clang::AnnotateAttr* attr = decl->getAttr<clang::AnnotateAttr>();
  118. return attr && (attr->getAnnotation() == anno);
  119. }
  120. static bool IsStackAnnotated(clang::Decl* decl) {
  121. return IsAnnotated(decl, "blink_stack_allocated");
  122. }
  123. static bool IsIgnoreAnnotated(clang::Decl* decl) {
  124. return IsAnnotated(decl, "blink_gc_plugin_ignore");
  125. }
  126. static bool IsIgnoreCycleAnnotated(clang::Decl* decl) {
  127. return IsAnnotated(decl, "blink_gc_plugin_ignore_cycle") ||
  128. IsIgnoreAnnotated(decl);
  129. }
  130. static bool IsVisitor(llvm::StringRef name) {
  131. return name == "Visitor" || name == "VisitorHelper";
  132. }
  133. static bool IsVisitorPtrType(const clang::QualType& formal_type) {
  134. if (!formal_type->isPointerType())
  135. return false;
  136. clang::CXXRecordDecl* pointee_type =
  137. formal_type->getPointeeType()->getAsCXXRecordDecl();
  138. if (!pointee_type)
  139. return false;
  140. if (!IsVisitor(pointee_type->getName()))
  141. return false;
  142. return true;
  143. }
  144. static bool IsVisitorDispatcherType(const clang::QualType& formal_type) {
  145. if (const clang::SubstTemplateTypeParmType* subst_type =
  146. clang::dyn_cast<clang::SubstTemplateTypeParmType>(
  147. formal_type.getTypePtr())) {
  148. if (IsVisitorPtrType(subst_type->getReplacementType())) {
  149. // VisitorDispatcher template parameter substituted to Visitor*.
  150. return true;
  151. }
  152. } else if (const clang::TemplateTypeParmType* parm_type =
  153. clang::dyn_cast<clang::TemplateTypeParmType>(
  154. formal_type.getTypePtr())) {
  155. if (parm_type->getDecl()->getName() == kVisitorDispatcherName) {
  156. // Unresolved, but its parameter name is VisitorDispatcher.
  157. return true;
  158. }
  159. }
  160. return IsVisitorPtrType(formal_type);
  161. }
  162. enum TraceMethodType {
  163. NOT_TRACE_METHOD,
  164. TRACE_METHOD,
  165. TRACE_AFTER_DISPATCH_METHOD,
  166. };
  167. static TraceMethodType GetTraceMethodType(const clang::FunctionDecl* method) {
  168. if (method->getNumParams() != 1)
  169. return NOT_TRACE_METHOD;
  170. const std::string& name = method->getNameAsString();
  171. if (name != kTraceName && name != kTraceAfterDispatchName)
  172. return NOT_TRACE_METHOD;
  173. const clang::QualType& formal_type = method->getParamDecl(0)->getType();
  174. if (!IsVisitorPtrType(formal_type)) {
  175. return NOT_TRACE_METHOD;
  176. }
  177. if (name == kTraceName)
  178. return TRACE_METHOD;
  179. if (name == kTraceAfterDispatchName)
  180. return TRACE_AFTER_DISPATCH_METHOD;
  181. assert(false && "Should not reach here");
  182. return NOT_TRACE_METHOD;
  183. }
  184. static bool IsTraceMethod(const clang::FunctionDecl* method) {
  185. return GetTraceMethodType(method) != NOT_TRACE_METHOD;
  186. }
  187. static bool IsTraceWrappersMethod(const clang::FunctionDecl* method);
  188. static bool StartsWith(const std::string& str, const std::string& prefix) {
  189. if (prefix.size() > str.size())
  190. return false;
  191. return str.compare(0, prefix.size(), prefix) == 0;
  192. }
  193. static bool EndsWith(const std::string& str, const std::string& suffix) {
  194. if (suffix.size() > str.size())
  195. return false;
  196. return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
  197. }
  198. // Test if a template specialization is an instantiation.
  199. static bool IsTemplateInstantiation(clang::CXXRecordDecl* record);
  200. };
  201. #endif // TOOLS_BLINK_GC_PLUGIN_CONFIG_H_