Jason, Please ignore the previous patch, where I have introduced an unintentional modification for PR c++/30195 in search.c, here is a new one, sorry about that.
-- Fabien
Index: gcc/testsuite/g++.old-deja/g++.other/using1.C =================================================================== --- gcc/testsuite/g++.old-deja/g++.other/using1.C (revision 178088) +++ gcc/testsuite/g++.old-deja/g++.other/using1.C (working copy) @@ -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 }; Index: gcc/testsuite/g++.dg/debug/using4.C =================================================================== --- gcc/testsuite/g++.dg/debug/using4.C (revision 0) +++ gcc/testsuite/g++.dg/debug/using4.C (revision 0) @@ -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; +} Index: gcc/testsuite/g++.dg/debug/using5.C =================================================================== --- gcc/testsuite/g++.dg/debug/using5.C (revision 0) +++ gcc/testsuite/g++.dg/debug/using5.C (revision 0) @@ -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; +} Index: gcc/testsuite/g++.dg/lookup/using36.C =================================================================== --- gcc/testsuite/g++.dg/lookup/using36.C (revision 0) +++ gcc/testsuite/g++.dg/lookup/using36.C (revision 0) @@ -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(); +} Index: gcc/testsuite/g++.dg/lookup/using24.C =================================================================== --- gcc/testsuite/g++.dg/lookup/using24.C (revision 0) +++ gcc/testsuite/g++.dg/lookup/using24.C (revision 0) @@ -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; } +}; Index: gcc/testsuite/g++.dg/lookup/using28.C =================================================================== --- gcc/testsuite/g++.dg/lookup/using28.C (revision 0) +++ gcc/testsuite/g++.dg/lookup/using28.C (revision 0) @@ -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; } +}; Index: gcc/testsuite/g++.dg/lookup/using33.C =================================================================== --- gcc/testsuite/g++.dg/lookup/using33.C (revision 0) +++ gcc/testsuite/g++.dg/lookup/using33.C (revision 0) @@ -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 ); +} Index: gcc/testsuite/g++.dg/lookup/using25.C =================================================================== --- gcc/testsuite/g++.dg/lookup/using25.C (revision 0) +++ gcc/testsuite/g++.dg/lookup/using25.C (revision 0) @@ -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(); +} Index: gcc/testsuite/g++.dg/lookup/using29.C =================================================================== --- gcc/testsuite/g++.dg/lookup/using29.C (revision 0) +++ gcc/testsuite/g++.dg/lookup/using29.C (revision 0) @@ -0,0 +1,81 @@ +// { dg-do compile } + +struct A +{ + int i; +}; + +struct B +{ + int i; +}; + +struct C : A, B +{ + using A::i; // { dg-error "conflicts with previous" } + using B::i; // { dg-error "declaration" } +}; + +struct E +{ + typedef int type; +}; + +struct F +{ + typedef int type; +}; + +struct G : E, F +{ + using E::type; // { dg-error "conflicts with previous" } + using F::type; // { dg-error "declaration" } +}; + +struct H +{ + typedef int type; +}; + +struct I : H +{ + typedef int type; // { dg-error "conflicts with previous" } + using H::type; // { dg-error "declaration" } +}; + +struct I2 : H +{ + using H::type; // { dg-error "conflicts with previous" } + typedef int type; // { dg-error "declaration" } +}; + +struct J +{ + struct type {}; +}; + +struct K : J +{ + struct type {}; // { dg-error "conflicts with previous" } + using J::type; // { dg-error "declaration" } +}; + +struct L : J +{ + using J::type; // { dg-error "conflicts with previous" } + struct type {}; // { dg-error "declaration" } +}; + +struct M +{ + typedef int type; + struct type2 {}; +}; + +struct N : M +{ + using M::type; // { dg-error "conflicts with previous" } + using M::type; // { dg-error "declaration" } + using M::type2; // { dg-error "conflicts with previous" } + using M::type2; // { dg-error "declaration" } +}; Index: gcc/testsuite/g++.dg/lookup/using30.C =================================================================== --- gcc/testsuite/g++.dg/lookup/using30.C (revision 0) +++ gcc/testsuite/g++.dg/lookup/using30.C (revision 0) @@ -0,0 +1,8 @@ +// { dg-do compile } + +struct H { typedef int type; }; +struct J : H +{ + struct type {}; // { dg-error "conflicts with previous" } + using H::type; // { dg-error "declaration" } +}; Index: gcc/testsuite/g++.dg/lookup/using34.C =================================================================== --- gcc/testsuite/g++.dg/lookup/using34.C (revision 0) +++ gcc/testsuite/g++.dg/lookup/using34.C (revision 0) @@ -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; +}; Index: gcc/testsuite/g++.dg/lookup/using26.C =================================================================== --- gcc/testsuite/g++.dg/lookup/using26.C (revision 0) +++ gcc/testsuite/g++.dg/lookup/using26.C (revision 0) @@ -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; + } +}; Index: gcc/testsuite/g++.dg/lookup/using31.C =================================================================== --- gcc/testsuite/g++.dg/lookup/using31.C (revision 0) +++ gcc/testsuite/g++.dg/lookup/using31.C (revision 0) @@ -0,0 +1,8 @@ +// { dg-do compile } + +struct H2 { int f (); }; +struct J2 : H2 +{ + struct f {}; + using H2::f; +}; Index: gcc/testsuite/g++.dg/lookup/using35.C =================================================================== --- gcc/testsuite/g++.dg/lookup/using35.C (revision 0) +++ gcc/testsuite/g++.dg/lookup/using35.C (revision 0) @@ -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;} +}; Index: gcc/testsuite/g++.dg/lookup/using23.C =================================================================== --- gcc/testsuite/g++.dg/lookup/using23.C (revision 0) +++ gcc/testsuite/g++.dg/lookup/using23.C (revision 0) @@ -0,0 +1,19 @@ +// PR c++/26256 +// { dg-do compile } + +struct A +{ +private: + typedef int type; // { dg-error "private" } +}; + +struct B +{ + typedef double type; +}; + +struct C : A, B // { dg-error "context" } +{ + using A::type; + type d; +}; Index: gcc/testsuite/g++.dg/lookup/using27.C =================================================================== --- gcc/testsuite/g++.dg/lookup/using27.C (revision 0) +++ gcc/testsuite/g++.dg/lookup/using27.C (revision 0) @@ -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(); +} Index: gcc/testsuite/g++.dg/lookup/using32.C =================================================================== --- gcc/testsuite/g++.dg/lookup/using32.C (revision 0) +++ gcc/testsuite/g++.dg/lookup/using32.C (revision 0) @@ -0,0 +1,9 @@ +// { dg-do compile } + +struct T { struct type {}; }; +struct T2 : T { using T::type; }; +struct T3 : T2 +{ + struct type {}; + type t; +}; Index: gcc/testsuite/g++.dg/cpp0x/forw_enum10.C =================================================================== --- gcc/testsuite/g++.dg/cpp0x/forw_enum10.C (revision 0) +++ gcc/testsuite/g++.dg/cpp0x/forw_enum10.C (revision 0) @@ -0,0 +1,32 @@ +// { 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" } + Index: gcc/testsuite/g++.dg/template/using2.C =================================================================== --- gcc/testsuite/g++.dg/template/using2.C (revision 178088) +++ gcc/testsuite/g++.dg/template/using2.C (working copy) @@ -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 "conflicts with previous" } + using Baz::i; // { dg-error "declaration" } - 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(); } Index: gcc/cp/typeck.c =================================================================== --- gcc/cp/typeck.c (revision 178088) +++ gcc/cp/typeck.c (working copy) @@ -2109,6 +2109,7 @@ build_class_member_access_expr (tree obj 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; @@ -2329,6 +2330,11 @@ build_class_member_access_expr (tree obj 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) Index: gcc/cp/class.c =================================================================== --- gcc/cp/class.c (revision 178088) +++ gcc/cp/class.c (working copy) @@ -1053,9 +1053,6 @@ add_method (tree type, tree method, tree 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 { @@ -3016,15 +3013,8 @@ check_field_decls (tree t, tree *access_ 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; } Index: gcc/cp/decl.c =================================================================== --- gcc/cp/decl.c (revision 178088) +++ gcc/cp/decl.c (working copy) @@ -11937,8 +11937,20 @@ start_enum (tree name, tree enumtype, tr *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 */ + 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; Index: gcc/cp/semantics.c =================================================================== --- gcc/cp/semantics.c (revision 178088) +++ gcc/cp/semantics.c (working copy) @@ -2670,8 +2670,7 @@ 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)) { /* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields go at the beginning. The reason is that lookup_field_1 Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revision 178088) +++ gcc/cp/parser.c (working copy) @@ -13046,6 +13046,9 @@ cp_parser_nonclass_name (cp_parser* pars /* 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))) { Index: gcc/cp/cp-tree.h =================================================================== --- gcc/cp/cp-tree.h (revision 178088) +++ gcc/cp/cp-tree.h (working copy) @@ -5776,7 +5776,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++ */ Index: gcc/cp/search.c =================================================================== --- gcc/cp/search.c (revision 178088) +++ gcc/cp/search.c (working copy) @@ -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 (tiem...@cygnus.com) @@ -449,6 +449,8 @@ lookup_field_1 (tree type, tree name, bo #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,19 @@ lookup_field_1 (tree type, tree name, bo if (temp) return temp; } - if (TREE_CODE (field) == USING_DECL) + + if (TREE_CODE (decl) == USING_DECL) { - /* 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_CLASS_TEMPLATE_P (field))) - return field; + || TREE_CODE (decl) == TYPE_DECL + || DECL_CLASS_TEMPLATE_P (decl))) + return decl; } /* Not found. */ if (name == vptr_identifier) Index: gcc/cp/name-lookup.c =================================================================== --- gcc/cp/name-lookup.c (revision 178088) +++ gcc/cp/name-lookup.c (working copy) @@ -394,6 +394,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 +427,45 @@ supplement_binding_1 (cxx_binding *bindi { tree bval = binding->value; bool ok = true; + tree target_bval = strip_using_decl (bval); + tree target_decl = strip_using_decl (decl); - if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (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 + 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. */ - !bval - /* BVAL is error_mark_node when DECL's name has been used + !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. */ - || bval == error_mark_node - /* If BVAL is anticipated but has not yet been declared, + || 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 (bval) == FUNCTION_DECL - && DECL_ANTICIPATED (bval) - && !DECL_HIDDEN_FRIEND_P (bval))) + || (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 +476,15 @@ supplement_binding_1 (cxx_binding *bindi 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 +506,9 @@ supplement_binding_1 (cxx_binding *bindi 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; @@ -3018,6 +3044,8 @@ push_class_level_binding_1 (tree name, t { 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)) { @@ -3025,8 +3053,8 @@ push_class_level_binding_1 (tree name, t 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; @@ -3038,18 +3066,21 @@ push_class_level_binding_1 (tree name, t 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)) - old_decl = bval; - else if (TREE_CODE (x) == USING_DECL && TREE_CODE (bval) == USING_DECL) - return true; - else if (TREE_CODE (x) == USING_DECL && is_overloaded_fn (bval)) + else if (TREE_CODE (target_decl) == OVERLOAD && is_overloaded_fn (target_bval)) old_decl = bval; - else if (TREE_CODE (bval) == USING_DECL && is_overloaded_fn (x)) + else if (TREE_CODE (decl) == USING_DECL + && DECL_DEPENDENT_P (decl) + && TREE_CODE (bval) == USING_DECL + && DECL_DEPENDENT_P (bval)) return true; + 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 (target_decl)) + return true; if (old_decl && binding->scope == class_binding_level) { Index: gcc/dbxout.c =================================================================== --- gcc/dbxout.c (revision 178088) +++ gcc/dbxout.c (working copy) @@ -1518,6 +1518,8 @@ dbxout_type_fields (tree type) if (TREE_CODE (tem) == TYPE_DECL /* Omit here the nameless fields that are used to skip bits. */ || DECL_IGNORED_P (tem) + /* Omit USING_DECL */ + || TREE_CODE (tem) >= LAST_AND_UNUSED_TREE_CODE /* Omit fields whose position or size are variable or too large to represent. */ || (TREE_CODE (tem) == FIELD_DECL