On Thu, Feb 23, 2017 at 03:09:47PM -0700, Jeff Law wrote: > Please refactor the restrict warning bits into their own function, then > calling that from check_function_arguments. That's the style already used > there. > > OK with that change.
Here is what I've committed after another bootstrap/regtest: 2017-02-24 Jakub Jelinek <ja...@redhat.com> PR c++/79588 c-family/ * c-common.c (check_function_restrict): New function. (check_function_arguments): Add FNDECL argument. Call check_function_restrict if -Wrestrict. * 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-02-20 13:43:15.169555324 +0100 +++ gcc/c-family/c-common.c 2017-02-24 19:44:47.239427073 +0100 @@ -5364,6 +5364,49 @@ check_function_sentinel (const_tree fnty } } +/* Check that the same argument isn't passed to restrict arguments + and other arguments. */ + +static void +check_function_restrict (const_tree fndecl, const_tree fntype, + int nargs, tree *argarray) +{ + 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; +} + /* Helper for check_function_nonnull; given a list of operands which must be non-null in ARGS, determine if operand PARAM_NUM should be checked. */ @@ -5605,8 +5648,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 +5667,9 @@ check_function_arguments (location_t loc if (warn_format) check_function_sentinel (fntype, nargs, argarray); + + if (warn_restrict) + check_function_restrict (fndecl, fntype, nargs, argarray); return warned_p; } --- gcc/c-family/c-warn.c.jj 2017-02-20 13:43:15.126555893 +0100 +++ gcc/c-family/c-warn.c 2017-02-24 19:39:43.621454404 +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-02-20 13:43:15.200554914 +0100 +++ gcc/c-family/c-common.h 2017-02-24 19:39:43.622454390 +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-20 13:43:15.041557018 +0100 +++ gcc/c/c-parser.c 2017-02-24 19:39:43.626454337 +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-02-22 22:32:35.477710734 +0100 +++ gcc/c/c-typeck.c 2017-02-24 19:39:43.629454298 +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-24 15:31:49.041955772 +0100 +++ gcc/cp/call.c 2017-02-24 19:39:43.631454271 +0100 @@ -7903,14 +7903,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-22 23:00:21.472093702 +0100 +++ gcc/cp/parser.c 2017-02-24 19:39:43.638454178 +0100 @@ -6934,29 +6934,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-20 13:43:21.485471769 +0100 +++ gcc/cp/typeck.c 2017-02-24 19:39:43.640454152 +0100 @@ -3667,7 +3667,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-24 19:39:43.640454152 +0100 +++ gcc/testsuite/g++.dg/warn/Wrestrict-1.C 2017-02-24 19:39:43.640454152 +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-24 19:39:43.640454152 +0100 +++ gcc/testsuite/g++.dg/warn/Wrestrict-2.C 2017-02-24 19:39:43.640454152 +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