Counter intuitively, asserts hurt gcc static dataflow analysis.
David Brown
david@westcontrol.com
Wed May 9 10:13:00 GMT 2018
On 09/05/18 10:35, Jonathan Wakely wrote:
> On 4 May 2018 at 14:34, Segher Boessenkool wrote:
>> On Fri, May 04, 2018 at 03:16:14PM +0200, Mason wrote:
>>> On 04/05/2018 01:03, John Carter wrote:
>>>
>>>> But compile with ...
>>>> gcc -O3 -W -Wall -Wextra -o a a.c
>>>> ...now results in NO warnings!
>>>>
>>>> ie. Although gcc _knows_ the assert _will_ trigger at run time... it can't
>>>> tell me at compile time anymore.
>>>>
>>>> ie. Counter intuitively, adding asserts and error checks to my code has
>>>> made me less safe.
>>>
>>> In the first version, gcc inlines the function call, which enables
>>> further analysis. In the second version, the assert() call makes
>>> gcc decide not to inline the function call, thus later analysis passes
>>> are no longer able to spot the out-of-bounds access.
>>
>> No, that's not it. In the second version there *is* no out of bounds
>> access!
>
> Right, the assert means that if the access would have been out of
> bounds the program terminates. So (when NDEBUG is not defined) it's
> impossible to reach the array access with an index >= 4.
>
> It doesn't hurt GCC's analysis, it just changes the program, and the
> analysis works on the new program.
>
What you might want here is a smarter assert:
extern void __attribute__((error("Smart assert always failed")))
__smartAssertAlwaysFail(void);
#define smart_assert(x) do { \
if (__builtin_constant_p(x)) { \
if (!(x)) __smartAssertAlwaysFail(); \
} else { \
assert(x); \
}
I use something similar for assertions in some of my embedded code (I
don't use normal asserts, because there is no output or way to exit the
program).
I am sure something related could be put in the normal assert macro -
perhaps with a warning rather than an error.
More information about the Gcc-help
mailing list