get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/807291/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 807291,
    "url": "http://patchwork.ozlabs.org/api/patches/807291/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/CADzB+2nk9ggOUZ-EZBs=6074RfRUckT68YyyaDNgh2x0P_YHjw@mail.gmail.com/",
    "project": {
        "id": 17,
        "url": "http://patchwork.ozlabs.org/api/projects/17/?format=api",
        "name": "GNU Compiler Collection",
        "link_name": "gcc",
        "list_id": "gcc-patches.gcc.gnu.org",
        "list_email": "gcc-patches@gcc.gnu.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<CADzB+2nk9ggOUZ-EZBs=6074RfRUckT68YyyaDNgh2x0P_YHjw@mail.gmail.com>",
    "list_archive_url": null,
    "date": "2017-08-29T20:36:57",
    "name": "C++ PATCH to overhaul lambdas in templates",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "d1dc843e0f2adfe80aac7b005d6e0eb46cd9c618",
    "submitter": {
        "id": 4337,
        "url": "http://patchwork.ozlabs.org/api/people/4337/?format=api",
        "name": "Jason Merrill",
        "email": "jason@redhat.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/CADzB+2nk9ggOUZ-EZBs=6074RfRUckT68YyyaDNgh2x0P_YHjw@mail.gmail.com/mbox/",
    "series": [
        {
            "id": 468,
            "url": "http://patchwork.ozlabs.org/api/series/468/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=468",
            "date": "2017-08-29T20:36:57",
            "name": "C++ PATCH to overhaul lambdas in templates",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/468/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/807291/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/807291/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<gcc-patches-return-461119-incoming=patchwork.ozlabs.org@gcc.gnu.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": [
            "patchwork-incoming@bilbo.ozlabs.org",
            "mailing list gcc-patches@gcc.gnu.org"
        ],
        "Authentication-Results": [
            "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=gcc-patches-return-461119-incoming=patchwork.ozlabs.org@gcc.gnu.org;\n\treceiver=<UNKNOWN>)",
            "ozlabs.org; dkim=pass (1024-bit key;\n\tunprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org\n\theader.b=\"j/mGIBVO\"; dkim-atps=neutral",
            "sourceware.org; auth=none"
        ],
        "Received": [
            "from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xhgS351hQz9s9Y\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed, 30 Aug 2017 06:37:38 +1000 (AEST)",
            "(qmail 124742 invoked by alias); 29 Aug 2017 20:37:29 -0000",
            "(qmail 124731 invoked by uid 89); 29 Aug 2017 20:37:28 -0000",
            "from mail-it0-f54.google.com (HELO mail-it0-f54.google.com)\n\t(209.85.214.54) by sourceware.org\n\t(qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP;\n\tTue, 29 Aug 2017 20:37:21 +0000",
            "by mail-it0-f54.google.com with SMTP id w191so637107itc.1 for\n\t<gcc-patches@gcc.gnu.org>; Tue, 29 Aug 2017 13:37:20 -0700 (PDT)",
            "by 10.107.181.23 with HTTP; Tue, 29 Aug 2017 13:36:57 -0700 (PDT)"
        ],
        "DomainKey-Signature": "a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender\n\t:mime-version:from:date:message-id:subject:to:content-type; q=\n\tdns; s=default; b=pvJrKRoULQtcfXfpPu+t0eOheFgmcS2s44jgEx+dmGhhv6\n\t4oiw2PtduUKVVtWb6KSxEDfNyfMrJoHfrpHi7GjWjiQ3nXnoAw3FKBACWOMY98wG\n\tcMuTho/vxt3xXsuHOKDITSSTnjrE1FeMYPzrtMLu7nO974KOvTc4MS5GvLhxY=",
        "DKIM-Signature": "v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender\n\t:mime-version:from:date:message-id:subject:to:content-type; s=\n\tdefault; bh=TNiJKVN/gmB933U8VXVKndBDIXA=; b=j/mGIBVO67Sz3tP1v8Dt\n\tD+JboTk1xWYWxRbp4+1V3pz/WvZlF19NcgHVWiBwyS2T6NOT4yzlZatwGnlYIRP0\n\tWdWS18PWOjHCcv1HzjpTkn+t84D7OvAUyX2JcGonULg1p18c2UdQ3SNuHAwTsd+O\n\tkDY9g+FaUbjS/HjcUcYrL18=",
        "Mailing-List": "contact gcc-patches-help@gcc.gnu.org; run by ezmlm",
        "Precedence": "bulk",
        "List-Id": "<gcc-patches.gcc.gnu.org>",
        "List-Unsubscribe": "<mailto:gcc-patches-unsubscribe-incoming=patchwork.ozlabs.org@gcc.gnu.org>",
        "List-Archive": "<http://gcc.gnu.org/ml/gcc-patches/>",
        "List-Post": "<mailto:gcc-patches@gcc.gnu.org>",
        "List-Help": "<mailto:gcc-patches-help@gcc.gnu.org>",
        "Sender": "gcc-patches-owner@gcc.gnu.org",
        "X-Virus-Found": "No",
        "X-Spam-SWARE-Status": "No, score=-24.5 required=5.0 tests=AWL, BAYES_00,\n\tGIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3,\n\tKAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW,\n\tRCVD_IN_SORBS_SPAM autolearn=ham version=3.3.2 spammy=",
        "X-HELO": "mail-it0-f54.google.com",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net;\n\ts=20161025;\n\th=x-gm-message-state:mime-version:from:date:message-id:subject:to;\n\tbh=uxvxhaNErvqksxstG+bEc831hmU5wrqk9bHDoMwUpiQ=;\n\tb=KN0fPmw0f0dRKyAh10JRjtamHsPEMWWFV6QlkNpOs0QDWjCjlN/EvCRbqjIyZxZyyG\n\t64GdxdMdDgP4zt6E/uWXxO0rVyQQVy8m53yuzQL7Rvu9OqHiEIoau0au9vGE68b5oRy2\n\t740m2DKQve9Ohj12sn9VFG2MynyWmoTrJX+4KPozqRmMXuRQc0WCx2xAsbzs1zs5avMI\n\tL1rYfejEi7N42e3GWAjY5DVQ1N3y2rk3/05ssK9vuJsdjp+tlrCjDzhvli8pUPJkB7dd\n\tGFPwt/SIMmzNmffiAGzilrACpIImE5wtqvhhxDiGNlXWMi9yx83dQGW1hGn4yrsRuQls\n\t8RxQ==",
        "X-Gm-Message-State": "AHYfb5hXLWIbAKft5RoJatiwX3hR7hA2DXqJxRsNp2K4S3QBPDJ8ZPYn\tr/kTskIq1Vz3oTj/dpLJWwHmttPyAnR9/J4J3w==",
        "X-Received": "by 10.36.159.194 with SMTP id c185mr6271708ite.181.1504039038571;\n\tTue, 29 Aug 2017 13:37:18 -0700 (PDT)",
        "MIME-Version": "1.0",
        "From": "Jason Merrill <jason@redhat.com>",
        "Date": "Tue, 29 Aug 2017 16:36:57 -0400",
        "Message-ID": "<CADzB+2nk9ggOUZ-EZBs=6074RfRUckT68YyyaDNgh2x0P_YHjw@mail.gmail.com>",
        "Subject": "C++ PATCH to overhaul lambdas in templates",
        "To": "gcc-patches List <gcc-patches@gcc.gnu.org>",
        "Content-Type": "multipart/mixed; boundary=\"94eb2c08e5509fde0d0557ea6018\"",
        "X-IsSubscribed": "yes"
    },
    "content": "Our old model for handling lambdas in templates was to handle them\nlike any other template class, and instantiate them by normal\nsubstitution.  This was insufficient for lambdas for two reasons: for\none, it made it impossible to get implicit captures quite right in\ntemplates.\n\nAlso, if a lambda appears in a pack expansion, e.g.\n\ntemplate <class... T>\nauto f() {\n  int i = 42;\n  return ([i]{ return T(i); }() + ...);\n}\n\nThere needs to be one lambda for each element of T, not just one for\neach instantiation of f.  So instantiating a LAMBDA_EXPR needs to\nbuild up a new LAMBDA_EXPR each time.  This patch implements that,\nprimarily in the new tsubst_lambda_expr function.\n\nGenerating the op() decl for the new lambda is a lot like a normal\ninstantiation, but not quite.  I decided to do this by factoring out\ntsubst_function_decl and tsubst_template_decl, and having them handle\nthe lambda special case appropriately: when we're dealing with the\nlambda function, it isn't actually a specialization of the lambda in\nthe template, and it isn't a member of a specialization of the closure\nin the template.\n\nThe code in process_outer_var_ref for handling generic lambdas\nspecifically can now go away; we now defer implicit capture until the\nenclosing context is instantiated for generic and non-generic lambdas.\n\nTested x86_64-pc-linux-gnu, applying to trunk.\ncommit bdbf060161375648283cf82d4662362ea788b298\nAuthor: Jason Merrill <jason@redhat.com>\nDate:   Thu Jul 6 19:32:32 2017 -0400\n\n            Reimplement handling of lambdas in templates.\n    \n            * cp-tree.h (LAMBDA_FUNCTION_P): Check DECL_DECLARES_FUNCTION_P.\n            * decl.c (start_preparsed_function): Call start_lambda_scope.\n            (finish_function): Call finish_lambda_scope.\n            * init.c (get_nsdmi): Call start/finish_lambda_scope.\n            * lambda.c (start_lambda_scope): Only ignore VAR_DECL in a function.\n            * parser.c (cp_parser_function_definition_after_declarator): Don't\n            call start/finish_lambda_scope.\n            * pt.c (retrieve_specialization): Ignore lambda functions in\n            templates.\n            (find_parameter_packs_r): Ignore capture proxies.  Look into\n            lambdas.\n            (check_for_bare_parameter_packs): Allow bare packs in lambdas.\n            (tsubst_default_argument): Call start/finish_lambda_scope.\n            (tsubst_function_decl): Handle lambda functions differently.\n            (tsubst_template_decl): Likewise.\n            (tsubst_expr) [DECL_EXPR]: Skip closure declarations and capture\n            proxies.\n            (tsubst_lambda_expr): Create a new closure rather than instantiate\n            the one from the template.\n            (tsubst_copy_and_build): Don't register a specialization of a pack.\n            (regenerate_decl_from_template): Call start/finish_lambda_scope.\n            (instantiate_decl): Remove special lambda function handling.\n            * semantics.c (process_outer_var_ref): Remove special generic lambda\n            handling.  Don't implicitly capture in a lambda in a template.  Look\n            for an existing proxy.\n            * class.c (current_nonlambda_class_type): Use decl_type_context.",
    "diff": "diff --git a/gcc/cp/class.c b/gcc/cp/class.c\nindex 28cf7dc..a5f1007 100644\n--- a/gcc/cp/class.c\n+++ b/gcc/cp/class.c\n@@ -7709,27 +7709,10 @@ outermost_open_class (void)\n tree\n current_nonlambda_class_type (void)\n {\n-  int i;\n-\n-  /* We start looking from 1 because entry 0 is from global scope,\n-     and has no type.  */\n-  for (i = current_class_depth; i > 0; --i)\n-    {\n-      tree c;\n-      if (i == current_class_depth)\n-\tc = current_class_type;\n-      else\n-\t{\n-\t  if (current_class_stack[i].hidden)\n-\t    break;\n-\t  c = current_class_stack[i].type;\n-\t}\n-      if (!c)\n-\tcontinue;\n-      if (!LAMBDA_TYPE_P (c))\n-\treturn c;\n-    }\n-  return NULL_TREE;\n+  tree type = current_class_type;\n+  while (type && LAMBDA_TYPE_P (type))\n+    type = decl_type_context (TYPE_NAME (type));\n+  return type;\n }\n \n /* When entering a class scope, all enclosing class scopes' names with\ndiff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h\nindex ad97be4..41c48ec 100644\n--- a/gcc/cp/cp-tree.h\n+++ b/gcc/cp/cp-tree.h\n@@ -1216,8 +1216,9 @@ struct GTY (()) tree_trait_expr {\n   (CLASS_TYPE_P (NODE) && CLASSTYPE_LAMBDA_EXPR (NODE))\n \n /* Test if FUNCTION_DECL is a lambda function.  */\n-#define LAMBDA_FUNCTION_P(FNDECL) \\\n-  (DECL_OVERLOADED_OPERATOR_P (FNDECL) == CALL_EXPR \\\n+#define LAMBDA_FUNCTION_P(FNDECL)\t\t\t\\\n+  (DECL_DECLARES_FUNCTION_P (FNDECL)\t\t\t\\\n+   && DECL_OVERLOADED_OPERATOR_P (FNDECL) == CALL_EXPR\t\\\n    && LAMBDA_TYPE_P (CP_DECL_CONTEXT (FNDECL)))\n \n enum cp_lambda_default_capture_mode_type {\n@@ -6828,6 +6829,11 @@ extern bool is_lambda_ignored_entity            (tree);\n extern bool lambda_static_thunk_p\t\t(tree);\n extern tree finish_builtin_launder\t\t(location_t, tree,\n \t\t\t\t\t\t tsubst_flags_t);\n+extern void start_lambda_scope\t\t\t(tree);\n+extern void record_lambda_scope\t\t\t(tree);\n+extern void finish_lambda_scope\t\t\t(void);\n+extern tree start_lambda_function\t\t(tree fn, tree lambda_expr);\n+extern void finish_lambda_function\t\t(tree body);\n \n /* in tree.c */\n extern int cp_tree_operand_length\t\t(const_tree);\ndiff --git a/gcc/cp/decl.c b/gcc/cp/decl.c\nindex 23829b0..d6b80c6 100644\n--- a/gcc/cp/decl.c\n+++ b/gcc/cp/decl.c\n@@ -15097,6 +15097,8 @@ start_preparsed_function (tree decl1, tree attrs, int flags)\n       && !implicit_default_ctor_p (decl1))\n     cp_ubsan_maybe_initialize_vtbl_ptrs (current_class_ptr);\n \n+  start_lambda_scope (decl1);\n+\n   return true;\n }\n \n@@ -15462,6 +15464,8 @@ finish_function (int flags)\n   if (fndecl == NULL_TREE)\n     return error_mark_node;\n \n+  finish_lambda_scope ();\n+\n   if (c_dialect_objc ())\n     objc_finish_function ();\n \n@@ -15565,11 +15569,11 @@ finish_function (int flags)\n \n   /* Lambda closure members are implicitly constexpr if possible.  */\n   if (cxx_dialect >= cxx1z\n-      && LAMBDA_TYPE_P (CP_DECL_CONTEXT (fndecl))\n-      && (processing_template_decl\n+      && LAMBDA_TYPE_P (CP_DECL_CONTEXT (fndecl)))\n+    DECL_DECLARED_CONSTEXPR_P (fndecl)\n+      = ((processing_template_decl\n \t  || is_valid_constexpr_fn (fndecl, /*complain*/false))\n-      && potential_constant_expression (DECL_SAVED_TREE (fndecl)))\n-    DECL_DECLARED_CONSTEXPR_P (fndecl) = true;\n+\t && potential_constant_expression (DECL_SAVED_TREE (fndecl)));\n \n   /* Save constexpr function body before it gets munged by\n      the NRV transformation.   */\ndiff --git a/gcc/cp/init.c b/gcc/cp/init.c\nindex 56a5df8..b01d662 100644\n--- a/gcc/cp/init.c\n+++ b/gcc/cp/init.c\n@@ -574,13 +574,17 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)\n \n \t  inject_this_parameter (DECL_CONTEXT (member), TYPE_UNQUALIFIED);\n \n+\t  start_lambda_scope (member);\n+\n \t  /* Do deferred instantiation of the NSDMI.  */\n \t  init = (tsubst_copy_and_build\n \t\t  (init, DECL_TI_ARGS (member),\n \t\t   complain, member, /*function_p=*/false,\n \t\t   /*integral_constant_expression_p=*/false));\n \t  init = digest_nsdmi_init (member, init, complain);\n-\t  \n+\n+\t  finish_lambda_scope ();\n+\n \t  DECL_INSTANTIATING_NSDMI_P (member) = 0;\n \n \t  if (init != error_mark_node)\ndiff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c\nindex 55d3415..4747a72 100644\n--- a/gcc/cp/lambda.c\n+++ b/gcc/cp/lambda.c\n@@ -1253,4 +1253,87 @@ is_lambda_ignored_entity (tree val)\n   return false;\n }\n \n+/* Lambdas that appear in variable initializer or default argument scope\n+   get that in their mangling, so we need to record it.  We might as well\n+   use the count for function and namespace scopes as well.  */\n+static GTY(()) tree lambda_scope;\n+static GTY(()) int lambda_count;\n+struct GTY(()) tree_int\n+{\n+  tree t;\n+  int i;\n+};\n+static GTY(()) vec<tree_int, va_gc> *lambda_scope_stack;\n+\n+void\n+start_lambda_scope (tree decl)\n+{\n+  tree_int ti;\n+  gcc_assert (decl);\n+  /* Once we're inside a function, we ignore variable scope and just push\n+     the function again so that popping works properly.  */\n+  if (current_function_decl && TREE_CODE (decl) == VAR_DECL)\n+    decl = current_function_decl;\n+  ti.t = lambda_scope;\n+  ti.i = lambda_count;\n+  vec_safe_push (lambda_scope_stack, ti);\n+  if (lambda_scope != decl)\n+    {\n+      /* Don't reset the count if we're still in the same function.  */\n+      lambda_scope = decl;\n+      lambda_count = 0;\n+    }\n+}\n+\n+void\n+record_lambda_scope (tree lambda)\n+{\n+  LAMBDA_EXPR_EXTRA_SCOPE (lambda) = lambda_scope;\n+  LAMBDA_EXPR_DISCRIMINATOR (lambda) = lambda_count++;\n+}\n+\n+void\n+finish_lambda_scope (void)\n+{\n+  tree_int *p = &lambda_scope_stack->last ();\n+  if (lambda_scope != p->t)\n+    {\n+      lambda_scope = p->t;\n+      lambda_count = p->i;\n+    }\n+  lambda_scope_stack->pop ();\n+}\n+\n+tree\n+start_lambda_function (tree fco, tree lambda_expr)\n+{\n+  /* Let the front end know that we are going to be defining this\n+     function.  */\n+  start_preparsed_function (fco,\n+\t\t\t    NULL_TREE,\n+\t\t\t    SF_PRE_PARSED | SF_INCLASS_INLINE);\n+\n+  tree body = begin_function_body ();\n+\n+  /* Push the proxies for any explicit captures.  */\n+  for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (lambda_expr); cap;\n+       cap = TREE_CHAIN (cap))\n+    build_capture_proxy (TREE_PURPOSE (cap));\n+\n+  return body;\n+}\n+\n+void\n+finish_lambda_function (tree body)\n+{\n+  finish_function_body (body);\n+\n+  /* Finish the function and generate code for it if necessary.  */\n+  tree fn = finish_function (/*inline*/2);\n+\n+  /* Only expand if the call op is not a template.  */\n+  if (!DECL_TEMPLATE_INFO (fn))\n+    expand_or_defer_fn (fn);\n+}\n+\n #include \"gt-cp-lambda.h\"\ndiff --git a/gcc/cp/parser.c b/gcc/cp/parser.c\nindex 9f62b43..d0d71fa 100644\n--- a/gcc/cp/parser.c\n+++ b/gcc/cp/parser.c\n@@ -9982,57 +9982,6 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)\n     }\n }\n \n-/* Lambdas that appear in variable initializer or default argument scope\n-   get that in their mangling, so we need to record it.  We might as well\n-   use the count for function and namespace scopes as well.  */\n-static GTY(()) tree lambda_scope;\n-static GTY(()) int lambda_count;\n-struct GTY(()) tree_int\n-{\n-  tree t;\n-  int i;\n-};\n-static GTY(()) vec<tree_int, va_gc> *lambda_scope_stack;\n-\n-static void\n-start_lambda_scope (tree decl)\n-{\n-  tree_int ti;\n-  gcc_assert (decl);\n-  /* Once we're inside a function, we ignore other scopes and just push\n-     the function again so that popping works properly.  */\n-  if (current_function_decl && TREE_CODE (decl) != FUNCTION_DECL)\n-    decl = current_function_decl;\n-  ti.t = lambda_scope;\n-  ti.i = lambda_count;\n-  vec_safe_push (lambda_scope_stack, ti);\n-  if (lambda_scope != decl)\n-    {\n-      /* Don't reset the count if we're still in the same function.  */\n-      lambda_scope = decl;\n-      lambda_count = 0;\n-    }\n-}\n-\n-static void\n-record_lambda_scope (tree lambda)\n-{\n-  LAMBDA_EXPR_EXTRA_SCOPE (lambda) = lambda_scope;\n-  LAMBDA_EXPR_DISCRIMINATOR (lambda) = lambda_count++;\n-}\n-\n-static void\n-finish_lambda_scope (void)\n-{\n-  tree_int *p = &lambda_scope_stack->last ();\n-  if (lambda_scope != p->t)\n-    {\n-      lambda_scope = p->t;\n-      lambda_count = p->i;\n-    }\n-  lambda_scope_stack->pop ();\n-}\n-\n /* Parse a lambda expression.\n \n    lambda-expression:\n@@ -10605,29 +10554,14 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)\n      + ctor_initializer_opt_and_function_body  */\n   {\n     tree fco = lambda_function (lambda_expr);\n-    tree body;\n+    tree body = start_lambda_function (fco, lambda_expr);\n     bool done = false;\n     tree compound_stmt;\n-    tree cap;\n-\n-    /* Let the front end know that we are going to be defining this\n-       function.  */\n-    start_preparsed_function (fco,\n-\t\t\t      NULL_TREE,\n-\t\t\t      SF_PRE_PARSED | SF_INCLASS_INLINE);\n-\n-    start_lambda_scope (fco);\n-    body = begin_function_body ();\n \n     matching_braces braces;\n     if (!braces.require_open (parser))\n       goto out;\n \n-    /* Push the proxies for any explicit captures.  */\n-    for (cap = LAMBDA_EXPR_CAPTURE_LIST (lambda_expr); cap;\n-\t cap = TREE_CHAIN (cap))\n-      build_capture_proxy (TREE_PURPOSE (cap));\n-\n     compound_stmt = begin_compound_stmt (0);\n \n     /* 5.1.1.4 of the standard says:\n@@ -10691,15 +10625,7 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)\n     finish_compound_stmt (compound_stmt);\n \n   out:\n-    finish_function_body (body);\n-    finish_lambda_scope ();\n-\n-    /* Finish the function and generate code for it if necessary.  */\n-    tree fn = finish_function (/*inline*/2);\n-\n-    /* Only expand if the call op is not a template.  */\n-    if (!DECL_TEMPLATE_INFO (fco))\n-      expand_or_defer_fn (fn);\n+    finish_lambda_function (body);\n   }\n \n   restore_omp_privatization_clauses (omp_privatization_save);\n@@ -26577,8 +26503,6 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,\n     = parser->num_template_parameter_lists;\n   parser->num_template_parameter_lists = 0;\n \n-  start_lambda_scope (current_function_decl);\n-\n   /* If the next token is `try', `__transaction_atomic', or\n      `__transaction_relaxed`, then we are looking at either function-try-block\n      or function-transaction-block.  Note that all of these include the\n@@ -26596,8 +26520,6 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,\n     ctor_initializer_p = cp_parser_ctor_initializer_opt_and_function_body\n       (parser, /*in_function_try_block=*/false);\n \n-  finish_lambda_scope ();\n-\n   /* Finish the function.  */\n   fn = finish_function ((ctor_initializer_p ? 1 : 0) |\n \t\t\t(inline_p ? 2 : 0));\ndiff --git a/gcc/cp/pt.c b/gcc/cp/pt.c\nindex e064a11..141b4d7 100644\n--- a/gcc/cp/pt.c\n+++ b/gcc/cp/pt.c\n@@ -220,6 +220,7 @@ static bool complex_alias_template_p (const_tree tmpl);\n static tree tsubst_attributes (tree, tree, tsubst_flags_t, tree);\n static tree canonicalize_expr_argument (tree, tsubst_flags_t);\n static tree make_argument_pack (tree);\n+static void register_parameter_specializations (tree, tree);\n \n /* Make the current scope suitable for access checking when we are\n    processing T.  T can be FUNCTION_DECL for instantiated function\n@@ -1190,6 +1191,19 @@ retrieve_specialization (tree tmpl, tree args, hashval_t hash)\n   if (flag_checking)\n     verify_unstripped_args (args);\n \n+  /* Lambda functions in templates aren't instantiated normally, but through\n+     tsubst_lambda_expr.  */\n+  if (LAMBDA_FUNCTION_P (tmpl))\n+    {\n+      bool generic = PRIMARY_TEMPLATE_P (tmpl);\n+      if (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)) > generic)\n+\treturn NULL_TREE;\n+\n+      /* But generic lambda functions are instantiated normally, once their\n+\t containing context is fully instantiated.  */\n+      gcc_assert (generic);\n+    }\n+\n   if (optimize_specialization_lookup_p (tmpl))\n     {\n       /* The template arguments actually apply to the containing\n@@ -3615,6 +3629,12 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)\n     case PARM_DECL:\n       return NULL_TREE;\n \n+    case DECL_EXPR:\n+      /* Ignore the declaration of a capture proxy for a parameter pack.  */\n+      if (is_capture_proxy (DECL_EXPR_DECL (t)))\n+\t*walk_subtrees = 0;\n+      return NULL_TREE;\n+\n     case RECORD_TYPE:\n       if (TYPE_PTRMEMFUNC_P (t))\n \treturn NULL_TREE;\n@@ -3662,6 +3682,15 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)\n       *walk_subtrees = 0;\n       return NULL_TREE;\n \n+    case LAMBDA_EXPR:\n+      {\n+\ttree fn = lambda_function (t);\n+\tcp_walk_tree (&DECL_SAVED_TREE (fn), &find_parameter_packs_r, ppd,\n+\t\t      ppd->visited);\n+\t*walk_subtrees = 0;\n+\treturn NULL_TREE;\n+      }\n+\n     case DECLTYPE_TYPE:\n       {\n \t/* When traversing a DECLTYPE_TYPE_EXPR, we need to set\n@@ -3849,6 +3878,10 @@ check_for_bare_parameter_packs (tree t)\n   if (!processing_template_decl || !t || t == error_mark_node)\n     return false;\n \n+  /* A lambda might use a parameter pack from the containing context.  */\n+  if (current_function_decl && LAMBDA_FUNCTION_P (current_function_decl))\n+    return false;\n+\n   if (TREE_CODE (t) == TYPE_DECL)\n     t = TREE_TYPE (t);\n \n@@ -12056,6 +12089,8 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,\n       cp_function_chain->x_current_class_ref = NULL_TREE;\n     }\n \n+  start_lambda_scope (parm);\n+\n   push_deferring_access_checks(dk_no_deferred);\n   /* The default argument expression may cause implicitly defined\n      member functions to be synthesized, which will result in garbage\n@@ -12069,6 +12104,8 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,\n   --function_depth;\n   pop_deferring_access_checks();\n \n+  finish_lambda_scope ();\n+\n   /* Restore the \"this\" pointer.  */\n   if (cfun)\n     {\n@@ -12125,6 +12162,441 @@ tsubst_default_arguments (tree fn, tsubst_flags_t complain)\n \t\t\t\t\t\t    complain);\n }\n \n+/* Subroutine of tsubst_decl for the case when T is a FUNCTION_DECL.  */\n+\n+static tree\n+tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,\n+\t\t      tree lambda_fntype)\n+{\n+  tree gen_tmpl, argvec;\n+  hashval_t hash = 0;\n+  tree in_decl = t;\n+\n+  /* Nobody should be tsubst'ing into non-template functions.  */\n+  gcc_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE);\n+\n+  if (TREE_CODE (DECL_TI_TEMPLATE (t)) == TEMPLATE_DECL)\n+    {\n+      /* If T is not dependent, just return it.  */\n+      if (!uses_template_parms (DECL_TI_ARGS (t)))\n+\treturn t;\n+\n+      /* Calculate the most general template of which R is a\n+\t specialization, and the complete set of arguments used to\n+\t specialize R.  */\n+      gen_tmpl = most_general_template (DECL_TI_TEMPLATE (t));\n+      argvec = tsubst_template_args (DECL_TI_ARGS\n+\t\t\t\t     (DECL_TEMPLATE_RESULT\n+\t\t\t\t      (DECL_TI_TEMPLATE (t))),\n+\t\t\t\t     args, complain, in_decl);\n+      if (argvec == error_mark_node)\n+\treturn error_mark_node;\n+\n+      /* Check to see if we already have this specialization.  */\n+      if (!lambda_fntype)\n+\t{\n+\t  hash = hash_tmpl_and_args (gen_tmpl, argvec);\n+\t  if (tree spec = retrieve_specialization (gen_tmpl, argvec, hash))\n+\t    return spec;\n+\t}\n+\n+      /* We can see more levels of arguments than parameters if\n+\t there was a specialization of a member template, like\n+\t this:\n+\n+\t template <class T> struct S { template <class U> void f(); }\n+\t template <> template <class U> void S<int>::f(U);\n+\n+\t Here, we'll be substituting into the specialization,\n+\t because that's where we can find the code we actually\n+\t want to generate, but we'll have enough arguments for\n+\t the most general template.\n+\n+\t We also deal with the peculiar case:\n+\n+\t template <class T> struct S {\n+\t template <class U> friend void f();\n+\t };\n+\t template <class U> void f() {}\n+\t template S<int>;\n+\t template void f<double>();\n+\n+\t Here, the ARGS for the instantiation of will be {int,\n+\t double}.  But, we only need as many ARGS as there are\n+\t levels of template parameters in CODE_PATTERN.  We are\n+\t careful not to get fooled into reducing the ARGS in\n+\t situations like:\n+\n+\t template <class T> struct S { template <class U> void f(U); }\n+\t template <class T> template <> void S<T>::f(int) {}\n+\n+\t which we can spot because the pattern will be a\n+\t specialization in this case.  */\n+      int args_depth = TMPL_ARGS_DEPTH (args);\n+      int parms_depth =\n+\tTMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (t)));\n+\n+      if (args_depth > parms_depth && !DECL_TEMPLATE_SPECIALIZATION (t))\n+\targs = get_innermost_template_args (args, parms_depth);\n+    }\n+  else\n+    {\n+      /* This special case arises when we have something like this:\n+\n+\t template <class T> struct S {\n+\t friend void f<int>(int, double);\n+\t };\n+\n+\t Here, the DECL_TI_TEMPLATE for the friend declaration\n+\t will be an IDENTIFIER_NODE.  We are being called from\n+\t tsubst_friend_function, and we want only to create a\n+\t new decl (R) with appropriate types so that we can call\n+\t determine_specialization.  */\n+      gen_tmpl = NULL_TREE;\n+      argvec = NULL_TREE;\n+    }\n+\n+  tree closure = (lambda_fntype ? TYPE_METHOD_BASETYPE (lambda_fntype)\n+\t\t  : NULL_TREE);\n+  tree ctx = closure ? closure : DECL_CONTEXT (t);\n+  bool member = ctx && TYPE_P (ctx);\n+\n+  if (member && !closure)\n+    ctx = tsubst_aggr_type (ctx, args,\n+\t\t\t    complain, t, /*entering_scope=*/1);\n+\n+  tree type = (lambda_fntype ? lambda_fntype\n+\t       : tsubst (TREE_TYPE (t), args,\n+\t\t\t complain | tf_fndecl_type, in_decl));\n+  if (type == error_mark_node)\n+    return error_mark_node;\n+\n+  /* If we hit excessive deduction depth, the type is bogus even if\n+     it isn't error_mark_node, so don't build a decl.  */\n+  if (excessive_deduction_depth)\n+    return error_mark_node;\n+\n+  /* We do NOT check for matching decls pushed separately at this\n+     point, as they may not represent instantiations of this\n+     template, and in any case are considered separate under the\n+     discrete model.  */\n+  tree r = copy_decl (t);\n+  DECL_USE_TEMPLATE (r) = 0;\n+  TREE_TYPE (r) = type;\n+  /* Clear out the mangled name and RTL for the instantiation.  */\n+  SET_DECL_ASSEMBLER_NAME (r, NULL_TREE);\n+  SET_DECL_RTL (r, NULL);\n+  /* Leave DECL_INITIAL set on deleted instantiations.  */\n+  if (!DECL_DELETED_FN (r))\n+    DECL_INITIAL (r) = NULL_TREE;\n+  DECL_CONTEXT (r) = ctx;\n+\n+  /* OpenMP UDRs have the only argument a reference to the declared\n+     type.  We want to diagnose if the declared type is a reference,\n+     which is invalid, but as references to references are usually\n+     quietly merged, diagnose it here.  */\n+  if (DECL_OMP_DECLARE_REDUCTION_P (t))\n+    {\n+      tree argtype\n+\t= TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (t))));\n+      argtype = tsubst (argtype, args, complain, in_decl);\n+      if (TREE_CODE (argtype) == REFERENCE_TYPE)\n+\terror_at (DECL_SOURCE_LOCATION (t),\n+\t\t  \"reference type %qT in \"\n+\t\t  \"%<#pragma omp declare reduction%>\", argtype);\n+      if (strchr (IDENTIFIER_POINTER (DECL_NAME (t)), '~') == NULL)\n+\tDECL_NAME (r) = omp_reduction_id (ERROR_MARK, DECL_NAME (t),\n+\t\t\t\t\t  argtype);\n+    }\n+\n+  if (member && DECL_CONV_FN_P (r))\n+    /* Type-conversion operator.  Reconstruct the name, in\n+       case it's the name of one of the template's parameters.  */\n+    DECL_NAME (r) = make_conv_op_name (TREE_TYPE (type));\n+\n+  tree parms = DECL_ARGUMENTS (t);\n+  if (closure)\n+    parms = DECL_CHAIN (parms);\n+  parms = tsubst (parms, args, complain, t);\n+  for (tree parm = parms; parm; parm = DECL_CHAIN (parm))\n+    DECL_CONTEXT (parm) = r;\n+  if (closure)\n+    {\n+      tree tparm = build_this_parm (r, closure, type_memfn_quals (type));\n+      DECL_CHAIN (tparm) = parms;\n+      parms = tparm;\n+    }\n+  DECL_ARGUMENTS (r) = parms;\n+  DECL_RESULT (r) = NULL_TREE;\n+\n+  TREE_STATIC (r) = 0;\n+  TREE_PUBLIC (r) = TREE_PUBLIC (t);\n+  DECL_EXTERNAL (r) = 1;\n+  /* If this is an instantiation of a function with internal\n+     linkage, we already know what object file linkage will be\n+     assigned to the instantiation.  */\n+  DECL_INTERFACE_KNOWN (r) = !TREE_PUBLIC (r);\n+  DECL_DEFER_OUTPUT (r) = 0;\n+  DECL_CHAIN (r) = NULL_TREE;\n+  DECL_PENDING_INLINE_INFO (r) = 0;\n+  DECL_PENDING_INLINE_P (r) = 0;\n+  DECL_SAVED_TREE (r) = NULL_TREE;\n+  DECL_STRUCT_FUNCTION (r) = NULL;\n+  TREE_USED (r) = 0;\n+  /* We'll re-clone as appropriate in instantiate_template.  */\n+  DECL_CLONED_FUNCTION (r) = NULL_TREE;\n+\n+  /* If we aren't complaining now, return on error before we register\n+     the specialization so that we'll complain eventually.  */\n+  if ((complain & tf_error) == 0\n+      && IDENTIFIER_ANY_OP_P (DECL_NAME (r))\n+      && !grok_op_properties (r, /*complain=*/false))\n+    return error_mark_node;\n+\n+  /* When instantiating a constrained member, substitute\n+     into the constraints to create a new constraint.  */\n+  if (tree ci = get_constraints (t))\n+    if (member)\n+      {\n+\tci = tsubst_constraint_info (ci, argvec, complain, NULL_TREE);\n+\tset_constraints (r, ci);\n+      }\n+\n+  /* Set up the DECL_TEMPLATE_INFO for R.  There's no need to do\n+     this in the special friend case mentioned above where\n+     GEN_TMPL is NULL.  */\n+  if (gen_tmpl && !closure)\n+    {\n+      DECL_TEMPLATE_INFO (r)\n+\t= build_template_info (gen_tmpl, argvec);\n+      SET_DECL_IMPLICIT_INSTANTIATION (r);\n+\n+      tree new_r\n+\t= register_specialization (r, gen_tmpl, argvec, false, hash);\n+      if (new_r != r)\n+\t/* We instantiated this while substituting into\n+\t   the type earlier (template/friend54.C).  */\n+\treturn new_r;\n+\n+      /* We're not supposed to instantiate default arguments\n+\t until they are called, for a template.  But, for a\n+\t declaration like:\n+\n+\t template <class T> void f ()\n+\t { extern void g(int i = T()); }\n+\n+\t we should do the substitution when the template is\n+\t instantiated.  We handle the member function case in\n+\t instantiate_class_template since the default arguments\n+\t might refer to other members of the class.  */\n+      if (!member\n+\t  && !PRIMARY_TEMPLATE_P (gen_tmpl)\n+\t  && !uses_template_parms (argvec))\n+\ttsubst_default_arguments (r, complain);\n+    }\n+  else\n+    DECL_TEMPLATE_INFO (r) = NULL_TREE;\n+\n+  /* Copy the list of befriending classes.  */\n+  for (tree *friends = &DECL_BEFRIENDING_CLASSES (r);\n+       *friends;\n+       friends = &TREE_CHAIN (*friends))\n+    {\n+      *friends = copy_node (*friends);\n+      TREE_VALUE (*friends)\n+\t= tsubst (TREE_VALUE (*friends), args, complain, in_decl);\n+    }\n+\n+  if (DECL_CONSTRUCTOR_P (r) || DECL_DESTRUCTOR_P (r))\n+    {\n+      maybe_retrofit_in_chrg (r);\n+      if (DECL_CONSTRUCTOR_P (r) && !grok_ctor_properties (ctx, r))\n+\treturn error_mark_node;\n+      /* If this is an instantiation of a member template, clone it.\n+\t If it isn't, that'll be handled by\n+\t clone_constructors_and_destructors.  */\n+      if (PRIMARY_TEMPLATE_P (gen_tmpl))\n+\tclone_function_decl (r, /*update_methods=*/false);\n+    }\n+  else if ((complain & tf_error) != 0\n+\t   && IDENTIFIER_ANY_OP_P (DECL_NAME (r))\n+\t   && !grok_op_properties (r, /*complain=*/true))\n+    return error_mark_node;\n+\n+  if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))\n+    SET_DECL_FRIEND_CONTEXT (r,\n+\t\t\t     tsubst (DECL_FRIEND_CONTEXT (t),\n+\t\t\t\t     args, complain, in_decl));\n+\n+  /* Possibly limit visibility based on template args.  */\n+  DECL_VISIBILITY (r) = VISIBILITY_DEFAULT;\n+  if (DECL_VISIBILITY_SPECIFIED (t))\n+    {\n+      DECL_VISIBILITY_SPECIFIED (r) = 0;\n+      DECL_ATTRIBUTES (r)\n+\t= remove_attribute (\"visibility\", DECL_ATTRIBUTES (r));\n+    }\n+  determine_visibility (r);\n+  if (DECL_DEFAULTED_OUTSIDE_CLASS_P (r)\n+      && !processing_template_decl)\n+    defaulted_late_check (r);\n+\n+  apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,\n+\t\t\t\t  args, complain, in_decl);\n+  return r;\n+}\n+\n+/* Subroutine of tsubst_decl for the case when T is a TEMPLATE_DECL.  */\n+\n+static tree\n+tsubst_template_decl (tree t, tree args, tsubst_flags_t complain,\n+\t\t      tree lambda_fntype)\n+{\n+  /* We can get here when processing a member function template,\n+     member class template, or template template parameter.  */\n+  tree decl = DECL_TEMPLATE_RESULT (t);\n+  tree in_decl = t;\n+  tree spec;\n+  tree tmpl_args;\n+  tree full_args;\n+  tree r;\n+  hashval_t hash = 0;\n+\n+  if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))\n+    {\n+      /* Template template parameter is treated here.  */\n+      tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);\n+      if (new_type == error_mark_node)\n+\tr = error_mark_node;\n+      /* If we get a real template back, return it.  This can happen in\n+\t the context of most_specialized_partial_spec.  */\n+      else if (TREE_CODE (new_type) == TEMPLATE_DECL)\n+\tr = new_type;\n+      else\n+\t/* The new TEMPLATE_DECL was built in\n+\t   reduce_template_parm_level.  */\n+\tr = TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (new_type);\n+      return r;\n+    }\n+\n+  if (!lambda_fntype)\n+    {\n+      /* We might already have an instance of this template.\n+\t The ARGS are for the surrounding class type, so the\n+\t full args contain the tsubst'd args for the context,\n+\t plus the innermost args from the template decl.  */\n+      tmpl_args = DECL_CLASS_TEMPLATE_P (t)\n+\t? CLASSTYPE_TI_ARGS (TREE_TYPE (t))\n+\t: DECL_TI_ARGS (DECL_TEMPLATE_RESULT (t));\n+      /* Because this is a template, the arguments will still be\n+\t dependent, even after substitution.  If\n+\t PROCESSING_TEMPLATE_DECL is not set, the dependency\n+\t predicates will short-circuit.  */\n+      ++processing_template_decl;\n+      full_args = tsubst_template_args (tmpl_args, args,\n+\t\t\t\t\tcomplain, in_decl);\n+      --processing_template_decl;\n+      if (full_args == error_mark_node)\n+\treturn error_mark_node;\n+\n+      /* If this is a default template template argument,\n+\t tsubst might not have changed anything.  */\n+      if (full_args == tmpl_args)\n+\treturn t;\n+\n+      hash = hash_tmpl_and_args (t, full_args);\n+      spec = retrieve_specialization (t, full_args, hash);\n+      if (spec != NULL_TREE)\n+\treturn spec;\n+    }\n+\n+  /* Make a new template decl.  It will be similar to the\n+     original, but will record the current template arguments.\n+     We also create a new function declaration, which is just\n+     like the old one, but points to this new template, rather\n+     than the old one.  */\n+  r = copy_decl (t);\n+  gcc_assert (DECL_LANG_SPECIFIC (r) != 0);\n+  DECL_CHAIN (r) = NULL_TREE;\n+\n+  // Build new template info linking to the original template decl.\n+  if (!lambda_fntype)\n+    {\n+      DECL_TEMPLATE_INFO (r) = build_template_info (t, args);\n+      SET_DECL_IMPLICIT_INSTANTIATION (r);\n+    }\n+  else\n+    DECL_TEMPLATE_INFO (r) = NULL_TREE;\n+\n+  /* The template parameters for this new template are all the\n+     template parameters for the old template, except the\n+     outermost level of parameters.  */\n+  DECL_TEMPLATE_PARMS (r)\n+    = tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args,\n+\t\t\t     complain);\n+\n+  if (TREE_CODE (decl) == TYPE_DECL\n+      && !TYPE_DECL_ALIAS_P (decl))\n+    {\n+      tree new_type;\n+      ++processing_template_decl;\n+      new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);\n+      --processing_template_decl;\n+      if (new_type == error_mark_node)\n+\treturn error_mark_node;\n+\n+      TREE_TYPE (r) = new_type;\n+      /* For a partial specialization, we need to keep pointing to\n+\t the primary template.  */\n+      if (!DECL_TEMPLATE_SPECIALIZATION (t))\n+\tCLASSTYPE_TI_TEMPLATE (new_type) = r;\n+      DECL_TEMPLATE_RESULT (r) = TYPE_MAIN_DECL (new_type);\n+      DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type);\n+      DECL_CONTEXT (r) = TYPE_CONTEXT (new_type);\n+    }\n+  else\n+    {\n+      tree new_decl;\n+      ++processing_template_decl;\n+      if (TREE_CODE (decl) == FUNCTION_DECL)\n+\tnew_decl = tsubst_function_decl (decl, args, complain, lambda_fntype);\n+      else\n+\tnew_decl = tsubst (decl, args, complain, in_decl);\n+      --processing_template_decl;\n+      if (new_decl == error_mark_node)\n+\treturn error_mark_node;\n+\n+      DECL_TEMPLATE_RESULT (r) = new_decl;\n+      TREE_TYPE (r) = TREE_TYPE (new_decl);\n+      DECL_CONTEXT (r) = DECL_CONTEXT (new_decl);\n+      if (lambda_fntype)\n+\t{\n+\t  tree args = template_parms_to_args (DECL_TEMPLATE_PARMS (r));\n+\t  DECL_TEMPLATE_INFO (new_decl) = build_template_info (r, args);\n+\t}\n+      else\n+\t{\n+\t  DECL_TI_TEMPLATE (new_decl) = r;\n+\t  DECL_TI_ARGS (r) = DECL_TI_ARGS (new_decl);\n+\t}\n+    }\n+\n+  DECL_TEMPLATE_INSTANTIATIONS (r) = NULL_TREE;\n+  DECL_TEMPLATE_SPECIALIZATIONS (r) = NULL_TREE;\n+\n+  if (PRIMARY_TEMPLATE_P (t))\n+    DECL_PRIMARY_TEMPLATE (r) = r;\n+\n+  if (TREE_CODE (decl) != TYPE_DECL && !VAR_P (decl)\n+      && !lambda_fntype)\n+    /* Record this non-type partial instantiation.  */\n+    register_specialization (r, t,\n+\t\t\t     DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)),\n+\t\t\t     false, hash);\n+\n+  return r;\n+}\n+\n /* Substitute the ARGS into the T, which is a _DECL.  Return the\n    result of the substitution.  Issue error and warning messages under\n    control of COMPLAIN.  */\n@@ -12145,395 +12617,11 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)\n   switch (TREE_CODE (t))\n     {\n     case TEMPLATE_DECL:\n-      {\n-\t/* We can get here when processing a member function template,\n-\t   member class template, or template template parameter.  */\n-\ttree decl = DECL_TEMPLATE_RESULT (t);\n-\ttree spec;\n-\ttree tmpl_args;\n-\ttree full_args;\n-\n-\tif (DECL_TEMPLATE_TEMPLATE_PARM_P (t))\n-\t  {\n-\t    /* Template template parameter is treated here.  */\n-\t    tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);\n-\t    if (new_type == error_mark_node)\n-\t      r = error_mark_node;\n-\t    /* If we get a real template back, return it.  This can happen in\n-\t       the context of most_specialized_partial_spec.  */\n-\t    else if (TREE_CODE (new_type) == TEMPLATE_DECL)\n-\t      r = new_type;\n-\t    else\n-\t      /* The new TEMPLATE_DECL was built in\n-\t\t reduce_template_parm_level.  */\n-\t      r = TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (new_type);\n-\t    break;\n-\t  }\n-\n-\t/* We might already have an instance of this template.\n-\t   The ARGS are for the surrounding class type, so the\n-\t   full args contain the tsubst'd args for the context,\n-\t   plus the innermost args from the template decl.  */\n-\ttmpl_args = DECL_CLASS_TEMPLATE_P (t)\n-\t  ? CLASSTYPE_TI_ARGS (TREE_TYPE (t))\n-\t  : DECL_TI_ARGS (DECL_TEMPLATE_RESULT (t));\n-\t/* Because this is a template, the arguments will still be\n-\t   dependent, even after substitution.  If\n-\t   PROCESSING_TEMPLATE_DECL is not set, the dependency\n-\t   predicates will short-circuit.  */\n-\t++processing_template_decl;\n-\tfull_args = tsubst_template_args (tmpl_args, args,\n-\t\t\t\t\t  complain, in_decl);\n-\t--processing_template_decl;\n-\tif (full_args == error_mark_node)\n-\t  RETURN (error_mark_node);\n-\n-\t/* If this is a default template template argument,\n-\t   tsubst might not have changed anything.  */\n-\tif (full_args == tmpl_args)\n-\t  RETURN (t);\n-\n-\thash = hash_tmpl_and_args (t, full_args);\n-\tspec = retrieve_specialization (t, full_args, hash);\n-\tif (spec != NULL_TREE)\n-\t  {\n-\t    r = spec;\n-\t    break;\n-\t  }\n-\n-\t/* Make a new template decl.  It will be similar to the\n-\t   original, but will record the current template arguments.\n-\t   We also create a new function declaration, which is just\n-\t   like the old one, but points to this new template, rather\n-\t   than the old one.  */\n-\tr = copy_decl (t);\n-\tgcc_assert (DECL_LANG_SPECIFIC (r) != 0);\n-\tDECL_CHAIN (r) = NULL_TREE;\n-\n-        // Build new template info linking to the original template decl.\n-\tDECL_TEMPLATE_INFO (r) = build_template_info (t, args);\n-\n-\tif (TREE_CODE (decl) == TYPE_DECL\n-\t    && !TYPE_DECL_ALIAS_P (decl))\n-\t  {\n-\t    tree new_type;\n-\t    ++processing_template_decl;\n-\t    new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);\n-\t    --processing_template_decl;\n-\t    if (new_type == error_mark_node)\n-\t      RETURN (error_mark_node);\n-\n-\t    TREE_TYPE (r) = new_type;\n-\t    /* For a partial specialization, we need to keep pointing to\n-\t       the primary template.  */\n-\t    if (!DECL_TEMPLATE_SPECIALIZATION (t))\n-\t      CLASSTYPE_TI_TEMPLATE (new_type) = r;\n-\t    DECL_TEMPLATE_RESULT (r) = TYPE_MAIN_DECL (new_type);\n-\t    DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type);\n-\t    DECL_CONTEXT (r) = TYPE_CONTEXT (new_type);\n-\t  }\n-\telse\n-\t  {\n-\t    tree new_decl;\n-\t    ++processing_template_decl;\n-\t    new_decl = tsubst (decl, args, complain, in_decl);\n-\t    --processing_template_decl;\n-\t    if (new_decl == error_mark_node)\n-\t      RETURN (error_mark_node);\n-\n-\t    DECL_TEMPLATE_RESULT (r) = new_decl;\n-\t    DECL_TI_TEMPLATE (new_decl) = r;\n-\t    TREE_TYPE (r) = TREE_TYPE (new_decl);\n-\t    DECL_TI_ARGS (r) = DECL_TI_ARGS (new_decl);\n-\t    DECL_CONTEXT (r) = DECL_CONTEXT (new_decl);\n-\t  }\n-\n-\tSET_DECL_IMPLICIT_INSTANTIATION (r);\n-\tDECL_TEMPLATE_INSTANTIATIONS (r) = NULL_TREE;\n-\tDECL_TEMPLATE_SPECIALIZATIONS (r) = NULL_TREE;\n-\n-\t/* The template parameters for this new template are all the\n-\t   template parameters for the old template, except the\n-\t   outermost level of parameters.  */\n-\tDECL_TEMPLATE_PARMS (r)\n-\t  = tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args,\n-\t\t\t\t   complain);\n-\n-\tif (PRIMARY_TEMPLATE_P (t))\n-\t  DECL_PRIMARY_TEMPLATE (r) = r;\n-\n-\tif (TREE_CODE (decl) != TYPE_DECL && !VAR_P (decl))\n-\t  /* Record this non-type partial instantiation.  */\n-\t  register_specialization (r, t,\n-\t\t\t\t   DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)),\n-\t\t\t\t   false, hash);\n-      }\n+      r = tsubst_template_decl (t, args, complain, /*lambda*/NULL_TREE);\n       break;\n \n     case FUNCTION_DECL:\n-      {\n-\ttree gen_tmpl, argvec;\n-\n-\t/* Nobody should be tsubst'ing into non-template functions.  */\n-\tgcc_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE);\n-\n-\tif (TREE_CODE (DECL_TI_TEMPLATE (t)) == TEMPLATE_DECL)\n-\t  {\n-\t    /* If T is not dependent, just return it.  */\n-\t    if (!uses_template_parms (DECL_TI_ARGS (t)))\n-\t      RETURN (t);\n-\n-\t    /* Calculate the most general template of which R is a\n-\t       specialization, and the complete set of arguments used to\n-\t       specialize R.  */\n-\t    gen_tmpl = most_general_template (DECL_TI_TEMPLATE (t));\n-\t    argvec = tsubst_template_args (DECL_TI_ARGS\n-                                          (DECL_TEMPLATE_RESULT\n-                                                 (DECL_TI_TEMPLATE (t))),\n-\t\t\t\t\t   args, complain, in_decl);\n-\t    if (argvec == error_mark_node)\n-\t      RETURN (error_mark_node);\n-\n-\t    /* Check to see if we already have this specialization.  */\n-\t    hash = hash_tmpl_and_args (gen_tmpl, argvec);\n-\t    if (tree spec = retrieve_specialization (gen_tmpl, argvec, hash))\n-\t      {\n-\t\tr = spec;\n-\t\tbreak;\n-\t      }\n-\n-\t    /* We can see more levels of arguments than parameters if\n-\t       there was a specialization of a member template, like\n-\t       this:\n-\n-\t\t template <class T> struct S { template <class U> void f(); }\n-\t\t template <> template <class U> void S<int>::f(U);\n-\n-\t       Here, we'll be substituting into the specialization,\n-\t       because that's where we can find the code we actually\n-\t       want to generate, but we'll have enough arguments for\n-\t       the most general template.\n-\n-\t       We also deal with the peculiar case:\n-\n-\t\t template <class T> struct S {\n-\t\t   template <class U> friend void f();\n-\t\t };\n-\t\t template <class U> void f() {}\n-\t\t template S<int>;\n-\t\t template void f<double>();\n-\n-\t       Here, the ARGS for the instantiation of will be {int,\n-\t       double}.  But, we only need as many ARGS as there are\n-\t       levels of template parameters in CODE_PATTERN.  We are\n-\t       careful not to get fooled into reducing the ARGS in\n-\t       situations like:\n-\n-\t\t template <class T> struct S { template <class U> void f(U); }\n-\t\t template <class T> template <> void S<T>::f(int) {}\n-\n-\t       which we can spot because the pattern will be a\n-\t       specialization in this case.  */\n-\t    int args_depth = TMPL_ARGS_DEPTH (args);\n-\t    int parms_depth =\n-\t      TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (t)));\n-\n-\t    if (args_depth > parms_depth && !DECL_TEMPLATE_SPECIALIZATION (t))\n-\t      args = get_innermost_template_args (args, parms_depth);\n-\t  }\n-\telse\n-\t  {\n-\t    /* This special case arises when we have something like this:\n-\n-\t\t template <class T> struct S {\n-\t\t   friend void f<int>(int, double);\n-\t\t };\n-\n-\t       Here, the DECL_TI_TEMPLATE for the friend declaration\n-\t       will be an IDENTIFIER_NODE.  We are being called from\n-\t       tsubst_friend_function, and we want only to create a\n-\t       new decl (R) with appropriate types so that we can call\n-\t       determine_specialization.  */\n-\t    gen_tmpl = NULL_TREE;\n-\t    argvec = NULL_TREE;\n-\t  }\n-\n-\ttree ctx = DECL_CONTEXT (t);\n-\tbool member = ctx && TYPE_P (ctx);\n-\n-\tif (member)\n-\t  ctx = tsubst_aggr_type (ctx, args,\n-\t\t\t\t  complain, t, /*entering_scope=*/1);\n-\n-\ttree type = tsubst (TREE_TYPE (t), args,\n-\t\t\t    complain | tf_fndecl_type, in_decl);\n-\tif (type == error_mark_node)\n-\t  RETURN (error_mark_node);\n-\n-\t/* If we hit excessive deduction depth, the type is bogus even if\n-\t   it isn't error_mark_node, so don't build a decl.  */\n-\tif (excessive_deduction_depth)\n-\t  RETURN (error_mark_node);\n-\n-\t/* We do NOT check for matching decls pushed separately at this\n-\t   point, as they may not represent instantiations of this\n-\t   template, and in any case are considered separate under the\n-\t   discrete model.  */\n-\tr = copy_decl (t);\n-\tDECL_USE_TEMPLATE (r) = 0;\n-\tTREE_TYPE (r) = type;\n-\t/* Clear out the mangled name and RTL for the instantiation.  */\n-\tSET_DECL_ASSEMBLER_NAME (r, NULL_TREE);\n-\tSET_DECL_RTL (r, NULL);\n-\t/* Leave DECL_INITIAL set on deleted instantiations.  */\n-\tif (!DECL_DELETED_FN (r))\n-\t  DECL_INITIAL (r) = NULL_TREE;\n-\tDECL_CONTEXT (r) = ctx;\n-\n-\t/* OpenMP UDRs have the only argument a reference to the declared\n-\t   type.  We want to diagnose if the declared type is a reference,\n-\t   which is invalid, but as references to references are usually\n-\t   quietly merged, diagnose it here.  */\n-\tif (DECL_OMP_DECLARE_REDUCTION_P (t))\n-\t  {\n-\t    tree argtype\n-\t      = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (t))));\n-\t    argtype = tsubst (argtype, args, complain, in_decl);\n-\t    if (TREE_CODE (argtype) == REFERENCE_TYPE)\n-\t      error_at (DECL_SOURCE_LOCATION (t),\n-\t\t\t\"reference type %qT in \"\n-\t\t\t\"%<#pragma omp declare reduction%>\", argtype);\n-\t    if (strchr (IDENTIFIER_POINTER (DECL_NAME (t)), '~') == NULL)\n-\t      DECL_NAME (r) = omp_reduction_id (ERROR_MARK, DECL_NAME (t),\n-\t\t\t\t\t\targtype);\n-\t  }\n-\n-\tif (member && DECL_CONV_FN_P (r))\n-\t  /* Type-conversion operator.  Reconstruct the name, in\n-\t     case it's the name of one of the template's parameters.  */\n-\t  DECL_NAME (r) = make_conv_op_name (TREE_TYPE (type));\n-\n-\tDECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args,\n-\t\t\t\t     complain, t);\n-\tfor (tree parm = DECL_ARGUMENTS (r); parm; parm = DECL_CHAIN (parm))\n-\t  DECL_CONTEXT (parm) = r;\n-\tDECL_RESULT (r) = NULL_TREE;\n-\n-\tTREE_STATIC (r) = 0;\n-\tTREE_PUBLIC (r) = TREE_PUBLIC (t);\n-\tDECL_EXTERNAL (r) = 1;\n-\t/* If this is an instantiation of a function with internal\n-\t   linkage, we already know what object file linkage will be\n-\t   assigned to the instantiation.  */\n-\tDECL_INTERFACE_KNOWN (r) = !TREE_PUBLIC (r);\n-\tDECL_DEFER_OUTPUT (r) = 0;\n-\tDECL_CHAIN (r) = NULL_TREE;\n-\tDECL_PENDING_INLINE_INFO (r) = 0;\n-\tDECL_PENDING_INLINE_P (r) = 0;\n-\tDECL_SAVED_TREE (r) = NULL_TREE;\n-\tDECL_STRUCT_FUNCTION (r) = NULL;\n-\tTREE_USED (r) = 0;\n-\t/* We'll re-clone as appropriate in instantiate_template.  */\n-\tDECL_CLONED_FUNCTION (r) = NULL_TREE;\n-\n-\t/* If we aren't complaining now, return on error before we register\n-\t   the specialization so that we'll complain eventually.  */\n-\tif ((complain & tf_error) == 0\n-\t    && IDENTIFIER_ANY_OP_P (DECL_NAME (r))\n-\t    && !grok_op_properties (r, /*complain=*/false))\n-\t  RETURN (error_mark_node);\n-\n-        /* When instantiating a constrained member, substitute\n-           into the constraints to create a new constraint.  */\n-        if (tree ci = get_constraints (t))\n-          if (member)\n-            {\n-              ci = tsubst_constraint_info (ci, argvec, complain, NULL_TREE);\n-              set_constraints (r, ci);\n-            }\n-\n-\t/* Set up the DECL_TEMPLATE_INFO for R.  There's no need to do\n-\t   this in the special friend case mentioned above where\n-\t   GEN_TMPL is NULL.  */\n-\tif (gen_tmpl)\n-\t  {\n-\t    DECL_TEMPLATE_INFO (r)\n-\t      = build_template_info (gen_tmpl, argvec);\n-\t    SET_DECL_IMPLICIT_INSTANTIATION (r);\n-\n-\t    tree new_r\n-\t      = register_specialization (r, gen_tmpl, argvec, false, hash);\n-\t    if (new_r != r)\n-\t      /* We instantiated this while substituting into\n-\t\t the type earlier (template/friend54.C).  */\n-\t      RETURN (new_r);\n-\n-\t    /* We're not supposed to instantiate default arguments\n-\t       until they are called, for a template.  But, for a\n-\t       declaration like:\n-\n-\t\t template <class T> void f ()\n-\t\t { extern void g(int i = T()); }\n-\n-\t       we should do the substitution when the template is\n-\t       instantiated.  We handle the member function case in\n-\t       instantiate_class_template since the default arguments\n-\t       might refer to other members of the class.  */\n-\t    if (!member\n-\t\t&& !PRIMARY_TEMPLATE_P (gen_tmpl)\n-\t\t&& !uses_template_parms (argvec))\n-\t      tsubst_default_arguments (r, complain);\n-\t  }\n-\telse\n-\t  DECL_TEMPLATE_INFO (r) = NULL_TREE;\n-\n-\t/* Copy the list of befriending classes.  */\n-\tfor (tree *friends = &DECL_BEFRIENDING_CLASSES (r);\n-\t     *friends;\n-\t     friends = &TREE_CHAIN (*friends))\n-\t  {\n-\t    *friends = copy_node (*friends);\n-\t    TREE_VALUE (*friends)\n-\t      = tsubst (TREE_VALUE (*friends), args, complain, in_decl);\n-\t  }\n-\n-\tif (DECL_CONSTRUCTOR_P (r) || DECL_DESTRUCTOR_P (r))\n-\t  {\n-\t    maybe_retrofit_in_chrg (r);\n-\t    if (DECL_CONSTRUCTOR_P (r) && !grok_ctor_properties (ctx, r))\n-\t      RETURN (error_mark_node);\n-\t    /* If this is an instantiation of a member template, clone it.\n-\t       If it isn't, that'll be handled by\n-\t       clone_constructors_and_destructors.  */\n-\t    if (PRIMARY_TEMPLATE_P (gen_tmpl))\n-\t      clone_function_decl (r, /*update_methods=*/false);\n-\t  }\n-\telse if ((complain & tf_error) != 0\n-\t\t && IDENTIFIER_ANY_OP_P (DECL_NAME (r))\n-\t\t && !grok_op_properties (r, /*complain=*/true))\n-\t  RETURN (error_mark_node);\n-\n-\tif (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))\n-\t  SET_DECL_FRIEND_CONTEXT (r,\n-\t\t\t\t   tsubst (DECL_FRIEND_CONTEXT (t),\n-\t\t\t\t\t    args, complain, in_decl));\n-\n-\t/* Possibly limit visibility based on template args.  */\n-\tDECL_VISIBILITY (r) = VISIBILITY_DEFAULT;\n-\tif (DECL_VISIBILITY_SPECIFIED (t))\n-\t  {\n-\t    DECL_VISIBILITY_SPECIFIED (r) = 0;\n-\t    DECL_ATTRIBUTES (r)\n-\t      = remove_attribute (\"visibility\", DECL_ATTRIBUTES (r));\n-\t  }\n-\tdetermine_visibility (r);\n-\tif (DECL_DEFAULTED_OUTSIDE_CLASS_P (r)\n-\t    && !processing_template_decl)\n-\t  defaulted_late_check (r);\n-\n-\tapply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,\n-\t\t\t\t\targs, complain, in_decl);\n-      }\n+      r = tsubst_function_decl (t, args, complain, /*lambda*/NULL_TREE);\n       break;\n \n     case PARM_DECL:\n@@ -15862,6 +15950,18 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,\n \t       instantiate the elements directly as needed.  */\n \t    break;\n \t  }\n+\telse if (is_capture_proxy (decl)\n+\t\t && !DECL_TEMPLATE_INSTANTIATION (current_function_decl))\n+\t  {\n+\t    /* We're in tsubst_lambda_expr, we've already inserted new capture\n+\t       proxies, and uses will find them with lookup_name.  */\n+\t    break;\n+\t  }\n+\telse if (DECL_IMPLICIT_TYPEDEF_P (decl)\n+\t\t && LAMBDA_TYPE_P (TREE_TYPE (decl)))\n+\t  /* Don't copy the old closure; we'll create a new one in\n+\t     tsubst_lambda_expr.  */\n+\t  break;\n \telse\n \t  {\n \t    init = DECL_INITIAL (decl);\n@@ -16659,6 +16759,149 @@ tsubst_non_call_postfix_expression (tree t, tree args,\n   return t;\n }\n \n+/* T is a LAMBDA_EXPR.  Generate a new LAMBDA_EXPR for the current\n+   instantiation context.  Instantiating a pack expansion containing a lambda\n+   might result in multiple lambdas all based on the same lambda in the\n+   template.  */\n+\n+tree\n+tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n+{\n+  tree oldfn = lambda_function (t);\n+  in_decl = oldfn;\n+\n+  tree r = build_lambda_expr ();\n+\n+  LAMBDA_EXPR_LOCATION (r)\n+    = LAMBDA_EXPR_LOCATION (t);\n+  LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (r)\n+    = LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (t);\n+  LAMBDA_EXPR_MUTABLE_P (r) = LAMBDA_EXPR_MUTABLE_P (t);\n+\n+  if (LAMBDA_EXPR_EXTRA_SCOPE (t) == NULL_TREE)\n+    LAMBDA_EXPR_EXTRA_SCOPE (r) = NULL_TREE;\n+  else\n+    record_lambda_scope (r);\n+\n+  gcc_assert (LAMBDA_EXPR_THIS_CAPTURE (t) == NULL_TREE\n+\t      && LAMBDA_EXPR_PENDING_PROXIES (t) == NULL);\n+\n+  for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (t); cap;\n+       cap = TREE_CHAIN (cap))\n+    {\n+      tree field = TREE_PURPOSE (cap);\n+      if (PACK_EXPANSION_P (field))\n+\tfield = PACK_EXPANSION_PATTERN (field);\n+      field = tsubst_decl (field, args, complain);\n+\n+      if (field == error_mark_node)\n+\treturn error_mark_node;\n+\n+      tree init = TREE_VALUE (cap);\n+      if (PACK_EXPANSION_P (init))\n+\tinit = tsubst_pack_expansion (init, args, complain, in_decl);\n+      else\n+\tinit = tsubst_copy_and_build (init, args, complain, in_decl,\n+\t\t\t\t      /*fn*/false, /*constexpr*/false);\n+\n+      if (TREE_CODE (field) == TREE_VEC)\n+\t{\n+\t  int len = TREE_VEC_LENGTH (field);\n+\t  gcc_assert (TREE_CODE (init) == TREE_VEC\n+\t\t      && TREE_VEC_LENGTH (init) == len);\n+\t  for (int i = 0; i < len; ++i)\n+\t    LAMBDA_EXPR_CAPTURE_LIST (r)\n+\t      = tree_cons (TREE_VEC_ELT (field, i),\n+\t\t\t   TREE_VEC_ELT (init, i),\n+\t\t\t   LAMBDA_EXPR_CAPTURE_LIST (r));\n+\t}\n+      else\n+\t{\n+\t  LAMBDA_EXPR_CAPTURE_LIST (r)\n+\t    = tree_cons (field, init, LAMBDA_EXPR_CAPTURE_LIST (r));\n+\n+\t  if (id_equal (DECL_NAME (field), \"__this\"))\n+\t    LAMBDA_EXPR_THIS_CAPTURE (r) = field;\n+\t}\n+    }\n+\n+  tree type = begin_lambda_type (r);\n+\n+  /* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set.  */\n+  determine_visibility (TYPE_NAME (type));\n+\n+  register_capture_members (LAMBDA_EXPR_CAPTURE_LIST (r));\n+\n+  tree oldtmpl = (generic_lambda_fn_p (oldfn)\n+\t\t  ? DECL_TI_TEMPLATE (oldfn)\n+\t\t  : NULL_TREE);\n+\n+  tree fntype = static_fn_type (oldfn);\n+  if (oldtmpl)\n+    ++processing_template_decl;\n+  fntype = tsubst (fntype, args, complain, in_decl);\n+  if (oldtmpl)\n+    --processing_template_decl;\n+\n+  if (fntype == error_mark_node)\n+    r = error_mark_node;\n+  else\n+    {\n+      /* Fix the type of 'this'.  */\n+      fntype = build_memfn_type (fntype, type,\n+\t\t\t\t type_memfn_quals (fntype),\n+\t\t\t\t type_memfn_rqual (fntype));\n+      tree fn, tmpl;\n+      if (oldtmpl)\n+\t{\n+\t  tmpl = tsubst_template_decl (oldtmpl, args, complain, fntype);\n+\t  fn = DECL_TEMPLATE_RESULT (tmpl);\n+\t  finish_member_declaration (tmpl);\n+\t}\n+      else\n+\t{\n+\t  tmpl = NULL_TREE;\n+\t  fn = tsubst_function_decl (oldfn, args, complain, fntype);\n+\t  finish_member_declaration (fn);\n+\t}\n+\n+      /* Let finish_function set this.  */\n+      DECL_DECLARED_CONSTEXPR_P (fn) = false;\n+\n+      bool nested = cfun;\n+      if (nested)\n+\tpush_function_context ();\n+\n+      tree body = start_lambda_function (fn, r);\n+\n+      local_specialization_stack s (lss_copy);\n+\n+      register_parameter_specializations (oldfn, fn);\n+\n+      tsubst_expr (DECL_SAVED_TREE (oldfn), args, complain, r,\n+\t\t   /*constexpr*/false);\n+\n+      finish_lambda_function (body);\n+\n+      if (nested)\n+\tpop_function_context ();\n+\n+      /* The capture list was built up in reverse order; fix that now.  */\n+      LAMBDA_EXPR_CAPTURE_LIST (r)\n+\t= nreverse (LAMBDA_EXPR_CAPTURE_LIST (r));\n+\n+      LAMBDA_EXPR_THIS_CAPTURE (r) = NULL_TREE;\n+\n+      maybe_add_lambda_conv_op (type);\n+    }\n+\n+  finish_struct (type, /*attr*/NULL_TREE);\n+\n+  insert_pending_capture_proxies ();\n+\n+  return r;\n+}\n+\n /* Like tsubst but deals with expressions and performs semantic\n    analysis.  FUNCTION_P is true if T is the \"F\" in \"F (ARGS)\".  */\n \n@@ -17861,7 +18104,7 @@ tsubst_copy_and_build (tree t,\n \telse if (outer_automatic_var_p (r))\n \t  {\n \t    r = process_outer_var_ref (r, complain);\n-\t    if (is_capture_proxy (r))\n+\t    if (is_capture_proxy (r) && !DECL_PACK_P (t))\n \t      register_local_specialization (r, t);\n \t  }\n \n@@ -17929,59 +18172,7 @@ tsubst_copy_and_build (tree t,\n \n     case LAMBDA_EXPR:\n       {\n-\ttree r = build_lambda_expr ();\n-\n-\ttree type = tsubst (LAMBDA_EXPR_CLOSURE (t), args, complain, NULL_TREE);\n-\tLAMBDA_EXPR_CLOSURE (r) = type;\n-\tCLASSTYPE_LAMBDA_EXPR (type) = r;\n-\n-\tLAMBDA_EXPR_LOCATION (r)\n-\t  = LAMBDA_EXPR_LOCATION (t);\n-\tLAMBDA_EXPR_DEFAULT_CAPTURE_MODE (r)\n-\t  = LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (t);\n-\tLAMBDA_EXPR_MUTABLE_P (r) = LAMBDA_EXPR_MUTABLE_P (t);\n-\tLAMBDA_EXPR_DISCRIMINATOR (r)\n-\t  = (LAMBDA_EXPR_DISCRIMINATOR (t));\n-\ttree scope = LAMBDA_EXPR_EXTRA_SCOPE (t);\n-\tif (!scope)\n-\t  /* No substitution needed.  */;\n-\telse if (VAR_OR_FUNCTION_DECL_P (scope))\n-\t  /* For a function or variable scope, we want to use tsubst so that we\n-\t     don't complain about referring to an auto before deduction.  */\n-\t  scope = tsubst (scope, args, complain, in_decl);\n-\telse if (TREE_CODE (scope) == PARM_DECL)\n-\t  {\n-\t    /* Look up the parameter we want directly, as tsubst_copy\n-\t       doesn't do what we need.  */\n-\t    tree fn = tsubst (DECL_CONTEXT (scope), args, complain, in_decl);\n-\t    tree parm = FUNCTION_FIRST_USER_PARM (fn);\n-\t    while (DECL_PARM_INDEX (parm) != DECL_PARM_INDEX (scope))\n-\t      parm = DECL_CHAIN (parm);\n-\t    scope = parm;\n-\t    /* FIXME Work around the parm not having DECL_CONTEXT set.  */\n-\t    if (DECL_CONTEXT (scope) == NULL_TREE)\n-\t      DECL_CONTEXT (scope) = fn;\n-\t  }\n-\telse if (TREE_CODE (scope) == FIELD_DECL)\n-\t  /* For a field, use tsubst_copy so that we look up the existing field\n-\t     rather than build a new one.  */\n-\t  scope = RECUR (scope);\n-\telse\n-\t  gcc_unreachable ();\n-\tLAMBDA_EXPR_EXTRA_SCOPE (r) = scope;\n-\n-\tgcc_assert (LAMBDA_EXPR_THIS_CAPTURE (t) == NULL_TREE\n-\t\t    && LAMBDA_EXPR_PENDING_PROXIES (t) == NULL);\n-\n-\t/* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set.  */\n-\tdetermine_visibility (TYPE_NAME (type));\n-\t/* Now that we know visibility, instantiate the type so we have a\n-\t   declaration of the op() for later calls to lambda_function.  */\n-\tcomplete_type (type);\n-\n-\tLAMBDA_EXPR_THIS_CAPTURE (r) = NULL_TREE;\n-\n-\tinsert_pending_capture_proxies ();\n+\ttree r = tsubst_lambda_expr (t, args, complain, in_decl);\n \n \tRETURN (build_lambda_object (r));\n       }\n@@ -22434,10 +22625,12 @@ regenerate_decl_from_template (tree decl, tree tmpl, tree args)\n     }\n   else if (VAR_P (decl))\n     {\n+      start_lambda_scope (decl);\n       DECL_INITIAL (decl) =\n \ttsubst_expr (DECL_INITIAL (code_pattern), args,\n \t\t     tf_error, DECL_TI_TEMPLATE (decl),\n \t\t     /*integral_constant_expression_p=*/false);\n+      finish_lambda_scope ();\n       if (VAR_HAD_UNKNOWN_BOUND (decl))\n \tTREE_TYPE (decl) = tsubst (TREE_TYPE (code_pattern), args,\n \t\t\t\t   tf_error, DECL_TI_TEMPLATE (decl));\n@@ -22605,6 +22798,38 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)\n   return true;\n }\n \n+/* We're starting to process the function INST, an instantiation of PATTERN;\n+   add their parameters to local_specializations.  */\n+\n+static void\n+register_parameter_specializations (tree pattern, tree inst)\n+{\n+  tree tmpl_parm = DECL_ARGUMENTS (pattern);\n+  tree spec_parm = DECL_ARGUMENTS (inst);\n+  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (inst))\n+    {\n+      register_local_specialization (spec_parm, tmpl_parm);\n+      spec_parm = skip_artificial_parms_for (inst, spec_parm);\n+      tmpl_parm = skip_artificial_parms_for (pattern, tmpl_parm);\n+    }\n+  for (; tmpl_parm; tmpl_parm = DECL_CHAIN (tmpl_parm))\n+    {\n+      if (!DECL_PACK_P (tmpl_parm))\n+\t{\n+\t  register_local_specialization (spec_parm, tmpl_parm);\n+\t  spec_parm = DECL_CHAIN (spec_parm);\n+\t}\n+      else\n+\t{\n+\t  /* Register the (value) argument pack as a specialization of\n+\t     TMPL_PARM, then move on.  */\n+\t  tree argpack = extract_fnparm_pack (tmpl_parm, &spec_parm);\n+\t  register_local_specialization (argpack, tmpl_parm);\n+\t}\n+    }\n+  gcc_assert (!spec_parm);\n+}\n+\n /* Produce the definition of D, a _DECL generated from a template.  If\n    DEFER_OK is true, then we don't have to actually do the\n    instantiation now; we just have to do it sometime.  Normally it is\n@@ -22939,10 +23164,7 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)\n   else if (TREE_CODE (d) == FUNCTION_DECL)\n     {\n       hash_map<tree, tree> *saved_local_specializations;\n-      tree tmpl_parm;\n-      tree spec_parm;\n       tree block = NULL_TREE;\n-      tree lambda_ctx = NULL_TREE;\n \n       /* Save away the current list, in case we are instantiating one\n \t template from within the body of another.  */\n@@ -22956,23 +23178,7 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)\n \t  && TREE_CODE (DECL_CONTEXT (code_pattern)) == FUNCTION_DECL)\n \tblock = push_stmt_list ();\n       else\n-\t{\n-\t  if (push_to_top && LAMBDA_FUNCTION_P (d))\n-\t    {\n-\t      /* When instantiating a lambda's templated function\n-\t\t operator, we need to push the non-lambda class scope\n-\t\t of the lambda itself so that the nested function\n-\t\t stack is sufficiently correct to deal with this\n-\t\t capture.  */\n-\t      lambda_ctx = DECL_CONTEXT (d);\n-\t      do \n-\t\tlambda_ctx = decl_type_context (TYPE_NAME (lambda_ctx));\n-\t      while (lambda_ctx && LAMBDA_TYPE_P (lambda_ctx));\n-\t      if (lambda_ctx)\n-\t\tpush_nested_class (lambda_ctx);\n-\t    }\n-\t  start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);\n-\t}\n+\tstart_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);\n \n       /* Some typedefs referenced from within the template code need to be\n \t access checked at template instantiation time, i.e now. These\n@@ -22982,30 +23188,7 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)\n \t\t\t\t     args);\n \n       /* Create substitution entries for the parameters.  */\n-      tmpl_parm = DECL_ARGUMENTS (code_pattern);\n-      spec_parm = DECL_ARGUMENTS (d);\n-      if (DECL_NONSTATIC_MEMBER_FUNCTION_P (d))\n-\t{\n-\t  register_local_specialization (spec_parm, tmpl_parm);\n-\t  spec_parm = skip_artificial_parms_for (d, spec_parm);\n-\t  tmpl_parm = skip_artificial_parms_for (code_pattern, tmpl_parm);\n-\t}\n-      for (; tmpl_parm; tmpl_parm = DECL_CHAIN (tmpl_parm))\n-\t{\n-\t  if (!DECL_PACK_P (tmpl_parm))\n-\t    {\n-\t      register_local_specialization (spec_parm, tmpl_parm);\n-\t      spec_parm = DECL_CHAIN (spec_parm);\n-\t    }\n-\t  else\n-\t    {\n-\t      /* Register the (value) argument pack as a specialization of\n-\t\t TMPL_PARM, then move on.  */\n-\t      tree argpack = extract_fnparm_pack (tmpl_parm, &spec_parm);\n-\t      register_local_specialization (argpack, tmpl_parm);\n-\t    }\n-\t}\n-      gcc_assert (!spec_parm);\n+      register_parameter_specializations (code_pattern, d);\n \n       /* Substitute into the body of the function.  */\n       if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern))\n@@ -23040,8 +23223,6 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)\n \t  d = finish_function (0);\n \t  expand_or_defer_fn (d);\n \t}\n-      if (lambda_ctx)\n-\tpop_nested_class ();\n \n       if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern))\n \tcp_check_omp_declare_reduction (d);\ndiff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c\nindex fe118cd..8f28221 100644\n--- a/gcc/cp/semantics.c\n+++ b/gcc/cp/semantics.c\n@@ -3301,40 +3301,56 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain)\n   if (!mark_used (decl, complain))\n     return error_mark_node;\n \n-  bool saw_generic_lambda = false;\n   if (parsing_nsdmi ())\n     containing_function = NULL_TREE;\n-  else\n-    /* If we are in a lambda function, we can move out until we hit\n-       1. the context,\n-       2. a non-lambda function, or\n-       3. a non-default capturing lambda function.  */\n-    while (context != containing_function\n-\t   /* containing_function can be null with invalid generic lambdas.  */\n-\t   && containing_function\n-\t   && LAMBDA_FUNCTION_P (containing_function))\n-      {\n-\ttree closure = DECL_CONTEXT (containing_function);\n-\tlambda_expr = CLASSTYPE_LAMBDA_EXPR (closure);\n \n-\tif (generic_lambda_fn_p (containing_function))\n-\t  saw_generic_lambda = true;\n+  if (containing_function && DECL_TEMPLATE_INFO (context)\n+      && LAMBDA_FUNCTION_P (containing_function))\n+    {\n+      /* Check whether we've already built a proxy;\n+\t insert_pending_capture_proxies doesn't update\n+\t local_specializations.  */\n+      tree d = lookup_name (DECL_NAME (decl));\n+      if (d && is_capture_proxy (d)\n+\t  && DECL_CONTEXT (d) == containing_function)\n+\treturn d;\n+    }\n \n-\tif (TYPE_CLASS_SCOPE_P (closure))\n-\t  /* A lambda in an NSDMI (c++/64496).  */\n-\t  break;\n+  /* If we are in a lambda function, we can move out until we hit\n+     1. the context,\n+     2. a non-lambda function, or\n+     3. a non-default capturing lambda function.  */\n+  while (context != containing_function\n+\t /* containing_function can be null with invalid generic lambdas.  */\n+\t && containing_function\n+\t && LAMBDA_FUNCTION_P (containing_function))\n+    {\n+      tree closure = DECL_CONTEXT (containing_function);\n+      lambda_expr = CLASSTYPE_LAMBDA_EXPR (closure);\n \n-\tif (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr)\n-\t    == CPLD_NONE)\n-\t  break;\n+      if (TYPE_CLASS_SCOPE_P (closure))\n+\t/* A lambda in an NSDMI (c++/64496).  */\n+\tbreak;\n \n-\tlambda_stack = tree_cons (NULL_TREE,\n-\t\t\t\t  lambda_expr,\n-\t\t\t\t  lambda_stack);\n+      if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr)\n+\t  == CPLD_NONE)\n+\tbreak;\n \n-\tcontaining_function\n-\t  = decl_function_context (containing_function);\n-      }\n+      lambda_stack = tree_cons (NULL_TREE,\n+\t\t\t\tlambda_expr,\n+\t\t\t\tlambda_stack);\n+\n+      containing_function\n+\t= decl_function_context (containing_function);\n+    }\n+\n+  /* In a lambda within a template, wait until instantiation\n+     time to implicitly capture.  */\n+  if (context == containing_function\n+      && DECL_TEMPLATE_INFO (containing_function)\n+      && any_dependent_template_arguments_p (DECL_TI_ARGS\n+\t\t\t\t\t     (containing_function)))\n+    return decl;\n \n   /* Core issue 696: \"[At the July 2009 meeting] the CWG expressed\n      support for an approach in which a reference to a local\n@@ -3343,26 +3359,11 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain)\n      the complexity of the problem\"\n \n      FIXME update for final resolution of core issue 696.  */\n-  if (decl_maybe_constant_var_p (decl))\n+  if (decl_constant_var_p (decl))\n     {\n-      if (processing_template_decl && !saw_generic_lambda)\n-\t/* In a non-generic lambda within a template, wait until instantiation\n-\t   time to decide whether to capture.  For a generic lambda, we can't\n-\t   wait until we instantiate the op() because the closure class is\n-\t   already defined at that point.  FIXME to get the semantics exactly\n-\t   right we need to partially-instantiate the lambda body so the only\n-\t   dependencies left are on the generic parameters themselves.  This\n-\t   probably means moving away from our current model of lambdas in\n-\t   templates (instantiating the closure type) to one based on creating\n-\t   the closure type when instantiating the lambda context.  That is\n-\t   probably also the way to handle lambdas within pack expansions.  */\n-\treturn decl;\n-      else if (decl_constant_var_p (decl))\n-\t{\n-\t  tree t = maybe_constant_value (convert_from_reference (decl));\n-\t  if (TREE_CONSTANT (t))\n-\t    return t;\n-\t}\n+      tree t = maybe_constant_value (convert_from_reference (decl));\n+      if (TREE_CONSTANT (t))\n+\treturn t;\n     }\n \n   if (lambda_expr && VAR_P (decl)\ndiff --git a/gcc/testsuite/g++.dg/cpp1z/fold-lambda.C b/gcc/testsuite/g++.dg/cpp1z/fold-lambda.C\nnew file mode 100644\nindex 0000000..5eaed4a\n--- /dev/null\n+++ b/gcc/testsuite/g++.dg/cpp1z/fold-lambda.C\n@@ -0,0 +1,14 @@\n+// { dg-do run }\n+// { dg-options -std=c++17 }\n+\n+template <class... T>\n+auto f() {\n+  int i = 42;\n+  return ([i]{ return T(i); }() + ...);\n+}\n+\n+int main()\n+{\n+  if (f<int,double>() != 84)\n+    __builtin_abort();\n+}\ndiff --git a/gcc/testsuite/g++.dg/warn/Wshadow-6.C b/gcc/testsuite/g++.dg/warn/Wshadow-6.C\nindex 9c2e8b8..1d8d21b 100644\n--- a/gcc/testsuite/g++.dg/warn/Wshadow-6.C\n+++ b/gcc/testsuite/g++.dg/warn/Wshadow-6.C\n@@ -43,7 +43,7 @@ template <class T>\n void f4(int i) {\n  [=]{\n    int j = i;\t\t\t// { dg-message \"shadowed declaration\" }\n-   int i;\t\t\t// { dg-warning \"shadows a lambda capture\" }\n+   int i;\t\t\t// { dg-warning \"shadows a \" }\n    i = 1;\n  };\n }\n",
    "prefixes": []
}