On Fri, Dec 16, 2016 at 09:13:33AM +0100, Markus Trippelsdorf wrote: > It does for me with an allmodconf. At -O2 I get three warnings, and at > -O3 I get two additional warnings. Now these additional ones happen way > too deep into the pipeline to be reliable. (For a reduced testcase see: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78817#c8) > > When you as the author of the warning have difficulties in figuring out > what causes these warnings, what about the average user? > > Therefore -fsanitize=undefined should be preferred. It gives you better > info and a backtrace that makes diagnosis easy. > > So in my opinion -Wnonnull should warn only for trivial cases.
Yeah. I've stated my opinion mostly in the PR, the reason we want most warnings in the FEs is that the IL is closest to the actual source and thus matches what the user wrote. The further in the optimization pipeline we warn, the source is more different from what the user wrote and the warnings can become so cryptic that it is really hard to decipher what they mean. In this case, it is enough if either somebody is just overly cautious in some unrelated function and adds a non-NULL check there, or if just the same function is sometimes used in a context which may return NULL and in other context it is guaranteed not to return NULL. So the -Wnonnull warning we have right now on the trunk became more of -Wmaybe-nonnull. Here is an untested proof of concept for: 1) keeping the warning in the FEs no matter what optimization level is on, just making sure TREE_NO_WARNING is set on the CALL_EXPR if we've warned 2) moving the rest of the warning shortly post IPA, when we have performed inlining already and some constant propagation afterwards, but where hopefully the IL still isn't too much different from the original source 3) as the nonnull attribute is a type property, it warns about the function type of the call, doesn't require a fndecl The tree-ssa-ccp.c location is just randomly chosen, the pass could go into its own file, or some other file. And I think e.g. the -Walloc-zero warning should move there as well. If you think warning later can be still useful to some users at the expense of higher false positive rate, we could have -Wmaybe-nonnull warning that would guard that and set the gimple no warning flag when we warn in the pass. If needed, there is always the option on the table to turn TREE_NO_WARNING/gimple_no_warning_p into a bit that says on the side hash table contains bitmap of disabled warnings for the expression or statement. IMHO we want to do that in any case, just not sure if it is urgent to do for GCC 7. --- gcc/tree-pass.h.jj 2016-11-22 21:31:49.000000000 +0100 +++ gcc/tree-pass.h 2016-12-16 10:32:25.421337439 +0100 @@ -422,6 +422,7 @@ extern gimple_opt_pass *make_pass_omp_de extern gimple_opt_pass *make_pass_object_sizes (gcc::context *ctxt); extern gimple_opt_pass *make_pass_strlen (gcc::context *ctxt); extern gimple_opt_pass *make_pass_fold_builtins (gcc::context *ctxt); +extern gimple_opt_pass *make_pass_post_ipa_warn (gcc::context *ctxt); extern gimple_opt_pass *make_pass_stdarg (gcc::context *ctxt); extern gimple_opt_pass *make_pass_early_warn_uninitialized (gcc::context *ctxt); extern gimple_opt_pass *make_pass_late_warn_uninitialized (gcc::context *ctxt); --- gcc/builtins.c.jj 2016-12-14 20:28:13.000000000 +0100 +++ gcc/builtins.c 2016-12-16 10:36:19.937240326 +0100 @@ -147,7 +147,7 @@ static tree fold_builtin_classify_type ( static tree fold_builtin_strlen (location_t, tree, tree); static tree fold_builtin_inf (location_t, tree, int); static tree rewrite_call_expr (location_t, tree, int, tree, int, ...); -static bool validate_arg (const_tree, enum tree_code code, bool = false); +static bool validate_arg (const_tree, enum tree_code code); static rtx expand_builtin_fabs (tree, rtx, rtx); static rtx expand_builtin_signbit (tree, rtx); static tree fold_builtin_memcmp (location_t, tree, tree, tree); @@ -1050,12 +1050,12 @@ validate_arglist (const_tree callexpr, . init_const_call_expr_arg_iterator (callexpr, &iter); /* Get a bitmap of pointer argument numbers declared attribute nonnull. */ - bitmap argmap = get_nonnull_args (callexpr); + tree fn = CALL_EXPR_FN (callexpr); + bitmap argmap = get_nonnull_args (TREE_TYPE (TREE_TYPE (fn))); for (unsigned argno = 1; ; ++argno) { code = (enum tree_code) va_arg (ap, int); - bool nonnull = false; switch (code) { @@ -1072,15 +1072,21 @@ validate_arglist (const_tree callexpr, . /* The actual argument must be nonnull when either the whole called function has been declared nonnull, or when the formal argument corresponding to the actual argument has been. */ - if (argmap) - nonnull = bitmap_empty_p (argmap) || bitmap_bit_p (argmap, argno); + if (argmap + && (bitmap_empty_p (argmap) || bitmap_bit_p (argmap, argno))) + { + arg = next_const_call_expr_arg (&iter); + if (!validate_arg (arg, code) || integer_zerop (arg)) + goto end; + break; + } /* FALLTHRU */ default: /* If no parameters remain or the parameter's code does not match the specified code, return false. Otherwise continue checking any remaining arguments. */ arg = next_const_call_expr_arg (&iter); - if (!validate_arg (arg, code, nonnull)) + if (!validate_arg (arg, code)) goto end; break; } @@ -9134,17 +9140,15 @@ rewrite_call_expr (location_t loc, tree } /* Validate a single argument ARG against a tree code CODE representing - a type. When NONNULL is true consider a pointer argument valid only - if it's non-null. Return true when argument is valid. */ + a type. Return true when argument is valid. */ static bool -validate_arg (const_tree arg, enum tree_code code, bool nonnull /*= false*/) +validate_arg (const_tree arg, enum tree_code code) { if (!arg) return false; else if (code == POINTER_TYPE) - return POINTER_TYPE_P (TREE_TYPE (arg)) - && (!nonnull || !integer_zerop (arg)); + return POINTER_TYPE_P (TREE_TYPE (arg)); else if (code == INTEGER_TYPE) return INTEGRAL_TYPE_P (TREE_TYPE (arg)); return code == TREE_CODE (TREE_TYPE (arg)); --- gcc/calls.h.jj 2016-12-14 20:28:16.000000000 +0100 +++ gcc/calls.h 2016-12-16 10:19:55.139247122 +0100 @@ -38,6 +38,5 @@ extern bool pass_by_reference (CUMULATIV extern bool reference_callee_copied (CUMULATIVE_ARGS *, machine_mode, tree, bool); extern void maybe_warn_alloc_args_overflow (tree, tree, tree[2], int[2]); -extern bitmap get_nonnull_args (const_tree); #endif // GCC_CALLS_H --- gcc/cp/typeck.c.jj 2016-11-28 16:21:02.000000000 +0100 +++ gcc/cp/typeck.c 2016-12-16 09:53:27.148151638 +0100 @@ -3654,10 +3654,18 @@ cp_build_function_call_vec (tree functio /* Check for errors in format strings and inappropriately null parameters. */ - check_function_arguments (input_location, fntype, nargs, argarray); + bool warned_p = check_function_arguments (input_location, fntype, + nargs, argarray); ret = build_cxx_call (function, nargs, argarray, complain); + if (warned_p) + { + tree c = extract_call_expr (ret); + if (TREE_CODE (c) == CALL_EXPR) + TREE_NO_WARNING (c) = 1; + } + if (allocated != NULL) release_tree_vector (allocated); --- gcc/cp/call.c.jj 2016-12-10 18:41:17.000000000 +0100 +++ gcc/cp/call.c 2016-12-16 09:53:00.165506388 +0100 @@ -7881,6 +7881,7 @@ build_over_call (struct z_candidate *can nonnull are disabled. Just in case that at least one of them is active the check_function_arguments function might warn about something. */ + bool warned_p = false; if (warn_nonnull || warn_format || warn_suggest_attribute_format) { tree *fargs = (!nargs ? argarray @@ -7888,7 +7889,8 @@ build_over_call (struct z_candidate *can for (j = 0; j < nargs; j++) fargs[j] = maybe_constant_value (argarray[j]); - check_function_arguments (input_location, TREE_TYPE (fn), nargs, fargs); + warned_p = check_function_arguments (input_location, TREE_TYPE (fn), + nargs, fargs); } if (DECL_INHERITED_CTOR (fn)) @@ -8107,6 +8109,12 @@ build_over_call (struct z_candidate *can /* build_new_op_1 will clear this when appropriate. */ CALL_EXPR_ORDERED_ARGS (c) = true; } + if (warned_p) + { + tree c = extract_call_expr (call); + if (TREE_CODE (c) == CALL_EXPR) + TREE_NO_WARNING (c) = 1; + } return call; } --- gcc/tree-ssa-ccp.c.jj 2016-12-15 17:46:43.000000000 +0100 +++ gcc/tree-ssa-ccp.c 2016-12-16 10:38:09.187798284 +0100 @@ -143,6 +143,7 @@ along with GCC; see the file COPYING3. #include "stor-layout.h" #include "optabs-query.h" #include "tree-ssa-ccp.h" +#include "diagnostic-core.h" /* Possible lattice values. */ typedef enum @@ -3188,3 +3189,97 @@ make_pass_fold_builtins (gcc::context *c { return new pass_fold_builtins (ctxt); } + +/* A simple pass that emits some warnings post IPA. */ + +namespace { + +const pass_data pass_data_post_ipa_warn = +{ + GIMPLE_PASS, /* type */ + "post_ipa_warn", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_NONE, /* tv_id */ + ( PROP_cfg | PROP_ssa ), /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ +}; + +class pass_post_ipa_warn : public gimple_opt_pass +{ +public: + pass_post_ipa_warn (gcc::context *ctxt) + : gimple_opt_pass (pass_data_post_ipa_warn, ctxt) + {} + + /* opt_pass methods: */ + opt_pass * clone () { return new pass_post_ipa_warn (m_ctxt); } + virtual bool gate (function *) { return warn_nonnull != 0; } + virtual unsigned int execute (function *); + +}; // class pass_fold_builtins + +unsigned int +pass_post_ipa_warn::execute (function *fun) +{ + basic_block bb; + + FOR_EACH_BB_FN (bb, fun) + { + gimple_stmt_iterator gsi; + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple *stmt = gsi_stmt (gsi); + if (!is_gimple_call (stmt) || gimple_no_warning_p (stmt)) + continue; + + if (warn_nonnull) + { + bitmap nonnullargs + = get_nonnull_args (gimple_call_fntype (stmt)); + if (nonnullargs) + { + for (unsigned i = 0; i < gimple_call_num_args (stmt); i++) + { + tree arg = gimple_call_arg (stmt, i); + if (TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE) + continue; + if (!integer_zerop (arg)) + continue; + if (!bitmap_empty_p (nonnullargs) + && !bitmap_bit_p (nonnullargs, i)) + continue; + + location_t loc = gimple_location (stmt); + if (warning_at (loc, OPT_Wnonnull, + "argument %u null where non-null " + "expected", i + 1)) + { + tree fndecl = gimple_call_fndecl (stmt); + if (fndecl && DECL_IS_BUILTIN (fndecl)) + inform (loc, "in a call to built-in function %qD", + fndecl); + else if (fndecl) + inform (DECL_SOURCE_LOCATION (fndecl), + "in a call to function %qD declared here", + fndecl); + + } + } + BITMAP_FREE (nonnullargs); + } + } + } + } + return 0; +} + +} // anon namespace + +gimple_opt_pass * +make_pass_post_ipa_warn (gcc::context *ctxt) +{ + return new pass_post_ipa_warn (ctxt); +} --- gcc/tree.h.jj 2016-11-25 10:40:41.000000000 +0100 +++ gcc/tree.h 2016-12-16 10:20:59.396398417 +0100 @@ -4855,6 +4855,7 @@ extern void DEBUG_FUNCTION verify_type ( extern bool gimple_canonical_types_compatible_p (const_tree, const_tree, bool trust_type_canonical = true); extern bool type_with_interoperable_signedness (const_tree); +extern bitmap get_nonnull_args (const_tree); /* Return simplified tree code of type that is used for canonical type merging. */ --- gcc/c/c-typeck.c.jj 2016-12-15 10:26:16.000000000 +0100 +++ gcc/c/c-typeck.c 2016-12-16 09:48:52.874757606 +0100 @@ -3110,15 +3110,15 @@ build_function_call_vec (location_t loc, return error_mark_node; /* Check that the arguments to the function are valid. */ - check_function_arguments (loc, fntype, nargs, argarray); + bool warned_p = check_function_arguments (loc, fntype, nargs, argarray); if (name != NULL_TREE && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10)) { if (require_constant_value) - result = - fold_build_call_array_initializer_loc (loc, TREE_TYPE (fntype), - function, nargs, argarray); + result + = fold_build_call_array_initializer_loc (loc, TREE_TYPE (fntype), + function, nargs, argarray); else result = fold_build_call_array_loc (loc, TREE_TYPE (fntype), function, nargs, argarray); @@ -3129,6 +3129,10 @@ build_function_call_vec (location_t loc, else result = build_call_array_loc (loc, TREE_TYPE (fntype), function, nargs, argarray); + /* If -Wnonnull warning has been diagnosed, avoid diagnosing it again + later. */ + if (warned_p && TREE_CODE (result) == CALL_EXPR) + TREE_NO_WARNING (result) = 1; /* In this improbable scenario, a nested function returns a VM type. Create a TARGET_EXPR so that the call always has a LHS, much as --- gcc/tree.c.jj 2016-12-13 11:51:33.000000000 +0100 +++ gcc/tree.c 2016-12-16 10:24:03.137971569 +0100 @@ -14313,6 +14313,56 @@ combined_fn_name (combined_fn fn) return internal_fn_name (as_internal_fn (fn)); } +/* Return a bitmap with a bit set corresponding to each argument in + a function call type FNTYPE declared with attribute nonnull, + or null if none of the function's argument are nonnull. The caller + must free the bitmap. */ + +bitmap +get_nonnull_args (const_tree fntype) +{ + if (fntype == NULL_TREE) + return NULL; + + tree attrs = TYPE_ATTRIBUTES (fntype); + if (!attrs) + return NULL; + + bitmap argmap = NULL; + + /* A function declaration can specify multiple attribute nonnull, + each with zero or more arguments. The loop below creates a bitmap + representing a union of all the arguments. An empty (but non-null) + bitmap means that all arguments have been declaraed nonnull. */ + for ( ; attrs; attrs = TREE_CHAIN (attrs)) + { + attrs = lookup_attribute ("nonnull", attrs); + if (!attrs) + break; + + if (!argmap) + argmap = BITMAP_ALLOC (NULL); + + if (!TREE_VALUE (attrs)) + { + /* Clear the bitmap in case a previous attribute nonnull + set it and this one overrides it for all arguments. */ + bitmap_clear (argmap); + return argmap; + } + + /* Iterate over the indices of the format arguments declared nonnull + and set a bit for each. */ + for (tree idx = TREE_VALUE (attrs); idx; idx = TREE_CHAIN (idx)) + { + unsigned int val = TREE_INT_CST_LOW (TREE_VALUE (idx)) - 1; + bitmap_set_bit (argmap, val); + } + } + + return argmap; +} + #if CHECKING_P namespace selftest { --- gcc/c-family/c-common.c.jj 2016-12-14 20:28:12.000000000 +0100 +++ gcc/c-family/c-common.c 2016-12-16 10:35:29.404907394 +0100 @@ -5250,11 +5250,21 @@ c_determine_visibility (tree decl) return false; } +/* Data to communicate through check_function_arguments_recurse between + check_function_nonnull and check_nonnull_arg. */ + +struct nonnull_arg_ctx +{ + location_t loc; + bool warned_p; +}; + /* Check the argument list of a function call for null in argument slots that are marked as requiring a non-null pointer argument. The NARGS - arguments are passed in the array ARGARRAY. */ + arguments are passed in the array ARGARRAY. Return true if we have + warned. */ -static void +static bool check_function_nonnull (location_t loc, tree attrs, int nargs, tree *argarray) { tree a; @@ -5262,7 +5272,7 @@ check_function_nonnull (location_t loc, attrs = lookup_attribute ("nonnull", attrs); if (attrs == NULL_TREE) - return; + return false; a = attrs; /* See if any of the nonnull attributes has no arguments. If so, @@ -5273,9 +5283,10 @@ check_function_nonnull (location_t loc, a = lookup_attribute ("nonnull", TREE_CHAIN (a)); while (a != NULL_TREE && TREE_VALUE (a) != NULL_TREE); + struct nonnull_arg_ctx ctx = { loc, false }; if (a != NULL_TREE) for (i = 0; i < nargs; i++) - check_function_arguments_recurse (check_nonnull_arg, &loc, argarray[i], + check_function_arguments_recurse (check_nonnull_arg, &ctx, argarray[i], i + 1); else { @@ -5291,10 +5302,11 @@ check_function_nonnull (location_t loc, } if (a != NULL_TREE) - check_function_arguments_recurse (check_nonnull_arg, &loc, + check_function_arguments_recurse (check_nonnull_arg, &ctx, argarray[i], i + 1); } } + return ctx.warned_p; } /* Check that the Nth argument of a function call (counting backwards @@ -5379,7 +5391,7 @@ nonnull_check_p (tree args, unsigned HOS static void check_nonnull_arg (void *ctx, tree param, unsigned HOST_WIDE_INT param_num) { - location_t *ploc = (location_t *) ctx; + struct nonnull_arg_ctx *pctx = (struct nonnull_arg_ctx *) ctx; /* Just skip checking the argument if it's not a pointer. This can happen if the "nonnull" attribute was given without an operand @@ -5391,9 +5403,12 @@ check_nonnull_arg (void *ctx, tree param /* When not optimizing diagnose the simple cases of null arguments. When optimization is enabled defer the checking until expansion when more cases can be detected. */ - if (!optimize && integer_zerop (param)) - warning_at (*ploc, OPT_Wnonnull, "null argument where non-null required " - "(argument %lu)", (unsigned long) param_num); + if (integer_zerop (param)) + { + warning_at (pctx->loc, OPT_Wnonnull, "null argument where non-null " + "required (argument %lu)", (unsigned long) param_num); + pctx->warned_p = true; + } } /* Helper for nonnull attribute handling; fetch the operand number @@ -5587,16 +5602,19 @@ attribute_fallthrough_p (tree attr) /* Check for valid arguments being passed to a function with FNTYPE. There are NARGS arguments in the array ARGARRAY. LOC should be used for - diagnostics. */ -void + diagnostics. Return true if -Wnonnull warning has been diagnosed. */ +bool check_function_arguments (location_t loc, const_tree fntype, int nargs, tree *argarray) { + bool warned_p = false; + /* Check for null being passed in a pointer argument that must be non-null. We also need to do this if format checking is enabled. */ if (warn_nonnull) - check_function_nonnull (loc, TYPE_ATTRIBUTES (fntype), nargs, argarray); + warned_p = check_function_nonnull (loc, TYPE_ATTRIBUTES (fntype), + nargs, argarray); /* Check for errors in format strings. */ @@ -5605,6 +5623,7 @@ check_function_arguments (location_t loc if (warn_format) check_function_sentinel (fntype, nargs, argarray); + return warned_p; } /* Generic argument checking recursion routine. PARAM is the argument to --- gcc/c-family/c-common.h.jj 2016-11-23 19:40:42.000000000 +0100 +++ gcc/c-family/c-common.h 2016-12-16 09:46:41.471485210 +0100 @@ -804,7 +804,7 @@ extern const char *fname_as_string (int) extern tree fname_decl (location_t, unsigned, tree); extern int check_user_alignment (const_tree, bool); -extern void check_function_arguments (location_t loc, const_tree, int, tree *); +extern bool check_function_arguments (location_t loc, const_tree, int, tree *); extern void check_function_arguments_recurse (void (*) (void *, tree, unsigned HOST_WIDE_INT), --- gcc/calls.c.jj 2016-12-14 20:28:16.000000000 +0100 +++ gcc/calls.c 2016-12-16 10:34:18.343845965 +0100 @@ -1501,91 +1501,6 @@ maybe_complain_about_tail_call (tree cal error_at (EXPR_LOCATION (call_expr), "cannot tail-call: %s", reason); } -/* Return a bitmap with a bit set corresponding to each argument in - a function call expression CALLEXPR declared with attribute nonnull, - or null if none of the function's argument are nonnull. The caller - must free the bitmap. */ - -bitmap -get_nonnull_args (const_tree callexpr) -{ - tree fn = CALL_EXPR_FN (callexpr); - if (!fn || TREE_CODE (fn) != ADDR_EXPR) - return NULL; - - tree fndecl = TREE_OPERAND (fn, 0); - tree fntype = TREE_TYPE (fndecl); - tree attrs = TYPE_ATTRIBUTES (fntype); - if (!attrs) - return NULL; - - bitmap argmap = NULL; - - /* A function declaration can specify multiple attribute nonnull, - each with zero or more arguments. The loop below creates a bitmap - representing a union of all the arguments. An empty (but non-null) - bitmap means that all arguments have been declaraed nonnull. */ - for ( ; attrs; attrs = TREE_CHAIN (attrs)) - { - attrs = lookup_attribute ("nonnull", attrs); - if (!attrs) - break; - - if (!argmap) - argmap = BITMAP_ALLOC (NULL); - - if (!TREE_VALUE (attrs)) - { - /* Clear the bitmap in case a previous attribute nonnull - set it and this one overrides it for all arguments. */ - bitmap_clear (argmap); - return argmap; - } - - /* Iterate over the indices of the format arguments declared nonnull - and set a bit for each. */ - for (tree idx = TREE_VALUE (attrs); idx; idx = TREE_CHAIN (idx)) - { - unsigned int val = TREE_INT_CST_LOW (TREE_VALUE (idx)) - 1; - bitmap_set_bit (argmap, val); - } - } - - return argmap; -} - -/* In a call EXP to a function FNDECL some of whose arguments may have - been declared with attribute nonnull as described by NONNULLARGS, - check actual argument ARG at the zero-based position ARGPOS for - equality to null and issue a warning if it is not expected to be. */ - -static void -maybe_warn_null_arg (tree fndecl, tree exp, tree arg, - unsigned argpos, bitmap nonnullargs) -{ - if (!optimize - || !nonnullargs - || TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE - || !integer_zerop (arg) - || (!bitmap_empty_p (nonnullargs) - && !bitmap_bit_p (nonnullargs, argpos))) - return; - - ++argpos; - - location_t exploc EXPR_LOCATION (exp); - - if (warning_at (exploc, OPT_Wnonnull, - "argument %u null where non-null expected", argpos)) - { - if (DECL_IS_BUILTIN (fndecl)) - inform (exploc, "in a call to built-in function %qD", fndecl); - else - inform (DECL_SOURCE_LOCATION (fndecl), - "in a call to function %qD declared here", fndecl); - } -} - /* Fill in ARGS_SIZE and ARGS array based on the parameters found in CALL_EXPR EXP. @@ -1769,9 +1684,6 @@ initialize_argument_information (int num /* Array for up to the two attribute alloc_size arguments. */ tree alloc_args[] = { NULL_TREE, NULL_TREE }; - /* Get a bitmap of pointer argument numbers declared attribute nonnull. */ - bitmap nonnullargs = get_nonnull_args (exp); - /* I counts args in order (to be) pushed; ARGPOS counts in order written. */ for (argpos = 0; argpos < num_actuals; i--, argpos++) { @@ -2003,11 +1915,6 @@ initialize_argument_information (int num if (args[i].locate.size.var) ADD_PARM_SIZE (*args_size, args[i].locate.size.var); - /* Check pointer argument for equality to NULL that is being passed - to arguments declared with attribute nonnull and warn. */ - maybe_warn_null_arg (fndecl, exp, args[i].tree_value, argpos, - nonnullargs); - /* Increment ARGS_SO_FAR, which has info about which arg-registers have been used, etc. */ @@ -2028,8 +1935,6 @@ initialize_argument_information (int num alloc_size. */ maybe_warn_alloc_args_overflow (fndecl, exp, alloc_args, alloc_idx); } - - BITMAP_FREE (nonnullargs); } /* Update ARGS_SIZE to contain the total size for the argument block. --- gcc/passes.def.jj 2016-12-02 22:22:31.000000000 +0100 +++ gcc/passes.def 2016-12-16 10:33:54.945155013 +0100 @@ -193,6 +193,7 @@ along with GCC; see the file COPYING3. They ensure memory accesses are not indirect wherever possible. */ NEXT_PASS (pass_strip_predict_hints); NEXT_PASS (pass_ccp, true /* nonzero_p */); + NEXT_PASS (pass_post_ipa_warn); /* After CCP we rewrite no longer addressed locals into SSA form if possible. */ NEXT_PASS (pass_complete_unrolli); @@ -360,6 +361,7 @@ along with GCC; see the file COPYING3. NEXT_PASS (pass_lower_vector_ssa); /* Perform simple scalar cleanup which is constant/copy propagation. */ NEXT_PASS (pass_ccp, true /* nonzero_p */); + NEXT_PASS (pass_post_ipa_warn); NEXT_PASS (pass_object_sizes); /* Fold remaining builtins. */ NEXT_PASS (pass_fold_builtins); Jakub