From: Richard Smith Date: Mon, 6 Aug 2012 02:25:10 +0000 (+0000) Subject: PR13527: don't assert if a function is explicitly defaulted when it's already X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=eef00293897a73cc47f4d42e2653ff47c59d6030;p=clang PR13527: don't assert if a function is explicitly defaulted when it's already been defined. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161315 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index eb5b0cdc72..c1086fbe14 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -7483,6 +7483,7 @@ void Sema::CheckForFunctionRedefinition(FunctionDecl *FD) { else Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName(); Diag(Definition->getLocation(), diag::note_previous_definition); + FD->setInvalidDecl(); } } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 8cd134a6a0..9933bd10e1 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4552,7 +4552,8 @@ bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() { /// C++11 [class.copy]p23, and C++11 [class.dtor]p5. bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, bool Diagnose) { - assert(!MD->isInvalidDecl()); + if (MD->isInvalidDecl()) + return false; CXXRecordDecl *RD = MD->getParent(); assert(!RD->isDependentType() && "do deletion after instantiation"); if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl()) diff --git a/test/SemaCXX/cxx0x-defaulted-functions.cpp b/test/SemaCXX/cxx0x-defaulted-functions.cpp index 61c4c3338c..ce7ee672ea 100644 --- a/test/SemaCXX/cxx0x-defaulted-functions.cpp +++ b/test/SemaCXX/cxx0x-defaulted-functions.cpp @@ -117,3 +117,35 @@ namespace DefaultedFnExceptionSpec { }; OdrUse use; // expected-note {{implicit default constructor for 'DefaultedFnExceptionSpec::OdrUse' first required here}} } + +namespace PR13527 { + struct X { + X() = delete; // expected-note {{here}} + X(const X&) = delete; // expected-note {{here}} + X(X&&) = delete; // expected-note {{here}} + X &operator=(const X&) = delete; // expected-note {{here}} + X &operator=(X&&) = delete; // expected-note {{here}} + ~X() = delete; // expected-note {{here}} + }; + X::X() = default; // expected-error {{redefinition}} + X::X(const X&) = default; // expected-error {{redefinition}} + X::X(X&&) = default; // expected-error {{redefinition}} + X &X::operator=(const X&) = default; // expected-error {{redefinition}} + X &X::operator=(X&&) = default; // expected-error {{redefinition}} + X::~X() = default; // expected-error {{redefinition}} + + struct Y { + Y() = default; + Y(const Y&) = default; + Y(Y&&) = default; + Y &operator=(const Y&) = default; + Y &operator=(Y&&) = default; + ~Y() = default; + }; + Y::Y() = default; // expected-error {{definition of explicitly defaulted}} + Y::Y(const Y&) = default; // expected-error {{definition of explicitly defaulted}} + Y::Y(Y&&) = default; // expected-error {{definition of explicitly defaulted}} + Y &Y::operator=(const Y&) = default; // expected-error {{definition of explicitly defaulted}} + Y &Y::operator=(Y&&) = default; // expected-error {{definition of explicitly defaulted}} + Y::~Y() = default; // expected-error {{definition of explicitly defaulted}} +}