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
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" */ +}