diff options
author | Jakub Jelinek <jakub@redhat.com> | 2008-10-10 20:22:17 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2008-10-10 20:22:17 +0200 |
commit | bbdf56821d76d939438fc91d7b921a387ac4e498 (patch) | |
tree | 2b5676fd735f4abebca2c0c12519e44ac76713d1 /gcc | |
parent | e14165f41af35dad913956a1edaad7874daba6f4 (diff) | |
download | gcc-bbdf56821d76d939438fc91d7b921a387ac4e498.zip gcc-bbdf56821d76d939438fc91d7b921a387ac4e498.tar.gz gcc-bbdf56821d76d939438fc91d7b921a387ac4e498.tar.bz2 |
re PR c++/37146 (Invalid types with COND_EXPR)
PR c++/37146
* cp-gimplify.c (cp_genericize_r): Fix up bitfield operands of
COND_EXPR.
* g++.dg/torture/pr37146-1.C: New test.
* g++.dg/torture/pr37146-2.C: New test.
* g++.dg/expr/bitfield10.C: New test.
From-SVN: r141045
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/cp-gimplify.c | 28 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/expr/bitfield10.C | 16 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/pr37146-1.C | 83 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/pr37146-2.C | 67 |
6 files changed, 207 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6ad8a8a..6b38199 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2008-10-10 Jakub Jelinek <jakub@redhat.com> + + PR c++/37146 + * cp-gimplify.c (cp_genericize_r): Fix up bitfield operands of + COND_EXPR. + 2008-10-09 Jakub Jelinek <jakub@redhat.com> PR c++/37568 diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index a1542b9..1641be5 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -803,6 +803,34 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) CLEANUP_BODY (stmt), CLEANUP_EXPR (stmt)); + /* COND_EXPR might have incompatible types in branches if one or both + arms are bitfields. Fix it up now. */ + else if (TREE_CODE (stmt) == COND_EXPR) + { + tree type_left + = (TREE_OPERAND (stmt, 1) + ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 1)) + : NULL_TREE); + tree type_right + = (TREE_OPERAND (stmt, 2) + ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 2)) + : NULL_TREE); + if (type_left) + { + TREE_OPERAND (stmt, 1) + = fold_convert (type_left, TREE_OPERAND (stmt, 1)); + gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt), + type_left)); + } + if (type_right) + { + TREE_OPERAND (stmt, 2) + = fold_convert (type_right, TREE_OPERAND (stmt, 2)); + gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt), + type_right)); + } + } + pointer_set_insert (p_set, *stmt_p); return NULL; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4232c49..92a0f41 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2008-10-10 Jakub Jelinek <jakub@redhat.com> + + PR c++/37146 + * g++.dg/torture/pr37146-1.C: New test. + * g++.dg/torture/pr37146-2.C: New test. + * g++.dg/expr/bitfield10.C: New test. + 2008-10-08 Jerry DeLisle <jvdelisle@gcc.gnu.org PR libfortran/37707 diff --git a/gcc/testsuite/g++.dg/expr/bitfield10.C b/gcc/testsuite/g++.dg/expr/bitfield10.C new file mode 100644 index 0000000..0a6581e --- /dev/null +++ b/gcc/testsuite/g++.dg/expr/bitfield10.C @@ -0,0 +1,16 @@ +// PR c++/37146 +// { dg-do compile } + +enum E { E0 = 0, E1 = 'E' }; + +struct S +{ + E s0 : 8; + enum E foo (bool, E); +}; + +E +S::foo (bool a, E b) +{ + return a ? s0 : b; +} diff --git a/gcc/testsuite/g++.dg/torture/pr37146-1.C b/gcc/testsuite/g++.dg/torture/pr37146-1.C new file mode 100644 index 0000000..ea65226 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr37146-1.C @@ -0,0 +1,83 @@ +// PR c++/37146 +// { dg-do run } + +extern "C" void abort (); +int a, b; +struct A { int i:8; int j:8; int k:16; int l:32; } c; + +void +f1 (int x, int y) +{ + (x ? a : b) = y; +} + +void +f2 (int x, int y) +{ + (x ? c.i : c.j) = y; +} + +void +f3 (int x, int y) +{ + (x ? c.i : a) = y; +} + +void +f4 (int x, int y) +{ + (x ? c.i : c.k) = y; +} + +void +f5 (int x, int y) +{ + (x ? c.l : b) = y; +} + +#define CHECK(var, exp) \ + do \ + { \ + if (var != exp) \ + abort (); \ + var = -1; \ + if (a != -1 \ + || b != -1 \ + || c.i != -1 \ + || c.j != -1 \ + || c.k != -1 \ + || c.l != -1) \ + abort (); \ + } \ + while (0) + +int +main () +{ + a = -1; + b = -1; + c.i = -1; + c.j = -1; + c.k = -1; + c.l = -1; + f1 (1, 264); + CHECK (a, 264); + f1 (0, 264); + CHECK (b, 264); + f2 (1, 112); + CHECK (c.i, 112); + f2 (0, 112); + CHECK (c.j, 112); + f3 (1, 26); + CHECK (c.i, 26); + f3 (0, 26); + CHECK (a, 26); + f4 (1, 107); + CHECK (c.i, 107); + f4 (0, 107); + CHECK (c.k, 107); + f5 (1, 95); + CHECK (c.l, 95); + f5 (0, 95); + CHECK (b, 95); +} diff --git a/gcc/testsuite/g++.dg/torture/pr37146-2.C b/gcc/testsuite/g++.dg/torture/pr37146-2.C new file mode 100644 index 0000000..2a54176 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr37146-2.C @@ -0,0 +1,67 @@ +// PR c++/37146 +// { dg-do run } + +extern "C" void abort (); +int a, b; +struct A { int i:8; int j:8; int k:16; int l:32; } c; + +int +f1 (int x) +{ + return x ? a : b; +} + +int +f2 (int x) +{ + return x ? c.i : c.j; +} + +int +f3 (int x) +{ + return x ? c.i : a; +} + +int +f4 (int x) +{ + return x ? c.i : c.k; +} + +int +f5 (int x) +{ + return x ? c.l : b; +} + +int +main () +{ + a = 17; + b = 18; + c.i = 19; + c.j = 20; + c.k = 21; + c.l = 22; + if (f1 (1) != a) + abort (); + if (f1 (0) != b) + abort (); + if (f2 (1) != c.i) + abort (); + if (f2 (0) != c.j) + abort (); + if (f3 (1) != c.i) + abort (); + if (f3 (0) != a) + abort (); + if (f4 (1) != c.i) + abort (); + if (f4 (0) != c.k) + abort (); + if (f5 (1) != c.l) + abort (); + if (f5 (0) != b) + abort (); +} |