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 5250eaa084d8e0ba2c341a563188a05760f297a2..b52a5d4be361c3a1edb2e921c081f503ea338d42 100644 |
--- a/tools/clang/blink_gc_plugin/RecordInfo.cpp |
+++ b/tools/clang/blink_gc_plugin/RecordInfo.cpp |
@@ -18,6 +18,7 @@ RecordInfo::RecordInfo(CXXRecordDecl* record, RecordCache* cache) |
is_stack_allocated_(kNotComputed), |
is_non_newable_(kNotComputed), |
is_only_placement_newable_(kNotComputed), |
+ does_need_finalization_(kNotComputed), |
determined_trace_methods_(false), |
trace_method_(0), |
trace_dispatch_method_(0), |
@@ -400,7 +401,48 @@ void RecordInfo::DetermineTracingMethods() { |
// TODO: Add classes with a finalize() method that specialize FinalizerTrait. |
bool RecordInfo::NeedsFinalization() { |
- return record_->hasNonTrivialDestructor(); |
+ if (does_need_finalization_ == kNotComputed) { |
+ // Rely on hasNonTrivialDestructor(), but if the only |
+ // identifiable reason why it is true is the presence |
+ // of a class with a safely ignorable class as a direct base, |
+ // or such a class is being represented here, then it does |
+ // not need finalization. |
+ does_need_finalization_ = |
+ record_->hasNonTrivialDestructor() ? kTrue : kFalse; |
+ if (does_need_finalization_) { |
zerny-chromium
2014/07/08 07:45:03
Add early exit instead:
if (!does_need_finalizati
sof
2014/07/08 08:47:05
Rephrased to use early returns instead of fallthro
|
+ // Checking if processing a class with a safely-ignorable destructor. |
+ NamespaceDecl* ns = |
+ dyn_cast<NamespaceDecl>(record_->getDeclContext()); |
+ if (ns && Config::HasIgnorableDestructor(ns->getName(), name_)) |
+ does_need_finalization_ = kFalse; |
zerny-chromium
2014/07/08 07:45:02
Do an early return in this block as well and avoid
|
+ } |
+ if (does_need_finalization_) { |
+ CXXDestructorDecl* dtor = record_->getDestructor(); |
+ bool is_candidate = !dtor || !dtor->isUserProvided(); |
+ for (Fields::iterator it = GetFields().begin(); |
+ is_candidate && it != GetFields().end(); |
+ ++it) { |
+ if (it->second.edge()->NeedsFinalization()) |
+ is_candidate = false; |
zerny-chromium
2014/07/08 07:45:03
This can just return does_need_finalization_ which
|
+ } |
+ |
+ for (Bases::iterator it = GetBases().begin(); |
+ is_candidate && it != GetBases().end(); |
+ ++it) { |
+ NamespaceDecl* ns = dyn_cast<NamespaceDecl>( |
+ it->second.info()->record()->getDeclContext()); |
+ if (ns && |
zerny-chromium
2014/07/08 07:45:03
This check is not be needed here. The ignored case
sof
2014/07/08 08:47:05
I was hesitant to remove it, in case the complete
sof
2014/07/08 08:48:49
s/in case/in scope/. Need more coffee.
|
+ Config::HasIgnorableDestructor(ns->getName(), |
+ it->second.info()->name())) |
+ continue; |
+ if (it->second.info()->NeedsFinalization()) |
+ is_candidate = false; |
zerny-chromium
2014/07/08 07:45:02
Just return does_need_finalization_
|
+ } |
+ if (is_candidate) |
zerny-chromium
2014/07/08 07:45:02
Here we can unconditionally set does_need_finaliza
|
+ does_need_finalization_ = kFalse; |
+ } |
+ } |
+ return does_need_finalization_; |
} |
// A class needs tracing if: |