+2018-08-01 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86650
+ * gimple-pretty-print.c (percent_G_format): Accept a "gimple *"
+ rather than a "gcall *". Directly pass the data of interest
+ to percent_K_format, rather than building a temporary CALL_EXPR
+ to hold it.
+ * gimple-fold.c (gimple_fold_builtin_strncpy): Adjust.
+ (gimple_fold_builtin_strncat): Adjust.
+ * gimple-ssa-warn-restrict.h (check_bounds_or_overlap): Replace
+ gcall* argument with gimple*.
+ * gimple-ssa-warn-restrict.c (check_call): Same.
+ (wrestrict_dom_walker::before_dom_children): Same.
+ (builtin_access::builtin_access): Same.
+ (check_bounds_or_overlap): Same
+ (maybe_diag_overlap): Same.
+ (maybe_diag_offset_bounds): Same.
+ * tree-diagnostic.c (default_tree_printer): Move usage of
+ EXPR_LOCATION (t) and TREE_BLOCK (t) from within percent_K_format
+ to this callsite.
+ * tree-pretty-print.c (percent_K_format): Add argument.
+ * tree-pretty-print.h: Add argument.
+ * tree-ssa-ccp.c (pass_post_ipa_warn::execute): Adjust.
+ * tree-ssa-strlen.c (maybe_diag_stxncpy_trunc): Adjust.
+ (maybe_diag_stxncpy_trunc): Same.
+ (handle_builtin_stxncpy): Same.
+ (handle_builtin_strcat): Same.
+
2018-08-01 Richard Sandiford <richard.sandiford@arm.com>
* match.pd: Optimise pointer range checks.
+2018-08-01 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86650
+ * c-family/c-format.c (gcc_tdiag_char_table): Update comment for "%G".
+ (gcc_cdiag_char_table, gcc_cxxdiag_char_table): Same.
+ (init_dynamic_diag_info): Update from "gcall *" to "gimple *".
+ * c-format.h (T89_G): Update to be "gimple *" rather than
+ "gcall *".
+ (local_gcall_ptr_node): Rename...
+ (local_gimple_ptr_node): ...to this.
+
2018-07-31 David Malcolm <dmalcolm@redhat.com>
* c-format.c (PP_FORMAT_CHAR_TABLE): New macro, based on existing
/* Initialized in init_dynamic_diag_info. */
static GTY(()) tree local_tree_type_node;
-static GTY(()) tree local_gcall_ptr_node;
+static GTY(()) tree local_gimple_ptr_node;
static GTY(()) tree locus;
static bool decode_format_attr (tree, function_format_info *, int);
{ "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL },
{ "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
- /* G requires a "gcall*" argument at runtime. */
+ /* G requires a "gimple*" argument at runtime. */
{ "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
{ NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
{ "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL },
{ "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
- /* G requires a "gcall*" argument at runtime. */
+ /* G requires a "gimple*" argument at runtime. */
{ "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
{ "v", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL },
{ "E", 1,STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL },
{ "K", 1, STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
- /* G requires a "gcall*" argument at runtime. */
+ /* G requires a "gimple*" argument at runtime. */
{ "G", 1, STD_C89,{ T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
/* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.) */
local_tree_type_node = void_type_node;
}
- /* Similar to the above but for gcall*. */
- if (!local_gcall_ptr_node
- || local_gcall_ptr_node == void_type_node)
+ /* Similar to the above but for gimple*. */
+ if (!local_gimple_ptr_node
+ || local_gimple_ptr_node == void_type_node)
{
- if ((local_gcall_ptr_node = maybe_get_identifier ("gcall")))
+ if ((local_gimple_ptr_node = maybe_get_identifier ("gimple")))
{
- local_gcall_ptr_node
- = identifier_global_value (local_gcall_ptr_node);
- if (local_gcall_ptr_node)
+ local_gimple_ptr_node
+ = identifier_global_value (local_gimple_ptr_node);
+ if (local_gimple_ptr_node)
{
- if (TREE_CODE (local_gcall_ptr_node) != TYPE_DECL)
+ if (TREE_CODE (local_gimple_ptr_node) != TYPE_DECL)
{
- error ("%<gcall%> is not defined as a type");
- local_gcall_ptr_node = 0;
+ error ("%<gimple%> is not defined as a type");
+ local_gimple_ptr_node = 0;
}
else
- local_gcall_ptr_node = TREE_TYPE (local_gcall_ptr_node);
+ local_gimple_ptr_node = TREE_TYPE (local_gimple_ptr_node);
}
}
else
- local_gcall_ptr_node = void_type_node;
+ local_gimple_ptr_node = void_type_node;
}
static tree hwi;
#define T_UC &unsigned_char_type_node
#define T99_UC { STD_C99, NULL, T_UC }
#define T_V &void_type_node
-#define T89_G { STD_C89, NULL, &local_gcall_ptr_node }
+#define T89_G { STD_C89, NULL, &local_gimple_ptr_node }
#define T89_T { STD_C89, NULL, &local_tree_type_node }
#define T89_V { STD_C89, NULL, T_V }
#define T_W &wchar_type_node
+2018-08-01 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86650
+ * c-objc-common.c (c_tree_printer): Move usage of EXPR_LOCATION (t)
+ and TREE_BLOCK (t) from within percent_K_format to this callsite.
+
2018-08-01 Jakub Jelinek <jakub@redhat.com>
PR c/85704
%D: a general decl,
%E: an identifier or expression,
%F: a function declaration,
- %G: a Gimple call statement,
+ %G: a Gimple statement,
%K: a CALL_EXPR,
%T: a type.
%V: a list of type qualifiers from a tree.
if (*spec == 'K')
{
t = va_arg (*text->args_ptr, tree);
- percent_K_format (text, t);
+ percent_K_format (text, EXPR_LOCATION (t), TREE_BLOCK (t));
return true;
}
+2018-08-01 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86650
+ * error.c (cp_printer): Move usage of EXPR_LOCATION (t) and
+ TREE_BLOCK (t) from within percent_K_format to this callsite.
+
2018-08-01 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/86661
return true;
case 'K':
t = va_arg (*text->args_ptr, tree);
- percent_K_format (text, t);
+ percent_K_format (text, EXPR_LOCATION (t), TREE_BLOCK (t));
return true;
case 'L': result = language_to_string (next_lang); break;
case 'O': result = op_to_string (false, next_tcode); break;
if (!nonstring)
{
tree fndecl = gimple_call_fndecl (stmt);
- gcall *call = as_a <gcall *> (stmt);
/* Warn about the lack of nul termination: the result is not
a (nul-terminated) string. */
warning_at (loc, OPT_Wstringop_truncation,
"%G%qD destination unchanged after copying no bytes "
"from a string of length %E",
- call, fndecl, slen);
+ stmt, fndecl, slen);
else
warning_at (loc, OPT_Wstringop_truncation,
"%G%qD destination unchanged after copying no bytes",
- call, fndecl);
+ stmt, fndecl);
}
replace_call_with_value (gsi, dest);
static bool
gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
{
- gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
+ gimple *stmt = gsi_stmt (*gsi);
tree dst = gimple_call_arg (stmt, 0);
tree src = gimple_call_arg (stmt, 1);
tree len = gimple_call_arg (stmt, 2);
/* Handle the %G format for TEXT. Same as %K in handle_K_format in
- tree-pretty-print.c but with a Gimple call statement as an argument. */
+ tree-pretty-print.c but with a Gimple statement as an argument. */
void
percent_G_format (text_info *text)
{
- gcall *stmt = va_arg (*text->args_ptr, gcall*);
+ gimple *stmt = va_arg (*text->args_ptr, gimple*);
- /* Build a call expression from the Gimple call statement and
- pass it to the K formatter that knows how to format it. */
- tree exp = build_vl_exp (CALL_EXPR, gimple_call_num_args (stmt) + 3);
- CALL_EXPR_FN (exp) = gimple_call_fn (stmt);
- TREE_TYPE (exp) = gimple_call_return_type (stmt);
- CALL_EXPR_STATIC_CHAIN (exp) = gimple_call_chain (stmt);
- SET_EXPR_LOCATION (exp, gimple_location (stmt));
-
- percent_K_format (text, exp);
+ tree block = gimple_block (stmt);
+ percent_K_format (text, gimple_location (stmt), block);
}
bool handle_gimple_call (gimple_stmt_iterator *);
private:
- void check_call (gcall *);
+ void check_call (gimple *);
};
edge
if (!is_gimple_call (stmt))
continue;
- if (gcall *call = as_a <gcall *> (stmt))
- check_call (call);
+ check_call (stmt);
}
return NULL;
return detect_overlap != &builtin_access::generic_overlap;
}
- builtin_access (gcall *, builtin_memref &, builtin_memref &);
+ builtin_access (gimple *, builtin_memref &, builtin_memref &);
/* Entry point to determine overlap. */
bool overlap ();
/* Create an association between the memory references DST and SRC
for access by a call EXPR to a memory or string built-in funtion. */
-builtin_access::builtin_access (gcall *call, builtin_memref &dst,
+builtin_access::builtin_access (gimple *call, builtin_memref &dst,
builtin_memref &src)
: dstref (&dst), srcref (&src), sizrange (), ovloff (), ovlsiz (),
dstoff (), srcoff (), dstsiz (), srcsiz ()
Return true when one has been detected, false otherwise. */
static bool
-maybe_diag_overlap (location_t loc, gcall *call, builtin_access &acs)
+maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
{
if (!acs.overlap ())
return false;
has been issued. */
static bool
-maybe_diag_offset_bounds (location_t loc, gcall *call, tree func, int strict,
+maybe_diag_offset_bounds (location_t loc, gimple *call, tree func, int strict,
tree expr, const builtin_memref &ref)
{
if (!warn_array_bounds)
if/when appropriate. */
void
-wrestrict_dom_walker::check_call (gcall *call)
+wrestrict_dom_walker::check_call (gimple *call)
{
/* Avoid checking the call if it has already been diagnosed for
some reason. */
detected and diagnosed, true otherwise. */
bool
-check_bounds_or_overlap (gcall *call, tree dst, tree src, tree dstsize,
+check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize,
tree srcsize, bool bounds_only /* = false */)
{
location_t loc = gimple_nonartificial_location (call);
#ifndef GIMPLE_SSA_WARN_RESTRICT_H
-extern bool check_bounds_or_overlap (gcall *, tree, tree, tree, tree,
+extern bool check_bounds_or_overlap (gimple *, tree, tree, tree, tree,
bool = false);
#endif /* GIMPLE_SSA_WARN_RESTRICT_H */
+2018-08-01 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86650
+ * gcc.dg/format/gcc_diag-10.c: Adjust.
+
2018-08-01 Richard Sandiford <richard.sandiford@arm.com>
* gcc.target/aarch64/sve/var_stride_2.c: Update expected form
union tree_node;
typedef union tree_node *tree;
-/* Define gcall as a dummy type. The typedef must be provided for
+/* Define gimple as a dummy type. The typedef must be provided for
the C test to find the symbol. */
-typedef struct gcall gcall;
+typedef struct gimple gimple;
#define FORMAT(kind) __attribute__ ((format (__gcc_## kind ##__, 1, 2)))
void tdiag (const char*, ...) FORMAT (tdiag);
void cxxdiag (const char*, ...) FORMAT (cxxdiag);
-void test_diag (tree t, gcall *gc)
+void test_diag (tree t, gimple *gc)
{
diag ("%<"); /* { dg-warning "unterminated quoting directive" } */
diag ("%>"); /* { dg-warning "unmatched quoting directive " } */
diag ("%<%r%R%>", "");
}
-void test_cdiag (tree t, gcall *gc)
+void test_cdiag (tree t, gimple *gc)
{
cdiag ("%<"); /* { dg-warning "unterminated quoting directive" } */
cdiag ("%>"); /* { dg-warning "unmatched quoting directive " } */
cdiag ("%<%qT%>", t); /* { dg-warning ".q. flag used within a quoted sequence" } */
}
-void test_tdiag (tree t, gcall *gc)
+void test_tdiag (tree t, gimple *gc)
{
tdiag ("%<"); /* { dg-warning "unterminated quoting directive" } */
tdiag ("%>"); /* { dg-warning "unmatched quoting directive " } */
tdiag ("%<%qT%>", t); /* { dg-warning ".q. flag used within a quoted sequence" } */
}
-void test_cxxdiag (tree t, gcall *gc)
+void test_cxxdiag (tree t, gimple *gc)
{
cxxdiag ("%A", t); /* { dg-warning ".A. conversion used unquoted" } */
cxxdiag ("%D", t); /* { dg-warning ".D. conversion used unquoted" } */
case 'K':
t = va_arg (*text->args_ptr, tree);
- percent_K_format (text, t);
+ percent_K_format (text, EXPR_LOCATION (t), TREE_BLOCK (t));
return true;
default:
/* Handle the %K format for TEXT. Separate from default_tree_printer
so it can also be used in front ends.
- Argument is a statement from which EXPR_LOCATION and TREE_BLOCK will
- be recorded. */
+ The location LOC and BLOCK are expected to be extracted by the caller
+ from the %K argument arg via EXPR_LOCATION(arg) and TREE_BLOCK(arg). */
void
-percent_K_format (text_info *text, tree t)
+percent_K_format (text_info *text, location_t loc, tree block)
{
- text->set_location (0, EXPR_LOCATION (t), true);
+ text->set_location (0, loc, true);
gcc_assert (pp_ti_abstract_origin (text) != NULL);
- tree block = TREE_BLOCK (t);
*pp_ti_abstract_origin (text) = NULL;
if (in_lto_p)
extern int op_prio (const_tree);
extern const char *op_symbol_code (enum tree_code);
extern void print_call_name (pretty_printer *, tree, dump_flags_t);
-extern void percent_K_format (text_info *, tree);
+extern void percent_K_format (text_info *, location_t, tree);
extern void pp_tree_identifier (pretty_printer *, tree);
extern void dump_function_header (FILE *, tree, dump_flags_t);
extern void pp_double_int (pretty_printer *pp, double_int d, bool uns);
location_t loc = gimple_location (stmt);
if (warning_at (loc, OPT_Wnonnull,
"%Gargument %u null where non-null "
- "expected", as_a <gcall *>(stmt), i + 1))
+ "expected", stmt, i + 1))
{
tree fndecl = gimple_call_fndecl (stmt);
if (fndecl && DECL_IS_BUILTIN (fndecl))
tree type = TREE_TYPE (oldlen);
oldlen = fold_build2 (PLUS_EXPR, type, oldlen,
build_int_cst (type, 1));
- check_bounds_or_overlap (as_a <gcall *>(stmt), olddsi->ptr, src,
- oldlen, NULL_TREE);
+ check_bounds_or_overlap (stmt, olddsi->ptr, src, oldlen, NULL_TREE);
}
return;
if (const strinfo *chksi = olddsi ? olddsi : dsi)
if (si
- && !check_bounds_or_overlap (as_a <gcall *>(stmt), chksi->ptr, si->ptr,
- NULL_TREE, len))
+ && !check_bounds_or_overlap (stmt, chksi->ptr, si->ptr, NULL_TREE, len))
{
gimple_set_no_warning (stmt, true);
set_no_warning = true;
lenrange[0] = wi::shwi (0, prec);
}
- gcall *call = as_a <gcall *> (stmt);
-
/* Set to true for strncat whose bound is derived from the length
of the destination (the expected usage pattern). */
bool cat_dstlen_bounded = false;
"%G%qD output truncated before terminating nul "
"copying %E bytes from a string of the same "
"length",
- call, func, cnt);
+ stmt, func, cnt);
else if (!cat_dstlen_bounded)
{
if (wi::geu_p (lenrange[0], cntrange[1]))
"from a string of length %wu",
"%G%qD output truncated copying %E bytes "
"from a string of length %wu",
- call, func, cnt, lenrange[0].to_uhwi ());
+ stmt, func, cnt, lenrange[0].to_uhwi ());
return warning_at (callloc, OPT_Wstringop_truncation,
"%G%qD output truncated copying between %wu "
"and %wu bytes from a string of length %wu",
- call, func, cntrange[0].to_uhwi (),
+ stmt, func, cntrange[0].to_uhwi (),
cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
}
else if (wi::geu_p (lenrange[1], cntrange[1]))
"byte from a string of length %wu",
"%G%qD output may be truncated copying %E "
"bytes from a string of length %wu",
- call, func, cnt, lenrange[1].to_uhwi ());
+ stmt, func, cnt, lenrange[1].to_uhwi ());
return warning_at (callloc, OPT_Wstringop_truncation,
"%G%qD output may be truncated copying between "
"%wu and %wu bytes from a string of length %wu",
- call, func, cntrange[0].to_uhwi (),
+ stmt, func, cntrange[0].to_uhwi (),
cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
}
}
return warning_at (callloc, OPT_Wstringop_truncation,
"%G%qD output may be truncated copying between "
"%wu and %wu bytes from a string of length %wu",
- call, func, cntrange[0].to_uhwi (),
+ stmt, func, cntrange[0].to_uhwi (),
cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
}
}
if (cntrange[0] == cntrange[1])
return warning_at (callloc, OPT_Wstringop_truncation,
"%G%qD specified bound %E equals destination size",
- as_a <gcall *> (stmt), func, cnt);
+ stmt, func, cnt);
}
return false;
else
srcsize = NULL_TREE;
- if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, src,
- dstsize, srcsize))
+ if (!check_bounds_or_overlap (stmt, dst, src, dstsize, srcsize))
{
gimple_set_no_warning (stmt, true);
return;
&& warning_at (callloc, OPT_Wstringop_truncation,
"%G%qD output truncated before terminating nul "
"copying as many bytes from a string as its length",
- as_a <gcall *>(stmt), func))
+ stmt, func))
warned = true;
else if (silen && is_strlen_related_p (src, silen->ptr))
warned = warning_at (callloc, OPT_Wstringop_overflow_,
"%G%qD specified bound depends on the length "
"of the source argument",
- as_a <gcall *>(stmt), func);
+ stmt, func);
if (warned)
{
location_t strlenloc = pss->second;
tree sptr = si && si->ptr ? si->ptr : src;
- if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, sptr,
- NULL_TREE, slen))
+ if (!check_bounds_or_overlap (stmt, dst, sptr, NULL_TREE, slen))
{
gimple_set_no_warning (stmt, true);
set_no_warning = true;
tree sptr = si && si->ptr ? si->ptr : src;
- if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, sptr,
- dstlen, srcsize))
+ if (!check_bounds_or_overlap (stmt, dst, sptr, dstlen, srcsize))
{
gimple_set_no_warning (stmt, true);
set_no_warning = true;