Thread overview
BUGs: Nested function problems
Dec 26, 2004
h3r3tic
Dec 28, 2004
Simon Buchan
Dec 30, 2004
Thomas Kuehne
December 26, 2004
Now this bug is interesting :>
I have a function taking some parameters, yet this function doesn't do anything directly. Instead it calls a nested function which in turn doesn't take any parameters. Now, the standard says " Nested functions have access to the variables and other symbols defined by the lexically enclosing function". This probably applies as well to the enclosing function's parameters as they are visible in the nested function.
However, in a very specific case, the data that the nested function accesses is somehow corrupted.
On the other hand, if I pass every parameter of the enclosing function to the nested one, the data is just fine.
The source for the bug is quite longish, yet I was unable to reduce its size any further. The function of interest is "extractTriangles". It contains a nested function "foobar". The code compiles and when ran, an exception is caught.
Now, when the nested function is removed (and its contents are moved to the enclosing function), the program runs just fine. It doesn't really matter what it does, the fact is that the variable "geomObj.name" contains invalid data, whilst it should contain text "NODE".

That's one thing. Another is that the nested 'foobar' function contains a try-catch block:
	void foobar()
	{
		try
		{
			writefln("name: ", geomObj.name);
			return;		
			geomObj.mesh.faces[0].a - geomObj.xlate;
		}
		catch(Object err)
		{
			throw err;
		}
	}

When the try and catch statements are removed like this:
	void foobar()
	{
			writefln("name: ", geomObj.name);
			return;		
			geomObj.mesh.faces[0].a - geomObj.xlate;
	}

And I compile with "-inline", then the compile result looks like this:
> Internal error: e2ir.c 615

But wait, that's not all... the internal error disappears when I leave the scope of the try block in place like this:
	void foobar()
	{
		{
			writefln("name: ", geomObj.name);
			return;
			geomObj.mesh.faces[0].a - geomObj.xlate;
		}
	}

But then I've got the original runtime exception as with try and catch


Here's the source:

// ------------------------------------------------------------

private import std.stdio;


struct vec3
{
	vec3 opSub(vec3 a)
	{
		vec3 x;
		return x;
	}
}

struct Face
{
	vec3	a;
}

struct Mesh
{
	Face[]	faces;
}
	
struct GeomObject
{
	Mesh	mesh;
	char[]	name;
	vec3		xlate;
}

class AseLoader
{
	this()
	{
		GeomObject go;
		go.name = "NODE";
		geomObjects ~= go;
	}
	
	GeomObject[]	geomObjects;
}


void extractTriangles(GeomObject geomObj)
{
	void foobar()
	{
		try
		{
			writefln("name: ", geomObj.name);

			return;  // avoid accessing the array with 0 elements in the next line			
			geomObj.mesh.faces[0].a - geomObj.xlate;  // when this line is removed, the bug doesn't appear
		}
		catch(Object err)
		{
			throw err;
		}
	}
	
	foobar();
}

void main()
{
	try
	{
		AseLoader al = new AseLoader;
	
		foreach(GeomObject go; al.geomObjects)
		{
			writefln("processing ", go.name);
			extractTriangles(go);
		}
	} catch(Object err)
	{
		writefln("Exception caught: ", err);
	}
	
	getchar();
}

// -----------------------------------------

Program output:
	processing NODE
	name: Exception caught: invalid UTF-8 sequence

// -----------------------------------------

My system:
DMD.109
WinXP SP2 EN
December 28, 2004
On Sun, 26 Dec 2004 19:04:40 +0100, h3r3tic <foo@bar.baz> wrote:

> Now this bug is interesting :>
> I have a function taking some parameters, yet this function doesn't do
> anything directly. Instead it calls a nested function which in turn
> doesn't take any parameters. Now, the standard says " Nested functions
> have access to the variables and other symbols defined by the lexically
> enclosing function". This probably applies as well to the enclosing
> function's parameters as they are visible in the nested function.
> However, in a very specific case, the data that the nested function
> accesses is somehow corrupted.
> On the other hand, if I pass every parameter of the enclosing function
> to the nested one, the data is just fine.
> The source for the bug is quite longish, yet I was unable to reduce its
> size any further. The function of interest is "extractTriangles". It
> contains a nested function "foobar". The code compiles and when ran, an
> exception is caught.

note: I only got this when compiled with -inline, and without -g.

> Now, when the nested function is removed (and its contents are moved to
> the enclosing function), the program runs just fine. It doesn't really
> matter what it does, the fact is that the variable "geomObj.name"
> contains invalid data, whilst it should contain text "NODE".
>
> That's one thing. Another is that the nested 'foobar' function contains
> a try-catch block:
> 	void foobar()
> 	{
> 		try
> 		{
> 			writefln("name: ", geomObj.name);
> 			return;		
> 			geomObj.mesh.faces[0].a - geomObj.xlate;
> 		}
> 		catch(Object err)
> 		{
> 			throw err;
> 		}
> 	}
>
> When the try and catch statements are removed like this:
> 	void foobar()
> 	{
> 			writefln("name: ", geomObj.name);
> 			return;		
> 			geomObj.mesh.faces[0].a - geomObj.xlate;
> 	}
>
> And I compile with "-inline", then the compile result looks like this:
>  > Internal error: e2ir.c 615
>
> But wait, that's not all... the internal error disappears when I leave
> the scope of the try block in place like this:
> 	void foobar()
> 	{
> 		{
> 			writefln("name: ", geomObj.name);
> 			return;
> 			geomObj.mesh.faces[0].a - geomObj.xlate;
> 		}
> 	}
>
> But then I've got the original runtime exception as with try and catch

confirmed the above (same system)

Note that simply nothing is printed on a UTF-8 capable console. (tested on
both Widows (sic) and my editors console)

Obviously, this is a DMD specific inlining error.

> // -----------------------------------------
>
> My system:
> DMD.109
> WinXP SP2 EN
>

December 30, 2004
Added to DStress as http://dstress.kuehne.cn/run/bug_20041226_A.d http://dstress.kuehne.cn/run/bug_20041226_B.d http://dstress.kuehne.cn/run/bug_20041226_C.d http://dstress.kuehne.cn/run/bug_20041226_D.d http://dstress.kuehne.cn/run/bug_20041226_E.d

Note: this seems to be a Windows specific DMD bug

Thomas