re PR c++/30274 (bool bit-field: wrong increment and decremenet)

PR c++/30274
	* cp-tree.h (unlowered_expr_type): New function.
	* typeck.c (is_bitfield_expr_with_lowered_type): Handle
	COMPOUND_EXPR, MODIFY_EXPR, and SAVE_EXPR.
	(unlowered_expr_type): New function.
	(build_unary_op): Disallow predecrements of bool bitfields.
	* call.c (build_conditional_expr): Use unlowered_expr_type.
	* pt.c (type_unification_real): Likewise.
	PR c++/30274
	* g++.dg/expr/bitfield3.C: New test.
	* g++.dg/expr/bitfield4.C: Likewise.
	* g++.dg/expr/bitfield5.C: Likewise.
	* g++.dg/expr/bitfield6.C: Likewise.

From-SVN: r122813
This commit is contained in:
Mark Mitchell 2007-03-11 03:07:59 +00:00 committed by Mark Mitchell
parent eae920410e
commit f9aa54d3c5
10 changed files with 125 additions and 20 deletions

View File

@ -1,3 +1,14 @@
2007-03-10 Mark Mitchell <mark@codesourcery.com>
PR c++/30274
* cp-tree.h (unlowered_expr_type): New function.
* typeck.c (is_bitfield_expr_with_lowered_type): Handle
COMPOUND_EXPR, MODIFY_EXPR, and SAVE_EXPR.
(unlowered_expr_type): New function.
(build_unary_op): Disallow predecrements of bool bitfields.
* call.c (build_conditional_expr): Use unlowered_expr_type.
* pt.c (type_unification_real): Likewise.
2007-03-09 Douglas Gregor <doug.gregor@gmail.com>
PR c++/20599

View File

@ -3250,12 +3250,8 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
array-to-pointer (_conv.array_), and function-to-pointer
(_conv.func_) standard conversions are performed on the second
and third operands. */
arg2_type = is_bitfield_expr_with_lowered_type (arg2);
if (!arg2_type)
arg2_type = TREE_TYPE (arg2);
arg3_type = is_bitfield_expr_with_lowered_type (arg3);
if (!arg3_type)
arg3_type = TREE_TYPE (arg3);
arg2_type = unlowered_expr_type (arg2);
arg3_type = unlowered_expr_type (arg3);
if (VOID_TYPE_P (arg2_type) || VOID_TYPE_P (arg3_type))
{
/* Do the conversions. We don't these for `void' type arguments

View File

@ -4645,6 +4645,7 @@ extern tree cxx_sizeof_or_alignof_type (tree, enum tree_code, bool);
#define cxx_sizeof_nowarn(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, false)
extern tree inline_conversion (tree);
extern tree is_bitfield_expr_with_lowered_type (tree);
extern tree unlowered_expr_type (tree);
extern tree decay_conversion (tree);
extern tree build_class_member_access_expr (tree, tree, tree, bool);
extern tree finish_class_member_access_expr (tree, tree, bool);

View File

@ -11260,7 +11260,7 @@ type_unification_real (tree tparms,
return 1;
continue;
}
arg = TREE_TYPE (arg);
arg = unlowered_expr_type (arg);
if (arg == error_mark_node)
return 1;
}

View File

@ -1418,23 +1418,52 @@ invalid_nonstatic_memfn_p (tree expr)
tree
is_bitfield_expr_with_lowered_type (tree exp)
{
tree field;
if (TREE_CODE (exp) == COND_EXPR)
switch (TREE_CODE (exp))
{
case COND_EXPR:
if (!is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 1)))
return NULL_TREE;
return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 2));
case COMPOUND_EXPR:
return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 1));
case MODIFY_EXPR:
case SAVE_EXPR:
return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0));
case COMPONENT_REF:
{
tree field;
field = TREE_OPERAND (exp, 1);
if (TREE_CODE (field) != FIELD_DECL || !DECL_C_BIT_FIELD (field))
return NULL_TREE;
if (same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (exp), DECL_BIT_FIELD_TYPE (field)))
return NULL_TREE;
return DECL_BIT_FIELD_TYPE (field);
}
default:
return NULL_TREE;
}
if (TREE_CODE (exp) != COMPONENT_REF)
return NULL_TREE;
field = TREE_OPERAND (exp, 1);
if (TREE_CODE (field) != FIELD_DECL || !DECL_C_BIT_FIELD (field))
return NULL_TREE;
if (same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (exp), DECL_BIT_FIELD_TYPE (field)))
return NULL_TREE;
return DECL_BIT_FIELD_TYPE (field);
}
/* Like is_bitfield_with_lowered_type, except that if EXP is not a
bitfield with a lowered type, the type of EXP is returned, rather
than NULL_TREE. */
tree
unlowered_expr_type (tree exp)
{
tree type;
type = is_bitfield_expr_with_lowered_type (exp);
if (!type)
type = TREE_TYPE (exp);
return type;
}
/* Perform the conversions in [expr] that apply when an lvalue appears
@ -4217,8 +4246,11 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
{
tree inc;
tree declared_type;
tree result_type = TREE_TYPE (arg);
declared_type = unlowered_expr_type (arg);
arg = get_unwidened (arg, 0);
argtype = TREE_TYPE (arg);
@ -4296,7 +4328,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
return error_mark_node;
/* Forbid using -- on `bool'. */
if (same_type_p (TREE_TYPE (arg), boolean_type_node))
if (same_type_p (declared_type, boolean_type_node))
{
if (code == POSTDECREMENT_EXPR || code == PREDECREMENT_EXPR)
{

View File

@ -1,5 +1,11 @@
2007-03-10 Mark Mitchell <mark@codesourcery.com>
PR c++/30274
* g++.dg/expr/bitfield3.C: New test.
* g++.dg/expr/bitfield4.C: Likewise.
* g++.dg/expr/bitfield5.C: Likewise.
* g++.dg/expr/bitfield6.C: Likewise.
PR c++/30924
* g++.dg/template/array18.C: New test.

View File

@ -0,0 +1,12 @@
// PR c++/30274
struct S {
bool x : 4;
};
S s;
void f() {
s.x--; // { dg-error "bool" }
--s.x; // { dg-error "bool" }
}

View File

@ -0,0 +1,19 @@
// PR c++/30274
// { dg-do link }
struct S {
bool x : 4;
};
S s;
template <typename T>
void f(T);
template <>
void f(bool) {}
int main() {
f(s.x++);
f(++s.x);
}

View File

@ -0,0 +1,17 @@
// PR c++/30274
// { dg-do run }
struct S {
bool x : 4;
};
S s;
int main() {
s.x++;
if (s.x != 1)
return 1;
++s.x;
if (s.x != 1)
return 2;
}

View File

@ -0,0 +1,11 @@
// PR c++/30274
struct S {
bool x : 4;
};
S s;
void f() {
++s.x = false;
}