summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorringabout <43030857+ringabout@users.noreply.github.com>2023-06-29 16:51:18 +0800
committerGitHub <noreply@github.com>2023-06-29 10:51:18 +0200
commitd139d99946c97dca9c864709726841855a089496 (patch)
treea305b0bcaa18e365bfe2bfb059cd7c69a40dba2f
parent57de460437924a951d393ced8b7c88418fe2541a (diff)
downloadNim-d139d99946c97dca9c864709726841855a089496.tar.gz
fixes #19101; zero initialization union casts (#22185)
* zero initialization union casts

* cleans up and adds a test case for #19101

* uses nimZeroMem
-rw-r--r--compiler/ccgexprs.nim11
-rw-r--r--compiler/condsyms.nim2
-rw-r--r--compiler/lineinfos.nim4
-rw-r--r--compiler/nim.cfg3
-rw-r--r--compiler/semexprs.nim5
-rw-r--r--tests/stdlib/tcasts.nim26
6 files changed, 38 insertions, 13 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 978ca8db8..e2498b57b 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -2205,8 +2205,15 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
     var lbl = p.labels.rope
     var tmp: TLoc
     tmp.r = "LOC$1.source" % [lbl]
-    linefmt(p, cpsLocals, "union { $1 source; $2 dest; } LOC$3;$n",
-      [getTypeDesc(p.module, e[1].typ), getTypeDesc(p.module, e.typ), lbl])
+    let destsize = getSize(p.config, destt)
+    let srcsize = getSize(p.config, srct)
+
+    if destsize > srcsize:
+      linefmt(p, cpsLocals, "union { $1 dest; $2 source; } LOC$3;$n #nimZeroMem(&LOC$3, sizeof(LOC$3));$n",
+        [getTypeDesc(p.module, e.typ), getTypeDesc(p.module, e[1].typ), lbl])
+    else:
+      linefmt(p, cpsLocals, "union { $1 source; $2 dest; } LOC$3;$n",
+        [getTypeDesc(p.module, e[1].typ), getTypeDesc(p.module, e.typ), lbl])
     tmp.k = locExpr
     tmp.lode = lodeTyp srct
     tmp.storage = OnStack
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim
index 4ff588852..12634248c 100644
--- a/compiler/condsyms.nim
+++ b/compiler/condsyms.nim
@@ -145,7 +145,7 @@ proc initDefines*(symbols: StringTableRef) =
   defineSymbol("nimHasCallsitePragma")
   defineSymbol("nimHasAmbiguousEnumHint")
 
-  defineSymbol("nimHasWarnCastSizes")
+  defineSymbol("nimHasWarnCastSizes") # deadcode
   defineSymbol("nimHasOutParams")
   defineSymbol("nimHasSystemRaisesDefect")
   defineSymbol("nimHasWarnUnnamedBreak")
diff --git a/compiler/lineinfos.nim b/compiler/lineinfos.nim
index 7c5a99c79..37adc5660 100644
--- a/compiler/lineinfos.nim
+++ b/compiler/lineinfos.nim
@@ -83,7 +83,7 @@ type
     warnCstringConv = "CStringConv",
     warnPtrToCstringConv = "PtrToCstringConv",
     warnEffect = "Effect",
-    warnCastSizes = "CastSizes"
+    warnCastSizes = "CastSizes", # deadcode
     warnAboveMaxSizeSet = "AboveMaxSizeSet",
     warnImplicitTemplateRedefinition = "ImplicitTemplateRedefinition",
     warnUnnamedBreak = "UnnamedBreak",
@@ -185,7 +185,7 @@ const
     warnCstringConv: "$1",
     warnPtrToCstringConv: "unsafe conversion to 'cstring' from '$1'; this will become a compile time error in the future",
     warnEffect: "$1",
-    warnCastSizes: "$1",
+    warnCastSizes: "$1", # deadcode
     warnAboveMaxSizeSet: "$1",
     warnImplicitTemplateRedefinition: "template '$1' is implicitly redefined; this is deprecated, add an explicit .redefine pragma",
     warnUnnamedBreak: "Using an unnamed break in a block is deprecated; Use a named block with a named break instead",
diff --git a/compiler/nim.cfg b/compiler/nim.cfg
index 5b418cfd3..c32dba4d1 100644
--- a/compiler/nim.cfg
+++ b/compiler/nim.cfg
@@ -31,9 +31,6 @@ define:useStdoutAsStdmsg
   warning[ObservableStores]:off
 @end
 
-@if nimHasWarnCastSizes:
-  warning[CastSizes]:on
-@end
 
 @if nimHasWarningAsError:
   warningAsError[GcUnsafe2]:on
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 3b40425cf..1d917f00d 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -288,11 +288,6 @@ proc isCastable(c: PContext; dst, src: PType, info: TLineInfo): bool =
     result = (dstSize >= srcSize) or
         (skipTypes(dst, abstractInst).kind in IntegralTypes) or
         (skipTypes(src, abstractInst-{tyTypeDesc}).kind in IntegralTypes)
-    if result and (dstSize > srcSize):
-      var warnMsg = "target type is larger than source type"
-      warnMsg.add("\n  target type: '$1' ($2)" % [$dst, if dstSize == 1: "1 byte" else: $dstSize & " bytes"])
-      warnMsg.add("\n  source type: '$1' ($2)" % [$src, if srcSize == 1: "1 byte" else: $srcSize & " bytes"])
-      message(conf, info, warnCastSizes, warnMsg)
   if result and src.kind == tyNil:
     return dst.size <= conf.target.ptrSize
 
diff --git a/tests/stdlib/tcasts.nim b/tests/stdlib/tcasts.nim
new file mode 100644
index 000000000..e01c7e940
--- /dev/null
+++ b/tests/stdlib/tcasts.nim
@@ -0,0 +1,26 @@
+import std/[strutils]
+import std/[assertions, objectdollar]
+
+# bug #19101
+type
+  Small = object
+    a: int
+
+  Big = object
+    a, b, c, d: int
+
+proc main =
+  var
+    n = 1'i8
+    f = 2.0
+    s = Small(a: 1)
+    b = Big(a: 12345, b: 23456, c: 34567, d: 45678)
+
+  doAssert $cast[int](f).toBin(64) == "0100000000000000000000000000000000000000000000000000000000000000"
+  f = cast[float](n)
+  doAssert $cast[int](f).toBin(64) == "0000000000000000000000000000000000000000000000000000000000000001"
+
+  doAssert $b == "(a: 12345, b: 23456, c: 34567, d: 45678)"
+  b = cast[Big](s)
+  doAssert $b == "(a: 1, b: 0, c: 0, d: 0)"
+main()