[clang] [clang] Fix a crash issue that caused by handling of fields with initializers in nested anonymous unions (PR #113049)

via cfe-commits cfe-commits at lists.llvm.org
Sat Oct 19 09:17:31 PDT 2024


https://github.com/yronglin created https://github.com/llvm/llvm-project/pull/113049

Fix a crash issue that caused by handling of fields with initializers in nested anonymous unions. 
If my thinking is wrong, I apologize, and IIUC seems it's caused by 5ae5774fb0b5cac11af479b0905dfdd5255b4047.

>From 57293112bb238ae6ac1d0dea9dafba72fa5e9fed Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Sun, 20 Oct 2024 00:12:00 +0800
Subject: [PATCH] [clang] Fix a crash issue that caused by handling of of
 fields with initializers in nested anonymous unions

Signed-off-by: yronglin <yronglin777 at gmail.com>
---
 clang/lib/Sema/SemaInit.cpp                       | 15 ++++++++++-----
 .../test/SemaCXX/cxx1y-initializer-aggregates.cpp | 11 +++++++++++
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index f560865681fa5a..4878dcb5d2c8e0 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -868,13 +868,19 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
 
   if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
     const RecordDecl *RDecl = RType->getDecl();
-    if (RDecl->isUnion() && ILE->getInitializedFieldInUnion()) {
+    if (RDecl->isUnion() && ILE->getInitializedFieldInUnion())
       FillInEmptyInitForField(0, ILE->getInitializedFieldInUnion(), Entity, ILE,
                               RequiresSecondPass, FillWithNoInit);
+    else if (RDecl->isUnion() && isa<CXXRecordDecl>(RDecl) &&
+             cast<CXXRecordDecl>(RDecl)->hasInClassInitializer()) {
+      for (auto *Field : RDecl->fields()) {
+        if (Field->hasInClassInitializer()) {
+          FillInEmptyInitForField(0, Field, Entity, ILE, RequiresSecondPass,
+                                  FillWithNoInit);
+          break;
+        }
+      }
     } else {
-      assert((!RDecl->isUnion() || !isa<CXXRecordDecl>(RDecl) ||
-              !cast<CXXRecordDecl>(RDecl)->hasInClassInitializer()) &&
-             "We should have computed initialized fields already");
       // The fields beyond ILE->getNumInits() are default initialized, so in
       // order to leave them uninitialized, the ILE is expanded and the extra
       // fields are then filled with NoInitExpr.
@@ -2296,7 +2302,6 @@ void InitListChecker::CheckStructUnionTypes(
           return;
         }
       }
-      llvm_unreachable("Couldn't find in-class initializer");
     }
 
     // Value-initialize the first member of the union that isn't an unnamed
diff --git a/clang/test/SemaCXX/cxx1y-initializer-aggregates.cpp b/clang/test/SemaCXX/cxx1y-initializer-aggregates.cpp
index 03a6800898d18f..8360b8fd7d8ee2 100644
--- a/clang/test/SemaCXX/cxx1y-initializer-aggregates.cpp
+++ b/clang/test/SemaCXX/cxx1y-initializer-aggregates.cpp
@@ -115,3 +115,14 @@ namespace nested_union {
   // of Test3, or we should exclude f(Test3) as a candidate.
   static_assert(f({1}) == 2, ""); // expected-error {{call to 'f' is ambiguous}}
 }
+
+// Fix crash issue https://github.com/llvm/llvm-project/issues/112560.
+// Make sure clang compiles the following code without crashing:
+namespace GH112560 {
+union U {
+  int f = ; // expected-error {{expected expression}}
+};
+void foo() {
+  U g{};
+}
+} // namespace GH112560



More information about the cfe-commits mailing list