Merge change 4067
* changes:
Improve symbol-related error checking
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index 60d1ddc..4af7f25 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -1312,6 +1312,12 @@
}
}
+ String& operator=(const String& other) {
+ clear();
+ appendBytes(other.getUnwrapped(), other.len());
+ return *this;
+ }
+
inline char* getUnwrapped() const {
return mpBase;
}
@@ -1439,6 +1445,12 @@
return result;
}
+ void forEach(bool (*callback)(String* key, V* value, void* context),
+ void* context) {
+ hashmapForEach(mpMap, (bool (*)(void*, void*, void*)) callback,
+ context);
+ }
+
protected:
void init(size_t initialCapacity) {
@@ -1670,11 +1682,21 @@
return addImp(0, pName);
}
+ void forEachGlobal(
+ bool (*callback)(String* key, VariableInfo* value, void* context),
+ void* context) {
+ mStack.get(0).pTable->forEach(callback, context);
+ }
+
private:
VariableInfo* addImp(int entryIndex, String* pName) {
Entry e = mStack.get(entryIndex);
SymbolTable* pTable = e.pTable;
+ if (pTable->contains(pName)) {
+ return NULL;
+ }
VariableInfo* v = new VariableInfo();
+
delete pTable->put(pName, v);
#if 0
fprintf(stderr, "Add \"%s\" %08x level %d\n", pName->getUnwrapped(), v, e.level);
@@ -2044,6 +2066,7 @@
void unary(intptr_t l) {
intptr_t n, t, a;
int c;
+ String tString;
t = 0;
n = 1; /* type of expression 0 = forward, 1 = value, other =
lvalue */
@@ -2063,6 +2086,7 @@
c = tokl;
a = tokc;
t = tok;
+ tString = mTokenString;
next();
if (t == TOK_NUM) {
pGen->li(a);
@@ -2112,14 +2136,15 @@
} else {
if (t == TOK_UNDEFINED_SYMBOL) {
t = (intptr_t) mSymbolTable.addGlobal(
- new String(mTokenString));
+ new String(tString));
}
- n = *(int *) t;
+ n = (intptr_t) ((VariableInfo*) t)->pAddress;
/* forward reference: try dlsym */
if (!n) {
n = (intptr_t) dlsym(RTLD_DEFAULT,
- mTokenString.getUnwrapped());
+ tString.getUnwrapped());
+ ((VariableInfo*) t)->pAddress = (void*) n;
}
if ((tok == '=') & l) {
/* assignment */
@@ -2128,6 +2153,9 @@
pGen->storeR0(n);
} else if (tok != '(') {
/* variable */
+ if (!n) {
+ error("Undefined variable %s", tString.getUnwrapped());
+ }
pGen->loadR0(n, tokl == 11, tokc);
if (tokl == 11) {
next();
@@ -2216,7 +2244,7 @@
return pGen->gtst(0, 0);
}
- void block(intptr_t l) {
+ void block(intptr_t l, bool outermostFunctionBlock) {
intptr_t a, n, t;
if (tok == TOK_IF) {
@@ -2224,12 +2252,12 @@
skip('(');
a = test_expr();
skip(')');
- block(l);
+ block(l, false);
if (tok == TOK_ELSE) {
next();
n = pGen->gjmp(0); /* jmp */
pGen->gsym(a);
- block(l);
+ block(l, false);
pGen->gsym(n); /* patch else jmp */
} else {
pGen->gsym(a); /* patch if test */
@@ -2259,18 +2287,22 @@
}
}
skip(')');
- block((intptr_t) &a);
+ block((intptr_t) &a, false);
pGen->gjmp(n - codeBuf.getPC() - pGen->jumpOffset()); /* jmp */
pGen->gsym(a);
} else if (tok == '{') {
- mSymbolTable.pushLevel();
+ if (! outermostFunctionBlock) {
+ mSymbolTable.pushLevel();
+ }
next();
/* declarations */
localDeclarations();
while (tok != '}' && tok != EOF)
- block(l);
+ block(l, false);
skip('}');
- mSymbolTable.popLevel();
+ if (! outermostFunctionBlock) {
+ mSymbolTable.popLevel();
+ }
} else {
if (tok == TOK_RETURN) {
next();
@@ -2350,18 +2382,22 @@
}
}
- void defineGlobalSymbol() {
- if (tok == TOK_UNDEFINED_SYMBOL) {
- // TODO: don't allow multiple definitions at same level.
- tok = (intptr_t) mSymbolTable.addGlobal(
- new String(mTokenString));
+ void addGlobalSymbol() {
+ tok = (intptr_t) mSymbolTable.addGlobal(
+ new String(mTokenString));
+ reportIfDuplicate();
+ }
+
+ void reportIfDuplicate() {
+ if (!tok) {
+ error("Duplicate definition of %s", mTokenString.getUnwrapped());
}
}
- void defineLocalSymbol() {
- // TODO: don't allow multiple definitions at same level.
+ void addLocalSymbol() {
tok = (intptr_t) mSymbolTable.addLocal(
new String(mTokenString));
+ reportIfDuplicate();
}
void localDeclarations() {
@@ -2371,10 +2407,11 @@
while (acceptType(base)) {
while (tok != ';') {
Type t = acceptPointerDeclaration(t);
- defineLocalSymbol();
- loc = loc + 4;
- *(int *) tok = -loc;
-
+ addLocalSymbol();
+ if (tok) {
+ loc = loc + 4;
+ *(int *) tok = -loc;
+ }
next();
if (tok == ',')
next();
@@ -2388,29 +2425,39 @@
Type base;
expectType(base);
Type t = acceptPointerDeclaration(t);
- defineGlobalSymbol();
+ if (tok == TOK_UNDEFINED_SYMBOL) {
+ addGlobalSymbol();
+ }
VariableInfo* name = (VariableInfo*) tok;
+ if (name && name->pAddress) {
+ error("Already defined global %s",
+ mTokenString.getUnwrapped());
+ }
next();
if (tok == ',' || tok == ';') {
// it's a variable declaration
for(;;) {
- name->pAddress = (int*) allocGlobalSpace(4);
+ if (name) {
+ name->pAddress = (int*) allocGlobalSpace(4);
+ }
if (tok != ',') {
break;
}
skip(',');
t = acceptPointerDeclaration(t);
- defineGlobalSymbol();
+ addGlobalSymbol();
name = (VariableInfo*) tok;
next();
}
skip(';');
} else {
- /* patch forward references (XXX: does not work for function
- pointers) */
- pGen->gsym((int) name->pForward);
- /* put function address */
- name->pAddress = (void*) codeBuf.getPC();
+ if (name) {
+ /* patch forward references (XXX: does not work for function
+ pointers) */
+ pGen->gsym((int) name->pForward);
+ /* put function address */
+ name->pAddress = (void*) codeBuf.getPC();
+ }
skip('(');
mSymbolTable.pushLevel();
intptr_t a = 8;
@@ -2419,10 +2466,12 @@
Type aType;
expectType(aType);
aType = acceptPointerDeclaration(aType);
- defineLocalSymbol();
- /* read param name and compute offset */
- *(int *) tok = a;
- a = a + 4;
+ addLocalSymbol();
+ if (tok) {
+ /* read param name and compute offset */
+ *(int *) tok = a;
+ a = a + 4;
+ }
next();
if (tok == ',')
next();
@@ -2431,7 +2480,7 @@
skip(')');
rsym = loc = 0;
a = pGen->functionEntry(argCount);
- block(0);
+ block(0, true);
pGen->gsym(rsym);
pGen->functionExit(argCount, a, loc);
mSymbolTable.popLevel();
@@ -2551,6 +2600,7 @@
inp();
next();
globalDeclarations();
+ checkForUndefinedForwardReferences();
result = pGen->finishCompile();
if (result == 0) {
if (mErrorBuf.len()) {
@@ -2560,6 +2610,27 @@
return result;
}
+ void checkForUndefinedForwardReferences() {
+ mSymbolTable.forEachGlobal(static_ufrcFn, this);
+ }
+
+ static bool static_ufrcFn(String* key, VariableInfo* value,
+ void* context) {
+ Compiler* pCompiler = (Compiler*) context;
+ return pCompiler->undefinedForwardReferenceCheck(key, value);
+ }
+
+ bool undefinedForwardReferenceCheck(String* key, VariableInfo* value) {
+#if 0
+ fprintf(stderr, "%s 0x%8x 0x%08x\n", key->getUnwrapped(),
+ value->pAddress, value->pForward);
+#endif
+ if (!value->pAddress && value->pForward) {
+ error("Undefined forward reference: %s", key->getUnwrapped());
+ }
+ return true;
+ }
+
int dump(FILE* out) {
fwrite(codeBuf.getBase(), 1, codeBuf.getSize(), out);
return 0;
diff --git a/libacc/tests/data/locals.c b/libacc/tests/data/locals.c
index 6982980..f1ef363 100644
--- a/libacc/tests/data/locals.c
+++ b/libacc/tests/data/locals.c
@@ -2,7 +2,9 @@
int f() {
int a;
- printf("f 0: a = %d b = %d\n", a, b);
+ // Undefined variable b
+ // printf("f 0: a = %d b = %d\n", a, b);
+ printf("f 0: a = %d\n", a);
a = 2;
printf("f 1: a = %d\n", a);
}
@@ -14,19 +16,23 @@
}
int h(int a) {
- int a; // gcc 4.3 says error: 'a' redeclared as different kind of symbol
+ // int a; // gcc 4.3 says error: 'a' redeclared as different kind of symbol
printf("h 0: a = %d\n", a);
a = 4;
printf("h 1: a = %d\n", a);
}
+// Already defined global
+// int h() {}
int globCheck() {
fprintf(stdout, "globCheck()\n");
}
int fwdCheck() {
b();
+ // Undefined forward reference
+ // c();
}
int b() {