diff mbox

[C++] PR c++/35878

Message ID CAFk2RUbHhy7Qrjn+bPunYTvB_QOzDrrQx2_ZdbqM5H81qEHprA@mail.gmail.com
State New
Headers show

Commit Message

Ville Voutilainen March 21, 2017, 1:21 a.m. UTC
On 21 March 2017 at 02:46, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> On 21 March 2017 at 02:43, Ville Voutilainen
> <ville.voutilainen@gmail.com> wrote:
>> Hmm. I should either rename that function or flip its logic. Now it's
>> a bit backwards. :) I'll flip its logic.
>
> In other words, see attached.

Let's call the function what it really is.

2017-03-21  Ville Voutilainen  <ville.voutilainen@gmail.com>

    gcc/

    PR c++/35878
    * cp/init.c (std_placement_new_fn_p): New.
    (build_new_1): Call it.

    testsuite/

    PR c++/35878
    * g++.dg/init/pr35878_1.C: New.
    * g++.dg/init/pr35878_2.C: Likewise.
    * g++.dg/init/pr35878_3.C: Likewise.

Comments

Jason Merrill March 21, 2017, 4:23 a.m. UTC | #1
OK.  Let's leave the BZ open to help remember to remove the
cxx_dialect check in stage 1.

Jason

On Mon, Mar 20, 2017 at 9:21 PM, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> On 21 March 2017 at 02:46, Ville Voutilainen
> <ville.voutilainen@gmail.com> wrote:
>> On 21 March 2017 at 02:43, Ville Voutilainen
>> <ville.voutilainen@gmail.com> wrote:
>>> Hmm. I should either rename that function or flip its logic. Now it's
>>> a bit backwards. :) I'll flip its logic.
>>
>> In other words, see attached.
>
> Let's call the function what it really is.
>
> 2017-03-21  Ville Voutilainen  <ville.voutilainen@gmail.com>
>
>     gcc/
>
>     PR c++/35878
>     * cp/init.c (std_placement_new_fn_p): New.
>     (build_new_1): Call it.
>
>     testsuite/
>
>     PR c++/35878
>     * g++.dg/init/pr35878_1.C: New.
>     * g++.dg/init/pr35878_2.C: Likewise.
>     * g++.dg/init/pr35878_3.C: Likewise.
Jakub Jelinek March 21, 2017, 6:48 a.m. UTC | #2
Hi!

On Tue, Mar 21, 2017 at 03:21:11AM +0200, Ville Voutilainen wrote:

Formatting etc. nits:

> 2017-03-21  Ville Voutilainen  <ville.voutilainen@gmail.com>
> 
>     gcc/
> 
>     PR c++/35878

This should go into gcc/cp/ ChangeLog

>     * cp/init.c (std_placement_new_fn_p): New.

without cp/ here.

>     (build_new_1): Call it.

> +/* Determine whether an allocation function is a namespace-scope
> +   non-replaceable placement new function. See DR 1748.
> +   TODO: Enable in all standard modes.  */
> +static bool std_placement_new_fn_p (tree alloc_fn)

static bool
std_placement_new_fn_p (tree alloc_fn)

> @@ -3171,7 +3186,8 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
>       So check for a null exception spec on the op new we just called.  */
>  
>    nothrow = TYPE_NOTHROW_P (TREE_TYPE (alloc_fn));
> -  check_new = (flag_check_new || nothrow);
> +  check_new = flag_check_new
> +    || (nothrow && !std_placement_new_fn_p (alloc_fn));

This should be either:
  check_new
    = flag_check_new || (nothrow && !std_placement_new_fn_p (alloc_fn));
or
  check_new = (flag_check_new
	       || (nothrow && !std_placement_new_fn_p (alloc_fn)));
i.e. || should not be when on next line at different column than
flag_check_new (and the ()s to make emacs happy).

> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/init/pr35878_1.C
> @@ -0,0 +1,21 @@
> +// { dg-options "-O2 --std=gnu++11" }

-O2 -std=gnu++11 is enough, no need for double dash --std=gnu++11.

> +// { dg-do compile }
> +// { dg-final { scan-assembler "test.*%rdi, %rdi" { target i?86-*-* x86_64-*-* } } }

This will surely fail on 32-bit or with -mx32.  So either you need to use it
on { target { { i?86-*-* x86_64-*-* } && lp64 } } only, or perhaps instead
of scanning assembler add -fdump-tree-optimized to dg-options and
scan-tree-dump for the NULL? pointer comparison there.

	Jakub
Ville Voutilainen March 21, 2017, 6:55 a.m. UTC | #3
On 21 March 2017 at 08:48, Jakub Jelinek <jakub@redhat.com> wrote:
> Formatting etc. nits:
>
>> 2017-03-21  Ville Voutilainen  <ville.voutilainen@gmail.com>
>>
>>     gcc/
>>
>>     PR c++/35878
>
> This should go into gcc/cp/ ChangeLog
>
>>     * cp/init.c (std_placement_new_fn_p): New.
>
> without cp/ here.

Yeah, so modified before the commit.

>>    nothrow = TYPE_NOTHROW_P (TREE_TYPE (alloc_fn));
>> -  check_new = (flag_check_new || nothrow);
>> +  check_new = flag_check_new
>> +    || (nothrow && !std_placement_new_fn_p (alloc_fn));
>
> This should be either:
>   check_new
>     = flag_check_new || (nothrow && !std_placement_new_fn_p (alloc_fn));
> or
>   check_new = (flag_check_new
>                || (nothrow && !std_placement_new_fn_p (alloc_fn)));
> i.e. || should not be when on next line at different column than
> flag_check_new (and the ()s to make emacs happy).

Bummer - I simply indented that with emacs and thought it does the right thing.

>
>> --- /dev/null
>> +++ b/gcc/testsuite/g++.dg/init/pr35878_1.C
>> @@ -0,0 +1,21 @@
>> +// { dg-options "-O2 --std=gnu++11" }
>
> -O2 -std=gnu++11 is enough, no need for double dash --std=gnu++11.
>
>> +// { dg-do compile }
>> +// { dg-final { scan-assembler "test.*%rdi, %rdi" { target i?86-*-* x86_64-*-* } } }
>
> This will surely fail on 32-bit or with -mx32.  So either you need to use it
> on { target { { i?86-*-* x86_64-*-* } && lp64 } } only, or perhaps instead
> of scanning assembler add -fdump-tree-optimized to dg-options and
> scan-tree-dump for the NULL? pointer comparison there.

I weakly vote for the former, since that's less intrusive. I managed
to commit the patch before
I saw these remarks, so we need to patch that fix in as a separate tweak.
diff mbox

Patch

diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 8bfcbde..a0cd64c 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2693,6 +2693,21 @@  malloc_alignment ()
   return MAX (max_align_t_align(), MALLOC_ABI_ALIGNMENT);
 }
 
+/* Determine whether an allocation function is a namespace-scope
+   non-replaceable placement new function. See DR 1748.
+   TODO: Enable in all standard modes.  */
+static bool std_placement_new_fn_p (tree alloc_fn)
+{
+  if ((cxx_dialect > cxx14) && DECL_NAMESPACE_SCOPE_P (alloc_fn))
+    {
+      tree first_arg = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn)));
+      if ((TREE_VALUE (first_arg) == ptr_type_node)
+	  && TREE_CHAIN (first_arg) == void_list_node)
+	return true;
+    }
+  return false;
+}
+
 /* Generate code for a new-expression, including calling the "operator
    new" function, initializing the object, and, if an exception occurs
    during construction, cleaning up.  The arguments are as for
@@ -3171,7 +3186,8 @@  build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
      So check for a null exception spec on the op new we just called.  */
 
   nothrow = TYPE_NOTHROW_P (TREE_TYPE (alloc_fn));
-  check_new = (flag_check_new || nothrow);
+  check_new = flag_check_new
+    || (nothrow && !std_placement_new_fn_p (alloc_fn));
 
   if (cookie_size)
     {
diff --git a/gcc/testsuite/g++.dg/init/pr35878_1.C b/gcc/testsuite/g++.dg/init/pr35878_1.C
new file mode 100644
index 0000000..b45c009
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/pr35878_1.C
@@ -0,0 +1,21 @@ 
+// { dg-options "-O2 --std=gnu++11" }
+// { dg-do compile }
+// { dg-final { scan-assembler "test.*%rdi, %rdi" { target i?86-*-* x86_64-*-* } } }
+#include <new>
+#include <utility>
+
+struct s1{
+  int a;
+  int b;
+  int c;
+};
+
+void f1 (s1 * v, s1&& s)
+{
+	new (v) s1(std::move(s));
+}
+
+void f2 (s1 * v, s1&& s)
+{
+	*v = std::move(s);
+}
diff --git a/gcc/testsuite/g++.dg/init/pr35878_2.C b/gcc/testsuite/g++.dg/init/pr35878_2.C
new file mode 100644
index 0000000..0664494
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/pr35878_2.C
@@ -0,0 +1,21 @@ 
+// { dg-options "-O2 --std=gnu++17 -fcheck-new" }
+// { dg-do compile }
+// { dg-final { scan-assembler "test.*%rdi, %rdi" { target i?86-*-* x86_64-*-* } } }
+#include <new>
+#include <utility>
+
+struct s1{
+  int a;
+  int b;
+  int c;
+};
+
+void f1 (s1 * v, s1&& s)
+{
+	new (v) s1(std::move(s));
+}
+
+void f2 (s1 * v, s1&& s)
+{
+	*v = std::move(s);
+}
diff --git a/gcc/testsuite/g++.dg/init/pr35878_3.C b/gcc/testsuite/g++.dg/init/pr35878_3.C
new file mode 100644
index 0000000..8a5614f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/pr35878_3.C
@@ -0,0 +1,21 @@ 
+// { dg-options "-O2 --std=gnu++17" }
+// { dg-do compile }
+// { dg-final { scan-assembler-not "test.*%rdi, %rdi" { target i?86-*-* x86_64-*-* } } }
+#include <new>
+#include <utility>
+
+struct s1{
+  int a;
+  int b;
+  int c;
+};
+
+void f1 (s1 * v, s1&& s)
+{
+	new (v) s1(std::move(s));
+}
+
+void f2 (s1 * v, s1&& s)
+{
+	*v = std::move(s);
+}