diff --git a/compiler/src/dmd/astbase.d b/compiler/src/dmd/astbase.d index bdc489871c36..1d91dd290df8 100644 --- a/compiler/src/dmd/astbase.d +++ b/compiler/src/dmd/astbase.d @@ -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) { super(loc, EXP.newAnonymousClass, __traits(classInstanceSize, NewAnonClassExp)); + this.placement = placement; this.thisexp = thisexp; this.cd = cd; this.arguments = arguments; @@ -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) { super(loc, EXP.new_, __traits(classInstanceSize, NewExp)); + this.placement = placement; this.thisexp = thisexp; this.newtype = newtype; this.arguments = arguments; diff --git a/compiler/src/dmd/dinterpret.d b/compiler/src/dmd/dinterpret.d index 4e04a272141a..f21c4aafbae6 100644 --- a/compiler/src/dmd/dinterpret.d +++ b/compiler/src/dmd/dinterpret.d @@ -5067,7 +5067,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); diff --git a/compiler/src/dmd/expression.d b/compiler/src/dmd/expression.d index 3c79b02caa02..a05ff9092732 100644 --- a/compiler/src/dmd/expression.d +++ b/compiler/src/dmd/expression.d @@ -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 @@ -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); } override NewExp syntaxCopy() { return new NewExp(loc, + placement ? placement.syntaxCopy() : null, thisexp ? thisexp.syntaxCopy() : null, newtype.syntaxCopy(), arraySyntaxCopy(arguments), @@ -2603,10 +2606,12 @@ 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; @@ -2614,7 +2619,9 @@ extern (C++) final class NewAnonClassExp : Expression 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) diff --git a/compiler/src/dmd/expression.h b/compiler/src/dmd/expression.h index c353a191a662..39e6994e44dc 100644 --- a/compiler/src/dmd/expression.h +++ b/compiler/src/dmd/expression.h @@ -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[] @@ -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); } @@ -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); } diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index 0e6bc114709d..4dca24015287 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -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: @@ -5555,7 +5555,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); diff --git a/compiler/src/dmd/frontend.h b/compiler/src/dmd/frontend.h index b36f54f6fbb8..ebccb5ab3e0f 100644 --- a/compiler/src/dmd/frontend.h +++ b/compiler/src/dmd/frontend.h @@ -3117,6 +3117,7 @@ class NewAnonClassExp final : public Expression Expression* thisexp; ClassDeclaration* cd; Array* arguments; + Expression* placement; NewAnonClassExp* syntaxCopy() override; void accept(Visitor* v) override; }; @@ -3128,12 +3129,13 @@ class NewExp final : public Expression Type* newtype; Array* arguments; Array* names; + Expression* placement; Expression* argprefix; CtorDeclaration* member; bool onstack; bool thrownew; Expression* lowering; - static NewExp* create(const Loc& loc, Expression* thisexp, Type* newtype, Array* arguments); + static NewExp* create(const Loc& loc, Expression* placement, Expression* thisexp, Type* newtype, Array* arguments); NewExp* syntaxCopy() override; void accept(Visitor* v) override; }; diff --git a/compiler/src/dmd/parse.d b/compiler/src/dmd/parse.d index e8324eb07106..2cd46b88dbbd 100644 --- a/compiler/src/dmd/parse.d +++ b/compiler/src/dmd/parse.d @@ -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); + } + AST.Expressions* arguments = null; AST.Identifiers* names = null; @@ -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; } @@ -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; } diff --git a/compiler/src/tests/cxxfrontend.cc b/compiler/src/tests/cxxfrontend.cc index 51669b51a8e1..3450d02b2a5d 100644 --- a/compiler/src/tests/cxxfrontend.cc +++ b/compiler/src/tests/cxxfrontend.cc @@ -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);