D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 5790 - "Error: variable result used before set" when -release -inline -O
Summary: "Error: variable result used before set" when -release -inline -O
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 critical
Assignee: Walter Bright
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-03-28 05:54 UTC by Jordi Rovira i Bonet
Modified: 2012-01-12 01:14 UTC (History)
6 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Jordi Rovira i Bonet 2011-03-28 05:54:10 UTC
When compiling the following code with 

dmd -c -release -inline -O resource.d

I get the message "Error: variable result used before set" without any line information, and compilation fails.

This happens only with the flags above. Removing any of them, or compiling in debug results in good output. I have verified that this error happens both in linux and windows, with dmd 2.052 and since many versions ago. 

<Speculation>
Even GDC crashes compiling this code in release, which makes me think it is in the front end.

<Data>
I have removed everything i could, and now the code doesn't make much sense, but the file resource.d is:

module 	bug;

import 	std.c.string;

class InputStream
{
public:
	
	InputStream opShr(T)( out T result )
	{
		memcpy( &result, &m_data[m_pos], T.sizeof );
		m_pos += T.sizeof;
		
		return this;
	} 

	int m_pos;
	const ubyte[] m_data;
}

struct GUID
{
	uint m_values[4];
};

struct Header
{
	int ver;
	int siz;
	GUID id;
}

void LoadResourceLegacyHeader( InputStream f, out Header header )
{
	f >> header.id;
}
Comment 1 bearophile_hugs 2011-03-28 10:13:29 UTC
(In reply to comment #0)

> I have removed everything i could,

Reduced program:


struct Foo {
    int x;
    int[3] y;
}
void baz(out int[3] y2) {
    y2[0]++;
}
void spam(out Foo f) {
    baz(f.y);
}
void main() {}
Comment 2 Jordi Rovira i Bonet 2011-03-28 10:17:14 UTC
(In reply to comment #1)
> (In reply to comment #0)
> 
> > I have removed everything i could,
> 
> Reduced program:
> 
> 
> struct Foo {
>     int x;
>     int[3] y;
> }
> void baz(out int[3] y2) {
>     y2[0]++;
> }
> void spam(out Foo f) {
>     baz(f.y);
> }
> void main() {}

Thanks!
Comment 3 bearophile_hugs 2011-03-28 10:18:41 UTC
Critical, as per Don request.
Comment 4 kennytm 2011-03-28 10:23:03 UTC
Also reproducible with '-inline -noboundscheck -O'. Should be a backend issue in gother.c.

-------- 

struct H {
    double a;
    int[3] b;   // must not be the first member in a struct, and must be an array with 3 or more members
}

void g(out int[3] t) {   // must take 'out' parameter
    t[0]=0;   // can be any mutating expression
}

void h (H* x) { // or 'out H' or 'ref H'
    g(x.b);
}
Comment 5 kennytm 2011-08-02 12:50:03 UTC
Another test case, which is triggered only on Linux and FreeBSD.

-----------------------------------
void test5790d() {
    int x;
    int y = *(1 + &x);
}
-----------------------------------
$ dmd -O -c test5790d.d
Error: variable x used before set
-----------------------------------

See also https://github.com/D-Programming-Language/dmd/pull/243#issuecomment-1706278.
Comment 6 Walter Bright 2011-08-03 09:58:41 UTC
This is possibly related to:

http://d.puremagic.com/issues/show_bug.cgi?id=5239
Comment 7 Brad Roberts 2011-08-03 20:41:58 UTC
Confirmed that the reduction in comment 2 still reproduces the problem.  It reports y2 as used before set (with no line number).

The two fixes to this part of the compiler aren't sufficient to catch this one.
Comment 8 Jonas Drewsen 2012-01-11 14:14:30 UTC
Additional test case using only the -O flag and no -inline or -release flags necessary.

import std.typecons;

void main(string[] args) {
    
    // Errors
    auto i = Tuple!(string,string)("foo", "bar")[1];

    // Ok
    auto j = Tuple!(string,string)("foo", "bar");
    auto k = j[1];
}
Comment 9 Kenji Hara 2012-01-12 01:12:06 UTC
(In reply to comment #8)
> Additional test case using only the -O flag and no -inline or -release flags
> necessary.
> 
> import std.typecons;
> 
> void main(string[] args) {
> 
>     // Errors
>     auto i = Tuple!(string,string)("foo", "bar")[1];
> 
>     // Ok
>     auto j = Tuple!(string,string)("foo", "bar");
>     auto k = j[1];
> }

This is a dup of 7263. See it.
Comment 10 Kenji Hara 2012-01-12 01:14:03 UTC
(In reply to comment #7)
> Confirmed that the reduction in comment 2 still reproduces the problem.  It
> reports y2 as used before set (with no line number).
> 
> The two fixes to this part of the compiler aren't sufficient to catch this one.

Walter already committed a fix for this issue.

https://github.com/D-Programming-Language/dmd/commit/68b51f24ec25b20df19a5f53b0252d820d2c4d1d

https://github.com/D-Programming-Language/dmd/commit/c5d673247289279a54339dfbb6d27733ed3fd63b

And comment#2 code can compile with 2.058head.