diff options
author | Martin Liska <mliska@suse.cz> | 2021-08-09 11:14:45 +0200 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2021-08-09 11:14:45 +0200 |
commit | 9207fa3effc9970d9e2a48993adbfc34c08a8f65 (patch) | |
tree | 460892004407fca4c097ec65831d468e61fca54f | |
parent | 01c909e1a5fca4988431a328454e9d8c0eea9ef6 (diff) | |
parent | a5e3c1e2c8dafcd2f6e4eeb2b2fa38fd40c5eda3 (diff) | |
download | gcc-9207fa3effc9970d9e2a48993adbfc34c08a8f65.zip gcc-9207fa3effc9970d9e2a48993adbfc34c08a8f65.tar.gz gcc-9207fa3effc9970d9e2a48993adbfc34c08a8f65.tar.bz2 |
Merge branch 'master' into devel/sphinx
77 files changed, 2440 insertions, 1023 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 7cb63e5..7b03fc2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -655,6 +655,7 @@ Marcel Vollweiler <marcel@codesourcery.com> Ville Voutilainen <ville.voutilainen@gmail.com> Nenad Vukicevic <nenad@intrepid.com> Feng Wang <fengwang@nudt.edu.cn> +Hongyu Wang <hongyu.wang@intel.com> Jiong Wang <jiong.wang@arm.com> Stephen M. Webb <stephen.webb@bregmasoft.com> John Wehle <john@feith.com> diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6b7a77d..9d39f0f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,291 @@ +2021-08-08 Sergei Trofimovich <siarheit@google.com> + + * lra-constraints.c: Fix s/otput/output/ typo. + +2021-08-06 Martin Sebor <msebor@redhat.com> + + * 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. + +2021-08-06 Richard Biener <rguenther@suse.de> + + PR tree-optimization/101801 + * tree-vectorizer.h (vect_worthwhile_without_simd_p): Rename... + (vect_can_vectorize_without_simd_p): ... to this. + * tree-vect-loop.c (vect_worthwhile_without_simd_p): Rename... + (vect_can_vectorize_without_simd_p): ... to this and fold + in vect_min_worthwhile_factor. + (vect_min_worthwhile_factor): Remove. + (vectorizable_reduction): Adjust and remove the cost part. + * tree-vect-stmts.c (vectorizable_shift): Likewise. + (vectorizable_operation): Likewise. + +2021-08-06 Uroš Bizjak <ubizjak@gmail.com> + + PR target/101797 + * config/i386/i386.md (cmove reg-to-reg move elimination peephole2s): + Add general_gr_operand predicate to operand 3. + +2021-08-06 Roger Sayle <roger@nextmovesoftware.com> + + * tree-ssa-phiopt.c (cond_removal_in_builtin_zero_pattern): Use + CFN_BUILT_IN_CLRSB* instead of BUILT_IN_CLRSB* for consistency. + +2021-08-06 Tamar Christina <tamar.christina@arm.com> + + * config/aarch64/aarch64-sve-builtins.cc (register_svpattern, + register_svprfop): Pass vec<> by pointer. + * langhooks-def.h (lhd_simulate_enum_decl): Likewise. + * langhooks.c (lhd_simulate_enum_decl): Likewise. + * langhooks.h (struct lang_hooks_for_types): Likewise. + +2021-08-06 Jonathan Wright <jonathan.wright@arm.com> + + * config/aarch64/arm_neon.h (vst1_bf16_x2): Use + __builtin_memcpy instead of constructing an additional + __builtin_aarch64_simd_oi one vector at a time. + (vst1q_bf16_x2): Likewise. + (vst1_bf16_x3): Use __builtin_memcpy instead of constructing + an additional __builtin_aarch64_simd_ci one vector at a time. + (vst1q_bf16_x3): Likewise. + (vst1_bf16_x4): Use __builtin_memcpy instead of a union. + (vst1q_bf16_x4): Likewise. + (vst2_bf16): Use __builtin_memcpy instead of constructing an + additional __builtin_aarch64_simd_oi one vector at a time. + (vst2q_bf16): Likewise. + (vst3_bf16): Use __builtin_memcpy instead of constructing an + additional __builtin_aarch64_simd_ci mode one vector at a + time. + (vst3q_bf16): Likewise. + (vst4_bf16): Use __builtin_memcpy instead of constructing an + additional __builtin_aarch64_simd_xi one vector at a time. + (vst4q_bf16): Likewise. + +2021-08-06 Jonathan Wright <jonathan.wright@arm.com> + + * config/aarch64/arm_neon.h (__ST2_LANE_FUNC): Delete. + (__ST2Q_LANE_FUNC): Delete. + (vst2_lane_f16): Use __builtin_memcpy to copy vector + structure instead of constructing __builtin_aarch64_simd_oi + one vector at a time. + (vst2_lane_f32): Likewise. + (vst2_lane_f64): Likewise. + (vst2_lane_p8): Likewise. + (vst2_lane_p16): Likewise. + (vst2_lane_p64): Likewise. + (vst2_lane_s8): Likewise. + (vst2_lane_s16): Likewise. + (vst2_lane_s32): Likewise. + (vst2_lane_s64): Likewise. + (vst2_lane_u8): Likewise. + (vst2_lane_u16): Likewise. + (vst2_lane_u32): Likewise. + (vst2_lane_u64): Likewise. + (vst2_lane_bf16): Likewise. + (vst2q_lane_f16): Use __builtin_memcpy to copy vector + structure instead of using a union. + (vst2q_lane_f32): Likewise. + (vst2q_lane_f64): Likewise. + (vst2q_lane_p8): Likewise. + (vst2q_lane_p16): Likewise. + (vst2q_lane_p64): Likewise. + (vst2q_lane_s8): Likewise. + (vst2q_lane_s16): Likewise. + (vst2q_lane_s32): Likewise. + (vst2q_lane_s64): Likewise. + (vst2q_lane_u8): Likewise. + (vst2q_lane_u16): Likewise. + (vst2q_lane_u32): Likewise. + (vst2q_lane_u64): Likewise. + (vst2q_lane_bf16): Likewise. + +2021-08-06 Jonathan Wright <jonathan.wright@arm.com> + + * config/aarch64/arm_neon.h (__ST3_LANE_FUNC): Delete. + (__ST3Q_LANE_FUNC): Delete. + (vst3_lane_f16): Use __builtin_memcpy to copy vector + structure instead of constructing __builtin_aarch64_simd_ci + one vector at a time. + (vst3_lane_f32): Likewise. + (vst3_lane_f64): Likewise. + (vst3_lane_p8): Likewise. + (vst3_lane_p16): Likewise. + (vst3_lane_p64): Likewise. + (vst3_lane_s8): Likewise. + (vst3_lane_s16): Likewise. + (vst3_lane_s32): Likewise. + (vst3_lane_s64): Likewise. + (vst3_lane_u8): Likewise. + (vst3_lane_u16): Likewise. + (vst3_lane_u32): Likewise. + (vst3_lane_u64): Likewise. + (vst3_lane_bf16): Likewise. + (vst3q_lane_f16): Use __builtin_memcpy to copy vector + structure instead of using a union. + (vst3q_lane_f32): Likewise. + (vst3q_lane_f64): Likewise. + (vst3q_lane_p8): Likewise. + (vst3q_lane_p16): Likewise. + (vst3q_lane_p64): Likewise. + (vst3q_lane_s8): Likewise. + (vst3q_lane_s16): Likewise. + (vst3q_lane_s32): Likewise. + (vst3q_lane_s64): Likewise. + (vst3q_lane_u8): Likewise. + (vst3q_lane_u16): Likewise. + (vst3q_lane_u32): Likewise. + (vst3q_lane_u64): Likewise. + (vst3q_lane_bf16): Likewise. + +2021-08-06 Jonathan Wright <jonathan.wright@arm.com> + + * config/aarch64/arm_neon.h (__ST4_LANE_FUNC): Delete. + (__ST4Q_LANE_FUNC): Delete. + (vst4_lane_f16): Use __builtin_memcpy to copy vector + structure instead of constructing __builtin_aarch64_simd_xi + one vector at a time. + (vst4_lane_f32): Likewise. + (vst4_lane_f64): Likewise. + (vst4_lane_p8): Likewise. + (vst4_lane_p16): Likewise. + (vst4_lane_p64): Likewise. + (vst4_lane_s8): Likewise. + (vst4_lane_s16): Likewise. + (vst4_lane_s32): Likewise. + (vst4_lane_s64): Likewise. + (vst4_lane_u8): Likewise. + (vst4_lane_u16): Likewise. + (vst4_lane_u32): Likewise. + (vst4_lane_u64): Likewise. + (vst4_lane_bf16): Likewise. + (vst4q_lane_f16): Use __builtin_memcpy to copy vector + structure instead of using a union. + (vst4q_lane_f32): Likewise. + (vst4q_lane_f64): Likewise. + (vst4q_lane_p8): Likewise. + (vst4q_lane_p16): Likewise. + (vst4q_lane_p64): Likewise. + (vst4q_lane_s8): Likewise. + (vst4q_lane_s16): Likewise. + (vst4q_lane_s32): Likewise. + (vst4q_lane_s64): Likewise. + (vst4q_lane_u8): Likewise. + (vst4q_lane_u16): Likewise. + (vst4q_lane_u32): Likewise. + (vst4q_lane_u64): Likewise. + (vst4q_lane_bf16): Likewise. + +2021-08-06 Martin Liska <mliska@suse.cz> + + * config/rs6000/rs6000.c (rs6000_option_override_internal): When + a target option is restored, it can have + rs6000_long_double_type_size set to FLOAT_PRECISION_TFmode + and error should not be emitted. + +2021-08-06 Sebastian Huber <sebastian.huber@embedded-brains.de> + + * gcov-io.h (gcov_write): Declare. + * gcov-io.c (gcov_write): New. + (gcov_write_counter): Remove. + (gcov_write_tag_length): Likewise. + (gcov_write_summary): Replace gcov_write_tag_length() with calls to + gcov_write_unsigned(). + * doc/invoke.texi (fprofile-info-section): Mention + __gcov_info_to_gdca(). + +2021-08-06 Martin Sebor <msebor@redhat.com> + + * dominance.c (prune_bbs_to_update_dominators): Adjust by-value vec + arguments to by-reference. + (iterate_fix_dominators): Same. + * dominance.h (iterate_fix_dominators): Same. + * ipa-prop.h: Call auto_vec::to_vec_legacy. + * tree-data-ref.c (dump_data_dependence_relation): Adjust by-value vec + arguments to by-reference. + (debug_data_dependence_relation): Same. + (dump_data_dependence_relations): Same. + * tree-data-ref.h (debug_data_dependence_relation): Same. + (dump_data_dependence_relations): Same. + * tree-predcom.c (dump_chains): Same. + (initialize_root_vars_lm): Same. + (determine_unroll_factor): Same. + (replace_phis_by_defined_names): Same. + (insert_init_seqs): Same. + (pcom_worker::tree_predictive_commoning_loop): Call + auto_vec::to_vec_legacy. + * tree-ssa-pre.c (insert_into_preds_of_block): Adjust by-value vec + arguments to by-reference. + * tree-ssa-threadbackward.c (populate_worklist): Same. + (back_threader::resolve_def): Same. + * tree-vect-data-refs.c (vect_check_nonzero_value): Same. + (vect_enhance_data_refs_alignment): Same. + (vect_check_lower_bound): Same. + (vect_prune_runtime_alias_test_list): Same. + (vect_permute_store_chain): Same. + * tree-vect-slp-patterns.c (vect_normalize_conj_loc): Same. + * tree-vect-stmts.c (vect_create_vectorized_demotion_stmts): Same. + * tree-vectorizer.h (vect_permute_store_chain): Same. + * vec.c (test_init): New function. + (vec_c_tests): Call new function. + * vec.h (vec): Declare ctors, dtor, and assignment. + (auto_vec::vec_to_legacy): New function. + (vec::copy): Adjust initialization. + 2021-08-05 H.J. Lu <hjl.tools@gmail.com> PR target/99744 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 891ccf6..859da5a 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210806 +20210809 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) { diff --git a/gcc/builtins.h b/gcc/builtins.h index 024ddbf..16b47ac 100644 --- a/gcc/builtins.h +++ b/gcc/builtins.h @@ -151,8 +151,4 @@ extern internal_fn replacement_internal_fn (gcall *); extern bool builtin_with_linkage_p (tree); -class access_data; -extern bool check_access (tree, tree, tree, tree, tree, - access_mode, const access_data * = NULL); - #endif /* GCC_BUILTINS_H */ diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 367c9c7..6f15b0f 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,20 @@ +2021-08-06 Tamar Christina <tamar.christina@arm.com> + + * c-decl.c (c_simulate_enum_decl): Pass vec<> by pointer. + * c-tree.h (c_simulate_enum_decl): Likewise. + +2021-08-06 Martin Sebor <msebor@redhat.com> + + * c-parser.c (c_parser_declaration_or_fndef): Adjust by-value function + vec arguments to by-reference. + (c_finish_omp_declare_simd): Same. + (c_parser_compound_statement_nostart): Same. + (c_parser_for_statement): Same. + (c_parser_objc_methodprotolist): Same. + (c_parser_oacc_routine): Same. + (c_parser_omp_for_loop): Same. + (c_parser_omp_declare_simd): Same. + 2021-07-21 Thomas Schwinge <thomas@codesourcery.com> Joseph Myers <joseph@codesourcery.com> Cesar Philippidis <cesar@codesourcery.com> diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 234ee16..221a67f 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -9379,7 +9379,7 @@ build_enumerator (location_t decl_loc, location_t loc, tree c_simulate_enum_decl (location_t loc, const char *name, - vec<string_int_pair> values) + vec<string_int_pair> *values_ptr) { location_t saved_loc = input_location; input_location = loc; @@ -9389,6 +9389,7 @@ c_simulate_enum_decl (location_t loc, const char *name, tree value_chain = NULL_TREE; string_int_pair *value; + vec<string_int_pair> values = *values_ptr; unsigned int i; FOR_EACH_VEC_ELT (values, i, value) { diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index ab6db38..a8a90ea 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -595,7 +595,7 @@ extern void finish_function (location_t = input_location); extern tree finish_struct (location_t, tree, tree, tree, class c_struct_parse_info *); extern tree c_simulate_enum_decl (location_t, const char *, - vec<string_int_pair>); + vec<string_int_pair> *); extern struct c_arg_info *build_arg_info (void); extern struct c_arg_info *get_parm_info (bool, tree); extern tree grokfield (location_t, struct c_declarator *, diff --git a/gcc/calls.c b/gcc/calls.c index 795d214..fcb0d6d 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -61,7 +61,7 @@ along with GCC; see the file COPYING3. If not see #include "attr-fnspec.h" #include "value-query.h" #include "pointer-query.h" - +#include "gimple-ssa-warn-access.h" #include "tree-pretty-print.h" /* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits. */ @@ -1614,314 +1614,6 @@ get_attr_nonstring_decl (tree expr, tree *ref) return NULL_TREE; } -/* Warn about passing a non-string array/pointer to a built-in function - that expects a nul-terminated string argument. Returns true if - a warning has been issued.*/ - -bool -maybe_warn_nonstring_arg (tree fndecl, tree exp) -{ - if (!fndecl || !fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)) - return false; - - if (!warn_stringop_overread || warning_suppressed_p (exp, OPT_Wstringop_overread)) - return false; - - /* Avoid clearly invalid calls (more checking done below). */ - unsigned nargs = call_expr_nargs (exp); - if (!nargs) - return false; - - /* The bound argument to a bounded string function like strncpy. */ - tree bound = NULL_TREE; - - /* The longest known or possible string argument to one of the comparison - functions. If the length is less than the bound it is used instead. - Since the length is only used for warning and not for code generation - disable strict mode in the calls to get_range_strlen below. */ - tree maxlen = NULL_TREE; - - /* It's safe to call "bounded" string functions with a non-string - argument since the functions provide an explicit bound for this - purpose. The exception is strncat where the bound may refer to - either the destination or the source. */ - int fncode = DECL_FUNCTION_CODE (fndecl); - switch (fncode) - { - case BUILT_IN_STRCMP: - case BUILT_IN_STRNCMP: - case BUILT_IN_STRNCASECMP: - { - /* For these, if one argument refers to one or more of a set - of string constants or arrays of known size, determine - the range of their known or possible lengths and use it - conservatively as the bound for the unbounded function, - and to adjust the range of the bound of the bounded ones. */ - for (unsigned argno = 0; - argno < MIN (nargs, 2) - && !(maxlen && TREE_CODE (maxlen) == INTEGER_CST); argno++) - { - tree arg = CALL_EXPR_ARG (exp, argno); - if (!get_attr_nonstring_decl (arg)) - { - c_strlen_data lendata = { }; - /* Set MAXBOUND to an arbitrary non-null non-integer - node as a request to have it set to the length of - the longest string in a PHI. */ - lendata.maxbound = arg; - get_range_strlen (arg, &lendata, /* eltsize = */ 1); - maxlen = lendata.maxbound; - } - } - } - /* Fall through. */ - - case BUILT_IN_STRNCAT: - case BUILT_IN_STPNCPY: - case BUILT_IN_STRNCPY: - if (nargs > 2) - bound = CALL_EXPR_ARG (exp, 2); - break; - - case BUILT_IN_STRNDUP: - if (nargs > 1) - bound = CALL_EXPR_ARG (exp, 1); - break; - - case BUILT_IN_STRNLEN: - { - tree arg = CALL_EXPR_ARG (exp, 0); - if (!get_attr_nonstring_decl (arg)) - { - c_strlen_data lendata = { }; - /* Set MAXBOUND to an arbitrary non-null non-integer - node as a request to have it set to the length of - the longest string in a PHI. */ - lendata.maxbound = arg; - get_range_strlen (arg, &lendata, /* eltsize = */ 1); - maxlen = lendata.maxbound; - } - if (nargs > 1) - bound = CALL_EXPR_ARG (exp, 1); - break; - } - - default: - break; - } - - /* Determine the range of the bound argument (if specified). */ - tree bndrng[2] = { NULL_TREE, NULL_TREE }; - if (bound) - { - STRIP_NOPS (bound); - get_size_range (bound, bndrng); - } - - location_t loc = EXPR_LOCATION (exp); - - if (bndrng[0]) - { - /* Diagnose excessive bound prior to the adjustment below and - regardless of attribute nonstring. */ - tree maxobjsize = max_object_size (); - if (tree_int_cst_lt (maxobjsize, bndrng[0])) - { - bool warned = false; - if (tree_int_cst_equal (bndrng[0], bndrng[1])) - warned = warning_at (loc, OPT_Wstringop_overread, - "%qD specified bound %E " - "exceeds maximum object size %E", - fndecl, bndrng[0], maxobjsize); - else - warned = warning_at (loc, OPT_Wstringop_overread, - "%qD specified bound [%E, %E] " - "exceeds maximum object size %E", - fndecl, bndrng[0], bndrng[1], - maxobjsize); - if (warned) - suppress_warning (exp, OPT_Wstringop_overread); - - return warned; - } - } - - if (maxlen && !integer_all_onesp (maxlen)) - { - /* Add one for the nul. */ - maxlen = const_binop (PLUS_EXPR, TREE_TYPE (maxlen), maxlen, - size_one_node); - - if (!bndrng[0]) - { - /* Conservatively use the upper bound of the lengths for - both the lower and the upper bound of the operation. */ - bndrng[0] = maxlen; - bndrng[1] = maxlen; - bound = void_type_node; - } - else if (maxlen) - { - /* Replace the bound on the operation with the upper bound - of the length of the string if the latter is smaller. */ - if (tree_int_cst_lt (maxlen, bndrng[0])) - bndrng[0] = maxlen; - else if (tree_int_cst_lt (maxlen, bndrng[1])) - bndrng[1] = maxlen; - } - } - - bool any_arg_warned = false; - /* Iterate over the built-in function's formal arguments and check - each const char* against the actual argument. If the actual - argument is declared attribute non-string issue a warning unless - the argument's maximum length is bounded. */ - function_args_iterator it; - function_args_iter_init (&it, TREE_TYPE (fndecl)); - - for (unsigned argno = 0; ; ++argno, function_args_iter_next (&it)) - { - /* Avoid iterating past the declared argument in a call - to function declared without a prototype. */ - if (argno >= nargs) - break; - - tree argtype = function_args_iter_cond (&it); - if (!argtype) - break; - - if (TREE_CODE (argtype) != POINTER_TYPE) - continue; - - argtype = TREE_TYPE (argtype); - - if (TREE_CODE (argtype) != INTEGER_TYPE - || !TYPE_READONLY (argtype)) - continue; - - argtype = TYPE_MAIN_VARIANT (argtype); - if (argtype != char_type_node) - continue; - - tree callarg = CALL_EXPR_ARG (exp, argno); - if (TREE_CODE (callarg) == ADDR_EXPR) - callarg = TREE_OPERAND (callarg, 0); - - /* See if the destination is declared with attribute "nonstring". */ - tree decl = get_attr_nonstring_decl (callarg); - if (!decl) - continue; - - /* The maximum number of array elements accessed. */ - offset_int wibnd = 0; - - if (argno && fncode == BUILT_IN_STRNCAT) - { - /* See if the bound in strncat is derived from the length - of the strlen of the destination (as it's expected to be). - If so, reset BOUND and FNCODE to trigger a warning. */ - tree dstarg = CALL_EXPR_ARG (exp, 0); - if (is_strlen_related_p (dstarg, bound)) - { - /* The bound applies to the destination, not to the source, - so reset these to trigger a warning without mentioning - the bound. */ - bound = NULL; - fncode = 0; - } - else if (bndrng[1]) - /* Use the upper bound of the range for strncat. */ - wibnd = wi::to_offset (bndrng[1]); - } - else if (bndrng[0]) - /* Use the lower bound of the range for functions other than - strncat. */ - wibnd = wi::to_offset (bndrng[0]); - - /* Determine the size of the argument array if it is one. */ - offset_int asize = wibnd; - bool known_size = false; - tree type = TREE_TYPE (decl); - - /* Determine the array size. For arrays of unknown bound and - pointers reset BOUND to trigger the appropriate warning. */ - if (TREE_CODE (type) == ARRAY_TYPE) - { - if (tree arrbnd = TYPE_DOMAIN (type)) - { - if ((arrbnd = TYPE_MAX_VALUE (arrbnd))) - { - asize = wi::to_offset (arrbnd) + 1; - known_size = true; - } - } - else if (bound == void_type_node) - bound = NULL_TREE; - } - else if (bound == void_type_node) - bound = NULL_TREE; - - /* In a call to strncat with a bound in a range whose lower but - not upper bound is less than the array size, reset ASIZE to - be the same as the bound and the other variable to trigger - the apprpriate warning below. */ - if (fncode == BUILT_IN_STRNCAT - && bndrng[0] != bndrng[1] - && wi::ltu_p (wi::to_offset (bndrng[0]), asize) - && (!known_size - || wi::ltu_p (asize, wibnd))) - { - asize = wibnd; - bound = NULL_TREE; - fncode = 0; - } - - bool warned = false; - - auto_diagnostic_group d; - if (wi::ltu_p (asize, wibnd)) - { - if (bndrng[0] == bndrng[1]) - warned = warning_at (loc, OPT_Wstringop_overread, - "%qD argument %i declared attribute " - "%<nonstring%> is smaller than the specified " - "bound %wu", - fndecl, argno + 1, wibnd.to_uhwi ()); - else if (wi::ltu_p (asize, wi::to_offset (bndrng[0]))) - warned = warning_at (loc, OPT_Wstringop_overread, - "%qD argument %i declared attribute " - "%<nonstring%> is smaller than " - "the specified bound [%E, %E]", - fndecl, argno + 1, bndrng[0], bndrng[1]); - else - warned = warning_at (loc, OPT_Wstringop_overread, - "%qD argument %i declared attribute " - "%<nonstring%> may be smaller than " - "the specified bound [%E, %E]", - fndecl, argno + 1, bndrng[0], bndrng[1]); - } - else if (fncode == BUILT_IN_STRNCAT) - ; /* Avoid warning for calls to strncat() when the bound - is equal to the size of the non-string argument. */ - else if (!bound) - warned = warning_at (loc, OPT_Wstringop_overread, - "%qD argument %i declared attribute %<nonstring%>", - fndecl, argno + 1); - - if (warned) - { - inform (DECL_SOURCE_LOCATION (decl), - "argument %qD declared here", decl); - any_arg_warned = true; - } - } - - if (any_arg_warned) - suppress_warning (exp, OPT_Wstringop_overread); - - return any_arg_warned; -} - /* Issue an error if CALL_EXPR was flagged as requiring tall-call optimization. */ diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc index f44f81f..f71b287 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins.cc @@ -3499,7 +3499,7 @@ register_svpattern () #undef PUSH acle_svpattern = lang_hooks.types.simulate_enum_decl (input_location, - "svpattern", values); + "svpattern", &values); } /* Register the svprfop enum. */ @@ -3513,7 +3513,7 @@ register_svprfop () #undef PUSH acle_svprfop = lang_hooks.types.simulate_enum_decl (input_location, - "svprfop", values); + "svprfop", &values); } /* Implement #pragma GCC aarch64 "arm_sve.h". */ diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 51e8b47..bc1c30b 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -19428,7 +19428,7 @@ (parallel [(set (reg FLAGS_REG) (match_operand 5)) (set (match_dup 0) (match_operand:SWI248 6))]) (set (match_operand:SWI248 2 "general_reg_operand") - (match_operand:SWI248 3)) + (match_operand:SWI248 3 "general_gr_operand")) (set (match_dup 0) (if_then_else:SWI248 (match_operator 4 "ix86_comparison_operator" [(reg FLAGS_REG) (const_int 0)]) @@ -19456,7 +19456,7 @@ ;; mov r2,r3; mov r0,r1; dec r0; cmov r0,r2 -> dec r1; mov r0,r3; cmov r0, r1 (define_peephole2 [(set (match_operand:SWI248 2 "general_reg_operand") - (match_operand:SWI248 3)) + (match_operand:SWI248 3 "general_gr_operand")) (set (match_operand:SWI248 0 "general_reg_operand") (match_operand:SWI248 1 "general_reg_operand")) (parallel [(set (reg FLAGS_REG) (match_operand 5)) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5b3e191..a8f70b0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2021-08-06 Tamar Christina <tamar.christina@arm.com> + + * cp-objcp-common.h (cxx_simulate_enum_decl): Pass vec<> by pointer. + * decl.c (cxx_simulate_enum_decl): Likewise. + 2021-08-04 Jakub Jelinek <jakub@redhat.com> PR c++/101759 diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h index 53c6e4c..f1704aa 100644 --- a/gcc/cp/cp-objcp-common.h +++ b/gcc/cp/cp-objcp-common.h @@ -38,7 +38,7 @@ extern bool cp_handle_option (size_t, const char *, HOST_WIDE_INT, int, location_t, const struct cl_option_handlers *); extern tree cxx_make_type_hook (tree_code); extern tree cxx_simulate_enum_decl (location_t, const char *, - vec<string_int_pair>); + vec<string_int_pair> *); /* Lang hooks that are shared between C++ and ObjC++ are defined here. Hooks specific to C++ or ObjC++ go in cp/cp-lang.c and objcp/objcp-lang.c, diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 6fa6b9a..f626f1e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -16408,7 +16408,7 @@ lookup_enumerator (tree enumtype, tree name) tree cxx_simulate_enum_decl (location_t loc, const char *name, - vec<string_int_pair> values) + vec<string_int_pair> *values) { location_t saved_loc = input_location; input_location = loc; diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c index fbe52c6..5e961e1 100644 --- a/gcc/diagnostic-spec.c +++ b/gcc/diagnostic-spec.c @@ -84,6 +84,7 @@ nowarn_spec_t::nowarn_spec_t (opt_code opt) case OPT_Wformat_overflow_: case OPT_Wformat_truncation_: case OPT_Wrestrict: + case OPT_Wsizeof_pointer_memaccess: case OPT_Wstrict_aliasing_: case OPT_Wstringop_overflow_: case OPT_Wstringop_overread: diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index c757bf0..2e7a9ad 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,9 @@ +2021-08-07 Harald Anlauf <anlauf@gmx.de> + + PR fortran/68568 + * primary.c (gfc_expr_attr): Variable attribute can only be + inquired when symtree is non-NULL. + 2021-07-28 Harald Anlauf <anlauf@gmx.de> PR fortran/101564 diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c index 9fe8d1e..56a78d6 100644 --- a/gcc/fortran/primary.c +++ b/gcc/fortran/primary.c @@ -2779,7 +2779,7 @@ gfc_expr_attr (gfc_expr *e) && e->value.function.isym->transformational && e->ts.type == BT_CLASS) attr = CLASS_DATA (e)->attr; - else + else if (e->symtree) attr = gfc_variable_attr (e, NULL); /* TODO: NULL() returns pointers. May have to take care of this diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index ad7b140..3f2c176 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -2073,7 +2073,7 @@ gimple_fold_builtin_strcpy (gimple_stmt_iterator *gsi, { /* Avoid folding calls with unterminated arrays. */ if (!warning_suppressed_p (stmt, OPT_Wstringop_overread)) - warn_string_no_nul (loc, NULL_TREE, "strcpy", src, nonstr); + warn_string_no_nul (loc, stmt, "strcpy", src, nonstr); suppress_warning (stmt, OPT_Wstringop_overread); return false; } @@ -3291,7 +3291,7 @@ gimple_fold_builtin_stpcpy (gimple_stmt_iterator *gsi) { /* Avoid folding calls with unterminated arrays. */ if (!warning_suppressed_p (stmt, OPT_Wstringop_overread)) - warn_string_no_nul (loc, NULL_TREE, "stpcpy", src, data.decl, size, + warn_string_no_nul (loc, stmt, "stpcpy", src, data.decl, size, exact); suppress_warning (stmt, OPT_Wstringop_overread); return false; diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc index e4d98b2..a4559dd 100644 --- a/gcc/gimple-ssa-warn-access.cc +++ b/gcc/gimple-ssa-warn-access.cc @@ -40,6 +40,7 @@ #include "tree-ssa.h" #include "tree-cfg.h" #include "tree-object-size.h" +#include "tree-ssa-strlen.h" #include "calls.h" #include "cfgloop.h" #include "intl.h" @@ -49,6 +50,83 @@ #include "demangle.h" #include "pointer-query.h" +/* Return true if STMT has an associated location. */ + +static inline location_t +has_location (const gimple *stmt) +{ + return gimple_has_location (stmt); +} + +/* Return true if tree node X has an associated location. */ + +static inline location_t +has_location (const_tree x) +{ + if (DECL_P (x)) + return DECL_SOURCE_LOCATION (x) != UNKNOWN_LOCATION; + + if (EXPR_P (x)) + return EXPR_HAS_LOCATION (x); + + return false; +} + +/* Return the associated location of STMT. */ + +static inline location_t +get_location (const gimple *stmt) +{ + return gimple_location (stmt); +} + +/* Return the associated location of tree node X. */ + +static inline location_t +get_location (tree x) +{ + if (DECL_P (x)) + return DECL_SOURCE_LOCATION (x); + + if (EXPR_P (x)) + return EXPR_LOCATION (x); + + return UNKNOWN_LOCATION; +} + +/* Overload of the nascent tree function for GIMPLE STMT. */ + +static inline tree +get_callee_fndecl (const gimple *stmt) +{ + return gimple_call_fndecl (stmt); +} + +static inline unsigned +call_nargs (const gimple *stmt) +{ + return gimple_call_num_args (stmt); +} + +static inline unsigned +call_nargs (const_tree expr) +{ + return call_expr_nargs (expr); +} + + +static inline tree +call_arg (const gimple *stmt, unsigned argno) +{ + return gimple_call_arg (stmt, argno); +} + +static inline tree +call_arg (tree expr, unsigned argno) +{ + return CALL_EXPR_ARG (expr, argno); +} + /* For a call EXPR at LOC to a function FNAME that expects a string in the argument ARG, issue a diagnostic due to it being a called with an argument that is a character array with no terminating @@ -56,10 +134,10 @@ of characters in which the NUL is expected. Either EXPR or FNAME may be null but noth both. SIZE may be null when BNDRNG is null. */ -void -warn_string_no_nul (location_t loc, tree expr, const char *fname, - tree arg, tree decl, tree size /* = NULL_TREE */, - bool exact /* = false */, +template <class GimpleOrTree> +static void +warn_string_no_nul (location_t loc, GimpleOrTree expr, const char *fname, + tree arg, tree decl, tree size, bool exact, const wide_int bndrng[2] /* = NULL */) { const opt_code opt = OPT_Wstringop_overread; @@ -152,7 +230,7 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname, if (warned) { - inform (DECL_SOURCE_LOCATION (decl), + inform (get_location (decl), "referenced argument declared here"); suppress_warning (arg, opt); if (expr) @@ -160,16 +238,80 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname, } } +void +warn_string_no_nul (location_t loc, gimple *stmt, const char *fname, + tree arg, tree decl, tree size /* = NULL_TREE */, + bool exact /* = false */, + const wide_int bndrng[2] /* = NULL */) +{ + return warn_string_no_nul<gimple *> (loc, stmt, fname, + arg, decl, size, exact, bndrng); +} + +void +warn_string_no_nul (location_t loc, tree expr, const char *fname, + tree arg, tree decl, tree size /* = NULL_TREE */, + bool exact /* = false */, + const wide_int bndrng[2] /* = NULL */) +{ + return warn_string_no_nul<tree> (loc, expr, fname, + arg, decl, size, exact, bndrng); +} + +/* If EXP refers to an unterminated constant character array return + the declaration of the object of which the array is a member or + element and if SIZE is not null, set *SIZE to the size of + the unterminated array and set *EXACT if the size is exact or + clear it otherwise. Otherwise return null. */ + +tree +unterminated_array (tree exp, tree *size /* = NULL */, bool *exact /* = NULL */) +{ + /* C_STRLEN will return NULL and set DECL in the info + structure if EXP references a unterminated array. */ + c_strlen_data lendata = { }; + tree len = c_strlen (exp, 1, &lendata); + if (len || !lendata.minlen || !lendata.decl) + return NULL_TREE; + + if (!size) + return lendata.decl; + + len = lendata.minlen; + if (lendata.off) + { + /* Constant offsets are already accounted for in LENDATA.MINLEN, + but not in a SSA_NAME + CST expression. */ + if (TREE_CODE (lendata.off) == INTEGER_CST) + *exact = true; + else if (TREE_CODE (lendata.off) == PLUS_EXPR + && TREE_CODE (TREE_OPERAND (lendata.off, 1)) == INTEGER_CST) + { + /* Subtract the offset from the size of the array. */ + *exact = false; + tree temp = TREE_OPERAND (lendata.off, 1); + temp = fold_convert (ssizetype, temp); + len = fold_build2 (MINUS_EXPR, ssizetype, len, temp); + } + else + *exact = false; + } + else + *exact = true; + + *size = len; + return lendata.decl; +} + /* For a call EXPR (which may be null) that expects a string argument SRC as an argument, returns false if SRC is a character array with no terminating NUL. When nonnull, BOUND is the number of characters - in which to expect the terminating NUL. RDONLY is true for read-only - accesses such as strcmp, false for read-write such as strcpy. When - EXPR is also issues a warning. */ + in which to expect the terminating NUL. When EXPR is nonnull also + issues a warning. */ -bool -check_nul_terminated_array (tree expr, tree src, - tree bound /* = NULL_TREE */) +template <class GimpleOrTree> +static bool +check_nul_terminated_array (GimpleOrTree expr, tree src, tree bound) { /* The constant size of the array SRC points to. The actual size may be less of EXACT is true, but not more. */ @@ -208,66 +350,355 @@ check_nul_terminated_array (tree expr, tree src, } if (expr) - warn_string_no_nul (EXPR_LOCATION (expr), expr, NULL, src, nonstr, + warn_string_no_nul (get_location (expr), expr, NULL, src, nonstr, size, exact, bound ? bndrng : NULL); return false; } -/* If EXP refers to an unterminated constant character array return - the declaration of the object of which the array is a member or - element and if SIZE is not null, set *SIZE to the size of - the unterminated array and set *EXACT if the size is exact or - clear it otherwise. Otherwise return null. */ +bool +check_nul_terminated_array (gimple *stmt, tree src, tree bound /* = NULL_TREE */) +{ + return check_nul_terminated_array<gimple *>(stmt, src, bound); +} -tree -unterminated_array (tree exp, tree *size /* = NULL */, bool *exact /* = NULL */) +bool +check_nul_terminated_array (tree expr, tree src, tree bound /* = NULL_TREE */) { - /* C_STRLEN will return NULL and set DECL in the info - structure if EXP references a unterminated array. */ - c_strlen_data lendata = { }; - tree len = c_strlen (exp, 1, &lendata); - if (len == NULL_TREE && lendata.minlen && lendata.decl) - { - if (size) + return check_nul_terminated_array<tree>(expr, src, bound); +} + +/* Warn about passing a non-string array/pointer to a built-in function + that expects a nul-terminated string argument. Returns true if + a warning has been issued.*/ + +template <class GimpleOrTree> +static bool +maybe_warn_nonstring_arg (tree fndecl, GimpleOrTree exp) +{ + if (!fndecl || !fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)) + return false; + + if (!warn_stringop_overread + || warning_suppressed_p (exp, OPT_Wstringop_overread)) + return false; + + /* Avoid clearly invalid calls (more checking done below). */ + unsigned nargs = call_nargs (exp); + if (!nargs) + return false; + + /* The bound argument to a bounded string function like strncpy. */ + tree bound = NULL_TREE; + + /* The longest known or possible string argument to one of the comparison + functions. If the length is less than the bound it is used instead. + Since the length is only used for warning and not for code generation + disable strict mode in the calls to get_range_strlen below. */ + tree maxlen = NULL_TREE; + + /* It's safe to call "bounded" string functions with a non-string + argument since the functions provide an explicit bound for this + purpose. The exception is strncat where the bound may refer to + either the destination or the source. */ + int fncode = DECL_FUNCTION_CODE (fndecl); + switch (fncode) + { + case BUILT_IN_STRCMP: + case BUILT_IN_STRNCMP: + case BUILT_IN_STRNCASECMP: + { + /* For these, if one argument refers to one or more of a set + of string constants or arrays of known size, determine + the range of their known or possible lengths and use it + conservatively as the bound for the unbounded function, + and to adjust the range of the bound of the bounded ones. */ + for (unsigned argno = 0; + argno < MIN (nargs, 2) + && !(maxlen && TREE_CODE (maxlen) == INTEGER_CST); argno++) + { + tree arg = call_arg (exp, argno); + if (!get_attr_nonstring_decl (arg)) + { + c_strlen_data lendata = { }; + /* Set MAXBOUND to an arbitrary non-null non-integer + node as a request to have it set to the length of + the longest string in a PHI. */ + lendata.maxbound = arg; + get_range_strlen (arg, &lendata, /* eltsize = */ 1); + maxlen = lendata.maxbound; + } + } + } + /* Fall through. */ + + case BUILT_IN_STRNCAT: + case BUILT_IN_STPNCPY: + case BUILT_IN_STRNCPY: + if (nargs > 2) + bound = call_arg (exp, 2); + break; + + case BUILT_IN_STRNDUP: + if (nargs < 2) + return false; + bound = call_arg (exp, 1); + break; + + case BUILT_IN_STRNLEN: + { + tree arg = call_arg (exp, 0); + if (!get_attr_nonstring_decl (arg)) + { + c_strlen_data lendata = { }; + /* Set MAXBOUND to an arbitrary non-null non-integer + node as a request to have it set to the length of + the longest string in a PHI. */ + lendata.maxbound = arg; + get_range_strlen (arg, &lendata, /* eltsize = */ 1); + maxlen = lendata.maxbound; + } + if (nargs > 1) + bound = call_arg (exp, 1); + break; + } + + default: + break; + } + + /* Determine the range of the bound argument (if specified). */ + tree bndrng[2] = { NULL_TREE, NULL_TREE }; + if (bound) + { + STRIP_NOPS (bound); + get_size_range (bound, bndrng); + } + + location_t loc = get_location (exp); + + if (bndrng[0]) + { + /* Diagnose excessive bound prior to the adjustment below and + regardless of attribute nonstring. */ + tree maxobjsize = max_object_size (); + if (tree_int_cst_lt (maxobjsize, bndrng[0])) { - len = lendata.minlen; - if (lendata.off) + bool warned = false; + if (tree_int_cst_equal (bndrng[0], bndrng[1])) + warned = warning_at (loc, OPT_Wstringop_overread, + "%qD specified bound %E " + "exceeds maximum object size %E", + fndecl, bndrng[0], maxobjsize); + else + warned = warning_at (loc, OPT_Wstringop_overread, + "%qD specified bound [%E, %E] " + "exceeds maximum object size %E", + fndecl, bndrng[0], bndrng[1], + maxobjsize); + if (warned) + suppress_warning (exp, OPT_Wstringop_overread); + + return warned; + } + } + + if (maxlen && !integer_all_onesp (maxlen)) + { + /* Add one for the nul. */ + maxlen = const_binop (PLUS_EXPR, TREE_TYPE (maxlen), maxlen, + size_one_node); + + if (!bndrng[0]) + { + /* Conservatively use the upper bound of the lengths for + both the lower and the upper bound of the operation. */ + bndrng[0] = maxlen; + bndrng[1] = maxlen; + bound = void_type_node; + } + else if (maxlen) + { + /* Replace the bound on the operation with the upper bound + of the length of the string if the latter is smaller. */ + if (tree_int_cst_lt (maxlen, bndrng[0])) + bndrng[0] = maxlen; + else if (tree_int_cst_lt (maxlen, bndrng[1])) + bndrng[1] = maxlen; + } + } + + bool any_arg_warned = false; + /* Iterate over the built-in function's formal arguments and check + each const char* against the actual argument. If the actual + argument is declared attribute non-string issue a warning unless + the argument's maximum length is bounded. */ + function_args_iterator it; + function_args_iter_init (&it, TREE_TYPE (fndecl)); + + for (unsigned argno = 0; ; ++argno, function_args_iter_next (&it)) + { + /* Avoid iterating past the declared argument in a call + to function declared without a prototype. */ + if (argno >= nargs) + break; + + tree argtype = function_args_iter_cond (&it); + if (!argtype) + break; + + if (TREE_CODE (argtype) != POINTER_TYPE) + continue; + + argtype = TREE_TYPE (argtype); + + if (TREE_CODE (argtype) != INTEGER_TYPE + || !TYPE_READONLY (argtype)) + continue; + + argtype = TYPE_MAIN_VARIANT (argtype); + if (argtype != char_type_node) + continue; + + tree callarg = call_arg (exp, argno); + if (TREE_CODE (callarg) == ADDR_EXPR) + callarg = TREE_OPERAND (callarg, 0); + + /* See if the destination is declared with attribute "nonstring". */ + tree decl = get_attr_nonstring_decl (callarg); + if (!decl) + continue; + + /* The maximum number of array elements accessed. */ + offset_int wibnd = 0; + + if (argno && fncode == BUILT_IN_STRNCAT) + { + /* See if the bound in strncat is derived from the length + of the strlen of the destination (as it's expected to be). + If so, reset BOUND and FNCODE to trigger a warning. */ + tree dstarg = call_arg (exp, 0); + if (is_strlen_related_p (dstarg, bound)) + { + /* The bound applies to the destination, not to the source, + so reset these to trigger a warning without mentioning + the bound. */ + bound = NULL; + fncode = 0; + } + else if (bndrng[1]) + /* Use the upper bound of the range for strncat. */ + wibnd = wi::to_offset (bndrng[1]); + } + else if (bndrng[0]) + /* Use the lower bound of the range for functions other than + strncat. */ + wibnd = wi::to_offset (bndrng[0]); + + /* Determine the size of the argument array if it is one. */ + offset_int asize = wibnd; + bool known_size = false; + tree type = TREE_TYPE (decl); + + /* Determine the array size. For arrays of unknown bound and + pointers reset BOUND to trigger the appropriate warning. */ + if (TREE_CODE (type) == ARRAY_TYPE) + { + if (tree arrbnd = TYPE_DOMAIN (type)) { - /* Constant offsets are already accounted for in LENDATA.MINLEN, - but not in a SSA_NAME + CST expression. */ - if (TREE_CODE (lendata.off) == INTEGER_CST) - *exact = true; - else if (TREE_CODE (lendata.off) == PLUS_EXPR - && TREE_CODE (TREE_OPERAND (lendata.off, 1)) == INTEGER_CST) + if ((arrbnd = TYPE_MAX_VALUE (arrbnd))) { - /* Subtract the offset from the size of the array. */ - *exact = false; - tree temp = TREE_OPERAND (lendata.off, 1); - temp = fold_convert (ssizetype, temp); - len = fold_build2 (MINUS_EXPR, ssizetype, len, temp); + asize = wi::to_offset (arrbnd) + 1; + known_size = true; } - else - *exact = false; } + else if (bound == void_type_node) + bound = NULL_TREE; + } + else if (bound == void_type_node) + bound = NULL_TREE; + + /* In a call to strncat with a bound in a range whose lower but + not upper bound is less than the array size, reset ASIZE to + be the same as the bound and the other variable to trigger + the apprpriate warning below. */ + if (fncode == BUILT_IN_STRNCAT + && bndrng[0] != bndrng[1] + && wi::ltu_p (wi::to_offset (bndrng[0]), asize) + && (!known_size + || wi::ltu_p (asize, wibnd))) + { + asize = wibnd; + bound = NULL_TREE; + fncode = 0; + } + + bool warned = false; + + auto_diagnostic_group d; + if (wi::ltu_p (asize, wibnd)) + { + if (bndrng[0] == bndrng[1]) + warned = warning_at (loc, OPT_Wstringop_overread, + "%qD argument %i declared attribute " + "%<nonstring%> is smaller than the specified " + "bound %wu", + fndecl, argno + 1, wibnd.to_uhwi ()); + else if (wi::ltu_p (asize, wi::to_offset (bndrng[0]))) + warned = warning_at (loc, OPT_Wstringop_overread, + "%qD argument %i declared attribute " + "%<nonstring%> is smaller than " + "the specified bound [%E, %E]", + fndecl, argno + 1, bndrng[0], bndrng[1]); else - *exact = true; + warned = warning_at (loc, OPT_Wstringop_overread, + "%qD argument %i declared attribute " + "%<nonstring%> may be smaller than " + "the specified bound [%E, %E]", + fndecl, argno + 1, bndrng[0], bndrng[1]); + } + else if (fncode == BUILT_IN_STRNCAT) + ; /* Avoid warning for calls to strncat() when the bound + is equal to the size of the non-string argument. */ + else if (!bound) + warned = warning_at (loc, OPT_Wstringop_overread, + "%qD argument %i declared attribute %<nonstring%>", + fndecl, argno + 1); - *size = len; + if (warned) + { + inform (DECL_SOURCE_LOCATION (decl), + "argument %qD declared here", decl); + any_arg_warned = true; } - return lendata.decl; - } + } + + if (any_arg_warned) + suppress_warning (exp, OPT_Wstringop_overread); + + return any_arg_warned; +} + +bool +maybe_warn_nonstring_arg (tree fndecl, gimple *stmt) +{ + return maybe_warn_nonstring_arg<gimple *>(fndecl, stmt); +} - return NULL_TREE; + +bool +maybe_warn_nonstring_arg (tree fndecl, tree expr) +{ + return maybe_warn_nonstring_arg<tree>(fndecl, expr); } /* Issue a warning OPT for a bounded call EXP with a bound in RANGE accessing an object with SIZE. */ -bool -maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func, - tree bndrng[2], tree size, - const access_data *pad /* = NULL */) +template <class GimpleOrTree> +static bool +maybe_warn_for_bound (opt_code opt, location_t loc, GimpleOrTree exp, tree func, + tree bndrng[2], tree size, const access_data *pad) { if (!bndrng[0] || warning_suppressed_p (exp, opt)) return false; @@ -352,15 +783,10 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func, bndrng[0], bndrng[1], size)); if (warned) { - if (pad && pad->src.ref) - { - if (DECL_P (pad->src.ref)) - inform (DECL_SOURCE_LOCATION (pad->src.ref), - "source object declared here"); - else if (EXPR_HAS_LOCATION (pad->src.ref)) - inform (EXPR_LOCATION (pad->src.ref), - "source object allocated here"); - } + if (pad && pad->src.ref + && has_location (pad->src.ref)) + inform (get_location (pad->src.ref), + "source object allocated here"); suppress_warning (exp, opt); } @@ -440,21 +866,33 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func, if (warned) { - if (pad && pad->dst.ref) - { - if (DECL_P (pad->dst.ref)) - inform (DECL_SOURCE_LOCATION (pad->dst.ref), - "destination object declared here"); - else if (EXPR_HAS_LOCATION (pad->dst.ref)) - inform (EXPR_LOCATION (pad->dst.ref), - "destination object allocated here"); - } + if (pad && pad->dst.ref + && has_location (pad->dst.ref)) + inform (get_location (pad->dst.ref), + "destination object allocated here"); suppress_warning (exp, opt); } return warned; } +bool +maybe_warn_for_bound (opt_code opt, location_t loc, gimple *stmt, tree func, + tree bndrng[2], tree size, + const access_data *pad /* = NULL */) +{ + return maybe_warn_for_bound<gimple *> (opt, loc, stmt, func, bndrng, size, + pad); +} + +bool +maybe_warn_for_bound (opt_code opt, location_t loc, tree expr, tree func, + tree bndrng[2], tree size, + const access_data *pad /* = NULL */) +{ + return maybe_warn_for_bound<tree> (opt, loc, expr, func, bndrng, size, pad); +} + /* For an expression EXP issue an access warning controlled by option OPT with access to a region SIZE bytes in size in the RANGE of sizes. WRITE is true for a write access, READ for a read access, neither for @@ -462,9 +900,10 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func, is expected to valid. Returns true when a warning has been issued. */ +template <class GimpleOrTree> static bool -warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2], - tree size, bool write, bool read, bool maybe) +warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt, + tree range[2], tree size, bool write, bool read, bool maybe) { bool warned = false; @@ -719,6 +1158,22 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2], return warned; } +static bool +warn_for_access (location_t loc, tree func, gimple *stmt, int opt, + tree range[2], tree size, bool write, bool read, bool maybe) +{ + return warn_for_access<gimple *>(loc, func, stmt, opt, range, size, + write, read, maybe); +} + +static bool +warn_for_access (location_t loc, tree func, tree expr, int opt, + tree range[2], tree size, bool write, bool read, bool maybe) +{ + return warn_for_access<tree>(loc, func, expr, opt, range, size, + write, read, maybe); +} + /* Helper to set RANGE to the range of BOUND if it's nonnull, bounded by BNDRNG if nonnull and valid. */ @@ -779,8 +1234,9 @@ get_size_range (tree bound, tree range[2], const offset_int bndrng[2]) If the call is successfully verified as safe return true, otherwise return false. */ -bool -check_access (tree exp, tree dstwrite, +template <class GimpleOrTree> +static bool +check_access (GimpleOrTree exp, tree dstwrite, tree maxread, tree srcstr, tree dstsize, access_mode mode, const access_data *pad /* = NULL */) { @@ -809,7 +1265,10 @@ check_access (tree exp, tree dstwrite, if (POINTER_TYPE_P (TREE_TYPE (srcstr))) { if (!check_nul_terminated_array (exp, srcstr, maxread)) + /* Return if the array is not nul-terminated and a warning + has been issued. */ return false; + /* Try to determine the range of lengths the source string refers to. If it can be determined and is less than the upper bound given by MAXREAD add one to it for @@ -881,7 +1340,7 @@ check_access (tree exp, tree dstwrite, && TREE_CODE (range[0]) == INTEGER_CST && tree_int_cst_lt (maxobjsize, range[0])) { - location_t loc = EXPR_LOCATION (exp); + location_t loc = get_location (exp); maybe_warn_for_bound (OPT_Wstringop_overflow_, loc, exp, func, range, NULL_TREE, pad); return false; @@ -909,7 +1368,7 @@ check_access (tree exp, tree dstwrite, && warning_suppressed_p (pad->dst.ref, opt))) return false; - location_t loc = EXPR_LOCATION (exp); + location_t loc = get_location (exp); bool warned = false; if (dstwrite == slen && at_least_one) { @@ -962,7 +1421,7 @@ check_access (tree exp, tree dstwrite, PAD is nonnull and BNDRNG is valid. */ get_size_range (maxread, range, pad ? pad->src.bndrng : NULL); - location_t loc = EXPR_LOCATION (exp); + location_t loc = get_location (exp); tree size = dstsize; if (pad && pad->mode == access_read_only) size = wide_int_to_tree (sizetype, pad->src.sizrng[1]); @@ -1023,7 +1482,7 @@ check_access (tree exp, tree dstwrite, && warning_suppressed_p (pad->src.ref, opt))) return false; - location_t loc = EXPR_LOCATION (exp); + location_t loc = get_location (exp); const bool read = mode == access_read_only || mode == access_read_write; const bool maybe = pad && pad->dst.parmarray; @@ -1040,6 +1499,96 @@ check_access (tree exp, tree dstwrite, return true; } +bool +check_access (gimple *stmt, tree dstwrite, + tree maxread, tree srcstr, tree dstsize, + access_mode mode, const access_data *pad /* = NULL */) +{ + return check_access<gimple *>(stmt, dstwrite, maxread, srcstr, dstsize, + mode, pad); +} + +bool +check_access (tree expr, tree dstwrite, + tree maxread, tree srcstr, tree dstsize, + access_mode mode, const access_data *pad /* = NULL */) +{ + return check_access<tree>(expr, dstwrite, maxread, srcstr, dstsize, + mode, pad); +} + +/* 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. */ + +template <class GimpleOrTree> +static bool +check_memop_access (GimpleOrTree expr, 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 (expr, 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 (expr, size, /*maxread=*/NULL_TREE, + srcsize, dstsize, data.mode, &data); +} + +bool +check_memop_access (gimple *stmt, tree dest, tree src, tree size) +{ + return check_memop_access<gimple *>(stmt, dest, src, size); +} + +bool +check_memop_access (tree expr, tree dest, tree src, tree size) +{ + return check_memop_access<tree>(expr, dest, src, size); +} + +/* A convenience wrapper for check_access above to check access + by a read-only function like puts. */ + +template <class GimpleOrTree> +static bool +check_read_access (GimpleOrTree expr, tree src, tree bound, int ost) +{ + 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); + + tree fndecl = get_callee_fndecl (expr); + maybe_warn_nonstring_arg (fndecl, expr); + + access_data data (expr, access_read_only, NULL_TREE, false, bound, true); + compute_objsize (src, ost, &data.src); + return check_access (expr, /*dstwrite=*/ NULL_TREE, /*maxread=*/ bound, + /*srcstr=*/ src, /*dstsize=*/ NULL_TREE, data.mode, + &data); +} + +bool +check_read_access (gimple *stmt, tree src, tree bound /* = NULL_TREE */, + int ost /* = 1 */) +{ + return check_read_access<gimple *>(stmt, src, bound, ost); +} + +bool +check_read_access (tree expr, tree src, tree bound /* = NULL_TREE */, + int ost /* = 1 */) +{ + return check_read_access<tree>(expr, src, bound, ost); +} + /* Return true if STMT is a call to an allocation function. Unless ALL_ALLOC is set, consider only functions that return dynmamically allocated objects. Otherwise return true even for all forms of @@ -1523,13 +2072,13 @@ warn_dealloc_offset (location_t loc, gimple *call, const access_ref &aref) return false; if (DECL_P (aref.ref)) - inform (DECL_SOURCE_LOCATION (aref.ref), "declared here"); + inform (get_location (aref.ref), "declared here"); else if (TREE_CODE (aref.ref) == SSA_NAME) { gimple *def_stmt = SSA_NAME_DEF_STMT (aref.ref); if (is_gimple_call (def_stmt)) { - location_t def_loc = gimple_location (def_stmt); + location_t def_loc = get_location (def_stmt); tree alloc_decl = gimple_call_fndecl (def_stmt); if (alloc_decl) inform (def_loc, @@ -1550,7 +2099,7 @@ warn_dealloc_offset (location_t loc, gimple *call, const access_ref &aref) a matching allocation function such as malloc or the corresponding form of C++ operatorn new. */ -void +static void maybe_emit_free_warning (gcall *call) { tree fndecl = gimple_call_fndecl (call); @@ -1584,10 +2133,7 @@ maybe_emit_free_warning (gcall *call) "%qD called on unallocated object %qD", dealloc_decl, ref)) { - loc = (DECL_P (ref) - ? DECL_SOURCE_LOCATION (ref) - : EXPR_LOCATION (ref)); - inform (loc, "declared here"); + inform (get_location (ref), "declared here"); return; } @@ -1704,8 +2250,14 @@ class pass_waccess : public gimple_opt_pass virtual bool gate (function *); virtual unsigned int execute (function *); + /* Check a call to a built-in function. */ + bool check_builtin (gcall *); + + /* Check statements in a basic block. */ void check (basic_block); - void check (gcall *); + + /* Check a call to a function. */ + void check (gcall *); private: gimple_ranger *m_ranger; @@ -1721,11 +2273,376 @@ pass_waccess::gate (function *) || warn_mismatched_new_delete); } +/* Check a call STMT to strcat() for overflow and warn if it does. */ + +static void +check_strcat (gimple *stmt) +{ + if (!warn_stringop_overflow) + return; + + tree dest = call_arg (stmt, 0); + tree src = call_arg (stmt, 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 (stmt, 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 (stmt, /*dstwrite=*/NULL_TREE, /*maxread=*/NULL_TREE, + src, destsize, data.mode, &data); +} + +/* Check a call STMT to strcat() for overflow and warn if it does. */ + +static void +check_strncat (gimple *stmt) +{ + if (!warn_stringop_overflow) + return; + + tree dest = call_arg (stmt, 0); + tree src = call_arg (stmt, 1); + /* The upper bound on the number of bytes to write. */ + tree maxread = call_arg (stmt, 2); + + /* Detect unterminated source (only). */ + if (!check_nul_terminated_array (stmt, src, maxread)) + return; + + /* 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 (stmt, 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 = get_location (stmt); + warning_at (loc, OPT_Wstringop_overflow_, + "%qD specified bound %E equals destination size", + get_callee_fndecl (stmt), maxread); + + return; + } + + if (!srclen + || (maxread && tree_fits_uhwi_p (maxread) + && tree_fits_uhwi_p (srclen) + && tree_int_cst_lt (maxread, srclen))) + srclen = maxread; + + check_access (stmt, /*dstwrite=*/NULL_TREE, maxread, srclen, + destsize, data.mode, &data); +} + +/* Check a call STMT to stpcpy() or strcpy() for overflow and warn + if it does. */ + +static void +check_stxcpy (gimple *stmt) +{ + tree dst = call_arg (stmt, 0); + tree src = call_arg (stmt, 1); + + 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 (get_location (stmt), stmt, NULL, src, nonstr, + size, exact); + return; + } + + if (warn_stringop_overflow) + { + access_data data (stmt, 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 (dst, ost, &data.dst); + check_access (stmt, /*dstwrite=*/ NULL_TREE, + /*maxread=*/ NULL_TREE, /*srcstr=*/ src, + dstsize, data.mode, &data); + } + + /* 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 (stmt); + maybe_warn_nonstring_arg (fndecl, stmt); +} + +/* Check a call STMT to stpncpy() or strncpy() for overflow and warn + if it does. */ + +static void +check_stxncpy (gimple *stmt) +{ + if (!warn_stringop_overflow) + return; + + tree dst = call_arg (stmt, 0); + tree src = call_arg (stmt, 1); + /* The number of bytes to write (not the maximum). */ + tree len = call_arg (stmt, 2); + + access_data data (stmt, 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 (dst, ost, &data.dst); + + check_access (stmt, /*dstwrite=*/len, + /*maxread=*/len, src, dstsize, data.mode, &data); +} + +/* Check a call STMT to stpncpy() or strncpy() for overflow and warn + if it does. */ + +static void +check_strncmp (gimple *stmt) +{ + if (!warn_stringop_overread) + return; + + tree arg1 = call_arg (stmt, 0); + tree arg2 = call_arg (stmt, 1); + tree bound = call_arg (stmt, 2); + + /* First check each argument separately, considering the bound. */ + if (!check_nul_terminated_array (stmt, arg1, bound) + || !check_nul_terminated_array (stmt, arg2, bound)) + return; + + /* A strncmp read from each argument 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. */ + + c_strlen_data lendata1{ }, lendata2{ }; + tree len1 = c_strlen (arg1, 1, &lendata1); + tree len2 = c_strlen (arg2, 1, &lendata2); + + if (len1 && len2) + /* If the length of both arguments was computed they must both be + nul-terminated and no further checking is necessary regardless + of the bound. */ + return; + + /* Check to see if the argument was declared with 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 (stmt), stmt)) + return; + + access_data adata1 (stmt, access_read_only, NULL_TREE, false, bound, true); + access_data adata2 (stmt, access_read_only, NULL_TREE, false, bound, true); + + /* Determine the range of the bound first and bail if it fails; it's + cheaper than computing the size of the objects. */ + tree bndrng[2] = { NULL_TREE, NULL_TREE }; + get_size_range (bound, bndrng, adata1.src.bndrng); + if (!bndrng[0] || integer_zerop (bndrng[0])) + return; + + if (len1 && tree_int_cst_lt (len1, bndrng[0])) + bndrng[0] = len1; + if (len2 && tree_int_cst_lt (len2, bndrng[0])) + bndrng[0] = len2; + + /* compute_objsize almost never fails (and ultimately should never + fail). Don't bother to handle the rare case when it does. */ + if (!compute_objsize (arg1, 1, &adata1.src) + || !compute_objsize (arg2, 1, &adata2.src)) + return; + + /* Compute the size of the remaining space in each array after + subtracting any offset into it. */ + offset_int rem1 = adata1.src.size_remaining (); + offset_int rem2 = adata2.src.size_remaining (); + + /* Cap REM1 and REM2 at the other if the other's argument is known + to be an unterminated array, either because there's no space + left in it after adding its offset or because it's constant and + has no nul. */ + if (rem1 == 0 || (rem1 < rem2 && lendata1.decl)) + rem2 = rem1; + else if (rem2 == 0 || (rem2 < rem1 && lendata2.decl)) + rem1 = rem2; + + /* Point PAD at the array to reference in the note if a warning + is issued. */ + access_data *pad = len1 ? &adata2 : &adata1; + offset_int maxrem = wi::max (rem1, rem2, UNSIGNED); + if (lendata1.decl || lendata2.decl + || maxrem < wi::to_offset (bndrng[0])) + { + /* Warn when either argument isn't nul-terminated or the maximum + remaining space in the two arrays is less than the bound. */ + tree func = get_callee_fndecl (stmt); + location_t loc = gimple_location (stmt); + maybe_warn_for_bound (OPT_Wstringop_overread, loc, stmt, func, + bndrng, wide_int_to_tree (sizetype, maxrem), + pad); + } +} + +/* Check call STMT to a built-in function for invalid accesses. Return + true if a call has been handled. */ + +bool +pass_waccess::check_builtin (gcall *stmt) +{ + tree callee = gimple_call_fndecl (stmt); + if (!callee) + return false; + + switch (DECL_FUNCTION_CODE (callee)) + { + case BUILT_IN_GETTEXT: + case BUILT_IN_PUTS: + case BUILT_IN_PUTS_UNLOCKED: + case BUILT_IN_STRDUP: + check_read_access (stmt, call_arg (stmt, 0)); + return true; + + case BUILT_IN_INDEX: + case BUILT_IN_RINDEX: + case BUILT_IN_STRCHR: + case BUILT_IN_STRRCHR: + case BUILT_IN_STRLEN: + check_read_access (stmt, call_arg (stmt, 0)); + return true; + + case BUILT_IN_FPUTS: + case BUILT_IN_FPUTS_UNLOCKED: + check_read_access (stmt, call_arg (stmt, 0)); + return true; + + case BUILT_IN_STRNDUP: + case BUILT_IN_STRNLEN: + check_read_access (stmt, call_arg (stmt, 0), call_arg (stmt, 1)); + return true; + + case BUILT_IN_STRCAT: + check_strcat (stmt); + return true; + + case BUILT_IN_STRNCAT: + check_strncat (stmt); + return true; + + case BUILT_IN_STPCPY: + case BUILT_IN_STRCPY: + check_stxcpy (stmt); + return true; + + case BUILT_IN_STPNCPY: + case BUILT_IN_STRNCPY: + check_stxncpy (stmt); + return true; + + case BUILT_IN_STRCASECMP: + case BUILT_IN_STRCMP: + case BUILT_IN_STRPBRK: + case BUILT_IN_STRSPN: + case BUILT_IN_STRCSPN: + case BUILT_IN_STRSTR: + check_read_access (stmt, call_arg (stmt, 0)); + check_read_access (stmt, call_arg (stmt, 1)); + return true; + + case BUILT_IN_STRNCASECMP: + case BUILT_IN_STRNCMP: + check_strncmp (stmt); + return true; + + case BUILT_IN_MEMCMP: + { + tree a1 = call_arg (stmt, 0); + tree a2 = call_arg (stmt, 1); + tree len = call_arg (stmt, 2); + check_read_access (stmt, a1, len, 0); + check_read_access (stmt, a2, len, 0); + return true; + } + + case BUILT_IN_MEMCPY: + case BUILT_IN_MEMPCPY: + case BUILT_IN_MEMMOVE: + { + tree dst = call_arg (stmt, 0); + tree src = call_arg (stmt, 1); + tree len = call_arg (stmt, 2); + check_memop_access (stmt, dst, src, len); + return true; + } + + case BUILT_IN_MEMCHR: + { + tree src = call_arg (stmt, 0); + tree len = call_arg (stmt, 2); + check_read_access (stmt, src, len, 0); + return true; + } + + case BUILT_IN_MEMSET: + { + tree dst = call_arg (stmt, 0); + tree len = call_arg (stmt, 2); + check_memop_access (stmt, dst, NULL_TREE, len); + return true; + } + + default: + return false; + } + + return true; +} + /* Check call STMT for invalid accesses. */ void pass_waccess::check (gcall *stmt) { + if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL) + && check_builtin (stmt)) + return; + maybe_emit_free_warning (stmt); } diff --git a/gcc/gimple-ssa-warn-access.h b/gcc/gimple-ssa-warn-access.h index 6197574..8b33ecb 100644 --- a/gcc/gimple-ssa-warn-access.h +++ b/gcc/gimple-ssa-warn-access.h @@ -24,6 +24,9 @@ #define GCC_GIMPLE_SSA_WARN_ACCESS_H extern bool check_nul_terminated_array (tree, tree, tree = NULL_TREE); +extern void warn_string_no_nul (location_t, gimple *, const char *, tree, + tree, tree = NULL_TREE, bool = false, + const wide_int[2] = NULL); extern void warn_string_no_nul (location_t, tree, const char *, tree, tree, tree = NULL_TREE, bool = false, const wide_int[2] = NULL); @@ -31,7 +34,17 @@ extern tree unterminated_array (tree, tree * = NULL, bool * = NULL); extern void get_size_range (tree, tree[2], const offset_int[2]); class access_data; +extern bool maybe_warn_for_bound (opt_code, location_t, gimple *, tree, + tree[2], tree, const access_data * = NULL); extern bool maybe_warn_for_bound (opt_code, location_t, tree, tree, tree[2], tree, const access_data * = NULL); +class access_data; +extern bool check_access (tree, tree, tree, tree, tree, access_mode, + const access_data * = NULL); + +extern bool check_memop_access (tree, tree, tree, tree); +extern bool check_read_access (gimple *, tree, tree = NULL_TREE, int ost = 1); +extern bool check_read_access (tree, tree, tree = NULL_TREE, int = 1); + #endif // GCC_GIMPLE_SSA_WARN_ACCESS_H diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 19ab2de..b983fda 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -32590102c464679f845667b5554e1dcce2549ad2 +d5d51242efc432fa62d4e9b141b01c280af32d19 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/escape.cc b/gcc/go/gofrontend/escape.cc index c8978ac..6da29ed 100644 --- a/gcc/go/gofrontend/escape.cc +++ b/gcc/go/gofrontend/escape.cc @@ -1646,6 +1646,7 @@ Escape_analysis_assign::expression(Expression** pexpr) case Runtime::MAKECHAN: case Runtime::MAKECHAN64: case Runtime::MAKEMAP: + case Runtime::MAKEMAP64: case Runtime::MAKESLICE: case Runtime::MAKESLICE64: this->context_->track(n); @@ -1705,8 +1706,52 @@ Escape_analysis_assign::expression(Expression** pexpr) } break; + case Runtime::MEMCMP: + case Runtime::DECODERUNE: + case Runtime::INTSTRING: + case Runtime::MAKEMAP_SMALL: + case Runtime::MAPACCESS1: + case Runtime::MAPACCESS1_FAST32: + case Runtime::MAPACCESS1_FAST64: + case Runtime::MAPACCESS1_FASTSTR: + case Runtime::MAPACCESS1_FAT: + case Runtime::MAPACCESS2: + case Runtime::MAPACCESS2_FAST32: + case Runtime::MAPACCESS2_FAST64: + case Runtime::MAPACCESS2_FASTSTR: + case Runtime::MAPACCESS2_FAT: + case Runtime::MAPASSIGN_FAST32: + case Runtime::MAPASSIGN_FAST64: + case Runtime::MAPITERINIT: + case Runtime::MAPITERNEXT: + case Runtime::MAPCLEAR: + case Runtime::CHANRECV2: + case Runtime::SELECTGO: + case Runtime::SELECTNBSEND: + case Runtime::SELECTNBRECV: + case Runtime::BLOCK: + case Runtime::IFACET2IP: + case Runtime::EQTYPE: + case Runtime::MEMCLRHASPTR: + case Runtime::FIELDTRACK: + case Runtime::BUILTIN_MEMSET: + case Runtime::PANIC_SLICE_CONVERT: + // these do not escape. + break; + + case Runtime::IFACEE2E2: + case Runtime::IFACEI2E2: + case Runtime::IFACEE2I2: + case Runtime::IFACEI2I2: + case Runtime::IFACEE2T2P: + case Runtime::IFACEI2T2P: + // handled in ::assign. + break; + default: - break; + // should not see other runtime calls. they are not yet + // lowered to runtime calls at this point. + go_unreachable(); } } else diff --git a/gcc/go/gofrontend/export.cc b/gcc/go/gofrontend/export.cc index e99c680..3d11334 100644 --- a/gcc/go/gofrontend/export.cc +++ b/gcc/go/gofrontend/export.cc @@ -106,11 +106,12 @@ class Collect_export_references : public Traverse { public: Collect_export_references(Export* exp, + const std::map<std::string, Package*>& packages, Unordered_set(Named_object*)* exports, Unordered_set(const Package*)* imports) : Traverse(traverse_expressions | traverse_types), - exp_(exp), exports_(exports), imports_(imports), + exp_(exp), packages_(packages), exports_(exports), imports_(imports), inline_fcn_worklist_(NULL), exports_finalized_(false) { } @@ -150,6 +151,8 @@ class Collect_export_references : public Traverse // The exporter. Export* exp_; + // The list of packages known to this compilation. + const std::map<std::string, Package*>& packages_; // The set of named objects to export. Unordered_set(Named_object*)* exports_; // Set containing all directly and indirectly imported packages. @@ -257,6 +260,24 @@ Collect_export_references::expression(Expression** pexpr) return TRAVERSE_CONTINUE; } + const Call_expression* call = expr->call_expression(); + if (call != NULL) + { + const Builtin_call_expression* bce = call->builtin_call_expression(); + if (bce != NULL + && (bce->code() == Builtin_call_expression::BUILTIN_ADD + || bce->code() == Builtin_call_expression::BUILTIN_SLICE)) + { + // This is a reference to unsafe.Add or unsafe.Slice. Make + // sure we list the "unsafe" package in the imports and give + // it a package index. + const std::map<std::string, Package*>::const_iterator p = + this->packages_.find("unsafe"); + go_assert(p != this->packages_.end()); + this->imports_->insert(p->second); + } + } + return TRAVERSE_CONTINUE; } @@ -589,7 +610,7 @@ Export::export_globals(const std::string& package_name, // Track all imported packages mentioned in export data. Unordered_set(const Package*) all_imports; - Collect_export_references collect(this, &exports, &all_imports); + Collect_export_references collect(this, packages, &exports, &all_imports); // Walk the set of inlinable routine bodies collected above. This // can potentially expand the exports set. @@ -1274,6 +1295,25 @@ Export::package_index(const Package* pkg) const return index; } +// Return the index of the "unsafe" package. + +int +Export::unsafe_package_index() const +{ + for (Unordered_map(const Package*, int)::const_iterator p = + this->packages_.begin(); + p != this->packages_.end(); + ++p) + { + if (p->first->pkgpath() == "unsafe") + { + go_assert(p->second != 0); + return p->second; + } + } + go_unreachable(); +} + // Return the index of a type. int diff --git a/gcc/go/gofrontend/export.h b/gcc/go/gofrontend/export.h index c93bced..1f61343 100644 --- a/gcc/go/gofrontend/export.h +++ b/gcc/go/gofrontend/export.h @@ -216,6 +216,11 @@ class Export : public String_dump int package_index(const Package* p) const; + // Return the index of the "unsafe" package, which must be one of + // the exported packages. + int + unsafe_package_index() const; + private: Export(const Export&); Export& operator=(const Export&); @@ -377,6 +382,11 @@ class Export_function_body : public String_dump package_index(const Package* p) const { return this->exp_->package_index(p); } + // Return the index of the "unsafe" package. + int + unsafe_package_index() const + { return this->exp_->unsafe_package_index(); } + // Record a temporary statement and return its index. unsigned int record_temporary(const Temporary_statement*); diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 33177a7..f462b0e 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -11039,6 +11039,14 @@ Builtin_call_expression::do_export(Export_function_body* efb) const // A trailing space lets us reliably identify the end of the number. efb->write_c_string(" "); } + else if (this->code_ == BUILTIN_ADD || this->code_ == BUILTIN_SLICE) + { + char buf[50]; + snprintf(buf, sizeof buf, "<p%d>%s", efb->unsafe_package_index(), + (this->code_ == BUILTIN_ADD ? "Add" : "Slice")); + efb->write_c_string(buf); + this->export_arguments(efb); + } else { const char *s = NULL; diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index 79a8785..9f8f4e9 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -732,6 +732,10 @@ class Expression call_expression() { return this->convert<Call_expression, EXPRESSION_CALL>(); } + const Call_expression* + call_expression() const + { return this->convert<const Call_expression, EXPRESSION_CALL>(); } + // If this is a call_result expression, return the Call_result_expression // structure. Otherwise, return NULL. This is a controlled dynamic // cast. @@ -2460,13 +2464,16 @@ class Call_expression : public Expression // Whether this is a call to builtin function. virtual bool - is_builtin() + is_builtin() const { return false; } // Convert to a Builtin_call_expression, or return NULL. inline Builtin_call_expression* builtin_call_expression(); + inline const Builtin_call_expression* + builtin_call_expression() const; + protected: int do_traverse(Traverse*); @@ -2625,12 +2632,12 @@ class Builtin_call_expression : public Call_expression }; Builtin_function_code - code() + code() const { return this->code_; } // This overrides Call_expression::is_builtin. bool - is_builtin() + is_builtin() const { return true; } // Return whether EXPR, of array type, is a constant if passed to @@ -2726,6 +2733,14 @@ Call_expression::builtin_call_expression() : NULL); } +inline const Builtin_call_expression* +Call_expression::builtin_call_expression() const +{ + return (this->is_builtin() + ? static_cast<const Builtin_call_expression*>(this) + : NULL); +} + // A single result from a call which returns multiple results. class Call_result_expression : public Expression diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index c49bc92..9ffd120 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -533,6 +533,10 @@ class Gogo register_package(const std::string& pkgpath, const std::string& pkgpath_symbol, Location); + // Add the unsafe bindings to the unsafe package. + void + add_unsafe_bindings(Package*); + // Look up a package by pkgpath, and return its pkgpath_symbol. std::string pkgpath_symbol_for_package(const std::string&); diff --git a/gcc/go/gofrontend/import.cc b/gcc/go/gofrontend/import.cc index f671416..6a5491b 100644 --- a/gcc/go/gofrontend/import.cc +++ b/gcc/go/gofrontend/import.cc @@ -497,6 +497,9 @@ Import::read_one_import() p->set_package_name(package_name, this->location()); this->packages_.push_back(p); + + if (pkgpath == "unsafe") + this->gogo_->add_unsafe_bindings(p); } // Read an indirectimport line. @@ -515,6 +518,9 @@ Import::read_one_indirect_import() p->set_package_name(package_name, this->location()); this->packages_.push_back(p); + + if (pkgpath == "unsafe") + this->gogo_->add_unsafe_bindings(p); } // Read the list of import control functions and/or init graph. diff --git a/gcc/go/gofrontend/unsafe.cc b/gcc/go/gofrontend/unsafe.cc index 18bd99e..c4a9346 100644 --- a/gcc/go/gofrontend/unsafe.cc +++ b/gcc/go/gofrontend/unsafe.cc @@ -10,15 +10,12 @@ #include "types.h" #include "gogo.h" -// Set up the builtin unsafe package. This should probably be driven -// by a table. +// Set up the builtin unsafe package. void Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported, Location location) { - Location bloc = Linemap::predeclared_location(); - bool add_to_globals; Package* package = this->add_imported_package("unsafe", local_name, is_local_name_exported, @@ -34,10 +31,40 @@ Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported, package->set_location(location); this->imports_.insert(std::make_pair("unsafe", package)); + this->add_unsafe_bindings(package); + + Named_object* pointer_no = package->bindings()->lookup_local("Pointer"); + pointer_no->type_value()->set_is_visible(); + + if (add_to_globals) + { + Bindings* bindings = package->bindings(); + for (Bindings::const_declarations_iterator p = + bindings->begin_declarations(); + p != bindings->end_declarations(); + ++p) + this->add_dot_import_object(p->second); + } +} + +// Add the unsafe bindings to the Package object. This should +// probably be driven by a table. + +void +Gogo::add_unsafe_bindings(Package* package) +{ Bindings* bindings = package->bindings(); + if (bindings->lookup_local("Sizeof") != NULL) + { + // Already done by an earlier import. + return; + } + + Location bloc = Linemap::predeclared_location(); + // The type may have already been created by an import. - Named_object* no = package->bindings()->lookup("Pointer"); + Named_object* no = bindings->lookup("Pointer"); if (no == NULL) { Type* type = Type::make_pointer_type(Type::make_void_type()); @@ -49,11 +76,12 @@ Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported, go_assert(no->package() == package); go_assert(no->is_type()); go_assert(no->type_value()->is_unsafe_pointer_type()); - no->type_value()->set_is_visible(); } Named_type* pointer_type = no->type_value(); - if (add_to_globals) - this->add_named_type(pointer_type); + + // This may be called during an import, so the type may not be + // visible yet. + pointer_type->clear_is_visible(); Type* uintptr_type = Type::lookup_integer_type("uintptr"); @@ -62,9 +90,7 @@ Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported, results->push_back(Typed_identifier("", uintptr_type, bloc)); Function_type* fntype = Type::make_function_type(NULL, NULL, results, bloc); fntype->set_is_builtin(); - no = bindings->add_function_declaration("Sizeof", package, fntype, bloc); - if (add_to_globals) - this->add_dot_import_object(no); + bindings->add_function_declaration("Sizeof", package, fntype, bloc); // Offsetof. results = new Typed_identifier_list; @@ -72,9 +98,7 @@ Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported, fntype = Type::make_function_type(NULL, NULL, results, bloc); fntype->set_is_varargs(); fntype->set_is_builtin(); - no = bindings->add_function_declaration("Offsetof", package, fntype, bloc); - if (add_to_globals) - this->add_dot_import_object(no); + bindings->add_function_declaration("Offsetof", package, fntype, bloc); // Alignof. results = new Typed_identifier_list; @@ -82,25 +106,19 @@ Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported, fntype = Type::make_function_type(NULL, NULL, results, bloc); fntype->set_is_varargs(); fntype->set_is_builtin(); - no = bindings->add_function_declaration("Alignof", package, fntype, bloc); - if (add_to_globals) - this->add_dot_import_object(no); + bindings->add_function_declaration("Alignof", package, fntype, bloc); // Add. results = new Typed_identifier_list; results->push_back(Typed_identifier("", pointer_type, bloc)); fntype = Type::make_function_type(NULL, NULL, results, bloc); fntype->set_is_builtin(); - no = bindings->add_function_declaration("Add", package, fntype, bloc); - if (add_to_globals) - this->add_dot_import_object(no); + bindings->add_function_declaration("Add", package, fntype, bloc); // Slice. fntype = Type::make_function_type(NULL, NULL, NULL, bloc); fntype->set_is_builtin(); - no = bindings->add_function_declaration("Slice", package, fntype, bloc); - if (add_to_globals) - this->add_dot_import_object(no); + bindings->add_function_declaration("Slice", package, fntype, bloc); if (!this->imported_unsafe_) { diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index 8b744d9..02b4681 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -55,7 +55,7 @@ extern void lhd_set_decl_assembler_name (tree decl); extern void lhd_overwrite_decl_assembler_name (tree decl, tree name); extern bool lhd_warn_unused_global_decl (const_tree); extern tree lhd_simulate_enum_decl (location_t, const char *, - vec<string_int_pair>); + vec<string_int_pair> *); extern tree lhd_type_for_size (unsigned precision, int unsignedp); extern void lhd_incomplete_type_error (location_t, const_tree, const_tree); extern tree lhd_type_promotes_to (tree); diff --git a/gcc/langhooks.c b/gcc/langhooks.c index d753199..48c7237 100644 --- a/gcc/langhooks.c +++ b/gcc/langhooks.c @@ -485,7 +485,7 @@ lhd_make_node (enum tree_code code) might be reusable elsewhere. */ tree lhd_simulate_enum_decl (location_t loc, const char *name, - vec<string_int_pair> values) + vec<string_int_pair> *values_ptr) { tree enumtype = lang_hooks.types.make_type (ENUMERAL_TYPE); tree enumdecl = build_decl (loc, TYPE_DECL, get_identifier (name), enumtype); @@ -493,6 +493,7 @@ lhd_simulate_enum_decl (location_t loc, const char *name, tree value_chain = NULL_TREE; string_int_pair *value; + vec<string_int_pair> values = *values_ptr; unsigned int i; FOR_EACH_VEC_ELT (values, i, value) { diff --git a/gcc/langhooks.h b/gcc/langhooks.h index 1b417a0..ffd3e0b 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -66,7 +66,7 @@ struct lang_hooks_for_types /* Make an enum type with the given name and values, associating them all with the given source location. */ - tree (*simulate_enum_decl) (location_t, const char *, vec<string_int_pair>); + tree (*simulate_enum_decl) (location_t, const char *, vec<string_int_pair> *); /* Return what kind of RECORD_TYPE this is, mainly for purposes of debug information. If not defined, record types are assumed to diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index a766f1f..a56080b 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -2771,7 +2771,7 @@ process_alt_operands (int only_alternative) if (lra_dump_file != NULL) fprintf (lra_dump_file, - " alt=%d: No input/otput reload -- refuse\n", + " alt=%d: No input/output reload -- refuse\n", nalt); goto fail; } diff --git a/gcc/pointer-query.h b/gcc/pointer-query.h index 6168c80..8bd538a 100644 --- a/gcc/pointer-query.h +++ b/gcc/pointer-query.h @@ -205,12 +205,22 @@ struct access_data { /* Set the access to at most MAXWRITE and MAXREAD bytes, and at least 1 when MINWRITE or MINREAD, respectively, is set. */ + access_data (gimple *stmt, access_mode mode, + tree maxwrite = NULL_TREE, bool minwrite = false, + tree maxread = NULL_TREE, bool minread = false) + : stmt (stmt), call (), + dst (maxwrite, minwrite), src (maxread, minread), mode (mode) { } + + /* Set the access to at most MAXWRITE and MAXREAD bytes, and + at least 1 when MINWRITE or MINREAD, respectively, is set. */ access_data (tree expr, access_mode mode, tree maxwrite = NULL_TREE, bool minwrite = false, tree maxread = NULL_TREE, bool minread = false) - : call (expr), + : stmt (), call (expr), dst (maxwrite, minwrite), src (maxread, minread), mode (mode) { } + /* Access statement. */ + gimple *stmt; /* Built-in function call. */ tree call; /* Destination and source of the access. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d4c0307..034fc30 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,78 @@ +2021-08-08 Jeff Law <jlaw@localhost.localdomain> + + * gcc.target/tic6x/rotdi16-scan.c: Pull rotate into its own function. + +2021-08-07 H.J. Lu <hjl.tools@gmail.com> + + PR tree-optimization/88531 + * gcc.target/i386/pr88531-1a.c: New test. + * gcc.target/i386/pr88531-1b.c: Likewise. + * gcc.target/i386/pr88531-1c.c: Likewise. + * gcc.target/i386/pr88531-2a.c: Likewise. + * gcc.target/i386/pr88531-2b.c: Likewise. + * gcc.target/i386/pr88531-2c.c: Likewise. + +2021-08-06 Martin Sebor <msebor@redhat.com> + + * 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. + +2021-08-06 Christophe Lyon <christophe.lyon@foss.st.com> + + PR target/101723 + * gcc.target/arm/pr69245.c: Make sure to emit code for fn1, fix + typo. + +2021-08-06 Christophe Lyon <christophe.lyon@foss.st.com> + + PR target/101723 + * gcc.target/arm/attr-neon3.c: Fix typo. + * gcc.target/arm/pragma_fpu_attribute_2.c: Fix typo. + +2021-08-06 Uroš Bizjak <ubizjak@gmail.com> + + PR target/101797 + * gcc.target/i386/pr101797.c: New test. + +2021-08-06 Jonathan Wright <jonathan.wright@arm.com> + + * gcc.target/aarch64/vector_structure_intrinsics.c: Add new + tests. + +2021-08-06 Jonathan Wright <jonathan.wright@arm.com> + + * gcc.target/aarch64/vector_structure_intrinsics.c: Add new + tests. + +2021-08-06 Jonathan Wright <jonathan.wright@arm.com> + + * gcc.target/aarch64/vector_structure_intrinsics.c: Add new + tests. + +2021-08-06 Jonathan Wright <jonathan.wright@arm.com> + + * gcc.target/aarch64/vector_structure_intrinsics.c: Add new + tests. + +2021-08-06 Martin Liska <mliska@suse.cz> + + * gcc.target/powerpc/pragma-optimize.c: New test. + +2021-08-06 Richard Biener <rguenther@suse.de> + + * gfortran.dg/vect/vect-8.f90: Simplify aarch64 scanning. + +2021-08-06 Sebastian Huber <sebastian.huber@embedded-brains.de> + + * gcc.dg/gcov-info-to-gcda.c: New test. + 2021-08-05 Jonathan Wakely <jwakely@redhat.com> * g++.old-deja/g++.other/inline7.C: Cast nodiscard call to void. diff --git a/gcc/testsuite/c-c++-common/Wsizeof-pointer-memaccess1.c b/gcc/testsuite/c-c++-common/Wsizeof-pointer-memaccess1.c index 38e06ba..6c8866d 100644 --- a/gcc/testsuite/c-c++-common/Wsizeof-pointer-memaccess1.c +++ b/gcc/testsuite/c-c++-common/Wsizeof-pointer-memaccess1.c @@ -1,7 +1,7 @@ /* Test -Wsizeof-pointer-memaccess warnings. */ /* { dg-do compile } */ -/* { dg-options "-Wall -Wno-array-bounds -Wno-sizeof-array-argument -Wno-stringop-overflow" } */ -/* { dg-options "-Wall -Wno-array-bounds -Wno-sizeof-array-argument -Wno-c++-compat -Wno-stringop-overflow" { target c } } */ +/* { dg-options "-Wall -Wno-array-bounds -Wno-sizeof-array-argument -Wno-stringop-overflow -Wno-stringop-overread" } */ +/* { dg-options "-Wall -Wno-array-bounds -Wno-sizeof-array-argument -Wno-c++-compat -Wno-stringop-overflow -Wno-stringop-overread" { target c } } */ /* { dg-require-effective-target alloca } */ typedef __SIZE_TYPE__ size_t; diff --git a/gcc/testsuite/c-c++-common/attr-nonstring-3.c b/gcc/testsuite/c-c++-common/attr-nonstring-3.c index e3ceabd..3add7fa 100644 --- a/gcc/testsuite/c-c++-common/attr-nonstring-3.c +++ b/gcc/testsuite/c-c++-common/attr-nonstring-3.c @@ -379,9 +379,9 @@ void test_stnrdup_warn (struct MemArrays *p) T (strndup (p->arr, N)); - T (strndup (arr, N + 1)); /* { dg-warning "specified bound 5 exceeds source size 4" } */ + T (strndup (arr, N + 1)); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound 5|specified bound 5 exceeds source size 4" } */ T (strndup (parr, N + 1)); - T (strndup (p->arr, N + 1)); /* { dg-warning "specified bound 5 exceeds source size 4" } */ + T (strndup (p->arr, N + 1)); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound 5|specified bound 5 exceeds source size 4" } */ T (strndup (p->parr, N + 1)); } diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-39.c b/gcc/testsuite/gcc.dg/Warray-bounds-39.c index 8317656..cb00fa9 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-39.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-39.c @@ -5,6 +5,8 @@ { dg-do compile } { dg-options "-O2 -Wall" } */ +#define NOIPA __attribute__ ((noipa)) + typedef __SIZE_TYPE__ size_t; extern void* memcpy (void*, const void*, size_t); @@ -19,65 +21,65 @@ const char s1_0[1][0] = { }; char d[4]; -void* test_memcpy_s0_1 (void *d) +NOIPA void* test_memcpy_s0_1 (void *d) { return memcpy (d, s0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -void* test_memcpy_s0_2 (void *d) +NOIPA void* test_memcpy_s0_2 (void *d) { return memcpy (d, s0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -void* test_memcpy_s0_0_1 (void *d) +NOIPA void* test_memcpy_s0_0_1 (void *d) { return memcpy (d, s0_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -void* test_memcpy_s0_0_2 (void *d) +NOIPA void* test_memcpy_s0_0_2 (void *d) { return memcpy (d, s0_0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -void* test_memcpy_s0_1_1 (void *d) +NOIPA void* test_memcpy_s0_1_1 (void *d) { return memcpy (d, s0_1, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -void* test_memcpy_s0_1_2 (void *d) +NOIPA void* test_memcpy_s0_1_2 (void *d) { return memcpy (d, s0_1, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -void* test_memcpy_s1_0_1 (void *d) +NOIPA void* test_memcpy_s1_0_1 (void *d) { return memcpy (d, s1_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -void* test_memcpy_s1_0_2 (void *d) +NOIPA void* test_memcpy_s1_0_2 (void *d) { return memcpy (d, s1_0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -void* test_memmove_s0_1 (void *d) +NOIPA void* test_memmove_s0_1 (void *d) { return memmove (d, s0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -void* test_memmove_s0_2 (void *d) +NOIPA void* test_memmove_s0_2 (void *d) { return memmove (d, s0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -void* test_memmove_s0_0_1 (void *d) +NOIPA void* test_memmove_s0_0_1 (void *d) { return memmove (d, s0_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -void* test_memmove_s0_0_2 (void *d) +NOIPA void* test_memmove_s0_0_2 (void *d) { return memmove (d, s0_0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } @@ -90,59 +92,60 @@ const struct Empty e0_0[0][0] = { }; const struct Empty e0_1[0][1] = { }; const struct Empty e1_0[1][0] = { }; -void* test_memcpy_e_1 (void *d) +NOIPA void* test_memcpy_e_1 (void *d) { return memcpy (d, &e, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -void* test_memcpy_e0_1 (void *d) +NOIPA void* test_memcpy_e0_1 (void *d) { return memcpy (d, e0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -void* test_memcpy_e0_0_1 (void *d) +NOIPA void* test_memcpy_e0_0_1 (void *d) { return memcpy (d, e0_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -void* test_memcpy_e0_1_1 (void *d) +NOIPA void* test_memcpy_e0_1_1 (void *d) { return memcpy (d, e0_1, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -void* test_memcpy_e1_0_1 (void *d) +NOIPA void* test_memcpy_e1_0_1 (void *d) { return memcpy (d, e1_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -char* test_strcpy_s0 (char *d) +NOIPA char* +test_strcpy_s0 (char *d) /* { dg-bogus "-Warray-bounds" "pr101679" { xfail *-*-* } } */ { return strcpy (d, s0); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -char* test_strcpy_s0_0 (char *d) +NOIPA char* test_strcpy_s0_0 (char *d) { return strcpy (d, s0_0[0]); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -char* test_strncpy_s0_1 (char *d) +NOIPA char* test_strncpy_s0_1 (char *d) { return strncpy (d, s0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -char* test_strncpy_s0_2 (char *d) +NOIPA char* test_strncpy_s0_2 (char *d) { return strncpy (d, s0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -char* test_strncpy_s0_0_1 (char *d) +NOIPA char* test_strncpy_s0_0_1 (char *d) { return strncpy (d, s0_0[0], 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } -char* test_strncpy_s0_0_2 (char *d) +NOIPA char* test_strncpy_s0_0_2 (char *d) { return strncpy (d, s0_0[0], 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } diff --git a/gcc/testsuite/gcc.dg/Wstring-compare-3.c b/gcc/testsuite/gcc.dg/Wstring-compare-3.c index d4d7121..6d0d5be 100644 --- a/gcc/testsuite/gcc.dg/Wstring-compare-3.c +++ b/gcc/testsuite/gcc.dg/Wstring-compare-3.c @@ -1,6 +1,6 @@ /* PR middle-end/95673 - missing -Wstring-compare for an impossible strncmp test { dg-do compile } - { dg-options "-O2 -Wall -Wstring-compare -ftrack-macro-expansion=0" } */ + { dg-options "-O2 -Wall -Wstring-compare -Wno-stringop-overread -ftrack-macro-expansion=0" } */ typedef __SIZE_TYPE__ size_t; diff --git a/gcc/testsuite/gcc.dg/Wstringop-overread-6.c b/gcc/testsuite/gcc.dg/Wstringop-overread-6.c new file mode 100644 index 0000000..a8177a3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overread-6.c @@ -0,0 +1,574 @@ +/* Verify -Wstringop-overread is issued appropriately for calls to string + functions at -O0 and without -Wall. + { dg-do compile } + { dg-options "-O0 -ftrack-macro-expansion=0" } */ + +typedef __SIZE_TYPE__ size_t; + +#define S2 "12" +#define S9 "123456789" + +// <libint.h> functions. + +char* gettext (const char *); + +// <stdio.h> functions. + +typedef struct FILE FILE; + +int fputs (const char*, FILE*); +int fputs_unlocked (const char*, FILE*); + +int puts (const char*); +int puts_unlocked (const char*); + +// <string.h> functions. + +void* memchr (const void*, int, size_t); +int memcmp (const void*, const void*, size_t); +void* memcpy (void*, const void*, size_t); +void* mempcpy (void*, const void*, size_t); +void* memmove (void*, const void*, size_t); + +char* strchr (const char*, int); +char* strrchr (const char*, int); + +int strcmp (const char*, const char*); +int strncmp (const char*, const char*, size_t); + +char* strcat (char*, const char*); +char* stpcpy (char*, const char*); +char* strcpy (char*, const char*); +char* stpncpy (char*, const char*, size_t); +char* strncpy (char*, const char*, size_t); +char* strdup (const char*); +char* strndup (const char*, size_t); + +char* strpbrk (const char*, const char*); +size_t strcspn (const char*, const char*); +size_t strspn (const char*, const char*); +char* strstr (const char*, const char*); + +size_t strlen (const char*); +size_t strnlen (const char*, size_t); + + +extern void* malloc (size_t); + +void sink (void*); + + +extern char *d; +extern char a0[0]; + +const char arr[7] = "abc\0def"; + +/* Unterminated array at the end of ARR above. */ +#define unterm (arr + __builtin_strlen (arr) + 1) + +/* Size of the unterminated array - 1. */ +#define unterm_size (sizeof arr - __builtin_strlen (arr) - 1) + +const void* nowarn_memchr (int x) +{ + const char *p1 = unterm; + return memchr (p1, x, unterm_size); +} + +const void* warn_memchr (int x) +{ + const char *p1 = unterm; + return memchr (p1, x, unterm_size + 1); // { dg-warning "-Wstringop-overread" } +} + + +void* nowarn_memcpy (void) +{ + const char *s = unterm; + return memcpy (d, s, unterm_size); +} + +void* warn_memcpy (void) +{ + const char *s = unterm; + /* Use + 2 for an odd size to prevent the memmove --> MEM_REF transform + from defeating the warning (for now). */ + return memcpy (d, s, unterm_size + 2 | 1); // { dg-warning "-Wstringop-overread" } +} + + +void* nowarn_mempcpy (void) +{ + const char *s = unterm; + return mempcpy (d, s, unterm_size); +} + +void* warn_mempcpy (void) +{ + const char *s = unterm; + /* Use + 2 for an odd size to prevent the memmove --> MEM_REF transform + from defeating the warning (for now). */ + return mempcpy (d, s, unterm_size + 2 | 1); // { dg-warning "-Wstringop-overread" } +} + + +void* nowarn_memmove (void) +{ + const char *s = unterm; + return memmove (d, s, unterm_size); +} + +void* warn_memmove (void) +{ + const char *s = unterm; + /* Use + 2 for an odd size to prevent the memmove --> MEM_REF transform + from defeating the warning (for now). */ + return memmove (d, s, unterm_size + 2); // { dg-warning "-Wstringop-overread" } +} + + +int nowarn_memcmp_1 (const char *p2) +{ + const char *p1 = unterm; + return memcmp (p1, p2, unterm_size); +} + +int warn_memcmp_1 (const char *p2) +{ + const char *p1 = unterm; + return memcmp (p1, p2, unterm_size + 1); // { dg-warning "-Wstringop-overread" } +} + +int nowarn_memcmp_2 (const char *p1) +{ + const char *p2 = unterm; + return memcmp (p1, p2, unterm_size); +} + +int warn_memcmp_2 (const char *p1) +{ + const char *p2 = unterm; + return memcmp (p1, p2, unterm_size + 1); // { dg-warning "-Wstringop-overread" } +} + + +void warn_strcat (void) +{ + strcat (d, unterm); // { dg-warning "-Wstringop-overread" } +} + +void warn_strcat_a0 (void) +{ + strcat (d, a0); // { dg-warning "-Wstringop-overread" } +} + +void warn_strcat_end (void) +{ + const char *s = arr + sizeof arr; + strcat (d, s); // { dg-warning "-Wstringop-overread" } +} + +char* warn_stpcpy (void) +{ + return stpcpy (d, unterm); // { dg-warning "-Wstringop-overread" } +} + +char* warn_stpcpy_a0 (void) +{ + return stpcpy (d, a0); // { dg-warning "-Wstringop-overread" } +} + +char* warn_stpcpy_end (void) +{ + const char *s = arr + sizeof arr; + return stpcpy (d, s); // { dg-warning "-Wstringop-overread" } +} + +char* warn_stpcpy_malloc0 (void) +{ + char *s = malloc (0); + sink (s); + return stpcpy (d, s); // { dg-warning "-Wstringop-overread" } +} + + +void warn_strcpy (void) +{ + strcpy (d, unterm); // { dg-warning "-Wstringop-overread" } +} + +void warn_strcpy_a0 (void) +{ + strcpy (d, a0); // { dg-warning "-Wstringop-overread" } +} + +void warn_strcpy_end (void) +{ + const char *s = arr + sizeof arr; + strcpy (d, s); // { dg-warning "-Wstringop-overread" } +} + +void warn_strcpy_malloc0 (void) +{ + char *s = malloc (0); + sink (s); + strcpy (d, s); // { dg-warning "-Wstringop-overread" } +} + + +char* nowarn_stpncpy (void) +{ + const char *s = unterm; + return stpncpy (d, s, unterm_size); +} + +char* warn_stpncpy (void) +{ + const char *s = unterm; + return stpncpy (d, s, unterm_size + 1); // { dg-warning "-Wstringop-overread" } +} + +char* warn_stpncpy_a0 (void) +{ + return stpncpy (d, a0, 3); // { dg-warning "-Wstringop-overread" } +} + +char* warn_stpncpy_end (void) +{ + const char *s = arr + sizeof arr; + return stpncpy (d, s, sizeof arr); // { dg-warning "-Wstringop-overread" } +} + + +void nowarn_strncpy (void) +{ + const char *s = unterm; + strncpy (d, s, unterm_size); +} + +void warn_strncpy (void) +{ + const char *s = unterm; + strncpy (d, s, unterm_size + 1); // { dg-warning "-Wstringop-overread" } +} + +void warn_strncpy_a0 (void) +{ + const char *s = a0; + strncpy (d, s, sizeof arr); // { dg-warning "-Wstringop-overread" } +} + +void warn_strncpy_end (void) +{ + const char *s = arr + sizeof arr; + strncpy (d, s, sizeof arr); // { dg-warning "-Wstringop-overread" } +} + + +int warn_strlen (void) +{ + return strlen (unterm); // { dg-warning "-Wstringop-overread" } +} + +int warn_strlen_a0 (void) +{ + return strlen (a0); // { dg-warning "-Wstringop-overread" } +} + +int warn_strlen_end (void) +{ + const char *s = arr + sizeof arr; + return strlen (s); // { dg-warning "-Wstringop-overread" } +} + +int warn_strlen_malloc0 (void) +{ + char *s = malloc (0); + sink (s); + return strlen (s); // { dg-warning "-Wstringop-overread" } +} + + +int nowarn_strnlen (void) +{ + return strnlen (unterm, unterm_size); +} + +int warn_strnlen (void) +{ + return strnlen (unterm, unterm_size + 1); // { dg-warning "-Wstringop-overread" } +} + +int warn_strnlen_end (void) +{ + const char *s = arr + sizeof arr; + return strnlen (s, 2); // { dg-warning "-Wstringop-overread" } +} + + +int warn_strcmp_1 (const char *s) +{ + return strcmp (unterm, s); // { dg-warning "-Wstringop-overread" } +} + +int warn_strcmp_2 (const char *s) +{ + return strcmp (s, unterm); // { dg-warning "-Wstringop-overread" } +} + +int warn_strcmp_2_end (const char *s) +{ + const char *t = arr + sizeof arr; + return strcmp (s, t); // { dg-warning "-Wstringop-overread" } +} + + +int nowarn_strncmp_1 (const char *s2) +{ + const char *s1 = unterm; + return strncmp (s1, s2, unterm_size); +} + +int warn_strncmp_1 (const char *s2) +{ + const char *s1 = unterm; + return strncmp (s1, s2, unterm_size + 1); // { dg-warning "-Wstringop-overread" } +} + +int nowarn_strncmp_2 (const char *s1) +{ + const char *s2 = unterm; + return strncmp (s1, s2, unterm_size); +} + +int warn_strncmp_2 (const char *s1) +{ + const char *s2 = unterm; + return strncmp (s1, s2, unterm_size + 1); // { dg-warning "-Wstringop-overread" } +} + +int warn_strncmp_2_end (const char *s1) +{ + const char *s2 = arr + sizeof arr;; + return strncmp (s1, s2, sizeof arr); // { dg-warning "-Wstringop-overread" } +} + + +int nowarn_strncmp_1_s2 (void) +{ + /* Since the read is also bounded by the length of the S2 literal + and so safe, expect no warning. */ + const char *s = unterm; + return strncmp (s, S2, unterm_size + 1); // { dg-bogus "-Wstringop-overread" "pr101778" { xfail *-*-* } } +} + +int warn_strncmp_2_s2 (void) +{ + /* Same as above. */ + const char *t = unterm; + return strncmp (S2, t, unterm_size + 1); // { dg-bogus "-Wstringop-overread" "pr101778" { xfail *-*-* } } +} + + +int warn_strncmp_1_s9 (void) +{ + /* Since both the bound and the length of the S9 literal are greater + than the size of UNNTERM the call reads past the end of the array. + Expect a warning. */ + const char *s1 = unterm; + return strncmp (s1, S9, unterm_size + 1); // { dg-warning "-Wstringop-overread" } +} + +int warn_strncmp_2_s9 (void) +{ + /* Same as above. */ + const char *s2 = unterm; + return strncmp (S9, s2, unterm_size + 1); // { dg-warning "-Wstringop-overread" } +} + + +const char* warn_strchr (int x) +{ + return strchr (unterm, x); // { dg-warning "-Wstringop-overread" } +} + +const char* warn_strchr_end (int x) +{ + const char *s = arr + sizeof arr; + return strchr (s, x); // { dg-warning "-Wstringop-overread" } +} + + +const char* warn_strrchr (int x) +{ + return strrchr (unterm, x); // { dg-warning "-Wstringop-overread" } +} + +const char* warn_strrchr_end (int x) +{ + const char *s = arr + sizeof arr; + return strrchr (s, x); // { dg-warning "-Wstringop-overread" } +} + + +char* warn_strdup (void) +{ + return strdup (unterm); // { dg-warning "-Wstringop-overread" } +} + +char* warn_strdup_end (void) +{ + const char *s = arr + sizeof arr; + return strdup (s); // { dg-warning "-Wstringop-overread" } +} + + +char* nowarn_strndup (void) +{ + return strndup (unterm, unterm_size); +} + +char* warn_strndup (void) +{ + return strndup (unterm, unterm_size + 1); // { dg-warning "-Wstringop-overread" } +} + +char* warn_strndup_end (void) +{ + const char *s = arr + sizeof arr; + return strndup (s, sizeof arr); // { dg-warning "-Wstringop-overread" } +} + + +const char* warn_strpbrk_1 (const char *s2) +{ + return strpbrk (unterm, s2); // { dg-warning "-Wstringop-overread" } +} + +const char* warn_strpbrk_2 (const char *s1) +{ + return strpbrk (s1, unterm); // { dg-warning "-Wstringop-overread" } +} + + +size_t warn_strspn_1 (const char *s2) +{ + return strspn (unterm, s2); // { dg-warning "-Wstringop-overread" } +} + +size_t warn_strspn_1_end (const char *s2) +{ + const char *s1 = arr + sizeof arr; + return strspn (s1, s2); // { dg-warning "-Wstringop-overread" } +} + +size_t warn_strspn_2 (const char *s1) +{ + return strspn (s1, unterm); // { dg-warning "-Wstringop-overread" } +} + +size_t warn_strspn_2_end (const char *s1) +{ + const char *s2 = arr + sizeof arr; + return strspn (s1, s2); // { dg-warning "-Wstringop-overread" } +} + + +size_t warn_strcspn_1 (const char *s2) +{ + return strcspn (unterm, s2); // { dg-warning "-Wstringop-overread" } +} + +size_t warn_strcspn_1_end (const char *s2) +{ + const char *s1 = arr + sizeof arr; + return strcspn (s1, s2); // { dg-warning "-Wstringop-overread" } +} + +size_t warn_strcspn_2 (const char *s1) +{ + return strcspn (s1, unterm); // { dg-warning "-Wstringop-overread" } +} + +size_t warn_strcspn_2_end (const char *s1) +{ + const char *s2 = arr + sizeof arr; + return strcspn (s1, s2); // { dg-warning "-Wstringop-overread" } +} + + +const char* warn_strstr_1 (const char *s2) +{ + return strstr (unterm, s2); // { dg-warning "-Wstringop-overread" } +} + +const char* warn_strstr_1_end (const char *s2) +{ + const char *s1 = arr + sizeof arr; + return strstr (s1, s2); // { dg-warning "-Wstringop-overread" } +} + + +const char* warn_strstr_2 (const char *s1) +{ + return strstr (s1, unterm); // { dg-warning "-Wstringop-overread" } +} + +const char* warn_strstr_2_end (const char *s1) +{ + const char *s2 = arr + sizeof arr; + return strstr (s1, s2); // { dg-warning "-Wstringop-overread" } +} + + +void warn_puts (void) +{ + puts (unterm); // { dg-warning "-Wstringop-overread" } +} + +void warn_puts_end (void) +{ + const char *s = arr + sizeof arr; + puts (s); // { dg-warning "-Wstringop-overread" } +} + + +void warn_fputs (FILE *f) +{ + fputs (unterm, f); // { dg-warning "-Wstringop-overread" } +} + +void warn_fputs_end (FILE *f) +{ + const char *s = arr + sizeof arr; + fputs (s, f); // { dg-warning "-Wstringop-overread" } +} + + +void warn_puts_unlocked (void) +{ + puts_unlocked (unterm); // { dg-warning "-Wstringop-overread" } +} + +void warn_puts_unlocked_end (void) +{ + const char *s = arr + sizeof arr; + puts_unlocked (s); // { dg-warning "-Wstringop-overread" } +} + +void warn_fputs_unlocked (FILE *f) +{ + fputs_unlocked (unterm, f); // { dg-warning "-Wstringop-overread" } +} + + +const char* warn_gettext (void) +{ + return gettext (unterm); // { dg-warning "-Wstringop-overread" } +} + +const char* warn_gettext_end (void) +{ + const char *s = arr + sizeof arr; + return gettext (s); // { dg-warning "-Wstringop-overread" } +} diff --git a/gcc/testsuite/gcc.dg/attr-nonstring-2.c b/gcc/testsuite/gcc.dg/attr-nonstring-2.c index ba4757d..44a102c 100644 --- a/gcc/testsuite/gcc.dg/attr-nonstring-2.c +++ b/gcc/testsuite/gcc.dg/attr-nonstring-2.c @@ -26,8 +26,8 @@ void test_strnlen_array_cst (void) T (strnlen (ns3, 1)); T (strnlen (ns3, 2)); T (strnlen (ns3, 3)); - T (strnlen (ns3, 4)); /* { dg-warning "specified bound 4 exceeds source size 3" } */ - T (strnlen (ns3, DIFF_MAX)); /* { dg-warning "specified bound \[0-9\]+ exceeds source size" } */ + T (strnlen (ns3, 4)); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound 4|specified bound 4 exceeds source size 3" } */ + T (strnlen (ns3, DIFF_MAX)); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound|specified bound \[0-9\]+ exceeds source size" } */ T (strnlen (ns3, SIZE_MAX)); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ NONSTRING char ns5[5]; @@ -37,8 +37,8 @@ void test_strnlen_array_cst (void) T (strnlen (ns5, 1)); T (strnlen (ns5, 2)); T (strnlen (ns5, 3)); - T (strnlen (ns5, 6)); /* { dg-warning "specified bound 6 exceeds source size 5" } */ - T (strnlen (ns5, DIFF_MAX)); /* { dg-warning "specified bound \[0-9\]+ exceeds source size 5" } */ + T (strnlen (ns5, 6)); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound 6|specified bound 6 exceeds source size 5" } */ + T (strnlen (ns5, DIFF_MAX)); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound|specified bound \[0-9\]+ exceeds source size 5" } */ T (strnlen (ns5, SIZE_MAX)); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ } @@ -52,8 +52,8 @@ void test_strnlen_array_range (void) T (strnlen (ns3, UR (0, 9))); T (strnlen (ns3, UR (3, 4))); T (strnlen (ns3, UR (3, DIFF_MAX))); - T (strnlen (ns3, UR (4, 5))); /* { dg-warning "specified bound \\\[4, 5] exceeds source size 3" } */ - T (strnlen (ns3, UR (DIFF_MAX, SIZE_MAX))); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds source size 3 " } */ + T (strnlen (ns3, UR (4, 5))); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound \\\[4, 5]|specified bound \\\[4, 5] exceeds source size 3" } */ + T (strnlen (ns3, UR (DIFF_MAX, SIZE_MAX))); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound \\\[\[0-9\]+, \[0-9\]+] |specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds source size 3 " } */ } @@ -73,8 +73,8 @@ void test_strnlen_string_cst (void) T (3, "12", 3, 1); T (3, "12", 3, 9); T (3, "123", 3, 1); - T (3, "123", 3, 4); /* { dg-warning "specified bound 4 exceeds source size 3" } */ - T (3, "123", 3, 9); /* { dg-warning "specified bound 9 exceeds source size 3" } */ + T (3, "123", 3, 4); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound 4|specified bound 4 exceeds source size 3" } */ + T (3, "123", 3, 9); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound 9|specified bound 9 exceeds source size 3" } */ T (5, "1", 2, 1); T (5, "1", 2, 2); @@ -84,7 +84,7 @@ void test_strnlen_string_cst (void) T (5, "12", 3, 9); T (5, "123", 3, 1); T (5, "123", 3, 5); - T (5, "123", 3, 6); /* { dg-warning "specified bound 6 exceeds source size 5" } */ + T (5, "123", 3, 6); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound 6|specified bound 6 exceeds source size 5" } */ /* Strnlen shouldn't trigger a warning for arrays of unknown size (except for accesses to uninitialized elements when those are @@ -110,6 +110,6 @@ void test_strnlen_string_range (void) { T (3, "1", 2, UR (0, 1)); T (3, "1", 2, UR (3, 9)); - T (3, "123", 3, UR (4, 5)); /* { dg-warning "specified bound \\\[4, 5] exceeds source size 3" } */ - T (3, "123", 3, UR (5, 9)); /* { dg-warning "specified bound \\\[5, 9] exceeds source size 3" } */ + T (3, "123", 3, UR (4, 5)); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound \\\[4, 5]|specified bound \\\[4, 5] exceeds source size 3" } */ + T (3, "123", 3, UR (5, 9)); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound \\\[5, 9]|specified bound \\\[5, 9] exceeds source size 3" } */ } diff --git a/gcc/testsuite/gcc.dg/attr-nonstring-4.c b/gcc/testsuite/gcc.dg/attr-nonstring-4.c index f2416c1..6f03a56 100644 --- a/gcc/testsuite/gcc.dg/attr-nonstring-4.c +++ b/gcc/testsuite/gcc.dg/attr-nonstring-4.c @@ -40,7 +40,7 @@ void strnlen_cst (void) T (NS, /* [] */, n); T (NS, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ - T (NS, 9, n); /* { dg-warning "specified bound \[0-9\]+ exceeds source size 9" } */ + T (NS, 9, n); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound \\d+|specified bound \\d+ exceeds source size 9" } */ T (NS, 10, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ } @@ -59,6 +59,6 @@ void strnlen_range (void) T (NS, /* [] */, n); T (NS, /* [] */, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */ - T (NS, 9, n); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds source size 9" } */ + T (NS, 9, n); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound \\\[\\d+, \\d+]|specified bound \\\[\\d+, \\d+] exceeds source size 9" } */ T (NS, 10, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */ } diff --git a/gcc/testsuite/gcc.dg/sso-14.c b/gcc/testsuite/gcc.dg/sso-14.c index 8941946..aeff3fb 100644 --- a/gcc/testsuite/gcc.dg/sso-14.c +++ b/gcc/testsuite/gcc.dg/sso-14.c @@ -46,10 +46,10 @@ int main(void) int same; msg1 = malloc (sizeof (t_s12)); - msg2 = malloc (sizeof (t_u12)); + msg2 = malloc (sizeof (t_s12)); memset (msg1, 0, sizeof (t_s12)); - memcpy (msg2, &msg1, sizeof (t_s12)); + memcpy (msg2, msg1, sizeof (t_s12)); same = memcmp (msg1, msg2, sizeof (t_s12)); return 0; diff --git a/gcc/testsuite/gcc.target/aarch64/sve/dup_lane_1.c b/gcc/testsuite/gcc.target/aarch64/sve/dup_lane_1.c index 14c1f5a..39b46da 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/dup_lane_1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/dup_lane_1.c @@ -56,27 +56,19 @@ TEST_ALL (DUP_LANE) /* { dg-final { scan-assembler-not {\ttbl\t} } } */ -/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.d, d[0-9]} 2 { - target { aarch64_little_endian } } } } */ -/* { dg-final { scan-assembler-times {\tdup\tz[0-9]+\.d, z[0-9]+\.d\[0\]} 2 { - target { aarch64_big_endian } } } } */ +/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.d, d[0-9]} 2 { target aarch64_little_endian } } } */ +/* { dg-final { scan-assembler-times {\tdup\tz[0-9]+\.d, z[0-9]+\.d\[0\]} 2 { target aarch64_big_endian } } } */ /* { dg-final { scan-assembler-times {\tdup\tz[0-9]+\.d, z[0-9]+\.d\[2\]} 2 } } */ /* { dg-final { scan-assembler-times {\tdup\tz[0-9]+\.d, z[0-9]+\.d\[3\]} 2 } } */ -/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.s, s[0-9]} 2 { - target { aarch64_little_endian } } } } */ -/* { dg-final { scan-assembler-times {\tdup\tz[0-9]+\.s, z[0-9]+\.s\[0\]} 2 { - target { aarch64_big_endian } } } } */ +/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.s, s[0-9]} 2 { target aarch64_little_endian } } } */ +/* { dg-final { scan-assembler-times {\tdup\tz[0-9]+\.s, z[0-9]+\.s\[0\]} 2 { target aarch64_big_endian } } } */ /* { dg-final { scan-assembler-times {\tdup\tz[0-9]+\.s, z[0-9]+\.s\[5\]} 2 } } */ /* { dg-final { scan-assembler-times {\tdup\tz[0-9]+\.s, z[0-9]+\.s\[7\]} 2 } } */ -/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.h, h[0-9]} 2 { - target { aarch64_little_endian } } } } */ -/* { dg-final { scan-assembler-times {\tdup\tz[0-9]+\.h, z[0-9]+\.h\[0\]} 2 { - target { aarch64_big_endian } } } } */ +/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.h, h[0-9]} 2 { target aarch64_little_endian } } } */ +/* { dg-final { scan-assembler-times {\tdup\tz[0-9]+\.h, z[0-9]+\.h\[0\]} 2 { target aarch64_big_endian } } } */ /* { dg-final { scan-assembler-times {\tdup\tz[0-9]+\.h, z[0-9]+\.h\[6\]} 2 } } */ /* { dg-final { scan-assembler-times {\tdup\tz[0-9]+\.h, z[0-9]+\.h\[15\]} 2 } } */ -/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.b, b[0-9]} 1 { - target { aarch64_little_endian } } } } */ -/* { dg-final { scan-assembler-times {\tdup\tz[0-9]+\.b, z[0-9]+\.b\[0\]} 1 { - target { aarch64_big_endian } } } } */ +/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.b, b[0-9]} 1 { target aarch64_little_endian } } } */ +/* { dg-final { scan-assembler-times {\tdup\tz[0-9]+\.b, z[0-9]+\.b\[0\]} 1 { target aarch64_big_endian } } } */ /* { dg-final { scan-assembler-times {\tdup\tz[0-9]+\.b, z[0-9]+\.b\[19\]} 1 } } */ /* { dg-final { scan-assembler-times {\tdup\tz[0-9]+\.b, z[0-9]+\.b\[31\]} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/extract_1.c b/gcc/testsuite/gcc.target/aarch64/sve/extract_1.c index 7d76c98..dbcc1d9 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/extract_1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/extract_1.c @@ -56,10 +56,8 @@ typedef _Float16 vnx8hf __attribute__((vector_size (32))); TEST_ALL (EXTRACT) -/* { dg-final { scan-assembler-times {\tfmov\tx[0-9]+, d[0-9]\n} 2 { - target { aarch64_little_endian } } } } */ -/* { dg-final { scan-assembler-times {\tumov\tx[0-9]+, v[0-9]+\.d\[0\]\n} 1 { - target { aarch64_big_endian } } } } */ +/* { dg-final { scan-assembler-times {\tfmov\tx[0-9]+, d[0-9]\n} 2 { target aarch64_little_endian } } } */ +/* { dg-final { scan-assembler-times {\tumov\tx[0-9]+, v[0-9]+\.d\[0\]\n} 1 { target aarch64_big_endian } } } */ /* { dg-final { scan-assembler-times {\tumov\tx[0-9]+, v[0-9]+\.d\[1\]\n} 1 } } */ /* { dg-final { scan-assembler-not {\tdup\td[0-9]+, v[0-9]+\.d\[0\]\n} } } */ /* { dg-final { scan-assembler-times {\tdup\td[0-9]+, v[0-9]+\.d\[1\]\n} 1 } } */ @@ -67,10 +65,8 @@ TEST_ALL (EXTRACT) /* { dg-final { scan-assembler-times {\tlastb\tx[0-9]+, p[0-7], z[0-9]+\.d\n} 1 } } */ /* { dg-final { scan-assembler-times {\tlastb\td[0-9]+, p[0-7], z[0-9]+\.d\n} 1 } } */ -/* { dg-final { scan-assembler-times {\tfmov\tx[0-9]+, s[0-9]\n} 2 { - target { aarch64_little_endian } } } } */ -/* { dg-final { scan-assembler-times {\tumov\tx[0-9]+, v[0-9]+\.s\[0\]\n} 1 { - target { aarch64_big_endian } } } } */ +/* { dg-final { scan-assembler-times {\tfmov\tw[0-9]+, s[0-9]\n} 2 { target aarch64_little_endian } } } */ +/* { dg-final { scan-assembler-times {\tumov\tw[0-9]+, v[0-9]+\.s\[0\]\n} 1 { target aarch64_big_endian } } } */ /* { dg-final { scan-assembler-times {\tumov\tw[0-9]+, v[0-9]+\.s\[1\]\n} 1 } } */ /* { dg-final { scan-assembler-times {\tumov\tw[0-9]+, v[0-9]+\.s\[3\]\n} 1 } } */ /* { dg-final { scan-assembler-not {\tdup\ts[0-9]+, v[0-9]+\.s\[0\]\n} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/extract_2.c b/gcc/testsuite/gcc.target/aarch64/sve/extract_2.c index a2644ce..a487746 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/extract_2.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/extract_2.c @@ -56,10 +56,8 @@ typedef _Float16 vnx16hf __attribute__((vector_size (64))); TEST_ALL (EXTRACT) -/* { dg-final { scan-assembler-times {\tfmov\tx[0-9]+, d[0-9]\n} 2 { - target { aarch64_little_endian } } } } */ -/* { dg-final { scan-assembler-times {\tumov\tx[0-9]+, v[0-9]+\.d\[0\]\n} 1 { - target { aarch64_big_endian } } } } */ +/* { dg-final { scan-assembler-times {\tfmov\tx[0-9]+, d[0-9]\n} 2 { target aarch64_little_endian } } } */ +/* { dg-final { scan-assembler-times {\tumov\tx[0-9]+, v[0-9]+\.d\[0\]\n} 1 { target aarch64_big_endian } } } */ /* { dg-final { scan-assembler-times {\tumov\tx[0-9]+, v[0-9]+\.d\[1\]\n} 1 } } */ /* { dg-final { scan-assembler-not {\tdup\td[0-9]+, v[0-9]+\.d\[0\]\n} } } */ /* { dg-final { scan-assembler-times {\tdup\td[0-9]+, v[0-9]+\.d\[1\]\n} 1 } } */ @@ -67,10 +65,8 @@ TEST_ALL (EXTRACT) /* { dg-final { scan-assembler-times {\tlastb\tx[0-9]+, p[0-7], z[0-9]+\.d\n} 1 } } */ /* { dg-final { scan-assembler-times {\tlastb\td[0-9]+, p[0-7], z[0-9]+\.d\n} 1 } } */ -/* { dg-final { scan-assembler-times {\tfmov\tx[0-9]+, s[0-9]\n} 2 { - target { aarch64_little_endian } } } } */ -/* { dg-final { scan-assembler-times {\tumov\tx[0-9]+, v[0-9]+\.s\[0\]\n} 1 { - target { aarch64_big_endian } } } } */ +/* { dg-final { scan-assembler-times {\tfmov\tw[0-9]+, s[0-9]\n} 2 { target aarch64_little_endian } } } */ +/* { dg-final { scan-assembler-times {\tumov\tw[0-9]+, v[0-9]+\.s\[0\]\n} 1 { target aarch64_big_endian } } } */ /* { dg-final { scan-assembler-times {\tumov\tw[0-9]+, v[0-9]+\.s\[1\]\n} 1 } } */ /* { dg-final { scan-assembler-times {\tumov\tw[0-9]+, v[0-9]+\.s\[3\]\n} 1 } } */ /* { dg-final { scan-assembler-not {\tdup\ts[0-9]+, v[0-9]+\.s\[0\]\n} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/extract_3.c b/gcc/testsuite/gcc.target/aarch64/sve/extract_3.c index baa5459..bf10bf1 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/extract_3.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/extract_3.c @@ -77,10 +77,8 @@ typedef _Float16 vnx32hf __attribute__((vector_size (128))); TEST_ALL (EXTRACT) -/* { dg-final { scan-assembler-times {\tfmov\tx[0-9]+, d[0-9]\n} 5 { - target { aarch64_little_endian } } } } */ -/* { dg-final { scan-assembler-times {\tumov\tx[0-9]+, v[0-9]+\.d\[0\]\n} 1 { - target { aarch64_big_endian } } } } */ +/* { dg-final { scan-assembler-times {\tfmov\tx[0-9]+, d[0-9]\n} 5 { target aarch64_little_endian } } } */ +/* { dg-final { scan-assembler-times {\tumov\tx[0-9]+, v[0-9]+\.d\[0\]\n} 1 { target aarch64_big_endian } } } */ /* { dg-final { scan-assembler-times {\tumov\tx[0-9]+, v[0-9]+\.d\[1\]\n} 1 } } */ /* { dg-final { scan-assembler-not {\tdup\td[0-9]+, v[0-9]+\.d\[0\]\n} } } */ /* { dg-final { scan-assembler-times {\tdup\td[0-9]+, v[0-9]+\.d\[1\]\n} 1 } } */ @@ -89,10 +87,8 @@ TEST_ALL (EXTRACT) /* { dg-final { scan-assembler-times {\tlastb\tx[0-9]+, p[0-7], z[0-9]+\.d\n} 1 } } */ /* { dg-final { scan-assembler-times {\tlastb\td[0-9]+, p[0-7], z[0-9]+\.d\n} 1 } } */ -/* { dg-final { scan-assembler-times {\tfmov\tx[0-9]+, s[0-9]\n} 5 { - target { aarch64_little_endian } } } } */ -/* { dg-final { scan-assembler-times {\tumov\tx[0-9]+, v[0-9]+\.s\[0\]\n} 1 { - target { aarch64_big_endian } } } } */ +/* { dg-final { scan-assembler-times {\tfmov\tw[0-9]+, s[0-9]\n} 5 { target aarch64_little_endian } } } */ +/* { dg-final { scan-assembler-times {\tumov\tw[0-9]+, v[0-9]+\.s\[0\]\n} 1 { target aarch64_big_endian } } } */ /* { dg-final { scan-assembler-times {\tumov\tw[0-9]+, v[0-9]+\.s\[1\]\n} 1 } } */ /* { dg-final { scan-assembler-times {\tumov\tw[0-9]+, v[0-9]+\.s\[3\]\n} 1 } } */ /* { dg-final { scan-assembler-not {\tdup\ts[0-9]+, v[0-9]+\.s\[0\]\n} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/extract_4.c b/gcc/testsuite/gcc.target/aarch64/sve/extract_4.c index aa6fe48..9805678 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/extract_4.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/extract_4.c @@ -84,10 +84,8 @@ typedef _Float16 v128hf __attribute__((vector_size (256))); TEST_ALL (EXTRACT) -/* { dg-final { scan-assembler-times {\tfmov\tx[0-9]+, d[0-9]\n} 6 { - target { aarch64_little_endian } } } } */ -/* { dg-final { scan-assembler-times {\tumov\tx[0-9]+, v[0-9]+\.d\[0\]\n} 1 { - target { aarch64_big_endian } } } } */ +/* { dg-final { scan-assembler-times {\tfmov\tx[0-9]+, d[0-9]\n} 6 { target aarch64_little_endian } } } */ +/* { dg-final { scan-assembler-times {\tumov\tx[0-9]+, v[0-9]+\.d\[0\]\n} 1 { target aarch64_big_endian } } } */ /* { dg-final { scan-assembler-times {\tumov\tx[0-9]+, v[0-9]+\.d\[1\]\n} 1 } } */ /* { dg-final { scan-assembler-not {\tdup\td[0-9]+, v[0-9]+\.d\[0\]\n} } } */ /* { dg-final { scan-assembler-times {\tdup\td[0-9]+, v[0-9]+\.d\[1\]\n} 1 } } */ @@ -96,10 +94,8 @@ TEST_ALL (EXTRACT) /* { dg-final { scan-assembler-times {\tlastb\tx[0-9]+, p[0-7], z[0-9]+\.d\n} 1 } } */ /* { dg-final { scan-assembler-times {\tlastb\td[0-9]+, p[0-7], z[0-9]+\.d\n} 1 } } */ -/* { dg-final { scan-assembler-times {\tfmov\tx[0-9]+, s[0-9]\n} 6 { - target { aarch64_little_endian } } } } */ -/* { dg-final { scan-assembler-times {\tumov\tx[0-9]+, v[0-9]+\.s\[0\]\n} 1 { - target { aarch64_big_endian } } } } */ +/* { dg-final { scan-assembler-times {\tfmov\tw[0-9]+, s[0-9]\n} 6 { target aarch64_little_endian } } } */ +/* { dg-final { scan-assembler-times {\tumov\tw[0-9]+, v[0-9]+\.s\[0\]\n} 1 { target aarch64_big_endian } } } */ /* { dg-final { scan-assembler-times {\tumov\tw[0-9]+, v[0-9]+\.s\[1\]\n} 1 } } */ /* { dg-final { scan-assembler-times {\tumov\tw[0-9]+, v[0-9]+\.s\[3\]\n} 1 } } */ /* { dg-final { scan-assembler-not {\tdup\ts[0-9]+, v[0-9]+\.s\[0\]\n} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/vector_structure_intrinsics.c b/gcc/testsuite/gcc.target/aarch64/vector_structure_intrinsics.c index 3e7e572..89e9de1 100644 --- a/gcc/testsuite/gcc.target/aarch64/vector_structure_intrinsics.c +++ b/gcc/testsuite/gcc.target/aarch64/vector_structure_intrinsics.c @@ -263,7 +263,7 @@ TEST_ST1x3 (vst1q, uint64x2x3_t, uint64_t*, u64, x3); TEST_ST1x3 (vst1q, poly64x2x3_t, poly64_t*, p64, x3); TEST_ST1x3 (vst1q, float64x2x3_t, float64_t*, f64, x3); -/* { dg-final { scan-assembler-not "mov\\t" } } */ +/* { dg-final { scan-assembler-not "mov\\t" { target aarch64_little_endian } } } */ /* { dg-final { scan-assembler-times "tbl\\t" 18} } */ /* { dg-final { scan-assembler-times "tbx\\t" 18} } */ diff --git a/gcc/testsuite/gcc.target/arm/attr-neon3.c b/gcc/testsuite/gcc.target/arm/attr-neon3.c index 0fbce6e..b6171e7 100644 --- a/gcc/testsuite/gcc.target/arm/attr-neon3.c +++ b/gcc/testsuite/gcc.target/arm/attr-neon3.c @@ -33,7 +33,7 @@ my (float32x2_t __a, float32x2_t __b) ** | ** vld1.64 {d[0-9]+}, \[r[0-9]+:64\]! ** vld1.64 {d[0-9]+}, \[r[0-9]+:64\] -** } +** ) ** ... ** bx lr */ diff --git a/gcc/testsuite/gcc.target/arm/pr69245.c b/gcc/testsuite/gcc.target/arm/pr69245.c index 34b97a2..58a6104 100644 --- a/gcc/testsuite/gcc.target/arm/pr69245.c +++ b/gcc/testsuite/gcc.target/arm/pr69245.c @@ -12,7 +12,7 @@ #pragma GCC target "fpu=neon-vfpv4" int a, c, d; float b; -static int fn1 () + int fn1 () { return 0; } @@ -26,5 +26,5 @@ void fn2 () /* Because we don't know the exact command-line options used to invoke the test we cannot expect these tests to match exactly once. But they must appear at least once. */ -/* { dg-final { scan-assembler "\.fpu\s+vfp\n" } } */ -/* { dg-final { scan-assembler "\.fpu\s+neon-vfpv4\n" } } */ +/* { dg-final { scan-assembler "\.fpu\\s+vfp\n" } } */ +/* { dg-final { scan-assembler "\.fpu\\s+neon-vfpv4\n" } } */ diff --git a/gcc/testsuite/gcc.target/arm/pragma_fpu_attribute_2.c b/gcc/testsuite/gcc.target/arm/pragma_fpu_attribute_2.c index 3d33b04..398d8ff 100644 --- a/gcc/testsuite/gcc.target/arm/pragma_fpu_attribute_2.c +++ b/gcc/testsuite/gcc.target/arm/pragma_fpu_attribute_2.c @@ -28,5 +28,5 @@ uint32_t restored () /* We can't tell exactly how many times the following tests will match because command-line options may cause additional instances to be generated, but each must be present at least once. */ -/* { dg-final { scan-assembler-times {\.fpu\s+vfpv4\n} } } */ -/* { dg-final { scan-assembler-times {\.fpu\s+vfpv3-d16\n} } } */ +/* { dg-final { scan-assembler {\.fpu\s+vfpv4\n} } } */ +/* { dg-final { scan-assembler {\.fpu\s+vfpv3-d16\n} } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr101797.c b/gcc/testsuite/gcc.target/i386/pr101797.c new file mode 100644 index 0000000..d5cc34e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr101797.c @@ -0,0 +1,15 @@ +/* PR target/101797 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int a; +int main() { + int b, c, d, e = 0; + if (a) { + c += a; + e = ~(a % c); + e || c || (b & d); + } + a = e; + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/pr88531-1a.c b/gcc/testsuite/gcc.target/i386/pr88531-1a.c new file mode 100644 index 0000000..d1c29b2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr88531-1a.c @@ -0,0 +1,19 @@ +/* { dg-do compile { target lp64 } } */ +/* { dg-options "-O3 -march=x86-64 -mfpmath=sse" } */ + +#include <stdint.h> + +#define loop_t uint32_t +#define idx_t uint32_t + +void loop(double * const __restrict__ dst, + double const * const __restrict__ src, + idx_t const * const __restrict__ idx, + loop_t const begin, + loop_t const end) +{ + for (loop_t i = begin; i < end; ++i) + dst[i] = 42.0 * src[idx[i]]; +} + +/* { dg-final { scan-assembler-times "mulpd" 2 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr88531-1b.c b/gcc/testsuite/gcc.target/i386/pr88531-1b.c new file mode 100644 index 0000000..812c8a1 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr88531-1b.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=skylake -mfpmath=sse" } */ + +#include "pr88531-1a.c" + +/* { dg-final { scan-assembler-times "vgatherdpd" 4 { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler-times "vgatherqpd" 4 { target lp64 } } } */ +/* { dg-final { scan-assembler-times "vmulpd" 4 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr88531-1c.c b/gcc/testsuite/gcc.target/i386/pr88531-1c.c new file mode 100644 index 0000000..43fc591 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr88531-1c.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=skylake-avx512 -mfpmath=sse" } */ + +#include "pr88531-1a.c" + +/* { dg-final { scan-assembler-times "vgatherdpd" 4 { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler-times "vgatherqpd" 4 { target lp64 } } } */ +/* { dg-final { scan-assembler-times "vmulpd" 4 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr88531-2a.c b/gcc/testsuite/gcc.target/i386/pr88531-2a.c new file mode 100644 index 0000000..8ab2b13 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr88531-2a.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=x86-64 -mfpmath=sse" } */ + +#include <stdint.h> + +#define loop_t uint32_t +#define idx_t uint32_t + +void loop(float * const __restrict__ dst, + float const * const __restrict__ src, + idx_t const * const __restrict__ idx, + loop_t const begin, + loop_t const end) +{ + for (loop_t i = begin; i < end; ++i) + dst[i] = 42.0 * src[idx[i]]; +} + +/* { dg-final { scan-assembler-times "mulps" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr88531-2b.c b/gcc/testsuite/gcc.target/i386/pr88531-2b.c new file mode 100644 index 0000000..011607c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr88531-2b.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=skylake -mfpmath=sse" } */ + +#include "pr88531-2a.c" + +/* { dg-final { scan-assembler-times "vmulps" 2 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr88531-2c.c b/gcc/testsuite/gcc.target/i386/pr88531-2c.c new file mode 100644 index 0000000..0f7ec38 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr88531-2c.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=skylake-avx512 -mfpmath=sse" } */ + +#include "pr88531-2a.c" + +/* { dg-final { scan-assembler-times "vmulps" 2 } } */ diff --git a/gcc/testsuite/gcc.target/tic6x/rotdi16-scan.c b/gcc/testsuite/gcc.target/tic6x/rotdi16-scan.c index 4d7816c..5504183 100644 --- a/gcc/testsuite/gcc.target/tic6x/rotdi16-scan.c +++ b/gcc/testsuite/gcc.target/tic6x/rotdi16-scan.c @@ -7,10 +7,14 @@ unsigned long long z = 0x012389ab4567cdefull; +unsigned long long __attribute__ ((noinline,noclone,noipa)) bar () +{ + return (z << 48) | (z >> 16); +} + int main () { - unsigned long long z2 = (z << 48) | (z >> 16); - if (z2 != 0xcdef012389ab4567ull) + if (bar() != 0xcdef012389ab4567ull) abort (); exit (0); } diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c index 66af902..0e339c4 100644 --- a/gcc/tree-ssa-phiopt.c +++ b/gcc/tree-ssa-phiopt.c @@ -2583,13 +2583,13 @@ cond_removal_in_builtin_zero_pattern (basic_block cond_bb, } } return false; - case BUILT_IN_CLRSB: + case CFN_BUILT_IN_CLRSB: val = TYPE_PRECISION (integer_type_node) - 1; break; - case BUILT_IN_CLRSBL: + case CFN_BUILT_IN_CLRSBL: val = TYPE_PRECISION (long_integer_type_node) - 1; break; - case BUILT_IN_CLRSBLL: + case CFN_BUILT_IN_CLRSBLL: val = TYPE_PRECISION (long_long_integer_type_node) - 1; break; default: diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index 1e21fe6..37c7daa 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -7227,24 +7227,13 @@ vectorizable_reduction (loop_vec_info loop_vinfo, if (dump_enabled_p ()) dump_printf (MSG_NOTE, "op not supported by target.\n"); if (maybe_ne (GET_MODE_SIZE (vec_mode), UNITS_PER_WORD) - || !vect_worthwhile_without_simd_p (loop_vinfo, code)) + || !vect_can_vectorize_without_simd_p (code)) ok = false; else if (dump_enabled_p ()) dump_printf (MSG_NOTE, "proceeding using word mode.\n"); } - /* Worthwhile without SIMD support? */ - if (ok - && !VECTOR_MODE_P (TYPE_MODE (vectype_in)) - && !vect_worthwhile_without_simd_p (loop_vinfo, code)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "not worthwhile without SIMD support.\n"); - ok = false; - } - /* lane-reducing operations have to go through vect_transform_reduction. For the other cases try without the single cycle optimization. */ if (!ok) @@ -7948,46 +7937,28 @@ vectorizable_phi (vec_info *, } -/* Function vect_min_worthwhile_factor. +/* Return true if we can emulate CODE on an integer mode representation + of a vector. */ - For a loop where we could vectorize the operation indicated by CODE, - return the minimum vectorization factor that makes it worthwhile - to use generic vectors. */ -static unsigned int -vect_min_worthwhile_factor (enum tree_code code) +bool +vect_can_vectorize_without_simd_p (tree_code code) { switch (code) { case PLUS_EXPR: case MINUS_EXPR: case NEGATE_EXPR: - return 4; - case BIT_AND_EXPR: case BIT_IOR_EXPR: case BIT_XOR_EXPR: case BIT_NOT_EXPR: - return 2; + return true; default: - return INT_MAX; + return false; } } -/* Return true if VINFO indicates we are doing loop vectorization and if - it is worth decomposing CODE operations into scalar operations for - that loop's vectorization factor. */ - -bool -vect_worthwhile_without_simd_p (vec_info *vinfo, tree_code code) -{ - loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo); - unsigned HOST_WIDE_INT value; - return (loop_vinfo - && LOOP_VINFO_VECT_FACTOR (loop_vinfo).is_constant (&value) - && value >= vect_min_worthwhile_factor (code)); -} - /* Function vectorizable_induction Check if STMT_INFO performs an induction computation that can be vectorized. diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index 94bdb74..5b94d41 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -5685,24 +5685,13 @@ vectorizable_shift (vec_info *vinfo, /* Check only during analysis. */ if (maybe_ne (GET_MODE_SIZE (vec_mode), UNITS_PER_WORD) || (!vec_stmt - && !vect_worthwhile_without_simd_p (vinfo, code))) + && !vect_can_vectorize_without_simd_p (code))) return false; if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "proceeding using word mode.\n"); } - /* Worthwhile without SIMD support? Check only during analysis. */ - if (!vec_stmt - && !VECTOR_MODE_P (TYPE_MODE (vectype)) - && !vect_worthwhile_without_simd_p (vinfo, code)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "not worthwhile without SIMD support.\n"); - return false; - } - if (!vec_stmt) /* transformation not required. */ { if (slp_node @@ -6094,24 +6083,13 @@ vectorizable_operation (vec_info *vinfo, "op not supported by target.\n"); /* Check only during analysis. */ if (maybe_ne (GET_MODE_SIZE (vec_mode), UNITS_PER_WORD) - || (!vec_stmt && !vect_worthwhile_without_simd_p (vinfo, code))) + || (!vec_stmt && !vect_can_vectorize_without_simd_p (code))) return false; if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "proceeding using word mode.\n"); } - /* Worthwhile without SIMD support? Check only during analysis. */ - if (!VECTOR_MODE_P (vec_mode) - && !vec_stmt - && !vect_worthwhile_without_simd_p (vinfo, code)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "not worthwhile without SIMD support.\n"); - return false; - } - int reduc_idx = STMT_VINFO_REDUC_IDX (stmt_info); vec_loop_masks *masks = (loop_vinfo ? &LOOP_VINFO_MASKS (loop_vinfo) : NULL); internal_fn cond_fn = get_conditional_internal_fn (code); diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 5571b3c..de0ecf8 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -2061,7 +2061,7 @@ extern bool vectorizable_lc_phi (loop_vec_info, stmt_vec_info, gimple **, slp_tree); extern bool vectorizable_phi (vec_info *, stmt_vec_info, gimple **, slp_tree, stmt_vector_for_cost *); -extern bool vect_worthwhile_without_simd_p (vec_info *, tree_code); +extern bool vect_can_vectorize_without_simd_p (tree_code); extern int vect_get_known_peeling_cost (loop_vec_info, int, int *, stmt_vector_for_cost *, stmt_vector_for_cost *, diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index de145fa..cd7394a 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,30 @@ +2021-08-06 Sebastian Huber <sebastian.huber@embedded-brains.de> + + * libgcov-driver.c (#include <stdint.h>): Remove. + (write_topn_counters): Use __INTPTR_TYPE__ instead of intptr_t. + +2021-08-06 Sebastian Huber <sebastian.huber@embedded-brains.de> + + * Makefile.in (LIBGCOV_DRIVER): Add _gcov_info_to_gcda. + * gcov.h (gcov_info): Declare. + (__gcov_info_to_gdca): Likewise. + * libgcov.h (gcov_write_counter): Remove. + (gcov_write_tag_length): Likewise. + * libgcov-driver.c (#include <stdint.h>): New. + (#include <string.h>): Remove. + (NEED_L_GCOV): Conditionally define. + (NEED_L_GCOV_INFO_TO_GCDA): Likewise. + (are_all_counters_zero): New. + (gcov_dump_handler): Likewise. + (gcov_allocate_handler): Likewise. + (dump_unsigned): Likewise. + (dump_counter): Likewise. + (write_topn_counters): Add dump_fn, allocate_fn, and arg parameters. + Use dump_unsigned() and dump_counter(). + (write_one_data): Add dump_fn, allocate_fn, and arg parameters. Use + dump_unsigned(), dump_counter(), and are_all_counters_zero(). + (__gcov_info_to_gcda): New. + 2021-08-05 Jakub Jelinek <jakub@redhat.com> * config/t-slibgcc (SHLIB_LINK): Add $(LDFLAGS). diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index be5daf0..70fb007 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,28 @@ +2021-08-08 François Dumont <fdumont@gcc.gnu.org> + + * testsuite/25_algorithms/copy/debug/constexpr_neg.cc: Replace 'failed_assertion' + dg-prune-output reason with 'builtin_unreachable'. + * testsuite/25_algorithms/copy_backward/debug/constexpr_neg.cc: Likewise. + * testsuite/25_algorithms/equal/debug/constexpr_neg.cc: Likewise. + * testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_neg.cc: Likewise. + * testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_pred_neg.cc: Likewise. + * testsuite/25_algorithms/lower_bound/debug/constexpr_valid_range_neg.cc: Likewise. + * testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_neg.cc: Likewise. + * testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_pred_neg.cc: Likewise. + * testsuite/25_algorithms/upper_bound/debug/constexpr_valid_range_neg.cc: Likewise. + +2021-08-08 Hans-Peter Nilsson <hp@bitrange.com> + + * testsuite/std/ranges/iota/max_size_type.cc: Set + dg-timeout-factor to 4. + +2021-08-06 Jonathan Wakely <jwakely@redhat.com> + + * libsupc++/compare (compare_three_way, strong_order) + (weak_order, partial_order, compare_strong_order_fallback) + (compare_weak_order_fallback, compare_partial_order_fallback): + Move nodiscard attributes to correct location. + 2021-08-05 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/101782 diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare index faeff64..5aee89e 100644 --- a/libstdc++-v3/libsupc++/compare +++ b/libstdc++-v3/libsupc++/compare @@ -548,9 +548,8 @@ namespace std template<typename _Tp, typename _Up> requires three_way_comparable_with<_Tp, _Up> constexpr auto - operator()(_Tp&& __t, _Up&& __u) const + operator() [[nodiscard]] (_Tp&& __t, _Up&& __u) const noexcept(noexcept(std::declval<_Tp>() <=> std::declval<_Up>())) - [[nodiscard]] { if constexpr (__detail::__3way_builtin_ptr_cmp<_Tp, _Up>) { @@ -672,9 +671,8 @@ namespace std template<typename _Tp, __decayed_same_as<_Tp> _Up> requires __strongly_ordered<_Tp, _Up> constexpr strong_ordering - operator()(_Tp&& __e, _Up&& __f) const + operator() [[nodiscard]] (_Tp&& __e, _Up&& __f) const noexcept(_S_noexcept<_Tp, _Up>()) - [[nodiscard]] { /* FIXME: if constexpr (floating_point<decay_t<_Tp>>) @@ -720,9 +718,8 @@ namespace std template<typename _Tp, __decayed_same_as<_Tp> _Up> requires __weakly_ordered<_Tp, _Up> constexpr weak_ordering - operator()(_Tp&& __e, _Up&& __f) const + operator() [[nodiscard]] (_Tp&& __e, _Up&& __f) const noexcept(_S_noexcept<_Tp, _Up>()) - [[nodiscard]] { if constexpr (floating_point<decay_t<_Tp>>) return __cmp_cust::__fp_weak_ordering(__e, __f); @@ -766,9 +763,8 @@ namespace std template<typename _Tp, __decayed_same_as<_Tp> _Up> requires __partially_ordered<_Tp, _Up> constexpr partial_ordering - operator()(_Tp&& __e, _Up&& __f) const + operator() [[nodiscard]] (_Tp&& __e, _Up&& __f) const noexcept(_S_noexcept<_Tp, _Up>()) - [[nodiscard]] { if constexpr (__adl_partial<_Tp, _Up>) return partial_ordering(partial_order(static_cast<_Tp&&>(__e), @@ -808,9 +804,8 @@ namespace std template<typename _Tp, __decayed_same_as<_Tp> _Up> requires __strongly_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up> constexpr strong_ordering - operator()(_Tp&& __e, _Up&& __f) const + operator() [[nodiscard]] (_Tp&& __e, _Up&& __f) const noexcept(_S_noexcept<_Tp, _Up>()) - [[nodiscard]] { if constexpr (__strongly_ordered<_Tp, _Up>) return _Strong_order{}(static_cast<_Tp&&>(__e), @@ -841,9 +836,8 @@ namespace std template<typename _Tp, __decayed_same_as<_Tp> _Up> requires __weakly_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up> constexpr weak_ordering - operator()(_Tp&& __e, _Up&& __f) const + operator() [[nodiscard]] (_Tp&& __e, _Up&& __f) const noexcept(_S_noexcept<_Tp, _Up>()) - [[nodiscard]] { if constexpr (__weakly_ordered<_Tp, _Up>) return _Weak_order{}(static_cast<_Tp&&>(__e), @@ -884,9 +878,8 @@ namespace std template<typename _Tp, __decayed_same_as<_Tp> _Up> requires __partially_ordered<_Tp, _Up> || __op_eq_lt_lt<_Tp, _Up> constexpr partial_ordering - operator()(_Tp&& __e, _Up&& __f) const + operator() [[nodiscard]] (_Tp&& __e, _Up&& __f) const noexcept(_S_noexcept<_Tp, _Up>()) - [[nodiscard]] { if constexpr (__partially_ordered<_Tp, _Up>) return _Partial_order{}(static_cast<_Tp&&>(__e), diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/debug/constexpr_neg.cc b/libstdc++-v3/testsuite/25_algorithms/copy/debug/constexpr_neg.cc index d8d2091..4f32403 100644 --- a/libstdc++-v3/testsuite/25_algorithms/copy/debug/constexpr_neg.cc +++ b/libstdc++-v3/testsuite/25_algorithms/copy/debug/constexpr_neg.cc @@ -49,5 +49,5 @@ test2() static_assert(test2()); // { dg-error "is outside the bounds" } // { dg-prune-output "in 'constexpr' expansion" } -// { dg-prune-output "failed_assertion" } +// { dg-prune-output "builtin_unreachable" } // { dg-prune-output "non-constant condition" } diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_backward/debug/constexpr_neg.cc b/libstdc++-v3/testsuite/25_algorithms/copy_backward/debug/constexpr_neg.cc index 8433a8f..05183cf 100644 --- a/libstdc++-v3/testsuite/25_algorithms/copy_backward/debug/constexpr_neg.cc +++ b/libstdc++-v3/testsuite/25_algorithms/copy_backward/debug/constexpr_neg.cc @@ -37,4 +37,4 @@ test() static_assert(test()); // { dg-error "non-constant condition" } // { dg-prune-output "in 'constexpr' expansion" } -// { dg-prune-output "failed_assertion" } +// { dg-prune-output "builtin_unreachable" } diff --git a/libstdc++-v3/testsuite/25_algorithms/equal/debug/constexpr_neg.cc b/libstdc++-v3/testsuite/25_algorithms/equal/debug/constexpr_neg.cc index 3716212..44f9fb9 100644 --- a/libstdc++-v3/testsuite/25_algorithms/equal/debug/constexpr_neg.cc +++ b/libstdc++-v3/testsuite/25_algorithms/equal/debug/constexpr_neg.cc @@ -48,4 +48,4 @@ static_assert(test02()); // { dg-error "outside the bounds" } // { dg-prune-output "non-constant condition" } // { dg-prune-output "in 'constexpr'" } -// { dg-prune-output "failed_assertion" } +// { dg-prune-output "builtin_unreachable" } diff --git a/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_neg.cc b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_neg.cc index 3536e64..56d80d6 100644 --- a/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_neg.cc +++ b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_neg.cc @@ -44,5 +44,5 @@ test() static_assert(test()); // { dg-error "" } -// { dg-prune-output "failed_assertion" } +// { dg-prune-output "builtin_unreachable" } // { dg-prune-output "in 'constexpr'" } diff --git a/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_pred_neg.cc b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_pred_neg.cc index ecda3f5..ab931bb 100644 --- a/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_pred_neg.cc +++ b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_pred_neg.cc @@ -34,5 +34,5 @@ test() static_assert(test()); // { dg-error "" } -// { dg-prune-output "failed_assertion" } +// { dg-prune-output "builtin_unreachable" } // { dg-prune-output "in 'constexpr'" } diff --git a/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_valid_range_neg.cc b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_valid_range_neg.cc index e719543..fee67e5 100644 --- a/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_valid_range_neg.cc +++ b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_valid_range_neg.cc @@ -47,6 +47,6 @@ test2() static_assert(test2()); // { dg-error "" } -// { dg-prune-output "failed_assertion" } +// { dg-prune-output "builtin_unreachable" } // { dg-prune-output "in 'constexpr'" } diff --git a/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_neg.cc b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_neg.cc index 04d6f73..7937ac8 100644 --- a/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_neg.cc +++ b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_neg.cc @@ -44,5 +44,5 @@ test() static_assert(test()); // { dg-error "" } -// { dg-prune-output "failed_assertion" } +// { dg-prune-output "builtin_unreachable" } // { dg-prune-output "in 'constexpr'" } diff --git a/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_pred_neg.cc b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_pred_neg.cc index 7d2ef73..7d33eb5 100644 --- a/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_pred_neg.cc +++ b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_pred_neg.cc @@ -34,5 +34,5 @@ test() static_assert(test()); // { dg-error "" } -// { dg-prune-output "failed_assertion" } +// { dg-prune-output "builtin_unreachable" } // { dg-prune-output "in 'constexpr'" } diff --git a/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_valid_range_neg.cc b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_valid_range_neg.cc index 33a09b7..9c2d065 100644 --- a/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_valid_range_neg.cc +++ b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_valid_range_neg.cc @@ -47,5 +47,5 @@ test2() static_assert(test2()); // { dg-error "" } -// { dg-prune-output "failed_assertion" } +// { dg-prune-output "builtin_unreachable" } // { dg-prune-output "in 'constexpr'" } diff --git a/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc b/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc index 983bdfb..a52e8e6 100644 --- a/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc +++ b/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc @@ -17,6 +17,7 @@ // { dg-options "-std=gnu++2a" } // { dg-do run { target c++2a } } +// { dg-timeout-factor 4 } #include <limits> #include <ranges> |