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:
parent
eae920410e
commit
f9aa54d3c5
10 changed files with 125 additions and 20 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
12
gcc/testsuite/g++.dg/expr/bitfield3.C
Normal file
12
gcc/testsuite/g++.dg/expr/bitfield3.C
Normal 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" }
|
||||
}
|
19
gcc/testsuite/g++.dg/expr/bitfield4.C
Normal file
19
gcc/testsuite/g++.dg/expr/bitfield4.C
Normal 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);
|
||||
}
|
17
gcc/testsuite/g++.dg/expr/bitfield5.C
Normal file
17
gcc/testsuite/g++.dg/expr/bitfield5.C
Normal 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;
|
||||
}
|
11
gcc/testsuite/g++.dg/expr/bitfield6.C
Normal file
11
gcc/testsuite/g++.dg/expr/bitfield6.C
Normal file
|
@ -0,0 +1,11 @@
|
|||
// PR c++/30274
|
||||
|
||||
struct S {
|
||||
bool x : 4;
|
||||
};
|
||||
|
||||
S s;
|
||||
|
||||
void f() {
|
||||
++s.x = false;
|
||||
}
|
Loading…
Add table
Reference in a new issue