Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add Placement New #17057

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions compiler/src/dmd/astbase.d
Original file line number Diff line number Diff line change
Expand Up @@ -4813,10 +4813,12 @@
Expression thisexp; // if !=null, 'this' for class being allocated
ClassDeclaration cd; // class being instantiated
Expressions* arguments; // Array of Expression's to call class constructor
Expression placement; // if != null, then PlacementExpression

extern (D) this(const ref Loc loc, Expression thisexp, ClassDeclaration cd, Expressions* arguments)
extern (D) this(const ref Loc loc, Expression placement, Expression thisexp, ClassDeclaration cd, Expressions* arguments)

Check warning on line 4818 in compiler/src/dmd/astbase.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/astbase.d#L4818

Added line #L4818 was not covered by tests
{
super(loc, EXP.newAnonymousClass, __traits(classInstanceSize, NewAnonClassExp));
this.placement = placement;

Check warning on line 4821 in compiler/src/dmd/astbase.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/astbase.d#L4821

Added line #L4821 was not covered by tests
this.thisexp = thisexp;
this.cd = cd;
this.arguments = arguments;
Expand Down Expand Up @@ -5025,10 +5027,12 @@
Type newtype;
Expressions* arguments; // Array of Expression's
Identifiers* names; // Array of names corresponding to expressions
Expression placement; // if != null, then PlacementExpression

extern (D) this(const ref Loc loc, Expression thisexp, Type newtype, Expressions* arguments, Identifiers* names = null)
extern (D) this(const ref Loc loc, Expression placement, Expression thisexp, Type newtype, Expressions* arguments, Identifiers* names = null)

Check warning on line 5032 in compiler/src/dmd/astbase.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/astbase.d#L5032

Added line #L5032 was not covered by tests
{
super(loc, EXP.new_, __traits(classInstanceSize, NewExp));
this.placement = placement;

Check warning on line 5035 in compiler/src/dmd/astbase.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/astbase.d#L5035

Added line #L5035 was not covered by tests
this.thisexp = thisexp;
this.newtype = newtype;
this.arguments = arguments;
Expand Down
9 changes: 8 additions & 1 deletion compiler/src/dmd/dinterpret.d
Original file line number Diff line number Diff line change
Expand Up @@ -2794,6 +2794,13 @@
printf("%s NewExp::interpret() %s\n", e.loc.toChars(), e.toChars());
}

if (e.placement)
{
error(e.placement.loc, "`new ( %s )` PlacementExpression cannot be evaluated at compile time", e.placement.toChars());
result = CTFEExp.cantexp;
return;

Check warning on line 2801 in compiler/src/dmd/dinterpret.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/dinterpret.d#L2799-L2801

Added lines #L2799 - L2801 were not covered by tests
}

Expression epre = interpret(pue, e.argprefix, istate, CTFEGoal.Nothing);
if (exceptionOrCant(epre))
return;
Expand Down Expand Up @@ -5067,7 +5074,7 @@
auto ce = e.e2.isCallExp();
assert(ce);

auto ne = new NewExp(e.loc, null, e.type, ce.arguments);
auto ne = new NewExp(e.loc, null, null, e.type, ce.arguments);
ne.type = e.e1.type;

result = interpret(ne, istate);
Expand Down
5 changes: 4 additions & 1 deletion compiler/src/dmd/dsymbolsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -1304,9 +1304,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
ex = (cast(AssignExp)ex).e2;
if (auto ne = ex.isNewExp())
{
if (ne.placement)
{
}
/* See if initializer is a NewExp that can be allocated on the stack.
*/
if (dsym.type.toBasetype().ty == Tclass)
else if (dsym.type.toBasetype().ty == Tclass)
{
/* Unsafe to allocate on stack if constructor is not `scope` because the `this` can leak.
* https://issues.dlang.org/show_bug.cgi?id=23145
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dmd/dtemplate.d
Original file line number Diff line number Diff line change
Expand Up @@ -3008,6 +3008,8 @@
override void visit(NewExp e)
{
//printf("NewExp.reliesOnTemplateParameters('%s')\n", e.toChars());
if (e.placement)
e.placement.accept(this);

Check warning on line 3012 in compiler/src/dmd/dtemplate.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/dtemplate.d#L3011-L3012

Added lines #L3011 - L3012 were not covered by tests
if (e.thisexp)
e.thisexp.accept(this);
result = e.newtype.reliesOnTemplateParameters(tparams);
Expand Down
59 changes: 41 additions & 18 deletions compiler/src/dmd/e2ir.d
Original file line number Diff line number Diff line change
Expand Up @@ -1116,19 +1116,27 @@
elem *ezprefix = null;
elem *ez = null;

if (ne.onstack)
if (ne.onstack || ne.placement)
{
/* Create an instance of the class on the stack,
* and call it stmp.
* Set ex to be the &stmp.
*/
.type *tc = type_struct_class(tclass.sym.toChars(),
tclass.sym.alignsize, tclass.sym.structsize,
null, null,
false, false, true, false);
tc.Tcount--;
Symbol *stmp = symbol_genauto(tc);
ex = el_ptr(stmp);
if (ne.placement)
{
ex = toElem(ne.placement, irs);
ex = addressElem(ex, ne.newtype.toBasetype(), false);
}
else
{
/* Create an instance of the class on the stack,
* and call it stmp.
* Set ex to be the &stmp.
*/
.type *tc = type_struct_class(tclass.sym.toChars(),
tclass.sym.alignsize, tclass.sym.structsize,
null, null,
false, false, true, false);
tc.Tcount--;
Symbol *stmp = symbol_genauto(tc);
ex = el_ptr(stmp);
}

Symbol *si = toInitializer(tclass.sym);
elem *ei = el_var(si);
Expand Down Expand Up @@ -1255,8 +1263,13 @@
elem *ezprefix = null;
elem *ez = null;

// Call _d_newitemT()
if (auto lowering = ne.lowering)
if (ne.placement)
{
ex = toElem(ne.placement, irs);
ex = addressElem(ex, tclass, false);
}
else if (auto lowering = ne.lowering)
// Call _d_newitemT()
ex = toElem(ne.lowering, irs);
else
assert(0, "This case should have been rewritten to `_d_newitemT` in the semantic phase");
Expand All @@ -1266,7 +1279,7 @@
elem *ev = el_same(ex);

if (ne.argprefix)
ezprefix = toElem(ne.argprefix, irs);
ezprefix = toElem(ne.argprefix, irs);

Check warning on line 1282 in compiler/src/dmd/e2ir.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/e2ir.d#L1282

Added line #L1282 was not covered by tests
if (ne.member)
{
if (sd.isNested())
Expand Down Expand Up @@ -1298,10 +1311,12 @@
{
StructLiteralExp sle = StructLiteralExp.create(ne.loc, sd, ne.arguments, t);
ez = toElemStructLit(sle, irs, EXP.construct, ev.Vsym, false);
if (tybasic(ez.Ety) == TYstruct)
ez = el_una(OPaddr, TYnptr, ez);
}
//elem_print(ex);
//elem_print(ey);
//elem_print(ez);
//printf("ez:\n"); elem_print(ez);

e = el_combine(ex, ey);
e = el_combine(e, ew);
Expand All @@ -1321,8 +1336,16 @@
{
elem *ezprefix = ne.argprefix ? toElem(ne.argprefix, irs) : null;

// call _d_newitemT()
e = toElem(ne.lowering, irs);
if (ne.placement)
{
e = toElem(ne.placement, irs);
e = addressElem(e, ne.newtype.toBasetype(), false);
}
else if (auto lowering = ne.lowering)
// Call _d_newitemT()
e = toElem(ne.lowering, irs);
else
assert(0, "This case should have been rewritten to `_d_newitemT` in the semantic phase");

if (ne.arguments && ne.arguments.length == 1)
{
Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dmd/escape.d
Original file line number Diff line number Diff line change
Expand Up @@ -1635,6 +1635,9 @@ void escapeExp(Expression e, ref scope EscapeByResults er, int deref)

void visitNew(NewExp e)
{
if (e.placement)
escapeExp(e.placement, er, deref);

Type tb = e.newtype.toBasetype();
if (tb.isTypeStruct() && !e.member && e.arguments)
{
Expand Down
17 changes: 12 additions & 5 deletions compiler/src/dmd/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -2554,6 +2554,7 @@
Type newtype;
Expressions* arguments; // Array of Expression's
Identifiers* names; // Array of names corresponding to expressions
Expression placement; // if !=null, then PlacementExpression

Expression argprefix; // expression to be evaluated just before arguments[]
CtorDeclaration member; // constructor function
Expand All @@ -2566,23 +2567,25 @@
/// The fields are still separate for backwards compatibility
extern (D) ArgumentList argumentList() { return ArgumentList(arguments, names); }

extern (D) this(const ref Loc loc, Expression thisexp, Type newtype, Expressions* arguments, Identifiers* names = null) @safe
extern (D) this(const ref Loc loc, Expression placement, Expression thisexp, Type newtype, Expressions* arguments, Identifiers* names = null) @safe
{
super(loc, EXP.new_);
this.placement = placement;
this.thisexp = thisexp;
this.newtype = newtype;
this.arguments = arguments;
this.names = names;
}

static NewExp create(const ref Loc loc, Expression thisexp, Type newtype, Expressions* arguments) @safe
static NewExp create(const ref Loc loc, Expression placement, Expression thisexp, Type newtype, Expressions* arguments) @safe
{
return new NewExp(loc, thisexp, newtype, arguments);
return new NewExp(loc, placement, thisexp, newtype, arguments);

Check warning on line 2582 in compiler/src/dmd/expression.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expression.d#L2582

Added line #L2582 was not covered by tests
}

override NewExp syntaxCopy()
{
return new NewExp(loc,
placement ? placement.syntaxCopy() : null,
thisexp ? thisexp.syntaxCopy() : null,
newtype.syntaxCopy(),
arraySyntaxCopy(arguments),
Expand All @@ -2603,18 +2606,22 @@
Expression thisexp; // if !=null, 'this' for class being allocated
ClassDeclaration cd; // class being instantiated
Expressions* arguments; // Array of Expression's to call class constructor
Expression placement; // if !=null, then PlacementExpression

extern (D) this(const ref Loc loc, Expression thisexp, ClassDeclaration cd, Expressions* arguments) @safe
extern (D) this(const ref Loc loc, Expression placement, Expression thisexp, ClassDeclaration cd, Expressions* arguments) @safe
{
super(loc, EXP.newAnonymousClass);
this.placement = placement;
this.thisexp = thisexp;
this.cd = cd;
this.arguments = arguments;
}

override NewAnonClassExp syntaxCopy()
{
return new NewAnonClassExp(loc, thisexp ? thisexp.syntaxCopy() : null, cd.syntaxCopy(null), arraySyntaxCopy(arguments));
return new NewAnonClassExp(loc, placement ? placement.syntaxCopy : null,
thisexp ? thisexp.syntaxCopy() : null,
cd.syntaxCopy(null), arraySyntaxCopy(arguments));
}

override void accept(Visitor v)
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dmd/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ class NewExp final : public Expression
Type *newtype;
Expressions *arguments; // Array of Expression's
Identifiers *names; // Array of names corresponding to expressions
Expression *placement; // if !NULL, placement expression

Expression *argprefix; // expression to be evaluated just before arguments[]

Expand All @@ -518,7 +519,7 @@ class NewExp final : public Expression

Expression *lowering; // lowered druntime hook: `_d_newclass`

static NewExp *create(const Loc &loc, Expression *thisexp, Type *newtype, Expressions *arguments);
static NewExp *create(const Loc &loc, Expression *placement, Expression *thisexp, Type *newtype, Expressions *arguments);
NewExp *syntaxCopy() override;

void accept(Visitor *v) override { v->visit(this); }
Expand All @@ -532,6 +533,7 @@ class NewAnonClassExp final : public Expression
Expression *thisexp; // if !NULL, 'this' for class being allocated
ClassDeclaration *cd; // class being instantiated
Expressions *arguments; // Array of Expression's to call class constructor
Expression *placement; // if !NULL, placement expression

NewAnonClassExp *syntaxCopy() override;
void accept(Visitor *v) override { v->visit(this); }
Expand Down
Loading
Loading