www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - Invalid method called - reduced test case

reply Tom S <h3r3tic -remove-.mat.uni.torun.pl> writes:
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

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 +/
Mar 03 2006
parent reply Thomas Kuehne <thomas-dloop kuehne.cn> writes:
-----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-----
Mar 06 2006
next sibling parent John Reimer <terminal.node gmail.com> writes:
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
Mar 06 2006
prev sibling parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
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 +/
Mar 06 2006
parent Thomas Kuehne <thomas-dloop kuehne.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

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 -----BEGIN PGP SIGNATURE----- iD8DBQFEDWcl3w+/yD4P9tIRArQyAKDG8+UWlPWyLHzgpAE2tpLJQoouGgCgx4Ux Z79AHuvWLxSt6iLTbj9wnq8= =9fkG -----END PGP SIGNATURE-----
Mar 07 2006