Roll src/third_party/WebKit f36d5e0:68b67cd (svn 193299:193303)
[chromium-blink-merge.git] / tools / clang / blink_gc_plugin / Config.h
blob02cbee9a922dc3671c9ff850c83bdd1f50315c75
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.
5 // This file defines the names used by GC infrastructure.
7 // TODO: Restructure the name determination to use fully qualified names (ala,
8 // blink::Foo) so that the plugin can be enabled for all of chromium. Doing so
9 // would allow us to catch errors with structures outside of blink that might
10 // have unsafe pointers to GC allocated blink structures.
12 #ifndef TOOLS_BLINK_GC_PLUGIN_CONFIG_H_
13 #define TOOLS_BLINK_GC_PLUGIN_CONFIG_H_
15 #include <cassert>
17 #include "clang/AST/AST.h"
18 #include "clang/AST/Attr.h"
20 const char kNewOperatorName[] = "operator new";
21 const char kCreateName[] = "create";
22 const char kTraceName[] = "trace";
23 const char kTraceImplName[] = "traceImpl";
24 const char kFinalizeName[] = "finalizeGarbageCollectedObject";
25 const char kTraceAfterDispatchName[] = "traceAfterDispatch";
26 const char kTraceAfterDispatchImplName[] = "traceAfterDispatchImpl";
27 const char kRegisterWeakMembersName[] = "registerWeakMembers";
28 const char kHeapAllocatorName[] = "HeapAllocator";
29 const char kTraceIfNeededName[] = "TraceIfNeeded";
30 const char kVisitorDispatcherName[] = "VisitorDispatcher";
31 const char kVisitorVarName[] = "visitor";
32 const char kAdjustAndMarkName[] = "adjustAndMark";
33 const char kIsHeapObjectAliveName[] = "isHeapObjectAlive";
35 class Config {
36 public:
37 static bool IsMember(const std::string& name) {
38 return name == "Member";
41 static bool IsWeakMember(const std::string& name) {
42 return name == "WeakMember";
45 static bool IsMemberHandle(const std::string& name) {
46 return IsMember(name) ||
47 IsWeakMember(name);
50 static bool IsPersistent(const std::string& name) {
51 return name == "Persistent";
54 static bool IsPersistentHandle(const std::string& name) {
55 return IsPersistent(name) ||
56 IsPersistentGCCollection(name);
59 static bool IsRawPtr(const std::string& name) {
60 return name == "RawPtr";
63 static bool IsRefPtr(const std::string& name) {
64 return name == "RefPtr";
67 static bool IsOwnPtr(const std::string& name) {
68 return name == "OwnPtr";
71 static bool IsWTFCollection(const std::string& name) {
72 return name == "Vector" ||
73 name == "Deque" ||
74 name == "HashSet" ||
75 name == "ListHashSet" ||
76 name == "LinkedHashSet" ||
77 name == "HashCountedSet" ||
78 name == "HashMap";
81 static bool IsGCCollection(const std::string& name) {
82 return name == "HeapVector" ||
83 name == "HeapDeque" ||
84 name == "HeapHashSet" ||
85 name == "HeapListHashSet" ||
86 name == "HeapLinkedHashSet" ||
87 name == "HeapHashCountedSet" ||
88 name == "HeapHashMap" ||
89 IsPersistentGCCollection(name);
92 static bool IsPersistentGCCollection(const std::string& name) {
93 return name == "PersistentHeapVector" ||
94 name == "PersistentHeapDeque" ||
95 name == "PersistentHeapHashSet" ||
96 name == "PersistentHeapListHashSet" ||
97 name == "PersistentHeapLinkedHashSet" ||
98 name == "PersistentHeapHashCountedSet" ||
99 name == "PersistentHeapHashMap";
102 static bool IsHashMap(const std::string& name) {
103 return name == "HashMap" ||
104 name == "HeapHashMap" ||
105 name == "PersistentHeapHashMap";
108 // Following http://crrev.com/369633033 (Blink r177436),
109 // ignore blink::ScriptWrappable's destructor.
110 // TODO: remove when its non-Oilpan destructor is removed.
111 static bool HasIgnorableDestructor(const std::string& ns,
112 const std::string& name) {
113 return ns == "blink" && name == "ScriptWrappable";
116 // Assumes name is a valid collection name.
117 static size_t CollectionDimension(const std::string& name) {
118 return (IsHashMap(name) || name == "pair") ? 2 : 1;
121 static bool IsDummyBase(const std::string& name) {
122 return name == "DummyBase";
125 static bool IsRefCountedBase(const std::string& name) {
126 return name == "RefCounted" ||
127 name == "ThreadSafeRefCounted";
130 static bool IsGCMixinBase(const std::string& name) {
131 return name == "GarbageCollectedMixin";
134 static bool IsGCFinalizedBase(const std::string& name) {
135 return name == "GarbageCollectedFinalized" ||
136 name == "RefCountedGarbageCollected" ||
137 name == "ThreadSafeRefCountedGarbageCollected";
140 static bool IsGCBase(const std::string& name) {
141 return name == "GarbageCollected" ||
142 IsGCFinalizedBase(name) ||
143 IsGCMixinBase(name);
146 // Returns true of the base classes that do not need a vtable entry for trace
147 // because they cannot possibly initiate a GC during construction.
148 static bool IsSafePolymorphicBase(const std::string& name) {
149 return IsGCBase(name) || IsDummyBase(name) || IsRefCountedBase(name);
152 static bool IsAnnotated(clang::Decl* decl, const std::string& anno) {
153 clang::AnnotateAttr* attr = decl->getAttr<clang::AnnotateAttr>();
154 return attr && (attr->getAnnotation() == anno);
157 static bool IsStackAnnotated(clang::Decl* decl) {
158 return IsAnnotated(decl, "blink_stack_allocated");
161 static bool IsIgnoreAnnotated(clang::Decl* decl) {
162 return IsAnnotated(decl, "blink_gc_plugin_ignore");
165 static bool IsIgnoreCycleAnnotated(clang::Decl* decl) {
166 return IsAnnotated(decl, "blink_gc_plugin_ignore_cycle") ||
167 IsIgnoreAnnotated(decl);
170 static bool IsVisitor(const std::string& name) {
171 return name == "Visitor" || name == "VisitorHelper";
174 static bool IsVisitorPtrType(const clang::QualType& formal_type) {
175 if (!formal_type->isPointerType())
176 return false;
178 clang::CXXRecordDecl* pointee_type =
179 formal_type->getPointeeType()->getAsCXXRecordDecl();
180 if (!pointee_type)
181 return false;
183 if (!IsVisitor(pointee_type->getName()))
184 return false;
186 return true;
189 static bool IsVisitorDispatcherType(const clang::QualType& formal_type) {
190 if (const clang::SubstTemplateTypeParmType* subst_type =
191 clang::dyn_cast<clang::SubstTemplateTypeParmType>(
192 formal_type.getTypePtr())) {
193 if (IsVisitorPtrType(subst_type->getReplacementType())) {
194 // VisitorDispatcher template parameter substituted to Visitor*.
195 return true;
197 } else if (const clang::TemplateTypeParmType* parm_type =
198 clang::dyn_cast<clang::TemplateTypeParmType>(
199 formal_type.getTypePtr())) {
200 if (parm_type->getDecl()->getName() == kVisitorDispatcherName) {
201 // Unresolved, but its parameter name is VisitorDispatcher.
202 return true;
206 return IsVisitorPtrType(formal_type);
209 enum TraceMethodType {
210 NOT_TRACE_METHOD,
211 TRACE_METHOD,
212 TRACE_AFTER_DISPATCH_METHOD,
213 TRACE_IMPL_METHOD,
214 TRACE_AFTER_DISPATCH_IMPL_METHOD
217 static TraceMethodType GetTraceMethodType(clang::FunctionDecl* method) {
218 if (method->getNumParams() != 1)
219 return NOT_TRACE_METHOD;
221 const std::string& name = method->getNameAsString();
222 if (name != kTraceName && name != kTraceAfterDispatchName &&
223 name != kTraceImplName && name != kTraceAfterDispatchImplName)
224 return NOT_TRACE_METHOD;
226 const clang::QualType& formal_type = method->getParamDecl(0)->getType();
227 if (name == kTraceImplName || name == kTraceAfterDispatchImplName) {
228 if (!IsVisitorDispatcherType(formal_type))
229 return NOT_TRACE_METHOD;
230 } else if (!IsVisitorPtrType(formal_type)) {
231 return NOT_TRACE_METHOD;
234 if (name == kTraceName)
235 return TRACE_METHOD;
236 if (name == kTraceAfterDispatchName)
237 return TRACE_AFTER_DISPATCH_METHOD;
238 if (name == kTraceImplName)
239 return TRACE_IMPL_METHOD;
240 if (name == kTraceAfterDispatchImplName)
241 return TRACE_AFTER_DISPATCH_IMPL_METHOD;
243 assert(false && "Should not reach here");
244 return NOT_TRACE_METHOD;
247 static bool IsTraceMethod(clang::FunctionDecl* method) {
248 return GetTraceMethodType(method) != NOT_TRACE_METHOD;
251 static bool IsTraceImplName(const std::string& name) {
252 return name == kTraceImplName || name == kTraceAfterDispatchImplName;
255 static bool StartsWith(const std::string& str, const std::string& prefix) {
256 if (prefix.size() > str.size())
257 return false;
258 return str.compare(0, prefix.size(), prefix) == 0;
261 static bool EndsWith(const std::string& str, const std::string& suffix) {
262 if (suffix.size() > str.size())
263 return false;
264 return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
268 #endif // TOOLS_BLINK_GC_PLUGIN_CONFIG_H_