Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2196362/?format=api
{ "id": 2196362, "url": "http://patchwork.ozlabs.org/api/patches/2196362/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/20260213151942.793332-1-ppalka@redhat.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": "<20260213151942.793332-1-ppalka@redhat.com>", "list_archive_url": null, "date": "2026-02-13T15:19:42", "name": "c++: equivalence of lowered constrained auto NTTPs [PR120136]", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "ac4672f210b6e52a3714deb09f0b91f38778d961", "submitter": { "id": 78319, "url": "http://patchwork.ozlabs.org/api/people/78319/?format=api", "name": "Patrick Palka", "email": "ppalka@redhat.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/20260213151942.793332-1-ppalka@redhat.com/mbox/", "series": [ { "id": 492112, "url": "http://patchwork.ozlabs.org/api/series/492112/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=492112", "date": "2026-02-13T15:19:42", "name": "c++: equivalence of lowered constrained auto NTTPs [PR120136]", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/492112/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2196362/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2196362/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=Jct6MQQU;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=38.145.34.32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)", "sourceware.org;\n\tdkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=Jct6MQQU", "sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com", "sourceware.org; spf=pass smtp.mailfrom=redhat.com", "server2.sourceware.org;\n arc=none smtp.remote-ip=170.10.129.124" ], "Received": [ "from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fCG7l0vq5z1xpl\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 14 Feb 2026 02:20:18 +1100 (AEDT)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id BBA624B9DB6E\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 13 Feb 2026 15:20:16 +0000 (GMT)", "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n by sourceware.org (Postfix) with ESMTP id BA11B4B9DB70\n for <gcc-patches@gcc.gnu.org>; Fri, 13 Feb 2026 15:19:47 +0000 (GMT)", "from mail-qk1-f200.google.com (mail-qk1-f200.google.com\n [209.85.222.200]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-653-KLQRfk62O_qqR1loWfMDHw-1; Fri, 13 Feb 2026 10:19:46 -0500", "by mail-qk1-f200.google.com with SMTP id\n af79cd13be357-8cb456d53a5so23908885a.2\n for <gcc-patches@gcc.gnu.org>; Fri, 13 Feb 2026 07:19:46 -0800 (PST)", "from idea ([2600:4040:aa66:bf00:9e8e:99ff:fed1:71f])\n by smtp.gmail.com with ESMTPSA id\n 6a1803df08f44-8971cdb5dbfsm74590646d6.41.2026.02.13.07.19.43\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Fri, 13 Feb 2026 07:19:43 -0800 (PST)" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org BBA624B9DB6E", "OpenDKIM Filter v2.11.0 sourceware.org BA11B4B9DB70" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org BA11B4B9DB70", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org BA11B4B9DB70", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1770995987; cv=none;\n b=mrTAZfK/u7StMYZKbMz0uHURRSvVOCwrSie3eqOcnpj2u1HH/xwIxIGz2itAnqYGGea7QT6xUPKzvZ1PYGsBPYQugIYuBJs09D7vT8Y1zVVKPck1r5riO/w12zAY+3O7viIx2JUubeh++PnHl+G1juMXIAZpMCwk7jA56KwE6Nw=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1770995987; c=relaxed/simple;\n bh=PcFMX7D2S6zTJ7a8Za4VH3eDxkWEMznZvfNywH6+xQM=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=Jpr8+eTt8eRbgqI59OAIuOmBh426New2T0SStEsKqCbb9Wz3kOoZjt08nu5tgDRassHYOccw2nK3G/uEk2sjQhc6J7eXkTa8jSNJt2zxw5HdvCldN+C5E5ed6iBaTLauc0SrbXdQnLb1zwTlNP0KcyyBAt2HQwHoefGw3Q9FpmA=", "ARC-Authentication-Results": "i=1; server2.sourceware.org", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1770995987;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding;\n bh=a9QZY80qHF7oQbX1c2tJDQvw4F2oPIZfEgznFdECr94=;\n b=Jct6MQQUaU3UT3pa8rnIw5GR+Q6IrSq7PXoGrk8XfVoVY0dUPXKL5WHQzs/AutMiu8xVCU\n tqePH52tXAqc+CcxlYHUjMzq8whfcqZi3Goy6f4H3dYYPm8q4ZRTFDxtMHAFfJyf4FrqE7\n rHn1opZXzvEe3J9/SCoj0fTP5H5cpt4=", "X-MC-Unique": "KLQRfk62O_qqR1loWfMDHw-1", "X-Mimecast-MFC-AGG-ID": "KLQRfk62O_qqR1loWfMDHw_1770995986", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1770995985; x=1771600785;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n :message-id:reply-to;\n bh=a9QZY80qHF7oQbX1c2tJDQvw4F2oPIZfEgznFdECr94=;\n b=gUvv/nQ/KFc3V6sYB5hfL+OcHGvgh24lse+vOCsA11jR+FM/qxcftcTnF/Z725Llsj\n VFbMg6UXuHvKYaBEvEDygn/fYTL+Eoh1xFBNjzSjo6FoPXwAnuTw717MjmzjtwgGVxcS\n 8lLGKI0FE4YonoeYsMbiOUEWlTNqAd0T2kDPRtu3gCZJqQc90oOZOKEnFjJ/3m+w+WyT\n VDM/4wx9IvjB8/zSbQ2WfrDo4tp5gjVkIDo9pofhRFEAQPf8vibK9a1HYG1JYu9JaUrW\n UlcdgVYsWMSjKDqLjYQpJwLC29+fkbpn45dvTpw7k0Sh6bzqxSE3+7nVdn3Z0n6Ai7WE\n D86A==", "X-Gm-Message-State": "AOJu0YyO0nW7EdXFYVUI50W8TgMlVowhOm7rxhLEUnGTcc2iPVC3Fie7\n YjSrrAfb5sEQXpGftw6Rwtu8/U+78nFPCegFe6ifawqZDCrEwjpgE7+iVDFDAZzjgHpYg/YF1Te\n IjtKNMUr0oBcu31lFT///Az2qJh1imAiFjrMcLigpr9/jOWSdMWCUQLcacaYWM+bOfURitw/zb9\n dYVxAn/C842BbuQWWhxZ7GMlxE7IbFxtKL5DtYtxDe", "X-Gm-Gg": "AZuq6aIomPa8kJIqUgo8IsmJrCR7O8aAwrZe7pDrrPtipMDev3bChTXO5RWBHJROV9S\n H6ekA2/7ZJ68ZEV7/FciVgT4wsxHIIjbRAlptqlSmpRSQxV/n7WCiPHjioMRzkea+fMcYGUZAhz\n HqL7DFGqeC65j7fz/ZU7r/cgnRVKxyUXpXiPeahbo0tTEC+RyVkGoPf/zHUi6k3gZ0n69LJpVr3\n JVioH316mzkmV6mN9ep0h4C/oaiRY1BulkIr8nD1jTdlUgjXTno4tMzpL/gPtOFVRXVHhs37irW\n tJGvtOUR5Eu3TF63FH0QrPzbpXeHy6FIbwDbmUz8HsDF/Bt5oSIsV60K4+suHzncR3qjGxqGDux\n xCrC8LA67gT4=", "X-Received": [ "by 2002:a05:620a:400a:b0:8cb:3df5:4b70 with SMTP id\n af79cd13be357-8cb4081fc2fmr263884685a.2.1770995984948;\n Fri, 13 Feb 2026 07:19:44 -0800 (PST)", "by 2002:a05:620a:400a:b0:8cb:3df5:4b70 with SMTP id\n af79cd13be357-8cb4081fc2fmr263880685a.2.1770995984261;\n Fri, 13 Feb 2026 07:19:44 -0800 (PST)" ], "From": "Patrick Palka <ppalka@redhat.com>", "To": "gcc-patches@gcc.gnu.org", "Cc": "jason@redhat.com,\n\tPatrick Palka <ppalka@redhat.com>", "Subject": "[PATCH] c++: equivalence of lowered constrained auto NTTPs [PR120136]", "Date": "Fri, 13 Feb 2026 10:19:42 -0500", "Message-ID": "<20260213151942.793332-1-ppalka@redhat.com>", "X-Mailer": "git-send-email 2.53.0.80.g6fcee47852", "MIME-Version": "1.0", "X-Mimecast-Spam-Score": "0", "X-Mimecast-MFC-PROC-ID": "sJ0WsULdbyKF5QJ0ZjAAUppBHNv-oIYgJlDvyq6pbBo_1770995986", "X-Mimecast-Originator": "redhat.com", "Content-Transfer-Encoding": "8bit", "content-type": "text/plain; charset=\"US-ASCII\"; x-default=true", "X-BeenThere": "gcc-patches@gcc.gnu.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "Gcc-patches mailing list <gcc-patches.gcc.gnu.org>", "List-Unsubscribe": "<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>", "List-Archive": "<https://gcc.gnu.org/pipermail/gcc-patches/>", "List-Post": "<mailto:gcc-patches@gcc.gnu.org>", "List-Help": "<mailto:gcc-patches-request@gcc.gnu.org?subject=help>", "List-Subscribe": "<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>", "Errors-To": "gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org" }, "content": "Bootstrapped and regtested on x86_64-pc-linux-gnu, does this approach\nseem reasonable?\n\n-- >8 --\n\nIn the first testcase below (pretending r16-7491 hasn't been merged and\nwe still do ad-hoc checking of simple constrained auto NTTPs), we find\nourselves conflating two dependent specializations of the form foo<c>\nwhere in one c is a constrained auto NTTP with original level 3, and in\nthe other with original level 2. Then during unification of foo<c> with\nfoo<42>, do_auto_deduction checks c's constraint against the argument 42.\nDue to the mentioned conflation this is done with a different ORIG_LEVEL\nauto, which causes the ORIG_LEVEL workaround in do_auto_deduction to\nmisbehave and we crash.\n\nThis patch fixes this issue by preferring to use the in-scope version\nof a constrained auto NTTP when a mismatch is noticed. Note this\nworkaround is needed even after r16-7491 for non-simple constrained\nautos as in the second and fourth testcases.\n\nThis approach, while ugly, is a narrow workaround that should be\nrelatively safe to backport. Another approach might be to \"unconstrain\"\nauto NTTP arguments in strip_typedefs_expr when forming a dependent\nspecialization so that later unification doesn't hit this situation,\nbut that'd mean rebuilding arbitrarily complex autos, e.g. auto***&.\n\nIt occurred to me that checking auto constraints when unifying foo<c>\nwith foo<42> is redundant here, because the specialization wouldn't\nhave been formed in the first place if the the constraint was invalid.\nSo yet another approach would be to make unify aware of this and avoid\nchecking constraints when recursing into specialization arguments.\n\n\tPR c++/120136\n\ngcc/cp/ChangeLog:\n\n\t* pt.cc (unify) <case TEMPLATE_PARM_INDEX>: Before doing\n\tdo_auto_deduction on a constrained auto NTTP, prefer using the\n\tin-scope version of the parameter.\n\ngcc/testsuite/ChangeLog:\n\n\t* g++.dg/cpp2a/concepts-placeholder16.C: New test.\n\t* g++.dg/cpp2a/concepts-placeholder16b.C: New test.\n\t* g++.dg/cpp2a/concepts-placeholder17.C: New test.\n\t* g++.dg/cpp2a/concepts-placeholder17b.C: New test.\n---\n gcc/cp/pt.cc | 31 ++++++++++++++++++\n .../g++.dg/cpp2a/concepts-placeholder16.C | 24 ++++++++++++++\n .../g++.dg/cpp2a/concepts-placeholder16b.C | 27 ++++++++++++++++\n .../g++.dg/cpp2a/concepts-placeholder17.C | 29 +++++++++++++++++\n .../g++.dg/cpp2a/concepts-placeholder17b.C | 32 +++++++++++++++++++\n 5 files changed, 143 insertions(+)\n create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16.C\n create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16b.C\n create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder17.C\n create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder17b.C", "diff": "diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc\nindex 20fd30a8b473..512e29980f7c 100644\n--- a/gcc/cp/pt.cc\n+++ b/gcc/cp/pt.cc\n@@ -26174,6 +26174,37 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,\n \n \t if (tree a = type_uses_auto (tparm))\n \t {\n+\t if (tree a_ci = PLACEHOLDER_TYPE_CONSTRAINTS_INFO (a))\n+\t\t{\n+\t\t /* Constrained auto NTTP checking is sensitive to\n+\t\t TEMPLATE_TYPE_ORIG_LEVEL and the set of in-scope template\n+\t\t parameters (i.e. TREE_PURPOSE (a_ci)), but our notion of\n+\t\t template argument equivalence isn't. So we'd conflate two\n+\t\t specializations A<V> where V is a lowered constrained auto\n+\t\t NTTP from different template contexts, which may break\n+\t\t constraint checking for V when unifying A<V> with A<...>.\n+\t\t Prefer using the in-scope V in this case, which matches\n+\t\t the current template context. */\n+\t\t tree scope_tparm\n+\t\t = TREE_TYPE (TREE_VALUE (TREE_VEC_ELT (tparms, idx)));\n+\t\t tree b = type_uses_auto (scope_tparm);\n+\t\t tree b_ci = PLACEHOLDER_TYPE_CONSTRAINTS_INFO (b);\n+\t\t gcc_checking_assert (equivalent_placeholder_constraints\n+\t\t\t\t (TREE_VALUE (a_ci), TREE_VALUE (b_ci)));\n+\t\t if (TEMPLATE_TYPE_ORIG_LEVEL (b)\n+\t\t != TEMPLATE_TYPE_ORIG_LEVEL (a))\n+\t\t {\n+\t\t ++processing_template_decl;\n+\t\t scope_tparm\n+\t\t\t= tsubst (scope_tparm, targs, tf_none, NULL_TREE);\n+\t\t --processing_template_decl;\n+\t\t b = type_uses_auto (scope_tparm);\n+\t\t gcc_checking_assert (same_type_p (tparm, scope_tparm));\n+\t\t tparm = scope_tparm;\n+\t\t a = b;\n+\t\t }\n+\t\t}\n+\n \t tparm = do_auto_deduction (tparm, arg, a,\n \t\t\t\t\t complain, adc_unify, targs,\n \t\t\t\t\t LOOKUP_NORMAL,\ndiff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16.C b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16.C\nnew file mode 100644\nindex 000000000000..bc29f8ed0e96\n--- /dev/null\n+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16.C\n@@ -0,0 +1,24 @@\n+// PR c++/120136\n+// { dg-do compile { target c++20 } }\n+\n+template <class> \n+concept car = true;\n+\n+template <auto... xs> \n+struct set {\n+ static auto contains(car auto x) { \n+ return ((x == xs) || ...); \n+ }\n+};\n+\n+template <auto>\n+struct foo {\n+ template <car auto c>\n+ friend bool operator==(foo, foo<c>);\n+};\n+\n+template <car auto c> foo<c> foobar;\n+\n+auto a = foobar<42>;\n+auto b = set<a>{};\n+auto c = b.contains(a);\ndiff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16b.C b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16b.C\nnew file mode 100644\nindex 000000000000..e62a3510d2ae\n--- /dev/null\n+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16b.C\n@@ -0,0 +1,27 @@\n+// PR c++/120136\n+// { dg-do compile { target c++20 } }\n+// A version of concepts-placeholder16.C using where the\n+// constrained auto NTTP 'c' is an auto&.\n+\n+template <class> \n+concept car = true;\n+\n+template <auto... xs> \n+struct set {\n+ static auto contains(car auto x) { \n+ return ((x == xs) || ...); \n+ }\n+};\n+\n+template <auto>\n+struct foo {\n+ template <car auto& c>\n+ friend bool operator==(foo, foo<c>);\n+};\n+\n+template <car auto& c> foo<c> foobar;\n+\n+inline constexpr int n = 42;\n+auto a = foobar<n>;\n+auto b = set<a>{};\n+auto c = b.contains(a);\ndiff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder17.C b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder17.C\nnew file mode 100644\nindex 000000000000..de8de1b74d6e\n--- /dev/null\n+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder17.C\n@@ -0,0 +1,29 @@\n+// PR c++/122204\n+// { dg-do compile { target c++20 } }\n+\n+template <int param>\n+struct A {};\n+\n+template <typename T>\n+struct IsA {\n+ static constexpr bool value = true;\n+};\n+\n+template <typename T>\n+concept Ac = IsA<T>::value;\n+\n+template <Ac auto dim>\n+struct V {};\n+\n+template <typename T>\n+struct IsV {};\n+template <Ac auto dim>\n+struct IsV<V<dim>> {};\n+\n+template <int i>\n+struct B {\n+ template <Ac auto dim>\n+ void f(V<dim>) const;\n+};\n+\n+void crashing_function() { B<0>{}.f(V<A<0>{}>{}); }\ndiff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder17b.C b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder17b.C\nnew file mode 100644\nindex 000000000000..fc8e2a6bb0fc\n--- /dev/null\n+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder17b.C\n@@ -0,0 +1,32 @@\n+// PR c++/122204\n+// { dg-do compile { target c++20 } }\n+// A version of concepts-placeholder16.C using where the\n+// constrained auto NTTP 'dim' is an auto&.\n+\n+template <int param>\n+struct A {};\n+\n+template <typename T>\n+struct IsA {\n+ static constexpr bool value = true;\n+};\n+\n+template <typename T>\n+concept Ac = IsA<T>::value;\n+\n+template <Ac auto& dim>\n+struct V {};\n+\n+template <typename T>\n+struct IsV {};\n+template <Ac auto& dim>\n+struct IsV<V<dim>> {};\n+\n+template <int i>\n+struct B {\n+ template <Ac auto& dim>\n+ void f(V<dim>) const;\n+};\n+\n+inline constexpr A<0> a;\n+void crashing_function() { B<0>{}.f(V<a>{}); }\n", "prefixes": [] }