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