Skip to content

Commit 788a70e

Browse files
committed
Refactor: expose canElideCopy to C++ with saner default parameters
1 parent 20f7dbf commit 788a70e

7 files changed

Lines changed: 19 additions & 6 deletions

File tree

compiler/src/dmd/cxxfrontend.d

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,12 @@ bool isLvalue(Expression exp)
430430
return dmd.expressionsem.isLvalue(exp);
431431
}
432432

433+
bool canElideCopy(Expression exp, Type to, bool checkMod)
434+
{
435+
import dmd.expressionsem;
436+
return dmd.expressionsem.canElideCopy(exp, to, checkMod);
437+
}
438+
433439
int getFieldIndex(ClassReferenceExp cre, Type fieldtype, uint fieldoffset)
434440
{
435441
import dmd.expressionsem;

compiler/src/dmd/expression.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ namespace dmd
6262
bool isIdentical(const Expression *exp, const Expression *e);
6363
bool equals(const Expression *exp, const Expression *e);
6464
bool isLvalue(Expression *exp);
65+
bool canElideCopy(Expression *exp, Type *to, bool checkMod = false);
6566
int32_t getFieldIndex(ClassReferenceExp *cre, Type *fieldtype, uint32_t fieldoffset);
6667
void fillTupleExpExps(TupleExp *te, TupleDeclaration *tup);
6768
Optional<bool> toBool(Expression *exp);

compiler/src/dmd/expressionsem.d

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -761,8 +761,13 @@ bool isLvalue(Expression _this)
761761
* Determine if copy elision is allowed when copying an expression to
762762
* a typed storage. This basically elides a restricted subset of so-called
763763
* "pure" rvalues, i.e. expressions with no reference semantics.
764+
*
765+
* Note: Please avoid using `checkMod` parameter because `canElideCopy()`
766+
* essentially defines a value category and should eventually be merged with
767+
* `isLvalue()` to return [isLvalue, allowEmplacement].
768+
* Checking type compatibility here is only a stopgap measure.
764769
*/
765-
bool canElideCopy(Expression e, Type to, bool checkMod = true)
770+
bool canElideCopy(Expression e, Type to, bool checkMod = false)
766771
{
767772
if (checkMod && !MODimplicitConv(e.type.mod, to.mod))
768773
return false;
@@ -791,7 +796,7 @@ bool canElideCopy(Expression e, Type to, bool checkMod = true)
791796
return false;
792797

793798
// If an aggregate can be elided, so are its fields
794-
return canElideCopy(e.e1, e.e1.type, false);
799+
return canElideCopy(e.e1, e.e1.type);
795800
}
796801

797802
switch (e.op)
@@ -1920,7 +1925,7 @@ extern (D) Expression doCopyOrMove(Scope* sc, Expression e, Type t, bool nrvo, b
19201925
{
19211926
e = callCpCtor(sc, e, t, nrvo);
19221927
}
1923-
else if (move && sd && sd.hasMoveCtor && !canElideCopy(e, t ? t : e.type, false))
1928+
else if (move && sd && sd.hasMoveCtor && !canElideCopy(e, t ? t : e.type))
19241929
{
19251930
// #move
19261931
/* Rewrite as:

compiler/src/dmd/glue/e2ir.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5518,7 +5518,7 @@ elem* callfunc(Loc loc,
55185518
bool hasDtor = v && (v.isArgDtorVar || v.storage_class & STC.rvalue);
55195519

55205520
/* Also do not copy __rvalue expressions or temporaries that can be elided. */
5521-
bool copy = !(hasDtor || arg.rvalue || (param && canElideCopy(arg, param.type)));
5521+
bool copy = !(hasDtor || arg.rvalue || (param && canElideCopy(arg, param.type, true)));
55225522

55235523
elems[i] = addressElem(ea, arg.type, copy);
55245524
continue;

compiler/src/dmd/inline.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ public:
403403
auto tf = ids.fd.type.isTypeFunction();
404404

405405
if (exp.type.ty == Tstruct && !tf.isRef &&
406-
!ids.fd.isCtorDeclaration() && !canElideCopy(s.exp, tf.nextOf()))
406+
!ids.fd.isCtorDeclaration() && !canElideCopy(s.exp, tf.nextOf(), true))
407407
{
408408
/* If the inlined function returns a copy of a struct,
409409
* and then the return value is used subsequently as an

compiler/src/dmd/semantic3.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -974,7 +974,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
974974
if (funcdecl.vresult)
975975
{
976976
// Create: return vresult = exp;
977-
if (canElideCopy(exp, funcdecl.vresult.type, false))
977+
if (canElideCopy(exp, funcdecl.vresult.type))
978978
exp = new ConstructExp(rs.loc, funcdecl.vresult, exp);
979979
else
980980
exp = new BlitExp(rs.loc, funcdecl.vresult, exp);

compiler/src/tests/cxxfrontend.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,6 +1773,7 @@ void expression_h(Expression *e, Scope *sc, Type *t, Loc loc, Expressions *es)
17731773
dmd::expandTuples(es);
17741774
dmd::optimize(e, 0);
17751775
dmd::isLvalue(e);
1776+
dmd::canElideCopy(e, t);
17761777
}
17771778

17781779
void hdrgen_h(Module *m, OutBuffer &buf, Modules &ms, ParameterList pl,

0 commit comments

Comments
 (0)