diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 75 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 21 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 656 | ||||
-rw-r--r-- | test/CXX/class/p6-0x.cpp | 2 | ||||
-rw-r--r-- | test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp | 60 | ||||
-rw-r--r-- | test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp | 2 | ||||
-rw-r--r-- | test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp | 27 | ||||
-rw-r--r-- | test/SemaCXX/PR10243.cpp | 4 | ||||
-rw-r--r-- | test/SemaCXX/cxx0x-cursory-default-delete.cpp | 16 | ||||
-rw-r--r-- | test/SemaCXX/cxx0x-defaulted-functions.cpp | 12 |
10 files changed, 290 insertions, 585 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 2b7875b332..1592867e26 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -4984,60 +4984,33 @@ def warn_cxx98_compat_explicit_conversion_functions : Warning< InGroup<CXX98Compat>, DefaultIgnore; // C++11 defaulted functions -def err_defaulted_default_ctor_params : Error< - "an explicitly-defaulted default constructor must have no parameters">; -def err_defaulted_copy_ctor_params : Error< - "an explicitly-defaulted copy constructor must have exactly one parameter">; -def err_defaulted_copy_ctor_volatile_param : Error< - "the parameter for an explicitly-defaulted copy constructor may not be " - "volatile">; -def err_defaulted_copy_ctor_const_param : Error< - "the parameter for this explicitly-defaulted copy constructor is const, but " - "a member or base requires it to be non-const">; -def err_defaulted_copy_assign_params : Error< - "an explicitly-defaulted copy assignment operator must have exactly one " - "parameter">; -def err_defaulted_copy_assign_return_type : Error< - "an explicitly-defaulted copy assignment operator must return an unqualified " - "lvalue reference to its class type">; +def err_defaulted_special_member_params : Error< + "an explicitly-defaulted %select{|copy |move }0constructor cannot " + "have default arguments">; +def err_defaulted_special_member_return_type : Error< + "explicitly-defaulted %select{copy|move}0 assignment operator must " + "return %1">; +def err_defaulted_special_member_quals : Error< + "an explicitly-defaulted %select{copy|move}0 assignment operator may not " + "have 'const', 'constexpr' or 'volatile' qualifiers">; +def err_defaulted_special_member_volatile_param : Error< + "the parameter for an explicitly-defaulted %select{<<ERROR>>|" + "copy constructor|move constructor|copy assignment operator|" + "move assignment operator|<<ERROR>>}0 may not be volatile">; +def err_defaulted_special_member_move_const_param : Error< + "the parameter for an explicitly-defaulted move " + "%select{constructor|assignment operator}0 may not be const">; +def err_defaulted_special_member_copy_const_param : Error< + "the parameter for this explicitly-defaulted copy " + "%select{constructor|assignment operator}0 is const, but a member or base " + "requires it to be non-const">; +def err_defaulted_special_member_copy_non_const_param : Error< + "explicitly-defaulted copy %select{constructor|assignment operator}0 with " + "a non-const parameter must be defaulted outside the class, unless a base or " + "member requires the parameter to be non-const">; def err_defaulted_copy_assign_not_ref : Error< "the parameter for an explicitly-defaulted copy assignment operator must be an " "lvalue reference type">; -def err_defaulted_copy_assign_volatile_param : Error< - "the parameter for an explicitly-defaulted copy assignment operator may not " - "be volatile">; -def err_defaulted_copy_assign_const_param : Error< - "the parameter for this explicitly-defaulted copy assignment operator is " - "const, but a member or base requires it to be non-const">; -def err_defaulted_copy_assign_quals : Error< - "an explicitly-defaulted copy assignment operator may not have 'const', " - "'constexpr' or 'volatile' qualifiers">; -def err_defaulted_move_ctor_params : Error< - "an explicitly-defaulted move constructor must have exactly one parameter">; -def err_defaulted_move_ctor_volatile_param : Error< - "the parameter for an explicitly-defaulted move constructor may not be " - "volatile">; -def err_defaulted_move_ctor_const_param : Error< - "the parameter for an explicitly-defaulted move constructor may not be " - "const">; -def err_defaulted_move_assign_params : Error< - "an explicitly-defaulted move assignment operator must have exactly one " - "parameter">; -def err_defaulted_move_assign_return_type : Error< - "an explicitly-defaulted move assignment operator must return an unqualified " - "lvalue reference to its class type">; -def err_defaulted_move_assign_not_ref : Error< - "the parameter for an explicitly-defaulted move assignment operator must be an " - "rvalue reference type">; -def err_defaulted_move_assign_volatile_param : Error< - "the parameter for an explicitly-defaulted move assignment operator may not " - "be volatile">; -def err_defaulted_move_assign_const_param : Error< - "the parameter for an explicitly-defaulted move assignment operator may not " - "be const">; -def err_defaulted_move_assign_quals : Error< - "an explicitly-defaulted move assignment operator may not have 'const', " - "'constexpr' or 'volatile' qualifiers">; def err_incorrect_defaulted_exception_spec : Error< "exception specification of explicitly defaulted %select{default constructor|" "copy constructor|move constructor|copy assignment operator|move assignment " diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index a231b8625b..c9e9e5244b 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3306,11 +3306,21 @@ public: ComputedEST = EST_Delayed; } - FunctionProtoType::ExtProtoInfo getEPI() const { - FunctionProtoType::ExtProtoInfo EPI; + /// \brief Have we been unable to compute this exception specification? + bool isDelayed() { + return ComputedEST == EST_Delayed; + } + + /// \brief Overwrite an EPI's exception specification with this + /// computed exception specification. + void getEPI(FunctionProtoType::ExtProtoInfo &EPI) const { EPI.ExceptionSpecType = getExceptionSpecType(); EPI.NumExceptions = size(); EPI.Exceptions = data(); + } + FunctionProtoType::ExtProtoInfo getEPI() const { + FunctionProtoType::ExtProtoInfo EPI; + getEPI(EPI); return EPI; } }; @@ -4276,12 +4286,7 @@ public: Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion); void CheckExplicitlyDefaultedMethods(CXXRecordDecl *Record); - void CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *Ctor); - void CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *Ctor); - void CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *Method); - void CheckExplicitlyDefaultedMoveConstructor(CXXConstructorDecl *Ctor); - void CheckExplicitlyDefaultedMoveAssignment(CXXMethodDecl *Method); - void CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *Dtor); + void CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD); //===--------------------------------------------------------------------===// // C++ Derived Classes diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 3c74f73163..9143eb282f 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3801,550 +3801,204 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { void Sema::CheckExplicitlyDefaultedMethods(CXXRecordDecl *Record) { for (CXXRecordDecl::method_iterator MI = Record->method_begin(), ME = Record->method_end(); - MI != ME; ++MI) { - if (!MI->isInvalidDecl() && MI->isExplicitlyDefaulted()) { - switch (getSpecialMember(&*MI)) { - case CXXDefaultConstructor: - CheckExplicitlyDefaultedDefaultConstructor( - cast<CXXConstructorDecl>(&*MI)); - break; - - case CXXDestructor: - CheckExplicitlyDefaultedDestructor(cast<CXXDestructorDecl>(&*MI)); - break; - - case CXXCopyConstructor: - CheckExplicitlyDefaultedCopyConstructor(cast<CXXConstructorDecl>(&*MI)); - break; - - case CXXCopyAssignment: - CheckExplicitlyDefaultedCopyAssignment(&*MI); - break; - - case CXXMoveConstructor: - CheckExplicitlyDefaultedMoveConstructor(cast<CXXConstructorDecl>(&*MI)); - break; - - case CXXMoveAssignment: - CheckExplicitlyDefaultedMoveAssignment(&*MI); - break; - - case CXXInvalid: - llvm_unreachable("non-special member explicitly defaulted!"); - } - } - } - + MI != ME; ++MI) + if (!MI->isInvalidDecl() && MI->isExplicitlyDefaulted()) + CheckExplicitlyDefaultedSpecialMember(&*MI); } -void Sema::CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *CD) { - assert(CD->isExplicitlyDefaulted() && CD->isDefaultConstructor()); - - // Whether this was the first-declared instance of the constructor. - // This affects whether we implicitly add an exception spec (and, eventually, - // constexpr). It is also ill-formed to explicitly default a constructor such - // that it would be deleted. (C++0x [decl.fct.def.default]) - bool First = CD == CD->getCanonicalDecl(); - - bool HadError = false; - if (CD->getNumParams() != 0) { - Diag(CD->getLocation(), diag::err_defaulted_default_ctor_params) - << CD->getSourceRange(); - HadError = true; - } - - ImplicitExceptionSpecification Spec - = ComputeDefaultedDefaultCtorExceptionSpec(CD->getParent()); - FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); - if (EPI.ExceptionSpecType == EST_Delayed) { - // Exception specification depends on some deferred part of the class. We'll - // try again when the class's definition has been fully processed. - return; - } - const FunctionProtoType *CtorType = CD->getType()->getAs<FunctionProtoType>(), - *ExceptionType = Context.getFunctionType( - Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>(); - - // C++11 [dcl.fct.def.default]p2: - // An explicitly-defaulted function may be declared constexpr only if it - // would have been implicitly declared as constexpr, - // Do not apply this rule to templates, since core issue 1358 makes such - // functions always instantiate to constexpr functions. - if (CD->isConstexpr() && - CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { - if (!CD->getParent()->defaultedDefaultConstructorIsConstexpr()) { - Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr) - << CXXDefaultConstructor; - HadError = true; - } - } - // and may have an explicit exception-specification only if it is compatible - // with the exception-specification on the implicit declaration. - if (CtorType->hasExceptionSpec()) { - if (CheckEquivalentExceptionSpec( - PDiag(diag::err_incorrect_defaulted_exception_spec) - << CXXDefaultConstructor, - PDiag(), - ExceptionType, SourceLocation(), - CtorType, CD->getLocation())) { - HadError = true; - } - } - - // If a function is explicitly defaulted on its first declaration, - if (First) { - // -- it is implicitly considered to be constexpr if the implicit - // definition would be, - CD->setConstexpr(CD->getParent()->defaultedDefaultConstructorIsConstexpr()); - - // -- it is implicitly considered to have the same - // exception-specification as if it had been implicitly declared - // - // FIXME: a compatible, but different, explicit exception specification - // will be silently overridden. We should issue a warning if this happens. - EPI.ExtInfo = CtorType->getExtInfo(); - - // Such a function is also trivial if the implicitly-declared function - // would have been. - CD->setTrivial(CD->getParent()->hasTrivialDefaultConstructor()); - } - - if (HadError) { - CD->setInvalidDecl(); - return; - } - - if (ShouldDeleteSpecialMember(CD, CXXDefaultConstructor)) { - if (First) { - CD->setDeletedAsWritten(); - } else { - Diag(CD->getLocation(), diag::err_out_of_line_default_deletes) - << CXXDefaultConstructor; - CD->setInvalidDecl(); - } - } -} +void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { + CXXRecordDecl *RD = MD->getParent(); + CXXSpecialMember CSM = getSpecialMember(MD); -void Sema::CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *CD) { - assert(CD->isExplicitlyDefaulted() && CD->isCopyConstructor()); + assert(MD->isExplicitlyDefaulted() && CSM != CXXInvalid && + "not an explicitly-defaulted special member"); // Whether this was the first-declared instance of the constructor. - bool First = CD == CD->getCanonicalDecl(); - - bool HadError = false; - if (CD->getNumParams() != 1) { - Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_params) - << CD->getSourceRange(); - HadError = true; - } - - ImplicitExceptionSpecification Spec(*this); - bool Const; - llvm::tie(Spec, Const) = - ComputeDefaultedCopyCtorExceptionSpecAndConst(CD->getParent()); - - FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); - const FunctionProtoType *CtorType = CD->getType()->getAs<FunctionProtoType>(), - *ExceptionType = Context.getFunctionType( - Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>(); - - // Check for parameter type matching. - // This is a copy ctor so we know it's a cv-qualified reference to T. - QualType ArgType = CtorType->getArgType(0); - if (ArgType->getPointeeType().isVolatileQualified()) { - Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_volatile_param); - HadError = true; - } - if (ArgType->getPointeeType().isConstQualified() && !Const) { - Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_const_param); - HadError = true; - } - - // C++11 [dcl.fct.def.default]p2: - // An explicitly-defaulted function may be declared constexpr only if it - // would have been implicitly declared as constexpr, - // Do not apply this rule to templates, since core issue 1358 makes such - // functions always instantiate to constexpr functions. - if (CD->isConstexpr() && - CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { - if (!CD->getParent()->defaultedCopyConstructorIsConstexpr()) { - Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr) - << CXXCopyConstructor; - HadError = true; - } - } - // and may have an explicit exception-specification only if it is compatible - // with the exception-specification on the implicit declaration. - if (CtorType->hasExceptionSpec()) { - if (CheckEquivalentExceptionSpec( - PDiag(diag::err_incorrect_defaulted_exception_spec) - << CXXCopyConstructor, - PDiag(), - ExceptionType, SourceLocation(), - CtorType, CD->getLocation())) { - HadError = true; - } - } - - // If a function is explicitly defaulted on its first declaration, - if (First) { - // -- it is implicitly considered to be constexpr if the implicit - // definition would be, - CD->setConstexpr(CD->getParent()->defaultedCopyConstructorIsConstexpr()); - - // -- it is implicitly considered to have the same - // exception-specification as if it had been implicitly declared, and - // - // FIXME: a compatible, but different, explicit exception specification - // will be silently overridden. We should issue a warning if this happens. - EPI.ExtInfo = CtorType->getExtInfo(); - - // -- [...] it shall have the same parameter type as if it had been - // implicitly declared. - CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI)); - - // Such a function is also trivial if the implicitly-declared function - // would have been. - CD->setTrivial(CD->getParent()->hasTrivialCopyConstructor()); - } - - if (HadError) { - CD->setInvalidDecl(); - return; - } - - if (ShouldDeleteSpecialMember(CD, CXXCopyConstructor)) { - if (First) { - CD->setDeletedAsWritten(); - } else { - Diag(CD->getLocation(), diag::err_out_of_line_default_deletes) - << CXXCopyConstructor; - CD->setInvalidDecl(); - } - } -} - -void Sema::CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *MD) { - assert(MD->isExplicitlyDefaulted()); - - // Whether this was the first-declared instance of the operator + // This affects whether we implicitly add an exception spec and constexpr. bool First = MD == MD->getCanonicalDecl(); bool HadError = false; - if (MD->getNumParams() != 1) { - Diag(MD->getLocation(), diag::err_defaulted_copy_assign_params) - << MD->getSourceRange(); - HadError = true; - } - QualType ReturnType = - MD->getType()->getAs<FunctionType>()->getResultType(); - if (!ReturnType->isLValueReferenceType() || - !Context.hasSameType( - Context.getCanonicalType(ReturnType->getPointeeType()), - Context.getCanonicalType(Context.getTypeDeclType(MD->getParent())))) { - Diag(MD->getLocation(), diag::err_defaulted_copy_assign_return_type); + // C++11 [dcl.fct.def.default]p1: + // A function that is explicitly defaulted shall + // -- be a special member function (checked elsewhere), + // -- have the same type (except for ref-qualifiers, and except that a + // copy operation can take a non-const reference) as an implicit + // declaration, and + // -- not have default arguments. + unsigned ExpectedParams = 1; + if (CSM == CXXDefaultConstructor || CSM == CXXDestructor) + ExpectedParams = 0; + if (MD->getNumParams() != ExpectedParams) { + // This also checks for default arguments: a copy or move constructor with a + // default argument is classified as a default constructor, and assignment + // operations and destructors can't have default arguments. + Diag(MD->getLocation(), diag::err_defaulted_special_member_params) + << CSM << MD->getSourceRange(); HadError = true; } - ImplicitExceptionSpecification Spec(*this); - bool Const; - llvm::tie(Spec, Const) = - ComputeDefaultedCopyCtorExceptionSpecAndConst(MD->getParent()); - - FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); - const FunctionProtoType *OperType = MD->getType()->getAs<FunctionProtoType>(), - *ExceptionType = Context.getFunctionType( - Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>(); + const FunctionProtoType *Type = MD->getType()->getAs<FunctionProtoType>(); - QualType ArgType = OperType->getArgType(0); - if (!ArgType->isLValueReferenceType()) { - Diag(MD->getLocation(), diag::err_defaulted_copy_assign_not_ref); - HadError = true; - } else { - if (ArgType->getPointeeType().isVolatileQualified()) { - Diag(MD->getLocation(), diag::err_defaulted_copy_assign_volatile_param); + // Compute implicit exception specification, argument constness, constexpr + // and triviality. + ImplicitExceptionSpecification Spec(*this); + bool Const = false; + bool Constexpr = false; + bool Trivial; + switch (CSM) { + case CXXDefaultConstructor: + Spec = ComputeDefaultedDefaultCtorExceptionSpec(RD); + if (Spec.isDelayed()) + // Exception specification depends on some deferred part of the class. + // We'll try again when the class's definition has been fully processed. + return; + Constexpr = RD->defaultedDefaultConstructorIsConstexpr(); + Trivial = RD->hasTrivialDefaultConstructor(); + break; + case CXXCopyConstructor: + llvm::tie(Spec, Const) = + ComputeDefaultedCopyCtorExceptionSpecAndConst(RD); + Constexpr = RD->defaultedCopyConstructorIsConstexpr(); + Trivial = RD->hasTrivialCopyConstructor(); + break; + case CXXCopyAssignment: + llvm::tie(Spec, Const) = + ComputeDefaultedCopyAssignmentExceptionSpecAndConst(RD); + Trivial = RD->hasTrivialCopyAssignment(); + break; + case CXXMoveConstructor: + Spec = ComputeDefaultedMoveCtorExceptionSpec(RD); + Constexpr = RD->defaultedMoveConstructorIsConstexpr(); + Trivial = RD->hasTrivialMoveConstructor(); + break; + case CXXMoveAssignment: + Spec = ComputeDefaultedMoveAssignmentExceptionSpec(RD); + Trivial = RD->hasTrivialMoveAssignment(); + break; + case CXXDestructor: + Spec = ComputeDefaultedDtorExceptionSpec(RD); + Trivial = RD->hasTrivialDestructor(); + break; + case CXXInvalid: + llvm_unreachable("non-special member explicitly defaulted!"); + } + + QualType ReturnType = Context.VoidTy; + if (CSM == CXXCopyAssignment || CSM == CXXMoveAssignment) { + // Check for return type matching. + ReturnType = Type->getResultType(); + QualType ExpectedReturnType = + Context.getLValueReferenceType(Context.getTypeDeclType(RD)); + if (!Context.hasSameType(ReturnType, ExpectedReturnType)) { + Diag(MD->getLocation(), diag::err_defaulted_special_member_return_type) + << (CSM == CXXMoveAssignment) << ExpectedReturnType; HadError = true; } - if (ArgType->getPointeeType().isConstQualified() && !Const) { - Diag(MD->getLocation(), diag::err_defaulted_copy_assign_const_param); + + // A defaulted special member cannot have cv-qualifiers. + if (Type->getTypeQuals()) { + Diag(MD->getLocation(), diag::err_defaulted_special_member_quals) + << (CSM == CXXMoveAssignment); HadError = true; } } - if (OperType->getTypeQuals()) { - Diag(MD->getLocation(), diag::err_defaulted_copy_assign_quals); - HadError = true; - } - - if (OperType->hasExceptionSpec()) { - if (CheckEquivalentExceptionSpec( - PDiag(diag::err_incorrect_defaulted_exception_spec) - << CXXCopyAssignment, - PDiag(), - ExceptionType, SourceLocation(), - OperType, MD->getLocation())) { + // Check for parameter type matching. + QualType ArgType = ExpectedParams ? Type->getArgType(0) : QualType(); + if (ExpectedParams && ArgType->isReferenceType()) { + // Argument must be reference to possibly-const T. + QualType ReferentType = ArgType->getPointeeType(); + + if (ReferentType.isVolatileQualified()) { + Diag(MD->getLocation(), + diag::err_defaulted_special_member_volatile_param) << CSM; HadError = true; } - } - if (First) { - // We set the declaration to have the computed exception spec here. - // We duplicate the one parameter type. - EPI.RefQualifier = OperType->getRefQualifier(); - EPI.ExtInfo = OperType->getExtInfo(); - MD->setType(Context.getFunctionType(ReturnType, &ArgType, 1, EPI)); - - // Such a function is also trivial if the implicitly-declared function - // would have been. - MD->setTrivial(MD->getParent()->hasTrivialCopyAssignment()); - } - if (HadError) { - MD->setInvalidDecl(); - return; - } - - if (ShouldDeleteSpecialMember(MD, CXXCopyAssignment)) { - if (First) { - MD->setDeletedAsWritten(); - } else { - Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) - << CXXCopyAssignment; - MD->setInvalidDecl(); + if (ReferentType.isConstQualified() && !Const) { + if (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment) { + Diag(MD->getLocation(), + diag::err_defaulted_special_member_copy_const_param) + << (CSM == CXXCopyAssignment); + // FIXME: Explain why this special member can't be const. + } else { + Diag(MD->getLocation(), + diag::err_defaulted_special_member_move_const_param) + << (CSM == CXXMoveAssignment); + } + HadError = true; } - } -} -void Sema::CheckExplicitlyDefaultedMoveConstructor(CXXConstructorDecl *CD) { - assert(CD->isExplicitlyDefaulted() && CD->isMoveConstructor()); - - // Whether this was the first-declared instance of the constructor. - bool First = CD == CD->getCanonicalDecl(); - - bool HadError = false; - if (CD->getNumParams() != 1) { - Diag(CD->getLocation(), diag::err_defaulted_move_ctor_params) - << CD->getSourceRange(); + // If a function is explicitly defaulted on its first declaration, it shall + // have the same parameter type as if it had been implicitly declared. + // (Presumably this is to prevent it from being trivial?) + if (!ReferentType.isConstQualified() && Const && First) + Diag(MD->getLocation(), + diag::err_defaulted_special_member_copy_non_const_param) + << (CSM == CXXCopyAssignment); + } else if (ExpectedParams) { + // A copy assignment operator can take its argument by value, but a + // defaulted one cannot. + assert(CSM == CXXCopyAssignment && "unexpected non-ref argument"); + Diag(MD->getLocation(), diag::err_defaulted_copy_assign_not_ref); HadError = true; } - ImplicitExceptionSpecification Spec( - ComputeDefaultedMoveCtorExceptionSpec(CD->getParent())); - - FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); - const FunctionProtoType *CtorType = CD->getType()->getAs<FunctionProtoType>(), - *ExceptionType = Context.getFunctionType( - Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>(); - - // Check for parameter type matching. - // This is a move ctor so we know it's a cv-qualified rvalue reference to T. - QualType ArgType = CtorType->getArgType(0); - if (ArgType->getPointeeType().isVolatileQualified()) { - Diag(CD->getLocation(), diag::err_defaulted_move_ctor_volatile_param); - HadError = true; - } - if (ArgType->getPointeeType().isConstQualified()) { - Diag(CD->getLocation(), diag::err_defaulted_move_ctor_const_param); - HadError = true; - } + // Rebuild the type with the implicit exception specification added. + FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo(); + Spec.getEPI(EPI); + const FunctionProtoType *ImplicitType = cast<FunctionProtoType>( + Context.getFunctionType(ReturnType, &ArgType, ExpectedParams, EPI)); // C++11 [dcl.fct.def.default]p2: // An explicitly-defaulted function may be declared constexpr only if it // would have been implicitly declared as constexpr, - // Do not apply this rule to templates, since core issue 1358 makes such - // functions always instantiate to constexpr functions. - if (CD->isConstexpr() && - CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { - if (!CD->getParent()->defaultedMoveConstructorIsConstexpr()) { - Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr) - << CXXMoveConstructor; - HadError = true; - } + // Do not apply this rule to members of class templates, since core issue 1358 + // makes such functions always instantiate to constexpr functions. For + // non-constructors, this is checked elsewhere. + if (isa<CXXConstructorDecl>(MD) && MD->isConstexpr() && !Constexpr && + MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { + Diag(MD->getLocStart(), diag::err_incorrect_defaulted_constexpr) << CSM; + HadError = true; } // and may have an explicit exception-specification only if it is compatible // with the exception-specification on the implicit declaration. - if (CtorType->hasExceptionSpec()) { - if (CheckEquivalentExceptionSpec( - PDiag(diag::err_incorrect_defaulted_exception_spec) - << CXXMoveConstructor, - PDiag(), - ExceptionType, SourceLocation(), - CtorType, CD->getLocation())) { - HadError = true; - } - } + if (Type->hasExceptionSpec() && + CheckEquivalentExceptionSpec( + PDiag(diag::err_incorrect_defaulted_exception_spec) << CSM, + PDiag(), ImplicitType, SourceLocation(), Type, MD->getLocation())) + HadError = true; // If a function is explicitly defaulted on its first declaration, if (First) { // -- it is implicitly considered to be constexpr if the implicit // definition would be, - CD->setConstexpr(CD->getParent()->defaultedMoveConstructorIsConstexpr()); - - // -- it is implicitly considered to have the same - // exception-specification as if it had been implicitly declared, and - // - // FIXME: a compatible, but different, explicit exception specification - // will be silently overridden. We should issue a warning if this happens. - EPI.ExtInfo = CtorType->getExtInfo(); + MD->setConstexpr(Constexpr); - // -- [...] it shall have the same parameter type as if it had been - // implicitly declared. - CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI)); + // -- it is implicitly considered to have the same exception-specification + // as if it had been implicitly declared, + MD->setType(QualType(ImplicitType, 0)); // Such a function is also trivial if the implicitly-declared function // would have been. - CD->setTrivial(CD->getParent()->hasTrivialMoveConstructor()); + MD->setTrivial(Trivial); } - if (HadError) { - CD->setInvalidDecl(); - return; - } - - if (ShouldDeleteSpecialMember(CD, CXXMoveConstructor)) { + if (ShouldDeleteSpecialMember(MD, CSM)) { if (First) { - CD->setDeletedAsWritten(); + MD->setDeletedAsWritten(); } else { - Diag(CD->getLocation(), diag::err_out_of_line_default_deletes) - << CXXMoveConstructor; - CD->setInvalidDecl(); - } - } -} - -void Sema::CheckExplicitlyDefaultedMoveAssignment(CXXMethodDecl *MD) { - assert(MD->isExplicitlyDefaulted()); - - // Whether this was the first-declared instance of the operator - bool First = MD == MD->getCanonicalDecl(); - - bool HadError = false; - if (MD->getNumParams() != 1) { - Diag(MD->getLocation(), diag::err_defaulted_move_assign_params) - << MD->getSourceRange(); - HadError = true; - } - - QualType ReturnType = - MD->getType()->getAs<FunctionType>()->getResultType(); - if (!ReturnType->isLValueReferenceType() || - !Context.hasSameType( - Context.getCanonicalType(ReturnType->getPointeeType()), - Context.getCanonicalType(Context.getTypeDeclType(MD->getParent())))) { - Diag(MD->getLocation(), diag::err_defaulted_move_assign_return_type); - HadError = true; - } - - ImplicitExceptionSpecification Spec( - ComputeDefaultedMoveCtorExceptionSpec(MD->getParent())); - - FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); - const FunctionProtoType *OperType = MD->getType()->getAs<FunctionProtoType>(), - *ExceptionType = Context.getFunctionType( - Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>(); - - QualType ArgType = OperType->getArgType(0); - if (!ArgType->isRValueReferenceType()) { - Diag(MD->getLocation(), diag::err_defaulted_move_assign_not_ref); - HadError = true; - } else { - if (ArgType->getPointeeType().isVolatileQualified()) { - Diag(MD->getLocation(), diag::err_defaulted_move_assign_volatile_param); + // C++11 [dcl.fct.def.default]p4: + // [For a] user-provided explicitly-defaulted function [...] if such a + // function is implicitly defined as deleted, the program is ill-formed. + Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM; HadError = true; } - if (ArgType->getPointeeType().isConstQualified()) { - Diag(MD->getLocation(), diag::err_defaulted_move_assign_const_param); - HadError = true; - } - } - - if (OperType->getTypeQuals()) { - Diag(MD->getLocation(), diag::err_defaulted_move_assign_quals); - HadError = true; - } - - if (OperType->hasExceptionSpec()) { - if (CheckEquivalentExceptionSpec( - PDiag(diag::err_incorrect_defaulted_exception_spec) - << CXXMoveAssignment, - PDiag(), - ExceptionType, SourceLocation(), - OperType, MD->getLocation())) { - HadError = true; - } - } - if (First) { - // We set the declaration to have the computed exception spec here. - // We duplicate the one parameter type. - EPI.RefQualifier = OperType->getRefQualifier(); - EPI.ExtInfo = OperType->getExtInfo(); - MD->setType(Context.getFunctionType(ReturnType, &ArgType, 1, EPI)); - - // Such a function is also trivial if the implicitly-declared function - // would have been. - MD->setTrivial(MD->getParent()->hasTrivialMoveAssignment()); } - if (HadError) { + if (HadError) MD->setInvalidDecl(); - return; - } - - if (ShouldDeleteSpecialMember(MD, CXXMoveAssignment)) { - if (First) { - MD->setDeletedAsWritten(); - } else { - Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) - << CXXMoveAssignment; - MD->setInvalidDecl(); - } - } -} - -void Sema::CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *DD) { - assert(DD->isExplicitlyDefaulted()); - - // Whether this was the first-declared instance of the destructor. - bool First = DD == DD->getCanonicalDecl(); - - ImplicitExceptionSpecification Spec - = ComputeDefaultedDtorExceptionSpec(DD->getParent()); - FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); - const FunctionProtoType *DtorType = DD->getType()->getAs<FunctionProtoType>(), - *ExceptionType = Context.getFunctionType( - Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>(); - - if (DtorType->hasExceptionSpec()) { - if (CheckEquivalentExceptionSpec( - PDiag(diag::err_incorrect_defaulted_exception_spec) - << CXXDestructor, - PDiag(), - ExceptionType, SourceLocation(), - DtorType, DD->getLocation())) { - DD->setInvalidDecl(); - return; - } - } - if (First) { - // We set the declaration to have the computed exception spec here. - // There are no parameters. - EPI.ExtInfo = DtorType->getExtInfo(); - DD->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); - - // Such a function is also trivial if the implicitly-declared function - // would have been. - DD->setTrivial(DD->getParent()->hasTrivialDestructor()); - } - - if (ShouldDeleteSpecialMember(DD, CXXDestructor)) { - if (First) { - DD->setDeletedAsWritten(); - } else { - Diag(DD->getLocation(), diag::err_out_of_line_default_deletes) - << CXXDestructor; - DD->setInvalidDecl(); - } - } } namespace { @@ -7021,7 +6675,7 @@ void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) { // specification is deferred until now. if (!CtorDecl->isInvalidDecl() && CtorDecl->isExplicitlyDefaulted() && !ClassDecl->isDependentType()) - CheckExplicitlyDefaultedDefaultConstructor(CtorDecl); + CheckExplicitlyDefaultedSpecialMember(CtorDecl); } void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { @@ -7600,7 +7254,7 @@ std::pair<Sema::ImplicitExceptionSpecification, bool> Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst( CXXRecordDecl *ClassDecl) { if (ClassDecl->isInvalidDecl()) - return std::make_pair(ImplicitExceptionSpecification(*this), false); + return std::make_pair(ImplicitExceptionSpecification(*this), true); // C++ [class.copy]p10: // If the class definition does not explicitly declare a copy @@ -8635,7 +8289,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, std::pair<Sema::ImplicitExceptionSpecification, bool> Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) { if (ClassDecl->isInvalidDecl()) - return std::make_pair(ImplicitExceptionSpecification(*this), false); + return std::make_pair(ImplicitExceptionSpecification(*this), true); // C++ [class.copy]p5: // The implicitly-declared copy constructor for a class X will @@ -10546,7 +10200,7 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { switch (Member) { case CXXDefaultConstructor: { CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD); - CheckExplicitlyDefaultedDefaultConstructor(CD); + CheckExplicitlyDefaultedSpecialMember(CD); if (!CD->isInvalidDecl()) DefineImplicitDefaultConstructor(DefaultLoc, CD); break; @@ -10554,14 +10208,14 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { case CXXCopyConstructor: { CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD); - CheckExplicitlyDefaultedCopyConstructor(CD); + CheckExplicitlyDefaultedSpecialMember(CD); if (!CD->isInvalidDecl()) DefineImplicitCopyConstructor(DefaultLoc, CD); break; } case CXXCopyAssignment: { - CheckExplicitlyDefaultedCopyAssignment(MD); + CheckExplicitlyDefaultedSpecialMember(MD); if (!MD->isInvalidDecl()) DefineImplicitCopyAssignment(DefaultLoc, MD); break; @@ -10569,7 +10223,7 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { case CXXDestructor: { CXXDestructorDecl *DD = cast<CXXDestructorDecl>(MD); - CheckExplicitlyDefaultedDestructor(DD); + CheckExplicitlyDefaultedSpecialMember(DD); if (!DD->isInvalidDecl()) DefineImplicitDestructor(DefaultLoc, DD); break; @@ -10577,14 +10231,14 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { case CXXMoveConstructor: { CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD); - CheckExplicitlyDefaultedMoveConstructor(CD); + CheckExplicitlyDefaultedSpecialMember(CD); if (!CD->isInvalidDecl()) DefineImplicitMoveConstructor(DefaultLoc, CD); break; } case CXXMoveAssignment: { - CheckExplicitlyDefaultedMoveAssignment(MD); + CheckExplicitlyDefaultedSpecialMember(MD); if (!MD->isInvalidDecl()) DefineImplicitMoveAssignment(DefaultLoc, MD); break; diff --git a/test/CXX/class/p6-0x.cpp b/test/CXX/class/p6-0x.cpp index f2cf482821..e153b4daaf 100644 --- a/test/CXX/class/p6-0x.cpp +++ b/test/CXX/class/p6-0x.cpp @@ -19,7 +19,7 @@ struct Trivial2 { Trivial2(const Trivial2 &) = default; Trivial2(Trivial2 &&) = default; Trivial2 &operator=(const Trivial2 &) = default; - Trivial2 &operator=(Trivial2 &) = default; + Trivial2 &operator=(Trivial2 &&) = default; ~Trivial2() = default; }; diff --git a/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp index 06dd1bb055..a4dffda1f9 100644 --- a/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp +++ b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -fcxx-exceptions %s // An explicitly-defaulted function may be declared constexpr only if it would // have been implicitly declared as constexpr. @@ -54,3 +54,61 @@ struct S5 { }; constexpr S5::S5() = default; static_assert(S5().m == 4, ""); + + +// An explicitly-defaulted function may have an exception specification only if +// it is compatible with the exception specification on an implicit declaration. +struct E1 { + E1() noexcept = default; + E1(const E1&) noexcept = default; + E1(E1&&) noexcept = default; + E1 &operator=(const E1&) noexcept = default; + E1 &operator=(E1&&) noexcept = default; + ~E1() noexcept = default; +}; +struct E2 { + E2() noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted default constructor does not match the calculated one}} + E2(const E2&) noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted copy constructor does not match the calculated one}} + E2(E2&&) noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted move constructor does not match the calculated one}} + E2 &operator=(const E2&) noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted copy assignment operator does not match the calculated one}} + E2 &operator=(E2&&) noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted move assignment operator does not match the calculated one}} + ~E2() noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted destructor does not match the calculated one}} +}; + +// If a function is explicitly defaulted on its first declaration +// -- it is implicitly considered to have the same exception-specification as +// if it had been implicitly declared +struct E3 { + E3() = default; + E3(const E3&) = default; + E3(E3&&) = default; + E3 &operator=(const E3&) = default; + E3 &operator=(E3&&) = default; + ~E3() = default; +}; +E3 e3; +static_assert(noexcept(E3(), E3(E3()), E3(e3), e3 = E3(), e3 = e3), ""); +struct E4 { + E4() noexcept(false); + E4(const E4&) noexcept(false); + E4(E4&&) noexcept(false); + E4 &operator=(const E4&) noexcept(false); + E4 &operator=(E4&&) noexcept(false); + ~E4() noexcept(false); +}; +struct E5 { + E5() = default; + E5(const E5&) = default; + E5(E5&&) = default; + E5 &operator=(const E5&) = default; + E5 &operator=(E5&&) = default; + ~E5() = default; + + E4 e4; +}; +E5 e5; +static_assert(!noexcept(E5()), ""); +static_assert(!noexcept(E5(static_cast<E5&&>(e5))), ""); +static_assert(!noexcept(E5(e5)), ""); +static_assert(!noexcept(e5 = E5()), ""); +static_assert(!noexcept(e5 = e5), ""); diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp index 7764980e34..fef3692609 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp @@ -72,7 +72,7 @@ struct DefaultedAggr { DefaultedAggr(const DefaultedAggr &) = default; DefaultedAggr(DefaultedAggr &&) = default; DefaultedAggr &operator=(const DefaultedAggr &) = default; - DefaultedAggr &operator=(DefaultedAggr &) = default; + DefaultedAggr &operator=(DefaultedAggr &&) = default; ~DefaultedAggr() = default; }; DefaultedAggr da = { 42 } ; diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp index a879829066..9b5ef78897 100644 --- a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp @@ -14,11 +14,11 @@ namespace move { }; struct AssignmentRet1 { - AssignmentRet1&& operator=(AssignmentRet1&&) = default; // expected-error {{an explicitly-defaulted move assignment operator must return an unqualified lvalue reference to its class type}} + AssignmentRet1&& operator=(AssignmentRet1&&) = default; // expected-error {{explicitly-defaulted move assignment operator must return 'move::AssignmentRet1 &'}} }; struct AssignmentRet2 { - const AssignmentRet2& operator=(AssignmentRet2&&) = default; // expected-error {{an explicitly-defaulted move assignment operator must return an unqualified lvalue reference to its class type}} + const AssignmentRet2& operator=(AssignmentRet2&&) = default; // expected-error {{explicitly-defaulted move assignment operator must return 'move::AssignmentRet2 &'}} }; struct ConstAssignment { @@ -38,22 +38,35 @@ namespace copy { }; struct NonConst { - NonConst(NonConst&) = default; - NonConst& operator=(NonConst&) = default; + NonConst(NonConst&) = default; // expected-error {{must be defaulted outside the class}} + NonConst& operator=(NonConst&) = default; // expected-error {{must be defaulted outside the class}} + }; + + struct NonConst2 { + NonConst2(NonConst2&); + NonConst2& operator=(NonConst2&); + }; + NonConst2::NonConst2(NonConst2&) = default; + NonConst2 &NonConst2::operator=(NonConst2&) = default; + + struct NonConst3 { + NonConst3(NonConst3&) = default; + NonConst3& operator=(NonConst3&) = default; + NonConst nc; }; struct BadConst { - NonConst nc; // makes implicit copy non-const BadConst(const BadConst&) = default; // expected-error {{is const, but}} BadConst& operator=(const BadConst&) = default; // expected-error {{is const, but}} + NonConst nc; // makes implicit copy non-const }; struct AssignmentRet1 { - AssignmentRet1&& operator=(const AssignmentRet1&) = default; // expected-error {{an explicitly-defaulted copy assignment operator must return an unqualified lvalue reference to its class type}} + AssignmentRet1&& operator=(const AssignmentRet1&) = default; // expected-error {{explicitly-defaulted copy assignment operator must return 'copy::AssignmentRet1 &'}} }; struct AssignmentRet2 { - const AssignmentRet2& operator=(const AssignmentRet2&) = default; // expected-error {{an explicitly-defaulted copy assignment operator must return an unqualified lvalue reference to its class type}} + const AssignmentRet2& operator=(const AssignmentRet2&) = default; // expected-error {{explicitly-defaulted copy assignment operator must return 'copy::AssignmentRet2 &'}} }; struct ConstAssignment { diff --git a/test/SemaCXX/PR10243.cpp b/test/SemaCXX/PR10243.cpp index 129ff80e2d..19a8b04e84 100644 --- a/test/SemaCXX/PR10243.cpp +++ b/test/SemaCXX/PR10243.cpp @@ -9,12 +9,12 @@ struct T0 { struct T1 { S s; // expected-error{{field has incomplete type 'S'}} - T1(T1&) = default; + T1(const T1&) = default; }; struct T2 { S s; // expected-error{{field has incomplete type 'S'}} - T2& operator=(T2&) = default; + T2& operator=(const T2&) = default; }; struct T3 { diff --git a/test/SemaCXX/cxx0x-cursory-default-delete.cpp b/test/SemaCXX/cxx0x-cursory-default-delete.cpp index 3290595616..f00297332a 100644 --- a/test/SemaCXX/cxx0x-cursory-default-delete.cpp +++ b/test/SemaCXX/cxx0x-cursory-default-delete.cpp @@ -7,11 +7,14 @@ struct non_copiable { }; struct non_const_copy { - non_const_copy(non_const_copy&) = default; // expected-note {{not viable}} - non_const_copy& operator = (non_const_copy&) & = default; // expected-note {{not viable}} - non_const_copy& operator = (non_const_copy&) && = default; // expected-note {{not viable}} + non_const_copy(non_const_copy&); + non_const_copy& operator = (non_const_copy&) &; + non_const_copy& operator = (non_const_copy&) &&; non_const_copy() = default; // expected-note {{not viable}} }; +non_const_copy::non_const_copy(non_const_copy&) = default; // expected-note {{not viable}} +non_const_copy& non_const_copy::operator = (non_const_copy&) & = default; // expected-note {{not viable}} +non_const_copy& non_const_copy::operator = (non_const_copy&) && = default; // expected-note {{not viable}} void fn1 () { non_copiable nc; @@ -32,9 +35,9 @@ struct non_const_derived : non_const_copy { }; struct bad_decls { - bad_decls(volatile bad_decls&) = default; // expected-error {{may not be volatile}} - bad_decls&& operator = (bad_decls) = default; // expected-error 2{{lvalue reference}} - bad_decls& operator = (volatile bad_decls&) = default; // expected-error {{may not be volatile}} + bad_decls(volatile bad_decls&) = default; // expected-error {{may not be volatile}} expected-error {{must be defaulted outside the class}} + bad_decls&& operator = (bad_decls) = default; // expected-error {{lvalue reference}} expected-error {{must return 'bad_decls &'}} + bad_decls& operator = (volatile bad_decls&) = default; // expected-error {{may not be volatile}} expected-error {{must be defaulted outside the class}} bad_decls& operator = (const bad_decls&) const = default; // expected-error {{may not have 'const', 'constexpr' or 'volatile' qualifiers}} }; @@ -72,4 +75,3 @@ struct except_spec_d_match : except_spec_a, except_spec_b { // (but not normal definitions) struct S { S(); }; S::S() __attribute((pure)) = default; - diff --git a/test/SemaCXX/cxx0x-defaulted-functions.cpp b/test/SemaCXX/cxx0x-defaulted-functions.cpp index 2e4107c13e..2ab0f73eae 100644 --- a/test/SemaCXX/cxx0x-defaulted-functions.cpp +++ b/test/SemaCXX/cxx0x-defaulted-functions.cpp @@ -6,26 +6,26 @@ struct foo { foo() = default; foo(const foo&) = default; - foo(foo&) = default; + foo(foo&&) = default; foo& operator = (const foo&) = default; - foo& operator = (foo&) = default; + foo& operator = (foo&&) = default; ~foo() = default; }; struct bar { bar(); bar(const bar&); - bar(bar&); + bar(bar&&); bar& operator = (const bar&); - bar& operator = (bar&); + bar& operator = (bar&&); ~bar(); }; bar::bar() = default; bar::bar(const bar&) = default; -bar::bar(bar&) = default; +bar::bar(bar&&) = default; bar& bar::operator = (const bar&) = default; -bar& bar::operator = (bar&) = default; +bar& bar::operator = (bar&&) = default; bar::~bar() = default; static_assert(__is_trivial(foo), "foo should be trivial"); |