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