Implement defaulting of destructors.

llvm-svn: 131260
This commit is contained in:
Alexis Hunt 2011-05-12 22:46:29 +00:00
parent f9172946be
commit 1f69a02fb9
6 changed files with 64 additions and 28 deletions

View File

@ -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,

View File

@ -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;

View File

@ -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<Expr>();
}
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<CXXMethodDecl>(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!");

View File

@ -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,

View File

@ -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);

View File

@ -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);