On Fri, Nov 22, 2013 at 01:59:47PM +0100, Marek Polacek wrote:
> On Fri, Nov 22, 2013 at 10:28:52AM +0100, Jakub Jelinek wrote:
> > Working virtually out of Pago Pago right now.
> > 
> > In C++, falling through the end of a function that returns a value
> > without returning a value is undefined behavior (unlike C?), so this patch
> > implements instrumentation of it.
> 
> I think we really want to have this in for C99+ as well, mainly
> because C99 removed implicit int rule.

That's true, but I couldn't find in the C99 standard what the C++98 says
in [stmt.return]/2:
"Flowing off the end of a function is equivalent to a return with no value;
this results in undefined behavior in a value-returning function."

Thus,
int foo () {}
int main () { foo (); return 0; }
if I read it well is undefined behavior in C++, but is it in C (in
particular, when you don't use the calls' value)?

> > --- gcc/ubsan.c.jj  2013-11-22 01:40:03.000000000 +0100
> > +++ gcc/ubsan.c     2013-11-22 10:05:29.491725405 +0100
> > @@ -227,8 +227,8 @@ ubsan_source_location (location_t loc)
> >    xloc = expand_location (loc);
> >  
> >    /* Fill in the values from LOC.  */
> > -  size_t len = strlen (xloc.file);
> > -  tree str = build_string (len + 1, xloc.file);
> > +  size_t len = xloc.file ? strlen (xloc.file) : 0;
> > +  tree str = build_string (len + 1, xloc.file ? xloc.file : "");
> 
> This shouldn't be needed - the ubsan_source_location call is guarded
> by if (loc != UNKNOWN_LOCATION).  But it doesn't hurt either.

I got an ICE without it.  First when UBSAN tried to instrument
*this_5(D) ={v} {CLOBBER};
which it shouldn't obviously, but later on also when trying to instrument
some destructor call with &b as argument.  Would be nice if the sanopt
pass detected that the argument is always non-NULL and just didn't create
the data for __ubsan_* handler at all - I'd say that e.g. trying to fold
comparison &b == 0 would yield it is always false, then you wouldn't
instrument anything and just drop the UBSAN_NULL internal call.

> > +  tree data = ubsan_create_data ("__ubsan_missing_return_data", loc,
> > +                            NULL,NULL_TREE);
> 
> Missing space after NULL.

Oops.

> --- gcc/tree-cfg.c.mp2        2013-11-22 12:42:13.452426763 +0100
> +++ gcc/tree-cfg.c    2013-11-22 13:56:41.051581885 +0100
> @@ -8090,9 +8090,16 @@ execute_warn_function_return (void)
>           {
>             location = gimple_location (last);
>             if (location == UNKNOWN_LOCATION)
> -               location = cfun->function_end_locus;
> -           warning_at (location, OPT_Wreturn_type, "control reaches end of 
> non-void function");
> +             location = cfun->function_end_locus;
> +           warning_at (location, OPT_Wreturn_type, "control reaches end "
> +                       "of non-void function");
>             TREE_NO_WARNING (cfun->decl) = 1;
> +           if (flag_sanitize & SANITIZE_RETURN)
> +             {
> +               gimple_stmt_iterator gsi = gsi_for_stmt (last);
> +               gsi_insert_before (&gsi, ubsan_instrument_return (location),
> +                                  GSI_SAME_STMT);
> +             }

I guess this depends on whether it is undefined behavior in C or not (if you
don't use the value in the caller).  Plus, !targetm.warn_func_return fns
shouldn't be instrumented (though perhaps that is checked earlier already).

        Jakub

Reply via email to