[clang] [clang][bytecode] Give a discarded composite prvalue a result object (PR #219952)
Yihan Wang via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 31 06:47:25 PDT 2026
https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/219952
>From aa8d3df0543f5964eabd01cfd5ec0c49499b9f49 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
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 <tbaeder at redhat.com>
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
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
More information about the cfe-commits
mailing list