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

Unified Diff: tools/clang/blink_gc_plugin/BlinkGCPlugin.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
« no previous file with comments | « no previous file | tools/clang/blink_gc_plugin/Edge.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
diff --git a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
index 15ce1aececc493172495d642a7fffe87651f4857..73cf38fd91ffea42866c4c5605fe8ffb80b7d54b 100644
--- a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
+++ b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
@@ -41,8 +41,8 @@ const char kClassContainsInvalidFields[] =
const char kClassContainsGCRoot[] =
"[blink-gc] Class %0 contains GC root in field %1.";
-const char kFinalizerInNonFinalizedClass[] =
- "[blink-gc] Non-finalized class %0 has a user-declared finalizer %1.";
+const char kClassRequiresFinalization[] =
+ "[blink-gc] Class %0 requires finalization.";
const char kFinalizerAccessesFinalizedField[] =
"[blink-gc] Finalizer %0 accesses potentially finalized field %1.";
@@ -65,6 +65,15 @@ const char kFieldContainsGCRoot[] =
const char kFinalizedFieldNote[] =
"[blink-gc] Potentially finalized field %0 declared here:";
+const char kUserDeclaredDestructorNote[] =
+ "[blink-gc] User-declared destructor declared here:";
+
+const char kBaseRequiresFinalizationNote[] =
+ "[blink-gc] Base class %0 requiring finalization declared here:";
+
+const char kFieldRequiresFinalizationNote[] =
+ "[blink-gc] Field %0 requiring finalization declared here:";
+
struct BlinkGCPluginOptions {
BlinkGCPluginOptions() : enable_oilpan(false) {}
bool enable_oilpan;
@@ -409,8 +418,8 @@ class BlinkGCPluginConsumer : public ASTConsumer {
kClassContainsInvalidFields);
diag_class_contains_gc_root_ =
diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot);
- diag_finalizer_in_nonfinalized_class_ = diagnostic_.getCustomDiagID(
- getErrorLevel(), kFinalizerInNonFinalizedClass);
+ diag_class_requires_finalization_ = diagnostic_.getCustomDiagID(
+ getErrorLevel(), kClassRequiresFinalization);
diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID(
getErrorLevel(), kFinalizerAccessesFinalizedField);
@@ -429,6 +438,12 @@ class BlinkGCPluginConsumer : public ASTConsumer {
DiagnosticsEngine::Note, kFieldContainsGCRoot);
diag_finalized_field_note_ = diagnostic_.getCustomDiagID(
DiagnosticsEngine::Note, kFinalizedFieldNote);
+ diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kUserDeclaredDestructorNote);
+ diag_base_requires_finalization_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kBaseRequiresFinalizationNote);
+ diag_field_requires_finalization_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kFieldRequiresFinalizationNote);
}
virtual void HandleTranslationUnit(ASTContext& context) {
@@ -490,37 +505,56 @@ class BlinkGCPluginConsumer : public ASTConsumer {
}
if (info->IsGCDerived()) {
- {
- CheckGCRootsVisitor visitor;
- if (visitor.ContainsGCRoots(info))
- ReportClassContainsGCRoots(info, &visitor.gc_roots());
- }
+ CheckGCRootsVisitor visitor;
+ if (visitor.ContainsGCRoots(info))
+ ReportClassContainsGCRoots(info, &visitor.gc_roots());
- // TODO: check for non-user defined and non-trivial destructors too.
- // TODO: support overridden finalize().
- if (CXXDestructorDecl* dtor = info->record()->getDestructor()) {
- if (dtor->isUserProvided() && !info->IsGCFinalized()) {
- // Don't report if using transition types and the body is empty.
- if (!options_.enable_oilpan) {
- ReportFinalizerInNonFinalizedClass(info, dtor);
- } else {
- if (dtor->hasBody()) {
- CompoundStmt* stmt = cast<CompoundStmt>(dtor->getBody());
- if (stmt && !stmt->body_empty())
- ReportFinalizerInNonFinalizedClass(info, dtor);
- }
- }
- }
+ if (info->NeedsFinalization())
+ CheckFinalization(info);
+ }
+ }
- if (dtor->hasBody()) {
- CheckFinalizerVisitor visitor(&cache_);
- visitor.TraverseCXXMethodDecl(dtor);
- if (!visitor.finalized_fields().empty()) {
- ReportFinalizerAccessesFinalizedFields(dtor,
- &visitor.finalized_fields());
- }
+ void CheckFinalization(RecordInfo* info) {
+ // TODO: Should we collect destructors similar to trace methods?
+ // TODO: Check overridden finalize().
+ CXXDestructorDecl* dtor = info->record()->getDestructor();
+
+ // For finalized classes, check the finalization method if possible.
+ if (info->IsGCFinalized()) {
+ if (dtor && dtor->hasBody()) {
+ CheckFinalizerVisitor visitor(&cache_);
+ visitor.TraverseCXXMethodDecl(dtor);
+ if (!visitor.finalized_fields().empty()) {
+ ReportFinalizerAccessesFinalizedFields(
+ dtor, &visitor.finalized_fields());
}
}
+ return;
+ }
+
+ // Don't require finalization of a mixin that has not yet been "mixed in".
+ if (info->IsUnmixedGCMixin())
+ return;
+
+ // Report the finalization error, and proceed to print possible causes for
+ // the finalization requirement.
+ ReportClassRequiresFinalization(info);
+
+ if (dtor && dtor->isUserProvided())
+ NoteUserDeclaredDestructor(dtor);
+
+ for (RecordInfo::Bases::iterator it = info->GetBases().begin();
+ it != info->GetBases().end();
+ ++it) {
+ if (it->second.info()->NeedsFinalization())
+ NoteBaseRequiresFinalization(&it->second);
+ }
+
+ for (RecordInfo::Fields::iterator it = info->GetFields().begin();
+ it != info->GetFields().end();
+ ++it) {
+ if (it->second.edge()->NeedsFinalization())
+ NoteField(&it->second, diag_field_requires_finalization_note_);
}
}
@@ -725,15 +759,6 @@ class BlinkGCPluginConsumer : public ASTConsumer {
}
}
- void ReportFinalizerInNonFinalizedClass(RecordInfo* info,
- CXXMethodDecl* dtor) {
- SourceLocation loc = dtor->getLocStart();
- SourceManager& manager = instance_.getSourceManager();
- FullSourceLoc full_loc(loc, manager);
- diagnostic_.Report(full_loc, diag_finalizer_in_nonfinalized_class_)
- << info->record() << dtor;
- }
-
void ReportFinalizerAccessesFinalizedFields(
CXXMethodDecl* dtor,
CheckFinalizerVisitor::Errors* fields) {
@@ -749,6 +774,14 @@ class BlinkGCPluginConsumer : public ASTConsumer {
}
}
+ void ReportClassRequiresFinalization(RecordInfo* info) {
+ SourceLocation loc = info->record()->getInnerLocStart();
+ SourceManager& manager = instance_.getSourceManager();
+ FullSourceLoc full_loc(loc, manager);
+ diagnostic_.Report(full_loc, diag_class_requires_finalization_)
+ << info->record();
+ }
+
void NoteFieldRequiresTracing(RecordInfo* holder, FieldDecl* field) {
NoteField(field, diag_field_requires_tracing_note_);
}
@@ -766,6 +799,21 @@ class BlinkGCPluginConsumer : public ASTConsumer {
NoteField(point, diag_field_contains_gc_root_note_);
}
+ void NoteUserDeclaredDestructor(CXXMethodDecl* dtor) {
+ SourceLocation loc = dtor->getLocStart();
+ SourceManager& manager = instance_.getSourceManager();
+ FullSourceLoc full_loc(loc, manager);
+ diagnostic_.Report(full_loc, diag_user_declared_destructor_note_);
+ }
+
+ void NoteBaseRequiresFinalization(BasePoint* base) {
+ SourceLocation loc = base->spec().getLocStart();
+ SourceManager& manager = instance_.getSourceManager();
+ FullSourceLoc full_loc(loc, manager);
+ diagnostic_.Report(full_loc, diag_base_requires_finalization_note_)
+ << base->info()->record();
+ }
+
void NoteField(FieldPoint* point, unsigned note) {
NoteField(point->field(), note);
}
@@ -782,7 +830,7 @@ class BlinkGCPluginConsumer : public ASTConsumer {
unsigned diag_fields_require_tracing_;
unsigned diag_class_contains_invalid_fields_;
unsigned diag_class_contains_gc_root_;
- unsigned diag_finalizer_in_nonfinalized_class_;
+ unsigned diag_class_requires_finalization_;
unsigned diag_finalizer_accesses_finalized_field_;
unsigned diag_field_requires_tracing_note_;
@@ -792,6 +840,9 @@ class BlinkGCPluginConsumer : public ASTConsumer {
unsigned diag_part_object_contains_gc_root_note_;
unsigned diag_field_contains_gc_root_note_;
unsigned diag_finalized_field_note_;
+ unsigned diag_user_declared_destructor_note_;
+ unsigned diag_base_requires_finalization_note_;
+ unsigned diag_field_requires_finalization_note_;
CompilerInstance& instance_;
DiagnosticsEngine& diagnostic_;
« no previous file with comments | « no previous file | tools/clang/blink_gc_plugin/Edge.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698