re PR c++/81327 (cast to void* does not suppress -Wclass-memaccess)
authorJakub Jelinek <jakub@redhat.com>
Wed, 10 Jan 2018 16:59:09 +0000 (17:59 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 10 Jan 2018 16:59:09 +0000 (17:59 +0100)
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

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/Wclass-memaccess-2.C

index 9b6f46265866bbb1e7cf6a8e9a88bab46d2748fa..3cce2120b5a1806be2119778495095dc53104626 100644 (file)
@@ -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
index 1c54bab124afc590652e8c8cb9f18688ed8d294a..515e4607de0db2f39cd1e7af4f056e1b6aed262e 100644 (file)
@@ -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)))
index dca24d8f28b1a314b4b5d673fd73db4650599d1a..0bfacf0d0e608122232bea93787122a3ba557053 100644 (file)
@@ -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
index 49581df1204dd0285fa424e69a61a13dd936f43b..f138b8b357e1e9f448209c14feaa1e6f67d737ac 100644 (file)
@@ -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]" }
 }