constexpr: initialization of a union from an empty initializer-list should
zero-initialize the first union member. Also fix a bug where initializing an array of types compatible with wchar_t from a wide string literal failed in C, and fortify the C++ tests in this area. This part can't be tested without a code change to enable array evaluation in C (where an existing test fails). llvm-svn: 148035
This commit is contained in:
parent
0014e38a8b
commit
9eae723c18
|
@ -3015,14 +3015,20 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
|
|||
const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD);
|
||||
|
||||
if (RD->isUnion()) {
|
||||
Result = APValue(E->getInitializedFieldInUnion());
|
||||
if (!E->getNumInits())
|
||||
const FieldDecl *Field = E->getInitializedFieldInUnion();
|
||||
Result = APValue(Field);
|
||||
if (!Field)
|
||||
return true;
|
||||
|
||||
// If the initializer list for a union does not contain any elements, the
|
||||
// first element of the union is value-initialized.
|
||||
ImplicitValueInitExpr VIE(Field->getType());
|
||||
const Expr *InitExpr = E->getNumInits() ? E->getInit(0) : &VIE;
|
||||
|
||||
LValue Subobject = This;
|
||||
HandleLValueMember(Info, E->getInit(0), Subobject,
|
||||
E->getInitializedFieldInUnion(), &Layout);
|
||||
HandleLValueMember(Info, InitExpr, Subobject, Field, &Layout);
|
||||
return EvaluateConstantExpression(Result.getUnionValue(), Info,
|
||||
Subobject, E->getInit(0));
|
||||
Subobject, InitExpr);
|
||||
}
|
||||
|
||||
assert((!isa<CXXRecordDecl>(RD) || !cast<CXXRecordDecl>(RD)->getNumBases()) &&
|
||||
|
@ -3065,6 +3071,10 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
|
|||
const CXXConstructorDecl *FD = E->getConstructor();
|
||||
bool ZeroInit = E->requiresZeroInitialization();
|
||||
if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) {
|
||||
// If we've already performed zero-initialization, we're already done.
|
||||
if (!Result.isUninit())
|
||||
return true;
|
||||
|
||||
if (ZeroInit)
|
||||
return ZeroInitialization(E);
|
||||
|
||||
|
@ -3391,7 +3401,7 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
|
|||
|
||||
// C++11 [dcl.init.string]p1: A char array [...] can be initialized by [...]
|
||||
// an appropriately-typed string literal enclosed in braces.
|
||||
if (E->getNumInits() == 1 && CAT->getElementType()->isAnyCharacterType() &&
|
||||
if (E->getNumInits() == 1 && E->getInit(0)->isGLValue() &&
|
||||
Info.Ctx.hasSameUnqualifiedType(E->getType(), E->getInit(0)->getType())) {
|
||||
LValue LV;
|
||||
if (!EvaluateLValue(E->getInit(0), LV, Info))
|
||||
|
@ -3446,7 +3456,9 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
|
|||
if (!CAT)
|
||||
return Error(E);
|
||||
|
||||
Result = APValue(APValue::UninitArray(), 0, CAT->getSize().getZExtValue());
|
||||
bool HadZeroInit = !Result.isUninit();
|
||||
if (!HadZeroInit)
|
||||
Result = APValue(APValue::UninitArray(), 0, CAT->getSize().getZExtValue());
|
||||
if (!Result.hasArrayFiller())
|
||||
return true;
|
||||
|
||||
|
@ -3454,6 +3466,9 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
|
|||
|
||||
bool ZeroInit = E->requiresZeroInitialization();
|
||||
if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) {
|
||||
if (HadZeroInit)
|
||||
return true;
|
||||
|
||||
if (ZeroInit) {
|
||||
LValue Subobject = This;
|
||||
Subobject.addArray(Info, E, CAT);
|
||||
|
@ -3485,7 +3500,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
|
|||
LValue Subobject = This;
|
||||
Subobject.addArray(Info, E, CAT);
|
||||
|
||||
if (ZeroInit) {
|
||||
if (ZeroInit && !HadZeroInit) {
|
||||
ImplicitValueInitExpr VIE(CAT->getElementType());
|
||||
if (!EvaluateConstantExpression(Result.getArrayFiller(), Info, Subobject,
|
||||
&VIE))
|
||||
|
|
|
@ -5,3 +5,15 @@ extern char x1[6];
|
|||
|
||||
char x2[] = "hello";
|
||||
extern char x2[6];
|
||||
|
||||
char x3[] = { "hello" };
|
||||
extern char x3[6];
|
||||
|
||||
wchar_t x4[](L"hello");
|
||||
extern wchar_t x4[6];
|
||||
|
||||
wchar_t x5[] = L"hello";
|
||||
extern wchar_t x5[6];
|
||||
|
||||
wchar_t x6[] = { L"hello" };
|
||||
extern wchar_t x6[6];
|
||||
|
|
|
@ -357,6 +357,8 @@ constexpr int MangleChars(const Char *p) {
|
|||
}
|
||||
|
||||
static_assert(MangleChars("constexpr!") == 1768383, "");
|
||||
static_assert(MangleChars(u8"constexpr!") == 1768383, "");
|
||||
static_assert(MangleChars(L"constexpr!") == 1768383, "");
|
||||
static_assert(MangleChars(u"constexpr!") == 1768383, "");
|
||||
static_assert(MangleChars(U"constexpr!") == 1768383, "");
|
||||
|
||||
|
@ -404,6 +406,12 @@ static_assert(t.c[4] == 0, "");
|
|||
static_assert(t.c[5] == 0, "");
|
||||
static_assert(t.c[6] == 0, ""); // expected-error {{constant expression}} expected-note {{one-past-the-end}}
|
||||
|
||||
struct U {
|
||||
wchar_t chars[6];
|
||||
int n;
|
||||
} constexpr u = { { L"test" }, 0 };
|
||||
static_assert(u.chars[2] == L's', "");
|
||||
|
||||
}
|
||||
|
||||
namespace Array {
|
||||
|
@ -726,6 +734,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, "");
|
||||
|
||||
constexpr U v = {};
|
||||
static_assert(v.a == 0, "");
|
||||
|
||||
union Empty {};
|
||||
constexpr Empty e = {};
|
||||
|
||||
// Make sure we handle trivial copy constructors for unions.
|
||||
constexpr U x = {42};
|
||||
constexpr U y = x;
|
||||
|
|
Loading…
Reference in New Issue