This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 15507, 15542, 15427, 15287
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 22 May 2004 12:29:32 -0700
- Subject: C++ PATCH: PR 15507, 15542, 15427, 15287
- Reply-to: mark at codesourcery dot com
This patch fixes 4 C++ regressions in 3.4; all of the patches are
quite straightforward. Tested on i686-pc-linux-gnu, applied on the
mainline and on the branch.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2004-05-22 Mark Mitchell <mark@codesourcery.com>
PR c++/15507
* class.c (layout_nonempty_base_or_field): Do not try to avoid
layout conflicts for unions.
PR c++/15542
* typeck.c (build_x_unary_op): Instantiate template class
specializations before looking for "operator &".
PR c++/15427
* typeck.c (complete_type): Layout non-dependent array types, even
in templates.
PR c++/15287
* typeck.c (build_unary_op): Do not optimize "&x[y]" when in a
template.
2004-05-22 Mark Mitchell <mark@codesourcery.com>
PR c++/15507
* g++.dg/inherit/union1.C: New test.
PR c++/15542
* g++.dg/template/addr1.C: New test.
PR c++/15427
* g++.dg/template/array5.C: New test.
PR c++/15287
* g++.dg/template/array6.C: New test.
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.595.4.7
diff -c -5 -p -r1.595.4.7 class.c
*** cp/class.c 9 Mar 2004 07:27:23 -0000 1.595.4.7
--- cp/class.c 22 May 2004 19:10:38 -0000
*************** layout_nonempty_base_or_field (record_la
*** 3421,3446 ****
struct record_layout_info_s old_rli = *rli;
/* Place this field. */
place_field (rli, decl);
offset = byte_position (decl);
!
/* We have to check to see whether or not there is already
something of the same type at the offset we're about to use.
! For example:
! struct S {};
! struct T : public S { int i; };
! struct U : public S, public T {};
Here, we put S at offset zero in U. Then, we can't put T at
offset zero -- its S component would be at the same address
as the S we already allocated. So, we have to skip ahead.
Since all data members, including those whose type is an
empty class, have nonzero size, any overlap can happen only
with a direct or indirect base-class -- it can't happen with
a data member. */
/* G++ 3.2 did not check for overlaps when placing a non-empty
virtual base. */
if (!abi_version_at_least (2) && binfo && TREE_VIA_VIRTUAL (binfo))
break;
if (layout_conflict_p (field_p ? type : binfo, offset,
--- 3421,3450 ----
struct record_layout_info_s old_rli = *rli;
/* Place this field. */
place_field (rli, decl);
offset = byte_position (decl);
!
/* We have to check to see whether or not there is already
something of the same type at the offset we're about to use.
! For example, consider:
! struct S {};
! struct T : public S { int i; };
! struct U : public S, public T {};
Here, we put S at offset zero in U. Then, we can't put T at
offset zero -- its S component would be at the same address
as the S we already allocated. So, we have to skip ahead.
Since all data members, including those whose type is an
empty class, have nonzero size, any overlap can happen only
with a direct or indirect base-class -- it can't happen with
a data member. */
+ /* In a union, overlap is permitted; all members are placed at
+ offset zero. */
+ if (TREE_CODE (rli->t) == UNION_TYPE)
+ break;
/* G++ 3.2 did not check for overlaps when placing a non-empty
virtual base. */
if (!abi_version_at_least (2) && binfo && TREE_VIA_VIRTUAL (binfo))
break;
if (layout_conflict_p (field_p ? type : binfo, offset,
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.519.2.14
diff -c -5 -p -r1.519.2.14 typeck.c
*** cp/typeck.c 1 Apr 2004 23:18:14 -0000 1.519.2.14
--- cp/typeck.c 22 May 2004 19:10:38 -0000
*************** complete_type (tree type)
*** 122,132 ****
if (type == error_mark_node || COMPLETE_TYPE_P (type))
;
else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
{
tree t = complete_type (TREE_TYPE (type));
! if (COMPLETE_TYPE_P (t) && ! processing_template_decl)
layout_type (type);
TYPE_NEEDS_CONSTRUCTING (type)
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t));
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (t));
--- 122,132 ----
if (type == error_mark_node || COMPLETE_TYPE_P (type))
;
else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
{
tree t = complete_type (TREE_TYPE (type));
! if (COMPLETE_TYPE_P (t) && !dependent_type_p (type))
layout_type (type);
TYPE_NEEDS_CONSTRUCTING (type)
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t));
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (t));
*************** build_x_unary_op (enum tree_code code, t
*** 3528,3543 ****
xarg = build_non_dependent_expr (xarg);
}
exp = NULL_TREE;
! /* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an
! error message. */
if (code == ADDR_EXPR
&& TREE_CODE (xarg) != TEMPLATE_ID_EXPR
! && ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (xarg)))
! && !COMPLETE_TYPE_P (TREE_TYPE (xarg)))
|| (TREE_CODE (xarg) == OFFSET_REF)))
/* Don't look for a function. */;
else
exp = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE,
/*overloaded_p=*/NULL);
--- 3528,3549 ----
xarg = build_non_dependent_expr (xarg);
}
exp = NULL_TREE;
! /* [expr.unary.op] says:
!
! The address of an object of incomplete type can be taken.
!
! (And is just the ordinary address operator, not an overloaded
! "operator &".) However, if the type is a template
! specialization, we must complete the type at this point so that
! an overloaded "operator &" will be available if required. */
if (code == ADDR_EXPR
&& TREE_CODE (xarg) != TEMPLATE_ID_EXPR
! && ((CLASS_TYPE_P (TREE_TYPE (xarg))
! && !COMPLETE_TYPE_P (complete_type (TREE_TYPE (xarg))))
|| (TREE_CODE (xarg) == OFFSET_REF)))
/* Don't look for a function. */;
else
exp = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE,
/*overloaded_p=*/NULL);
*************** build_unary_op (enum tree_code code, tre
*** 3942,3953 ****
/* Don't let this be an lvalue. */
return non_lvalue (arg);
return arg;
}
! /* For &x[y], return x+y. */
! if (TREE_CODE (arg) == ARRAY_REF)
{
if (!cxx_mark_addressable (TREE_OPERAND (arg, 0)))
return error_mark_node;
return cp_build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1));
--- 3948,3963 ----
/* Don't let this be an lvalue. */
return non_lvalue (arg);
return arg;
}
! /* For &x[y], return x+y. But, in a template, ARG may be an
! ARRAY_REF representing a non-dependent expression. In that
! case, there may be an overloaded "operator []" that will be
! chosen at instantiation time; we must not try to optimize
! here. */
! if (TREE_CODE (arg) == ARRAY_REF && !processing_template_decl)
{
if (!cxx_mark_addressable (TREE_OPERAND (arg, 0)))
return error_mark_node;
return cp_build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1));
Index: testsuite/g++.dg/inherit/union1.C
===================================================================
RCS file: testsuite/g++.dg/inherit/union1.C
diff -N testsuite/g++.dg/inherit/union1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/inherit/union1.C 22 May 2004 19:10:40 -0000
***************
*** 0 ****
--- 1,14 ----
+ // PR c++/15507
+
+ struct A {
+ // empty
+ };
+
+ struct B : A {
+ int b;
+ };
+
+ union U {
+ A a;
+ B b;
+ };
Index: testsuite/g++.dg/template/addr1.C
===================================================================
RCS file: testsuite/g++.dg/template/addr1.C
diff -N testsuite/g++.dg/template/addr1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/addr1.C 22 May 2004 19:10:41 -0000
***************
*** 0 ****
--- 1,12 ----
+ // PR c++/15542
+
+ template <typename> struct S_T {
+ const char** operator & ();
+ };
+
+ template <class T> void foo(T **) {}
+
+ template <typename> void templateTest() {
+ S_T<const char> s_t;
+ foo(&s_t);
+ }
Index: testsuite/g++.dg/template/array5.C
===================================================================
RCS file: testsuite/g++.dg/template/array5.C
diff -N testsuite/g++.dg/template/array5.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/array5.C 22 May 2004 19:10:41 -0000
***************
*** 0 ****
--- 1,14 ----
+ // PR c++/15427
+
+ template<class T>
+ struct A
+ {
+ T foo;
+ };
+
+ template<class T>
+ struct B
+ {
+ A<int> _squares[2];
+ };
+
Index: testsuite/g++.dg/template/array6.C
===================================================================
RCS file: testsuite/g++.dg/template/array6.C
diff -N testsuite/g++.dg/template/array6.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/array6.C 22 May 2004 19:10:41 -0000
***************
*** 0 ****
--- 1,13 ----
+ // PR c++/15287
+
+ struct S {};
+
+ struct Array {
+ S operator[](int);
+ } array;
+
+ void (S::*mem_fun_ptr)();
+
+ template <int> void foo() {
+ (array[0].*mem_fun_ptr)();
+ }