forked from OSchip/llvm-project
PR11724: Implement evaluation for constexpr defaulted trivial union copy/move
constructors. These are a special case whose behavior cannot be modeled as a user-written constructor. llvm-svn: 147839
This commit is contained in:
parent
f714d3d7f2
commit
1bc5c2c7ef
|
@ -1854,8 +1854,22 @@ static bool HandleConstructorCall(const Expr *CallExpr, const LValue &This,
|
|||
return EvaluateConstantExpression(Result, Info, This, (*I)->getInit());
|
||||
}
|
||||
|
||||
// Reserve space for the struct members.
|
||||
// For a trivial copy or move constructor, perform an APValue copy. This is
|
||||
// essential for unions, where the operations performed by the constructor
|
||||
// cannot be represented by ctor-initializers.
|
||||
const CXXRecordDecl *RD = Definition->getParent();
|
||||
if (Definition->isDefaulted() &&
|
||||
((Definition->isCopyConstructor() && RD->hasTrivialCopyConstructor()) ||
|
||||
(Definition->isMoveConstructor() && RD->hasTrivialMoveConstructor()))) {
|
||||
LValue RHS;
|
||||
RHS.setFrom(ArgValues[0]);
|
||||
CCValue Value;
|
||||
return HandleLValueToRValueConversion(Info, Args[0], Args[0]->getType(),
|
||||
RHS, Value) &&
|
||||
CheckConstantExpression(Info, CallExpr, Value, Result);
|
||||
}
|
||||
|
||||
// Reserve space for the struct members.
|
||||
if (!RD->isUnion() && Result.isUninit())
|
||||
Result = APValue(APValue::UninitStruct(), RD->getNumBases(),
|
||||
std::distance(RD->field_begin(), RD->field_end()));
|
||||
|
@ -3073,7 +3087,7 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
|
|||
if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition))
|
||||
return false;
|
||||
|
||||
// FIXME: Elide the copy/move construction wherever we can.
|
||||
// Avoid materializing a temporary for an elidable copy/move constructor.
|
||||
if (E->isElidable() && !ZeroInit)
|
||||
if (const MaterializeTemporaryExpr *ME
|
||||
= dyn_cast<MaterializeTemporaryExpr>(E->getArg(0)))
|
||||
|
|
|
@ -726,6 +726,12 @@ static_assert((&u[1].b)[1] == 2, ""); // expected-error {{constant expression}}
|
|||
static_assert(*(&(u[1].b) + 1 + 1) == 3, ""); // expected-error {{constant expression}} expected-note {{cannot refer to element 2 of non-array object}}
|
||||
static_assert((&(u[1]) + 1 + 1)->b == 3, "");
|
||||
|
||||
// Make sure we handle trivial copy constructors for unions.
|
||||
constexpr U x = {42};
|
||||
constexpr U y = x;
|
||||
static_assert(y.a == 42, "");
|
||||
static_assert(y.b == 42, ""); // expected-error {{constant expression}} expected-note {{'b' of union with active member 'a'}}
|
||||
|
||||
}
|
||||
|
||||
namespace MemberPointer {
|
||||
|
|
Loading…
Reference in New Issue