Jakub Jelinek <ja...@redhat.com> writes:
> Hi!
>
> The recent pp_wide_int changes for _BitInt support (because not all
> wide_ints fit into the small fixed size digit_buffer anymore) apparently
> broke
> +FAIL: gcc.dg/analyzer/out-of-bounds-diagram-1-debug.c (test for excess 
> errors)
> +FAIL: gcc.dg/analyzer/out-of-bounds-diagram-1-debug.c 2 blank line(s) in 
> output
> +FAIL: gcc.dg/analyzer/out-of-bounds-diagram-1-debug.c expected multiline 
> pattern lines 17-39
> (and I couldn't reproduce that in bisect seed (which is -O0 compiled) and
> thought it would be some analyzer diagnostic bug).
>
> The problem is that analyzer uses pp_wide_int with a function call in the
> second argument.  Previously, when pp_wide_int macro just did
>   print_dec (W, pp_buffer (PP)->digit_buffer, SGN);
>   pp_string (PP, pp_buffer (PP)->digit_buffer);
> it worked, because the const wide_int_ref & first argument to print_dec
> bound to a temporary, which was only destructed at the end of the full
> statement after print_dec was called.
> But with my changes where I need to first compare the precision of the
> const wide_int_ref & to decide whether to use digit_buffer or XALLOCAVEC
> something larger, this means that pp_wide_int_ref binds to a temporary
> which is destroyed at the end of full statement which is the
>   const wide_int_ref &pp_wide_int_ref = (W);
> declaration, so then invokes UB accessing a destructed temporary.
>
> The following patch fixes it by rewriting pp_wide_int into an inline
> function, so that the end of the full statement is the end of the inline
> function call.  As functions using alloca aren't normally inlined, I've
> also split that part into a separate out of line function.  Putting that
> into pretty-print.cc didn't work, e.g. the gm2 binary doesn't link,
> because pretty-print.o is in libcommon.a, but wide-print-print.o which
> defines print_dec is not.  So I've put that out of line function into
> wide-int-print.cc instead.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2023-09-08  Jakub Jelinek  <ja...@redhat.com>
>
>       PR middle-end/111329
>       * pretty-print.h (pp_wide_int): Rewrite from macro into inline
>       function.  For printing values which don't fit into digit_buffer
>       use out-of-line function.
>       * wide-int-print.h (pp_wide_int_large): Declare.
>       * wide-int-print.cc: Include pretty-print.h.
>       (pp_wide_int_large): Define.

OK, thanks.

Richard

> --- gcc/pretty-print.h.jj     2023-09-06 14:36:53.485246347 +0200
> +++ gcc/pretty-print.h        2023-09-08 11:11:21.173649942 +0200
> @@ -333,28 +333,6 @@ pp_get_prefix (const pretty_printer *pp)
>  #define pp_decimal_int(PP, I)  pp_scalar (PP, "%d", I)
>  #define pp_unsigned_wide_integer(PP, I) \
>     pp_scalar (PP, HOST_WIDE_INT_PRINT_UNSIGNED, (unsigned HOST_WIDE_INT) I)
> -#define pp_wide_int(PP, W, SGN)                                      \
> -  do                                                         \
> -    {                                                                \
> -      const wide_int_ref &pp_wide_int_ref = (W);             \
> -      unsigned int pp_wide_int_prec                          \
> -     = pp_wide_int_ref.get_precision ();                     \
> -      if ((pp_wide_int_prec + 3) / 4                         \
> -       > sizeof (pp_buffer (PP)->digit_buffer) - 3)          \
> -     {                                                       \
> -       char *pp_wide_int_buf                                 \
> -         = XALLOCAVEC (char, (pp_wide_int_prec + 3) / 4 + 3);\
> -       print_dec (pp_wide_int_ref, pp_wide_int_buf, SGN);    \
> -       pp_string (PP, pp_wide_int_buf);                      \
> -     }                                                       \
> -      else                                                   \
> -     {                                                       \
> -       print_dec (pp_wide_int_ref,                           \
> -                  pp_buffer (PP)->digit_buffer, SGN);        \
> -       pp_string (PP, pp_buffer (PP)->digit_buffer);         \
> -     }                                                       \
> -    }                                                                \
> -  while (0)
>  #define pp_vrange(PP, R)                                     \
>    do                                                         \
>      {                                                                \
> @@ -453,6 +431,19 @@ pp_wide_integer (pretty_printer *pp, HOS
>    pp_scalar (pp, HOST_WIDE_INT_PRINT_DEC, i);
>  }
>  
> +inline void
> +pp_wide_int (pretty_printer *pp, const wide_int_ref &w, signop sgn)
> +{
> +  unsigned int prec = w.get_precision ();
> +  if (UNLIKELY ((prec + 3) / 4 > sizeof (pp_buffer (pp)->digit_buffer) - 3))
> +    pp_wide_int_large (pp, w, sgn);
> +  else
> +    {
> +      print_dec (w, pp_buffer (pp)->digit_buffer, sgn);
> +      pp_string (pp, pp_buffer (pp)->digit_buffer);
> +    }
> +}
> +
>  template<unsigned int N, typename T>
>  void pp_wide_integer (pretty_printer *pp, const poly_int_pod<N, T> &);
>  
> --- gcc/wide-int-print.h.jj   2023-09-08 11:03:48.320944156 +0200
> +++ gcc/wide-int-print.h      2023-09-08 11:11:46.982292282 +0200
> @@ -34,5 +34,6 @@ extern void print_decu (const wide_int_r
>  extern void print_decu (const wide_int_ref &wi, FILE *file);
>  extern void print_hex (const wide_int_ref &wi, char *buf);
>  extern void print_hex (const wide_int_ref &wi, FILE *file);
> +extern void pp_wide_int_large (pretty_printer *, const wide_int_ref &, 
> signop);
>  
>  #endif /* WIDE_INT_PRINT_H */
> --- gcc/wide-int-print.cc.jj  2023-09-08 11:03:51.543898946 +0200
> +++ gcc/wide-int-print.cc     2023-09-08 11:12:11.481952762 +0200
> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.
>  #include "config.h"
>  #include "system.h"
>  #include "coretypes.h"
> +#include "pretty-print.h"
>  
>  /*
>   * public printing routines.
> @@ -138,3 +139,14 @@ print_hex (const wide_int_ref &wi, FILE
>    fputs (buf, file);
>  }
>  
> +/* Print larger precision wide_int.  Not defined as inline in a header
> +   together with pp_wide_int because XALLOCAVEC will make it uninlinable.  */
> +
> +void
> +pp_wide_int_large (pretty_printer *pp, const wide_int_ref &w, signop sgn)
> +{
> +  unsigned int prec = w.get_precision ();
> +  char *buf = XALLOCAVEC (char, (prec + 3) / 4 + 3);
> +  print_dec (w, buf, sgn);
> +  pp_string (pp, buf);
> +}
>
>       Jakub

Reply via email to