diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2021-01-04 19:05:38 +0100 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2021-01-05 22:09:10 +0100 |
commit | c5e94699efa816444c0ae49ad55d0e01a48203df (patch) | |
tree | f527fd1748c2f034d74ca1b268d4f56fc36cf050 /gcc/testsuite/gdc.test/compilable | |
parent | ae1ada95fee1ee4fac0dec0486076d9787988a03 (diff) |
d: Merge upstream dmd a5c86f5b9
Adds the following new `__traits' to the D language.
- isDeprecated: used to detect if a function is deprecated.
- isDisabled: used to detect if a function is marked with @disable.
- isFuture: used to detect if a function is marked with @__future.
- isModule: used to detect if a given symbol represents a module, this
enhancement also adds support using `is(sym == module)'.
- isPackage: used to detect if a given symbol represents a package,
this enhancement also adds support using `is(sym == package)'.
- child: takes two arguments. The first must be a symbol or expression
and the second must be a symbol, such as an alias to a member of the
first 'parent' argument. The result is the second 'member' argument
interpreted with its 'this' context set to 'parent'. This is the
inverse of `__traits(parent, member)'.
- isReturnOnStack: determines if a function's return value is placed on
the stack, or is returned via registers.
- isZeroInit: used to detect if a type's default initializer has no
non-zero bits.
- getTargetInfo: used to query features of the target being compiled
for, the back-end can expand this to register any key to handle the
given argument, however a reliable subset exists which includes
"cppRuntimeLibrary", "cppStd", "floatAbi", and "objectFormat".
- getLocation: returns a tuple whose entries correspond to the
filename, line number, and column number of where the argument was
declared.
- hasPostblit: used to detect if a type is a struct with a postblit.
- isCopyable: used to detect if a type allows copying its value.
- getVisibility: an alias for the getProtection trait.
Reviewed-on: https://github.com/dlang/dmd/pull/12093
gcc/d/ChangeLog:
* dmd/MERGE: Merge upstream dmd a5c86f5b9.
* d-builtins.cc (d_eval_constant_expression): Handle ADDR_EXPR trees
created by build_string_literal.
* d-frontend.cc (retStyle): Remove function.
* d-target.cc (d_language_target_info): New variable.
(d_target_info_table): Likewise.
(Target::_init): Initialize d_target_info_table.
(Target::isReturnOnStack): New function.
(d_add_target_info_handlers): Likewise.
(d_handle_target_cpp_std): Likewise.
(d_handle_target_cpp_runtime_library): Likewise.
(Target::getTargetInfo): Likewise.
* d-target.h (struct d_target_info_spec): New type.
(d_add_target_info_handlers): Declare.
Diffstat (limited to 'gcc/testsuite/gdc.test/compilable')
10 files changed, 306 insertions, 2 deletions
diff --git a/gcc/testsuite/gdc.test/compilable/Test16206.d b/gcc/testsuite/gdc.test/compilable/Test16206.d new file mode 100644 index 00000000000..0b9ccf31876 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/Test16206.d @@ -0,0 +1,28 @@ +struct S { + static int foo()() { return 0; } + static int foo()(int n) { return 1; } + static int foo(string s) { return 2; } + enum foo(int[] arr) = arr.length; +} + +alias AliasSeq(T...) = T; + +alias allFoos = AliasSeq!(__traits(getOverloads, S, "foo", true)); + +static assert(allFoos.length == 4); + +static assert(allFoos[0]("") == 2); +static assert(allFoos[1]() == 0); +static assert(allFoos[2](1) == 1); +alias foo3 = allFoos[3]; +static assert(foo3!([]) == 0); + +static assert(S.foo() == 0); +static assert(S.foo(1) == 1); +static assert(S.foo("") == 2); +static assert(S.foo!([]) == 0); + + +alias fooFuns = AliasSeq!(__traits(getOverloads, S, "foo")); +static assert(fooFuns.length == 1); +static assert(fooFuns[0]("") == 2);
\ No newline at end of file diff --git a/gcc/testsuite/gdc.test/compilable/imports/pkgmodule/package.d b/gcc/testsuite/gdc.test/compilable/imports/pkgmodule/package.d new file mode 100644 index 00000000000..b6e98ff011b --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/pkgmodule/package.d @@ -0,0 +1,3 @@ +/// Used to test is(x == package) and is(x == module) + +module imports.pkgmodule; diff --git a/gcc/testsuite/gdc.test/compilable/imports/pkgmodule/plainmodule.d b/gcc/testsuite/gdc.test/compilable/imports/pkgmodule/plainmodule.d new file mode 100644 index 00000000000..948a87e5fee --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/pkgmodule/plainmodule.d @@ -0,0 +1,2 @@ +/// Used to test is(x == module) +module imports.pkgmodule.plainmodule; diff --git a/gcc/testsuite/gdc.test/compilable/imports/plainpackage/plainmodule.d b/gcc/testsuite/gdc.test/compilable/imports/plainpackage/plainmodule.d new file mode 100644 index 00000000000..9e9933b379b --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/plainpackage/plainmodule.d @@ -0,0 +1,4 @@ +/// Used to test is(x == module) + +module imports.plainpackage.plainmodule; + diff --git a/gcc/testsuite/gdc.test/compilable/isZeroInit.d b/gcc/testsuite/gdc.test/compilable/isZeroInit.d new file mode 100644 index 00000000000..b5423cfb636 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/isZeroInit.d @@ -0,0 +1,78 @@ +alias AliasSeq(T...) = T; + +struct Holder(T, ubyte val) +{ + T x = val; +} + +struct SArrayHolder(T, ubyte val) +{ + T[2] x = val; +} + +static foreach (T; AliasSeq!(bool, byte, short, int, long, + ubyte, ushort, uint, ulong, + char, wchar, dchar, + float, double, real)) +{ + static assert(__traits(isZeroInit, T) == (T.init is T(0))); + static assert(__traits(isZeroInit, T[2]) == (T.init is T(0))); + + static assert(!__traits(isZeroInit, Holder!(T, 1))); + static assert(__traits(isZeroInit, Holder!(T, 0))); + + static assert(__traits(isZeroInit, SArrayHolder!(T, 0))); + static assert(!__traits(isZeroInit, SArrayHolder!(T, 1))); + +} + +static assert(__traits(isZeroInit, void)); // For initializing arrays of element type `void`. +static assert(__traits(isZeroInit, void*)); +static assert(__traits(isZeroInit, void[])); +static assert(__traits(isZeroInit, float[])); +static assert(__traits(isZeroInit, Object)); +class C1 : Object +{ + int x = 1; +} +static assert(__traits(isZeroInit, C1)); // An Object's fields are irrelevant. + +struct S1 +{ + int[] a; + int b; +} +static assert(__traits(isZeroInit, S1)); + +struct S2 +{ + alias H = Holder!(int, 1); + H h; + int a; +} +static assert(!__traits(isZeroInit, S2)); + +struct S3 +{ + S1 h; + float f = 0; +} +static assert(__traits(isZeroInit, S3)); + +struct S4 +{ + S2 h = S2(S2.H(0), 0); + int a; +} +static assert(__traits(isZeroInit, S4)); + +struct S5 +{ + Object o = null; +} +static assert(__traits(isZeroInit, S5)); + +version(D_SIMD): +import core.simd : int4; +static assert(__traits(isZeroInit, Holder!(int4, 0))); +static assert(!__traits(isZeroInit, Holder!(int4, 1))); diff --git a/gcc/testsuite/gdc.test/compilable/isreturnonstack.d b/gcc/testsuite/gdc.test/compilable/isreturnonstack.d new file mode 100644 index 00000000000..8bdb97de13f --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/isreturnonstack.d @@ -0,0 +1,7 @@ +struct S { int[10] a; } +int test1(); +S test2(); + +static assert(__traits(isReturnOnStack, test1) == false); +static assert(__traits(isReturnOnStack, test2) == true); + diff --git a/gcc/testsuite/gdc.test/compilable/line.d b/gcc/testsuite/gdc.test/compilable/line.d index 5122ed3cbf8..14e178988c8 100644 --- a/gcc/testsuite/gdc.test/compilable/line.d +++ b/gcc/testsuite/gdc.test/compilable/line.d @@ -19,12 +19,12 @@ static assert(__FILE_FULL_PATH__[$-__FILE__.length..$] == __FILE__); static assert(__LINE__ == 101); static assert(__FILE__ == "newfile.d"); -static assert(__FILE_FULL_PATH__ == "newfile.d"); +static assert(__FILE_FULL_PATH__[$ - 9 .. $] == "newfile.d"); # line 200 static assert(__LINE__ == 201); static assert(__FILE__ == "newfile.d"); -static assert(__FILE_FULL_PATH__ == "newfile.d"); +static assert(__FILE_FULL_PATH__[$ - 9 .. $] == "newfile.d"); diff --git a/gcc/testsuite/gdc.test/compilable/test16002.d b/gcc/testsuite/gdc.test/compilable/test16002.d new file mode 100644 index 00000000000..f3303c0e310 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test16002.d @@ -0,0 +1,24 @@ +module test.compilable.test16002; + +import imports.plainpackage.plainmodule; +import imports.pkgmodule.plainmodule; + +struct MyStruct; + +alias a = imports.plainpackage; +alias b = imports.pkgmodule.plainmodule; + +static assert(is(imports.plainpackage == package)); +static assert(is(a == package)); +static assert(!is(imports.plainpackage.plainmodule == package)); +static assert(!is(b == package)); +static assert(is(imports.pkgmodule == package)); +static assert(!is(MyStruct == package)); + +static assert(!is(imports.plainpackage == module)); +static assert(!is(a == module)); +static assert(is(imports.plainpackage.plainmodule == module)); +static assert(is(b == module)); +// This is supposed to work even though we haven't directly imported imports.pkgmodule. +static assert(is(imports.pkgmodule == module)); +static assert(!is(MyStruct == module)); diff --git a/gcc/testsuite/gdc.test/compilable/test17791.d b/gcc/testsuite/gdc.test/compilable/test17791.d new file mode 100644 index 00000000000..3244c129aa9 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test17791.d @@ -0,0 +1,28 @@ +/* +REQUIRED_ARGS: -de +TEST_OUTPUT: +--- +--- +*/ +deprecated("A deprecated class") { +class DepClass +{ +} +} + +class NewClass +{ +} + +void main() +{ + // test that a symbol (which is not likely to be deprecated) + // is not depercated + static assert(!__traits(isDeprecated, int)); + // check that a class marked deprecated "isDeprecated" + static assert(__traits(isDeprecated, DepClass)); + // check that a class not marked deprecated is not deprecated + static assert(!__traits(isDeprecated, NewClass)); + // Check for expressions (18617) + static assert(__traits(isDeprecated, { scope foo = new DepClass; })); +} diff --git a/gcc/testsuite/gdc.test/compilable/traits.d b/gcc/testsuite/gdc.test/compilable/traits.d index 736eae4a89d..4d8a5e140c4 100644 --- a/gcc/testsuite/gdc.test/compilable/traits.d +++ b/gcc/testsuite/gdc.test/compilable/traits.d @@ -1,10 +1,140 @@ // REQUIRED_ARGS: +// 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"); +} + +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) {} + } +} + +struct U(T) +{ + this (ref U rhs) {} +} + +struct SPostblit +{ + this(this) {} +} + +struct DisabledPostblit +{ + @disable this(this); +} + +struct NoCpCtor { } +class C19902 { } + +static assert(__traits(compiles, foo!int)); +static assert(__traits(compiles, foo!S)); +static assert(!__traits(hasPostblit, U!S)); +static assert(__traits(hasPostblit, SPostblit)); + +static assert(!__traits(hasPostblit, NoCpCtor)); +static assert(!__traits(hasPostblit, C19902)); +static assert(!__traits(hasPostblit, int)); + +// Check that invalid use cases don't compile +static assert(!__traits(compiles, __traits(hasPostblit))); +static assert(!__traits(compiles, __traits(hasPostblit, S()))); + +static assert(__traits(isCopyable, int)); +static assert(!__traits(isCopyable, DisabledPostblit)); |