Commit b7820022 authored by Roberto Raggi's avatar Roberto Raggi

Warn for undefined namespaces in using namespace directives.

parent 19dd2b81
......@@ -567,6 +567,32 @@ bool Binder::visit(Block *)
} // end of anonymous namespace
static NamespaceBinding *find_helper(Namespace *symbol, NamespaceBinding *binding,
QSet<QByteArray> *processed)
{
const QByteArray id = binding->qualifiedId();
if (! processed->contains(id)) {
processed->insert(id);
if (binding->symbols.contains(symbol))
return binding;
foreach (NamespaceBinding *nestedBinding, binding->children) {
if (NamespaceBinding *ns = find_helper(symbol, nestedBinding, processed))
return ns;
}
}
return 0;
}
NamespaceBinding *NamespaceBinding::find(Namespace *symbol, NamespaceBinding *binding)
{
QSet<QByteArray> processed;
return find_helper(symbol, binding, &processed);
}
NamespaceBindingPtr CPlusPlus::bind(Document::Ptr doc, Snapshot snapshot)
{
NamespaceBindingPtr global(new NamespaceBinding());
......
......@@ -118,6 +118,8 @@ public:
virtual NamespaceBinding *asNamespaceBinding() { return this; }
static NamespaceBinding *find(Namespace *symbol, NamespaceBinding *binding);
private:
NamespaceBinding *findNamespaceBindingForNameId(NameId *name);
......
......@@ -252,13 +252,16 @@ namespace {
class Process;
class CheckUndefinedBaseClasses: protected ASTVisitor
class CheckUndefinedSymbols: protected ASTVisitor
{
public:
CheckUndefinedBaseClasses(Control *control)
: ASTVisitor(control), _context(0)
CheckUndefinedSymbols(Document::Ptr doc)
: ASTVisitor(doc->control()), _process(0), _doc(doc)
{ }
void setGlobalNamespaceBinding(NamespaceBindingPtr globalNamespaceBinding)
{ _globalNamespaceBinding = globalNamespaceBinding; }
void operator()(AST *ast, Process *process)
{ _process = process; accept(ast); }
......@@ -290,6 +293,26 @@ protected:
"expected class-name %s token", token);
}
}
return true;
}
virtual bool visit(UsingDirectiveAST *ast)
{
if (ast->name && ast->name->name && _globalNamespaceBinding) {
const Location loc = Location(ast->symbol);
NamespaceBinding *binding = _globalNamespaceBinding.data();
if (Scope *enclosingNamespaceScope = ast->symbol->enclosingNamespaceScope())
binding = NamespaceBinding::find(enclosingNamespaceScope->owner()->asNamespace(), binding);
if (! binding || ! binding->resolveNamespace(loc, ast->name->name)) {
translationUnit()->warning(ast->name->firstToken(),
"expected a namespace after `=' token");
}
}
return true;
}
......@@ -297,7 +320,9 @@ protected:
private:
Process *_process;
Document::Ptr _doc;
LookupContext _context;
NamespaceBindingPtr _globalNamespaceBinding;
};
class Process: public std::unary_function<Document::Ptr, void>
......@@ -334,12 +359,12 @@ public:
if (_workingCopy.contains(doc->fileName())) {
// run the binding pass
NamespaceBindingPtr ns = bind(doc, _snapshot);
Q_UNUSED(ns);
// check for undefined symbols.
CheckUndefinedSymbols checkUndefinedSymbols(doc);
checkUndefinedSymbols.setGlobalNamespaceBinding(ns);
CheckUndefinedBaseClasses checkUndefinedBaseClasses(doc->control());
checkUndefinedBaseClasses(doc->translationUnit()->ast(), this);
checkUndefinedSymbols(doc->translationUnit()->ast(), this);
}
doc->releaseTranslationUnit();
......@@ -349,7 +374,7 @@ public:
}
};
LookupContext CheckUndefinedBaseClasses::lookupContext(unsigned line, unsigned column) const
LookupContext CheckUndefinedSymbols::lookupContext(unsigned line, unsigned column) const
{ return _process->lookupContext(line, column); }
} // end of anonymous namespace
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment