From: Sean Hunt Date: Thu, 12 May 2011 22:46:29 +0000 (+0000) Subject: Implement defaulting of destructors. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2be7e90b81509204b99b7bbf9753ad17b894a12a;p=clang Implement defaulting of destructors. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131260 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 137121a05c..8f4bfac323 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1293,6 +1293,8 @@ public: QualType ResultType, Expr *Value); + bool CanPerformCopyInitialization(const InitializedEntity &Entity, + ExprResult Init); ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init); @@ -2795,7 +2797,8 @@ public: bool FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, DeclarationName Name, Expr** Args, unsigned NumArgs, DeclContext *Ctx, - bool AllowMissing, FunctionDecl *&Operator); + bool AllowMissing, FunctionDecl *&Operator, + bool Diagnose = true); void DeclareGlobalNewDelete(); void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return, QualType Argument, @@ -2803,7 +2806,7 @@ public: bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, DeclarationName Name, FunctionDecl* &Operator, - bool AllowMissing = false); + bool Diagnose = true); /// ActOnCXXDelete - Parsed a C++ 'delete' expression ExprResult ActOnCXXDelete(SourceLocation StartLoc, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index d80bfb9b7e..b78f01c94d 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3109,8 +3109,6 @@ void Sema::CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *DD) { Diag(DD->getLocation(), diag::err_out_of_line_default_deletes) << 3 /* destructor */; } - - CheckDestructor(DD); } bool Sema::ShouldDeleteDefaultConstructor(CXXConstructorDecl *CD) { @@ -3257,7 +3255,7 @@ bool Sema::ShouldDeleteDefaultConstructor(CXXConstructorDecl *CD) { !UnionFieldRecord->hasTrivialDefaultConstructor()) return true; } - + if (AllConst) return true; diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 867bd3515b..a843ba4284 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1327,11 +1327,12 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, DeclarationName Name, Expr** Args, unsigned NumArgs, DeclContext *Ctx, - bool AllowMissing, FunctionDecl *&Operator) { + bool AllowMissing, FunctionDecl *&Operator, + bool Diagnose) { LookupResult R(*this, Name, StartLoc, LookupOrdinaryName); LookupQualifiedName(R, Ctx); if (R.empty()) { - if (AllowMissing) + if (AllowMissing || !Diagnose) return false; return Diag(StartLoc, diag::err_ovl_no_viable_function_in_call) << Name << Range; @@ -1375,40 +1376,46 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, // Watch out for variadic allocator function. unsigned NumArgsInFnDecl = FnDecl->getNumParams(); for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) { + InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, + FnDecl->getParamDecl(i)); + + if (!Diagnose && !CanPerformCopyInitialization(Entity, Owned(Args[i]))) + return true; + ExprResult Result - = PerformCopyInitialization(InitializedEntity::InitializeParameter( - Context, - FnDecl->getParamDecl(i)), - SourceLocation(), - Owned(Args[i])); + = PerformCopyInitialization(Entity, SourceLocation(), Owned(Args[i])); if (Result.isInvalid()) return true; Args[i] = Result.takeAs(); } Operator = FnDecl; - CheckAllocationAccess(StartLoc, Range, R.getNamingClass(), Best->FoundDecl); + CheckAllocationAccess(StartLoc, Range, R.getNamingClass(), Best->FoundDecl, + Diagnose); return false; } case OR_No_Viable_Function: - Diag(StartLoc, diag::err_ovl_no_viable_function_in_call) - << Name << Range; + if (Diagnose) + Diag(StartLoc, diag::err_ovl_no_viable_function_in_call) + << Name << Range; Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); return true; case OR_Ambiguous: - Diag(StartLoc, diag::err_ovl_ambiguous_call) - << Name << Range; + if (Diagnose) + Diag(StartLoc, diag::err_ovl_ambiguous_call) + << Name << Range; Candidates.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs); return true; case OR_Deleted: { - Diag(StartLoc, diag::err_ovl_deleted_call) - << Best->Function->isDeleted() - << Name - << getDeletedOrUnavailableSuffix(Best->Function) - << Range; + if (Diagnose) + Diag(StartLoc, diag::err_ovl_deleted_call) + << Best->Function->isDeleted() + << Name + << getDeletedOrUnavailableSuffix(Best->Function) + << Range; Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); return true; } @@ -1569,7 +1576,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, DeclarationName Name, - FunctionDecl* &Operator, bool AllowMissing) { + FunctionDecl* &Operator, bool Diagnose) { LookupResult Found(*this, Name, StartLoc, LookupOrdinaryName); // Try to find operator delete/operator delete[] in class scope. LookupQualifiedName(Found, RD); @@ -1596,13 +1603,22 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, // There's exactly one suitable operator; pick it. if (Matches.size() == 1) { Operator = cast(Matches[0]->getUnderlyingDecl()); + + if (Operator->isDeleted()) { + if (Diagnose) { + Diag(StartLoc, diag::err_deleted_function_use); + Diag(Operator->getLocation(), diag::note_unavailable_here) << true; + } + return true; + } + CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(), - Matches[0], !AllowMissing); + Matches[0], Diagnose); return false; // We found multiple suitable operators; complain about the ambiguity. } else if (!Matches.empty()) { - if (!AllowMissing) { + if (Diagnose) { Diag(StartLoc, diag::err_ambiguous_suitable_delete_member_function_found) << Name << RD; @@ -1617,7 +1633,7 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, // We did find operator delete/operator delete[] declarations, but // none of them were suitable. if (!Found.empty()) { - if (!AllowMissing) { + if (Diagnose) { Diag(StartLoc, diag::err_no_suitable_delete_member_function_found) << Name << RD; @@ -1637,8 +1653,8 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, Expr* DeallocArgs[1]; DeallocArgs[0] = &Null; if (FindAllocationOverload(StartLoc, SourceRange(), Name, - DeallocArgs, 1, TUDecl, AllowMissing, - Operator)) + DeallocArgs, 1, TUDecl, !Diagnose, + Operator, Diagnose)) return true; assert(Operator && "Did not find a deallocation function!"); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 26d030419a..cfa8f33fad 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -4723,6 +4723,21 @@ void InitializationSequence::dump() const { //===----------------------------------------------------------------------===// // Initialization helper functions //===----------------------------------------------------------------------===// +bool +Sema::CanPerformCopyInitialization(const InitializedEntity &Entity, + ExprResult Init) { + if (Init.isInvalid()) + return false; + + Expr *InitE = Init.get(); + assert(InitE && "No initialization expression"); + + InitializationKind Kind = InitializationKind::CreateCopy(SourceLocation(), + SourceLocation()); + InitializationSequence Seq(*this, Entity, Kind, &InitE, 1); + return Seq.getKind() != InitializationSequence::FailedSequence; +} + ExprResult Sema::PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 6c6a65a570..85c8f079c0 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -429,6 +429,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->HasWrittenPrototype = Record[Idx++]; FD->IsDeleted = Record[Idx++]; FD->IsTrivial = Record[Idx++]; + FD->IsDefaulted = Record[Idx++]; + FD->IsExplicitlyDefaulted = Record[Idx++]; FD->HasImplicitReturnZero = Record[Idx++]; FD->EndRangeLoc = ReadSourceLocation(Record, Idx); diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 8c1774a030..b0ca826e4f 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -324,6 +324,8 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Record.push_back(D->hasWrittenPrototype()); Record.push_back(D->isDeletedAsWritten()); Record.push_back(D->isTrivial()); + Record.push_back(D->isDefaulted()); + Record.push_back(D->isExplicitlyDefaulted()); Record.push_back(D->hasImplicitReturnZero()); Writer.AddSourceLocation(D->getLocEnd(), Record);