From 577b02d86397e9f5a09392d2ea9f722b8a250709 Mon Sep 17 00:00:00 2001
From: Mark Mitchell <mark@codesourcery.com>
Date: Fri, 20 Jan 2006 03:07:58 +0000
Subject: [PATCH] re PR c++/22136 (Rejects old-style using declaration)

	PR c++/22136
	* name-lookup.c (do_class_using_decl): Don't try to look up base
	classes in templates with dependent base types.
	PR c++/22136
	* g++.dg/template/using10.C: New test.
	* g++.dg/temlpate/using11.C: Likewise.
	* g++.dg/inherit/using5.C: Tweak error messages.

From-SVN: r110017
---
 gcc/cp/ChangeLog                        |  6 ++
 gcc/cp/name-lookup.c                    | 99 ++++++++++++++++---------
 gcc/testsuite/ChangeLog                 |  7 ++
 gcc/testsuite/g++.dg/inherit/using5.C   |  2 +-
 gcc/testsuite/g++.dg/template/using10.C | 11 +++
 gcc/testsuite/g++.dg/template/using11.C |  8 ++
 6 files changed, 95 insertions(+), 38 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/using10.C
 create mode 100644 gcc/testsuite/g++.dg/template/using11.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 53b2953320a7..5fabf49df71e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2006-01-19  Mark Mitchell  <mark@codesourcery.com>
+
+	PR c++/22136
+	* name-lookup.c (do_class_using_decl): Don't try to look up base
+	classes in templates with dependent base types.
+
 2006-01-19  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
 	PR c++/25854
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 4a2482f58806..190ae24cd94e 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -2722,9 +2722,21 @@ push_class_level_binding (tree name, tree x)
 tree
 do_class_using_decl (tree scope, tree name)
 {
-  tree value, decl, binfo;
-  base_kind b_kind;
-  bool dependent_p;
+  /* The USING_DECL returned by this function.  */
+  tree value;
+  /* The declaration (or declarations) name by this using
+     declaration.  NULL if we are in a template and cannot figure out
+     what has been named.  */
+  tree decl;
+  /* True if SCOPE is a dependent type.  */
+  bool scope_dependent_p;
+  /* True if SCOPE::NAME is dependent.  */
+  bool name_dependent_p;
+  /* True if any of the bases of CURRENT_CLASS_TYPE are dependent.  */
+  bool bases_dependent_p;
+  tree binfo;
+  tree base_binfo;
+  int i;
 
   if (!scope || !TYPE_P (scope))
     {
@@ -2732,25 +2744,6 @@ do_class_using_decl (tree scope, tree name)
       return NULL_TREE;
     }
 
-  /* Make sure the scope is a base.  */
-  dependent_p = dependent_type_p (scope);
-  if (!dependent_p)
-    binfo = lookup_base (current_class_type, scope, ba_any, &b_kind);
-  else
-    {
-      binfo = NULL;
-      if (same_type_p (current_class_type, scope))
-	b_kind = bk_same_type;
-      else
-	b_kind = bk_proper_base;
-    }
-
-  if (b_kind < bk_proper_base)
-    {
-      error_not_base_type (scope, current_class_type);
-      return NULL_TREE;
-    }
-
   /* Make sure the name is not invalid */
   if (TREE_CODE (name) == BIT_NOT_EXPR)
     {
@@ -2769,32 +2762,64 @@ do_class_using_decl (tree scope, tree name)
       return NULL_TREE;
     }
 
-  if (!dependent_p
-      && IDENTIFIER_OPNAME_P (name) && dependent_type_p (TREE_TYPE (name)))
-    dependent_p = 1;
+  scope_dependent_p = dependent_type_p (scope);
+  name_dependent_p = (scope_dependent_p 
+		      || (IDENTIFIER_OPNAME_P (name)
+			  && dependent_type_p (TREE_TYPE (name))));
+
+  bases_dependent_p = false;
+  if (processing_template_decl)
+    for (binfo = TYPE_BINFO (current_class_type), i = 0;
+	 BINFO_BASE_ITERATE (binfo, i, base_binfo); 
+	 i++)
+      if (dependent_type_p (TREE_TYPE (base_binfo)))
+	{
+	  bases_dependent_p = true;
+	  break;
+	}
 
-  /* See if there are any members of the base. */
-  if (!dependent_p)
-    {
-      decl = lookup_member (binfo, name, 0, false);
+  decl = NULL_TREE;
+
+  /* From [namespace.udecl]:
 
-      if (!decl)
+       A using-declaration used as a member-declaration shall refer to a
+       member of a base class of the class being defined.  
+     
+     In general, we cannot check this constraint in a template because
+     we do not know the entire set of base classes of the current
+     class type.  However, if all of the base classes are
+     non-dependent, then we can avoid delaying the check until
+     instantiation.  */
+  if (!scope_dependent_p && !bases_dependent_p)
+    {
+      base_kind b_kind;
+      tree binfo;
+      binfo = lookup_base (current_class_type, scope, ba_any, &b_kind);
+      if (b_kind < bk_proper_base)
 	{
-	  error ("no members matching %<%T::%D%> in %q#T", scope, name, scope);
+	  error_not_base_type (scope, current_class_type);
 	  return NULL_TREE;
 	}
 
-      if (BASELINK_P (decl))
-	/* Ignore base type this came from.  */
-	decl = BASELINK_FUNCTIONS (decl);
+      if (!name_dependent_p)
+	{
+	  decl = lookup_member (binfo, name, 0, false);
+	  if (!decl)
+	    {
+	      error ("no members matching %<%T::%D%> in %q#T", scope, name, 
+		     scope);
+	      return NULL_TREE;
+	    }
+	  /* The binfo from which the functions came does not matter.  */
+	  if (BASELINK_P (decl))
+	    decl = BASELINK_FUNCTIONS (decl);
+	}
    }
-  else
-    decl = NULL_TREE;
 
   value = build_lang_decl (USING_DECL, name, NULL_TREE);
   USING_DECL_DECLS (value) = decl;
   USING_DECL_SCOPE (value) = scope;
-  DECL_DEPENDENT_P (value) = dependent_p;
+  DECL_DEPENDENT_P (value) = !decl;
 
   return value;
 }
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index cc736693be36..b41928e4d82c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2006-01-19  Mark Mitchell  <mark@codesourcery.com>
+
+	PR c++/22136
+	* g++.dg/template/using10.C: New test.
+	* g++.dg/temlpate/using11.C: Likewise.
+	* g++.dg/inherit/using5.C: Tweak error messages.
+
 2006-01-20  Alan Modra  <amodra@bigpond.net.au>
 
 	* gcc.target/powerpc/rs6000-ldouble-1.c: Tweak powerpc linux
diff --git a/gcc/testsuite/g++.dg/inherit/using5.C b/gcc/testsuite/g++.dg/inherit/using5.C
index 896c2d461de3..89c7ca03ba69 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 "not a base" }
+  A::A; // { dg-error "constructor" }
 };
 
 struct B
diff --git a/gcc/testsuite/g++.dg/template/using10.C b/gcc/testsuite/g++.dg/template/using10.C
new file mode 100644
index 000000000000..8f0cbda2a888
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/using10.C
@@ -0,0 +1,11 @@
+// PR c++/22136
+
+struct B { 
+  void foo(); 
+}; 
+ 
+template <typename T> class I : public B {}; 
+ 
+template <typename T> class D : private I<T> { 
+  I<T>::B::foo; 
+}; 
diff --git a/gcc/testsuite/g++.dg/template/using11.C b/gcc/testsuite/g++.dg/template/using11.C
new file mode 100644
index 000000000000..21cc5d2ef2da
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/using11.C
@@ -0,0 +1,8 @@
+struct X {
+  void f();
+};
+
+template <typename T> 
+struct S : public T {
+  using X::f;
+};
-- 
GitLab