From patchwork Thu Apr 11 13:16:24 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 235739 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id EFC9C2C0082 for ; Thu, 11 Apr 2013 23:16:34 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=ILDjf4fY8FDa7bf+JNQOtLnZWzLmzr53blOWyx1wGDeBc9 agy8hOf12Ljkpj0JWMc3Fwx8vCrQ+LOevdE7zScHw0ee4fg+R0I4KuN5Ifrfy7Qv xZC8irtx7YnizJxy1dDPPYGFKfr8ube/bCgWhX48pmP4mvKjbNEvHkHpzswP4= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=tY02K1ziSgZvbv9ds2tFObLG1VI=; b=sYqCAjb7imEcIPpXEsjW Qeoy5lscPv6+snfY/1MRBPZW57QjrFyX2VYr2CArpdOVyzHbhiZaWc9znH8xKNG6 pm6X8O9wYNr2sXqllgd7RnzPVSNF7iBRlsBXcCyXaxYrt3c7Mfu4aFeQEXUPEbBG WC4n3/WtP9uB4ju7MPfdtyQ= Received: (qmail 8159 invoked by alias); 11 Apr 2013 13:16:27 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 8140 invoked by uid 89); 11 Apr 2013 13:16:27 -0000 X-Spam-SWARE-Status: No, score=-7.6 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.1 Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Thu, 11 Apr 2013 13:16:26 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r3BDGPtZ017580 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 11 Apr 2013 09:16:25 -0400 Received: from [10.3.113.30] (ovpn-113-30.phx2.redhat.com [10.3.113.30]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id r3BDGOG1006103 for ; Thu, 11 Apr 2013 09:16:24 -0400 Message-ID: <5166B7A8.30706@redhat.com> Date: Thu, 11 Apr 2013 09:16:24 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; Linux i686; rv:22.0) Gecko/20100101 Thunderbird/22.0a2 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH for c++/23055 (function parms with only non-deducible template parameters) X-Virus-Found: No This bug has accumulated a lot of duplicates over the years. The issue is that the standard says that "Implicit conversions (Clause 4) will be performed on a function argument to convert it to the type of the corresponding function parameter if the parameter type contains no template-parameters that participate in template argument deduction." We were doing this for types that contain no template-parameters at all, but not for types that contain template-parameters that only appear in non-deduced locations. Tested x86_64-pc-linux-gnu, applying to trunk. commit 1af65c13d382c9ce0ec26b9d79fa68517343a844 Author: Jason Merrill Date: Tue Apr 9 17:24:30 2013 -0400 PR c++/23055 * pt.c (uses_deducible_template_parms): New. (deducible_array_bound, deducible_expression): New. (deducible_template_args): New. (unify_one_argument): Call uses_deducible_template_parms. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 7367a3a..1c0b3ec 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -15390,6 +15390,135 @@ check_non_deducible_conversion (tree parm, tree arg, int strict, return unify_arg_conversion (explain_p, parm, type, arg); } +static bool uses_deducible_template_parms (tree type); + +/* Returns true iff the expression EXPR is one from which a template + argument can be deduced. In other words, if it's an undecorated + use of a template non-type parameter. */ + +static bool +deducible_expression (tree expr) +{ + return (TREE_CODE (expr) == TEMPLATE_PARM_INDEX); +} + +/* Returns true iff the array domain DOMAIN uses a template parameter in a + deducible way; that is, if it has a max value of - 1. */ + +static bool +deducible_array_bound (tree domain) +{ + if (domain == NULL_TREE) + return false; + + tree max = TYPE_MAX_VALUE (domain); + if (TREE_CODE (max) != MINUS_EXPR) + return false; + + return deducible_expression (TREE_OPERAND (max, 0)); +} + +/* Returns true iff the template arguments ARGS use a template parameter + in a deducible way. */ + +static bool +deducible_template_args (tree args) +{ + for (int i = 0; i < TREE_VEC_LENGTH (args); ++i) + { + bool deducible; + tree elt = TREE_VEC_ELT (args, i); + if (ARGUMENT_PACK_P (elt)) + deducible = deducible_template_args (ARGUMENT_PACK_ARGS (elt)); + else + { + if (PACK_EXPANSION_P (elt)) + elt = PACK_EXPANSION_PATTERN (elt); + if (TREE_CODE (elt) == TEMPLATE_TEMPLATE_PARM) + deducible = true; + else if (TYPE_P (elt)) + deducible = uses_deducible_template_parms (elt); + else + deducible = deducible_expression (elt); + } + if (deducible) + return true; + } + return false; +} + +/* Returns true iff TYPE contains any deducible references to template + parameters, as per 14.8.2.5. */ + +static bool +uses_deducible_template_parms (tree type) +{ + if (PACK_EXPANSION_P (type)) + type = PACK_EXPANSION_PATTERN (type); + + /* T + cv-list T + TT + TT + TT<> */ + if (TREE_CODE (type) == TEMPLATE_TYPE_PARM + || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM) + return true; + + /* T* + T& + T&& */ + if (POINTER_TYPE_P (type)) + return uses_deducible_template_parms (TREE_TYPE (type)); + + /* T[integer-constant ] + type [i] */ + if (TREE_CODE (type) == ARRAY_TYPE) + return (uses_deducible_template_parms (TREE_TYPE (type)) + || deducible_array_bound (TYPE_DOMAIN (type))); + + /* T type ::* + type T::* + T T::* + T (type ::*)() + type (T::*)() + type (type ::*)(T) + type (T::*)(T) + T (type ::*)(T) + T (T::*)() + T (T::*)(T) */ + if (TYPE_PTRMEM_P (type)) + return (uses_deducible_template_parms (TYPE_PTRMEM_CLASS_TYPE (type)) + || (uses_deducible_template_parms + (TYPE_PTRMEM_POINTED_TO_TYPE (type)))); + + /* template-name (where template-name refers to a class template) + template-name (where template-name refers to a class template) */ + if (CLASS_TYPE_P (type) + && CLASSTYPE_TEMPLATE_INFO (type) + && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))) + return deducible_template_args (INNERMOST_TEMPLATE_ARGS + (CLASSTYPE_TI_ARGS (type))); + + /* type (T) + T() + T(T) */ + if (TREE_CODE (type) == FUNCTION_TYPE + || TREE_CODE (type) == METHOD_TYPE) + { + if (uses_deducible_template_parms (TREE_TYPE (type))) + return true; + tree parm = TYPE_ARG_TYPES (type); + if (TREE_CODE (type) == METHOD_TYPE) + parm = TREE_CHAIN (parm); + for (; parm; parm = TREE_CHAIN (parm)) + if (uses_deducible_template_parms (TREE_VALUE (parm))) + return true; + } + + return false; +} + /* Subroutine of type_unification_real and unify_pack_expansion to handle unification of a single P/A pair. Parameters are as for those functions. */ @@ -15409,10 +15538,21 @@ unify_one_argument (tree tparms, tree targs, tree parm, tree arg, template args from other function args. */ return unify_success (explain_p); - /* FIXME uses_deducible_template_parms */ + /* Implicit conversions (Clause 4) will be performed on a function + argument to convert it to the type of the corresponding function + parameter if the parameter type contains no template-parameters that + participate in template argument deduction. */ if (TYPE_P (parm) && !uses_template_parms (parm)) + /* For function parameters that contain no template-parameters at all, + we have historically checked for convertibility in order to shortcut + consideration of this candidate. */ return check_non_deducible_conversion (parm, arg, strict, flags, explain_p); + else if (strict == DEDUCE_CALL + && TYPE_P (parm) && !uses_deducible_template_parms (parm)) + /* For function parameters with only non-deducible template parameters, + just return. */ + return unify_success (explain_p); switch (strict) { diff --git a/gcc/testsuite/g++.dg/template/non-deducible1.C b/gcc/testsuite/g++.dg/template/non-deducible1.C new file mode 100644 index 0000000..4213524 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/non-deducible1.C @@ -0,0 +1,8 @@ +// PR c++/23055 + +template struct S { typedef int type; }; + +template +int foo(T, typename S::type * ret); + +int j = foo(1, 0); diff --git a/gcc/testsuite/g++.dg/template/nontype25.C b/gcc/testsuite/g++.dg/template/nontype25.C index bcdcce5..f399408 100644 --- a/gcc/testsuite/g++.dg/template/nontype25.C +++ b/gcc/testsuite/g++.dg/template/nontype25.C @@ -7,7 +7,7 @@ template class C {}; template class D {}; template class E {}; -template void f(D &, C(b)> &) {} // { dg-error "" "" { target c++98 } } +template void f(D &, C(b)> &) {} // { dg-error "" "" } template void g(D &, E(b)> &) {} // { dg-error "" "" { target c++98 } } B b;