This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH] Fix ICE with PTRMEM_CST (PR c++/70869)


Hi!

As mentioned in the PR, we ICE on these testcases because PTRMEM_CST for
non-static var DECL_INITIAL is now supposed to be replaced during
genericization, but for some artifical vars the initializers are actually
never genericized.

For user variables, the VAR_DECLs should appear in BIND_EXPR_VARS and
walk_tree walks those when walking the corresponding BIND_EXPR.
So I think walking the initializers for non-artificial vars is a waste of
time, though genericization is using a pointer-set and thus shouldn't walk
anything multiple times, so if you think dropping the DECL_ARTIFICIAL
is desirable, I can try to test that.
The walking is only done on DECL_EXPR.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/6.2?

2016-07-01  Jakub Jelinek  <jakub@redhat.com>
	    Kai Tietz  <ktietz70@googlemail.com>

	PR c++/70869
	PR c++/71054
	* cp-gimplify.c (cp_genericize_r): For DECL_EXPR for non-static
	artificial vars, genericize their initializers.

	* g++.dg/cpp0x/pr70869.C: New test.
	* g++.dg/cpp0x/pr71054.C: New test.

--- gcc/cp/cp-gimplify.c.jj	2016-06-15 09:17:22.000000000 +0200
+++ gcc/cp/cp-gimplify.c	2016-07-01 14:36:16.222764199 +0200
@@ -1304,7 +1304,15 @@ cp_genericize_r (tree *stmt_p, int *walk
     {
       tree d = DECL_EXPR_DECL (stmt);
       if (TREE_CODE (d) == VAR_DECL)
-	gcc_assert (CP_DECL_THREAD_LOCAL_P (d) == DECL_THREAD_LOCAL_P (d));
+	{
+	  gcc_assert (CP_DECL_THREAD_LOCAL_P (d) == DECL_THREAD_LOCAL_P (d));
+	  /* User var initializers should be genericized during containing
+	     BIND_EXPR genericization when walk_tree walks DECL_INITIAL
+	     of BIND_EXPR_VARS.  Artificial temporaries might not be
+	     mentioned there though, so walk them now.  */
+	  if (DECL_ARTIFICIAL (d) && !TREE_STATIC (d) && DECL_INITIAL (d))
+	    cp_walk_tree (&DECL_INITIAL (d), cp_genericize_r, data, NULL);
+	}
     }
   else if (TREE_CODE (stmt) == OMP_PARALLEL
 	   || TREE_CODE (stmt) == OMP_TASK
--- gcc/testsuite/g++.dg/cpp0x/pr70869.C.jj	2016-07-01 14:45:47.737806235 +0200
+++ gcc/testsuite/g++.dg/cpp0x/pr70869.C	2016-07-01 14:45:09.000000000 +0200
@@ -0,0 +1,25 @@
+// PR c++/70869
+// { dg-do run { target c++11 } }
+
+#include <initializer_list>
+
+struct A
+{
+  int f () { return 1; }
+  int g () { return 2; }
+  int h () { return 3; }
+};
+
+int
+main ()
+{
+  int cnt = 0;
+  for (const auto &m : { &A::f, &A::g, &A::h })
+    {
+      A a;
+      if ((a.*m) () != ++cnt)
+	__builtin_abort ();
+    }
+  if (cnt != 3)
+    __builtin_abort ();
+}
--- gcc/testsuite/g++.dg/cpp0x/pr71054.C.jj	2016-07-01 14:53:31.650154643 +0200
+++ gcc/testsuite/g++.dg/cpp0x/pr71054.C	2016-07-01 14:53:25.000000000 +0200
@@ -0,0 +1,21 @@
+// PR c++/71054
+// { dg-do compile { target c++11 } }
+
+#include <initializer_list>
+
+template <typename D, typename T = decltype (&D::U)>
+struct S
+{
+  struct A
+  {
+    int a;
+    int b;
+    T p;
+  };
+  S () { std::initializer_list<A> a{ {0, 0, &D::V} }; }
+};
+struct R {
+  void V (int);
+  void U (int);
+};
+S<R> b;

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]