[clang] [clang][bytecode] Avoid copies with elidable CXXConstructExprs (PR #166931)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Nov 7 04:05:50 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
To fix the newly added cwg6.cpp.
---
Full diff: https://github.com/llvm/llvm-project/pull/166931.diff
2 Files Affected:
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+12-1)
- (modified) clang/test/AST/ByteCode/cxx11.cpp (+8)
``````````diff
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 84f7e6287609c..c12b1f24fcec0 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -3235,7 +3235,8 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
return this->visitInitializer(E->getArg(0));
// Zero initialization.
- if (E->requiresZeroInitialization()) {
+ bool ZeroInit = E->requiresZeroInitialization();
+ if (ZeroInit) {
const Record *R = getRecord(E->getType());
if (!this->visitZeroRecordInitializer(R, E))
@@ -3246,6 +3247,16 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
return true;
}
+ // Avoid materializing a temporary for an elidable copy/move constructor.
+ if (!ZeroInit && E->isElidable()) {
+ const Expr *SrcObj = E->getArg(0);
+ assert(SrcObj->isTemporaryObject(Ctx.getASTContext(), Ctor->getParent()));
+ assert(Ctx.getASTContext().hasSameUnqualifiedType(E->getType(),
+ SrcObj->getType()));
+ if (const auto *ME = dyn_cast<MaterializeTemporaryExpr>(SrcObj))
+ return this->visit(ME->getSubExpr());
+ }
+
const Function *Func = getFunction(Ctor);
if (!Func)
diff --git a/clang/test/AST/ByteCode/cxx11.cpp b/clang/test/AST/ByteCode/cxx11.cpp
index e283a7b42e554..753e51dfbfc1c 100644
--- a/clang/test/AST/ByteCode/cxx11.cpp
+++ b/clang/test/AST/ByteCode/cxx11.cpp
@@ -379,3 +379,11 @@ namespace DiscardedAddrLabel {
}
}
+struct Counter {
+ int copies;
+ constexpr Counter(int copies) : copies(copies) {}
+ constexpr Counter(const Counter& other) : copies(other.copies + 1) {}
+};
+// Passing an lvalue by value makes a non-elidable copy.
+constexpr int PassByValue(Counter c) { return c.copies; }
+static_assert(PassByValue(Counter(0)) == 0, "expect no copies");
``````````
</details>
https://github.com/llvm/llvm-project/pull/166931
More information about the cfe-commits
mailing list