Commit 981af4f4 authored by Jenkins CI's avatar Jenkins CI
Browse files

Merge remote-tracking branch 'downstream/master' into EPI

parents d427efb7 933e232a
......@@ -1535,8 +1535,7 @@ defm vrgatherei16 : RVVOutBuiltinSet<"vrgatherei16_vv", "csil",
let HasMask = false,
ManualCodegen = [{
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 3);
ID = Intrinsic::riscv_vcompress;
IntrinsicTypes = {ResultType, Ops[3]->getType()};
IntrinsicTypes = {ResultType, Ops[3]->getType()};
}] in {
// signed and floating type
defm vcompress : RVVOutBuiltinSet<"vcompress", "csilfd",
......
......@@ -3455,6 +3455,12 @@ public:
bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
bool isSameOrCompatibleFunctionType(CanQualType Param, CanQualType Arg);
 
ExprResult PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
const VarDecl *NRVOCandidate,
QualType ResultType,
Expr *Value,
bool AllowNRVO = true);
bool CanPerformAggregateInitializationForOverloadResolution(
const InitializedEntity &Entity, InitListExpr *From);
 
......@@ -4754,30 +4760,28 @@ public:
SourceLocation Loc,
unsigned NumParams);
 
struct NamedReturnInfo {
const VarDecl *Candidate;
enum Status : uint8_t { None, MoveEligible, MoveEligibleAndCopyElidable };
Status S;
bool isMoveEligible() const { return S != None; };
bool isCopyElidable() const { return S == MoveEligibleAndCopyElidable; }
enum CopyElisionSemanticsKind {
CES_Strict = 0,
CES_AllowParameters = 1,
CES_AllowDifferentTypes = 2,
CES_AllowExceptionVariables = 4,
CES_AllowRValueReferenceType = 8,
CES_ImplicitlyMovableCXX11CXX14CXX17 =
(CES_AllowParameters | CES_AllowDifferentTypes),
CES_ImplicitlyMovableCXX20 =
(CES_AllowParameters | CES_AllowDifferentTypes |
CES_AllowExceptionVariables | CES_AllowRValueReferenceType),
};
NamedReturnInfo getNamedReturnInfo(Expr *&E, bool ForceCXX2b = false);
NamedReturnInfo getNamedReturnInfo(const VarDecl *VD,
bool ForceCXX20 = false);
const VarDecl *getCopyElisionCandidate(NamedReturnInfo &Info,
QualType ReturnType);
 
ExprResult PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
const NamedReturnInfo &NRInfo,
Expr *Value);
VarDecl *getCopyElisionCandidate(QualType ReturnType, Expr *E,
CopyElisionSemanticsKind CESK);
bool isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
CopyElisionSemanticsKind CESK);
 
StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
Scope *CurScope);
StmtResult BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp);
StmtResult ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
NamedReturnInfo &NRInfo);
StmtResult ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp);
 
StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
bool IsVolatile, unsigned NumOutputs,
......
......@@ -1949,10 +1949,9 @@ 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.PerformCopyInitialization(
InitializedEntity::InitializeBlock(Loc, T, false), SourceLocation(),
VarRef);
ExprResult Result = S.PerformMoveOrCopyInitialization(
InitializedEntity::InitializeBlock(Loc, T, false), VD, VD->getType(),
VarRef, /*AllowNRVO=*/true);
if (!Result.isInvalid()) {
Result = S.MaybeCreateExprWithCleanups(Result);
Expr *Init = Result.getAs<Expr>();
......
......@@ -994,10 +994,26 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E,
E = R.get();
}
// Move the return value if we can
if (E) {
const VarDecl *NRVOCandidate = this->getCopyElisionCandidate(
E->getType(), E, CES_ImplicitlyMovableCXX20);
if (NRVOCandidate) {
InitializedEntity Entity =
InitializedEntity::InitializeResult(Loc, E->getType(), NRVOCandidate);
ExprResult MoveResult = this->PerformMoveOrCopyInitialization(
Entity, NRVOCandidate, E->getType(), 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();
......@@ -1554,7 +1570,7 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
// Trigger a nice error message.
InitializedEntity Entity =
InitializedEntity::InitializeResult(Loc, FnRetType, false);
S.PerformCopyInitialization(Entity, SourceLocation(), ReturnValue);
S.PerformMoveOrCopyInitialization(Entity, nullptr, FnRetType, ReturnValue);
noteMemberDeclaredHere(S, ReturnValue, Fn);
return false;
}
......@@ -1570,8 +1586,8 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
return false;
InitializedEntity Entity = InitializedEntity::InitializeVariable(GroDecl);
ExprResult Res =
S.PerformCopyInitialization(Entity, SourceLocation(), ReturnValue);
ExprResult Res = S.PerformMoveOrCopyInitialization(Entity, nullptr, GroType,
this->ReturnValue);
if (Res.isInvalid())
return false;
......
......@@ -854,6 +854,10 @@ 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.
......@@ -869,17 +873,15 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
// operation from the operand to the exception object (15.1) can be
// omitted by constructing the automatic object directly into the
// exception object
NamedReturnInfo NRInfo =
IsThrownVarInScope ? getNamedReturnInfo(Ex) : NamedReturnInfo();
QualType ExceptionObjectTy = Context.getExceptionObjectType(Ex->getType());
if (CheckCXXThrowOperand(OpLoc, ExceptionObjectTy, Ex))
return ExprError();
const VarDecl *NRVOVariable = nullptr;
if (IsThrownVarInScope)
NRVOVariable = getCopyElisionCandidate(QualType(), Ex, CES_Strict);
InitializedEntity Entity = InitializedEntity::InitializeException(
OpLoc, ExceptionObjectTy,
/*NRVO=*/NRInfo.isCopyElidable());
ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRInfo, Ex);
/*NRVO=*/NRVOVariable != nullptr);
ExprResult Res = PerformMoveOrCopyInitialization(
Entity, NRVOVariable, QualType(), Ex, IsThrownVarInScope);
if (Res.isInvalid())
return ExprError();
Ex = Res.get();
......
This diff is collapsed.
......@@ -23,7 +23,6 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateInstCallback.h"
......@@ -1086,30 +1085,11 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, Owner,
StartingScope, InstantiatingVarTemplate);
if (D->isNRVOVariable()) {
QualType FT;
if (auto *F = dyn_cast<FunctionDecl>(DC))
FT = F->getType();
else if (isa<BlockDecl>(DC))
FT = SemaRef.getCurBlock()->FunctionType;
else
llvm_unreachable("Unknown context type");
// This is the last chance we have of checking copy elision eligibility
// for functions in depdendent contexts. The sema actions for building
// the return statement during template instantiation will have no effect
// regarding copy elision, since NRVO propagation runs on the scope exit
// actions, and these are not run on instantiation.
// This might run through some VarDecls which were returned from non-taken
// 'if constexpr' branches, and these will end up being constructed on the
// return slot even if they will never be returned, as a sort of accidental
// 'optimization'. Notably, functions with 'auto' return types won't have it
// deduced by this point. Coupled with the limitation described
// previously, this makes it very hard to support copy elision for these.
Sema::NamedReturnInfo Info = SemaRef.getNamedReturnInfo(Var);
bool NRVO = SemaRef.getCopyElisionCandidate(
Info, cast<FunctionType>(FT)->getReturnType()) != nullptr;
Var->setNRVOVariable(NRVO);
QualType ReturnType = cast<FunctionDecl>(DC)->getReturnType();
if (SemaRef.isCopyElisionCandidate(ReturnType, Var, Sema::CES_Strict))
Var->setNRVOVariable(true);
}
Var->setImplicit(D->isImplicit());
......
......@@ -8967,10 +8967,6 @@ 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:
......@@ -8981,7 +8977,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>(IDExpr))
if (const auto *SNTTPE = dyn_cast<SubstNonTypeTemplateParmExpr>(E))
return SNTTPE->getParameterType(S.Context);
// - if e is an unparenthesized id-expression or an unparenthesized class
......@@ -8990,22 +8986,21 @@ 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>(IDExpr)) {
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
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>(IDExpr)) {
} else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
if (const ValueDecl *VD = ME->getMemberDecl())
if (isa<FieldDecl>(VD) || isa<VarDecl>(VD))
return VD->getType();
} else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(IDExpr)) {
} else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(E)) {
return IR->getDecl()->getType();
} else if (const ObjCPropertyRefExpr *PR =
dyn_cast<ObjCPropertyRefExpr>(IDExpr)) {
} else if (const ObjCPropertyRefExpr *PR = dyn_cast<ObjCPropertyRefExpr>(E)) {
if (PR->isExplicitProperty())
return PR->getExplicitProperty()->getType();
} else if (auto *PE = dyn_cast<PredefinedExpr>(IDExpr)) {
} else if (auto *PE = dyn_cast<PredefinedExpr>(E)) {
return PE->getType();
}
......@@ -9018,8 +9013,8 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
// entity.
using namespace sema;
if (S.getCurLambda()) {
if (isa<ParenExpr>(IDExpr)) {
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(IDExpr->IgnoreParens())) {
if (isa<ParenExpr>(E)) {
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
QualType T = S.getCapturedDeclRefType(Var, DRE->getLocation());
if (!T.isNull())
......
// 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,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
namespace test_delete_function {
struct A1 {
......@@ -409,10 +409,8 @@ Target t4() {
namespace test_simpler_implicit_move {
struct 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}}
CopyOnly();
CopyOnly(CopyOnly &);
};
struct MoveOnly {
MoveOnly();
......@@ -421,7 +419,7 @@ struct MoveOnly {
MoveOnly &&rref();
MoveOnly &&test1(MoveOnly &&w) {
return w; // cxx11_20-error {{cannot bind to lvalue of type}}
return w; // expected-error {{cannot bind to lvalue of type}}
}
CopyOnly test2(bool b) {
......@@ -430,22 +428,22 @@ CopyOnly test2(bool b) {
if (b) {
return w1;
} else {
return w2; // cxx2b-error {{no matching constructor for initialization}}
return w2;
}
}
template <class T> T &&test3(T &&x) { return x; } // cxx11_20-error {{cannot bind to lvalue of type}}
template <class T> T &&test3(T &&x) { return x; } // expected-error {{cannot bind to lvalue of type}}
template MoveOnly& test3<MoveOnly&>(MoveOnly&);
template MoveOnly &&test3<MoveOnly>(MoveOnly &&); // cxx11_20-note {{in instantiation of function template specialization}}
template MoveOnly&& test3<MoveOnly>(MoveOnly&&); // expected-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; // expected-error {{cannot bind to lvalue of type}}
}
void test5() try {
CopyOnly x;
throw x; // cxx2b-error {{no matching constructor for initialization}}
throw x;
} catch (...) {
}
......
// 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
// 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
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); // cxx2b-note {{previous definition is here}}
using IntLRef = decltype(x4d);
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)); // cxx2b-error {{type alias redefinition with different types ('decltype(f3d(0))' (aka 'int &&') vs 'decltype(x4d)' (aka 'int &'))}}
using IntLRef = decltype(f3d(0));
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; } // cxx14_20-error {{rvalue reference to type 'int' cannot bind to lvalue}}
decltype(auto) f5dd(int n) { decltype(auto) x = f(); return x; } // expected-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));
......
// 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
// 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
namespace dr300 { // dr300: yes
template<typename R, typename A> void f(R (&)(A)) {}
......@@ -628,8 +628,7 @@ namespace dr349 { // dr349: no
struct A {
template <class T> operator T ***() {
int ***p = 0;
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 ***'}}
return p; // expected-error {{cannot initialize return object of type 'const int ***' with an lvalue of type 'int ***'}}
}
};
......
// 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
// 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
int a;
int &b = [] (int &r) -> decltype(auto) { return r; } (a);
......@@ -9,15 +9,13 @@ 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; }; //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 MRef = [](auto b) -> auto& { return b; }; //expected-warning{{reference to stack}}
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);
......
// 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
// 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
struct A {
template <class T> operator T*();
......@@ -67,10 +67,8 @@ struct X0 {
template<typename T> operator const T*() const {
T x = T();
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'}}
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'}}
}
};
......
......@@ -29,6 +29,8 @@ L(2, t, X&);
// CHECK-LABEL: define{{.*}} void @_Z2l3v
// CHECK: call {{.*}} @_ZN1XC1Ev
// CHECK-NEXT: call {{.*}} @_ZN1XC1EOS_
// CHECK-NEXT: call void @llvm.lifetime.end
// CHECK-NEXT: call void @llvm.lifetime.end
// CHECK-NEXT: ret void
L(3, t, T);
......@@ -150,11 +152,7 @@ F(8, (t), decltype(auto));
}; }()(); \
}
// CHECK-LABEL: define{{.*}} void @_Z2b1v
// CHECK: call {{.*}} @_ZN1XC1Ev
// CHECK-NEXT: call void @llvm.lifetime.end
// CHECK-NEXT: ret void
B(1, X);
//B(1, X); // Uncomment this line at your own peril ;)
// CHECK-LABEL: define{{.*}} void @_Z2b2v
// CHECK: call {{.*}} @_ZN1XC1Ev
......@@ -166,6 +164,8 @@ B(2, X&);
// CHECK-LABEL: define{{.*}} void @_Z2b3v
// CHECK: call {{.*}} @_ZN1XC1Ev
// CHECK-NEXT: call {{.*}} @_ZN1XC1EOS_
// CHECK-NEXT: call void @llvm.lifetime.end
// CHECK-NEXT: call void @llvm.lifetime.end
// CHECK-NEXT: ret void
B(3, T);
......
// 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
// 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
namespace StaticAssertFoldTest {
......@@ -1938,18 +1938,13 @@ 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) {}
// 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 S(int) : r(get_rv(0)), s(get(0)), t(s) {} // expected-note {{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}}
......
// 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
// 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
struct S {
// dummy ctor to make this a literal type
......@@ -269,23 +269,16 @@ 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, "");
#endif
static_assert(postdec(0) == -1, "");
#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}}
......@@ -298,42 +291,37 @@ namespace incdec {
// inc on bool sets to true
static_assert(++ref(false), "");
// cxx14-warning@-1 {{incrementing expression of type bool}}
// cxx20-error@-2 {{incrementing expression of type bool}}
// cxx20_2b-error@-2 {{incrementing expression of type bool}}
static_assert(++ref(true), "");
// cxx14-warning@-1 {{incrementing expression of type bool}}
// cxx20-error@-2 {{incrementing expression of type bool}}
#endif
// cxx20_2b-error@-2 {{incrementing expression of type bool}}
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}}
#endif
static_assert(postdec(&arr[1]) == &arr[0], "");
static_assert(postinc(0.0) == 1.0, "");
static_assert(postdec(0.0) == -1.0, "");
#if __cplusplus <= 202002L
int x;