diff options
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index 2cb1996..25e01e4 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -3151,21 +3151,39 @@ expand_builtin_strnlen (tree exp, rtx target, machine_mode target_mode) exp, func, min.to_uhwi (), max.to_uhwi (), maxobjsize)) TREE_NO_WARNING (exp) = true; + bool exact = true; if (!len || TREE_CODE (len) != INTEGER_CST) - return NULL_RTX; + { + data.decl = unterminated_array (src, &len, &exact); + if (!data.decl) + return NULL_RTX; + } - if (!TREE_NO_WARNING (exp) - && wi::ltu_p (wi::to_wide (len), min) - && warning_at (loc, OPT_Wstringop_overflow_, - "%K%qD specified bound [%wu, %wu] " - "exceeds the size %E of unterminated array", - exp, func, min.to_uhwi (), max.to_uhwi (), len)) + if (data.decl + && !TREE_NO_WARNING (exp) + && (wi::ltu_p (wi::to_wide (len), min) + || !exact)) { - inform (DECL_SOURCE_LOCATION (data.decl), - "referenced argument declared here"); - TREE_NO_WARNING (exp) = true; + location_t warnloc + = expansion_point_location_if_in_system_header (loc); + + if (warning_at (warnloc, OPT_Wstringop_overflow_, + exact + ? G_("%K%qD specified bound [%wu, %wu] exceeds " + "the size %E of unterminated array") + : G_("%K%qD specified bound [%wu, %wu] may exceed " + "the size of at most %E of unterminated array"), + exp, func, min.to_uhwi (), max.to_uhwi (), len)) + { + inform (DECL_SOURCE_LOCATION (data.decl), + "referenced argument declared here"); + TREE_NO_WARNING (exp) = true; + } } + if (data.decl) + return NULL_RTX; + if (wi::gtu_p (min, wi::to_wide (len))) return expand_expr (len, target, target_mode, EXPAND_NORMAL); |