get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2215606,
    "url": "http://patchwork.ozlabs.org/api/patches/2215606/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/acLrujgOt2w8gd5_@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": "<acLrujgOt2w8gd5_@redhat.com>",
    "list_archive_url": null,
    "date": "2026-03-24T19:53:30",
    "name": "[v2] c++/reflection: ICE with substitute and undeduced auto [PR123613]",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "b6ac09e132916693a25f6251e422e66ad612ff01",
    "submitter": {
        "id": 14370,
        "url": "http://patchwork.ozlabs.org/api/people/14370/?format=api",
        "name": "Marek Polacek",
        "email": "polacek@redhat.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/acLrujgOt2w8gd5_@redhat.com/mbox/",
    "series": [
        {
            "id": 497341,
            "url": "http://patchwork.ozlabs.org/api/series/497341/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=497341",
            "date": "2026-03-24T19:53:30",
            "name": "[v2] c++/reflection: ICE with substitute and undeduced auto [PR123613]",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/497341/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2215606/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2215606/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=JzSSYXyJ;\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=JzSSYXyJ",
            "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.133.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 4fgLMk0K4Cz1y1K\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 25 Mar 2026 06:54:08 +1100 (AEDT)",
            "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id AE90F4BB3BF5\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 24 Mar 2026 19:54:06 +0000 (GMT)",
            "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by sourceware.org (Postfix) with ESMTP id 5030D4BB3BC9\n for <gcc-patches@gcc.gnu.org>; Tue, 24 Mar 2026 19:53:36 +0000 (GMT)",
            "from mail-qt1-f198.google.com (mail-qt1-f198.google.com\n [209.85.160.198]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-306-AA9Y5m4fO6GUFpjX-n7MTA-1; Tue, 24 Mar 2026 15:53:34 -0400",
            "by mail-qt1-f198.google.com with SMTP id\n d75a77b69052e-50b4b81c632so60600981cf.1\n for <gcc-patches@gcc.gnu.org>; Tue, 24 Mar 2026 12:53:34 -0700 (PDT)",
            "from redhat.com ([2603:7000:9500:10::1db4])\n by smtp.gmail.com with ESMTPSA id\n 6a1803df08f44-89c852181b3sm136686126d6.9.2026.03.24.12.53.32\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 24 Mar 2026 12:53:32 -0700 (PDT)"
        ],
        "DKIM-Filter": [
            "OpenDKIM Filter v2.11.0 sourceware.org AE90F4BB3BF5",
            "OpenDKIM Filter v2.11.0 sourceware.org 5030D4BB3BC9"
        ],
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 5030D4BB3BC9",
        "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 5030D4BB3BC9",
        "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1774382016; cv=none;\n b=D5H8aqxEalSu0f+K/1QjP8D1VJMHQxfDZvlw11QT9B0psJ7z7LXnajLpKvavqU6u5DxPgqX7a3uDjqEzWG4IoATJm+RimqZ83LPq7vGCBdmFaEyo5SK35SxDSm8qM5WrlpCS2xjclfpHRj7i1QiFLyhSBUIfWnP5X9Rv0ly/r6Q=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1774382016; c=relaxed/simple;\n bh=rFZQZy4IPn6IeoxCyOx+12CECvPi33QD8iT0E6r978c=;\n h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version;\n b=kLC+RzACJW9LUCmxGQC6QRSpmlWt0laMEG0RfENuqoFNO3/jWz1ZQF9p6L+cq5ZlocA4GTvsu/O9qz/vSfDW7FZ2PDIvouzJ2FyVO14cQWrtxrWg+ywKgErofRpgjlJnojMuN+8LyNjcyUpgUgmDsguUK9swlM89PRv5FSPCBf0=",
        "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=1774382016;\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 in-reply-to:in-reply-to:references:references;\n bh=r8EvdnUJoxnteqgopV1/aG3qaoGHY6pU3cuYUrCdOCc=;\n b=JzSSYXyJUGf2EDjOBXx/4UGiUjlF7rcPAcZ2fFJlYWHzKUpWofxkowZJZfb91DmKY+iydz\n iHhDw0rX7oiuSN+Oe2it4f7gRFvlnDNSnnbsP7EBQ4wHfXMFPSZpfYxZQ0v3FI/TwYLcVp\n PWjmIgd7D0pPtL5nrwN7gvobJaS/dCk=",
        "X-MC-Unique": "AA9Y5m4fO6GUFpjX-n7MTA-1",
        "X-Mimecast-MFC-AGG-ID": "AA9Y5m4fO6GUFpjX-n7MTA_1774382014",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1774382014; x=1774986814;\n h=user-agent:in-reply-to:content-disposition:mime-version:references\n :message-id:subject:cc:to:from:date:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=r8EvdnUJoxnteqgopV1/aG3qaoGHY6pU3cuYUrCdOCc=;\n b=U+esUddPereEL6sMHjWlFjth9Ohn8C+HZyl4jQERDnd6TJPbktQXofJ6CtNM/snsuh\n mZjFFsgHKrKPnzTC/iatzYGC39Wk8zXjeiS0y9e2mINvjnBLheu3IKOl0hq3e1edHZV0\n SclhVU3XxZzl8yIEqxvMk6GtJ6ayqFIIQ0qCR28bOrrbq/FO6+zoItl34ITD9kig4FR+\n ZXxvuEJy1Zlf0jXwpaop4MIdv445rQoirmmUlpKxnEdyqMWjhxTKYzHoRDJmSkjjPiMp\n jV/tU4vbJn/hjruZ52znj/1jFazOQ97tRnYUY/mL+DnM938KNFCJNJuxR0gaGYJGxNC2\n wznA==",
        "X-Gm-Message-State": "AOJu0Yzd6Z0Kd5MRdLgRg4bQX/Xyh7fZbLddot8n1Rp0sVUCHaxWpaVL\n BCybbStNQ3So8AE/FVXswhvYixbzQcfRuT+5LSJTV3+yqkDnDbmRneJ1eU7pvVa8A86GZtlgzxk\n ERiCII2KOzV8gLE9k5RfVF5kNcisD8wWLs/LqMyB3HWEQEVCfUQk+3UYD7j8=",
        "X-Gm-Gg": "ATEYQzx4beU7glBGZ7ZzbsXLX572e8rlU257TTiOnG0nxKTMk/2vXK0k9imXcMMVKrX\n jMBtYJVCvf5qECUPjtUaYDSvTGN0xnFdjZB35oiS+LQJ7GYRBnrfRJLlp1wxONzrbbj3b+6y1Bl\n a7YlZjv6jCl8NTGsbkZWl1bDPJQd4yAK6bHZnvPW245IpGm27FJ45AqhF0oGWLFRedUKMWFj4Eq\n qErMiaf+iPArWBnAQisdt2a1X372mUU5OMoG1+QoZ7+yXYlOtpSzm1BUmFNGfPYGzxIKL7lJv1s\n 0cfyZEaMNA+R8C0nfF7wLe6RFtsL7cplbWnmZU1Iu7JA00b3rZA3fHpDgue/bCF/H/yIlnN7bfK\n rGw==",
        "X-Received": [
            "by 2002:ac8:4542:0:b0:50b:4be1:7c95 with SMTP id\n d75a77b69052e-50b80d581b4mr10960361cf.30.1774382013873;\n Tue, 24 Mar 2026 12:53:33 -0700 (PDT)",
            "by 2002:ac8:4542:0:b0:50b:4be1:7c95 with SMTP id\n d75a77b69052e-50b80d581b4mr10960131cf.30.1774382013305;\n Tue, 24 Mar 2026 12:53:33 -0700 (PDT)"
        ],
        "Date": "Tue, 24 Mar 2026 15:53:30 -0400",
        "From": "Marek Polacek <polacek@redhat.com>",
        "To": "Jason Merrill <jason@redhat.com>",
        "Cc": "GCC Patches <gcc-patches@gcc.gnu.org>, Jakub Jelinek <jakub@redhat.com>",
        "Subject": "[PATCH v2] c++/reflection: ICE with substitute and undeduced auto\n [PR123613]",
        "Message-ID": "<acLrujgOt2w8gd5_@redhat.com>",
        "References": "<20260319180156.1398725-1-polacek@redhat.com>\n <5d918cf0-da0a-4043-8946-7e70566ede9c@redhat.com>",
        "MIME-Version": "1.0",
        "In-Reply-To": "<5d918cf0-da0a-4043-8946-7e70566ede9c@redhat.com>",
        "User-Agent": "Mutt/2.3.0 (2026-01-25)",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-MFC-PROC-ID": "r-1Gac-ZtxO0fj-pc95tgpMCw5h48NUu09ikPm64Alk_1774382014",
        "X-Mimecast-Originator": "redhat.com",
        "Content-Type": "text/plain; charset=us-ascii",
        "Content-Disposition": "inline",
        "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": "On Fri, Mar 20, 2026 at 06:19:18PM -0400, Jason Merrill wrote:\n> On 3/19/26 2:01 PM, Marek Polacek wrote:\n> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?\n> > \n> > -- >8 --\n> > In substitute7.C we have\n> > \n> >    template <typename T, auto ... Vs>\n> >    constexpr auto construct_from = T{Vs...}; // #1\n> >    struct Inner {};\n> >    struct Outer { Inner m; };\n> >    constexpr auto r = substitute(^^construct_from,\n> >                                 { ^^Outer, ^^construct_from<Inner> });\n> > \n> > which crashes because the auto in #1 hadn't been deduced when we\n> > called eval_can_substitute -> lookup_template_variable when processing\n> > the substitute call.\n> \n> Hmm, why wasn't it already deduced when we took the reflection? Likewise for\n> the resolve_, actually.\n\nIt seems like I can do the instantiation earlier, in get_reflection.  We\nalready perform the resolve_ there, so eval_can_substitute probably does\nnot need to do it again.\n \nThus, v2:\n\nBootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?\n\n-- >8 --\nIn substitute7.C we have\n\n  template <typename T, auto ... Vs>\n  constexpr auto construct_from = T{Vs...}; // #1\n  struct Inner {};\n  struct Outer { Inner m; };\n  constexpr auto r = substitute(^^construct_from,\n                               { ^^Outer, ^^construct_from<Inner> });\n\nwhich crashes because the auto in #1 hadn't been deduced when we\ncalled eval_can_substitute -> lookup_template_variable when processing\nthe substitute call.  We can call mark_used to resolve this, because\nit has:\n\n  if (undeduced_auto_decl (decl))\n    maybe_instantiate_decl (decl);\n\nand to make the json-parser.C test work, we have to do something\nsimilar in eval_substitute, otherwise we crash due to another\nundeduced auto.\n\n\tPR c++/123613\n\ngcc/cp/ChangeLog:\n\n\t* reflect.cc (get_reflection): Call mark_used.\n\t(eval_can_substitute): Don't resolve_nondeduced_context here.\n\t(eval_substitute): Call lookup_and_finish_template_variable instead\n\tof lookup_template_variable and finish_template_variable.\n\ngcc/testsuite/ChangeLog:\n\n\t* g++.dg/reflect/json-parser.C: New test.\n\t* g++.dg/reflect/substitute7.C: New test.\n\t* g++.dg/reflect/test.json: New test.\n---\n gcc/cp/reflect.cc                          |  16 +-\n gcc/testsuite/g++.dg/reflect/json-parser.C | 161 +++++++++++++++++++++\n gcc/testsuite/g++.dg/reflect/substitute7.C |  14 ++\n gcc/testsuite/g++.dg/reflect/test.json     |   4 +\n 4 files changed, 188 insertions(+), 7 deletions(-)\n create mode 100644 gcc/testsuite/g++.dg/reflect/json-parser.C\n create mode 100644 gcc/testsuite/g++.dg/reflect/substitute7.C\n create mode 100644 gcc/testsuite/g++.dg/reflect/test.json\n\n\nbase-commit: 5cd3889135d77bf951e4ffe169868b453c36257d",
    "diff": "diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc\nindex 0b1d3a36f37..e4313ae5e98 100644\n--- a/gcc/cp/reflect.cc\n+++ b/gcc/cp/reflect.cc\n@@ -212,8 +212,14 @@ get_reflection (location_t loc, tree t, reflect_kind kind/*=REFLECT_UNDEF*/)\n      overload resolution for the expression &S with no target shall\n      select a unique function; R represents that function.  */\n   else if (!processing_template_decl && t != unknown_type_node)\n-    /* Resolve all TEMPLATE_ID_EXPRs here.  */\n-    t = resolve_nondeduced_context_or_error (t, tf_warning_or_error);\n+    {\n+      /* Resolve all TEMPLATE_ID_EXPRs here.  */\n+      t = resolve_nondeduced_context_or_error (t, tf_warning_or_error);\n+      /* The argument could have a deduced return type, so we need to\n+\t instantiate it now to find out its type.  */\n+      if (!mark_used (t))\n+\treturn error_mark_node;\n+    }\n \n   /* For injected-class-name, use the main variant so that comparing\n      reflections works (cf. compare3.C).  */\n@@ -5359,7 +5365,6 @@ eval_can_substitute (location_t loc, const constexpr_ctx *ctx,\n \treturn throw_exception (loc, ctx,\n \t\t\t\t\"invalid argument to can_substitute\",\n \t\t\t\tfun, non_constant_p, jump_target);\n-      a = resolve_nondeduced_context (a, tf_warning_or_error);\n       a = convert_from_reference (a);\n       TREE_VEC_ELT (rvec, i) = a;\n     }\n@@ -5432,10 +5437,7 @@ eval_substitute (location_t loc, const constexpr_ctx *ctx,\n       return get_reflection_raw (loc, ret, REFLECT_VALUE);\n     }\n   else if (variable_template_p (r))\n-    {\n-      ret = lookup_template_variable (r, rvec, tf_none);\n-      ret = finish_template_variable (ret, tf_none);\n-    }\n+    ret = lookup_and_finish_template_variable (r, rvec, tf_none);\n   else\n     {\n       if (DECL_FUNCTION_TEMPLATE_P (r))\ndiff --git a/gcc/testsuite/g++.dg/reflect/json-parser.C b/gcc/testsuite/g++.dg/reflect/json-parser.C\nnew file mode 100644\nindex 00000000000..6c54bb51704\n--- /dev/null\n+++ b/gcc/testsuite/g++.dg/reflect/json-parser.C\n@@ -0,0 +1,161 @@\n+// PR c++/123613\n+// { dg-do compile { target c++26 } }\n+// { dg-additional-options \"-freflection\" }\n+\n+#include <meta>\n+#include <charconv>\n+#include <string>\n+#include <algorithm>\n+\n+template <std::meta::info ...Ms>\n+struct Outer {\n+    struct Inner;\n+    consteval {\n+        define_aggregate(^^Inner, {Ms...});\n+    }\n+};\n+\n+template <std::meta::info ...Ms>\n+using Cls = Outer<Ms...>::Inner;\n+\n+template <typename T, auto ... Vs>\n+constexpr auto construct_from = T{Vs...};\n+\n+consteval std::meta::info parse_json(std::string_view json) {\n+  auto cursor = json.begin();\n+  auto end = json.end();\n+\n+  auto is_whitespace = [](char c) {\n+    return c == ' ' || c == '\\n' || c == '\\t';\n+  };\n+\n+  auto skip_whitespace = [&] -> void {\n+    while (is_whitespace(*cursor)) cursor++;\n+  };\n+\n+  auto expect_consume = [&] (char c) -> void {\n+    skip_whitespace();\n+    if (cursor == end || *(cursor++) != c) throw \"unexpected character\";\n+  };\n+\n+  auto parse_until = [&](std::vector<char> delims, std::string &out) -> void {\n+    skip_whitespace();\n+    while (cursor != end &&\n+           !std::ranges::any_of(delims, [&](char c) { return c == *cursor; }))\n+      out += *(cursor++);\n+  };\n+\n+  auto parse_delimited = [&](char lhs, std::string &out, char rhs) -> void {\n+    skip_whitespace();\n+    expect_consume(lhs);\n+    parse_until({rhs}, out);\n+    expect_consume(rhs);\n+  };\n+\n+  auto parse_value = [&](std::string &out) -> void {\n+    skip_whitespace();\n+\n+    bool quoted = false;\n+    unsigned depth = 0;\n+    while (true) {\n+      if (cursor == end) throw \"unexpected end of stream\";\n+      if (is_whitespace(*cursor) && !quoted && depth == 0)\n+        break;\n+\n+      if (depth == 0 && (*cursor == ',' || *cursor == '}'))\n+        break;\n+      out += *(cursor++);\n+\n+      if (out.back() == '{')\n+        ++depth;\n+      else if (out.back() == '}')\n+        --depth;\n+      else if (out.back() == '\"') {\n+        if (quoted && depth == 0)\n+          break;\n+        quoted = true;\n+      }\n+    };\n+  };\n+\n+  skip_whitespace();\n+  expect_consume('{');\n+\n+  std::vector<std::meta::info> members;\n+  std::vector<std::meta::info> values = {^^void};\n+\n+  using std::meta::reflect_constant, std::meta::reflect_constant_string;\n+  while (cursor != end && *cursor != '}') {\n+    std::string field_name;\n+    std::string value;\n+\n+    std::meta::info parsed_type;\n+\n+    parse_delimited('\"', field_name, '\"');\n+    expect_consume(':');\n+    parse_value(value);\n+\n+    if (value.empty()) throw \"expected value\";\n+    if (cursor == end) throw \"unexpected end of stream\";\n+\n+    if (value[0] == '\"') {\n+      if (value.back() == '}' && value[1] == 'f') throw \"hmm\";\n+      if (value.back() != '\"') throw \"expected end of string\";\n+      std::string_view contents(&value[1], value.size() - 2);\n+\n+      auto dms = data_member_spec(^^char const*, {.name=field_name});\n+      members.push_back(reflect_constant(dms));\n+      values.push_back(reflect_constant_string(contents));\n+    } else if (value[0] >= '0' && value[0] <= '9') {\n+      int contents = [](std::string_view in) {\n+        int out;\n+        std::from_chars(in.data(), in.data() + in.size(), out);\n+        return out;\n+      }(value);\n+\n+      auto dms = data_member_spec(^^int, {.name=field_name});\n+      members.push_back(reflect_constant(dms));\n+      values.push_back(reflect_constant(contents));\n+    } else if (value[0] == '{') {\n+      std::meta::info parsed = parse_json(value);\n+\n+      auto dms = data_member_spec(type_of(parsed), {.name=field_name});\n+      members.push_back(reflect_constant(dms));\n+      values.push_back(parsed);\n+    }\n+    skip_whitespace();\n+    if (cursor != end && *cursor == ',')\n+      ++cursor;\n+  }\n+  if (cursor == end) throw \"hmm\";\n+  expect_consume('}');\n+\n+  values[0] = substitute(^^Cls, members);\n+  return substitute(^^construct_from, values);\n+}\n+\n+struct JSONString {\n+    std::meta::info Rep;\n+    consteval JSONString(const char *Json) : Rep{parse_json(Json)} {}\n+};\n+\n+template <JSONString json>\n+consteval auto operator\"\"_json() {\n+    return [:json.Rep:];\n+}\n+\n+template <JSONString json>\n+inline constexpr auto json_to_object = [: json.Rep :];\n+\n+constexpr const char data[] = {\n+    #embed \"test.json\"\n+    , 0\n+};\n+\n+int main() {\n+  constexpr auto v = json_to_object<data>;\n+  static_assert(std::string_view(v.outer) == \"text\");\n+  static_assert(v.inner.number == 2996);\n+  static_assert(std::string_view(v.inner.field) == \"yes\");\n+  static_assert(R\"({\"field\": \"yes\", \"number\": 2996})\"_json.number == 2996);\n+}\ndiff --git a/gcc/testsuite/g++.dg/reflect/substitute7.C b/gcc/testsuite/g++.dg/reflect/substitute7.C\nnew file mode 100644\nindex 00000000000..15bacd09371\n--- /dev/null\n+++ b/gcc/testsuite/g++.dg/reflect/substitute7.C\n@@ -0,0 +1,14 @@\n+// PR c++/123613\n+// { dg-do compile { target c++26 } }\n+// { dg-additional-options \"-freflection\" }\n+\n+#include <meta>\n+\n+template <typename T, auto ... Vs>\n+constexpr auto construct_from = T{Vs...};\n+\n+struct Inner {};\n+struct Outer { Inner m; };\n+\n+constexpr auto r = substitute(^^construct_from,\n+                             { ^^Outer, ^^construct_from<Inner> });\ndiff --git a/gcc/testsuite/g++.dg/reflect/test.json b/gcc/testsuite/g++.dg/reflect/test.json\nnew file mode 100644\nindex 00000000000..b95cd80b88e\n--- /dev/null\n+++ b/gcc/testsuite/g++.dg/reflect/test.json\n@@ -0,0 +1,4 @@\n+{ \n+    \"outer\": \"text\", \n+    \"inner\": { \"field\": \"yes\", \"number\": 2996 }\n+} \n",
    "prefixes": [
        "v2"
    ]
}