From patchwork Wed Oct 27 15:59:15 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 69370 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]) by ozlabs.org (Postfix) with SMTP id 01C6DB70D1 for ; Thu, 28 Oct 2010 02:59:29 +1100 (EST) Received: (qmail 8198 invoked by alias); 27 Oct 2010 15:59:25 -0000 Received: (qmail 8188 invoked by uid 22791); 27 Oct 2010 15:59:24 -0000 X-SWARE-Spam-Status: No, hits=-6.1 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 27 Oct 2010 15:59:17 +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.13.8/8.13.8) with ESMTP id o9RFxGki031718 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 27 Oct 2010 11:59:16 -0400 Received: from [127.0.0.1] (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o9RFxFEP008112 for ; Wed, 27 Oct 2010 11:59:15 -0400 Message-ID: <4CC84C53.5030300@redhat.com> Date: Wed, 27 Oct 2010 11:59:15 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.14) Gecko/20101020 Lightning/1.0b1 Shredder/3.0.10pre MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH to add build_integral_nontype_arg_conv 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 14.3.2 restricts the conversions that can be performed on a non-type template argument to bring it to the type of the parameter. In C++98 this is pretty trivial, as it basically just means that the original argument needs to be integral, but in C++0x we can use a constexpr conversion function to convert from a constant argument of literal class type. So this new function implements the rules for this conversion. This patch also improves the diagnostic on init/member1.C; now we say C::j in the error message rather than . Tested x86_64-pc-linux-gnu, applied to trunk. commit 0ff4fb22ceeccec01a08fd768f9f5710a7c124d2 Author: Jason Merrill Date: Tue Oct 26 21:37:07 2010 -0400 * call.c (build_integral_nontype_arg_conv): New. * cp-tree.h: Declare it. * pt.c (convert_nontype_argument): Use it. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 1831718..204fda5 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -3165,6 +3165,76 @@ build_user_type_conversion (tree totype, tree expr, int flags) return NULL_TREE; } +/* Subroutine of convert_nontype_argument. + + EXPR is an argument for a template non-type parameter of integral or + enumeration type. Do any necessary conversions (that are permitted for + non-type arguments) to convert it to the parameter type. + + If conversion is successful, returns the converted expression; + otherwise, returns error_mark_node. */ + +tree +build_integral_nontype_arg_conv (tree type, tree expr, tsubst_flags_t complain) +{ + conversion *conv; + void *p; + tree t; + + if (error_operand_p (expr)) + return error_mark_node; + + gcc_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type)); + + /* Get the high-water mark for the CONVERSION_OBSTACK. */ + p = conversion_obstack_alloc (0); + + conv = implicit_conversion (type, TREE_TYPE (expr), expr, + /*c_cast_p=*/false, + LOOKUP_IMPLICIT); + + /* for a non-type template-parameter of integral or + enumeration type, integral promotions (4.5) and integral + conversions (4.7) are applied. */ + /* It should be sufficient to check the outermost conversion step, since + there are no qualification conversions to integer type. */ + if (conv) + switch (conv->kind) + { + /* A conversion function is OK. If it isn't constexpr, we'll + complain later that the argument isn't constant. */ + case ck_user: + /* The lvalue-to-rvalue conversion is OK. */ + case ck_rvalue: + case ck_identity: + break; + + case ck_std: + t = conv->u.next->type; + if (INTEGRAL_OR_ENUMERATION_TYPE_P (t)) + break; + + if (complain & tf_error) + error ("conversion from %qT to %qT not considered for " + "non-type template argument", t, type); + /* and fall through. */ + + default: + conv = NULL; + break; + } + + if (conv) + expr = convert_like (conv, expr, complain); + else + expr = error_mark_node; + + /* Free all the conversions we allocated. */ + obstack_free (&conversion_obstack, p); + + return expr; +} + /* Do any initial processing on the arguments to a function call. */ static VEC(tree,gc) * diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 05282ba..ec026a4 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4651,6 +4651,7 @@ extern tree strip_top_quals (tree); extern bool reference_related_p (tree, tree); extern tree perform_implicit_conversion (tree, tree, tsubst_flags_t); extern tree perform_implicit_conversion_flags (tree, tree, tsubst_flags_t, int); +extern tree build_integral_nontype_arg_conv (tree, tree, tsubst_flags_t); extern tree perform_direct_initialization_if_possible (tree, tree, bool, tsubst_flags_t); extern tree in_charge_arg_for_name (tree); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 1de5d55..8a6d451 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5069,10 +5069,17 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) (_conv.integral_) are applied. */ if (INTEGRAL_OR_ENUMERATION_TYPE_P (type)) { - if (!INTEGRAL_OR_ENUMERATION_TYPE_P (expr_type)) + tree t = build_integral_nontype_arg_conv (type, expr, complain); + t = fold_decl_constant_value (t); + if (t != error_mark_node) + expr = t; + + if (!same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (expr))) return error_mark_node; - expr = fold_decl_constant_value (expr); + /* Conversion was allowed: fold it to a bare integer constant. */ + expr = fold (expr); + /* Notice that there are constant expressions like '4 % 0' which do not fold into integer constants. */ if (TREE_CODE (expr) != INTEGER_CST) @@ -5082,16 +5089,6 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) "because it is a non-constant expression", expr, type); return NULL_TREE; } - - /* At this point, an implicit conversion does what we want, - because we already know that the expression is of integral - type. */ - expr = perform_implicit_conversion (type, expr, complain); - if (expr == error_mark_node) - return error_mark_node; - - /* Conversion was allowed: fold it to a bare integer constant. */ - expr = fold (expr); } /* [temp.arg.nontype]/5, bullet 2