D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 3986 - Struct constructors bypass default initialization of member variables
Summary: Struct constructors bypass default initialization of member variables
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: Other Windows
: P2 blocker
Assignee: No Owner
URL:
Keywords: patch, wrong-code
Depends on:
Blocks:
 
Reported: 2010-03-19 16:13 UTC by Don
Modified: 2015-06-09 01:27 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Don 2010-03-19 16:13:43 UTC
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 Don 2010-03-20 00:26:22 UTC
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
Comment 2 Walter Bright 2010-03-27 00:34:11 UTC
changeset 421
Comment 3 Don 2010-04-10 12:45:32 UTC
Fixed DMD2.043.