From 21e12bde0a1d9ccf531fe45343b7d5013676bfc2 Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Wed, 9 Dec 2020 22:42:17 +0100 Subject: [PATCH] Fixed problem with local variable not shadowing global functions. Closes #597 --- .../dk/camelot64/kickc/passes/Pass1Procedures.java | 13 +++++++++---- .../java/dk/camelot64/kickc/test/TestPrograms.java | 5 +++++ src/test/kc/local-var-shadowing-procedure.c | 12 ++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 src/test/kc/local-var-shadowing-procedure.c diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1Procedures.java b/src/main/java/dk/camelot64/kickc/passes/Pass1Procedures.java index f063ff711..63bd13316 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1Procedures.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1Procedures.java @@ -6,6 +6,8 @@ import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementCall; import dk.camelot64.kickc.model.symbols.Procedure; +import dk.camelot64.kickc.model.symbols.Scope; +import dk.camelot64.kickc.model.symbols.Symbol; /** * Updates procedure calls to point to the actual procedure called. @@ -23,10 +25,13 @@ public class Pass1Procedures extends Pass2SsaOptimization { if(statement instanceof StatementCall) { StatementCall call = (StatementCall) statement; String procedureName = call.getProcedureName(); - Procedure procedure = getScope().getLocalProcedure(procedureName); - if(procedure == null) { - throw new CompileError("Called procedure not found. " + call.toString(getProgram(), false), statement.getSource()); - } + Scope localScope = (Scope) getScope().getSymbol(block.getScope()); + final Symbol procedureSymbol = localScope.findSymbol(procedureName); + if(procedureSymbol == null) + throw new CompileError("Called procedure not found. " + procedureName, statement.getSource()); + if(!(procedureSymbol instanceof Procedure)) + throw new CompileError("Called symbol is not a procedure. " + procedureSymbol.toString(), statement.getSource()); + Procedure procedure = (Procedure) procedureSymbol; call.setProcedure(procedure.getRef()); if(procedure.isVariableLengthParameterList() && procedure.getParameters().size() > call.getParameters().size()) { throw new CompileError("Wrong number of parameters in call. Expected " + procedure.getParameters().size() + " or more. " + statement.toString(), statement.getSource()); diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 1ea5cf149..fe68034a4 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -42,6 +42,11 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testLocalVarShadowingProcedure() throws IOException, URISyntaxException { + assertError("local-var-shadowing-procedure.c", "Called symbol is not a procedure. main::doit"); + } + @Test public void testAdventOfCode04() throws IOException, URISyntaxException { compileAndCompare("adventofcode/2020-04.c"); diff --git a/src/test/kc/local-var-shadowing-procedure.c b/src/test/kc/local-var-shadowing-procedure.c new file mode 100644 index 000000000..6210a6065 --- /dev/null +++ b/src/test/kc/local-var-shadowing-procedure.c @@ -0,0 +1,12 @@ +// Demonstrate that local variable shadowing a global procedure causes an error + +void main() { + char doit = 7; + doit(); +} + +char * const SCREEN = 0x0400; + +void doit() { + SCREEN[0] = '*'; +} \ No newline at end of file