Skip to content

Commit 49f712a

Browse files
committed
[clang][bytecode] Avoid copies with elidable CXXConstructExprs
To fix the newly added cwg6.cpp.
1 parent 9b114c5 commit 49f712a

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3235,7 +3235,8 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
32353235
return this->visitInitializer(E->getArg(0));
32363236

32373237
// Zero initialization.
3238-
if (E->requiresZeroInitialization()) {
3238+
bool ZeroInit = E->requiresZeroInitialization();
3239+
if (ZeroInit) {
32393240
const Record *R = getRecord(E->getType());
32403241

32413242
if (!this->visitZeroRecordInitializer(R, E))
@@ -3246,6 +3247,16 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
32463247
return true;
32473248
}
32483249

3250+
// Avoid materializing a temporary for an elidable copy/move constructor.
3251+
if (!ZeroInit && E->isElidable()) {
3252+
const Expr *SrcObj = E->getArg(0);
3253+
assert(SrcObj->isTemporaryObject(Ctx.getASTContext(), Ctor->getParent()));
3254+
assert(Ctx.getASTContext().hasSameUnqualifiedType(E->getType(),
3255+
SrcObj->getType()));
3256+
if (const auto *ME = dyn_cast<MaterializeTemporaryExpr>(SrcObj))
3257+
return this->visit(ME->getSubExpr());
3258+
}
3259+
32493260
const Function *Func = getFunction(Ctor);
32503261

32513262
if (!Func)

clang/test/AST/ByteCode/cxx11.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,3 +379,11 @@ namespace DiscardedAddrLabel {
379379
}
380380
}
381381

382+
struct Counter {
383+
int copies;
384+
constexpr Counter(int copies) : copies(copies) {}
385+
constexpr Counter(const Counter& other) : copies(other.copies + 1) {}
386+
};
387+
// Passing an lvalue by value makes a non-elidable copy.
388+
constexpr int PassByValue(Counter c) { return c.copies; }
389+
static_assert(PassByValue(Counter(0)) == 0, "expect no copies");

0 commit comments

Comments
 (0)