D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 3634 - return value not passed to out contracts of private methods
Summary: return value not passed to out contracts of private methods
Status: RESOLVED DUPLICATE of issue 3667
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: Other Linux
: P2 major
Assignee: No Owner
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2009-12-18 22:37 UTC by Witold Baryluk
Modified: 2015-06-09 01:27 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Witold Baryluk 2009-12-18 22:37:44 UTC
This code failes, but it should pass.

class A {
	this() {
		x_ = 10;
	}
private:
	uint x_;

	uint x()
	out(ret) {
		assert(ret == 10); // fails  // line 10
		assert(ret == x_); // fails
	}
	body {
		return x_;
	}
}

import std.stdio;

void main() {
	auto a = new A();
	writefln("%d", a.x());
}

$ dmd2 -debug a.d; ./a
 core.exception.AssertError@t(10): Assertion failure
$

When I change x() method to 'public' problems dissaper.


Here is dissambled code

        assume  CS:.text._D1t1A1xMFZk
_D1t1A1xMFZk:
                push    EBP
                mov     EBP,ESP
                sub     ESP,0Ch
                add     EAX,8
                mov     ECX,[EAX]
                mov     -8[EBP],ECX
                mov     -0Ch[EBP],EAX
                mov     EAX,0Ah
                call    near ptr _D1t8__assertFiZv@PC32
                mov     EDX,-0Ch[EBP]
                cmp     dword ptr [EDX],0
                je      L2D
                mov     EAX,0Bh
                call    near ptr _D1t8__assertFiZv@PC32
L2D:            mov     EAX,-8[EBP]
                leave
                ret
                nop
                nop
.text._D1t1A1xMFZk      ends


Also without "-debug" switch the same code is generated.
If i comment a assert statments (or don't use ret), method properly returns value to callee.


In release mode it works correclty (but contracts are called):

.text._D1t1A1xMFZk      segment
        assume  CS:.text._D1t1A1xMFZk
_D1t1A1xMFZk:
                push    EBP
                mov     EBP,ESP
                sub     ESP,4
                mov     EAX,8[EAX]
                leave
                ret
                nop
.text._D1t1A1xMFZk      ends
Comment 1 Witold Baryluk 2009-12-18 22:59:08 UTC
Original code (with "private") fails also with "-O", "-O -inline", and many others.

Here is simplified case:

class A {
	this() {
		x_ = 0x40;
	}
private:
	uint x_;
//public:
	uint x()
	out(ret) {
		pppp(ret);
	}
	body {
		return x_;
	}
}
import std.stdio;
void main() { 	auto a = new A(); }
void pppp(uint xxx) {	xxx ++; }

.text._D1t1A1xMFZk      segment
        assume  CS:.text._D1t1A1xMFZk
_D1t1A1xMFZk:
                push    EBP
                mov     EBP,ESP
                sub     ESP,8
                mov     ECX,8[EAX]   // move field x_ to the ECX register
                mov     -8[EBP],ECX  // save ret in EBP[-8]
                xor     EAX,EAX       // set ret = 0
                call    near ptr _D1t4ppppFkZv@PC32 // call pppp(EAX)
                mov     EAX,-8[EBP] // restore ret after return from ppp
                leave
                ret   // return
.text._D1t1A1xMFZk      ends

When changed to "public":

.text._D1t1A1xMFZk      segment
        assume  CS:.text._D1t1A1xMFZk
_D1t1A1xMFZk:
                push    EBP
                mov     EBP,ESP
                sub     ESP,8
                mov     -4[EBP],EAX
                call    near ptr _D9invariant12_d_invariantFC6ObjectZv@PC32
                mov     EAX,-4[EBP]
                mov     ECX,8[EAX]
                mov     -8[EBP],ECX
                lea     EDX,-8[EBP]
                push    EDX
                call    near ptr _D1t1A1xMFZk8__ensureMFKxkZv@PC32
                mov     EAX,-8[EBP]
                leave
                ret
                nop
                nop
                nop
.text._D1t1A1xMFZk      ends
.text._D1t1A1xMFZk8__ensureMFKxkZv      segment
        assume  CS:.text._D1t1A1xMFZk8__ensureMFKxkZv
_D1t1A1xMFZk8__ensureMFKxkZv:
                push    EBP
                mov     EBP,ESP
                sub     ESP,4
                mov     ECX,8[EBP]  // take address of field x_ and put into ECX
                mov     EAX,[ECX] // move content of field x_ into EAX
                call    near ptr _D1t4ppppFkZv@PC32 // call pppp(EAX)
                leave
                ret     4 // return
.text._D1t1A1xMFZk8__ensureMFKxkZv      ends

_D9invariant12_d_invariantFC6ObjectZv@PC32 is and Object.invariant() from base class.
Comment 2 Witold Baryluk 2009-12-18 23:03:34 UTC
Using "protected" attributed it works correctly:

.text._D1t1A1xMFZk      segment
        assume  CS:.text._D1t1A1xMFZk
_D1t1A1xMFZk:
                push    EBP
                mov     EBP,ESP
                sub     ESP,8
                mov     ECX,8[EAX]
                mov     -8[EBP],ECX
                lea     EDX,-8[EBP]
                push    EDX
                call    near ptr _D1t1A1xMFZk8__ensureMFKxkZv@PC32
                mov     EAX,-8[EBP]
                leave
                ret
                nop
                nop
.text._D1t1A1xMFZk      ends
.text._D1t1A1xMFZk8__ensureMFKxkZv      segment
        assume  CS:.text._D1t1A1xMFZk8__ensureMFKxkZv
_D1t1A1xMFZk8__ensureMFKxkZv:
                push    EBP
                mov     EBP,ESP
                sub     ESP,4
                mov     ECX,8[EBP]
                mov     EAX,[ECX]
                call    near ptr _D1t4ppppFkZv@PC32
                leave
                ret     4
.text._D1t1A1xMFZk8__ensureMFKxkZv      ends


I was first thinking this is problem with constatnt propagation, but i don't think this is good guess. Hope someone with better knowledge of backend can say something more relevant. :)
Comment 3 Don 2010-06-07 00:11:57 UTC
This was a regression in 2.037. Fixed in the beta of 2.047.

*** This issue has been marked as a duplicate of issue 3667 ***