Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Strive for a sane evaluation order of arguments when using argprefix
If argprefix is required, make sure it covers the very first argument up to and including the last potentially throwing argument. Only evaluate subsequent arguments directly. This also includes ref and out params, but not lazy ones. Note that previously, `appendToPrefix` would be set by the first arg with dtor (if a subsequent arg may throw), and only reset when processing the last throwing arg (i == lastthrow). So all non-ref/out/lazy args inbetween would be added to `eprefix`, leading to this staggering evaluation order: [firstDtor..lastThrow (except for ref/out/lazy)] [0..firstDtor] [firstDtor..lastThrow (only ref/out/lazy)] [lastThrow..$] Also prepare for potential right-to-left arguments evaluation order (array ops).
- Loading branch information
Showing
2 changed files
with
200 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import core.stdc.stdio : printf; | ||
|
||
__gshared int counter; | ||
|
||
int getID(int expectedID) nothrow { | ||
printf("getID: counter = %d, expecting %d\n", counter, expectedID); | ||
assert(counter == expectedID); | ||
++counter; | ||
return expectedID; | ||
} | ||
|
||
ref int getCounterRef(int expectedID) nothrow { | ||
getID(expectedID); | ||
return counter; | ||
} | ||
|
||
struct StructWithDtor { | ||
__gshared int numDtor; | ||
int id; | ||
|
||
this(int expectedID) nothrow { | ||
printf("constructing %d\n", expectedID); | ||
this.id = getID(expectedID); | ||
} | ||
|
||
~this() nothrow { | ||
printf("destructing %d\n", id); | ||
++numDtor; | ||
} | ||
} | ||
|
||
StructWithDtor make(int expectedID, bool doThrow) { | ||
if (doThrow) | ||
throw new Exception("make()"); | ||
return StructWithDtor(expectedID); | ||
} | ||
|
||
void evaluationOrder(int a, int b, StructWithDtor c, int d, int e, ref int f, StructWithDtor g, int h, int i) { | ||
assert(f is counter); | ||
} | ||
void evaluationOrderTest() { | ||
counter = StructWithDtor.numDtor = 0; | ||
evaluationOrder(getID(0), getID(1), StructWithDtor(2), getID(3), getID(4), getCounterRef(5), make(6, false), getID(7), getID(8)); | ||
assert(counter == 9); | ||
|
||
// TODO: add right-to-left test (array ops) | ||
} | ||
|
||
void dtors(StructWithDtor a, StructWithDtor b, StructWithDtor c, StructWithDtor d) { | ||
throw new Exception("dtors()"); | ||
} | ||
void dtorsTest() { | ||
// no throw in args, but in callee | ||
counter = StructWithDtor.numDtor = 0; | ||
try { | ||
dtors(StructWithDtor(0), make(1, false), StructWithDtor(2), make(3, false)); | ||
assert(0); | ||
} catch (Exception) {} | ||
assert(counter == 4); | ||
assert(StructWithDtor.numDtor == 4); | ||
|
||
// throw in last arg | ||
counter = StructWithDtor.numDtor = 0; | ||
try { | ||
dtors(StructWithDtor(0), make(1, false), StructWithDtor(2), make(3, true)); | ||
assert(0); | ||
} catch (Exception) {} | ||
assert(counter == 3); | ||
assert(StructWithDtor.numDtor == 3); | ||
|
||
// throw in 2nd arg | ||
counter = StructWithDtor.numDtor = 0; | ||
try { | ||
dtors(StructWithDtor(0), make(1, true), StructWithDtor(2), make(3, true)); | ||
assert(0); | ||
} catch (Exception) {} | ||
assert(counter == 1); | ||
assert(StructWithDtor.numDtor == 1); | ||
|
||
// TODO: test exception chaining with throwing dtors | ||
} | ||
|
||
void main() { | ||
evaluationOrderTest(); | ||
dtorsTest(); | ||
} |