Support function declarations in the definitions of other functions.
As part of this, function declarations are no longer scoped (this is permitted
by the C standard, as it turns out.) So code like:
void foo() { void bar(); }
void bat() { bar(); }
Compiles correctly; the declaration of bar() in foo() is still available in the
definition of bar().
Fixes issue #129.
This commit is contained in:
30
decl.cpp
30
decl.cpp
@@ -535,8 +535,6 @@ Declaration::GetVariableDeclarations() const {
|
||||
std::vector<VariableDeclaration> vars;
|
||||
|
||||
for (unsigned int i = 0; i < declarators.size(); ++i) {
|
||||
if (declarators[i] == NULL)
|
||||
continue;
|
||||
Declarator *decl = declarators[i];
|
||||
if (decl == NULL)
|
||||
// Ignore earlier errors
|
||||
@@ -545,11 +543,7 @@ Declaration::GetVariableDeclarations() const {
|
||||
Symbol *sym = decl->GetSymbol();
|
||||
sym->type = sym->type->ResolveUnboundVariability(Type::Varying);
|
||||
|
||||
if (dynamic_cast<const FunctionType *>(sym->type) != NULL) {
|
||||
// function declaration
|
||||
m->symbolTable->AddFunction(sym);
|
||||
}
|
||||
else {
|
||||
if (dynamic_cast<const FunctionType *>(sym->type) == NULL) {
|
||||
m->symbolTable->AddVariable(sym);
|
||||
vars.push_back(VariableDeclaration(sym, decl->initExpr));
|
||||
}
|
||||
@@ -558,6 +552,28 @@ Declaration::GetVariableDeclarations() const {
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Declaration::DeclareFunctions() {
|
||||
Assert(declSpecs->storageClass != SC_TYPEDEF);
|
||||
|
||||
for (unsigned int i = 0; i < declarators.size(); ++i) {
|
||||
Declarator *decl = declarators[i];
|
||||
if (decl == NULL)
|
||||
// Ignore earlier errors
|
||||
continue;
|
||||
|
||||
Symbol *sym = decl->GetSymbol();
|
||||
sym->type = sym->type->ResolveUnboundVariability(Type::Varying);
|
||||
|
||||
if (dynamic_cast<const FunctionType *>(sym->type) == NULL)
|
||||
continue;
|
||||
|
||||
bool isInline = (declSpecs->typeQualifiers & TYPEQUAL_INLINE);
|
||||
m->AddFunctionDeclaration(sym, isInline);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Declaration::Print(int indent) const {
|
||||
printf("%*cDeclaration: specs [", indent, ' ');
|
||||
|
||||
4
decl.h
4
decl.h
@@ -210,6 +210,10 @@ public:
|
||||
Declarator representation.) */
|
||||
std::vector<VariableDeclaration> GetVariableDeclarations() const;
|
||||
|
||||
/** For any function declarations in the Declaration, add the
|
||||
declaration to the module. */
|
||||
void DeclareFunctions();
|
||||
|
||||
DeclSpecs *declSpecs;
|
||||
std::vector<Declarator *> declarators;
|
||||
};
|
||||
|
||||
1
parse.yy
1
parse.yy
@@ -494,6 +494,7 @@ declaration_statement
|
||||
$$ = NULL;
|
||||
}
|
||||
else {
|
||||
$1->DeclareFunctions();
|
||||
std::vector<VariableDeclaration> vars = $1->GetVariableDeclarations();
|
||||
$$ = new DeclStmt(vars, @1);
|
||||
}
|
||||
|
||||
73
sym.cpp
73
sym.cpp
@@ -72,8 +72,7 @@ SymbolTable::SymbolTable() {
|
||||
|
||||
SymbolTable::~SymbolTable() {
|
||||
// Otherwise we have mismatched push/pop scopes
|
||||
Assert(variables.size() == 1 && functions.size() == 1 &&
|
||||
types.size() == 1);
|
||||
Assert(variables.size() == 1 && types.size() == 1);
|
||||
PopScope();
|
||||
}
|
||||
|
||||
@@ -81,7 +80,6 @@ SymbolTable::~SymbolTable() {
|
||||
void
|
||||
SymbolTable::PushScope() {
|
||||
variables.push_back(new SymbolMapType);
|
||||
functions.push_back(new FunctionMapType);
|
||||
types.push_back(new TypeMapType);
|
||||
}
|
||||
|
||||
@@ -92,10 +90,6 @@ SymbolTable::PopScope() {
|
||||
delete variables.back();
|
||||
variables.pop_back();
|
||||
|
||||
Assert(functions.size() > 1);
|
||||
delete functions.back();
|
||||
functions.pop_back();
|
||||
|
||||
Assert(types.size() > 1);
|
||||
delete types.back();
|
||||
types.pop_back();
|
||||
@@ -160,7 +154,7 @@ SymbolTable::AddFunction(Symbol *symbol) {
|
||||
// the symbol table
|
||||
return false;
|
||||
|
||||
std::vector<Symbol *> &funOverloads = (*functions.back())[symbol->name];
|
||||
std::vector<Symbol *> &funOverloads = functions[symbol->name];
|
||||
funOverloads.push_back(symbol);
|
||||
return true;
|
||||
}
|
||||
@@ -168,17 +162,14 @@ SymbolTable::AddFunction(Symbol *symbol) {
|
||||
|
||||
bool
|
||||
SymbolTable::LookupFunction(const char *name, std::vector<Symbol *> *matches) {
|
||||
for (int i = (int)functions.size() - 1; i >= 0; --i) {
|
||||
FunctionMapType &fm = *(functions[i]);
|
||||
FunctionMapType::iterator iter = fm.find(name);
|
||||
if (iter != fm.end()) {
|
||||
if (matches == NULL)
|
||||
return true;
|
||||
else {
|
||||
const std::vector<Symbol *> &funcs = iter->second;
|
||||
for (int j = 0; j < (int)funcs.size(); ++j)
|
||||
matches->push_back(funcs[j]);
|
||||
}
|
||||
FunctionMapType::iterator iter = functions.find(name);
|
||||
if (iter != functions.end()) {
|
||||
if (matches == NULL)
|
||||
return true;
|
||||
else {
|
||||
const std::vector<Symbol *> &funcs = iter->second;
|
||||
for (int j = 0; j < (int)funcs.size(); ++j)
|
||||
matches->push_back(funcs[j]);
|
||||
}
|
||||
}
|
||||
return matches ? (matches->size() > 0) : false;
|
||||
@@ -187,15 +178,12 @@ SymbolTable::LookupFunction(const char *name, std::vector<Symbol *> *matches) {
|
||||
|
||||
Symbol *
|
||||
SymbolTable::LookupFunction(const char *name, const FunctionType *type) {
|
||||
for (int i = (int)functions.size() - 1; i >= 0; --i) {
|
||||
FunctionMapType &fm = *(functions[i]);
|
||||
FunctionMapType::iterator iter = fm.find(name);
|
||||
if (iter != fm.end()) {
|
||||
std::vector<Symbol *> funcs = iter->second;
|
||||
for (int j = 0; j < (int)funcs.size(); ++j) {
|
||||
if (Type::Equal(funcs[j]->type, type))
|
||||
return funcs[j];
|
||||
}
|
||||
FunctionMapType::iterator iter = functions.find(name);
|
||||
if (iter != functions.end()) {
|
||||
std::vector<Symbol *> funcs = iter->second;
|
||||
for (int j = 0; j < (int)funcs.size(); ++j) {
|
||||
if (Type::Equal(funcs[j]->type, type))
|
||||
return funcs[j];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@@ -261,14 +249,11 @@ SymbolTable::ClosestVariableOrFunctionMatch(const char *str) const {
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)functions.size(); ++i) {
|
||||
const FunctionMapType &fm = *(functions[i]);
|
||||
FunctionMapType::const_iterator iter;
|
||||
for (iter = fm.begin(); iter != fm.end(); ++iter) {
|
||||
int dist = StringEditDistance(str, iter->first, maxDelta+1);
|
||||
if (dist <= maxDelta)
|
||||
matches[dist].push_back(iter->first);
|
||||
}
|
||||
FunctionMapType::const_iterator iter;
|
||||
for (iter = functions.begin(); iter != functions.end(); ++iter) {
|
||||
int dist = StringEditDistance(str, iter->first, maxDelta+1);
|
||||
if (dist <= maxDelta)
|
||||
matches[dist].push_back(iter->first);
|
||||
}
|
||||
|
||||
// Now, return the first entry of matches[] that is non-empty, if any.
|
||||
@@ -346,15 +331,13 @@ SymbolTable::Print() {
|
||||
}
|
||||
|
||||
fprintf(stderr, "Functions:\n----------------\n");
|
||||
for (int i = 0; i < (int)functions.size(); ++i) {
|
||||
FunctionMapType::iterator fiter = functions[i]->begin();
|
||||
while (fiter != functions[i]->end()) {
|
||||
fprintf(stderr, "%s\n", fiter->first.c_str());
|
||||
std::vector<Symbol *> &syms = fiter->second;
|
||||
for (unsigned int j = 0; j < syms.size(); ++j)
|
||||
fprintf(stderr, " %s\n", syms[j]->type->GetString().c_str());
|
||||
++fiter;
|
||||
}
|
||||
FunctionMapType::iterator fiter = functions.begin();
|
||||
while (fiter != functions.end()) {
|
||||
fprintf(stderr, "%s\n", fiter->first.c_str());
|
||||
std::vector<Symbol *> &syms = fiter->second;
|
||||
for (unsigned int j = 0; j < syms.size(); ++j)
|
||||
fprintf(stderr, " %s\n", syms[j]->type->GetString().c_str());
|
||||
++fiter;
|
||||
}
|
||||
|
||||
depth = 0;
|
||||
|
||||
26
sym.h
26
sym.h
@@ -257,12 +257,13 @@ private:
|
||||
typedef std::map<std::string, Symbol *> SymbolMapType;
|
||||
std::vector<SymbolMapType *> variables;
|
||||
|
||||
/** Function declarations are also scoped., A STL \c vector is used to
|
||||
store the function symbols for a given name since, due to function
|
||||
overloading, a name can have multiple function symbols associated
|
||||
with it. */
|
||||
/** Function declarations are *not* scoped. (C99, for example, allows
|
||||
an implementation to maintain function declarations in a single
|
||||
namespace.) A STL \c vector is used to store the function symbols
|
||||
for a given name since, due to function overloading, a name can
|
||||
have multiple function symbols associated with it. */
|
||||
typedef std::map<std::string, std::vector<Symbol *> > FunctionMapType;
|
||||
std::vector<FunctionMapType *> functions;
|
||||
FunctionMapType functions;
|
||||
|
||||
/** Type definitions can also be scoped. A new \c TypeMapType
|
||||
is added to the back of the \c types \c vector each time a new scope
|
||||
@@ -278,15 +279,12 @@ SymbolTable::GetMatchingFunctions(Predicate pred,
|
||||
std::vector<Symbol *> *matches) const {
|
||||
// Iterate through all function symbols and apply the given predicate.
|
||||
// If it returns true, add the Symbol * to the provided vector.
|
||||
for (unsigned int i = 0; i < functions.size(); ++i) {
|
||||
FunctionMapType &fm = *(functions[i]);
|
||||
FunctionMapType::const_iterator iter;
|
||||
for (iter = fm.begin(); iter != fm.end(); ++iter) {
|
||||
const std::vector<Symbol *> &syms = iter->second;
|
||||
for (unsigned int j = 0; j < syms.size(); ++j) {
|
||||
if (pred(syms[j]))
|
||||
matches->push_back(syms[j]);
|
||||
}
|
||||
FunctionMapType::const_iterator iter;
|
||||
for (iter = functions.begin(); iter != functions.end(); ++iter) {
|
||||
const std::vector<Symbol *> &syms = iter->second;
|
||||
for (unsigned int j = 0; j < syms.size(); ++j) {
|
||||
if (pred(syms[j]))
|
||||
matches->push_back(syms[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user