From: "Fabien Chêne" <fabien.chene@gmail.com>
To: Jason Merrill <jason@redhat.com>
Cc: gcc-patches@gcc.gnu.org
Subject: Re: [Patch] PR c++/26256
Date: Sun, 25 Sep 2011 20:49:00 -0000 [thread overview]
Message-ID: <CAFH4-djv5gaJah69nQQ=4eo_h1yYf3jSsWGFhedbsUNsMUD5zA@mail.gmail.com> (raw)
In-Reply-To: <CAFH4-dhwz2eWSzrajMri_+nQLHAKB0Y8qsJa0ZMWr4HtepY1XQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2546 bytes --]
I've updated the patch. I can't resist to tackle PR 25994 at the same
time. There was a diagnostic about conflicting using declarations in
add_method, which is no longer necessary and bogus in the case of PR
25994, so I just removed it. Duplicated using declarations are now
diagnosed in supplement_binding_1. Tested x86_64-unknown-linux-gnu, OK
to commit?
gcc/ChangeLog
2011-09-21 Fabien Chêne <fabien@gcc.gnu.org>
PR c++/26256
* dbxout.c (dbxout_type_fields): Ignore using declarations.
gcc/testsuite/ChangeLog
2011-09-21 Fabien Chêne <fabien@gcc.gnu.org>
PR c++/26256
PR c++/25994
* g++.dg/lookup/using23.C: New.
* 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/debug/using4.C: New.
* g++.dg/debug/using5.C: New.
* g++.dg/cpp0x/forw_enum10.C: New.
* g++.old-deja/g++.other/using1.C: Adjust.
* g++.dg/template/using2.C: Likewise.
gcc/cp/ChangeLog
2011-09-21 Fabien Chêne <fabien@gcc.gnu.org>
PR c++/26256
PR c++/25994
* search.c (lookup_field_1): Get rid of the comment saying that
USING_DECL should not be returned, and actually return USING_DECL
if appropriate.
* semantics.c (finish_member_declaration): Remove the check that
prevents USING_DECLs from being verified by pushdecl_class_level.
* typeck.c (build_class_member_access_expr): Handle USING_DECLs.
* class.c (check_field_decls): Keep using
declarations.
(add_method): Remove a wrong diagnostic about
conflicting using declarations.
* parser.c (cp_parser_nonclass_name): Handle USING_DECLs.
* decl.c (start_enum): Call xref_tag whenever possible.
* 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.
(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.
--
Fabien
[-- Attachment #2: patch_26256 --]
[-- Type: application/octet-stream, Size: 25883 bytes --]
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,88 @@
+// { 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,16 @@
+// { 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,15 @@
+// { 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,12 @@
+// { 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,12 @@
+// { 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,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/lookup/using32.C
===================================================================
--- gcc/testsuite/g++.dg/lookup/using32.C (revision 0)
+++ gcc/testsuite/g++.dg/lookup/using32.C (revision 0)
@@ -0,0 +1,17 @@
+// { 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 (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)
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
next prev parent reply other threads:[~2011-09-25 19:54 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-05-11 19:44 Fabien Chêne
2010-05-16 19:20 ` Fabien Chêne
2010-06-08 21:50 ` Jason Merrill
2010-06-09 9:23 ` Fabien Chêne
2010-06-09 9:23 ` Fabien Chêne
2010-06-09 12:17 ` Jason Merrill
2010-06-16 21:21 ` Fabien Chêne
2010-06-17 8:39 ` Fabien Chêne
2010-06-18 8:18 ` Jason Merrill
2010-07-30 13:42 ` Fabien Chêne
2010-08-18 19:29 ` Fabien Chêne
2010-08-20 23:29 ` Jason Merrill
2010-11-15 21:40 ` Fabien Chêne
2010-11-15 21:41 ` Fabien Chêne
2010-11-17 11:25 ` Fabien Chêne
2010-12-20 16:51 ` Fabien Chêne
2010-12-22 23:10 ` Jason Merrill
2011-03-04 8:11 ` Fabien Chêne
2011-03-05 20:07 ` Jason Merrill
2011-03-08 21:48 ` Fabien Chêne
2011-06-15 19:42 ` Fabien Chêne
2011-06-22 15:56 ` Jason Merrill
2011-09-17 18:49 ` Fabien Chêne
2011-09-20 1:53 ` Jason Merrill
2011-09-21 18:33 ` Fabien Chêne
2011-09-21 18:52 ` Fabien Chêne
2011-09-21 19:01 ` Jason Merrill
2011-09-22 10:34 ` Fabien Chêne
2011-09-22 16:50 ` Jason Merrill
2011-09-22 23:01 ` Fabien Chêne
2011-09-22 23:48 ` Jason Merrill
2011-09-23 8:57 ` Fabien Chêne
2011-09-25 20:49 ` Fabien Chêne [this message]
2011-09-25 21:05 ` Paolo Carlini
2011-09-25 21:48 ` Fabien Chêne
2011-09-25 22:35 ` Paolo Carlini
2011-09-26 1:28 ` Fabien Chêne
2011-09-26 14:28 ` Jason Merrill
2011-10-10 20:35 ` Fabien Chêne
2011-10-11 15:35 ` Jason Merrill
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAFH4-djv5gaJah69nQQ=4eo_h1yYf3jSsWGFhedbsUNsMUD5zA@mail.gmail.com' \
--to=fabien.chene@gmail.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jason@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).