This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/56358 (inheriting ctors breaking lookup)


We were trying to keep the USING_DECL for an inheriting constructor from interfering with name lookup, but it still did. It occurred to me that the obvious way to avoid it interfering with the name of the base is to give the USING_DECL the constructor name, and then we can remove some of the special handling.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 57dd2e9e8586a6d6b0134904a8eb2cb0bd4fc09b
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Feb 26 13:01:48 2013 -0500

    	PR c++/56358
    	PR c++/56323
    	* name-lookup.c (do_class_using_decl): Use ctor_identifier instead
    	of the base name for inheriting ctors.
    	(push_class_level_binding_1): Remove inheriting ctor handling.
    	* pt.c (tsubst_decl) [USING_DECL]: Likewise.
    	* class.c (add_implicitly_declared_members): Adjust.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index eaa109a..2a0351f 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -3010,11 +3010,10 @@ add_implicitly_declared_members (tree t, tree* access_decls,
     {
       tree using_decl = TREE_VALUE (*access_decls);
       tree decl = USING_DECL_DECLS (using_decl);
-      if (DECL_SELF_REFERENCE_P (decl))
+      if (DECL_NAME (using_decl) == ctor_identifier)
 	{
 	  /* declare, then remove the decl */
-	  tree ctor_list = lookup_fnfields_slot (TREE_TYPE (decl),
-						 ctor_identifier);
+	  tree ctor_list = decl;
 	  location_t loc = input_location;
 	  input_location = DECL_SOURCE_LOCATION (using_decl);
 	  if (ctor_list)
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 1f3c042..2a47331 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3027,13 +3027,6 @@ push_class_level_binding_1 (tree name, tree x)
       && TREE_TYPE (decl) == error_mark_node)
     decl = TREE_VALUE (decl);
 
-  if (TREE_CODE (decl) == USING_DECL
-      && TYPE_NAME (USING_DECL_SCOPE (decl))
-      && DECL_NAME (decl) == TYPE_IDENTIFIER (USING_DECL_SCOPE (decl)))
-    /* This using-declaration declares inheriting constructors; it does not
-       redeclare the name of a template parameter.  */
-    return true;
-
   if (!check_template_shadow (decl))
     return false;
 
@@ -3225,12 +3218,14 @@ 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);
+  /* Using T::T declares inheriting ctors, even if T is a typedef.  */
+  if (MAYBE_CLASS_TYPE_P (scope)
+      && ((TYPE_NAME (scope) && name == TYPE_IDENTIFIER (scope))
+	  || constructor_name_p (name, scope)))
+    {
+      maybe_warn_cpp0x (CPP0X_INHERITING_CTORS);
+      name = ctor_identifier;
+    }
   if (constructor_name_p (name, current_class_type))
     {
       error ("%<%T::%D%> names constructor in %qT",
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9b7fc3a..eb9fc7f 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10490,14 +10490,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
       if (DECL_DEPENDENT_P (t)
 	  || uses_template_parms (USING_DECL_SCOPE (t)))
 	{
-	  tree scope = USING_DECL_SCOPE (t);
 	  tree inst_scope = tsubst_copy (USING_DECL_SCOPE (t), args,
 					 complain, in_decl);
 	  tree name = tsubst_copy (DECL_NAME (t), args, complain, in_decl);
-	  /* 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);
 	  if (!r)
 	    r = error_mark_node;
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor18.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor18.C
new file mode 100644
index 0000000..0573555
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor18.C
@@ -0,0 +1,22 @@
+// PR c++/56358
+// { dg-do compile { target c++11 } }
+
+struct foo {
+  explicit foo(int) {}
+};
+
+template<typename T>
+struct bar: T {
+  using T::T;
+
+  // Bad
+  explicit bar(): T(0) {}
+
+  void baz()
+  {
+    // Also bad
+    using qux = T;
+  }
+};
+
+bar<foo> b, b2(42);
diff --git a/gcc/testsuite/g++.dg/inherit/using5.C b/gcc/testsuite/g++.dg/inherit/using5.C
index 89c7ca0..b8e5107 100644
--- a/gcc/testsuite/g++.dg/inherit/using5.C
+++ b/gcc/testsuite/g++.dg/inherit/using5.C
@@ -6,7 +6,7 @@
 
 template<int> struct A
 {
-  A::A; // { dg-error "constructor" }
+  A::A; // { dg-error "constructor|not a base" }
 };
 
 struct B
diff --git a/gcc/testsuite/g++.old-deja/g++.other/using3.C b/gcc/testsuite/g++.old-deja/g++.other/using3.C
index f30ecbc..3df78f0 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/using3.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/using3.C
@@ -8,5 +8,5 @@ typedef struct {
 } S;
 
 struct B: S{
-  using S::S;        // { dg-error "" } no such field
+  using S::S;	       // { dg-error "" "" { target c++98 } } no such field
 };

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]