blob: a01a5ca6039a13b514b26c3381ed6d0aff9446ed [file] [log] [blame]
/*
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;
}