summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ccgexprs.nim32
-rw-r--r--compiler/cgen.nim2
-rw-r--r--tests/ccgbugs/tcgbug.nim1
-rw-r--r--tests/ccgbugs/tmissingbracket.nim2
-rw-r--r--tests/objects/tobject3.nim33
-rw-r--r--tests/objects/toop1.nim7
6 files changed, 61 insertions, 16 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 0bf2359c5..e05828f8f 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1872,18 +1872,34 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) =
     expr(p, n.sons[0], d)     # downcast does C++ for us
   else:
     var dest = skipTypes(n.typ, abstractPtrs)
-    var src = skipTypes(n.sons[0].typ, abstractPtrs)
+
+    var arg = n.sons[0]
+    while arg.kind == nkObjDownConv: arg = arg.sons[0]
+
+    var src = skipTypes(arg.typ, abstractPtrs)
     var a: TLoc
-    initLocExpr(p, n.sons[0], a)
+    initLocExpr(p, arg, a)
     var r = rdLoc(a)
-    if skipTypes(n.sons[0].typ, abstractInst).kind in {tyRef, tyPtr, tyVar} and
-        n.sons[0].kind notin {nkHiddenAddr, nkAddr, nkObjDownConv}:
+    let isRef = skipTypes(arg.typ, abstractInst).kind in {tyRef, tyPtr, tyVar}
+    if isRef:
       app(r, "->Sup")
-      for i in countup(2, abs(inheritanceDiff(dest, src))): app(r, ".Sup")
-      r = con("&", r)
     else:
-      for i in countup(1, abs(inheritanceDiff(dest, src))): app(r, ".Sup")
-    putIntoDest(p, d, n.typ, r)
+      app(r, ".Sup")
+    for i in countup(2, abs(inheritanceDiff(dest, src))): app(r, ".Sup")
+    if isRef:
+      # it can happen that we end up generating '&&x->Sup' here, so we pack
+      # the '&x->Sup' into a temporary and then those address is taken
+      # (see bug #837). However sometimes using a temporary is not correct: 
+      # init(TFigure(my)) # where it is passed to a 'var TFigure'. We test
+      # this by ensuring the destination is also a pointer:
+      if d.k == locNone and skipTypes(n.typ, abstractInst).kind in {tyRef, tyPtr, tyVar}:
+        getTemp(p, n.typ, d)
+        linefmt(p, cpsStmts, "$1 = &$2;$n", rdLoc(d), r)
+      else:
+        r = con("&", r)
+        putIntoDest(p, d, n.typ, r)
+    else:
+      putIntoDest(p, d, n.typ, r)
 
 proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
   var t = getUniqueType(n.typ)
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 112203ef1..b00c0b0a7 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -310,7 +310,7 @@ proc rdLoc(a: TLoc): PRope =
 proc addrLoc(a: TLoc): PRope =
   result = a.r
   if lfIndirect notin a.flags and mapType(a.t) != ctArray:
-    result = con("&", result)
+    result = con("(&", result).con(")")
 
 proc rdCharLoc(a: TLoc): PRope =
   # read a location that may need a char-cast:
diff --git a/tests/ccgbugs/tcgbug.nim b/tests/ccgbugs/tcgbug.nim
index 3e4755f2f..92e7b3a66 100644
--- a/tests/ccgbugs/tcgbug.nim
+++ b/tests/ccgbugs/tcgbug.nim
@@ -35,3 +35,4 @@ type
     cb: proc (future: PFuture[T]) {.closure.}
 
 var k = PFuture[void]()
+
diff --git a/tests/ccgbugs/tmissingbracket.nim b/tests/ccgbugs/tmissingbracket.nim
index ba681ebda..886884d0c 100644
--- a/tests/ccgbugs/tmissingbracket.nim
+++ b/tests/ccgbugs/tmissingbracket.nim
@@ -34,7 +34,7 @@ proc newInstance(T: typedesc): T =
 var o = TObj.newInstance()
 
 type
-    TestObj* = object of TObject
+    TestObj* = object of RootObj
         t:int
     SubObject* = object of TestObj
 
diff --git a/tests/objects/tobject3.nim b/tests/objects/tobject3.nim
index 935e6ca8c..85cf1cfe3 100644
--- a/tests/objects/tobject3.nim
+++ b/tests/objects/tobject3.nim
@@ -1,5 +1,9 @@
+
+# It turned out that it's hard to generate correct for these two test cases at
+# the same time.
+
 type
-  TFoo = ref object of TObject
+  TFoo = ref object of RootObj
     Data: int  
   TBar = ref object of TFoo
     nil
@@ -26,3 +30,30 @@ var b: TBar2
 new(b)
 
 Foo(b)
+
+# bug #837
+type
+  PView* = ref TView
+  TView* {.inheritable.} = object
+    data: int
+
+  PWindow* = ref TWindow
+  TWindow* = object of TView
+    data3: int
+
+  PDesktop* = ref TDesktop
+  TDesktop* = object of TView
+    data2: int
+
+proc makeDesktop(): PDesktop = new(TDesktop)
+
+proc makeWindow(): PWindow = new(TWindow)
+
+proc thisCausesError(a: var PView, b: PView) =
+  discard
+
+var dd = makeDesktop()
+var aa = makeWindow()
+
+thisCausesError(dd, aa)
+
diff --git a/tests/objects/toop1.nim b/tests/objects/toop1.nim
index 350799f51..0d8ba124b 100644
--- a/tests/objects/toop1.nim
+++ b/tests/objects/toop1.nim
@@ -6,7 +6,7 @@ discard """
 import macros
 
 type
-  TFigure = object of TObject    # abstract base class:
+  TFigure = object of RootObj    # abstract base class:
     draw: proc (my: var TFigure) {.nimcall.} # concrete classes implement this
   
 proc init(f: var TFigure) = 
@@ -56,7 +56,7 @@ macro `!` (n: expr): stmt {.immediate.} =
     result.add(n[1]) # obj
 
 type
-  TSocket* = object of TObject
+  TSocket* = object of RootObj
     FHost: int # cannot be accessed from the outside of the module
                # the `F` prefix is a convention to avoid clashes since
                # the accessors are named `host`
@@ -84,6 +84,3 @@ r!draw
 c!draw() 
 
 #OUT 34[]o 5
-
-
-