From b56fa1d1b02c93151f0a25d868f4459cac8d6a4d Mon Sep 17 00:00:00 2001 From: k-hara Date: Sat, 6 Feb 2016 16:03:41 +0900 Subject: [PATCH] fix Issue 15490 - Error variable __nrvoretval cannot be modified at compile time when using -inline CTFE interpretr can recognize a form `CommaExp(DeclaraationExp(v), VarExp(v))` as a CTFEable variable declaration when `v._init` is `null`. In other cases, for examle a sole `DeclarationExp` should have v._init for CTFE-ability. Supply `VoidInitializer` to allow inlining the temporary for NRVO. --- src/dinterpret.d | 6 +++++- src/inline.d | 2 +- test/compilable/imports/imp15490a.d | 8 ++++++++ test/compilable/imports/imp15490b.d | 12 ++++++++++++ test/compilable/test15490.d | 12 ++++++++++++ 5 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 test/compilable/imports/imp15490a.d create mode 100644 test/compilable/imports/imp15490b.d create mode 100644 test/compilable/test15490.d diff --git a/src/dinterpret.d b/src/dinterpret.d index cb9d04bcfbc7..60a06deefad6 100644 --- a/src/dinterpret.d +++ b/src/dinterpret.d @@ -4916,9 +4916,13 @@ public: istate = &istateComma; } result = CTFEExp.cantexp; + // If the comma returns a temporary variable, it needs to be an lvalue // (this is particularly important for struct constructors) - if (e.e1.op == TOKdeclaration && e.e2.op == TOKvar && (cast(DeclarationExp)e.e1).declaration == (cast(VarExp)e.e2).var && (cast(VarExp)e.e2).var.storage_class & STCctfe) // same as Expression::isTemp + if (e.e1.op == TOKdeclaration && + e.e2.op == TOKvar && + (cast(DeclarationExp)e.e1).declaration == (cast(VarExp)e.e2).var && + (cast(VarExp)e.e2).var.storage_class & STCctfe) { VarExp ve = cast(VarExp)e.e2; VarDeclaration v = ve.var.isVarDeclaration(); diff --git a/src/inline.d b/src/inline.d index 50ab0176a1f1..137112f31684 100644 --- a/src/inline.d +++ b/src/inline.d @@ -2116,7 +2116,7 @@ void expandInline(FuncDeclaration fd, FuncDeclaration parent, Expression eret, else { Identifier tmp = Identifier.generateId("__nrvoretval"); - auto vd = new VarDeclaration(fd.loc, fd.nrvo_var.type, tmp, null); + auto vd = new VarDeclaration(fd.loc, fd.nrvo_var.type, tmp, new VoidInitializer(fd.loc)); assert(!tf.isref); vd.storage_class = STCtemp | STCrvalue; vd.linkage = tf.linkage; diff --git a/test/compilable/imports/imp15490a.d b/test/compilable/imports/imp15490a.d new file mode 100644 index 000000000000..edb3b45e6002 --- /dev/null +++ b/test/compilable/imports/imp15490a.d @@ -0,0 +1,8 @@ +module imports.imp15490a; + +import imports.imp15490b; + +void listenTCP() +{ + enum r = regex(); +} diff --git a/test/compilable/imports/imp15490b.d b/test/compilable/imports/imp15490b.d new file mode 100644 index 000000000000..3a2490c9f6c9 --- /dev/null +++ b/test/compilable/imports/imp15490b.d @@ -0,0 +1,12 @@ +module imports.imp15490b; + +int regex() +{ + return regexImpl(); +} + +auto regexImpl() +{ + int r = 0; + return r; +} diff --git a/test/compilable/test15490.d b/test/compilable/test15490.d new file mode 100644 index 000000000000..eab5c61a74c8 --- /dev/null +++ b/test/compilable/test15490.d @@ -0,0 +1,12 @@ +// REQUIRED_ARGS: -o- -inline +// PERMUTE_ARGS: +module test15490; + +import imports.imp15490a; +import imports.imp15490b; + +void main() +{ + regex(); + listenTCP(); +}