re PR tree-optimization/35503 (Warning about restricted pointers?)
2016-11-13 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org> PR c/35503 * doc/invoke.texi: Document Wrestrict. * pretty-print.c (pp_format): Add case for "Z" specifier. (test_pp_format): Test "Z" specifier. c-family/ * c-common.h (warn_for_restrict): Declare. * c-warn.c: Include gcc-rich-location.h. (warn_for_restrict): New function. * c-format.c (gcc_tdiag_char_table): Add entry for "Z" specifier. (gcc_cdiag_char_table): Likewise. (gcc_cxxdiag_char_table): Likewise. * c.opt (Wrestrict): New option. c/ * c-parser.c (c_parser_postfix_expression_after_primary): Call warn_for_restrict. cp/ * parser.c (cp_parser_postfix_pexpression): Call warn_for_restrict. testsuite/ * c-c++-common/pr35503-1.c: New test. * c-c++-common/pr35503-2.c: Likewise. * c-c++-common/pr35503-3.c: Likewise. * gcc.dg/format/gcc_diag-1.c: Add tests for "Z" specifier. From-SVN: r242366
This commit is contained in:
parent
8d5a1b4f64
commit
975672f357
|
@ -1,3 +1,23 @@
|
|||
2016-11-13 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
|
||||
|
||||
PR c/35503
|
||||
* doc/invoke.texi: Document Wrestrict.
|
||||
* pretty-print.c (pp_format): Add case for "Z" specifier.
|
||||
(test_pp_format): Test "Z" specifier.
|
||||
c-family/
|
||||
* c-common.h (warn_for_restrict): Declare.
|
||||
* c-warn.c: Include gcc-rich-location.h.
|
||||
(warn_for_restrict): New function.
|
||||
* c-format.c (gcc_tdiag_char_table): Add entry for "Z" specifier.
|
||||
(gcc_cdiag_char_table): Likewise.
|
||||
(gcc_cxxdiag_char_table): Likewise.
|
||||
* c.opt (Wrestrict): New option.
|
||||
c/
|
||||
* c-parser.c (c_parser_postfix_expression_after_primary): Call
|
||||
warn_for_restrict.
|
||||
cp/
|
||||
* parser.c (cp_parser_postfix_pexpression): Call warn_for_restrict.
|
||||
|
||||
2016-11-13 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* ipa-icf.c (sem_function::merge): Do not create a wrapper also if the
|
||||
|
|
|
@ -1492,6 +1492,7 @@ extern void warnings_for_convert_and_check (location_t, tree, tree, tree);
|
|||
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> *);
|
||||
|
||||
/* Places where an lvalue, or modifiable lvalue, may be required.
|
||||
Used to select diagnostic messages in lvalue_error and
|
||||
|
|
|
@ -713,6 +713,7 @@ static const format_char_info gcc_tdiag_char_table[] =
|
|||
{ "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "cR", NULL },
|
||||
{ "<>'R",0, STD_C89, NOARGUMENTS, "", "", NULL },
|
||||
{ "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL },
|
||||
{ "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_tdiag_char_table[0] },
|
||||
{ NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -736,6 +737,7 @@ static const format_char_info gcc_cdiag_char_table[] =
|
|||
{ "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "cR", NULL },
|
||||
{ "<>'R",0, STD_C89, NOARGUMENTS, "", "", NULL },
|
||||
{ "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL },
|
||||
{ "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_tdiag_char_table[0] },
|
||||
{ NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -762,6 +764,7 @@ static const format_char_info gcc_cxxdiag_char_table[] =
|
|||
{ "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "cR", NULL },
|
||||
{ "<>'R",0, STD_C89, NOARGUMENTS, "", "", NULL },
|
||||
{ "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL },
|
||||
{ "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_tdiag_char_table[0] },
|
||||
{ NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "diagnostic.h"
|
||||
#include "intl.h"
|
||||
#include "asan.h"
|
||||
#include "gcc-rich-location.h"
|
||||
|
||||
/* Print a warning if a constant expression had overflow in folding.
|
||||
Invoke this function on every expression that the language
|
||||
|
@ -2161,3 +2162,58 @@ maybe_warn_bool_compare (location_t loc, enum tree_code code, tree op0,
|
|||
"with boolean expression is always false", cst);
|
||||
}
|
||||
}
|
||||
|
||||
/* Warn if an argument at position param_pos is passed to a
|
||||
restrict-qualified param, and it aliases with another argument. */
|
||||
|
||||
void
|
||||
warn_for_restrict (unsigned param_pos, vec<tree, va_gc> *args)
|
||||
{
|
||||
tree arg = (*args)[param_pos];
|
||||
if (TREE_VISITED (arg) || operand_equal_p (arg, null_pointer_node, 0))
|
||||
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;
|
||||
|
||||
FOR_EACH_VEC_ELT (*args, i, current_arg)
|
||||
{
|
||||
if (i == param_pos)
|
||||
continue;
|
||||
|
||||
tree current_arg = (*args)[i];
|
||||
if (operand_equal_p (arg, current_arg, 0))
|
||||
{
|
||||
TREE_VISITED (current_arg) = 1;
|
||||
arg_positions[arg_positions_len++] = (i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (arg_positions_len == 0)
|
||||
{
|
||||
free (arg_positions);
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < arg_positions_len; i++)
|
||||
{
|
||||
unsigned pos = arg_positions[i];
|
||||
tree arg = (*args)[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,
|
||||
"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);
|
||||
}
|
||||
|
|
|
@ -1085,6 +1085,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 ObjC C++ ObjC++ Var(warn_restrict) Warning LangEnabledBy(C ObjC C++ ObjC++)
|
||||
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++).
|
||||
|
|
|
@ -8451,6 +8451,28 @@ 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)
|
||||
{
|
||||
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
|
||||
|
|
|
@ -6925,6 +6925,29 @@ 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)
|
||||
{
|
||||
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);
|
||||
|
|
|
@ -292,7 +292,7 @@ Objective-C and Objective-C++ Dialects}.
|
|||
-Wparentheses -Wno-pedantic-ms-format @gol
|
||||
-Wplacement-new -Wplacement-new=@var{n} @gol
|
||||
-Wpointer-arith -Wno-pointer-to-int-cast @gol
|
||||
-Wno-pragmas -Wredundant-decls -Wno-return-local-addr @gol
|
||||
-Wno-pragmas -Wredundant-decls -Wrestrict -Wno-return-local-addr @gol
|
||||
-Wreturn-type -Wsequence-point -Wshadow -Wno-shadow-ivar @gol
|
||||
-Wshadow=global, -Wshadow=local, -Wshadow=compatible-local @gol
|
||||
-Wshift-overflow -Wshift-overflow=@var{n} @gol
|
||||
|
@ -6187,6 +6187,12 @@ reduce the padding and so make the structure smaller.
|
|||
Warn if anything is declared more than once in the same scope, even in
|
||||
cases where multiple declaration is valid and changes nothing.
|
||||
|
||||
@item -Wrestrict
|
||||
@opindex Wrestrict
|
||||
@opindex Wno-restrict
|
||||
Warn when an argument passed to a restrict-qualified parameter
|
||||
aliases with another argument.
|
||||
|
||||
@item -Wnested-externs @r{(C and Objective-C only)}
|
||||
@opindex Wnested-externs
|
||||
@opindex Wno-nested-externs
|
||||
|
|
|
@ -294,6 +294,8 @@ pp_indent (pretty_printer *pp)
|
|||
integer.
|
||||
%Ns: likewise, but length specified as constant in the format string.
|
||||
Flag 'q': quote formatted text (must come immediately after '%').
|
||||
%Z: Requires two arguments - array of int, and len. Prints elements
|
||||
of the array.
|
||||
|
||||
Arguments can be used sequentially, or through %N$ resp. *N$
|
||||
notation Nth argument after the format string. If %N$ / *N$
|
||||
|
@ -610,6 +612,23 @@ pp_format (pretty_printer *pp, text_info *text)
|
|||
(pp, *text->args_ptr, precision, unsigned, "u");
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
{
|
||||
int *v = va_arg (*text->args_ptr, int *);
|
||||
unsigned len = va_arg (*text->args_ptr, unsigned);
|
||||
|
||||
for (unsigned i = 0; i < len; ++i)
|
||||
{
|
||||
pp_scalar (pp, "%i", v[i]);
|
||||
if (i < len - 1)
|
||||
{
|
||||
pp_comma (pp);
|
||||
pp_space (pp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'x':
|
||||
if (wide)
|
||||
pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
|
||||
|
@ -1424,6 +1443,13 @@ test_pp_format ()
|
|||
"`\33[01m\33[Kfoo\33[m\33[K' 12345678", "%qs %x",
|
||||
"foo", 0x12345678);
|
||||
|
||||
/* Verify %Z. */
|
||||
int v[] = { 1, 2, 3 };
|
||||
ASSERT_PP_FORMAT_3 ("1, 2, 3 12345678", "%Z %x", v, 3, 0x12345678);
|
||||
|
||||
int v2[] = { 0 };
|
||||
ASSERT_PP_FORMAT_3 ("0 12345678", "%Z %x", v2, 1, 0x12345678);
|
||||
|
||||
/* Verify that combinations work, along with unformatted text. */
|
||||
assert_pp_format (SELFTEST_LOCATION,
|
||||
"the quick brown fox jumps over the lazy dog",
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
2016-11-13 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
|
||||
|
||||
PR c/35503
|
||||
* c-c++-common/pr35503-1.c: New test.
|
||||
* c-c++-common/pr35503-2.c: Likewise.
|
||||
* c-c++-common/pr35503-3.c: Likewise.
|
||||
* gcc.dg/format/gcc_diag-1.c: Add tests for "Z" specifier.
|
||||
|
||||
2016-11-13 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
PR rtl-optimization/78232
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wrestrict" } */
|
||||
|
||||
int foo (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" } */
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-fdiagnostics-show-caret -Wrestrict" } */
|
||||
|
||||
void f(int *__restrict x, int *y, int *__restrict z, int *w);
|
||||
|
||||
void foo(int alpha, int beta)
|
||||
{
|
||||
f (&alpha, &beta, &alpha, &alpha); /* { dg-warning "passing argument 1 to restrict-qualified parameter aliases with arguments 3, 4" } */
|
||||
|
||||
/* { dg-begin-multiline-output "" }
|
||||
f (&alpha, &beta, &alpha, &alpha);
|
||||
^~~~~~ ~~~~~~ ~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wrestrict" } */
|
||||
|
||||
void f(int *x, int *__restrict y);
|
||||
|
||||
void foo(int a)
|
||||
{
|
||||
f (&a, &a); /* { dg-warning "passing argument 2 to restrict-qualified parameter aliases with argument 1" } */
|
||||
}
|
|
@ -32,7 +32,7 @@ foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p,
|
|||
ullong ull, unsigned int *un, const int *cn, signed char *ss,
|
||||
unsigned char *us, const signed char *css, unsigned int u1,
|
||||
unsigned int u2, location_t *loc, tree t1, union tree_node *t2,
|
||||
tree *t3, tree t4[])
|
||||
tree *t3, tree t4[], int *v, unsigned v_len)
|
||||
{
|
||||
/* Acceptable C90 specifiers, flags and modifiers. */
|
||||
diag ("%%");
|
||||
|
@ -90,6 +90,10 @@ foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p,
|
|||
cdiag ("%v%qv%#v", i, i, i);
|
||||
cxxdiag ("%v%qv%#v", i, i, i);
|
||||
|
||||
tdiag ("%Z", v, v_len);
|
||||
cdiag ("%Z", v, v_len);
|
||||
cxxdiag ("%Z", v, v_len);
|
||||
|
||||
/* Bad stuff with extensions. */
|
||||
diag ("%m", i); /* { dg-warning "format" "extra arg" } */
|
||||
tdiag ("%m", i); /* { dg-warning "format" "extra arg" } */
|
||||
|
@ -133,6 +137,9 @@ foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p,
|
|||
cdiag ("%v", t1); /* { dg-warning "format" "wrong arg" } */
|
||||
cxxdiag ("%v", t1); /* { dg-warning "format" "wrong arg" } */
|
||||
|
||||
tdiag ("%Z"); /* { dg-warning "format" "missing arg" } */
|
||||
tdiag ("%Z", t1); /* { dg-warning "format" "wrong arg" } */
|
||||
|
||||
/* Standard specifiers not accepted in the diagnostic framework. */
|
||||
diag ("%X\n", u); /* { dg-warning "format" "HEX" } */
|
||||
diag ("%f\n", d); /* { dg-warning "format" "float" } */
|
||||
|
|
Loading…
Reference in New Issue