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