diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 4a5f939491720aba4e9f3e2a664f75221892e784..de0923a96cf14b4bcfb8095932b7837a3f9877a8 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,17 @@
+2003-08-02  Nathan Sidwell  <nathan@codesourcery.com>
+
+	PR c++/9447
+	* cp-tree.def (USING_DECL): Document its type.
+	* class.c (pushclass): If we're entering a template, push any
+	dependent using decls it has.
+	* decl2.c (do_class_using_decl): Refactor. Type is NULL iff it is
+	a dependent scope.
+	* pt.c (tsubst_decl) <USING_DECL case>: Set type.
+	(tsubst): Remove USING_DECL checks.
+	(type_dependent_expression_p): Remove USING_DECL case.
+	* semantics.c (finish_member_declaration): A USING_DECL's type
+	indicates whether it is dependent.
+
 2003-08-02  Nathan Sidwell  <nathan@codesourcery.com>
 
 	* cp-tree.h (pushclass): Remove unneeded parameter.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index a85b11274c8dddfc504dd4c192859741bd3068cf..bf1672127bfd9f22ff713825487cb844f07bbf53 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -5457,7 +5457,21 @@ pushclass (tree type)
   pushlevel_class ();
 
   if (type != previous_class_type || current_class_depth > 1)
-    push_class_decls (type);
+    {
+      push_class_decls (type);
+      if (CLASSTYPE_IS_TEMPLATE (type))
+	{
+	  /* If we are entering the scope of a template (not a
+	     specialization), we need to push all the using decls with
+	     dependent scope too.  */
+	  tree fields;
+
+	  for (fields = TYPE_FIELDS (type);
+	       fields; fields = TREE_CHAIN (fields))
+	    if (TREE_CODE (fields) == USING_DECL && !TREE_TYPE (fields))
+	      pushdecl_class_level (fields);
+	}
+    }
   else
     {
       tree item;
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index 5e853fea085799271e490b3a02f2a0f35d4e9bb3..f020a23d6a2f65e68c57d3f1fbf69dd4be943b0c 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -195,7 +195,9 @@ DEFTREECODE (UNBOUND_CLASS_TEMPLATE, "unbound_class_template", 't', 0)
 DEFTREECODE (TYPEOF_TYPE, "typeof_type", 't', 0)
 
 /* A using declaration.  DECL_INITIAL contains the specified scope.  
-   This is not an alias, but is later expanded into multiple aliases.  */
+   This is not an alias, but is later expanded into multiple aliases.
+   The decl will have a NULL_TYPE iff the scope is a dependent scope,
+   otherwise it will have a void type. */
 DEFTREECODE (USING_DECL, "using_decl", 'd', 0)
 
 /* A using directive. The operand is USING_STMT_NAMESPACE. */     
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 593dcede6e6ba4d89cad3444dfd10844d4124bb4..ab6913cc0c81ae584645612d49b7a6e7d70417bc 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -11632,7 +11632,8 @@ grokdeclarator (tree declarator,
 			    inlinep, friendp, raises != NULL_TREE);
 	  }
       }
-    else if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
+    else if (TREE_CODE (type) == FUNCTION_TYPE
+	     || TREE_CODE (type) == METHOD_TYPE)
       {
 	tree original_name;
 	int publicp = 0;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 6f0686069e13d5db7a18cf127ab47d1fea3c1bcd..8ec34b2e03e5292f3e1e1b89fc9eb1ce8b5520f7 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4045,8 +4045,8 @@ do_local_using_decl (tree decl)
 tree
 do_class_using_decl (tree decl)
 {
-  tree name, value;
-
+  tree name, value, scope, type;
+  
   if (TREE_CODE (decl) != SCOPE_REF
       || !TREE_OPERAND (decl, 0)
       || !TYPE_P (TREE_OPERAND (decl, 0)))
@@ -4054,50 +4054,44 @@ do_class_using_decl (tree decl)
       error ("using-declaration for non-member at class scope");
       return NULL_TREE;
     }
+  scope = TREE_OPERAND (decl, 0);
   name = TREE_OPERAND (decl, 1);
   if (TREE_CODE (name) == BIT_NOT_EXPR)
     {
-      error ("using-declaration for destructor");
+      error ("using-declaration cannot name destructor");
       return NULL_TREE;
     }
   else if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
     {
-      name = TREE_OPERAND (name, 0);
-      error ("a using-declaration cannot specify a template-id.  Try  `using %T::%D'", TREE_OPERAND (decl, 0), name);
+    template_id_error:;
+      
+      error ("a using-declaration cannot specify a template-id");
       return NULL_TREE;
     }
   if (TREE_CODE (name) == TYPE_DECL)
     {
-      tree type = TREE_TYPE (name);
       if (CLASSTYPE_USE_TEMPLATE (TREE_TYPE (name)))
-	{
-	  name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (type));
-	  error ("a using-declaration cannot specify a template-id.");
-	  return NULL_TREE;
-	}
+	goto template_id_error;
       name = DECL_NAME (name);
     }
   else if (TREE_CODE (name) == TEMPLATE_DECL)
      name = DECL_NAME (name);
   else if (BASELINK_P (name))
     {
-      tree fns;
-
-      fns = BASELINK_FUNCTIONS (name);
+      tree fns = BASELINK_FUNCTIONS (name);
+      
       if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
-	{
-	  fns = TREE_OPERAND (fns, 0);
-	  error ("a using-declaration cannot specify a template-id.  Try  `using %T::%D'", 
-		 BASELINK_ACCESS_BINFO (name),
-		 DECL_NAME (get_first_fn (fns)));
-	}
+	goto template_id_error;
       name = DECL_NAME (get_first_fn (fns));
     }
 
   my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716);
 
-  value = build_lang_decl (USING_DECL, name, NULL_TREE);
-  DECL_INITIAL (value) = TREE_OPERAND (decl, 0);
+  /* Dependent using decls have a NULL type, non-dependent ones have a
+     void type.  */
+  type = dependent_type_p (scope) ? NULL_TREE : void_type_node;
+  value = build_lang_decl (USING_DECL, name, type);
+  DECL_INITIAL (value) = scope;
   return value;
 }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 35c13670c7c20dff5722b95a0cae157bdd8f7b0f..185a203c20024cd29d067cb10d2ec8103e972b04 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6093,6 +6093,8 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
     case USING_DECL:
       {
 	r = copy_node (t);
+	/* It is not a dependent using decl any more.  */
+	TREE_TYPE (r) = void_type_node;
 	DECL_INITIAL (r)
 	  = tsubst_copy (DECL_INITIAL (t), args, complain, in_decl);
 	TREE_CHAIN (r) = NULL_TREE;
@@ -6403,15 +6405,13 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
   else
     type = TREE_TYPE (t);
 
-  my_friendly_assert (type != unknown_type_node
-		      || TREE_CODE (t) == USING_DECL, 20030716);
+  my_friendly_assert (type != unknown_type_node, 20030716);
 
   if (type && TREE_CODE (t) != FUNCTION_DECL
       && TREE_CODE (t) != TYPENAME_TYPE
       && TREE_CODE (t) != TEMPLATE_DECL
       && TREE_CODE (t) != IDENTIFIER_NODE
       && TREE_CODE (t) != FUNCTION_TYPE
-      && TREE_CODE (t) != USING_DECL
       && TREE_CODE (t) != METHOD_TYPE)
     type = tsubst (type, args, complain, in_decl);
   if (type == error_mark_node)
@@ -11623,8 +11623,6 @@ type_dependent_expression_p (tree expression)
 
   if (TREE_TYPE (expression) == unknown_type_node)
     {
-      if (TREE_CODE (expression) == USING_DECL)
-	return true;
       if (TREE_CODE (expression) == ADDR_EXPR)
 	return type_dependent_expression_p (TREE_OPERAND (expression, 0));
       if (TREE_CODE (expression) == BASELINK)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 11f5ff045d3bd478ee0f2db23bdab8f853fa5317..0931e891e048bc13fcc8eba3b2af053fcfa5233d 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2099,8 +2099,7 @@ finish_member_declaration (tree decl)
 					  /*friend_p=*/0);
     }
   /* Enter the DECL into the scope of the class.  */
-  else if ((TREE_CODE (decl) == USING_DECL && !processing_template_decl
-	    && !dependent_type_p (DECL_INITIAL (decl)))
+  else if ((TREE_CODE (decl) == USING_DECL && TREE_TYPE (decl))
 	   || pushdecl_class_level (decl))
     {
       /* All TYPE_DECLs go at the end of TYPE_FIELDS.  Ordinary fields
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9b982ee16b291c66f58b228d5dcc9662d5e506e5..93da3595af9078562e95f49a2d74cb1f712a6702 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2003-08-02  Nathan Sidwell  <nathan@codesourcery.com>
+
+	PR c++/9447
+	* g++.dg/template/using7.C: New test.
+
 2003-08-02  Neil Booth  <neil@daikokuya.co.uk>
 
 	* import1.c, import2.c: New tests.
diff --git a/gcc/testsuite/g++.dg/template/using7.C b/gcc/testsuite/g++.dg/template/using7.C
new file mode 100644
index 0000000000000000000000000000000000000000..390dfbaace9d185fd5bf7d7e50a6662b39571bfa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/using7.C
@@ -0,0 +1,21 @@
+// { dg-do compile }
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 1 Aug 2003 <nathan@codesourcery.com>
+
+// PR 9447. Using decls in reopened template classes.
+
+template <typename> struct A { int i; };
+
+template <typename T> struct B : public A<T>
+{
+    using A<T>::i;
+    int foo() const;
+};
+
+struct C {};
+
+template <typename T> int B<T>::foo() const
+{
+  return i;
+}