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_
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";
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
) ||
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" ||
75 name
== "ListHashSet" ||
76 name
== "LinkedHashSet" ||
77 name
== "HashCountedSet" ||
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
) ||
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())
178 clang::CXXRecordDecl
* pointee_type
=
179 formal_type
->getPointeeType()->getAsCXXRecordDecl();
183 if (!IsVisitor(pointee_type
->getName()))
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*.
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.
206 return IsVisitorPtrType(formal_type
);
209 enum TraceMethodType
{
212 TRACE_AFTER_DISPATCH_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
)
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())
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())
264 return str
.compare(str
.size() - suffix
.size(), suffix
.size(), suffix
) == 0;
268 #endif // TOOLS_BLINK_GC_PLUGIN_CONFIG_H_