* C++ PATCH for c++/38007
@ 2008-11-12 21:05 Jason Merrill
0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2008-11-12 21:05 UTC (permalink / raw)
To: gcc-patches List
[-- Attachment #1: Type: text/plain, Size: 277 bytes --]
When we changed the type of bitfield FIELD_DECLs to reflect the range
allowed by the bitfield, we didn't update cp_build_modify_expr
accordingly. This patch does that.
Tested x86_64-pc-linux-gnu, applied to trunk. I'll test and apply to
4.3 and 4.2 as well as they pass.
[-- Attachment #2: 38007.patch --]
[-- Type: text/x-patch, Size: 8562 bytes --]
2008-11-12 Jason Merrill <jason@redhat.com>
PR c++/38007
gcc/cp/
* typeck.c (cp_build_modify_expr): Update bitfield handling.
gcc/
* c-common.c (c_common_signed_or_unsigned_type): Remove C++
special casing.
gcc/testsuite/
* g++.dg/conversion/bitfield10.C: New test.
* g++.dg/warn/pr35635.C (func1): Accept additional warning.
* g++.old-deja/g++.mike/enum1.C: Expect warn about assignment.
* g++.dg/expr/bitfield9.C: Pass -Wno-overflow.
Index: cp/typeck.c
===================================================================
*** cp/typeck.c (revision 141769)
--- cp/typeck.c (working copy)
*************** cp_build_modify_expr (tree lhs, enum tre
*** 5801,5807 ****
tree newrhs = rhs;
tree lhstype = TREE_TYPE (lhs);
tree olhstype = lhstype;
- tree olhs = NULL_TREE;
bool plain_assign = (modifycode == NOP_EXPR);
/* Avoid duplicate error messages from operands that had errors. */
--- 5801,5806 ----
*************** cp_build_modify_expr (tree lhs, enum tre
*** 6005,6039 ****
return error_mark_node;
}
! /* If storing into a structure or union member, it has probably been
! given type `int'. Compute the type that would go with the actual
! amount of storage the member occupies. */
! if (TREE_CODE (lhs) == COMPONENT_REF
! && (TREE_CODE (lhstype) == INTEGER_TYPE
! || TREE_CODE (lhstype) == REAL_TYPE
! || TREE_CODE (lhstype) == ENUMERAL_TYPE))
! {
! lhstype = TREE_TYPE (get_unwidened (lhs, 0));
!
! /* If storing in a field that is in actuality a short or narrower
! than one, we must store in the field in its actual type. */
!
! if (lhstype != TREE_TYPE (lhs))
! {
! /* Avoid warnings converting integral types back into enums for
! enum bit fields. */
! if (TREE_CODE (lhstype) == INTEGER_TYPE
! && TREE_CODE (olhstype) == ENUMERAL_TYPE)
! {
! if (TREE_SIDE_EFFECTS (lhs))
! lhs = stabilize_reference (lhs);
! olhs = lhs;
! }
! lhs = copy_node (lhs);
! TREE_TYPE (lhs) = lhstype;
! }
! }
/* Convert new value to destination type. */
--- 6004,6014 ----
return error_mark_node;
}
! /* If storing into a structure or union member, it may have been given a
! lowered bitfield type. We need to convert to the declared type first,
! so retrieve it now. */
! olhstype = unlowered_expr_type (lhs);
/* Convert new value to destination type. */
*************** cp_build_modify_expr (tree lhs, enum tre
*** 6073,6094 ****
}
if (modifycode == INIT_EXPR)
! newrhs = convert_for_initialization (lhs, lhstype, newrhs, LOOKUP_NORMAL,
"initialization", NULL_TREE, 0,
complain);
else
{
- /* Avoid warnings on enum bit fields. */
- if (TREE_CODE (olhstype) == ENUMERAL_TYPE
- && TREE_CODE (lhstype) == INTEGER_TYPE)
- {
- newrhs = convert_for_assignment (olhstype, newrhs, "assignment",
- NULL_TREE, 0, complain);
- newrhs = convert_force (lhstype, newrhs, 0);
- }
- else
- newrhs = convert_for_assignment (lhstype, newrhs, "assignment",
- NULL_TREE, 0, complain);
if (TREE_CODE (newrhs) == CALL_EXPR
&& TYPE_NEEDS_CONSTRUCTING (lhstype))
newrhs = build_cplus_new (lhstype, newrhs);
--- 6048,6065 ----
}
if (modifycode == INIT_EXPR)
! newrhs = convert_for_initialization (lhs, olhstype, newrhs, LOOKUP_NORMAL,
"initialization", NULL_TREE, 0,
complain);
else
+ newrhs = convert_for_assignment (olhstype, newrhs, "assignment",
+ NULL_TREE, 0, complain);
+
+ if (!same_type_p (lhstype, olhstype))
+ newrhs = cp_convert_and_check (lhstype, newrhs);
+
+ if (modifycode != INIT_EXPR)
{
if (TREE_CODE (newrhs) == CALL_EXPR
&& TYPE_NEEDS_CONSTRUCTING (lhstype))
newrhs = build_cplus_new (lhstype, newrhs);
*************** cp_build_modify_expr (tree lhs, enum tre
*** 6120,6140 ****
if (!plain_assign)
TREE_NO_WARNING (result) = 1;
! /* If we got the LHS in a different type for storing in,
! convert the result back to the nominal type of LHS
! so that the value we return always has the same type
! as the LHS argument. */
!
! if (olhstype == TREE_TYPE (result))
! return result;
! if (olhs)
! {
! result = build2 (COMPOUND_EXPR, olhstype, result, olhs);
! TREE_NO_WARNING (result) = 1;
! return result;
! }
! return convert_for_assignment (olhstype, result, "assignment",
! NULL_TREE, 0, complain);
}
tree
--- 6091,6097 ----
if (!plain_assign)
TREE_NO_WARNING (result) = 1;
! return result;
}
tree
Index: c-common.c
===================================================================
*** c-common.c (revision 141769)
--- c-common.c (working copy)
*************** c_common_signed_or_unsigned_type (int un
*** 2719,2725 ****
#define TYPE_OK(node) \
(TYPE_MODE (type) == TYPE_MODE (node) \
! && (c_dialect_cxx () || TYPE_PRECISION (type) == TYPE_PRECISION (node)))
if (TYPE_OK (signed_char_type_node))
return unsignedp ? unsigned_char_type_node : signed_char_type_node;
if (TYPE_OK (integer_type_node))
--- 2719,2725 ----
#define TYPE_OK(node) \
(TYPE_MODE (type) == TYPE_MODE (node) \
! && TYPE_PRECISION (type) == TYPE_PRECISION (node))
if (TYPE_OK (signed_char_type_node))
return unsignedp ? unsigned_char_type_node : signed_char_type_node;
if (TYPE_OK (integer_type_node))
*************** c_common_signed_or_unsigned_type (int un
*** 2749,2758 ****
return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
#undef TYPE_OK
! if (c_dialect_cxx ())
! return type;
! else
! return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
}
/* Build a bit-field integer type for the given WIDTH and UNSIGNEDP. */
--- 2749,2755 ----
return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
#undef TYPE_OK
! return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
}
/* Build a bit-field integer type for the given WIDTH and UNSIGNEDP. */
Index: testsuite/g++.old-deja/g++.mike/enum1.C
===================================================================
*** testsuite/g++.old-deja/g++.mike/enum1.C (revision 141769)
--- testsuite/g++.old-deja/g++.mike/enum1.C (working copy)
*************** struct Type {
*** 8,11 ****
void setBTK();
};
! void Type::setBTK() { kind = DTK; }
--- 8,11 ----
void setBTK();
};
! void Type::setBTK() { kind = DTK; } // { dg-warning "truncate" }
Index: testsuite/g++.dg/warn/pr35635.C
===================================================================
*** testsuite/g++.dg/warn/pr35635.C (revision 141769)
--- testsuite/g++.dg/warn/pr35635.C (working copy)
*************** void func1()
*** 32,38 ****
/* At least one branch of ? does not fit in the destination, thus
warn. */
unsigned_bit.x = bar != 0 ? 2 : 0; /* { dg-warning "conversion" } */
! unsigned_bit.x = bar != 0 ? 0 : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
}
void func2()
--- 32,38 ----
/* At least one branch of ? does not fit in the destination, thus
warn. */
unsigned_bit.x = bar != 0 ? 2 : 0; /* { dg-warning "conversion" } */
! unsigned_bit.x = bar != 0 ? 0 : -1; /* { dg-warning "conver" } */
}
void func2()
Index: testsuite/g++.dg/expr/bitfield9.C
===================================================================
*** testsuite/g++.dg/expr/bitfield9.C (revision 141769)
--- testsuite/g++.dg/expr/bitfield9.C (working copy)
***************
*** 1,5 ****
--- 1,6 ----
// PR c++/32346
// { dg-do run }
+ // { dg-options "-Wno-overflow" }
extern "C" void abort();
Index: testsuite/g++.dg/conversion/bitfield10.C
===================================================================
*** testsuite/g++.dg/conversion/bitfield10.C (revision 0)
--- testsuite/g++.dg/conversion/bitfield10.C (revision 0)
***************
*** 0 ****
--- 1,24 ----
+ // PR c++/38007
+ // We need to use the conversion function to the declared type of a bitfield,
+ // not the lowered bitfield type.
+ // { dg-do link }
+
+ struct A
+ {
+ operator unsigned int() { return 42; }
+ operator unsigned char();
+ };
+
+ struct B
+ {
+ unsigned int b : 8;
+ };
+
+ int
+ main ()
+ {
+ A u;
+ unsigned int v = u;
+ B w;
+ w.b = u;
+ }
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2008-11-12 20:50 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-11-12 21:05 C++ PATCH for c++/38007 Jason Merrill
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).