--- /dev/null
+/* PR middle-end/93646 - confusing -Wstringop-truncation on strncat where
+ -Wstringop-overflow is expected
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+extern __SIZE_TYPE__ strlen (const char*);
+extern char* strncat (char*, const char*, __SIZE_TYPE__);
+
+
+char a[4];
+
+
+void f0 (char *d, const char *s)
+{
+ strncat (d, s, strlen (s)); // { dg-warning "specified bound depends on the length of the source argument" }
+ /* { dg-message "function 'f0'.*inlined from 'f1'" "inlining stack" { target *-*-* } 0 } */
+
+ // Prevent f0 from being replaced by g0.
+ *d = 'f';
+}
+
+void f1 (const char *s)
+{
+ f0 (a, s);
+}
+
+
+static void g0 (char *d, const char *s)
+{
+ strncat (d, s, strlen (s)); // { dg-warning "specified bound 3 equals source length" }
+ /* { dg-message "function 'g0'.*inlined from 'g1'" "inlining stack" { target *-*-* } 0 } */
+
+ // Prevent g0 from being replaced by f0.
+ *d = 'g';
+}
+
+void g1 (void)
+{
+ g0 (a, "123");
+}
} laststmt;
static int get_stridx_plus_constant (strinfo *, unsigned HOST_WIDE_INT, tree);
-static void handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *);
+static void handle_builtin_stxncpy_strncat (bool, gimple_stmt_iterator *);
/* Sets MINMAX to either the constant value or the range VAL is in
and returns either the constant value or VAL on success or null
and if so, issue an appropriate warning. */
static void
-handle_builtin_strncat (built_in_function bcode, gimple_stmt_iterator *gsi)
+handle_builtin_strncat (built_in_function, gimple_stmt_iterator *gsi)
{
/* Same as stxncpy(). */
- handle_builtin_stxncpy (bcode, gsi);
+ handle_builtin_stxncpy_strncat (true, gsi);
}
/* Return true if LEN depends on a call to strlen(SRC) in an interesting
return false;
}
-/* Called by handle_builtin_stxncpy and by gimple_fold_builtin_strncpy
- in gimple-fold.c.
+/* Called by handle_builtin_stxncpy_strncat and by
+ gimple_fold_builtin_strncpy in gimple-fold.c.
Check to see if the specified bound is a) equal to the size of
the destination DST and if so, b) if it's immediately followed by
DST[CNT - 1] = '\0'. If a) holds and b) does not, warn. Otherwise,
return false;
}
-/* Check the arguments to the built-in forms of stpncpy and strncpy for
- out-of-bounds offsets or overlapping access, and to see if the size
- is derived from calling strlen() on the source argument, and if so,
- issue the appropriate warning. */
+/* Check the arguments to the built-in forms of stpncpy, strncpy, and
+ strncat, for out-of-bounds offsets or overlapping access, and to see
+ if the size is derived from calling strlen() on the source argument,
+ and if so, issue the appropriate warning.
+ APPEND_P is true for strncat. */
static void
-handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *gsi)
+handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
{
if (!strlen_to_stridx)
return;
whether its value is known. Otherwise, issue the more generic
-Wstringop-overflow which triggers for LEN arguments that in
any meaningful way depend on strlen(SRC). */
- if (sisrc == silen
+ if (!append_p
+ && sisrc == silen
&& is_strlen_related_p (src, len)
&& warning_at (callloc, OPT_Wstringop_truncation,
"%G%qD output truncated before terminating nul "
case BUILT_IN_STPNCPY_CHK:
case BUILT_IN_STRNCPY:
case BUILT_IN_STRNCPY_CHK:
- handle_builtin_stxncpy (DECL_FUNCTION_CODE (callee), gsi);
+ handle_builtin_stxncpy_strncat (false, gsi);
break;
case BUILT_IN_MEMCPY: