Am Dienstag, dem 15.10.2024 um 12:15 +0200 schrieb Jakub Jelinek:
> On Tue, Oct 15, 2024 at 11:50:21AM +0200, Richard Biener wrote:
> > > Would it be reasonable to approve this patch now and I try
> > > to improve this later?
> > 
> > On the patch itself:
> > 
> >  void
> >  expand_builtin_trap (void)
> >  {
> > +  if (warn_trap)
> > +    {
> > +      location_t current_location =
> 
> Formatting-wise, = shouldn't be at the end of line.
> 
> > +       linemap_unwind_to_first_non_reserved_loc (line_table, 
> > input_location,
> > +                                                 NULL);
> > +       warning_at (current_location, OPT_Wtrap, "trap generated");
> > +    }
> > +
> >    if (targetm.have_trap ())
> > 
> > this also diagnoses calls the user puts in by calling __builtin_trap (),
> > the documentation should probably mention this.  I see the only testcase
> > exercises only this path.  I have doubts -fsanitize-trap with any
> > sanitizer will ever yield a clean binary, so I wonder about practical
> > uses besides very small testcases?
> 
> Given that even simple
> int foo (int x, int y) { return x + y; }
> calls it for -fsanitize=undefined -fsanitize-trap=undefined, and more
> importantly, we try not to optimize away sanitizer checks based on VRP and
> other optimizations at least to some extent, because VRP and other
> optimizations optimize on UB not happening while sanitizers try to catch
> the UB, I have serious doubts about the warning.
> One would need completely different approach, where we try as much as
> possible to prove UB can't happen and only warn if we couldn't prove it
> can't.  Still, there would be tons of false positives where things just
> aren't inlined and we can't prove UB won't happen, or warnings on dead
> code...
> 

It would not be practical with some sanitizers (and sanitizers are also not
the only usecase anyhow). But attached below is the list of emitted warnings
for different sanitizers depending on the optimization level for
BART (https://github.com/mrirecon/bart).  The first number is optimization,
then the number of warnings, and then the number with different warnings
from the same source location (e.g. macros) combined.  The project has
>400 C source files.

For some sanitizers the number is rather low and e.g. shift is something
I was looking at specifically and where I already found this useful.  But
also for  some the others the numbers are low enough to investigate each case. 
For new code, an average number of warnings per file of 10 would also
still seem entirely reasonable, so I think one could eliminate all
integer overflow cases if one wanted to. But also doing this only for
criticial pieces of code (e.g. using #pragma GCC diagnostic ...) would
seem useful.

One also sees that the optimizer actually does remove a lot of traps. That
the total number sometimes goes up with -O2 is mostly likely due to code
duplication, but the unique cases always go down with more optimization.
(except for object-size which does not run fully for -O1 I believe)

I have to admit I did not understand your comment about VRP, but
in my experience we remove UB sanitization based on value ranges, e.g.
in this example for signed overflow.

https://godbolt.org/z/zeMvas3nq

Martin



shift 0 525 31
shift 1 298 19
shift 2 221 19
signed-integer-overflow 0 12212 11350
signed-integer-overflow 1 6310 5913
signed-integer-overflow 2 3803 3172
integer-divide-by-zero 0 332 332
integer-divide-by-zero 1 135 135
integer-divide-by-zero 2 95 95
unreachable 0 0 0
unreachable 1 0 0
unreachable 2 4 4
vla-bound 0 2671 2426
vla-bound 1 1206 1143
vla-bound 2 1024 906
null 0 32041 26739
null 1 8926 7666
null 2 8622 6769
return 0 0 0
return 1 0 0
return 2 4 4
bounds 0 5031 4830
bounds 1 4776 4551
bounds 2 4986 4547
bounds-strict 0 5031 4830
bounds-strict 1 4776 4551
bounds-strict 2 4986 4547
alignment 0 31818 26524
alignment 1 9848 8441
alignment 2 10031 7855
object-size 0 465 453
object-size 1 5928 5491
object-size 2 6013 5366
float-divide-by-zero 0 532 532
float-divide-by-zero 1 430 429
float-divide-by-zero 2 250 245
float-cast-overflow 0 107 98
float-cast-overflow 1 99 91
float-cast-overflow 2 65 59
nonnull-attribute 0 13433 7672
nonnull-attribute 1 5199 3466
nonnull-attribute 2 1085 1005
return-nonnull-attribute 0 0 0
return-nonnull-attribute 1 0 0
return-nonnull-attribute 2 0 0
bool 0 1053 1036
bool 1 988 972
bool 2 371 363
enum 0 0 0
enum 1 0 0
enum 2 4 4
pointer-overflow 0 29095 25298
pointer-overflow 1 17284 16254
pointer-overflow 2 18598 16110
builtin 0 0 0
builtin 1 0 0
builtin 2 4 4

Reply via email to