Skip to content

Commit 15362c9

Browse files
shafikahatanaka
authored andcommitted
[Clang] Fix crash when emitting diagnostic for out of order designated initializers in C++
In C++ we are not allowed to use designated initializers to initialize fields out of order. In some cases when diagnosing this we are crashing because we are not indexing correctly and therefore going out of bounds. This fixes: llvm#63605 Differential Revision: https://reviews.llvm.org/D154675 (cherry picked from commit c9ef33e) Conflicts: clang/docs/ReleaseNotes.rst clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp
1 parent cb96a4a commit 15362c9

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,9 @@ Bug Fixes
274274
- Fix assert that fails when the expression causing the this pointer to be
275275
captured by a block is part of a constexpr if statement's branch and
276276
instantiation of the enclosing method causes the branch to be discarded.
277+
- Fix crash when emitting diagnostic for out of order designated initializers
278+
in C++.
279+
(`#63605 <https://github.com/llvm/llvm-project/issues/63605>`_)
277280

278281
Improvements to Clang's diagnostics
279282
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaInit.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2712,7 +2712,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
27122712
SemaRef.Diag(DIE->getBeginLoc(), diag::ext_designated_init_reordered)
27132713
<< KnownField << PrevField << DIE->getSourceRange();
27142714

2715-
unsigned OldIndex = NumBases + PrevField->getFieldIndex();
2715+
unsigned OldIndex = StructuredIndex - 1;
27162716
if (StructuredList && OldIndex <= StructuredList->getNumInits()) {
27172717
if (Expr *PrevInit = StructuredList->getInit(OldIndex)) {
27182718
SemaRef.Diag(PrevInit->getBeginLoc(),
@@ -2816,8 +2816,12 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
28162816
// If this the first designator, our caller will continue checking
28172817
// the rest of this struct/class/union subobject.
28182818
if (IsFirstDesignator) {
2819+
if (Field != RT->getDecl()->field_end() && Field->isUnnamedBitfield())
2820+
++Field;
2821+
28192822
if (NextField)
28202823
*NextField = Field;
2824+
28212825
StructuredIndex = FieldIndex;
28222826
return false;
28232827
}

clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ C c = {
6363
.x = 1, // override-note {{previous}}
6464
.x = 1, // override-error {{overrides prior initialization}} override-note {{previous}}
6565
.y = 1, // override-note {{previous}}
66-
.y = 1, // override-error {{overrides prior initialization}}
66+
.y = 1, // override-error {{overrides prior initialization}} // reorder-note {{previous initialization for field 'y' is here}}
6767
.x = 1, // reorder-error {{declaration order}} override-error {{overrides prior initialization}} override-note {{previous}}
6868
.x = 1, // override-error {{overrides prior initialization}}
6969
};
@@ -156,3 +156,43 @@ namespace deduction {
156156
j3<D, E>({}); // ok, selects E overload by SFINAE (too many braces for D)
157157
}
158158
}
159+
160+
namespace GH63605 {
161+
struct A {
162+
unsigned x;
163+
unsigned y;
164+
unsigned z;
165+
};
166+
167+
struct B {
168+
unsigned a;
169+
unsigned b;
170+
};
171+
172+
struct : public A, public B {
173+
unsigned : 2;
174+
unsigned a : 6;
175+
unsigned : 1;
176+
unsigned b : 6;
177+
unsigned : 2;
178+
unsigned c : 6;
179+
unsigned d : 1;
180+
unsigned e : 2;
181+
} data = {
182+
{.z=0,
183+
// pedantic-note@-1 {{first non-designated initializer is here}}
184+
// reorder-note@-2 {{previous initialization for field 'z' is here}}
185+
.y=1, // reorder-error {{field 'z' will be initialized after field 'y'}}
186+
// reorder-note@-1 {{previous initialization for field 'y' is here}}
187+
.x=2}, // reorder-error {{field 'y' will be initialized after field 'x'}}
188+
{.b=3, // reorder-note {{previous initialization for field 'b' is here}}
189+
.a=4}, // reorder-error {{field 'b' will be initialized after field 'a'}}
190+
.e = 1, // reorder-note {{previous initialization for field 'e' is here}}
191+
// pedantic-error@-1 {{mixture of designated and non-designated initializers in the same initializer list is a C99 extension}}
192+
.d = 1, // reorder-error {{field 'e' will be initialized after field 'd'}}
193+
// reorder-note@-1 {{previous initialization for field 'd' is here}}
194+
.c = 1, // reorder-error {{field 'd' will be initialized after field 'c'}} // reorder-note {{previous initialization for field 'c' is here}}
195+
.b = 1, // reorder-error {{field 'c' will be initialized after field 'b'}} // reorder-note {{previous initialization for field 'b' is here}}
196+
.a = 1, // reorder-error {{field 'b' will be initialized after field 'a'}}
197+
};
198+
}

0 commit comments

Comments
 (0)