Roll src/third_party/WebKit d10c917:a1123a1 (svn 198729:198730)
[chromium-blink-merge.git] / tools / clang / blink_gc_plugin / Config.h
blob197e294f76a48dc0c2aa2fd3c8e19b4f0ae8efcb
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";
34 const char kIsEagerlyFinalizedName[] = "IsEagerlyFinalizedMarker";
36 class Config {
37 public:
38 static bool IsMember(const std::string& name) {
39 return name == "Member";
42 static bool IsWeakMember(const std::string& name) {
43 return name == "WeakMember";
46 static bool IsMemberHandle(const std::string& name) {
47 return IsMember(name) ||
48 IsWeakMember(name);
51 static bool IsPersistent(const std::string& name) {
52 return name == "Persistent";
55 static bool IsPersistentHandle(const std::string& name) {
56 return IsPersistent(name) ||
57 IsPersistentGCCollection(name);
60 static bool IsRawPtr(const std::string& name) {
61 return name == "RawPtr";
64 static bool IsRefPtr(const std::string& name) {
65 return name == "RefPtr";
68 static bool IsOwnPtr(const std::string& name) {
69 return name == "OwnPtr";
72 static bool IsWTFCollection(const std::string& name) {
73 return name == "Vector" ||
74 name == "Deque" ||
75 name == "HashSet" ||
76 name == "ListHashSet" ||
77 name == "LinkedHashSet" ||
78 name == "HashCountedSet" ||
79 name == "HashMap";
82 static bool IsGCCollection(const std::string& name) {
83 return name == "HeapVector" ||
84 name == "HeapDeque" ||
85 name == "HeapHashSet" ||
86 name == "HeapListHashSet" ||
87 name == "HeapLinkedHashSet" ||
88 name == "HeapHashCountedSet" ||
89 name == "HeapHashMap" ||
90 IsPersistentGCCollection(name);
93 static bool IsPersistentGCCollection(const std::string& name) {
94 return name == "PersistentHeapVector" ||
95 name == "PersistentHeapDeque" ||
96 name == "PersistentHeapHashSet" ||
97 name == "PersistentHeapListHashSet" ||
98 name == "PersistentHeapLinkedHashSet" ||
99 name == "PersistentHeapHashCountedSet" ||
100 name == "PersistentHeapHashMap";
103 static bool IsHashMap(const std::string& name) {
104 return name == "HashMap" ||
105 name == "HeapHashMap" ||
106 name == "PersistentHeapHashMap";
109 // Following http://crrev.com/369633033 (Blink r177436),
110 // ignore blink::ScriptWrappable's destructor.
111 // TODO: remove when its non-Oilpan destructor is removed.
112 static bool HasIgnorableDestructor(const std::string& ns,
113 const std::string& name) {
114 return ns == "blink" && name == "ScriptWrappable";
117 // Assumes name is a valid collection name.
118 static size_t CollectionDimension(const std::string& name) {
119 return (IsHashMap(name) || name == "pair") ? 2 : 1;
122 static bool IsDummyBase(const std::string& name) {
123 return name == "DummyBase";
126 static bool IsRefCountedBase(const std::string& name) {
127 return name == "RefCounted" ||
128 name == "ThreadSafeRefCounted";
131 static bool IsGCMixinBase(const std::string& name) {
132 return name == "GarbageCollectedMixin";
135 static bool IsGCFinalizedBase(const std::string& name) {
136 return name == "GarbageCollectedFinalized" ||
137 name == "RefCountedGarbageCollected" ||
138 name == "ThreadSafeRefCountedGarbageCollected";
141 static bool IsGCBase(const std::string& name) {
142 return name == "GarbageCollected" ||
143 IsGCFinalizedBase(name) ||
144 IsGCMixinBase(name);
147 // Returns true of the base classes that do not need a vtable entry for trace
148 // because they cannot possibly initiate a GC during construction.
149 static bool IsSafePolymorphicBase(const std::string& name) {
150 return IsGCBase(name) || IsDummyBase(name) || IsRefCountedBase(name);
153 static bool IsAnnotated(clang::Decl* decl, const std::string& anno) {
154 clang::AnnotateAttr* attr = decl->getAttr<clang::AnnotateAttr>();
155 return attr && (attr->getAnnotation() == anno);
158 static bool IsStackAnnotated(clang::Decl* decl) {
159 return IsAnnotated(decl, "blink_stack_allocated");
162 static bool IsIgnoreAnnotated(clang::Decl* decl) {
163 return IsAnnotated(decl, "blink_gc_plugin_ignore");
166 static bool IsIgnoreCycleAnnotated(clang::Decl* decl) {
167 return IsAnnotated(decl, "blink_gc_plugin_ignore_cycle") ||
168 IsIgnoreAnnotated(decl);
171 static bool IsVisitor(const std::string& name) {
172 return name == "Visitor" || name == "VisitorHelper";
175 static bool IsVisitorPtrType(const clang::QualType& formal_type) {
176 if (!formal_type->isPointerType())
177 return false;
179 clang::CXXRecordDecl* pointee_type =
180 formal_type->getPointeeType()->getAsCXXRecordDecl();
181 if (!pointee_type)
182 return false;
184 if (!IsVisitor(pointee_type->getName()))
185 return false;
187 return true;
190 static bool IsVisitorDispatcherType(const clang::QualType& formal_type) {
191 if (const clang::SubstTemplateTypeParmType* subst_type =
192 clang::dyn_cast<clang::SubstTemplateTypeParmType>(
193 formal_type.getTypePtr())) {
194 if (IsVisitorPtrType(subst_type->getReplacementType())) {
195 // VisitorDispatcher template parameter substituted to Visitor*.
196 return true;
198 } else if (const clang::TemplateTypeParmType* parm_type =
199 clang::dyn_cast<clang::TemplateTypeParmType>(
200 formal_type.getTypePtr())) {
201 if (parm_type->getDecl()->getName() == kVisitorDispatcherName) {
202 // Unresolved, but its parameter name is VisitorDispatcher.
203 return true;
207 return IsVisitorPtrType(formal_type);
210 enum TraceMethodType {
211 NOT_TRACE_METHOD,
212 TRACE_METHOD,
213 TRACE_AFTER_DISPATCH_METHOD,
214 TRACE_IMPL_METHOD,
215 TRACE_AFTER_DISPATCH_IMPL_METHOD
218 static TraceMethodType GetTraceMethodType(const clang::FunctionDecl* method) {
219 if (method->getNumParams() != 1)
220 return NOT_TRACE_METHOD;
222 const std::string& name = method->getNameAsString();
223 if (name != kTraceName && name != kTraceAfterDispatchName &&
224 name != kTraceImplName && name != kTraceAfterDispatchImplName)
225 return NOT_TRACE_METHOD;
227 const clang::QualType& formal_type = method->getParamDecl(0)->getType();
228 if (name == kTraceImplName || name == kTraceAfterDispatchImplName) {
229 if (!IsVisitorDispatcherType(formal_type))
230 return NOT_TRACE_METHOD;
231 } else if (!IsVisitorPtrType(formal_type)) {
232 return NOT_TRACE_METHOD;
235 if (name == kTraceName)
236 return TRACE_METHOD;
237 if (name == kTraceAfterDispatchName)
238 return TRACE_AFTER_DISPATCH_METHOD;
239 if (name == kTraceImplName)
240 return TRACE_IMPL_METHOD;
241 if (name == kTraceAfterDispatchImplName)
242 return TRACE_AFTER_DISPATCH_IMPL_METHOD;
244 assert(false && "Should not reach here");
245 return NOT_TRACE_METHOD;
248 static bool IsTraceMethod(const clang::FunctionDecl* method) {
249 return GetTraceMethodType(method) != NOT_TRACE_METHOD;
252 static bool IsTraceImplName(const std::string& name) {
253 return name == kTraceImplName || name == kTraceAfterDispatchImplName;
256 static bool StartsWith(const std::string& str, const std::string& prefix) {
257 if (prefix.size() > str.size())
258 return false;
259 return str.compare(0, prefix.size(), prefix) == 0;
262 static bool EndsWith(const std::string& str, const std::string& suffix) {
263 if (suffix.size() > str.size())
264 return false;
265 return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
269 #endif // TOOLS_BLINK_GC_PLUGIN_CONFIG_H_