This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix ICE with PTRMEM_CST (PR c++/70869)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Jason Merrill <jason at redhat dot com>, Kai Tietz <ktietz70 at googlemail dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Fri, 1 Jul 2016 17:23:19 +0200
- Subject: [C++ PATCH] Fix ICE with PTRMEM_CST (PR c++/70869)
- Authentication-results: sourceware.org; auth=none
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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