From afcda23927bb79dfd7446aa90bfc741d5254c2e2 Mon Sep 17 00:00:00 2001 From: naveen-seth Date: Sat, 8 Nov 2025 19:53:08 +0100 Subject: [PATCH 1/2] [clang][Sema] Fix crash on designated initializer of union member in subobject Fixes #166327 Clang previously hit an assertion in C++ mode when a nested initializer list was followed by a designated initializer that referred to a union member of the same subobject. This fixes the assertion. --- clang/lib/Sema/SemaInit.cpp | 5 +++- .../crash-union-designated-initializer.cpp | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 clang/test/SemaCXX/crash-union-designated-initializer.cpp diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index cc6ddf568d346..13fb22ebfe0ef 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2402,8 +2402,11 @@ void InitListChecker::CheckStructUnionTypes( CheckEmptyInitializable( InitializedEntity::InitializeMember(*Field, &Entity), IList->getEndLoc()); - if (StructuredList) + if (StructuredList) { StructuredList->setInitializedFieldInUnion(*Field); + StructuredList->resizeInits(SemaRef.Context, + StructuredList->getNumInits() + 1); + } break; } } 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}} +} From 3fbca9a0595292e9309747b29a27cace266c2b84 Mon Sep 17 00:00:00 2001 From: naveen-seth Date: Sat, 8 Nov 2025 21:02:47 +0100 Subject: [PATCH 2/2] Revert back to previous strategy to fix failing tests --- clang/lib/Sema/SemaInit.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 13fb22ebfe0ef..11cb9527525a9 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2402,11 +2402,8 @@ void InitListChecker::CheckStructUnionTypes( CheckEmptyInitializable( InitializedEntity::InitializeMember(*Field, &Entity), IList->getEndLoc()); - if (StructuredList) { + if (StructuredList) StructuredList->setInitializedFieldInUnion(*Field); - StructuredList->resizeInits(SemaRef.Context, - StructuredList->getNumInits() + 1); - } break; } } @@ -3032,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(