mirror of https://github.com/aamine/cbc
* 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
This commit is contained in:
parent
46109b45b1
commit
c2298ffbd2
91
ChangeLog
91
ChangeLog
|
|
@ -1,3 +1,94 @@
|
|||
Wed Jan 2 19:18:29 2008 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* 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 <aamine@loveruby.net>
|
||||
|
||||
* net/loveruby/cflat/compiler/TypeChecker.java: allow ptr + int,
|
||||
|
|
|
|||
5
ToDo
5
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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ public class FunctionTypeRef extends TypeRef {
|
|||
this.params = params;
|
||||
}
|
||||
|
||||
public boolean isFunctionTypeRef() {
|
||||
public boolean isFunction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,10 +19,6 @@ public class IntegerType extends Type {
|
|||
return true;
|
||||
}
|
||||
|
||||
public boolean isNumeric() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isSigned() {
|
||||
return signed;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(); }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ public class VoidTypeRef extends TypeRef {
|
|||
public VoidTypeRef() {
|
||||
}
|
||||
|
||||
public boolean isVoidTypeRef() {
|
||||
public boolean isVoid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
void f(void) { return 1; }
|
||||
|
|
@ -0,0 +1 @@
|
|||
int f(void) { return; }
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
struct st { int x; };
|
||||
struct st f(void) { return; }
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
union u { int x; };
|
||||
union u f(void) { return 1; }
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
union u { int x; };
|
||||
typedef union u mytype;
|
||||
mytype g(void) { return 1; }
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
struct s { int x; };
|
||||
typedef struct s mytype;
|
||||
mytype f(void) { return 1; }
|
||||
|
|
@ -0,0 +1 @@
|
|||
int[2] f(void) { return 1; }
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue