OK if Joseph doesn't object in the next couple of days.
On Mon, Feb 20, 2017 at 12:35 PM, Jakub Jelinek <ja...@redhat.com> wrote: > 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