mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +03:00

* Fix Bugzilla 24383 - Index assignment expression in __traits(compiles) fails to parse * Fix parsing more than one argument * Fix comment Co-authored-by: Paul Backus <snarwin@gmail.com> --------- Co-authored-by: Paul Backus <snarwin@gmail.com>
322 lines
9.9 KiB
D
322 lines
9.9 KiB
D
// REQUIRED_ARGS: -extern-std=c++98
|
|
// EXTRA_FILES: imports/plainpackage/plainmodule.d imports/pkgmodule/package.d imports/pkgmodule/plainmodule.d
|
|
|
|
// This file is intended to contain all compilable traits-related tests in an
|
|
// effort to keep the number of files in the `compilable` folder to a minimum.
|
|
|
|
// https://issues.dlang.org/show_bug.cgi?id=19152
|
|
module traits;
|
|
|
|
class C19152
|
|
{
|
|
int OnExecute()
|
|
{
|
|
auto name = __traits(getOverloads, this, "OnExecute").stringof;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static assert(is(typeof(__traits(getTargetInfo, "cppRuntimeLibrary")) == string));
|
|
version (CppRuntime_Microsoft)
|
|
{
|
|
static assert(__traits(getTargetInfo, "cppRuntimeLibrary") == "libcmt" ||
|
|
__traits(getTargetInfo, "cppRuntimeLibrary")[0..6] == "msvcrt"); // includes mingw import libs
|
|
}
|
|
|
|
version (D_HardFloat)
|
|
static assert(__traits(getTargetInfo, "floatAbi") == "hard");
|
|
|
|
version (Win64)
|
|
static assert(__traits(getTargetInfo, "objectFormat") == "coff");
|
|
version (OSX)
|
|
static assert(__traits(getTargetInfo, "objectFormat") == "macho");
|
|
version (linux)
|
|
static assert(__traits(getTargetInfo, "objectFormat") == "elf");
|
|
|
|
static assert(__traits(getTargetInfo, "cppStd") == 199711);
|
|
|
|
import imports.plainpackage.plainmodule;
|
|
import imports.pkgmodule.plainmodule;
|
|
|
|
#line 40
|
|
struct MyStruct;
|
|
|
|
alias a = imports.plainpackage;
|
|
alias b = imports.pkgmodule.plainmodule;
|
|
|
|
static assert(__traits(isPackage, imports.plainpackage));
|
|
static assert(__traits(isPackage, a));
|
|
static assert(!__traits(isPackage, imports.plainpackage.plainmodule));
|
|
static assert(!__traits(isPackage, b));
|
|
static assert(__traits(isPackage, imports.pkgmodule));
|
|
static assert(!__traits(isPackage, MyStruct));
|
|
|
|
static assert(!__traits(isModule, imports.plainpackage));
|
|
static assert(!__traits(isModule, a));
|
|
static assert(__traits(isModule, imports.plainpackage.plainmodule));
|
|
static assert(__traits(isModule, b));
|
|
// This is supposed to work even though we haven't directly imported imports.pkgmodule.
|
|
static assert(__traits(isModule, imports.pkgmodule));
|
|
static assert(!__traits(isModule, MyStruct));
|
|
|
|
/******************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=19942
|
|
|
|
static assert(!__traits(compiles, { a.init; }));
|
|
static assert(!__traits(compiles, { import m : a; a.init; }));
|
|
|
|
version(Windows)
|
|
static assert(__traits(getLocation, MyStruct)[0] == `compilable\traits.d`);
|
|
else
|
|
static assert(__traits(getLocation, MyStruct)[0] == "compilable/traits.d");
|
|
static assert(__traits(getLocation, MyStruct)[1] == 40);
|
|
static assert(__traits(getLocation, MyStruct)[2] == 1);
|
|
|
|
int foo();
|
|
int foo(int);
|
|
|
|
static assert(__traits(getLocation, __traits(getOverloads, traits, "foo")[1])[1] == 74);
|
|
|
|
mixin("int bar;");
|
|
static assert(__traits(getLocation, bar)[1] == 78);
|
|
|
|
struct Outer
|
|
{
|
|
struct Nested{}
|
|
|
|
void method() {}
|
|
}
|
|
static assert(__traits(getLocation, Outer.Nested)[1] == 83);
|
|
static assert(__traits(getLocation, Outer.method)[1] == 85);
|
|
|
|
/******************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=19902
|
|
// Define hasElaborateCopyConstructor trait
|
|
// but done as two independent traits per conversation
|
|
// in https://github.com/dlang/dmd/pull/10265
|
|
|
|
struct S
|
|
{
|
|
this (ref S rhs) {}
|
|
}
|
|
|
|
struct OuterS
|
|
{
|
|
struct S
|
|
{
|
|
this (ref S rhs) {}
|
|
}
|
|
|
|
S s;
|
|
}
|
|
|
|
void foo(T)()
|
|
{
|
|
struct S(U)
|
|
{
|
|
this (ref S rhs) {}
|
|
}
|
|
static assert (__traits(hasCopyConstructor, S!int));
|
|
}
|
|
|
|
struct U(T)
|
|
{
|
|
this (ref U rhs) {}
|
|
}
|
|
|
|
struct SPostblit
|
|
{
|
|
this(this) {}
|
|
}
|
|
|
|
struct DisabledPostblit
|
|
{
|
|
@disable this(this);
|
|
}
|
|
|
|
struct NoCpCtor { }
|
|
class C19902 { }
|
|
|
|
static assert(__traits(hasCopyConstructor, S));
|
|
static assert(__traits(hasCopyConstructor, OuterS.S));
|
|
static assert(__traits(hasCopyConstructor, OuterS));
|
|
static assert(__traits(compiles, foo!int));
|
|
static assert(__traits(compiles, foo!S));
|
|
static assert(__traits(hasCopyConstructor, U!int));
|
|
static assert(__traits(hasCopyConstructor, U!S));
|
|
static assert(!__traits(hasPostblit, U!S));
|
|
static assert(__traits(hasPostblit, SPostblit));
|
|
static assert(!__traits(hasCopyConstructor, SPostblit));
|
|
|
|
static assert(!__traits(hasCopyConstructor, NoCpCtor));
|
|
static assert(!__traits(hasCopyConstructor, C19902));
|
|
static assert(!__traits(hasCopyConstructor, int));
|
|
static assert(!__traits(hasPostblit, NoCpCtor));
|
|
static assert(!__traits(hasPostblit, C19902));
|
|
static assert(!__traits(hasPostblit, int));
|
|
|
|
static assert(__traits(isCopyable, int));
|
|
static assert(!__traits(isCopyable, DisabledPostblit));
|
|
struct S1 {} // Fine. Can be copied
|
|
struct S2 { this(this) {} } // Fine. Can be copied
|
|
struct S3 { @disable this(this); } // Not fine. Copying is disabled.
|
|
struct S4 { S3 s; } // Not fine. A field has copying disabled.
|
|
class C1 {}
|
|
static assert( __traits(isCopyable, S1));
|
|
static assert( __traits(isCopyable, S2));
|
|
static assert(!__traits(isCopyable, S3));
|
|
static assert(!__traits(isCopyable, S4));
|
|
static assert(__traits(isCopyable, C1));
|
|
static assert(__traits(isCopyable, int));
|
|
static assert(__traits(isCopyable, int[]));
|
|
|
|
enum E1 : S1 { a = S1(), }
|
|
enum E2 : S2 { a = S2(), }
|
|
enum E3 : S3 { a = S3(), }
|
|
enum E4 : S4 { a = S4(), }
|
|
|
|
static assert(__traits(isCopyable, E1));
|
|
static assert(__traits(isCopyable, E2));
|
|
static assert(!__traits(isCopyable, E3));
|
|
static assert(!__traits(isCopyable, E4));
|
|
|
|
struct S5
|
|
{
|
|
@disable this(ref S5);
|
|
}
|
|
static assert(!__traits(isCopyable, S5));
|
|
|
|
/******************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=20884
|
|
|
|
struct S20884
|
|
{
|
|
int x;
|
|
}
|
|
|
|
alias T20884 = immutable(S20884);
|
|
enum m20884 = "x";
|
|
|
|
static assert(is(typeof(__traits(getMember, T20884, m20884)) == immutable(int))); // OK now
|
|
static assert(is( typeof(mixin("T20884." ~ m20884)) == immutable(int)));
|
|
static assert(is( typeof(T20884.x) == immutable(int)));
|
|
|
|
/******************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=20761
|
|
|
|
alias Seq(T...) = T;
|
|
|
|
static assert(__traits(isSame, Seq!(1, 2), Seq!(1, 2)));
|
|
static assert(!__traits(isSame, Seq!(1, 1), Seq!(2, 2)));
|
|
static assert(!__traits(isSame, Seq!(1, 1, 2), Seq!(1, 1)));
|
|
static assert(!__traits(isSame, Seq!(1, 1), Seq!(1, 1, 2)));
|
|
|
|
static assert(__traits(isSame,
|
|
Seq!(string, wstring),
|
|
Seq!(immutable(char)[], immutable(wchar)[]))
|
|
);
|
|
|
|
static assert(__traits(isSame,
|
|
Seq!(i => i.value, (a, b) => a + b),
|
|
Seq!(a => a.value, (x, y) => x + y)
|
|
));
|
|
|
|
static assert(__traits(isSame,
|
|
Seq!(float, Seq!(double, Seq!real)),
|
|
Seq!(Seq!(Seq!float, double), real)
|
|
));
|
|
|
|
static assert(!__traits(isSame,
|
|
Seq!(int, Seq!(a => a + a)),
|
|
Seq!(int, Seq!(a => a * a))
|
|
));
|
|
|
|
// Do these out of order to ensure there are no forward refencing bugs
|
|
|
|
extern(C++, __traits(getCppNamespaces,GetNamespaceTest1)) struct GetNamespaceTest4 {}
|
|
static assert (__traits(getCppNamespaces,GetNamespaceTest1) ==
|
|
__traits(getCppNamespaces,GetNamespaceTest4));
|
|
|
|
extern(C++, "ns") struct GetNamespaceTest1 {}
|
|
extern(C++, "multiple", "namespaces") struct GetNamespaceTest2 {}
|
|
extern(C++, mixin("Seq!(`ns`, `nt`)")) struct GetNamespaceTest3 {}
|
|
static assert(__traits(getCppNamespaces,GetNamespaceTest1)[0] == "ns");
|
|
static assert(__traits(getCppNamespaces,GetNamespaceTest2) == Seq!("multiple","namespaces"));
|
|
static assert(__traits(getCppNamespaces,GetNamespaceTest3) == Seq!("ns", "nt"));
|
|
|
|
extern(C++, __traits(getCppNamespaces,GetNamespaceTest5)) struct GetNamespaceTest8 {}
|
|
static assert (__traits(getCppNamespaces,GetNamespaceTest5) ==
|
|
__traits(getCppNamespaces,GetNamespaceTest8));
|
|
|
|
extern(C++, ns) struct GetNamespaceTest5 {}
|
|
extern(C++, multiple) extern(C++, namespaces) struct GetNamespaceTest6 {}
|
|
static assert(__traits(getCppNamespaces,GetNamespaceTest5)[0] == "ns");
|
|
static assert(__traits(getCppNamespaces,GetNamespaceTest6) == Seq!("multiple","namespaces"));
|
|
|
|
extern(C++, NS)
|
|
{
|
|
struct GetNamespaceTest9 {}
|
|
extern(C++, nested)
|
|
{
|
|
struct GetNamespaceTest10 {}
|
|
extern(C++,"nested2")
|
|
struct GetNamespaceTest11 {}
|
|
}
|
|
extern (C++, "nested3")
|
|
{
|
|
extern(C++, nested4)
|
|
struct GetNamespaceTest12 {}
|
|
}
|
|
}
|
|
static assert (__traits(getCppNamespaces,NS.GetNamespaceTest9)[0] == "NS");
|
|
static assert (__traits(getCppNamespaces,NS.GetNamespaceTest10) == Seq!("NS", "nested"));
|
|
static assert (__traits(getCppNamespaces,NS.GetNamespaceTest11) == Seq!("NS", "nested", "nested2"));
|
|
static assert (__traits(getCppNamespaces,NS.GetNamespaceTest12) == Seq!("NS", "nested4", "nested3"));
|
|
|
|
extern(C++, `ns`) struct GetNamespaceTestTemplated(T) {}
|
|
extern(C++, `ns`)
|
|
template GetNamespaceTestTemplated2(T)
|
|
{
|
|
struct GetNamespaceTestTemplated2 {}
|
|
}
|
|
|
|
template GetNamespaceTestTemplated3(T)
|
|
{
|
|
extern(C++, `ns`)
|
|
struct GetNamespaceTestTemplated3 {}
|
|
}
|
|
|
|
static assert (__traits(getCppNamespaces,GetNamespaceTestTemplated!int) == Seq!("ns"));
|
|
static assert (__traits(getCppNamespaces,GetNamespaceTestTemplated2!int) == Seq!("ns"));
|
|
static assert (__traits(getCppNamespaces,GetNamespaceTestTemplated3!int) == Seq!("ns"));
|
|
extern(C++, `ns2`)
|
|
template GetNamespaceTestTemplated4(T)
|
|
{
|
|
extern(C++, `ns`)
|
|
struct GetNamespaceTestTemplated4
|
|
{
|
|
struct GetNamespaceTestTemplated5 {}
|
|
struct GetNamespaceTestTemplated6(T) {}
|
|
}
|
|
}
|
|
|
|
static assert (__traits(getCppNamespaces,GetNamespaceTestTemplated4!int) == Seq!("ns2","ns"));
|
|
static assert (__traits(getCppNamespaces,GetNamespaceTestTemplated4!int.GetNamespaceTestTemplated5) == Seq!("ns2","ns"));
|
|
static assert (__traits(getCppNamespaces,GetNamespaceTestTemplated4!int.GetNamespaceTestTemplated6!int) == Seq!("ns2","ns"));
|
|
|
|
// Currently ignored due to https://issues.dlang.org/show_bug.cgi?id=21373
|
|
extern(C++, `decl`)
|
|
mixin template GetNamespaceTestTemplatedMixin()
|
|
{
|
|
extern(C++, `f`)
|
|
void foo() {}
|
|
}
|
|
|
|
extern(C++, `inst`)
|
|
mixin GetNamespaceTestTemplatedMixin!() GNTT;
|
|
|
|
static assert (__traits(getCppNamespaces, GNTT.foo) == Seq!(`inst`,/*`decl`,*/ `f`));
|
|
|
|
int[1] arr;
|
|
// test that index assignment parses as an expression, not a type
|
|
enum _ = __traits(compiles, arr[0] = 0);
|