This comes from PR 34389 and it only fails in C++. There is already a testcase: trunk/gcc/testsuite/g++.dg/warn/Wconversion-pr34389.C short mask1(short x) { short y = 0x7fff; return x & y; /* { dg-bogus "conversion" "conversion" { xfail *-*-* } 8 } */ } In C, build_binary_op constructs: <bit_and_expr 0x2aaaab068200 type <integer_type 0x2aaaab08e540 short int HI size <integer_cst 0x2aaaab08c930 constant 16> unit size <integer_cst 0x2aaaab08c960 constant 2> arg 0 <parm_decl 0x2aaaab095240 x type <integer_type 0x2aaaab08e540 short int> arg 1 <var_decl 0x2aaaab161280 y type <integer_type 0x2aaaab08e540 short int> while C++ builds: <bit_and_expr 0x2aaaab21df80 type <integer_type 0x2aaaab08e6c0 int public SI size <integer_cst 0x2aaaab08ca20 constant 32> unit size <integer_cst 0x2aaaab08c690 constant 4> arg 0 <nop_expr 0x2aaaab21df00 type <integer_type 0x2aaaab08e6c0 int> arg 0 <parm_decl 0x2aaaab095a20 x type <integer_type 0x2aaaab08e540 short int> arg 1 <nop_expr 0x2aaaab21df40 type <integer_type 0x2aaaab08e6c0 int> arg 0 <var_decl 0x2aaaab238000 y type <integer_type 0x2aaaab08e540 short int> The difference is in shorten_binary_op->common_type. In C, it returns short int, while in C++ it returns int. If it returned short int in C++, I think it will avoid warning. A more robust fix would be to make conversion_warning smart enough to handle the C++ expression. Not sure how to do that, though.
INVALID (not FIXED).
Wrong bug (argh!).
In C: /* Wrapper around c_common_type that is used by c-common.c and other front end optimizations that remove promotions. ENUMERAL_TYPEs are allowed here and are converted to their compatible integer types. BOOLEAN_TYPEs are allowed here and return either boolean_type_node or preferably a non-Boolean type as the common type. */ tree common_type (tree t1, tree t2) In C++: /* Return the common type of two types. We assume that comptypes has already been done and returned 1; if that isn't so, this may crash. This is the type for the result of most arithmetic operations if the operands have the given two types. */ tree common_type (tree t1, tree t2) They are not the same. C++ performs integral promotion, C doesn't. Which is a waste of time in C++ because everywhere common_type is called, integral promotions have been performed already. Duplicationg type_after_usual_arithmetic_conversions with a variant that does not perform promotions fixes the problem. But there should be a more elegant way to handle this than just duplicating the whole function...
Subject: Bug 37004 Author: manu Date: Sun Oct 19 22:53:01 2008 New Revision: 141233 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=141233 Log: 2008-10-20 Manuel López-Ibáñez <manu@gcc.gnu.org> PR c++/37004 cp/ * typeck.c (cp_common_type): New. The same as type_after_usual_arithmetic_conversions but without promotions. (type_after_usual_arithmetic_conversions): Do the promotions and call cp_common_type. (common_type): Make it behave like the C version of this function. Do not handle pointer types. (common_pointer_type): Move handling of pointer types from common_type to here. (cp_build_binary_op): Use common_pointer_type instead of common_type in call to pointer_diff. Use cp_common_type instead of common_type. * cp-tree.h (common_pointer_type): Declare. testsuite/ * g++.dg/warn/Wconversion-pr34389.C: Remove XFAIL. Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/cp-tree.h trunk/gcc/cp/typeck.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/warn/Wconversion-pr34389.C
Fixed in GCC 4.4