forked from OSchip/llvm-project
[clang] Implement P2266 Simpler implicit move
This Implements [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2266r1.html|P2266 Simpler implicit move]]. Signed-off-by: Matheus Izvekov <mizvekov@gmail.com> Reviewed By: Quuxplusone Differential Revision: https://reviews.llvm.org/D99005
This commit is contained in:
parent
7f7be19e6a
commit
ced6b204d1
|
@ -4763,7 +4763,7 @@ public:
|
|||
bool isMoveEligible() const { return S != None; };
|
||||
bool isCopyElidable() const { return S == MoveEligibleAndCopyElidable; }
|
||||
};
|
||||
NamedReturnInfo getNamedReturnInfo(const Expr *E, bool ForceCXX20 = false);
|
||||
NamedReturnInfo getNamedReturnInfo(Expr *&E, bool ForceCXX2b = false);
|
||||
NamedReturnInfo getNamedReturnInfo(const VarDecl *VD,
|
||||
bool ForceCXX20 = false);
|
||||
const VarDecl *getCopyElisionCandidate(NamedReturnInfo &Info,
|
||||
|
|
|
@ -1965,9 +1965,17 @@ static void checkEscapingByref(VarDecl *VD, Sema &S) {
|
|||
SourceLocation Loc = VD->getLocation();
|
||||
Expr *VarRef =
|
||||
new (S.Context) DeclRefExpr(S.Context, VD, false, T, VK_LValue, Loc);
|
||||
ExprResult Result = S.PerformMoveOrCopyInitialization(
|
||||
InitializedEntity::InitializeBlock(Loc, T, false),
|
||||
Sema::NamedReturnInfo{VD, Sema::NamedReturnInfo::MoveEligible}, VarRef);
|
||||
ExprResult Result;
|
||||
auto IE = InitializedEntity::InitializeBlock(Loc, T, false);
|
||||
if (S.getLangOpts().CPlusPlus2b) {
|
||||
auto *E = ImplicitCastExpr::Create(S.Context, T, CK_NoOp, VarRef, nullptr,
|
||||
VK_XValue, FPOptionsOverride());
|
||||
Result = S.PerformCopyInitialization(IE, SourceLocation(), E);
|
||||
} else {
|
||||
Result = S.PerformMoveOrCopyInitialization(
|
||||
IE, Sema::NamedReturnInfo{VD, Sema::NamedReturnInfo::MoveEligible},
|
||||
VarRef);
|
||||
}
|
||||
|
||||
if (!Result.isInvalid()) {
|
||||
Result = S.MaybeCreateExprWithCleanups(Result);
|
||||
|
|
|
@ -994,22 +994,10 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E,
|
|||
E = R.get();
|
||||
}
|
||||
|
||||
// Move the return value if we can
|
||||
NamedReturnInfo NRInfo = getNamedReturnInfo(E, /*ForceCXX20=*/true);
|
||||
if (NRInfo.isMoveEligible()) {
|
||||
InitializedEntity Entity = InitializedEntity::InitializeResult(
|
||||
Loc, E->getType(), NRInfo.Candidate);
|
||||
ExprResult MoveResult = PerformMoveOrCopyInitialization(Entity, NRInfo, E);
|
||||
if (MoveResult.get())
|
||||
E = MoveResult.get();
|
||||
}
|
||||
|
||||
// FIXME: If the operand is a reference to a variable that's about to go out
|
||||
// of scope, we should treat the operand as an xvalue for this overload
|
||||
// resolution.
|
||||
VarDecl *Promise = FSI->CoroutinePromise;
|
||||
ExprResult PC;
|
||||
if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) {
|
||||
getNamedReturnInfo(E, /*ForceCXX2b=*/true);
|
||||
PC = buildPromiseCall(*this, Promise, Loc, "return_value", E);
|
||||
} else {
|
||||
E = MakeFullDiscardedValueExpr(E).get();
|
||||
|
|
|
@ -854,10 +854,6 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
|
|||
Diag(OpLoc, diag::err_omp_simd_region_cannot_use_stmt) << "throw";
|
||||
|
||||
if (Ex && !Ex->isTypeDependent()) {
|
||||
QualType ExceptionObjectTy = Context.getExceptionObjectType(Ex->getType());
|
||||
if (CheckCXXThrowOperand(OpLoc, ExceptionObjectTy, Ex))
|
||||
return ExprError();
|
||||
|
||||
// Initialize the exception result. This implicitly weeds out
|
||||
// abstract types or types with inaccessible copy constructors.
|
||||
|
||||
|
@ -876,6 +872,10 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
|
|||
NamedReturnInfo NRInfo =
|
||||
IsThrownVarInScope ? getNamedReturnInfo(Ex) : NamedReturnInfo();
|
||||
|
||||
QualType ExceptionObjectTy = Context.getExceptionObjectType(Ex->getType());
|
||||
if (CheckCXXThrowOperand(OpLoc, ExceptionObjectTy, Ex))
|
||||
return ExprError();
|
||||
|
||||
InitializedEntity Entity = InitializedEntity::InitializeException(
|
||||
OpLoc, ExceptionObjectTy,
|
||||
/*NRVO=*/NRInfo.isCopyElidable());
|
||||
|
|
|
@ -3312,15 +3312,16 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
|
|||
/// without considering function return type, if applicable.
|
||||
///
|
||||
/// \param E The expression being returned from the function or block,
|
||||
/// being thrown, or being co_returned from a coroutine.
|
||||
/// being thrown, or being co_returned from a coroutine. This expression
|
||||
/// might be modified by the implementation.
|
||||
///
|
||||
/// \param ForceCXX20 Overrides detection of current language mode
|
||||
/// and uses the rules for C++20.
|
||||
/// \param ForceCXX2b Overrides detection of current language mode
|
||||
/// and uses the rules for C++2b.
|
||||
///
|
||||
/// \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 Expr *E, bool ForceCXX20) {
|
||||
Sema::NamedReturnInfo Sema::getNamedReturnInfo(Expr *&E, bool ForceCXX2b) {
|
||||
if (!E)
|
||||
return NamedReturnInfo();
|
||||
// - in a return statement in a function [where] ...
|
||||
|
@ -3331,7 +3332,14 @@ Sema::NamedReturnInfo Sema::getNamedReturnInfo(const Expr *E, bool ForceCXX20) {
|
|||
const auto *VD = dyn_cast<VarDecl>(DR->getDecl());
|
||||
if (!VD)
|
||||
return NamedReturnInfo();
|
||||
return getNamedReturnInfo(VD, ForceCXX20);
|
||||
NamedReturnInfo Res = getNamedReturnInfo(VD, /*ForceCXX20=*/ForceCXX2b);
|
||||
if (Res.Candidate && !E->isXValue() &&
|
||||
(ForceCXX2b || getLangOpts().CPlusPlus2b)) {
|
||||
E = ImplicitCastExpr::Create(Context, VD->getType().getNonReferenceType(),
|
||||
CK_NoOp, E, nullptr, VK_XValue,
|
||||
FPOptionsOverride());
|
||||
}
|
||||
return Res;
|
||||
}
|
||||
|
||||
/// Updates the status in the given NamedReturnInfo object to disallow
|
||||
|
@ -3566,7 +3574,7 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
|
|||
const NamedReturnInfo &NRInfo,
|
||||
Expr *Value) {
|
||||
|
||||
if (NRInfo.Candidate) {
|
||||
if (NRInfo.Candidate && !getLangOpts().CPlusPlus2b) {
|
||||
if (NRInfo.isMoveEligible()) {
|
||||
ExprResult Res;
|
||||
if (!TryMoveInitialization(*this, Entity, NRInfo.Candidate, Value,
|
||||
|
|
|
@ -8899,6 +8899,10 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
|
|||
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:
|
||||
|
||||
|
@ -8909,7 +8913,7 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
|
|||
// 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
|
||||
|
@ -8918,21 +8922,22 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
|
|||
// 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();
|
||||
}
|
||||
|
||||
|
@ -8945,8 +8950,8 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
|
|||
// 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())
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -fcxx-exceptions -verify=expected,cxx20_2b %s
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected,cxx20_2b %s
|
||||
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -fcxx-exceptions -verify=expected,cxx11_17 %s
|
||||
// RUN: %clang_cc1 -std=c++14 -fsyntax-only -fcxx-exceptions -verify=expected,cxx11_17 %s
|
||||
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fcxx-exceptions -verify=expected,cxx11_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_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
|
||||
|
||||
namespace test_delete_function {
|
||||
struct A1 {
|
||||
|
@ -409,8 +409,10 @@ Target t4() {
|
|||
namespace test_simpler_implicit_move {
|
||||
|
||||
struct CopyOnly {
|
||||
CopyOnly();
|
||||
CopyOnly(CopyOnly &);
|
||||
CopyOnly(); // cxx2b-note {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
|
||||
// cxx2b-note@-1 {{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}}
|
||||
// cxx2b-note@-1 {{candidate constructor not viable: expects an lvalue for 1st argument}}
|
||||
};
|
||||
struct MoveOnly {
|
||||
MoveOnly();
|
||||
|
@ -419,7 +421,7 @@ struct MoveOnly {
|
|||
MoveOnly &&rref();
|
||||
|
||||
MoveOnly &&test1(MoveOnly &&w) {
|
||||
return w; // expected-error {{cannot bind to lvalue of type}}
|
||||
return w; // cxx11_20-error {{cannot bind to lvalue of type}}
|
||||
}
|
||||
|
||||
CopyOnly test2(bool b) {
|
||||
|
@ -428,22 +430,22 @@ CopyOnly test2(bool b) {
|
|||
if (b) {
|
||||
return w1;
|
||||
} else {
|
||||
return w2;
|
||||
return w2; // cxx2b-error {{no matching constructor for initialization}}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T> T &&test3(T &&x) { return x; } // expected-error {{cannot bind to lvalue of type}}
|
||||
template <class T> T &&test3(T &&x) { return x; } // cxx11_20-error {{cannot bind to lvalue of type}}
|
||||
template MoveOnly& test3<MoveOnly&>(MoveOnly&);
|
||||
template MoveOnly&& test3<MoveOnly>(MoveOnly&&); // expected-note {{in instantiation of function template specialization}}
|
||||
template MoveOnly &&test3<MoveOnly>(MoveOnly &&); // cxx11_20-note {{in instantiation of function template specialization}}
|
||||
|
||||
MoveOnly &&test4() {
|
||||
MoveOnly &&x = rref();
|
||||
return x; // expected-error {{cannot bind to lvalue of type}}
|
||||
return x; // cxx11_20-error {{cannot bind to lvalue of type}}
|
||||
}
|
||||
|
||||
void test5() try {
|
||||
CopyOnly x;
|
||||
throw x;
|
||||
throw x; // cxx2b-error {{no matching constructor for initialization}}
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -verify -std=c++2b -verify %s
|
||||
// RUN: %clang_cc1 -verify -std=c++20 -verify %s
|
||||
// RUN: %clang_cc1 -verify -std=c++14 -verify %s
|
||||
// RUN: %clang_cc1 -verify -std=c++2b -verify=expected,cxx2b %s
|
||||
// RUN: %clang_cc1 -verify -std=c++20 -verify=expected,cxx14_20 %s
|
||||
// RUN: %clang_cc1 -verify -std=c++14 -verify=expected,cxx14_20 %s
|
||||
|
||||
namespace std {
|
||||
template<typename T> struct initializer_list {
|
||||
|
@ -30,7 +30,7 @@ using Int = decltype(x3d);
|
|||
auto x4a = (i);
|
||||
decltype(auto) x4d = (i);
|
||||
using Int = decltype(x4a);
|
||||
using IntLRef = decltype(x4d);
|
||||
using IntLRef = decltype(x4d); // cxx2b-note {{previous definition is here}}
|
||||
|
||||
auto x5a = f();
|
||||
decltype(auto) x5d = f();
|
||||
|
@ -81,7 +81,7 @@ using Int = decltype(f2d(0));
|
|||
auto f3a(int n) { return (n); }
|
||||
decltype(auto) f3d(int n) { return (n); } // expected-warning {{reference to stack memory}}
|
||||
using Int = decltype(f3a(0));
|
||||
using IntLRef = decltype(f3d(0));
|
||||
using IntLRef = decltype(f3d(0)); // cxx2b-error {{type alias redefinition with different types ('decltype(f3d(0))' (aka 'int &&') vs 'decltype(x4d)' (aka 'int &'))}}
|
||||
|
||||
auto f4a(int n) { return f(); }
|
||||
decltype(auto) f4d(int n) { return f(); }
|
||||
|
@ -91,7 +91,7 @@ using IntRRef = decltype(f4d(0));
|
|||
auto f5aa(int n) { auto x = f(); return x; }
|
||||
auto f5ad(int n) { decltype(auto) x = f(); return x; }
|
||||
decltype(auto) f5da(int n) { auto x = f(); return x; }
|
||||
decltype(auto) f5dd(int n) { decltype(auto) x = f(); return x; } // expected-error {{rvalue reference to type 'int' cannot bind to lvalue}}
|
||||
decltype(auto) f5dd(int n) { decltype(auto) x = f(); return x; } // cxx14_20-error {{rvalue reference to type 'int' cannot bind to lvalue}}
|
||||
using Int = decltype(f5aa(0));
|
||||
using Int = decltype(f5ad(0));
|
||||
using Int = decltype(f5da(0));
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// RUN: %clang_cc1 -std=c++2b -verify=expected,cxx20_2b -triple %itanium_abi_triple %s -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
// RUN: %clang_cc1 -std=c++20 -verify=expected,cxx20_2b -triple %itanium_abi_triple %s -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
// RUN: %clang_cc1 -std=c++17 -verify=expected,cxx98_17 -triple %itanium_abi_triple %s -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
// RUN: %clang_cc1 -std=c++14 -verify=expected,cxx98_17 -triple %itanium_abi_triple %s -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
// RUN: %clang_cc1 -std=c++11 -verify=expected,cxx98_17 -triple %itanium_abi_triple %s -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
// RUN: %clang_cc1 -std=c++98 -verify=expected,cxx98_17 -triple %itanium_abi_triple %s -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
// RUN: %clang_cc1 -std=c++2b -verify=expected,cxx20_2b,cxx2b -triple %itanium_abi_triple %s -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
// RUN: %clang_cc1 -std=c++20 -verify=expected,cxx98_20,cxx20_2b -triple %itanium_abi_triple %s -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
// RUN: %clang_cc1 -std=c++17 -verify=expected,cxx98_17,cxx98_20 -triple %itanium_abi_triple %s -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
// RUN: %clang_cc1 -std=c++14 -verify=expected,cxx98_17,cxx98_20 -triple %itanium_abi_triple %s -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
// RUN: %clang_cc1 -std=c++11 -verify=expected,cxx98_17,cxx98_20 -triple %itanium_abi_triple %s -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
// RUN: %clang_cc1 -std=c++98 -verify=expected,cxx98_17,cxx98_20 -triple %itanium_abi_triple %s -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
|
||||
namespace dr300 { // dr300: yes
|
||||
template<typename R, typename A> void f(R (&)(A)) {}
|
||||
|
@ -628,7 +628,8 @@ namespace dr349 { // dr349: no
|
|||
struct A {
|
||||
template <class T> operator T ***() {
|
||||
int ***p = 0;
|
||||
return p; // expected-error {{cannot initialize return object of type 'const int ***' with an lvalue of type 'int ***'}}
|
||||
return p; // cxx98_20-error {{cannot initialize return object of type 'const int ***' with an lvalue of type 'int ***'}}
|
||||
// cxx2b-error@-1 {{cannot initialize return object of type 'const int ***' with an rvalue of type 'int ***'}}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=expected,cxx2b %s
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20 %s
|
||||
// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,cxx14_20 %s
|
||||
|
||||
int a;
|
||||
int &b = [] (int &r) -> decltype(auto) { return r; } (a);
|
||||
|
@ -9,13 +9,15 @@ int &d = [] (int &r) -> auto & { return r; } (a);
|
|||
int &e = [] (int &r) -> auto { return r; } (a); // expected-error {{cannot bind to a temporary}}
|
||||
int &f = [] (int r) -> decltype(auto) { return r; } (a); // expected-error {{cannot bind to a temporary}}
|
||||
int &g = [] (int r) -> decltype(auto) { return (r); } (a); // expected-warning {{reference to stack}}
|
||||
// cxx2b-error@-1 {{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
|
||||
|
||||
int test_explicit_auto_return()
|
||||
{
|
||||
struct X {};
|
||||
auto L = [](auto F, auto a) { return F(a); };
|
||||
auto M = [](auto a) -> auto { return a; }; // OK
|
||||
auto MRef = [](auto b) -> auto& { return b; }; //expected-warning{{reference to stack}}
|
||||
auto MRef = [](auto b) -> auto & { return b; }; //cxx14_20-warning{{reference to stack}}
|
||||
// cxx2b-error@-1 {{non-const lvalue reference to type 'X' cannot bind to a temporary of type 'X'}}
|
||||
auto MPtr = [](auto c) -> auto* { return &c; }; //expected-warning{{address of stack}}
|
||||
auto MDeclType = [](auto&& d) -> decltype(auto) { return static_cast<decltype(d)>(d); }; //OK
|
||||
M(3);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=expected,cxx2b %s
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx98_20 %s
|
||||
// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify=expected,cxx98_20 %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98_20 %s
|
||||
|
||||
struct A {
|
||||
template <class T> operator T*();
|
||||
|
@ -67,8 +67,10 @@ struct X0 {
|
|||
|
||||
template<typename T> operator const T*() const {
|
||||
T x = T();
|
||||
return x; // expected-error{{cannot initialize return object of type 'const char *' with an lvalue of type 'char'}} \
|
||||
// expected-error{{cannot initialize return object of type 'const int *' with an lvalue of type 'int'}}
|
||||
return x; // cxx98_20-error{{cannot initialize return object of type 'const char *' with an lvalue of type 'char'}} \
|
||||
// cxx98_20-error{{cannot initialize return object of type 'const int *' with an lvalue of type 'int'}} \
|
||||
// cxx2b-error{{cannot initialize return object of type 'const char *' with an rvalue of type 'char'}} \
|
||||
// cxx2b-error{{cannot initialize return object of type 'const int *' with an rvalue of type 'int'}}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=expected,cxx20_2b -triple x86_64-linux -Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array -Wno-c99-designator -fcxx-exceptions -pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx20_2b -triple x86_64-linux -Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array -Wno-c99-designator -fcxx-exceptions -pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion
|
||||
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify=expected,cxx11 -triple x86_64-linux -Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array -Wno-c99-designator -fcxx-exceptions -pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion
|
||||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=expected,cxx20_2b,cxx2b -triple x86_64-linux -Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array -Wno-c99-designator -fcxx-exceptions -pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx11_20,cxx20_2b -triple x86_64-linux -Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array -Wno-c99-designator -fcxx-exceptions -pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion
|
||||
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify=expected,cxx11_20,cxx11 -triple x86_64-linux -Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array -Wno-c99-designator -fcxx-exceptions -pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion
|
||||
|
||||
namespace StaticAssertFoldTest {
|
||||
|
||||
|
@ -1938,13 +1938,18 @@ namespace Lifetime {
|
|||
}
|
||||
|
||||
constexpr int &get(int &&n) { return n; }
|
||||
// cxx2b-error@-1 {{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
|
||||
// cxx2b-error@-2 {{no return statement in constexpr function}} See PR40598
|
||||
constexpr int &&get_rv(int &&n) { return static_cast<int&&>(n); }
|
||||
struct S {
|
||||
int &&r;
|
||||
int &s;
|
||||
int t;
|
||||
constexpr S() : r(get_rv(0)), s(get(0)), t(r) {} // expected-note {{read of object outside its lifetime}}
|
||||
constexpr S(int) : r(get_rv(0)), s(get(0)), t(s) {} // expected-note {{read of object outside its lifetime}}
|
||||
constexpr S(int) : r(get_rv(0)), s(get(0)), t(s) {}
|
||||
// cxx2b-warning@-1 {{reference 's' is not yet bound to a value when used here}}
|
||||
// cxx2b-note@-2 {{read of uninitialized object is not allowed in a constant expression}}
|
||||
// cxx11_20-note@-3 {{read of object outside its lifetime}}
|
||||
};
|
||||
constexpr int k1 = S().t; // expected-error {{constant expression}} expected-note {{in call}}
|
||||
constexpr int k2 = S(0).t; // expected-error {{constant expression}} expected-note {{in call}}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=expected,cxx20_2b %s -fcxx-exceptions -triple=x86_64-linux-gnu
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx20_2b %s -fcxx-exceptions -triple=x86_64-linux-gnu
|
||||
// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,cxx14 %s -fcxx-exceptions -triple=x86_64-linux-gnu
|
||||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=expected,cxx20_2b,cxx2b %s -fcxx-exceptions -triple=x86_64-linux-gnu
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_2b,cxx20 %s -fcxx-exceptions -triple=x86_64-linux-gnu
|
||||
// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,cxx14_20,cxx14 %s -fcxx-exceptions -triple=x86_64-linux-gnu
|
||||
|
||||
struct S {
|
||||
// dummy ctor to make this a literal type
|
||||
|
@ -269,16 +269,23 @@ namespace null {
|
|||
|
||||
namespace incdec {
|
||||
template<typename T> constexpr T &ref(T &&r) { return r; }
|
||||
// cxx2b-error@-1 {{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
|
||||
template<typename T> constexpr T postinc(T &&r) { return (r++, r); }
|
||||
template<typename T> constexpr T postdec(T &&r) { return (r--, r); }
|
||||
|
||||
template int &ref<int>(int &&);
|
||||
// cxx2b-note@-1 {{in instantiation of function template specialization}}
|
||||
|
||||
static_assert(postinc(0) == 1, "");
|
||||
static_assert(postdec(0) == -1, "");
|
||||
#if __cplusplus <= 202002L
|
||||
static_assert(++ref(0) == 1, "");
|
||||
static_assert(ref(0)++ == 0, "");
|
||||
static_assert(postinc(0) == 1, "");
|
||||
static_assert(--ref(0) == -1, "");
|
||||
static_assert(ref(0)-- == 0, "");
|
||||
static_assert(postdec(0) == -1, "");
|
||||
#endif
|
||||
|
||||
#if __cplusplus <= 202002L
|
||||
constexpr int overflow_int_inc_1 = ref(0x7fffffff)++; // expected-error {{constant}} expected-note {{2147483648}}
|
||||
constexpr int overflow_int_inc_1_ok = ref(0x7ffffffe)++;
|
||||
constexpr int overflow_int_inc_2 = ++ref(0x7fffffff); // expected-error {{constant}} expected-note {{2147483648}}
|
||||
|
@ -291,37 +298,42 @@ namespace incdec {
|
|||
// inc on bool sets to true
|
||||
static_assert(++ref(false), "");
|
||||
// cxx14-warning@-1 {{incrementing expression of type bool}}
|
||||
// cxx20_2b-error@-2 {{incrementing expression of type bool}}
|
||||
// cxx20-error@-2 {{incrementing expression of type bool}}
|
||||
static_assert(++ref(true), "");
|
||||
// cxx14-warning@-1 {{incrementing expression of type bool}}
|
||||
// cxx20_2b-error@-2 {{incrementing expression of type bool}}
|
||||
// cxx20-error@-2 {{incrementing expression of type bool}}
|
||||
#endif
|
||||
|
||||
int arr[10];
|
||||
static_assert(postinc(&arr[0]) == &arr[1], "");
|
||||
static_assert(postdec(&arr[1]) == &arr[0], "");
|
||||
#if __cplusplus <= 202002L
|
||||
static_assert(++ref(&arr[0]) == &arr[1], "");
|
||||
static_assert(++ref(&arr[9]) == &arr[10], "");
|
||||
static_assert(++ref(&arr[10]) == &arr[11], ""); // expected-error {{constant}} expected-note {{cannot refer to element 11}}
|
||||
static_assert(ref(&arr[0])++ == &arr[0], "");
|
||||
static_assert(ref(&arr[10])++ == &arr[10], ""); // expected-error {{constant}} expected-note {{cannot refer to element 11}}
|
||||
static_assert(postinc(&arr[0]) == &arr[1], "");
|
||||
static_assert(--ref(&arr[10]) == &arr[9], "");
|
||||
static_assert(--ref(&arr[1]) == &arr[0], "");
|
||||
static_assert(--ref(&arr[0]) != &arr[0], ""); // expected-error {{constant}} expected-note {{cannot refer to element -1}}
|
||||
static_assert(ref(&arr[1])-- == &arr[1], "");
|
||||
static_assert(ref(&arr[0])-- == &arr[0], ""); // expected-error {{constant}} expected-note {{cannot refer to element -1}}
|
||||
static_assert(postdec(&arr[1]) == &arr[0], "");
|
||||
#endif
|
||||
|
||||
static_assert(postinc(0.0) == 1.0, "");
|
||||
static_assert(postdec(0.0) == -1.0, "");
|
||||
#if __cplusplus <= 202002L
|
||||
int x;
|
||||
static_assert(++ref(&x) == &x + 1, "");
|
||||
|
||||
static_assert(++ref(0.0) == 1.0, "");
|
||||
static_assert(ref(0.0)++ == 0.0, "");
|
||||
static_assert(postinc(0.0) == 1.0, "");
|
||||
static_assert(--ref(0.0) == -1.0, "");
|
||||
static_assert(ref(0.0)-- == 0.0, "");
|
||||
static_assert(postdec(0.0) == -1.0, "");
|
||||
|
||||
static_assert(++ref(1e100) == 1e100, "");
|
||||
static_assert(--ref(1e100) == 1e100, "");
|
||||
#endif
|
||||
|
||||
union U {
|
||||
int a, b;
|
||||
|
@ -863,9 +875,13 @@ namespace VirtualFromBase {
|
|||
|
||||
namespace Lifetime {
|
||||
constexpr int &get(int &&r) { return r; }
|
||||
// cxx2b-error@-1 {{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
|
||||
// cxx2b-error@-2 {{no return statement in constexpr function}} See PR40598
|
||||
constexpr int f() {
|
||||
int &r = get(123);
|
||||
return r; // expected-note {{read of object outside its lifetime}}
|
||||
return r;
|
||||
// cxx2b-note@-1 {{use of reference outside its lifetime is not allowed in a constant expression}}
|
||||
// cxx14_20-note@-2 {{read of object outside its lifetime}}
|
||||
}
|
||||
static_assert(f() == 123, ""); // expected-error {{constant expression}} expected-note {{in call}}
|
||||
|
||||
|
|
|
@ -39,15 +39,14 @@ struct suspend_never {
|
|||
};
|
||||
|
||||
struct MoveOnly {
|
||||
MoveOnly() {};
|
||||
MoveOnly() = default;
|
||||
MoveOnly(const MoveOnly&) = delete;
|
||||
MoveOnly(MoveOnly&&) noexcept {};
|
||||
~MoveOnly() {};
|
||||
MoveOnly(MoveOnly &&) = default;
|
||||
};
|
||||
|
||||
struct NoCopyNoMove {
|
||||
NoCopyNoMove() = default;
|
||||
NoCopyNoMove(const NoCopyNoMove &) = delete; // expected-note 4{{'NoCopyNoMove' has been explicitly marked deleted here}}
|
||||
NoCopyNoMove(const NoCopyNoMove &) = delete;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
@ -63,13 +62,12 @@ struct task {
|
|||
|
||||
task<NoCopyNoMove> local2val() {
|
||||
NoCopyNoMove value;
|
||||
co_return value; // expected-error {{call to deleted constructor of 'NoCopyNoMove'}}
|
||||
// expected-error@-1 {{value reference to type 'NoCopyNoMove' cannot bind to lvalue of type 'NoCopyNoMove'}}
|
||||
co_return value;
|
||||
}
|
||||
|
||||
task<NoCopyNoMove &> local2ref() {
|
||||
NoCopyNoMove value;
|
||||
co_return value; // expected-error {{call to deleted constructor of 'NoCopyNoMove'}}
|
||||
co_return value; // expected-error {{non-const lvalue reference to type 'NoCopyNoMove' cannot bind to a temporary of type 'NoCopyNoMove'}}
|
||||
}
|
||||
|
||||
// We need the move constructor for construction of the coroutine.
|
||||
|
@ -82,8 +80,7 @@ task<NoCopyNoMove> lvalue2val(NoCopyNoMove &value) {
|
|||
}
|
||||
|
||||
task<NoCopyNoMove> rvalue2val(NoCopyNoMove &&value) {
|
||||
co_return value; // expected-error {{rvalue reference to type 'NoCopyNoMove' cannot bind to lvalue of type 'NoCopyNoMove'}}
|
||||
// expected-error@-1 {{call to deleted constructor of 'NoCopyNoMove'}}
|
||||
co_return value;
|
||||
}
|
||||
|
||||
task<NoCopyNoMove &> lvalue2ref(NoCopyNoMove &value) {
|
||||
|
@ -91,7 +88,7 @@ task<NoCopyNoMove &> lvalue2ref(NoCopyNoMove &value) {
|
|||
}
|
||||
|
||||
task<NoCopyNoMove &> rvalue2ref(NoCopyNoMove &&value) {
|
||||
co_return value; // expected-error {{call to deleted constructor of 'NoCopyNoMove'}}
|
||||
co_return value; // expected-error {{non-const lvalue reference to type 'NoCopyNoMove' cannot bind to a temporary of type 'NoCopyNoMove'}}
|
||||
}
|
||||
|
||||
struct To {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// This file contains references to sections of the Coroutines TS, which can be
|
||||
// found at http://wg21.link/coroutines.
|
||||
|
||||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=expected,cxx20_2b %s -fcxx-exceptions -fexceptions -Wunused-result
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx20_2b %s -fcxx-exceptions -fexceptions -Wunused-result
|
||||
// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -fsyntax-only -verify=expected %s -fcxx-exceptions -fexceptions -Wunused-result
|
||||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=expected,cxx20_2b,cxx2b %s -fcxx-exceptions -fexceptions -Wunused-result
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_2b %s -fcxx-exceptions -fexceptions -Wunused-result
|
||||
// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -fsyntax-only -verify=expected,cxx14_20 %s -fcxx-exceptions -fexceptions -Wunused-result
|
||||
|
||||
void no_coroutine_traits_bad_arg_await() {
|
||||
co_await a; // expected-error {{include <experimental/coroutine>}}
|
||||
|
@ -934,7 +934,8 @@ struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag2> {
|
|||
};
|
||||
|
||||
extern "C" int f(mismatch_gro_type_tag2) {
|
||||
// expected-error@-1 {{cannot initialize return object of type 'int' with an lvalue of type 'void *'}}
|
||||
// cxx2b-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void *'}}
|
||||
// cxx14_20-error@-2 {{cannot initialize return object of type 'int' with an lvalue of type 'void *'}}
|
||||
co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=expected,cxx20_2b %s
|
||||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=expected,cxx20_2b %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
|
||||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=expected,cxx20_2b,cxx2b %s
|
||||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=expected,cxx20_2b,cxx2b %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
|
||||
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx20_2b %s
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx20_2b %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_2b %s
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_2b %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
|
||||
|
||||
// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,cxx14 %s
|
||||
// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,cxx14 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
|
||||
// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,cxx14_20,cxx14 %s
|
||||
// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,cxx14_20,cxx14 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
|
||||
|
||||
auto f(); // expected-note {{previous}}
|
||||
int f(); // expected-error {{differ only in their return type}}
|
||||
|
@ -129,10 +129,14 @@ namespace Templates {
|
|||
return T() + 1;
|
||||
}
|
||||
template<typename T> auto &f2(T &&v) { return v; }
|
||||
// cxx2b-error@-1 {{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
|
||||
// cxx2b-error@-2 {{non-const lvalue reference to type 'double' cannot bind to a temporary of type 'double'}}
|
||||
// cxx2b-note@-3 {{candidate template ignored: substitution failure [with T = double]}}
|
||||
int a = f1<int>();
|
||||
const int &b = f2(0);
|
||||
const int &b = f2(0); // cxx2b-note {{in instantiation of function template specialization 'Templates::f2<int>' requested here}}
|
||||
double d;
|
||||
float &c = f2(0.0); // expected-error {{non-const lvalue reference to type 'float' cannot bind to a value of unrelated type 'double'}}
|
||||
// cxx2b-note@-1 {{in instantiation of function template specialization 'Templates::f2<double>' requested here}}
|
||||
|
||||
template<typename T> auto fwd_decl(); // expected-note {{declared here}}
|
||||
int e = fwd_decl<int>(); // expected-error {{cannot be used before it is defined}}
|
||||
|
@ -145,8 +149,9 @@ namespace Templates {
|
|||
auto (*p)() = f1; // expected-error {{incompatible initializer}}
|
||||
auto (*q)() = f1<int>; // ok
|
||||
|
||||
typedef decltype(f2(1.2)) dbl; // expected-note {{previous}}
|
||||
typedef float dbl; // expected-error {{typedef redefinition with different types ('float' vs 'decltype(f2(1.2))' (aka 'double &'))}}
|
||||
typedef decltype(f2(1.2)) dbl; // cxx14_20-note {{previous}}
|
||||
// cxx2b-error@-1 {{no matching function for call to 'f2'}}
|
||||
typedef float dbl; // cxx14_20-error {{typedef redefinition with different types ('float' vs 'decltype(f2(1.2))' (aka 'double &'))}}
|
||||
|
||||
extern template auto fwd_decl<double>();
|
||||
int k1 = fwd_decl<double>();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=expected %s
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected %s
|
||||
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify=expected,cxx11 %s
|
||||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=expected,cxx2b %s
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx11_20 %s
|
||||
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify=expected,cxx11_20,cxx11 %s
|
||||
|
||||
int* ret_local() {
|
||||
int x = 1;
|
||||
|
@ -29,7 +29,8 @@ int* ret_local_array_element_const_index() {
|
|||
|
||||
int& ret_local_ref() {
|
||||
int x = 1;
|
||||
return x; // expected-warning {{reference to stack memory}}
|
||||
return x; // cxx11_20-warning {{reference to stack memory}}
|
||||
// cxx2b-error@-1 {{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
|
||||
}
|
||||
|
||||
int* ret_local_addrOf() {
|
||||
|
@ -154,8 +155,10 @@ void ret_from_lambda() {
|
|||
(void) [&]() -> int& { return b; };
|
||||
(void) [=]() mutable -> int& { return a; };
|
||||
(void) [=]() mutable -> int& { return b; };
|
||||
(void) [&]() -> int& { int a; return a; }; // expected-warning {{reference to stack}}
|
||||
(void) [=]() -> int& { int a; return a; }; // expected-warning {{reference to stack}}
|
||||
(void) [&]() -> int& { int a; return a; }; // cxx11_20-warning {{reference to stack}}
|
||||
// cxx2b-error@-1 {{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
|
||||
(void) [=]() -> int& { int a; return a; }; // cxx11_20-warning {{reference to stack}}
|
||||
// cxx2b-error@-1 {{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
|
||||
(void) [&]() -> int& { int &a = b; return a; };
|
||||
(void) [=]() mutable -> int& { int &a = b; return a; };
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=cxx20_2b -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++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
|
||||
|
@ -217,8 +217,8 @@ ConvertFromBase testRParam6(Derived&& d) {
|
|||
}
|
||||
|
||||
// But if the return type is a reference type, then moving would be wrong.
|
||||
Derived& testRetRef1(Derived&& d) { return d; }
|
||||
Base& testRetRef2(Derived&& d) { return d; }
|
||||
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); }
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fobjc-arc -fblocks -verify=cxx98_20,cxx20 %s
|
||||
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fobjc-arc -fblocks -verify=cxx98_20,cxx98_11 %s
|
||||
// RUN: %clang_cc1 -std=c++98 -fsyntax-only -fobjc-arc -fblocks -Wno-c++11-extensions -verify=cxx98_20,cxx98_11 %s
|
||||
// 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
|
||||
|
||||
#define TEST(T) void test_##T() { \
|
||||
__block T x; \
|
||||
|
@ -8,17 +9,17 @@
|
|||
}
|
||||
|
||||
struct CopyOnly {
|
||||
CopyOnly();
|
||||
CopyOnly(CopyOnly &);
|
||||
CopyOnly(); // cxx2b-note {{not viable}}
|
||||
CopyOnly(CopyOnly &); // cxx2b-note {{not viable}}
|
||||
};
|
||||
TEST(CopyOnly);
|
||||
TEST(CopyOnly); // cxx2b-error {{no matching constructor}}
|
||||
|
||||
struct CopyNoMove {
|
||||
CopyNoMove();
|
||||
CopyNoMove(CopyNoMove &);
|
||||
CopyNoMove(CopyNoMove &&) = delete; // cxx98_20-note {{marked deleted here}}
|
||||
CopyNoMove(CopyNoMove &&) = delete; // cxx98_2b-note {{marked deleted here}}
|
||||
};
|
||||
TEST(CopyNoMove); // cxx98_20-error {{call to deleted constructor}}
|
||||
TEST(CopyNoMove); // cxx98_2b-error {{call to deleted constructor}}
|
||||
|
||||
struct MoveOnly {
|
||||
MoveOnly();
|
||||
|
@ -30,9 +31,9 @@ TEST(MoveOnly);
|
|||
struct NoCopyNoMove {
|
||||
NoCopyNoMove();
|
||||
NoCopyNoMove(NoCopyNoMove &) = delete;
|
||||
NoCopyNoMove(NoCopyNoMove &&) = delete; // cxx98_20-note {{marked deleted here}}
|
||||
NoCopyNoMove(NoCopyNoMove &&) = delete; // cxx98_2b-note {{marked deleted here}}
|
||||
};
|
||||
TEST(NoCopyNoMove); // cxx98_20-error {{call to deleted constructor}}
|
||||
TEST(NoCopyNoMove); // cxx98_2b-error {{call to deleted constructor}}
|
||||
|
||||
struct ConvertingRVRef {
|
||||
ConvertingRVRef();
|
||||
|
@ -50,11 +51,11 @@ struct ConvertingCLVRef {
|
|||
ConvertingCLVRef(ConvertingCLVRef &);
|
||||
|
||||
struct X {};
|
||||
ConvertingCLVRef(X &&); // cxx20-note {{passing argument to parameter here}}
|
||||
ConvertingCLVRef(X &&); // cxx20_2b-note {{passing argument to parameter here}}
|
||||
operator X() const &;
|
||||
operator X() && = delete; // cxx20-note {{marked deleted here}}
|
||||
operator X() && = delete; // cxx20_2b-note {{marked deleted here}}
|
||||
};
|
||||
TEST(ConvertingCLVRef); // cxx20-error {{invokes a deleted function}}
|
||||
TEST(ConvertingCLVRef); // cxx20_2b-error {{invokes a deleted function}}
|
||||
|
||||
struct SubSubMove {};
|
||||
struct SubMove : SubSubMove {
|
||||
|
|
|
@ -1278,6 +1278,11 @@ C++20, informally referred to as C++2b.</p>
|
|||
<td><a href="https://wg21.link/p1102r2">P1102R2</a></td>
|
||||
<td class="unreleased" align="center">Clang 13</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Simpler implicit move</td>
|
||||
<td><a href="https://wg21.link/p2266r1">P2266R1</a></td>
|
||||
<td class="unreleased" align="center">Clang 13</td>
|
||||
</tr>
|
||||
</table>
|
||||
</details>
|
||||
|
||||
|
|
Loading…
Reference in New Issue