diff options
author | kazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-01-28 05:19:44 +0000 |
---|---|---|
committer | kazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-01-28 05:19:44 +0000 |
commit | 924a018c3737e202e6b0617502c4c812ecbca88c (patch) | |
tree | 4ddc98ebd807edb66fa95964e68d043ebfd32d12 /gcc/c-typeck.c | |
parent | abecc17da75baf5f443b436334ef64d8bc4241ce (diff) | |
download | gcc-924a018c3737e202e6b0617502c4c812ecbca88c.tar.gz |
gcc/
PR c/19606.
* c-typeck.c (build_binary_op): Perform implicit casts of
operands before shortening them.
gcc/testsuite/
PR c/19606.
* gcc.c-torture/execute/pr19606.c: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@110321 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-typeck.c')
-rw-r--r-- | gcc/c-typeck.c | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index e1f78458146..ef518951c52 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -8101,12 +8101,35 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (shorten && none_complex) { int unsigned0, unsigned1; - tree arg0 = get_narrower (op0, &unsigned0); - tree arg1 = get_narrower (op1, &unsigned1); - /* UNS is 1 if the operation to be done is an unsigned one. */ - int uns = TYPE_UNSIGNED (result_type); + tree arg0, arg1; + int uns; tree type; + /* Cast OP0 and OP1 to RESULT_TYPE. Doing so prevents + excessive narrowing when we call get_narrower below. For + example, suppose that OP0 is of unsigned int extended + from signed char and that RESULT_TYPE is long long int. + If we explicitly cast OP0 to RESULT_TYPE, OP0 would look + like + + (long long int) (unsigned int) signed_char + + which get_narrower would narrow down to + + (unsigned int) signed char + + If we do not cast OP0 first, get_narrower would return + signed_char, which is inconsistent with the case of the + explicit cast. */ + op0 = convert (result_type, op0); + op1 = convert (result_type, op1); + + arg0 = get_narrower (op0, &unsigned0); + arg1 = get_narrower (op1, &unsigned1); + + /* UNS is 1 if the operation to be done is an unsigned one. */ + uns = TYPE_UNSIGNED (result_type); + final_type = result_type; /* Handle the case that OP0 (or OP1) does not *contain* a conversion |