forked from OSchip/llvm-project
Improve diagnostic when constant-evaluating a std::initializer_list with
an unexpected form.
This commit is contained in:
parent
592d8e7d75
commit
57acbaece1
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue