Re: [C++ PATCH] Fix ICE with PTRMEM_CST (PR c++/70869)
OK for trunk; just the earlier patch is fine for 6.2. On Mon, Jul 11, 2016 at 4:17 PM, Jakub Jelinekwrote: > On Thu, Jul 07, 2016 at 03:06:55PM -0400, Jason Merrill wrote: >> On Thu, Jul 7, 2016 at 2:23 PM, Jakub Jelinek wrote: >> > On Thu, Jul 07, 2016 at 12:32:02PM -0400, Jason Merrill wrote: >> >> Hmm, I wonder if walk_tree_1 should walk into DECL_EXPR like it does into >> >> BIND_EXPR_VARS. But your patch is OK. >> > >> > Well, walk_tree_1 does walk into DECL_EXPR, but cp_genericize_r says >> > *walk_subtrees on the VAR_DECL inside of it. >> > When walking BIND_EXPR_VARS, it doesn't walk the vars themselves, but >> > /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk >> >into declarations that are just mentioned, rather than >> >declared; they don't really belong to this part of the tree. >> >And, we can see cycles: the initializer for a declaration >> >can refer to the declaration itself. */ >> > WALK_SUBTREE (DECL_INITIAL (decl)); >> > WALK_SUBTREE (DECL_SIZE (decl)); >> > WALK_SUBTREE (DECL_SIZE_UNIT (decl)); >> > Do you mean walk_tree_1 should walk DECL_INITIAL/DECL_SIZE/DECL_SIZE_UNIT >> > of the var mentioned in the DECL_EXPR? Then for many vars (which are both >> > mentioned in BIND_EXPR_VARS and in DECL_EXPR) it would walk them twice. >> >> Yes, that's what I meant. Or perhaps since this is a C++ FE issue, >> cp_walk_subtrees should walk those fields for artificial variables. > > I've already committed the patch, given your "But your patch is OK." above. > But the following works too, bootstrapped/regtested on x86_64-linux and > i686-linux, ok for trunk? > > If yes, do you want the combined diff from both patches on the 6.2 branch > too, or just the earlier patch? > > 2016-07-11 Jakub Jelinek > > PR c++/70869 > PR c++/71054 > * cp-gimplify.c (cp_genericize_r): Revert the 2016-07-07 change. > * tree.c (cp_walk_subtrees): For DECL_EXPR on DECL_ARTIFICIAL > non-static VAR_DECL, walk the decl's DECL_INITIAL, DECL_SIZE and > DECL_SIZE_UNIT. > > --- gcc/cp/cp-gimplify.c.jj 2016-07-11 11:24:30.554083084 +0200 > +++ gcc/cp/cp-gimplify.c2016-07-11 15:21:30.459546129 +0200 > @@ -1351,15 +1351,7 @@ 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)); > - /* 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 (_INITIAL (d), cp_genericize_r, data, NULL); > - } > + gcc_assert (CP_DECL_THREAD_LOCAL_P (d) == DECL_THREAD_LOCAL_P (d)); > } >else if (TREE_CODE (stmt) == OMP_PARALLEL >|| TREE_CODE (stmt) == OMP_TASK > --- gcc/cp/tree.c.jj2016-07-11 11:14:28.0 +0200 > +++ gcc/cp/tree.c 2016-07-11 15:30:38.635047697 +0200 > @@ -4075,6 +4075,22 @@ cp_walk_subtrees (tree *tp, int *walk_su >*walk_subtrees_p = 0; >break; > > +case DECL_EXPR: > + /* User variables should be mentioned in BIND_EXPR_VARS > +and their initializers and sizes walked when walking > +the containing BIND_EXPR. Compiler temporaries are > +handled here. */ > + if (VAR_P (TREE_OPERAND (*tp, 0)) > + && DECL_ARTIFICIAL (TREE_OPERAND (*tp, 0)) > + && !TREE_STATIC (TREE_OPERAND (*tp, 0))) > + { > + tree decl = TREE_OPERAND (*tp, 0); > + WALK_SUBTREE (DECL_INITIAL (decl)); > + WALK_SUBTREE (DECL_SIZE (decl)); > + WALK_SUBTREE (DECL_SIZE_UNIT (decl)); > + } > + break; > + > default: >return NULL_TREE; > } > > > Jakub
Re: [C++ PATCH] Fix ICE with PTRMEM_CST (PR c++/70869)
On Thu, Jul 07, 2016 at 03:06:55PM -0400, Jason Merrill wrote: > On Thu, Jul 7, 2016 at 2:23 PM, Jakub Jelinekwrote: > > On Thu, Jul 07, 2016 at 12:32:02PM -0400, Jason Merrill wrote: > >> Hmm, I wonder if walk_tree_1 should walk into DECL_EXPR like it does into > >> BIND_EXPR_VARS. But your patch is OK. > > > > Well, walk_tree_1 does walk into DECL_EXPR, but cp_genericize_r says > > *walk_subtrees on the VAR_DECL inside of it. > > When walking BIND_EXPR_VARS, it doesn't walk the vars themselves, but > > /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk > >into declarations that are just mentioned, rather than > >declared; they don't really belong to this part of the tree. > >And, we can see cycles: the initializer for a declaration > >can refer to the declaration itself. */ > > WALK_SUBTREE (DECL_INITIAL (decl)); > > WALK_SUBTREE (DECL_SIZE (decl)); > > WALK_SUBTREE (DECL_SIZE_UNIT (decl)); > > Do you mean walk_tree_1 should walk DECL_INITIAL/DECL_SIZE/DECL_SIZE_UNIT > > of the var mentioned in the DECL_EXPR? Then for many vars (which are both > > mentioned in BIND_EXPR_VARS and in DECL_EXPR) it would walk them twice. > > Yes, that's what I meant. Or perhaps since this is a C++ FE issue, > cp_walk_subtrees should walk those fields for artificial variables. I've already committed the patch, given your "But your patch is OK." above. But the following works too, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? If yes, do you want the combined diff from both patches on the 6.2 branch too, or just the earlier patch? 2016-07-11 Jakub Jelinek PR c++/70869 PR c++/71054 * cp-gimplify.c (cp_genericize_r): Revert the 2016-07-07 change. * tree.c (cp_walk_subtrees): For DECL_EXPR on DECL_ARTIFICIAL non-static VAR_DECL, walk the decl's DECL_INITIAL, DECL_SIZE and DECL_SIZE_UNIT. --- gcc/cp/cp-gimplify.c.jj 2016-07-11 11:24:30.554083084 +0200 +++ gcc/cp/cp-gimplify.c2016-07-11 15:21:30.459546129 +0200 @@ -1351,15 +1351,7 @@ 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)); - /* 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 (_INITIAL (d), cp_genericize_r, data, NULL); - } + gcc_assert (CP_DECL_THREAD_LOCAL_P (d) == DECL_THREAD_LOCAL_P (d)); } else if (TREE_CODE (stmt) == OMP_PARALLEL || TREE_CODE (stmt) == OMP_TASK --- gcc/cp/tree.c.jj2016-07-11 11:14:28.0 +0200 +++ gcc/cp/tree.c 2016-07-11 15:30:38.635047697 +0200 @@ -4075,6 +4075,22 @@ cp_walk_subtrees (tree *tp, int *walk_su *walk_subtrees_p = 0; break; +case DECL_EXPR: + /* User variables should be mentioned in BIND_EXPR_VARS +and their initializers and sizes walked when walking +the containing BIND_EXPR. Compiler temporaries are +handled here. */ + if (VAR_P (TREE_OPERAND (*tp, 0)) + && DECL_ARTIFICIAL (TREE_OPERAND (*tp, 0)) + && !TREE_STATIC (TREE_OPERAND (*tp, 0))) + { + tree decl = TREE_OPERAND (*tp, 0); + WALK_SUBTREE (DECL_INITIAL (decl)); + WALK_SUBTREE (DECL_SIZE (decl)); + WALK_SUBTREE (DECL_SIZE_UNIT (decl)); + } + break; + default: return NULL_TREE; } Jakub
Re: [C++ PATCH] Fix ICE with PTRMEM_CST (PR c++/70869)
On Thu, Jul 7, 2016 at 2:23 PM, Jakub Jelinekwrote: > On Thu, Jul 07, 2016 at 12:32:02PM -0400, Jason Merrill wrote: >> Hmm, I wonder if walk_tree_1 should walk into DECL_EXPR like it does into >> BIND_EXPR_VARS. But your patch is OK. > > Well, walk_tree_1 does walk into DECL_EXPR, but cp_genericize_r says > *walk_subtrees on the VAR_DECL inside of it. > When walking BIND_EXPR_VARS, it doesn't walk the vars themselves, but > /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk >into declarations that are just mentioned, rather than >declared; they don't really belong to this part of the tree. >And, we can see cycles: the initializer for a declaration >can refer to the declaration itself. */ > WALK_SUBTREE (DECL_INITIAL (decl)); > WALK_SUBTREE (DECL_SIZE (decl)); > WALK_SUBTREE (DECL_SIZE_UNIT (decl)); > Do you mean walk_tree_1 should walk DECL_INITIAL/DECL_SIZE/DECL_SIZE_UNIT > of the var mentioned in the DECL_EXPR? Then for many vars (which are both > mentioned in BIND_EXPR_VARS and in DECL_EXPR) it would walk them twice. Yes, that's what I meant. Or perhaps since this is a C++ FE issue, cp_walk_subtrees should walk those fields for artificial variables. Jason
Re: [C++ PATCH] Fix ICE with PTRMEM_CST (PR c++/70869)
On Thu, Jul 07, 2016 at 12:32:02PM -0400, Jason Merrill wrote: > Hmm, I wonder if walk_tree_1 should walk into DECL_EXPR like it does into > BIND_EXPR_VARS. But your patch is OK. Well, walk_tree_1 does walk into DECL_EXPR, but cp_genericize_r says *walk_subtrees on the VAR_DECL inside of it. When walking BIND_EXPR_VARS, it doesn't walk the vars themselves, but /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk into declarations that are just mentioned, rather than declared; they don't really belong to this part of the tree. And, we can see cycles: the initializer for a declaration can refer to the declaration itself. */ WALK_SUBTREE (DECL_INITIAL (decl)); WALK_SUBTREE (DECL_SIZE (decl)); WALK_SUBTREE (DECL_SIZE_UNIT (decl)); Do you mean walk_tree_1 should walk DECL_INITIAL/DECL_SIZE/DECL_SIZE_UNIT of the var mentioned in the DECL_EXPR? Then for many vars (which are both mentioned in BIND_EXPR_VARS and in DECL_EXPR) it would walk them twice. Jakub
Re: [C++ PATCH] Fix ICE with PTRMEM_CST (PR c++/70869)
On Thu, Jul 7, 2016 at 12:32 PM, Jason Merrillwrote: > Hmm, I wonder if walk_tree_1 should walk into DECL_EXPR like it does into > BIND_EXPR_VARS. But your patch is OK. > > Jason > > > On Fri, Jul 1, 2016 at 11:23 AM, Jakub Jelinek wrote: >> >> 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 >> Kai Tietz >> >> 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.0 +0200 >> +++ gcc/cp/cp-gimplify.c2016-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 (_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.C2016-07-01 >> 14:45:09.0 +0200 >> @@ -0,0 +1,25 @@ >> +// PR c++/70869 >> +// { dg-do run { target c++11 } } >> + >> +#include >> + >> +struct A >> +{ >> + int f () { return 1; } >> + int g () { return 2; } >> + int h () { return 3; } >> +}; >> + >> +int >> +main () >> +{ >> + int cnt = 0; >> + for (const auto : { ::f, ::g, ::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.C2016-07-01 >> 14:53:25.0 +0200 >> @@ -0,0 +1,21 @@ >> +// PR c++/71054 >> +// { dg-do compile { target c++11 } } >> + >> +#include >> + >> +template >> +struct S >> +{ >> + struct A >> + { >> +int a; >> +int b; >> +T p; >> + }; >> + S () { std::initializer_list a{ {0, 0, ::V} }; } >> +}; >> +struct R { >> + void V (int); >> + void U (int); >> +}; >> +S b; >> >> Jakub > >
[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 JelinekKai Tietz 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.0 +0200 +++ gcc/cp/cp-gimplify.c2016-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 (_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.C2016-07-01 14:45:09.0 +0200 @@ -0,0 +1,25 @@ +// PR c++/70869 +// { dg-do run { target c++11 } } + +#include + +struct A +{ + int f () { return 1; } + int g () { return 2; } + int h () { return 3; } +}; + +int +main () +{ + int cnt = 0; + for (const auto : { ::f, ::g, ::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.C2016-07-01 14:53:25.0 +0200 @@ -0,0 +1,21 @@ +// PR c++/71054 +// { dg-do compile { target c++11 } } + +#include + +template +struct S +{ + struct A + { +int a; +int b; +T p; + }; + S () { std::initializer_list a{ {0, 0, ::V} }; } +}; +struct R { + void V (int); + void U (int); +}; +S b; Jakub