Index: tools/clang/blink_gc_plugin/RecordInfo.cpp |
diff --git a/tools/clang/blink_gc_plugin/RecordInfo.cpp b/tools/clang/blink_gc_plugin/RecordInfo.cpp |
index ed1817d5576f54ca19317f9da29e014c9c920aa0..9072d0340ef327bcea54591863a343bd4f6c112f 100644 |
--- a/tools/clang/blink_gc_plugin/RecordInfo.cpp |
+++ b/tools/clang/blink_gc_plugin/RecordInfo.cpp |
@@ -113,8 +113,9 @@ bool RecordInfo::IsGCFinalized() { |
return false; |
} |
-// A mixin has not yet been "mixed in" if its only GC base is the mixin base. |
-bool RecordInfo::IsUnmixedGCMixin() { |
+// A GC mixin is a class that inherits from a GC mixin base and has |
+// has not yet been "mixed in" with another GC base class. |
+bool RecordInfo::IsGCMixin() { |
if (!IsGCDerived() || base_paths_->begin() == base_paths_->end()) |
return false; |
// Get the last element of the first path. |
@@ -124,7 +125,7 @@ bool RecordInfo::IsUnmixedGCMixin() { |
// If it is not a mixin base we are done. |
if (!Config::IsGCMixinBase(base->getName())) |
return false; |
- // Otherwise, this is unmixed if there are no other paths to GC bases. |
+ // This is a mixin if there are no other paths to GC bases. |
return ++it == base_paths_->end(); |
} |
@@ -194,6 +195,34 @@ bool RecordInfo::InheritsNonPureTrace() { |
return false; |
} |
+CXXMethodDecl* RecordInfo::InheritsNonVirtualTrace() { |
+ if (CXXMethodDecl* trace = GetTraceMethod()) |
+ return trace->isVirtual() ? 0 : trace; |
+ for (Bases::iterator it = GetBases().begin(); it != GetBases().end(); ++it) { |
+ if (CXXMethodDecl* trace = it->second.info()->InheritsNonVirtualTrace()) |
+ return trace; |
+ } |
+ return 0; |
+} |
+ |
+// A (non-virtual) class is considered abstract in Blink if it has |
+// no public constructors and no create methods. |
+bool RecordInfo::IsConsideredAbstract() { |
+ for (CXXRecordDecl::ctor_iterator it = record_->ctor_begin(); |
+ it != record_->ctor_end(); |
+ ++it) { |
+ if (!it->isCopyOrMoveConstructor() && it->getAccess() == AS_public) |
+ return false; |
+ } |
+ for (CXXRecordDecl::method_iterator it = record_->method_begin(); |
+ it != record_->method_end(); |
+ ++it) { |
+ if (it->getNameAsString() == kCreateName) |
+ return false; |
+ } |
+ return true; |
+} |
+ |
RecordInfo::Bases* RecordInfo::CollectBases() { |
// Compute the collection locally to avoid inconsistent states. |
Bases* bases = new Bases; |
@@ -254,7 +283,6 @@ void RecordInfo::DetermineTracingMethods() { |
it != record_->method_end(); |
++it) { |
if (Config::IsTraceMethod(*it, &isTraceAfterDispatch)) { |
- // TODO: Test that the formal parameter is of type Visitor*. |
if (isTraceAfterDispatch) { |
traceAfterDispatch = *it; |
} else { |
@@ -271,6 +299,16 @@ void RecordInfo::DetermineTracingMethods() { |
trace_method_ = trace; |
trace_dispatch_method_ = 0; |
} |
+ if (trace_dispatch_method_) |
+ return; |
+ // If this class does not define a trace dispatch method inherit it. |
+ for (Bases::iterator it = GetBases().begin(); it != GetBases().end(); ++it) { |
+ if (CXXMethodDecl* dispatch = it->second.info()->GetTraceDispatchMethod()) { |
+ // TODO: Does it make sense to inherit multiple dispatch methods? |
+ assert(!trace_dispatch_method_ && "Multiple trace dispatching methods"); |
+ trace_dispatch_method_ = dispatch; |
+ } |
+ } |
} |
// TODO: Add classes with a finalize() method that specialize FinalizerTrait. |