Skip to content

Commit f374d5c

Browse files
committed
Consider v.__ctor() an lvalue
1 parent 03bf6f0 commit f374d5c

2 files changed

Lines changed: 59 additions & 2 deletions

File tree

compiler/src/dmd/expressionsem.d

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -681,8 +681,19 @@ bool isLvalue(Expression _this)
681681
if (tf && tf.isRef)
682682
{
683683
if (auto dve = _this.e1.isDotVarExp())
684+
{
684685
if (dve.var.isCtorDeclaration())
685-
return false;
686+
{
687+
// Allow taking the address of explicit constructor calls,
688+
// but not (__stmp = S(), __stmp).__ctor().
689+
690+
auto ve = lastComma(dve.e1).isVarExp();
691+
if (ve && (ve.var.storage_class & STC.temp) != 0)
692+
return false;
693+
694+
return isLvalue(dve.e1);
695+
}
696+
}
686697
return true; // function returns a reference
687698
}
688699
return false;
@@ -775,8 +786,19 @@ bool canElideCopy(Expression e, Type to, bool checkMod = false)
775786
static bool visitCallExp(CallExp e)
776787
{
777788
if (auto dve = e.e1.isDotVarExp())
789+
{
778790
if (dve.var.isCtorDeclaration())
779-
return true;
791+
{
792+
// Allow (__stmp = S(), __stmp).__ctor() to be elided,
793+
// but force a copy for (s2 = s1.__ctor()).
794+
795+
auto ve = lastComma(dve.e1).isVarExp();
796+
if (ve && (ve.var.storage_class & STC.temp) != 0)
797+
return true;
798+
799+
return canElideCopy(dve.e1, e.type);
800+
}
801+
}
780802

781803
auto tb = e.e1.type.toBasetype();
782804
if (tb.ty == Tdelegate || tb.ty == Tpointer)

compiler/test/runnable/sctor.d

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,40 @@ void test19389()
465465
assert(bar.b.x == 7); // fails
466466
}
467467

468+
/***************************************************/
469+
// https://github.com/dlang/dmd/issues/22604
470+
471+
struct S22604
472+
{
473+
S22604* ptr;
474+
475+
this(int)
476+
{
477+
ptr = &this;
478+
}
479+
480+
this(this)
481+
{
482+
ptr = &this;
483+
}
484+
}
485+
486+
struct T22604
487+
{
488+
S22604 a, b;
489+
490+
this(int)
491+
{
492+
a = b = S22604(1);
493+
}
494+
}
495+
496+
void test22604()
497+
{
498+
T22604 t = T22604(1);
499+
assert(t.a.ptr is &t.a);
500+
assert(t.b.ptr is &t.b);
501+
}
468502

469503
/***************************************************/
470504

@@ -478,6 +512,7 @@ int main()
478512
test14944();
479513
test15869();
480514
test19389();
515+
test22604();
481516

482517
printf("Success\n");
483518
return 0;

0 commit comments

Comments
 (0)