diff mbox

C++ PATCH for c++/56323 (rejects valid inheriting constructors)

Message ID 511D681C.4060106@redhat.com
State New
Headers show

Commit Message

Jason Merrill Feb. 14, 2013, 10:41 p.m. UTC
The standard says that using X::X always means inheriting constructors, 
even if X is a typedef.  In templates, we also need to support this 
usage for template template parameters, not just type parameters.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit 2b5203157486e00788228c2fe8572b5bbf4b555a
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Feb 14 11:40:28 2013 -0500

    	PR c++/56323
    	* name-lookup.c (do_class_using_decl): Handle typedefs with
    	inheriting constructors.
    	(push_class_level_binding_1): Allow inheriting from template
    	template parameter, too.
    	* pt.c (tsubst_decl) [USING_DECL]: Likewise.

diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 074dcf3..1f3c042 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3028,11 +3028,10 @@  push_class_level_binding_1 (tree name, tree x)
     decl = TREE_VALUE (decl);
 
   if (TREE_CODE (decl) == USING_DECL
-      && TREE_CODE (USING_DECL_SCOPE (decl)) == TEMPLATE_TYPE_PARM
+      && TYPE_NAME (USING_DECL_SCOPE (decl))
       && DECL_NAME (decl) == TYPE_IDENTIFIER (USING_DECL_SCOPE (decl)))
-    /* This using-declaration declares constructors that inherit from the
-       constructors for the template parameter.  It does not redeclare the
-       name of the template parameter.  */
+    /* This using-declaration declares inheriting constructors; it does not
+       redeclare the name of a template parameter.  */
     return true;
 
   if (!check_template_shadow (decl))
@@ -3226,6 +3225,10 @@  do_class_using_decl (tree scope, tree name)
       error ("%<%T::%D%> names destructor", scope, name);
       return NULL_TREE;
     }
+  if (TYPE_NAME (scope) && name == TYPE_IDENTIFIER (scope))
+    /* 3.4.3.1 says that using B::B always names the constructor even if B
+       is a typedef; now replace the second B with the real name.  */
+    name = TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (scope));
   if (MAYBE_CLASS_TYPE_P (scope) && constructor_name_p (name, scope))
     maybe_warn_cpp0x (CPP0X_INHERITING_CTORS);
   if (constructor_name_p (name, current_class_type))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index aa868a4..e88ea85 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10492,7 +10492,8 @@  tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 	  tree inst_scope = tsubst_copy (USING_DECL_SCOPE (t), args,
 					 complain, in_decl);
 	  tree name = tsubst_copy (DECL_NAME (t), args, complain, in_decl);
-	  if (TREE_CODE (scope) == TEMPLATE_TYPE_PARM
+	  /* Handle 'using T::T'.  */
+	  if (TYPE_NAME (scope)
 	      && name == TYPE_IDENTIFIER (scope))
 	    name = TYPE_IDENTIFIER (inst_scope);
 	  r = do_class_using_decl (inst_scope, name);
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor17.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor17.C
new file mode 100644
index 0000000..22eda3a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor17.C
@@ -0,0 +1,45 @@ 
+// PR c++/56323
+// { dg-do compile { target c++11 } }
+
+struct A {
+  A(int i);
+};
+
+typedef A B;
+
+struct C : B {
+  using B::B;
+};
+
+struct D : B {
+  using B::A;
+};
+
+C c(0);
+D d(0);
+
+template <class T>
+struct E {
+  typedef T type;
+};
+
+template <class T>
+struct F : E<T>::type {
+  using E<T>::type::type; // error: E<T>::type is a typedef
+};
+
+F<A> f(0);
+
+template <class T>
+struct AT
+{
+  AT(T);
+};
+
+template <template <class> class T>
+struct G : T<int>
+{
+  using T<int>::T;
+};
+
+G<AT> g(0);