public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-7641] c++: Reject __builtin_clear_padding on non-trivially-copyable types with one exception [PR102586]
@ 2022-03-14  9:49 Jakub Jelinek
  0 siblings, 0 replies; only message in thread
From: Jakub Jelinek @ 2022-03-14  9:49 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:c879b92c30d088ff01eb0c3e912eb8a01f9fc6e3

commit r12-7641-gc879b92c30d088ff01eb0c3e912eb8a01f9fc6e3
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Mon Mar 14 10:47:38 2022 +0100

    c++: Reject __builtin_clear_padding on non-trivially-copyable types with one exception [PR102586]
    
    As mentioned by Jason in the PR, non-trivially-copyable types (or non-POD
    for purposes of layout?) types can be base classes of derived classes in
    which the padding in those non-trivially-copyable types can be reused for
    some real data members or even the layout can change and data members can
    be moved to other positions.
    __builtin_clear_padding is right now used for multiple purposes,
    in <atomic> where it isn't used yet but was planned as the main spot
    it can be used for trivially copyable types only, ditto for std::bit_cast
    where we also use it.  It is used for OpenMP long double atomics too but
    long double is trivially copyable, and lastly for -ftrivial-auto-var-init=.
    
    The following patch restricts the builtin to pointers to trivially-copyable
    types, with the exception when it is called directly on an address of a
    variable, in that case already the FE can verify it is the complete object
    type and so it is safe to clear all the paddings in it.
    
    2022-03-14  Jakub Jelinek  <jakub@redhat.com>
    
            PR tree-optimization/102586
    gcc/
            * doc/extend.texi (__builtin_clear_padding): Clearify that for C++
            argument type should be pointer to trivially-copyable type unless it
            is address of a variable or parameter.
    gcc/cp/
            * call.cc (build_cxx_call): Diagnose __builtin_clear_padding where
            first argument's type is pointer to non-trivially-copyable type unless
            it is address of a variable or parameter.
    gcc/testsuite/
            * g++.dg/cpp2a/builtin-clear-padding1.C: New test.

Diff:
---
 gcc/cp/call.cc                                     | 21 +++++++++
 gcc/doc/extend.texi                                |  5 +++
 .../g++.dg/cpp2a/builtin-clear-padding1.C          | 50 ++++++++++++++++++++++
 3 files changed, 76 insertions(+)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 8fe8ef306ea..23d3fc496b8 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -10409,6 +10409,27 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
       if (!check_builtin_function_arguments (EXPR_LOCATION (fn), vNULL, fndecl,
 					     orig_fndecl, nargs, argarray))
 	return error_mark_node;
+      else if (fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING))
+	{
+	  tree arg0 = argarray[0];
+	  STRIP_NOPS (arg0);
+	  if (TREE_CODE (arg0) == ADDR_EXPR
+	      && DECL_P (TREE_OPERAND (arg0, 0))
+	      && same_type_ignoring_top_level_qualifiers_p
+			(TREE_TYPE (TREE_TYPE (argarray[0])),
+			 TREE_TYPE (TREE_TYPE (arg0))))
+	    /* For __builtin_clear_padding (&var) we know the type
+	       is for a complete object, so there is no risk in clearing
+	       padding that is reused in some derived class member.  */;
+	  else if (!trivially_copyable_p (TREE_TYPE (TREE_TYPE (argarray[0]))))
+	    {
+	      error_at (EXPR_LOC_OR_LOC (argarray[0], input_location),
+			"argument %u in call to function %qE "
+			"has pointer to a non-trivially-copyable type (%qT)",
+			1, fndecl, TREE_TYPE (argarray[0]));
+	      return error_mark_node;
+	    }
+	}
     }
 
   if (VOID_TYPE_P (TREE_TYPE (fn)))
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 0dc752e8aad..a4a25e86928 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -13993,6 +13993,11 @@ bits that are padding bits for all the union members.
 This built-in-function is useful if the padding bits of an object might
 have intederminate values and the object representation needs to be
 bitwise compared to some other object, for example for atomic operations.
+
+For C++, @var{ptr} argument type should be pointer to trivially-copyable
+type, unless the argument is address of a variable or parameter, because
+otherwise it isn't known if the type isn't just a base class whose padding
+bits are reused or laid out differently in a derived class.
 @end deftypefn
 
 @deftypefn {Built-in Function} @var{type} __builtin_bit_cast (@var{type}, @var{arg})
diff --git a/gcc/testsuite/g++.dg/cpp2a/builtin-clear-padding1.C b/gcc/testsuite/g++.dg/cpp2a/builtin-clear-padding1.C
new file mode 100644
index 00000000000..7b1282e7798
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/builtin-clear-padding1.C
@@ -0,0 +1,50 @@
+// PR tree-optimization/102586
+// { dg-do compile }
+// { dg-options "-Wno-inaccessible-base" }
+
+struct C0 {};
+struct C1 {};
+struct C2 : C1, virtual C0 {};
+struct C3 : virtual C2, C1 {};
+struct C4 : virtual C3, C1 {};
+struct C5 : C4 {};
+struct C6 { char c; };
+struct C7 : virtual C6, virtual C3, C1 {};
+struct C8 : C7 {};
+
+void
+foo (C0 *c0, C1 *c1, C2 *c2, C3 *c3, C4 *c4, C5 *c5, C6 *c6, C7 *c7, C8 *c8)
+{
+  __builtin_clear_padding (c0);
+  __builtin_clear_padding (c1);
+  __builtin_clear_padding (c2);	// { dg-error "argument 1 in call to function '__builtin_clear_padding' has pointer to a non-trivially-copyable type \\\('C2\\\*'\\\)" }
+  __builtin_clear_padding (c3);	// { dg-error "argument 1 in call to function '__builtin_clear_padding' has pointer to a non-trivially-copyable type \\\('C3\\\*'\\\)" }
+  __builtin_clear_padding (c4);	// { dg-error "argument 1 in call to function '__builtin_clear_padding' has pointer to a non-trivially-copyable type \\\('C4\\\*'\\\)" }
+  __builtin_clear_padding (c5);	// { dg-error "argument 1 in call to function '__builtin_clear_padding' has pointer to a non-trivially-copyable type \\\('C5\\\*'\\\)" }
+  __builtin_clear_padding (c6);
+  __builtin_clear_padding (c7);	// { dg-error "argument 1 in call to function '__builtin_clear_padding' has pointer to a non-trivially-copyable type \\\('C7\\\*'\\\)" }
+  __builtin_clear_padding (c8);	// { dg-error "argument 1 in call to function '__builtin_clear_padding' has pointer to a non-trivially-copyable type \\\('C8\\\*'\\\)" }
+}
+
+void
+bar ()
+{
+  C0 c0;
+  C1 c1;
+  C2 c2;
+  C3 c3;
+  C4 c4;
+  C5 c5;
+  C6 c6;
+  C7 c7;
+  C8 c8;
+  __builtin_clear_padding (&c0);
+  __builtin_clear_padding (&c1);
+  __builtin_clear_padding (&c2);
+  __builtin_clear_padding (&c3);
+  __builtin_clear_padding (&c4);
+//  __builtin_clear_padding (&c5);
+  __builtin_clear_padding (&c6);
+  __builtin_clear_padding (&c7);
+  __builtin_clear_padding (&c8);
+}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-03-14  9:49 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-14  9:49 [gcc r12-7641] c++: Reject __builtin_clear_padding on non-trivially-copyable types with one exception [PR102586] Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).