Bug 3986 – Struct constructors bypass default initialization of member variables
Status
RESOLVED
Resolution
FIXED
Severity
blocker
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
Windows
Creation time
2010-03-19T16:13:00Z
Last change time
2015-06-09T01:27:03Z
Keywords
patch, wrong-code
Assigned to
nobody
Creator
clugdbug
Comments
Comment #0 by clugdbug — 2010-03-19T16:13:43Z
If a struct constructor is called implicitly, member variables are
not default initialized. Applies to D2.036 and later.
Here's a simple test case with an assert that fails. (Beware: this test case doesn't capture the more complex case where one of the members is itself a struct with a constructor). I'm pretty sure the problem is in declaration.c, around line 1140.
struct SiberianHamster
{
int rat = 813;
this(string z) { }
}
void main()
{
SiberianHamster basil = "cybil";
assert(basil.rat == 813);
}
Comment #1 by clugdbug — 2010-03-20T00:26:22Z
PATCH: In VarDeclaration::semantic, it should be doing a blit of the default initializer before it calls the constructor.
Currently it only does that for explicit constructor calls.
This bug as a blocker, since it makes struct invariants unusable: if a struct with a class invariant is used as a member of another struct, the invariant will fail on first use of that struct.
Index: declaration.c
===================================================================
--- declaration.c (revision 418)
+++ declaration.c (working copy)
@@ -1139,6 +1139,14 @@
// Rewrite as e1.ctor(arguments)
Expression *ector = new DotIdExp(loc, e1, Id::ctor);
ei->exp = new CallExp(loc, ector, ei->exp);
+ /* Before calling the constructor, initialize
+ * variable with a bit copy of the default
+ * initializer
+ */
+ Expression *e = new AssignExp(loc, e1, t->defaultInit(loc));
+ e->op = TOKblit;
+ e->type = t;
+ ei->exp = new CommaExp(loc, e, ei->exp);
}
else
/* Look for opCall