[C++ PATCH] Fix decltype on a trivial dtor with -flifetime-dse (PR c++/90598)
Jakub Jelinek
jakub@redhat.com
Fri May 24 08:21:00 GMT 2019
Hi!
The following testcase is rejected, because we determine B as void &
rather than the expected void when -flifetime-dse.
I'd say the main problem is premature folding, that we lower the trivial
destructor already at parsing time, rather than cp_fold, I'd say that goes
against the intentions of the late folding.
That said, these patch attempts to address this differently (in a way that
would also be backportable).
With -fno-lifetime-dse, when the test passes, the trivial destructor is
folded into (void) &instance and lvalue_kind returns clk_none for that, so
finish_decltype_type returns just void for it.
With -flifetime-dse, the trivial destructor is folded into a void mode
MODIFY_EXPR instance = {CLOBBER} and lvalue_kind returns clk_ordinary in
that case, so finish_decltype_type then applies the rules and makes void &
out of it.
The first patch fixes this by forcibly wrapping the MODIFY_EXPR into a void
type NOP_EXPR, so that lvalue_kind still considers it clk_none.
The second patch fixes that by special casing void type MODIFY_EXPR, I
believe if we have void type MODIFY_EXPR, then it can't be an lvalue.
Another option would be to tweak finish_decltype_type to special case
VOID_TYPE_P and never try to create a reference for it (which is not valid
in C++).
Both patches successfully bootstrapped/regtested on x86_64-linux and
i686-linux.
2019-05-24 Jakub Jelinek <jakub@redhat.com>
PR c++/90598
* call.c (build_trivial_dtor_call): Wrap MODIFY_EXPR for
-flifetime-dse into void_type_node NOP_EXPR.
* g++.dg/cpp0x/pr90598.C: New test.
--- gcc/cp/call.c.jj 2019-05-23 12:57:16.658493722 +0200
+++ gcc/cp/call.c 2019-05-23 18:37:09.570874611 +0200
@@ -7995,8 +7995,8 @@ build_trivial_dtor_call (tree instance)
/* A trivial destructor should still clobber the object. */
tree clobber = build_clobber (TREE_TYPE (instance));
- return build2 (MODIFY_EXPR, void_type_node,
- instance, clobber);
+ return build1 (NOP_EXPR, void_type_node,
+ build2 (MODIFY_EXPR, void_type_node, instance, clobber));
}
/* Subroutine of the various build_*_call functions. Overload resolution
--- gcc/testsuite/g++.dg/cpp0x/pr90598.C.jj 2019-05-23 18:39:37.034464509 +0200
+++ gcc/testsuite/g++.dg/cpp0x/pr90598.C 2019-05-23 18:39:05.471980348 +0200
@@ -0,0 +1,8 @@
+// PR c++/90598
+// { dg-do compile { target c++11 } }
+
+struct A {};
+using B = decltype(A ().~A ());
+template <typename T> struct C;
+template <> struct C<void> {};
+C<B> t;
Jakub
-------------- next part --------------
2019-05-24 Jakub Jelinek <jakub@redhat.com>
PR c++/90598
* tree.c (lvalue_kind): Return clk_none for MODIFY_EXPR with
VOID_TYPE_P.
* g++.dg/cpp0x/pr90598.C: New test.
--- gcc/cp/tree.c.jj 2019-05-20 21:59:19.886720194 +0200
+++ gcc/cp/tree.c 2019-05-23 23:37:42.335181291 +0200
@@ -245,6 +245,10 @@ lvalue_kind (const_tree ref)
return clk_ordinary;
case MODIFY_EXPR:
+ if (TREE_TYPE (ref) && VOID_TYPE_P (TREE_TYPE (ref)))
+ return clk_none;
+ return clk_ordinary;
+
case TYPEID_EXPR:
return clk_ordinary;
--- gcc/testsuite/g++.dg/cpp0x/pr90598.C.jj 2019-05-23 18:39:37.034464509 +0200
+++ gcc/testsuite/g++.dg/cpp0x/pr90598.C 2019-05-23 18:39:05.471980348 +0200
@@ -0,0 +1,8 @@
+// PR c++/90598
+// { dg-do compile { target c++11 } }
+
+struct A {};
+using B = decltype(A ().~A ());
+template <typename T> struct C;
+template <> struct C<void> {};
+C<B> t;
More information about the Gcc-patches
mailing list