From 2efe245bb88bf4574e322ef7e6d2df83d9e13237 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 13 May 2021 16:05:50 -0600 Subject: Avoid -Wuninitialized false negatives with sanitization and VLAs. Resolves: PR tree-optimization/93100 - gcc -fsanitize=address inhibits -Wuninitialized PR middle-end/98583 - missing -Wuninitialized reading from a second VLA in its own block gcc/ChangeLog: PR tree-optimization/93100 PR middle-end/98583 * tree-ssa-uninit.c (check_defs): Exclude intrinsic functions that don't modify referenced objects. gcc/testsuite/ChangeLog: PR tree-optimization/93100 PR middle-end/98583 * g++.dg/warn/uninit-pr93100.C: New test. * gcc.dg/uninit-pr93100.c: New test. * gcc.dg/uninit-pr98583.c: New test. --- gcc/tree-ssa-uninit.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'gcc/tree-ssa-uninit.c') diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index 0800f59..f55ce19 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -209,6 +209,16 @@ check_defs (ao_ref *ref, tree vdef, void *data_) { check_defs_data *data = (check_defs_data *)data_; gimple *def_stmt = SSA_NAME_DEF_STMT (vdef); + + /* The ASAN_MARK intrinsic doesn't modify the variable. */ + if (is_gimple_call (def_stmt) + && gimple_call_internal_p (def_stmt, IFN_ASAN_MARK)) + return false; + + /* End of VLA scope is not a kill. */ + if (gimple_call_builtin_p (def_stmt, BUILT_IN_STACK_RESTORE)) + return false; + /* If this is a clobber then if it is not a kill walk past it. */ if (gimple_clobber_p (def_stmt)) { @@ -216,6 +226,7 @@ check_defs (ao_ref *ref, tree vdef, void *data_) return true; return false; } + /* Found a may-def on this path. */ data->found_may_defs = true; return true; -- cgit v1.1 From 45f4e2b01b82c72b3a11ff4ad184d7edcf0e63d4 Mon Sep 17 00:00:00 2001 From: Aldy Hernandez Date: Wed, 19 May 2021 18:44:08 +0200 Subject: Convert remaining passes to get_range_query. This patch converts the remaining users of get_range_info and get_ptr_nonnull to the get_range_query API. No effort was made to move passes away from VR_ANTI_RANGE, or any other use of deprecated methods. This was a straight up conversion to the new API, nothing else. gcc/ChangeLog: * builtins.c (check_nul_terminated_array): Convert to get_range_query. (expand_builtin_strnlen): Same. (determine_block_size): Same. * fold-const.c (expr_not_equal_to): Same. * gimple-fold.c (size_must_be_zero_p): Same. * gimple-match-head.c: Include gimple-range.h. * gimple-pretty-print.c (dump_ssaname_info): Convert to get_range_query. * gimple-ssa-warn-restrict.c (builtin_memref::extend_offset_range): Same. * graphite-sese-to-poly.c (add_param_constraints): Same. * internal-fn.c (get_min_precision): Same. * ipa-fnsummary.c (set_switch_stmt_execution_predicate): Same. * ipa-prop.c (ipa_compute_jump_functions_for_edge): Same. * match.pd: Same. * tree-data-ref.c (split_constant_offset): Same. (dr_step_indicator): Same. * tree-dfa.c (get_ref_base_and_extent): Same. * tree-scalar-evolution.c (iv_can_overflow_p): Same. * tree-ssa-loop-niter.c (refine_value_range_using_guard): Same. (determine_value_range): Same. (record_nonwrapping_iv): Same. (infer_loop_bounds_from_signedness): Same. (scev_var_range_cant_overflow): Same. * tree-ssa-phiopt.c (two_value_replacement): Same. * tree-ssa-pre.c (insert_into_preds_of_block): Same. * tree-ssa-reassoc.c (optimize_range_tests_to_bit_test): Same. * tree-ssa-strlen.c (handle_builtin_stxncpy_strncat): Same. (get_range): Same. (dump_strlen_info): Same. (set_strlen_range): Same. (maybe_diag_stxncpy_trunc): Same. (get_len_or_size): Same. (handle_integral_assign): Same. * tree-ssa-structalias.c (find_what_p_points_to): Same. * tree-ssa-uninit.c (find_var_cmp_const): Same. * tree-switch-conversion.c (bit_test_cluster::emit): Same. * tree-vect-patterns.c (vect_get_range_info): Same. (vect_recog_divmod_pattern): Same. * tree-vrp.c (intersect_range_with_nonzero_bits): Same. (register_edge_assert_for_2): Same. (determine_value_range_1): Same. * tree.c (get_range_pos_neg): Same. * vr-values.c (vr_values::get_lattice_entry): Same. (vr_values::update_value_range): Same. (simplify_conversion_using_ranges): Same. --- gcc/tree-ssa-uninit.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'gcc/tree-ssa-uninit.c') diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index f55ce19..dcfdec9 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see #include "attribs.h" #include "builtins.h" #include "calls.h" +#include "gimple-range.h" /* This implements the pass that does predicate aware warning on uses of possibly uninitialized variables. The pass first collects the set of @@ -1606,11 +1607,14 @@ find_var_cmp_const (pred_chain_union preds, gphi *phi, gimple **flag_def, flag_var <= [min, max] -> flag_var < [min, max+1] flag_var >= [min, max] -> flag_var > [min-1, max] if no overflow/wrap. */ - wide_int min, max; tree type = TREE_TYPE (cond_lhs); + value_range r; if (!INTEGRAL_TYPE_P (type) - || get_range_info (cond_rhs, &min, &max) != VR_RANGE) + || !get_range_query (cfun)->range_of_expr (r, cond_rhs) + || r.kind () != VR_RANGE) continue; + wide_int min = r.lower_bound (); + wide_int max = r.upper_bound (); if (code == LE_EXPR && max != wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type))) { -- cgit v1.1 From 9816f509db4966fcb90ed3baab72cc6cd901f06c Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Fri, 4 Jun 2021 10:49:06 -0600 Subject: PR middle-end/100732 - ICE on sprintf %s with integer argument gcc/ChangeLog: PR middle-end/100732 * gimple-fold.c (gimple_fold_builtin_sprintf): Avoid folding calls with either source or destination argument of invalid type. * tree-ssa-uninit.c (maybe_warn_pass_by_reference): Avoid checking calls with arguments of invalid type. gcc/testsuite/ChangeLog: PR middle-end/100732 * gcc.dg/tree-ssa/builtin-snprintf-11.c: New test. * gcc.dg/tree-ssa/builtin-snprintf-12.c: New test. * gcc.dg/tree-ssa/builtin-sprintf-28.c: New test. * gcc.dg/tree-ssa/builtin-sprintf-29.c: New test. * gcc.dg/uninit-pr100732.c: New test. --- gcc/tree-ssa-uninit.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'gcc/tree-ssa-uninit.c') diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index dcfdec9..7c002f8 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -541,6 +541,9 @@ maybe_warn_pass_by_reference (gcall *stmt, wlimits &wlims) continue; tree arg = gimple_call_arg (stmt, argno - 1); + if (!POINTER_TYPE_P (TREE_TYPE (arg))) + /* Avoid actual arguments with invalid types. */ + continue; ao_ref ref; ao_ref_init_from_ptr_and_size (&ref, arg, access_size); -- cgit v1.1 From e9e2bad7251477db92ab9ebcdc010f9282dd9890 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 24 Jun 2021 19:22:06 -0600 Subject: middle-end: add support for per-location warning groups. gcc/ChangeLog: * builtins.c (warn_string_no_nul): Replace uses of TREE_NO_WARNING, gimple_no_warning_p and gimple_set_no_warning with warning_suppressed_p, and suppress_warning. (c_strlen): Same. (maybe_warn_for_bound): Same. (warn_for_access): Same. (check_access): Same. (expand_builtin_strncmp): Same. (fold_builtin_varargs): Same. * calls.c (maybe_warn_nonstring_arg): Same. (maybe_warn_rdwr_sizes): Same. * cfgexpand.c (expand_call_stmt): Same. * cgraphunit.c (check_global_declaration): Same. * fold-const.c (fold_undefer_overflow_warnings): Same. (fold_truth_not_expr): Same. (fold_unary_loc): Same. (fold_checksum_tree): Same. * gimple-array-bounds.cc (array_bounds_checker::check_array_ref): Same. (array_bounds_checker::check_mem_ref): Same. (array_bounds_checker::check_addr_expr): Same. (array_bounds_checker::check_array_bounds): Same. * gimple-expr.c (copy_var_decl): Same. * gimple-fold.c (gimple_fold_builtin_strcpy): Same. (gimple_fold_builtin_strncat): Same. (gimple_fold_builtin_stxcpy_chk): Same. (gimple_fold_builtin_stpcpy): Same. (gimple_fold_builtin_sprintf): Same. (fold_stmt_1): Same. * gimple-ssa-isolate-paths.c (diag_returned_locals): Same. * gimple-ssa-nonnull-compare.c (do_warn_nonnull_compare): Same. * gimple-ssa-sprintf.c (handle_printf_call): Same. * gimple-ssa-store-merging.c (imm_store_chain_info::output_merged_store): Same. * gimple-ssa-warn-restrict.c (maybe_diag_overlap): Same. * gimple-ssa-warn-restrict.h: Adjust declarations. (maybe_diag_access_bounds): Replace uses of TREE_NO_WARNING, gimple_no_warning_p and gimple_set_no_warning with warning_suppressed_p, and suppress_warning. (check_call): Same. (check_bounds_or_overlap): Same. * gimple.c (gimple_build_call_from_tree): Same. * gimplify.c (gimplify_return_expr): Same. (gimplify_cond_expr): Same. (gimplify_modify_expr_complex_part): Same. (gimplify_modify_expr): Same. (gimple_push_cleanup): Same. (gimplify_expr): Same. * omp-expand.c (expand_omp_for_generic): Same. (expand_omp_taskloop_for_outer): Same. * omp-low.c (lower_rec_input_clauses): Same. (lower_lastprivate_clauses): Same. (lower_send_clauses): Same. (lower_omp_target): Same. * tree-cfg.c (pass_warn_function_return::execute): Same. * tree-complex.c (create_one_component_var): Same. * tree-inline.c (remap_gimple_op_r): Same. (copy_tree_body_r): Same. (declare_return_variable): Same. (expand_call_inline): Same. * tree-nested.c (lookup_field_for_decl): Same. * tree-sra.c (create_access_replacement): Same. (generate_subtree_copies): Same. * tree-ssa-ccp.c (pass_post_ipa_warn::execute): Same. * tree-ssa-forwprop.c (combine_cond_expr_cond): Same. * tree-ssa-loop-ch.c (ch_base::copy_headers): Same. * tree-ssa-loop-im.c (execute_sm): Same. * tree-ssa-phiopt.c (cond_store_replacement): Same. * tree-ssa-strlen.c (maybe_warn_overflow): Same. (handle_builtin_strcpy): Same. (maybe_diag_stxncpy_trunc): Same. (handle_builtin_stxncpy_strncat): Same. (handle_builtin_strcat): Same. * tree-ssa-uninit.c (get_no_uninit_warning): Same. (set_no_uninit_warning): Same. (uninit_undefined_value_p): Same. (warn_uninit): Same. (maybe_warn_operand): Same. * tree-vrp.c (compare_values_warnv): Same. * vr-values.c (vr_values::extract_range_for_var_from_comparison_expr): Same. (test_for_singularity): Same. * gimple.h (warning_suppressed_p): New function. (suppress_warning): Same. (copy_no_warning): Same. (gimple_set_block): Call gimple_set_location. (gimple_set_location): Call copy_warning. --- gcc/tree-ssa-uninit.c | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) (limited to 'gcc/tree-ssa-uninit.c') diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index 7c002f8..99442d7 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -87,17 +87,33 @@ has_undefined_value_p (tree t) && possibly_undefined_names->contains (t))); } -/* Like has_undefined_value_p, but don't return true if TREE_NO_WARNING - is set on SSA_NAME_VAR. */ +/* Return true if EXPR should suppress either uninitialized warning. */ + +static inline bool +get_no_uninit_warning (tree expr) +{ + return warning_suppressed_p (expr, OPT_Wuninitialized); +} + +/* Suppress both uninitialized warnings for EXPR. */ + +static inline void +set_no_uninit_warning (tree expr) +{ + suppress_warning (expr, OPT_Wuninitialized); +} + +/* Like has_undefined_value_p, but don't return true if the no-warning + bit is set on SSA_NAME_VAR for either uninit warning. */ static inline bool uninit_undefined_value_p (tree t) { if (!has_undefined_value_p (t)) return false; - if (SSA_NAME_VAR (t) && TREE_NO_WARNING (SSA_NAME_VAR (t))) - return false; - return true; + if (!SSA_NAME_VAR (t)) + return true; + return !get_no_uninit_warning (SSA_NAME_VAR (t)); } /* Emit warnings for uninitialized variables. This is done in two passes. @@ -165,10 +181,10 @@ warn_uninit (enum opt_code wc, tree t, tree expr, tree var, /* TREE_NO_WARNING either means we already warned, or the front end wishes to suppress the warning. */ if ((context - && (gimple_no_warning_p (context) + && (warning_suppressed_p (context, OPT_Wuninitialized) || (gimple_assign_single_p (context) - && TREE_NO_WARNING (gimple_assign_rhs1 (context))))) - || TREE_NO_WARNING (expr)) + && get_no_uninit_warning (gimple_assign_rhs1 (context))))) + || get_no_uninit_warning (expr)) return; if (context != NULL && gimple_has_location (context)) @@ -185,7 +201,7 @@ warn_uninit (enum opt_code wc, tree t, tree expr, tree var, auto_diagnostic_group d; if (warning_at (location, wc, gmsgid, expr)) { - TREE_NO_WARNING (expr) = 1; + suppress_warning (expr, wc); if (location == DECL_SOURCE_LOCATION (var)) return; @@ -260,7 +276,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs, use_operand_p luse_p; imm_use_iterator liter; - if (TREE_NO_WARNING (rhs)) + if (get_no_uninit_warning (rhs)) return NULL_TREE; /* Do not warn if the base was marked so or this is a @@ -268,7 +284,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs, tree base = ao_ref_base (&ref); if ((VAR_P (base) && DECL_HARD_REGISTER (base)) - || TREE_NO_WARNING (base)) + || get_no_uninit_warning (base)) return NULL_TREE; /* Do not warn if the access is fully outside of the variable. */ @@ -407,7 +423,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs, rhs = TREE_OPERAND (rhs, 0); /* Check again since RHS may have changed above. */ - if (TREE_NO_WARNING (rhs)) + if (get_no_uninit_warning (rhs)) return NULL_TREE; /* Avoid warning about empty types such as structs with no members. @@ -435,7 +451,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs, uses or accesses by functions as it may hide important locations. */ if (lhs) - TREE_NO_WARNING (rhs) = 1; + set_no_uninit_warning (rhs); warned = true; } } -- cgit v1.1 From 6d3bab5d5adb3e28ddb16c97b0831efdea23cf7d Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 6 Jul 2021 13:41:02 -0600 Subject: Improve warning suppression for inlined functions. Resolves: PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at declaration site PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective in conjunction with alias attribute gcc/ChangeLog: * builtins.c (warn_string_no_nul): Remove %G. (maybe_warn_for_bound): Same. (warn_for_access): Same. (check_access): Same. (check_strncat_sizes): Same. (expand_builtin_strncat): Same. (expand_builtin_strncmp): Same. (expand_builtin): Same. (expand_builtin_object_size): Same. (warn_dealloc_offset): Same. (maybe_emit_free_warning): Same. * calls.c (maybe_warn_alloc_args_overflow): Same. (maybe_warn_nonstring_arg): Same. (maybe_warn_rdwr_sizes): Same. * expr.c (expand_expr_real_1): Remove %K. * gimple-fold.c (gimple_fold_builtin_strncpy): Remove %G. (gimple_fold_builtin_strncat): Same. * gimple-ssa-sprintf.c (format_directive): Same. (handle_printf_call): Same. * gimple-ssa-warn-alloca.c (pass_walloca::execute): Same. * gimple-ssa-warn-restrict.c (maybe_diag_overlap): Same. (maybe_diag_access_bounds): Same. Call gimple_location. (check_bounds_or_overlap): Same. * trans-mem.c (ipa_tm_scan_irr_block): Remove %K. Simplify. * tree-ssa-ccp.c (pass_post_ipa_warn::execute): Remove %G. * tree-ssa-strlen.c (maybe_warn_overflow): Same. (maybe_diag_stxncpy_trunc): Same. (handle_builtin_stxncpy_strncat): Same. (maybe_warn_pointless_strcmp): Same. * tree-ssa-uninit.c (maybe_warn_operand): Same. gcc/testsuite/ChangeLog: * gcc.dg/Wobjsize-1.c: Prune expected output. * gcc.dg/Warray-bounds-71.c: New test. * gcc.dg/Warray-bounds-71.h: New test header. * gcc.dg/Warray-bounds-72.c: New test. * gcc.dg/Warray-bounds-73.c: New test. * gcc.dg/Warray-bounds-74.c: New test. * gcc.dg/Warray-bounds-75.c: New test. * gcc.dg/Wfree-nonheap-object-4.c: Adjust expected output. * gcc.dg/Wfree-nonheap-object-5.c: New test. * gcc.dg/Wfree-nonheap-object-6.c: New test. * gcc.dg/pragma-diag-10.c: New test. * gcc.dg/pragma-diag-9.c: New test. * gcc.dg/uninit-suppress_3.c: New test. * gcc.dg/pr79214.c: Xfail tests. * gcc.dg/tree-ssa/builtin-sprintf-warn-27.c: New test. * gcc.dg/format/c90-printf-1.c: Adjust expected output. --- gcc/tree-ssa-uninit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc/tree-ssa-uninit.c') diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index 99442d7..24ac031 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -444,7 +444,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs, if (wlims.always_executed) { if (warning_at (location, OPT_Wuninitialized, - "%G%qE is used uninitialized", stmt, rhs)) + "%qE is used uninitialized", rhs)) { /* ??? This is only effective for decls as in gcc.dg/uninit-B-O0.c. Avoid doing this for maybe-uninit @@ -457,7 +457,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs, } else if (wlims.wmaybe_uninit) warned = warning_at (location, OPT_Wmaybe_uninitialized, - "%G%qE may be used uninitialized", stmt, rhs); + "%qE may be used uninitialized", rhs); return warned ? base : NULL_TREE; } -- cgit v1.1 From e07d30fdcaec4906e0dcb948fc4748bf74c15c05 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 20 Jul 2021 13:08:39 -0600 Subject: Handle all UBSAN built-ins in -Wuninitialized [PR101300]. Resolves: PR middle-end/101300 - -fsanitize=undefined suppresses -Wuninitialized for a VLA read at -O0 gcc/ChangeLog: PR middle-end/101300 * tree-ssa-uninit.c (check_defs): Handle UBSAN built-ins. gcc/testsuite/ChangeLog: PR middle-end/101300 * gcc.dg/uninit-pr101300.c: New test. --- gcc/tree-ssa-uninit.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'gcc/tree-ssa-uninit.c') diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index 24ac031..148f3c2 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -228,9 +228,26 @@ check_defs (ao_ref *ref, tree vdef, void *data_) gimple *def_stmt = SSA_NAME_DEF_STMT (vdef); /* The ASAN_MARK intrinsic doesn't modify the variable. */ - if (is_gimple_call (def_stmt) - && gimple_call_internal_p (def_stmt, IFN_ASAN_MARK)) - return false; + if (is_gimple_call (def_stmt)) + { + if (gimple_call_internal_p (def_stmt) + && gimple_call_internal_fn (def_stmt) == IFN_ASAN_MARK) + return false; + + if (tree fndecl = gimple_call_fndecl (def_stmt)) + { + /* Some sanitizer calls pass integer arguments to built-ins + that expect pointers. Avoid using gimple_call_builtin_p() + which fails for such calls. */ + if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) + { + built_in_function fncode = DECL_FUNCTION_CODE (fndecl); + if (fncode > BEGIN_SANITIZER_BUILTINS + && fncode < END_SANITIZER_BUILTINS) + return false; + } + } + } /* End of VLA scope is not a kill. */ if (gimple_call_builtin_p (def_stmt, BUILT_IN_STACK_RESTORE)) -- cgit v1.1 From 66030d68a7edfc9504a50469598e0707b8f787ce Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 22 Jul 2021 12:26:16 +0200 Subject: tree-optimization/101573 - improve uninit warning at -O0 We can improve uninit warnings from the early pass by looking at PHI arguments on fallthru edges that are uninitialized and have uses that are before a possible loop exit. This catches some cases earlier that we'd only warn in a more confusing way after early inlining as seen by testcase adjustments. It introduces FAIL: gcc.dg/uninit-23.c (test for excess errors) where we additionally warn gcc.dg/uninit-23.c:21:13: warning: 't4' is used uninitialized [-Wuninitialized] which I think is OK even if it's not obvious that the new warning is an improvement when you look at the obvious source. Somehow for all cases I never get the `'foo' was declared here` notes, I didn't dig why that happens but it's odd. 2021-07-22 Richard Biener PR tree-optimization/101573 * tree-ssa-uninit.c (warn_uninit_phi_uses): New function looking at uninitialized PHI arg defs in some constrained cases. (warn_uninitialized_vars): Call it. (execute_early_warn_uninitialized): Calculate dominators. * gcc.dg/uninit-pr101573.c: New testcase. * gcc.dg/uninit-15-O0.c: Adjust. * gcc.dg/uninit-15.c: Likewise. * gcc.dg/uninit-23.c: Likewise. * c-c++-common/uninit-17.c: Likewise. --- gcc/tree-ssa-uninit.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) (limited to 'gcc/tree-ssa-uninit.c') diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index 148f3c2..718b326 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -638,6 +638,76 @@ maybe_warn_pass_by_reference (gcall *stmt, wlimits &wlims) wlims.always_executed = save_always_executed; } +/* Warn about an uninitialized PHI argument on the fallthru path to + an always executed block BB. */ + +static void +warn_uninit_phi_uses (basic_block bb) +{ + edge_iterator ei; + edge e, found = NULL, found_back = NULL; + /* Look for a fallthru and possibly a single backedge. */ + FOR_EACH_EDGE (e, ei, bb->preds) + { + /* Ignore backedges. */ + if (dominated_by_p (CDI_DOMINATORS, e->src, bb)) + { + if (found_back) + { + found = NULL; + break; + } + found_back = e; + continue; + } + if (found) + { + found = NULL; + break; + } + found = e; + } + if (!found) + return; + + basic_block succ = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)); + for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si); + gsi_next (&si)) + { + gphi *phi = si.phi (); + tree def = PHI_ARG_DEF_FROM_EDGE (phi, found); + if (TREE_CODE (def) != SSA_NAME + || !SSA_NAME_IS_DEFAULT_DEF (def) + || virtual_operand_p (def)) + continue; + /* If there's a default def on the fallthru edge PHI + value and there's a use that post-dominates entry + then that use is uninitialized and we can warn. */ + imm_use_iterator iter; + use_operand_p use_p; + gimple *use_stmt = NULL; + FOR_EACH_IMM_USE_FAST (use_p, iter, gimple_phi_result (phi)) + { + use_stmt = USE_STMT (use_p); + if (gimple_location (use_stmt) != UNKNOWN_LOCATION + && dominated_by_p (CDI_POST_DOMINATORS, succ, + gimple_bb (use_stmt)) + /* If we found a non-fallthru edge make sure the + use is inside the loop, otherwise the backedge + can serve as initialization. */ + && (!found_back + || dominated_by_p (CDI_DOMINATORS, found_back->src, + gimple_bb (use_stmt)))) + break; + use_stmt = NULL; + } + if (use_stmt) + warn_uninit (OPT_Wuninitialized, def, SSA_NAME_VAR (def), + SSA_NAME_VAR (def), + "%qD is used uninitialized", use_stmt, + UNKNOWN_LOCATION); + } +} static unsigned int warn_uninitialized_vars (bool wmaybe_uninit) @@ -652,6 +722,10 @@ warn_uninitialized_vars (bool wmaybe_uninit) { basic_block succ = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)); wlims.always_executed = dominated_by_p (CDI_POST_DOMINATORS, succ, bb); + + if (wlims.always_executed) + warn_uninit_phi_uses (bb); + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple *stmt = gsi_stmt (gsi); @@ -3135,6 +3209,7 @@ execute_early_warn_uninitialized (void) optimization we want to warn about possible uninitialized as late as possible, thus don't do it here. However, without optimization we need to warn here about "may be uninitialized". */ + calculate_dominance_info (CDI_DOMINATORS); calculate_dominance_info (CDI_POST_DOMINATORS); warn_uninitialized_vars (/*warn_maybe_uninitialized=*/!optimize); -- cgit v1.1 From 6aacd901b800ee8a2a03123669b299a08aad0504 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 27 Jul 2021 16:02:54 -0600 Subject: Let -Wuninitialized assume built-ins don't change const arguments [PR101584]. PR tree-optimization/101584 - missing -Wuninitialized with an allocated object after a built-in call gcc/ChangeLog: PR tree-optimization/101584 * tree-ssa-uninit.c (builtin_call_nomodifying_p): New function. (check_defs): Call it. gcc/testsuite/ChangeLog: PR tree-optimization/101584 * gcc.dg/uninit-38.c: Remove assertions. * gcc.dg/uninit-41.c: New test. --- gcc/tree-ssa-uninit.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'gcc/tree-ssa-uninit.c') diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index 718b326..ab64a68 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -219,6 +219,70 @@ struct check_defs_data bool found_may_defs; }; +/* Return true if STMT is a call to built-in function all of whose + by-reference arguments are const-qualified (i.e., the function can + be assumed not to modify them). */ + +static bool +builtin_call_nomodifying_p (gimple *stmt) +{ + if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)) + return false; + + tree fndecl = gimple_call_fndecl (stmt); + if (!fndecl) + return false; + + tree fntype = TREE_TYPE (fndecl); + if (!fntype) + return false; + + /* Check the called function's signature for non-constc pointers. + If one is found, return false. */ + unsigned argno = 0; + tree argtype; + function_args_iterator it; + FOREACH_FUNCTION_ARGS (fntype, argtype, it) + { + if (VOID_TYPE_P (argtype)) + return true; + + ++argno; + + if (!POINTER_TYPE_P (argtype)) + continue; + + if (TYPE_READONLY (TREE_TYPE (argtype))) + continue; + + return false; + } + + /* If the number of actual arguments to the call is less than or + equal to the number of parameters, return false. */ + unsigned nargs = gimple_call_num_args (stmt); + if (nargs <= argno) + return false; + + /* Check arguments passed through the ellipsis in calls to variadic + functions for pointers. If one is found that's a non-constant + pointer, return false. */ + for (; argno < nargs; ++argno) + { + tree arg = gimple_call_arg (stmt, argno); + argtype = TREE_TYPE (arg); + if (!POINTER_TYPE_P (argtype)) + continue; + + if (TYPE_READONLY (TREE_TYPE (argtype))) + continue; + + return false; + } + + return true; +} + /* Callback for walk_aliased_vdefs. */ static bool @@ -261,6 +325,9 @@ check_defs (ao_ref *ref, tree vdef, void *data_) return false; } + if (builtin_call_nomodifying_p (def_stmt)) + return false; + /* Found a may-def on this path. */ data->found_may_defs = true; return true; -- cgit v1.1 From 1121e495b70105deeb82295f8210e30f2080bc37 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Wed, 28 Jul 2021 16:25:40 -0600 Subject: Correct uninitialized object offset and size computation [PR101494]. Resolves: PR middle-end/101494 - -Wuninitialized false alarm with memrchr of size 0 gcc/ChangeLog: PR middle-end/101494 * tree-ssa-uninit.c (maybe_warn_operand): Correct object offset and size computation. gcc/testsuite/ChangeLog: PR middle-end/101494 * gcc.dg/uninit-pr101494.c: New test. --- gcc/tree-ssa-uninit.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'gcc/tree-ssa-uninit.c') diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index ab64a68..5d7bc80 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -371,16 +371,20 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs, || get_no_uninit_warning (base)) return NULL_TREE; - /* Do not warn if the access is fully outside of the variable. */ + /* Do not warn if the access is zero size or if it's fully outside + the object. */ poly_int64 decl_size; + if (known_size_p (ref.size) + && known_eq (ref.max_size, ref.size) + && (known_eq (ref.size, 0) + || known_le (ref.offset + ref.size, 0))) + return NULL_TREE; + if (DECL_P (base) - && ((known_size_p (ref.size) - && known_eq (ref.max_size, ref.size) - && known_le (ref.offset + ref.size, 0)) - || (known_ge (ref.offset, 0) - && DECL_SIZE (base) - && poly_int_tree_p (DECL_SIZE (base), &decl_size) - && known_le (decl_size, ref.offset)))) + && known_ge (ref.offset, 0) + && DECL_SIZE (base) + && poly_int_tree_p (DECL_SIZE (base), &decl_size) + && known_le (decl_size, ref.offset)) return NULL_TREE; /* Do not warn if the result of the access is then used for -- cgit v1.1 From fb85d6eb6c392e829d1ee5b8a2e2b81c53c9840f Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Fri, 13 Aug 2021 12:21:20 -0600 Subject: Warn for reads from write-only arguments [PR101734]. Resolves: PR middle-end/101734 - missing warning reading from a write-only object gcc/ChangeLog: PR middle-end/101734 * tree-ssa-uninit.c (maybe_warn_read_write_only): New function. (maybe_warn_operand): Call it. gcc/testsuite/ChangeLog: PR middle-end/101734 * gcc.dg/uninit-42.c: New test. --- gcc/tree-ssa-uninit.c | 89 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 9 deletions(-) (limited to 'gcc/tree-ssa-uninit.c') diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index 5d7bc80..d5cdffb 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -283,6 +283,64 @@ builtin_call_nomodifying_p (gimple *stmt) return true; } +/* If ARG is a FNDECL parameter declared with attribute access none or + write_only issue a warning for its read access via PTR. */ + +static void +maybe_warn_read_write_only (tree fndecl, gimple *stmt, tree arg, tree ptr) +{ + if (!fndecl) + return; + + if (get_no_uninit_warning (arg)) + return; + + tree fntype = TREE_TYPE (fndecl); + if (!fntype) + return; + + /* Initialize a map of attribute access specifications for arguments + to the function function call. */ + rdwr_map rdwr_idx; + init_attr_rdwr_indices (&rdwr_idx, TYPE_ATTRIBUTES (fntype)); + + unsigned argno = 0; + tree parms = DECL_ARGUMENTS (fndecl); + for (tree parm = parms; parm; parm = TREE_CHAIN (parm), ++argno) + { + if (parm != arg) + continue; + + const attr_access* access = rdwr_idx.get (argno); + if (!access) + break; + + if (access->mode != access_none + && access->mode != access_write_only) + continue; + + location_t stmtloc + = linemap_resolve_location (line_table, gimple_location (stmt), + LRK_SPELLING_LOCATION, NULL); + + if (!warning_at (stmtloc, OPT_Wmaybe_uninitialized, + "%qE may be used uninitialized", ptr)) + break; + + suppress_warning (arg, OPT_Wmaybe_uninitialized); + + const char* const access_str = + TREE_STRING_POINTER (access->to_external_string ()); + + location_t parmloc = DECL_SOURCE_LOCATION (parm); + inform (parmloc, "accessing argument %u of a function declared with " + "attribute %<%s%>", + argno + 1, access_str); + + break; + } +} + /* Callback for walk_aliased_vdefs. */ static bool @@ -350,7 +408,9 @@ struct wlimits }; /* Determine if REF references an uninitialized operand and diagnose - it if so. */ + it if so. STMS is the referencing statement. LHS is the result + of the access and may be null. RHS is the variable referenced by + the access; it may not be null. */ static tree maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs, @@ -497,14 +557,25 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs, /* Do not warn if it can be initialized outside this function. If we did not reach function entry then we found killing clobbers on all paths to entry. */ - if (!found_alloc - && fentry_reached - /* ??? We'd like to use ref_may_alias_global_p but that - excludes global readonly memory and thus we get bogus - warnings from p = cond ? "a" : "b" for example. */ - && (!VAR_P (base) - || is_global_var (base))) - return NULL_TREE; + if (!found_alloc && fentry_reached) + { + if (TREE_CODE (base) == SSA_NAME) + { + tree var = SSA_NAME_VAR (base); + if (var && TREE_CODE (var) == PARM_DECL) + { + maybe_warn_read_write_only (cfun->decl, stmt, var, rhs); + return NULL_TREE; + } + } + + if (!VAR_P (base) + || is_global_var (base)) + /* ??? We'd like to use ref_may_alias_global_p but that + excludes global readonly memory and thus we get bogus + warnings from p = cond ? "a" : "b" for example. */ + return NULL_TREE; + } /* Strip the address-of expression from arrays passed to functions. */ if (TREE_CODE (rhs) == ADDR_EXPR) -- cgit v1.1 From e12946df34c997e96c3bc7eb5a0247e889ddb7ea Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Wed, 18 Aug 2021 13:25:28 +0200 Subject: Add EAF_NOREAD check to tree-ssa-uninit gcc/ChangeLog: 2021-08-18 Jan Hubicka * tree-ssa-uninit.c (maybe_warn_pass_by_reference): Check also EAF_NOREAD. --- gcc/tree-ssa-uninit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc/tree-ssa-uninit.c') diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index d5cdffb..ad2cf48 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -712,7 +712,7 @@ maybe_warn_pass_by_reference (gcall *stmt, wlimits &wlims) wlims.always_executed = false; /* Ignore args we are not going to read from. */ - if (gimple_call_arg_flags (stmt, argno - 1) & EAF_UNUSED) + if (gimple_call_arg_flags (stmt, argno - 1) & (EAF_UNUSED | EAF_NOREAD)) continue; tree arg = gimple_call_arg (stmt, argno - 1); -- cgit v1.1 From 4e84e381f27113b20c8adac4430813931962c917 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 26 Aug 2021 13:15:38 -0600 Subject: Refactor warn_uninit() code. gcc/ChangeLog: * tree-ssa-uninit.c (warn_uninit): Refactor and simplify. (warn_uninit_phi_uses): Remove argument from calls to warn_uninit. (warn_uninitialized_vars): Same. Reduce visibility of locals. (warn_uninitialized_phi): Same. --- gcc/tree-ssa-uninit.c | 186 ++++++++++++++++++++++---------------------------- 1 file changed, 83 insertions(+), 103 deletions(-) (limited to 'gcc/tree-ssa-uninit.c') diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index ad2cf48..394dbf4 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -131,20 +131,19 @@ uninit_undefined_value_p (tree t) again for plain uninitialized variables, since optimization may have changed conditionally uninitialized to unconditionally uninitialized. */ -/* Emit a warning for EXPR based on variable VAR at the point in the - program T, an SSA_NAME, is used being uninitialized. The exact - warning text is in MSGID and DATA is the gimple stmt with info about - the location in source code. When DATA is a GIMPLE_PHI, PHIARG_IDX - gives which argument of the phi node to take the location from. WC - is the warning code. */ +/* Emit warning OPT for variable VAR at the point in the program where + the SSA_NAME T is being used uninitialized. The warning text is in + MSGID and STMT is the statement that does the uninitialized read. + PHI_ARG_LOC is the location of the PHI argument if T and VAR are one, + or UNKNOWN_LOCATION otherwise. */ static void -warn_uninit (enum opt_code wc, tree t, tree expr, tree var, - const char *gmsgid, void *data, location_t phiarg_loc) +warn_uninit (opt_code opt, tree t, tree var, const char *gmsgid, + gimple *context, location_t phi_arg_loc = UNKNOWN_LOCATION) { - gimple *context = (gimple *) data; - location_t location, cfun_loc; - expanded_location xloc, floc; + /* Bail if the value isn't provably uninitialized. */ + if (!has_undefined_value_p (t)) + return; /* Ignore COMPLEX_EXPR as initializing only a part of a complex turns in a COMPLEX_EXPR with the not initialized part being @@ -152,65 +151,69 @@ warn_uninit (enum opt_code wc, tree t, tree expr, tree var, if (is_gimple_assign (context) && gimple_assign_rhs_code (context) == COMPLEX_EXPR) return; - if (!has_undefined_value_p (t)) - return; - /* Anonymous SSA_NAMEs shouldn't be uninitialized, but ssa_undefined_value_p - can return true if the def stmt of anonymous SSA_NAME is COMPLEX_EXPR + can return true if the def stmt of an anonymous SSA_NAME is COMPLEX_EXPR created for conversion from scalar to complex. Use the underlying var of the COMPLEX_EXPRs real part in that case. See PR71581. */ - if (expr == NULL_TREE - && var == NULL_TREE - && SSA_NAME_VAR (t) == NULL_TREE - && is_gimple_assign (SSA_NAME_DEF_STMT (t)) - && gimple_assign_rhs_code (SSA_NAME_DEF_STMT (t)) == COMPLEX_EXPR) - { - tree v = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (t)); - if (TREE_CODE (v) == SSA_NAME - && has_undefined_value_p (v) - && zerop (gimple_assign_rhs2 (SSA_NAME_DEF_STMT (t)))) + if (!var && !SSA_NAME_VAR (t)) + { + gimple *def_stmt = SSA_NAME_DEF_STMT (t); + if (is_gimple_assign (def_stmt) + && gimple_assign_rhs_code (def_stmt) == COMPLEX_EXPR) { - expr = SSA_NAME_VAR (v); - var = expr; + tree v = gimple_assign_rhs1 (def_stmt); + if (TREE_CODE (v) == SSA_NAME + && has_undefined_value_p (v) + && zerop (gimple_assign_rhs2 (def_stmt))) + var = SSA_NAME_VAR (v); } } - if (expr == NULL_TREE) + if (var == NULL_TREE) return; - /* TREE_NO_WARNING either means we already warned, or the front end - wishes to suppress the warning. */ - if ((context - && (warning_suppressed_p (context, OPT_Wuninitialized) - || (gimple_assign_single_p (context) - && get_no_uninit_warning (gimple_assign_rhs1 (context))))) - || get_no_uninit_warning (expr)) + /* Avoid warning if we've already done so or if the warning has been + suppressed. */ + if (((warning_suppressed_p (context, OPT_Wuninitialized) + || (gimple_assign_single_p (context) + && get_no_uninit_warning (gimple_assign_rhs1 (context))))) + || get_no_uninit_warning (var)) return; - if (context != NULL && gimple_has_location (context)) + /* Use either the location of the read statement or that of the PHI + argument, or that of the uninitialized variable, in that order, + whichever is valid. */ + location_t location; + if (gimple_has_location (context)) location = gimple_location (context); - else if (phiarg_loc != UNKNOWN_LOCATION) - location = phiarg_loc; + else if (phi_arg_loc != UNKNOWN_LOCATION) + location = phi_arg_loc; else location = DECL_SOURCE_LOCATION (var); location = linemap_resolve_location (line_table, location, LRK_SPELLING_LOCATION, NULL); - cfun_loc = DECL_SOURCE_LOCATION (cfun->decl); - xloc = expand_location (location); - floc = expand_location (cfun_loc); + auto_diagnostic_group d; - if (warning_at (location, wc, gmsgid, expr)) - { - suppress_warning (expr, wc); + if (!warning_at (location, opt, gmsgid, var)) + return; - if (location == DECL_SOURCE_LOCATION (var)) - return; - if (xloc.file != floc.file - || linemap_location_before_p (line_table, location, cfun_loc) - || linemap_location_before_p (line_table, cfun->function_end_locus, + /* Avoid subsequent warnings for reads of the same variable again. */ + suppress_warning (var, opt); + + /* Issue a note pointing to the read variable unless the warning + is at the same location. */ + location_t var_loc = DECL_SOURCE_LOCATION (var); + if (location == var_loc) + return; + + location_t cfun_loc = DECL_SOURCE_LOCATION (cfun->decl); + expanded_location xloc = expand_location (location); + expanded_location floc = expand_location (cfun_loc); + if (xloc.file != floc.file + || linemap_location_before_p (line_table, location, cfun_loc) + || linemap_location_before_p (line_table, cfun->function_end_locus, location)) - inform (DECL_SOURCE_LOCATION (var), "%qD was declared here", var); - } + inform (var_loc, "%qD was declared here", var); } struct check_defs_data @@ -845,13 +848,14 @@ warn_uninit_phi_uses (basic_block bb) } if (use_stmt) warn_uninit (OPT_Wuninitialized, def, SSA_NAME_VAR (def), - SSA_NAME_VAR (def), - "%qD is used uninitialized", use_stmt, - UNKNOWN_LOCATION); + "%qD is used uninitialized", use_stmt); } } -static unsigned int +/* Issue warnings about reads of uninitialized variables. WMAYBE_UNINIT + is true to issue -Wmaybe-uninitialized, otherwise -Wuninitialized. */ + +static void warn_uninitialized_vars (bool wmaybe_uninit) { /* Counters and limits controlling the the depth of the warning. */ @@ -871,15 +875,13 @@ warn_uninitialized_vars (bool wmaybe_uninit) for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple *stmt = gsi_stmt (gsi); - use_operand_p use_p; - ssa_op_iter op_iter; - tree use; - if (is_gimple_debug (stmt)) continue; /* We only do data flow with SSA_NAMEs, so that's all we can warn about. */ + use_operand_p use_p; + ssa_op_iter op_iter; FOR_EACH_SSA_USE_OPERAND (use_p, stmt, op_iter, SSA_OP_USE) { /* BIT_INSERT_EXPR first operand should not be considered @@ -890,17 +892,13 @@ warn_uninitialized_vars (bool wmaybe_uninit) && use_p->use == gimple_assign_rhs1_ptr (ass)) continue; } - use = USE_FROM_PTR (use_p); + tree use = USE_FROM_PTR (use_p); if (wlims.always_executed) warn_uninit (OPT_Wuninitialized, use, SSA_NAME_VAR (use), - SSA_NAME_VAR (use), - "%qD is used uninitialized", stmt, - UNKNOWN_LOCATION); + "%qD is used uninitialized", stmt); else if (wmaybe_uninit) warn_uninit (OPT_Wmaybe_uninitialized, use, SSA_NAME_VAR (use), - SSA_NAME_VAR (use), - "%qD may be used uninitialized", - stmt, UNKNOWN_LOCATION); + "%qD may be used uninitialized", stmt); } /* For limiting the alias walk below we count all @@ -930,8 +928,6 @@ warn_uninitialized_vars (bool wmaybe_uninit) } } } - - return 0; } /* Checks if the operand OPND of PHI is defined by @@ -943,16 +939,13 @@ warn_uninitialized_vars (bool wmaybe_uninit) static bool can_skip_redundant_opnd (tree opnd, gimple *phi) { - gimple *op_def; - tree phi_def; - int i, n; - - phi_def = gimple_phi_result (phi); - op_def = SSA_NAME_DEF_STMT (opnd); + tree phi_def = gimple_phi_result (phi); + gimple *op_def = SSA_NAME_DEF_STMT (opnd); if (gimple_code (op_def) != GIMPLE_PHI) return false; - n = gimple_phi_num_args (op_def); - for (i = 0; i < n; ++i) + + unsigned n = gimple_phi_num_args (op_def); + for (unsigned i = 0; i < n; ++i) { tree op = gimple_phi_arg_def (op_def, i); if (TREE_CODE (op) != SSA_NAME) @@ -970,15 +963,14 @@ can_skip_redundant_opnd (tree opnd, gimple *phi) static unsigned compute_uninit_opnds_pos (gphi *phi) { - size_t i, n; unsigned uninit_opnds = 0; - n = gimple_phi_num_args (phi); + unsigned n = gimple_phi_num_args (phi); /* Bail out for phi with too many args. */ if (n > max_phi_args) return 0; - for (i = 0; i < n; ++i) + for (unsigned i = 0; i < n; ++i) { tree op = gimple_phi_arg_def (phi, i); if (TREE_CODE (op) == SSA_NAME @@ -998,8 +990,7 @@ compute_uninit_opnds_pos (gphi *phi) return uninit_opnds; } -/* Find the immediate postdominator PDOM of the specified - basic block BLOCK. */ +/* Find the immediate postdominator of the specified basic block BLOCK. */ static inline basic_block find_pdom (basic_block block) @@ -1015,7 +1006,7 @@ find_pdom (basic_block block) } } -/* Find the immediate DOM of the specified basic block BLOCK. */ +/* Find the immediate dominator of the specified basic block BLOCK. */ static inline basic_block find_dom (basic_block block) @@ -1053,9 +1044,7 @@ is_non_loop_exit_postdominating (basic_block bb1, basic_block bb2) static inline basic_block find_control_equiv_block (basic_block bb) { - basic_block pdom; - - pdom = find_pdom (bb); + basic_block pdom = find_pdom (bb); /* Skip the postdominating bb that is also loop exit. */ if (!is_non_loop_exit_postdominating (pdom, bb)) @@ -3193,18 +3182,11 @@ static void warn_uninitialized_phi (gphi *phi, vec *worklist, hash_set *added_to_worklist) { - unsigned uninit_opnds; - gimple *uninit_use_stmt = 0; - tree uninit_op; - int phiarg_index; - location_t loc; - /* Don't look at virtual operands. */ if (virtual_operand_p (gimple_phi_result (phi))) return; - uninit_opnds = compute_uninit_opnds_pos (phi); - + unsigned uninit_opnds = compute_uninit_opnds_pos (phi); if (MASK_EMPTY (uninit_opnds)) return; @@ -3215,25 +3197,23 @@ warn_uninitialized_phi (gphi *phi, vec *worklist, } /* Now check if we have any use of the value without proper guard. */ - uninit_use_stmt = find_uninit_use (phi, uninit_opnds, - worklist, added_to_worklist); + gimple *uninit_use_stmt = find_uninit_use (phi, uninit_opnds, + worklist, added_to_worklist); /* All uses are properly guarded. */ if (!uninit_use_stmt) return; - phiarg_index = MASK_FIRST_SET_BIT (uninit_opnds); - uninit_op = gimple_phi_arg_def (phi, phiarg_index); + int phiarg_index = MASK_FIRST_SET_BIT (uninit_opnds); + tree uninit_op = gimple_phi_arg_def (phi, phiarg_index); if (SSA_NAME_VAR (uninit_op) == NULL_TREE) return; - if (gimple_phi_arg_has_location (phi, phiarg_index)) - loc = gimple_phi_arg_location (phi, phiarg_index); - else - loc = UNKNOWN_LOCATION; - warn_uninit (OPT_Wmaybe_uninitialized, uninit_op, SSA_NAME_VAR (uninit_op), + + location_t phi_arg_loc = gimple_phi_arg_location (phi, phiarg_index); + warn_uninit (OPT_Wmaybe_uninitialized, uninit_op, SSA_NAME_VAR (uninit_op), "%qD may be used uninitialized in this function", - uninit_use_stmt, loc); + uninit_use_stmt, phi_arg_loc); } static bool -- cgit v1.1 From 9695e1c23be5b5c55d572ced152897313ddb96ae Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 2 Sep 2021 09:20:09 -0600 Subject: Improve -Wuninitialized note location. Related: PR tree-optimization/17506 - warning about uninitialized variable points to wrong location PR testsuite/37182 - Revision 139286 caused gcc.dg/pr17506.c and gcc.dg/uninit-15.c gcc/ChangeLog: PR tree-optimization/17506 PR testsuite/37182 * tree-ssa-uninit.c (warn_uninit): Remove conditional guarding note. gcc/testsuite/ChangeLog: PR tree-optimization/17506 PR testsuite/37182 * gcc.dg/diagnostic-tree-expr-ranges-2.c: Add expected output. * gcc.dg/uninit-15-O0.c: Remove xfail. * gcc.dg/uninit-15.c: Same. --- gcc/tree-ssa-uninit.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'gcc/tree-ssa-uninit.c') diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index 394dbf4..cb6d114 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -206,14 +206,7 @@ warn_uninit (opt_code opt, tree t, tree var, const char *gmsgid, if (location == var_loc) return; - location_t cfun_loc = DECL_SOURCE_LOCATION (cfun->decl); - expanded_location xloc = expand_location (location); - expanded_location floc = expand_location (cfun_loc); - if (xloc.file != floc.file - || linemap_location_before_p (line_table, location, cfun_loc) - || linemap_location_before_p (line_table, cfun->function_end_locus, - location)) - inform (var_loc, "%qD was declared here", var); + inform (var_loc, "%qD was declared here", var); } struct check_defs_data -- cgit v1.1 From a25e0b5e6ac8a77a71c229e0a7b744603365b0e9 Mon Sep 17 00:00:00 2001 From: qing zhao Date: Thu, 9 Sep 2021 15:44:49 -0700 Subject: Add -ftrivial-auto-var-init option and uninitialized variable attribute. Initialize automatic variables with either a pattern or with zeroes to increase the security and predictability of a program by preventing uninitialized memory disclosure and use. GCC still considers an automatic variable that doesn't have an explicit initializer as uninitialized, -Wuninitialized will still report warning messages on such automatic variables. With this option, GCC will also initialize any padding of automatic variables that have structure or union types to zeroes. You can control this behavior for a specific variable by using the variable attribute "uninitialized" to control runtime overhead. gcc/ChangeLog: 2021-09-09 qing zhao * builtins.c (expand_builtin_memset): Make external visible. * builtins.h (expand_builtin_memset): Declare extern. * common.opt (ftrivial-auto-var-init=): New option. * doc/extend.texi: Document the uninitialized attribute. * doc/invoke.texi: Document -ftrivial-auto-var-init. * flag-types.h (enum auto_init_type): New enumerated type auto_init_type. * gimple-fold.c (clear_padding_type): Add one new parameter. (clear_padding_union): Likewise. (clear_padding_emit_loop): Likewise. (clear_type_padding_in_mask): Likewise. (gimple_fold_builtin_clear_padding): Handle this new parameter. * gimplify.c (gimple_add_init_for_auto_var): New function. (gimple_add_padding_init_for_auto_var): New function. (is_var_need_auto_init): New function. (gimplify_decl_expr): Add initialization to automatic variables per users' requests. (gimplify_call_expr): Add one new parameter for call to __builtin_clear_padding. (gimplify_init_constructor): Add padding initialization in the end. * internal-fn.c (INIT_PATTERN_VALUE): New macro. (expand_DEFERRED_INIT): New function. * internal-fn.def (DEFERRED_INIT): New internal function. * tree-cfg.c (verify_gimple_call): Verify calls to .DEFERRED_INIT. * tree-sra.c (generate_subtree_deferred_init): New function. (scan_function): Avoid setting cannot_scalarize_away_bitmap for calls to .DEFERRED_INIT. (sra_modify_deferred_init): New function. (sra_modify_function_body): Handle calls to DEFERRED_INIT specially. * tree-ssa-structalias.c (find_func_aliases_for_call): Likewise. * tree-ssa-uninit.c (warn_uninit): Handle calls to DEFERRED_INIT specially. (check_defs): Likewise. (warn_uninitialized_vars): Likewise. * tree-ssa.c (ssa_undefined_value_p): Likewise. * tree.c (build_common_builtin_nodes): Build tree node for BUILT_IN_CLEAR_PADDING when needed. gcc/c-family/ChangeLog: 2021-09-09 qing zhao * c-attribs.c (handle_uninitialized_attribute): New function. (c_common_attribute_table): Add "uninitialized" attribute. gcc/testsuite/ChangeLog: 2021-09-09 qing zhao * c-c++-common/auto-init-1.c: New test. * c-c++-common/auto-init-10.c: New test. * c-c++-common/auto-init-11.c: New test. * c-c++-common/auto-init-12.c: New test. * c-c++-common/auto-init-13.c: New test. * c-c++-common/auto-init-14.c: New test. * c-c++-common/auto-init-15.c: New test. * c-c++-common/auto-init-16.c: New test. * c-c++-common/auto-init-2.c: New test. * c-c++-common/auto-init-3.c: New test. * c-c++-common/auto-init-4.c: New test. * c-c++-common/auto-init-5.c: New test. * c-c++-common/auto-init-6.c: New test. * c-c++-common/auto-init-7.c: New test. * c-c++-common/auto-init-8.c: New test. * c-c++-common/auto-init-9.c: New test. * c-c++-common/auto-init-esra.c: New test. * c-c++-common/auto-init-padding-1.c: New test. * c-c++-common/auto-init-padding-2.c: New test. * c-c++-common/auto-init-padding-3.c: New test. * g++.dg/auto-init-uninit-pred-1_a.C: New test. * g++.dg/auto-init-uninit-pred-2_a.C: New test. * g++.dg/auto-init-uninit-pred-3_a.C: New test. * g++.dg/auto-init-uninit-pred-4.C: New test. * gcc.dg/auto-init-sra-1.c: New test. * gcc.dg/auto-init-sra-2.c: New test. * gcc.dg/auto-init-uninit-1.c: New test. * gcc.dg/auto-init-uninit-12.c: New test. * gcc.dg/auto-init-uninit-13.c: New test. * gcc.dg/auto-init-uninit-14.c: New test. * gcc.dg/auto-init-uninit-15.c: New test. * gcc.dg/auto-init-uninit-16.c: New test. * gcc.dg/auto-init-uninit-17.c: New test. * gcc.dg/auto-init-uninit-18.c: New test. * gcc.dg/auto-init-uninit-19.c: New test. * gcc.dg/auto-init-uninit-2.c: New test. * gcc.dg/auto-init-uninit-20.c: New test. * gcc.dg/auto-init-uninit-21.c: New test. * gcc.dg/auto-init-uninit-22.c: New test. * gcc.dg/auto-init-uninit-23.c: New test. * gcc.dg/auto-init-uninit-24.c: New test. * gcc.dg/auto-init-uninit-25.c: New test. * gcc.dg/auto-init-uninit-26.c: New test. * gcc.dg/auto-init-uninit-3.c: New test. * gcc.dg/auto-init-uninit-34.c: New test. * gcc.dg/auto-init-uninit-36.c: New test. * gcc.dg/auto-init-uninit-37.c: New test. * gcc.dg/auto-init-uninit-4.c: New test. * gcc.dg/auto-init-uninit-5.c: New test. * gcc.dg/auto-init-uninit-6.c: New test. * gcc.dg/auto-init-uninit-8.c: New test. * gcc.dg/auto-init-uninit-9.c: New test. * gcc.dg/auto-init-uninit-A.c: New test. * gcc.dg/auto-init-uninit-B.c: New test. * gcc.dg/auto-init-uninit-C.c: New test. * gcc.dg/auto-init-uninit-H.c: New test. * gcc.dg/auto-init-uninit-I.c: New test. * gcc.target/aarch64/auto-init-1.c: New test. * gcc.target/aarch64/auto-init-2.c: New test. * gcc.target/aarch64/auto-init-3.c: New test. * gcc.target/aarch64/auto-init-4.c: New test. * gcc.target/aarch64/auto-init-5.c: New test. * gcc.target/aarch64/auto-init-6.c: New test. * gcc.target/aarch64/auto-init-7.c: New test. * gcc.target/aarch64/auto-init-8.c: New test. * gcc.target/aarch64/auto-init-padding-1.c: New test. * gcc.target/aarch64/auto-init-padding-10.c: New test. * gcc.target/aarch64/auto-init-padding-11.c: New test. * gcc.target/aarch64/auto-init-padding-12.c: New test. * gcc.target/aarch64/auto-init-padding-2.c: New test. * gcc.target/aarch64/auto-init-padding-3.c: New test. * gcc.target/aarch64/auto-init-padding-4.c: New test. * gcc.target/aarch64/auto-init-padding-5.c: New test. * gcc.target/aarch64/auto-init-padding-6.c: New test. * gcc.target/aarch64/auto-init-padding-7.c: New test. * gcc.target/aarch64/auto-init-padding-8.c: New test. * gcc.target/aarch64/auto-init-padding-9.c: New test. * gcc.target/i386/auto-init-1.c: New test. * gcc.target/i386/auto-init-2.c: New test. * gcc.target/i386/auto-init-21.c: New test. * gcc.target/i386/auto-init-22.c: New test. * gcc.target/i386/auto-init-23.c: New test. * gcc.target/i386/auto-init-24.c: New test. * gcc.target/i386/auto-init-3.c: New test. * gcc.target/i386/auto-init-4.c: New test. * gcc.target/i386/auto-init-5.c: New test. * gcc.target/i386/auto-init-6.c: New test. * gcc.target/i386/auto-init-7.c: New test. * gcc.target/i386/auto-init-8.c: New test. * gcc.target/i386/auto-init-padding-1.c: New test. * gcc.target/i386/auto-init-padding-10.c: New test. * gcc.target/i386/auto-init-padding-11.c: New test. * gcc.target/i386/auto-init-padding-12.c: New test. * gcc.target/i386/auto-init-padding-2.c: New test. * gcc.target/i386/auto-init-padding-3.c: New test. * gcc.target/i386/auto-init-padding-4.c: New test. * gcc.target/i386/auto-init-padding-5.c: New test. * gcc.target/i386/auto-init-padding-6.c: New test. * gcc.target/i386/auto-init-padding-7.c: New test. * gcc.target/i386/auto-init-padding-8.c: New test. * gcc.target/i386/auto-init-padding-9.c: New test. --- gcc/tree-ssa-uninit.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'gcc/tree-ssa-uninit.c') diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index cb6d114..84eadd1 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -151,6 +151,42 @@ warn_uninit (opt_code opt, tree t, tree var, const char *gmsgid, if (is_gimple_assign (context) && gimple_assign_rhs_code (context) == COMPLEX_EXPR) return; + + /* Ignore REALPART_EXPR or IMAGPART_EXPR if its operand is a call to + .DEFERRED_INIT. This is for handling the following case correctly: + + 1 typedef _Complex float C; + 2 C foo (int cond) + 3 { + 4 C f; + 5 __imag__ f = 0; + 6 if (cond) + 7 { + 8 __real__ f = 1; + 9 return f; + 10 } + 11 return f; + 12 } + + with -ftrivial-auto-var-init, compiler will insert the following + artificial initialization at line 4: + f = .DEFERRED_INIT (f, 2); + _1 = REALPART_EXPR ; + + without the following special handling, _1 = REALPART_EXPR will + be treated as the uninitialized use point, which is incorrect. (the + real uninitialized use point is at line 11). */ + if (is_gimple_assign (context) + && (gimple_assign_rhs_code (context) == REALPART_EXPR + || gimple_assign_rhs_code (context) == IMAGPART_EXPR)) + { + tree v = gimple_assign_rhs1 (context); + if (TREE_CODE (TREE_OPERAND (v, 0)) == SSA_NAME + && gimple_call_internal_p (SSA_NAME_DEF_STMT (TREE_OPERAND (v, 0)), + IFN_DEFERRED_INIT)) + return; + } + /* Anonymous SSA_NAMEs shouldn't be uninitialized, but ssa_undefined_value_p can return true if the def stmt of an anonymous SSA_NAME is COMPLEX_EXPR created for conversion from scalar to complex. Use the underlying var of @@ -345,6 +381,11 @@ check_defs (ao_ref *ref, tree vdef, void *data_) check_defs_data *data = (check_defs_data *)data_; gimple *def_stmt = SSA_NAME_DEF_STMT (vdef); + /* Ignore the vdef if the definition statement is a call + to .DEFERRED_INIT function. */ + if (gimple_call_internal_p (def_stmt, IFN_DEFERRED_INIT)) + return false; + /* The ASAN_MARK intrinsic doesn't modify the variable. */ if (is_gimple_call (def_stmt)) { @@ -868,6 +909,13 @@ warn_uninitialized_vars (bool wmaybe_uninit) for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple *stmt = gsi_stmt (gsi); + + /* The call is an artificial use, will not provide meaningful + error message. If the result of the call is used somewhere + else, we warn there instead. */ + if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT)) + continue; + if (is_gimple_debug (stmt)) continue; -- cgit v1.1