diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a33332cc6a93aa5da7696cdce87ec36f57b23f47..e9a7330db63e19e6f7fcb08142b10a01e5f75081 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,37 @@
+2011-11-14  Fabien Chêne  <fabien@gcc.gnu.org>
+
+	PR c++/6936
+	PR c++/25994
+	PR c++/26256
+	PR c++/30195
+	* search.c (lookup_field_1): Look through USING_DECL.
+	(lookup_field_r): Call lookup_fnfields_slot instead of
+	lookup_fnfields_1.
+	* semantics.c (finish_member_declaration): Remove the check that
+	prevents USING_DECLs from being verified by
+	pushdecl_class_level. Call add_method for using declarations that
+	designates functions if the using declaration is in a template
+	class. Set DECL_IGNORED_P on class-scope using declarations.
+	* typeck.c (build_class_member_access_expr): Handle USING_DECLs.
+	* class.c (check_field_decls): Keep using declarations.
+	(add_method): Remove two diagnostics about conflicting using
+	declarations.
+	* parser.c (cp_parser_nonclass_name): Handle USING_DECLs.
+	* decl.c (start_enum): Call xref_tag whenever possible.
+	* cp-tree.h (strip_using_decl): Declare, and reident the previous
+	function.
+	* name-lookup.c (strip_using_decl): New function.
+	(supplement_binding_1): Call strip_using_decl on decl and
+	bval. Perform most of the checks with USING_DECLs stripped.  Also
+	check that the target decl and the target bval does not refer to
+	the same declaration. Allow pushing an enum multiple times in a
+	template class. Adjustment to diagnose using redeclarations. Call
+	diagnose_name_conflict.
+	(push_class_level_binding): Call strip_using_decl on decl and
+	bval. Perform most of the checks with USING_DECLs stripped. Return
+	true if both decl and bval refer to USING_DECLs and are dependent.
+	(diagnose_name_conflict): New function.
+
 2011-11-12  Jason Merrill  <jason@redhat.com>
 
 	PR c++/986
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index d2cf63c7d0f51e992d91d251c799a3b813d7fbf8..4a291acca8ac0886ee75cc712cd7439371d63b39 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1058,11 +1058,6 @@ add_method (tree type, tree method, tree using_decl)
 	      if (DECL_CONTEXT (fn) == type)
 		/* Defer to the local function.  */
 		return false;
-	      if (DECL_CONTEXT (fn) == DECL_CONTEXT (method))
-		error ("repeated using declaration %q+D", using_decl);
-	      else
-		error ("using declaration %q+D conflicts with a previous using declaration",
-		       using_decl);
 	    }
 	  else
 	    {
@@ -3039,15 +3034,8 @@ check_field_decls (tree t, tree *access_decls,
 
       if (TREE_CODE (x) == USING_DECL)
 	{
-	  /* Prune the access declaration from the list of fields.  */
-	  *field = DECL_CHAIN (x);
-
 	  /* Save the access declarations for our caller.  */
 	  *access_decls = tree_cons (NULL_TREE, x, *access_decls);
-
-	  /* Since we've reset *FIELD there's no reason to skip to the
-	     next field.  */
-	  next = field;
 	  continue;
 	}
 
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b306976c62c9e4a9eed214b7c9941c51a22e3b76..fe50e34e7d9ea12c97c937a322aad0f64f081ee6 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5886,7 +5886,8 @@ extern void cxx_omp_finish_clause		(tree);
 extern bool cxx_omp_privatize_by_reference	(const_tree);
 
 /* in name-lookup.c */
-extern void suggest_alternatives_for (location_t, tree);
+extern void suggest_alternatives_for            (location_t, tree);
+extern tree strip_using_decl                    (tree);
 
 /* -- end of C++ */
 
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 1c46adf99a1d11652ebdc36eb1170c50614844d6..d744da85f3e510b4a43073c84fe77566e09d3061 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -11988,8 +11988,22 @@ start_enum (tree name, tree enumtype, tree underlying_type,
 	    *is_new = true;
 	}
       prevtype = enumtype;
-      enumtype = cxx_make_type (ENUMERAL_TYPE);
-      enumtype = pushtag (name, enumtype, /*tag_scope=*/ts_current);
+
+      /* Do not push the decl more than once, unless we need to
+	 compare underlying types at instantiation time */
+      if (!enumtype
+	  || (underlying_type
+	      && dependent_type_p (underlying_type))
+	  || (ENUM_UNDERLYING_TYPE (enumtype)
+	      && dependent_type_p (ENUM_UNDERLYING_TYPE (enumtype))))
+	{
+	  enumtype = cxx_make_type (ENUMERAL_TYPE);
+	  enumtype = pushtag (name, enumtype, /*tag_scope=*/ts_current);
+	}
+      else
+	  enumtype = xref_tag (enum_type, name, /*tag_scope=*/ts_current,
+			       false);
+
       if (enumtype == error_mark_node)
 	return error_mark_node;
 
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 044a97f715758a3a5af902acccef94489e74937b..7f6b8cdcf296beb6e5e97f7ffbf5a86d3cfcc946 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -53,6 +53,7 @@ static bool qualified_lookup_using_namespace (tree, tree,
 static tree lookup_type_current_level (tree);
 static tree push_using_directive (tree);
 static tree lookup_extern_c_fun_in_all_ns (tree);
+static void diagnose_name_conflict (tree, tree);
 
 /* The :: namespace.  */
 
@@ -394,6 +395,16 @@ pop_binding (tree id, tree decl)
     }
 }
 
+/* Strip non dependent using declarations.  */
+
+tree
+strip_using_decl (tree decl)
+{
+  while (TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl))
+    decl = USING_DECL_DECLS (decl);
+  return decl;
+}
+
 /* BINDING records an existing declaration for a name in the current scope.
    But, DECL is another declaration for that same identifier in the
    same scope.  This is the `struct stat' hack whereby a non-typedef
@@ -417,29 +428,46 @@ supplement_binding_1 (cxx_binding *binding, tree decl)
 {
   tree bval = binding->value;
   bool ok = true;
-
-  if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
+  tree target_bval = strip_using_decl (bval);
+  tree target_decl = strip_using_decl (decl);
+
+  if (TREE_CODE (target_decl) == TYPE_DECL && DECL_ARTIFICIAL (target_decl)
+      && target_decl != target_bval
+      && (TREE_CODE (target_bval) != TYPE_DECL
+	  /* We allow pushing an enum multiple times in a class
+	     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
+	      && TREE_CODE (TREE_TYPE (target_bval)) == ENUMERAL_TYPE
+	      && (dependent_type_p (ENUM_UNDERLYING_TYPE
+				    (TREE_TYPE (target_decl)))
+		  || dependent_type_p (ENUM_UNDERLYING_TYPE
+				       (TREE_TYPE (target_bval)))))))
     /* The new name is the type name.  */
     binding->type = decl;
-  else if (/* BVAL is null when push_class_level_binding moves an
-	      inherited type-binding out of the way to make room for a
-	      new value binding.  */
-	   !bval
-	   /* BVAL is error_mark_node when DECL's name has been used
-	      in a non-class scope prior declaration.  In that case,
-	      we should have already issued a diagnostic; for graceful
-	      error recovery purpose, pretend this was the intended
-	      declaration for that name.  */
-	   || bval == error_mark_node
-	   /* If BVAL is anticipated but has not yet been declared,
-	      pretend it is not there at all.  */
-	   || (TREE_CODE (bval) == FUNCTION_DECL
-	       && DECL_ANTICIPATED (bval)
-	       && !DECL_HIDDEN_FRIEND_P (bval)))
+  else if (/* TARGET_BVAL is null when push_class_level_binding moves
+	      an inherited type-binding out of the way to make room
+	      for a new value binding.  */
+	   !target_bval
+	   /* TARGET_BVAL is error_mark_node when TARGET_DECL's name
+	      has been used in a non-class scope prior declaration.
+	      In that case, we should have already issued a
+	      diagnostic; for graceful error recovery purpose, pretend
+	      this was the intended declaration for that name.  */
+	   || target_bval == error_mark_node
+	   /* If TARGET_BVAL is anticipated but has not yet been
+	      declared, pretend it is not there at all.  */
+	   || (TREE_CODE (target_bval) == FUNCTION_DECL
+	       && DECL_ANTICIPATED (target_bval)
+	       && !DECL_HIDDEN_FRIEND_P (target_bval)))
     binding->value = decl;
-  else if (TREE_CODE (bval) == TYPE_DECL && DECL_ARTIFICIAL (bval)
-	   && (TREE_CODE (decl) != TYPE_DECL
-	       || same_type_p (TREE_TYPE (decl), TREE_TYPE (bval))))
+  else if (TREE_CODE (target_bval) == TYPE_DECL
+	   && DECL_ARTIFICIAL (target_bval)
+	   && target_decl != target_bval
+	   && (TREE_CODE (target_decl) != TYPE_DECL
+	       || same_type_p (TREE_TYPE (target_decl),
+			       TREE_TYPE (target_bval))))
     {
       /* The old binding was a type name.  It was placed in
 	 VALUE field because it was thought, at the point it was
@@ -450,15 +478,15 @@ supplement_binding_1 (cxx_binding *binding, tree decl)
       binding->value = decl;
       binding->value_is_inherited = false;
     }
-  else if (TREE_CODE (bval) == TYPE_DECL
-	   && TREE_CODE (decl) == TYPE_DECL
-	   && DECL_NAME (decl) == DECL_NAME (bval)
+  else if (TREE_CODE (target_bval) == TYPE_DECL
+	   && TREE_CODE (target_decl) == TYPE_DECL
+	   && DECL_NAME (target_decl) == DECL_NAME (target_bval)
 	   && binding->scope->kind != sk_class
-	   && (same_type_p (TREE_TYPE (decl), TREE_TYPE (bval))
+	   && (same_type_p (TREE_TYPE (target_decl), TREE_TYPE (target_bval))
 	       /* If either type involves template parameters, we must
 		  wait until instantiation.  */
-	       || uses_template_parms (TREE_TYPE (decl))
-	       || uses_template_parms (TREE_TYPE (bval))))
+	       || uses_template_parms (TREE_TYPE (target_decl))
+	       || uses_template_parms (TREE_TYPE (target_bval))))
     /* We have two typedef-names, both naming the same type to have
        the same name.  In general, this is OK because of:
 
@@ -480,9 +508,10 @@ supplement_binding_1 (cxx_binding *binding, tree decl)
 
        A member shall not be declared twice in the
        member-specification.  */
-  else if (TREE_CODE (decl) == VAR_DECL && TREE_CODE (bval) == VAR_DECL
-	   && DECL_EXTERNAL (decl) && DECL_EXTERNAL (bval)
-	   && !DECL_CLASS_SCOPE_P (decl))
+  else if (TREE_CODE (target_decl) == VAR_DECL
+	   && TREE_CODE (target_bval) == VAR_DECL
+	   && DECL_EXTERNAL (target_decl) && DECL_EXTERNAL (target_bval)
+	   && !DECL_CLASS_SCOPE_P (target_decl))
     {
       duplicate_decls (decl, binding->value, /*newdecl_is_friend=*/false);
       ok = false;
@@ -501,14 +530,30 @@ supplement_binding_1 (cxx_binding *binding, tree decl)
     ok = false;
   else
     {
-      error ("declaration of %q#D", decl);
-      error ("conflicts with previous declaration %q+#D", bval);
+      diagnose_name_conflict (decl, bval);
       ok = false;
     }
 
   return ok;
 }
 
+/* Diagnose a name conflict between DECL and BVAL.  */
+
+static void
+diagnose_name_conflict (tree decl, tree bval)
+{
+  if (TREE_CODE (decl) == TREE_CODE (bval)
+      && (TREE_CODE (decl) != TYPE_DECL
+	  || (DECL_ARTIFICIAL (decl) && DECL_ARTIFICIAL (bval))
+	  || (!DECL_ARTIFICIAL (decl) && !DECL_ARTIFICIAL (bval)))
+      && !is_overloaded_fn (decl))
+    error ("redeclaration of %q#D", decl);
+  else
+    error ("%q#D conflicts with a previous declaration", decl);
+
+  inform (input_location, "previous declaration %q+#D", bval);
+}
+
 /* Wrapper for supplement_binding_1.  */
 
 static bool
@@ -3028,6 +3073,8 @@ push_class_level_binding_1 (tree name, tree x)
     {
       tree bval = binding->value;
       tree old_decl = NULL_TREE;
+      tree target_decl = strip_using_decl (decl);
+      tree target_bval = strip_using_decl (bval);
 
       if (INHERITED_VALUE_BINDING_P (binding))
 	{
@@ -3035,8 +3082,10 @@ push_class_level_binding_1 (tree name, tree x)
 	     tag name, slide it over to make room for the new binding.
 	     The old binding is still visible if explicitly qualified
 	     with a class-key.  */
-	  if (TREE_CODE (bval) == TYPE_DECL && DECL_ARTIFICIAL (bval)
-	      && !(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
+	  if (TREE_CODE (target_bval) == TYPE_DECL
+	      && DECL_ARTIFICIAL (target_bval)
+	      && !(TREE_CODE (target_decl) == TYPE_DECL
+		   && DECL_ARTIFICIAL (target_decl)))
 	    {
 	      old_decl = binding->type;
 	      binding->type = bval;
@@ -3048,17 +3097,31 @@ push_class_level_binding_1 (tree name, tree x)
 	      old_decl = bval;
 	      /* Any inherited type declaration is hidden by the type
 		 declaration in the derived class.  */
-	      if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x))
+	      if (TREE_CODE (target_decl) == TYPE_DECL
+		  && DECL_ARTIFICIAL (target_decl))
 		binding->type = NULL_TREE;
 	    }
 	}
-      else if (TREE_CODE (x) == OVERLOAD && is_overloaded_fn (bval))
+      else if (TREE_CODE (target_decl) == OVERLOAD
+	       && is_overloaded_fn (target_bval))
 	old_decl = bval;
-      else if (TREE_CODE (x) == USING_DECL && TREE_CODE (bval) == USING_DECL)
+      else if (TREE_CODE (decl) == USING_DECL
+	       && TREE_CODE (bval) == USING_DECL
+	       && same_type_p (USING_DECL_SCOPE (decl),
+			       USING_DECL_SCOPE (bval)))
+	/* This is a using redeclaration that will be diagnosed later
+	   in supplement_binding */
+	;
+      else if (TREE_CODE (decl) == USING_DECL
+	       && TREE_CODE (bval) == USING_DECL
+	       && DECL_DEPENDENT_P (decl)
+	       && DECL_DEPENDENT_P (bval))
 	return true;
-      else if (TREE_CODE (x) == USING_DECL && is_overloaded_fn (bval))
+      else if (TREE_CODE (decl) == USING_DECL
+	       && is_overloaded_fn (target_bval))
 	old_decl = bval;
-      else if (TREE_CODE (bval) == USING_DECL && is_overloaded_fn (x))
+      else if (TREE_CODE (bval) == USING_DECL
+	       && is_overloaded_fn (target_decl))
 	return true;
 
       if (old_decl && binding->scope == class_binding_level)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index fc8f3c82bac82242396f1f17ad4e560ce8988cfc..23885b867cd01b035bdb4af9309289a0858ea7e1 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -13758,6 +13758,9 @@ cp_parser_nonclass_name (cp_parser* parser)
   /* Look up the type-name.  */
   type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location);
 
+  /* If it is a using decl, use its underlying decl.  */
+  type_decl = strip_using_decl (type_decl);
+
   if (TREE_CODE (type_decl) != TYPE_DECL
       && (objc_is_id (identifier) || objc_is_class_name (identifier)))
     {
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 7d9551c28bf618d8f98bb443827ae45ff9f914a3..9f308e29d7921ca92bd5f95c7f5a54fbe13c733a 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -1,7 +1,7 @@
 /* Breadth-first and depth-first routines for
    searching multiple-inheritance lattice for GNU C++.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
+   1999, 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
@@ -449,6 +449,8 @@ lookup_field_1 (tree type, tree name, bool want_type)
 #endif /* GATHER_STATISTICS */
   for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
     {
+      tree decl = field;
+
 #ifdef GATHER_STATISTICS
       n_fields_searched++;
 #endif /* GATHER_STATISTICS */
@@ -460,26 +462,20 @@ lookup_field_1 (tree type, tree name, bool want_type)
 	  if (temp)
 	    return temp;
 	}
-      if (TREE_CODE (field) == USING_DECL)
+
+      if (TREE_CODE (decl) == USING_DECL
+	  && DECL_NAME (decl) == name)
 	{
-	  /* We generally treat class-scope using-declarations as
-	     ARM-style access specifications, because support for the
-	     ISO semantics has not been implemented.  So, in general,
-	     there's no reason to return a USING_DECL, and the rest of
-	     the compiler cannot handle that.  Once the class is
-	     defined, USING_DECLs are purged from TYPE_FIELDS; see
-	     handle_using_decl.  However, we make special efforts to
-	     make using-declarations in class templates and class
-	     template partial specializations work correctly.  */
-	  if (!DECL_DEPENDENT_P (field))
+	  decl = strip_using_decl (decl);
+	  if (is_overloaded_fn (decl))
 	    continue;
 	}
 
-      if (DECL_NAME (field) == name
+      if (DECL_NAME (decl) == name
 	  && (!want_type
-	      || TREE_CODE (field) == TYPE_DECL
-	      || DECL_TYPE_TEMPLATE_P (field)))
-	return field;
+	      || TREE_CODE (decl) == TYPE_DECL
+	      || DECL_TYPE_TEMPLATE_P (decl)))
+	return decl;
     }
   /* Not found.  */
   if (name == vptr_identifier)
@@ -1028,11 +1024,7 @@ lookup_field_r (tree binfo, void *data)
      member with the same name, and if there's a function and a type
      with the same name, the type is hidden by the function.  */
   if (!lfi->want_type)
-    {
-      int idx = lookup_fnfields_1 (type, lfi->name);
-      if (idx >= 0)
-	nval = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), idx);
-    }
+    nval = lookup_fnfields_slot (type, lfi->name);
 
   if (!nval)
     /* Look for a data member or type.  */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index e9da3817577969e87ea6c805729b00e061d695dc..f70bdb377b5551c922cd32cde6457fa82753accc 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2658,9 +2658,29 @@ finish_member_declaration (tree decl)
 	}
     }
   /* Enter the DECL into the scope of the class.  */
-  else if ((TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl))
-	   || pushdecl_class_level (decl))
+  else if (pushdecl_class_level (decl))
     {
+      if (TREE_CODE (decl) == USING_DECL)
+	{
+	  /* We need to add the target functions to the
+	     CLASSTYPE_METHOD_VEC if an enclosing scope is a template
+	     class, so that this function be found by lookup_fnfields_1
+	     when the using declaration is not instantiated yet.  */
+
+	  tree target_decl = strip_using_decl (decl);
+	  if (dependent_type_p (current_class_type)
+	      && is_overloaded_fn (target_decl))
+	    {
+	      tree t = target_decl;
+	      for (; t; t = OVL_NEXT (t))
+		add_method (current_class_type, OVL_CURRENT (t), decl);
+	    }
+
+	  /* For now, ignore class-scope USING_DECLS, so that
+	     debugging backends do not see them. */
+	  DECL_IGNORED_P (decl) = 1;
+	}
+
       /* All TYPE_DECLs go at the end of TYPE_FIELDS.  Ordinary fields
 	 go at the beginning.  The reason is that lookup_field_1
 	 searches the list in order, and we want a field name to
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 722cec5b5b98b5c78e26d389532804b6d35ef160..f08877c5b612059a11f061efd5f854f1da81e161 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2115,6 +2115,7 @@ build_class_member_access_expr (tree object, tree member,
   tree object_type;
   tree member_scope;
   tree result = NULL_TREE;
+  tree using_decl = NULL_TREE;
 
   if (error_operand_p (object) || error_operand_p (member))
     return error_mark_node;
@@ -2343,6 +2344,11 @@ build_class_member_access_expr (tree object, tree member,
 	result = build2 (COMPOUND_EXPR, TREE_TYPE (result),
 			 object, result);
     }
+  else if ((using_decl = strip_using_decl (member)) != member)
+    result = build_class_member_access_expr (object,
+					     using_decl,
+					     access_path, preserve_reference,
+					     complain);
   else
     {
       if (complain & tf_error)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 57e5eb57ea55be3c1db897c58b11b6f7de51e6f2..7a7445e90e7d0872df7a0a91f3b0b41c724eb33b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,50 @@
+2011-11-14  Fabien Chêne  <fabien@gcc.gnu.org>
+
+	PR c++/6936
+	PR c++/25994
+	PR c++/26256
+	PR c++/30195
+	* g++.old-deja/g++.brendan/misc14.C: Adjust.
+	* g++.old-deja/g++.jason/scoping16.C: Likewise.
+	* g++.old-deja/g++.other/anon7.C: Likewise.
+	* g++.old-deja/g++.other/using1.C: Likewise.
+	* g++.old-deja/g++.other/redecl1.C: Likewise.
+	* g++.old-deja/g++.other/typedef7.C: Likewise.
+	* g++.old-deja/g++.bugs/900127_02.C: Likewise.
+	* g++.dg/template/using2.C: Likewise.
+	* g++.dg/template/static4.C: Likewise.
+	* g++.dg/template/typedef1.C: Likewise.
+	* g++.dg/lookup/name-clash9.C: Likewise.
+	* g++.dg/abi/mangle41.C: Likewise.
+	* g++.dg/parse/ctor5.C: Likewise.
+	* g++.dg/inherit/using4.C: Likewise.
+	* g++.dg/lookup/using24.C: New.
+	* g++.dg/lookup/using25.C: New.
+	* g++.dg/lookup/using26.C: New.
+	* g++.dg/lookup/using27.C: New.
+	* g++.dg/lookup/using28.C: New.
+	* g++.dg/lookup/using29.C: New.
+	* g++.dg/lookup/using30.C: New.
+	* g++.dg/lookup/using31.C: New.
+	* g++.dg/lookup/using32.C: New.
+	* g++.dg/lookup/using33.C: New.
+	* g++.dg/lookup/using34.C: New.
+	* g++.dg/lookup/using35.C: New.
+	* g++.dg/lookup/using36.C: New.
+	* g++.dg/lookup/using37.C: New.
+	* g++.dg/lookup/using38.C: New.
+	* g++.dg/lookup/using39.C: New.
+	* g++.dg/lookup/using40.C: New.
+	* g++.dg/lookup/using41.C: New.
+	* g++.dg/lookup/using42.C: New.
+	* g++.dg/lookup/using43.C: New.
+	* g++.dg/lookup/using44.C: New.
+	* g++.dg/lookup/using45.C: New.
+	* g++.dg/lookup/pr6936.C: New.
+	* g++.dg/debug/using4.C: New.
+	* g++.dg/debug/using5.C: New.
+	* g++.dg/cpp0x/forw_enum10.C: New.
+
 2011-11-14  Zolotukhin Michael  <michael.v.zolotukhin@gmail.com>
 	    Jan Hubicka  <jh@suse.cz>
 
diff --git a/gcc/testsuite/g++.dg/abi/mangle41.C b/gcc/testsuite/g++.dg/abi/mangle41.C
index 3a9c04f77d00bee9f2101ccd1aa2a092abe0b8ed..4c0d0038e8031e932f35621a8d935048bc21e8a5 100644
--- a/gcc/testsuite/g++.dg/abi/mangle41.C
+++ b/gcc/testsuite/g++.dg/abi/mangle41.C
@@ -3,5 +3,6 @@
 // { dg-options "-mavx -fabi-version=2" }
 
 #include <x86intrin.h>
-void f(__m128) { }		// { dg-error "previous" }
-void f(__m256) { }		// { dg-message "declaration|mangling" }
+void f(__m128) { }		// { dg-message "previous declaration" }
+void f(__m256) { }		// { dg-error "conflicts" }
+// { dg-message "mangling" "" { target *-*-* } 7 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum10.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum10.C
new file mode 100644
index 0000000000000000000000000000000000000000..a57c0a9f415469f3fc4c8f9b46932fff156b1551
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum10.C
@@ -0,0 +1,31 @@
+// { dg-do compile }
+// { dg-options "-std=c++0x" }
+
+//This error is diagnosed at instantiation time
+template<typename T> struct S1
+{
+    enum E : T;   // { dg-error "previous definition" }
+    enum E : int;     // { dg-error "different underlying type" }
+};
+template struct S1<short>; // { dg-message "required from here" }
+
+template<typename T> struct S2
+{
+    enum E : T;
+    enum E : T;
+};
+template struct S2<short>;
+
+template<typename T1, typename T2> struct S3
+{
+    enum E : T1;
+    enum E : T2;
+};
+template struct S3<short,short>;
+
+template<typename T1, typename T2> struct S4
+{
+    enum E : T1; // { dg-error "previous definition" }
+    enum E : T2; // { dg-error "different underlying type" }
+};
+template struct S4<short,char>; // { dg-message "required from here" }
diff --git a/gcc/testsuite/g++.dg/debug/using4.C b/gcc/testsuite/g++.dg/debug/using4.C
new file mode 100644
index 0000000000000000000000000000000000000000..8a6162606c4a4aa60c1c36633663eef5c4598233
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/using4.C
@@ -0,0 +1,24 @@
+// PR c++/26256
+// { dg-do compile }
+
+struct A
+{
+    typedef char type;
+};
+
+struct B
+{
+    typedef int type;
+};
+
+struct C : A, B
+{
+    using A::type;
+    type f (type);
+};
+
+C::type C::f( type )
+{
+    type c = 'e';
+    return c;
+}
diff --git a/gcc/testsuite/g++.dg/debug/using5.C b/gcc/testsuite/g++.dg/debug/using5.C
new file mode 100644
index 0000000000000000000000000000000000000000..3f2de9bfb8063f7f19773f92a245069f60ab1233
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/using5.C
@@ -0,0 +1,23 @@
+// PR c++/26256
+// { dg-do compile }
+
+struct A
+{
+    int i;
+};
+
+struct B
+{
+    int i;
+};
+
+struct C : A, B
+{
+    using B::i;
+    int f ();
+};
+
+int C::f()
+{
+    return i;
+}
diff --git a/gcc/testsuite/g++.dg/inherit/using4.C b/gcc/testsuite/g++.dg/inherit/using4.C
index a0b38737e1ea22a63e8a305d48bb019677f5ea39..4b7a28f0f463a3e1cd02041b1502e1b870965619 100644
--- a/gcc/testsuite/g++.dg/inherit/using4.C
+++ b/gcc/testsuite/g++.dg/inherit/using4.C
@@ -9,6 +9,6 @@ struct B {
 }; 
  
 struct D : B { 
-  using B::f; 
-  using B::f;  // { dg-error "repeated" }
+  using B::f; // { dg-message "previous declaration" }
+  using B::f; // { dg-error "redeclaration" }
 }; 
diff --git a/gcc/testsuite/g++.dg/lookup/name-clash9.C b/gcc/testsuite/g++.dg/lookup/name-clash9.C
index 4167f47b4a94465b337b56bd35a7d31d225717e2..1e04fafd5b9fb96c9882763e1993ebe03509df86 100644
--- a/gcc/testsuite/g++.dg/lookup/name-clash9.C
+++ b/gcc/testsuite/g++.dg/lookup/name-clash9.C
@@ -3,6 +3,6 @@
 
 struct A
 {
-  struct type {}; // { dg-error "conflicts with previous" }
-  typedef int type; // { dg-error "declaration" }
+  struct type {}; // { dg-message "previous" }
+  typedef int type; // { dg-error "conflicts" }
 };
diff --git a/gcc/testsuite/g++.dg/lookup/pr6936.C b/gcc/testsuite/g++.dg/lookup/pr6936.C
new file mode 100644
index 0000000000000000000000000000000000000000..377fbcce1e3142e1268be72b32d66e751be82f9e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/pr6936.C
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// PR c++/6936
+
+struct Baser
+{
+    enum { j, i }; // { dg-error "inaccessible" }
+};
+
+struct Base : Baser
+{
+    static void j();
+    static void i();
+};
+
+struct Derv : Base
+{
+  using Baser::j;
+private:
+  using Baser::i;
+};
+
+int k = Derv::j;
+int l = Derv::i; // { dg-error "context" }
diff --git a/gcc/testsuite/g++.dg/lookup/using24.C b/gcc/testsuite/g++.dg/lookup/using24.C
new file mode 100644
index 0000000000000000000000000000000000000000..4413be1f0322c0c4588ecd90915ceb86fa239bba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using24.C
@@ -0,0 +1,12 @@
+// PR c++/26256
+// { dg-do compile }
+
+struct A { int next; };
+struct B { int next; };
+struct C : B { using B::next; };
+
+struct D : A, C
+{
+   using C::next;
+   void f() { next = 1; }
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using25.C b/gcc/testsuite/g++.dg/lookup/using25.C
new file mode 100644
index 0000000000000000000000000000000000000000..eb605700d8d07232c5ab6ec770f89de1f501a82f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using25.C
@@ -0,0 +1,28 @@
+// PR c++/26256
+// { dg-do run }
+
+struct A
+{
+    int next;
+};
+
+struct B
+{
+    int next;
+};
+
+struct C : public A, public B
+{
+    using A::next;
+};
+
+void foo(C& c) { c.next = 42; }
+
+int main()
+{
+    C c;
+    foo (c);
+    c.B::next = 12;
+    if (c.next != 42 || c.A::next != 42 || c.B::next != 12)
+	__builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using26.C b/gcc/testsuite/g++.dg/lookup/using26.C
new file mode 100644
index 0000000000000000000000000000000000000000..141d14581c181a95fa18c03eb2b9eed4f79807cd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using26.C
@@ -0,0 +1,27 @@
+// PR c++/26256
+// { dg-do compile }
+
+struct A
+{
+    double next;
+};
+
+struct B
+{
+private:
+    int next; // { dg-error "private" }
+};
+
+struct C
+{
+    int next;
+};
+
+struct D : A, B, C // { dg-error "context" }
+{
+    using B::next;
+    void f()
+    {
+	next = 12;
+    }
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using27.C b/gcc/testsuite/g++.dg/lookup/using27.C
new file mode 100644
index 0000000000000000000000000000000000000000..c94cf6ea1a5669fe72dd467e43f466c106208f68
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using27.C
@@ -0,0 +1,48 @@
+// PR c++/26256
+// { dg-do run }
+
+struct A
+{
+    typedef int type;
+};
+
+struct B
+{
+    typedef double type;
+};
+
+struct C : A, B
+{
+    using A::type;
+    type d;
+
+    void f()
+    {
+	type e;
+	if (sizeof (type) != sizeof (A::type))
+	    __builtin_abort();
+    }
+
+    void g();
+};
+
+void C::g()
+{
+    type x;
+    if (sizeof (type) != sizeof (A::type))
+	__builtin_abort();
+}
+
+int main ()
+{
+    if (sizeof (C::type) != sizeof (A::type))
+	__builtin_abort();
+
+    if (sizeof (C::d) != sizeof (A::type))
+	__builtin_abort();
+
+    C::type x;
+    C c;
+    c.f();
+    c.g();
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using28.C b/gcc/testsuite/g++.dg/lookup/using28.C
new file mode 100644
index 0000000000000000000000000000000000000000..ae4067a23ea011e153aa16bd9efe26d71685a312
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using28.C
@@ -0,0 +1,11 @@
+// PR c++/26256
+// { dg-do compile }
+
+struct A { int f; };
+struct B { int f; };
+struct C : A, B { using B::f; };
+
+struct D : C
+{
+    void g() { f = 1; }
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using29.C b/gcc/testsuite/g++.dg/lookup/using29.C
new file mode 100644
index 0000000000000000000000000000000000000000..428021cf778712aabbf740f95035670f9c8e5b73
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using29.C
@@ -0,0 +1,81 @@
+// { dg-do compile }
+
+struct A
+{
+  int i;
+};
+
+struct B
+{
+  int i;
+};
+
+struct C : A, B
+{
+  using A::i; // { dg-message "previous" }
+  using B::i; // { dg-error "redeclaration" }
+};
+
+struct E
+{
+  typedef int type;
+};
+
+struct F
+{
+  typedef int type;
+};
+
+struct G : E, F
+{
+  using E::type; // { dg-message "previous" }
+  using F::type; // { dg-error "redeclaration" }
+};
+
+struct H
+{
+  typedef int type;
+};
+
+struct I : H
+{
+  typedef int type; // { dg-message "previous" }
+  using H::type; // { dg-error "conflicts" }
+};
+
+struct I2 : H
+{
+  using H::type; // { dg-message "previous" }
+  typedef int type; // { dg-error "conflicts" }
+};
+
+struct J
+{
+  struct type {};
+};
+
+struct K : J
+{
+  struct type {}; // { dg-message "previous" }
+  using J::type; // { dg-error "conflicts" }
+};
+
+struct L : J
+{
+  using J::type; // { dg-message "previous" }
+  struct type {}; // { dg-error "conflicts" }
+};
+
+struct M
+{
+  typedef int type;
+  struct type2 {};
+};
+
+struct N : M
+{
+  using M::type; // { dg-message "previous" }
+  using M::type; // { dg-error "redeclaration" }
+  using M::type2; // { dg-message "previous" }
+  using M::type2; // { dg-error "redeclaration" }
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using30.C b/gcc/testsuite/g++.dg/lookup/using30.C
new file mode 100644
index 0000000000000000000000000000000000000000..3fbe96c3ce8e3c4c3764f7e5023ea5974830ad6b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using30.C
@@ -0,0 +1,8 @@
+// { dg-do compile }
+
+struct H { typedef int type; };
+struct J : H
+{
+  struct type {}; // { dg-message "previous" }
+  using H::type; // { dg-error "conflicts" }
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using31.C b/gcc/testsuite/g++.dg/lookup/using31.C
new file mode 100644
index 0000000000000000000000000000000000000000..3b1f6e90e10459c3d48ecf18039f6b9b2714708c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using31.C
@@ -0,0 +1,8 @@
+// { dg-do compile }
+
+struct H2 { int f (); };
+struct J2 : H2
+{
+  struct f {};
+  using H2::f;
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using32.C b/gcc/testsuite/g++.dg/lookup/using32.C
new file mode 100644
index 0000000000000000000000000000000000000000..cc0e96ca6b18381ba2bb16390eb0ab3af623c745
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using32.C
@@ -0,0 +1,9 @@
+// { dg-do compile }
+
+struct T { struct type {}; };
+struct T2 : T { using T::type; };
+struct T3 : T2
+{
+  struct type {};
+  type t;
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using33.C b/gcc/testsuite/g++.dg/lookup/using33.C
new file mode 100644
index 0000000000000000000000000000000000000000..a80be036442574f9a99f09274c664c3e983c21d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using33.C
@@ -0,0 +1,26 @@
+// { dg-do run }
+
+template <class T>
+struct Foo
+{
+  int k (float) {return 0;}
+};
+
+template <class T>
+struct Baz
+{
+  int k (int) {return 1;}
+};
+
+template <class T>
+struct Bar : Foo<T> , Baz<T>
+{
+  using Foo<T>::k;
+  using Baz<T>::k;
+};
+
+int main()
+{
+  Bar<int> bar;
+  return bar.k( 1.0f );
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using34.C b/gcc/testsuite/g++.dg/lookup/using34.C
new file mode 100644
index 0000000000000000000000000000000000000000..79c019d0216feedc1bc09e07f4bded1ea1830e4f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using34.C
@@ -0,0 +1,10 @@
+// { dg-do compile }
+
+struct A { int f (); };
+struct B : A
+{
+  using A::f;
+  struct f {};
+  void g() { f(); struct f ff; }
+  struct f ff;
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using35.C b/gcc/testsuite/g++.dg/lookup/using35.C
new file mode 100644
index 0000000000000000000000000000000000000000..e7e82741d643b8f6206676423eada93db1f304e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using35.C
@@ -0,0 +1,11 @@
+// { dg-do compile }
+
+struct A { typedef int type; };
+struct B { typedef int type; };
+struct C : B { using B::type; };
+
+struct D : A, C
+{
+  using C::type;
+  void f() { type t = 0;}
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using36.C b/gcc/testsuite/g++.dg/lookup/using36.C
new file mode 100644
index 0000000000000000000000000000000000000000..966c60b896147b8981203c8c2bec92989476ca4f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using36.C
@@ -0,0 +1,31 @@
+// PR c++/25994
+// { dg-do run }
+
+struct B1
+{
+  void f (char) {}
+  void f (double) { __builtin_abort(); }
+};
+
+struct B2
+{
+  void f (double) { __builtin_abort(); }
+  void f (int) {}
+};
+
+struct D : public B1, public B2
+{
+  using B1::f;
+  using B2::f;
+  void g ()
+  {
+    f ('a');           // should call B1::f(char)
+    f (33);            // should call B2::f(int)
+  }
+};
+
+int main()
+{
+  D d;
+  d.g();
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using37.C b/gcc/testsuite/g++.dg/lookup/using37.C
new file mode 100644
index 0000000000000000000000000000000000000000..a71206e89f763b10a394cab283a42c924719b3e4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using37.C
@@ -0,0 +1,22 @@
+// PR c++/30195
+// { dg-do run }
+
+template<class T> struct B
+{
+    void foo(T) {}
+};
+
+template<class T>
+struct D : B<int>, B<double>
+{
+  using B<int>::foo;
+  using B<double>::foo;
+  void bar() { foo(3); }
+};
+
+int main()
+{
+  D<int> x;
+  x.bar();
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using38.C b/gcc/testsuite/g++.dg/lookup/using38.C
new file mode 100644
index 0000000000000000000000000000000000000000..377fbcce1e3142e1268be72b32d66e751be82f9e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using38.C
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// PR c++/6936
+
+struct Baser
+{
+    enum { j, i }; // { dg-error "inaccessible" }
+};
+
+struct Base : Baser
+{
+    static void j();
+    static void i();
+};
+
+struct Derv : Base
+{
+  using Baser::j;
+private:
+  using Baser::i;
+};
+
+int k = Derv::j;
+int l = Derv::i; // { dg-error "context" }
diff --git a/gcc/testsuite/g++.dg/lookup/using39.C b/gcc/testsuite/g++.dg/lookup/using39.C
new file mode 100644
index 0000000000000000000000000000000000000000..56ae89a4a2251f68c32a7228324c6b0f4aa8dea0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using39.C
@@ -0,0 +1,63 @@
+// { dg-do run }
+
+template <class T>
+struct A
+{
+    int f() { return 1; }
+};
+
+template <class T>
+struct B : A<T>
+{
+    int f() { return 2; }
+
+    using A<T>::f;
+    void g()
+    {
+	if (A<T>::f() != 1 )
+	    __builtin_abort();
+
+	if( B<T>::f() != 2 )
+	    __builtin_abort();
+
+	if( this->f() != 2 )
+	    __builtin_abort();
+    }
+};
+
+template <class T>
+struct C
+{
+    int h( int i ) { return 1; }
+    int h( double d ) { return 2; }
+};
+
+template <class T>
+struct D : private C<T>
+{
+    using C<T>::h;
+    int h( char c ) { return 0; }
+    int h() { return 3; }
+};
+
+int main()
+{
+    B<int> b;
+    b.g();
+    b.f();
+    b.A<int>::f();
+    b.B<int>::f();
+
+    D<int> d;
+    if( d.h( 'a' ) != 0 )
+	__builtin_abort();
+
+    if( d.h( 3 ) != 1 )
+	__builtin_abort();
+
+    if( d.h( 3.14 ) != 2 )
+	__builtin_abort();
+
+    if( d.h() != 3 )
+	__builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using40.C b/gcc/testsuite/g++.dg/lookup/using40.C
new file mode 100644
index 0000000000000000000000000000000000000000..1bcdd0dbf5e31933fbfb4d5496f85132f4f92319
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using40.C
@@ -0,0 +1,28 @@
+// { dg-do compile }
+
+struct Base
+{
+    void f();
+    typedef int type;
+    struct Type {};
+    int i;
+    static int j;
+};
+
+struct A : Base
+{
+    using Base::f; // { dg-message "previous declaration" }
+    using Base::f; // { dg-error "redeclaration" }
+
+    using Base::type; // { dg-message "previous declaration" }
+    using Base::type; // { dg-error "redeclaration" }
+
+    using Base::Type; // { dg-message "previous declaration" }
+    using Base::Type; // { dg-error "redeclaration" }
+
+    using Base::i; // { dg-message "previous declaration" }
+    using Base::i; // { dg-error "redeclaration" }
+
+    using Base::j; // { dg-message "previous declaration" }
+    using Base::j; // { dg-error "redeclaration" }
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using41.C b/gcc/testsuite/g++.dg/lookup/using41.C
new file mode 100644
index 0000000000000000000000000000000000000000..dcc618ba56847e48e88c09bd9a9ff56b51ee1633
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using41.C
@@ -0,0 +1,21 @@
+// { dg-do compile }
+
+template <class T>
+struct Base
+{
+    void f();
+};
+
+template <class T>
+struct A : Base<T>
+{
+    using Base<T>::f; // { dg-message "previous declaration" }
+    using Base<T>::f; // { dg-error "redeclaration" }
+};
+
+template <class T, class U>
+struct B : Base<T>, Base<U>
+{
+    using Base<T>::f;
+    using Base<U>::f;
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using42.C b/gcc/testsuite/g++.dg/lookup/using42.C
new file mode 100644
index 0000000000000000000000000000000000000000..bca65acc74fedc0d162115da97b515ba8caa84b7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using42.C
@@ -0,0 +1,26 @@
+// PR c++/30195
+// { dg-do run }
+
+template <class T>
+struct B
+{
+    void foo(T) {}
+};
+
+template<class T>
+struct Out
+{
+    struct D : B<T>, B<double>
+    {
+	using B<T>::foo;
+	using B<double>::foo;
+	void bar() { foo(3); }
+    };
+};
+
+int main()
+{
+    Out<int>::D x;
+    x.bar();
+    return 0;
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using44.C b/gcc/testsuite/g++.dg/lookup/using44.C
new file mode 100644
index 0000000000000000000000000000000000000000..d754befd0a4378a180aaaaeb632658716402fca8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using44.C
@@ -0,0 +1,28 @@
+// PR c++/30195
+// { dg-do run }
+
+template <class T>
+struct B
+{
+    void foo(char) { __builtin_abort(); }
+    void foo(short) { __builtin_abort(); }
+    void foo(T) {}
+};
+
+template<class T>
+struct Out
+{
+    struct D : B<T>, B<double>
+    {
+	using B<T>::foo;
+	using B<double>::foo;
+	void bar() { foo(3); }
+    };
+};
+
+int main()
+{
+    Out<int>::D x;
+    x.bar();
+    return 0;
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using45.C b/gcc/testsuite/g++.dg/lookup/using45.C
new file mode 100644
index 0000000000000000000000000000000000000000..c92b794d9c5099f009a2ba6c76cbe7c613df369d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using45.C
@@ -0,0 +1,33 @@
+// PR c++/30195
+// { dg-do run }
+
+template <class T>
+struct A
+{
+    int f(int) { return 0; }
+    int f(double) { return 1; }
+    int f(char) { return 2; }
+};
+
+template <class T>
+struct B : A<T>
+{
+    using A<T>::f;
+    int f(int) { return 3; }
+};
+
+int main()
+{
+    B<int> b;
+    if( b.f( 42 ) != 3 )
+	__builtin_abort();
+
+    if( b.f( 3.14 ) != 1 )
+	__builtin_abort();
+
+    if( b.f( 'a' ) != 2 )
+	__builtin_abort();
+
+    if( b.A<int>::f( 42 ) != 0 )
+	__builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/parse/ctor5.C b/gcc/testsuite/g++.dg/parse/ctor5.C
index 3ea23549c0bbf20b3241c798a66f6029ff5ac760..f980b4a184f562673acaa55540a1c2a267f08609 100644
--- a/gcc/testsuite/g++.dg/parse/ctor5.C
+++ b/gcc/testsuite/g++.dg/parse/ctor5.C
@@ -2,7 +2,7 @@
 
 struct A
 {
-  int i; // { dg-error "conflicts" }
+  int i; // { dg-message "previous" }
   A() i() {}  // { dg-error "declaration" }
 };
 
diff --git a/gcc/testsuite/g++.dg/template/static4.C b/gcc/testsuite/g++.dg/template/static4.C
index c5486326cddcc8672789454130ad478fade85a8c..526ced67e51822f3594e075fcc3de6ddda6fe493 100644
--- a/gcc/testsuite/g++.dg/template/static4.C
+++ b/gcc/testsuite/g++.dg/template/static4.C
@@ -1,6 +1,6 @@
 template <class R>
 struct A {
-  static int _test; // { dg-error "" }
+  static int _test; // { dg-message "" }
   static int _test; // { dg-error "" }
 };
 template <class R> int A<R>::_test = 0;
diff --git a/gcc/testsuite/g++.dg/template/typedef1.C b/gcc/testsuite/g++.dg/template/typedef1.C
index 75b00e0fb2a68c8fcf3d65a06ff25ed07f950b00..270adcdc9840d0406930ba303351910416ef1465 100644
--- a/gcc/testsuite/g++.dg/template/typedef1.C
+++ b/gcc/testsuite/g++.dg/template/typedef1.C
@@ -12,7 +12,7 @@ template <typename T> struct A
 
 template <typename T> struct B
 {
-  typedef int xxx; // { dg-error "" }
+  typedef int xxx; // { dg-message "" }
   typedef T xxx; // { dg-error "" }
   typedef typename A<T>::type xxx; // { dg-error "" }
   typedef A<int>::type xxx; // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/template/using2.C b/gcc/testsuite/g++.dg/template/using2.C
index 6dd9ef46ce73bb6b8fe2d450e1cf319a7b6b93d3..5987254d432f7d43d82ebe9858a94475d2e87408 100644
--- a/gcc/testsuite/g++.dg/template/using2.C
+++ b/gcc/testsuite/g++.dg/template/using2.C
@@ -7,24 +7,25 @@
 
 template <class T>
 struct Foo {
-  int i; // { dg-error "Foo" }
+  int i;
 };
 
 struct Baz 
 {
-  int i; // { dg-error "Baz" }
+  int i;
 };
 
 template <class T>
-struct Bar : public Foo<T>, Baz {
-  using Foo<T>::i;
-  using Baz::i;
+struct Bar : public Foo<T>, Baz
+{
+  using Foo<T>::i; // { dg-message "previous declaration" }
+  using Baz::i; // { dg-error "redeclaration" }
 
-  int foo () { return i; } // { dg-error "request for member" }
+  int foo () { return i; }
 };
 
 void foo (Bar<int> &bar)
 {
-  bar.foo(); // { dg-message "required" }
+  bar.foo();
 }
 
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/misc14.C b/gcc/testsuite/g++.old-deja/g++.brendan/misc14.C
index d2e49095a3b64f3837e6c836ba14b48582bca4e7..ea6ce4c74c761b52892eefa9c718d0dce207c120 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/misc14.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/misc14.C
@@ -3,11 +3,11 @@
 class X {
 public:
     enum e {
-	New // { dg-error "conflicts with previous" }
+	New // { dg-message "previous" }
 	,   // { dg-error "comma at end" "" { target c++98 } }
     };
 
-    static int New(int); // { dg-error "declaration of" }
+    static int New(int); // { dg-error "conflicts with a previous" }
 };
 
 int main() {}
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900127_02.C b/gcc/testsuite/g++.old-deja/g++.bugs/900127_02.C
index 0ae23881fc44b08470e5c58db039683a65ae836a..12ae64a36a0f6771d42a9f98ccb1a923c35756ba 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900127_02.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900127_02.C
@@ -23,12 +23,12 @@ int global1 ();			// { dg-error "" } xref for below
 int global1;			// { dg-error "" } caught
 
 struct struct_0 {
-  int class_local ();		// { dg-error "" } 
+  int class_local ();		// { dg-message "" }
   int class_local;		// { dg-error "" } 
 };
 
 struct struct_1 {
-  int class_local;		// { dg-error "" } 
+  int class_local;		// { dg-message "" }
   int class_local ();		// { dg-error "" } 
 };
 
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/scoping16.C b/gcc/testsuite/g++.old-deja/g++.jason/scoping16.C
index 9b9d915ba4eedf58e3ba295593ee105078e9541e..1c225c75f784e0ccc3242e2d173750d5a737410f 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/scoping16.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/scoping16.C
@@ -1,5 +1,5 @@
 // { dg-do assemble  }
 struct A {
-  int a();			// { dg-error "" } 
+  int a();			// { dg-message "" }
   int a;			// { dg-error "" } 
 };
diff --git a/gcc/testsuite/g++.old-deja/g++.other/anon7.C b/gcc/testsuite/g++.old-deja/g++.other/anon7.C
index ebc378005cd7686f23691aefc612ffe8204b5aef..6a951a97c62177c72cfb14d15a50550216411674 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/anon7.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/anon7.C
@@ -2,13 +2,13 @@
 
 struct A {
   union {
-    int a;	// { dg-error "" } conflicts with previous declaration
+    int a;	// { dg-message "" } conflicts with previous declaration
   };
   int a;	// { dg-error "" } 
 };
 
 struct B {
-  int b;	// { dg-error "" } conflicts with previous declaration
+  int b;	// { dg-message "" } conflicts with previous declaration
   union {
     int b;	// { dg-error "" } duplicate member
   };
@@ -16,7 +16,7 @@ struct B {
 
 struct C {
   union {
-    int c;	// { dg-error "" } conflicts with previous declaration
+    int c;	// { dg-message "" } conflicts with previous declaration
   };
   union {
     int c;	// { dg-error "" } duplicate member
diff --git a/gcc/testsuite/g++.old-deja/g++.other/redecl1.C b/gcc/testsuite/g++.old-deja/g++.other/redecl1.C
index bd6382ee0528c1112410261496a4977e703c418b..d979786587580b636ff76fe0c8da78c3162cc38d 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/redecl1.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/redecl1.C
@@ -1,6 +1,6 @@
 // { dg-do assemble  }
 struct X{
   void i();
-  void i(int);  // { dg-error "" } 
+  void i(int);  // { dg-message "" }
   int i;        // { dg-error "" } conflict
 };
diff --git a/gcc/testsuite/g++.old-deja/g++.other/typedef7.C b/gcc/testsuite/g++.old-deja/g++.other/typedef7.C
index 42cf4f1c5e23a55901da6c1bc5d2b7806a8a85e2..93784c08d8707279ce37e6ce8f2a99e2cc08bd48 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/typedef7.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/typedef7.C
@@ -8,13 +8,13 @@ typedef int I;
 // invalid.
 
 struct A {
-  typedef int I; // { dg-error "" }
+  typedef int I; // { dg-message "" }
   typedef int I; // { dg-error "" }
 };
 
 template <class T>
 struct S {
-  typedef int I;  // { dg-error "" }
+  typedef int I;  // { dg-message "" }
   typedef int I;  // { dg-error "" }
 };
 
diff --git a/gcc/testsuite/g++.old-deja/g++.other/using1.C b/gcc/testsuite/g++.old-deja/g++.other/using1.C
index d734576ac8c3abed2490e3d759c252bb23455cbb..48c29f79b19994fcaf7d91b74c6015388aa26408 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/using1.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/using1.C
@@ -16,12 +16,12 @@ public:
   using B::b;
 };
 
-class D2 : public B { // { dg-error "" } conflicting access specifications
+class D2 : public B {
 public:
   using B::a;
-  using B::b;
+  using B::b; // { dg-message "" } conflicting declaration
 
 private:
-  using B::b; 
+  using B::b; // { dg-error "" } conflicts
 };