diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d55757183d58e..c501903815955 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -695,6 +695,9 @@ Bug Fixes to C++ Support - Fix handling of using-declarations in the init statements of for loop declarations. (`#63627 `_) +- Fix crash when emitting diagnostic for out of order designated initializers + in C++. + (`#63605 `_) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 289643f690da4..8e2177bce4fd7 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2847,7 +2847,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, SemaRef.Diag(DIE->getBeginLoc(), diag::ext_designated_init_reordered) << KnownField << PrevField << DIE->getSourceRange(); - unsigned OldIndex = NumBases + PrevField->getFieldIndex(); + unsigned OldIndex = StructuredIndex - 1; if (StructuredList && OldIndex <= StructuredList->getNumInits()) { if (Expr *PrevInit = StructuredList->getInit(OldIndex)) { SemaRef.Diag(PrevInit->getBeginLoc(), @@ -2951,8 +2951,12 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // If this the first designator, our caller will continue checking // the rest of this struct/class/union subobject. if (IsFirstDesignator) { + if (Field != RD->field_end() && Field->isUnnamedBitfield()) + ++Field; + if (NextField) *NextField = Field; + StructuredIndex = FieldIndex; return false; } diff --git a/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp b/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp index 3cc3f9cf6dff4..eaca12a5f5c0c 100644 --- a/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp +++ b/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp @@ -63,7 +63,7 @@ C c = { .x = 1, // override-note {{previous}} .x = 1, // override-error {{overrides prior initialization}} override-note {{previous}} .y = 1, // override-note {{previous}} - .y = 1, // override-error {{overrides prior initialization}} + .y = 1, // override-error {{overrides prior initialization}} // reorder-note {{previous initialization for field 'y' is here}} .x = 1, // reorder-error {{declaration order}} override-error {{overrides prior initialization}} override-note {{previous}} .x = 1, // override-error {{overrides prior initialization}} }; @@ -177,3 +177,43 @@ namespace no_unwrap { h({.a = 1}); } } + +namespace GH63605 { +struct A { + unsigned x; + unsigned y; + unsigned z; +}; + +struct B { + unsigned a; + unsigned b; +}; + +struct : public A, public B { + unsigned : 2; + unsigned a : 6; + unsigned : 1; + unsigned b : 6; + unsigned : 2; + unsigned c : 6; + unsigned d : 1; + unsigned e : 2; +} data = { + {.z=0, + // pedantic-note@-1 {{first non-designated initializer is here}} + // reorder-note@-2 {{previous initialization for field 'z' is here}} + .y=1, // reorder-error {{field 'z' will be initialized after field 'y'}} + // reorder-note@-1 {{previous initialization for field 'y' is here}} + .x=2}, // reorder-error {{field 'y' will be initialized after field 'x'}} + {.b=3, // reorder-note {{previous initialization for field 'b' is here}} + .a=4}, // reorder-error {{field 'b' will be initialized after field 'a'}} + .e = 1, // reorder-note {{previous initialization for field 'e' is here}} + // pedantic-error@-1 {{mixture of designated and non-designated initializers in the same initializer list is a C99 extension}} + .d = 1, // reorder-error {{field 'e' will be initialized after field 'd'}} + // reorder-note@-1 {{previous initialization for field 'd' is here}} + .c = 1, // reorder-error {{field 'd' will be initialized after field 'c'}} // reorder-note {{previous initialization for field 'c' is here}} + .b = 1, // reorder-error {{field 'c' will be initialized after field 'b'}} // reorder-note {{previous initialization for field 'b' is here}} + .a = 1, // reorder-error {{field 'b' will be initialized after field 'a'}} +}; +}