NOTE: This page is now obsolete and kept just for reference. It is completely superseded by NewWconversion.
Wcoercion option: warn of any implicit conversion that may change a value
Google Summer of Code 2006 Project
Student: Manuel López-Ibáñez (Email: manu gcc gnu org)
Mentor: Ian Lance Taylor
Contents
Synopsis
- The goal of this project is to develop an option warning of any implicit conversion that may change a value. Examples of such conversions are passing a double value to a function declared to receive a float argument and setting a signed constant to an unsigned variable. The option should not warn of explicit conversions or of cases where the value cannot in fact change despite the implicit conversion. These options would be particularly useful for security auditing and scientific applications.
Background
We are interested on coercions, that is, implicit type conversions, that may alter a value. Such alteration can be overflow, underflow, sign change, truncation and loss of precision.
float f = sqrt(2.0);
int si = 0.5;
unsigned int ui = -1;
We are not interested in coercions where the value cannot change:
double d = sqrtf(2.0f);
size_t size = 20;
int i = 4.0;
Current situation
Wconversion:
Warn if a prototype causes a type conversion that is different from what would happen to the same argument in the absence of a prototype. This includes conversions of fixed point to floating and vice versa, and conversions changing the width or signedness of a fixed point argument except when the same as the default promotion.
Also, warn if a negative integer constant expression is implicitly converted to an unsigned type. For example, warn about the assignment x = -1 if x is unsigned. But do not warn about explicit casts like (unsigned) -1.
Wconversion is solely intended to translate old C code (like K&R code) to ISO C debian-gcc 2003]. In particular, GCC provides a tool, protoize, to add prototypes to old C code, which is a requisite to convert a program to ISO C. Wconversion is used to find where the use of protoize may introduce bugs in the code (see Protoize Caveats).
Thus, Wconversion is not recommended for general use. Although it may detect coercions that may change a value, such as:
void fint(int x);
void h {
fint(3.2);
}
it will also generate warnings for perfectly reasonable code
void fchar(char x);
void h {
fchar('A');
}
These warning messages are confusing for users, who are misled by the name of the option, when they use Wconversion for ISO C code gnu.gcc.bug 1999, GNU libc FAQ, gcc 2000, gcc 2001, gcc 2002, freebsd-questions 2003, tcl-bugs 2003, gsl-discuss 2005, comp.lang.c 2005].
This confusion is exacerbated by the fact that Wconversion in addition warns for negative constants converted to unsigned type. Therefore, it is not surprising that many incorrectly believe that the purpose of Wconversion is to warn about implicit type conversions that could cause unexpected results An Introduction to GCC, Network Theory Ltd], when actually it is not. It is intended for one-shot translations of old C code to ISO C, the fact that it warns for some coercions that may change a value is just a side-effect. Sadly, the wrong belief is currently wide-spread.
On the other hand, there are some warning options in gcc that identify coercions that may change a value, for example Wsign-compare.
Proposed solution
Our proposal is two warning options. One of them would encapsulate the behaviour required by protoize to detect where the addition of prototypes may led to new bugs. The other warning option will identify coercions that may change a value. Tentatively, we will call the former Wtraditional-conversion and the latter Wcoercion just for the sake of clarity and to distinguish both of them from the original Wconversion (we don't discard that the name Wconversion will be kept for one of them).
Wtraditional-conversion:
- Warn if a prototype causes a type conversion that is different from what would happen to the same argument in the absence of a prototype. This includes conversions of fixed point to floating and vice versa, and conversions changing the width or signedness of a fixed point argument except when the same as the default promotion.
This definition of Wtraditional-conversion is actually the same as for Wconversion although we may decide to clarify it, warn that it is not intended for general use and point the reader to Wcoercion.
Wcoercion:
- Warn if a implicit type conversion may alter a value. This includes negative constants or signed variables converted to unsigned types, overflow / underflow, truncation and loss of precission.
The definition of Wcoercion may also describe a number of selected examples suggestions are welcome.
Alternative names for Wtraditional-conversion might be Wprotoize, Wadded-prototypes and Wconversion. An alternative name for Wcoercion might be Wconversion.
Testcases
1. Negative integer constant expression is implicitly converted to an unsigned type. This is currently a feature of Wconversion which will be taken away by Wcoercion (see Bug 9072).
1 /* Test for diagnostics for negative constants coerced to unsigned types
2 These tests come from gcc/testsuite/gcc.dg/overflow-warn-2.c
3 Origin: Manuel Lopez-Ibanez <lopezibanez@gmail.com> */
4 /* { dg-do compile } */
5 /* { dg-options "-std=c99 -Wcoercion" } */
6 #include <limits.h>
7 void fuc (unsigned char);
8 void hc (int x)
9 {
10 unsigned char uc;
11 fuc (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
12 uc = -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
13 uc = x ? 1U : -1; /* { dg-warning "coercion to 'unsigned char' from 'unsigned int' may alter its value" } */
14 /* { dg-warning "negative integer implicitly converted to unsigned type" "" { target *-*-* } 18 } */
15 uc = x ? SCHAR_MIN : 1U; /* { dg-warning "coercion to 'unsigned char' from 'unsigned int' may alter its value" } */
16 /* { dg-warning "negative integer implicitly converted to unsigned type" "" { target *-*-* } 20 } */
17 uc = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
18 fuc('A');
19 uc = 'A';
20 uc = x ? 1 : -1; /* { dg-warning "coercion to 'unsigned char' from 'int' may alter its value" } */
21 uc = x ? SCHAR_MIN : 1; /* { dg-warning "coercion to 'unsigned char' from 'int' may alter its value" } */
22 }
23 unsigned fui (unsigned int ui);
24 unsigned fsi (signed int ui);
25 void hi (int x)
26 {
27 unsigned ui;
28 fui (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
29 ui = -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
30 ui = x ? 1U : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
31 ui = x ? INT_MIN : 1U; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
32 ui = ui ? SCHAR_MIN : 1U; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
33 ui = 1U * -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
34 ui = ui + INT_MIN; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
35 ui = -1 * (1 * -1);
36 ui = (unsigned) -1;
37 ui = x ? 1 : -1; /* { dg-warning "coercion to 'unsigned int' from 'int' may alter its value" } */
38 ui = x ? INT_MIN : 1; /* { dg-warning "coercion to 'unsigned int' from 'int' may alter its value" } */
39 ui = ui ? SCHAR_MIN : 1; /* { dg-warning "coercion to 'unsigned int' from 'int' may alter its value" } */
40 }
41 void hs(void)
42 {
43 fsi(UINT_MAX - 1); /* { dg-warning "coercion as 'int' alters 'unsigned int' constant value" } */
44 fsi(UINT_MAX - 1U); /* { dg-warning "coercion as 'int' alters 'unsigned int' constant value" } */
45 fsi(UINT_MAX/3U);
46 fsi(UINT_MAX/3);
47 fui(UINT_MAX - 1);
48 }
49 unsigned fui(unsigned a) { return a + -1; } /* { dg-warning "negative integer implicitly converted to unsigned type" } */
2. Function calls Wconversion related, (see Bug 9072 comment 12). (The same test cases would apply to assignments)
1 /* { dg-do compile }
2 /* { dg-options "-fsigned-char -std=c99 -Wcoercion" } */
3 #include <limits.h>
4 #include <float.h>
5 # define M_PI 3.14159265358979323846 /* pi */
6 void fchar(char x);
7 void ffloat(float x);
8 void fdouble(double x);
9 void flongdouble(long double x);
10 void fshortint(short int x);
11 void fint(int x);
12 void flongint(long int x);
13 void flonglong(long long x);
14 void h(void)
15 {
16 unsigned int ui = 3;
17 int si = 3;
18 float f = 3;
19 double d = 3;
20 fint(3.1f); /* { dg-warning "coercion" } */
21 fint(3.1); /* { dg-warning "coercion" } */
22 ffloat(INT_MAX); /* { dg-warning "coercion" } */
23 ffloat(DBL_MIN); /* { dg-warning "coercion" } */
24 ffloat(M_PI); /* { dg-warning "coercion" } */
25 ffloat(3.1); /* { dg-warning "coercion" } */
26 fint(d); /* { dg-warning "coercion" } */
27 ffloat(d); /* { dg-warning "coercion" } */
28 ffloat(si); /* { dg-warning "coercion" } */
29 ffloat(ui); /* { dg-warning "coercion" } */
30 ffloat(16777217); /* { dg-warning "coercion" } */
31 fint(3);
32 fint(3.0f);
33 fint(3.0);
34 fint(16777217.0f);
35 ffloat(3U);
36 ffloat(3);
37 ffloat(INT_MIN);
38 fdouble(UINT_MAX);
39 fdouble(ui);
40 ffloat(3.0);
41 ffloat(3.1f);
42 ffloat(0.25);
43 ffloat(f);
44 fdouble(d);
45 fdouble(f);
46 fdouble(16777217);
47 }
48 void fuc(unsigned char uc);
49 void fui(unsigned int ui);
50 void h2(void)
51 {
52 unsigned int ui = 3;
53 int si = 3;
54 unsigned char uc = 3;
55 signed char sc = 3;
56 fint(ui); /* { dg-warning "coercion" } */
57 fui(si);/* { dg-warning "coercion" } */
58 fui(sc); /* { dg-warning "coercion" } */
59 fui(-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
60 fui('\xa0'); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
61 fuc('\xa0'); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
62 fint(uc);
63 fui(uc);
64 fui('A');
65 fuc('A');
66 fint('A');
67 fchar('A');
68 fchar('\xa0');
69 }
3. Assignments .
1 /* { dg-do compile }
2 /* { dg-options "-fsigned-char -std=c99 -Wcoercion" } */
3 #include <limits.h>
4 #include <float.h>
5 # define M_PI 3.14159265358979323846 /* pi */
6 float vfloat;
7 double vdouble;
8 long double vlongdouble;
9 char vchar;
10 short int vshortint;
11 int vint;
12 long vlongint;
13 long long vlonglong;
14 void h(void)
15 {
16 unsigned int ui = 3;
17 int si = 3;
18 float f = 3;
19 double d = 3;
20 vint = 3.1f; /* { dg-warning "coercion" } */
21 vint = 3.1; /* { dg-warning "coercion" } */
22 vfloat = INT_MAX; /* { dg-warning "coercion" } */
23 vfloat = DBL_MIN; /* { dg-warning "coercion" } */
24 vfloat = M_PI; /* { dg-warning "coercion" } */
25 vfloat = 3.1; /* { dg-warning "coercion" } */
26 vint = d; /* { dg-warning "coercion" } */
27 vfloat = d; /* { dg-warning "coercion" } */
28 vfloat = si; /* { dg-warning "coercion" } */
29 vfloat = ui; /* { dg-warning "coercion" } */
30 vfloat = 16777217; /* { dg-warning "coercion" } */
31 /* No warning */
32 vint = 3;
33 vint = 3.0f;
34 vint = 3.0;
35 vint = 16777217.0f;
36 vfloat = 3U;
37 vfloat = 3;
38 vfloat = INT_MIN;
39 vdouble = UINT_MAX;
40 vdouble = ui;
41 vfloat = 3.0;
42 vfloat = 3.1f;
43 vfloat = 0.25;
44 vfloat = f;
45 vdouble = d;
46 vdouble = f;
47 vdouble = 16777217;
48 }
49 unsigned char vuc;
50 unsigned int vui;
51 void h2(void)
52 {
53 unsigned int ui = 3;
54 int si = 3;
55 unsigned char uc = 3;
56 signed char sc = 3;
57 vint = ui;/* { dg-warning "coercion" } */
58 vui = si; /* { dg-warning "coercion" } */
59 vui = sc; /* { dg-warning "coercion" } */
60 vui = -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
61 vui = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
62 vuc = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
63 /* no warning */
64 vint = uc;
65 vui = uc;
66 vui = 'A';
67 vuc = 'A';
68 vint = 'A';
69 vchar = 'A';
70 vchar = '\xa0';
71 }
4. Decimal float .
1 /* { dg-do compile } */
2 /* { dg-options "-std=gnu99 -Wcoercion" } */
3 void fd32(_Decimal32);
4 void fd64(_Decimal64);
5 void fd128(_Decimal128);
6 void fint (int);
7 _Decimal32 d32;
8 _Decimal64 d64;
9 _Decimal128 d128;
10 float vfloat;
11 double vdouble;
12 long double vlongdouble;
13 void h()
14 {
15 vfloat = 2.0df;
16 vdouble = 2.0df;
17 vlongdouble = 2.0df;
18 vfloat = -7.0dd;
19 vdouble = -7.0dd;
20 vlongdouble = -7.0dd;
21 vfloat = 30.0dl;
22 vdouble = 30.0dl;
23 vlongdouble = 30.0dl;
24 d32 = 3;
25 d64 = 3;
26 d128 = 3;
27 d32 = -2.0;
28 d64 = -2.0;
29 d128 = -2.0;
30 fd128(d128);
31 fd128(d64);
32 fd128(d32);
33 fd64(d64);
34 fd64(d32);
35 fd32(d32);
36 fint(2.0df);
37 fint(2.0dd);
38 fint(2.0dl);
39 d64 = 123.4df;
40 d128 = 123.4df;
41 d128 = 345.678dd;
42 /* Conversions to smaller types for which the value fits. */
43 d32 = 3456.789dd;
44 d32 = 123.4567dl;
45 d64 = 1234567890.123456dl;
46 }
47 void g()
48 {
49 vfloat = 2.1df; /* { dg-warning "coercion as 'float' alters '_Decimal32' constant value" } */
50 vdouble = 2.1df; /* { dg-warning "coercion as 'double' alters '_Decimal32' constant value" } */
51 vlongdouble = 2.1df; /* { dg-warning "coercion as 'long double' alters '_Decimal32' constant value" } */
52 fint(2.1df); /* { dg-warning "coercion as 'int' alters '_Decimal32' constant value" } */
53 fint(2.1dd); /* { dg-warning "coercion as 'int' alters '_Decimal64' constant value" } */
54 fint(2.1dl); /* { dg-warning "coercion as 'int' alters '_Decimal128' constant value" } */
55 d32 = 9.99999949E96DD; /* { dg-warning "coercion as '_Decimal32' alters '_Decimal64' constant value" } */
56 d64 = 9.9999999999999995E384DL; /* { dg-warning "coercion as '_Decimal64' alters '_Decimal128' constant value" } */
57 fd32(d128); /* { dg-warning "coercion to '_Decimal32' from '_Decimal128' may alter its value" } */
58 fd32(d64); /* { dg-warning "coercion to '_Decimal32' from '_Decimal64' may alter its value" } */
59 fd64(d128); /* { dg-warning "coercion to '_Decimal64' from '_Decimal128' may alter its value" } */
60 d32 = vfloat; /* { dg-warning "coercion to '_Decimal32' from 'float' may alter its value" } */
61 d32 = vdouble; /* { dg-warning "coercion to '_Decimal32' from 'double' may alter its value" } */
62 d64 = vdouble; /* { dg-warning "coercion to '_Decimal64' from 'double' may alter its value" } */
63 d128 = vdouble; /* { dg-warning "coercion to '_Decimal128' from 'double' may alter its value" } */
64 vfloat = d32; /* { dg-warning "coercion to 'float' from '_Decimal32' may alter its value" } */
65 vdouble = d32; /* { dg-warning "coercion to 'double' from '_Decimal32' may alter its value" } */
66 vlongdouble = d32; /* { dg-warning "coercion to 'long double' from '_Decimal32' may alter its value" } */
67 }
Oustanding Issues
- Inexact conversions:
int i = 16777217.0f; /* i == 16777216 */
- Is this important? I think it is not, since anyway:
float f = 16777217.0f; /* f == 16777216 */
isn't it funny?
- No dataflow solving in front-ends. That is, even if the value of a variable is known at compile time, it is not known by the front end.
How bool and enum types should be handled ? Which are the default promotions when bool and enum are involved? Which coercions may change a value ?
Should we warn for NULL to non-pointer coercions ? Already implemented in C++. In C, NULL is typically defined as (void*)0 what by default triggers warnings and errors on the following testcases.
1 void k(int) {}
2 int main()
3 {
4 int i = NULL; // { dg-warning "" } converting NULL to non-pointer type
5 float z = NULL; // { dg-warning "" } converting NULL to non-pointer type
6 int a[2];
7 i != NULL; // { dg-warning "" } NULL used in arithmetic
8 NULL != z; // { dg-warning "" } NULL used in arithmetic
9 k != NULL; // No warning: decay conversion
10 NULL != a; // Likewise.
11 -NULL; // { dg-warning "" } converting NULL to non-pointer type
12 +NULL; // { dg-warning "" } converting NULL to non-pointer type
13 ~NULL; // { dg-warning "" } converting NULL to non-pointer type
14 a[NULL] = 3; // { dg-warning "" } converting NULL to non-pointer-type
15 i = NULL; // { dg-warning "" } converting NULL to non-pointer type
16 z = NULL; // { dg-warning "" } converting NULL to non-pointer type
17 k(NULL); // { dg-warning "" } converting NULL to int
18 NULL && NULL; // No warning: converting NULL to bool is OK
19 }
signed to unsigned and viceversa (Part II). Warn when a comparison between signed and unsigned values could produce an incorrect result when the signed value is converted to unsigned. (Wsign_compare)
Wsign-compared The following testcase issues a warning when using gcc but not when using g++, as reported by Vassili Karpov in gcc Sep 2005: 11: warning: signed and unsigned type in conditional expression. When using Wcoercion two warnings are issued by both gcc and g++: 11: warning: coercion to 'unsigned int' from 'int' may alter its value and 11: warning: coercion to 'char' from 'unsigned int' may alter its value.
Undocumented behaviour of Wconversion in g++ . This will be just moved to Wcoercion and documented.
Unary minus on unsigned: http://gcc.gnu.org/ml/gcc/1999-06n/msg00806.html
Related bugs
Bug 13932 g++ warns for int i = 1.
Bug 2707 gcc does not warn on truncate
Bug 26167 -Wconversion fails to detect signedness conversion from int to unsigned int in fuction call
bug 26298 -Wconversion fails to detect signedness change during widening conversion
bug 28986 Failure to diagnose overflow in constant expression
bug 18063 Gcc doesn't check overflowed size of structure
bug 19976 integer division by zero in subexpression should be overflow
bug 19977 overflow in non-static initializer should not be pedwarn
bug 19978 overflow in expression of constants should not cause multiple warnings
bug 20019 incorrect overflow warning
bug 23572 No warning for assigning a value to a 'float' variable that overflows with option -Wextra
bug 29887 wrong-code for errno handling on overflow/underflow
( maybe or maybe not? ) Complete list
- Likely
Bug 12242 : g++ should warn about out-of-range int->enum conversions
No idea
Bug 8715 : '~' operator for unsigned char and conversion to bool
Docs and Links
(2) SvnSetup Internal Documentation Internal Documentation (PDF)
(3) Installing GCC: Configuration and Building Makefile Targets
(5) Contributing to GCC: Testing Patches
(6) Installing GCC: Testing TestingGCC GCC_Patch_Tracking DebuggingGCC GCC Coding Conventions
Wikibook: GNU C Compiler Internals/GNU C Compiler Architecture 4.1
The Inner Workings of GCC by Diego Novillo
Acknowledgements
First-time GCC development
Get the code
(1)
svn -q co svn://gcc.gnu.org/svn/gcc/trunk gcc
What directories are not required to build and test gcc and g++ ?
Most directories are not required. However, you are going to have to build all languages anyway to make sure that the new warning does not trigger when you're building the other front ends that are also written in C. This would break bootstrap because GCC bootstraps with -Werror Fortunately, for testing and development you can configure GCC such that only the C and C++ front ends are built. See below. --StevenBosscher
Removing directories from your subversion working copy (2) : there is little point to do this since you need all of them to perform a complete bootstrap and test.
Build
(3)
cd /home/manu/myproject mkdir -p objdir local cd objdir
Configure: just need to do it once unless you want to change configuration or paths or do a complete bootstrap and test
./src/trunk/configure --prefix=`pwd`/../local --enable-languages=c,c++,objc --disable-mudflap --disable-libmudflap
Build:
make -j 2 all-gcc # this still takes an awful lot of time make install # is this actually needed ?
Interesting options for configure and make ?
--enable-languages=c,c++,objc : configure GCC to only build gcc g++ and objc Beware that you cannot test any other languages, even if you are able to do make check-obj-c++. You will need to run configure --enable-languages=all before bootstrapping and complete test.
--disable-libgcj : this is redundant with --enable-languages
--disable-bootstrap : build GCC only once, with the system compiler (nice for development) yet, it seems to compile things again using the just built xgcc (It seems that this shouldn't be used at all, make all-gcc compiles without bootstrapping).
--disable-mudflap --disable-libmudflap : not documented (3) ? pinskia told me in IRC that this is tested on GNU/Linux, thus we need it when testing
Testing
cd objdir make -C gcc check-gcc RUNTESTFLAGS=dg.exp # all tests of dg make -C gcc check-gcc RUNTESTFLAGS=dg.exp=overflow-warn-1.c # to test only overflow-warn-1.c
Any changes, except changes in front ends different from the C one, require a complete bootstrap and test: (5)
cd objdir ./src/trunk/configure --prefix=`pwd`/../local --enable-languages=all make bootstrap make -k check
Before you submit patches, you must complete a bootstrap, and you should test at least c,c++,objc You'll make new friends at Apple if you also test objc++ Assuming you've built all languages, you can tell make to only test those languages:--StevenBosscher
make check-gcc check-c++ check-objc check-obj-c++ # it may take several hours...
Here you say make check-c++ however, here (4) it says make check-g++, are they just the same? --ManuelLópezIbáñez
Produce a patch
diff -up trunk/ wcoercion/ > woercion.patch
svn diff --diff-cmd diff -x -up trunk/ wcoercion/ > woercion.patch
Other proposals
Here I recollect extensions or changes to the current proposal suggested by other people. Initially, I have no plan to work on them, since (a) it would be hard enough to get GCC core developers to agree with the current changes, and (b) I have a limited amount of free time. Nevertheless, feel free to clearly define your proposals, or even better, create a new wiki page and put definitions, testcases, links, quotes and whatever information you may be able to get. Also, you may also ask GCC core developers their opinion about your idea.
I think there are two different types of conversions:
A*) Conversions which give clearly wrong results (negative constant --> unsigned, float --> int, ...).
B*) Conversions which loose precision (double --> float, int --> double, ...).
Maybe there should be a level for the Wcoercion option to control which types of conversions should generate warnings.
-Wcoercion=all for types A + B and -Wcoercion=serious only for type *A*. --MichaelCieslinski
Actually, float to int just loses precision and I don't understand why you say that int to double loses precision (either there is no change or there is an overflow, which in particular for int to double there is not)--ManuelLópezIbáñez
float to int can loose a lot of precision e.g.: 1.5f --> int in that case it is nearly undefined whether you get 1 or 2 You are right, the conversion int to double is not a problem at all. A better wording would be:
A*) Conversions which give clearly wrong results or can introduce serious rounding errors (negative constant --> unsigned, float --> int, ...).
B*) Conversions which loose only some precision or convert to a narrower range (double --> float, int --> short, ...). --MichaelCieslinski
I would encourage you to test what happens on those conversions. I am sure you will be surprised by the results. First, float to int may or may not lose more precision than double to float Actually, in absolute quantity, as seems to be measured in your example, the highest potential loss is on double to float since the difference between the highest representable double and its conversion to float is much larger than the difference between the highest representable float and its conversion to int Second, double to float is also a conversion to a narrower width. On the other hand, int to short may give very wrong results (possible overflow/underflow). Still, it is not clear what you *exactly* mean by "wrong results" and "serious rounding errors" as oppossed to "some precision loss". Finally, take into account that a negative int may be converted to an unsigned short The last bit of fun is float f = 16777217;, try printing f --ManuelLópezIbáñez
From that point of view you are absolutely right and also I don't want to offend you. It is just my personal perception that normally overflow and precision is not such a problem in typical programs since programmers tend to use data types with far larger ranges or precision than actually needed for a value - at least I program in that way, especially at places where it does't matter. But I remember that I was hit by programming errors like assigning a floating point value to an int. Often that oversight results in a bug because you have to consider rounding.
When I proposed a level for Wcoercion I thought it would be nice to have an option to warn about the common programming mistakes which I would enable by default and the full option which I would use after completing some work. Typically it is not a problem to assign an int to a short because the values are mostly small. If the range of values could be a problem typically I write some checking code and clip the value or emit an error message. So for me it would be nice to have a wcoercion level which would not trigger to often so I can enable it by default. --MichaelCieslinskiFeel free to re-write our conversation and summarise your proposal taking into account my comments. Otherwise, in some moment in the future I will attack this thread with my flaming sword of organizational justice . --ManuelLópezIbáñez
Is this checking done by the middle end or by C/C++ front end? Especially, if the former, it would be nice if it were working with Fortran as well.--TobiasBurnus
I have not started the implementation. I still have to read a lot of GCC documentation. However, it seems that the easier thing is to do it in the C/C++ front end. Now, this has some limitations, as pointed out above there is no flow control in the front ends. So, if you think this can be done in the middle end without introducing any disruption in GCC, just write me an email or point me to some links so I can learn about it. --ManuelLópezIbáñez
It's generally believed diagnostics belong in the front end. --NeilBooth