On 09/05/18 12:31, Jonathan Wakely wrote: > On 9 May 2018 at 11:13, David Brown wrote: >> 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. > > IIUC __attribute__((warning("..."))) requires linking to an extern > function, which might not be desirable in the general case for assert. > Can you not use this? static void __attribute__((warning("Smart assert always failed"))) __smartAssertAlwaysFail(void) {} (In the case of the error, I see it as an advantage that the error function is not defined and will also give a linker error if I somehow manage to compile code with the call left in.)