From patchwork Wed Jul 14 15:26:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 1505301 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=O7/bQME+; dkim-atps=neutral Received: from sourceware.org (ip-8-43-85-97.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GQ1b62Fkjz9sRf for ; Thu, 15 Jul 2021 01:27:29 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 85DFC3985808 for ; Wed, 14 Jul 2021 15:27:26 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 85DFC3985808 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1626276446; bh=V/Gp2Vu+pTZeLGhZBKa5z9KVee7/xziD4m+r94/nN0o=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=O7/bQME+ibTdfW80NW8Lxh4mAVSje0LnMZu6lM0Z9UEmSE4fxaIeyqrCHj9GtT2h6 DCX2/NibabrfFTyTPnDiepc7A0Zh5GvBP+tdUNzODJ28U0FuBPCoAWwMuc5Ycqj/RF QS1ndzn9KdTpVPSAeTtxydCAxsHiFzxoeQ4YxMg4= 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.133.124]) by sourceware.org (Postfix) with ESMTP id 8CC08385043E for ; Wed, 14 Jul 2021 15:27:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8CC08385043E Received: from mail-qt1-f197.google.com (mail-qt1-f197.google.com [209.85.160.197]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-580-cAfjwqRNNc2NdVV0-TwdGg-1; Wed, 14 Jul 2021 11:27:03 -0400 X-MC-Unique: cAfjwqRNNc2NdVV0-TwdGg-1 Received: by mail-qt1-f197.google.com with SMTP id v16-20020a05622a0150b029025a2609eb04so2102151qtw.17 for ; Wed, 14 Jul 2021 08:27:03 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=V/Gp2Vu+pTZeLGhZBKa5z9KVee7/xziD4m+r94/nN0o=; b=KOeUr/aF3rC5GzFnHg3qbjwIAdsBVDfEf7RJV945Vbq4rCo5XGStuVJANMhFwLhZ7S IbsjHHAly3YUL/Lvd2LnJNWT9TKnzQKf9bm49ZrF5Am+eEAzQE664O+KVZY2IW1Gbi72 cPotUNJbPFXOsMXtKtk5wEEI6AEbsb80dlN5E6K3AyupqR8kguD7QHBXF5+2YusqXiuO AHH0ercSDHnHhQdqEoW2hgR9bU5ycdEaHljR0RgWMRf2UHfz9CQWpgccm7uA3qMUYX// f1glSm4tuQwttDkzNnPubeymfLCvpQrynU4yAt8Va0pr6czCTCYqnsirWkQfgLJItK4b 3bZA== X-Gm-Message-State: AOAM5303WthtABIXGOzxnxj4fivslYhuLo7hE3KHjSIYj3faaAFPMzKw SmqijTdSN3/yn9lVtYErnS0B3wtgqaCt6BYQsY2vBttNsJtdQL8XRp3IxYlOxIAVbPwvXzw2OGd 2tGp+RWdkK+HhvUoMBf6J5PCcF1KTgkn9yb7POlLST8t/o1Nya/1Od1Jj4fGdgBvjO2c= X-Received: by 2002:a0c:e7c9:: with SMTP id c9mr11413738qvo.47.1626276422213; Wed, 14 Jul 2021 08:27:02 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxeSRjfauOEzeLG4MOuKUJcgWU0tbZjkANKoTYsVjjgJ1XJ+0Pe1LJv4CCicrgwVIn9ttDVOA== X-Received: by 2002:a0c:e7c9:: with SMTP id c9mr11413708qvo.47.1626276421802; Wed, 14 Jul 2021 08:27:01 -0700 (PDT) Received: from localhost.localdomain (ool-457d493a.dyn.optonline.net. [69.125.73.58]) by smtp.gmail.com with ESMTPSA id w2sm1143184qkm.65.2021.07.14.08.27.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Jul 2021 08:27:01 -0700 (PDT) To: gcc-patches@gcc.gnu.org Subject: [PATCH] c++: CTAD and forwarding references [PR88252] Date: Wed, 14 Jul 2021 11:26:39 -0400 Message-Id: <20210714152639.947266-1-ppalka@redhat.com> X-Mailer: git-send-email 2.32.0.264.g75ae10bc75 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-16.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_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, 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-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: Patrick Palka via Gcc-patches From: Patrick Palka Reply-To: Patrick Palka Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Here we're incorrectly treating T&& as a forwarding reference during CTAD even though T is a template parameter of the class template. This happens because the template parameter T in the out-of-line definition of the constructor doesn't have the flag TEMPLATE_TYPE_PARM_FOR_CLASS set, and during duplicate_decls the the redeclaration (which is in terms of this unflagged T) prevails. To fix this, we could perhaps be more consistent about setting the flag, but it appears we don't really need the flag to make the determination. Since the template parameters of an artificial guide consist of the template parameters of the class template followed by those of the constructor (if any), it should suffice to look at the index of the template parameter to determine whether T&& is a forwarding reference or not. This patch replaces the TEMPLATE_TYPE_PARM_FOR_CLASS flag with this approach. Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk? PR c++/88252 gcc/cp/ChangeLog: * cp-tree.h (TEMPLATE_TYPE_PARM_FOR_CLASS): Remove. * pt.c (push_template_decl): Remove TEMPLATE_TYPE_PARM_FOR_CLASS handling. (redeclare_class_template): Likewise. (parm_can_form_fwding_ref_p): Define. (maybe_adjust_types_for_deduction): Use it instead of TEMPLATE_TYPE_PARM_FOR_CLASS. Add tparms parameter. (unify_one_argument): Pass tparms to maybe_adjust_types_for_deduction. (try_one_overload): Likewise. (unify): Likewise. (rewrite_template_parm): Remove TEMPLATE_TYPE_PARM_FOR_CLASS handling. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/class-deduction96.C: New test. --- gcc/cp/cp-tree.h | 6 -- gcc/cp/pt.c | 67 ++++++++++++------- .../g++.dg/cpp1z/class-deduction96.C | 34 ++++++++++ 3 files changed, 75 insertions(+), 32 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction96.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b1cf44ecdb8..f4bcab5b18d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -443,7 +443,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; BLOCK_OUTER_CURLY_BRACE_P (in BLOCK) FOLD_EXPR_MODOP_P (*_FOLD_EXPR) IF_STMT_CONSTEXPR_P (IF_STMT) - TEMPLATE_TYPE_PARM_FOR_CLASS (TEMPLATE_TYPE_PARM) DECL_NAMESPACE_INLINE_P (in NAMESPACE_DECL) SWITCH_STMT_ALL_CASES_P (in SWITCH_STMT) REINTERPRET_CAST_P (in NOP_EXPR) @@ -5863,11 +5862,6 @@ enum auto_deduction_context adc_decomp_type /* Decomposition declaration initializer deduction */ }; -/* True if this type-parameter belongs to a class template, used by C++17 - class template argument deduction. */ -#define TEMPLATE_TYPE_PARM_FOR_CLASS(NODE) \ - (TREE_LANG_FLAG_0 (TEMPLATE_TYPE_PARM_CHECK (NODE))) - /* True iff this TEMPLATE_TYPE_PARM represents decltype(auto). */ #define AUTO_IS_DECLTYPE(NODE) \ (TYPE_LANG_FLAG_5 (TEMPLATE_TYPE_PARM_CHECK (NODE))) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index cf0ce770d52..01ef2984f23 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -154,8 +154,8 @@ static void tsubst_enum (tree, tree, tree); static bool check_instantiated_args (tree, tree, tsubst_flags_t); static int check_non_deducible_conversion (tree, tree, int, int, struct conversion **, bool); -static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*, - tree); +static int maybe_adjust_types_for_deduction (tree, unification_kind_t, + tree*, tree*, tree); static int type_unification_real (tree, tree, tree, const tree *, unsigned int, int, unification_kind_t, vec **, @@ -5801,18 +5801,7 @@ push_template_decl (tree decl, bool is_friend) } else if (DECL_IMPLICIT_TYPEDEF_P (decl) && CLASS_TYPE_P (TREE_TYPE (decl))) - { - /* Class template, set TEMPLATE_TYPE_PARM_FOR_CLASS. */ - tree parms = INNERMOST_TEMPLATE_PARMS (current_template_parms); - for (int i = 0; i < TREE_VEC_LENGTH (parms); ++i) - { - tree t = TREE_VALUE (TREE_VEC_ELT (parms, i)); - if (TREE_CODE (t) == TYPE_DECL) - t = TREE_TYPE (t); - if (TREE_CODE (t) == TEMPLATE_TYPE_PARM) - TEMPLATE_TYPE_PARM_FOR_CLASS (t) = true; - } - } + /* Class template. */; else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_ALIAS_P (decl)) /* alias-declaration */ @@ -6292,9 +6281,6 @@ redeclare_class_template (tree type, tree parms, tree cons) gcc_assert (DECL_CONTEXT (parm) == NULL_TREE); DECL_CONTEXT (parm) = tmpl; } - - if (TREE_CODE (parm) == TYPE_DECL) - TEMPLATE_TYPE_PARM_FOR_CLASS (TREE_TYPE (parm)) = true; } tree ci = get_constraints (tmpl); @@ -21709,6 +21695,35 @@ fn_type_unification (tree fn, return r; } +/* Return true if the template type parameter PARM for the + template TMPL can form a forwarding reference. */ + +static bool +parm_can_form_fwding_ref_p (tree tmpl, tree parm) +{ + gcc_assert (!tmpl || TREE_CODE (tmpl) == TEMPLATE_DECL); + gcc_assert (TREE_CODE (parm) == TEMPLATE_TYPE_PARM); + + /* As per [temp.deduct.call], all template parameters except those + that represent a template parameter of a class template during + CTAD can form a forwarding reference. */ + if (tmpl + && deduction_guide_p (tmpl) + && DECL_ARTIFICIAL (tmpl)) + { + tree ctmpl = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (TREE_TYPE (tmpl))); + /* Since the template parameters of an artificial guide consist of + the template parameters of the class template followed by those + of the constructor (if any), we can tell if PARM represents a template + parameter of the class template by comparing its index with the arity + of the class template. */ + if (TEMPLATE_TYPE_IDX (parm) + < TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (ctmpl))) + return false; + } + return true; +} + /* Adjust types before performing type deduction, as described in [temp.deduct.call] and [temp.deduct.conv]. The rules in these two sections are symmetric. PARM is the type of a function parameter @@ -21718,7 +21733,8 @@ fn_type_unification (tree fn, ARG_EXPR is the original argument expression, which may be null. */ static int -maybe_adjust_types_for_deduction (unification_kind_t strict, +maybe_adjust_types_for_deduction (tree tparms, + unification_kind_t strict, tree* parm, tree* arg, tree arg_expr) @@ -21790,7 +21806,8 @@ maybe_adjust_types_for_deduction (unification_kind_t strict, if (TYPE_REF_P (*parm) && TYPE_REF_IS_RVALUE (*parm) && TREE_CODE (TREE_TYPE (*parm)) == TEMPLATE_TYPE_PARM - && !TEMPLATE_TYPE_PARM_FOR_CLASS (TREE_TYPE (*parm)) + && parm_can_form_fwding_ref_p (TPARMS_PRIMARY_TEMPLATE (tparms), + TREE_TYPE (*parm)) && cp_type_quals (TREE_TYPE (*parm)) == TYPE_UNQUALIFIED && (arg_expr ? lvalue_p (arg_expr) /* try_one_overload doesn't provide an arg_expr, but @@ -22080,8 +22097,8 @@ unify_one_argument (tree tparms, tree targs, tree parm, tree arg, return unify_invalid (explain_p); } - arg_strict |= - maybe_adjust_types_for_deduction (strict, &parm, &arg, arg_expr); + arg_strict |= maybe_adjust_types_for_deduction (tparms, strict, + &parm, &arg, arg_expr); } else if ((TYPE_P (parm) || TREE_CODE (parm) == TEMPLATE_DECL) @@ -22750,7 +22767,8 @@ try_one_overload (tree tparms, else if (addr_p) arg = build_pointer_type (arg); - sub_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg, NULL); + sub_strict |= maybe_adjust_types_for_deduction (tparms, strict, + &parm, &arg, NULL_TREE); /* We don't copy orig_targs for this because if we have already deduced some template args from previous args, unify would complain when we @@ -23449,7 +23467,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, /* It should only be possible to get here for a call. */ gcc_assert (elt_strict & UNIFY_ALLOW_OUTER_LEVEL); elt_strict |= maybe_adjust_types_for_deduction - (DEDUCE_CALL, &elttype, &type, elt); + (tparms, DEDUCE_CALL, &elttype, &type, elt); elt = type; } @@ -28495,9 +28513,6 @@ rewrite_template_parm (tree olddecl, unsigned index, unsigned level, tree oldtype = TREE_TYPE (olddecl); newtype = cxx_make_type (TREE_CODE (oldtype)); TYPE_MAIN_VARIANT (newtype) = newtype; - if (TREE_CODE (oldtype) == TEMPLATE_TYPE_PARM) - TEMPLATE_TYPE_PARM_FOR_CLASS (newtype) - = TEMPLATE_TYPE_PARM_FOR_CLASS (oldtype); } else { diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction96.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction96.C new file mode 100644 index 00000000000..7fa8400830e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction96.C @@ -0,0 +1,34 @@ +// PR c++/88252 +// { dg-do compile { target c++17 } } + +template +struct A { + A(T&&); + template A(T&&, U&&); + template struct B; +}; + +template +A::A(T&&) { } + +template +template +A::A(T&&, U&&) { } + +template +template +struct A::B { + B(U&&); + template B(U&&, V&&); +}; + +int i; + +int main() { + A{i}; // { dg-error "deduction|no match|rvalue reference" } + A{i, 0}; // { dg-error "deduction|no match|rvalue reference" } + A{0, i}; + A::B{i}; // { dg-error "deduction|no match|rvalue reference" } + A::B{i, 0}; // { dg-error "deduction|no match|rvalue reference" } + A::B{0, i}; +}