forked from OSchip/llvm-project
Patch to mark destructors when they are used.
llvm-svn: 74359
This commit is contained in:
parent
bae2737202
commit
24a175b37c
|
@ -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">;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue