Skip to content

Commit

Permalink
[Clang] Fix crash when emitting diagnostic for out of order designate…
Browse files Browse the repository at this point in the history
…d 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: #63605

Differential Revision: https://reviews.llvm.org/D154675
  • Loading branch information
shafik committed Jul 14, 2023
1 parent ef4a2b6 commit c9ef33e
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 2 deletions.
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Expand Up @@ -695,6 +695,9 @@ Bug Fixes to C++ Support
- Fix handling of using-declarations in the init statements of for
loop declarations.
(`#63627 <https://github.com/llvm/llvm-project/issues/63627>`_)
- Fix crash when emitting diagnostic for out of order designated initializers
in C++.
(`#63605 <https://github.com/llvm/llvm-project/issues/63605>`_)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/Sema/SemaInit.cpp
Expand Up @@ -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(),
Expand Down Expand Up @@ -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;
}
Expand Down
42 changes: 41 additions & 1 deletion clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp
Expand Up @@ -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}}
};
Expand Down Expand Up @@ -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'}}
};
}

0 comments on commit c9ef33e

Please sign in to comment.