summaryrefslogtreecommitdiff
path: root/chapter17
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-09-28 09:23:27 -0700
committerCliff Click <cliffc@acm.org>2026-09-28 09:23:27 -0700
commit8212a66ff27e56531e0b48807088f1c544d75756 (patch)
treed1a1cdbf1ae790ddd8378714d4325a84b90bfc17 /chapter17
parent3d226b49e1cd23b41fd9baf3917f751973c1ad11 (diff)
downloadSimple-8212a66ff27e56531e0b48807088f1c544d75756.tar.gz
Simple-8212a66ff27e56531e0b48807088f1c544d75756.zip
Check un-init not-null constructor fields
Propagate BOT inputs; Arith, Load. CallEnd inlining, the FUnPtr dies early. Load asserts when loading against uninit not-null field. Keep not-nill state for storage class. Clean up Node.peep as constant.
Diffstat (limited to 'chapter17')
-rw-r--r--chapter17/src/main/java/com/seaofnodes/simple/Parser.java2
-rw-r--r--chapter17/src/test/java/com/seaofnodes/simple/Chapter10Test.java6
-rw-r--r--chapter17/src/test/java/com/seaofnodes/simple/Chapter16Test.java13
3 files changed, 11 insertions, 10 deletions
diff --git a/chapter17/src/main/java/com/seaofnodes/simple/Parser.java b/chapter17/src/main/java/com/seaofnodes/simple/Parser.java
index 07312396..86b59dc3 100644
--- a/chapter17/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter17/src/main/java/com/seaofnodes/simple/Parser.java
@@ -992,7 +992,7 @@ public class Parser {
}
// Check that all fields are initialized
for( int i=idx; i<init.size(); i++ )
- if( /*init.at(i)._type == Type.TOP ||*/ init.at(i)._type == Type.BOTTOM )
+ if( init.at(i)._type == Type.TOP || init.at(i)._type == Type.BOTTOM )
throw error("'"+tmp._obj._name+"' is not fully initialized, field '" + fs[i-idx]._fname + "' needs to be set in a constructor");
Node ptr = newStruct(tmp._obj, con(tmp._obj.offset(fs.length)), idx, init );
if( hasConstructor )
diff --git a/chapter17/src/test/java/com/seaofnodes/simple/Chapter10Test.java b/chapter17/src/test/java/com/seaofnodes/simple/Chapter10Test.java
index 089649bf..e3d8b177 100644
--- a/chapter17/src/test/java/com/seaofnodes/simple/Chapter10Test.java
+++ b/chapter17/src/test/java/com/seaofnodes/simple/Chapter10Test.java
@@ -48,6 +48,7 @@ public class Chapter10Test {
public void testNullGuardErrors() {
for( String body : new String[] {
"return p.x;",
+ "if (p == null) return p.x; return -1;",
"if (!!points) return p.x; return -1;",
"if (!!p) { int x = p.x; } return p.x;"
} ) {
@@ -55,7 +56,10 @@ public class Chapter10Test {
new Parser(NULLABLE_POINT_SOURCE+body).parse().iterate();
fail(body);
} catch( RuntimeException e ) {
- assertEquals(body,"Might be null accessing 'x'",e.getMessage());
+ // Known null is rejected during parsing in these chapters.
+ String expected = body.startsWith("if (p == null)")
+ ? "Accessing unknown field 'x' from 'null'" : "Might be null accessing 'x'";
+ assertEquals(body,expected,e.getMessage());
}
}
}
diff --git a/chapter17/src/test/java/com/seaofnodes/simple/Chapter16Test.java b/chapter17/src/test/java/com/seaofnodes/simple/Chapter16Test.java
index 5450824a..36510737 100644
--- a/chapter17/src/test/java/com/seaofnodes/simple/Chapter16Test.java
+++ b/chapter17/src/test/java/com/seaofnodes/simple/Chapter16Test.java
@@ -144,14 +144,11 @@ return p;
@Test
public void testStructFinal3() {
- Parser parser = new Parser("""
-struct Point { var x; var y; };
-Point p = new Point;
-p.x++;
-return p;
-""");
- try { parser.parse().iterate(); fail(); }
- catch( Exception e ) { assertEquals("'Point' is not fully initialized, field 'x' needs to be set in a constructor",e.getMessage()); }
+ for( String fields : new String[] { "var x; var y;", "int[] x;", "int[] !x;" } ) {
+ String src = "struct Point { "+fields+" }; Point p = new Point; p.x++; return p;";
+ try { new Parser(src).parse().iterate(); fail(fields); }
+ catch( Exception e ) { assertEquals("'Point' is not fully initialized, field 'x' needs to be set in a constructor",e.getMessage()); }
+ }
}
@Test