From patchwork Wed May 2 03:01:48 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Carlini X-Patchwork-Id: 156322 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 79696B6F62 for ; Wed, 2 May 2012 13:02:50 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1336532571; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Message-ID:Date:From:User-Agent:MIME-Version: To:CC:Subject:References:In-Reply-To:Content-Type:Mailing-List: Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:Sender:Delivered-To; bh=e5P71d13pigSEaoy4KV/ux4AJTA=; b=VUJ9tL+F7VOankG5nn5XNSp2kWuxGwbeCoptZSFDOz4qriX9+uvanGuftMoNNf Gl1O55JxIlYlQjdSRIGweTcrN++LAKSJYiZG/DdtrlKO2HvEsa7+Yq3BW1k0Igon mUAitlHfSyi4FOwoysP4F3pfux9+Vt+y/WdSdeJAqGPF4= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:Received:Message-ID:Date:From:User-Agent:MIME-Version:To:CC:Subject:References:In-Reply-To:Content-Type:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=fyse5/bSXp2YixCMNamUuF0eoAP122OWO1MVEKrEaaTE50LuCo3ifwP2Gpx0wt MrU5zRVVuMPoR2r/9VKky24S+H/EYPGjDjlrev4k+FIwJyIeClCnJtR9EnKHiBo5 49zMVPusPuqHoWnJWes7RqVjsXqZF0MKksQga+n2SR93g=; Received: (qmail 10286 invoked by alias); 2 May 2012 03:02:46 -0000 Received: (qmail 10235 invoked by uid 22791); 2 May 2012 03:02:34 -0000 X-SWARE-Spam-Status: No, hits=-7.2 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, KHOP_THREADED, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_NO, RCVD_IN_HOSTKARMA_W, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from acsinet15.oracle.com (HELO acsinet15.oracle.com) (141.146.126.227) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 02 May 2012 03:02:19 +0000 Received: from ucsinet21.oracle.com (ucsinet21.oracle.com [156.151.31.93]) by acsinet15.oracle.com (Sentrion-MTA-4.2.2/Sentrion-MTA-4.2.2) with ESMTP id q4232GFq010526 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 2 May 2012 03:02:17 GMT Received: from acsmt358.oracle.com (acsmt358.oracle.com [141.146.40.158]) by ucsinet21.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id q4232Ftn015431 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 2 May 2012 03:02:15 GMT Received: from abhmt106.oracle.com (abhmt106.oracle.com [141.146.116.58]) by acsmt358.oracle.com (8.12.11.20060308/8.12.11) with ESMTP id q4232FN2019862; Tue, 1 May 2012 22:02:15 -0500 Received: from [192.168.1.4] (/79.52.234.239) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Tue, 01 May 2012 20:02:14 -0700 Message-ID: <4FA0A39C.5030404@oracle.com> Date: Wed, 02 May 2012 05:01:48 +0200 From: Paolo Carlini User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20120421 Thunderbird/12.0 MIME-Version: 1.0 To: Jason Merrill CC: "gcc-patches@gcc.gnu.org" Subject: Re: [RFH / Patch] PR 51222 References: <4F9B4B10.7090409@oracle.com> <4F9B62F0.5090202@redhat.com> <4F9BD0B8.4030005@oracle.com> <4F9CB2C9.3060700@redhat.com> <4F9D6180.4030408@oracle.com> <4F9EC605.2050703@redhat.com> <4F9F2243.7000802@oracle.com> <4F9F665D.2090806@redhat.com> <4F9FD050.7040700@oracle.com> <4FA02552.2060905@redhat.com> <4FA04229.3050407@oracle.com> <4FA0660C.3050702@redhat.com> <4FA07163.80604@oracle.com> <4FA07414.7090104@oracle.com> <4FA075D4.1080005@redhat.com> <4FA07C61.5020804@oracle.com> <4FA0922E.4@redhat.com> In-Reply-To: <4FA0922E.4@redhat.com> X-IsSubscribed: yes 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 Hi, On 05/02/2012 03:47 AM, Jason Merrill wrote: > On 05/01/2012 08:14 PM, Paolo Carlini wrote: >>> I think we need to handle FIELD_DECL, too. >> Are there hopes that handling FIELD_DECL like FUNCTION_DECL and VAR_DECL >> (besides the DECL_LANG_SPECIFIC check) would work? > I would think so. Ok, if we want it, I adjusted the code, see attached. >> A data point I can give you, I put a gcc_assert (TREE_CODE (t) != >> FIELD_DECL) in the default case of the walk_template_parms_r switch, >> and it never triggers for the whole testsuite. > > With your patch, what happens if you have a member access like > > template > struct A > { > T t; > auto f(A a) -> decltype (sizeof (a.t)) { } > }; > > I would expect that to hit the FIELD_DECL case. Well, not really. The first time walk_template_parms_r is called, t is a SIZEOF_EXPR which remains unhandled, the function returns NULL_TREE. The second time, t is a COMPONENT_REF, thus !TYPE_P (t) is true, TREE_TYPE is NULL, the function immediately returns error_mark_node and the iteration ends (with the correct result that the expression is instantiation-dependent). Does it make sense? Anyway, the attached appear to also pass the testsuite, I could test it more completely tomorrow. If the FIELD_DECL bits seem safe to have... ;) Thanks, Paolo. Index: pt.c =================================================================== --- pt.c (revision 187012) +++ pt.c (working copy) @@ -145,8 +145,8 @@ static tree convert_nontype_argument_function (tre static tree convert_nontype_argument (tree, tree, tsubst_flags_t); static tree convert_template_argument (tree, tree, tree, tsubst_flags_t, int, tree); -static int for_each_template_parm (tree, tree_fn_t, void*, - struct pointer_set_t*, bool); +static int walk_template_parms (tree, tree_fn_t, void*, + struct pointer_set_t*, bool, bool); static tree expand_template_argument_pack (tree); static tree build_template_parm_index (int, int, int, int, tree, tree); static bool inline_needs_template_parms (tree); @@ -185,7 +185,7 @@ static int coerce_template_template_parms (tree, t static bool template_template_parm_bindings_ok_p (tree, tree); static int template_args_equal (tree, tree); static void tsubst_default_arguments (tree); -static tree for_each_template_parm_r (tree *, int *, void *); +static tree walk_template_parms_r (tree *, int *, void *); static tree copy_default_args_to_explicit_spec_1 (tree, tree); static void copy_default_args_to_explicit_spec (tree); static int invalid_nontype_parm_type_p (tree, tsubst_flags_t); @@ -4276,8 +4276,8 @@ mark_template_parm (tree t, void* data) tpd->arg_uses_template_parms[tpd->current_arg] = 1; } - /* Return zero so that for_each_template_parm will continue the - traversal of the tree; we want to mark *every* template parm. */ + /* Return zero so that walk_template_parms will continue the traversal + of the tree; we want to mark *every* template parm. */ return 0; } @@ -4344,11 +4344,12 @@ process_partial_specialization (tree decl) for (i = 0; i < nargs; ++i) { tpd.current_arg = i; - for_each_template_parm (TREE_VEC_ELT (inner_args, i), - &mark_template_parm, - &tpd, - NULL, - /*include_nondeduced_p=*/false); + walk_template_parms (TREE_VEC_ELT (inner_args, i), + &mark_template_parm, + &tpd, + NULL, + /*check_types=*/false, + /*include_nondeduced_p=*/false); } for (i = 0; i < ntparms; ++i) if (tpd.parms[i] == 0) @@ -4481,11 +4482,12 @@ process_partial_specialization (tree decl) tpd2.current_arg = i; tpd2.arg_uses_template_parms[i] = 0; memset (tpd2.parms, 0, sizeof (int) * nargs); - for_each_template_parm (type, - &mark_template_parm, - &tpd2, - NULL, - /*include_nondeduced_p=*/false); + walk_template_parms (type, + &mark_template_parm, + &tpd2, + NULL, + /*check_types=*/false, + /*include_nondeduced_p=*/false); if (tpd2.arg_uses_template_parms [i]) { @@ -4755,7 +4757,7 @@ check_default_tmpl_args (tree decl, tree parms, in } /* Worker for push_template_decl_real, called via - for_each_template_parm. DATA is really an int, indicating the + walk_template_parms. DATA is really an int, indicating the level of the parameters we are interested in. If T is a template parameter of that level, return nonzero. */ @@ -7750,26 +7752,34 @@ struct pair_fn_data { tree_fn_t fn; void *data; + bool check_types; /* True when we should also visit template parameters that occur in non-deduced contexts. */ bool include_nondeduced_p; struct pointer_set_t *visited; }; -/* Called from for_each_template_parm via walk_tree. */ +/* Called from walk_template_parms via walk_tree. */ static tree -for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d) +walk_template_parms_r (tree *tp, int *walk_subtrees, void *d) { tree t = *tp; struct pair_fn_data *pfd = (struct pair_fn_data *) d; tree_fn_t fn = pfd->fn; void *data = pfd->data; + /* If the type is null, this is a type-dependent expression, and if + we're checking types, we would find the relevant template parameters. + And fn must be null, so we can just return. */ + if (pfd->check_types && !TYPE_P (t) && TREE_TYPE (t) == NULL_TREE) + return error_mark_node; + if (TYPE_P (t) && (pfd->include_nondeduced_p || TREE_CODE (t) != TYPENAME_TYPE) - && for_each_template_parm (TYPE_CONTEXT (t), fn, data, pfd->visited, - pfd->include_nondeduced_p)) + && walk_template_parms (TYPE_CONTEXT (t), fn, data, + pfd->visited, pfd->check_types, + pfd->include_nondeduced_p)) return error_mark_node; switch (TREE_CODE (t)) @@ -7783,34 +7793,39 @@ static tree case ENUMERAL_TYPE: if (!TYPE_TEMPLATE_INFO (t)) *walk_subtrees = 0; - else if (for_each_template_parm (TI_ARGS (TYPE_TEMPLATE_INFO (t)), - fn, data, pfd->visited, - pfd->include_nondeduced_p)) + else if (walk_template_parms (TI_ARGS (TYPE_TEMPLATE_INFO (t)), + fn, data, pfd->visited, + pfd->check_types, + pfd->include_nondeduced_p)) return error_mark_node; break; case INTEGER_TYPE: - if (for_each_template_parm (TYPE_MIN_VALUE (t), - fn, data, pfd->visited, - pfd->include_nondeduced_p) - || for_each_template_parm (TYPE_MAX_VALUE (t), - fn, data, pfd->visited, - pfd->include_nondeduced_p)) + if (walk_template_parms (TYPE_MIN_VALUE (t), + fn, data, pfd->visited, + pfd->check_types, + pfd->include_nondeduced_p) + || walk_template_parms (TYPE_MAX_VALUE (t), + fn, data, pfd->visited, + pfd->check_types, + pfd->include_nondeduced_p)) return error_mark_node; break; case METHOD_TYPE: /* Since we're not going to walk subtrees, we have to do this explicitly here. */ - if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data, - pfd->visited, pfd->include_nondeduced_p)) + if (walk_template_parms (TYPE_METHOD_BASETYPE (t), fn, data, + pfd->visited, pfd->check_types, + pfd->include_nondeduced_p)) return error_mark_node; /* Fall through. */ case FUNCTION_TYPE: /* Check the return type. */ - if (for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited, - pfd->include_nondeduced_p)) + if (walk_template_parms (TREE_TYPE (t), fn, data, + pfd->visited, pfd->check_types, + pfd->include_nondeduced_p)) return error_mark_node; /* Check the parameter types. Since default arguments are not @@ -7823,8 +7838,9 @@ static tree tree parm; for (parm = TYPE_ARG_TYPES (t); parm; parm = TREE_CHAIN (parm)) - if (for_each_template_parm (TREE_VALUE (parm), fn, data, - pfd->visited, pfd->include_nondeduced_p)) + if (walk_template_parms (TREE_VALUE (parm), fn, data, + pfd->visited, pfd->check_types, + pfd->include_nondeduced_p)) return error_mark_node; /* Since we've already handled the TYPE_ARG_TYPES, we don't @@ -7836,37 +7852,48 @@ static tree case TYPEOF_TYPE: case UNDERLYING_TYPE: if (pfd->include_nondeduced_p - && for_each_template_parm (TYPE_FIELDS (t), fn, data, - pfd->visited, - pfd->include_nondeduced_p)) + && walk_template_parms (TYPE_FIELDS (t), fn, data, + pfd->visited, pfd->check_types, + pfd->include_nondeduced_p)) return error_mark_node; break; case FUNCTION_DECL: case VAR_DECL: - if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t) - && for_each_template_parm (DECL_TI_ARGS (t), fn, data, - pfd->visited, pfd->include_nondeduced_p)) + case FIELD_DECL: + if ((TREE_CODE (t) == FIELD_DECL + || DECL_LANG_SPECIFIC (t)) && DECL_TEMPLATE_INFO (t) + && walk_template_parms (DECL_TI_ARGS (t), fn, data, + pfd->visited, pfd->check_types, + pfd->include_nondeduced_p)) return error_mark_node; /* Fall through. */ case PARM_DECL: case CONST_DECL: if (TREE_CODE (t) == CONST_DECL && DECL_TEMPLATE_PARM_P (t) - && for_each_template_parm (DECL_INITIAL (t), fn, data, - pfd->visited, pfd->include_nondeduced_p)) + && walk_template_parms (DECL_INITIAL (t), fn, data, + pfd->visited, pfd->check_types, + pfd->include_nondeduced_p)) return error_mark_node; if (DECL_CONTEXT (t) && pfd->include_nondeduced_p - && for_each_template_parm (DECL_CONTEXT (t), fn, data, - pfd->visited, pfd->include_nondeduced_p)) + && walk_template_parms (DECL_CONTEXT (t), fn, data, + pfd->visited, pfd->check_types, + pfd->include_nondeduced_p)) return error_mark_node; + if (pfd->check_types && TREE_TYPE (t) + && walk_template_parms (TREE_TYPE(t), fn, data, + pfd->visited, pfd->check_types, + pfd->include_nondeduced_p)) + return error_mark_node; break; case BOUND_TEMPLATE_TEMPLATE_PARM: /* Record template parameters such as `T' inside `TT'. */ - if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data, pfd->visited, - pfd->include_nondeduced_p)) + if (walk_template_parms (TYPE_TI_ARGS (t), fn, data, + pfd->visited, pfd->check_types, + pfd->include_nondeduced_p)) return error_mark_node; /* Fall through. */ @@ -7882,8 +7909,9 @@ static tree case TEMPLATE_DECL: /* A template template parameter is encountered. */ if (DECL_TEMPLATE_TEMPLATE_PARM_P (t) - && for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited, - pfd->include_nondeduced_p)) + && walk_template_parms (TREE_TYPE (t), fn, data, + pfd->visited, pfd->check_types, + pfd->include_nondeduced_p)) return error_mark_node; /* Already substituted template template parameter */ @@ -7892,44 +7920,27 @@ static tree case TYPENAME_TYPE: if (!fn - || for_each_template_parm (TYPENAME_TYPE_FULLNAME (t), fn, - data, pfd->visited, - pfd->include_nondeduced_p)) + || walk_template_parms (TYPENAME_TYPE_FULLNAME (t), fn, + data, pfd->visited, pfd->check_types, + pfd->include_nondeduced_p)) return error_mark_node; break; case CONSTRUCTOR: if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)) && pfd->include_nondeduced_p - && for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE - (TREE_TYPE (t)), fn, data, - pfd->visited, pfd->include_nondeduced_p)) + && walk_template_parms (TYPE_PTRMEMFUNC_FN_TYPE + (TREE_TYPE (t)), fn, data, + pfd->visited, pfd->check_types, + pfd->include_nondeduced_p)) return error_mark_node; - break; - - case INDIRECT_REF: - case COMPONENT_REF: - /* If there's no type, then this thing must be some expression - involving template parameters. */ - if (!fn && !TREE_TYPE (t)) + else if (pfd->check_types && TREE_TYPE (t) + && walk_template_parms (TREE_TYPE (t), fn, data, + pfd->visited, pfd->check_types, + pfd->include_nondeduced_p)) return error_mark_node; break; - case MODOP_EXPR: - case CAST_EXPR: - case IMPLICIT_CONV_EXPR: - case REINTERPRET_CAST_EXPR: - case CONST_CAST_EXPR: - case STATIC_CAST_EXPR: - case DYNAMIC_CAST_EXPR: - case ARROW_EXPR: - case DOTSTAR_EXPR: - case TYPEID_EXPR: - case PSEUDO_DTOR_EXPR: - if (!fn) - return error_mark_node; - break; - default: break; } @@ -7938,35 +7949,41 @@ static tree return NULL_TREE; } -/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, - BOUND_TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX in T, - call FN with the parameter and the DATA. - If FN returns nonzero, the iteration is terminated, and - for_each_template_parm returns 1. Otherwise, the iteration - continues. If FN never returns a nonzero value, the value - returned by for_each_template_parm is 0. If FN is NULL, it is - considered to be the function which always returns 1. +/* Walk T looking for TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, + BOUND_TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX. + If CHECK_TYPES, return 1 if any, 0 otherwise. + + If FN is non-null, for each the iteration calls FN with the parameter + and the DATA. If FN returns nonzero, the iteration is terminated, + and walk_template_parms returns 1. Otherwise, the iteration continues. + If FN never returns a nonzero value, the value returned by + walk_template_parms is 0. If FN is NULL, it is considered to be the + function which always returns 1. + If INCLUDE_NONDEDUCED_P, then this routine will also visit template parameters that occur in non-deduced contexts. When false, only visits those template parameters that can be deduced. */ static int -for_each_template_parm (tree t, tree_fn_t fn, void* data, - struct pointer_set_t *visited, - bool include_nondeduced_p) +walk_template_parms (tree t, tree_fn_t fn, void* data, + struct pointer_set_t *visited, + bool check_types, bool include_nondeduced_p) { struct pair_fn_data pfd; int result; + gcc_assert (!check_types || !fn); + /* Set up. */ pfd.fn = fn; pfd.data = data; + pfd.check_types = check_types; pfd.include_nondeduced_p = include_nondeduced_p; /* Walk the tree. (Conceptually, we would like to walk without - duplicates, but for_each_template_parm_r recursively calls - for_each_template_parm, so we would need to reorganize a fair + duplicates, but walk_template_parms_r recursively calls + walk_template_parms, so we would need to reorganize a fair bit to use walk_tree_without_duplicates, so we keep our own visited list.) */ if (visited) @@ -7974,7 +7991,7 @@ static int else pfd.visited = pointer_set_create (); result = cp_walk_tree (&t, - for_each_template_parm_r, + walk_template_parms_r, &pfd, pfd.visited) != NULL_TREE; @@ -8035,8 +8052,9 @@ uses_template_parms (tree t) int uses_template_parms_level (tree t, int level) { - return for_each_template_parm (t, template_parm_this_level_p, &level, NULL, - /*include_nondeduced_p=*/true); + return walk_template_parms (t, template_parm_this_level_p, &level, NULL, + /*check_types=*/false, + /*include_nondeduced_p=*/true); } /* Returns TRUE iff INST is an instantiation we don't need to do in an @@ -19744,6 +19762,27 @@ type_dependent_expression_p (tree expression) return (dependent_type_p (TREE_TYPE (expression))); } +/* Returns TRUE if the EXPRESSION is instantiation-dependent, in the + sense defined by the ABI: + + "An expression is instantiation-dependent if it is type-dependent + or value-dependent, or it has a subexpression that is type-dependent + or value-dependent." */ + +bool +instantiation_dependent_expression_p (tree expression) +{ + if (!processing_template_decl) + return false; + + if (expression == error_mark_node) + return false; + + return walk_template_parms (expression, /*fn=*/NULL, NULL, NULL, + /*check_types=*/true, + /*include_nondeduced_p=*/true); +} + /* Like type_dependent_expression_p, but it also works while not processing a template definition, i.e. during substitution or mangling. */ Index: semantics.c =================================================================== --- semantics.c (revision 187012) +++ semantics.c (working copy) @@ -5168,8 +5168,7 @@ finish_decltype_type (tree expr, bool id_expressio return error_mark_node; } - /* FIXME instantiation-dependent */ - if (type_dependent_expression_p (expr) + if (instantiation_dependent_expression_p (expr) /* In a template, a COMPONENT_REF has an IDENTIFIER_NODE for op1 even if it isn't dependent, so that we can check access control at instantiation time, so defer the decltype as well (PR 42277). */ @@ -8171,7 +8170,7 @@ potential_constant_expression_1 (tree t, bool want /* -- a reinterpret_cast. FIXME not implemented, and this rule may change to something more specific to type-punning (DR 1312). */ { - tree from = TREE_OPERAND (t, 0); + tree from = TREE_OPERAND (t, 0); return (potential_constant_expression_1 (from, TREE_CODE (t) != VIEW_CONVERT_EXPR, flags)); } Index: cp-tree.h =================================================================== --- cp-tree.h (revision 187012) +++ cp-tree.h (working copy) @@ -5363,6 +5363,7 @@ extern bool any_type_dependent_arguments_p (c extern bool any_type_dependent_elements_p (const_tree); extern bool type_dependent_expression_p_push (tree); extern bool value_dependent_expression_p (tree); +extern bool instantiation_dependent_expression_p(tree); extern bool any_value_dependent_elements_p (const_tree); extern bool dependent_omp_for_p (tree, tree, tree, tree); extern tree resolve_typename_type (tree, bool);