From patchwork Fri Nov 17 21:46:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 166402 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:9910:0:b0:403:3b70:6f57 with SMTP id i16csp832376vqn; Fri, 17 Nov 2023 13:47:04 -0800 (PST) X-Google-Smtp-Source: AGHT+IEkBLdrU/WFMUCvLgAxRowpPtYj7i8RaCWMfbnIC7R7mqf7X4exGdnEAsAocp5mt36TzoiL X-Received: by 2002:a05:6102:53c9:b0:462:7763:342a with SMTP id bs9-20020a05610253c900b004627763342amr647738vsb.32.1700257624020; Fri, 17 Nov 2023 13:47:04 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1700257624; cv=pass; d=google.com; s=arc-20160816; b=o0YJzBgWSUUI7S9mJmGSC6pWxTlv5aAIS+T1LU9DAlVJ3yb9qKFzt9X2JQl9V9A1mv 3y0FfpJxahoZ4JOgeizaAyGw0u1f7YebYrL53AQhdDStJkljw+LeFkVDUVDqrauRYkXp 56EJOtsI/tjUouP7V4pY8Gf96mPq5PJFPAvArvn+RG90f+MORS0iboqS7JrxN16j7Y0B wIbPnMHK81LTJRV1fIQt7kfzlHBZ8fITXFgYsnqVUz4oY3zv+ZwWTO4FER12nqNBZ9py avFnDUmZfoM4JSFa0jDGJpKw5PJEVOyCWKaMY1J4D+ElpXsZGM932LJXutokC4wsuLQW BvfA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:to:from:dkim-signature :arc-filter:dmarc-filter:delivered-to; bh=1IMUtIB5Wwp1Os/vDGeOjiiFewt8nPQIwxQpWs8Kxn4=; fh=2BFo3VQCimnyWTJsWe6sNdepvNrW+J/2ctoM6N7MZ0Y=; b=ynxm5nzFr46l2hcEwj9t62FS8HPf2Yl6FgpiiSFjlLaCwJnaplkQwxMurF0E562ZQR Uz7/LoYGKUaifl6/n0DFODJ7N4LS6pNRpeq6p2kEkHaHIX/F8UkUstbwOrDG4uXKIEo/ KOYDx5byQFutKlmq4fp7bw1K9hFw3bqVR+qvxlpeFUG38bJkNy8HCdPhuu/bTOE14Obu 9DnmzrDgzcA6EM42xIVaJAdbVTWvmlnBIIg8n1QbnAV7yfqIGoHCXLLBK6AU5PhzoJxx 1RJTT0FiCQQvjADFHmNGiX7bxbLCXisKvlaUmfzHIpbLJsQDmI/xHJ4/YF5tmRtBqSC3 U6yw== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=gdz4uujq; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id hu6-20020a056214234600b0066d0819ca14si2726343qvb.380.2023.11.17.13.47.03 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Nov 2023 13:47:03 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=gdz4uujq; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C40F13857BB6 for ; Fri, 17 Nov 2023 21:47:03 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 397353858D39 for ; Fri, 17 Nov 2023 21:46:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 397353858D39 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 397353858D39 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700257599; cv=none; b=pXvvnt7Jfve0hnsmSLARZyplPyFYcEFvW3pvcmRHMQh2+sGVa4j1KpaTSQT9FoHR0x8Rm+zETSsaBRoNveN+6XV7cpWbIZ/cO9ti+93dWPzaY3sIG+v1oHhLOIbl902kmWtVd2Mb+44dCNgrqKwvsppnloX7OrQ0NnPDpRGLht8= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700257599; c=relaxed/simple; bh=JZefUKUynYz+3+eLgQ/7/S2dXhqBlqmURni3qY27H8Q=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=noDD0l17AH+/+u5w6aRMTtmkt97A3uaCnmTtZNLnXoCrCyD3mlpaP1Z5vtSTxKVP0elX9Bqvgur5XhCM+Nvjc39GA42bOYqxV7dn8rV1gdquOvy3iK/yS3QsDDLaLcAuPqrcvKQJTMNi+cvZkwclWbg8ninpCWbyG5l0+3kIQQA= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1700257588; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=1IMUtIB5Wwp1Os/vDGeOjiiFewt8nPQIwxQpWs8Kxn4=; b=gdz4uujqoFC0D+oB2YRsAKXUyQcZqGhaLQyoHVue3oDYZ+gkWcitlUSYHOugTZbdPZKZZB yxpN6y3y4iZsIhzF5yiNnhx1LSY9YgW0TzmzaHRM2OnkckD2r25lXjXzyD7+UU5GZap0xC P3YYzkMxFHeW6sk7gIolp4lT82tSJHk= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-387-2hH9br9wOOOkg_FJ_sLX4g-1; Fri, 17 Nov 2023 16:46:17 -0500 X-MC-Unique: 2hH9br9wOOOkg_FJ_sLX4g-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 72EF58527A8 for ; Fri, 17 Nov 2023 21:46:17 +0000 (UTC) Received: from pdp-11.redhat.com (unknown [10.22.10.120]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4CB3740C6EB9; Fri, 17 Nov 2023 21:46:17 +0000 (UTC) From: Marek Polacek To: GCC Patches , Jason Merrill Subject: [PATCH] c++: P2280R4, Using unknown refs in constant expr [PR106650] Date: Fri, 17 Nov 2023 16:46:10 -0500 Message-ID: <20231117214610.173872-1-polacek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1782849338216461048 X-GMAIL-MSGID: 1782849338216461048 Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? -- >8 -- This patch is an attempt to implement (part of?) P2280, Using unknown pointers and references in constant expressions. (Note that R4 seems to only allow References to unknown/Accesses via this, but not Pointers to unknown.) This patch works to the extent that the test case added in [expr.const] works as expected, as well as the test in Most importantly, the proposal makes this compile: template constexpr auto array_size(T (&)[N]) -> size_t { return N; } void check(int const (¶m)[3]) { constexpr auto s = array_size(param); static_assert (s == 3); } and I think it would be a pity not to have it in GCC 14. What still doesn't work (and I don't know if it should) is the test in $3.2: struct A2 { constexpr int f() { return 0; } }; struct B2 : virtual A2 {}; void f2(B2 &b) { constexpr int k = b.f(); } where we say error: '* & b' is not a constant expression PR c++/106650 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_constant_expression): Allow reference to unknown as per P2280. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/constexpr-array-ptr6.C: Remove dg-error. * g++.dg/cpp0x/constexpr-ref12.C: Likewise. * g++.dg/cpp1y/lambda-generic-const10.C: Likewise. * g++.dg/cpp0x/constexpr-ref13.C: New test. * g++.dg/cpp1z/constexpr-ref1.C: New test. * g++.dg/cpp1z/constexpr-ref2.C: New test. * g++.dg/cpp2a/constexpr-ref1.C: New test. --- gcc/cp/constexpr.cc | 2 + .../g++.dg/cpp0x/constexpr-array-ptr6.C | 2 +- gcc/testsuite/g++.dg/cpp0x/constexpr-ref12.C | 4 +- gcc/testsuite/g++.dg/cpp0x/constexpr-ref13.C | 25 +++++++++ .../g++.dg/cpp1y/lambda-generic-const10.C | 2 +- gcc/testsuite/g++.dg/cpp1z/constexpr-ref1.C | 26 +++++++++ gcc/testsuite/g++.dg/cpp1z/constexpr-ref2.C | 23 ++++++++ gcc/testsuite/g++.dg/cpp2a/constexpr-ref1.C | 54 +++++++++++++++++++ 8 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-ref13.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-ref1.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-ref2.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-ref1.C base-commit: 231bb992592a9e1bd7ce6583131acb1874c8e34e diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 344107d494b..d5e487801cc 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -7378,6 +7378,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, r = build_constructor (TREE_TYPE (t), NULL); TREE_CONSTANT (r) = true; } + else if (TYPE_REF_P (TREE_TYPE (t))) + /* P2280 allows references to unknown. */; else { if (!ctx->quiet) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C index 1c065120314..d212665e51f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C @@ -12,7 +12,7 @@ constexpr auto sz_d = size(array_double); static_assert(sz_d == 3, "Array size failure"); void f(bool (¶m)[2]) { - static_assert(size(param) == 2, "Array size failure"); // { dg-error "" } + static_assert(size(param) == 2, "Array size failure"); short data[] = {-1, 2, -45, 6, 88, 99, -345}; static_assert(size(data) == 7, "Array size failure"); } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref12.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref12.C index 7c3ce66b4c9..f4500144946 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref12.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref12.C @@ -40,7 +40,7 @@ void f(a ap, a& arp) static_assert (g(ar2),""); // { dg-error "constant" } static_assert (h(ar2),""); // { dg-error "constant" } - static_assert (arp.g(),""); // { dg-error "constant" } - static_assert (g(arp),""); // { dg-error "constant" } + static_assert (arp.g(),""); + static_assert (g(arp),""); static_assert (h(arp),""); // { dg-error "constant" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref13.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref13.C new file mode 100644 index 00000000000..4be729c2301 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref13.C @@ -0,0 +1,25 @@ +// P2280R4 - Using unknown pointers and references in constant expressions +// PR c++/106650 +// { dg-do compile { target c++11 } } + +using size_t = decltype(sizeof(42)); + +template +constexpr auto array_size(T (&)[N]) -> size_t { + return N; +} + +void check(int const (¶m)[3]) { + int local[] = {1, 2, 3}; + constexpr auto s0 = array_size(local); + constexpr auto s1 = array_size(param); +} + +template +constexpr size_t array_size_ptr(T (*)[N]) { + return N; +} + +void check_ptr(int const (*param)[3]) { + constexpr auto s2 = array_size_ptr(param); // { dg-error "not a constant" } +} diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const10.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const10.C index 2f48dae4746..47a49f58419 100644 --- a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const10.C +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const10.C @@ -11,7 +11,7 @@ int main() constexpr auto x = f(); //ok, call constexpr const non-static method [](auto const &f) { - constexpr auto x = f(); // { dg-error "" } + constexpr auto x = f(); }(f); [&]() { diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-ref1.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-ref1.C new file mode 100644 index 00000000000..82771814a80 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-ref1.C @@ -0,0 +1,26 @@ +// P2280R4 - Using unknown pointers and references in constant expressions +// PR c++/106650 +// { dg-do compile { target c++17 } } + +#include + +template +constexpr bool is_type(U &&) +{ + return std::is_same_v>; +} + +auto visitor = [](auto&& v) { + if constexpr(is_type(v)) { + // ... + } else if constexpr(is_type(v)) { + // ... + } +}; + +void +g (int i) +{ + visitor (i); + constexpr bool b = is_type(i); +} diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-ref2.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-ref2.C new file mode 100644 index 00000000000..ca734378141 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-ref2.C @@ -0,0 +1,23 @@ +// P2280R4 - Using unknown pointers and references in constant expressions +// PR c++/106650 +// { dg-do compile { target c++17 } } + +template +struct Widget { + struct Config { + static constexpr bool value = V; + } config; + + void f() { + if constexpr (config.value) { + // ... + } + } +}; + +void +g () +{ + Widget w; + w.f(); +} diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-ref1.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-ref1.C new file mode 100644 index 00000000000..36866306684 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-ref1.C @@ -0,0 +1,54 @@ +// P2280R4 - Using unknown pointers and references in constant expressions +// PR c++/106650 +// { dg-do compile { target c++20 } } + +#include + +using size_t = decltype(sizeof(42)); + +template +constexpr size_t array_size(T (&)[N]) { + return N; +} + +void use_array(int const (&gold_medal_mel)[2]) { + constexpr auto gold = array_size(gold_medal_mel); // OK +} + +constexpr auto olympic_mile() { + const int ledecky = 1500; + return []{ return ledecky; }; +} +static_assert(olympic_mile()() == 1500); // OK + +struct Swim { + constexpr int phelps() { return 28; } + virtual constexpr int lochte() { return 12; } + int coughlin = 12; +}; + +constexpr int how_many(Swim& swam) { + Swim* p = &swam; + return (p + 1 - 1)->phelps(); +} + +void splash(Swim& swam) { + static_assert(swam.phelps() == 28); // OK + static_assert((&swam)->phelps() == 28); // OK + + Swim* pswam = &swam; + static_assert(pswam->phelps() == 28); // { dg-error "non-constant|not usable" } + + static_assert(how_many(swam) == 28); // OK + static_assert(Swim().lochte() == 12); // OK + + static_assert(swam.lochte() == 12); // { dg-error "non-constant|not a constant" } + + static_assert(swam.coughlin == 12); // { dg-error "non-constant|not a constant" } +} + +extern Swim dc; +extern Swim& trident; + +constexpr auto& sandeno = typeid(dc); // OK, can only be typeid(Swim) +constexpr auto& gallagher = typeid(trident); // { dg-error "not usable" }