| // PERMUTE_ARGS: -property |
| /* |
| TEST_OUTPUT: |
| --- |
| decl: test |
| stmt: test |
| --- |
| |
| RUN_OUTPUT: |
| --- |
| 0: getter |
| 1: setter |
| 2: getter |
| 3: setter |
| 4: setter |
| 5: compile error |
| 6: compile error |
| 7: setter |
| Success |
| --- |
| */ |
| |
| extern (C) int printf(const char* fmt, ...); |
| |
| // Is -property option specified? |
| enum enforceProperty = !__traits(compiles, { |
| int prop(){ return 1; } |
| int n = prop; |
| }); |
| |
| /*******************************************/ |
| |
| template select(alias v1, alias v2) |
| { |
| static if (enforceProperty) |
| enum select = v1; |
| else |
| enum select = v2; |
| } |
| |
| struct Test(int N) |
| { |
| int value; |
| int getset; |
| |
| static if (N == 0) |
| { |
| ref foo(){ getset = 1; return value; } |
| |
| enum result = select!(0, 1); |
| // -property test.d(xx): Error: not a property foo |
| // (no option) prints "getter" |
| } |
| static if (N == 1) |
| { |
| ref foo(int x){ getset = 2; value = x; return value; } |
| |
| enum result = select!(0, 2); |
| // -property test.d(xx): Error: not a property foo |
| // (no option) prints "setter" |
| } |
| static if (N == 2) |
| { |
| @property ref foo(){ getset = 1; return value; } |
| |
| enum result = select!(1, 1); |
| // -property prints "getter" |
| // (no option) prints "getter" |
| } |
| static if (N == 3) |
| { |
| @property ref foo(int x){ getset = 2; value = x; return value; } |
| |
| enum result = select!(2, 2); |
| // -property prints "setter" |
| // (no option) prints "setter" |
| } |
| |
| |
| static if (N == 4) |
| { |
| ref foo() { getset = 1; return value; } |
| ref foo(int x){ getset = 2; value = x; return value; } |
| |
| enum result = select!(0, 2); |
| // -property test.d(xx): Error: not a property foo |
| // (no option) prints "setter" |
| } |
| static if (N == 5) |
| { |
| @property ref foo() { getset = 1; return value; } |
| ref foo(int x){ getset = 2; value = x; return value; } |
| |
| enum result = select!(0, 0); |
| // -property test.d(xx): Error: cannot overload both property and non-property functions |
| // (no option) test.d(xx): Error: cannot overload both property and non-property functions |
| } |
| static if (N == 6) |
| { |
| ref foo() { getset = 1; return value; } |
| @property ref foo(int x){ getset = 2; value = x; return value; } |
| |
| enum result = select!(0, 0); |
| // -property test.d(xx): Error: cannot overload both property and non-property functions |
| // (no option) test.d(xx): Error: cannot overload both property and non-property functions |
| } |
| static if (N == 7) |
| { |
| @property ref foo() { getset = 1; return value; } |
| @property ref foo(int x){ getset = 2; value = x; return value; } |
| |
| enum result = select!(2, 2); |
| // -property prints "setter" |
| // (no option) prints "setter" |
| } |
| } |
| |
| template seq(T...) |
| { |
| alias T seq; |
| } |
| template iota(int begin, int end) |
| if (begin <= end) |
| { |
| static if (begin == end) |
| alias seq!() iota; |
| else |
| alias seq!(begin, iota!(begin+1, end)) iota; |
| } |
| |
| void test1() |
| { |
| foreach (N; iota!(0, 8)) |
| { |
| printf("%d: ", N); |
| |
| Test!N s; |
| static if (Test!N.result == 0) |
| { |
| static assert(!is(typeof({ s.foo = 1; }))); |
| printf("compile error\n"); |
| } |
| else |
| { |
| s.foo = 1; |
| if (s.getset == 1) |
| printf("getter\n"); |
| else |
| printf("setter\n"); |
| assert(s.getset == Test!N.result); |
| } |
| } |
| } |
| |
| /*******************************************/ |
| // 7722 |
| |
| class Foo7722 {} |
| void spam7722(Foo7722 f) {} |
| |
| void test7722() |
| { |
| auto f = new Foo7722; |
| static if (enforceProperty) |
| static assert(!__traits(compiles, f.spam7722)); |
| else |
| f.spam7722; |
| } |
| |
| /*******************************************/ |
| |
| @property void check(alias v1, alias v2, alias dg)() |
| { |
| void checkImpl(alias v)() |
| { |
| static if (v == 0) |
| static assert(!__traits(compiles, dg(0))); |
| else |
| assert(dg(0) == v); |
| } |
| |
| static if (enforceProperty) |
| checkImpl!(v1)(); |
| else |
| checkImpl!(v2)(); |
| } |
| |
| struct S {} |
| |
| int foo(int n) { return 1; } |
| int foo(int n, int m) { return 2; } |
| int goo(int[] a) { return 1; } |
| int goo(int[] a, int m) { return 2; } |
| int bar(S s) { return 1; } |
| int bar(S s, int n) { return 2; } |
| |
| int baz(X)(X x) { return 1; } |
| int baz(X)(X x, int n) { return 2; } |
| |
| int temp; |
| ref int boo(int n) { return temp; } |
| ref int coo(int[] a) { return temp; } |
| ref int mar(S s) { return temp; } |
| |
| ref int maz(X)(X x) { return temp; } |
| |
| void test7722a() |
| { |
| int n; |
| int[] a; |
| S s; |
| |
| check!(1, 1, x => foo(4) ); check!(1, 1, x => baz(4) ); |
| check!(1, 1, x => 4.foo() ); check!(1, 1, x => 4.baz() ); |
| check!(0, 1, x => 4.foo ); check!(0, 1, x => 4.baz ); |
| check!(2, 2, x => foo(4, 2) ); check!(2, 2, x => baz(4, 2) ); |
| check!(2, 2, x => 4.foo(2) ); check!(2, 2, x => 4.baz(2) ); |
| check!(0, 2, x => (4.foo = 2) ); check!(0, 2, x => (4.baz = 2) ); |
| |
| check!(1, 1, x => goo(a) ); check!(1, 1, x => baz(a) ); |
| check!(1, 1, x => a.goo() ); check!(1, 1, x => a.baz() ); |
| check!(0, 1, x => a.goo ); check!(0, 1, x => a.baz ); |
| check!(2, 2, x => goo(a, 2) ); check!(2, 2, x => baz(a, 2) ); |
| check!(2, 2, x => a.goo(2) ); check!(2, 2, x => a.baz(2) ); |
| check!(0, 2, x => (a.goo = 2) ); check!(0, 2, x => (a.baz = 2) ); |
| |
| check!(1, 1, x => bar(s) ); check!(1, 1, x => baz(s) ); |
| check!(1, 1, x => s.bar() ); check!(1, 1, x => s.baz() ); |
| check!(0, 1, x => s.bar ); check!(0, 1, x => s.baz ); |
| check!(2, 2, x => bar(s, 2) ); check!(2, 2, x => baz(s, 2) ); |
| check!(2, 2, x => s.bar(2) ); check!(2, 2, x => s.baz(2) ); |
| check!(0, 2, x => (s.bar = 2) ); check!(0, 2, x => (s.baz = 2) ); |
| |
| check!(2, 2, x => ( boo(4) = 2)); check!(2, 2, x => ( maz(4) = 2)); |
| check!(0, 2, x => (4.boo = 2)); check!(0, 2, x => (4.maz = 2)); |
| check!(2, 2, x => ( coo(a) = 2)); check!(2, 2, x => ( maz(a) = 2)); |
| check!(0, 2, x => (a.coo = 2)); check!(0, 2, x => (a.maz = 2)); |
| check!(2, 2, x => ( mar(s) = 2)); check!(2, 2, x => ( maz(s) = 2)); |
| check!(0, 2, x => (s.mar = 2)); check!(0, 2, x => (s.maz = 2)); |
| } |
| |
| int hoo(T)(int n) { return 1; } |
| int hoo(T)(int n, int m) { return 2; } |
| int koo(T)(int[] a) { return 1; } |
| int koo(T)(int[] a, int m) { return 2; } |
| int var(T)(S s) { return 1; } |
| int var(T)(S s, int n) { return 2; } |
| |
| int vaz(T, X)(X x) { return 1; } |
| int vaz(T, X)(X x, int n) { return 2; } |
| |
| //int temp; |
| ref int voo(T)(int n) { return temp; } |
| ref int woo(T)(int[] a) { return temp; } |
| ref int nar(T)(S s) { return temp; } |
| |
| ref int naz(T, X)(X x) { return temp; } |
| |
| void test7722b() |
| { |
| int n; |
| int[] a; |
| S s; |
| |
| check!(1, 1, x => hoo!int(4) ); check!(1, 1, x => vaz!int(4) ); |
| check!(1, 1, x => 4.hoo!int() ); check!(1, 1, x => 4.vaz!int() ); |
| check!(0, 1, x => 4.hoo!int ); check!(0, 1, x => 4.vaz!int ); |
| check!(2, 2, x => hoo!int(4, 2) ); check!(2, 2, x => vaz!int(4, 2) ); |
| check!(2, 2, x => 4.hoo!int(2) ); check!(2, 2, x => 4.vaz!int(2) ); |
| check!(0, 2, x => (4.hoo!int = 2) ); check!(0, 2, x => (4.vaz!int = 2) ); |
| |
| check!(1, 1, x => koo!int(a) ); check!(1, 1, x => vaz!int(a) ); |
| check!(1, 1, x => a.koo!int() ); check!(1, 1, x => a.vaz!int() ); |
| check!(0, 1, x => a.koo!int ); check!(0, 1, x => a.vaz!int ); |
| check!(2, 2, x => koo!int(a, 2) ); check!(2, 2, x => vaz!int(a, 2) ); |
| check!(2, 2, x => a.koo!int(2) ); check!(2, 2, x => a.vaz!int(2) ); |
| check!(0, 2, x => (a.koo!int = 2) ); check!(0, 2, x => (a.vaz!int = 2) ); |
| |
| check!(1, 1, x => var!int(s) ); check!(1, 1, x => vaz!int(s) ); |
| check!(1, 1, x => s.var!int() ); check!(1, 1, x => s.vaz!int() ); |
| check!(0, 1, x => s.var!int ); check!(0, 1, x => s.vaz!int ); |
| check!(2, 2, x => var!int(s, 2) ); check!(2, 2, x => vaz!int(s, 2) ); |
| check!(2, 2, x => s.var!int(2) ); check!(2, 2, x => s.vaz!int(2) ); |
| check!(0, 2, x => (s.var!int = 2) ); check!(0, 2, x => (s.vaz!int = 2) ); |
| |
| check!(2, 2, x => ( voo!int(4) = 2)); check!(2, 2, x => ( naz!int(4) = 2)); |
| check!(0, 2, x => (4.voo!int = 2)); check!(0, 2, x => (4.naz!int = 2)); |
| check!(2, 2, x => ( woo!int(a) = 2)); check!(2, 2, x => ( naz!int(a) = 2)); |
| check!(0, 2, x => (a.woo!int = 2)); check!(0, 2, x => (a.naz!int = 2)); |
| check!(2, 2, x => ( nar!int(s) = 2)); check!(2, 2, x => ( naz!int(s) = 2)); |
| check!(0, 2, x => (s.nar!int = 2)); check!(0, 2, x => (s.naz!int = 2)); |
| } |
| |
| /*******************************************/ |
| // 7174 |
| |
| void test7174() |
| { |
| @property bool foo7174() { return true; } |
| static if (foo7174) {} |
| } |
| |
| /***************************************************/ |
| // 7274 |
| |
| @property foo7274(){ return "test"; } |
| @property bar7274(){ return "kernel32.lib"; } |
| |
| pragma(msg, "decl: ", foo7274); // print "decl: foo", not "decl: test" |
| version(Windows) pragma(lib, bar7274); // Error: pragma lib string expected for library name, not 'bar' |
| |
| void test7274() |
| { |
| pragma(msg, "stmt: ", foo7274); // print "stmt: foo", not "stmt: test" |
| //pragma(lib, bar); // Error: pragma(lib) not allowed as statement |
| } |
| |
| /***************************************************/ |
| // 7275 |
| |
| void test7275() |
| { |
| @property int bar1() { return 0; } |
| @property int bar2() { return 1; } |
| @property int bar3() { return 2; } |
| |
| switch (0){ |
| case bar1: break; |
| case bar2: .. |
| case bar3: break; |
| default: break; |
| } |
| } |
| |
| /*****************************************/ |
| // 7538 |
| |
| void test7538() |
| { |
| struct P |
| { |
| @property long pr() { return 1; } |
| @property void pr(int) {} |
| |
| @property long a1()() { return 1; } |
| @property void a1()(int) {} |
| template a2() { @property long a2() { return 1; } } |
| template a2() { @property void a2(int) {} } |
| template a3() { long a3() @property { return 1; } } |
| template a3() { void a3(int) @property {} } |
| |
| static |
| { |
| @property long b1()() { return 1; } |
| @property void b1()(int) {} |
| template b2() { @property long b2() { return 1; } } |
| template b2() { @property void b2(int) {} } |
| template b3() { long b3() @property { return 1; } } |
| template b3() { void b3(int) @property {} } |
| } |
| |
| @property long c1(T)() { return 1; } |
| @property long c1(T)(int) { return 1; } |
| template c2(T) { @property long c2() { return 1; } } |
| template c2(T) { @property void c2(int) {} } |
| template c3(T) { long c3() @property { return 1; } } |
| template c3(T) { void c3(int) @property {} } |
| |
| static |
| { |
| @property long d1(T)() { return 1; } |
| @property void d1(T)(int) {} |
| template d2(T) { @property long d2() { return 1; } } |
| template d2(T) { @property void d2(int) {} } |
| template d3(T) { long d3() @property { return 1; } } |
| template d3(T) { void d3(int) @property {} } |
| } |
| |
| void test() |
| { |
| // TOKvar |
| static assert(is(typeof(pr) == long)); |
| |
| // TOKtemplate |
| static assert(is(typeof(b1) == long)); |
| static assert(is(typeof(b2) == long)); |
| static assert(is(typeof(b3) == long)); |
| |
| // TOKimport |
| static assert(is(typeof(d1!int) == long)); |
| static assert(is(typeof(d2!int) == long)); |
| static assert(is(typeof(d3!int) == long)); |
| } |
| } |
| P p; |
| { |
| // TOKdotvar |
| static assert(is(typeof(p.pr) == long)); |
| |
| // TOKdottd |
| static assert(is(typeof(p.a1) == long)); |
| static assert(is(typeof(p.a2) == long)); |
| static assert(is(typeof(p.a3) == long)); |
| |
| // TOKimport |
| static assert(is(typeof(P.b1) == long)); |
| static assert(is(typeof(P.b2) == long)); |
| static assert(is(typeof(P.b3) == long)); |
| |
| // TOKdotti; |
| static assert(is(typeof(p.c1!int) == long)); |
| static assert(is(typeof(p.c2!int) == long)); |
| static assert(is(typeof(p.c3!int) == long)); |
| } |
| |
| struct F |
| { |
| long fn() { return 1; } |
| void fn(int) {} |
| |
| long a1()() { return 1; } |
| void a1()(int) {} |
| template a2() { long a2() { return 1; } } |
| template a2() { void a2(int) {} } |
| |
| static |
| { |
| long b1()() { return 1; } |
| void b1()(int) {} |
| template b2() { long b2() { return 1; } } |
| template b2() { void b2(int) {} } |
| } |
| |
| long c1(T)() { return 1; } |
| long c1(T)(int) { return 1; } |
| template c2(T) { long c2() { return 1; } } |
| template c2(T) { void c2(int) {} } |
| |
| static |
| { |
| long d1(T)() { return 1; } |
| void d1(T)(int) {} |
| template d2(T) { long d2() { return 1; } } |
| template d2(T) { void d2(int) {} } |
| } |
| |
| void test() |
| { |
| // TOKvar |
| static assert( is(typeof(fn) == function)); |
| |
| // TOKtemplate |
| static assert(!is(typeof(b1) == long)); |
| static assert(!is(typeof(b2) == long)); |
| |
| // TOKimport |
| static assert(!is(typeof(d1!int) == long)); |
| static assert(!is(typeof(d2!int) == long)); |
| } |
| } |
| F f; |
| { |
| // TOKdotvar |
| static assert(is( typeof(f.fn) == function)); |
| |
| // TOKdottd |
| static assert(!is(typeof(f.a1) == long)); |
| static assert(!is(typeof(f.a2) == long)); |
| |
| // TOKimport |
| static assert(!is(typeof(F.b1) == long)); |
| static assert(!is(typeof(F.b2) == long)); |
| |
| // TOKdotti; |
| static assert(!is(typeof(f.c1!int) == long)); |
| static assert(!is(typeof(f.c2!int) == long)); |
| } |
| } |
| |
| /*****************************************/ |
| // 8251 |
| |
| struct S8251 |
| { |
| static @property int min() { return 123; } |
| } |
| @property int T8251_Min() { return 456; } |
| |
| template T8251a (int v) { int T8251a = v; } |
| |
| template T8251b1(int v = S8251.min) { int T8251b1 = v; } |
| template T8251b2(int v = T8251_Min) { int T8251b2 = v; } |
| |
| template T8251c1(int v : S8251.min) { int T8251c1 = v; } |
| template T8251c2(int v : T8251_Min) { int T8251c2 = v; } |
| |
| void test8251() |
| { |
| static assert(S8251.min == 123); // OK |
| static assert(T8251_Min == 456); // OK |
| int a0 = T8251a!(S8251.min()); // OK |
| int b0 = T8251a!(T8251_Min()); // OK |
| |
| // TemplateValueParameter |
| int a1 = T8251a!(S8251.min); // NG |
| int b1 = T8251a!(T8251_Min); // NG |
| |
| // TemplateValueParameterDefault |
| int a2 = T8251b1!(); // NG |
| int b2 = T8251b2!(); // NG |
| |
| // TemplateValueParameterSpecialization |
| int a3 = T8251c1!(123); // NG |
| int b3 = T8251c2!(456); // NG |
| } |
| |
| /*****************************************/ |
| // 9063 |
| |
| @property bool foo9063(){ return true; } |
| static assert(foo9063); |
| |
| /*****************************************/ |
| // 9234 |
| |
| class Fizz9234 |
| { |
| void bar() {} |
| Foo9234!bar foobar; |
| } |
| |
| struct Foo9234(alias F) {} |
| struct Foo9234(string thunk) {} |
| |
| /*****************************************/ |
| // 10103 |
| |
| mixin template Getter10103() |
| { |
| @property auto foo() { return v; } |
| @property auto bar()() { return v; } |
| @property auto baz(T)() { return v; } |
| |
| static @property auto goo() { return 1; } |
| } |
| |
| mixin template Setter10103() |
| { |
| @property void foo(int x) { v = x; } |
| @property void bar()(int x) { v = x; } |
| @property void baz(T)(int x) { v = x; } |
| |
| static @property void goo(int x) {} |
| } |
| |
| struct Foo10103 |
| { |
| int v; |
| mixin Getter10103!(); |
| mixin Setter10103!(); |
| } |
| |
| void test10103() |
| { |
| auto f = Foo10103(4); |
| |
| f.foo; |
| f.foo = 3; |
| |
| f.bar; |
| f.bar = 3; |
| |
| f.baz!int; |
| f.baz!int = 3; |
| |
| Foo10103.goo = 3; |
| } |
| |
| /*****************************************/ |
| // 10197 |
| |
| template OriginalType10197(T) |
| { |
| static if (is(T U == enum)) |
| alias OriginalType10197 = U; |
| else |
| static assert(0); |
| } |
| |
| void test10197() |
| { |
| enum E : int { F = -20 } |
| struct S |
| { |
| int val; |
| @trusted @property T as(T)() |
| if (is(T == int) && !is(T == enum)) |
| { |
| return cast(T)(val); |
| } |
| @trusted @property T as(T)() |
| if (is(T == enum)) |
| { |
| return cast(T)as!(OriginalType10197!T); |
| } |
| } |
| |
| S val = S(-20); |
| assert(val.as!int == -20); |
| assert(val.as!E == E.F); |
| } |
| |
| /*****************************************/ |
| |
| int main() |
| { |
| test1(); |
| test7722(); |
| test7722a(); |
| test7722b(); |
| test7174(); |
| test7274(); |
| test7275(); |
| test7538(); |
| test8251(); |
| test10103(); |
| test10197(); |
| |
| printf("Success\n"); |
| return 0; |
| } |