mizvekov updated this revision to Diff 332140.
mizvekov added a comment.
- Removed special flag, now is enabled on -std=c++2b
- Always enabled for coroutines
- Ran test suite
- Some relevant test files updated to also run c++2b
- Some new tests added
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D99005/new/
https://reviews.llvm.org/D99005
Files:
clang/include/clang/Sema/Sema.h
clang/lib/Sema/Sema.cpp
clang/lib/Sema/SemaCoroutine.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaStmt.cpp
clang/lib/Sema/SemaType.cpp
clang/test/CXX/class/class.init/class.copy.elision/p3.cpp
clang/test/CXX/special/class.copy/p33-0x.cpp
Index: clang/test/CXX/special/class.copy/p33-0x.cpp
===================================================================
--- clang/test/CXX/special/class.copy/p33-0x.cpp
+++ clang/test/CXX/special/class.copy/p33-0x.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++2b -fsyntax-only -verify=expected,cxx2b %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++11 -fsyntax-only -verify=expected,cxx11 %s
+// cxx2b-no-diagnostics
class X {
X(const X&);
@@ -27,7 +29,7 @@
struct X {
X();
X(X&&);
- X(const X&) = delete; // expected-note 2{{'X' has been explicitly marked deleted here}}
+ X(const X&) = delete; // cxx11-note 2{{'X' has been explicitly marked deleted here}}
};
void f(int i) {
@@ -36,7 +38,7 @@
X x2;
if (i)
throw x2; // okay
- throw x; // expected-error{{call to deleted constructor of 'PR10142::X'}}
+ throw x; // cxx11-error{{call to deleted constructor of 'PR10142::X'}}
} catch (...) {
}
}
@@ -48,10 +50,10 @@
T x2;
if (i)
throw x2; // okay
- throw x; // expected-error{{call to deleted constructor of 'PR10142::X'}}
+ throw x; // cxx11-error{{call to deleted constructor of 'PR10142::X'}}
} catch (...) {
}
}
- template void f2<X>(int); // expected-note{{in instantiation of function template specialization 'PR10142::f2<PR10142::X>' requested here}}
+ template void f2<X>(int); // cxx11-note{{in instantiation of function template specialization 'PR10142::f2<PR10142::X>' requested here}}
}
Index: clang/test/CXX/class/class.init/class.copy.elision/p3.cpp
===================================================================
--- clang/test/CXX/class/class.init/class.copy.elision/p3.cpp
+++ clang/test/CXX/class/class.init/class.copy.elision/p3.cpp
@@ -1,7 +1,8 @@
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected,cxx20 %s
-// RUN: %clang_cc1 -std=c++17 -fsyntax-only -fcxx-exceptions -verify=expected,cxx11_14_17 %s
-// RUN: %clang_cc1 -std=c++14 -fsyntax-only -fcxx-exceptions -verify=expected,cxx11_14_17 %s
-// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fcxx-exceptions -verify=expected,cxx11_14_17 %s
+// 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_14_17_20,cxx20_2b %s
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -fcxx-exceptions -verify=expected,cxx11_14_17_20,cxx11_14_17 %s
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -fcxx-exceptions -verify=expected,cxx11_14_17_20,cxx11_14_17 %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fcxx-exceptions -verify=expected,cxx11_14_17_20,cxx11_14_17 %s
namespace test_delete_function {
struct A1 {
@@ -72,20 +73,20 @@
struct B1 {
B1(const B1 &);
- B1(B1 &&) = delete; // cxx20-note {{'B1' has been explicitly marked deleted here}}
+ B1(B1 &&) = delete; // cxx20_2b-note {{'B1' has been explicitly marked deleted here}}
};
B1 test3(B1 &&b) {
- return b; // cxx20-error {{call to deleted constructor of 'test_implicitly_movable_rvalue_ref::B1'}}
+ return b; // cxx20_2b-error {{call to deleted constructor of 'test_implicitly_movable_rvalue_ref::B1'}}
}
struct B2 {
B2(const B2 &);
private:
- B2(B2 &&); // cxx20-note {{declared private here}}
+ B2(B2 &&); // cxx20_2b-note {{declared private here}}
};
B2 test4(B2 &&b) {
- return b; // cxx20-error {{calling a private constructor of class 'test_implicitly_movable_rvalue_ref::B2'}}
+ return b; // cxx20_2b-error {{calling a private constructor of class 'test_implicitly_movable_rvalue_ref::B2'}}
}
} // namespace test_implicitly_movable_rvalue_ref
@@ -96,13 +97,13 @@
struct A1 {
A1(const A1 &);
- A1(A1 &&) = delete; // cxx20-note {{'A1' has been explicitly marked deleted here}}
+ A1(A1 &&) = delete; // cxx20_2b-note {{'A1' has been explicitly marked deleted here}}
};
void test1() {
try {
func();
} catch (A1 a) {
- throw a; // cxx20-error {{call to deleted constructor of 'test_throw_parameter::A1'}}
+ throw a; // cxx20_2b-error {{call to deleted constructor of 'test_throw_parameter::A1'}}
}
}
@@ -110,13 +111,13 @@
A2(const A2 &);
private:
- A2(A2 &&); // cxx20-note {{declared private here}}
+ A2(A2 &&); // cxx20_2b-note {{declared private here}}
};
void test2() {
try {
func();
} catch (A2 a) {
- throw a; // cxx20-error {{calling a private constructor of class 'test_throw_parameter::A2'}}
+ throw a; // cxx20_2b-error {{calling a private constructor of class 'test_throw_parameter::A2'}}
}
}
} // namespace test_throw_parameter
@@ -148,22 +149,22 @@
struct B1 {
operator C() const &;
- operator C() && = delete; // cxx20-note {{'operator C' has been explicitly marked deleted here}}
+ operator C() && = delete; // cxx20_2b-note {{'operator C' has been explicitly marked deleted here}}
};
C test3() {
B1 b;
- return b; // cxx20-error {{conversion function from 'test_non_ctor_conversion::B1' to 'test_non_ctor_conversion::C' invokes a deleted function}}
+ return b; // cxx20_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-note {{declared private here}}
+ operator C() &&; // cxx20_2b-note {{declared private here}}
};
C test4() {
B2 b;
- return b; // cxx20-error {{'operator C' is a private member of 'test_non_ctor_conversion::B2'}}
+ return b; // cxx20_2b-error {{'operator C' is a private member of 'test_non_ctor_conversion::B2'}}
}
} // namespace test_non_ctor_conversion
@@ -184,7 +185,7 @@
struct NeedValue {
NeedValue(A1); // cxx11_14_17-note 2 {{passing argument to parameter here}}
NeedValue(A2);
- NeedValue(B1); // cxx20-note 2 {{passing argument to parameter here}}
+ NeedValue(B1); // cxx20_2b-note 2 {{passing argument to parameter here}}
NeedValue(B2);
};
@@ -243,26 +244,26 @@
struct B1 {
B1();
B1(const B1 &);
- B1(B1 &&) = delete; // cxx20-note 3 {{'B1' has been explicitly marked deleted here}}
+ B1(B1 &&) = delete; // cxx20_2b-note 3 {{'B1' has been explicitly marked deleted here}}
};
NeedValue test_3_1() {
// not rvalue reference
// same type
B1 b;
- return b; // cxx20-error {{call to deleted constructor of 'test_ctor_param_rvalue_ref::B1'}}
+ return b; // cxx20_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-error {{call to deleted constructor of 'test_ctor_param_rvalue_ref::B1'}}
+ return b; // cxx20_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-error {{call to deleted constructor of 'test_ctor_param_rvalue_ref::B1'}}
+ return b; // cxx20_2b-error {{call to deleted constructor of 'test_ctor_param_rvalue_ref::B1'}}
}
struct B2 {
@@ -270,25 +271,68 @@
B2(const B2 &);
private:
- B2(B2 &&); // cxx20-note 3 {{declared private here}}
+ B2(B2 &&); // cxx20_2b-note 3 {{declared private here}}
};
NeedValue test_4_1() {
// not rvalue reference
// same type
B2 b;
- return b; // cxx20-error {{calling a private constructor of class 'test_ctor_param_rvalue_ref::B2'}}
+ return b; // cxx20_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-error {{calling a private constructor of class 'test_ctor_param_rvalue_ref::B2'}}
+ return b; // cxx20_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-error {{calling a private constructor of class 'test_ctor_param_rvalue_ref::B2'}}
+ return b; // cxx20_2b-error {{calling a private constructor of class 'test_ctor_param_rvalue_ref::B2'}}
}
} // namespace test_ctor_param_rvalue_ref
+namespace test_simpler_implicit_move {
+struct CopyOnly {
+ CopyOnly(); // cxx2b-note {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
+ CopyOnly(CopyOnly&); // cxx2b-note {{candidate constructor not viable: expects an lvalue for 1st argument}}
+};
+struct MoveOnly {
+ MoveOnly();
+ MoveOnly(MoveOnly&&); // cxx11_14_17_20-note {{copy constructor is implicitly deleted}}
+};
+MoveOnly&& rref();
+
+MoveOnly&& test_1(MoveOnly&& w) {
+ return w; // cxx11_14_17_20-error {{cannot bind to lvalue of type}}
+}
+
+CopyOnly test_2(bool b) {
+ static CopyOnly w1;
+ CopyOnly w2;
+ if (b) {
+ return w1;
+ } else {
+ return w2; // cxx2b-error {{no matching constructor for initialization}}
+ }
+}
+
+template<class T> T&& test_3a(T&& x) { return x; } // cxx11_14_17_20-error {{cannot bind to lvalue of type}}
+void test_3b(MoveOnly w) {
+ MoveOnly& r = test_3a(w);
+ MoveOnly&& rr = test_3a(static_cast<MoveOnly&&>(w)); // cxx11_14_17_20-note {{in instantiation of function template specialization}}
+}
+
+MoveOnly&& test_4() {
+ MoveOnly &&x = rref();
+ return x; // cxx11_14_17_20-error {{cannot bind to lvalue of type}}
+}
+
+void test_5() {
+ MoveOnly x;
+ try {
+ throw x; // cxx11_14_17_20-error {{call to implicitly-deleted copy constructor}}
+ } catch(...) {}
+}
+} // namespace test_simpler_implicit_move
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -8839,6 +8839,10 @@
if (E->isTypeDependent())
return S.Context.DependentTy;
+ Expr *IDExpr = E;
+ if (auto *ImplCastExpr = dyn_cast<ImplicitCastExpr>(E))
+ IDExpr = ImplCastExpr->getSubExpr();
+
// C++11 [dcl.type.simple]p4:
// The type denoted by decltype(e) is defined as follows:
@@ -8849,7 +8853,7 @@
// Note that this does not pick up the implicit 'const' for a template
// parameter object. This rule makes no difference before C++20 so we apply
// it unconditionally.
- if (const auto *SNTTPE = dyn_cast<SubstNonTypeTemplateParmExpr>(E))
+ if (const auto *SNTTPE = dyn_cast<SubstNonTypeTemplateParmExpr>(IDExpr))
return SNTTPE->getParameterType(S.Context);
// - if e is an unparenthesized id-expression or an unparenthesized class
@@ -8858,21 +8862,22 @@
// functions, the program is ill-formed;
//
// We apply the same rules for Objective-C ivar and property references.
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(IDExpr)) {
const ValueDecl *VD = DRE->getDecl();
if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(VD))
return TPO->getType().getUnqualifiedType();
return VD->getType();
- } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+ } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(IDExpr)) {
if (const ValueDecl *VD = ME->getMemberDecl())
if (isa<FieldDecl>(VD) || isa<VarDecl>(VD))
return VD->getType();
- } else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(E)) {
+ } else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(IDExpr)) {
return IR->getDecl()->getType();
- } else if (const ObjCPropertyRefExpr *PR = dyn_cast<ObjCPropertyRefExpr>(E)) {
+ } else if (const ObjCPropertyRefExpr *PR =
+ dyn_cast<ObjCPropertyRefExpr>(IDExpr)) {
if (PR->isExplicitProperty())
return PR->getExplicitProperty()->getType();
- } else if (auto *PE = dyn_cast<PredefinedExpr>(E)) {
+ } else if (auto *PE = dyn_cast<PredefinedExpr>(IDExpr)) {
return PE->getType();
}
@@ -8885,8 +8890,8 @@
// entity.
using namespace sema;
if (S.getCurLambda()) {
- if (isa<ParenExpr>(E)) {
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
+ if (isa<ParenExpr>(IDExpr)) {
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(IDExpr->IgnoreParens())) {
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
QualType T = S.getCapturedDeclRefType(Var, DRE->getLocation());
if (!T.isNull())
Index: clang/lib/Sema/SemaStmt.cpp
===================================================================
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -3041,6 +3041,8 @@
/// NRVO, or NULL if there is no such candidate.
VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType, Expr *E,
CopyElisionSemanticsKind CESK) {
+ if (auto ImplCastExpr = dyn_cast<ImplicitCastExpr>(E))
+ E = ImplCastExpr->getSubExpr();
// - in a return statement in a function [where] ...
// ... the expression is the name of a non-volatile automatic object ...
DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParens());
@@ -3086,15 +3088,14 @@
if (VD->hasAttr<BlocksAttr>())
return false;
- // ...non-volatile...
- if (VD->getType().isVolatileQualified())
- return false;
-
- // C++20 [class.copy.elision]p3:
- // ...rvalue reference to a non-volatile...
- if (VD->getType()->isRValueReferenceType() &&
- (!(CESK & CES_AllowRValueReferenceType) ||
- VD->getType().getNonReferenceType().isVolatileQualified()))
+ QualType VDNonRefType = VDType;
+ if (VDType->isReferenceType()) {
+ if (!(CESK & CES_AllowRValueReferenceType) ||
+ !VDType->isRValueReferenceType())
+ return false;
+ VDNonRefType = VDType.getNonReferenceType();
+ }
+ if (!VDNonRefType->isObjectType() || VDNonRefType.isVolatileQualified())
return false;
if (CESK & CES_AllowDifferentTypes)
@@ -3102,8 +3103,8 @@
// Variables with higher required alignment than their type's ABI
// alignment cannot use NRVO.
- if (!VD->getType()->isDependentType() && VD->hasAttr<AlignedAttr>() &&
- Context.getDeclAlign(VD) > Context.getTypeAlignInChars(VD->getType()))
+ if (!VDNonRefType->isDependentType() && VD->hasAttr<AlignedAttr>() &&
+ Context.getDeclAlign(VD) > Context.getTypeAlignInChars(VDNonRefType))
return false;
return true;
@@ -3222,14 +3223,13 @@
bool NeedSecondOverloadResolution = true;
if (AllowNRVO) {
- CopyElisionSemanticsKind CESK = CES_Strict;
- if (getLangOpts().CPlusPlus20) {
- CESK = CES_ImplicitlyMovableCXX20;
- } else if (getLangOpts().CPlusPlus11) {
- CESK = CES_ImplicitlyMovableCXX11CXX14CXX17;
- }
-
if (!NRVOCandidate) {
+ CopyElisionSemanticsKind CESK = CES_Strict;
+ if (getLangOpts().CPlusPlus20) {
+ CESK = CES_ImplicitlyMovableCXX20;
+ } else if (getLangOpts().CPlusPlus11) {
+ CESK = CES_ImplicitlyMovableCXX11CXX14CXX17;
+ }
NRVOCandidate = getCopyElisionCandidate(ResultType, Value, CESK);
}
@@ -3432,8 +3432,9 @@
InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
FnRetType,
NRVOCandidate != nullptr);
- ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate,
- FnRetType, RetValExp);
+ ExprResult Res = PerformMoveOrCopyInitialization(
+ Entity, NRVOCandidate, FnRetType, RetValExp,
+ /*AllowNRVO=*/!getLangOpts().CPlusPlus2b);
if (Res.isInvalid()) {
// FIXME: Cleanup temporaries here, anyway?
return StmtError();
@@ -3650,6 +3651,15 @@
if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp))
return StmtError();
+ if (getLangOpts().CPlusPlus2b && RetValExp) {
+ if (VarDecl *VD = getCopyElisionCandidate(QualType{}, RetValExp,
+ CES_ImplicitlyMovableCXX20)) {
+ RetValExp = ImplicitCastExpr::Create(
+ Context, VD->getType().getNonReferenceType(), CK_NoOp, RetValExp,
+ nullptr, VK_XValue, FPOptionsOverride());
+ }
+ }
+
if (isa<CapturingScopeInfo>(getCurFunction()))
return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp);
@@ -3846,8 +3856,9 @@
InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
RetType,
NRVOCandidate != nullptr);
- ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate,
- RetType, RetValExp);
+ ExprResult Res = PerformMoveOrCopyInitialization(
+ Entity, NRVOCandidate, RetType, RetValExp,
+ /*AllowNRVO=*/!getLangOpts().CPlusPlus2b);
if (Res.isInvalid()) {
// FIXME: Clean up temporaries here anyway?
return StmtError();
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -851,6 +851,15 @@
Diag(OpLoc, diag::err_omp_simd_region_cannot_use_stmt) << "throw";
if (Ex && !Ex->isTypeDependent()) {
+ if (getLangOpts().CPlusPlus2b) {
+ if (VarDecl *VD = getCopyElisionCandidate(QualType{}, Ex,
+ CES_ImplicitlyMovableCXX20)) {
+ Ex = ImplicitCastExpr::Create(
+ Context, VD->getType().getNonReferenceType(), CK_NoOp, Ex, nullptr,
+ VK_XValue, FPOptionsOverride());
+ }
+ }
+
QualType ExceptionObjectTy = Context.getExceptionObjectType(Ex->getType());
if (CheckCXXThrowOperand(OpLoc, ExceptionObjectTy, Ex))
return ExprError();
@@ -878,7 +887,8 @@
OpLoc, ExceptionObjectTy,
/*NRVO=*/NRVOVariable != nullptr);
ExprResult Res = PerformMoveOrCopyInitialization(
- Entity, NRVOVariable, QualType(), Ex, IsThrownVarInScope);
+ Entity, NRVOVariable, QualType(), Ex,
+ /*AllowNRVO=*/!getLangOpts().CPlusPlus2b && IsThrownVarInScope);
if (Res.isInvalid())
return ExprError();
Ex = Res.get();
Index: clang/lib/Sema/SemaCoroutine.cpp
===================================================================
--- clang/lib/Sema/SemaCoroutine.cpp
+++ clang/lib/Sema/SemaCoroutine.cpp
@@ -999,10 +999,14 @@
const VarDecl *NRVOCandidate = this->getCopyElisionCandidate(
E->getType(), E, CES_ImplicitlyMovableCXX20);
if (NRVOCandidate) {
+ QualType T = NRVOCandidate->getType();
+ E = ImplicitCastExpr::Create(Context, T.getNonReferenceType(), CK_NoOp, E,
+ nullptr, VK_XValue, FPOptionsOverride());
InitializedEntity Entity =
- InitializedEntity::InitializeResult(Loc, E->getType(), NRVOCandidate);
- ExprResult MoveResult = this->PerformMoveOrCopyInitialization(
- Entity, NRVOCandidate, E->getType(), E);
+ InitializedEntity::InitializeResult(Loc, T, NRVOCandidate);
+ ExprResult MoveResult =
+ this->PerformMoveOrCopyInitialization(Entity, NRVOCandidate, T, E,
+ /*AllowNRVO=*/false);
if (MoveResult.get())
E = MoveResult.get();
}
@@ -1570,7 +1574,8 @@
// Trigger a nice error message.
InitializedEntity Entity =
InitializedEntity::InitializeResult(Loc, FnRetType, false);
- S.PerformMoveOrCopyInitialization(Entity, nullptr, FnRetType, ReturnValue);
+ S.PerformMoveOrCopyInitialization(Entity, nullptr, FnRetType, ReturnValue,
+ /*AllowNRVO=*/false);
noteMemberDeclaredHere(S, ReturnValue, Fn);
return false;
}
@@ -1587,7 +1592,8 @@
InitializedEntity Entity = InitializedEntity::InitializeVariable(GroDecl);
ExprResult Res = S.PerformMoveOrCopyInitialization(Entity, nullptr, GroType,
- this->ReturnValue);
+ this->ReturnValue,
+ /*AllowNRVO=*/false);
if (Res.isInvalid())
return false;
Index: clang/lib/Sema/Sema.cpp
===================================================================
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -1954,7 +1954,7 @@
new (S.Context) DeclRefExpr(S.Context, VD, false, T, VK_LValue, Loc);
ExprResult Result = S.PerformMoveOrCopyInitialization(
InitializedEntity::InitializeBlock(Loc, T, false), VD, VD->getType(),
- VarRef, /*AllowNRVO=*/true);
+ VarRef, /*AllowNRVO=*/!S.getLangOpts().CPlusPlus2b);
if (!Result.isInvalid()) {
Result = S.MaybeCreateExprWithCleanups(Result);
Expr *Init = Result.getAs<Expr>();
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -3428,9 +3428,8 @@
ExprResult PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
const VarDecl *NRVOCandidate,
- QualType ResultType,
- Expr *Value,
- bool AllowNRVO = true);
+ QualType ResultType, Expr *Value,
+ bool AllowNRVO);
bool CanPerformAggregateInitializationForOverloadResolution(
const InitializedEntity &Entity, InitListExpr *From);
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits