From patchwork Fri Sep 17 16:15:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Barrett Adair X-Patchwork-Id: 45135 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id BE6BF385700B for ; Fri, 17 Sep 2021 16:16:22 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BE6BF385700B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1631895382; bh=mch0ssEW1KDCam+qA5Q0bFlbpaJ/UorRyUd3F+HQmBg=; h=Date:Subject:To:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=P1BEgw2W5FWQmQIkrul5hHScEpV0IoONE7x8W0MRlhEb/y+/qYFq2wOBwus0iYA2Q a305fR469igl+SzyPlYol1Qx9kxR1JhEyEhbfBwkM/3tGhOv5bIy0v9ubL1cHbRO9S VyEziAqmdJ/7npysFsEd8s7y9zx6hyMbn/bAu2vE= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-qk1-x731.google.com (mail-qk1-x731.google.com [IPv6:2607:f8b0:4864:20::731]) by sourceware.org (Postfix) with ESMTPS id 69A073858D29 for ; Fri, 17 Sep 2021 16:15:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 69A073858D29 Received: by mail-qk1-x731.google.com with SMTP id t4so19024328qkb.9 for ; Fri, 17 Sep 2021 09:15:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:from:date:message-id:subject:to:cc; bh=VdUvDRRHUUfxkYZOK3i7L9MPcfBoIu8qSr7OqaiK6+k=; b=y/B9A1JQUwZud1bHiTfOqKEMoVZaYo/bezcwB1AUD+uhzNZloidO8viLaFN5CNHecQ Ql4URgWfU3Nd21ujhGO9mdKYnF/6tkCxEalr8ujo8bOacklp0BPxOGQZq6tEkLlIAbcp sQfVdERLqnVbBT7iJkzskhZMcAThGSspWx1O3GwYUAKM1R1M4Sp/gPNbYN265BF8FfJ2 ZQBgr/rVuLTLhpnQOLXO2ydvGc7TZlYlw8XrPgfbZr5ruFqA2hRRJWjlCb+KXOpAXmrM oxY5nPn8EYptE4/p6oTkyfM1LY6DKyHHiMd5Z+qVroXJK9D/JnYtuPQiUl8yNdQgKnMZ 29+Q== X-Gm-Message-State: AOAM533LTlwsFs0/xOG+/oGtcujaWPv8cCC3XR0eGn4ljr0+ypoviQbY b2tCyU3Kj0SAB/1Ze237pbqaL5iUdmVyypZ4zq2sRPU/P9Y= X-Google-Smtp-Source: ABdhPJwkX8yz3xZVx8I6DNdzbpsdwLI+bY18k9bqxEZAD3XUxJMgA3W6FARBxU27oJ5XaLpglYmOe6FKi9p8pcAUHpw= X-Received: by 2002:a05:620a:2906:: with SMTP id m6mr11512778qkp.190.1631895351801; Fri, 17 Sep 2021 09:15:51 -0700 (PDT) MIME-Version: 1.0 Date: Fri, 17 Sep 2021 11:15:41 -0500 Message-ID: Subject: [RFC] c++: Allow parm use outside function body for constexpr members To: gcc-patches@gcc.gnu.org X-Spam-Status: No, score=-9.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, HTML_MESSAGE, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Barrett Adair via Gcc-patches From: Barrett Adair Reply-To: Barrett Adair Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" The WIP attached patch attempts to enable usage of parameters' constexpr members before the function body begins (see new tests dependent-expr11.C and dependent-expr12.C). Unfortunately, I hit a "vexing" snag: gcc/testsuite/g++.dg/parse/ambig7.C breaks with this patch. After several hours of debugging, here's what I think happens: In trunk, ambig7.C's testFail line compiles because the tentative parse -- where "testFail" is a function and int(A) is a parameter type -- fails only when seeing that function uses "parameter outside function body" (the error removed by this patch). This occurs when parsing the template argument list, before calling finish_template_type. After applying the patch, the tentative parse still fails because function is not a type, but this only occurs after finish_template_type is called, which causes the incorrect template-id for function to be cached with broken arguments, such that function remains "unresolved overloaded function type": ambig7.C:16:36: error: no matching function for call to ‘Helper::Helper(int, )’ 16 | Helper testFail(int(A), function); Any suggestions on how to go about fixing this? For instance, is it possible to repair or roll back the cached template instantation? From 609cbe53b758afaf344f6798be776cce0d00a3fa Mon Sep 17 00:00:00 2001 From: Barrett Adair Date: Fri, 17 Sep 2021 10:46:46 -0500 Subject: [PATCH] Allow parm use outside function body for constexpr members --- gcc/cp/pt.c | 11 +++++++---- gcc/cp/semantics.c | 13 ++----------- gcc/testsuite/g++.dg/cpp0x/noexcept34.C | 2 +- .../g++.dg/parse/parameter-declaration-2.C | 2 +- gcc/testsuite/g++.dg/template/dependent-expr11.C | 6 ++++++ gcc/testsuite/g++.dg/template/dependent-expr12.C | 10 ++++++++++ gcc/testsuite/g++.dg/template/memfriend19.C | 12 ++++++++++++ gcc/testsuite/g++.dg/template/memfriend20.C | 11 +++++++++++ 8 files changed, 50 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/dependent-expr11.C create mode 100644 gcc/testsuite/g++.dg/template/dependent-expr12.C create mode 100644 gcc/testsuite/g++.dg/template/memfriend19.C create mode 100644 gcc/testsuite/g++.dg/template/memfriend20.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 12c8812d8b2..3e864c9fd8e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -15133,9 +15133,13 @@ tsubst_function_type (tree t, inject_this_parameter (this_type, cp_type_quals (this_type)); } + begin_scope (sk_function_parms, in_decl); + /* Substitute the return type. */ return_type = tsubst (TREE_TYPE (t), args, complain, in_decl); + finish_scope (); + if (do_inject) { current_class_ptr = save_ccp; @@ -16594,10 +16598,9 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (DECL_NAME (t) == this_identifier && current_class_ptr) return current_class_ptr; - /* This can happen for a parameter name used later in a function - declaration (such as in a late-specified return type). Just - make a dummy decl, since it's only used for its type. */ - gcc_assert (cp_unevaluated_operand != 0); + gcc_assert (cp_unevaluated_operand != 0 + || current_binding_level->kind == sk_function_parms); + r = tsubst_decl (t, args, complain); /* Give it the template pattern as its context; its true context hasn't been instantiated yet and this is good enough for diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 35a7b9f7b83..d0987166361 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3742,7 +3742,8 @@ outer_var_p (tree decl) && DECL_FUNCTION_SCOPE_P (decl) /* Don't get confused by temporaries. */ && DECL_NAME (decl) - && (DECL_CONTEXT (decl) != current_function_decl + && ((current_function_decl != NULL + && DECL_CONTEXT (decl) != current_function_decl) || parsing_nsdmi ())); } @@ -4002,16 +4003,6 @@ finish_id_expression_1 (tree id_expression, if (decl == error_mark_node) return error_mark_node; } - - /* Also disallow uses of function parameters outside the function - body, except inside an unevaluated context (i.e. decltype). */ - if (TREE_CODE (decl) == PARM_DECL - && DECL_CONTEXT (decl) == NULL_TREE - && !cp_unevaluated_operand) - { - *error_msg = G_("use of parameter outside function body"); - return error_mark_node; - } } /* If we didn't find anything, or what we found was a type, diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept34.C b/gcc/testsuite/g++.dg/cpp0x/noexcept34.C index dce35652ef5..822a8597f63 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept34.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept34.C @@ -10,7 +10,7 @@ template struct A void g () noexcept (f()) { } // { dg-error "use of parameter" } void g2 () noexcept (this->f()) { } // { dg-error "use of parameter" } void g3 () noexcept (b) { } // { dg-error "use of .this. in a constant expression|use of parameter" } - void g4 (int i) noexcept (i) { } // { dg-error "use of parameter" } + void g4 (int i) noexcept (i) { } // { dg-error "use of parameter|not a constant expression" } void g5 () noexcept (A::f()) { } // { dg-error "use of parameter" } void g6 () noexcept (foo(b)) { } // { dg-error "use of .this. in a constant expression|use of parameter" } void g7 () noexcept (int{f()}) { } // { dg-error "use of parameter" } diff --git a/gcc/testsuite/g++.dg/parse/parameter-declaration-2.C b/gcc/testsuite/g++.dg/parse/parameter-declaration-2.C index 3c983cc748c..236cda7e3be 100644 --- a/gcc/testsuite/g++.dg/parse/parameter-declaration-2.C +++ b/gcc/testsuite/g++.dg/parse/parameter-declaration-2.C @@ -1,2 +1,2 @@ -void f (int i, int p[i]); // { dg-error "use of parameter.*outside function body" } +void f (int i, int p[i]); // { dg-error "use of parameter.*outside function body|integral constant" } // { dg-prune-output "array bound" } diff --git a/gcc/testsuite/g++.dg/template/dependent-expr11.C b/gcc/testsuite/g++.dg/template/dependent-expr11.C new file mode 100644 index 00000000000..d1fa63fc792 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/dependent-expr11.C @@ -0,0 +1,6 @@ +// { dg-do compile { target c++11 } } +template struct bool_c{ static constexpr bool value = u; }; +struct foo { constexpr bool operator()() const { return true; } }; +template auto bar(T t) -> bool_c; +template auto bar(T t) -> bool_c; +static_assert(decltype(bar(foo{}))::value, ""); diff --git a/gcc/testsuite/g++.dg/template/dependent-expr12.C b/gcc/testsuite/g++.dg/template/dependent-expr12.C new file mode 100644 index 00000000000..1ebc132f7d9 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/dependent-expr12.C @@ -0,0 +1,10 @@ +// { dg-do compile { target c++14 } } +template +struct foo { + constexpr operator int() { return i; } +}; +void bar() { + [](auto i) -> foo { + return {}; + }; +} diff --git a/gcc/testsuite/g++.dg/template/memfriend19.C b/gcc/testsuite/g++.dg/template/memfriend19.C new file mode 100644 index 00000000000..b33d11dc10d --- /dev/null +++ b/gcc/testsuite/g++.dg/template/memfriend19.C @@ -0,0 +1,12 @@ +// { dg-do compile { target c++11 } } +template +struct foo { + auto operator()(T t) -> decltype(t->v); +}; + +class bar { + friend struct foo; + int v; +}; + +decltype(foo{}(nullptr)) x; diff --git a/gcc/testsuite/g++.dg/template/memfriend20.C b/gcc/testsuite/g++.dg/template/memfriend20.C new file mode 100644 index 00000000000..42373abacc7 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/memfriend20.C @@ -0,0 +1,11 @@ +// { dg-do compile { target c++11 } } +template +struct foo { + auto operator()(T t) -> decltype(t->v); // { dg-error "private" } +}; + +class bar { + int v; +}; + +decltype(foo{}(nullptr)) x; -- 2.30.2