Support local namespace aliases and permit them to be instantiated.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96335 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 06f8afc..0978c6d 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -1628,6 +1628,16 @@
     return const_cast<NamespaceAliasDecl*>(this)->getNamespace();
   }
 
+  /// Returns the location of the alias name, i.e. 'foo' in
+  /// "namespace foo = ns::bar;".
+  SourceLocation getAliasLoc() const { return AliasLoc; }
+
+  /// Returns the location of the 'namespace' keyword.
+  SourceLocation getNamespaceLoc() const { return getLocation(); }
+
+  /// Returns the location of the identifier in the named namespace.
+  SourceLocation getTargetNameLoc() const { return IdentLoc; }
+
   /// \brief Retrieve the namespace that this alias refers to, which
   /// may either be a NamespaceDecl or a NamespaceAliasDecl.
   NamedDecl *getAliasedNamespace() const { return Namespace; }
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index d47758d..9defcca 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -3691,7 +3691,7 @@
                                (NestedNameSpecifier *)SS.getScopeRep(),
                                IdentLoc, R.getFoundDecl());
 
-  CurContext->addDecl(AliasDecl);
+  PushOnScopeChains(AliasDecl, S);
   return DeclPtrTy::make(AliasDecl);
 }
 
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index a55193a..0b0efcb 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -43,6 +43,7 @@
     // clang/AST/DeclNodes.def.
     Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
     Decl *VisitNamespaceDecl(NamespaceDecl *D);
+    Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
     Decl *VisitTypedefDecl(TypedefDecl *D);
     Decl *VisitVarDecl(VarDecl *D);
     Decl *VisitFieldDecl(FieldDecl *D);
@@ -126,6 +127,21 @@
   return D;
 }
 
+Decl *
+TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+  NamespaceAliasDecl *Inst
+    = NamespaceAliasDecl::Create(SemaRef.Context, Owner,
+                                 D->getNamespaceLoc(),
+                                 D->getAliasLoc(),
+                                 D->getNamespace()->getIdentifier(),
+                                 D->getQualifierRange(),
+                                 D->getQualifier(),
+                                 D->getTargetNameLoc(),
+                                 D->getNamespace());
+  Owner->addDecl(Inst);
+  return Inst;
+}
+
 Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
   bool Invalid = false;
   TypeSourceInfo *DI = D->getTypeSourceInfo();
diff --git a/test/SemaCXX/namespace-alias.cpp b/test/SemaCXX/namespace-alias.cpp
index f983606..06114c3 100644
--- a/test/SemaCXX/namespace-alias.cpp
+++ b/test/SemaCXX/namespace-alias.cpp
@@ -62,3 +62,24 @@
     func();
   }
 }
+
+namespace K {
+  namespace KA { void func(); }
+
+  void f() {
+    namespace KB = KA;
+    KB::func();
+  }
+
+  template <class T> void g() {
+    namespace KC = KA;
+    KC::func();
+  }
+  template void g<int>();
+  template void g<long>();
+
+  void h() {
+    KB::func(); // expected-error {{undeclared identifier 'KB'}}
+    KC::func(); // expected-error {{undeclared identifier 'KC'}}
+  }
+}