Improve diagnostic when constant-evaluating a std::initializer_list with

an unexpected form.
This commit is contained in:
Richard Smith 2020-04-15 13:23:56 -07:00
parent 592d8e7d75
commit 57acbaece1
2 changed files with 22 additions and 5 deletions

View File

@ -9338,24 +9338,30 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr(
// Get a pointer to the first element of the array.
Array.addArray(Info, E, ArrayType);
auto InvalidType = [&] {
Info.FFDiag(E, diag::note_constexpr_unsupported_layout)
<< E->getType();
return false;
};
// FIXME: Perform the checks on the field types in SemaInit.
RecordDecl *Record = E->getType()->castAs<RecordType>()->getDecl();
RecordDecl::field_iterator Field = Record->field_begin();
if (Field == Record->field_end())
return Error(E);
return InvalidType();
// Start pointer.
if (!Field->getType()->isPointerType() ||
!Info.Ctx.hasSameType(Field->getType()->getPointeeType(),
ArrayType->getElementType()))
return Error(E);
return InvalidType();
// FIXME: What if the initializer_list type has base classes, etc?
Result = APValue(APValue::UninitStruct(), 0, 2);
Array.moveInto(Result.getStructField(0));
if (++Field == Record->field_end())
return Error(E);
return InvalidType();
if (Field->getType()->isPointerType() &&
Info.Ctx.hasSameType(Field->getType()->getPointeeType(),
@ -9370,10 +9376,10 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr(
// Length.
Result.getStructField(1) = APValue(APSInt(ArrayType->getSize()));
else
return Error(E);
return InvalidType();
if (++Field != Record->field_end())
return Error(E);
return InvalidType();
return true;
}

View File

@ -365,3 +365,14 @@ namespace designated_init {
static_assert(c.size() == 5, "");
static_assert(d.size() == 1, "");
}
namespace weird_initlist {
struct weird {};
}
template<> struct std::initializer_list<weird_initlist::weird> { int a, b, c; };
namespace weird_initlist {
// We don't check the struct layout in Sema.
auto x = {weird{}, weird{}, weird{}, weird{}, weird{}};
// ... but we do in constant evaluation.
constexpr auto y = {weird{}, weird{}, weird{}, weird{}, weird{}}; // expected-error {{constant}} expected-note {{type 'const std::initializer_list<weird_initlist::weird>' has unexpected layout}}
}