1 // PERMUTE_ARGS: -property
2 /*
3 TEST_OUTPUT:
4 ---
5 decl: test
6 stmt: test
7 ---
8 
9 RUN_OUTPUT:
10 ---
11 0: getter
12 1: setter
13 2: getter
14 3: setter
15 4: setter
16 5: compile error
17 6: compile error
18 7: setter
19 Success
20 ---
21 */
22 
23 extern (C) int printf(const char* fmt, ...);
24 
25 // Is -property option specified?
26 enum enforceProperty = !__traits(compiles, {
27     int prop(){ return 1; }
28     int n = prop;
29 });
30 
31 /*******************************************/
32 
select(alias v1,alias v2)33 template select(alias v1, alias v2)
34 {
35     static if (enforceProperty)
36         enum select = v1;
37     else
38         enum select = v2;
39 }
40 
Test(int N)41 struct Test(int N)
42 {
43     int value;
44     int getset;
45 
46     static if (N == 0)
47     {
48         ref foo(){ getset = 1; return value; }
49 
50         enum result = select!(0, 1);
51         // -property    test.d(xx): Error: not a property foo
52         // (no option)  prints "getter"
53     }
54     static if (N == 1)
55     {
56         ref foo(int x){ getset = 2; value = x; return value; }
57 
58         enum result = select!(0, 2);
59         // -property    test.d(xx): Error: not a property foo
60         // (no option)  prints "setter"
61     }
62     static if (N == 2)
63     {
64         @property ref foo(){ getset = 1; return value; }
65 
66         enum result = select!(1, 1);
67         // -property    prints "getter"
68         // (no option)  prints "getter"
69     }
70     static if (N == 3)
71     {
72         @property ref foo(int x){ getset = 2; value = x; return value; }
73 
74         enum result = select!(2, 2);
75         // -property    prints "setter"
76         // (no option)  prints "setter"
77     }
78 
79 
80     static if (N == 4)
81     {
82         ref foo()     { getset = 1; return value; }
83         ref foo(int x){ getset = 2; value = x; return value; }
84 
85         enum result = select!(0, 2);
86         // -property    test.d(xx): Error: not a property foo
87         // (no option)  prints "setter"
88     }
89     static if (N == 5)
90     {
91         @property ref foo()     { getset = 1; return value; }
92                   ref foo(int x){ getset = 2; value = x; return value; }
93 
94         enum result = select!(0, 0);
95         // -property    test.d(xx): Error: cannot overload both property and non-property functions
96         // (no option)  test.d(xx): Error: cannot overload both property and non-property functions
97     }
98     static if (N == 6)
99     {
100                   ref foo()     { getset = 1; return value; }
101         @property ref foo(int x){ getset = 2; value = x; return value; }
102 
103         enum result = select!(0, 0);
104         // -property    test.d(xx): Error: cannot overload both property and non-property functions
105         // (no option)  test.d(xx): Error: cannot overload both property and non-property functions
106     }
107     static if (N == 7)
108     {
109         @property ref foo()     { getset = 1; return value; }
110         @property ref foo(int x){ getset = 2; value = x; return value; }
111 
112         enum result = select!(2, 2);
113         // -property    prints "setter"
114         // (no option)  prints "setter"
115     }
116 }
117 
seq(T...)118 template seq(T...)
119 {
120     alias T seq;
121 }
122 template iota(int begin, int end)
123     if (begin <= end)
124 {
125     static if (begin == end)
126         alias seq!() iota;
127     else
128         alias seq!(begin, iota!(begin+1, end)) iota;
129 }
130 
test1()131 void test1()
132 {
133     foreach (N; iota!(0, 8))
134     {
135         printf("%d: ", N);
136 
137         Test!N s;
138         static if (Test!N.result == 0)
139         {
140             static assert(!is(typeof({ s.foo = 1; })));
141             printf("compile error\n");
142         }
143         else
144         {
145             s.foo = 1;
146             if (s.getset == 1)
147                 printf("getter\n");
148             else
149                 printf("setter\n");
150             assert(s.getset == Test!N.result);
151         }
152     }
153 }
154 
155 /*******************************************/
156 // 7722
157 
158 class Foo7722 {}
spam7722(Foo7722 f)159 void spam7722(Foo7722 f) {}
160 
test7722()161 void test7722()
162 {
163     auto f = new Foo7722;
164     static if (enforceProperty)
165         static assert(!__traits(compiles, f.spam7722));
166     else
167         f.spam7722;
168 }
169 
170 /*******************************************/
171 
check(alias v1,alias v2,alias dg)172 @property void check(alias v1, alias v2, alias dg)()
173 {
174     void checkImpl(alias v)()
175     {
176         static if (v == 0)
177             static assert(!__traits(compiles, dg(0)));
178         else
179             assert(dg(0) == v);
180     }
181 
182     static if (enforceProperty)
183         checkImpl!(v1)();
184     else
185         checkImpl!(v2)();
186 }
187 
188 struct S {}
189 
foo(int n)190 int foo(int n)          { return 1; }
foo(int n,int m)191 int foo(int n, int m)   { return 2; }
goo(int[]a)192 int goo(int[] a)        { return 1; }
goo(int[]a,int m)193 int goo(int[] a, int m) { return 2; }
bar(S s)194 int bar(S s)            { return 1; }
bar(S s,int n)195 int bar(S s, int n)     { return 2; }
196 
baz(X)197 int baz(X)(X x)         { return 1; }
baz(X)198 int baz(X)(X x, int n)  { return 2; }
199 
200 int temp;
boo(int n)201 ref int boo(int n)      { return temp; }
coo(int[]a)202 ref int coo(int[] a)    { return temp; }
mar(S s)203 ref int mar(S s)        { return temp; }
204 
maz(X)205 ref int maz(X)(X x)     { return temp; }
206 
test7722a()207 void test7722a()
208 {
209     int n;
210     int[] a;
211     S s;
212 
213     check!(1, 1, x =>    foo(4)     );      check!(1, 1, x =>    baz(4)     );
214     check!(1, 1, x =>  4.foo()      );      check!(1, 1, x =>  4.baz()      );
215     check!(0, 1, x =>  4.foo        );      check!(0, 1, x =>  4.baz        );
216     check!(2, 2, x =>    foo(4, 2)  );      check!(2, 2, x =>    baz(4, 2)  );
217     check!(2, 2, x =>  4.foo(2)     );      check!(2, 2, x =>  4.baz(2)     );
218     check!(0, 2, x => (4.foo = 2)   );      check!(0, 2, x => (4.baz = 2)   );
219 
220     check!(1, 1, x =>    goo(a)     );      check!(1, 1, x =>    baz(a)     );
221     check!(1, 1, x =>  a.goo()      );      check!(1, 1, x =>  a.baz()      );
222     check!(0, 1, x =>  a.goo        );      check!(0, 1, x =>  a.baz        );
223     check!(2, 2, x =>    goo(a, 2)  );      check!(2, 2, x =>    baz(a, 2)  );
224     check!(2, 2, x =>  a.goo(2)     );      check!(2, 2, x =>  a.baz(2)     );
225     check!(0, 2, x => (a.goo = 2)   );      check!(0, 2, x => (a.baz = 2)   );
226 
227     check!(1, 1, x =>    bar(s)     );      check!(1, 1, x =>    baz(s)     );
228     check!(1, 1, x =>  s.bar()      );      check!(1, 1, x =>  s.baz()      );
229     check!(0, 1, x =>  s.bar        );      check!(0, 1, x =>  s.baz        );
230     check!(2, 2, x =>    bar(s, 2)  );      check!(2, 2, x =>    baz(s, 2)  );
231     check!(2, 2, x =>  s.bar(2)     );      check!(2, 2, x =>  s.baz(2)     );
232     check!(0, 2, x => (s.bar = 2)   );      check!(0, 2, x => (s.baz = 2)   );
233 
234     check!(2, 2, x => (  boo(4) = 2));      check!(2, 2, x => (  maz(4) = 2));
235     check!(0, 2, x => (4.boo    = 2));      check!(0, 2, x => (4.maz    = 2));
236     check!(2, 2, x => (  coo(a) = 2));      check!(2, 2, x => (  maz(a) = 2));
237     check!(0, 2, x => (a.coo    = 2));      check!(0, 2, x => (a.maz    = 2));
238     check!(2, 2, x => (  mar(s) = 2));      check!(2, 2, x => (  maz(s) = 2));
239     check!(0, 2, x => (s.mar    = 2));      check!(0, 2, x => (s.maz    = 2));
240 }
241 
hoo(T)242 int hoo(T)(int n)          { return 1; }
hoo(T)243 int hoo(T)(int n, int m)   { return 2; }
koo(T)244 int koo(T)(int[] a)        { return 1; }
koo(T)245 int koo(T)(int[] a, int m) { return 2; }
var(T)246 int var(T)(S s)            { return 1; }
var(T)247 int var(T)(S s, int n)     { return 2; }
248 
vaz(T,X)249 int vaz(T, X)(X x)         { return 1; }
vaz(T,X)250 int vaz(T, X)(X x, int n)  { return 2; }
251 
252 //int temp;
voo(T)253 ref int voo(T)(int n)      { return temp; }
woo(T)254 ref int woo(T)(int[] a)    { return temp; }
nar(T)255 ref int nar(T)(S s)        { return temp; }
256 
naz(T,X)257 ref int naz(T, X)(X x)     { return temp; }
258 
test7722b()259 void test7722b()
260 {
261     int n;
262     int[] a;
263     S s;
264 
265     check!(1, 1, x =>    hoo!int(4)     );  check!(1, 1, x =>    vaz!int(4)     );
266     check!(1, 1, x =>  4.hoo!int()      );  check!(1, 1, x =>  4.vaz!int()      );
267     check!(0, 1, x =>  4.hoo!int        );  check!(0, 1, x =>  4.vaz!int        );
268     check!(2, 2, x =>    hoo!int(4, 2)  );  check!(2, 2, x =>    vaz!int(4, 2)  );
269     check!(2, 2, x =>  4.hoo!int(2)     );  check!(2, 2, x =>  4.vaz!int(2)     );
270     check!(0, 2, x => (4.hoo!int = 2)   );  check!(0, 2, x => (4.vaz!int = 2)   );
271 
272     check!(1, 1, x =>    koo!int(a)     );  check!(1, 1, x =>    vaz!int(a)     );
273     check!(1, 1, x =>  a.koo!int()      );  check!(1, 1, x =>  a.vaz!int()      );
274     check!(0, 1, x =>  a.koo!int        );  check!(0, 1, x =>  a.vaz!int        );
275     check!(2, 2, x =>    koo!int(a, 2)  );  check!(2, 2, x =>    vaz!int(a, 2)  );
276     check!(2, 2, x =>  a.koo!int(2)     );  check!(2, 2, x =>  a.vaz!int(2)     );
277     check!(0, 2, x => (a.koo!int = 2)   );  check!(0, 2, x => (a.vaz!int = 2)   );
278 
279     check!(1, 1, x =>    var!int(s)     );  check!(1, 1, x =>    vaz!int(s)     );
280     check!(1, 1, x =>  s.var!int()      );  check!(1, 1, x =>  s.vaz!int()      );
281     check!(0, 1, x =>  s.var!int        );  check!(0, 1, x =>  s.vaz!int        );
282     check!(2, 2, x =>    var!int(s, 2)  );  check!(2, 2, x =>    vaz!int(s, 2)  );
283     check!(2, 2, x =>  s.var!int(2)     );  check!(2, 2, x =>  s.vaz!int(2)     );
284     check!(0, 2, x => (s.var!int = 2)   );  check!(0, 2, x => (s.vaz!int = 2)   );
285 
286     check!(2, 2, x => (  voo!int(4) = 2));  check!(2, 2, x => (  naz!int(4) = 2));
287     check!(0, 2, x => (4.voo!int    = 2));  check!(0, 2, x => (4.naz!int    = 2));
288     check!(2, 2, x => (  woo!int(a) = 2));  check!(2, 2, x => (  naz!int(a) = 2));
289     check!(0, 2, x => (a.woo!int    = 2));  check!(0, 2, x => (a.naz!int    = 2));
290     check!(2, 2, x => (  nar!int(s) = 2));  check!(2, 2, x => (  naz!int(s) = 2));
291     check!(0, 2, x => (s.nar!int    = 2));  check!(0, 2, x => (s.naz!int    = 2));
292 }
293 
294 /*******************************************/
295 // 7174
296 
test7174()297 void test7174()
298 {
299     @property bool foo7174() { return true; }
300     static if (foo7174) {}
301 }
302 
303 /***************************************************/
304 // 7274
305 
foo7274()306 @property foo7274(){ return "test"; }
bar7274()307 @property bar7274(){ return "kernel32.lib"; }
308 
309 pragma(msg, "decl: ", foo7274);   // print "decl: foo", not "decl: test"
310 version(Windows) pragma(lib, bar7274); // Error: pragma lib string expected for library name, not 'bar'
311 
test7274()312 void test7274()
313 {
314     pragma(msg, "stmt: ", foo7274);  // print "stmt: foo", not "stmt: test"
315     //pragma(lib, bar);   // Error: pragma(lib) not allowed as statement
316 }
317 
318 /***************************************************/
319 // 7275
320 
test7275()321 void test7275()
322 {
323     @property int bar1() { return 0; }
324     @property int bar2() { return 1; }
325     @property int bar3() { return 2; }
326 
327     switch (0){
328         case bar1:  break;
329         case bar2: ..
330         case bar3:  break;
331         default:    break;
332     }
333 }
334 
335 /*****************************************/
336 // 7538
337 
test7538()338 void test7538()
339 {
340     struct P
341     {
342         @property long pr() { return 1; }
343         @property void pr(int) {}
344 
345         @property long a1()() { return 1; }
346         @property void a1()(int) {}
347         template a2() { @property long a2() { return 1; } }
348         template a2() { @property void a2(int) {} }
349         template a3() { long a3() @property { return 1; } }
350         template a3() { void a3(int) @property {} }
351 
352       static
353       {
354         @property long b1()() { return 1; }
355         @property void b1()(int) {}
356         template b2() { @property long b2() { return 1; } }
357         template b2() { @property void b2(int) {} }
358         template b3() { long b3() @property { return 1; } }
359         template b3() { void b3(int) @property {} }
360       }
361 
362         @property long c1(T)()    { return 1; }
363         @property long c1(T)(int) { return 1; }
364         template c2(T) { @property long c2() { return 1; } }
365         template c2(T) { @property void c2(int) {} }
366         template c3(T) { long c3() @property { return 1; } }
367         template c3(T) { void c3(int) @property {} }
368 
369       static
370       {
371         @property long d1(T)() { return 1; }
372         @property void d1(T)(int) {}
373         template d2(T) { @property long d2() { return 1; } }
374         template d2(T) { @property void d2(int) {} }
375         template d3(T) { long d3() @property { return 1; } }
376         template d3(T) { void d3(int) @property {} }
377       }
378 
379         void test()
380         {
381             // TOKvar
382             static assert(is(typeof(pr) == long));
383 
384             // TOKtemplate
385             static assert(is(typeof(b1) == long));
386             static assert(is(typeof(b2) == long));
387             static assert(is(typeof(b3) == long));
388 
389             // TOKimport
390             static assert(is(typeof(d1!int) == long));
391             static assert(is(typeof(d2!int) == long));
392             static assert(is(typeof(d3!int) == long));
393         }
394     }
395     P p;
396     {
397         // TOKdotvar
398         static assert(is(typeof(p.pr) == long));
399 
400         // TOKdottd
401         static assert(is(typeof(p.a1) == long));
402         static assert(is(typeof(p.a2) == long));
403         static assert(is(typeof(p.a3) == long));
404 
405         // TOKimport
406         static assert(is(typeof(P.b1) == long));
407         static assert(is(typeof(P.b2) == long));
408         static assert(is(typeof(P.b3) == long));
409 
410         // TOKdotti;
411         static assert(is(typeof(p.c1!int) == long));
412         static assert(is(typeof(p.c2!int) == long));
413         static assert(is(typeof(p.c3!int) == long));
414     }
415 
416     struct F
417     {
418         long fn() { return 1; }
419         void fn(int) {}
420 
421         long a1()() { return 1; }
422         void a1()(int) {}
423         template a2() { long a2() { return 1; } }
424         template a2() { void a2(int) {} }
425 
426       static
427       {
428         long b1()() { return 1; }
429         void b1()(int) {}
430         template b2() { long b2() { return 1; } }
431         template b2() { void b2(int) {} }
432       }
433 
434         long c1(T)()    { return 1; }
435         long c1(T)(int) { return 1; }
436         template c2(T) { long c2() { return 1; } }
437         template c2(T) { void c2(int) {} }
438 
439       static
440       {
441         long d1(T)() { return 1; }
442         void d1(T)(int) {}
443         template d2(T) { long d2() { return 1; } }
444         template d2(T) { void d2(int) {} }
445       }
446 
447         void test()
448         {
449             // TOKvar
450             static assert( is(typeof(fn) == function));
451 
452             // TOKtemplate
453             static assert(!is(typeof(b1) == long));
454             static assert(!is(typeof(b2) == long));
455 
456             // TOKimport
457             static assert(!is(typeof(d1!int) == long));
458             static assert(!is(typeof(d2!int) == long));
459         }
460     }
461     F f;
462     {
463         // TOKdotvar
464         static assert(is( typeof(f.fn) == function));
465 
466         // TOKdottd
467         static assert(!is(typeof(f.a1) == long));
468         static assert(!is(typeof(f.a2) == long));
469 
470         // TOKimport
471         static assert(!is(typeof(F.b1) == long));
472         static assert(!is(typeof(F.b2) == long));
473 
474         // TOKdotti;
475         static assert(!is(typeof(f.c1!int) == long));
476         static assert(!is(typeof(f.c2!int) == long));
477     }
478 }
479 
480 /*****************************************/
481 // 8251
482 
483 struct S8251
484 {
minS8251485     static @property int min() { return 123; }
486 }
T8251_Min()487 @property int T8251_Min() { return 456; }
488 
T8251a(int v)489 template T8251a (int v)             { int T8251a  = v; }
490 
491 template T8251b1(int v = S8251.min) { int T8251b1 = v; }
492 template T8251b2(int v = T8251_Min) { int T8251b2 = v; }
493 
494 template T8251c1(int v : S8251.min) { int T8251c1 = v; }
495 template T8251c2(int v : T8251_Min) { int T8251c2 = v; }
496 
test8251()497 void test8251()
498 {
499     static assert(S8251.min == 123);    // OK
500     static assert(T8251_Min == 456);    // OK
501     int a0 = T8251a!(S8251.min());      // OK
502     int b0 = T8251a!(T8251_Min());      // OK
503 
504     // TemplateValueParameter
505     int a1 = T8251a!(S8251.min);        // NG
506     int b1 = T8251a!(T8251_Min);        // NG
507 
508     // TemplateValueParameterDefault
509     int a2 = T8251b1!();                // NG
510     int b2 = T8251b2!();                // NG
511 
512     // TemplateValueParameterSpecialization
513     int a3 = T8251c1!(123);             // NG
514     int b3 = T8251c2!(456);             // NG
515 }
516 
517 /*****************************************/
518 // 9063
519 
foo9063()520 @property bool foo9063(){ return true; }
521 static assert(foo9063);
522 
523 /*****************************************/
524 // 9234
525 
526 class Fizz9234
527 {
bar()528     void bar() {}
529     Foo9234!bar foobar;
530 }
531 
Foo9234(alias F)532 struct Foo9234(alias F) {}
Foo9234(string thunk)533 struct Foo9234(string thunk) {}
534 
535 /*****************************************/
536 // 10103
537 
Getter10103()538 mixin template Getter10103()
539 {
540     @property auto foo() { return v; }
541     @property auto bar()() { return v; }
542     @property auto baz(T)() { return v; }
543 
544     static @property auto goo() { return 1; }
545 }
546 
Setter10103()547 mixin template Setter10103()
548 {
549     @property void foo(int x) { v = x; }
550     @property void bar()(int x) { v = x; }
551     @property void baz(T)(int x) { v = x; }
552 
553     static @property void goo(int x) {}
554 }
555 
556 struct Foo10103
557 {
558     int v;
559     mixin Getter10103!();
560     mixin Setter10103!();
561 }
562 
test10103()563 void test10103()
564 {
565     auto f = Foo10103(4);
566 
567     f.foo;
568     f.foo = 3;
569 
570     f.bar;
571     f.bar = 3;
572 
573     f.baz!int;
574     f.baz!int = 3;
575 
576     Foo10103.goo = 3;
577 }
578 
579 /*****************************************/
580 // 10197
581 
OriginalType10197(T)582 template OriginalType10197(T)
583 {
584     static if (is(T U == enum))
585         alias OriginalType10197 = U;
586     else
587         static assert(0);
588 }
589 
test10197()590 void test10197()
591 {
592     enum E : int { F = -20 }
593     struct S
594     {
595         int val;
596         @trusted @property T as(T)()
597         if (is(T == int) && !is(T == enum))
598         {
599             return cast(T)(val);
600         }
601         @trusted @property T as(T)()
602         if (is(T == enum))
603         {
604             return cast(T)as!(OriginalType10197!T);
605         }
606     }
607 
608     S val = S(-20);
609     assert(val.as!int == -20);
610     assert(val.as!E == E.F);
611 }
612 
613 /*****************************************/
614 
main()615 int main()
616 {
617     test1();
618     test7722();
619     test7722a();
620     test7722b();
621     test7174();
622     test7274();
623     test7275();
624     test7538();
625     test8251();
626     test10103();
627     test10197();
628 
629     printf("Success\n");
630     return 0;
631 }
632