diff --git a/src/libs/cplusplus/CppBindings.cpp b/src/libs/cplusplus/CppBindings.cpp index 722db83460d..769eaddfdfb 100644 --- a/src/libs/cplusplus/CppBindings.cpp +++ b/src/libs/cplusplus/CppBindings.cpp @@ -567,6 +567,32 @@ bool Binder::visit(Block *) } // end of anonymous namespace +static NamespaceBinding *find_helper(Namespace *symbol, NamespaceBinding *binding, + QSet *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 processed; + return find_helper(symbol, binding, &processed); +} + NamespaceBindingPtr CPlusPlus::bind(Document::Ptr doc, Snapshot snapshot) { NamespaceBindingPtr global(new NamespaceBinding()); diff --git a/src/libs/cplusplus/CppBindings.h b/src/libs/cplusplus/CppBindings.h index 24b308cee77..ed34461b1a8 100644 --- a/src/libs/cplusplus/CppBindings.h +++ b/src/libs/cplusplus/CppBindings.h @@ -118,6 +118,8 @@ public: virtual NamespaceBinding *asNamespaceBinding() { return this; } + static NamespaceBinding *find(Namespace *symbol, NamespaceBinding *binding); + private: NamespaceBinding *findNamespaceBindingForNameId(NameId *name); diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 0451b930e50..0927486d44f 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -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 @@ -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