Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Unified Diff: tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp

Issue 939303005: BlinkGCPlugin: Support overloaded trace() call from template. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix a subtle typo. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tools/clang/blink_gc_plugin/Config.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 2924fd304fac91fe76adc32866d7c371b0f42c57..85cf08671894c966f8c74c392c9bcf54aff0e473 100644
--- a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
+++ b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
@@ -365,6 +365,11 @@ class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> {
Expr* arg = call->getArg(0);
if (UnresolvedMemberExpr* expr = dyn_cast<UnresolvedMemberExpr>(callee)) {
+ // This could be a trace call of a base class, as explained in the
+ // comments of CheckTraceBaseCall().
+ if (CheckTraceBaseCall(call))
+ return true;
+
// If we find a call to registerWeakMembers which is unresolved we
// unsoundly consider all weak members as traced.
// TODO: Find out how to validate weak member tracing for unresolved call.
@@ -403,7 +408,6 @@ class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> {
}
private:
-
CXXRecordDecl* GetDependentTemplatedDecl(CXXDependentScopeMemberExpr* expr) {
NestedNameSpecifier* qual = expr->getQualifier();
if (!qual)
@@ -461,42 +465,87 @@ class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> {
}
bool CheckTraceBaseCall(CallExpr* call) {
- MemberExpr* callee = dyn_cast<MemberExpr>(call->getCallee());
- if (!callee)
- return false;
+ // Checks for "Base::trace(visitor)"-like calls.
+
+ // Checking code for these two variables is shared among MemberExpr* case
+ // and UnresolvedMemberCase* case below.
+ //
+ // For example, if we've got "Base::trace(visitor)" as |call|,
+ // callee_record will be "Base", and func_name will be "trace".
+ CXXRecordDecl* callee_record = nullptr;
+ std::string func_name;
+
+ if (MemberExpr* callee = dyn_cast<MemberExpr>(call->getCallee())) {
+ if (!callee->hasQualifier())
+ return false;
- FunctionDecl* fn = dyn_cast<FunctionDecl>(callee->getMemberDecl());
- if (!fn || !Config::IsTraceMethod(fn))
- return false;
+ FunctionDecl* trace_decl =
+ dyn_cast<FunctionDecl>(callee->getMemberDecl());
+ if (!trace_decl || !Config::IsTraceMethod(trace_decl))
+ return false;
+
+ const Type* type = callee->getQualifier()->getAsType();
+ if (!type)
+ return false;
+
+ callee_record = type->getAsCXXRecordDecl();
+ func_name = trace_decl->getName();
+ } else if (UnresolvedMemberExpr* callee =
+ dyn_cast<UnresolvedMemberExpr>(call->getCallee())) {
+ // Callee part may become unresolved if the type of the argument
+ // ("visitor") is a template parameter and the called function is
+ // overloaded (i.e. trace(Visitor*) and
+ // trace(InlinedGlobalMarkingVisitor)).
+ //
+ // Here, we try to find a function that looks like trace() from the
+ // candidate overloaded functions, and if we find one, we assume it is
+ // called here.
+
+ CXXMethodDecl* trace_decl = nullptr;
+ for (NamedDecl* named_decl : callee->decls()) {
+ if (CXXMethodDecl* method_decl = dyn_cast<CXXMethodDecl>(named_decl)) {
+ if (Config::IsTraceMethod(method_decl)) {
+ trace_decl = method_decl;
+ break;
+ }
+ }
+ }
+ if (!trace_decl)
+ return false;
+
+ // Check if the passed argument is named "visitor".
kouhei (in TOK) 2015/02/24 07:46:32 Nit: Should we document this change in CL desc?
Yuta Kitamura 2015/02/24 08:35:58 Done.
+ if (call->getNumArgs() != 1)
+ return false;
+ DeclRefExpr* arg = dyn_cast<DeclRefExpr>(call->getArg(0));
+ if (!arg || arg->getNameInfo().getAsString() != kVisitorVarName)
+ return false;
+
+ callee_record = trace_decl->getParent();
+ func_name = callee->getMemberName().getAsString();
+ }
if (trace_->getName() == kTraceImplName) {
- if (fn->getName() != kTraceName)
+ if (func_name != kTraceName)
return false;
} else if (trace_->getName() == kTraceAfterDispatchImplName) {
- if (fn->getName() != kTraceAfterDispatchName)
+ if (func_name != kTraceAfterDispatchName)
return false;
} else {
// Currently, a manually dispatched class cannot have mixin bases (having
// one would add a vtable which we explicitly check against). This means
// that we can only make calls to a trace method of the same name. Revisit
// this if our mixin/vtable assumption changes.
- if (fn->getName() != trace_->getName())
+ if (func_name != trace_->getName())
return false;
}
- CXXRecordDecl* decl = 0;
- if (callee && callee->hasQualifier()) {
- if (const Type* type = callee->getQualifier()->getAsType())
- decl = type->getAsCXXRecordDecl();
- }
- if (!decl)
+ if (!callee_record)
+ return false;
+ RecordInfo::Bases::iterator iter = info_->GetBases().find(callee_record);
+ if (iter == info_->GetBases().end())
return false;
- RecordInfo::Bases::iterator it = info_->GetBases().find(decl);
- if (it != info_->GetBases().end()) {
- it->second.MarkTraced();
- }
-
+ iter->second.MarkTraced();
return true;
}
« no previous file with comments | « no previous file | tools/clang/blink_gc_plugin/Config.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698