r290072 - Fix name hiding and redeclaration checking for dependent local

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Sun Dec 18 14:01:46 PST 2016


Author: rsmith
Date: Sun Dec 18 16:01:46 2016
New Revision: 290072

URL: http://llvm.org/viewvc/llvm-project?rev=290072&view=rev
Log:
Fix name hiding and redeclaration checking for dependent local
using-declarations.

Modified:
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=290072&r1=290071&r2=290072&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Dec 18 16:01:46 2016
@@ -9247,6 +9247,8 @@ bool Sema::CheckUsingDeclRedeclaration(S
                                        const CXXScopeSpec &SS,
                                        SourceLocation NameLoc,
                                        const LookupResult &Prev) {
+  NestedNameSpecifier *Qual = SS.getScopeRep();
+
   // C++03 [namespace.udecl]p8:
   // C++0x [namespace.udecl]p10:
   //   A using-declaration is a declaration and can therefore be used
@@ -9254,10 +9256,28 @@ bool Sema::CheckUsingDeclRedeclaration(S
   //   allowed.
   //
   // That's in non-member contexts.
-  if (!CurContext->getRedeclContext()->isRecord())
+  if (!CurContext->getRedeclContext()->isRecord()) {
+    // A dependent qualifier outside a class can only ever resolve to an
+    // enumeration type. Therefore it conflicts with any other non-type
+    // declaration in the same scope.
+    // FIXME: How should we check for dependent type-type conflicts at block
+    // scope?
+    if (Qual->isDependent() && !HasTypenameKeyword) {
+      for (auto *D : Prev) {
+        if (!isa<TypeDecl>(D) && !isa<UsingDecl>(D)) {
+          bool OldCouldBeEnumerator =
+              isa<UnresolvedUsingValueDecl>(D) || isa<EnumConstantDecl>(D);
+          Diag(NameLoc,
+               OldCouldBeEnumerator ? diag::err_redefinition
+                                    : diag::err_redefinition_different_kind)
+              << Prev.getLookupName();
+          Diag(D->getLocation(), diag::note_previous_definition);
+          return true;
+        }
+      }
+    }
     return false;
-
-  NestedNameSpecifier *Qual = SS.getScopeRep();
+  }
 
   for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) {
     NamedDecl *D = *I;
@@ -9275,19 +9295,7 @@ bool Sema::CheckUsingDeclRedeclaration(S
                  = dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
       DTypename = true;
       DQual = UD->getQualifier();
-    } else if (!isa<TypeDecl>(D) && Qual->isDependent() &&
-               !HasTypenameKeyword) {
-      // A dependent qualifier outside a class can only ever resolve to an
-      // enumeration type. Therefore it conflicts with any other non-type
-      // declaration in the same scope.
-      // FIXME: How should we check for dependent type-type conflicts at block
-      // scope?
-      Diag(NameLoc, diag::err_redefinition_different_kind)
-          << Prev.getLookupName();
-      Diag(D->getLocation(), diag::note_previous_definition);
-      return true;
-    }
-    else continue;
+    } else continue;
 
     // using decls differ if one says 'typename' and the other doesn't.
     // FIXME: non-dependent using decls?

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=290072&r1=290071&r2=290072&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Sun Dec 18 16:01:46 2016
@@ -450,15 +450,18 @@ static bool canHideTag(NamedDecl *D) {
   //   Given a set of declarations in a single declarative region [...]
   //   exactly one declaration shall declare a class name or enumeration name
   //   that is not a typedef name and the other declarations shall all refer to
-  //   the same variable or enumerator, or all refer to functions and function
-  //   templates; in this case the class name or enumeration name is hidden.
+  //   the same variable, non-static data member, or enumerator, or all refer
+  //   to functions and function templates; in this case the class name or
+  //   enumeration name is hidden.
   // C++ [basic.scope.hiding]p2:
   //   A class name or enumeration name can be hidden by the name of a
   //   variable, data member, function, or enumerator declared in the same
   //   scope.
+  // An UnresolvedUsingValueDecl always instantiates to one of these.
   D = D->getUnderlyingDecl();
   return isa<VarDecl>(D) || isa<EnumConstantDecl>(D) || isa<FunctionDecl>(D) ||
-         isa<FunctionTemplateDecl>(D) || isa<FieldDecl>(D);
+         isa<FunctionTemplateDecl>(D) || isa<FieldDecl>(D) ||
+         isa<UnresolvedUsingValueDecl>(D);
 }
 
 /// Resolves the result kind of this lookup.

Modified: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp?rev=290072&r1=290071&r2=290072&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp Sun Dec 18 16:01:46 2016
@@ -87,12 +87,12 @@ namespace PR21933 {
     extern int a(); // expected-error {{different kind of symbol}}
     a();
 
-    extern int b();
-    using T::b;
+    extern int b(); // expected-note {{previous}}
+    using T::b; // expected-error {{different kind of symbol}}
     b();
 
-    using T::c;
-    using U::c;
+    using T::c; // expected-note {{previous}}
+    using U::c; // expected-error-re {{redefinition of 'c'{{$}}}}
     c();
   }
 
@@ -101,29 +101,28 @@ namespace PR21933 {
     typedef struct {} Xt; // expected-error {{different kind of symbol}}
     (void)Xt;
 
-    using T::Xs; // expected-note {{candidate}}
-    struct Xs {}; // expected-note {{candidate}}
-    // FIXME: This is wrong, the using declaration hides the type.
-    Xs xs; // expected-error {{ambiguous}}
-
-    using T::Xe; // expected-note {{candidate}}
-    enum Xe {}; // expected-note {{candidate}}
-    // FIXME: This is wrong, the using declaration hides the type.
-    Xe xe; // expected-error {{ambiguous}}
+    using T::Xs; // expected-note {{hidden by}}
+    struct Xs {};
+    (void)Xs;
+    Xs xs; // expected-error {{must use 'struct'}}
+
+    using T::Xe; // expected-note {{hidden by}}
+    enum Xe {};
+    (void)Xe;
+    Xe xe; // expected-error {{must use 'enum'}}
 
     typedef struct {} Yt; // expected-note {{candidate}}
     using T::Yt; // eypected-error {{different kind of symbol}} expected-note {{candidate}}
     Yt yt; // expected-error {{ambiguous}}
 
-    struct Ys {}; // expected-note {{candidate}}
-    using T::Ys; // expected-note {{candidate}}
-    // FIXME: This is wrong, the using declaration hides the type.
-    Ys ys; // expected-error {{ambiguous}}
-
-    enum Ye {}; // expected-note {{candidate}}
-    using T::Ye; // expected-note {{candidate}}
-    // FIXME: This is wrong, the using declaration hides the type.
-    Ye ye; // expected-error {{ambiguous}}
+    struct Ys {};
+    using T::Ys; // expected-note {{hidden by}}
+    (void)Ys;
+    Ys ys; // expected-error {{must use 'struct'}}
+
+    enum Ye {};
+    using T::Ye; // expected-note {{hidden by}}
+    Ye ye; // expected-error {{must use 'enum'}}
   }
 
   template<typename T> void type() {




More information about the cfe-commits mailing list