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 <ja...@redhat.com> Kai Tietz <ktiet...@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