This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Counter intuitively, asserts hurt gcc static dataflow analysis.


I have just put something very similar to this in our code base....

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); \
    }

...and it's working quite well. Better than I expected in that it's not
just catching things that are declared const.

It catches stupid things like....

if( expression) {
    ....
   assert( !expression);
}

It catches things that can be inlined but seen as constant at comile time.

I think as gcc's optimizer get's smarter this will be quite a win.

It also basically subsumes static_assert()

It's not the full solution I'm looking for, but hey, it's better than
before.

Where people have done things like....

switch(x) {
case a:
case b:
 ....
default:
   assert(false);
}

Yup, it yowls about that.

But I have created another noreturn function assert_not_reached() and
replaced all assert(false) by assert_not_reached();



On Wed, May 9, 2018 at 10:13 PM, David Brown <david@westcontrol.com> 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.
>
>


-- 
John Carter
Phone : (64)(3) 358 6639
Tait Electronics
PO Box 1645 Christchurch
New Zealand

-- 
This Communication is Confidential. We only send and receive email on the

basis of the terms set out at www.taitradio.com/email_disclaimer 
<http://www.taitradio.com/email_disclaimer>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]