diff options
author | Martin Sebor <msebor@redhat.com> | 2021-08-06 15:29:33 -0600 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2021-08-06 16:08:36 -0600 |
commit | 81d6cdd335ffc60c216a020d5c99306f659377a2 (patch) | |
tree | dfc6982f6965e62985d4cc77343c1e26dccebb41 /gcc/builtins.c | |
parent | 629b5699fb555b30c25ebc0b503e87b470bed076 (diff) | |
download | gcc-81d6cdd335ffc60c216a020d5c99306f659377a2.zip gcc-81d6cdd335ffc60c216a020d5c99306f659377a2.tar.gz gcc-81d6cdd335ffc60c216a020d5c99306f659377a2.tar.bz2 |
Move more code to new gimple-ssa-warn-access pass.
gcc/ChangeLog:
* builtins.c (expand_builtin_memchr): Move to gimple-ssa-warn-access.cc.
(expand_builtin_strcat): Same.
(expand_builtin_stpncpy): Same.
(expand_builtin_strncat): Same.
(check_read_access): Same.
(check_memop_access): Same.
(expand_builtin_strlen): Move checks to gimple-ssa-warn-access.cc.
(expand_builtin_strnlen): Same.
(expand_builtin_memcpy): Same.
(expand_builtin_memmove): Same.
(expand_builtin_mempcpy): Same.
(expand_builtin_strcpy): Same.
(expand_builtin_strcpy_args): Same.
(expand_builtin_stpcpy_1): Same.
(expand_builtin_strncpy): Same.
(expand_builtin_memset): Same.
(expand_builtin_bzero): Same.
(expand_builtin_strcmp): Same.
(expand_builtin_strncmp): Same.
(expand_builtin): Remove handlers.
(fold_builtin_strlen): Add a comment.
* builtins.h (check_access): Move to gimple-ssa-warn-access.cc.
* calls.c (maybe_warn_nonstring_arg): Same.
* diagnostic-spec.c (nowarn_spec_t::nowarn_spec_t): Add warning option.
* gimple-fold.c (gimple_fold_builtin_strcpy): Pass argument to callee.
(gimple_fold_builtin_stpcpy): Same.
* gimple-ssa-warn-access.cc (has_location): New function.
(get_location): Same.
(get_callee_fndecl): Same.
(call_nargs): Same.
(call_arg): Same.
(warn_string_no_nul): Define.
(unterminated_array): Same.
(check_nul_terminated_array): Same.
(maybe_warn_nonstring_arg): Same.
(maybe_warn_for_bound): Same.
(warn_for_access): Same.
(check_access): Same.
(check_memop_access): Same.
(check_read_access): Same.
(warn_dealloc_offset): Use helper functions.
(maybe_emit_free_warning): Same.
(class pass_waccess): Add members.
(check_strcat): New function.
(check_strncat): New function.
(check_stxcpy): New function.
(check_stxncpy): New function.
(check_strncmp): New function.
(pass_waccess::check_builtin): New function.
(pass_waccess::check): Call it.
* gimple-ssa-warn-access.h (warn_string_no_nul): Move here from
builtins.h.
(maybe_warn_for_bound): Same.
(check_access): Same.
(check_memop_access): Same.
(check_read_access): Same.
* pointer-query.h (struct access_data): Define a ctor overload.
gcc/testsuite/ChangeLog:
* c-c++-common/Wsizeof-pointer-memaccess1.c: Also disable
-Wstringop-overread.
* c-c++-common/attr-nonstring-3.c: Adjust pattern of expected message.
* gcc.dg/Warray-bounds-39.c: Add an xfail due to a known bug.
* gcc.dg/Wstring-compare-3.c: Also disable -Wstringop-overread.
* gcc.dg/attr-nonstring-2.c: Adjust pattern of expected message.
* gcc.dg/attr-nonstring-4.c: Same.
* gcc.dg/Wstringop-overread-6.c: New test.
* gcc.dg/sso-14.c: Fix typos to avoid buffer overflow.
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 399 |
1 files changed, 7 insertions, 392 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index 2387b5d..d2be807f 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -131,7 +131,6 @@ static rtx expand_builtin_va_copy (tree); static rtx inline_expand_builtin_bytecmp (tree, rtx); static rtx expand_builtin_strcmp (tree, rtx); static rtx expand_builtin_strncmp (tree, rtx, machine_mode); -static rtx expand_builtin_memchr (tree, rtx); static rtx expand_builtin_memcpy (tree, rtx); static rtx expand_builtin_memory_copy_args (tree dest, tree src, tree len, rtx target, tree exp, @@ -140,12 +139,9 @@ static rtx expand_builtin_memory_copy_args (tree dest, tree src, tree len, static rtx expand_builtin_memmove (tree, rtx); static rtx expand_builtin_mempcpy (tree, rtx); static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, tree, memop_ret); -static rtx expand_builtin_strcat (tree); static rtx expand_builtin_strcpy (tree, rtx); static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx); static rtx expand_builtin_stpcpy (tree, rtx, machine_mode); -static rtx expand_builtin_stpncpy (tree, rtx); -static rtx expand_builtin_strncat (tree, rtx); static rtx expand_builtin_strncpy (tree, rtx); static rtx expand_builtin_memset (tree, rtx, machine_mode); static rtx expand_builtin_memset_args (tree, tree, tree, rtx, machine_mode, tree); @@ -186,7 +182,6 @@ static rtx expand_builtin_memory_chk (tree, rtx, machine_mode, static void maybe_emit_chk_warning (tree, enum built_in_function); static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function); static tree fold_builtin_object_size (tree, tree); -static bool check_read_access (tree, tree, tree = NULL_TREE, int = 1); unsigned HOST_WIDE_INT target_newline; unsigned HOST_WIDE_INT target_percent; @@ -2957,8 +2952,6 @@ expand_builtin_strlen (tree exp, rtx target, return NULL_RTX; tree src = CALL_EXPR_ARG (exp, 0); - if (!check_read_access (exp, src)) - return NULL_RTX; /* If the length can be computed at compile-time, return it. */ if (tree len = c_strlen (src, 0)) @@ -3062,8 +3055,6 @@ expand_builtin_strnlen (tree exp, rtx target, machine_mode target_mode) if (!bound) return NULL_RTX; - check_read_access (exp, src, bound); - location_t loc = UNKNOWN_LOCATION; if (EXPR_HAS_LOCATION (exp)) loc = EXPR_LOCATION (exp); @@ -3201,65 +3192,6 @@ determine_block_size (tree len, rtx len_rtx, GET_MODE_MASK (GET_MODE (len_rtx))); } -/* A convenience wrapper for check_access above to check access - by a read-only function like puts. */ - -static bool -check_read_access (tree exp, tree src, tree bound /* = NULL_TREE */, - int ost /* = 1 */) -{ - if (!warn_stringop_overread) - return true; - - if (bound && !useless_type_conversion_p (size_type_node, TREE_TYPE (bound))) - bound = fold_convert (size_type_node, bound); - access_data data (exp, access_read_only, NULL_TREE, false, bound, true); - compute_objsize (src, ost, &data.src); - return check_access (exp, /*dstwrite=*/ NULL_TREE, /*maxread=*/ bound, - /*srcstr=*/ src, /*dstsize=*/ NULL_TREE, data.mode, - &data); -} - -/* Helper to determine and check the sizes of the source and the destination - of calls to __builtin_{bzero,memcpy,mempcpy,memset} calls. EXP is the - call expression, DEST is the destination argument, SRC is the source - argument or null, and LEN is the number of bytes. Use Object Size type-0 - regardless of the OPT_Wstringop_overflow_ setting. Return true on success - (no overflow or invalid sizes), false otherwise. */ - -static bool -check_memop_access (tree exp, tree dest, tree src, tree size) -{ - /* For functions like memset and memcpy that operate on raw memory - try to determine the size of the largest source and destination - object using type-0 Object Size regardless of the object size - type specified by the option. */ - access_data data (exp, access_read_write); - tree srcsize = src ? compute_objsize (src, 0, &data.src) : NULL_TREE; - tree dstsize = compute_objsize (dest, 0, &data.dst); - - return check_access (exp, size, /*maxread=*/NULL_TREE, - srcsize, dstsize, data.mode, &data); -} - -/* Validate memchr arguments without performing any expansion. - Return NULL_RTX. */ - -static rtx -expand_builtin_memchr (tree exp, rtx) -{ - if (!validate_arglist (exp, - POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return NULL_RTX; - - tree arg1 = CALL_EXPR_ARG (exp, 0); - tree len = CALL_EXPR_ARG (exp, 2); - - check_read_access (exp, arg1, len, 0); - - return NULL_RTX; -} - /* Expand a call EXP to the memcpy builtin. Return NULL_RTX if we failed, the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient (and in @@ -3276,8 +3208,6 @@ expand_builtin_memcpy (tree exp, rtx target) tree src = CALL_EXPR_ARG (exp, 1); tree len = CALL_EXPR_ARG (exp, 2); - check_memop_access (exp, dest, src, len); - return expand_builtin_memory_copy_args (dest, src, len, target, exp, /*retmode=*/ RETURN_BEGIN, false); } @@ -3296,8 +3226,6 @@ expand_builtin_memmove (tree exp, rtx target) tree src = CALL_EXPR_ARG (exp, 1); tree len = CALL_EXPR_ARG (exp, 2); - check_memop_access (exp, dest, src, len); - return expand_builtin_memory_copy_args (dest, src, len, target, exp, /*retmode=*/ RETURN_BEGIN, true); } @@ -3334,8 +3262,6 @@ expand_builtin_mempcpy (tree exp, rtx target) /* Avoid expanding mempcpy into memcpy when the call is determined to overflow the buffer. This also prevents the same overflow from being diagnosed again when expanding memcpy. */ - if (!check_memop_access (exp, dest, src, len)) - return NULL_RTX; return expand_builtin_mempcpy_args (dest, src, len, target, exp, /*retmode=*/ RETURN_END); @@ -3511,36 +3437,6 @@ expand_movstr (tree dest, tree src, rtx target, memop_ret retmode) return target; } -/* Do some very basic size validation of a call to the strcpy builtin - given by EXP. Return NULL_RTX to have the built-in expand to a call - to the library function. */ - -static rtx -expand_builtin_strcat (tree exp) -{ - if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE) - || !warn_stringop_overflow) - return NULL_RTX; - - tree dest = CALL_EXPR_ARG (exp, 0); - tree src = CALL_EXPR_ARG (exp, 1); - - /* There is no way here to determine the length of the string in - the destination to which the SRC string is being appended so - just diagnose cases when the souce string is longer than - the destination object. */ - access_data data (exp, access_read_write, NULL_TREE, true, - NULL_TREE, true); - const int ost = warn_stringop_overflow ? warn_stringop_overflow - 1 : 1; - compute_objsize (src, ost, &data.src); - tree destsize = compute_objsize (dest, ost, &data.dst); - - check_access (exp, /*dstwrite=*/NULL_TREE, /*maxread=*/NULL_TREE, - src, destsize, data.mode, &data); - - return NULL_RTX; -} - /* Expand expression EXP, which is a call to the strcpy builtin. Return NULL_RTX if we failed the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient (and in mode MODE if that's @@ -3555,29 +3451,7 @@ expand_builtin_strcpy (tree exp, rtx target) tree dest = CALL_EXPR_ARG (exp, 0); tree src = CALL_EXPR_ARG (exp, 1); - if (warn_stringop_overflow) - { - access_data data (exp, access_read_write, NULL_TREE, true, - NULL_TREE, true); - const int ost = warn_stringop_overflow ? warn_stringop_overflow - 1 : 1; - compute_objsize (src, ost, &data.src); - tree dstsize = compute_objsize (dest, ost, &data.dst); - check_access (exp, /*dstwrite=*/ NULL_TREE, - /*maxread=*/ NULL_TREE, /*srcstr=*/ src, - dstsize, data.mode, &data); - } - - if (rtx ret = expand_builtin_strcpy_args (exp, dest, src, target)) - { - /* Check to see if the argument was declared attribute nonstring - and if so, issue a warning since at this point it's not known - to be nul-terminated. */ - tree fndecl = get_callee_fndecl (exp); - maybe_warn_nonstring_arg (fndecl, exp); - return ret; - } - - return NULL_RTX; + return expand_builtin_strcpy_args (exp, dest, src, target); } /* Helper function to do the actual work for expand_builtin_strcpy. The @@ -3587,19 +3461,8 @@ expand_builtin_strcpy (tree exp, rtx target) expand_builtin_strcpy. */ static rtx -expand_builtin_strcpy_args (tree exp, tree dest, tree src, rtx target) +expand_builtin_strcpy_args (tree, tree dest, tree src, rtx target) { - /* Detect strcpy calls with unterminated arrays.. */ - tree size; - bool exact; - if (tree nonstr = unterminated_array (src, &size, &exact)) - { - /* NONSTR refers to the non-nul terminated constant array. */ - warn_string_no_nul (EXPR_LOCATION (exp), exp, NULL, src, nonstr, - size, exact); - return NULL_RTX; - } - return expand_movstr (dest, src, target, /*retmode=*/ RETURN_BEGIN); } @@ -3620,15 +3483,6 @@ expand_builtin_stpcpy_1 (tree exp, rtx target, machine_mode mode) dst = CALL_EXPR_ARG (exp, 0); src = CALL_EXPR_ARG (exp, 1); - if (warn_stringop_overflow) - { - access_data data (exp, access_read_write); - tree destsize = compute_objsize (dst, warn_stringop_overflow - 1, - &data.dst); - check_access (exp, /*dstwrite=*/NULL_TREE, /*maxread=*/NULL_TREE, - src, destsize, data.mode, &data); - } - /* If return value is ignored, transform stpcpy into strcpy. */ if (target == const0_rtx && builtin_decl_implicit (BUILT_IN_STRCPY)) { @@ -3651,9 +3505,6 @@ expand_builtin_stpcpy_1 (tree exp, rtx target, machine_mode mode) return expand_movstr (dst, src, target, /*retmode=*/ RETURN_END_MINUS_ONE); - if (lendata.decl) - warn_string_no_nul (EXPR_LOCATION (exp), exp, NULL, src, lendata.decl); - lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1)); ret = expand_builtin_mempcpy_args (dst, src, lenp1, target, exp, @@ -3715,30 +3566,6 @@ expand_builtin_stpcpy (tree exp, rtx target, machine_mode mode) return NULL_RTX; } -/* Check a call EXP to the stpncpy built-in for validity. - Return NULL_RTX on both success and failure. */ - -static rtx -expand_builtin_stpncpy (tree exp, rtx) -{ - if (!validate_arglist (exp, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE) - || !warn_stringop_overflow) - return NULL_RTX; - - /* The source and destination of the call. */ - tree dest = CALL_EXPR_ARG (exp, 0); - tree src = CALL_EXPR_ARG (exp, 1); - - /* The exact number of bytes to write (not the maximum). */ - tree len = CALL_EXPR_ARG (exp, 2); - access_data data (exp, access_read_write); - /* The size of the destination object. */ - tree destsize = compute_objsize (dest, warn_stringop_overflow - 1, &data.dst); - check_access (exp, len, /*maxread=*/len, src, destsize, data.mode, &data); - return NULL_RTX; -} - /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE) bytes from constant string DATA + OFFSET and return it as target constant. */ @@ -3817,78 +3644,6 @@ check_strncat_sizes (tree exp, tree objsize) objsize, data.mode, &data); } -/* Similar to expand_builtin_strcat, do some very basic size validation - of a call to the strcpy builtin given by EXP. Return NULL_RTX to have - the built-in expand to a call to the library function. */ - -static rtx -expand_builtin_strncat (tree exp, rtx) -{ - if (!validate_arglist (exp, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE) - || !warn_stringop_overflow) - return NULL_RTX; - - tree dest = CALL_EXPR_ARG (exp, 0); - tree src = CALL_EXPR_ARG (exp, 1); - /* The upper bound on the number of bytes to write. */ - tree maxread = CALL_EXPR_ARG (exp, 2); - - /* Detect unterminated source (only). */ - if (!check_nul_terminated_array (exp, src, maxread)) - return NULL_RTX; - - /* The length of the source sequence. */ - tree slen = c_strlen (src, 1); - - /* Try to determine the range of lengths that the source expression - refers to. Since the lengths are only used for warning and not - for code generation disable strict mode below. */ - tree maxlen = slen; - if (!maxlen) - { - c_strlen_data lendata = { }; - get_range_strlen (src, &lendata, /* eltsize = */ 1); - maxlen = lendata.maxbound; - } - - access_data data (exp, access_read_write); - /* Try to verify that the destination is big enough for the shortest - string. First try to determine the size of the destination object - into which the source is being copied. */ - tree destsize = compute_objsize (dest, warn_stringop_overflow - 1, &data.dst); - - /* Add one for the terminating nul. */ - tree srclen = (maxlen - ? fold_build2 (PLUS_EXPR, size_type_node, maxlen, - size_one_node) - : NULL_TREE); - - /* The strncat function copies at most MAXREAD bytes and always appends - the terminating nul so the specified upper bound should never be equal - to (or greater than) the size of the destination. */ - if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (destsize) - && tree_int_cst_equal (destsize, maxread)) - { - location_t loc = EXPR_LOCATION (exp); - warning_at (loc, OPT_Wstringop_overflow_, - "%qD specified bound %E equals destination size", - get_callee_fndecl (exp), maxread); - - return NULL_RTX; - } - - if (!srclen - || (maxread && tree_fits_uhwi_p (maxread) - && tree_fits_uhwi_p (srclen) - && tree_int_cst_lt (maxread, srclen))) - srclen = maxread; - - check_access (exp, /*dstwrite=*/NULL_TREE, maxread, srclen, - destsize, data.mode, &data); - return NULL_RTX; -} - /* Expand expression EXP, which is a call to the strncpy builtin. Return NULL_RTX if we failed the caller should emit a normal call. */ @@ -3908,18 +3663,6 @@ expand_builtin_strncpy (tree exp, rtx target) /* The length of the source sequence. */ tree slen = c_strlen (src, 1); - if (warn_stringop_overflow) - { - access_data data (exp, access_read_write, len, true, len, true); - const int ost = warn_stringop_overflow ? warn_stringop_overflow - 1 : 1; - compute_objsize (src, ost, &data.src); - tree dstsize = compute_objsize (dest, ost, &data.dst); - /* The number of bytes to write is LEN but check_access will also - check SLEN if LEN's value isn't known. */ - check_access (exp, /*dstwrite=*/len, - /*maxread=*/len, src, dstsize, data.mode, &data); - } - /* We must be passed a constant len and src parameter. */ if (!tree_fits_uhwi_p (len) || !slen || !tree_fits_uhwi_p (slen)) return NULL_RTX; @@ -4141,8 +3884,6 @@ expand_builtin_memset (tree exp, rtx target, machine_mode mode) tree val = CALL_EXPR_ARG (exp, 1); tree len = CALL_EXPR_ARG (exp, 2); - check_memop_access (exp, dest, NULL_TREE, len); - return expand_builtin_memset_args (dest, val, len, target, mode, exp); } @@ -4470,8 +4211,6 @@ expand_builtin_bzero (tree exp) tree dest = CALL_EXPR_ARG (exp, 0); tree size = CALL_EXPR_ARG (exp, 1); - check_memop_access (exp, dest, NULL_TREE, size); - /* New argument list transforming bzero(ptr x, int y) to memset(ptr x, int 0, size_t y). This is done this way so that if it isn't expanded inline, we fallback to @@ -4622,10 +4361,6 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target) tree arg1 = CALL_EXPR_ARG (exp, 0); tree arg2 = CALL_EXPR_ARG (exp, 1); - if (!check_read_access (exp, arg1) - || !check_read_access (exp, arg2)) - return NULL_RTX; - /* Due to the performance benefit, always inline the calls first. */ rtx result = NULL_RTX; result = inline_expand_builtin_bytecmp (exp, target); @@ -4707,11 +4442,6 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target) tree fndecl = get_callee_fndecl (exp); if (result) { - /* Check to see if the argument was declared attribute nonstring - and if so, issue a warning since at this point it's not known - to be nul-terminated. */ - maybe_warn_nonstring_arg (fndecl, exp); - /* Return the value in the proper mode for this function. */ machine_mode mode = TYPE_MODE (TREE_TYPE (exp)); if (GET_MODE (result) == mode) @@ -4725,6 +4455,7 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target) /* Expand the library call ourselves using a stabilized argument list to avoid re-evaluating the function's arguments twice. */ tree fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2); + copy_warning (fn, exp); gcc_assert (TREE_CODE (fn) == CALL_EXPR); CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); return expand_call (fn, target, target == const0_rtx); @@ -4746,66 +4477,10 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target, tree arg2 = CALL_EXPR_ARG (exp, 1); tree arg3 = CALL_EXPR_ARG (exp, 2); - if (!check_nul_terminated_array (exp, arg1, arg3) - || !check_nul_terminated_array (exp, arg2, arg3)) - return NULL_RTX; - location_t loc = EXPR_LOCATION (exp); tree len1 = c_strlen (arg1, 1); tree len2 = c_strlen (arg2, 1); - if (!len1 || !len2) - { - /* Check to see if the argument was declared attribute nonstring - and if so, issue a warning since at this point it's not known - to be nul-terminated. */ - if (!maybe_warn_nonstring_arg (get_callee_fndecl (exp), exp) - && !len1 && !len2) - { - /* A strncmp read is constrained not just by the bound but - also by the length of the shorter string. Specifying - a bound that's larger than the size of either array makes - no sense and is likely a bug. When the length of neither - of the two strings is known but the sizes of both of - the arrays they are stored in is, issue a warning if - the bound is larger than than the size of the larger - of the two arrays. */ - - access_ref ref1 (arg3, true); - access_ref ref2 (arg3, true); - - tree bndrng[2] = { NULL_TREE, NULL_TREE }; - get_size_range (arg3, bndrng, ref1.bndrng); - - tree size1 = compute_objsize (arg1, 1, &ref1); - tree size2 = compute_objsize (arg2, 1, &ref2); - tree func = get_callee_fndecl (exp); - - if (size1 && size2 && bndrng[0] && !integer_zerop (bndrng[0])) - { - offset_int rem1 = ref1.size_remaining (); - offset_int rem2 = ref2.size_remaining (); - if (rem1 == 0 || rem2 == 0) - maybe_warn_for_bound (OPT_Wstringop_overread, loc, exp, func, - bndrng, integer_zero_node); - else - { - offset_int maxrem = wi::max (rem1, rem2, UNSIGNED); - if (maxrem < wi::to_offset (bndrng[0])) - maybe_warn_for_bound (OPT_Wstringop_overread, loc, exp, - func, bndrng, - wide_int_to_tree (sizetype, maxrem)); - } - } - else if (bndrng[0] - && !integer_zerop (bndrng[0]) - && ((size1 && integer_zerop (size1)) - || (size2 && integer_zerop (size2)))) - maybe_warn_for_bound (OPT_Wstringop_overread, loc, exp, func, - bndrng, integer_zero_node); - } - } - /* Due to the performance benefit, always inline the calls first. */ rtx result = NULL_RTX; result = inline_expand_builtin_bytecmp (exp, target); @@ -7544,63 +7219,12 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, return target; break; - case BUILT_IN_STRCAT: - target = expand_builtin_strcat (exp); - if (target) - return target; - break; - - case BUILT_IN_GETTEXT: - case BUILT_IN_PUTS: - case BUILT_IN_PUTS_UNLOCKED: - case BUILT_IN_STRDUP: - if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE)) - check_read_access (exp, CALL_EXPR_ARG (exp, 0)); - break; - - case BUILT_IN_INDEX: - case BUILT_IN_RINDEX: - case BUILT_IN_STRCHR: - case BUILT_IN_STRRCHR: - if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - check_read_access (exp, CALL_EXPR_ARG (exp, 0)); - break; - - case BUILT_IN_FPUTS: - case BUILT_IN_FPUTS_UNLOCKED: - if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) - check_read_access (exp, CALL_EXPR_ARG (exp, 0)); - break; - - case BUILT_IN_STRNDUP: - if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - check_read_access (exp, CALL_EXPR_ARG (exp, 0), CALL_EXPR_ARG (exp, 1)); - break; - - case BUILT_IN_STRCASECMP: - case BUILT_IN_STRPBRK: - case BUILT_IN_STRSPN: - case BUILT_IN_STRCSPN: - case BUILT_IN_STRSTR: - if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) - { - check_read_access (exp, CALL_EXPR_ARG (exp, 0)); - check_read_access (exp, CALL_EXPR_ARG (exp, 1)); - } - break; - case BUILT_IN_STRCPY: target = expand_builtin_strcpy (exp, target); if (target) return target; break; - case BUILT_IN_STRNCAT: - target = expand_builtin_strncat (exp, target); - if (target) - return target; - break; - case BUILT_IN_STRNCPY: target = expand_builtin_strncpy (exp, target); if (target) @@ -7613,18 +7237,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, return target; break; - case BUILT_IN_STPNCPY: - target = expand_builtin_stpncpy (exp, target); - if (target) - return target; - break; - - case BUILT_IN_MEMCHR: - target = expand_builtin_memchr (exp, target); - if (target) - return target; - break; - case BUILT_IN_MEMCPY: target = expand_builtin_memcpy (exp, target); if (target) @@ -8626,8 +8238,11 @@ fold_builtin_strlen (location_t loc, tree expr, tree type, tree arg) if (len) return fold_convert_loc (loc, type, len); + /* TODO: Move this to gimple-ssa-warn-access once the pass runs + also early enough to detect invalid reads in multimensional + arrays and struct members. */ if (!lendata.decl) - c_strlen (arg, 1, &lendata); + c_strlen (arg, 1, &lendata); if (lendata.decl) { |