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