Patch to mark destructors when they are used.

llvm-svn: 74359
This commit is contained in:
Fariborz Jahanian 2009-06-26 23:49:16 +00:00
parent bae2737202
commit 24a175b37c
6 changed files with 85 additions and 8 deletions

View File

@ -593,7 +593,7 @@ def err_defining_default_ctor : Error<
"%2 does not have any default constructor">;
def note_previous_class_decl : Note<
"%0 declared here">;
def err_unintialized_member_for_assign : Error<
def err_uninitialized_member_for_assign : Error<
"cannot define the implicit default assignment operator for %0, because "
"non-static %select{reference|const}1 member %2 can't use default "
"assignment operator">;

View File

@ -1593,11 +1593,20 @@ public:
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,

View File

@ -2792,9 +2792,13 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) {
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);
}
}
}

View File

@ -1945,6 +1945,56 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
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 @@ void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation,
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 @@ void Sema::InitializeVarWithConstructor(VarDecl *VD,
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 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
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;
}

View File

@ -5593,9 +5593,10 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
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) {

View File

@ -1567,7 +1567,7 @@ Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) {
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));
}