diff --git a/src/shared/cplusplus/ASTVisitor.cpp b/src/shared/cplusplus/ASTVisitor.cpp
index 7b9ca1ed7faeb251e911a61803594198790a6bd2..d08d1c4d93d17a471c03f4c591d58ec4c9aa580e 100644
--- a/src/shared/cplusplus/ASTVisitor.cpp
+++ b/src/shared/cplusplus/ASTVisitor.cpp
@@ -77,12 +77,7 @@ int ASTVisitor::tokenKind(unsigned index) const
 { return translationUnit()->tokenKind(index); }
 
 const char *ASTVisitor::spell(unsigned index) const
-{
-    if (! index)
-        return 0;
-
-    return translationUnit()->tokenAt(index).spell();
-}
+{ return translationUnit()->spell(index); }
 
 Identifier *ASTVisitor::identifier(unsigned index) const
 { return translationUnit()->identifier(index); }
diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp
index f8ddde8b48e8b8162ba29888fafd067633dbcf79..038583c27d4bab26a0448e3548f0042953ac8cbf 100644
--- a/src/shared/cplusplus/CheckDeclaration.cpp
+++ b/src/shared/cplusplus/CheckDeclaration.cpp
@@ -389,6 +389,11 @@ bool CheckDeclaration::visit(UsingDirectiveAST *ast)
     UsingNamespaceDirective *u = control()->newUsingNamespaceDirective(ast->firstToken(), name);
     ast->symbol = u;
     _scope->enterSymbol(u);
+
+    if (! (_scope->isBlockScope() || _scope->isNamespaceScope()))
+        translationUnit()->error(ast->firstToken(),
+                                 "using-directive not within namespace or block scope");
+
     return false;
 }
 
diff --git a/src/shared/cplusplus/TranslationUnit.cpp b/src/shared/cplusplus/TranslationUnit.cpp
index 40a95c0f05d7f49860012e780ec2cc7ad75583f9..ebadf35c75a9d2cfaf485b4034838ae656bc0075 100644
--- a/src/shared/cplusplus/TranslationUnit.cpp
+++ b/src/shared/cplusplus/TranslationUnit.cpp
@@ -134,6 +134,14 @@ const Token &TranslationUnit::tokenAt(unsigned index) const
 int TranslationUnit::tokenKind(unsigned index) const
 { return _tokens->at(index).kind; }
 
+const char *TranslationUnit::spell(unsigned index) const
+{
+    if (! index)
+        return 0;
+
+    return _tokens->at(index).spell();
+}
+
 Identifier *TranslationUnit::identifier(unsigned index) const
 { return _tokens->at(index).identifier; }
 
diff --git a/src/shared/cplusplus/TranslationUnit.h b/src/shared/cplusplus/TranslationUnit.h
index aa490701ef9d01ab7ad6478571bd10e996e6c674..7a57950ac34078034cc5ef76b68d9a0d2a2e596b 100644
--- a/src/shared/cplusplus/TranslationUnit.h
+++ b/src/shared/cplusplus/TranslationUnit.h
@@ -87,6 +87,7 @@ public:
     unsigned tokenCount() const;
     const Token &tokenAt(unsigned index) const;
     int tokenKind(unsigned index) const;
+    const char *spell(unsigned index) const;
 
     unsigned matchingBrace(unsigned index) const;
     Identifier *identifier(unsigned index) const;
diff --git a/tests/manual/binding/main.cpp b/tests/manual/binding/main.cpp
index 8e889b6b514e2098da831e43ecb5f2bad20c4804..77aa298b0e09227e9e4c2e303551a7c46d903417 100644
--- a/tests/manual/binding/main.cpp
+++ b/tests/manual/binding/main.cpp
@@ -43,6 +43,8 @@
 #include <Symbols.h>
 #include <Literals.h>
 
+#include <vector>
+
 #include <cstdio>
 #include <cstdlib>
 #include <cassert>
@@ -79,6 +81,11 @@ public:
     /// Returns the binding associated with the given symbol.
     NamespaceBinding *findOrCreateNamespaceBinding(Namespace *symbol);
 
+    NamespaceBinding *resolveNamespace(QualifiedNameId *q, unsigned index,
+                                       unsigned count);
+
+    NamespaceBinding *resolveNamespace(Name *name, bool lookAtParent = true);
+
     /// Helpers.
     std::string qualifiedId() const;
     void dump();
@@ -96,6 +103,9 @@ public: // attributes
     /// This binding's connections.
     Array<NamespaceBinding *> children;
 
+    /// This binding's usings
+    Array<NamespaceBinding *> usings;
+
     /// This binding's namespace symbols.
     Array<Namespace *> symbols;
 };
@@ -211,6 +221,99 @@ NamespaceBinding *NamespaceBinding::findOrCreateNamespaceBinding(Namespace *symb
     return binding;
 }
 
+static void closure(NamespaceBinding *binding, Name *name,
+                    Array<NamespaceBinding *> *bindings)
+{
+    for (unsigned i = 0; i < bindings->size(); ++i) {
+        NamespaceBinding *b = bindings->at(i);
+
+        if (b == binding)
+            return;
+    }
+
+    bindings->push_back(binding);
+
+    assert(name->isNameId());
+
+    Identifier *id = name->asNameId()->identifier();
+    bool ignoreUsingDirectives = false;
+
+    for (unsigned i = 0; i < binding->symbols.size(); ++i) {
+        Namespace *symbol = binding->symbols.at(i);
+        Scope *scope = symbol->members();
+
+        for (Symbol *symbol = scope->lookat(id); symbol; symbol = symbol->next()) {
+            if (symbol->isUsingDeclaration() || symbol->isUsingNamespaceDirective())
+                continue;
+
+            //printf("found declaration at %s:%d\n", symbol->fileName(), symbol->line());
+
+            // ### FIXME: ignoreUsingDirectives = true;
+            break;
+        }
+    }
+
+    if (ignoreUsingDirectives)
+        return;
+
+    for (unsigned i = 0; i < binding->usings.size(); ++i) {
+        NamespaceBinding *u = binding->usings.at(i);
+
+        closure(u, name, bindings);
+    }
+}
+
+
+NamespaceBinding *NamespaceBinding::resolveNamespace(Name *name, bool lookAtParent)
+{
+    if (! name)
+        return 0;
+
+    else if (NameId *nameId = name->asNameId()) {
+        Array<NamespaceBinding *> bindings;
+        closure(this, nameId, &bindings);
+
+        Array<NamespaceBinding *> results;
+
+        for (unsigned i = 0; i < bindings.size(); ++i) {
+            NamespaceBinding *binding = bindings.at(i);
+
+            if (NamespaceBinding *b = binding->findNamespaceBinding(nameId))
+                results.push_back(b);
+        }
+
+        if (results.size() == 1)
+            return results.at(0);
+
+        else if (results.size() > 1) {
+            // ### FIXME: return 0;
+            return results.at(0);
+        }
+
+        else if (parent && lookAtParent)
+            return parent->resolveNamespace(name);
+
+    } else if (QualifiedNameId *q = name->asQualifiedNameId()) {
+        if (q->nameCount() == 1) {
+            assert(q->isGlobal());
+
+            return globalNamespaceBinding()->resolveNamespace(q->nameAt(0));
+        }
+
+        NamespaceBinding *current = this;
+        if (q->isGlobal())
+            current = globalNamespaceBinding();
+
+        current = current->resolveNamespace(q->nameAt(0));
+        for (unsigned i = 1; current && i < q->nameCount(); ++i)
+            current = current->resolveNamespace(q->nameAt(i), false);
+
+        return current;
+    }
+
+    return 0;
+}
+
 // ### rewrite me
 std::string NamespaceBinding::qualifiedId() const
 {
@@ -255,28 +358,38 @@ public:
     Binder();
     virtual ~Binder();
 
-    NamespaceBinding *operator()(Symbol *symbol)
-    { return bind(symbol, 0); }
+    NamespaceBinding *operator()(TranslationUnit *u, Namespace *globals)
+    {
+        TranslationUnit *previousUnit = unit;
+        unit = u;
+        NamespaceBinding *binding = bind(globals, 0);
+        unit = previousUnit;
+        return binding;
+    }
 
 protected:
     NamespaceBinding *bind(Symbol *symbol, NamespaceBinding *binding);
     NamespaceBinding *findOrCreateNamespaceBinding(Namespace *symbol);
+    NamespaceBinding *resolveNamespace(Name *name);
 
     NamespaceBinding *switchNamespaceBinding(NamespaceBinding *binding);
 
     using SymbolVisitor::visit;
 
     virtual bool visit(Namespace *);
+    virtual bool visit(UsingNamespaceDirective *);
     virtual bool visit(Class *);
     virtual bool visit(Function *);
     virtual bool visit(Block *);
 
 private:
     NamespaceBinding *namespaceBinding;
+    TranslationUnit *unit;
 };
 
 Binder::Binder()
-    : namespaceBinding(0)
+    : namespaceBinding(0),
+      unit(0)
 { }
 
 Binder::~Binder()
@@ -299,6 +412,15 @@ NamespaceBinding *Binder::findOrCreateNamespaceBinding(Namespace *symbol)
     return namespaceBinding;
 }
 
+NamespaceBinding *Binder::resolveNamespace(Name *name)
+{
+    if (! namespaceBinding)
+        return 0;
+
+    return namespaceBinding->resolveNamespace(name);
+}
+
+
 NamespaceBinding *Binder::switchNamespaceBinding(NamespaceBinding *binding)
 {
     NamespaceBinding *previousBinding = namespaceBinding;
@@ -319,6 +441,20 @@ bool Binder::visit(Namespace *symbol)
     return false;
 }
 
+bool Binder::visit(UsingNamespaceDirective *u)
+{
+    NamespaceBinding *resolved = resolveNamespace(u->name());
+
+    if (! resolved) {
+        unit->error(u->sourceLocation(), "expected namespace-name");
+        return false;
+    }
+
+    namespaceBinding->usings.push_back(resolved);
+
+    return false;
+}
+
 bool Binder::visit(Class *)
 { return false; }
 
@@ -376,7 +512,7 @@ int main(int argc, char *argv[])
 
     // bind
     Binder bind;
-    NamespaceBinding *binding = bind(globalNamespace);
+    NamespaceBinding *binding = bind(&unit, globalNamespace);
     binding->dump();
     delete binding;