https://github.com/arhwx created 
https://github.com/llvm/llvm-project/pull/208923

`findSubobject()` didn't look through `AtomicType` while walking a designator, 
so reaching a subobject of an object wrapped in `_Atomic` crashed: a null 
`CXXRecordDecl` deref for base classes (the segfault in the issue) and a 
`cast<RecordType>` assertion for fields. The value of an atomic object is 
already represented like a value of the underlying type, so it's enough to look 
through the wrapper before dispatching on the subobject kind.

The crash goes back to clang 9, and the new bytecode interpreter already 
handles this correctly, but the test covers both evaluators anyway, at C++14 
(the earliest standard that can hit the crash) and at C++20 (so `constinit` can 
verify the initializers are indeed constant).

Fixes #203328

>From 3aa875100e0c01a4bc9a13a8664e76004c9234ed Mon Sep 17 00:00:00 2001
From: arhwx <[email protected]>
Date: Sat, 11 Jul 2026 12:09:18 -0400
Subject: [PATCH] [clang] Fix crash on subobject access through _Atomic in
 constant evaluation

findSubobject() didn't look through AtomicType while walking a designator, so 
reaching a base class or field of an object wrapped in _Atomic crashed the 
evaluator. Look through the wrapper since the value of an atomic object is 
already represented like a value of the underlying
type.

Fixes #203328
---
 clang/docs/ReleaseNotes.md              |  1 +
 clang/lib/AST/ExprConstant.cpp          |  7 ++++
 clang/test/SemaCXX/atomic-constexpr.cpp | 44 +++++++++++++++++++++++++
 3 files changed, 52 insertions(+)
 create mode 100644 clang/test/SemaCXX/atomic-constexpr.cpp

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index bbd42848a98c2..10f41c969c3d6 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -919,6 +919,7 @@ latest release, please see the [Clang Web 
Site](https://clang.llvm.org) or the
 - Fixed a crash when using a pack indexing type (e.g. ``Ts...[0]``) imported 
from another module. (#GH204479)
 - Fixed an ODR-merging error in modules, where class-scope `using enum` 
declarations were not recognized as matching across module
   boundaries.  (#GH207066)
+- Fixed a crash when constant evaluation accessed a base class or member of an 
object wrapped in `_Atomic`. (#GH203328)
 
 #### Bug Fixes to AST Handling
 
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 25a96a9c3eceb..7d9dba8cd33fc 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -4254,6 +4254,13 @@ findSubobject(EvalInfo &Info, const Expr *E, const 
CompleteObject &Obj,
     }
 
     LastField = nullptr;
+
+    // The value of an atomic object is represented like a value of the
+    // underlying type, so look through the _Atomic wrapper.
+    if (const AtomicType *AT = ObjType->getAs<AtomicType>())
+      ObjType = Info.Ctx.getQualifiedType(AT->getValueType(),
+                                          ObjType.getQualifiers());
+
     if (ObjType->isArrayType()) {
       // Next subobject is an array element.
       const ArrayType *AT = Info.Ctx.getAsArrayType(ObjType);
diff --git a/clang/test/SemaCXX/atomic-constexpr.cpp 
b/clang/test/SemaCXX/atomic-constexpr.cpp
new file mode 100644
index 0000000000000..0fabc4ff1344c
--- /dev/null
+++ b/clang/test/SemaCXX/atomic-constexpr.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -std=c++14 -verify %s
+// RUN: %clang_cc1 -std=c++14 -verify -fexperimental-new-constant-interpreter 
%s
+// RUN: %clang_cc1 -std=c++20 -verify %s
+// RUN: %clang_cc1 -std=c++20 -verify -fexperimental-new-constant-interpreter 
%s
+// expected-no-diagnostics
+
+namespace GH203328 {
+// Constant evaluation used to crash when it had to find a subobject of an
+// object wrapped in _Atomic.
+
+struct Base {
+  constexpr void set(int) {}
+};
+
+struct Derived : Base {
+  // The member call walks to the base-class subobject of 'this'.
+  constexpr Derived(int x) { set(x); }
+};
+
+struct MemberCall {
+  _Atomic(Derived) a;
+  constexpr MemberCall(int x) : a(Derived(x)) {}
+};
+
+MemberCall mc(0);
+
+struct WithField {
+  int x;
+  // The assignment walks to the field subobject of 'this'.
+  constexpr WithField(int v) : x(v) { x = x + 1; }
+};
+
+struct FieldAccess {
+  _Atomic(WithField) a;
+  constexpr FieldAccess(int v) : a(WithField(v)) {}
+};
+
+FieldAccess fa(1);
+
+#if __cplusplus >= 202002L
+constinit MemberCall mc2(0);
+constinit FieldAccess fa2(1);
+#endif
+} // namespace GH203328

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

Reply via email to