public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Move -Wrestrict warning later in the FEs and fix some issues in it (PR c++/79588)
@ 2017-02-20 20:38 Jakub Jelinek
  2017-02-21 20:45 ` Jason Merrill
  2017-02-23 22:13 ` Jeff Law
  0 siblings, 2 replies; 4+ messages in thread
From: Jakub Jelinek @ 2017-02-20 20:38 UTC (permalink / raw)
  To: Jason Merrill, Joseph S. Myers; +Cc: gcc-patches

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  <jakub@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

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] Move -Wrestrict warning later in the FEs and fix some issues in it (PR c++/79588)
  2017-02-20 20:38 [PATCH] Move -Wrestrict warning later in the FEs and fix some issues in it (PR c++/79588) Jakub Jelinek
@ 2017-02-21 20:45 ` Jason Merrill
  2017-02-23 22:13 ` Jeff Law
  1 sibling, 0 replies; 4+ messages in thread
From: Jason Merrill @ 2017-02-21 20:45 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Joseph S. Myers, gcc-patches List

OK if Joseph doesn't object in the next couple of days.

On Mon, Feb 20, 2017 at 12:35 PM, Jakub Jelinek <jakub@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  <jakub@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

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] Move -Wrestrict warning later in the FEs and fix some issues in it (PR c++/79588)
  2017-02-20 20:38 [PATCH] Move -Wrestrict warning later in the FEs and fix some issues in it (PR c++/79588) Jakub Jelinek
  2017-02-21 20:45 ` Jason Merrill
@ 2017-02-23 22:13 ` Jeff Law
  2017-02-24 20:44   ` Jakub Jelinek
  1 sibling, 1 reply; 4+ messages in thread
From: Jeff Law @ 2017-02-23 22:13 UTC (permalink / raw)
  To: Jakub Jelinek, Jason Merrill, Joseph S. Myers; +Cc: gcc-patches

On 02/20/2017 01:35 PM, Jakub Jelinek 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  <jakub@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.
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.

jeff

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] Move -Wrestrict warning later in the FEs and fix some issues in it (PR c++/79588)
  2017-02-23 22:13 ` Jeff Law
@ 2017-02-24 20:44   ` Jakub Jelinek
  0 siblings, 0 replies; 4+ messages in thread
From: Jakub Jelinek @ 2017-02-24 20:44 UTC (permalink / raw)
  To: Jeff Law; +Cc: Jason Merrill, Joseph S. Myers, gcc-patches

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  <jakub@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

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2017-02-24 20:42 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-20 20:38 [PATCH] Move -Wrestrict warning later in the FEs and fix some issues in it (PR c++/79588) Jakub Jelinek
2017-02-21 20:45 ` Jason Merrill
2017-02-23 22:13 ` Jeff Law
2017-02-24 20:44   ` Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).