Index: gcc/testsuite/g++.old-deja/g++.other/using1.C =================================================================== --- gcc/testsuite/g++.old-deja/g++.other/using1.C (revision 160857) +++ gcc/testsuite/g++.old-deja/g++.other/using1.C (working copy) @@ -19,9 +19,9 @@ public: class D2 : public B { // { dg-error "" } conflicting access specifications 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++.old-deja/g++.other/using8.C =================================================================== --- gcc/testsuite/g++.old-deja/g++.other/using8.C (revision 160857) +++ gcc/testsuite/g++.old-deja/g++.other/using8.C (working copy) @@ -14,10 +14,6 @@ struct A void D (); }; -struct A2 { - typedef int f; -}; - struct B : A { using A::f; 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/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/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,87 @@ +// { dg-do compile } + +struct A +{ + int i; +}; + +struct B +{ + int i; +}; + + +struct C : A, B +{ + using A::i; // { dg-message "conflicting using declaration" } + using B::i; // { dg-error "using declaration" } +}; + + +struct E +{ + typedef int type; +}; + +struct F +{ + typedef int type; +}; + +struct G : E, F +{ + using E::type; // { dg-message "conflicting using declaration" } + using F::type; // { dg-error "using declaration" } +}; + + +struct H +{ + typedef int type; +}; + +struct I : H +{ + typedef int type; // { dg-message "local member" } + using H::type; // { dg-error "invalid" } +}; + + +struct I2 : H +{ + using H::type; // { dg-message "conflicting using declaration" } + typedef int type; // { dg-error "conflicts" } +}; + + +struct J +{ + struct type {}; +}; + +struct K : J +{ + struct type {}; // { dg-message "local member" } + using J::type; // { dg-error "invalid" } +}; + +struct L : J +{ + using J::type; // { dg-message "conflicting using declaration" } + struct type {}; // { dg-error "conflicts" } +}; + + +struct M +{ + typedef int type; + struct type2 {}; +}; + +struct N : M +{ + using M::type; // { dg-message "conflicting using declaration" } + using M::type; // { dg-error "conflicts" } + using M::type2; // { dg-message "conflicting using declaration" } + using M::type2; // { dg-error "conflicts" } +}; 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/using23.C =================================================================== --- gcc/testsuite/g++.dg/lookup/using23.C (revision 0) +++ gcc/testsuite/g++.dg/lookup/using23.C (revision 0) @@ -0,0 +1,21 @@ +// 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; // { dg-error "context" } +}; + + 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,49 @@ +// 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/template/using2.C =================================================================== --- gcc/testsuite/g++.dg/template/using2.C (revision 160857) +++ 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 "conflicting using declaration" } + using Baz::i; // { dg-error "conflicts" } - int foo () { return i; } // { dg-error "request for member" } + int foo () { return i; } }; void foo (Bar &bar) { - bar.foo(); // { dg-message "instantiated" } + bar.foo(); } Index: gcc/cp/typeck.c =================================================================== --- gcc/cp/typeck.c (revision 160857) +++ gcc/cp/typeck.c (working copy) @@ -1,6 +1,6 @@ /* Build expressions with type checking for C++ compiler. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) @@ -2400,6 +2400,11 @@ build_class_member_access_expr (tree obj result = build2 (COMPOUND_EXPR, TREE_TYPE (result), object, result); } + else if (TREE_CODE (member) == USING_DECL) + result = build_class_member_access_expr (object, + USING_DECL_DECLS (member), + access_path, preserve_reference, + complain); else { if (complain & tf_error) Index: gcc/cp/class.c =================================================================== --- gcc/cp/class.c (revision 160857) +++ gcc/cp/class.c (working copy) @@ -207,6 +207,7 @@ static bool base_derived_from (tree, tre static int empty_base_at_nonzero_offset_p (tree, tree, splay_tree); static tree end_of_base (tree); static tree get_vcall_index (tree, tree); +static bool diagnose_conflicting_using_decls (tree, tree, tree); /* Variables shared between class.c and call.c. */ @@ -1222,7 +1223,8 @@ handle_using_decl (tree using_decl, tree return; } } - else if (!DECL_ARTIFICIAL (old_value)) + else if (!DECL_ARTIFICIAL (old_value) + || TREE_CODE (decl) != FUNCTION_DECL) { error ("%q+D invalid in %q#T", using_decl, t); error (" because of local member %q+#D with same name", old_value); @@ -2873,6 +2875,29 @@ check_field_decl (tree field, } } +/* Issue an error if USING_DECL conflicts with a DECL already in + scope. If REAL_DECL is a using declaration, then DECL == + USING_DECL_DECLS (REAL_DECL); otherwise, DECL and USING_DECL_DECLS + are the same. */ +static bool +diagnose_conflicting_using_decls (tree decl, tree real_decl, tree using_decl) +{ + if ((TREE_CODE (decl) == FIELD_DECL + || TREE_CODE (decl) == TYPE_DECL) + && TREE_CODE (USING_DECL_DECLS (using_decl)) != FUNCTION_DECL + && DECL_NAME (decl) == DECL_NAME (using_decl)) + { + error_at (DECL_SOURCE_LOCATION (real_decl), + "declaration %qD conflicts with a using declaration " + "already in scope", real_decl); + inform (DECL_SOURCE_LOCATION (using_decl), + "conflicting using declaration %qD", using_decl); + return true; + } + return false; +} + + /* Check the data members (both static and non-static), class-scoped typedefs, etc., appearing in the declaration of T. Issue appropriate diagnostics. Sets ACCESS_DECLS to a list (in @@ -2928,15 +2953,17 @@ check_field_decls (tree t, tree *access_ if (TREE_CODE (x) == USING_DECL) { - /* Prune the access declaration from the list of fields. */ - *field = TREE_CHAIN (x); + tree f; + for (f = x; f != NULL_TREE; f = TREE_CHAIN (f)) + { + if (f != x + && !diagnose_conflicting_using_decls (f, f, x) + && TREE_CODE (f) == USING_DECL) + diagnose_conflicting_using_decls (USING_DECL_DECLS (f), f, 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/semantics.c =================================================================== --- gcc/cp/semantics.c (revision 160857) +++ gcc/cp/semantics.c (working copy) @@ -2489,7 +2489,8 @@ finish_member_declaration (tree decl) also keep a pointer to the correct insertion points in the list.) */ - if (TREE_CODE (decl) == TYPE_DECL) + if (TREE_CODE (decl) == TYPE_DECL + || TREE_CODE (decl) == USING_DECL) TYPE_FIELDS (current_class_type) = chainon (TYPE_FIELDS (current_class_type), decl); else Index: gcc/cp/search.c =================================================================== --- gcc/cp/search.c (revision 160857) +++ 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 + 1999, 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) @@ -460,19 +460,18 @@ lookup_field_1 (tree type, tree name, bo if (temp) return temp; } + if (TREE_CODE (field) == 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)) - continue; + { + tree using_decl = USING_DECL_DECLS (field); + if ((TREE_CODE (using_decl) == FIELD_DECL + || TREE_CODE (using_decl) == TYPE_DECL) + && DECL_NAME (using_decl) == name) + return using_decl; + continue; + } } if (DECL_NAME (field) == name Index: gcc/dbxout.c =================================================================== --- gcc/dbxout.c (revision 160857) +++ gcc/dbxout.c (working copy) @@ -1,6 +1,6 @@ /* Output dbx-format symbol table information from GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -1431,6 +1431,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