4004 – DMD 2.042 CTFE regression with functions taking ref parameters

D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 4004 - DMD 2.042 CTFE regression with functions taking ref parameters
Summary: DMD 2.042 CTFE regression with functions taking ref parameters
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: Other Windows
: P2 regression
Assignee: No Owner
URL:
Keywords: patch, wrong-code
Depends on:
Blocks:
Reported: 2010年03月25日 13:04 UTC by Rob Jacques
Modified: 2015年06月09日 05:13 UTC (History)
2 users (show)

See Also:


Attachments
Add an attachment (proposed patch, testcase, etc.)

Note You need to log in before you can comment on or make changes to this issue.
Description Rob Jacques 2010年03月25日 13:04:06 UTC
There appears to be a weird regression introduced in DMD 2.042 with the compile time handling of ref parameters (runtime versions of the function are unaffected). It appears that when a function taking a ref parameter passes it as a ref parameter to another function. If the first function modifies the parameter then modifications made by the second function won't be observed.
Below is a very simple test case:
import std.stdio: writeln;
void foo2(ref size_t offset) {
 offset = 8;
}
void foo(ref size_t offset) {
 auto okay = offset; // Reading from the ref param is okay
 offset += 0; // comment this line out and it works
 foo2(offset);
}
size_t bar() {
 size_t offset = 0;
 foo(offset);
 return offset;
}
template foobar() { immutable foobar = bar; }
void main(string[] args) {
writeln(foobar!(),'\t', bar ); // prints 0 8 instead of 8 8
}
Comment 1 Don 2010年03月26日 12:09:15 UTC
Reduced test case for test suite.
--------
void bug4004a(ref int a) {
assert(a==7);
a+=3;
}
void bug4004b(ref int b) {
 b= 7;
 bug4004a(b); 
}
int bug4004c() {
 int offset = 5;
 bug4004b(offset);
 return offset;
}
static assert(bug4004c()==10);
-------------------------
PATCH:
Index: interpret.c
===================================================================
--- interpret.c	(revision 420)
+++ interpret.c	(working copy)
@@ -53,7 +53,7 @@
 Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclaration *fd);
 
 ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type, Expression *elem, size_t dim);
-Expression * resolveReferences(Expression *e, Expression *thisval);
+Expression * resolveReferences(Expression *e, Expression *thisval, bool *isReference = NULL);
 
 /*************************************
 * Attempt to interpret a function given the arguments.
@@ -1107,8 +1107,11 @@
 // -------------------------------------------------------------
 // The variable used in a dotvar, index, or slice expression,
 // after 'out', 'ref', and 'this' have been removed.
-Expression * resolveReferences(Expression *e, Expression *thisval)
+// *isReference will be set to true if a reference was removed.
+Expression * resolveReferences(Expression *e, Expression *thisval, bool *isReference /*=NULL */)
 {
+ if (isReference)
+	*isReference = false;
 for(;;)
 {
 	if (e->op == TOKthis)
@@ -1131,6 +1134,8 @@
 		VarExp *ve2 = (VarExp *)v->value;
 		if (!ve2->var->isSymbolDeclaration())
 		{
+		 if (isReference)
+			*isReference = true;
 		 e = v->value;
 		 continue;
 		}
@@ -2087,7 +2092,8 @@
 	v->value = e2;
 	return e2;
 }
- e1 = resolveReferences(e1, istate->localThis);
+ bool destinationIsReference = false;
+ e1 = resolveReferences(e1, istate->localThis, &destinationIsReference);
 
 // Unless we have a simple var assignment, we're
 // only modifying part of the variable.
@@ -2167,7 +2174,8 @@
 {
 	VarExp *ve = (VarExp *)e1;
 	VarDeclaration *v = ve->var->isVarDeclaration(); 
-	addVarToInterstate(istate, v);
+	if (!destinationIsReference)
+	 addVarToInterstate(istate, v);
 	v->value = newval;
 }
 else if (e1->op == TOKindex)
Comment 2 Walter Bright 2010年04月01日 13:53:22 UTC
changeset 429


AltStyle によって変換されたページ (->オリジナル) /