Thread overview
[Issue 4004] New: DMD 2.042 CTFE regression with functions taking ref parameters
Mar 25, 2010
Rob Jacques
Mar 26, 2010
Don
Apr 01, 2010
Walter Bright
Apr 10, 2010
Don
March 25, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4004

           Summary: DMD 2.042 CTFE regression with functions taking ref
                    parameters
           Product: D
           Version: future
          Platform: Other
        OS/Version: Windows
            Status: NEW
          Keywords: wrong-code
          Severity: regression
          Priority: P2
         Component: DMD
        AssignedTo: nobody@puremagic.com
        ReportedBy: sandford@jhu.edu


--- Comment #0 from Rob Jacques <sandford@jhu.edu> 2010-03-25 13:04:06 PDT ---
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

}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
March 26, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4004


Don <clugdbug@yahoo.com.au> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |patch
                 CC|                            |clugdbug@yahoo.com.au


--- Comment #1 from Don <clugdbug@yahoo.com.au> 2010-03-26 12:09:15 PDT ---
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)

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
April 01, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4004


Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzilla@digitalmars.com


--- Comment #2 from Walter Bright <bugzilla@digitalmars.com> 2010-04-01 13:53:22 PDT ---
changeset 429

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
April 10, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4004


Don <clugdbug@yahoo.com.au> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |FIXED


-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------