| /* |
| EXTRA_FILES: imports/a9741.d |
| TEST_OUTPUT: |
| --- |
| tuple(3, 4, 7, (SSS)) |
| tuple(3, 4, 7, (SSS)) |
| 7 |
| SSS |
| tuple("hello") |
| tuple('c') |
| tuple((FFF)) |
| tuple(10) |
| tuple(20) |
| tuple(30) |
| tuple((Test6)) |
| tuple(Test7(3, "foo")) |
| tuple((Test8!"foo")) |
| tuple((Test9!"foo")) |
| tuple(Test10(3)) |
| tuple(Test11(3)) |
| tuple(10) |
| tuple(20) |
| tuple() |
| tuple(40) |
| B9741 |
| tuple((A9741)) |
| tuple(1) |
| tuple(2) |
| --- |
| |
| RUN_OUTPUT: |
| --- |
| Success |
| --- |
| */ |
| |
| import core.stdc.stdio; |
| |
| template Tuple(T...) |
| { |
| alias T Tuple; |
| } |
| |
| |
| |
| enum EEE = 7; |
| @("hello") struct SSS { } |
| |
| @(3) { @(4)@(EEE)@(SSS) int foo; } |
| |
| pragma(msg, __traits(getAttributes, foo)); |
| |
| alias Tuple!(__traits(getAttributes, foo)) TP; |
| |
| pragma(msg, TP); |
| pragma(msg, TP[2]); |
| TP[3] a; |
| pragma(msg, typeof(a)); |
| |
| |
| alias Tuple!(__traits(getAttributes, typeof(a))) TT; |
| |
| pragma(msg, TT); |
| |
| @('c') string s; |
| pragma(msg, __traits(getAttributes, s)); |
| |
| /************************************************/ |
| |
| enum FFF; |
| @(FFF) int x1; |
| pragma(msg, __traits(getAttributes, x1)); |
| |
| void test1() |
| { |
| alias Tuple!(__traits(getAttributes, x1)) tp; |
| assert(tp.length == 1); |
| if (!is(FFF == tp[0])) |
| assert(0); |
| } |
| |
| /************************************************/ |
| |
| void test2() |
| { |
| int x; |
| alias Tuple!(__traits(getAttributes, x)) tp; |
| assert(tp.length == 0); |
| } |
| |
| /************************************************/ |
| |
| void test3() |
| { |
| alias Tuple!(__traits(getAttributes, foo)) tp; |
| assert(tp.length == 4); |
| assert(tp[0] == 3); |
| assert(tp[1] == 4); |
| assert(tp[2] == 7); |
| } |
| |
| /************************************************/ |
| |
| @(1) void foo4(); |
| @(2) void foo4(int x); |
| |
| void test4() |
| { |
| int i = 1; |
| foreach (o; __traits(getOverloads, uda, "foo4")) |
| { |
| alias Tuple!(__traits(getAttributes, o)) attrs; |
| pragma(msg, attrs.stringof); |
| assert(attrs[0] == i); |
| ++i; |
| } |
| } |
| |
| /************************************************/ |
| |
| pragma(msg, __traits(getAttributes, aa)); |
| alias Tuple!(__traits(getAttributes, aa)) Taa; |
| @(10) int aa; |
| |
| pragma(msg, __traits(getAttributes, bb)); |
| alias Tuple!(__traits(getAttributes, bb)) Tbb; |
| @(20) int bb; |
| alias Tuple!(__traits(getAttributes, bb)) Tbbc; |
| |
| @(30) int cc; |
| pragma(msg, __traits(getAttributes, cc)); |
| alias Tuple!(__traits(getAttributes, cc)) Tcc; |
| |
| void test5() |
| { |
| assert(Taa[0] == 10); |
| assert(Tbb[0] == 20); |
| assert(Tbbc[0] == 20); |
| assert(Tcc[0] == 30); |
| } |
| |
| /************************************************/ |
| |
| enum Test6; |
| @Test6 int x6; |
| pragma(msg, __traits(getAttributes, x6)); |
| |
| void test6() |
| { |
| alias Tuple!(__traits(getAttributes, x6)) tp; |
| |
| assert(tp.length == 1); |
| |
| if (!is(Test6 == tp[0])) |
| assert(0); |
| } |
| |
| /************************************************/ |
| |
| struct Test7 |
| { |
| int a; |
| string b; |
| } |
| |
| @Test7(3, "foo") int x7; |
| pragma(msg, __traits(getAttributes, x7)); |
| |
| void test7() |
| { |
| alias Tuple!(__traits(getAttributes, x7)) tp; |
| |
| assert(tp.length == 1); |
| |
| if (!is(Test7 == typeof(tp[0]))) |
| assert(0); |
| |
| assert(tp[0] == Test7(3, "foo")); |
| } |
| |
| /************************************************/ |
| |
| struct Test8 (string foo) {} |
| |
| @Test8!"foo" int x8; |
| pragma(msg, __traits(getAttributes, x8)); |
| |
| void test8() |
| { |
| alias Tuple!(__traits(getAttributes, x8)) tp; |
| |
| assert(tp.length == 1); |
| |
| if (!is(Test8!("foo") == tp[0])) |
| assert(0); |
| } |
| |
| /************************************************/ |
| |
| struct Test9 (string foo) {} |
| |
| @Test9!("foo") int x9; |
| pragma(msg, __traits(getAttributes, x9)); |
| |
| void test9() |
| { |
| alias Tuple!(__traits(getAttributes, x9)) tp; |
| |
| assert(tp.length == 1); |
| |
| if (!is(Test9!("foo") == tp[0])) |
| assert(0); |
| } |
| |
| /************************************************/ |
| |
| struct Test10 (string foo) |
| { |
| int a; |
| } |
| |
| @Test10!"foo"(3) int x10; |
| pragma(msg, __traits(getAttributes, x10)); |
| |
| void test10() |
| { |
| alias Tuple!(__traits(getAttributes, x10)) tp; |
| |
| assert(tp.length == 1); |
| |
| if (!is(Test10!("foo") == typeof(tp[0]))) |
| assert(0); |
| |
| assert(tp[0] == Test10!("foo")(3)); |
| } |
| |
| /************************************************/ |
| |
| struct Test11 (string foo) |
| { |
| int a; |
| } |
| |
| @Test11!("foo")(3) int x11; |
| pragma(msg, __traits(getAttributes, x11)); |
| |
| void test11() |
| { |
| alias Tuple!(__traits(getAttributes, x11)) tp; |
| |
| assert(tp.length == 1); |
| |
| if (!is(Test11!("foo") == typeof(tp[0]))) |
| assert(0); |
| |
| assert(tp[0] == Test11!("foo")(3)); |
| } |
| |
| /************************************************/ |
| |
| void test12() |
| { |
| @(1) static struct S1 { } |
| S1 s1; |
| static @(2) struct S2 { } |
| S2 s2; |
| @(1) @(2) struct S3 { } |
| |
| @(1) static @(2) struct S { } |
| alias Tuple!(__traits(getAttributes, S)) tps; |
| assert(tps.length == 2); |
| assert(tps[0] == 1); |
| assert(tps[1] == 2); |
| |
| @(3) int x; |
| alias Tuple!(__traits(getAttributes, x)) tpx; |
| assert(tpx.length == 1); |
| assert(tpx[0] == 3); |
| x = x + 1; |
| |
| @(4) int bar() { return x; } |
| alias Tuple!(__traits(getAttributes, bar)) tpb; |
| assert(tpb.length == 1); |
| assert(tpb[0] == 4); |
| bar(); |
| } |
| |
| /************************************************/ |
| // 9178 |
| |
| void test9178() |
| { |
| static class Foo { @(1) int a; } |
| |
| Foo foo = new Foo; |
| static assert(__traits(getAttributes, foo.tupleof[0])[0] == 1); |
| } |
| |
| /************************************************/ |
| // 9652 |
| |
| struct Bug9652 |
| { |
| pragma(msg, __traits(getAttributes, enum_field)); |
| alias Tuple!(__traits(getAttributes, enum_field)) Tenum_field; |
| private @(10) enum enum_field = 42; |
| |
| static assert(Tenum_field[0] == 10); |
| static assert(__traits(getAttributes, enum_field)[0] == 10); |
| static assert(__traits(getProtection, enum_field) == "private"); |
| static assert(__traits(isSame, __traits(parent, enum_field), Bug9652)); |
| static assert(__traits(isSame, enum_field, enum_field)); |
| |
| pragma(msg, __traits(getAttributes, anon_enum_member)); |
| alias Tuple!(__traits(getAttributes, anon_enum_member)) Tanon_enum_member; |
| private @(20) enum {anon_enum_member} |
| |
| static assert(Tanon_enum_member[0] == 20); |
| static assert(__traits(getAttributes, anon_enum_member)[0] == 20); |
| static assert(__traits(getProtection, anon_enum_member) == "private"); |
| static assert(__traits(isSame, __traits(parent, anon_enum_member), Bug9652)); |
| static assert(__traits(isSame, anon_enum_member, anon_enum_member)); |
| |
| pragma(msg, __traits(getAttributes, Foo.enum_member)); |
| alias Tuple!(__traits(getAttributes, Foo.enum_member)) Tfoo_enum_member; |
| private @(30) enum Foo {enum_member} |
| static assert(Tfoo_enum_member.length == 0); //Foo has attributes, not Foo.enum_member |
| static assert(__traits(getAttributes, Foo.enum_member).length == 0); |
| static assert(__traits(getProtection, Foo.enum_member) == "public"); |
| static assert(__traits(isSame, __traits(parent, Foo.enum_member), Foo)); |
| static assert(__traits(isSame, Foo.enum_member, Foo.enum_member)); |
| |
| pragma(msg, __traits(getAttributes, anon_enum_member_2)); |
| alias Tuple!(__traits(getAttributes, anon_enum_member_2)) Tanon_enum_member_2; |
| private @(40) enum {long anon_enum_member_2 = 2L} |
| |
| static assert(Tanon_enum_member_2[0] == 40); |
| static assert(__traits(getAttributes, anon_enum_member_2)[0] == 40); |
| static assert(__traits(getProtection, anon_enum_member_2) == "private"); |
| static assert(__traits(isSame, __traits(parent, anon_enum_member_2), Bug9652)); |
| static assert(__traits(isSame, anon_enum_member_2, anon_enum_member_2)); |
| |
| template Bug(alias X, bool is_exp) |
| { |
| static assert(is_exp == !__traits(compiles, __traits(parent, X))); |
| static assert(is_exp == !__traits(compiles, __traits(getAttributes, X))); |
| static assert(is_exp == !__traits(compiles, __traits(getProtection, X))); |
| enum Bug = 0; |
| } |
| enum en = 0; |
| enum dummy1 = Bug!(5, true); |
| enum dummy2 = Bug!(en, false); |
| } |
| |
| /************************************************/ |
| // 9741 |
| |
| import imports.a9741; |
| |
| struct A9741 {} |
| |
| alias X9741 = ShowAttributes!(B9741); |
| |
| @A9741 struct B9741 {} |
| |
| /************************************************/ |
| // 12160 |
| |
| auto before12160(alias Hook)(string) { return 0; } |
| |
| template checkUDAs12160(alias Func) |
| { |
| enum x = __traits(getAttributes, Func).length; |
| } |
| |
| void test12160() |
| { |
| int foo() { return 42; } // OK <- NG |
| |
| @before12160!foo("name1") |
| void bar(int name1, double name2) {} |
| |
| alias X = checkUDAs12160!(bar); |
| } |
| |
| /************************************************/ |
| // 10208 |
| |
| @( 10) enum int x10208_01 = 100; |
| @( 20) int x10208_02; |
| @( 30) const int x10208_03; |
| @( 40) immutable int x10208_04; |
| @( 50) int x10208_05 = 500; |
| @( 60) const int x10208_06 = 600; |
| @( 70) immutable int x10208_07 = 700; |
| @( 80) __gshared enum int x10208_08 = 800; |
| @( 90) __gshared int x10208_09; |
| @(100) __gshared const int x10208_10; |
| @(110) __gshared immutable int x10208_11; |
| @(120) __gshared int x10208_12 = 1200; |
| @(130) __gshared const int x10208_13 = 1300; |
| @(140) __gshared immutable int x10208_14 = 1400; |
| static assert(__traits(getAttributes, x10208_01)[0] == 10); // OK |
| static assert(__traits(getAttributes, x10208_02)[0] == 20); // OK |
| static assert(__traits(getAttributes, x10208_03)[0] == 30); // OK |
| static assert(__traits(getAttributes, x10208_04)[0] == 40); // OK |
| static assert(__traits(getAttributes, x10208_05)[0] == 50); // OK |
| static assert(__traits(getAttributes, x10208_06)[0] == 60); // Error -> OK |
| static assert(__traits(getAttributes, x10208_07)[0] == 70); // Error -> OK |
| static assert(__traits(getAttributes, x10208_08)[0] == 80); // OK |
| static assert(__traits(getAttributes, x10208_09)[0] == 90); // OK |
| static assert(__traits(getAttributes, x10208_10)[0] == 100); // OK |
| static assert(__traits(getAttributes, x10208_11)[0] == 110); // OK |
| static assert(__traits(getAttributes, x10208_12)[0] == 120); // OK |
| static assert(__traits(getAttributes, x10208_13)[0] == 130); // Error -> OK |
| static assert(__traits(getAttributes, x10208_14)[0] == 140); // Error -> OK |
| |
| /************************************************/ |
| // 11677, 11678 |
| |
| bool test_uda(alias func)() @safe |
| { |
| alias Tuple!(__traits(getAttributes, func)) udas; |
| static assert([udas] == [10, 20]); |
| |
| func(); // @safe attribute check |
| |
| return true; |
| } |
| |
| @(10) @(20) @safe void func11677a() {} // OK |
| @safe @(10) @(20) void func11677b() {} // OK <- NG |
| @(10) @safe @(20) void func11677c() {} // OK <- NG |
| |
| static assert(test_uda!func11677a()); |
| static assert(test_uda!func11677b()); |
| static assert(test_uda!func11677c()); |
| |
| void func11678a() @safe @(10) @(20) {} // OK <- NG |
| void func11678b() @(10) @safe @(20) {} // OK <- NG |
| void func11678c() @(10) @(20) @safe {} // OK <- NG |
| |
| static assert(test_uda!func11678a()); |
| static assert(test_uda!func11678b()); |
| static assert(test_uda!func11678c()); |
| |
| /************************************************/ |
| // 11678 |
| |
| class C11678 |
| { |
| this() @(10) @(20) {} |
| ~this() @(10) @(20) {} |
| } |
| |
| //static this() @(10) @(20) {} |
| static ~this() @(10) @(20) {} |
| |
| //shared static this() @(10) @(20) {} |
| shared static ~this() @(10) @(20) {} |
| |
| /************************************************/ |
| // 11679 |
| |
| void test11679() |
| { |
| @(10) @(20) auto var = 1; |
| static assert([__traits(getAttributes, var)] == [10, 20]); |
| } |
| |
| /************************************************/ |
| // 11680 |
| |
| @(10) gvar11680 = 1; // OK <- NG |
| @(10) gfun11680() {} // OK <- NG |
| |
| void test11680() |
| { |
| @(10) lvar11680 = 1; // OK <- NG |
| @(10) lfun11680() {} // OK <- NG |
| } |
| |
| /************************************************/ |
| // 11844 |
| |
| auto make_encode11844(T, string name)() |
| { |
| return mixin("function(T self) { return self.encodeField!\""~ name ~ "\"();}"); |
| } |
| |
| class FileData11844 |
| { |
| ulong _member; |
| |
| @make_encode11844!(FileData11844, "member")() |
| ulong member() const { return _member; } |
| |
| ubyte[] encodeField(string key)() { return [1,2,3]; } |
| } |
| |
| static assert(__traits(getAttributes, FileData11844.member)[0](new FileData11844()) == [1,2,3]); |
| |
| /************************************************/ |
| |
| template AliasSeq(T...) |
| { |
| alias AliasSeq = T; |
| } |
| |
| template ParameterUDA(size_t p_num, func...) |
| if (func.length == 1 && is(typeof(func[0]) PT == __parameters) && PT.length > p_num) |
| { |
| static if (is(typeof(func[0]) PT == __parameters)) |
| { |
| template Get(size_t i) |
| { |
| static if (//!isFunctionPointer!func && !isDelegate!func |
| // Parameters without UDA may yield CT error. |
| /*&&*/ is(typeof(__traits(getAttributes, PT[i..i+1]))x)) |
| { |
| alias Get = AliasSeq!(__traits(getAttributes, PT[i..i+1])); |
| } |
| else |
| { |
| alias Get = AliasSeq!(); |
| } |
| } |
| } |
| else |
| { |
| static assert(0, func[0].stringof ~ "is not a function"); |
| |
| // Define dummy entities to avoid pointless errors |
| template Get(size_t i) { alias Get = AliasSeq!(); } |
| alias PT = AliasSeq!(); |
| } |
| |
| alias ParameterUDA = Get!p_num; |
| } |
| |
| void test13x(@(10) int a, @(20) int, @(30) @(40) int[] arr...) {} |
| |
| void test13() |
| { |
| static assert([ParameterUDA!(0, test13x)] == [10]); |
| static assert([ParameterUDA!(1, test13x)] == [20]); |
| static assert([ParameterUDA!(2, test13x)] == [30, 40]); |
| } |
| |
| template Test13t(F) |
| { |
| static assert(!__traits(compiles, ParameterUDA!(0, F))); |
| static assert(!__traits(compiles, ParameterUDA!(1, F))); |
| static assert(!__traits(compiles, ParameterUDA!(2, F))); |
| enum Test13t = true; |
| } |
| |
| alias test13t = Test13t!(typeof(test13x)); |
| |
| enum Test14UDA1; |
| |
| struct Test14UDA2 |
| { |
| string str; |
| } |
| |
| Test14UDA2 test14uda3(string name) |
| { |
| return Test14UDA2(name); |
| } |
| |
| struct Test14UDA4(string v) |
| { |
| } |
| |
| void test14x(@Test14UDA1 int, @Test14UDA2("1") int, @test14uda3("2") int, @Test14UDA4!"3" int) {} |
| void test14() |
| { |
| static assert(is(ParameterUDA!(0, test14x)[0] == Test14UDA1)); |
| static assert(ParameterUDA!(1, test14x)[0] == Test14UDA2("1")); |
| static assert(ParameterUDA!(2, test14x)[0] == test14uda3("2")); |
| static assert(is(ParameterUDA!(3, test14x)[0] == Test14UDA4!"3")); |
| } |
| |
| void test15x(@(20) void delegate(int) @safe dg) |
| { |
| static assert([__traits(getAttributes, dg)] == [20]); |
| static assert(is(typeof(dg) == void delegate(int) @safe)); |
| } |
| |
| template MinimalFunctionTypeOf(func...) |
| if (func.length == 1) |
| { |
| static if (is(func[0] T) || is(typeof(func[0]) T) && is(T Fdlg == delegate)) |
| alias MinimalFunctionTypeOf = Fdlg; // HIT: delegate |
| else |
| static assert(0); |
| } |
| |
| template Parameters(func...) |
| if (func.length == 1) |
| { |
| static if (is(MinimalFunctionTypeOf!func P == function)) |
| alias Parameters = P; |
| else |
| static assert(0, "argument has no parameters"); |
| } |
| |
| void test15y(@(20) void delegate(@Test14UDA2("2") @("test15yUDA") int) @safe dg) |
| { |
| static assert([__traits(getAttributes, dg)] == [20]); |
| static assert(is(typeof(dg) == void delegate(int) @safe)); |
| auto foo = (@("myUDA") int x){ |
| static assert([__traits(getAttributes, x)] == ["myUDA"]); |
| }; |
| static assert(__traits(getAttributes, Parameters!dg)[0] == Test14UDA2("2")); |
| static assert(__traits(getAttributes, Parameters!dg)[1] == "test15yUDA"); |
| } |
| |
| void test15z() |
| { |
| test15y((@(15) @(16) int x){ |
| static assert([__traits(getAttributes, x)] == [15, 16]); |
| }); |
| } |
| |
| void test16x(A)(@(22) A a) |
| { |
| static assert([__traits(getAttributes, a)] == [22]); |
| } |
| |
| void test16() |
| { |
| static assert([ParameterUDA!(0, test16x!int)] == [22]); |
| } |
| |
| void test17() |
| { |
| void test17x(A)(@(23) A a) |
| { |
| static assert([__traits(getAttributes, a)] == [23]); |
| } |
| static assert([ParameterUDA!(0, test17x!int)] == [23]); |
| } |
| |
| void test18() |
| { |
| void test18a(@(Tuple!(18, "a")) int a) |
| { |
| static assert(__traits(getAttributes, a) == Tuple!(18, "a")); |
| } |
| void test18b(@Tuple!(18, "b") int a) |
| { |
| static assert(__traits(getAttributes, a) == Tuple!(18, "b")); |
| } |
| |
| static assert(ParameterUDA!(0, test18a) == Tuple!(18, "a")); |
| static assert(ParameterUDA!(0, test18b) == Tuple!(18, "b")); |
| } |
| |
| // Lambdas with parentheses: |
| void test19() |
| { |
| // lambdas without parentheses |
| alias test19a = @(3) b => 1 + 2; |
| alias test19b = @(3) @(4) b => 1 + 2; |
| |
| alias test19c = (@(3) c, @(5) d) => 1 + 2; |
| alias test19d = (@(3) @(4) c, @(5) d) => 1 + 2; |
| auto test19e = (@(3) int c, @(5) int d) => 1 + 2; |
| |
| // still allow alias function declarations |
| alias FuncType = @safe void function(); |
| alias FuncType2 = @safe nothrow void function(); |
| alias FuncType3 = nothrow void function(); |
| alias FuncType4 = nothrow @safe void function(); |
| } |
| |
| void test20() |
| { |
| // Using a delegate with inferred parameter type |
| void test20a(int delegate(int) t){ t(1); } |
| test20a((@(19) a) { |
| static assert([__traits(getAttributes, a)] == [19]); |
| return a + 2; |
| }); |
| } |
| |
| /************************************************/ |
| |
| |
| int main() |
| { |
| test1(); |
| test2(); |
| test3(); |
| test4(); |
| test5(); |
| test6(); |
| test7(); |
| test8(); |
| test9(); |
| test10(); |
| test11(); |
| test12(); |
| test9178(); |
| test13(); |
| test14(); |
| test16(); |
| test17(); |
| test18(); |
| test19(); |
| test20(); |
| |
| printf("Success\n"); |
| return 0; |
| } |