Index: tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp |
diff --git a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp |
index d24d67ade4ff4c37aa2016b8d4d76567ea422652..6cb6b43544a675ac9f62f925ef55989a6e4e7310 100644 |
--- a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp |
+++ b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp |
@@ -197,7 +197,8 @@ class CollectVisitor : public RecursiveASTVisitor<CollectVisitor> { |
// Collect tracing method definitions, but don't traverse method bodies. |
bool TraverseCXXMethodDecl(CXXMethodDecl* method) { |
- if (method->isThisDeclarationADefinition() && Config::IsTraceMethod(method)) |
+ if (method->isThisDeclarationADefinition() && |
+ Config::IsTraceMethod(method, nullptr)) |
trace_decls_.push_back(method); |
return true; |
} |
@@ -322,7 +323,9 @@ class CheckDispatchVisitor : public RecursiveASTVisitor<CheckDispatchVisitor> { |
class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> { |
public: |
CheckTraceVisitor(CXXMethodDecl* trace, RecordInfo* info) |
- : trace_(trace), info_(info) {} |
+ : trace_(trace), info_(info), delegates_to_traceimpl_(false) {} |
+ |
+ bool delegates_to_traceimpl() const { return delegates_to_traceimpl_; } |
bool VisitMemberExpr(MemberExpr* member) { |
// In weak callbacks, consider any occurrence as a correct usage. |
@@ -383,6 +386,11 @@ class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> { |
if (CXXMemberCallExpr* expr = dyn_cast<CXXMemberCallExpr>(call)) { |
if (CheckTraceFieldCall(expr) || CheckRegisterWeakMembers(expr)) |
return true; |
+ |
+ if (expr->getMethodDecl()->getNameAsString() == kTraceImplName) { |
+ delegates_to_traceimpl_ = true; |
+ return true; |
+ } |
} |
CheckTraceBaseCall(call); |
@@ -400,21 +408,29 @@ class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> { |
if (!type) |
return 0; |
- const TemplateSpecializationType* tmpl_type = |
- type->getAs<TemplateSpecializationType>(); |
- if (!tmpl_type) |
- return 0; |
- |
- TemplateDecl* tmpl_decl = tmpl_type->getTemplateName().getAsTemplateDecl(); |
- if (!tmpl_decl) |
- return 0; |
- |
- return dyn_cast<CXXRecordDecl>(tmpl_decl->getTemplatedDecl()); |
+ return RecordInfo::GetDependentTemplatedDecl(*type); |
} |
void CheckCXXDependentScopeMemberExpr(CallExpr* call, |
CXXDependentScopeMemberExpr* expr) { |
string fn_name = expr->getMember().getAsString(); |
+ |
+ // Check for VisitorDispatcher::trace(field) |
+ if (!expr->isImplicitAccess()) { |
+ if (clang::DeclRefExpr* base_decl = |
+ clang::dyn_cast<clang::DeclRefExpr>(expr->getBase())) { |
+ if (Config::IsVisitorDispatcherType(base_decl->getType()) && |
+ call->getNumArgs() == 1 && fn_name == kTraceName) { |
+ FindFieldVisitor finder; |
+ finder.TraverseStmt(call->getArg(0)); |
+ if (finder.field()) |
+ FoundField(finder.field()); |
+ |
+ return; |
+ } |
+ } |
+ } |
+ |
CXXRecordDecl* tmpl = GetDependentTemplatedDecl(expr); |
if (!tmpl) |
return; |
@@ -445,7 +461,7 @@ class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> { |
return false; |
FunctionDecl* fn = dyn_cast<FunctionDecl>(callee->getMemberDecl()); |
- if (!fn || !Config::IsTraceMethod(fn)) |
+ if (!fn || !Config::IsTraceMethod(fn, nullptr)) |
return false; |
// Currently, a manually dispatched class cannot have mixin bases (having |
@@ -565,6 +581,7 @@ class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> { |
CXXMethodDecl* trace_; |
RecordInfo* info_; |
+ bool delegates_to_traceimpl_; |
}; |
// This visitor checks that the fields of a class and the fields of |
@@ -1042,7 +1059,7 @@ class BlinkGCPluginConsumer : public ASTConsumer { |
while (it != left_most->bases_end()) { |
left_most_base = it->getType()->getAsCXXRecordDecl(); |
if (!left_most_base && it->getType()->isDependentType()) |
- left_most_base = GetDependentTemplatedDecl(*it->getType()); |
+ left_most_base = RecordInfo::GetDependentTemplatedDecl(*it->getType()); |
// TODO: Find a way to correctly check actual instantiations |
// for dependent types. The escape below will be hit, eg, when |
@@ -1103,7 +1120,7 @@ class BlinkGCPluginConsumer : public ASTConsumer { |
CXXRecordDecl::base_class_iterator it = left_most->bases_begin(); |
while (it != left_most->bases_end()) { |
if (it->getType()->isDependentType()) |
- left_most = GetDependentTemplatedDecl(*it->getType()); |
+ left_most = RecordInfo::GetDependentTemplatedDecl(*it->getType()); |
else |
left_most = it->getType()->getAsCXXRecordDecl(); |
if (!left_most || !left_most->hasDefinition()) |
@@ -1122,12 +1139,9 @@ class BlinkGCPluginConsumer : public ASTConsumer { |
} |
void CheckLeftMostDerived(RecordInfo* info) { |
- CXXRecordDecl* left_most = info->record(); |
- CXXRecordDecl::base_class_iterator it = left_most->bases_begin(); |
- while (it != left_most->bases_end()) { |
- left_most = it->getType()->getAsCXXRecordDecl(); |
- it = left_most->bases_begin(); |
- } |
+ CXXRecordDecl* left_most = GetLeftMostBase(info->record()); |
+ if (!left_most) |
+ return; |
if (!Config::IsGCBase(left_most->getName())) |
ReportClassMustLeftMostlyDeriveGC(info); |
} |
@@ -1303,6 +1317,11 @@ class BlinkGCPluginConsumer : public ASTConsumer { |
CheckTraceVisitor visitor(trace, parent); |
visitor.TraverseCXXMethodDecl(trace); |
+ // Skip reporting if this trace method is a just delegate to |
+ // traceImpl method. We will report on CheckTraceMethod on traceImpl method. |
+ if (visitor.delegates_to_traceimpl()) |
+ return; |
+ |
for (RecordInfo::Bases::iterator it = parent->GetBases().begin(); |
it != parent->GetBases().end(); |
++it) { |