Warn when casting to a larger type (#20103)
* Warn when casting to a larger type * Revert change to error message to fix CI
This commit is contained in:
parent
424e87fd09
commit
528b6d1c3f
2 changed files with 12 additions and 8 deletions
|
|
@ -80,6 +80,7 @@ type
|
||||||
warnHoleEnumConv = "HoleEnumConv",
|
warnHoleEnumConv = "HoleEnumConv",
|
||||||
warnCstringConv = "CStringConv",
|
warnCstringConv = "CStringConv",
|
||||||
warnEffect = "Effect",
|
warnEffect = "Effect",
|
||||||
|
warnCastSizes = "CastSizes"
|
||||||
warnUser = "User",
|
warnUser = "User",
|
||||||
# hints
|
# hints
|
||||||
hintSuccess = "Success", hintSuccessX = "SuccessX",
|
hintSuccess = "Success", hintSuccessX = "SuccessX",
|
||||||
|
|
@ -173,6 +174,7 @@ const
|
||||||
warnHoleEnumConv: "$1",
|
warnHoleEnumConv: "$1",
|
||||||
warnCstringConv: "$1",
|
warnCstringConv: "$1",
|
||||||
warnEffect: "$1",
|
warnEffect: "$1",
|
||||||
|
warnCastSizes: "$1",
|
||||||
warnUser: "$1",
|
warnUser: "$1",
|
||||||
hintSuccess: "operation successful: $#",
|
hintSuccess: "operation successful: $#",
|
||||||
# keep in sync with `testament.isSuccess`
|
# keep in sync with `testament.isSuccess`
|
||||||
|
|
|
||||||
|
|
@ -196,10 +196,10 @@ proc checkConvertible(c: PContext, targetTyp: PType, src: PNode): TConvStatus =
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
proc isCastable(c: PContext; dst, src: PType): bool =
|
proc isCastable(c: PContext; dst, src: PType, info: TLineInfo): bool =
|
||||||
## Checks whether the source type can be cast to the destination type.
|
## Checks whether the source type can be cast to the destination type.
|
||||||
## Casting is very unrestrictive; casts are allowed as long as
|
## Casting is very unrestrictive; casts are allowed as long as
|
||||||
## castDest.size >= src.size, and typeAllowed(dst, skParam)
|
## dst.size >= src.size, and typeAllowed(dst, skParam)
|
||||||
#const
|
#const
|
||||||
# castableTypeKinds = {tyInt, tyPtr, tyRef, tyCstring, tyString,
|
# castableTypeKinds = {tyInt, tyPtr, tyRef, tyCstring, tyString,
|
||||||
# tySequence, tyPointer, tyNil, tyOpenArray,
|
# tySequence, tyPointer, tyNil, tyOpenArray,
|
||||||
|
|
@ -228,19 +228,21 @@ proc isCastable(c: PContext; dst, src: PType): bool =
|
||||||
# Just assume the programmer knows what he is doing.
|
# Just assume the programmer knows what he is doing.
|
||||||
return true
|
return true
|
||||||
if dstSize < 0:
|
if dstSize < 0:
|
||||||
result = false
|
return false
|
||||||
elif srcSize < 0:
|
elif srcSize < 0:
|
||||||
result = false
|
return false
|
||||||
elif typeAllowed(dst, skParam, c) != nil:
|
elif typeAllowed(dst, skParam, c) != nil:
|
||||||
result = false
|
return false
|
||||||
elif dst.kind == tyProc and dst.callConv == ccClosure:
|
elif dst.kind == tyProc and dst.callConv == ccClosure:
|
||||||
result = src.kind == tyProc and src.callConv == ccClosure
|
return src.kind == tyProc and src.callConv == ccClosure
|
||||||
else:
|
else:
|
||||||
result = (dstSize >= srcSize) or
|
result = (dstSize >= srcSize) or
|
||||||
(skipTypes(dst, abstractInst).kind in IntegralTypes) or
|
(skipTypes(dst, abstractInst).kind in IntegralTypes) or
|
||||||
(skipTypes(src, abstractInst-{tyTypeDesc}).kind in IntegralTypes)
|
(skipTypes(src, abstractInst-{tyTypeDesc}).kind in IntegralTypes)
|
||||||
|
if result and (dstSize > srcSize):
|
||||||
|
message(conf, info, warnCastSizes, "target type is larger than source type")
|
||||||
if result and src.kind == tyNil:
|
if result and src.kind == tyNil:
|
||||||
result = dst.size <= conf.target.ptrSize
|
return dst.size <= conf.target.ptrSize
|
||||||
|
|
||||||
proc isSymChoice(n: PNode): bool {.inline.} =
|
proc isSymChoice(n: PNode): bool {.inline.} =
|
||||||
result = n.kind in nkSymChoices
|
result = n.kind in nkSymChoices
|
||||||
|
|
@ -359,7 +361,7 @@ proc semCast(c: PContext, n: PNode): PNode =
|
||||||
let castedExpr = semExprWithType(c, n[1])
|
let castedExpr = semExprWithType(c, n[1])
|
||||||
if tfHasMeta in targetType.flags:
|
if tfHasMeta in targetType.flags:
|
||||||
localError(c.config, n[0].info, "cannot cast to a non concrete type: '$1'" % $targetType)
|
localError(c.config, n[0].info, "cannot cast to a non concrete type: '$1'" % $targetType)
|
||||||
if not isCastable(c, targetType, castedExpr.typ):
|
if not isCastable(c, targetType, castedExpr.typ, n.info):
|
||||||
let tar = $targetType
|
let tar = $targetType
|
||||||
let alt = typeToString(targetType, preferDesc)
|
let alt = typeToString(targetType, preferDesc)
|
||||||
let msg = if tar != alt: tar & "=" & alt else: tar
|
let msg = if tar != alt: tar & "=" & alt else: tar
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue