Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2215606/?format=api
{ "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" ] }