Bug 1432 – Bogus "overlapping initialization" error with structs, unions, and member initializers

Status
REOPENED
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2007-08-19T09:58:36Z
Last change time
2024-12-13T17:47:56Z
Keywords
rejects-valid
Assigned to
No Owner
Creator
Jarrett Billingsley
Moved to GitHub: dmd#17615 →

Comments

Comment #0 by jarrett.billingsley — 2007-08-19T09:58:36Z
struct S { int blah = 5; union { int x; T t; Object o; } } struct T { int y; } Gives the error "dtest.d(26): struct dtest.S overlapping initialization for struct S.blah" If you remove the initializer for S.blah, or if you remove the t member from that union, or if you make the union named, it works.
Comment #1 by tomas — 2009-04-22T21:33:19Z
Another variation: union S { float[2] a; struct { union { float i = 1; float x; } union { float j = 2; float y; } } } $ dmd bar.d -c bar.d(2): Error: union bar.S overlapping initialization for struct S.i bar.d(2): Error: union bar.S overlapping initialization for struct S.j If 'a' is moved below the anonymous struct it works. The spec does not mention this special case as far as I can tell. Explicit initialization of aggregate fields inside anonymous struct/union combinations should be documented.
Comment #2 by hoganmeier — 2011-11-27T06:08:55Z
The first example compiles fine now. Really not sure if the second should compile at all, but the order of compilation dependence is definitely a bug.
Comment #3 by k.hara.pg — 2013-10-01T07:16:17Z
(In reply to comment #1) > Another variation: > > union S > { > float[2] a; > struct > { > union { float i = 1; float x; } > union { float j = 2; float y; } > } > } > > $ dmd bar.d -c > bar.d(2): Error: union bar.S overlapping initialization for struct S.i > bar.d(2): Error: union bar.S overlapping initialization for struct S.j > > If 'a' is moved below the anonymous struct it works. The spec does not mention > this special case as far as I can tell. Explicit initialization of aggregate > fields inside anonymous struct/union combinations should be documented. More reduced test case. union U1 { int a = 1; // OK string b; } union U2 { int a; string b = "s"; // overlapping initialization for struct U2.b } I discovered this behavior while debugging other compiler bug. If there's overlapped fields, and the non-first field is explicitly initialized, compiler rejects it by "overlapping initialization". As far as I see, the behavior seems to be intended by the current compiler code. However, normally D language semantics does not rely on the lexical order of declarations. I can agree that the behavior is contrary to the basic principle. --- I'd propose more better semantics: If exactly one field has an explicit initializer between overlapped fields, compiler should prefer it for default initialization. U1 u1; assert(u1.a == 1); U2 u2; assert(u2.b == "s"); If there's no explicitly initialized field between overlapped siblings, the first one is initialized at the default initialization. union U3 { int a; char c; } U3 u3; assert(u3.a == 0); union U4 { char c; int a; } U4 u4; assert(u4.c == 0xff); If two or more fields have explicit initializers between overlapped siblings, it would cause compilation error. union U5 { int a = 1, string b = "s" } U5 u5; // Error: overlapped initialization between U5.a and U5.b How about that?
Comment #4 by k.hara.pg — 2013-10-01T07:17:08Z
Change to D2 issue.
Comment #5 by code — 2013-12-16T00:10:49Z
Do we have a distinction between explicit and implicit initialization somewhere else in the language? Otherwise it's idfficult to explain, why these two differ. union { int a; string b = "s"; } union { int a = 0; string b = "s"; }
Comment #6 by k.hara.pg — 2013-12-16T00:51:07Z
(In reply to comment #5) > Do we have a distinction between explicit and implicit initialization somewhere > else in the language? > Otherwise it's idfficult to explain, why these two differ. > union { int a; string b = "s"; } > union { int a = 0; string b = "s"; } I think the main argument of this issue is, that explicitly initialized overlapped field should be always preferred than default initializing. The two concepts, overlapping fields and default initializing behavior for safely programming is normally conflict each other, because Compiler cannot initialize all of overlapped fields by default. Therefore, D language should specially treat overlapped fields. For union U { T1 f1; T2 f2; ... }, T1.init is picked for the default initializer of overlapped fields. I think it is legitimate behavior because it is C-compatible. However, if only one overlapped fields are explicitly initialized by programmer, current dmd behaves foolish. union U1 { T1 f1 = x; T2 f2; } // x is used for default initializer union U2 { T1 f1; T2 f2 = x; } // x conflicts with implicitly picked default initializer T1.init ! This is D-specific case, and I think the current behavior is contrary to the two D language concepts - 1. If programmer specifies something explicitly, compiler should respect it. 2. If it is unnecessary, order dependent feature is not good. In the U2 case, programmer explicitly add a initializer for the overlapped field f2. So, I think compiler should pick it. Of course, two or more overlapped fields have explicit initializers, it should be an error. union U3 { T1 f1 = x; T2 f2 = y; // explicit specified initializers x and y conflicts each other
Comment #7 by code — 2013-12-16T12:52:04Z
I see, you're right. Specifically one should be able to explicitly default initialize a field. union { T1 t1; T2 t2 = T2.init; } NB: A workaround to the aforementioned bug is to simply change the order of union fields so that the one with explicit initializer comes first.
Comment #8 by simen.kjaras — 2017-09-19T09:54:10Z
This works in 2.075.1.
Comment #9 by ibuclaw — 2021-12-26T22:52:18Z
This issue seems to be closed for the wrong reason. From runnable/structlit.d: --- union U7727A3 { int i; double d = 2.5; } union U7727B3 { double d; int i = 123; } void test7727() { import core.stdc.math : isnan; // Blocked by https://issues.dlang.org/show_bug.cgi?id=1432 { U7727A3 u; assert(u.d == 2.5); } { U7727A3 u = { i: 1024 }; assert(u.i == 1024); } { U7727A3 u = { d: 1.225 }; assert(u.d == 1.225); } static assert(!__traits(compiles, { U7727A3 u = { i: 1024, d: 1.225 }; } )); // Blocked by https://issues.dlang.org/show_bug.cgi?id=1432 { U7727B3 u; assert(u.i == 123); } { U7727B3 u = { i: 1024 }; assert(u.i == 1024); } { U7727B3 u = { d: 1.225 }; assert(u.d == 1.225); } static assert(!__traits(compiles, { U7727B3 u = { i: 1024, d: 1.225 }; } )); }
Comment #10 by robert.schadek — 2024-12-13T17:47:56Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/17615 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB