aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/call.cc21
-rw-r--r--gcc/doc/extend.texi5
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/builtin-clear-padding1.C50
3 files changed, 76 insertions, 0 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 8fe8ef3..23d3fc4 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 0dc752e8..a4a25e8 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 0000000..7b1282e
--- /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);
+}