diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index cc6ddf568d346..11cb9527525a9 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3029,10 +3029,11 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, if (StructuredList) { FieldDecl *CurrentField = StructuredList->getInitializedFieldInUnion(); if (CurrentField && !declaresSameEntity(CurrentField, *Field)) { - assert(StructuredList->getNumInits() == 1 - && "A union should never have more than one initializer!"); + const auto NumInits = StructuredList->getNumInits(); + assert(StructuredList->getNumInits() <= 1 && + "A union should never have more than one initializer!"); - Expr *ExistingInit = StructuredList->getInit(0); + Expr *ExistingInit = NumInits ? StructuredList->getInit(0) : nullptr; if (ExistingInit) { // We're about to throw away an initializer, emit warning. diagnoseInitOverride( diff --git a/clang/test/SemaCXX/crash-union-designated-initializer.cpp b/clang/test/SemaCXX/crash-union-designated-initializer.cpp new file mode 100644 index 0000000000000..7ba40311eac0b --- /dev/null +++ b/clang/test/SemaCXX/crash-union-designated-initializer.cpp @@ -0,0 +1,23 @@ +// Ensures that Clang does not crash in C++ mode, when a nested initializer +// is followed by a designated initializer for a union member of that same +// subobject. +// See issue #166327. + +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s + +auto main(void) -> int { + struct Point { + float x; + float y; + union { + int idx; + char label; + } extra; + }; + + struct SavePoint { + struct Point p; + }; + + SavePoint save = {.p = {.x = 3.0, .y = 4.0}, .p.extra.label = 'p'}; // expected-warning {{nested designators are a C99 extension}} +}