https://github.com/yronglin updated 
https://github.com/llvm/llvm-project/pull/219952

>From aa8d3df0543f5964eabd01cfd5ec0c49499b9f49 Mon Sep 17 00:00:00 2001
From: yronglin <[email protected]>
Date: Mon, 31 Aug 2026 06:47:04 -0700
Subject: [PATCH] [clang][bytecode] Give a discarded composite prvalue a result
 object
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Timm Bäder <[email protected]>
Signed-off-by: yronglin <[email protected]>
---
 clang/lib/AST/ByteCode/Compiler.cpp | 40 ++++++++++++++++++++---------
 clang/test/AST/ByteCode/records.cpp | 29 +++++++++++++++++++--
 2 files changed, 55 insertions(+), 14 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index 55abd51659b46..e566d8f64db9e 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -265,7 +265,9 @@ template <class Emitter> class InitStackScope final {
 public:
   InitStackScope(Compiler<Emitter> *Ctx, bool Active)
       : Ctx(Ctx), OldValue(Ctx->InitStackActive), Active(Active) {
-    Ctx->InitStackActive = Active;
+    // An explicit initializer nested in a default member initializer still
+    // needs the surrounding default initializer's `this` reconstruction.
+    Ctx->InitStackActive = OldValue || Active;
     if (Active)
       Ctx->InitStack.push_back(InitLink::DIE());
   }
@@ -2308,24 +2310,38 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const 
Expr *> Inits,
     return this->emitInvalid(E);
   }
 
-  // Handle discarding first.
-  if (DiscardResult) {
-    for (const Expr *Init : Inits) {
-      if (!this->discard(Init))
-        return false;
-    }
-    return true;
-  }
-
-  // Primitive values.
+  // Primitive values. A discarded one can simply discard each initializer;
+  // there is no object to establish.
   if (OptPrimType T = classify(QT)) {
-    assert(!DiscardResult);
+    if (DiscardResult) {
+      for (const Expr *Init : Inits) {
+        if (!this->discard(Init))
+          return false;
+      }
+      return true;
+    }
     if (Inits.size() == 0)
       return this->visitZeroInitializer(*T, QT, E);
     assert(Inits.size() == 1);
     return this->delegate(Inits[0]);
   }
 
+  assert(!canClassify(E->getType()));
+
+  // A composite prvalue needs somewhere to live even when it is discarded: a
+  // default member initializer may read subobjects initialized earlier in this
+  // same list, so those have to actually be written and `this` has to denote
+  // the object. Materialize one and initialize into it.
+  if (DiscardResult && !Initializing) {
+    UnsignedOrNone LocalIndex = allocateLocal(E);
+    if (!LocalIndex)
+      return false;
+    if (!this->emitGetPtrLocal(*LocalIndex, E))
+      return false;
+    InitLinkScope<Emitter> ILS2(this, InitLink::Temp(*LocalIndex));
+    return this->visitInitializerPop(E);
+  }
+
   if (QT->isRecordType()) {
     const Record *R = getRecord(QT);
 
diff --git a/clang/test/AST/ByteCode/records.cpp 
b/clang/test/AST/ByteCode/records.cpp
index 36b5cb62fe95f..e522072802308 100644
--- a/clang/test/AST/ByteCode/records.cpp
+++ b/clang/test/AST/ByteCode/records.cpp
@@ -1302,11 +1302,36 @@ namespace {
   };
   constexpr int a() {
     int x = 1;
-    int f = B{x}.x;
+    {
+      B b{x};
+    }
+    return x;
+  }
+  static_assert(a() == 0);
+
+  constexpr int discarded() {
+    int x = 1;
     B{x}; // both-warning {{expression result unused}}
+    return x;
+  }
 
-    return 1;
+  /// Before the result object was allocated, this could not be evaluated at
+  /// all. The temporary 'B' is not destroyed until the end of the enclosing
+  /// full-expression, so 'x' still reads 1 here, matching legacy evaluator.
+  ///
+  /// FIXME: See https://github.com/llvm/llvm-project/issues/85601.
+  static_assert(discarded() == 1);
+
+  /// A const-qualified composite result is writable while under construction.
+  constexpr int decrement(int &x) {
+    return --x;
   }
+  struct DMIConstComposite {
+    int a;
+    int b = decrement(a);
+  };
+  constexpr DMIConstComposite c{1};
+  static_assert(c.a == 0);
 }
 #endif
 

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

Reply via email to