From 407b92bcfb34f352b6aad7b629bf365c02114469 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 27 Aug 2019 23:31:44 +0000 Subject: [PATCH] PR tree-optimization/91567 - Spurious -Wformat-overflow warnings building glibc (32-bit only) gcc/ChangeLog: PR tree-optimization/91567 * gimple-ssa-sprintf.c (get_string_length): Handle more forms of lengths of unknown strings. * vr-values.c (vr_values::extract_range_basic): Set strlen upper bound to PTRDIFF_MAX - 2. gcc/testsuite/ChangeLog: PR tree-optimization/91567 * gcc.dg/tree-ssa/builtin-snprintf-6.c: Xfail a subset of assertions on targets other than x86_64 to work around PR 83543. * gcc.dg/tree-ssa/builtin-sprintf-warn-22.c: New test. From-SVN: r274976 --- gcc/ChangeLog | 8 +++ gcc/gimple-ssa-sprintf.c | 19 ++++-- gcc/testsuite/ChangeLog | 7 +++ .../gcc.dg/tree-ssa/builtin-snprintf-6.c | 7 +++ .../gcc.dg/tree-ssa/builtin-sprintf-warn-22.c | 58 +++++++++++++++++++ gcc/vr-values.c | 7 ++- 6 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-22.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1d9d6cf0ff2..1213e958bb8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2019-08-27 Martin Sebor + + PR tree-optimization/91567 + * gimple-ssa-sprintf.c (get_string_length): Handle more forms of lengths + of unknown strings. + * vr-values.c (vr_values::extract_range_basic): Set strlen upper bound + to PTRDIFF_MAX - 2. + 2019-08-27 Jeff Law * tree-ssa-strlen.c (printf_strlen_execute): Initialize diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c index 6a39a71900a..b11d7989d5e 100644 --- a/gcc/gimple-ssa-sprintf.c +++ b/gcc/gimple-ssa-sprintf.c @@ -1994,10 +1994,21 @@ get_string_length (tree str, unsigned eltsize, const vr_values *vr) or it's SIZE_MAX otherwise. */ /* Return the default result when nothing is known about the string. */ - if (lendata.maxbound - && integer_all_onesp (lendata.maxbound) - && integer_all_onesp (lendata.maxlen)) - return fmtresult (); + if (lendata.maxbound) + { + if (integer_all_onesp (lendata.maxbound) + && integer_all_onesp (lendata.maxlen)) + return fmtresult (); + + if (!tree_fits_uhwi_p (lendata.maxbound) + || !tree_fits_uhwi_p (lendata.maxlen)) + return fmtresult (); + + unsigned HOST_WIDE_INT lenmax = tree_to_uhwi (max_object_size ()) - 2; + if (lenmax <= tree_to_uhwi (lendata.maxbound) + && lenmax <= tree_to_uhwi (lendata.maxlen)) + return fmtresult (); + } HOST_WIDE_INT min = (tree_fits_uhwi_p (lendata.minlen) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2560faf8526..cd6fb7fc8f6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2019-08-27 Martin Sebor + + PR tree-optimization/91567 + * gcc.dg/tree-ssa/builtin-snprintf-6.c: Xfail a subset of assertions + on targets other than x86_64 to work around PR 83543. + * gcc.dg/tree-ssa/builtin-sprintf-warn-22.c: New test. + 2019-08-27 Jeff Law * gcc.c-torture/compile/20190827-1.c: New test. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-6.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-6.c index 0d9b27505ec..df0e6b7d19c 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-6.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-6.c @@ -65,6 +65,10 @@ void test_assign_init_list (void) T (5, ARGS ({ 1, 2, 3, 4, 5, 6, 0 }), "s=%.*s", 3, &a[2]); } +#if __x86_64__ + +/* Enabled only on x86_64 to work around PR 83543. */ + #undef T #define T(expect, init, fmt, ...) \ do { \ @@ -87,6 +91,9 @@ void test_assign_aggregate (void) T (5, "123456", "s=%.*s", 3, &s.a[2]); } +/* { dg-final { scan-tree-dump-times "Function test_assign_aggregate" 1 "optimized" { xfail { { ! x86_64-*-* } || { ilp32 } } } } } */ + +#endif /* x86_64 */ #undef T #define T(expect, init, fmt, ...) \ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-22.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-22.c new file mode 100644 index 00000000000..6fd1bca3c7b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-22.c @@ -0,0 +1,58 @@ +/* PR tree-optimization/91567 - Spurious -Wformat-overflow warnings building + glibc (32-bit only) + { dg-do compile } + { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */ + +typedef __SIZE_TYPE__ size_t; + +extern int sprintf (char*, const char*, ...); +extern size_t strlen (const char*); + +void f (char *); + +void g (char *s1, char *s2) +{ + char b[1025]; + size_t n = __builtin_strlen (s1), d = __builtin_strlen (s2); + if (n + d + 1 >= 1025) + return; + + sprintf (b, "%s.%s", s1, s2); // { dg-bogus "\\\[-Wformat-overflow" } + + f (b); +} + +/* Extracted from gcc/c-cppbuiltin.c. */ + +void cpp_define (char*); + +static void +builtin_define_type_minmax (const char *min_macro, const char *max_macro, + void *type) +{ + extern const char *suffix; + char *buf; + + if (type) + { + buf = (char *) __builtin_alloca (__builtin_strlen (min_macro) + 2 + + __builtin_strlen (suffix) + 1); + sprintf (buf, "%s=0%s", min_macro, suffix); // { dg-bogus "\\\[-Wformat-overflow" } + } + else + { + buf = (char *) __builtin_alloca (__builtin_strlen (min_macro) + 3 + + __builtin_strlen (max_macro) + 6); + sprintf (buf, "%s=(-%s - 1)", min_macro, max_macro); // { dg-bogus "\\\[-Wformat-overflow" } + } + + cpp_define (buf); +} + +void +c_cpp_builtins (void *type) +{ + + builtin_define_type_minmax ("__WCHAR_MIN__", "__WCHAR_MAX__", type); + builtin_define_type_minmax ("__WINT_MIN__", "__WINT_MAX__", type); +} diff --git a/gcc/vr-values.c b/gcc/vr-values.c index 96c764c987b..256cae73ebb 100644 --- a/gcc/vr-values.c +++ b/gcc/vr-values.c @@ -1319,7 +1319,12 @@ vr_values::extract_range_basic (value_range *vr, gimple *stmt) tree max = vrp_val_max (ptrdiff_type_node); wide_int wmax = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max))); tree range_min = build_zero_cst (type); - tree range_max = wide_int_to_tree (type, wmax - 1); + /* To account for the terminating NUL, the maximum length + is one less than the maximum array size, which in turn + is one less than PTRDIFF_MAX (or SIZE_MAX where it's + smaller than the former type). + FIXME: Use max_object_size() - 1 here. */ + tree range_max = wide_int_to_tree (type, wmax - 2); vr->set (VR_RANGE, range_min, range_max); return; } -- 2.30.2