Hi again,

On 08/22/2012 05:13 PM, Jason Merrill wrote:
On 08/22/2012 10:55 AM, Paolo Carlini wrote:
. thus, in short, what is happening is that, for this testcase:

class B
{
protected:
   enum E { E1, E2, E3 };
};

class D : private B
{
public:
   using B::E;

private:
   enum E { };
};

we parse the new declaration enum E { }; and we reach
supplement_binding_1 before setting the underlying type of the new
declaration. The old declaration is fine, would not ICE dependent_type_p.

So with your change would we still ICE if D were a template? It seems like what we should be checking for is null underlying type.
Good question ;) Yesterday night I double checked with this:

template<typename T>
class BT
{
protected:
  enum E { E1, E2, E3 };
  struct S { int i; E e; };
};

template<typename T>
class DT : private BT<T>
{
public:
  using BT<T>::E;
  using BT<T>::S;

private:
  enum E {};
  struct S {};
};

template class DT<int>;

and we handle it correctly (note: we error out *only* at instantiation time).

At this point, let me know, I could either add to the testcase a templated variant like the above (see attached), or rework the code to explicitly check the underlying type (I would add locals hosting the TREE_TYPEs to shorten a bit things, etc).

The below passes testing, anyway.

Thanks,
Paolo.

///////////////////////
Index: testsuite/g++.dg/lookup/using53.C
===================================================================
--- testsuite/g++.dg/lookup/using53.C   (revision 0)
+++ testsuite/g++.dg/lookup/using53.C   (revision 0)
@@ -0,0 +1,53 @@
+// PR c++/20420
+
+class B
+{
+protected:
+  enum E { E1, E2, E3 };
+  struct S { int i; E e; };
+};
+
+class D : private B
+{
+public:
+  using B::E;       // { dg-message "previous" }
+  using B::S;       // { dg-message "previous" }
+
+private:
+  enum E {};        // { dg-error "conflicts" }
+  struct S {};      // { dg-error "conflicts" }
+};
+
+template<typename T>
+class BT
+{
+protected:
+  enum E { E1, E2, E3 };
+  struct S { int i; E e; };
+};
+
+template<typename T>
+class DT : private BT<T>
+{
+public:
+  using BT<T>::E;   // { dg-message "previous" }
+  using BT<T>::S;   // { dg-message "previous" }
+
+private:
+  enum E {};        // { dg-error "conflicts" }
+  struct S {};      // { dg-error "conflicts" }
+};
+
+template class DT<int>;
+
+namespace N
+{
+  int i;
+}
+
+void
+f ()
+{
+  using N::i;
+  using N::i;       // { dg-error "declared" }
+}
Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c    (revision 190590)
+++ cp/name-lookup.c    (working copy)
@@ -441,7 +441,8 @@ supplement_binding_1 (cxx_binding *binding, tree d
             template in order to handle late matching of underlying
             type on an opaque-enum-declaration followed by an
             enum-specifier.  */
-         || (TREE_CODE (TREE_TYPE (target_decl)) == ENUMERAL_TYPE
+         || (processing_template_decl
+             && TREE_CODE (TREE_TYPE (target_decl)) == ENUMERAL_TYPE
              && TREE_CODE (TREE_TYPE (target_bval)) == ENUMERAL_TYPE
              && (dependent_type_p (ENUM_UNDERLYING_TYPE
                                    (TREE_TYPE (target_decl)))
@@ -2420,7 +2421,15 @@ validate_nonmember_using_decl (tree decl, tree sco
   gcc_assert (DECL_P (decl));
 
   /* Make a USING_DECL.  */
-  return push_using_decl (scope, name);
+  tree using_decl = push_using_decl (scope, name);
+
+  if (using_decl == NULL_TREE
+      && at_function_scope_p ()
+      && TREE_CODE (decl) == VAR_DECL)
+    /* C++11 7.3.3/10.  */
+    error ("%qD is already declared in this scope", name);
+  
+  return using_decl;
 }
 
 /* Process local and global using-declarations.  */

Reply via email to