diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-06-26 23:49:16 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-06-26 23:49:16 +0000 |
commit | 8d2b35630d4afc474b766eeab1f1bef469cf633a (patch) | |
tree | 94846952532109c4495294d17428906a13aa37b7 | |
parent | 0b7f789945acfa0494238069895d74d44812cdea (diff) |
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
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 9 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 67 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 2 |
6 files changed, 85 insertions, 8 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 7e8c34c9c9..4ba1083089 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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">; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 48e6772353..cbe0ad7161 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1592,12 +1592,21 @@ public: 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 c154ddf86c..13162d8e8e 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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); + } } } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 016cedfe0e..b238318533 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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; } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 2f84306654..383edeca07 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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) { diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 5777c81c4e..bc8fc4eae5 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -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)); } |