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

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

Issue 192933002: Check that classes with non-trivial destructors have finalization support. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: comments Created 6 years, 9 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
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 2fa8d5363b92a3ebb30f301121e186615ca209fb..1878f1ecdd58ec8ef3e25d4c71b34409ddf192fa 100644
--- a/tools/clang/blink_gc_plugin/RecordInfo.cpp
+++ b/tools/clang/blink_gc_plugin/RecordInfo.cpp
@@ -113,6 +113,21 @@ 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() {
+ if (!IsGCDerived() || base_paths_->begin() == base_paths_->end())
+ return false;
+ // Get the last element of the first path.
+ CXXBasePaths::paths_iterator it = base_paths_->begin();
+ const CXXBasePathElement& elem = (*it)[it->size() - 1];
+ CXXRecordDecl* base = elem.Base->getType()->getAsCXXRecordDecl();
+ // 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.
+ return ++it == base_paths_->end();
+}
+
// Test if a record is allocated on the managed heap.
bool RecordInfo::IsGCAllocated() {
return IsGCDerived() || IsHeapAllocatedCollection();
@@ -171,16 +186,20 @@ bool RecordInfo::InheritsNonPureTrace() {
RecordInfo::Bases* RecordInfo::CollectBases() {
// Compute the collection locally to avoid inconsistent states.
Bases* bases = new Bases;
+ if (!record_->hasDefinition())
+ return bases;
for (CXXRecordDecl::base_class_iterator it = record_->bases_begin();
it != record_->bases_end();
++it) {
- if (CXXRecordDecl* base = it->getType()->getAsCXXRecordDecl()) {
- RecordInfo* info = cache_->Lookup(base);
- TracingStatus status = info->InheritsNonPureTrace()
- ? TracingStatus::Needed()
- : TracingStatus::Unneeded();
- bases->insert(std::make_pair(base, BasePoint(info, status)));
- }
+ const CXXBaseSpecifier& spec = *it;
+ RecordInfo* info = cache_->Lookup(spec.getType());
+ if (!info)
+ continue;
+ CXXRecordDecl* base = info->record();
+ TracingStatus status = info->InheritsNonPureTrace()
+ ? TracingStatus::Needed()
+ : TracingStatus::Unneeded();
+ bases->insert(std::make_pair(base, BasePoint(spec, info, status)));
}
return bases;
}
@@ -194,6 +213,8 @@ RecordInfo::Fields& RecordInfo::GetFields() {
RecordInfo::Fields* RecordInfo::CollectFields() {
// Compute the collection locally to avoid inconsistent states.
Fields* fields = new Fields;
+ if (!record_->hasDefinition())
+ return fields;
TracingStatus fields_status = TracingStatus::Unneeded();
for (RecordDecl::field_iterator it = record_->field_begin();
it != record_->field_end();
@@ -241,14 +262,28 @@ void RecordInfo::DetermineTracingMethods() {
}
}
+// TODO: Add classes with a finalize() method that specialize FinalizerTrait.
+bool RecordInfo::NeedsFinalization() {
+ return record_->hasNonTrivialDestructor();
+}
+
// A class needs tracing if:
// - it is allocated on the managed heap,
-// - it defines a trace method (of the proper signature), or
+// - it is derived from a class that needs tracing, or
// - it contains fields that need tracing.
+// TODO: Defining NeedsTracing based on whether a class defines a trace method
+// (of the proper signature) over approximates too much. The use of transition
+// types causes some classes to have trace methods without them needing to be
+// traced.
TracingStatus RecordInfo::NeedsTracing(Edge::NeedsTracingOption option) {
- if (IsGCAllocated() || GetTraceMethod())
+ if (IsGCAllocated())
return TracingStatus::Needed();
+ for (Bases::iterator it = GetBases().begin(); it != GetBases().end(); ++it) {
+ if (it->second.info()->NeedsTracing(option).IsNeeded())
+ return TracingStatus::Needed();
+ }
+
if (option == Edge::kRecursive)
GetFields();
@@ -266,15 +301,13 @@ Edge* RecordInfo::CreateEdge(const Type* type) {
return 0;
}
- CXXRecordDecl* record = type->getAsCXXRecordDecl();
+ RecordInfo* info = cache_->Lookup(type);
// If the type is neither a pointer or a C++ record we ignore it.
- if (!record) {
+ if (!info) {
return 0;
}
- RecordInfo* info = cache_->Lookup(record);
-
TemplateArgs args;
if (Config::IsRawPtr(info->name()) && info->GetTemplateArgs(1, &args)) {
@@ -328,7 +361,7 @@ Edge* RecordInfo::CreateEdge(const Type* type) {
size_t count = Config::CollectionDimension(info->name());
if (!info->GetTemplateArgs(count, &args))
return 0;
- Collection* edge = new Collection(on_heap, is_root);
+ Collection* edge = new Collection(info, on_heap, is_root);
for (TemplateArgs::iterator it = args.begin(); it != args.end(); ++it) {
if (Edge* member = CreateEdge(*it)) {
edge->members().push_back(member);
« no previous file with comments | « tools/clang/blink_gc_plugin/RecordInfo.h ('k') | tools/clang/blink_gc_plugin/tests/class_requires_finalization_base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698