[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:18:02 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: None (yronglin)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/113049.diff


2 Files Affected:

- (modified) clang/lib/Sema/SemaInit.cpp (+10-5) 
- (modified) clang/test/SemaCXX/cxx1y-initializer-aggregates.cpp (+11) 


``````````diff
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

``````````

</details>


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


More information about the cfe-commits mailing list