Skip to content

Commit ed95059

Browse files
committed
Check for polymorphic types and bases
1 parent b664217 commit ed95059

File tree

4 files changed

+40
-21
lines changed

4 files changed

+40
-21
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12210,7 +12210,7 @@ def err_std_source_location_impl_malformed : Error<
1221012210
"'std::source_location::__impl' must be standard-layout and have only two 'const char *' fields '_M_file_name' and '_M_function_name', and two integral fields '_M_line' and '_M_column'">;
1221112211

1221212212
def err_std_initializer_list_malformed : Error<
12213-
"%0 layout not recognized. Must be a struct with two fields, a 'const E *' and either another 'const E *' or a 'std::size_t'">;
12213+
"%0 layout not recognized. Must be a non-polymorphic class type with no bases and two fields: a 'const E *' and either another 'const E *' or a 'std::size_t'">;
1221412214

1221512215
// HLSL Diagnostics
1221612216
def err_hlsl_attr_unsupported_in_stage : Error<"attribute %0 is unsupported in '%1' shaders, requires %select{|one of the following: }2%3">;

clang/lib/Sema/SemaInit.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9393,16 +9393,16 @@ ExprResult InitializationSequence::Perform(Sema &S,
93939393
CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE);
93949394

93959395
if (!Step->Type->isDependentType()) {
9396-
assert(S.isCompleteType(CurInit.get()->getExprLoc(), Step->Type,
9397-
Sema::CompleteTypeKind::Normal) &&
9398-
"std::initializer_list<E> incomplete when used during "
9399-
"initialization");
94009396
QualType ElementType;
94019397
[[maybe_unused]] bool IsStdInitializerList =
94029398
S.isStdInitializerList(Step->Type, &ElementType);
94039399
assert(IsStdInitializerList &&
94049400
"StdInitializerList step to non-std::initializer_list");
9405-
RecordDecl *Record = Step->Type->castAs<RecordType>()->getDecl();
9401+
const CXXRecordDecl *Record =
9402+
Step->Type->getAsCXXRecordDecl()->getDefinition();
9403+
assert(Record && Record->isCompleteDefinition() &&
9404+
"std::initializer_list should have already be "
9405+
"complete/instantiated by this point");
94069406

94079407
auto InvalidType = [&] {
94089408
S.Diag(Record->getLocation(),
@@ -9411,8 +9411,8 @@ ExprResult InitializationSequence::Perform(Sema &S,
94119411
return ExprError();
94129412
};
94139413

9414-
// FIXME: What if the initializer_list type has base classes, etc?
9415-
if (Record->isUnion())
9414+
if (Record->isUnion() || Record->getNumBases() != 0 ||
9415+
Record->isPolymorphic())
94169416
return InvalidType();
94179417

94189418
RecordDecl::field_iterator Field = Record->field_begin();
@@ -9429,12 +9429,12 @@ ExprResult InitializationSequence::Perform(Sema &S,
94299429
return InvalidType();
94309430

94319431
// Size or end pointer
9432-
if (Field->getType()->isPointerType()) {
9433-
if (!S.Context.hasSameType(Field->getType()->getPointeeType(),
9432+
if (const auto *PT = Field->getType()->getAs<PointerType>()) {
9433+
if (!S.Context.hasSameType(PT->getPointeeType(),
94349434
ElementType.withConst()))
94359435
return InvalidType();
94369436
} else {
9437-
if (Field->isUnnamedBitField() ||
9437+
if (Field->isBitField() ||
94389438
!S.Context.hasSameType(Field->getType(), S.Context.getSizeType()))
94399439
return InvalidType();
94409440
}

clang/test/SemaCXX/PR20334-std_initializer_list_diagnosis_assertion.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
// RUN: %clang_cc1 -std=c++11 -verify=cxx11 -emit-llvm-only %s
2-
// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify=cxx98 %s -DCPP98
2+
// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify=cxx98 %s
33
// RUN: %clang_cc1 -std=c++11 -verify=cxx11 -emit-llvm-only %s -fexperimental-new-constant-interpreter
4-
// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify=cxx98 %s -DCPP98 -fexperimental-new-constant-interpreter
4+
// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify=cxx98 %s -fexperimental-new-constant-interpreter
55

66

77
namespace std {
88
template <class _E>
9-
class initializer_list
10-
{};
11-
// cxx11-error@-2 {{'std::initializer_list<int>' layout not recognized}}
9+
class initializer_list {};
10+
// cxx11-error@-1 {{'std::initializer_list<int>' layout not recognized. Must be a non-polymorphic class type with no bases and two fields: a 'const E *' and either another 'const E *' or a 'std::size_t'}}
1211
}
1312

1413
template<class E> int f(std::initializer_list<E> il);

clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -390,19 +390,39 @@ template<> struct std::initializer_list<weird_initlist::weird<1>> { std::size_t
390390
template<> struct std::initializer_list<weird_initlist::weird<2>> { const weird_initlist::weird<2>* first; const weird_initlist::weird<2>* last; };
391391
template<> struct std::initializer_list<weird_initlist::weird<3>> { weird_initlist::weird<3>* p; std::size_t sz; };
392392
// expected-error@-1 {{'std::initializer_list<weird<3>>' layout not recognized}}
393-
template<> struct std::initializer_list<weird_initlist::weird<4>> { const weird_initlist::weird<3>& p; std::size_t sz; };
393+
template<> struct std::initializer_list<weird_initlist::weird<4>> { const weird_initlist::weird<4>& p; std::size_t sz; };
394394
// expected-error@-1 {{'std::initializer_list<weird<4>>' layout not recognized}}
395-
template<> struct std::initializer_list<weird_initlist::weird<5>> { const weird_initlist::weird<3>* p; std::size_t : sizeof(std::size_t) * __CHAR_BIT__; };
395+
template<> struct std::initializer_list<weird_initlist::weird<5>> { const weird_initlist::weird<5>* p; std::size_t : sizeof(std::size_t) * __CHAR_BIT__; };
396396
// expected-error@-1 {{'std::initializer_list<weird<5>>' layout not recognized}}
397+
template<> struct std::initializer_list<weird_initlist::weird<6>> { const weird_initlist::weird<6>* p; std::size_t sz : sizeof(std::size_t) * __CHAR_BIT__; };
398+
// expected-error@-1 {{'std::initializer_list<weird<6>>' layout not recognized}}
399+
struct empty_base {};
400+
template<> struct std::initializer_list<weird_initlist::weird<7>> : empty_base { const weird_initlist::weird<7>* p; std::size_t sz; };
401+
// expected-error@-1 {{'std::initializer_list<weird<7>>' layout not recognized}}
402+
template<> struct std::initializer_list<weird_initlist::weird<8>> { const weird_initlist::weird<8>* p; std::size_t sz; ~initializer_list(); };
403+
template<> struct std::initializer_list<weird_initlist::weird<9>> { const weird_initlist::weird<9>* p; std::size_t sz; virtual void f(); };
404+
// expected-error@-1 {{'std::initializer_list<weird<9>>' layout not recognized}}
405+
template<> struct std::initializer_list<weird_initlist::weird<10>> { const weird_initlist::weird<10>* p; alignas(64) std::size_t sz; };
406+
template<> struct std::initializer_list<weird_initlist::weird<11>>;
407+
// expected-note@-1 {{forward declaration of 'std::initializer_list<weird_initlist::weird<11>>'}}
397408
namespace weird_initlist {
398409
auto _0 = {weird<0>{}, weird<0>{}, weird<0>{}, weird<0>{}, weird<0>{}};
399-
constexpr auto _00 = {weird<0>{}, weird<0>{}, weird<0>{}, weird<0>{}, weird<0>{}};
410+
constexpr auto _0c = {weird<0>{}, weird<0>{}, weird<0>{}, weird<0>{}, weird<0>{}};
400411
auto _1 = {weird<1>{}, weird<1>{}};
401-
constexpr auto _2 = {weird<2>{}, weird<2>{}, weird<2>{}}; // (Two pointer representation is supported)
402-
static_assert(_2.first + 3 == _2.last, "");
412+
auto _2 = {weird<2>{}, weird<2>{}, weird<2>{}};
413+
constexpr auto _2c = {weird<2>{}, weird<2>{}, weird<2>{}}; // (Two pointer representation is supported)
414+
static_assert(_2c.first + 3 == _2c.last, "");
403415
auto _3 = {weird<3>{}, weird<3>{}};
404416
auto _4 = {weird<4>{}, weird<4>{}};
405417
auto _5 = {weird<5>{}, weird<5>{}};
418+
auto _6 = {weird<6>{}, weird<6>{}};
419+
auto _7 = {weird<7>{}, weird<7>{}};
420+
auto _8 = {weird<8>{}, weird<8>{}};
421+
auto _9 = {weird<9>{}, weird<9>{}};
422+
auto _10 = {weird<10>{}, weird<10>{}};
423+
constexpr auto _10c = {weird<10>{}, weird<10>{}, weird<10>{}};
424+
static_assert(_10c.sz == 3, "");
425+
const auto& _11 = {weird<11>{}, weird<11>{}}; // expected-error {{initialization of incomplete type 'const std::initializer_list<weird<11>>'}}
406426
}
407427

408428
auto v = std::initializer_list<int>{1,2,3}; // expected-warning {{array backing local initializer list 'v' will be destroyed at the end of the full-expression}}

0 commit comments

Comments
 (0)