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

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

Issue 827693004: Blink GC plugin: improve handling of type dependent bases. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years 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
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 b491e4738db8ef5c40b19cbb9342ecd901f28450..cd5263289a1cab84fedf470eb83af45593815efd 100644
--- a/tools/clang/blink_gc_plugin/RecordInfo.cpp
+++ b/tools/clang/blink_gc_plugin/RecordInfo.cpp
@@ -23,13 +23,11 @@ RecordInfo::RecordInfo(CXXRecordDecl* record, RecordCache* cache)
trace_method_(0),
trace_dispatch_method_(0),
finalize_dispatch_method_(0),
- is_gc_derived_(false),
- base_paths_(0) {}
+ is_gc_derived_(false) {}
RecordInfo::~RecordInfo() {
delete fields_;
delete bases_;
- delete base_paths_;
}
// Get |count| number of template arguments. Returns false if there
@@ -74,22 +72,12 @@ bool RecordInfo::IsHeapAllocatedCollection() {
return Config::IsGCCollection(name_);
}
-static bool IsGCBaseCallback(const CXXBaseSpecifier* specifier,
- CXXBasePath& path,
- void* data) {
- if (CXXRecordDecl* record = specifier->getType()->getAsCXXRecordDecl())
- return Config::IsGCBase(record->getName());
- return false;
-}
-
// Test if a record is derived from a garbage collected base.
bool RecordInfo::IsGCDerived() {
// If already computed, return the known result.
- if (base_paths_)
+ if (gc_base_names_.size())
return is_gc_derived_;
- base_paths_ = new CXXBasePaths(true, true, false);
-
if (!record_->hasDefinition())
return false;
@@ -98,19 +86,62 @@ bool RecordInfo::IsGCDerived() {
return false;
// Walk the inheritance tree to find GC base classes.
- is_gc_derived_ = record_->lookupInBases(IsGCBaseCallback, 0, *base_paths_);
+ walkBases();
return is_gc_derived_;
}
+CXXRecordDecl* RecordInfo::GetDependentTemplatedDecl(const Type& type) {
+ const TemplateSpecializationType* tmpl_type =
+ type.getAs<TemplateSpecializationType>();
+ if (!tmpl_type)
+ return 0;
+
+ TemplateDecl* tmpl_decl = tmpl_type->getTemplateName().getAsTemplateDecl();
+ if (!tmpl_decl)
+ return 0;
+
+ return dyn_cast_or_null<CXXRecordDecl>(tmpl_decl->getTemplatedDecl());
+}
+
+void RecordInfo::walkBases() {
+ // This traversal is akin to CXXRecordDecl::forallBases()'s,
+ // but without stepping over dependent bases -- these might also
+ // have a "GC base name", so are to be included and considered.
+ SmallVector<const CXXRecordDecl*, 8> queue;
+
+ const CXXRecordDecl *base_record = record();
+ while (true) {
+ for (const auto& it : base_record->bases()) {
+ const RecordType *type = it.getType()->getAs<RecordType>();
+ CXXRecordDecl* base;
+ if (!type)
+ base = GetDependentTemplatedDecl(*it.getType());
+ else {
+ base = cast_or_null<CXXRecordDecl>(type->getDecl()->getDefinition());
+ if (base)
+ queue.push_back(base);
+ }
+ if (!base)
+ continue;
+
+ const std::string& name = base->getName();
+ if (Config::IsGCBase(name)) {
+ gc_base_names_.push_back(name);
+ is_gc_derived_ = true;
+ }
+ }
+
+ if (queue.empty())
+ break;
+ base_record = queue.pop_back_val(); // not actually a queue.
+ }
+}
+
bool RecordInfo::IsGCFinalized() {
if (!IsGCDerived())
return false;
- for (CXXBasePaths::paths_iterator it = base_paths_->begin();
- it != base_paths_->end();
- ++it) {
- const CXXBasePathElement& elem = (*it)[it->size() - 1];
- CXXRecordDecl* base = elem.Base->getType()->getAsCXXRecordDecl();
- if (Config::IsGCFinalizedBase(base->getName()))
+ for (const auto& gc_base : gc_base_names_) {
+ if (Config::IsGCFinalizedBase(gc_base))
return true;
}
return false;
@@ -119,16 +150,11 @@ bool RecordInfo::IsGCFinalized() {
// A GC mixin is a class that inherits from a GC mixin base and has
// not yet been "mixed in" with another GC base class.
bool RecordInfo::IsGCMixin() {
- if (!IsGCDerived() || base_paths_->begin() == base_paths_->end())
+ if (!IsGCDerived() || !gc_base_names_.size())
return false;
- for (CXXBasePaths::paths_iterator it = base_paths_->begin();
- it != base_paths_->end();
- ++it) {
- // Get the last element of the path.
- const CXXBasePathElement& elem = (*it)[it->size() - 1];
- CXXRecordDecl* base = elem.Base->getType()->getAsCXXRecordDecl();
+ for (const auto& gc_base : gc_base_names_) {
// If it is not a mixin base we are done.
- if (!Config::IsGCMixinBase(base->getName()))
+ if (!Config::IsGCMixinBase(gc_base))
return false;
}
// This is a mixin if all GC bases are mixins.

Powered by Google App Engine
This is Rietveld 408576698