Index: tools/clang/blink_gc_plugin/Config.h |
diff --git a/tools/clang/blink_gc_plugin/Config.h b/tools/clang/blink_gc_plugin/Config.h |
index 37cecd0df992115833730fdc32a5ff56afae230b..53d65713eb1ab6c1349d355acb305d18ad78687b 100644 |
--- a/tools/clang/blink_gc_plugin/Config.h |
+++ b/tools/clang/blink_gc_plugin/Config.h |
@@ -18,11 +18,13 @@ |
const char kNewOperatorName[] = "operator new"; |
const char kCreateName[] = "create"; |
const char kTraceName[] = "trace"; |
+const char kTraceImplName[] = "traceImpl"; |
const char kFinalizeName[] = "finalizeGarbageCollectedObject"; |
const char kTraceAfterDispatchName[] = "traceAfterDispatch"; |
const char kRegisterWeakMembersName[] = "registerWeakMembers"; |
const char kHeapAllocatorName[] = "HeapAllocator"; |
const char kTraceIfNeededName[] = "TraceIfNeeded"; |
+const char kVisitorDispatcherName[] = "VisitorDispatcher"; |
class Config { |
public: |
@@ -163,16 +165,7 @@ class Config { |
return name == "Visitor" || name == "VisitorHelper"; |
} |
- static bool IsTraceMethod(clang::FunctionDecl* method, |
- bool* isTraceAfterDispatch = 0) { |
- if (method->getNumParams() != 1) |
- return false; |
- |
- const std::string& name = method->getNameAsString(); |
- if (name != kTraceName && name != kTraceAfterDispatchName) |
- return false; |
- |
- const clang::QualType& formal_type = method->getParamDecl(0)->getType(); |
+ static bool IsVisitorPtrType(const clang::QualType& formal_type) { |
if (!formal_type->isPointerType()) |
return false; |
@@ -184,8 +177,50 @@ class Config { |
if (!IsVisitor(pointee_type->getName())) |
return false; |
- if (isTraceAfterDispatch) |
- *isTraceAfterDispatch = (name == kTraceAfterDispatchName); |
+ return true; |
+ } |
+ |
+ static bool IsVisitorDispatcherType(const clang::QualType& formal_type) { |
+ if (const clang::SubstTemplateTypeParmType* subst_type = |
+ clang::dyn_cast<clang::SubstTemplateTypeParmType>( |
+ formal_type.getTypePtr())) { |
+ if (IsVisitorPtrType(subst_type->getReplacementType())) { |
+ // VisitorDispatcher template parameter substituted to Visitor*. |
+ return true; |
+ } |
+ } else if (const clang::TemplateTypeParmType* parm_type = |
+ clang::dyn_cast<clang::TemplateTypeParmType>( |
+ formal_type.getTypePtr())) { |
+ if (parm_type->getDecl()->getName() == kVisitorDispatcherName) { |
+ // Unresolved, but its parameter name is VisitorDispatcher. |
+ return false; |
+ } |
+ } |
+ |
+ return IsVisitorPtrType(formal_type); |
+ } |
+ |
+ static bool IsTraceMethod(clang::FunctionDecl* method, |
+ bool* is_trace_after_dispatch) { |
+ if (method->getNumParams() != 1) |
+ return false; |
+ |
+ const std::string& name = method->getNameAsString(); |
+ if (name != kTraceName && name != kTraceAfterDispatchName && |
+ name != kTraceImplName) |
+ return false; |
+ |
+ const clang::QualType& formal_type = method->getParamDecl(0)->getType(); |
+ if (name == kTraceImplName) { |
+ if (!IsVisitorDispatcherType(formal_type)) |
+ return false; |
+ } else if (!IsVisitorPtrType(formal_type)) { |
+ return false; |
+ } |
+ |
+ if (is_trace_after_dispatch) |
+ *is_trace_after_dispatch = (name == kTraceAfterDispatchName); |
+ |
return true; |
} |