https://github.com/nataliakokoromyti updated 
https://github.com/llvm/llvm-project/pull/175512

>From 6c3d7bd99351e52a3b72212d9f2b6074e6bd2305 Mon Sep 17 00:00:00 2001
From: Natalia Kokoromyti <[email protected]>
Date: Mon, 12 Jan 2026 02:12:16 -0800
Subject: [PATCH 1/3] [clang][bytecode] Add test case for issue #175432

Add test case for assertion crash with GlobalInlineDescriptor
when checking initialization of constexpr pointer arrays.
---
 clang/test/AST/ByteCode/arrays.cpp | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/clang/test/AST/ByteCode/arrays.cpp 
b/clang/test/AST/ByteCode/arrays.cpp
index d83ae97fc8213..f9b4f7b55332a 100644
--- a/clang/test/AST/ByteCode/arrays.cpp
+++ b/clang/test/AST/ByteCode/arrays.cpp
@@ -835,3 +835,12 @@ namespace MultiDimConstructExpr {
   constexpr b d;
   static_assert(d.m[2][1].p == &d.m[2][1]);
 }
+
+// Test for issue #175432 - assertion crash with GlobalInlineDescriptor
+// Previously crashed with: Assertion `BS.Base != 
sizeof(GlobalInlineDescriptor)` failed
+namespace gh175432 {
+  constexpr const int *arr[][2] = {{nullptr, nullptr}};
+  static_assert(arr[0][0] == nullptr, "");
+  static_assert(arr[0][1] == nullptr, "");
+}
+

>From d8b43055ce6d783d24ab2f6867c56f1c2669efa0 Mon Sep 17 00:00:00 2001
From: Natalia Kokoromyti <[email protected]>
Date: Mon, 12 Jan 2026 02:24:44 -0800
Subject: [PATCH 2/3] [clang][bytecode] Fix assertion in
 Pointer::isInitialized() for GlobalInlineDescriptor

The function was calling getFieldDesc() which internally calls getInlineDesc(),
triggering an assertion when BS.Base == sizeof(GlobalInlineDescriptor).

The existing check at the start of the function handles the case where
isRoot() && Offset == BS.Base, but doesn't cover cases where
BS.Base == sizeof(GlobalInlineDescriptor) but Offset != BS.Base.

Added a safety check before calling getFieldDesc() to return true for
these cases, avoiding the crash while preserving existing behavior for
the normal isRoot() path.

Fixes #175432
---
 clang/docs/ReleaseNotes.rst        |  2 ++
 clang/lib/AST/ByteCode/Pointer.cpp |  6 ++++++
 clang/test/AST/ByteCode/arrays.cpp | 13 ++++++-------
 3 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index cc04deb45bb53..eecab591508ff 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -127,6 +127,8 @@ Bug Fixes to C++ Support
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 
+- Fixed assertion crash in bytecode interpreter when checking initialization of
+  constexpr pointer arrays with GlobalInlineDescriptor. (#GH175432)
 Miscellaneous Bug Fixes
 ^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/clang/lib/AST/ByteCode/Pointer.cpp 
b/clang/lib/AST/ByteCode/Pointer.cpp
index c5e0fd83021d7..1d9b5a36390cc 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -454,6 +454,12 @@ bool Pointer::isInitialized() const {
     return GD.InitState == GlobalInitState::Initialized;
   }
 
+  // Safety check: if BS.Base == sizeof(GlobalInlineDescriptor) but we're not
+  // in the isRoot() case above, we still cannot call getInlineDesc().
+  // This can happen when Offset != BS.Base. Return true to avoid crash.
+  if (BS.Base == sizeof(GlobalInlineDescriptor))
+    return true;
+
   assert(BS.Pointee && "Cannot check if null pointer was initialized");
   const Descriptor *Desc = getFieldDesc();
   assert(Desc);
diff --git a/clang/test/AST/ByteCode/arrays.cpp 
b/clang/test/AST/ByteCode/arrays.cpp
index f9b4f7b55332a..255bfb99783b9 100644
--- a/clang/test/AST/ByteCode/arrays.cpp
+++ b/clang/test/AST/ByteCode/arrays.cpp
@@ -834,13 +834,12 @@ namespace MultiDimConstructExpr {
   };
   constexpr b d;
   static_assert(d.m[2][1].p == &d.m[2][1]);
-}
 
-// Test for issue #175432 - assertion crash with GlobalInlineDescriptor
-// Previously crashed with: Assertion `BS.Base != 
sizeof(GlobalInlineDescriptor)` failed
-namespace gh175432 {
-  constexpr const int *arr[][2] = {{nullptr, nullptr}};
-  static_assert(arr[0][0] == nullptr, "");
-  static_assert(arr[0][1] == nullptr, "");
 }
 
+namespace GH175432 {
+  constexpr const int *foo[][2] = {
+      {nullptr, int}, // both-error {{expected '(' for function-style cast or 
type construction}}
+  };
+  static_assert(foo[0][0] == nullptr, ""); // both-error {{not an integral 
constant expression}}
+}

>From 9a9baa1d340f42a2d2c6a3bd3fdef8134ba50afc Mon Sep 17 00:00:00 2001
From: Natalia <[email protected]>
Date: Tue, 13 Jan 2026 19:12:27 -0800
Subject: [PATCH 3/3] Fix initialization check to return false for edge case

Changes return value from true to false when BS.Base == 
sizeof(GlobalInlineDescriptor)
but isRoot() conditions are not met. Returning true was too permissive and 
caused
test failures. Returning false is more conservative and prevents the crash while
maintaining correct behavior for valid code.

Also updated test expectations to use expected-error instead of both-error since
this issue only affects the new constant evaluator.
---
 clang/lib/AST/ByteCode/Pointer.cpp | 12 +++++++-----
 clang/test/AST/ByteCode/arrays.cpp | 11 ++++++++---
 2 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Pointer.cpp 
b/clang/lib/AST/ByteCode/Pointer.cpp
index 1d9b5a36390cc..8f623a3cb7890 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -454,13 +454,15 @@ bool Pointer::isInitialized() const {
     return GD.InitState == GlobalInitState::Initialized;
   }
 
-  // Safety check: if BS.Base == sizeof(GlobalInlineDescriptor) but we're not
-  // in the isRoot() case above, we still cannot call getInlineDesc().
-  // This can happen when Offset != BS.Base. Return true to avoid crash.
+  assert(BS.Pointee && "Cannot check if null pointer was initialized");
+
+  // Handle the case where BS.Base == sizeof(GlobalInlineDescriptor) but
+  // the pointer is not a proper root. This can happen with invalid code.
+  // We cannot call getFieldDesc() or getInlineDesc() in this case as they
+  // would trigger assertions. Conservatively return false.
   if (BS.Base == sizeof(GlobalInlineDescriptor))
-    return true;
+    return false;
 
-  assert(BS.Pointee && "Cannot check if null pointer was initialized");
   const Descriptor *Desc = getFieldDesc();
   assert(Desc);
   if (Desc->isPrimitiveArray())
diff --git a/clang/test/AST/ByteCode/arrays.cpp 
b/clang/test/AST/ByteCode/arrays.cpp
index 255bfb99783b9..b18f8e50c1e59 100644
--- a/clang/test/AST/ByteCode/arrays.cpp
+++ b/clang/test/AST/ByteCode/arrays.cpp
@@ -838,8 +838,13 @@ namespace MultiDimConstructExpr {
 }
 
 namespace GH175432 {
-  constexpr const int *foo[][2] = {
-      {nullptr, int}, // both-error {{expected '(' for function-style cast or 
type construction}}
+  // Test that we don't crash when checking initialization of
+  // pointer arrays with invalid initializers
+  constexpr const int *foo[][2] = { // expected-error {{must be initialized by 
a constant expression}} \
+                                    // expected-note {{declared here}}
+      {nullptr, int}, // expected-error {{expected '(' for function-style cast 
or type construction}}
   };
-  static_assert(foo[0][0] == nullptr, ""); // both-error {{not an integral 
constant expression}}
+
+  static_assert(foo[0][0] == nullptr, ""); // expected-error {{not an integral 
constant expression}} \
+                                           // expected-note {{initializer of 
'foo' is unknown}}
 }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to