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

Reply via email to