Skip to content

Commit

Permalink
add Placement New
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Nov 10, 2024
1 parent 7c8e8ec commit 4db86a4
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 16 deletions.
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 @@ struct ASTBase
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 @@ struct ASTBase
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 @@ public:
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 @@ public:
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
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 @@ extern (C++) final class NewExp : Expression
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 @@ extern (C++) final class NewExp : Expression
/// 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 @@ extern (C++) final class NewAnonClassExp : 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, 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
17 changes: 15 additions & 2 deletions compiler/src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -3130,7 +3130,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
auto args = new Expressions(nargs - i);
foreach (u; i .. nargs)
(*args)[u - i] = (*arguments)[u];
arg = new NewExp(loc, null, p.type, args);
arg = new NewExp(loc, null, null, p.type, args);
break;
}
default:
Expand Down Expand Up @@ -4902,6 +4902,19 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}

if (exp.placement)
{
exp.placement = exp.placement.expressionSemantic(sc);
auto p = exp.placement;
if (p.op == EXP.error)
return setError();
if (!p.isLvalue())

Check warning on line 4911 in compiler/src/dmd/expressionsem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expressionsem.d#L4907-L4911

Added lines #L4907 - L4911 were not covered by tests
{
error(p.loc, "PlacementExpression `%s` is an rvalue, but must be an lvalue", p.toChars());
return setError();

Check warning on line 4914 in compiler/src/dmd/expressionsem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expressionsem.d#L4913-L4914

Added lines #L4913 - L4914 were not covered by tests
}
}

//for error messages if the argument in [] is not convertible to size_t
const originalNewtype = exp.newtype;

Expand Down Expand Up @@ -5555,7 +5568,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
sds.members.push(e.cd);
}

Expression n = new NewExp(e.loc, e.thisexp, e.cd.type, e.arguments);
Expression n = new NewExp(e.loc, e.placement, e.thisexp, e.cd.type, e.arguments);

Expression c = new CommaExp(e.loc, d, n);
result = c.expressionSemantic(sc);
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dmd/frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -3117,6 +3117,7 @@ class NewAnonClassExp final : public Expression
Expression* thisexp;
ClassDeclaration* cd;
Array<Expression* >* arguments;
Expression* placement;
NewAnonClassExp* syntaxCopy() override;
void accept(Visitor* v) override;
};
Expand All @@ -3128,12 +3129,13 @@ class NewExp final : public Expression
Type* newtype;
Array<Expression* >* arguments;
Array<Identifier* >* names;
Expression* placement;
Expression* argprefix;
CtorDeclaration* member;
bool onstack;
bool thrownew;
Expression* lowering;
static NewExp* create(const Loc& loc, Expression* thisexp, Type* newtype, Array<Expression* >* arguments);
static NewExp* create(const Loc& loc, Expression* placement, Expression* thisexp, Type* newtype, Array<Expression* >* arguments);
NewExp* syntaxCopy() override;
void accept(Visitor* v) override;
};
Expand Down
16 changes: 13 additions & 3 deletions compiler/src/dmd/parse.d
Original file line number Diff line number Diff line change
Expand Up @@ -9516,7 +9516,17 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
{
const loc = token.loc;

nextToken();
nextToken(); // skip past `new`

// parse PlacementExpression if any
AST.Expression placement;
if (token.value == TOK.leftParenthesis)
{
nextToken();
placement = parseAssignExp();
check(TOK.rightParenthesis);

Check warning on line 9527 in compiler/src/dmd/parse.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/parse.d#L9525-L9527

Added lines #L9525 - L9527 were not covered by tests
}

AST.Expressions* arguments = null;
AST.Identifiers* names = null;

Expand Down Expand Up @@ -9552,7 +9562,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
}

auto cd = new AST.ClassDeclaration(loc, id, baseclasses, members, false);
auto e = new AST.NewAnonClassExp(loc, thisexp, cd, arguments);
auto e = new AST.NewAnonClassExp(loc, placement, thisexp, cd, arguments);
return e;
}

Expand All @@ -9576,7 +9586,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
parseNamedArguments(arguments, names);
}

auto e = new AST.NewExp(loc, thisexp, t, arguments, names);
auto e = new AST.NewExp(loc, placement, thisexp, t, arguments, names);
return e;
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/src/tests/cxxfrontend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1351,7 +1351,7 @@ class MiniGlueVisitor : public Visitor
(void)d->csym;
(void)d->vtblSymbol()->csym;
(void)d->sinit;
NewExp *ne = NewExp::create(d->loc, NULL, d->type, NULL);
NewExp *ne = NewExp::create(d->loc, NULL, NULL, d->type, NULL);
ne->type = d->type;
Expression *e = dmd::ctfeInterpret(ne);
assert(e->op == EXP::classReference);
Expand Down

0 comments on commit 4db86a4

Please sign in to comment.