D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 3190 - enum doesn't work as the increment in a for loop
Summary: enum doesn't work as the increment in a for loop
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86_64 Linux
: P2 major
Assignee: No Owner
URL:
Keywords: patch, wrong-code
: 3394 (view as issue list)
Depends on:
Blocks:
 
Reported: 2009-07-19 02:16 UTC by Lars T. Kyllingstad
Modified: 2015-06-09 01:28 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Lars T. Kyllingstad 2009-07-19 02:16:13 UTC
The following should print a list of numbers from 0 to 10:

    enum real ONE = 1.0;
    real x;
    for (x=0.0; x<10.0; x+=ONE)  writeln(x);
    writeln(x);

Instead it prints:

    0
    nan

I.e. the loop is only executed once, and x is set to NaN after the first iteration. The same happens if float is used instead of real. If double is used, the program goes into a near-infinite loop, spitting out very small numbers (starting with 6.65345e-316).

The following makes the program behave as expected:
  - making ONE a normal variable instead of an enum
  - writing "enum { real ONE }" instead
  - putting the increment inside the loop body
Comment 1 Don 2009-07-20 00:15:11 UTC
I suspect this is related to bug#2414 or bug#2998. There's definitely something badly wrong with D2 enum (manifest constant) assignment.
Comment 2 Don 2009-09-10 05:34:59 UTC
There are two problems here.
PROBLEM 1: This problem only shows up in for() loops because the increment condition isn't doing constant folding. This is a more general problem, which also affects D1.

statement.c line 1160 (DMD 2.032).

    if (increment)
    {	increment = increment->semantic(sc);
	increment = resolveProperties(sc, increment);
+	increment = increment->optimize(0);
    }

This change is enough to make the bug go away, but there's another oddity:

PROBLEM 2: It only happens for enum real ONE = 1.0; but not for enum : real { ONE = 1.0 }.
This is because expression.c DsymbolExp::semantic(Scope *sc) checks for enum members, but not for the new D2 manifest constants. I suspect that it probably should convert them, too, as in this second patch:

expression.c, line 2168.

    if (v)
    {
	//printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
	if (!type)
	{   type = v->type;
	    if (!v->type)
	    {	error("forward reference of %s %s", v->kind(), v->toChars());
		type = Type::terror;
	    }
	}
+	if ((v->storage_class & STCmanifest) && v->init) {
+	    e = v->init->toExpression();
+	    e->semantic(sc);
+	    return e;
+	}
	e = new VarExp(loc, v);
	e->type = type;
	e = e->semantic(sc);
	return e->deref();
    }
Comment 3 Don 2009-10-13 09:12:18 UTC
*** Issue 3394 has been marked as a duplicate of this issue. ***
Comment 4 Don 2009-10-21 06:40:59 UTC
Fixed DMD2.035.