Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/808274/?format=api
{ "id": 808274, "url": "http://patchwork.ozlabs.org/api/patches/808274/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/CADzB+2n+cETRk6CPdNF95bNZrT_3vJVdggDPwAyyiH1fsucu-A@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+2n+cETRk6CPdNF95bNZrT_3vJVdggDPwAyyiH1fsucu-A@mail.gmail.com>", "list_archive_url": null, "date": "2017-08-31T15:18:07", "name": "C++ PATCH for c++/82029, ICE with __func__ in lambda in template", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "7bce6c81af79cd031db020eaaeb71621a5dab8f2", "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+2n+cETRk6CPdNF95bNZrT_3vJVdggDPwAyyiH1fsucu-A@mail.gmail.com/mbox/", "series": [ { "id": 847, "url": "http://patchwork.ozlabs.org/api/series/847/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=847", "date": "2017-08-31T15:18:07", "name": "C++ PATCH for c++/82029, ICE with __func__ in lambda in template", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/847/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/808274/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/808274/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<gcc-patches-return-461213-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-461213-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=\"cryFzkwX\"; 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 3xjmHF6V5sz9s7c\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri, 1 Sep 2017 01:18:48 +1000 (AEST)", "(qmail 30838 invoked by alias); 31 Aug 2017 15:18:40 -0000", "(qmail 30829 invoked by uid 89); 31 Aug 2017 15:18:40 -0000", "from mail-io0-f172.google.com (HELO mail-io0-f172.google.com)\n\t(209.85.223.172) by sourceware.org\n\t(qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP;\n\tThu, 31 Aug 2017 15:18:30 +0000", "by mail-io0-f172.google.com with SMTP id k22so332260iod.2 for\n\t<gcc-patches@gcc.gnu.org>; Thu, 31 Aug 2017 08:18:30 -0700 (PDT)", "by 10.107.181.23 with HTTP; Thu, 31 Aug 2017 08:18:07 -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=dz3+AGN4Ppz+A+IM7DjPBGeom1zXn4M9DkWwKeh8o6I56E\n\tkXjEMq1vWyQE5zZfsBk4voEdH32NWIFMjtFeVB8Zc37WfZOub1STS5xN0lQMtlLO\n\t5+6tbNdJEqcpfDv6vlv2+GXK32yejrCqRgNZqAP1+gBSeqG3d+0l/Q8n4LfX0=", "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=d4WKAnOzHPTTKI3YPA+o4SDePOc=; b=cryFzkwXSmMMsBF9cwEL\n\t0PaxTpOLxtadI9ImniKpyqx5ZvTGfNCZfuti9PXzvTMr0iMD+gmqsE00usLRd+P9\n\ty3L8+yRmuMUabdyQKFKU/XuX2XtAGYaRYamTika8xyLECVIDk8T4LyJEriyLoAF9\n\t3Kkdw03hwUxqedxDGxi0pkA=", "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=-25.0 required=5.0 tests=AWL, BAYES_00,\n\tGIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3,\n\tRCVD_IN_DNSWL_NONE,\n\tRCVD_IN_SORBS_SPAM autolearn=ham version=3.3.2 spammy=revisit", "X-HELO": "mail-io0-f172.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=LO983qWA0tiSOJdiTidL4Y2OUiP/4pRxQUsaj8Te+68=;\n\tb=WBERXUiYhWQ+LvCdZNCrIutjRPCl99pq88hoOczbqsZTrHabai21nQyv6I4M6NGybB\n\tBYuZ7BezSa+opx5j88j8Y7hWIVLDIjPhojRCxUaUQsBqp+MbfmxLbHWwjPp6t2bvt5w7\n\tJdhpiboAmAQEreqhwZ49QgmCibgoMiQtzYmxdKOijZPRxICwZIPAZWW1QqYNeNxoVy4c\n\t7AVnwqzq7jeqrsiVVX1y6+BPAXonFgBBeZCLr3MxmU+twNIxBMKj7febec0vvsy7bPR4\n\thT2+br0ZgnzmSP3rcdn/Gd+a81b4u+6kqQnmbsPEGe8IHH1XKcG7Mpta0PrtSQ1MG3ji\n\tKPZg==", "X-Gm-Message-State": "AHYfb5hArRGbsApNuC/L72Svyk8OYRm2ZosP294aHeDMaXLWRuec6G0x\tluJKndLZtMWrGnWSzuikdxqRsKTH4EIis4s=", "X-Google-Smtp-Source": "ADKCNb7zsdKMqkEmzYlDMntAYBu6Lpih+hCaltrb1zrlVqIl9QNVxBWqMRggvtbc0D9wdewHdXgrKbjWctRnRxjh/GQ=", "X-Received": "by 10.36.216.8 with SMTP id b8mr1244942itg.55.1504192708219;\n\tThu, 31 Aug 2017 08:18:28 -0700 (PDT)", "MIME-Version": "1.0", "From": "Jason Merrill <jason@redhat.com>", "Date": "Thu, 31 Aug 2017 11:18:07 -0400", "Message-ID": "<CADzB+2n+cETRk6CPdNF95bNZrT_3vJVdggDPwAyyiH1fsucu-A@mail.gmail.com>", "Subject": "C++ PATCH for c++/82029, ICE with __func__ in lambda in template", "To": "gcc-patches List <gcc-patches@gcc.gnu.org>", "Content-Type": "multipart/mixed; boundary=\"94eb2c05e89e0caafc05580e28cd\"", "X-IsSubscribed": "yes" }, "content": "When tsubst_decl creates a new local static variable, it checks to see\nif it belongs to current_function_decl. It has done this by tsubsting\nthe old DECL_CONTEXT, but that doesn't work with the new lambda model,\nwhere we can't get to the new lambda op() by tsubsting the old one.\nSo this patch introduces a new function enclosing_instantiation_of,\nwhich looks out from current_function_decl to find which enclosing\nfunction corresponds to the context of the variable in the template.\n\nI've attached two versions of this patch: one which matches up lambdas\nbased on nesting level within an enclosing function, and one which\nuses a hash table. I've been ambivalent about which to go with; the\nfirst has more complicated logic, but uses less space, so I think\nthat's the one I'm going to check in now. I might revisit this choice\nif I find other uses for the hash table.\n\nTested x86_64-pc-linux-gnu, applying to trunk.\ncommit 4c88ba8c2a00d662c33f0e2569526122759dc2cb\nAuthor: Jason Merrill <jason@redhat.com>\nDate: Wed Aug 30 16:26:24 2017 -0400\n\n PR c++/82029 - __PRETTY_FUNCTION__ in lambda in template\n \n * pt.c (enclosing_instantiation_of, lambda_fn_in_template_p)\n (regenerated_lambda_fn_p): New.\n (tsubst_decl) [VAR_DECL]: Use enclosing_instantiation_of.\n (tsubst_copy) [VAR_DECL]: Likewise.\ncommit 3edefaa7d1dd5d6b947d4311be1e508552b303c9\nAuthor: Jason Merrill <jason@redhat.com>\nDate: Wed Aug 30 16:26:24 2017 -0400\n\n PR c++/82029 - __PRETTY_FUNCTION__ in lambda in template\n \n * pt.c (enclosing_instantiation_of): New.\n (tsubst_decl) [VAR_DECL]: Use it.\n (tsubst_copy) [VAR_DECL]: Likewise.\n (lambda_fn_origin): New hash table.\n (tsubst_lambda_expr): Populate it.\n\ndiff --git a/gcc/cp/pt.c b/gcc/cp/pt.c\nindex f4868ab..41fecaf 100644\n--- a/gcc/cp/pt.c\n+++ b/gcc/cp/pt.c\n@@ -12587,6 +12587,37 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain,\n return r;\n }\n \n+/* A hash table from a lambda op() in a template instantiation to the op() of\n+ the corresponding lambda in the uninstantiated template. */\n+static GTY(()) hash_map<tree, tree> *lambda_fn_origin;\n+\n+/* We're instantiating a variable from template function TCTX. Return the\n+ corresponding current enclosing scope. This gets complicated because lambda\n+ functions in templates are regenerated rather than instantiated, but generic\n+ lambda functions are subsequently instantiated. */\n+\n+static tree\n+enclosing_instantiation_of (tree tctx)\n+{\n+ for (tree fn = current_function_decl; fn; fn = decl_function_context (fn))\n+ {\n+ tree origin;\n+ tree *slot;\n+\n+ if (LAMBDA_FUNCTION_P (fn) && lambda_fn_origin\n+\t && (slot = lambda_fn_origin->get (fn)))\n+\torigin = *slot;\n+ else if (DECL_TEMPLATE_INFO (fn))\n+\torigin = DECL_TEMPLATE_RESULT (most_general_template (fn));\n+ else\n+\torigin = fn;\n+\n+ if (origin == tctx)\n+\treturn fn;\n+ }\n+ gcc_unreachable ();\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@@ -12955,7 +12986,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)\n \t enclosing function, in which case we need to fill it in now. */\n \t if (TREE_STATIC (t))\n \t {\n-\t\ttree fn = tsubst (DECL_CONTEXT (t), args, complain, in_decl);\n+\t\ttree fn = enclosing_instantiation_of (DECL_CONTEXT (t));\n \t\tif (fn != current_function_decl)\n \t\t ctx = fn;\n \t }\n@@ -14734,9 +14765,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n \t if (r && !is_capture_proxy (r))\n \t\t{\n \t\t /* Make sure that the one we found is the one we want. */\n-\t\t tree ctx = DECL_CONTEXT (t);\n-\t\t if (DECL_LANG_SPECIFIC (ctx) && DECL_TEMPLATE_INFO (ctx))\n-\t\t ctx = tsubst (ctx, args, complain, in_decl);\n+\t\t tree ctx = enclosing_instantiation_of (DECL_CONTEXT (t));\n \t\t if (ctx != DECL_CONTEXT (r))\n \t\t r = NULL_TREE;\n \t\t}\n@@ -16855,6 +16884,10 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n \t finish_member_declaration (fn);\n \t}\n \n+ if (!lambda_fn_origin)\n+\tlambda_fn_origin = hash_map<tree,tree>::create_ggc (37);\n+ lambda_fn_origin->put (fn, oldfn);\n+\n /* Let finish_function set this. */\n DECL_DECLARED_CONSTEXPR_P (fn) = false;\n \ndiff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C\nnew file mode 100644\nindex 0000000..bc0e3b2\n--- /dev/null\n+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C\n@@ -0,0 +1,13 @@\n+// PR c++/82029\n+// { dg-do compile { target c++11 } }\n+\n+template <typename> struct A {\n+ void m_fn1() {\n+ [] { return __func__; }();\n+ }\n+};\n+struct B {\n+ A<int> a;\n+ void m_fn2();\n+};\n+void B::m_fn2() { a.m_fn1(); }", "diff": "diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c\nindex f4868ab..d5ab939 100644\n--- a/gcc/cp/pt.c\n+++ b/gcc/cp/pt.c\n@@ -12587,6 +12587,63 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain,\n return r;\n }\n \n+/* True if FN is the op() for a lambda in an uninstantiated template. */\n+\n+bool\n+lambda_fn_in_template_p (tree fn)\n+{\n+ if (!LAMBDA_FUNCTION_P (fn))\n+ return false;\n+ tree closure = DECL_CONTEXT (fn);\n+ return CLASSTYPE_TEMPLATE_INFO (closure) != NULL_TREE;\n+}\n+\n+/* True if FN is the op() for a lambda regenerated from a lambda in an\n+ uninstantiated template. */\n+\n+bool\n+regenerated_lambda_fn_p (tree fn)\n+{\n+ return (LAMBDA_FUNCTION_P (fn)\n+\t && !DECL_TEMPLATE_INSTANTIATION (fn));\n+}\n+\n+/* We're instantiating a variable from template function TCTX. Return the\n+ corresponding current enclosing scope. This gets complicated because lambda\n+ functions in templates are regenerated rather than instantiated, but generic\n+ lambda functions are subsequently instantiated. */\n+\n+static tree\n+enclosing_instantiation_of (tree tctx)\n+{\n+ tree fn = current_function_decl;\n+ int lambda_count = 0;\n+\n+ for (; tctx && lambda_fn_in_template_p (tctx);\n+ tctx = decl_function_context (tctx))\n+ ++lambda_count;\n+ for (; fn; fn = decl_function_context (fn))\n+ {\n+ tree lambda = fn;\n+ int flambda_count = 0;\n+ for (; fn && regenerated_lambda_fn_p (fn);\n+\t fn = decl_function_context (fn))\n+\t++flambda_count;\n+ if (DECL_TEMPLATE_INFO (fn)\n+\t ? most_general_template (fn) != most_general_template (tctx)\n+\t : fn != tctx)\n+\tcontinue;\n+ if (lambda_count)\n+\t{\n+\t fn = lambda;\n+\t while (flambda_count-- > lambda_count)\n+\t fn = decl_function_context (fn);\n+\t}\n+ return fn;\n+ }\n+ gcc_unreachable ();\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@@ -12955,7 +13012,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)\n \t enclosing function, in which case we need to fill it in now. */\n \t if (TREE_STATIC (t))\n \t {\n-\t\ttree fn = tsubst (DECL_CONTEXT (t), args, complain, in_decl);\n+\t\ttree fn = enclosing_instantiation_of (DECL_CONTEXT (t));\n \t\tif (fn != current_function_decl)\n \t\t ctx = fn;\n \t }\n@@ -14734,9 +14791,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n \t if (r && !is_capture_proxy (r))\n \t\t{\n \t\t /* Make sure that the one we found is the one we want. */\n-\t\t tree ctx = DECL_CONTEXT (t);\n-\t\t if (DECL_LANG_SPECIFIC (ctx) && DECL_TEMPLATE_INFO (ctx))\n-\t\t ctx = tsubst (ctx, args, complain, in_decl);\n+\t\t tree ctx = enclosing_instantiation_of (DECL_CONTEXT (t));\n \t\t if (ctx != DECL_CONTEXT (r))\n \t\t r = NULL_TREE;\n \t\t}\ndiff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C\nnew file mode 100644\nindex 0000000..bc0e3b2\n--- /dev/null\n+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C\n@@ -0,0 +1,13 @@\n+// PR c++/82029\n+// { dg-do compile { target c++11 } }\n+\n+template <typename> struct A {\n+ void m_fn1() {\n+ [] { return __func__; }();\n+ }\n+};\n+struct B {\n+ A<int> a;\n+ void m_fn2();\n+};\n+void B::m_fn2() { a.m_fn1(); }\n", "prefixes": [] }