| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| // PERMUTE_ARGS: | ||
|
|
||
| struct A(T) { ~this() {} } | ||
| class C { A!int[1] array; } | ||
|
|
||
| void test14838() pure nothrow @nogc @safe | ||
| { | ||
| C c; | ||
| c.__xdtor(); // C.~this() will also be inferred to | ||
| // pure nothrow @nogc @safe | ||
|
|
||
| A!int[1] array; | ||
| // scope destructor call does not cause attribute violation. | ||
| } | ||
|
|
||
| // ---- | ||
|
|
||
| /* | ||
| * This is a reduced test case comes from std.container.Array template, | ||
| * to fix the semantic analysis order issue for correct destructor attribute inference. | ||
| * | ||
| * Before the bugfix: | ||
| * 1. StructDeclaration('Array!int')->semantic() instantiates | ||
| * RangeT!(Array!int) at the `alias Range = ...;`, but | ||
| * StructDeclaration('RangeT!(Array!int)')->semantic() exits | ||
| * with sizeok == SIZEOKfwd, because the size of _outer_ field is not yet determined. | ||
| * 2. StructDeclaration('Array!int')->semantic() succeeds to determine the size | ||
| * (sizeok = SIZEOKdone). | ||
| * 3. StructDeclaration('Array!int')->buildOpAssign() will generate opAssign because | ||
| * Array!int._data field has identity opAssign member function. | ||
| * 4. The semantic3 will get called for the generated opAssign, then | ||
| * 6-1. Array!int.~this() semantic3, and | ||
| * 6-2. RefCounted!(Array!int.Payload).~this() semantic3 | ||
| * will also get called to infer their attributes. | ||
| * 5. In RefCounted!(Array!int.Payload).~this(), destroy(t) will be instantiated. | ||
| * At that, TemplateInstance::expandMembers() will invoke runDeferredSemantic() | ||
| * and it will re-run StructDeclaration('RangeT!(Array!int)')->semantic(). | ||
| * 6. StructDeclaration('RangeT!(Array!int)')->semantic() determines the size | ||
| * (sizeok = SIZEOKdone). Then, it will generate identity opAssign and run its semantic3. | ||
| * It will need to infer RangeT!(Array!int).~this() attribute, then it requires the | ||
| * correct attribute of Array!int.~this(). | ||
| * | ||
| * However, the Array!int.~this() attribute is not yet determined! [bug] | ||
| * -> it's wongly handled as impure/system/throwable/gc-able. | ||
| * | ||
| * -> then, the attribute inference results for | ||
| * RangeT!(Array!int).~this() and Array!int.~this() will be incorrect. | ||
| * | ||
| * After the bugfix: | ||
| * In 6, StructDeclaration('RangeT!(Array!int)')->semantic() will check that: | ||
| * all base struct types of the instance fields have completed addition of | ||
| * special functions (dtor, opAssign, etc). | ||
| * If not, it will defer the completion of its semantic pass. | ||
| */ | ||
|
|
||
| void destroy14838(S)(ref S s) if (is(S == struct)) | ||
| { | ||
| s.__xdtor(); | ||
| } | ||
|
|
||
| struct RefCounted14838(T) | ||
| { | ||
| ~this() | ||
| { | ||
| T t; | ||
| .destroy14838(t); | ||
| } | ||
|
|
||
| void opAssign(typeof(this) rhs) {} | ||
| } | ||
|
|
||
| struct RangeT14838(A) | ||
| { | ||
| A[1] _outer_; | ||
| } | ||
|
|
||
| struct Array14838(T) | ||
| { | ||
| struct Payload | ||
| { | ||
| ~this() {} | ||
| } | ||
| RefCounted14838!Payload _data; | ||
|
|
||
| alias Range = RangeT14838!Array14838; | ||
| } | ||
|
|
||
| class Test14838 | ||
| { | ||
| Array14838!int[1] field; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| module link14834a; | ||
|
|
||
| struct DirIterator | ||
| { | ||
| int i = 1; | ||
|
|
||
| @property bool empty() { return i == 0; } | ||
| @property int front() { return 10; } | ||
| void popFront() { --i; } | ||
| } | ||
|
|
||
| auto dirEntries(string path) | ||
| { | ||
| bool f(int x) | ||
| { | ||
| assert(path == "."); // should pass | ||
| return true; | ||
| } | ||
| return filter!f(DirIterator()); | ||
| } | ||
|
|
||
| template filter(alias pred) | ||
| { | ||
| auto filter(R)(R range) | ||
| { | ||
| return FilterResult!(pred, R)(range); | ||
| } | ||
| } | ||
|
|
||
| struct FilterResult(alias pred, R) | ||
| { | ||
| R input; | ||
|
|
||
| this(R r) | ||
| { | ||
| input = r; | ||
| while (!input.empty && !pred(input.front)) | ||
| { | ||
| input.popFront(); | ||
| } | ||
| } | ||
|
|
||
| @property bool empty() { return input.empty; } | ||
|
|
||
| @property auto ref front() | ||
| { | ||
| return input.front; | ||
| } | ||
|
|
||
| void popFront() | ||
| { | ||
| do | ||
| { | ||
| input.popFront(); | ||
| } while (!input.empty && !pred(input.front)); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| import link14834a; | ||
|
|
||
| void main() | ||
| { | ||
| foreach (n; dirEntries(".")) | ||
| { | ||
| assert(n == 10); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| module imports.link14814a; | ||
|
|
||
| void fun0() | ||
| { | ||
| } | ||
|
|
||
| void fun4() | ||
| { | ||
| void function()[TypeInfo] funs; | ||
| funs[typeid(int)] = &fun0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| // EXTRA_SOURCES: imports/link14814a.d | ||
| // PERMUTE_ARGS: -inline -release -g -O -fPIC | ||
| // COMPILE_SEPARATELY | ||
|
|
||
| import imports.link14814a; | ||
|
|
||
| void main() | ||
| { | ||
| fun4; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| src=runnable${SEP}extra-files | ||
| dir=${RESULTS_DIR}${SEP}runnable | ||
| output_file=${dir}${SEP}link14834.sh.out | ||
|
|
||
| rm -f ${output_file} | ||
|
|
||
| if [ $OS == "win32" -o $OS == "win64" ]; then | ||
| LIBEXT=.lib | ||
| else | ||
| LIBEXT=.a | ||
| fi | ||
|
|
||
| libname=${dir}${SEP}link14834${LIBEXT} | ||
| exename=${dir}${SEP}link14834${EXE} | ||
|
|
||
| $DMD -m${MODEL} -I${src} -lib -of${libname} ${src}${SEP}link14834a.d > ${output_file} || exit 1 | ||
| $DMD -m${MODEL} -I${src} -inline -debug -of${exename} ${src}${SEP}link14834b.d ${libname} > ${output_file} || exit 1 | ||
|
|
||
| ${dir}/link14834 || exit 1 | ||
|
|
||
| rm ${libname} ${exename} ${dir}${SEP}link14834${OBJ} | ||
|
|
||
| echo Success > ${output_file} |