summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorcooldome <cdome@bk.ru>2018-03-16 15:21:03 +0000
committerAndreas Rumpf <rumpf_a@web.de>2018-03-16 16:21:03 +0100
commit70b28a39fedfe030ac4e1615d32328d7ffd3f79d (patch)
treee1a382756971f788634e9d82d79a06b5c10250e0
parenta9f21cffdf7304272b5bbabeabec4a3e659819fa (diff)
downloadNim-70b28a39fedfe030ac4e1615d32328d7ffd3f79d.tar.gz
Codegen: use type forward declarations more aggresively. Fixes #7339 (#7340)
Do not emit object definition it if used only by ref or ptr
-rw-r--r--compiler/ccgexprs.nim3
-rw-r--r--compiler/ccgtypes.nim3
-rw-r--r--tests/ccgbugs/mymodule.nim12
-rw-r--r--tests/ccgbugs/tforward_decl_only.nim15
4 files changed, 32 insertions, 1 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 998220469..060a5fdbd 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1364,6 +1364,7 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
     if t.kind notin {tyVar, tyLent} or not p.module.compileToCpp:
       r = rfmt(nil, "(*$1)", r)
     t = skipTypes(t.lastSon, typedescInst)
+  discard getTypeDesc(p.module, t)
   if not p.module.compileToCpp:
     while t.kind == tyObject and t.sons[0] != nil:
       add(r, ~".Sup")
@@ -2062,6 +2063,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
 
 proc downConv(p: BProc, n: PNode, d: var TLoc) =
   if p.module.compileToCpp:
+    discard getTypeDesc(p.module, skipTypes(n[0].typ, abstractPtrs))
     expr(p, n.sons[0], d)     # downcast does C++ for us
   else:
     var dest = skipTypes(n.typ, abstractPtrs)
@@ -2070,6 +2072,7 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) =
     while arg.kind == nkObjDownConv: arg = arg.sons[0]
 
     var src = skipTypes(arg.typ, abstractPtrs)
+    discard getTypeDesc(p.module, src)
     var a: TLoc
     initLocExpr(p, arg, a)
     var r = rdLoc(a)
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index bdba34e36..4fc029116 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -368,6 +368,8 @@ proc getTypeForward(m: BModule, typ: PType; sig: SigHash): Rope =
     if not isImportedType(concrete):
       addf(m.s[cfsForwardTypes], getForwardStructFormat(m),
           [structOrUnion(typ), result])
+    else:
+      pushType(m, concrete)
     doAssert m.forwTypeCache[sig] == result
   else: internalError("getTypeForward(" & $typ.kind & ')')
 
@@ -665,7 +667,6 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
         let name = getTypeForward(m, et, hashType et)
         result = name & star
         m.typeCache[sig] = result
-        pushType(m, et)
     of tySequence:
       # no restriction! We have a forward declaration for structs
       let name = getTypeForward(m, et, hashType et)
diff --git a/tests/ccgbugs/mymodule.nim b/tests/ccgbugs/mymodule.nim
new file mode 100644
index 000000000..d3306ec49
--- /dev/null
+++ b/tests/ccgbugs/mymodule.nim
@@ -0,0 +1,12 @@
+type
+  MyRefObject* = ref object
+    s: string
+
+
+proc newMyRefObject*(s: string): MyRefObject =
+  new(result)
+  result.s = s
+  
+proc `$`*(o: MyRefObject): string =
+  o.s
+  
\ No newline at end of file
diff --git a/tests/ccgbugs/tforward_decl_only.nim b/tests/ccgbugs/tforward_decl_only.nim
new file mode 100644
index 000000000..dcd74eaf4
--- /dev/null
+++ b/tests/ccgbugs/tforward_decl_only.nim
@@ -0,0 +1,15 @@
+discard """
+ccodecheck: "\\i !@('struct tyObject_MyRefObject'[0-z]+' {')"
+output: "hello"
+"""
+
+# issue #7339 
+# Test that MyRefObject is only forward declared as it used only by reference
+
+import mymodule
+type AnotherType = object
+  f: MyRefObject 
+
+let x = AnotherType(f: newMyRefObject("hello"))
+echo $x.f
+