This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] consider casts in -Wclass-memaccess (PR c++/81169)
- From: Martin Sebor <msebor at gmail dot com>
- To: Gcc Patch List <gcc-patches at gcc dot gnu dot org>, Jason Merrill <jason at redhat dot com>
- Date: Thu, 22 Jun 2017 12:00:22 -0600
- Subject: [PATCH] consider casts in -Wclass-memaccess (PR c++/81169)
- Authentication-results: sourceware.org; auth=none
By making use of STRIP_NOPS() on the destination of the memory
function call, besides discarding the (implicit) conversion to
void* the warning also strips any explicit casts that remove
cv-qualifiers. This causes warnings that should otherwise be
suppressed, as pointed out in bug 81169.
The attached patch only strips the outermost NOP_EXPR's to avoid
the unexpected warning in these cases.
Martin
PR c++/81169 - -Wclass-memaccess illegitimate warning related to volatile
gcc/cp/ChangeLog:
PR c++/81169
* call.c (maybe_warn_class_memaccess): Preserve explicit conversions
to detect casting away cv-qualifiers.
gcc/testsuite/ChangeLog:
PR c++/81169
* g++.dg/Wclass-memaccess-2.C: New test.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index d1f27dd..cdb83bb 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -8338,7 +8338,10 @@ maybe_warn_class_memaccess (location_t loc, tree fndecl, tree *args)
if (!dest || !TREE_TYPE (dest) || !POINTER_TYPE_P (TREE_TYPE (dest)))
return;
- STRIP_NOPS (dest);
+ /* 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;
@@ -8355,7 +8358,7 @@ maybe_warn_class_memaccess (location_t loc, tree fndecl, tree *args)
if (current_function_decl
&& (DECL_CONSTRUCTOR_P (current_function_decl)
|| DECL_DESTRUCTOR_P (current_function_decl))
- && is_this_parameter (dest))
+ && is_this_parameter (tree_strip_nop_conversions (dest)))
{
tree ctx = DECL_CONTEXT (current_function_decl);
bool special = same_type_ignoring_top_level_qualifiers_p (ctx, desttype);
diff --git a/gcc/testsuite/g++.dg/Wclass-memaccess-2.C b/gcc/testsuite/g++.dg/Wclass-memaccess-2.C
new file mode 100644
index 0000000..49581df
--- /dev/null
+++ b/gcc/testsuite/g++.dg/Wclass-memaccess-2.C
@@ -0,0 +1,61 @@
+// PR c++/81169 - -Wclass-memaccess illegitimate warning related to volatile
+// { dg-do compile }
+// { dg-options "-Wclass-memaccess" }
+
+struct S { int x; };
+
+void cast_const (const S *p)
+{
+ __builtin_memset (const_cast<S*>(p), 0, sizeof *p);
+}
+
+void cast_volatile (volatile S *p)
+{
+ __builtin_memset (const_cast<S*>(p), 0, sizeof *p);
+}
+
+void cast_const_volatile (const volatile S *p)
+{
+ __builtin_memset (const_cast<S*>(p), 0, sizeof *p);
+}
+
+void c_cast_const_volatile (const volatile S *p)
+{
+ __builtin_memset ((S*)p, 0, sizeof *p);
+}
+
+// A C cast to void* suppresses the warning because it casts away
+// the qualifiers from the otherwise trivial pointed-to type..
+void c_void_cast_const_volatile (const volatile S *p)
+{
+ __builtin_memset ((void*)p, 0, sizeof *p);
+}
+
+// Also verify that casting to char* suppresses the warning for
+// non-trivial types.
+
+struct NonTrivial
+{
+ NonTrivial ();
+ NonTrivial (const NonTrivial&);
+ NonTrivial& operator= (const NonTrivial&);
+ ~NonTrivial ();
+};
+
+void cast_void (NonTrivial *p)
+{
+ __builtin_memset (reinterpret_cast<char*>(p), 0, sizeof *p);
+}
+
+// A C cast to a character (or any trivial) type suppresses the warning.
+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]" }
+}