Patch to mark destructors when they are used.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74359 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 48e6772..cbe0ad7 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1592,12 +1592,21 @@
CXXConstructorDecl *Constructor,
QualType DeclInitType,
Expr **Exprs, unsigned NumExprs);
+
+ /// MarcDestructorReferenced - Prepare for calling destructor on the
+ /// constructed decl.
+ void MarcDestructorReferenced(SourceLocation Loc, QualType DeclInitType);
/// DefineImplicitDefaultConstructor - Checks for feasibility of
/// defining this constructor as the default constructor.
void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor);
+ /// DefineImplicitDestructor - Checks for feasibility of
+ /// defining this destructor as the default destructor.
+ void DefineImplicitDestructor(SourceLocation CurrentLocation,
+ CXXDestructorDecl *Destructor);
+
/// DefineImplicitCopyConstructor - Checks for feasibility of
/// defining this constructor as the copy constructor.
void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index c154ddf..13162d8 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2792,9 +2792,13 @@
IK_Default);
if (!Constructor)
Var->setInvalidDecl();
- else
+ else {
if (!RD->hasTrivialConstructor())
InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0);
+ // FIXME. Must do all that is needed to destroy the object
+ // on scope exit. For now, just mark the destructor as used.
+ MarcDestructorReferenced(Var->getLocation(), InitType);
+ }
}
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 016cedf..b238318 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1945,6 +1945,56 @@
Constructor->setInvalidDecl();
}
+void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
+ CXXDestructorDecl *Destructor) {
+ assert((Destructor->isImplicit() && !Destructor->isUsed()) &&
+ "DefineImplicitDestructor - call it for implicit default dtor");
+
+ CXXRecordDecl *ClassDecl
+ = cast<CXXRecordDecl>(Destructor->getDeclContext());
+ assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
+ // C++ [class.dtor] p5
+ // Before the implicitly-declared default destructor for a class is
+ // implicitly defined, all the implicitly-declared default destructors
+ // for its base class and its non-static data members shall have been
+ // implicitly defined.
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
+ Base != ClassDecl->bases_end(); ++Base) {
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
+ if (!BaseClassDecl->hasTrivialDestructor()) {
+ if (CXXDestructorDecl *BaseDtor =
+ const_cast<CXXDestructorDecl*>(BaseClassDecl->getDestructor(Context)))
+ MarkDeclarationReferenced(CurrentLocation, BaseDtor);
+ else
+ assert(false &&
+ "DefineImplicitDestructor - missing dtor in a base class");
+ }
+ }
+
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context);
+ Field != ClassDecl->field_end(Context);
+ ++Field) {
+ QualType FieldType = Context.getCanonicalType((*Field)->getType());
+ if (const ArrayType *Array = Context.getAsArrayType(FieldType))
+ FieldType = Array->getElementType();
+ if (const RecordType *FieldClassType = FieldType->getAsRecordType()) {
+ CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+ if (!FieldClassDecl->hasTrivialDestructor()) {
+ if (CXXDestructorDecl *FieldDtor =
+ const_cast<CXXDestructorDecl*>(
+ FieldClassDecl->getDestructor(Context)))
+ MarkDeclarationReferenced(CurrentLocation, FieldDtor);
+ else
+ assert(false &&
+ "DefineImplicitDestructor - missing dtor in class of a data member");
+ }
+ }
+ }
+ Destructor->setUsed();
+}
+
void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation,
CXXMethodDecl *MethodDecl) {
assert((MethodDecl->isImplicit() && MethodDecl->isOverloadedOperator() &&
@@ -1984,14 +2034,14 @@
MarkDeclarationReferenced(CurrentLocation, FieldAssignOpMethod);
}
else if (FieldType->isReferenceType()) {
- Diag(ClassDecl->getLocation(), diag::err_unintialized_member_for_assign)
+ Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
<< Context.getTagDeclType(ClassDecl) << 0 << (*Field)->getNameAsCString();
Diag((*Field)->getLocation(), diag::note_declared_at);
Diag(CurrentLocation, diag::note_first_required_here);
err = true;
}
else if (FieldType.isConstQualified()) {
- Diag(ClassDecl->getLocation(), diag::err_unintialized_member_for_assign)
+ Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
<< Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getNameAsCString();
Diag((*Field)->getLocation(), diag::note_declared_at);
Diag(CurrentLocation, diag::note_first_required_here);
@@ -2084,6 +2134,16 @@
VD->setInit(Context, Temp);
}
+void Sema::MarcDestructorReferenced(SourceLocation Loc, QualType DeclInitType)
+{
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(
+ DeclInitType->getAsRecordType()->getDecl());
+ if (!ClassDecl->hasTrivialDestructor())
+ if (CXXDestructorDecl *Destructor =
+ const_cast<CXXDestructorDecl*>(ClassDecl->getDestructor(Context)))
+ MarkDeclarationReferenced(Loc, Destructor);
+}
+
/// AddCXXDirectInitializerToDecl - This action is called immediately after
/// ActOnDeclarator, when a C++ direct initializer is present.
/// e.g: "int x(1);"
@@ -2150,6 +2210,9 @@
VDecl->setCXXDirectInitializer(true);
InitializeVarWithConstructor(VDecl, Constructor, DeclInitType,
(Expr**)Exprs.release(), NumExprs);
+ // FIXME. Must do all that is needed to destroy the object
+ // on scope exit. For now, just mark the destructor as used.
+ MarcDestructorReferenced(VDecl->getLocation(), DeclInitType);
}
return;
}
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 2f84306..383edec 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -5593,9 +5593,10 @@
if (!Constructor->isUsed())
DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals);
}
- // FIXME: more checking for other implicits go here.
- else
- Constructor->setUsed(true);
+ } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
+ if (Destructor->isImplicit() && !Destructor->isUsed())
+ DefineImplicitDestructor(Loc, Destructor);
+
} else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D)) {
if (MethodDecl->isImplicit() && MethodDecl->isOverloadedOperator() &&
MethodDecl->getOverloadedOperator() == OO_Equal) {
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 5777c81..bc8fc4e 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1567,7 +1567,7 @@
CXXTemporary *Temp = CXXTemporary::Create(Context,
RD->getDestructor(Context));
ExprTemporaries.push_back(Temp);
-
+ MarcDestructorReferenced(E->getExprLoc(), E->getType());
// FIXME: Add the temporary to the temporaries vector.
return Owned(CXXBindTemporaryExpr::Create(Context, Temp, E));
}