re PR c++/81327 (cast to void* does not suppress -Wclass-memaccess)
PR c++/81327 * call.c (maybe_warn_class_memaccess): Add forward declaration. Change last argument from tree * to const vec<tree, va_gc> *, adjust args uses and check number of operands too. Don't strip away any nops. Use maybe_constant_value when looking for INTEGER_CST args. Deal with src argument not having pointer type. Check tree_fits_uhwi_p before calling tree_to_uhwi. Remove useless test. (build_over_call): Call maybe_warn_class_memaccess here on the original arguments. (build_cxx_call): Rather than here on converted arguments. * g++.dg/Wclass-memaccess-2.C: Don't expect a warning when explicitly cast to void *. From-SVN: r256440
This commit is contained in:
parent
75ce74bbdd
commit
e99ef40892
4 changed files with 55 additions and 33 deletions
|
@ -1,3 +1,17 @@
|
|||
2018-01-10 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/81327
|
||||
* call.c (maybe_warn_class_memaccess): Add forward declaration.
|
||||
Change last argument from tree * to const vec<tree, va_gc> *, adjust
|
||||
args uses and check number of operands too. Don't strip away any
|
||||
nops. Use maybe_constant_value when looking for INTEGER_CST args.
|
||||
Deal with src argument not having pointer type. Check
|
||||
tree_fits_uhwi_p before calling tree_to_uhwi. Remove useless
|
||||
test.
|
||||
(build_over_call): Call maybe_warn_class_memaccess here on the
|
||||
original arguments.
|
||||
(build_cxx_call): Rather than here on converted arguments.
|
||||
|
||||
2018-01-10 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
|
||||
PR c++/81055
|
||||
|
|
|
@ -147,6 +147,8 @@ static int equal_functions (tree, tree);
|
|||
static int joust (struct z_candidate *, struct z_candidate *, bool,
|
||||
tsubst_flags_t);
|
||||
static int compare_ics (conversion *, conversion *);
|
||||
static void maybe_warn_class_memaccess (location_t, tree,
|
||||
const vec<tree, va_gc> *);
|
||||
static tree build_over_call (struct z_candidate *, int, tsubst_flags_t);
|
||||
#define convert_like(CONV, EXPR, COMPLAIN) \
|
||||
convert_like_real ((CONV), (EXPR), NULL_TREE, 0, \
|
||||
|
@ -8180,6 +8182,12 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
|
|||
&& !mark_used (fn, complain))
|
||||
return error_mark_node;
|
||||
|
||||
/* Warn if the built-in writes to an object of a non-trivial type. */
|
||||
if (warn_class_memaccess
|
||||
&& vec_safe_length (args) >= 2
|
||||
&& DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL)
|
||||
maybe_warn_class_memaccess (input_location, fn, args);
|
||||
|
||||
if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0
|
||||
/* Don't mess with virtual lookup in instantiate_non_dependent_expr;
|
||||
virtual functions can't be constexpr. */
|
||||
|
@ -8360,7 +8368,8 @@ has_trivial_copy_p (tree type, bool access, bool hasctor[2])
|
|||
assignments. */
|
||||
|
||||
static void
|
||||
maybe_warn_class_memaccess (location_t loc, tree fndecl, tree *args)
|
||||
maybe_warn_class_memaccess (location_t loc, tree fndecl,
|
||||
const vec<tree, va_gc> *args)
|
||||
{
|
||||
/* Except for bcopy where it's second, the destination pointer is
|
||||
the first argument for all functions handled here. Compute
|
||||
|
@ -8368,15 +8377,10 @@ maybe_warn_class_memaccess (location_t loc, tree fndecl, tree *args)
|
|||
unsigned dstidx = DECL_FUNCTION_CODE (fndecl) == BUILT_IN_BCOPY;
|
||||
unsigned srcidx = !dstidx;
|
||||
|
||||
tree dest = args[dstidx];
|
||||
if (!dest || !TREE_TYPE (dest) || !POINTER_TYPE_P (TREE_TYPE (dest)))
|
||||
tree dest = (*args)[dstidx];
|
||||
if (!TREE_TYPE (dest) || !POINTER_TYPE_P (TREE_TYPE (dest)))
|
||||
return;
|
||||
|
||||
/* Remove the outermost (usually implicit) conversion to the void*
|
||||
argument type. */
|
||||
if (TREE_CODE (dest) == NOP_EXPR)
|
||||
dest = TREE_OPERAND (dest, 0);
|
||||
|
||||
tree srctype = NULL_TREE;
|
||||
|
||||
/* Determine the type of the pointed-to object and whether it's
|
||||
|
@ -8436,7 +8440,7 @@ maybe_warn_class_memaccess (location_t loc, tree fndecl, tree *args)
|
|||
switch (DECL_FUNCTION_CODE (fndecl))
|
||||
{
|
||||
case BUILT_IN_MEMSET:
|
||||
if (!integer_zerop (args[1]))
|
||||
if (!integer_zerop (maybe_constant_value ((*args)[1])))
|
||||
{
|
||||
/* Diagnose setting non-copy-assignable or non-trivial types,
|
||||
or types with a private member, to (potentially) non-zero
|
||||
|
@ -8497,8 +8501,11 @@ maybe_warn_class_memaccess (location_t loc, tree fndecl, tree *args)
|
|||
case BUILT_IN_MEMMOVE:
|
||||
case BUILT_IN_MEMPCPY:
|
||||
/* Determine the type of the source object. */
|
||||
srctype = STRIP_NOPS (args[srcidx]);
|
||||
srctype = TREE_TYPE (TREE_TYPE (srctype));
|
||||
srctype = TREE_TYPE ((*args)[srcidx]);
|
||||
if (!srctype || !POINTER_TYPE_P (srctype))
|
||||
srctype = void_type_node;
|
||||
else
|
||||
srctype = TREE_TYPE (srctype);
|
||||
|
||||
/* Since it's impossible to determine wheter the byte copy is
|
||||
being used in place of assignment to an existing object or
|
||||
|
@ -8547,13 +8554,16 @@ maybe_warn_class_memaccess (location_t loc, tree fndecl, tree *args)
|
|||
"assignment or copy-initialization instead",
|
||||
fndecl, desttype, access, fld, srctype);
|
||||
}
|
||||
else if (!trivial && TREE_CODE (args[2]) == INTEGER_CST)
|
||||
else if (!trivial && vec_safe_length (args) > 2)
|
||||
{
|
||||
tree sz = maybe_constant_value ((*args)[2]);
|
||||
if (!tree_fits_uhwi_p (sz))
|
||||
break;
|
||||
|
||||
/* Finally, warn on partial copies. */
|
||||
unsigned HOST_WIDE_INT typesize
|
||||
= tree_to_uhwi (TYPE_SIZE_UNIT (desttype));
|
||||
if (unsigned HOST_WIDE_INT partial
|
||||
= tree_to_uhwi (args[2]) % typesize)
|
||||
if (unsigned HOST_WIDE_INT partial = tree_to_uhwi (sz) % typesize)
|
||||
warned = warning_at (loc, OPT_Wclass_memaccess,
|
||||
(typesize - partial > 1
|
||||
? G_("%qD writing to an object of "
|
||||
|
@ -8577,16 +8587,17 @@ maybe_warn_class_memaccess (location_t loc, tree fndecl, tree *args)
|
|||
else if (!get_dtor (desttype, tf_none))
|
||||
warnfmt = G_("%qD moving an object of type %#qT with deleted "
|
||||
"destructor");
|
||||
else if (!trivial
|
||||
&& TREE_CODE (args[1]) == INTEGER_CST
|
||||
&& tree_int_cst_lt (args[1], TYPE_SIZE_UNIT (desttype)))
|
||||
else if (!trivial)
|
||||
{
|
||||
/* Finally, warn on reallocation into insufficient space. */
|
||||
warned = warning_at (loc, OPT_Wclass_memaccess,
|
||||
"%qD moving an object of non-trivial type "
|
||||
"%#qT and size %E into a region of size %E",
|
||||
fndecl, desttype, TYPE_SIZE_UNIT (desttype),
|
||||
args[1]);
|
||||
tree sz = maybe_constant_value ((*args)[1]);
|
||||
if (TREE_CODE (sz) == INTEGER_CST
|
||||
&& tree_int_cst_lt (sz, TYPE_SIZE_UNIT (desttype)))
|
||||
/* Finally, warn on reallocation into insufficient space. */
|
||||
warned = warning_at (loc, OPT_Wclass_memaccess,
|
||||
"%qD moving an object of non-trivial type "
|
||||
"%#qT and size %E into a region of size %E",
|
||||
fndecl, desttype, TYPE_SIZE_UNIT (desttype),
|
||||
sz);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -8594,9 +8605,6 @@ maybe_warn_class_memaccess (location_t loc, tree fndecl, tree *args)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!warned && !warnfmt)
|
||||
return;
|
||||
|
||||
if (warnfmt)
|
||||
{
|
||||
if (suggest)
|
||||
|
@ -8643,10 +8651,6 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
|
|||
if (!check_builtin_function_arguments (EXPR_LOCATION (fn), vNULL, fndecl,
|
||||
nargs, argarray))
|
||||
return error_mark_node;
|
||||
|
||||
/* Warn if the built-in writes to an object of a non-trivial type. */
|
||||
if (nargs)
|
||||
maybe_warn_class_memaccess (loc, fndecl, argarray);
|
||||
}
|
||||
|
||||
if (VOID_TYPE_P (TREE_TYPE (fn)))
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2018-01-10 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/81327
|
||||
* g++.dg/Wclass-memaccess-2.C: Don't expect a warning when explicitly
|
||||
cast to void *.
|
||||
|
||||
2018-01-10 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
|
||||
PR c++/81055
|
||||
|
|
|
@ -53,9 +53,7 @@ void c_cast_uchar (NonTrivial *p)
|
|||
__builtin_memset ((unsigned char*)p, 0, sizeof *p);
|
||||
}
|
||||
|
||||
// A cast to void* does not suppress the warning. That is (or can be)
|
||||
// considered a feature.
|
||||
void c_cast_void (NonTrivial *p)
|
||||
{
|
||||
__builtin_memset ((void*)p, 0, sizeof *p); // { dg-warning "\\\[-Wclass-memaccess]" }
|
||||
__builtin_memset ((void*)p, 0, sizeof *p); // { dg-bogus "\\\[-Wclass-memaccess]" }
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue