PR35503 - warn for restrict pointer
Prathamesh Kulkarni
prathamesh.kulkarni@linaro.org
Fri Aug 26 11:39:00 GMT 2016
Hi,
The following patch adds option -Wrestrict that warns when an argument
is passed to a restrict qualified parameter and it aliases with
another argument.
eg:
int foo (const char *__restrict buf, const char *__restrict fmt, ...);
void f(void)
{
char buf[100] = "hello";
foo (buf, "%s-%s", buf, "world");
}
With the patch, C FE warns:
test-3.c: In function ‘f’:
test-3.c:6:3: warning: passing argument 1 to restrict qualified
parameter aliases with argument 3
foo (buf, "%s-%s", buf, "world");
^~~
However with C++FE it appears TYPE_RESTRICT is not set for the
parameters (buf and fmt)
and hence the warning doesn't get emitted for C++.
C FE sets TYPE_RESTRICT for them. I am not sure how to workaround this
issue, and would be grateful for suggestions.
Thanks,
Prathamesh
-------------- next part --------------
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 3feb910..e1f2823 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -13057,4 +13057,35 @@ diagnose_mismatched_attributes (tree olddecl, tree newdecl)
return warned;
}
+/* Warn if an argument is passed to a restrict-qualified param,
+ and it aliases with another argument. */
+
+void
+warn_for_restrict (location_t loc, tree fn_decl, vec<tree, va_gc> *args)
+{
+ unsigned param_pos = 0;
+
+ for (tree t = TYPE_ARG_TYPES (TREE_TYPE (fn_decl)); t; t = TREE_CHAIN (t), param_pos++)
+ {
+ tree type = TREE_VALUE (t);
+ if (POINTER_TYPE_P (type) && TYPE_RESTRICT (type))
+ {
+ tree arg = (*args)[param_pos];
+ gcc_assert (POINTER_TYPE_P (TREE_TYPE (arg)));
+
+ for (unsigned i = 0; i < args->length (); ++i)
+ {
+ if (i == param_pos)
+ continue;
+
+ tree current_arg = (*args)[i];
+ if (operand_equal_p (arg, current_arg, 0))
+ warning_at (loc, 0,
+ "passing argument %u to restrict qualified parameter aliases with "
+ "argument %u\n", param_pos + 1, i + 1);
+ }
+ }
+ }
+}
+
#include "gt-c-family-c-common.h"
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index bc22baa..006cb13 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -920,6 +920,7 @@ extern void c_parse_final_cleanups (void);
extern void warn_for_omitted_condop (location_t, tree);
extern void warn_for_memset (location_t, tree, tree, int);
+extern void warn_for_restrict (location_t, tree, vec<tree, va_gc> *);
/* These macros provide convenient access to the various _STMT nodes. */
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index a5358ed..a029a86 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -1012,6 +1012,11 @@ Wduplicate-decl-specifier
C ObjC Var(warn_duplicate_decl_specifier) Warning LangEnabledBy(C ObjC,Wall)
Warn when a declaration has duplicate const, volatile, restrict or _Atomic specifier.
+Wrestrict
+C C++ Var(warn_restrict) Warning LangEnabledBy(C C++,Wall)
+Warn when an argument passed to a restrict-qualified parameter aliases with
+another argument.
+
ansi
C ObjC C++ ObjC++
A synonym for -std=c89 (for C) or -std=c++98 (for C++).
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index fe0c95f..0016183 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -8369,6 +8369,9 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask);
}
+ if (TREE_CODE (expr.value) == FUNCTION_DECL && warn_restrict)
+ warn_for_restrict (expr_loc, expr.value, exprlist);
+
start = expr.get_start ();
finish = parser->tokens_buf[0].get_finish ();
expr.value
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 690e928..0fd7cd1 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6878,6 +6878,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
warn_for_memset (input_location, arg0, arg2, literal_mask);
}
+ if (TREE_CODE (postfix_expression) == FUNCTION_DECL
+ && warn_restrict)
+ warn_for_restrict (input_location, postfix_expression, args);
+
if (TREE_CODE (postfix_expression) == COMPONENT_REF)
{
tree instance = TREE_OPERAND (postfix_expression, 0);
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 1f04501..ac8aab5 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -261,7 +261,7 @@ Objective-C and Objective-C++ Dialects}.
-Wc++-compat -Wc++11-compat -Wc++14-compat -Wcast-align -Wcast-qual @gol
-Wchar-subscripts -Wclobbered -Wcomment -Wconditionally-supported @gol
-Wconversion -Wcoverage-mismatch -Wno-cpp -Wdangling-else -Wdate-time @gol
--Wdelete-incomplete @gol
+-Wdelete-incomplete -Wrestrict @gol
-Wno-deprecated -Wno-deprecated-declarations -Wno-designated-init @gol
-Wdisabled-optimization @gol
-Wno-discarded-qualifiers -Wno-discarded-array-qualifiers @gol
@@ -5274,6 +5274,12 @@ compilations.
Warn when deleting a pointer to incomplete type, which may cause
undefined behavior at runtime. This warning is enabled by default.
+@item -Wrestrict @r{(C and C++ only)}
+@opindex Wrestrict
+@opindex Wno-restrict
+Warn when an argument passed to a restrict-qualified parameter
+aliases with another argument
+
@item -Wuseless-cast @r{(C++ and Objective-C++ only)}
@opindex Wuseless-cast
@opindex Wno-useless-cast
diff --git a/gcc/testsuite/c-c++-common/pr35503.c b/gcc/testsuite/c-c++-common/pr35503.c
new file mode 100644
index 0000000..d689a8e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr35503.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-Wrestrict" } */
+
+int foo (const char *__restrict buf, const char *__restrict fmt, ...);
+
+void f(void)
+{
+ char buf[100] = "hello";
+ foo (buf, "%s-%s", buf, "world") /* dg-warning "passing argument 1 to restrict qualified parameter aliases with argument 3" */
+}
More information about the Gcc-patches
mailing list