* net/loveruby/cflat/compiler/TypeChecker.java: check member validity for s.memb, s->memb, u.memb, u->memb.

* net/loveruby/cflat/type/Type.java: new method #isComplexType.
* net/loveruby/cflat/type/ComplexType.java: override it.
* net/loveruby/cflat/compiler/LocalReferenceResolver.java: should resolve variable initializer.
* net/loveruby/cflat/ast/DefinedVariable.java: new method #hasInitializer.
* test/test.sh: run tests.
* test/struct-semcheck5.cb: check if member is valid on s.memb.
* test/struct-semcheck6.cb: check if member is valid on sptr->memb.
* test/union-semcheck5.cb: check if member is valid on u.memb.
* test/union-semcheck6.cb: check if member is valid on uptr->memb.


git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@3766 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
Minero Aoki 2008-01-01 16:24:09 +00:00
parent 0b70938a5f
commit 705818d1dc
12 changed files with 154 additions and 74 deletions

View File

@ -1,3 +1,29 @@
Wed Jan 2 01:24:05 2008 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/compiler/TypeChecker.java: check member
validity for s.memb, s->memb, u.memb, u->memb.
* net/loveruby/cflat/type/Type.java: new method #isComplexType.
* net/loveruby/cflat/type/ComplexType.java: override it.
* net/loveruby/cflat/compiler/LocalReferenceResolver.java: should
resolve variable initializer.
* net/loveruby/cflat/ast/DefinedVariable.java: new method
#hasInitializer.
* test/test.sh: run tests.
* test/struct-semcheck5.cb: check if member is valid on s.memb.
* test/struct-semcheck6.cb: check if member is valid on
sptr->memb.
* test/union-semcheck5.cb: check if member is valid on u.memb.
* test/union-semcheck6.cb: check if member is valid on uptr->memb.
Wed Jan 2 00:38:48 2008 Minero Aoki <aamine@loveruby.net> Wed Jan 2 00:38:48 2008 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/compiler/TypeChecker.java: check aref base * net/loveruby/cflat/compiler/TypeChecker.java: check aref base

19
ToDo
View File

@ -155,13 +155,23 @@
- warn unused static variables - warn unused static variables
- warn unused local variables - warn unused local variables
- warn unused static functions - warn unused static functions
- check if aref base expr is indexable (a must be indeable where a[0])
- check if funcall base expr is callable (a must be callable where a())
* semantic check (type) * semantic check (type)
- simple type check (binary ops, unary ops)
- a[0]
- *ptr
- ct.memb
- ptr->memb
- funcall args
- prohibit circular struct/union definition - prohibit circular struct/union definition
* type check - implicit cast
* implicit cast - validate struct/union member (ct.memb)
* check return type - validate struct/union member (ct->memb)
* check duplicated struct/union members * check duplicated struct/union members
* validate struct/union member * ptr + int; ptr - int
* check return type
* check if assignable
- op for various types - op for various types
- signed char - signed char
- signed short - signed short
@ -186,6 +196,7 @@
* warn no return * warn no return
* data flow graph * data flow graph
* --dump-dflow * --dump-dflow
* warn unused variable
* warn uninitialized use of variables * warn uninitialized use of variables
* semantic check (dflow) * semantic check (dflow)
* register allocation * register allocation

View File

@ -18,10 +18,14 @@ public class DefinedVariable extends Variable {
return true; return true;
} }
public boolean isInitialized() { public boolean hasInitializer() {
return (initializer != null); return (initializer != null);
} }
public boolean isInitialized() {
return hasInitializer();
}
public Node initializer() { public Node initializer() {
return initializer; return initializer;
} }

View File

@ -74,6 +74,7 @@ public class LocalReferenceResolver extends Visitor {
public void visit(BlockNode node) { public void visit(BlockNode node) {
pushScope(node.variables()); pushScope(node.variables());
resolveInitializers(node.variables());
super.visit(node); super.visit(node);
node.setScope(popScope()); node.setScope(popScope());
} }
@ -100,6 +101,15 @@ public class LocalReferenceResolver extends Visitor {
return (Scope)scopeStack.getLast(); return (Scope)scopeStack.getLast();
} }
protected void resolveInitializers(Iterator vars) {
while (vars.hasNext()) {
DefinedVariable var = (DefinedVariable)vars.next();
if (var.hasInitializer()) {
resolve(var.initializer());
}
}
}
public void visit(StringLiteralNode node) { public void visit(StringLiteralNode node) {
node.setEntry(constantTable.intern(node.value())); node.setEntry(constantTable.intern(node.value()));
} }

View File

@ -320,19 +320,39 @@ class TypeChecker extends Visitor {
} }
public void visit(MemberNode node) { public void visit(MemberNode node) {
super.visit(node); resolve(node.expr());
// FIXME: validate member here? checkMemberRef(node.expr().type(), node.name());
} }
public void visit(PtrMemberNode node) { public void visit(PtrMemberNode node) {
super.visit(node); resolve(node.expr());
// FIXME: validate member here? if (! node.expr().type().isPointer()) {
notPointerError(node.type());
return;
}
PointerType pt = (PointerType)node.expr().type();
checkMemberRef(pt.base(), node.name());
}
protected void checkMemberRef(Type t, String memb) {
if (! t.isComplexType()) {
errorHandler.error("is not struct/union: " + t.textize());
return;
}
ComplexType type = (ComplexType)t;
if (! type.hasMember(memb)) {
errorHandler.error(type.textize() +
" does not have member " + memb);
return;
}
} }
public void visit(DereferenceNode node) { public void visit(DereferenceNode node) {
super.visit(node); super.visit(node);
if (node.type().isPointer()) return; if (! node.expr().type().isPointer()) {
notPointerError(node.type()); notPointerError(node.type());
return;
}
} }
public void visit(AddressNode node) { public void visit(AddressNode node) {

View File

@ -16,6 +16,10 @@ abstract public class ComplexType extends Type {
isRecursiveChecked = false; isRecursiveChecked = false;
} }
public boolean isComplexType() {
return true;
}
public String name() { public String name() {
return name; return name;
} }
@ -31,6 +35,10 @@ abstract public class ComplexType extends Type {
return members.iterator(); return members.iterator();
} }
public boolean hasMember(String name) {
return (get(name) != null);
}
public Type memberType(String name) { public Type memberType(String name) {
return fetch(name).type(); return fetch(name).type();
} }

View File

@ -9,69 +9,24 @@ public abstract class Type {
public abstract long size(); public abstract long size();
public boolean isReferable() { public boolean isVoid() { return false; }
return false; public boolean isInt() { return false; }
} public boolean isInteger() { return false; }
public boolean isSigned()
public boolean isVoid() { { throw new Error("#isSigned for non-integer type"); }
return false; public boolean isNumeric() { return false; }
} public boolean isPointer() { return false; }
public boolean isArray() { return false; }
public boolean isInt() { public boolean isStruct() { return false; }
return false; public boolean isUnion() { return false; }
} public boolean isComplexType() { return false; }
public boolean isUserType() { return false; }
public boolean isInteger() { public boolean isFunction() { return false; }
return false; public boolean isCompatible(Type other) { return false; }
} public boolean isCastableTo(Type target) { return equals(target); }
public boolean isReferable() { return false; }
public boolean isSigned() { public boolean isCallable() { return false; }
throw new Error("#isSigned for non-integer type"); public boolean isIndexable() { return false; }
}
public boolean isNumeric() {
return false;
}
public boolean isPointer() {
return false;
}
public boolean isArray() {
return false;
}
public boolean isStruct() {
return false;
}
public boolean isUnion() {
return false;
}
public boolean isUserType() {
return false;
}
public boolean isFunction() {
return false;
}
public abstract String textize(); public abstract String textize();
public boolean isCompatible(Type other) {
return false;
}
public boolean isCastableTo(Type target) {
return equals(target);
}
public boolean isCallable() {
return false;
}
public boolean isIndexable() {
return false;
}
} }

10
test/struct-semcheck5.cb Normal file
View File

@ -0,0 +1,10 @@
struct a {
int x;
};
int main(int argc, char **argv)
{
struct a s;
s.x = 1;
return s.nosuchmember;
}

11
test/struct-semcheck6.cb Normal file
View File

@ -0,0 +1,11 @@
struct a {
int x;
};
int main(int argc, char **argv)
{
struct a s;
struct a *ptr = &s;
ptr->x = 1;
return ptr->nosuchmember;
}

View File

@ -122,12 +122,16 @@ assert_status 0 ./struct-semcheck
assert_error $CBC struct-semcheck2.cb assert_error $CBC struct-semcheck2.cb
assert_error $CBC struct-semcheck3.cb assert_error $CBC struct-semcheck3.cb
assert_error $CBC struct-semcheck4.cb assert_error $CBC struct-semcheck4.cb
assert_error $CBC struct-semcheck5.cb
assert_error $CBC struct-semcheck6.cb
assert_out "1;2;513" ./union # little endian assert_out "1;2;513" ./union # little endian
assert_status 0 ./union-semcheck assert_status 0 ./union-semcheck
assert_error $CBC union-semcheck2.cb assert_error $CBC union-semcheck2.cb
assert_error $CBC union-semcheck3.cb assert_error $CBC union-semcheck3.cb
assert_error $CBC union-semcheck4.cb assert_error $CBC union-semcheck4.cb
assert_error $CBC union-semcheck5.cb
assert_error $CBC union-semcheck6.cb
assert_out "5;5" ./pointer assert_out "5;5" ./pointer
assert_out "1;2" ./ptrmemb assert_out "1;2" ./ptrmemb

10
test/union-semcheck5.cb Normal file
View File

@ -0,0 +1,10 @@
union a {
int x;
};
int main(int argc, char **argv)
{
union a u;
u.x = 1;
return u.nosuchmember;
}

11
test/union-semcheck6.cb Normal file
View File

@ -0,0 +1,11 @@
union a {
int x;
};
int main(int argc, char **argv)
{
union a u;
union a* ptr = &u;
ptr->x = 1;
return ptr->nosuchmember;
}