mirror of
https://github.com/irmen/prog8.git
synced 2024-11-23 07:32:10 +00:00
fix silent typecast on return statements that could lose data (word->byte)
This commit is contained in:
parent
c0b398e0ce
commit
5da3abe6b4
@ -380,12 +380,14 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
|||||||
|
|
||||||
override fun after(returnStmt: Return, parent: Node): Iterable<IAstModification> {
|
override fun after(returnStmt: Return, parent: Node): Iterable<IAstModification> {
|
||||||
// add a typecast to the return type if it doesn't match the subroutine's signature
|
// add a typecast to the return type if it doesn't match the subroutine's signature
|
||||||
|
// but only if no data loss occurs
|
||||||
val returnValue = returnStmt.value
|
val returnValue = returnStmt.value
|
||||||
if(returnValue!=null) {
|
if(returnValue!=null) {
|
||||||
val subroutine = returnStmt.definingSubroutine!!
|
val subroutine = returnStmt.definingSubroutine!!
|
||||||
if(subroutine.returntypes.size==1) {
|
if(subroutine.returntypes.size==1) {
|
||||||
val subReturnType = subroutine.returntypes.first()
|
val subReturnType = subroutine.returntypes.first()
|
||||||
if (returnValue.inferType(program) istype subReturnType)
|
val returnDt = returnValue.inferType(program)
|
||||||
|
if (returnDt istype subReturnType or returnDt.isNotAssignableTo(subReturnType))
|
||||||
return noModifications
|
return noModifications
|
||||||
if (returnValue is NumericLiteral) {
|
if (returnValue is NumericLiteral) {
|
||||||
val cast = returnValue.cast(subroutine.returntypes.single())
|
val cast = returnValue.cast(subroutine.returntypes.single())
|
||||||
|
@ -1003,7 +1003,7 @@ main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("byte when choices silently converted to word for convenience") {
|
test("byte when choices silently converted to word for convenience") {
|
||||||
var text="""
|
val text="""
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
uword z = 3
|
uword z = 3
|
||||||
@ -1016,4 +1016,35 @@ main {
|
|||||||
}"""
|
}"""
|
||||||
compileText(C64Target(), false, text, writeAssembly = false) shouldNotBe null
|
compileText(C64Target(), false, text, writeAssembly = false) shouldNotBe null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("returning smaller dt than returndt is ok") {
|
||||||
|
val text="""
|
||||||
|
main {
|
||||||
|
sub start() {
|
||||||
|
void test()
|
||||||
|
}
|
||||||
|
|
||||||
|
sub test() -> uword {
|
||||||
|
return cx16.r0L
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
compileText(C64Target(), false, text, writeAssembly = false) shouldNotBe null
|
||||||
|
}
|
||||||
|
|
||||||
|
test("returning bigger dt than returndt is not ok") {
|
||||||
|
val text="""
|
||||||
|
main {
|
||||||
|
sub start() {
|
||||||
|
void test()
|
||||||
|
}
|
||||||
|
|
||||||
|
sub test() -> ubyte {
|
||||||
|
return cx16.r0
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
val errors=ErrorReporterForTests()
|
||||||
|
compileText(C64Target(), false, text, writeAssembly = false, errors=errors) shouldBe null
|
||||||
|
errors.errors.single() shouldContain "doesn't match"
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
- this should give a compiler error because word returnvalue:
|
|
||||||
sub atan_coarse_qd(ubyte quadrant, ubyte xdelta, ubyte ydelta) -> ubyte {
|
|
||||||
return mkword(math.atan(0, 0, xdelta, ydelta), 0) / 2730
|
|
||||||
}
|
|
||||||
|
|
||||||
- vm: fix syscall.ATAN calculation
|
- vm: fix syscall.ATAN calculation
|
||||||
- document some library modules better (diskio, etc)
|
- document some library modules better (diskio, etc)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user