Hi Richard,
I was trying to have a look at PR35503.
The attached patch tries to warn when an argument is passed to a
restrict-qualified parameter
and the argument could alias with other argument.

For the following test-case:
int f2(int *restrict x, int *y);

void f(void)
{
  int a;
  f2 (&a, &a);
}

The patch warns:
test-1.c: In function ‘f’:
test-1.c:6:3: warning: Passing argument 1 to restrict-qualified
parameter may alias with argument 2 [-Wrestrict]
   f2 (&a, &a);
   ^~~~~~~~~~~

However it gives false positives if arg is a string constant as in
following case:
int foo (char *restrict buf, char *restrict fmt, ...);

int f(void)
{
  char buf[10];
  foo (buf, "%s-%s", buf, "hello");
}

The patch gives false positives for argument 2:

test-3.c: In function ‘f’:
test-3.c:6:3: warning: Passing argument 1 to restrict-qualified
parameter may alias with argument 3 [-Wrestrict]
   foo (buf, "%s-%s", buf, "hello");
   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test-3.c:6:3: warning: Passing argument 2 to restrict-qualified
parameter may alias with argument 1 [-Wrestrict]
test-3.c:6:3: warning: Passing argument 2 to restrict-qualified
parameter may alias with argument 3 [-Wrestrict]
test-3.c:6:3: warning: Passing argument 2 to restrict-qualified
parameter may alias with argument 4 [-Wrestrict]

I am using compute_may_aliases() to obtain alias analysis info,
and then using ptr_derefs_may_alias_p(arg, current_arg) to check if
the arguments
could potentially alias. Is that incorrect ?

Thanks,
Prathamesh
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 8d7cc51..5d8263d 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1549,6 +1549,7 @@ OBJS = \
        varpool.o \
        vmsdbgout.o \
        vtable-verify.o \
+       warn-restrict.o \
        web.o \
        wide-int.o \
        wide-int-print.o \
diff --git a/gcc/common.opt b/gcc/common.opt
index 65a9762..afb2327 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -732,6 +732,11 @@ Wmaybe-uninitialized
 Common Var(warn_maybe_uninitialized) Warning EnabledBy(Wuninitialized)
 Warn about maybe uninitialized automatic variables.
 
+Wrestrict
+Common Var(warn_restrict) Warning EanbledBy(Wall)
+Warn when a pointer argument is passed to a parameter qualified with restrict,
+and it potentially aliases with another arguments.
+
 Wunreachable-code
 Common Ignore Warning
 Does nothing. Preserved for backward compatibility.
diff --git a/gcc/passes.def b/gcc/passes.def
index 533157d..2cccd6d 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -141,6 +141,7 @@ along with GCC; see the file COPYING3.  If not see
   NEXT_PASS (pass_ipa_increase_alignment);
   NEXT_PASS (pass_ipa_tm);
   NEXT_PASS (pass_ipa_lower_emutls);
+  NEXT_PASS (pass_ipa_warn_restrict);
   TERMINATE_PASS_LIST (all_small_ipa_passes)
 
   INSERT_PASSES_AFTER (all_regular_ipa_passes)
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index c0059de..90d06b5 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -485,6 +485,7 @@ extern ipa_opt_pass_d 
*make_pass_ipa_whole_program_visibility (gcc::context
                                                               *ctxt);
 extern simple_ipa_opt_pass *make_pass_ipa_increase_alignment (gcc::context
                                                              *ctxt);
+extern simple_ipa_opt_pass *make_pass_ipa_warn_restrict (gcc::context *ctxt);
 extern ipa_opt_pass_d *make_pass_ipa_inline (gcc::context *ctxt);
 extern simple_ipa_opt_pass *make_pass_ipa_free_lang_data (gcc::context *ctxt);
 extern simple_ipa_opt_pass *make_pass_ipa_free_inline_summary (gcc::context
diff --git a/gcc/warn-restrict.c b/gcc/warn-restrict.c
new file mode 100644
index 0000000..fa6d9b1
--- /dev/null
+++ b/gcc/warn-restrict.c
@@ -0,0 +1,131 @@
+/*
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "target.h"
+#include "tree.h"
+#include "gimple.h"
+#include "tree-pass.h"
+#include "tree-streamer.h"
+#include "cgraph.h"
+#include "diagnostic.h"
+#include "calls.h"
+#include "cfganal.h"
+#include "tree-eh.h"
+#include "gimple-iterator.h"
+#include "gimple-walk.h"
+#include "tree-cfg.h"
+#include "tree-ssa-loop-niter.h"
+#include "langhooks.h"
+#include "ipa-utils.h"
+#include "gimple-pretty-print.h"
+#include "cfgloop.h"
+#include "tree-scalar-evolution.h"
+#include "intl.h"
+#include "opts.h"
+#include "fold-const.h"
+
+static void 
+do_warn_restrict (function *fun)
+{
+  push_cfun (fun);
+  compute_may_aliases ();
+
+  cgraph_node *cnode = cgraph_node::get (current_function_decl);
+  for (cgraph_edge *e = cnode->callees; e; e = e->next_callee)
+    {
+      cgraph_node *callee = e->callee->function_symbol ();
+      tree callee_decl = callee->decl;
+      gcall *call_stmt = e->call_stmt;
+
+      unsigned param_pos = 0;
+      for (tree t = TYPE_ARG_TYPES (TREE_TYPE (callee_decl)); t; t = 
TREE_CHAIN (t), param_pos++)
+       {
+         tree type = TREE_VALUE (t);
+         if (POINTER_TYPE_P (type) && TYPE_RESTRICT (type))
+           {
+             tree arg = gimple_call_arg (call_stmt, param_pos);
+             gcc_assert (POINTER_TYPE_P (TREE_TYPE (arg)));
+
+             for (unsigned i = 0; i < gimple_call_num_args (call_stmt); i++)
+               {
+                 if (i == param_pos)
+                   continue;
+
+                 tree current_arg = gimple_call_arg (call_stmt, i);
+                 if (POINTER_TYPE_P (TREE_TYPE (current_arg))
+                     && ptr_derefs_may_alias_p (arg, current_arg))
+                   warning_at (gimple_location (call_stmt), OPT_Wrestrict,
+                               "Passing argument %d to restrict-qualified 
parameter "
+                               "may alias with argument %d",
+                               param_pos + 1, i + 1);
+               }
+           }
+       }
+    }
+
+  pop_cfun ();
+}
+
+namespace {
+
+const pass_data pass_data_warn_restrict =
+{
+  SIMPLE_IPA_PASS, /* type */
+  "*warn-restrict", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  TV_NONE, /* tv_id */
+  0, /* properties required */
+  0, /* properties provided */
+  0, /* properties destroyed */
+  0, /* todo_flags_start */
+  0, /* todo_flags_finish */
+};
+
+class pass_ipa_warn_restrict: public simple_ipa_opt_pass 
+{
+public:
+  pass_ipa_warn_restrict (gcc::context *ctxt)
+    : simple_ipa_opt_pass (pass_data_warn_restrict, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  virtual bool gate (function *) { return warn_restrict; } 
+  virtual unsigned execute (function *);
+}; // class pass_warn_function_noreturn
+
+unsigned
+pass_ipa_warn_restrict::execute (function *)
+{
+  cgraph_node *cnode;
+
+  FOR_EACH_DEFINED_FUNCTION (cnode)
+    do_warn_restrict (DECL_STRUCT_FUNCTION (cnode->decl));
+
+  return 0;
+}
+
+} // anon namespace
+
+simple_ipa_opt_pass *
+make_pass_ipa_warn_restrict (gcc::context *ctxt)
+{
+  return new pass_ipa_warn_restrict (ctxt);
+}

Reply via email to