From patchwork Wed Jun 3 14:47:17 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 136402 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 51D964BA2E1B for ; Wed, 3 Jun 2026 14:48:49 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 51D964BA2E1B Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=dHgoTJhQ 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 D67FA4BA2E3C for ; Wed, 3 Jun 2026 14:47:23 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D67FA4BA2E3C Authentication-Results: sourceware.org; dmarc=pass (p=quarantine 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 D67FA4BA2E3C Authentication-Results: sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1780498044; cv=none; b=gRMb9ans0IyQRmwY2rP6kOGjbbkRvKJbYmxReVwgWmakyJCDO5RLk51VHShqaxIsMKeSZXRHH2BVOxasb9NKdJQ0Gu0E18IQ/qjs4FlPq+RAb/HOAvmQkk6o0letYBxemQYzGXbQh9AAvZKy8Jgg2tPoAp61T1QbqwI9nHrWgJI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1780498044; c=relaxed/simple; bh=CGuFfnGZfU9czLai+1661Gl+F8JCXldRtOcO9R5kzVw=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=INHlY6dvT0wUJevtQv2noPJUiyi4HAIvEoAKw3pTR4fraIddoRSgkoaP3zzdfWeSMpCivsBl12BK6V8IodRk+Pt8YUtc45JIwT793eZytY2G69RCfpyf3ZdJ/Hy49/tyB+aIEePrxxd3KV0guXoO/beXRSF3huTur48a9/CTL1A= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=dHgoTJhQ DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D67FA4BA2E3C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780498043; 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: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ej+AGXE8A5yPbz2Z7oS9FNHcHYxa21UGCCNr2Rx7qbk=; b=dHgoTJhQlgz07Q/wI3qEVDz28qmYXyn60v1vVE0a7UX5haxnG8ZAR9ZGlfedK3v1mA0pUV bX/gUhjTssUsLGs3vwYi1FYhKqVRbDyIDEjzV3pf6H+IfJd/tJyudAyZNn3gMbRvp3927y 4sL2FfafVpxUmp+sh48wqEYLvqbjUHk= Received: from mail-qt1-f200.google.com (mail-qt1-f200.google.com [209.85.160.200]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-230--QGsTHnOP9iaIKfbBTtWYg-1; Wed, 03 Jun 2026 10:47:21 -0400 X-MC-Unique: -QGsTHnOP9iaIKfbBTtWYg-1 X-Mimecast-MFC-AGG-ID: -QGsTHnOP9iaIKfbBTtWYg_1780498040 Received: by mail-qt1-f200.google.com with SMTP id d75a77b69052e-516d1a8a6c8so190196691cf.2 for ; Wed, 03 Jun 2026 07:47:21 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780498040; x=1781102840; h=user-agent:in-reply-to:content-transfer-encoding :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=ej+AGXE8A5yPbz2Z7oS9FNHcHYxa21UGCCNr2Rx7qbk=; b=kIyYw7krDpp1SEzKGwkzgjngx3bDA0t44MdH0WGPx6p6OdsovYfwgKgGr2K/r+AOWE GTjJHlIqseZawKGFIh6J926WX9pBOZLkrsqB0d6zH4p2YbL6QaEZvCgZjmEGgTY4SUoZ /4VLADK1W4fzzSrs5EklQrW4OhCB1PSrW7lXAT10dOppJzTbgJPGmA7vc65cNtyxiics ddkOgCveCHsZ6pcGhH8iGhdLaudq/Y3m8zASS513fL/VaX1iHhMh0sRXKb+XN7S+Bd7L MU/ONUdcwqpb9wxgQ5sFrwO/6hupWyPgsQlbllkYs9aKrvJ3KMNmEmiAbqvohh2UG5XX GMSw== X-Gm-Message-State: AOJu0YxsybqlbdRbGrSPHsQv3ZIkLGv4mQv+FbIltGMdwUrX35Dsw7FK 1K3+DB3XBc6Vq4dPSYBgiyxuZZoZne5Wu4lENqRJkrTw368QQpOvPvxtpuGZbtUgmPj2aZM2aGw rDIFyu7IBhrVL01didA5wbW+2jQhW1shArePrSLshvAvBxOHzGL21Arlkg7DBX7KA50Q= X-Gm-Gg: Acq92OHExJ+JZEf+yM3D/uivbPbGcuLJO9r5AKbcoJMfJ5eDxBAeU1PJpQygylFNKbt +RLN9Y37s37csz/QioRwlvrUwAEpdw0SHGXSdiV5/HucmAOGv8kw/r++T7QOlggQ0HJ2BxW4ejy q85vFmdi9JqZ6/9Yf7cnLfECzbtBGpLImSwp/8u6virdcxC8MOrC+mmqcwH1Nimt0BoALsvGJN6 osv3St+UyzuUA4+ZTN7JMs7rL5tYmubbbd6TwfqTLHyufPuxHqlrFS87gEZ2kXmSfUXR3YdoszU oeRmaYLRmAsc8zpyux1L0BbfZEvcWonvVE1FMX0Q6PQxrqUuT32aK56Zii5njbcjWWHqhlR5bZE XQkDbhAcShZzsR/qfhv+MtTWUUoJKIdsJ X-Received: by 2002:a05:622a:4c0b:b0:516:ddc3:6248 with SMTP id d75a77b69052e-517786d5867mr57186711cf.29.1780498040276; Wed, 03 Jun 2026 07:47:20 -0700 (PDT) X-Received: by 2002:a05:622a:4c0b:b0:516:ddc3:6248 with SMTP id d75a77b69052e-517786d5867mr57186151cf.29.1780498039594; Wed, 03 Jun 2026 07:47:19 -0700 (PDT) Received: from redhat.com ([2603:7002:1f00:31d2:7d6:2158:b5c9:50b2]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-51775d81f7asm25473431cf.19.2026.06.03.07.47.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jun 2026 07:47:18 -0700 (PDT) Date: Wed, 3 Jun 2026 10:47:17 -0400 From: Marek Polacek To: Jason Merrill Cc: GCC Patches Subject: [PATCH v5] c++: reference tparm refers to temporary object [PR107124] Message-ID: References: <20260527203200.1900636-1-polacek@redhat.com> <48a4843c-2e54-4a7e-8cc2-fd10695c40f5@redhat.com> <03f5342d-e449-412a-a545-08282cf71383@redhat.com> <069c2788-b8f2-4a38-9669-cea1a54a38df@redhat.com> MIME-Version: 1.0 In-Reply-To: <069c2788-b8f2-4a38-9669-cea1a54a38df@redhat.com> User-Agent: Mutt/2.3.1 (2026-03-20) X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: lPezSLmLUipLCByiUOAbw8ahacnhg2JDo1Ap826A0zI_1780498040 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-13.7 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_BLOCKED, RCVD_IN_HOSTKARMA_W, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, RCVD_IN_PBL, SPF_HELO_PASS, SPF_NONE, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on 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 Wed, Jun 03, 2026 at 08:54:51AM -0400, Jason Merrill wrote: > On 6/2/26 6:01 PM, Marek Polacek wrote: > > On Fri, May 29, 2026 at 04:37:55PM -0400, Jason Merrill wrote: > > > On 5/29/26 4:21 PM, Marek Polacek wrote: > > > > On Thu, May 28, 2026 at 03:21:35PM -0400, Jason Merrill wrote: > > > > > On 5/28/26 11:42 AM, Marek Polacek wrote: > > > > > > On Wed, May 27, 2026 at 06:15:04PM -0400, Jason Merrill wrote: > > > > > > > On 5/27/26 4:32 PM, Marek Polacek wrote: > > > > > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > > > > > > > > > > > > > > > -- >8 -- > > > > > > > > [temp.arg.nontype] tells us that a temporary object is not an acceptable > > > > > > > > template-argument when the corresponding template parameter has reference > > > > > > > > type. So > > > > > > > > > > > > > > > > template struct B {}; > > > > > > > > B<1> b; > > > > > > > > > > > > > > > > is ill-formed. In the test below we have a tparm `const int &I` and we > > > > > > > > are trying to deduce `I` from `A<0>`. Since a temporary would be required > > > > > > > > for the template argument, this should be a deduction failure. > > > > > > > > > > > > > > > > PR c++/107124 > > > > > > > > > > > > > > > > gcc/cp/ChangeLog: > > > > > > > > > > > > > > > > * pt.cc (unify) : Return > > > > > > > > unify_type_mismatch if a temporary would be required for the > > > > > > > > template argument. > > > > > > > > > > > > > > > > gcc/testsuite/ChangeLog: > > > > > > > > > > > > > > > > * g++.dg/template/deduce11.C: New test. > > > > > > > > * g++.dg/template/deduce12.C: New test. > > > > > > > > --- > > > > > > > > gcc/cp/pt.cc | 7 ++++++- > > > > > > > > gcc/testsuite/g++.dg/template/deduce11.C | 15 +++++++++++++++ > > > > > > > > gcc/testsuite/g++.dg/template/deduce12.C | 11 +++++++++++ > > > > > > > > 3 files changed, 32 insertions(+), 1 deletion(-) > > > > > > > > create mode 100644 gcc/testsuite/g++.dg/template/deduce11.C > > > > > > > > create mode 100644 gcc/testsuite/g++.dg/template/deduce12.C > > > > > > > > > > > > > > > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > > > > > > > > index ada5f53a9f1..41b86a4e4f7 100644 > > > > > > > > --- a/gcc/cp/pt.cc > > > > > > > > +++ b/gcc/cp/pt.cc > > > > > > > > @@ -26485,7 +26485,12 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, > > > > > > > > ; > > > > > > > > else if (same_type_ignoring_top_level_qualifiers_p > > > > > > > > (non_reference (TREE_TYPE (arg)), > > > > > > > > - non_reference (tparm))) > > > > > > > > + non_reference (tparm)) > > > > > > > > + /* A temporary object is not an acceptable template-argument > > > > > > > > + when the corresponding template parm has reference type. */ > > > > > > > > + && !(TYPE_REF_P (tparm) > > > > > > > > + && ref_conv_binds_to_temporary > > > > > > > > + (tparm, convert_from_reference (arg)).is_true ())) > > > > > > > > > > > > > > This seems like an awkward place for this check since it isn't a type > > > > > > > mismatch, which leads to the unhelpful diagnostic > > > > > > > > > > > > > > > • mismatched types ‘const int&’ and ‘int’ > > > > > > > > > > > > > > I think better would be to after checking for pack mismatch, check > > > > > > > invalid_tparm_referent_p, get the diagnostic from there, and return plain > > > > > > > unify_invalid if it fails. > > > > > > > > > > > > I put it there because it seemed simple to fall back on unify_type_mismatch > > > > > > (and it's what clang++ says too). But fair enough; I agree with your point. > > > > > > > > > > > > I can't use invalid_tparm_referent_p because it wouldn't detect the problem > > > > > > (it's the first thing I tried). So I propose this version. > > > > > > > > > > Ah, because arg is still INTEGER_CST. This suggests that we want the full > > > > > convert_nontype_argument, which gives > > > > > > > > > > > initializing ‘const int&’ with ‘int’ in converted constant expression does not bind directly > > > > > > > > > > then we should be able to drop the separate strip_typedefs_expr. > > > > > > > > So like this? I'm not certain about the forced argument. But the > > > > dependent_implicit_conv_p is necessary to avoid crashing on dependent > > > > trees. > > > > > > I think forced false is correct, we shouldn't be dealing with aliases or > > > concepts here. > > > > > > > -- >8 -- > > > > [temp.arg.nontype] tells us that a temporary object is not an acceptable > > > > template-argument when the corresponding template parameter has reference > > > > type. So > > > > > > > > template struct B { }; > > > > B<1> b; > > > > > > > > is ill-formed. In the test below we have a tparm `const int &I` and we > > > > are trying to deduce `I` from `A<0>`. Since a temporary would be required > > > > for the template argument, this should be a deduction failure. > > > > > > > > PR c++/107124 > > > > > > > > gcc/cp/ChangeLog: > > > > > > > > * pt.cc (unify) : Call > > > > convert_nontype_argument and return unify_invalid if it failed. > > > > Don't call strip_typedefs_expr. > > > > > > > > gcc/testsuite/ChangeLog: > > > > > > > > * g++.dg/template/deduce11.C: New test. > > > > * g++.dg/template/deduce12.C: New test. > > > > --- > > > > gcc/cp/pt.cc | 12 ++++++++---- > > > > gcc/testsuite/g++.dg/template/deduce11.C | 15 +++++++++++++++ > > > > gcc/testsuite/g++.dg/template/deduce12.C | 12 ++++++++++++ > > > > 3 files changed, 35 insertions(+), 4 deletions(-) > > > > create mode 100644 gcc/testsuite/g++.dg/template/deduce11.C > > > > create mode 100644 gcc/testsuite/g++.dg/template/deduce12.C > > > > > > > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > > > > index ada5f53a9f1..a70a758c61f 100644 > > > > --- a/gcc/cp/pt.cc > > > > +++ b/gcc/cp/pt.cc > > > > @@ -26530,10 +26530,14 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, > > > > && !TEMPLATE_PARM_PARAMETER_PACK (parm)) > > > > return unify_parameter_pack_mismatch (explain_p, parm, arg); > > > > - { > > > > - bool removed_attr = false; > > > > - arg = strip_typedefs_expr (arg, &removed_attr); > > > > - } > > > > + if (!dependent_implicit_conv_p (tparm, arg, /*forced=*/false)) > > > > + { > > > > + arg = convert_from_reference (arg); > > > > + arg = convert_nontype_argument (tparm, arg, complain); > > > > + if (!arg || arg == error_mark_node) > > > > + return unify_invalid (explain_p); > > > > + } > > > > > > We probably want the else from convert_template_argument, too: > > > > > > > if (!dependent_implicit_conv_p (t, orig_arg, force_conv)) > > > > /* We used to call digest_init here. However, digest_init > > > > will report errors, which we don't want when complain > > > > is zero. More importantly, digest_init will try too > > > > hard to convert things: for example, `0' should not be > > > > converted to pointer type at this point according to > > > > the standard. Accepting this is not merely an > > > > extension, since deciding whether or not these > > > > conversions can occur is part of determining which > > > > function template to call, or whether a given explicit > > > > argument specification is valid. */ > > > > val = convert_nontype_argument (t, orig_arg, complain); > > > > else > > > > { > > > > val = canonicalize_expr_argument (orig_arg, complain); > > > > val = maybe_convert_nontype_argument (t, val, force_conv); > > > > } > > > > > > ...maybe factoring that out into another function. > > > > Sounds good, done here. > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > > > -- >8 -- > > [temp.arg.nontype] tells us that a temporary object is not an acceptable > > template-argument when the corresponding template parameter has reference > > type. So > > > > template struct B { }; > > B<1> b; > > > > is ill-formed. In the test below we have a tparm `const int &I` and we > > are trying to deduce `I` from `A<0>`. Since a temporary would be required > > for the template argument, this should be a deduction failure. > > > > PR c++/107124 > > > > gcc/cp/ChangeLog: > > > > * pt.cc (coerce_nontype_argument): New, factored out of... > > (convert_template_argument): ...here. > > Hmm, this name adds to the already-confusing group of similarly-named > functions. How about convert_nontype_argument_maybe_dependent, and note in Done. > the convert_nontype_argument function comment that it expects non-dependent > TYPE and non-type-dependent EXPR? And the existing We already say that: "Both TYPE and EXPR must be non-dependent." > maybe_convert_nontype_argument should probably be something more distinct > like maybe_build_nontype_implicit_conv. Done. Ran dg.exp. Ok for trunk? -- >8 -- [temp.arg.nontype] tells us that a temporary object is not an acceptable template-argument when the corresponding template parameter has reference type. So template struct B { }; B<1> b; is ill-formed. In the test below we have a tparm `const int &I` and we are trying to deduce `I` from `A<0>`. Since a temporary would be required for the template argument, this should be a deduction failure. PR c++/107124 gcc/cp/ChangeLog: * cp-tree.h: Adjust comments to mention maybe_build_nontype_implicit_conv instead of maybe_convert_nontype_argument. * pt.cc (maybe_convert_nontype_argument): Rename to... (maybe_build_nontype_implicit_conv): ...this. (convert_nontype_argument_maybe_dependent): New, factored out of... (convert_template_argument): ...here. (unify) : Call convert_nontype_argument_maybe_dependent and return unify_invalid if it failed. Don't call strip_typedefs_expr. gcc/testsuite/ChangeLog: * g++.dg/template/deduce11.C: New test. * g++.dg/template/deduce12.C: New test. --- gcc/cp/cp-tree.h | 4 +- gcc/cp/pt.cc | 58 +++++++++++++++--------- gcc/testsuite/g++.dg/template/deduce11.C | 15 ++++++ gcc/testsuite/g++.dg/template/deduce12.C | 12 +++++ 4 files changed, 65 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/deduce11.C create mode 100644 gcc/testsuite/g++.dg/template/deduce12.C base-commit: 42989c22cfdbcd4207482bc6476ddb8d00a3424d diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 65f112714d1..bf477a67a34 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5138,7 +5138,7 @@ get_vec_init_expr (tree t) (TREE_LANG_FLAG_0 (IMPLICIT_CONV_EXPR_CHECK (NODE))) /* True if NODE represents a dependent conversion of a non-type template - argument. Set by maybe_convert_nontype_argument. */ + argument. Set by maybe_build_nontype_implicit_conv. */ #define IMPLICIT_CONV_EXPR_NONTYPE_ARG(NODE) \ (TREE_LANG_FLAG_1 (IMPLICIT_CONV_EXPR_CHECK (NODE))) @@ -5148,7 +5148,7 @@ get_vec_init_expr (tree t) (TREE_LANG_FLAG_2 (IMPLICIT_CONV_EXPR_CHECK (NODE))) /* True if NODE represents a conversion forced to be represented in - maybe_convert_nontype_argument, i.e. for an alias template. */ + maybe_build_nontype_implicit_conv, i.e. for an alias template. */ #define IMPLICIT_CONV_EXPR_FORCED(NODE) \ (TREE_LANG_FLAG_3 (IMPLICIT_CONV_EXPR_CHECK (NODE))) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index b334882de81..4683b57f34b 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -8740,7 +8740,7 @@ is_compatible_template_arg (tree parm, tree arg, tree args) conversion for the benefit of cp_tree_equal. */ static tree -maybe_convert_nontype_argument (tree type, tree arg, bool force) +maybe_build_nontype_implicit_conv (tree type, tree arg, bool force) { /* Auto parms get no conversion. */ if (type_uses_auto (type)) @@ -8780,6 +8780,33 @@ dependent_implicit_conv_p (tree type, tree expr, bool forced) && value_dependent_expression_p (expr))); } +/* Convert the non-type template parameter ARG to the indicated TYPE. + If one of them is dependent, create an appropriate conversion. + FORCE_CONV is true in a forced context (i.e. alias or concept). */ + +static tree +convert_nontype_argument_maybe_dependent (tree type, tree arg, + bool force_conv, + tsubst_flags_t complain) +{ + if (dependent_implicit_conv_p (type, arg, force_conv)) + { + tree val = canonicalize_expr_argument (arg, complain); + return maybe_build_nontype_implicit_conv (type, val, force_conv); + } + + /* We used to call digest_init here. However, digest_init will report + errors, which we don't want when complain is zero. More importantly, + digest_init will try too hard to convert things: for example, + `0' should not be converted to pointer type at this point according to + the standard. Accepting this is not merely an extension, since + deciding whether or not these conversions can occur is part of + determining which function template to call, or whether a given + explicit argument specification is valid. */ + return convert_nontype_argument (type, convert_from_reference (arg), + complain); +} + /* Convert the indicated template ARG as necessary to match the indicated template PARM. Returns the converted ARG, or error_mark_node if the conversion was unsuccessful. Error and @@ -9060,23 +9087,8 @@ convert_template_argument (tree parm, && same_type_p (TREE_TYPE (orig_arg), t)) orig_arg = TREE_OPERAND (orig_arg, 0); - if (!dependent_implicit_conv_p (t, orig_arg, force_conv)) - /* We used to call digest_init here. However, digest_init - will report errors, which we don't want when complain - is zero. More importantly, digest_init will try too - hard to convert things: for example, `0' should not be - converted to pointer type at this point according to - the standard. Accepting this is not merely an - extension, since deciding whether or not these - conversions can occur is part of determining which - function template to call, or whether a given explicit - argument specification is valid. */ - val = convert_nontype_argument (t, orig_arg, complain); - else - { - val = canonicalize_expr_argument (orig_arg, complain); - val = maybe_convert_nontype_argument (t, val, force_conv); - } + val = convert_nontype_argument_maybe_dependent (t, orig_arg, force_conv, + complain); if (val == NULL_TREE) val = error_mark_node; @@ -26567,10 +26579,12 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, && !TEMPLATE_PARM_PARAMETER_PACK (parm)) return unify_parameter_pack_mismatch (explain_p, parm, arg); - { - bool removed_attr = false; - arg = strip_typedefs_expr (arg, &removed_attr); - } + arg = convert_nontype_argument_maybe_dependent (tparm, arg, + /*forced=*/false, + complain); + if (!arg || arg == error_mark_node) + return unify_invalid (explain_p); + TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg; return unify_success (explain_p); diff --git a/gcc/testsuite/g++.dg/template/deduce11.C b/gcc/testsuite/g++.dg/template/deduce11.C new file mode 100644 index 00000000000..c7671c04397 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/deduce11.C @@ -0,0 +1,15 @@ +// PR c++/107124 +// { dg-do compile { target c++11 } } + +template +struct A {}; + +template +constexpr int f (A) { return 0; } + +template +constexpr int f (T) { return 1; } + +const int a = 42; +static_assert (f (A<0>{}) == 1, ""); +static_assert (f (A{}) == 1, ""); diff --git a/gcc/testsuite/g++.dg/template/deduce12.C b/gcc/testsuite/g++.dg/template/deduce12.C new file mode 100644 index 00000000000..0bd2762edd4 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/deduce12.C @@ -0,0 +1,12 @@ +// PR c++/107124 +// { dg-do compile { target c++11 } } + +template +struct A {}; + +template +constexpr int f (A) { return 0; } + +constexpr int i = f (A<0>{}); // { dg-error "no matching function for call" } +// { dg-message "(candidate|does not bind directly|could not convert)" "candidate note" { target c++17 } .-1 } +// { dg-message "(candidate|not a valid template argument)" "candidate note" { target c++14_down } .-2 }