| extern (C) int printf(const(char*) fmt, ...); |
| |
| static int foo(); |
| |
| /**********************************/ |
| |
| auto red()() |
| { |
| return foo(); |
| } |
| |
| void test13350() |
| { |
| int[] data; |
| assert(is(typeof(red()))); |
| } |
| |
| /**********************************/ |
| |
| struct A1(T) { void f1() {} } |
| struct B1(T) { void f2() {} } |
| |
| A1!(B1!int) func1()() { return typeof(return).init; } |
| |
| void test1() |
| { |
| static if (is(typeof(func1()) R : X!(Y), alias X, Y)) |
| { |
| R.init.f1(); |
| Y.init.f2(); |
| } |
| else |
| static assert(0); |
| } |
| |
| /**********************************/ |
| |
| struct A2(T) { void f1() { foo(); } } |
| struct B2(T) { void f2() { foo(); } } |
| |
| A2!(B2!int) func2()() { return typeof(return).init; } |
| |
| void test2() |
| { |
| static if (is(typeof(func2()))) |
| { |
| } |
| else |
| static assert(0); |
| } |
| |
| /**********************************/ |
| |
| template A3() { void foo() { B3!().bar(); } } |
| template B3() { void bar() {} } |
| |
| void test3() |
| { |
| // A3!() and B3!() are marked as 'speculative' |
| static assert(is(typeof(A3!().foo()))); |
| |
| // A3!() is unspeculative, but B3!() isn't. |
| A3!().foo(); |
| |
| // in codegen phase, B3!() will generate its members, because |
| // the tinst chain contains unspeculative instance A3!(). |
| } |
| |
| /**********************************/ |
| |
| struct S4(T) |
| { |
| string toString() const { return "instantiated"; } |
| } |
| |
| void test4() |
| { |
| // inside typeof is not speculative context |
| alias X = typeof(S4!int()); |
| assert(typeid(X).xtoString !is null); |
| } |
| |
| /**********************************/ |
| |
| struct S5(T) |
| { |
| string toString() const { return "instantiated"; } |
| } |
| |
| void test5() |
| { |
| enum x = S5!int(); |
| assert(x.toString() == "instantiated"); |
| } |
| |
| /**********************************/ |
| |
| int foo6()() { return 0; } |
| |
| template A6() { alias f = foo6!(); } |
| void testa6()() if (is(typeof(A6!().f))) {} |
| |
| template B6() { alias f = foo6!(); } |
| void testb6()() if (is(typeof(B6!().f))) {} |
| |
| template C6() { void f() { B6!().f(); } } |
| |
| void test6() |
| { |
| testa6(); |
| // foo6!() is speculatively instantiated from A6!() [TemplateInstance a] |
| // -> foo6!() is instantiated in A6!(), so it should be inserted to the members of this module. |
| |
| testb6(); |
| // foo6!() is speculatively instantiated from B6!() [TemplateInstance b], |
| // but the tinst of cached [TemplateInstance a] is not changed. |
| // -> insert [b] to the tnext chain of [a] |
| |
| C6!().f(); |
| // foo6!() is used through C6!(), so it should be linked to the final executable. |
| // but its first instance does not link to any non-speculative instances. |
| // -> look for tnext chain and determine its codegen is really necessary. |
| } |
| |
| /**********************************/ |
| |
| int main() |
| { |
| test13350(); |
| test1(); |
| test2(); |
| test3(); |
| test4(); |
| test5(); |
| test6(); |
| |
| printf("Success\n"); |
| return 0; |
| } |