Skip to content

Commit

Permalink
Improve diagnostic when constant-evaluating a std::initializer_list with
Browse files Browse the repository at this point in the history
an unexpected form.
  • Loading branch information
zygoloid committed Apr 15, 2020
1 parent 592d8e7 commit 57acbae
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 5 deletions.
16 changes: 11 additions & 5 deletions clang/lib/AST/ExprConstant.cpp
Expand Up @@ -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(),
Expand All @@ -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;
}
Expand Down
11 changes: 11 additions & 0 deletions clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
Expand Up @@ -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}}
}

0 comments on commit 57acbae

Please sign in to comment.