avoid compiler crash when using char literal in str initialization

fix compiler crash when using str var in an expression without &
This commit is contained in:
Irmen de Jong
2024-12-18 00:17:52 +01:00
parent 7c79cdbd2f
commit 73baaeff1f
5 changed files with 35 additions and 6 deletions

View File

@@ -3,6 +3,7 @@ package prog8.compiler.astprocessing
import prog8.ast.IStatementContainer import prog8.ast.IStatementContainer
import prog8.ast.Node import prog8.ast.Node
import prog8.ast.Program import prog8.ast.Program
import prog8.ast.expressions.BinaryExpression
import prog8.ast.expressions.CharLiteral import prog8.ast.expressions.CharLiteral
import prog8.ast.expressions.IdentifierReference import prog8.ast.expressions.IdentifierReference
import prog8.ast.expressions.NumericLiteral import prog8.ast.expressions.NumericLiteral
@@ -82,6 +83,18 @@ internal fun Program.charLiteralsToUByteLiterals(target: ICompilationTarget, err
} }
return noModifications return noModifications
} }
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
if(decl.datatype.isString) {
val initvalue = decl.value
if(initvalue!=null && initvalue is BinaryExpression) {
if(initvalue.left is CharLiteral || initvalue.right is CharLiteral) {
errors.err("using a char literal in a string initialization expression, should probably be a string literal with one character in it instead", initvalue.position)
}
}
}
return noModifications
}
} }
walker.visit(this) walker.visit(this)

View File

@@ -368,4 +368,19 @@ main {
errors.warnings.size shouldBe 0 errors.warnings.size shouldBe 0
errors.errors[0] shouldContain "requires integer or boolean type" errors.errors[0] shouldContain "requires integer or boolean type"
} }
test("missing address of in expression operand") {
val src="""
main {
sub start() {
str name = "foo"
cx16.r0 = name+2
}
}"""
val errors = ErrorReporterForTests()
compileText(C64Target(), false, src, writeAssembly = false, errors = errors) shouldBe null
errors.errors.size shouldBe 1
errors.warnings.size shouldBe 0
errors.errors[0] shouldContain "missing &"
}
}) })

View File

@@ -253,7 +253,7 @@ class BinaryExpression(
// if left or right is a numeric literal, and its value fits in the type of the other operand, use the other's operand type // if left or right is a numeric literal, and its value fits in the type of the other operand, use the other's operand type
// EXCEPTION: if the numeric value is a word and the other operand is a byte type (to allow v * $0008 for example) // EXCEPTION: if the numeric value is a word and the other operand is a byte type (to allow v * $0008 for example)
if (left is NumericLiteral) { if (left is NumericLiteral && rightDt.isNumericOrBool) {
if(!(leftDt.isWord && rightDt.isByte)) { if(!(leftDt.isWord && rightDt.isByte)) {
val optimal = NumericLiteral.optimalNumeric(rightDt.base, null, left.number, left.position) val optimal = NumericLiteral.optimalNumeric(rightDt.base, null, left.number, left.position)
if (optimal.type != leftDt.base && DataType.forDt(optimal.type) isAssignableTo rightDt) { if (optimal.type != leftDt.base && DataType.forDt(optimal.type) isAssignableTo rightDt) {
@@ -261,7 +261,7 @@ class BinaryExpression(
} }
} }
} }
if (right is NumericLiteral) { if (right is NumericLiteral && leftDt.isNumericOrBool) {
if(!(rightDt.isWord && leftDt.isByte)) { if(!(rightDt.isWord && leftDt.isByte)) {
val optimal = NumericLiteral.optimalNumeric(leftDt.base, null, right.number, right.position) val optimal = NumericLiteral.optimalNumeric(leftDt.base, null, right.number, right.position)
if (optimal.type != rightDt.base && DataType.forDt(optimal.type) isAssignableTo leftDt) { if (optimal.type != rightDt.base && DataType.forDt(optimal.type) isAssignableTo leftDt) {

View File

@@ -22,6 +22,8 @@ Future Things and Ideas
Make up our mind! Maybe all setup does need to be put into start() ? because the program cannot function correctly when the variables aren't initialized properly bss is not cleared etc. etc. Make up our mind! Maybe all setup does need to be put into start() ? because the program cannot function correctly when the variables aren't initialized properly bss is not cleared etc. etc.
Add a -library $xxxx command line option (and/or some directive) to preselect every setting that is required to make a library at $xxxx rather than a normal loadable and runnable program? Add a -library $xxxx command line option (and/or some directive) to preselect every setting that is required to make a library at $xxxx rather than a normal loadable and runnable program?
Need to add some way to generate a stable jump table at a given address. Need to add some way to generate a stable jump table at a given address.
Need library to not call init_system AND init_system_phase2 not either.
Library must not include prog8_program_start stuff either.
- Fix missing cases where regular & has to return the start of the split array in memory whatever byte comes first. Search TODO("address of split word array") - Fix missing cases where regular & has to return the start of the split array in memory whatever byte comes first. Search TODO("address of split word array")
- Add a syntax to access specific bits in a variable, to avoid manually shifts&ands, something like variable[4:8] ? (or something else this may be too similar to regular array indexing) - Add a syntax to access specific bits in a variable, to avoid manually shifts&ands, something like variable[4:8] ? (or something else this may be too similar to regular array indexing)
- something to reduce the need to use fully qualified names all the time. 'with' ? Or 'using <prefix>'? - something to reduce the need to use fully qualified names all the time. 'with' ? Or 'using <prefix>'?

View File

@@ -1,8 +1,7 @@
main { main {
sub start() { sub start() {
uword[] tasklist = [1111,2222,3333] ;str test = '?' * 10
uword task_address = tasklist[0] str name = "foo"
goto task_address cx16.r0 = name+2
goto task_address+1
} }
} }