From patchwork Thu Apr 4 23:15:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 88063 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 5C03A384645B for ; Thu, 4 Apr 2024 23:15:55 +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 338023858C98 for ; Thu, 4 Apr 2024 23:15:23 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 338023858C98 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 338023858C98 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=1712272525; cv=none; b=Y0WHlXjEtJWqPJ+bYz3MkHG1bdqM2+zWEtt606b4LU2MFQex4hkfm5P4lAP8TcvjJbjyVl4lfmNR446uuZMrnB2He6ohulcJ5HMinSN36Uy57zLUmGMpm9P0aGU33k49P9xhMszyACNFnrQOhWhPNx00IDSCmvpvSiSYDGrsiWg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1712272525; c=relaxed/simple; bh=XFOE+f/NPksmwvGYX0pm+I1IeXa7byvct5KM4MAy6ZI=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=w+wLFo3dBk6+UjH8qKTjL1is8BWwmFPycw6XqMBqibsa4SGjxPKOTSYFusySsXdIe+3qAtxR+TcoYS/srIg2DTWoX1aZecM8xUR5oWo7Uht6qAr+tciBjBqO8rINeJ/6hrnh1fDQpwKqHKEAyduKKEZ9+CnUemSY0dKSnnq1itw= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712272522; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=aquhg7zMU7ZphuF1X72xRdGoiMSQJcaZL/JGtuj34Jc=; b=g5yx/+RS3Oj46+t9uuF3QBjyJIw54WLhpvA2/1EMXn8B/gsPlIHkODFa+FSrQ7L6+2pMCp xJiHgzQFyCV80G6RhPelROdl4JZJht+T59VwwDZKBNohDLejp0r7LFGASQR6qp+vo5RWPl G9M1gUv9ttArGQdN51kM9WPIFk4gvn0= Received: from mail-qv1-f71.google.com (mail-qv1-f71.google.com [209.85.219.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-441-N8hchlOfMj6eZackRfltNw-1; Thu, 04 Apr 2024 19:15:21 -0400 X-MC-Unique: N8hchlOfMj6eZackRfltNw-1 Received: by mail-qv1-f71.google.com with SMTP id 6a1803df08f44-69929513885so37141446d6.1 for ; Thu, 04 Apr 2024 16:15:20 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712272520; x=1712877320; h=user-agent:in-reply-to:content-disposition:mime-version:references :message-id:subject:cc:to:from:date:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=aquhg7zMU7ZphuF1X72xRdGoiMSQJcaZL/JGtuj34Jc=; b=WtYlpmyOq9uXLm+sLRo3AFRf7BndIwgBc+t+vDsBnqpChesKgU0s0FGAgx9aDZLOe8 Eu9cdhDFR0Kv1qkkBP/pKGrUP0i44q4N3FDqcATuC3aX9myKdj0rbW+17XrlGQhpgcwb fJsXLpQqoFR3oCP9JhgE6CqPZll1rYBJodEv6csJl/f1vuwWT0tPm8wRETxEjUyQOWgB JTmbPrI7XS7vW+3biGcQ8QlKxE38MIGm3zYgh5mO0PgCTrt6kbB/+PfL5S0kg40hDl6u J0aBo7+GysHK3Iu+5niYHSbaUVO+ey3Afq9lW8WpMOgkKbX5FkcvGNUIglpwCI2yrGxx LOLg== X-Gm-Message-State: AOJu0YwjlGi/6/gchIU79ekr/FvqssnQUMrIqrzwPPegDrIKDc6zPJos hGrxeZuOuOR3vkqfDtFjOnJ95WJRynAAjsjgPlXmgEddKhuF55eI50V/lmheOomNrS1GbNmvD23 nbACnBuY2EHfTggW4Bj+pQJ2nCQh49PjSb75CelCI6V+lAZk01P7pUZs= X-Received: by 2002:ad4:5ba6:0:b0:691:4d1f:6a65 with SMTP id 6-20020ad45ba6000000b006914d1f6a65mr1720090qvq.27.1712272520458; Thu, 04 Apr 2024 16:15:20 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHIv0r6cp53LcofV2ANsSbZGzhtcSxGCUhy+1sZaMmm8NmLNsVObRexEmnOqpzbXLB9IR+h6Q== X-Received: by 2002:ad4:5ba6:0:b0:691:4d1f:6a65 with SMTP id 6-20020ad45ba6000000b006914d1f6a65mr1720053qvq.27.1712272520050; Thu, 04 Apr 2024 16:15:20 -0700 (PDT) Received: from redhat.com (2603-7000-9500-34a5-0000-0000-0000-1db4.res6.spectrum.com. [2603:7000:9500:34a5::1db4]) by smtp.gmail.com with ESMTPSA id n14-20020ad444ae000000b006987540b47esm152325qvt.64.2024.04.04.16.15.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Apr 2024 16:15:19 -0700 (PDT) Date: Thu, 4 Apr 2024 19:15:17 -0400 From: Marek Polacek To: Jason Merrill Cc: GCC Patches , Jakub Jelinek Subject: [PATCH v2] c++: constexpr error with fn redecl in local scope [PR111132] Message-ID: References: <20240402175237.482119-1-polacek@redhat.com> <0a3fe0db-9466-478b-bd4f-2957863b585c@redhat.com> MIME-Version: 1.0 In-Reply-To: <0a3fe0db-9466-478b-bd4f-2957863b585c@redhat.com> User-Agent: Mutt/2.2.12 (2023-09-09) X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-11.5 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, RCVD_IN_SORBS_WEB, SPF_HELO_NONE, SPF_NONE, TXREP 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+patchwork=sourceware.org@gcc.gnu.org On Thu, Apr 04, 2024 at 05:28:22PM -0400, Jason Merrill wrote: > On 4/4/24 14:43, Marek Polacek wrote: > > On Wed, Apr 03, 2024 at 01:14:46PM -0400, Jason Merrill wrote: > > > On 4/2/24 13:52, Marek Polacek wrote: > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/13? > > > > > > > > -- >8 -- > > > > We evaluate constexpr functions on the original, pre-genericization bodies. > > > > That means that the function body we're evaluating will not have gone > > > > through cp_genericize_r's "Map block scope extern declarations to visible > > > > declarations with the same name and type in outer scopes if any". Here: > > > > > > > > constexpr bool bar() { return true; } // #1 > > > > constexpr bool foo() { > > > > constexpr bool bar(void); // #2 > > > > return bar(); > > > > } > > > > > > > > it means that we: > > > > 1) register_constexpr_fundef (#1) > > > > 2) cp_genericize (#1) > > > > nothing interesting happens > > > > 3) register_constexpr_fundef (foo) > > > > does copy_fn, so we have two copies of the BIND_EXPR > > > > 4) cp_genericize (foo) > > > > this remaps #2 to #1, but only on one copy of the BIND_EXPR > > > > 5) retrieve_constexpr_fundef (foo) > > > > we find it, no problem > > > > 6) retrieve_constexpr_fundef (#2) > > > > and here #2 isn't found in constexpr_fundef_table, because > > > > we're working on the BIND_EXPR copy where #2 wasn't mapped to #1 > > > > so we fail. We've only registered #1. > > > > > > > > It should work to use DECL_LOCAL_DECL_ALIAS (which used to be > > > > extern_decl_map). We evaluate constexpr functions on pre-cp_fold > > > > bodies to avoid diagnostic problems, but the remapping I'm proposing > > > > should not interfere with diagnostics. > > > > > > > > This is not a problem for a global scope redeclaration; there we go > > > > through duplicate_decls which keeps the DECL_UID: > > > > DECL_UID (olddecl) = olddecl_uid; > > > > and DECL_UID is what constexpr_fundef_hasher::hash uses. > > > > > > > > PR c++/111132 > > > > > > > > gcc/cp/ChangeLog: > > > > > > > > * constexpr.cc (get_function_named_in_call): If there's > > > > a DECL_LOCAL_DECL_ALIAS, use it. > > > > > > Perhaps this function should use cp_get_fndecl_from_callee, and this change > > > should be made there instead? > > > > It doesn't seem that get_function_named_in_call can use cp_get_fndecl_from_callee, > > (or be replaced with cp_get_callee_fndecl_nofold). We can get e.g. a CALL_EXPR > > whose CALL_EXPR_FN is a TEMPLATE_ID_EXPR, and get_function_named_in_call > > returns the TEMPLATE_ID_EXPR whereas cp_get_fndecl_from_callee would return > > null: > > > > if (TREE_CODE (fn) == FUNCTION_DECL) > > return fn; > > tree type = TREE_TYPE (fn); > > if (type == NULL_TREE || !INDIRECT_TYPE_P (type)) > > return NULL_TREE; > > Why couldn't this function use cp_get_fndecl_from_callee and return the > original argument if that function returns null? It could. (The lambda below could have been a goto but either should be fine.) Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/13? -- >8 -- We evaluate constexpr functions on the original, pre-genericization bodies. That means that the function body we're evaluating will not have gone through cp_genericize_r's "Map block scope extern declarations to visible declarations with the same name and type in outer scopes if any". Here: constexpr bool bar() { return true; } // #1 constexpr bool foo() { constexpr bool bar(void); // #2 return bar(); } it means that we: 1) register_constexpr_fundef (#1) 2) cp_genericize (#1) nothing interesting happens 3) register_constexpr_fundef (foo) does copy_fn, so we have two copies of the BIND_EXPR 4) cp_genericize (foo) this remaps #2 to #1, but only on one copy of the BIND_EXPR 5) retrieve_constexpr_fundef (foo) we find it, no problem 6) retrieve_constexpr_fundef (#2) and here #2 isn't found in constexpr_fundef_table, because we're working on the BIND_EXPR copy where #2 wasn't mapped to #1 so we fail. We've only registered #1. It should work to use DECL_LOCAL_DECL_ALIAS (which used to be extern_decl_map). We evaluate constexpr functions on pre-cp_fold bodies to avoid diagnostic problems, but the remapping I'm proposing should not interfere with diagnostics. This is not a problem for a global scope redeclaration; there we go through duplicate_decls which keeps the DECL_UID: DECL_UID (olddecl) = olddecl_uid; and DECL_UID is what constexpr_fundef_hasher::hash uses. PR c++/111132 gcc/cp/ChangeLog: * constexpr.cc (get_function_named_in_call): Use cp_get_fndecl_from_callee. * cvt.cc (cp_get_fndecl_from_callee): If there's a DECL_LOCAL_DECL_ALIAS, use it. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/constexpr-redeclaration3.C: New test. * g++.dg/cpp0x/constexpr-redeclaration4.C: New test. --- gcc/cp/constexpr.cc | 10 ++++------ gcc/cp/cvt.cc | 18 ++++++++++++++++-- .../g++.dg/cpp0x/constexpr-redeclaration3.C | 13 +++++++++++++ .../g++.dg/cpp0x/constexpr-redeclaration4.C | 14 ++++++++++++++ 4 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration3.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration4.C base-commit: 27b6d081f68528435066be2234c7329e31e0e84f diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index fa346fe01c9..410ccdf597f 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -702,16 +702,14 @@ build_constexpr_constructor_member_initializers (tree type, tree body) /* We have an expression tree T that represents a call, either CALL_EXPR or AGGR_INIT_EXPR. If the call is lexically to a named function, - retrun the _DECL for that function. */ + return the _DECL for that function. */ static tree get_function_named_in_call (tree t) { - tree fun = cp_get_callee (t); - if (fun && TREE_CODE (fun) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (fun, 0)) == FUNCTION_DECL) - fun = TREE_OPERAND (fun, 0); - return fun; + tree callee = cp_get_callee (t); + tree fun = cp_get_fndecl_from_callee (callee, /*fold*/false); + return fun ? fun : callee; } /* Subroutine of check_constexpr_fundef. BODY is the body of a function diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc index cbed847b343..db086c017e8 100644 --- a/gcc/cp/cvt.cc +++ b/gcc/cp/cvt.cc @@ -1001,8 +1001,22 @@ cp_get_fndecl_from_callee (tree fn, bool fold /* = true */) { if (fn == NULL_TREE) return fn; + + /* We evaluate constexpr functions on the original, pre-genericization + bodies. So block-scope extern declarations have not been mapped to + declarations in outer scopes. Use the namespace-scope declaration, + if any, so that retrieve_constexpr_fundef can find it (PR111132). */ + auto fn_or_local_alias = [] (tree f) + { + if (DECL_LOCAL_DECL_P (f)) + if (tree alias = DECL_LOCAL_DECL_ALIAS (f)) + if (alias != error_mark_node) + return alias; + return f; + }; + if (TREE_CODE (fn) == FUNCTION_DECL) - return fn; + return fn_or_local_alias (fn); tree type = TREE_TYPE (fn); if (type == NULL_TREE || !INDIRECT_TYPE_P (type)) return NULL_TREE; @@ -1013,7 +1027,7 @@ cp_get_fndecl_from_callee (tree fn, bool fold /* = true */) || TREE_CODE (fn) == FDESC_EXPR) fn = TREE_OPERAND (fn, 0); if (TREE_CODE (fn) == FUNCTION_DECL) - return fn; + return fn_or_local_alias (fn); return NULL_TREE; } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration3.C new file mode 100644 index 00000000000..2b41b456fc3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration3.C @@ -0,0 +1,13 @@ +// PR c++/111132 +// { dg-do compile { target c++11 } } + +constexpr bool bar(void) { + return true; +} + +constexpr bool foo() { + constexpr bool bar(void); + return bar(); +} + +static_assert(foo(), ""); diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration4.C new file mode 100644 index 00000000000..c58247218c6 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration4.C @@ -0,0 +1,14 @@ +// PR c++/111132 +// { dg-do compile { target c++11 } } + +constexpr bool bar(void) { + return true; +} + +constexpr bool bar(void); + +constexpr bool foo() { + return bar(); +} + +static_assert(foo(), "");