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

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

Issue 964273002: BlinkGCPlugin: Handle omitted trace() in intermediary classes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use range-for. 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/tests/traceimpl_omitted_trace.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 fb87ce8cd29f84387c481ac212b324adfa8358a6..41e694dcd8538c43f22c43bbfcc489248a1b6e82 100644
--- a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
+++ b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
@@ -325,8 +325,12 @@ class CheckDispatchVisitor : public RecursiveASTVisitor<CheckDispatchVisitor> {
// - A base is traced if a base-qualified call to a trace method is found.
class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> {
public:
- CheckTraceVisitor(CXXMethodDecl* trace, RecordInfo* info)
- : trace_(trace), info_(info), delegates_to_traceimpl_(false) {}
+ CheckTraceVisitor(CXXMethodDecl* trace, RecordInfo* info, RecordCache* cache)
+ : trace_(trace),
+ info_(info),
+ cache_(cache),
+ delegates_to_traceimpl_(false) {
+ }
bool delegates_to_traceimpl() const { return delegates_to_traceimpl_; }
@@ -541,12 +545,48 @@ class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> {
if (!IsTraceCallName(func_name))
return false;
- RecordInfo::Bases::iterator iter = info_->GetBases().find(callee_record);
- if (iter == info_->GetBases().end())
- return false;
+ for (auto& base : info_->GetBases()) {
+ // We want to deal with omitted trace() function in an intermediary
+ // class in the class hierarchy, e.g.:
+ // class A : public GarbageCollected<A> { trace() { ... } };
+ // class B : public A { /* No trace(); have nothing to trace. */ };
+ // class C : public B { trace() { B::trace(visitor); } }
+ // where, B::trace() is actually A::trace(), and in some cases we get
+ // A as |callee_record| instead of B. We somehow need to mark B as
+ // traced if we find A::trace() call.
+ //
+ // To solve this, here we keep going up the class hierarchy as long as
+ // they are not required to have a trace method. The implementation is
+ // a simple DFS, where |base_records| represents the set of base classes
+ // we need to visit.
+
+ std::vector<CXXRecordDecl*> base_records;
+ base_records.push_back(base.first);
+
+ while (!base_records.empty()) {
+ CXXRecordDecl* base_record = base_records.back();
+ base_records.pop_back();
+
+ if (base_record == callee_record) {
+ // If we find a matching trace method, pretend the user has written
+ // a correct trace() method of the base; in the example above, we
+ // find A::trace() here and mark B as correctly traced.
+ base.second.MarkTraced();
+ return true;
+ }
- iter->second.MarkTraced();
- return true;
+ if (RecordInfo* base_info = cache_->Lookup(base_record)) {
+ if (!base_info->RequiresTraceMethod()) {
+ // If this base class is not required to have a trace method, then
+ // the actual trace method may be defined in an ancestor.
+ for (auto& inner_base : base_info->GetBases())
+ base_records.push_back(inner_base.first);
+ }
+ }
+ }
+ }
+
+ return false;
}
bool CheckTraceFieldCall(CXXMemberCallExpr* call) {
@@ -609,7 +649,8 @@ class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> {
};
// Nested checking for weak callbacks.
- CheckTraceVisitor(RecordInfo* info) : trace_(0), info_(info) {}
+ CheckTraceVisitor(RecordInfo* info)
+ : trace_(nullptr), info_(info), cache_(nullptr) {}
bool IsWeakCallback() { return !trace_; }
@@ -643,6 +684,7 @@ class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> {
CXXMethodDecl* trace_;
RecordInfo* info_;
+ RecordCache* cache_;
bool delegates_to_traceimpl_;
};
@@ -1387,7 +1429,7 @@ class BlinkGCPluginConsumer : public ASTConsumer {
}
}
- CheckTraceVisitor visitor(trace, parent);
+ CheckTraceVisitor visitor(trace, parent, &cache_);
visitor.TraverseCXXMethodDecl(trace);
// Skip reporting if this trace method is a just delegate to
« no previous file with comments | « no previous file | tools/clang/blink_gc_plugin/tests/traceimpl_omitted_trace.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698