diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6485,12 +6485,6 @@ InGroup, DefaultIgnore; def note_remove_move : Note<"remove std::move call here">; -def warn_return_std_move : Warning< - "local variable %0 will be copied despite being %select{returned|thrown}1 by name">, - InGroup, DefaultIgnore; -def note_add_std_move : Note< - "call 'std::move' explicitly to avoid copying">; - def warn_string_plus_int : Warning< "adding %0 to a string does not append to the string">, InGroup; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4782,8 +4782,7 @@ bool isCopyElidable() const { return S == MoveEligibleAndCopyElidable; } }; NamedReturnInfo getNamedReturnInfo(Expr *&E, bool ForceCXX2b = false); - NamedReturnInfo getNamedReturnInfo(const VarDecl *VD, - bool ForceCXX20 = false); + NamedReturnInfo getNamedReturnInfo(const VarDecl *VD); const VarDecl *getCopyElisionCandidate(NamedReturnInfo &Info, QualType ReturnType); diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3332,7 +3332,7 @@ const auto *VD = dyn_cast(DR->getDecl()); if (!VD) return NamedReturnInfo(); - NamedReturnInfo Res = getNamedReturnInfo(VD, /*ForceCXX20=*/ForceCXX2b); + NamedReturnInfo Res = getNamedReturnInfo(VD); if (Res.Candidate && !E->isXValue() && (ForceCXX2b || getLangOpts().CPlusPlus2b)) { E = ImplicitCastExpr::Create(Context, VD->getType().getNonReferenceType(), @@ -3342,46 +3342,28 @@ return Res; } -/// Updates the status in the given NamedReturnInfo object to disallow -/// copy elision, and optionally also implicit move. -/// -/// \param Info The NamedReturnInfo object to update. -/// -/// \param CanMove If true, disallow only copy elision. -/// If false, also disallow implcit move. -static void disallowNRVO(Sema::NamedReturnInfo &Info, bool CanMove) { - Info.S = std::min(Info.S, CanMove ? Sema::NamedReturnInfo::MoveEligible - : Sema::NamedReturnInfo::None); -} - /// Determine whether the given NRVO candidate variable is move-eligible or /// copy-elidable, without considering function return type. /// /// \param VD The NRVO candidate variable. /// -/// \param ForceCXX20 Overrides detection of current language mode -/// and uses the rules for C++20. -/// /// \returns An aggregate which contains the Candidate and isMoveEligible /// and isCopyElidable methods. If Candidate is non-null, it means /// isMoveEligible() would be true under the most permissive language standard. -Sema::NamedReturnInfo Sema::getNamedReturnInfo(const VarDecl *VD, - bool ForceCXX20) { - bool hasCXX11 = getLangOpts().CPlusPlus11 || ForceCXX20; - bool hasCXX20 = getLangOpts().CPlusPlus20 || ForceCXX20; +Sema::NamedReturnInfo Sema::getNamedReturnInfo(const VarDecl *VD) { NamedReturnInfo Info{VD, NamedReturnInfo::MoveEligibleAndCopyElidable}; // C++20 [class.copy.elision]p3: // - in a return statement in a function with ... // (other than a function ... parameter) if (VD->getKind() == Decl::ParmVar) - disallowNRVO(Info, hasCXX11); + Info.S = NamedReturnInfo::MoveEligible; else if (VD->getKind() != Decl::Var) return NamedReturnInfo(); // (other than ... a catch-clause parameter) if (VD->isExceptionVariable()) - disallowNRVO(Info, hasCXX20); + Info.S = NamedReturnInfo::MoveEligible; // ...automatic... if (!VD->hasLocalStorage()) @@ -3406,7 +3388,7 @@ if (VDReferencedType.isVolatileQualified() || !VDReferencedType->isObjectType()) return NamedReturnInfo(); - disallowNRVO(Info, hasCXX20); + Info.S = NamedReturnInfo::MoveEligible; } else { return NamedReturnInfo(); } @@ -3415,7 +3397,7 @@ // alignment cannot use NRVO. if (!VDType->isDependentType() && VD->hasAttr() && Context.getDeclAlign(VD) > Context.getTypeAlignInChars(VDType)) - disallowNRVO(Info, hasCXX11); + Info.S = NamedReturnInfo::MoveEligible; return Info; } @@ -3459,110 +3441,11 @@ // When considering moving this expression out, allow dissimilar types. if (!VDType->isDependentType() && !Context.hasSameUnqualifiedType(ReturnType, VDType)) - disallowNRVO(Info, getLangOpts().CPlusPlus11); + Info.S = NamedReturnInfo::MoveEligible; } return Info.isCopyElidable() ? Info.Candidate : nullptr; } -/// Try to perform the initialization of a potentially-movable value, -/// which is the operand to a return or throw statement. -/// -/// This routine implements C++20 [class.copy.elision]p3, which attempts to -/// treat returned lvalues as rvalues in certain cases (to prefer move -/// construction), then falls back to treating them as lvalues if that failed. -/// -/// \param ConvertingConstructorsOnly If true, follow [class.copy.elision]p3 and -/// reject resolutions that find non-constructors, such as derived-to-base -/// conversions or `operator T()&&` member functions. If false, do consider such -/// conversion sequences. -/// -/// \param Res We will fill this in if move-initialization was possible. -/// If move-initialization is not possible, such that we must fall back to -/// treating the operand as an lvalue, we will leave Res in its original -/// invalid state. -/// -/// \returns Whether we need to do the second overload resolution. If the first -/// overload resolution fails, or if the first overload resolution succeeds but -/// the selected constructor/operator doesn't match the additional criteria, we -/// need to do the second overload resolution. -static bool TryMoveInitialization(Sema &S, const InitializedEntity &Entity, - const VarDecl *NRVOCandidate, Expr *&Value, - bool ConvertingConstructorsOnly, - bool IsDiagnosticsCheck, ExprResult &Res) { - ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(), - CK_NoOp, Value, VK_XValue, FPOptionsOverride()); - - Expr *InitExpr = &AsRvalue; - - InitializationKind Kind = InitializationKind::CreateCopy( - Value->getBeginLoc(), Value->getBeginLoc()); - - InitializationSequence Seq(S, Entity, Kind, InitExpr); - - bool NeedSecondOverloadResolution = true; - if (!Seq && - (IsDiagnosticsCheck || Seq.getFailedOverloadResult() != OR_Deleted)) { - return NeedSecondOverloadResolution; - } - - for (const InitializationSequence::Step &Step : Seq.steps()) { - if (Step.Kind != InitializationSequence::SK_ConstructorInitialization && - Step.Kind != InitializationSequence::SK_UserConversion) - continue; - - FunctionDecl *FD = Step.Function.Function; - if (ConvertingConstructorsOnly) { - if (isa(FD)) { - // C++11 [class.copy]p32: - // C++14 [class.copy]p32: - // C++17 [class.copy.elision]p3: - // [...] if the type of the first parameter of the selected constructor - // is not an rvalue reference to the object's type (possibly - // cv-qualified), overload resolution is performed again, considering - // the object as an lvalue. - const RValueReferenceType *RRefType = - FD->getParamDecl(0)->getType()->getAs(); - if (!RRefType) - break; - if (!S.Context.hasSameUnqualifiedType(RRefType->getPointeeType(), - NRVOCandidate->getType())) - break; - } else { - continue; - } - } else { - if (isa(FD)) { - // Check that overload resolution selected a constructor taking an - // rvalue reference. If it selected an lvalue reference, then we - // didn't need to cast this thing to an rvalue in the first place. - if (IsDiagnosticsCheck && - !isa(FD->getParamDecl(0)->getType())) - break; - } else if (isa(FD)) { - // Check that overload resolution selected a conversion operator - // taking an rvalue reference. - if (cast(FD)->getRefQualifier() != RQ_RValue) - break; - } else { - continue; - } - } - - NeedSecondOverloadResolution = false; - // Promote "AsRvalue" to the heap, since we now need this - // expression node to persist. - Value = - ImplicitCastExpr::Create(S.Context, Value->getType(), CK_NoOp, Value, - nullptr, VK_XValue, FPOptionsOverride()); - - // Complete type-checking the initialization of the return type - // using the constructor we found. - Res = Seq.Perform(S, Entity, Kind, Value); - } - - return NeedSecondOverloadResolution; -} - /// Perform the initialization of a potentially-movable value, which /// is the result of return value. /// @@ -3573,42 +3456,26 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, const NamedReturnInfo &NRInfo, Expr *Value) { - - if (NRInfo.Candidate && !getLangOpts().CPlusPlus2b) { - if (NRInfo.isMoveEligible()) { - ExprResult Res; - if (!TryMoveInitialization(*this, Entity, NRInfo.Candidate, Value, - !getLangOpts().CPlusPlus20, false, Res)) - return Res; - } - if (!getDiagnostics().isIgnored(diag::warn_return_std_move, - Value->getExprLoc())) { - QualType QT = NRInfo.Candidate->getType(); - if (QT.getNonReferenceType().getUnqualifiedType().isTriviallyCopyableType( - Context)) { - // Adding 'std::move' around a trivially copyable variable is probably - // pointless. Don't suggest it. - } else { - ExprResult FakeRes = ExprError(); - Expr *FakeValue = Value; - TryMoveInitialization(*this, Entity, NRInfo.Candidate, FakeValue, false, - true, FakeRes); - if (!FakeRes.isInvalid()) { - bool IsThrow = (Entity.getKind() == InitializedEntity::EK_Exception); - SmallString<32> Str; - Str += "std::move("; - Str += NRInfo.Candidate->getDeclName().getAsString(); - Str += ")"; - Diag(Value->getExprLoc(), diag::warn_return_std_move) - << Value->getSourceRange() << NRInfo.Candidate->getDeclName() - << IsThrow; - Diag(Value->getExprLoc(), diag::note_add_std_move) - << FixItHint::CreateReplacement(Value->getSourceRange(), Str); - } - } + if (getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus2b && + NRInfo.isMoveEligible()) { + ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(), + CK_NoOp, Value, VK_XValue, FPOptionsOverride()); + Expr *InitExpr = &AsRvalue; + auto Kind = InitializationKind::CreateCopy(Value->getBeginLoc(), + Value->getBeginLoc()); + InitializationSequence Seq(*this, Entity, Kind, InitExpr); + auto Res = Seq.getFailedOverloadResult(); + if (Res == OR_Success || Res == OR_Deleted) { + // Promote "AsRvalue" to the heap, since we now need this + // expression node to persist. + Value = + ImplicitCastExpr::Create(Context, Value->getType(), CK_NoOp, Value, + nullptr, VK_XValue, FPOptionsOverride()); + // Complete type-checking the initialization of the return type + // using the constructor we found. + return Seq.Perform(*this, Entity, Kind, Value); } } - // Either we didn't meet the criteria for treating an lvalue as an rvalue, // above, or overload resolution failed. Either way, we need to try // (again) now with the return value expression as written. diff --git a/clang/test/CXX/class/class.init/class.copy.elision/p3.cpp b/clang/test/CXX/class/class.init/class.copy.elision/p3.cpp --- a/clang/test/CXX/class/class.init/class.copy.elision/p3.cpp +++ b/clang/test/CXX/class/class.init/class.copy.elision/p3.cpp @@ -1,18 +1,17 @@ -// RUN: %clang_cc1 -std=c++2b -fsyntax-only -fcxx-exceptions -verify=expected,cxx20_2b,cxx2b %s -// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected,cxx11_20,cxx20_2b %s -// RUN: %clang_cc1 -std=c++17 -fsyntax-only -fcxx-exceptions -verify=expected,cxx11_17,cxx11_20 %s -// RUN: %clang_cc1 -std=c++14 -fsyntax-only -fcxx-exceptions -verify=expected,cxx11_17,cxx11_20 %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fcxx-exceptions -verify=expected,cxx11_17,cxx11_20 %s +// RUN: %clang_cc1 -std=c++2b -fsyntax-only -fcxx-exceptions -verify=expected,cxx11_2b,cxx2b %s +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected,cxx98_20,cxx11_2b,cxx11_20 %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fcxx-exceptions -verify=expected,cxx98_20,cxx11_2b,cxx11_20 %s +// RUN: %clang_cc1 -std=c++98 -fsyntax-only -fcxx-exceptions -Wno-c++11-extensions -verify=expected,cxx98_20,cxx98 %s namespace test_delete_function { struct A1 { A1(); A1(const A1 &); - A1(A1 &&) = delete; // expected-note {{'A1' has been explicitly marked deleted here}} + A1(A1 &&) = delete; // cxx11_2b-note {{'A1' has been explicitly marked deleted here}} }; A1 test1() { A1 a; - return a; // expected-error {{call to deleted constructor of 'test_delete_function::A1'}} + return a; // cxx11_2b-error {{call to deleted constructor of 'test_delete_function::A1'}} } struct A2 { @@ -20,91 +19,90 @@ A2(const A2 &); private: - A2(A2 &&); // expected-note {{declared private here}} + A2(A2 &&); // cxx11_2b-note {{declared private here}} }; A2 test2() { A2 a; - return a; // expected-error {{calling a private constructor of class 'test_delete_function::A2'}} + return a; // cxx11_2b-error {{calling a private constructor of class 'test_delete_function::A2'}} } struct C {}; struct B1 { B1(C &); - B1(C &&) = delete; // expected-note {{'B1' has been explicitly marked deleted here}} + B1(C &&) = delete; // cxx11_2b-note {{'B1' has been explicitly marked deleted here}} }; B1 test3() { C c; - return c; // expected-error {{conversion function from 'test_delete_function::C' to 'test_delete_function::B1' invokes a deleted function}} + return c; // cxx11_2b-error {{conversion function from 'test_delete_function::C' to 'test_delete_function::B1' invokes a deleted function}} } struct B2 { B2(C &); private: - B2(C &&); // expected-note {{declared private here}} + B2(C &&); // cxx11_2b-note {{declared private here}} }; B2 test4() { C c; - return c; // expected-error {{calling a private constructor of class 'test_delete_function::B2'}} + return c; // cxx11_2b-error {{calling a private constructor of class 'test_delete_function::B2'}} } } // namespace test_delete_function -// In C++20, implicitly movable entity can be rvalue reference to non-volatile +// Implicitly movable entity can be rvalue reference to non-volatile // automatic object. namespace test_implicitly_movable_rvalue_ref { struct A1 { A1(A1 &&); - A1(const A1 &) = delete; // cxx11_17-note {{'A1' has been explicitly marked deleted here}} + A1(const A1 &) = delete; // cxx98-note {{marked deleted here}} }; A1 test1(A1 &&a) { - return a; // cxx11_17-error {{call to deleted constructor of 'test_implicitly_movable_rvalue_ref::A1'}} + return a; // cxx98-error {{call to deleted constructor}} } struct A2 { A2(A2 &&); private: - A2(const A2 &); // cxx11_17-note {{declared private here}} + A2(const A2 &); // cxx98-note {{declared private here}} }; A2 test2(A2 &&a) { - return a; // cxx11_17-error {{calling a private constructor of class 'test_implicitly_movable_rvalue_ref::A2'}} + return a; // cxx98-error {{calling a private constructor}} } struct B1 { B1(const B1 &); - B1(B1 &&) = delete; // cxx20_2b-note {{'B1' has been explicitly marked deleted here}} + B1(B1 &&) = delete; // cxx11_2b-note {{'B1' has been explicitly marked deleted here}} }; B1 test3(B1 &&b) { - return b; // cxx20_2b-error {{call to deleted constructor of 'test_implicitly_movable_rvalue_ref::B1'}} + return b; // cxx11_2b-error {{call to deleted constructor of 'test_implicitly_movable_rvalue_ref::B1'}} } struct B2 { B2(const B2 &); private: - B2(B2 &&); // cxx20_2b-note {{declared private here}} + B2(B2 &&); // cxx11_2b-note {{declared private here}} }; B2 test4(B2 &&b) { - return b; // cxx20_2b-error {{calling a private constructor of class 'test_implicitly_movable_rvalue_ref::B2'}} + return b; // cxx11_2b-error {{calling a private constructor of class 'test_implicitly_movable_rvalue_ref::B2'}} } } // namespace test_implicitly_movable_rvalue_ref -// In C++20, operand of throw-expression can be function parameter or +// Operand of throw-expression can be function parameter or // catch-clause parameter. namespace test_throw_parameter { void func(); struct A1 { A1(const A1 &); - A1(A1 &&) = delete; // cxx20_2b-note {{'A1' has been explicitly marked deleted here}} - // expected-note@-1 {{'A1' has been explicitly marked deleted here}} + A1(A1 &&) = delete; // cxx11_2b-note 2{{'A1' has been explicitly marked deleted here}} }; void test1() { try { func(); } catch (A1 a) { - throw a; // cxx20_2b-error {{call to deleted constructor of 'test_throw_parameter::A1'}} + throw a; // cxx11_2b-error {{call to deleted constructor of 'test_throw_parameter::A1'}} } } @@ -112,70 +110,70 @@ A2(const A2 &); private: - A2(A2 &&); // cxx20_2b-note {{declared private here}} + A2(A2 &&); // cxx11_2b-note {{declared private here}} }; void test2() { try { func(); } catch (A2 a) { - throw a; // cxx20_2b-error {{calling a private constructor of class 'test_throw_parameter::A2'}} + throw a; // cxx11_2b-error {{calling a private constructor of class 'test_throw_parameter::A2'}} } } void test3(A1 a) try { func(); } catch (...) { - throw a; // expected-error {{call to deleted constructor of 'test_throw_parameter::A1'}} + throw a; // cxx11_2b-error {{call to deleted constructor of 'test_throw_parameter::A1'}} } } // namespace test_throw_parameter -// In C++20, during the first overload resolution, the selected function no +// During the first overload resolution, the selected function no // need to be a constructor. namespace test_non_ctor_conversion { class C {}; struct A1 { operator C() &&; - operator C() const & = delete; // cxx11_17-note {{'operator C' has been explicitly marked deleted here}} + operator C() const & = delete; // cxx98-note {{marked deleted here}} }; C test1() { A1 a; - return a; // cxx11_17-error {{conversion function from 'test_non_ctor_conversion::A1' to 'test_non_ctor_conversion::C' invokes a deleted function}} + return a; // cxx98-error {{invokes a deleted function}} } struct A2 { operator C() &&; private: - operator C() const &; // cxx11_17-note {{declared private here}} + operator C() const &; // cxx98-note {{declared private here}} }; C test2() { A2 a; - return a; // cxx11_17-error {{'operator C' is a private member of 'test_non_ctor_conversion::A2'}} + return a; // cxx98-error {{'operator C' is a private member}} } struct B1 { operator C() const &; - operator C() && = delete; // cxx20_2b-note {{'operator C' has been explicitly marked deleted here}} + operator C() && = delete; // cxx11_2b-note {{'operator C' has been explicitly marked deleted here}} }; C test3() { B1 b; - return b; // cxx20_2b-error {{conversion function from 'test_non_ctor_conversion::B1' to 'test_non_ctor_conversion::C' invokes a deleted function}} + return b; // cxx11_2b-error {{conversion function from 'test_non_ctor_conversion::B1' to 'test_non_ctor_conversion::C' invokes a deleted function}} } struct B2 { operator C() const &; private: - operator C() &&; // cxx20_2b-note {{declared private here}} + operator C() &&; // cxx11_2b-note {{declared private here}} }; C test4() { B2 b; - return b; // cxx20_2b-error {{'operator C' is a private member of 'test_non_ctor_conversion::B2'}} + return b; // cxx11_2b-error {{'operator C' is a private member of 'test_non_ctor_conversion::B2'}} } } // namespace test_non_ctor_conversion -// In C++20, during the first overload resolution, the first parameter of the +// During the first overload resolution, the first parameter of the // selected function no need to be an rvalue reference to the object's type. namespace test_ctor_param_rvalue_ref { struct A1; @@ -190,35 +188,35 @@ NeedRvalueRef(B2 &&); }; struct NeedValue { - NeedValue(A1); // cxx11_17-note 2 {{passing argument to parameter here}} + NeedValue(A1); // cxx98-note 2 {{passing argument to parameter here}} NeedValue(A2); - NeedValue(B1); // cxx20_2b-note 2 {{passing argument to parameter here}} + NeedValue(B1); // cxx11_2b-note 2 {{passing argument to parameter here}} NeedValue(B2); }; struct A1 { A1(); A1(A1 &&); - A1(const A1 &) = delete; // cxx11_17-note 3 {{'A1' has been explicitly marked deleted here}} + A1(const A1 &) = delete; // cxx98-note 3{{marked deleted here}} }; NeedValue test_1_1() { // not rvalue reference // same type A1 a; - return a; // cxx11_17-error {{call to deleted constructor of 'test_ctor_param_rvalue_ref::A1'}} + return a; // cxx98-error {{call to deleted constructor}} } class DerivedA1 : public A1 {}; A1 test_1_2() { // rvalue reference // not same type DerivedA1 a; - return a; // cxx11_17-error {{call to deleted constructor of 'test_ctor_param_rvalue_ref::A1'}} + return a; // cxx98-error {{call to deleted constructor}} } NeedValue test_1_3() { // not rvalue reference // not same type DerivedA1 a; - return a; // cxx11_17-error {{call to deleted constructor of 'test_ctor_param_rvalue_ref::A1'}} + return a; // cxx98-error {{call to deleted constructor}} } struct A2 { @@ -226,51 +224,51 @@ A2(A2 &&); private: - A2(const A2 &); // cxx11_17-note 3 {{declared private here}} + A2(const A2 &); // cxx98-note 3{{declared private here}} }; NeedValue test_2_1() { // not rvalue reference // same type A2 a; - return a; // cxx11_17-error {{calling a private constructor of class 'test_ctor_param_rvalue_ref::A2'}} + return a; // cxx98-error {{calling a private constructor}} } class DerivedA2 : public A2 {}; A2 test_2_2() { // rvalue reference // not same type DerivedA2 a; - return a; // cxx11_17-error {{calling a private constructor of class 'test_ctor_param_rvalue_ref::A2'}} + return a; // cxx98-error {{calling a private constructor}} } NeedValue test_2_3() { // not rvalue reference // not same type DerivedA2 a; - return a; // cxx11_17-error {{calling a private constructor of class 'test_ctor_param_rvalue_ref::A2'}} + return a; // cxx98-error {{calling a private constructor}} } struct B1 { B1(); B1(const B1 &); - B1(B1 &&) = delete; // cxx20_2b-note 3 {{'B1' has been explicitly marked deleted here}} + B1(B1 &&) = delete; // cxx11_2b-note 3 {{'B1' has been explicitly marked deleted here}} }; NeedValue test_3_1() { // not rvalue reference // same type B1 b; - return b; // cxx20_2b-error {{call to deleted constructor of 'test_ctor_param_rvalue_ref::B1'}} + return b; // cxx11_2b-error {{call to deleted constructor of 'test_ctor_param_rvalue_ref::B1'}} } class DerivedB1 : public B1 {}; B1 test_3_2() { // rvalue reference // not same type DerivedB1 b; - return b; // cxx20_2b-error {{call to deleted constructor of 'test_ctor_param_rvalue_ref::B1'}} + return b; // cxx11_2b-error {{call to deleted constructor of 'test_ctor_param_rvalue_ref::B1'}} } NeedValue test_3_3() { // not rvalue reference // not same type DerivedB1 b; - return b; // cxx20_2b-error {{call to deleted constructor of 'test_ctor_param_rvalue_ref::B1'}} + return b; // cxx11_2b-error {{call to deleted constructor of 'test_ctor_param_rvalue_ref::B1'}} } struct B2 { @@ -278,49 +276,46 @@ B2(const B2 &); private: - B2(B2 &&); // cxx20_2b-note 3 {{declared private here}} + B2(B2 &&); // cxx11_2b-note 3 {{declared private here}} }; NeedValue test_4_1() { // not rvalue reference // same type B2 b; - return b; // cxx20_2b-error {{calling a private constructor of class 'test_ctor_param_rvalue_ref::B2'}} + return b; // cxx11_2b-error {{calling a private constructor of class 'test_ctor_param_rvalue_ref::B2'}} } class DerivedB2 : public B2 {}; B2 test_4_2() { // rvalue reference // not same type DerivedB2 b; - return b; // cxx20_2b-error {{calling a private constructor of class 'test_ctor_param_rvalue_ref::B2'}} + return b; // cxx11_2b-error {{calling a private constructor of class 'test_ctor_param_rvalue_ref::B2'}} } NeedValue test_4_3() { // not rvalue reference // not same type DerivedB2 b; - return b; // cxx20_2b-error {{calling a private constructor of class 'test_ctor_param_rvalue_ref::B2'}} + return b; // cxx11_2b-error {{calling a private constructor of class 'test_ctor_param_rvalue_ref::B2'}} } } // namespace test_ctor_param_rvalue_ref namespace test_lvalue_ref_is_not_moved_from { struct Target {}; - // expected-note@-1 {{candidate constructor (the implicit copy constructor) not viable}} - // expected-note@-2 {{candidate constructor (the implicit move constructor) not viable}} - // cxx11_17-note@-3 {{candidate constructor (the implicit copy constructor) not viable}} - // cxx11_17-note@-4 {{candidate constructor (the implicit move constructor) not viable}} +// cxx11_2b-note@-1 {{candidate constructor (the implicit copy constructor) not viable}} +// cxx98-note@-2 2{{candidate constructor (the implicit copy constructor) not viable}} +// cxx11_2b-note@-3 {{candidate constructor (the implicit move constructor) not viable}} struct CopyOnly { - CopyOnly(CopyOnly&&) = delete; // cxx20_2b-note {{has been explicitly marked deleted here}} + CopyOnly(CopyOnly &&) = delete; // cxx11_2b-note {{has been explicitly marked deleted here}} CopyOnly(CopyOnly&); - operator Target() && = delete; // cxx20_2b-note {{has been explicitly marked deleted here}} + operator Target() && = delete; // cxx11_2b-note {{has been explicitly marked deleted here}} operator Target() &; }; struct MoveOnly { - MoveOnly(MoveOnly&&); // expected-note {{copy constructor is implicitly deleted because}} - // cxx11_17-note@-1 {{copy constructor is implicitly deleted because}} - operator Target() &&; // expected-note {{candidate function not viable}} - // cxx11_17-note@-1 {{candidate function not viable}} + MoveOnly(MoveOnly &&); // cxx11_2b-note {{copy constructor is implicitly deleted because}} + operator Target() &&; // expected-note {{candidate function not viable}} cxx98-note {{candidate function not viable}} }; extern CopyOnly copyonly; @@ -333,17 +328,17 @@ CopyOnly t2() { CopyOnly&& r = static_cast(copyonly); - return r; // cxx20_2b-error {{call to deleted constructor}} + return r; // cxx11_2b-error {{call to deleted constructor}} } MoveOnly t3() { MoveOnly& r = moveonly; - return r; // expected-error {{call to implicitly-deleted copy constructor}} + return r; // cxx11_2b-error {{call to implicitly-deleted copy constructor}} } MoveOnly t4() { MoveOnly&& r = static_cast(moveonly); - return r; // cxx11_17-error {{call to implicitly-deleted copy constructor}} + return r; } Target t5() { @@ -353,7 +348,7 @@ Target t6() { CopyOnly&& r = static_cast(copyonly); - return r; // cxx20_2b-error {{invokes a deleted function}} + return r; // cxx11_2b-error {{invokes a deleted function}} } Target t7() { @@ -363,7 +358,7 @@ Target t8() { MoveOnly&& r = static_cast(moveonly); - return r; // cxx11_17-error {{no viable conversion}} + return r; // cxx98-error {{no viable conversion}} } } // namespace test_lvalue_ref_is_not_moved_from @@ -376,8 +371,7 @@ struct Target { Target(CopyOnly (&)()); Target(CopyOnly (&&)()) = delete; - Target(MoveOnly (&)()) = delete; // expected-note {{has been explicitly marked deleted here}} - // expected-note@-1 {{has been explicitly marked deleted here}} + Target(MoveOnly (&)()) = delete; // expected-note 2{{has been explicitly marked deleted here}} Target(MoveOnly (&&)()); }; @@ -406,6 +400,49 @@ } // namespace test_rvalue_ref_to_nonobject +namespace test_constandnonconstcopy { +struct ConstCopyOnly { + ConstCopyOnly(); + ConstCopyOnly(ConstCopyOnly &) = delete; // cxx98-note {{marked deleted here}} + ConstCopyOnly(const ConstCopyOnly &); +}; +ConstCopyOnly t1() { + ConstCopyOnly x; + return x; // cxx98-error {{call to deleted constructor}} +} + +struct NonConstCopyOnly { + NonConstCopyOnly(); + NonConstCopyOnly(NonConstCopyOnly &); + NonConstCopyOnly(const NonConstCopyOnly &) = delete; // cxx11_2b-note {{marked deleted here}} +}; +NonConstCopyOnly t2() { + NonConstCopyOnly x; + return x; // cxx11_2b-error {{call to deleted constructor}} +} + +} // namespace test_constandnonconstcopy + +namespace test_conversion { + +struct B; +struct A { + A(B &) = delete; // cxx98-note {{has been explicitly deleted}} +}; +struct B { + operator A(); // cxx98-note {{candidate function}} +}; +A test1(B x) { return x; } // cxx98-error-re {{conversion {{.*}} is ambiguous}} + +struct C {}; +struct D { + operator C() &; + operator C() const & = delete; // cxx11_2b-note {{marked deleted here}} +}; +C test2(D x) { return x; } // cxx11_2b-error {{invokes a deleted function}} + +} // namespace test_conversion + namespace test_simpler_implicit_move { struct CopyOnly { @@ -421,7 +458,7 @@ MoveOnly &&rref(); MoveOnly &&test1(MoveOnly &&w) { - return w; // cxx11_20-error {{cannot bind to lvalue of type}} + return w; // cxx98_20-error {{cannot bind to lvalue of type}} } CopyOnly test2(bool b) { @@ -434,13 +471,13 @@ } } -template T &&test3(T &&x) { return x; } // cxx11_20-error {{cannot bind to lvalue of type}} +template T &&test3(T &&x) { return x; } // cxx98_20-error {{cannot bind to lvalue of type}} template MoveOnly& test3(MoveOnly&); -template MoveOnly &&test3(MoveOnly &&); // cxx11_20-note {{in instantiation of function template specialization}} +template MoveOnly &&test3(MoveOnly &&); // cxx98_20-note {{in instantiation of function template specialization}} MoveOnly &&test4() { MoveOnly &&x = rref(); - return x; // cxx11_20-error {{cannot bind to lvalue of type}} + return x; // cxx98_20-error {{cannot bind to lvalue of type}} } void test5() try { diff --git a/clang/test/SemaCXX/P1155.cpp b/clang/test/SemaCXX/P1155.cpp --- a/clang/test/SemaCXX/P1155.cpp +++ b/clang/test/SemaCXX/P1155.cpp @@ -1,9 +1,7 @@ -// RUN: %clang_cc1 -std=c++2b -fsyntax-only -fcxx-exceptions -verify=cxx20_2b %s -// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=cxx20_2b %s -// RUN: %clang_cc1 -std=c++17 -fsyntax-only -fcxx-exceptions -verify=cxx11_17 %s -// RUN: %clang_cc1 -std=c++14 -fsyntax-only -fcxx-exceptions -verify=cxx11_17 %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fcxx-exceptions -verify=cxx11_17 %s -// cxx20_2b-no-diagnostics +// RUN: %clang_cc1 -std=c++2b -fsyntax-only -fcxx-exceptions -verify %s +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fcxx-exceptions -verify %s +// expected-no-diagnostics // Throwing namespace test_throwing { @@ -14,7 +12,7 @@ }; void seven(Widget w) { - throw w; // Clang already do this implicit move before -std=c++20 + throw w; } } // namespace test_throwing @@ -23,13 +21,13 @@ class Widget {}; struct To { - operator Widget() const & = delete; // cxx11_17-note {{'operator Widget' has been explicitly marked deleted here}} + operator Widget() const & = delete; operator Widget() &&; }; Widget nine() { To t; - return t; // cxx11_17-error {{conversion function from 'test_non_constructor_conversion::To' to 'test_non_constructor_conversion::Widget' invokes a deleted function}} + return t; } } // namespace test_non_constructor_conversion @@ -39,16 +37,16 @@ public: Widget(); Widget(Widget &&); - Widget(const Widget &) = delete; // cxx11_17-note {{'Widget' has been explicitly marked deleted here}} + Widget(const Widget &) = delete; }; struct Fowl { - Fowl(Widget); // cxx11_17-note {{passing argument to parameter here}} + Fowl(Widget); }; Fowl eleven() { Widget w; - return w; // cxx11_17-error {{call to deleted constructor of 'test_by_value_sinks::Widget'}} + return w; } } // namespace test_by_value_sinks @@ -58,13 +56,13 @@ public: Base(); Base(Base &&); - Base(Base const &) = delete; // cxx11_17-note {{'Base' has been explicitly marked deleted here}} + Base(Base const &) = delete; }; class Derived : public Base {}; Base thirteen() { Derived result; - return result; // cxx11_17-error {{call to deleted constructor of 'test_slicing::Base'}} + return result; } } // namespace test_slicing diff --git a/clang/test/SemaCXX/conversion-function.cpp b/clang/test/SemaCXX/conversion-function.cpp --- a/clang/test/SemaCXX/conversion-function.cpp +++ b/clang/test/SemaCXX/conversion-function.cpp @@ -1,9 +1,7 @@ -// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=expected -triple %itanium_abi_triple -Wbind-to-temporary-copy %s -// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected -triple %itanium_abi_triple -Wbind-to-temporary-copy %s -// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,cxx98_14 -triple %itanium_abi_triple -Wbind-to-temporary-copy %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify=expected,cxx98_14 -triple %itanium_abi_triple -Wbind-to-temporary-copy %s -// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify=expected,cxx98_14 -triple %itanium_abi_triple -Wbind-to-temporary-copy %s -// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98_14 -triple %itanium_abi_triple -Wbind-to-temporary-copy %s +// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=expected -triple %itanium_abi_triple -Wbind-to-temporary-copy %s +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected -triple %itanium_abi_triple -Wbind-to-temporary-copy %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify=expected,cxx98_11,cxx11 -triple %itanium_abi_triple -Wbind-to-temporary-copy %s +// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify=expected,cxx98_11,cxx98 -triple %itanium_abi_triple -Wbind-to-temporary-copy %s class X { public: @@ -126,7 +124,7 @@ class AutoPtrRef { }; class AutoPtr { - AutoPtr(AutoPtr &); // cxx98_14-note{{declared private here}} + AutoPtr(AutoPtr &); // cxx98-note {{declared private here}} public: AutoPtr(); @@ -142,7 +140,7 @@ AutoPtr p; if (Cond) - return p; // cxx98_14-error{{calling a private constructor}} + return p; // cxx98-error {{calling a private constructor}} return AutoPtr(); } @@ -152,17 +150,14 @@ ~A1(); private: - A1(const A1&); // cxx98_14-note 2 {{declared private here}} + A1(const A1 &); // cxx98_11-note 2 {{declared private here}} }; A1 f() { // FIXME: redundant diagnostics! - return "Hello"; // cxx98_14-error {{calling a private constructor}} -#if __cplusplus <= 199711L - // expected-warning@-2 {{an accessible copy constructor}} -#else - // cxx98_14-warning@-4 {{copying parameter of type 'A1' when binding a reference to a temporary would invoke an inaccessible constructor in C++98}} -#endif + return "Hello"; // cxx98_11-error {{calling a private constructor}} + // cxx98-warning@-1 {{an accessible copy constructor}} + // cxx11-warning@-2 {{copying parameter of type 'A1' when binding a reference to a temporary would invoke an inaccessible constructor in C++98}} } namespace source_locations { diff --git a/clang/test/SemaCXX/warn-return-std-move.cpp b/clang/test/SemaCXX/warn-return-std-move.cpp deleted file mode 100644 --- a/clang/test/SemaCXX/warn-return-std-move.cpp +++ /dev/null @@ -1,351 +0,0 @@ -// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=cxx20_2b,cxx2b -fcxx-exceptions -Wreturn-std-move %s -// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=cxx20_2b -fcxx-exceptions -Wreturn-std-move %s -// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify=cxx11_17 -fcxx-exceptions -Wreturn-std-move %s -// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=cxx11_17 -fcxx-exceptions -Wreturn-std-move %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify=cxx11_17 -fcxx-exceptions -Wreturn-std-move %s - -// RUN: %clang_cc1 -std=c++17 -fsyntax-only -fcxx-exceptions -Wreturn-std-move -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s -check-prefix=CHECK -// RUN: %clang_cc1 -std=c++14 -fsyntax-only -fcxx-exceptions -Wreturn-std-move -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s -check-prefix=CHECK -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fcxx-exceptions -Wreturn-std-move -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s -check-prefix=CHECK - -// definitions for std::move -namespace std { -inline namespace foo { -template struct remove_reference { typedef T type; }; -template struct remove_reference { typedef T type; }; -template struct remove_reference { typedef T type; }; - -template typename remove_reference::type &&move(T &&t); -} // namespace foo -} // namespace std - -struct Instrument { - Instrument() {} - Instrument(Instrument&&) { /* MOVE */ } - Instrument(const Instrument&) { /* COPY */ } -}; -struct ConvertFromBase { Instrument i; }; -struct ConvertFromDerived { Instrument i; }; -struct Base { - Instrument i; - operator ConvertFromBase() const& { return ConvertFromBase{i}; } - operator ConvertFromBase() && { return ConvertFromBase{std::move(i)}; } -}; -struct Derived : public Base { - operator ConvertFromDerived() const& { return ConvertFromDerived{i}; } - operator ConvertFromDerived() && { return ConvertFromDerived{std::move(i)}; } -}; -struct ConstructFromBase { - Instrument i; - ConstructFromBase(const Base& b): i(b.i) {} - ConstructFromBase(Base&& b): i(std::move(b.i)) {} -}; -struct ConstructFromDerived { - Instrument i; - ConstructFromDerived(const Derived& d): i(d.i) {} - ConstructFromDerived(Derived&& d): i(std::move(d.i)) {} -}; - -struct TrivialInstrument { - int i = 42; -}; -struct ConvertFromTrivialBase { TrivialInstrument i; }; -struct ConvertFromTrivialDerived { TrivialInstrument i; }; -struct TrivialBase { - TrivialInstrument i; - operator ConvertFromTrivialBase() const& { return ConvertFromTrivialBase{i}; } - operator ConvertFromTrivialBase() && { return ConvertFromTrivialBase{std::move(i)}; } -}; -struct TrivialDerived : public TrivialBase { - operator ConvertFromTrivialDerived() const& { return ConvertFromTrivialDerived{i}; } - operator ConvertFromTrivialDerived() && { return ConvertFromTrivialDerived{std::move(i)}; } -}; -struct ConstructFromTrivialBase { - TrivialInstrument i; - ConstructFromTrivialBase(const TrivialBase& b): i(b.i) {} - ConstructFromTrivialBase(TrivialBase&& b): i(std::move(b.i)) {} -}; -struct ConstructFromTrivialDerived { - TrivialInstrument i; - ConstructFromTrivialDerived(const TrivialDerived& d): i(d.i) {} - ConstructFromTrivialDerived(TrivialDerived&& d): i(std::move(d.i)) {} -}; - -Derived test1() { - Derived d1; - return d1; // ok -} -Base test2() { - Derived d2; - return d2; // e1 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:14}:"std::move(d2)" -} -ConstructFromDerived test3() { - Derived d3; - return d3; // ok -} -ConstructFromBase test4() { - Derived d4; - return d4; // e3 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:14}:"std::move(d4)" -} -ConvertFromDerived test5() { - Derived d5; - return d5; // e4 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:14}:"std::move(d5)" -} -ConvertFromBase test6() { - Derived d6; - return d6; // e5 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:14}:"std::move(d6)" -} - -// These test cases should not produce the warning. -Derived ok1() { Derived d; return d; } -Base ok2() { Derived d; return static_cast(d); } -ConstructFromDerived ok3() { Derived d; return static_cast(d); } -ConstructFromBase ok4() { Derived d; return static_cast(d); } -ConvertFromDerived ok5() { Derived d; return static_cast(d); } -ConvertFromBase ok6() { Derived d; return static_cast(d); } - -// If the target is an lvalue reference, assume it's not safe to move from. -Derived ok_plvalue1(Derived& d) { return d; } -Base ok_plvalue2(Derived& d) { return d; } -ConstructFromDerived ok_plvalue3(const Derived& d) { return d; } -ConstructFromBase ok_plvalue4(Derived& d) { return d; } -ConvertFromDerived ok_plvalue5(Derived& d) { return d; } -ConvertFromBase ok_plvalue6(Derived& d) { return d; } - -Derived ok_lvalue1(Derived *p) { Derived& d = *p; return d; } -Base ok_lvalue2(Derived *p) { Derived& d = *p; return d; } -ConstructFromDerived ok_lvalue3(Derived *p) { const Derived& d = *p; return d; } -ConstructFromBase ok_lvalue4(Derived *p) { Derived& d = *p; return d; } -ConvertFromDerived ok_lvalue5(Derived *p) { Derived& d = *p; return d; } -ConvertFromBase ok_lvalue6(Derived *p) { Derived& d = *p; return d; } - -// If the target is a global, assume it's not safe to move from. -static Derived global_d; -Derived ok_global1() { return global_d; } -Base ok_global2() { return global_d; } -ConstructFromDerived ok_global3() { return global_d; } -ConstructFromBase ok_global4() { return global_d; } -ConvertFromDerived ok_global5() { return global_d; } -ConvertFromBase ok_global6() { return global_d; } - -// If the target's copy constructor is trivial, assume the programmer doesn't care. -TrivialDerived ok_trivial1(TrivialDerived d) { return d; } -TrivialBase ok_trivial2(TrivialDerived d) { return d; } -ConstructFromTrivialDerived ok_trivial3(TrivialDerived d) { return d; } -ConstructFromTrivialBase ok_trivial4(TrivialDerived d) { return d; } -ConvertFromTrivialDerived ok_trivial5(TrivialDerived d) { return d; } -ConvertFromTrivialBase ok_trivial6(TrivialDerived d) { return d; } - -// If the target is a parameter, do apply the diagnostic. -Derived testParam1(Derived d) { return d; } -Base testParam2(Derived d) { - return d; // e6 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)" -} -ConstructFromDerived testParam3(Derived d) { - return d; // ok -} -ConstructFromBase testParam4(Derived d) { - return d; // e8 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)" -} -ConvertFromDerived testParam5(Derived d) { - return d; // e9 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)" -} -ConvertFromBase testParam6(Derived d) { - return d; // e10 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)" -} - -// If the target is an rvalue reference parameter, do apply the diagnostic. -Derived testRParam1(Derived&& d) { - return d; // e11 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)" -} -Base testRParam2(Derived&& d) { - return d; // e12 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)" -} -ConstructFromDerived testRParam3(Derived&& d) { - return d; // e13 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)" -} -ConstructFromBase testRParam4(Derived&& d) { - return d; // e14 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)" -} -ConvertFromDerived testRParam5(Derived&& d) { - return d; // e15 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)" -} -ConvertFromBase testRParam6(Derived&& d) { - return d; // e16 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)" -} - -// But if the return type is a reference type, then moving would be wrong. -Derived &testRetRef1(Derived &&d) { return d; } // cxx2b-error {{non-const lvalue reference to type 'Derived' cannot bind to a temporary of type 'Derived'}} -Base &testRetRef2(Derived &&d) { return d; } // cxx2b-error {{non-const lvalue reference to type 'Base' cannot bind to a temporary of type 'Derived'}} -#if __cplusplus >= 201402L -auto&& testRetRef3(Derived&& d) { return d; } -decltype(auto) testRetRef4(Derived&& d) { return (d); } -#endif - -// As long as we're checking parentheses, make sure parentheses don't disable the warning. -Base testParens1() { - Derived d; - return (d); // e17 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:15}:"std::move(d)" -} -ConstructFromDerived testParens2() { - Derived d; - return (d); // ok -} - -// If the target is a catch-handler parameter, do apply the diagnostic. -void throw_derived(); -Derived testEParam1() { - try { throw_derived(); } catch (Derived d) { return d; } // e19 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:57-[[@LINE-3]]:58}:"std::move(d)" - __builtin_unreachable(); -} -Base testEParam2() { - try { throw_derived(); } catch (Derived d) { return d; } // e20 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:57-[[@LINE-3]]:58}:"std::move(d)" - __builtin_unreachable(); -} -ConstructFromDerived testEParam3() { - try { throw_derived(); } catch (Derived d) { return d; } // e21 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:57-[[@LINE-3]]:58}:"std::move(d)" - __builtin_unreachable(); -} -ConstructFromBase testEParam4() { - try { throw_derived(); } catch (Derived d) { return d; } // e22 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:57-[[@LINE-3]]:58}:"std::move(d)" - __builtin_unreachable(); -} -ConvertFromDerived testEParam5() { - try { throw_derived(); } catch (Derived d) { return d; } // e23 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:57-[[@LINE-3]]:58}:"std::move(d)" - __builtin_unreachable(); -} -ConvertFromBase testEParam6() { - try { throw_derived(); } catch (Derived d) { return d; } // e24 - // cxx11_17-warning@-1{{will be copied despite being returned by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:57-[[@LINE-3]]:58}:"std::move(d)" - __builtin_unreachable(); -} - -// If the exception variable is an lvalue reference, we cannot be sure -// that we own it; it is extremely contrived, but possible, for this to -// be a reference to an exception object that was thrown via -// `std::rethrow_exception(xp)` in Thread A, and meanwhile somebody else -// has got a copy of `xp` in Thread B, so that moving out of this object -// in Thread A would be observable (and racy) with respect to Thread B. -// Therefore assume it's not safe to move from. -Derived ok_REParam1() { try { throw_derived(); } catch (Derived& d) { return d; } __builtin_unreachable(); } -Base ok_REParam2() { try { throw_derived(); } catch (Derived& d) { return d; } __builtin_unreachable(); } -ConstructFromDerived ok_REParam3() { try { throw_derived(); } catch (Derived& d) { return d; } __builtin_unreachable(); } -ConstructFromBase ok_REParam4() { try { throw_derived(); } catch (Derived& d) { return d; } __builtin_unreachable(); } -ConvertFromDerived ok_REParam5() { try { throw_derived(); } catch (Derived& d) { return d; } __builtin_unreachable(); } -ConvertFromBase ok_REParam6() { try { throw_derived(); } catch (Derived& d) { return d; } __builtin_unreachable(); } - -Derived ok_CEParam1() { try { throw_derived(); } catch (const Derived& d) { return d; } __builtin_unreachable(); } -Base ok_CEParam2() { try { throw_derived(); } catch (const Derived& d) { return d; } __builtin_unreachable(); } -ConstructFromDerived ok_CEParam3() { try { throw_derived(); } catch (const Derived& d) { return d; } __builtin_unreachable(); } -ConstructFromBase ok_CEParam4() { try { throw_derived(); } catch (const Derived& d) { return d; } __builtin_unreachable(); } -ConvertFromDerived ok_CEParam5() { try { throw_derived(); } catch (const Derived& d) { return d; } __builtin_unreachable(); } -ConvertFromBase ok_CEParam6() { try { throw_derived(); } catch (const Derived& d) { return d; } __builtin_unreachable(); } - -// If rvalue overload resolution would find a copy constructor anyway, -// or if the copy constructor actually selected is trivial, then don't warn. -struct TriviallyCopyable {}; -struct OnlyCopyable { - OnlyCopyable() = default; - OnlyCopyable(const OnlyCopyable&) {} -}; - -TriviallyCopyable ok_copy1() { TriviallyCopyable c; return c; } -OnlyCopyable ok_copy2() { OnlyCopyable c; return c; } -TriviallyCopyable ok_copyparam1(TriviallyCopyable c) { return c; } -OnlyCopyable ok_copyparam2(OnlyCopyable c) { return c; } - -void test_throw1(Derived&& d) { - throw d; // e25 - // cxx11_17-warning@-1{{will be copied despite being thrown by name}} - // cxx11_17-note@-2{{to avoid copying}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:12}:"std::move(d)" -} - -void ok_throw1() { - Derived d; - throw d; -} -void ok_throw2(Derived d) { throw d; } -void ok_throw3(Derived &d) { throw d; } -void ok_throw4(Derived d) { throw std::move(d); } -void ok_throw5(Derived &d) { throw std::move(d); } -void ok_throw6(Derived &d) { throw static_cast(d); } -void ok_throw7(TriviallyCopyable d) { throw d; } -void ok_throw8(OnlyCopyable d) { throw d; } - -namespace test_delete { -struct Base { - Base(); - Base(Base &&) = delete; // cxx20_2b-note {{'Base' has been explicitly marked deleted here}} - Base(Base const &); -}; - -struct Derived : public Base {}; - -Base test_ok() { - Derived d; - return d; // cxx20_2b-error {{call to deleted constructor of 'test_delete::Base'}} -} -} // namespace test_delete diff --git a/clang/test/SemaObjCXX/block-capture.mm b/clang/test/SemaObjCXX/block-capture.mm --- a/clang/test/SemaObjCXX/block-capture.mm +++ b/clang/test/SemaObjCXX/block-capture.mm @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -std=c++2b -fsyntax-only -fobjc-arc -fblocks -verify=cxx98_2b,cxx20_2b,cxx2b %s -// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fobjc-arc -fblocks -verify=cxx98_2b,cxx20_2b %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fobjc-arc -fblocks -verify=cxx98_2b,cxx98_11 %s -// RUN: %clang_cc1 -std=c++98 -fsyntax-only -fobjc-arc -fblocks -Wno-c++11-extensions -verify=cxx98_2b,cxx98_11 %s +// RUN: %clang_cc1 -std=c++2b -fsyntax-only -fobjc-arc -fblocks -verify=cxx98_2b,cxx11_2b,cxx2b %s +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fobjc-arc -fblocks -verify=cxx98_2b,cxx11_2b %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fobjc-arc -fblocks -verify=cxx98_2b,cxx11_2b %s +// RUN: %clang_cc1 -std=c++98 -fsyntax-only -fobjc-arc -fblocks -Wno-c++11-extensions -verify=cxx98_2b,cxx98 %s #define TEST(T) void test_##T() { \ __block T x; \ @@ -14,54 +14,68 @@ }; TEST(CopyOnly); // cxx2b-error {{no matching constructor}} +struct ConstCopyOnly { + ConstCopyOnly(); + ConstCopyOnly(ConstCopyOnly &) = delete; // cxx98-note {{marked deleted here}} + ConstCopyOnly(const ConstCopyOnly &); +}; +TEST(ConstCopyOnly); // cxx98-error {{call to deleted constructor}} + +struct NonConstCopyOnly { + NonConstCopyOnly(); + NonConstCopyOnly(NonConstCopyOnly &); + NonConstCopyOnly(const NonConstCopyOnly &) = delete; // cxx11_2b-note {{marked deleted here}} +}; +TEST(NonConstCopyOnly); // cxx11_2b-error {{call to deleted constructor}} + struct CopyNoMove { CopyNoMove(); CopyNoMove(CopyNoMove &); - CopyNoMove(CopyNoMove &&) = delete; // cxx98_2b-note {{marked deleted here}} + CopyNoMove(CopyNoMove &&) = delete; // cxx11_2b-note {{marked deleted here}} }; -TEST(CopyNoMove); // cxx98_2b-error {{call to deleted constructor}} +TEST(CopyNoMove); // cxx11_2b-error {{call to deleted constructor}} struct MoveOnly { MoveOnly(); - MoveOnly(MoveOnly &) = delete; + MoveOnly(MoveOnly &) = delete; // cxx98-note {{marked deleted here}} MoveOnly(MoveOnly &&); }; -TEST(MoveOnly); +TEST(MoveOnly); // cxx98-error {{call to deleted constructor}} struct NoCopyNoMove { NoCopyNoMove(); - NoCopyNoMove(NoCopyNoMove &) = delete; - NoCopyNoMove(NoCopyNoMove &&) = delete; // cxx98_2b-note {{marked deleted here}} + NoCopyNoMove(NoCopyNoMove &) = delete; // cxx98-note {{marked deleted here}} + NoCopyNoMove(NoCopyNoMove &&) = delete; // cxx11_2b-note {{marked deleted here}} }; TEST(NoCopyNoMove); // cxx98_2b-error {{call to deleted constructor}} struct ConvertingRVRef { ConvertingRVRef(); - ConvertingRVRef(ConvertingRVRef &) = delete; // cxx98_11-note {{marked deleted here}} + ConvertingRVRef(ConvertingRVRef &) = delete; // cxx98-note {{marked deleted here}} struct X {}; ConvertingRVRef(X &&); operator X() const & = delete; operator X() &&; }; -TEST(ConvertingRVRef); // cxx98_11-error {{call to deleted constructor}} +TEST(ConvertingRVRef); // cxx98-error {{call to deleted constructor}} struct ConvertingCLVRef { ConvertingCLVRef(); ConvertingCLVRef(ConvertingCLVRef &); struct X {}; - ConvertingCLVRef(X &&); // cxx20_2b-note {{passing argument to parameter here}} + ConvertingCLVRef(X &&); // cxx11_2b-note {{passing argument to parameter here}} operator X() const &; - operator X() && = delete; // cxx20_2b-note {{marked deleted here}} + operator X() && = delete; // cxx11_2b-note {{marked deleted here}} }; -TEST(ConvertingCLVRef); // cxx20_2b-error {{invokes a deleted function}} +TEST(ConvertingCLVRef); // cxx11_2b-error {{invokes a deleted function}} struct SubSubMove {}; struct SubMove : SubSubMove { SubMove(); - SubMove(SubMove &) = delete; // cxx98_11-note {{marked deleted here}} + SubMove(SubMove &) = delete; // cxx98-note {{marked deleted here}} SubMove(SubSubMove &&); }; -TEST(SubMove); // cxx98_11-error {{call to deleted constructor}} +TEST(SubMove); // cxx98-error {{call to deleted constructor}}