// 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; }