Bug 4322 – "void initializer has no value" on struct/union members initialized to "void"

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Linux
Creation time
2010-06-15T10:37:00Z
Last change time
2011-03-01T17:09:41Z
Keywords
patch
Assigned to
nobody
Creator
graham.fawcett

Attachments

IDFilenameSummaryContent-TypeSize
664expression.patchproposed patchtext/plain643
665mtype.patchpatch for mtype.ctext/plain1134

Comments

Comment #0 by graham.fawcett — 2010-06-15T10:37:45Z
The following code fails to compile: struct Foo { int[1] a = void; } void main() { Foo f = Foo(); } $ dmd err.d err.d(2): Error: void initializer has no value Removing the "= void" initializer resolves the issue. The error is not related to the size of the array, or the element type. Note that phobos/std/variant.d, line 192, has such a declaration, which causes some variant-using application code to fail with the same error message.
Comment #1 by graham.fawcett — 2010-06-15T13:15:09Z
FWIW, removing line 100 in init.c allows simple examples to compile and run correctly. Of course I'm not 100% clear on why the error message was there in the first place. :) diff --git a/trunk/src/init.c b/trunk/src/init.c index ed3a091..cf9bc72 100644 --- a/trunk/src/init.c +++ b/trunk/src/init.c @@ -97,7 +97,6 @@ Initializer *VoidInitializer::semantic(Scope *sc, Type *t) Expression *VoidInitializer::toExpression() { - error(loc, "void initializer has no value"); return new IntegerExp(0); } best, Graham
Comment #2 by bearophile_hugs — 2010-06-15T14:05:06Z
Answer to Comment 1. You can try to compile this, this must raise an 'void initializer has no value' error still: void main() { void[1] a; }
Comment #3 by clugdbug — 2010-06-15T14:55:14Z
(In reply to comment #1) > FWIW, removing line 100 in init.c allows simple examples to > compile and run correctly. Of course I'm not 100% clear on why the > error message was there in the first place. :) > > diff --git a/trunk/src/init.c b/trunk/src/init.c > index ed3a091..cf9bc72 100644 > --- a/trunk/src/init.c > +++ b/trunk/src/init.c > @@ -97,7 +97,6 @@ Initializer *VoidInitializer::semantic(Scope *sc, Type > *t) > > Expression *VoidInitializer::toExpression() > { > - error(loc, "void initializer has no value"); > return new IntegerExp(0); > } > > best, > Graham That's too general, the error message is important in other places. I think the correct fix for the bug, is to allow a void initializer to be used inside another initializer. This might be a bug in the array literal initializers in mtype.c, which (from memory) creates an array literal by converting the initializers to expressions. At least in the case where ALL initializers are void, the final initializer could also be void. So the test case should be transformed into: Foo f = void; But the simplest solution is probably to change all members into default initializers, if they are a VoidInitializers. I recommend to put a breakpoint on the error message and find out where it's being called from.
Comment #4 by graham.fawcett — 2010-06-16T06:39:19Z
Created attachment 664 proposed patch When initializing an array, this patch tests whether the initializer is a VoidInitializer, and if so, avoids the toExpression() call. This permits arrays to be initialized "= void". This compiles and appears to work as expected: void main() { struct foo { union { char[100] c = void; ubyte[100] b } ubyte[5] good = 44; ubyte[5] bad = void; } foo f = foo(); writeln("b ", f.b); writeln("c ", f.c); writeln("good ", f.good); writeln("bad ", f.bad); } "good" displays as '44 44 44 44 44', but the void attributes appear uninitialized. This still fails to compile (as it should): void main() { void[1] a; }
Comment #5 by graham.fawcett — 2010-06-16T12:31:07Z
(In reply to comment #3) > That's too general, the error message is important in other places. I think the > correct fix for the bug, is to allow a void initializer to be used inside > another initializer. This might be a bug in the array literal initializers in > mtype.c, which (from memory) creates an array literal by converting the > initializers to expressions. At least in the case where ALL initializers are > void, the final initializer could also be void. > So the test case should be transformed into: > Foo f = void; > But the simplest solution is probably to change all members into default > initializers, if they are a VoidInitializers. > I recommend to put a breakpoint on the error message and find out where it's > being called from. Don, you're right. My test case above did not fail through mtype.c, but rather through expression.c (and I've proposed a patch for that). But I was able to produce a similar bug through mtype.c: import std.stdio; import std.variant; import std.algorithm; void main() { foreach (int v; map! "a.get!int" (variantArray(1,2,3))) writeln(v); } which fails here: #0 VoidInitializer::toExpression (this=0x9139748) at init.c:100 #1 0x0810047b in TypeStruct::defaultInitLiteral (this=0x8d98ff0, loc=...) at mtype.c:6921 #2 0x081039b5 in Type::getProperty (this=0x8d98ff0, loc=..., ident=0x81aec50) at mtype.c:1691 #3 0x08102944 in Type::dotExp (this=0x8d98ff0, sc=0x9177c50, e=0x9320c88, ident=0x81aec50) at mtype.c:1809 etc. I'll take a look into mtype.c as well.
Comment #6 by graham.fawcett — 2010-06-16T12:42:14Z
Created attachment 665 patch for mtype.c This extends my earlier patch by modifying mtype.c as well. I don't have a bare case unfortunately, but this will compile properly with a patched compiler: import std.algorithm; import std.variant; import std.stdio; void main() { foreach (int v; map! "a.get!int" (variantArray(1,2,3))) writeln(v); }
Comment #7 by braddr — 2011-02-06T15:40:39Z
Mass migration of bugs marked as x86-64 to just x86. The platform run on isn't what's relevant, it's if the app is a 32 or 64 bit app.
Comment #8 by clugdbug — 2011-03-01T17:09:41Z