mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 05:00:16 +03:00

* Fix 24056 - const uninitialized data at module scope is not in TLS * Update tests * Add changelog entry
116 lines
3.2 KiB
D
116 lines
3.2 KiB
D
|
|
/******************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=3449
|
|
|
|
template TypeTuple(T...) { alias TypeTuple = T; }
|
|
|
|
// If module variable has no explicit initializer,
|
|
// constant folding is not allowed for that.
|
|
int mg1;
|
|
const int cg1;
|
|
immutable int ig1;
|
|
static this()
|
|
{
|
|
mg1 = 10;
|
|
}
|
|
|
|
shared static this()
|
|
{
|
|
cg1 = 10;
|
|
ig1 = 10;
|
|
}
|
|
static assert(!__traits(compiles, { static assert(mg1 == 0); }));
|
|
static assert(!__traits(compiles, { static assert(cg1 == 0); }));
|
|
static assert(!__traits(compiles, { static assert(ig1 == 0); }));
|
|
|
|
// But, if module variable has explicit initializer and
|
|
// non-mutable type, constant folding is allowed for that..
|
|
int mg2 = 1;
|
|
const int cg2 = 1;
|
|
immutable int ig2 = 1;
|
|
static this()
|
|
{
|
|
mg2 = 11;
|
|
static assert(!__traits(compiles, cg2 = 11)); // not allowed for constant folding
|
|
static assert(!__traits(compiles, ig2 = 11)); // not allowed for constant folding
|
|
}
|
|
static assert(!__traits(compiles, { static assert(mg2 == 1); }));
|
|
static assert(cg2 == 1); // possible
|
|
static assert(ig2 == 1); // possible
|
|
|
|
// For aggregate fields, compiler behavior will be changed.
|
|
void test3449()
|
|
{
|
|
static struct S(T)
|
|
{
|
|
T field1; // doesn't have explicit initializer
|
|
T field2 = 1; // has explicit initializer
|
|
|
|
this(int n)
|
|
{
|
|
field1 = n; // allowed
|
|
field2 = n; // NEW! re-assigning during construction is allowed for any qualified fields.
|
|
}
|
|
}
|
|
|
|
foreach (T; TypeTuple!(int, const int, immutable int))
|
|
{
|
|
alias S!T ST;
|
|
|
|
auto s1 = ST(); // default construction
|
|
assert(s1.field1 == 0); // == T.init
|
|
assert(s1.field2 == 1); // == specified initializer
|
|
|
|
// Getting address for non-mutable field is allowed.
|
|
T* s1p1 = &s1.field1;
|
|
T* s1p2 = &s1.field2;
|
|
assert(*s1p1 == 0);
|
|
assert(*s1p2 == 1);
|
|
static if (is(T == int))
|
|
{ // If T is mutable,
|
|
// modification through indirection is allowed
|
|
*s1p1 = 100, *s1p2 = 101;
|
|
assert(*s1p1 == 100);
|
|
assert(*s1p2 == 101);
|
|
}
|
|
else
|
|
{ // If T is not mutable, modification is not allowed
|
|
static assert(!__traits(compiles, *s1p1 = 100));
|
|
static assert(!__traits(compiles, *s1p2 = 100));
|
|
}
|
|
|
|
// Access to non-static non-mutable field is
|
|
// now correctly rejected by "need this" error.
|
|
static assert(!__traits(compiles, ST.field1 == 1));
|
|
static assert(!__traits(compiles, ST.field2 == 0));
|
|
|
|
// So, re-assignment of non-mutable fields
|
|
// during construction is enough acceptable.
|
|
auto s2 = ST(10);
|
|
assert(s2.field1 == 10);
|
|
assert(s2.field2 == 10);
|
|
}
|
|
}
|
|
|
|
/******************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=10643
|
|
|
|
struct S10643
|
|
{
|
|
const int[1000] x = void;
|
|
|
|
this(int n)
|
|
{
|
|
x[] = n;
|
|
}
|
|
}
|
|
static assert(S10643.sizeof == int.sizeof * 1000);
|
|
|
|
/******************************************/
|
|
|
|
int main()
|
|
{
|
|
test3449();
|
|
|
|
return 0;
|
|
}
|