632 lines
17 KiB
D
632 lines
17 KiB
D
// 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;
|
|
}
|