* 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>
* net/loveruby/cflat/compiler/TypeChecker.java: check aref base

19
ToDo
View File

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

View File

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

View File

@ -74,6 +74,7 @@ public class LocalReferenceResolver extends Visitor {
public void visit(BlockNode node) {
pushScope(node.variables());
resolveInitializers(node.variables());
super.visit(node);
node.setScope(popScope());
}
@ -100,6 +101,15 @@ public class LocalReferenceResolver extends Visitor {
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) {
node.setEntry(constantTable.intern(node.value()));
}

View File

@ -320,19 +320,39 @@ class TypeChecker extends Visitor {
}
public void visit(MemberNode node) {
super.visit(node);
// FIXME: validate member here?
resolve(node.expr());
checkMemberRef(node.expr().type(), node.name());
}
public void visit(PtrMemberNode node) {
super.visit(node);
// FIXME: validate member here?
resolve(node.expr());
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) {
super.visit(node);
if (node.type().isPointer()) return;
notPointerError(node.type());
if (! node.expr().type().isPointer()) {
notPointerError(node.type());
return;
}
}
public void visit(AddressNode node) {

View File

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

View File

@ -9,69 +9,24 @@ public abstract class Type {
public abstract long size();
public boolean isReferable() {
return false;
}
public boolean isVoid() {
return false;
}
public boolean isInt() {
return false;
}
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;
}
public boolean isUnion() {
return false;
}
public boolean isUserType() {
return false;
}
public boolean isFunction() {
return false;
}
public boolean isVoid() { return false; }
public boolean isInt() { return false; }
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; }
public boolean isUnion() { return false; }
public boolean isComplexType() { return false; }
public boolean isUserType() { return false; }
public boolean isFunction() { return false; }
public boolean isCompatible(Type other) { return false; }
public boolean isCastableTo(Type target) { return equals(target); }
public boolean isReferable() { return false; }
public boolean isCallable() { return false; }
public boolean isIndexable() { return false; }
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-semcheck3.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_status 0 ./union-semcheck
assert_error $CBC union-semcheck2.cb
assert_error $CBC union-semcheck3.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 "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;
}