]> granicus.if.org Git - clang/commitdiff
PR25731: namespace alias declarations can appear at block scope; ensure that we
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 3 Dec 2015 23:24:04 +0000 (23:24 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 3 Dec 2015 23:24:04 +0000 (23:24 +0000)
do scope-based lookup when looking for redeclarations of them. Add some related
missing checks for the scope-based redeclaration lookup: properly filter the
list of found declarations to match the scope, and diagnose shadowing of a
template parameter name.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@254663 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
test/CXX/temp/temp.res/temp.local/p6.cpp
test/SemaCXX/namespace-alias.cpp

index eb010e9e39a93b16b18748c8f06944053ae1a0ea..3745641eb01b01defd9e3dc2d81fb574b20e63ca 100644 (file)
@@ -8682,29 +8682,39 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
     }
   }
   assert(!R.isAmbiguous() && !R.empty());
+  NamedDecl *ND = R.getFoundDecl();
 
   // Check if we have a previous declaration with the same name.
   LookupResult PrevR(*this, Alias, AliasLoc, LookupOrdinaryName,
                      ForRedeclaration);
-  LookupQualifiedName(PrevR, CurContext->getRedeclContext());
-  NamedDecl *PrevDecl = PrevR.getAsSingle<NamedDecl>();
-  if (PrevDecl && !isVisible(PrevDecl))
-    PrevDecl = nullptr;
+  LookupName(PrevR, S);
 
-  NamedDecl *ND = R.getFoundDecl();
+  // Check we're not shadowing a template parameter.
+  if (PrevR.isSingleResult() && PrevR.getFoundDecl()->isTemplateParameter()) {
+    DiagnoseTemplateParameterShadow(AliasLoc, PrevR.getFoundDecl());
+    PrevR.clear();
+  }
+
+  // Filter out any other lookup result from an enclosing scope.
+  FilterLookupForScope(PrevR, CurContext, S, /*ConsiderLinkage*/false,
+                       /*AllowInlineNamespace*/false);
 
-  if (PrevDecl) {
+  // Find the previous declaration and check that we can redeclare it.
+  NamespaceAliasDecl *Prev = nullptr; 
+  if (NamedDecl *PrevDecl = PrevR.getAsSingle<NamedDecl>()) {
     if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) {
       // We already have an alias with the same name that points to the same
       // namespace; check that it matches.
-      if (!AD->getNamespace()->Equals(getNamespaceDecl(ND))) {
+      if (AD->getNamespace()->Equals(getNamespaceDecl(ND))) {
+        Prev = AD;
+      } else if (isVisible(PrevDecl)) {
         Diag(AliasLoc, diag::err_redefinition_different_namespace_alias)
           << Alias;
         Diag(PrevDecl->getLocation(), diag::note_previous_namespace_alias)
           << AD->getNamespace();
         return nullptr;
       }
-    } else {
+    } else if (isVisible(PrevDecl)) {
       unsigned DiagID = isa<NamespaceDecl>(PrevDecl)
                             ? diag::err_redefinition
                             : diag::err_redefinition_different_kind;
@@ -8721,8 +8731,8 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
     NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc,
                                Alias, SS.getWithLocInContext(Context),
                                IdentLoc, ND);
-  if (PrevDecl)
-    AliasDecl->setPreviousDecl(cast<NamespaceAliasDecl>(PrevDecl));
+  if (Prev)
+    AliasDecl->setPreviousDecl(Prev);
 
   PushOnScopeChains(AliasDecl, S);
   return AliasDecl;
index eccbb8993213b8b51139159ad3ca99464ec1b097..06eb1bef7fea2e9537f85aae2a55dd3b4c22b3eb 100644 (file)
@@ -1,9 +1,11 @@
 // RUN: %clang_cc1 -verify %s -fcxx-exceptions -std=c++1y
 
+namespace N {}
+
 template<typename T, // expected-note {{declared here}}
          typename T> struct X {}; // expected-error {{declaration of 'T' shadows template parameter}}
 
-template<typename T> struct Y { // expected-note 15{{declared here}}
+template<typename T> struct Y { // expected-note 16{{declared here}}
   template<typename T> struct A {}; // expected-error {{declaration of 'T' shadows template parameter}}
 
   struct B {
@@ -50,6 +52,9 @@ template<typename T> struct Y { // expected-note 15{{declared here}}
   void d() {
     void T(); // expected-error {{declaration of 'T' shadows template parameter}}
   }
+  void e() {
+    namespace T = N; // expected-error {{declaration of 'T' shadows template parameter}}
+  }
 
   friend struct T; // expected-error {{declaration of 'T' shadows template parameter}}
 };
index 63615ecbd352e626b324b594bc1b62ba7e36ecab..1cf820e3e38d8a3a1faec979dc959ad4addc58e7 100644 (file)
@@ -125,3 +125,11 @@ namespace PR7014 {
 
   namespace Y = X::Y;
 }
+
+namespace PR25731 {
+  void f() {
+    namespace X = PR25731;
+    namespace X = PR25731;
+    X::f();
+  }
+}