From patchwork Sun Sep 25 20:24:15 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Fabien_Ch=C3=AAne?= X-Patchwork-Id: 116328 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 40BFFB6F72 for ; Mon, 26 Sep 2011 08:11:19 +1000 (EST) Received: (qmail 29474 invoked by alias); 25 Sep 2011 20:24:37 -0000 Received: (qmail 29460 invoked by uid 22791); 25 Sep 2011 20:24:33 -0000 X-SWARE-Spam-Status: No, hits=-2.5 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, TW_CX, TW_FN X-Spam-Check-By: sourceware.org Received: from mail-qy0-f175.google.com (HELO mail-qy0-f175.google.com) (209.85.216.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sun, 25 Sep 2011 20:24:16 +0000 Received: by qyk10 with SMTP id 10so7799598qyk.20 for ; Sun, 25 Sep 2011 13:24:15 -0700 (PDT) MIME-Version: 1.0 Received: by 10.229.68.198 with SMTP id w6mr4220571qci.9.1316982255422; Sun, 25 Sep 2011 13:24:15 -0700 (PDT) Received: by 10.229.133.78 with HTTP; Sun, 25 Sep 2011 13:24:15 -0700 (PDT) In-Reply-To: <46E788AC-54C0-45AE-A435-BD2F0950C0C2@oracle.com> References: <4C6E0571.3070802@redhat.com> <4D1279FD.6010706@redhat.com> <4D7297F5.2000708@redhat.com> <4E020BE2.7080207@redhat.com> <4E77D811.5000701@redhat.com> <4E7A28A0.8020805@redhat.com> <4E7B5816.6010802@redhat.com> <4E7BB7A5.8020305@redhat.com> <46E788AC-54C0-45AE-A435-BD2F0950C0C2@oracle.com> Date: Sun, 25 Sep 2011 22:24:15 +0200 Message-ID: Subject: Re: [Patch] PR c++/26256 From: =?ISO-8859-1?Q?Fabien_Ch=EAne?= To: Paolo Carlini Cc: Jason Merrill , "gcc-patches@gcc.gnu.org" X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 2011/9/25 Paolo Carlini : > ... nitpicking, of course, but in the testcases you have many blank trailing lines (and also some gratuitus, imho, blank lines in the middle) Indeed, I've removed the blank trailing lines, and some in the middle, not all though, I like it readable as well ;-) 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 +struct Foo +{ + int k (float) {return 0;} +}; + +template +struct Baz +{ + int k (int) {return 1;} +}; + +template +struct Bar : Foo , Baz +{ + using Foo::k; + using Baz::k; +}; + +int main() +{ + Bar 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 struct S1 +{ + enum E : T; // { dg-error "previous definition" } + enum E : int; // { dg-error "different underlying type" } +}; +template struct S1; // { dg-message "required from here" } + +template struct S2 +{ + enum E : T; + enum E : T; +}; +template struct S2; + +template struct S3 +{ + enum E : T1; + enum E : T2; +}; +template struct S3; + +template struct S4 +{ + enum E : T1; // { dg-error "previous definition" } + enum E : T2; // { dg-error "different underlying type" } +}; +template struct S4; // { 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 struct Foo { - int i; // { dg-error "Foo" } + int i; }; struct Baz { - int i; // { dg-error "Baz" } + int i; }; template -struct Bar : public Foo, Baz { - using Foo::i; - using Baz::i; +struct Bar : public Foo, Baz +{ + using Foo::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 &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 (tiemann@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) @@ -1423,7 +1418,7 @@ lookup_fnfields_1 (tree type, tree name) #endif /* GATHER_STATISTICS */ tmp = VEC_index (tree, method_vec, i); - tmp = DECL_NAME (OVL_CURRENT (tmp)); + tmp = DECL_NAME (strip_using_decl (OVL_CURRENT (tmp))); if (tmp > name) hi = i; else if (tmp < name) @@ -1438,7 +1433,7 @@ lookup_fnfields_1 (tree type, tree name) #ifdef GATHER_STATISTICS n_outer_fields_searched++; #endif /* GATHER_STATISTICS */ - if (DECL_NAME (OVL_CURRENT (fn)) == name) + if (DECL_NAME (strip_using_decl (OVL_CURRENT (fn))) == name) return i; } 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