Thread overview
Invalid method called - reduced test case
Mar 03, 2006
Tom S
Mar 06, 2006
Thomas Kuehne
Mar 06, 2006
John Reimer
Mar 06, 2006
Tom S
Mar 07, 2006
Thomas Kuehne
March 03, 2006
DMD seems to be picky about the order of files passed to it. The
attached program is a reduced version of what Ant encountered while
working on Duit. I believe this is the same bug that Tyler reported
regarding DWT.
The .zip archive contains 3 D modules: a.d, b.d and main.d

When compiled using:
dmd b.d a.d main.d

...the resulting executable will be buggy. More specifically, an assertion (that I put in a function which should never be called) will fail :)

The behavior is the same if one builds a .lib or .a file using dmd -c b.d a.d

...and then links to main.d

Tested on Windows and Linux using the #D compiler farm ;)


-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M d-pu s+: a-->----- C+++$>++++ UL P+ L+ E--- W++ N++ o? K? w++ !O
!M V? PS- PE- Y PGP t 5 X? R tv-- b DI- D+ G e>+++ h>++ !r !y
------END GEEK CODE BLOCK------

Tomasz Stachowiak  /+ a.k.a. h3r3tic +/


March 06, 2006
Tom S schrieb am 2006-03-03:
>
> DMD seems to be picky about the order of files passed to it. The
> attached program is a reduced version of what Ant encountered while
> working on Duit. I believe this is the same bug that Tyler reported
> regarding DWT.
> The .zip archive contains 3 D modules: a.d, b.d and main.d
>
> When compiled using:
> dmd b.d a.d main.d
>
> ...the resulting executable will be buggy. More specifically, an assertion (that I put in a function which should never be called) will fail :)
>
> The behavior is the same if one builds a .lib or .a file using dmd -c b.d a.d
>
> ...and then links to main.d
>
> Tested on Windows and Linux using the #D compiler farm ;)

Your test case seems to be broken:

=== a.d ===
private import b;

class Foo : Bar {
	void foo() {
		assert(false);	// this should never be called !
	}
}

=== b.d ===
class Bar {
	private import a;

	void bar() {
		printf("Bar.bar()\n");
	}
}

=== main.d ===
private import a;

void main() {
	(new Foo()).bar();
}


You call Foo.bar in main - that's exactly the function you didn't expect to execute.

The real bug is: the private of "private import a;" isn't enforced and thus interpreted as "import a;" - the protection attributes are known not to work properly in many situations.

Thomas


March 06, 2006
Thomas Kuehne wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Tom S schrieb am 2006-03-03:
>> DMD seems to be picky about the order of files passed to it. The attached program is a reduced version of what Ant encountered while working on Duit. I believe this is the same bug that Tyler reported regarding DWT.
>> The .zip archive contains 3 D modules: a.d, b.d and main.d
>>
>> When compiled using:
>> dmd b.d a.d main.d
>>
>> ...the resulting executable will be buggy. More specifically, an assertion (that I put in a function which should never be called) will fail :)
>>
>> The behavior is the same if one builds a .lib or .a file using
>> dmd -c b.d a.d
>>
>> ...and then links to main.d
>>
>> Tested on Windows and Linux using the #D compiler farm ;)
> 
> Your test case seems to be broken:
> 
> === a.d ===
> private import b;
> 
> class Foo : Bar {
> 	void foo() {
> 		assert(false);	// this should never be called !
> 	}
> }
> 
> === b.d ===
> class Bar {
> 	private import a;
> 
> 	void bar() {
> 		printf("Bar.bar()\n");
> 	}
> }
> 
> === main.d ===
> private import a;
> 
> void main() {
> 	(new Foo()).bar();
> }
> 
> 
> You call Foo.bar in main - that's exactly the function you didn't expect
> to execute.
> 
> The real bug is: the private of "private import a;" isn't enforced and thus
> interpreted as "import a;" - the protection attributes are known not to
> work properly in many situations.
> 
> Thomas
> 
> 
> -----BEGIN PGP SIGNATURE-----
> 
> iD8DBQFEDASk3w+/yD4P9tIRAljXAKDCRA+aN1NNiC4cgMyX8WNyXjYjkQCgwViR
> rw5WgcU4IBE4e64MtO1zzUA=
> =NlAj
> -----END PGP SIGNATURE-----


How is it broken?

I fail to understand, then, why Foo.foo() is called when a call to Foo.bar() is made?  Their function signatures are quite different, no? Are the vtables getting reassigned from the compile/link order?

Change the compile order with this:

dmd main.d a.d b.d

and Foo.bar() is called as expected.  This seems to be a compile order-related issue.  Why does this work just because the objects are built in a different order?

In what situation would we see main.d /not/ put first in the build list?

This does appear to be a dangerous problem, nonetheless...

-JJR
March 06, 2006
Thomas Kuehne wrote:
> Your test case seems to be broken:
> 
> === a.d ===
> private import b;
> 
> class Foo : Bar {
> 	void foo() {
> 		assert(false);	// this should never be called !
> 	}
> }
> 
> === b.d ===
> class Bar {
> 	private import a;
> 
> 	void bar() {
> 		printf("Bar.bar()\n");
> 	}
> }
> 
> === main.d ===
> private import a;
> 
> void main() {
> 	(new Foo()).bar();
> }
> 
> 
> You call Foo.bar in main - that's exactly the function you didn't expect
> to execute.

Wrong.

I tell it to call Foo.bar but Foo.foo gets called (the function that contains the assert) :)

The order in which these modules are passed to the compiler is important.


-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M d-pu s+: a-->----- C+++$>++++ UL P+ L+ E--- W++ N++ o? K? w++ !O !M V? PS- PE- Y PGP t 5 X? R tv-- b DI- D+ G e>+++ h>++ !r !y
------END GEEK CODE BLOCK------

Tomasz Stachowiak  /+ a.k.a. h3r3tic +/
March 07, 2006
Tom S schrieb am 2006-03-06:
> Thomas Kuehne wrote:
>> Your test case seems to be broken:
>> 
>> === a.d ===
>> private import b;
>> 
>> class Foo : Bar {
>> 	void foo() {
>> 		assert(false);	// this should never be called !
>> 	}
>> }
>> 
>> === b.d ===
>> class Bar {
>> 	private import a;
>> 
>> 	void bar() {
>> 		printf("Bar.bar()\n");
>> 	}
>> }
>> 
>> === main.d ===
>> private import a;
>> 
>> void main() {
>> 	(new Foo()).bar();
>> }
>> 
>> 
>> You call Foo.bar in main - that's exactly the function you didn't expect to execute.
>
> Wrong.
>
> I tell it to call Foo.bar but Foo.foo gets called (the function that contains the assert) :)
>
> The order in which these modules are passed to the compiler is important.

You are right.

Added to DStress as: http://dstress.kuehne.cn/compile/i/import_13_A.d http://dstress.kuehne.cn/compile/i/import_13_B.d http://dstress.kuehne.cn/run/i/import_13_C.d http://dstress.kuehne.cn/run/i/import_13_D.d http://dstress.kuehne.cn/run/i/import_13_E.d http://dstress.kuehne.cn/run/i/import_13_F.d http://dstress.kuehne.cn/compile/i/import_13_G.d http://dstress.kuehne.cn/compile/i/import_13_H.d http://dstress.kuehne.cn/run/i/import_13_I.d http://dstress.kuehne.cn/run/i/import_13_J.d http://dstress.kuehne.cn/run/i/import_13_K.d http://dstress.kuehne.cn/run/i/import_13_L.d http://dstress.kuehne.cn/compile/i/import_13_M.d http://dstress.kuehne.cn/compile/i/import_13_N.d http://dstress.kuehne.cn/run/i/import_13_O.d http://dstress.kuehne.cn/run/i/import_13_P.d http://dstress.kuehne.cn/run/i/import_13_Q.d http://dstress.kuehne.cn/run/i/import_13_R.d

Thomas