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.