Hi! As mentioned in the PR, -Wrestrict warning is done way too early, where e.g. default arguments aren't filled up yet (reason for ICE on first testcase) or where arguments in templates aren't instantiated yet (reason why we don't diagnose anything on the second testcase).
This patch moves it later where e.g. -Wformat is diagnosed and fixes some issues I found while looking at the code. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2017-02-20 Jakub Jelinek <ja...@redhat.com> PR c++/79588 c-family/ * c-common.c (check_function_arguments): Add FNDECL argument. Handle -Wrestrict here. * c-warn.c (warn_for_restrict): Remove ARGS argument, add ARGARRAY and NARGS. Use auto_vec for ARG_POSITIONS, simplify. * c-common.h (check_function_arguments): Add FNDECL argument. (warn_for_restrict): Remove ARGS argument, add ARGARRAY and NARGS. c/ * c-parser.c (c_parser_postfix_expression_after_primary): Don't handle -Wrestrict here. * c-typeck.c (build_function_call_vec): Adjust check_function_arguments caller. cp/ * call.c (build_over_call): Call check_function_arguments even for -Wrestrict, adjust check_function_arguments caller. * parser.c (cp_parser_postfix_expression): Don't handle -Wrestrict here. * typeck.c (cp_build_function_call_vec): Adjust check_function_arguments caller. testsuite/ * g++.dg/warn/Wrestrict-1.C: New test. * g++.dg/warn/Wrestrict-2.C: New test. --- gcc/c-family/c-common.c.jj 2017-01-24 23:29:05.000000000 +0100 +++ gcc/c-family/c-common.c 2017-02-20 13:17:06.601211847 +0100 @@ -5605,8 +5605,8 @@ attribute_fallthrough_p (tree attr) There are NARGS arguments in the array ARGARRAY. LOC should be used for diagnostics. Return true if -Wnonnull warning has been diagnosed. */ bool -check_function_arguments (location_t loc, const_tree fntype, int nargs, - tree *argarray) +check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype, + int nargs, tree *argarray) { bool warned_p = false; @@ -5624,6 +5624,44 @@ check_function_arguments (location_t loc if (warn_format) check_function_sentinel (fntype, nargs, argarray); + + if (warn_restrict) + { + int i; + tree parms; + + if (fndecl + && TREE_CODE (fndecl) == FUNCTION_DECL + && DECL_ARGUMENTS (fndecl)) + parms = DECL_ARGUMENTS (fndecl); + else + parms = TYPE_ARG_TYPES (fntype); + + for (i = 0; i < nargs; i++) + TREE_VISITED (argarray[i]) = 0; + + for (i = 0; i < nargs && parms && parms != void_list_node; i++) + { + tree type; + if (TREE_CODE (parms) == PARM_DECL) + { + type = TREE_TYPE (parms); + parms = DECL_CHAIN (parms); + } + else + { + type = TREE_VALUE (parms); + parms = TREE_CHAIN (parms); + } + if (POINTER_TYPE_P (type) + && TYPE_RESTRICT (type) + && !TYPE_READONLY (TREE_TYPE (type))) + warn_for_restrict (i, argarray, nargs); + } + + for (i = 0; i < nargs; i++) + TREE_VISITED (argarray[i]) = 0; + } return warned_p; } --- gcc/c-family/c-warn.c.jj 2017-02-15 18:06:19.000000000 +0100 +++ gcc/c-family/c-warn.c 2017-02-20 12:36:29.008455672 +0100 @@ -2170,55 +2170,49 @@ maybe_warn_bool_compare (location_t loc, restrict-qualified param, and it aliases with another argument. */ void -warn_for_restrict (unsigned param_pos, vec<tree, va_gc> *args) +warn_for_restrict (unsigned param_pos, tree *argarray, unsigned nargs) { - tree arg = (*args)[param_pos]; - if (TREE_VISITED (arg) || operand_equal_p (arg, null_pointer_node, 0)) + tree arg = argarray[param_pos]; + if (TREE_VISITED (arg) || integer_zerop (arg)) return; location_t loc = EXPR_LOC_OR_LOC (arg, input_location); gcc_rich_location richloc (loc); unsigned i; - tree current_arg; - int *arg_positions = XNEWVEC (int, args->length ()); - unsigned arg_positions_len = 0; + auto_vec<int, 16> arg_positions; - FOR_EACH_VEC_ELT (*args, i, current_arg) + for (i = 0; i < nargs; i++) { if (i == param_pos) continue; - tree current_arg = (*args)[i]; + tree current_arg = argarray[i]; if (operand_equal_p (arg, current_arg, 0)) { TREE_VISITED (current_arg) = 1; - arg_positions[arg_positions_len++] = (i + 1); + arg_positions.safe_push (i + 1); } } - if (arg_positions_len == 0) - { - free (arg_positions); - return; - } + if (arg_positions.is_empty ()) + return; - for (unsigned i = 0; i < arg_positions_len; i++) + int pos; + FOR_EACH_VEC_ELT (arg_positions, i, pos) { - unsigned pos = arg_positions[i]; - tree arg = (*args)[pos - 1]; + arg = argarray[pos - 1]; if (EXPR_HAS_LOCATION (arg)) richloc.add_range (EXPR_LOCATION (arg), false); } - warning_at_rich_loc_n (&richloc, OPT_Wrestrict, arg_positions_len, + warning_at_rich_loc_n (&richloc, OPT_Wrestrict, arg_positions.length (), "passing argument %i to restrict-qualified parameter" " aliases with argument %Z", "passing argument %i to restrict-qualified parameter" " aliases with arguments %Z", - param_pos + 1, arg_positions, arg_positions_len); - - free (arg_positions); + param_pos + 1, arg_positions.address (), + arg_positions.length ()); } /* Callback function to determine whether an expression TP or one of its --- gcc/c-family/c-common.h.jj 2017-01-24 23:29:05.000000000 +0100 +++ gcc/c-family/c-common.h 2017-02-20 13:00:55.540080276 +0100 @@ -807,7 +807,8 @@ extern const char *fname_as_string (int) extern tree fname_decl (location_t, unsigned, tree); extern int check_user_alignment (const_tree, bool); -extern bool check_function_arguments (location_t loc, const_tree, int, tree *); +extern bool check_function_arguments (location_t loc, const_tree, const_tree, + int, tree *); extern void check_function_arguments_recurse (void (*) (void *, tree, unsigned HOST_WIDE_INT), @@ -1501,7 +1502,7 @@ extern void warnings_for_convert_and_che extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool, bool); extern void warn_for_omitted_condop (location_t, tree); -extern void warn_for_restrict (unsigned, vec<tree, va_gc> *); +extern void warn_for_restrict (unsigned, tree *, unsigned); /* Places where an lvalue, or modifiable lvalue, may be required. Used to select diagnostic messages in lvalue_error and --- gcc/c/c-parser.c.jj 2017-02-16 13:01:31.000000000 +0100 +++ gcc/c/c-parser.c 2017-02-20 12:22:55.610210942 +0100 @@ -8418,28 +8418,6 @@ c_parser_postfix_expression_after_primar warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask); } - if (TREE_CODE (expr.value) == FUNCTION_DECL && warn_restrict) - { - unsigned i; - tree arg; - FOR_EACH_VEC_SAFE_ELT (exprlist, i, arg) - TREE_VISITED (arg) = 0; - - unsigned param_pos = 0; - function_args_iterator iter; - tree t; - FOREACH_FUNCTION_ARGS (TREE_TYPE (expr.value), t, iter) - { - if (POINTER_TYPE_P (t) && TYPE_RESTRICT (t) - && !TYPE_READONLY (TREE_TYPE (t))) - warn_for_restrict (param_pos, exprlist); - param_pos++; - } - - FOR_EACH_VEC_SAFE_ELT (exprlist, i, arg) - TREE_VISITED (arg) = 0; - } - start = expr.get_start (); finish = parser->tokens_buf[0].get_finish (); expr.value --- gcc/c/c-typeck.c.jj 2017-01-21 02:25:57.000000000 +0100 +++ gcc/c/c-typeck.c 2017-02-20 13:01:36.829532979 +0100 @@ -3110,7 +3110,8 @@ build_function_call_vec (location_t loc, return error_mark_node; /* Check that the arguments to the function are valid. */ - bool warned_p = check_function_arguments (loc, fntype, nargs, argarray); + bool warned_p = check_function_arguments (loc, fundecl, fntype, + nargs, argarray); if (name != NULL_TREE && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10)) --- gcc/cp/call.c.jj 2017-02-17 18:29:21.000000000 +0100 +++ gcc/cp/call.c 2017-02-20 13:03:21.874140599 +0100 @@ -7900,14 +7900,17 @@ build_over_call (struct z_candidate *can the check_function_arguments function might warn about something. */ bool warned_p = false; - if (warn_nonnull || warn_format || warn_suggest_attribute_format) + if (warn_nonnull + || warn_format + || warn_suggest_attribute_format + || warn_restrict) { tree *fargs = (!nargs ? argarray : (tree *) alloca (nargs * sizeof (tree))); for (j = 0; j < nargs; j++) fargs[j] = maybe_constant_value (argarray[j]); - warned_p = check_function_arguments (input_location, TREE_TYPE (fn), + warned_p = check_function_arguments (input_location, fn, TREE_TYPE (fn), nargs, fargs); } --- gcc/cp/parser.c.jj 2017-02-18 14:12:36.000000000 +0100 +++ gcc/cp/parser.c 2017-02-20 12:21:32.257313679 +0100 @@ -6933,29 +6933,6 @@ cp_parser_postfix_expression (cp_parser warn_for_memset (input_location, arg0, arg2, literal_mask); } - if (TREE_CODE (postfix_expression) == FUNCTION_DECL - && warn_restrict) - { - unsigned i; - tree arg; - FOR_EACH_VEC_SAFE_ELT (args, i, arg) - TREE_VISITED (arg) = 0; - - unsigned param_pos = 0; - for (tree decl = DECL_ARGUMENTS (postfix_expression); - decl != NULL_TREE; - decl = DECL_CHAIN (decl), param_pos++) - { - tree type = TREE_TYPE (decl); - if (POINTER_TYPE_P (type) && TYPE_RESTRICT (type) - && !TYPE_READONLY (TREE_TYPE (type))) - warn_for_restrict (param_pos, args); - } - - FOR_EACH_VEC_SAFE_ELT (args, i, arg) - TREE_VISITED (arg) = 0; - } - if (TREE_CODE (postfix_expression) == COMPONENT_REF) { tree instance = TREE_OPERAND (postfix_expression, 0); --- gcc/cp/typeck.c.jj 2017-02-13 20:30:33.000000000 +0100 +++ gcc/cp/typeck.c 2017-02-20 13:04:10.994489395 +0100 @@ -3661,7 +3661,7 @@ cp_build_function_call_vec (tree functio /* Check for errors in format strings and inappropriately null parameters. */ - bool warned_p = check_function_arguments (input_location, fntype, + bool warned_p = check_function_arguments (input_location, fndecl, fntype, nargs, argarray); ret = build_cxx_call (function, nargs, argarray, complain); --- gcc/testsuite/g++.dg/warn/Wrestrict-1.C.jj 2017-02-18 18:07:19.535116220 +0100 +++ gcc/testsuite/g++.dg/warn/Wrestrict-1.C 2017-02-18 18:05:52.000000000 +0100 @@ -0,0 +1,12 @@ +// PR c++/79588 +// { dg-do compile } +// { dg-options "-Wrestrict" } + +void foo (char *__restrict, char *__restrict = __null); + +void +bar (char *p) +{ + foo (p, p); // { dg-warning "to restrict-qualified parameter aliases with" } + foo (p); +} --- gcc/testsuite/g++.dg/warn/Wrestrict-2.C.jj 2017-02-20 13:07:34.635789299 +0100 +++ gcc/testsuite/g++.dg/warn/Wrestrict-2.C 2017-02-20 12:55:12.000000000 +0100 @@ -0,0 +1,30 @@ +// PR c++/79588 +// { dg-do compile } +// { dg-options "-Wrestrict" } + +void foo (char *__restrict, char *__restrict = __null); + +template <int N> +void +bar (char **p) +{ + foo (p[0], p[0]); // { dg-warning "to restrict-qualified parameter aliases with" } + foo (p[0], p[N]); // { dg-warning "to restrict-qualified parameter aliases with" } + foo (p[0]); +} + +template <int N> +void +bar2 (char **p) +{ + foo (p[0], p[0]); // { dg-warning "to restrict-qualified parameter aliases with" } + foo (p[0], p[N]); // { dg-bogus "to restrict-qualified parameter aliases with" } + foo (p[0]); +} + +void +baz (char **p) +{ + bar<0> (p); + bar2<1> (p); +} Jakub