PR c++/81525 - wrong constant value with generic lambda
authorJason Merrill <jason@redhat.com>
Wed, 9 Aug 2017 19:21:49 +0000 (15:21 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 9 Aug 2017 19:21:49 +0000 (15:21 -0400)
* pt.c (tsubst_decl) [VAR_DECL]: Avoid clobbering auto.
(tsubst_copy) [VAR_DECL]: Handle auto.

From-SVN: r250999

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C [new file with mode: 0644]

index 5476c1135b6994caed0b35674aa88d0d3d2f8113..d3510cf1965797d9b79d6248edc67987c8a08870 100644 (file)
@@ -1,5 +1,9 @@
 2017-08-09  Jason Merrill  <jason@redhat.com>
 
+       PR c++/81525 - wrong constant value with generic lambda
+       * pt.c (tsubst_decl) [VAR_DECL]: Avoid clobbering auto.
+       (tsubst_copy) [VAR_DECL]: Handle auto.
+
        PR c++/81359 - Unparsed NSDMI error from SFINAE context.
        * init.c (get_nsdmi): Add complain parm.
        * typeck2.c (digest_nsdmi_init): Add complain parm.
index 3d6f4b512b536484c7add41d645580c20f4e2b91..0f899b9edecb45b5dafd79ea13415338de6f8b6f 100644 (file)
@@ -12875,7 +12875,15 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
                && VAR_HAD_UNKNOWN_BOUND (t)
                && type != error_mark_node)
              type = strip_array_domain (type);
+           tree auto_node = type_uses_auto (type);
+           int len = TREE_VEC_LENGTH (args);
+           if (auto_node)
+             /* Mask off any template args past the variable's context so we
+                don't replace the auto with an unrelated argument.  */
+             TREE_VEC_LENGTH (args) = TEMPLATE_TYPE_LEVEL (auto_node) - 1;
            type = tsubst (type, args, complain, in_decl);
+           if (auto_node)
+             TREE_VEC_LENGTH (args) = len;
          }
        if (VAR_P (r))
          {
@@ -14656,6 +14664,10 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
                        DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)
                          = TREE_CONSTANT (r) = true;
                      DECL_INITIAL (r) = init;
+                     if (tree auto_node = type_uses_auto (TREE_TYPE (r)))
+                       TREE_TYPE (r)
+                         = do_auto_deduction (TREE_TYPE (r), init, auto_node,
+                                              complain, adc_variable_type);
                    }
                  gcc_assert (cp_unevaluated_operand || TREE_STATIC (r)
                              || decl_constant_var_p (r)
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C
new file mode 100644 (file)
index 0000000..52f4373
--- /dev/null
@@ -0,0 +1,20 @@
+// PR c++/81525
+// { dg-do compile { target c++14 } }
+
+template <int i> struct A {
+  constexpr operator int () const { return i; }
+};
+template <int i> constexpr A<i> a = {};
+
+template <typename F> void foo (F f) {
+  f (A<0>{});
+}
+template <typename T>
+void bar (T) {
+  constexpr auto N = a<1>;
+  auto f = [&] (auto i) {
+    static_assert (static_cast<int>(N) == 1, "");
+  };
+  foo (f);
+}
+int main () { bar (0); }