OK.
On Sat, Aug 4, 2018 at 1:54 AM, Jakub Jelinek <ja...@redhat.com> wrote: > Hi! > > As mentioned in the PR, for valid structured bindings this patch should be > unnecessary, because the identifiers from the structured binding shouldn't > be used in the initializer of the structured binding, but for invalid source > it can matter. When tsubst_init is called before tsubst_decomp_names, > the local specializations for the decomp id VAR_DECLs aren't created and > so the tsubst of those VAR_DECLs gives the PARM_DECL in this testcase, or > something else unrelated to the decomp. > > Fixed by doing tsubst_decomp_names first, then tsubst_init the initializer > and then the rest. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk and 8.3 > after a while? > > 2018-08-03 Jakub Jelinek <ja...@redhat.com> > > PR c++/86836 > * pt.c (tsubst_expr): For structured bindings, call > tsubst_decomp_names > before tsubst_init, not after it. > > * g++.dg/cpp1z/decomp46.C: New test. > > --- gcc/cp/pt.c.jj 2018-08-03 11:36:25.550755429 +0200 > +++ gcc/cp/pt.c 2018-08-03 11:48:51.144567965 +0200 > @@ -16740,7 +16740,17 @@ tsubst_expr (tree t, tree args, tsubst_f > else > { > int const_init = false; > + unsigned int cnt = 0; > + tree first = NULL_TREE, ndecl = error_mark_node; > maybe_push_decl (decl); > + > + if (VAR_P (decl) > + && DECL_DECOMPOSITION_P (decl) > + && TREE_TYPE (pattern_decl) != error_mark_node) > + ndecl = tsubst_decomp_names (decl, pattern_decl, args, > + complain, in_decl, &first, > + &cnt); > + > if (VAR_P (decl) > && DECL_PRETTY_FUNCTION_P (decl)) > { > @@ -16756,23 +16766,14 @@ tsubst_expr (tree t, tree args, tsubst_f > if (VAR_P (decl)) > const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P > (pattern_decl)); > - if (VAR_P (decl) > - && DECL_DECOMPOSITION_P (decl) > - && TREE_TYPE (pattern_decl) != error_mark_node) > - { > - unsigned int cnt; > - tree first; > - tree ndecl > - = tsubst_decomp_names (decl, pattern_decl, args, > - complain, in_decl, &first, > &cnt); > - if (ndecl != error_mark_node) > - cp_maybe_mangle_decomp (ndecl, first, cnt); > - cp_finish_decl (decl, init, const_init, NULL_TREE, 0); > - if (ndecl != error_mark_node) > - cp_finish_decomp (ndecl, first, cnt); > - } > - else > - cp_finish_decl (decl, init, const_init, NULL_TREE, 0); > + > + if (ndecl != error_mark_node) > + cp_maybe_mangle_decomp (ndecl, first, cnt); > + > + cp_finish_decl (decl, init, const_init, NULL_TREE, 0); > + > + if (ndecl != error_mark_node) > + cp_finish_decomp (ndecl, first, cnt); > } > } > } > --- gcc/testsuite/g++.dg/cpp1z/decomp46.C.jj 2018-08-03 12:00:10.524066454 > +0200 > +++ gcc/testsuite/g++.dg/cpp1z/decomp46.C 2018-08-03 11:59:49.925018174 > +0200 > @@ -0,0 +1,25 @@ > +// PR c++/86836 > +// { dg-do compile { target c++11 } } > +// { dg-options "" } > + > +struct A { > + int operator*(); > + void operator++(); > + bool operator!=(A); > +}; > +template <typename> class map { > +public: > + A begin(); > + A end(); > +}; > + > +template <typename T> void mergemap(map<T> orig, map<T> toadd) { > + for (auto p : toadd) > + auto [orig] = orig; // { dg-error "use of 'orig' before > deduction of 'auto'" } > +} // { dg-warning "structured bindings only > available with" "" { target c++14_down } .-1 } > + > +int > +main() { > + map<double> x, y; > + mergemap(x, y); > +} > > Jakub