PR c++/82053 - ICE with default argument in lambda in template
authorJason Merrill <jason@redhat.com>
Thu, 7 Sep 2017 01:02:46 +0000 (21:02 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 7 Sep 2017 01:02:46 +0000 (21:02 -0400)
* pt.c (tsubst_arg_types): Substitute default arguments for lambdas
in templates.
(retrieve_specialization): Use lambda_fn_in_template_p.
* cp-tree.h: Declare it.

From-SVN: r251826

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

index e497094c4d50b46ab96f3f472ec5e862c5443e25..6c4a31d7850e902c4f1b7c39e79c8a2558123ad5 100644 (file)
@@ -1,5 +1,11 @@
 2017-09-06  Jason Merrill  <jason@redhat.com>
 
+       PR c++/82053 - ICE with default argument in lambda in template
+       * pt.c (tsubst_arg_types): Substitute default arguments for lambdas
+       in templates.
+       (retrieve_specialization): Use lambda_fn_in_template_p.
+       * cp-tree.h: Declare it.
+
        PR c++/82070 - error with nested lambda capture
        * pt.c (tsubst_expr) [DECL_EXPR]: Register capture proxies with
        register_local_specialization.
index 20fa03915c55c05626b730b6e30f7cfdb2f04deb..a0e31d3d19d313dbbe7944e81bf17149e307069f 100644 (file)
@@ -6821,6 +6821,7 @@ extern tree current_nonlambda_function            (void);
 extern tree nonlambda_method_basetype          (void);
 extern tree current_nonlambda_scope            (void);
 extern bool generic_lambda_fn_p                        (tree);
+extern bool lambda_fn_in_template_p            (tree);
 extern void maybe_add_lambda_conv_op            (tree);
 extern bool is_lambda_ignored_entity            (tree);
 extern bool lambda_static_thunk_p              (tree);
index 4a65e31b6618e45039f340d4dee997129e8a0478..ec7bbc890c6b93a0e1126313ebad4939573b2254 100644 (file)
@@ -1193,16 +1193,8 @@ retrieve_specialization (tree tmpl, tree args, hashval_t hash)
 
   /* Lambda functions in templates aren't instantiated normally, but through
      tsubst_lambda_expr.  */
-  if (LAMBDA_FUNCTION_P (tmpl))
-    {
-      bool generic = PRIMARY_TEMPLATE_P (tmpl);
-      if (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)) > generic)
-       return NULL_TREE;
-
-      /* But generic lambda functions are instantiated normally, once their
-        containing context is fully instantiated.  */
-      gcc_assert (generic);
-    }
+  if (lambda_fn_in_template_p (tmpl))
+    return NULL_TREE;
 
   if (optimize_specialization_lookup_p (tmpl))
     {
@@ -12579,7 +12571,7 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain,
 bool
 lambda_fn_in_template_p (tree fn)
 {
-  if (!LAMBDA_FUNCTION_P (fn))
+  if (!fn || !LAMBDA_FUNCTION_P (fn))
     return false;
   tree closure = DECL_CONTEXT (fn);
   return CLASSTYPE_TEMPLATE_INFO (closure) != NULL_TREE;
@@ -13248,6 +13240,13 @@ tsubst_arg_types (tree arg_types,
        done in build_over_call.  */
     default_arg = TREE_PURPOSE (arg_types);
 
+    /* Except that we do substitute default arguments under tsubst_lambda_expr,
+       since the new op() won't have any associated template arguments for us
+       to refer to later.  */
+    if (lambda_fn_in_template_p (in_decl))
+      default_arg = tsubst_copy_and_build (default_arg, args, complain, in_decl,
+                                          false/*fn*/, false/*constexpr*/);
+
     if (default_arg && TREE_CODE (default_arg) == DEFAULT_ARG)
       {
         /* We've instantiated a template before its default arguments
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-defarg7.C b/gcc/testsuite/g++.dg/cpp1y/lambda-defarg7.C
new file mode 100644 (file)
index 0000000..f67dfee
--- /dev/null
@@ -0,0 +1,13 @@
+// PR c++/82053
+// { dg-do compile { target c++14 } }
+
+template<class T>
+int fn() { return 42; }
+
+template<class T>
+auto lam = [](int = fn<T>()){};
+
+int main()
+{
+  lam<int>();
+}