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..23daa0f45aee7a9720fcf32b4cdaf766270add50 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,46 @@ 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 for it being true is the presence |
+ // of a safely ignorable class as a direct base, |
+ // or we're processing such an 'ignorable' class, then it does |
+ // not need finalization. |
+ does_need_finalization_ = |
+ record_->hasNonTrivialDestructor() ? kTrue : kFalse; |
+ if (!does_need_finalization_) |
+ return does_need_finalization_; |
+ |
+ // 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; |
+ return does_need_finalization_; |
+ } |
+ |
+ CXXDestructorDecl* dtor = record_->getDestructor(); |
+ if (dtor && dtor->isUserProvided()) |
+ return does_need_finalization_; |
+ for (Fields::iterator it = GetFields().begin(); |
+ it != GetFields().end(); |
+ ++it) { |
+ if (it->second.edge()->NeedsFinalization()) |
+ return does_need_finalization_; |
+ } |
+ |
+ for (Bases::iterator it = GetBases().begin(); |
+ it != GetBases().end(); |
+ ++it) { |
+ if (it->second.info()->NeedsFinalization()) |
+ return does_need_finalization_; |
+ } |
+ // Destructor was non-trivial due to bases with destructors that |
+ // can be safely ignored. Hence, no need for finalization. |
+ does_need_finalization_ = kFalse; |
+ } |
+ return does_need_finalization_; |
} |
// A class needs tracing if: |