From bf3e5632ddf21c109f7ef0f61bcc62e2ed0f9d49 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Sat, 19 Sep 2026 10:30:13 -0700 Subject: Handle double-negation preserving not-null knowledge --- .../java/com/seaofnodes/simple/Chapter10Test.java | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'chapter10/src/test/java/com') diff --git a/chapter10/src/test/java/com/seaofnodes/simple/Chapter10Test.java b/chapter10/src/test/java/com/seaofnodes/simple/Chapter10Test.java index f2e7ca2c..c39c19b3 100644 --- a/chapter10/src/test/java/com/seaofnodes/simple/Chapter10Test.java +++ b/chapter10/src/test/java/com/seaofnodes/simple/Chapter10Test.java @@ -12,6 +12,46 @@ import static org.junit.Assert.fail; public class Chapter10Test { + // Issue #246: null-check guards start in Chapter 10; arrays arrive in Chapter 15. + private static final String NULLABLE_POINT_SOURCE = """ + struct Point { int x; }; + Point point = new Point; + point.x = 42; + Point? p = null; + if (arg) p = point; + """; + + @Test + public void testNullGuards() { + for( String body : new String[] { + "if (p != null) return p.x; return -1;", + "if (null != p) return p.x; return -1;", + "if (!!!!p) return p.x; return -1;", + "if (!!!p) return -1; else return p.x;", + "int b = !!p; if (b) return p.x + b - 1; return -1;" + } ) { + StopNode stop = new Parser(NULLABLE_POINT_SOURCE+body).parse().iterate(); + assertEquals(body,-1L,com.seaofnodes.simple.evaluator.Evaluator.evaluate(stop,0)); + assertEquals(body,42L,com.seaofnodes.simple.evaluator.Evaluator.evaluate(stop,1)); + } + } + + @Test + public void testNullGuardErrors() { + for( String body : new String[] { + "return p.x;", + "if (!!point) return p.x; return -1;", + "if (!!p) { int x = p.x; } return p.x;" + } ) { + try { + new Parser(NULLABLE_POINT_SOURCE+body).parse().iterate(); + fail(body); + } catch( RuntimeException e ) { + assertEquals(body,"Might be null accessing 'x'",e.getMessage()); + } + } + } + @Test public void testFuzzer() { Parser parser = new Parser( -- cgit v1.2.3