From c2298ffbd2d3d3fa1157cf69ba6a8043c34cbcc2 Mon Sep 17 00:00:00 2001 From: Minero Aoki Date: Wed, 2 Jan 2008 10:18:38 +0000 Subject: [PATCH] * net/loveruby/cflat/compiler/TypeChecker.java: check return type. * net/loveruby/cflat/compiler/JumpResolver.java: set exiting function to ReturnNode. * net/loveruby/cflat/ast/ReturnNode.java: new method #setExpr. * net/loveruby/cflat/ast/ReturnNode.java: new method #function. * net/loveruby/cflat/ast/ReturnNode.java: new method #setFunction. * net/loveruby/cflat/ast/Function.java: new method #isVoid. * net/loveruby/cflat/ast/Function.java: new method #returnType. * net/loveruby/cflat/ast/Function.java: new method #functionType. * net/loveruby/cflat/type/TypeRef.java: new method #getPointerTypeRef. * net/loveruby/cflat/type/TypeRef.java: new method #getArrayTypeRef. * net/loveruby/cflat/type/TypeRef.java: new method #getStructTypeRef. * net/loveruby/cflat/type/TypeRef.java: new method #getUnionTypeRef. * net/loveruby/cflat/type/TypeRef.java: new method #getFunctionTypeRef. * net/loveruby/cflat/type/TypeRef.java: #isFunctionType -> #isFunction. * net/loveruby/cflat/type/FunctionTypeRef.java: ditto. * net/loveruby/cflat/type/TypeRef.java: #isVoidTypeRef -> #isVoid. * net/loveruby/cflat/type/VoidTypeRef.java: ditto. * net/loveruby/cflat/type/TypeRef.java: #isArrayTypeRef -> #isArray. * net/loveruby/cflat/type/ArrayTypeRef.java: ditto. * net/loveruby/cflat/type/Type.java: #isNumeric removed. * net/loveruby/cflat/type/IntegerType.java: ditto. * net/loveruby/cflat/type/Type.java: new method #getComplexType. * net/loveruby/cflat/type/Type.java: new method #getStructType. * net/loveruby/cflat/type/Type.java: new method #getUnionType. * net/loveruby/cflat/type/Type.java: new method #getArrayType. * net/loveruby/cflat/type/Type.java: new method #getPointerType. * net/loveruby/cflat/type/Type.java: new method #getFunctionType. * net/loveruby/cflat/type/UserType.java: override them. * net/loveruby/cflat/type/PointerType.java (equals): reduce instanceof. * net/loveruby/cflat/type/TypeTable.java: reduce instanceof/cast. * test/test.sh: invoke following tests. * test/defun-semcheck2.cb: test returning value from void function. * test/defun-semcheck3.cb: test returning nothing from non-void function. * test/defun-semcheck4.cb: test returning struct. * test/defun-semcheck5.cb: test returning union. * test/defun-semcheck6.cb: test returning user type, which is union. * test/defun-semcheck7.cb: test returning user type, which is struct. * test/defun-semcheck8.cb: test returning array. git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@3771 1b9489fe-b721-0410-924e-b54b9192deb8 --- ChangeLog | 91 +++++++++++++++++++ ToDo | 5 +- net/loveruby/cflat/ast/Function.java | 12 +++ net/loveruby/cflat/ast/ReturnNode.java | 19 +++- net/loveruby/cflat/compiler/JumpResolver.java | 18 ++-- net/loveruby/cflat/compiler/TypeChecker.java | 43 ++++++++- net/loveruby/cflat/type/ArrayTypeRef.java | 13 +-- net/loveruby/cflat/type/FunctionTypeRef.java | 2 +- net/loveruby/cflat/type/IntegerType.java | 4 - net/loveruby/cflat/type/PointerType.java | 11 +-- net/loveruby/cflat/type/Type.java | 8 +- net/loveruby/cflat/type/TypeRef.java | 9 +- net/loveruby/cflat/type/TypeTable.java | 19 ++-- net/loveruby/cflat/type/UserType.java | 9 +- net/loveruby/cflat/type/VoidTypeRef.java | 2 +- test/defun-semcheck2.cb | 1 + test/defun-semcheck3.cb | 1 + test/defun-semcheck4.cb | 2 + test/defun-semcheck5.cb | 2 + test/defun-semcheck6.cb | 3 + test/defun-semcheck7.cb | 3 + test/defun-semcheck8.cb | 1 + test/test.sh | 7 ++ 23 files changed, 243 insertions(+), 42 deletions(-) create mode 100644 test/defun-semcheck2.cb create mode 100644 test/defun-semcheck3.cb create mode 100644 test/defun-semcheck4.cb create mode 100644 test/defun-semcheck5.cb create mode 100644 test/defun-semcheck6.cb create mode 100644 test/defun-semcheck7.cb create mode 100644 test/defun-semcheck8.cb diff --git a/ChangeLog b/ChangeLog index 555616a..da97b31 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,94 @@ +Wed Jan 2 19:18:29 2008 Minero Aoki + + * net/loveruby/cflat/compiler/TypeChecker.java: check return type. + + * net/loveruby/cflat/compiler/JumpResolver.java: set exiting + function to ReturnNode. + + * net/loveruby/cflat/ast/ReturnNode.java: new method #setExpr. + + * net/loveruby/cflat/ast/ReturnNode.java: new method #function. + + * net/loveruby/cflat/ast/ReturnNode.java: new method #setFunction. + + * net/loveruby/cflat/ast/Function.java: new method #isVoid. + + * net/loveruby/cflat/ast/Function.java: new method #returnType. + + * net/loveruby/cflat/ast/Function.java: new method #functionType. + + * net/loveruby/cflat/type/TypeRef.java: new method + #getPointerTypeRef. + + * net/loveruby/cflat/type/TypeRef.java: new method + #getArrayTypeRef. + + * net/loveruby/cflat/type/TypeRef.java: new method + #getStructTypeRef. + + * net/loveruby/cflat/type/TypeRef.java: new method + #getUnionTypeRef. + + * net/loveruby/cflat/type/TypeRef.java: new method + #getFunctionTypeRef. + + * net/loveruby/cflat/type/TypeRef.java: #isFunctionType -> + #isFunction. + + * net/loveruby/cflat/type/FunctionTypeRef.java: ditto. + + * net/loveruby/cflat/type/TypeRef.java: #isVoidTypeRef -> #isVoid. + + * net/loveruby/cflat/type/VoidTypeRef.java: ditto. + + * net/loveruby/cflat/type/TypeRef.java: #isArrayTypeRef -> + #isArray. + + * net/loveruby/cflat/type/ArrayTypeRef.java: ditto. + + * net/loveruby/cflat/type/Type.java: #isNumeric removed. + + * net/loveruby/cflat/type/IntegerType.java: ditto. + + * net/loveruby/cflat/type/Type.java: new method #getComplexType. + + * net/loveruby/cflat/type/Type.java: new method #getStructType. + + * net/loveruby/cflat/type/Type.java: new method #getUnionType. + + * net/loveruby/cflat/type/Type.java: new method #getArrayType. + + * net/loveruby/cflat/type/Type.java: new method #getPointerType. + + * net/loveruby/cflat/type/Type.java: new method #getFunctionType. + + * net/loveruby/cflat/type/UserType.java: override them. + + * net/loveruby/cflat/type/PointerType.java (equals): reduce + instanceof. + + * net/loveruby/cflat/type/TypeTable.java: reduce instanceof/cast. + + * test/test.sh: invoke following tests. + + * test/defun-semcheck2.cb: test returning value from void + function. + + * test/defun-semcheck3.cb: test returning nothing from non-void + function. + + * test/defun-semcheck4.cb: test returning struct. + + * test/defun-semcheck5.cb: test returning union. + + * test/defun-semcheck6.cb: test returning user type, which is + union. + + * test/defun-semcheck7.cb: test returning user type, which is + struct. + + * test/defun-semcheck8.cb: test returning array. + Wed Jan 2 04:03:10 2008 Minero Aoki * net/loveruby/cflat/compiler/TypeChecker.java: allow ptr + int, diff --git a/ToDo b/ToDo index dde7304..70471b1 100644 --- a/ToDo +++ b/ToDo @@ -139,7 +139,7 @@ * their combination - bare block ({...}) - cast -- semantic check (control) +* semantic check (control) - reject break from out of loop/switch - reject continue from out of loop * reject no return @@ -165,8 +165,9 @@ - validate struct/union member (ct->memb) - check duplicated struct/union members - ptr + int; ptr - int - * check return type + - check return type * check if assignable + * use user type instead of struct/union - op for various types - signed char - signed short diff --git a/net/loveruby/cflat/ast/Function.java b/net/loveruby/cflat/ast/Function.java index 777c868..b7e5651 100644 --- a/net/loveruby/cflat/ast/Function.java +++ b/net/loveruby/cflat/ast/Function.java @@ -13,4 +13,16 @@ abstract public class Function extends Entity { abstract public boolean isDefined(); abstract public Iterator parameters(); abstract public AsmEntity address(); + + public FunctionType functionType() { + return type().getPointerType().base().getFunctionType(); + } + + public Type returnType() { + return functionType().returnType(); + } + + public boolean isVoid() { + return returnType().isVoid(); + } } diff --git a/net/loveruby/cflat/ast/ReturnNode.java b/net/loveruby/cflat/ast/ReturnNode.java index 0df11ed..65ed45d 100644 --- a/net/loveruby/cflat/ast/ReturnNode.java +++ b/net/loveruby/cflat/ast/ReturnNode.java @@ -2,6 +2,7 @@ package net.loveruby.cflat.ast; public class ReturnNode extends Node { Node expr; + Function function; public ReturnNode(Node e) { super(); @@ -13,6 +14,22 @@ public class ReturnNode extends Node { } public Node expr() { - return expr; + return this.expr; + } + + public void setExpr(Node expr) { + this.expr = expr; + } + + public void setFunction(Function f) { + if (this.function != null) + throw new Error("setFunction called twice"); + this.function = f; + } + + public Function function() { + if (this.function == null) + throw new Error("ReturnNode#function called before setFunction"); + return this.function; } } diff --git a/net/loveruby/cflat/compiler/JumpResolver.java b/net/loveruby/cflat/compiler/JumpResolver.java index 6b4cffe..df7307a 100644 --- a/net/loveruby/cflat/compiler/JumpResolver.java +++ b/net/loveruby/cflat/compiler/JumpResolver.java @@ -10,13 +10,13 @@ public class JumpResolver extends Visitor { new JumpResolver(h).resolveAST(ast); } - protected ErrorHandler handler; + protected ErrorHandler errorHandler; protected LinkedList breakTargetStack; protected LinkedList continueTargetStack; protected DefinedFunction currentFunction; public JumpResolver(ErrorHandler h) { - handler = h; + errorHandler = h; } public void resolveAST(AST ast) throws SemanticException { @@ -26,9 +26,9 @@ public class JumpResolver extends Visitor { while (funcs.hasNext()) { currentFunction = (DefinedFunction)funcs.next(); resolve(currentFunction.body()); - currentFunction.checkJumpLinks(handler); + currentFunction.checkJumpLinks(errorHandler); } - if (handler.errorOccured()) { + if (errorHandler.errorOccured()) { throw new SemanticException("semantic error"); } } @@ -90,7 +90,7 @@ public class JumpResolver extends Visitor { node.setTargetLabel(currentBreakTarget().endLabel()); } catch (SemanticException ex) { - handler.error(ex.getMessage()); + errorHandler.error(ex.getMessage()); } } @@ -99,7 +99,7 @@ public class JumpResolver extends Visitor { node.setTargetLabel(currentContinueTarget().continueLabel()); } catch (SemanticException ex) { - handler.error(ex.getMessage()); + errorHandler.error(ex.getMessage()); } } @@ -109,11 +109,15 @@ public class JumpResolver extends Visitor { node.setLabel(label); } catch (SemanticException ex) { - handler.error(ex.getMessage()); + errorHandler.error(ex.getMessage()); } } public void visit(GotoNode node) { node.setTargetLabel(currentFunction.referLabel(node.target())); } + + public void visit(ReturnNode node) { + node.setFunction(currentFunction); + } } diff --git a/net/loveruby/cflat/compiler/TypeChecker.java b/net/loveruby/cflat/compiler/TypeChecker.java index 6937e3a..d7dc6b0 100644 --- a/net/loveruby/cflat/compiler/TypeChecker.java +++ b/net/loveruby/cflat/compiler/TypeChecker.java @@ -22,10 +22,23 @@ class TypeChecker extends Visitor { Iterator funcs = ast.functions(); while (funcs.hasNext()) { DefinedFunction f = (DefinedFunction)funcs.next(); + checkReturnType(f); resolve(f.body()); } if (errorHandler.errorOccured()) { - throw new SemanticException("compile error"); + throw new SemanticException("compile failed."); + } + } + + protected void checkReturnType(Function f) { + if (f.returnType().isArray()) { + errorHandler.error("returns an array: " + f.name()); + } + else if (f.returnType().isStruct()) { + errorHandler.error("returns a struct: " + f.name()); + } + else if (f.returnType().isUnion()) { + errorHandler.error("returns a union: " + f.name()); } } @@ -130,7 +143,33 @@ class TypeChecker extends Visitor { public void visit(ReturnNode node) { super.visit(node); - // FIXME: check return type + if (node.function().isVoid()) { + if (node.expr() != null) { + errorHandler.error("returning value from void function"); + } + } + else { // non-void function + if (node.expr() == null) { + errorHandler.error("missing return value"); + return; + } + insertImplicitCast(node); + } + } + + protected void insertImplicitCast(ReturnNode node) { + Type exprType = node.expr().type(); + Type retType = node.function().returnType(); + if (exprType.equals(retType)) { // type matches + return; + } + else if (exprType.isCompatible(retType)) { + node.setExpr(newCastNode(retType, node.expr())); + } + else { + errorHandler.error("returning incompatible value: " + + exprType.textize()); + } } // diff --git a/net/loveruby/cflat/type/ArrayTypeRef.java b/net/loveruby/cflat/type/ArrayTypeRef.java index c87abe6..13f694b 100644 --- a/net/loveruby/cflat/type/ArrayTypeRef.java +++ b/net/loveruby/cflat/type/ArrayTypeRef.java @@ -6,16 +6,17 @@ public class ArrayTypeRef extends TypeRef { static final protected long undefined = -1; public ArrayTypeRef(TypeRef base) { - this(base, undefined); + this.base = base; + this.length = undefined; } - public ArrayTypeRef(TypeRef ref, long len) { - if (len < 0) throw new Error("negative array length"); - base = ref; - length = len; + public ArrayTypeRef(TypeRef base, long length) { + if (length < 0) throw new Error("negative array length"); + this.base = base; + this.length = length; } - public boolean isArrayTypeRef() { + public boolean isArray() { return true; } diff --git a/net/loveruby/cflat/type/FunctionTypeRef.java b/net/loveruby/cflat/type/FunctionTypeRef.java index fb1de5b..28b3a28 100644 --- a/net/loveruby/cflat/type/FunctionTypeRef.java +++ b/net/loveruby/cflat/type/FunctionTypeRef.java @@ -11,7 +11,7 @@ public class FunctionTypeRef extends TypeRef { this.params = params; } - public boolean isFunctionTypeRef() { + public boolean isFunction() { return true; } diff --git a/net/loveruby/cflat/type/IntegerType.java b/net/loveruby/cflat/type/IntegerType.java index 21aa858..3a9c4d6 100644 --- a/net/loveruby/cflat/type/IntegerType.java +++ b/net/loveruby/cflat/type/IntegerType.java @@ -19,10 +19,6 @@ public class IntegerType extends Type { return true; } - public boolean isNumeric() { - return true; - } - public boolean isSigned() { return signed; } diff --git a/net/loveruby/cflat/type/PointerType.java b/net/loveruby/cflat/type/PointerType.java index 98e7f65..5104d78 100644 --- a/net/loveruby/cflat/type/PointerType.java +++ b/net/loveruby/cflat/type/PointerType.java @@ -29,18 +29,15 @@ public class PointerType extends Type { return true; } - public boolean isNumeric() { - return true; - } - public boolean isPointer() { return true; } public boolean equals(Object other) { - if (! (other instanceof PointerType)) return false; - PointerType otherptr = (PointerType)other; - return this.base.equals(otherptr.base()); + if (! (other instanceof Type)) return false; + Type t = (Type)other; + if (! t.isPointer()) return false; + return this.base.equals(t.getPointerType().base()); } public String textize() { diff --git a/net/loveruby/cflat/type/Type.java b/net/loveruby/cflat/type/Type.java index a042c78..867be2e 100644 --- a/net/loveruby/cflat/type/Type.java +++ b/net/loveruby/cflat/type/Type.java @@ -14,7 +14,6 @@ public abstract class Type { public boolean isInteger() { return false; } public boolean isSigned() { throw new Error("#isSigned for non-integer type"); } - public boolean isNumeric() { return false; } public boolean isPointer() { return false; } public boolean isArray() { return false; } public boolean isStruct() { return false; } @@ -29,4 +28,11 @@ public abstract class Type { public boolean isIndexable() { return false; } public abstract String textize(); + + public PointerType getPointerType() { return (PointerType)this; } + public FunctionType getFunctionType() { return (FunctionType)this; } + public StructType getStructType() { return (StructType)this; } + public UnionType getUnionType() { return (UnionType)this; } + public ComplexType getComplexType() { return (ComplexType)this; } + public ArrayType getArrayType() { return (ArrayType)this; } } diff --git a/net/loveruby/cflat/type/TypeRef.java b/net/loveruby/cflat/type/TypeRef.java index 155b977..0024e63 100644 --- a/net/loveruby/cflat/type/TypeRef.java +++ b/net/loveruby/cflat/type/TypeRef.java @@ -1,6 +1,7 @@ package net.loveruby.cflat.type; public abstract class TypeRef { + public boolean isVoid() { return false; } public boolean isSignedChar() { return false; } public boolean isSignedShort() { return false; } public boolean isSignedInt() { return false; } @@ -14,5 +15,11 @@ public abstract class TypeRef { public boolean isStruct() { return false; } public boolean isUnion() { return false; } public boolean isUserType() { return false; } - public boolean isFunctionType() { return false; } + public boolean isFunction() { return false; } + + public PointerTypeRef getPointerTypeRef() { return (PointerTypeRef)this; } + public ArrayTypeRef getArrayTypeRef() { return (ArrayTypeRef)this; } + public StructTypeRef getStructTypeRef() { return (StructTypeRef)this; } + public UnionTypeRef getUnionTypeRef() { return (UnionTypeRef)this; } + public FunctionTypeRef getFunctionTypeRef() { return (FunctionTypeRef)this;} } diff --git a/net/loveruby/cflat/type/TypeTable.java b/net/loveruby/cflat/type/TypeTable.java index 54ff5bd..ddc7cc4 100644 --- a/net/loveruby/cflat/type/TypeTable.java +++ b/net/loveruby/cflat/type/TypeTable.java @@ -55,20 +55,20 @@ public class TypeTable { public Type get(TypeRef ref) { Type type = (Type)table.get(ref); if (type == null) { - if (ref instanceof PointerTypeRef) { - PointerTypeRef pref = (PointerTypeRef)ref; + if (ref.isPointer()) { + PointerTypeRef pref = ref.getPointerTypeRef(); Type t = new PointerType(pointerSize, get(pref.base())); table.put(pref, t); return t; } - else if (ref instanceof ArrayTypeRef) { - ArrayTypeRef aref = (ArrayTypeRef)ref; + else if (ref.isArray()) { + ArrayTypeRef aref = ref.getArrayTypeRef(); Type t = new ArrayType(get(aref.base()), aref.length()); table.put(aref, t); return t; } - else if (ref instanceof FunctionTypeRef) { - FunctionTypeRef fref = (FunctionTypeRef)ref; + else if (ref.isFunction()) { + FunctionTypeRef fref = ref.getFunctionTypeRef(); Type t = new FunctionType(get(fref.returnType()), fref.params().internTypes(this)); table.put(fref, t); @@ -138,6 +138,9 @@ public class TypeTable { public void semanticCheck(ErrorHandler errorHandler) { Iterator types = table.values().iterator(); while (types.hasNext()) { + // We should check true ComplexType. + // We do not need to check UserType because refered + // ComplexType must be kept in this table. Type t = (Type)types.next(); if (t instanceof ComplexType) { checkDuplicatedMembers((ComplexType)t, errorHandler); @@ -176,8 +179,8 @@ public class TypeTable { Iterator membs = t.members(); while (membs.hasNext()) { Slot slot = (Slot)membs.next(); - if (slot.type() instanceof ComplexType) { - checkRecursiveDefinition((ComplexType)slot.type(), + if (slot.type().isComplexType()) { + checkRecursiveDefinition(slot.type().getComplexType(), seen, errorHandler); } } diff --git a/net/loveruby/cflat/type/UserType.java b/net/loveruby/cflat/type/UserType.java index b921569..dcd08c6 100644 --- a/net/loveruby/cflat/type/UserType.java +++ b/net/loveruby/cflat/type/UserType.java @@ -31,11 +31,18 @@ public class UserType extends Type { public boolean isReferable() { return real().isReferable(); } public boolean isInt() { return real().isInt(); } public boolean isInteger() { return real().isInteger(); } - public boolean isNumeric() { return real().isNumeric(); } public boolean isPointer() { return real().isPointer(); } public boolean isArray() { return real().isArray(); } + public boolean isComplexType() { return real().isComplexType(); } public boolean isStruct() { return real().isStruct(); } public boolean isUnion() { return real().isUnion(); } public boolean isUserType() { return true; } public boolean isFunction() { return real().isFunction(); } + + public ComplexType getComplexType() { return real().getComplexType(); } + public StructType getStructType() { return real().getStructType(); } + public UnionType getUnionType() { return real().getUnionType(); } + public ArrayType getArrayType() { return real().getArrayType(); } + public PointerType getPointerType() { return real().getPointerType(); } + public FunctionType getFunctionType() { return real().getFunctionType(); } } diff --git a/net/loveruby/cflat/type/VoidTypeRef.java b/net/loveruby/cflat/type/VoidTypeRef.java index 8718254..ef3ea96 100644 --- a/net/loveruby/cflat/type/VoidTypeRef.java +++ b/net/loveruby/cflat/type/VoidTypeRef.java @@ -4,7 +4,7 @@ public class VoidTypeRef extends TypeRef { public VoidTypeRef() { } - public boolean isVoidTypeRef() { + public boolean isVoid() { return true; } diff --git a/test/defun-semcheck2.cb b/test/defun-semcheck2.cb new file mode 100644 index 0000000..e0372f7 --- /dev/null +++ b/test/defun-semcheck2.cb @@ -0,0 +1 @@ +void f(void) { return 1; } diff --git a/test/defun-semcheck3.cb b/test/defun-semcheck3.cb new file mode 100644 index 0000000..3a0bf05 --- /dev/null +++ b/test/defun-semcheck3.cb @@ -0,0 +1 @@ +int f(void) { return; } diff --git a/test/defun-semcheck4.cb b/test/defun-semcheck4.cb new file mode 100644 index 0000000..78920fd --- /dev/null +++ b/test/defun-semcheck4.cb @@ -0,0 +1,2 @@ +struct st { int x; }; +struct st f(void) { return; } diff --git a/test/defun-semcheck5.cb b/test/defun-semcheck5.cb new file mode 100644 index 0000000..a2798e8 --- /dev/null +++ b/test/defun-semcheck5.cb @@ -0,0 +1,2 @@ +union u { int x; }; +union u f(void) { return 1; } diff --git a/test/defun-semcheck6.cb b/test/defun-semcheck6.cb new file mode 100644 index 0000000..340d5d2 --- /dev/null +++ b/test/defun-semcheck6.cb @@ -0,0 +1,3 @@ +union u { int x; }; +typedef union u mytype; +mytype g(void) { return 1; } diff --git a/test/defun-semcheck7.cb b/test/defun-semcheck7.cb new file mode 100644 index 0000000..19e75f5 --- /dev/null +++ b/test/defun-semcheck7.cb @@ -0,0 +1,3 @@ +struct s { int x; }; +typedef struct s mytype; +mytype f(void) { return 1; } diff --git a/test/defun-semcheck8.cb b/test/defun-semcheck8.cb new file mode 100644 index 0000000..934ae18 --- /dev/null +++ b/test/defun-semcheck8.cb @@ -0,0 +1 @@ +int[2] f(void) { return 1; } diff --git a/test/test.sh b/test/test.sh index 932791c..5452c05 100755 --- a/test/test.sh +++ b/test/test.sh @@ -156,6 +156,13 @@ assert_out "1;2;3" ./defvar assert_out "OK" ./funcptr assert_error $CBC defun-semcheck.cb +assert_error $CBC defun-semcheck2.cb +assert_error $CBC defun-semcheck3.cb +assert_error $CBC defun-semcheck4.cb +assert_error $CBC defun-semcheck5.cb +assert_error $CBC defun-semcheck6.cb +assert_error $CBC defun-semcheck7.cb +assert_error $CBC defun-semcheck8.cb assert_error $CBC funcall-semcheck.cb assert_error $CBC funcall-semcheck2.cb