Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't GCC throw a warning in this example

With -Wsequence-point enabled, GCC should warn user when undefined behavior code is spotted. For example

b = a + ++a;

should be noticed by GCC and should be reported as "undefined behavior" code (because ISO C doesn't specify the order of evaluating operands for addition).

However, I played with the syntax and I tried this one:

int *a = malloc(sizeof(int) * 2);
a[0] = 1;
printf("%d\n", *(a + (*a)++ - *a));

Of course, I got the warning

warning: operation on '*a' may be undefined [-Wsequence-point]

which is what I expected, because the value of *a (which is a[0]) may be incremented or may not be while processing the third operand. But, I tried the following one:

int *a = malloc(sizeof(int) * 2);
a[0] = 1;
printf("%d\n", *(a + (*a)++ - 1));

I was surprised because I got no warnings. Shouldn't this be UB too? I mean, according to ISO C99, post increment operation may be evaluated at any point durring expression evaluation (except for comma operators and ternary operators). In my latter example, I am not incrementing pointer, but instead the integer it points to. So, accordning to the standard, it can be incremented at any point (which means that it can be incremented after whole expression is evaluated), so the program may print both 1 or 2, right?

Why doesn't GCC throw any warnings? Or did I miss something? Did I wrongly understand the specs?

like image 826
guest736427364 Avatar asked May 14 '17 11:05

guest736427364


People also ask

How do I enable warnings in GCC?

To enable all warnings, use following list of warnings (probably some warnings are duplicated, because I didn't bother to filter warnings enabled by -Wall ). Show activity on this post. Someone has created a set of tools for determining the complete set of warnings for a given GCC or Clang version.

How does GCC treat warning errors?

You can use the -Werror compiler flag to turn all or some warnings into errors. Show activity on this post. You can use -fdiagnostics-show-option to see the -W option that applies to a particular warning.

Which option of GCC inhibit all warning messages?

If -Wfatal-errors is also specified, then -Wfatal-errors takes precedence over this option. Inhibit all warning messages. Make all warnings into errors.

Which GCC flag is used to enable all compiler warnings?

gcc -Wall enables all compiler's warning messages. This option should always be used, in order to generate better code.


1 Answers

Static analysis tool of gcc does not handle this situation.

The expression *(a + (*a)++ - x) is too hard for static analysis of gcc, because it results in undefined behavior due to lack of sequence point under some very specific circumstances - namely, when *a contains x. This is when (*a)++ - x "undo" each other, so overall expression becomes equivalent to *a plus some side effects.

In order for gcc code analysis to spot this error, the compiler must track the content of *a throughout its lifetime. Although it looks simple in your example, a more complex program, say, where data is read into a from user input, renders such analysis impossible.

like image 156
Sergey Kalinichenko Avatar answered Sep 22 '22 20:09

Sergey Kalinichenko