Bug 37004 - [C++ only] Wconversion warns for short y = 0x7fff; short z = (short) x & y;
Summary: [C++ only] Wconversion warns for short y = 0x7fff; short z = (short) x & y;
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.4.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2008-08-01 19:34 UTC by Manuel López-Ibáñez
Modified: 2008-10-19 22:55 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2008-08-01 19:35:25


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Manuel López-Ibáñez 2008-08-01 19:34:39 UTC
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.
Comment 1 Manuel López-Ibáñez 2008-08-02 19:03:09 UTC
INVALID (not FIXED).
Comment 2 Manuel López-Ibáñez 2008-08-02 19:03:41 UTC
Wrong bug (argh!).
Comment 3 Manuel López-Ibáñez 2008-08-23 18:06:07 UTC
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...
Comment 4 Manuel López-Ibáñez 2008-10-19 22:54:28 UTC
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

Comment 5 Manuel López-Ibáñez 2008-10-19 22:55:51 UTC
Fixed in GCC 4.4