[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