From patchwork Tue Sep 28 11:28:34 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dodji Seketeli X-Patchwork-Id: 65959 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 E98A1B70A8 for ; Tue, 28 Sep 2010 21:28:54 +1000 (EST) Received: (qmail 19091 invoked by alias); 28 Sep 2010 11:28:53 -0000 Received: (qmail 19066 invoked by uid 22791); 28 Sep 2010 11:28:47 -0000 X-SWARE-Spam-Status: No, hits=-5.3 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, TW_RG, 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; Tue, 28 Sep 2010 11:28:39 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o8SBSciB018780 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 28 Sep 2010 07:28:38 -0400 Received: from adjoa.redhat.com (ovpn-113-54.phx2.redhat.com [10.3.113.54]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o8SBSYuF031388; Tue, 28 Sep 2010 07:28:35 -0400 From: Dodji Seketeli To: Jason Merrill Cc: "H.J. Lu" , Paolo Carlini , GCC Patches Subject: Re: Require canonical type comparison for typedefs again. References: <4C630F87.9060303@redhat.com> <4C640257.4080804@redhat.com> <4C9673B7.5010505@oracle.com> <4C97C9E5.2090907@redhat.com> <4C9E863C.30208@redhat.com> X-URL: http://www.seketeli.net/~dodji Date: Tue, 28 Sep 2010 13:28:34 +0200 In-Reply-To: (Dodji Seketeli's message of "Tue, 28 Sep 2010 13:25:57 +0200") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) MIME-Version: 1.0 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 In my previous email, I forgot to insert the fully updated patch. Here it is. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index c594d6a..1537786 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -6673,7 +6673,7 @@ build_self_reference (void) DECL_CONTEXT (value) = current_class_type; DECL_ARTIFICIAL (value) = 1; SET_DECL_SELF_REFERENCE_P (value); - cp_set_underlying_type (value); + set_underlying_type (value); if (processing_template_decl) value = push_template_decl (value); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index c78beb7..cf936d2 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3954,6 +3954,8 @@ enum tsubst_flags { when issuing other errors. */ /* Do not instantiate classes (used by count_non_default_template_args). */ tf_no_class_instantiations = 1 << 8, + tf_no_tpl_reduce = 1 << 9, /* Do not reduce the level of + template parameters. */ /* Convenient substitution flags combinations. */ tf_warning_or_error = tf_warning | tf_error }; @@ -4321,10 +4323,13 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG }; (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE))) #define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \ (TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE))) -/* The list of template parms that a given template parameter of type - TEMPLATE_TYPE_PARM belongs to.*/ -#define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \ - (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval + +/* The length of the template parms list this template parm belongs + to. This is a an integer wrapped into a tree node. */ +#define TEMPLATE_NUM_SIBLING_PARMS(NODE) \ + (TREE_CHECK3 ((NODE), TEMPLATE_TYPE_PARM, \ + TEMPLATE_TEMPLATE_PARM, \ + BOUND_TEMPLATE_TEMPLATE_PARM))->type.maxval /* These constants can used as bit flags in the process of tree formatting. @@ -5005,7 +5010,7 @@ extern void append_type_to_template_for_access_check (tree, tree, tree, extern tree splice_late_return_type (tree, tree); extern bool is_auto (const_tree); extern tree process_template_parm (tree, location_t, tree, - bool, bool); + bool, bool, unsigned); extern tree end_template_parm_list (tree); extern void end_template_decl (void); extern tree maybe_update_decl_type (tree, tree); @@ -5341,7 +5346,6 @@ extern bool type_has_nontrivial_copy_init (const_tree); extern bool class_tmpl_impl_spec_p (const_tree); extern int zero_init_p (const_tree); extern tree strip_typedefs (tree); -extern void cp_set_underlying_type (tree); extern tree copy_binfo (tree, tree, tree, tree *, int); extern int member_p (const_tree); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 63197705..1c6bbbe 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -879,7 +879,7 @@ grokfield (const cp_declarator *declarator, if (declspecs->specs[(int)ds_typedef] && TREE_TYPE (value) != error_mark_node && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value) - cp_set_underlying_type (value); + set_underlying_type (value); return value; } diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 41feb57..a044659 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -872,7 +872,7 @@ pushdecl_maybe_friend (tree x, bool is_friend) inlining. */ && (!TYPE_NAME (type) || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x)))) - cp_set_underlying_type (x); + set_underlying_type (x); if (type != error_mark_node && TYPE_NAME (type) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 9385344..b8c35b3 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -10997,6 +10997,15 @@ cp_parser_template_parameter_list (cp_parser* parser) tree parameter_list = NULL_TREE; begin_template_parm_list (); + + /* The loop below parses the template parms. Note that dependent + types created during this parsing require structural comparison + rather than canonical type comparison. This is because we first + need to know the total number of template parms to be able to + compute canonical types of each dependent type. So after the + loop, when we know the total number of template parms, + end_template_parm_list computes the proper canonical types and + fixes up the dependent types accordingly. */ while (true) { tree parameter; @@ -11015,11 +11024,11 @@ cp_parser_template_parameter_list (cp_parser* parser) parm_loc, parameter, is_non_type, - is_parameter_pack); + is_parameter_pack, + 0); else { tree err_parm = build_tree_list (parameter, parameter); - TREE_VALUE (err_parm) = error_mark_node; parameter_list = chainon (parameter_list, err_parm); } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f5e09ee..bf13978 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -93,10 +93,14 @@ static GTY ((param_is (spec_entry))) static GTY ((param_is (spec_entry))) htab_t type_specializations; -/* Contains canonical template parameter types. The vector is indexed by - the TEMPLATE_TYPE_IDX of the template parameter. Each element is a - TREE_LIST, whose TREE_VALUEs contain the canonical template - parameters of various types and levels. */ +/* Contains canonical template parameter types. The vector is indexed + by the TEMPLATE_TYPE_IDX of the template parameter. Each element is + a TREE_LIST, whose TREE_PURPOSE is a INT_CST tree representing a + total size of the template parameter list a given template + parameter would belong too, and whose TREE_VALUEs contain the + canonical template parameters of various types and levels, + belonging to a set of template parameters which size is + TREE_PURPOSE. */ static GTY(()) VEC(tree,gc) *canonical_template_parms; #define UNIFY_ALLOW_NONE 0 @@ -190,6 +194,9 @@ static void append_type_to_template_for_access_check_1 (tree, tree, tree, static hashval_t iterative_hash_template_arg (tree arg, hashval_t val); static tree listify (tree); static tree listify_autos (tree, tree); +static tree current_template_args (void); +static void fixup_template_parms_canonical_types (void); +static tree tsubst_template_parm (tree, tree, tsubst_flags_t); /* Make the current scope suitable for access checking when we are processing T. T can be FUNCTION_DECL for instantiated function @@ -3369,12 +3376,25 @@ build_template_parm_index (int index, /* Find the canonical type parameter for the given template type parameter. Returns the canonical type parameter, which may be TYPE - if no such parameter existed. */ + if no such parameter existed. TOTAL_NUM_PARMS is the number of + template parameters carried by the considered template. + + If TYPE is the template parameter at position P in a + template, this function won't return the same canonical type as for + a another TYPE that would be a template parameter at position Q, + with Q != P. + + If TOTAL_NUM_PARMS is 0, the function returns NULL_TREE. */ + static tree -canonical_type_parameter (tree type) +canonical_type_parameter (tree type, unsigned total_num_parms) { tree list; int idx = TEMPLATE_TYPE_IDX (type); + + if (total_num_parms == 0) + return NULL_TREE; + if (!canonical_template_parms) canonical_template_parms = VEC_alloc (tree, gc, idx+1); @@ -3382,15 +3402,20 @@ canonical_type_parameter (tree type) VEC_safe_push (tree, gc, canonical_template_parms, NULL_TREE); list = VEC_index (tree, canonical_template_parms, idx); - while (list && !comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL)) - list = TREE_CHAIN (list); + while (list) + { + if (TREE_INT_CST_LOW (TREE_PURPOSE (list)) == total_num_parms + && comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL)) + break; + list = TREE_CHAIN (list); + } if (list) return TREE_VALUE (list); else { VEC_replace(tree, canonical_template_parms, idx, - tree_cons (NULL_TREE, type, + tree_cons (size_int (total_num_parms), type, VEC_index (tree, canonical_template_parms, idx))); return type; } @@ -3438,15 +3463,21 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args, return TEMPLATE_PARM_DESCENDANTS (index); } -/* Process information from new template parameter PARM and append it to the - LIST being built. This new parameter is a non-type parameter iff - IS_NON_TYPE is true. This new parameter is a parameter - pack iff IS_PARAMETER_PACK is true. The location of PARM is in - PARM_LOC. */ +/* Process information from new template parameter PARM and append it + to the LIST being built. This new parameter is a non-type + parameter iff IS_NON_TYPE is true. This new parameter is a + parameter pack iff IS_PARAMETER_PACK is true. The location of PARM + is in PARM_LOC. NUM_TEMPLATE_PARMS is the size of the template + parameter list PARM belongs to. This is used used to create a + proper canonical type for the type of PARM that is to be created, + iff PARM is a type. If the size is not known, this parameter can + be set to 0. Setting it to zero would create a template type + parameter with no canonical type. */ tree -process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type, - bool is_parameter_pack) +process_template_parm (tree list, location_t parm_loc, tree parm, + bool is_non_type, bool is_parameter_pack, + unsigned num_template_parms) { tree decl = 0; tree defval; @@ -3556,8 +3587,9 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty processing_template_decl, decl, TREE_TYPE (parm)); TEMPLATE_TYPE_PARAMETER_PACK (t) = is_parameter_pack; - TYPE_CANONICAL (t) = canonical_type_parameter (t); - } + TYPE_CANONICAL (t) = + canonical_type_parameter (t, num_template_parms); + } DECL_ARTIFICIAL (decl) = 1; SET_DECL_TEMPLATE_PARM_P (decl); pushdecl (decl); @@ -3573,9 +3605,9 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty tree end_template_parm_list (tree parms) { - int nparms; + int nparms, length = list_length (parms); tree parm, next; - tree saved_parmlist = make_tree_vec (list_length (parms)); + tree saved_parmlist = make_tree_vec (length); current_template_parms = tree_cons (size_int (processing_template_decl), @@ -3586,16 +3618,141 @@ end_template_parm_list (tree parms) next = TREE_CHAIN (parm); TREE_VEC_ELT (saved_parmlist, nparms) = parm; TREE_CHAIN (parm) = NULL_TREE; - if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL) - TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) = - current_template_parms; + if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL + || TREE_CODE (TREE_VALUE (parm)) == TEMPLATE_DECL) + TEMPLATE_NUM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) = + size_int (length); } + fixup_template_parms_canonical_types (); + --processing_template_parmlist; return saved_parmlist; } +/* Walk current the template parms and properly compute the canonical + types of the dependent types created during + cp_parser_template_parameter_list. */ + +static void +fixup_template_parms_canonical_types (void) +{ + tree parm; + tree full_template_args; + tree parameter_vec; + int i, num_parms; + + parameter_vec = INNERMOST_TEMPLATE_PARMS (current_template_parms); + if (parameter_vec == NULL_TREE) + return; + + num_parms = TREE_VEC_LENGTH (parameter_vec); + + /* In this first loop, let's update the canonical type of each + type template parameter. */ + for (i = 0; i < num_parms; ++i) + { + tree main_type, variant; + + parm = TREE_VALUE (TREE_VEC_ELT (parameter_vec, i)); + if (TREE_CODE (parm) == TYPE_DECL + || TREE_CODE (parm) == TEMPLATE_DECL) + { + if (TREE_CODE (parm) == TEMPLATE_DECL) + { + tree arglist = current_template_args (); + tree tparms; + int j; + + /* So PARM is a template tempate parameter, e.g, like TT + in: + + template class TT> class S; + + In this case we want to substitute T into the + template parameters of TT. + + Sot let's walk the template parms of PARM here, and + tsubst ARGLIST into into each of the template + parms. */ + tparms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (parm)); + for (j = 0; j < TREE_VEC_LENGTH (tparms); ++j) + { + tree substed_parm; + ++cp_unevaluated_operand; + /* Note the use of tf_no_tpl_reduce as the last + argument to tsubst_template_parm here. Suppose + the current template parameter of PARM is itself + a template. In that case, we do not want + tsubst_template_parm to reduce the level of the + parameters of that later template , as tsubst or + tsubst_template_parms would normally do [because + we are not tsubsting here for the purpose of + instantiating a type, rather, we just want to + substitute template parameters "in + place"]. Therefore, we use tf_no_tpl_reduce to + really avoid that template parm level + reduction. */ + substed_parm = tsubst_template_parm (TREE_VEC_ELT (tparms, j), + arglist, + tf_no_tpl_reduce); + --cp_unevaluated_operand; + TREE_VEC_ELT (tparms, j) = substed_parm; + } + } + + /* Compute the canonical type of type template + parameters and their variants. */ + main_type = TYPE_MAIN_VARIANT (TREE_TYPE (parm)); + TYPE_CANONICAL (main_type) = + canonical_type_parameter (main_type, num_parms); + for (variant = TYPE_NEXT_VARIANT (main_type); + variant; + variant = TYPE_NEXT_VARIANT (variant)) + TYPE_CANONICAL (variant) = + canonical_type_parameter (variant, num_parms); + } + } + + /* And now let's substitute the template type parameters into + dependent non-type template arguments and default template + arguments. */ + full_template_args = current_template_args (); + for (i = 0; i < num_parms; ++i) + { + tree cur = TREE_VEC_ELT (parameter_vec, i); + + if ((TREE_CODE (parm) == TYPE_DECL + || TREE_CODE (parm) == TEMPLATE_DECL) + && TREE_PURPOSE (cur)) + { + tree default_arg = TREE_PURPOSE (cur); + + if (TYPE_P (default_arg) + && !dependent_type_p (default_arg)) + continue; + + ++cp_unevaluated_operand; + TREE_PURPOSE (cur) = + tsubst_expr (default_arg, full_template_args, + tf_none, default_arg, false); + --cp_unevaluated_operand; + } + + if (TREE_CODE (TREE_VALUE (cur)) == PARM_DECL) + { + tree non_type_parm = TREE_VALUE (cur); + ++cp_unevaluated_operand; + TREE_VALUE (cur) = + tsubst_decl (non_type_parm, + full_template_args, + tf_none); + --cp_unevaluated_operand; + } + } +} + /* end_template_decl is called after a template declaration is seen. */ void @@ -3706,7 +3863,23 @@ current_template_args (void) else args = a; } - + + if (length > 1 && TREE_VEC_ELT (args, 0) == NULL_TREE) + /* This can happen for template parms of a template template + parameter, e.g: + + template class TT> struct S; + + Consider the level of the parms of TT; T and U both have + level 2; TT has no template parm of level 1. So in this case + the first element of full_template_args is NULL_TREE. If we + leave it like this TMPL_ARG_DEPTH on args returns 1 instead + of 2. This will make tsubst wrongly consider that T and U + have level 1. Instead, let's create a dummy vector as the + first element of full_template_args so that TMPL_ARG_DEPTH + returns the correct depth for args. + */ + TREE_VEC_ELT (args, 0) = make_tree_vec (1); return args; } @@ -6681,16 +6854,22 @@ lookup_template_class (tree d1, if (context == current_function_decl) pushtag (DECL_NAME (gen_tmpl), t, /*tag_scope=*/ts_current); - if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist)) + if (any_template_arguments_need_structural_equality_p (arglist)) + /* Some of the template arguments require structural + equality testing, so this template class requires + structural equality testing. Note that we check this + condition first because for dependent types that are + created /during/ the parsing of template parameter lists, + we must not require canonical type equality because + canonical types of dependent types are actually going + to be properly computed right at /the end/ of the + template parms parsing. */ + SET_TYPE_STRUCTURAL_EQUALITY (t); + else if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist)) /* This instantiation is another name for the primary template type. Set the TYPE_CANONICAL field appropriately. */ TYPE_CANONICAL (t) = template_type; - else if (any_template_arguments_need_structural_equality_p (arglist)) - /* Some of the template arguments require structural - equality testing, so this template class requires - structural equality testing. */ - SET_TYPE_STRUCTURAL_EQUALITY (t); } /* If we called start_enum or pushtag above, this information @@ -8722,6 +8901,7 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain) { tree r = NULL_TREE; tree* new_parms; + bool reduce_level_p = !(complain & tf_no_tpl_reduce); /* When substituting into a template, we must set PROCESSING_TEMPLATE_DECL as the template parameters may be @@ -8730,19 +8910,18 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain) ++processing_template_decl; for (new_parms = &r; - TMPL_PARMS_DEPTH (parms) > TMPL_ARGS_DEPTH (args); + ((reduce_level_p && TMPL_PARMS_DEPTH (parms) > TMPL_ARGS_DEPTH (args)) + ||(!reduce_level_p && parms)); new_parms = &(TREE_CHAIN (*new_parms)), parms = TREE_CHAIN (parms)) { tree new_vec = make_tree_vec (TREE_VEC_LENGTH (TREE_VALUE (parms))); - int i; + int i, new_level; for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i) { tree tuple; - tree default_value; - tree parm_decl; if (parms == error_mark_node) continue; @@ -8752,23 +8931,16 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain) if (tuple == error_mark_node) continue; - default_value = TREE_PURPOSE (tuple); - parm_decl = TREE_VALUE (tuple); - - parm_decl = tsubst (parm_decl, args, complain, NULL_TREE); - if (TREE_CODE (parm_decl) == PARM_DECL - && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain)) - parm_decl = error_mark_node; - default_value = tsubst_template_arg (default_value, args, - complain, NULL_TREE); - - tuple = build_tree_list (default_value, parm_decl); - TREE_VEC_ELT (new_vec, i) = tuple; + TREE_VEC_ELT (new_vec, i) = + tsubst_template_parm (tuple, args, complain); } + new_level = reduce_level_p + ? TMPL_PARMS_DEPTH (parms) - TMPL_ARGS_DEPTH (args) + : TMPL_PARMS_DEPTH (parms); + *new_parms = - tree_cons (size_int (TMPL_PARMS_DEPTH (parms) - - TMPL_ARGS_DEPTH (args)), + tree_cons (size_int (new_level), new_vec, NULL_TREE); } @@ -8777,6 +8949,36 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain) return r; } +/* Return the result of substituting ARGS into one template parameter + given by T. T Must be a TREE_LIST which TREE_VALUE is the template + parameter and which TREE_PURPOSE is the default argument of the + template parameter. */ + +static tree +tsubst_template_parm (tree t, tree args, tsubst_flags_t complain) +{ + tree default_value, parm_decl; + + if (args == NULL_TREE + || t == NULL_TREE + || t == error_mark_node) + return t; + + gcc_assert (TREE_CODE (t) == TREE_LIST); + + default_value = TREE_PURPOSE (t); + parm_decl = TREE_VALUE (t); + + parm_decl = tsubst (parm_decl, args, complain, NULL_TREE); + if (TREE_CODE (parm_decl) == PARM_DECL + && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain)) + parm_decl = error_mark_node; + default_value = tsubst_template_arg (default_value, args, + complain, NULL_TREE); + + return build_tree_list (default_value, parm_decl); +} + /* Substitute the ARGS into the indicated aggregate (or enumeration) type T. If T is not an aggregate or enumeration type, it is handled as if by tsubst. IN_DECL is as for tsubst. If @@ -10271,9 +10473,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) else { r = copy_type (t); - TEMPLATE_TYPE_PARM_INDEX (r) - = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t), - r, levels, args, complain); + if (!(complain & tf_no_tpl_reduce)) + TEMPLATE_TYPE_PARM_INDEX (r) + = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t), + r, levels, args, complain); TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r); TYPE_MAIN_VARIANT (r) = r; TYPE_POINTER_TO (r) = NULL_TREE; @@ -10291,7 +10494,14 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) else if (TYPE_STRUCTURAL_EQUALITY_P (t)) SET_TYPE_STRUCTURAL_EQUALITY (r); else - TYPE_CANONICAL (r) = canonical_type_parameter (r); + { + unsigned num_parms = + (TEMPLATE_NUM_SIBLING_PARMS (t)) + ? TREE_INT_CST_LOW (TEMPLATE_NUM_SIBLING_PARMS (t)) + : 0; + TYPE_CANONICAL (r) = + canonical_type_parameter (r, num_parms); + } if (code == BOUND_TEMPLATE_TEMPLATE_PARM) { @@ -10307,7 +10517,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) break; case TEMPLATE_PARM_INDEX: - r = reduce_template_parm_level (t, type, levels, args, complain); + if (complain & tf_no_tpl_reduce) + r = t; + else + r = reduce_template_parm_level (t, type, levels, args, complain); break; default: @@ -14701,6 +14914,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) { tree parmvec = TYPE_TI_ARGS (parm); tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg)); + tree full_argvec = add_to_template_args (targs, argvec); tree parm_parms = DECL_INNERMOST_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm)); @@ -14735,7 +14949,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) the global operator+ will be used; if they are not, the Lvalue_proxy will be converted to float. */ if (coerce_template_parms (parm_parms, - argvec, + full_argvec, TYPE_TI_TEMPLATE (parm), tf_none, /*require_all_args=*/true, @@ -17781,7 +17995,8 @@ type_dependent_expression_p (tree expression) if (!processing_template_decl) return false; - if (expression == error_mark_node) + if (expression == error_mark_node + || expression == NULL_TREE) return false; /* An unresolved name is always dependent. */ @@ -18401,7 +18616,7 @@ make_auto (void) TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index (0, processing_template_decl + 1, processing_template_decl + 1, TYPE_NAME (au), NULL_TREE); - TYPE_CANONICAL (au) = canonical_type_parameter (au); + TYPE_CANONICAL (au) = canonical_type_parameter (au, 0); DECL_ARTIFICIAL (TYPE_NAME (au)) = 1; SET_DECL_TEMPLATE_PARM_P (TYPE_NAME (au)); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index ea01d1f..580ebf3 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1063,22 +1063,6 @@ strip_typedefs (tree t) return cp_build_qualified_type (result, cp_type_quals (t)); } -/* Setup a TYPE_DECL node as a typedef representation. - See comments of set_underlying_type in c-common.c. */ - -void -cp_set_underlying_type (tree t) -{ - set_underlying_type (t); - /* If T is a template type parm, make it require structural equality. - This is useful when comparing two template type parms, - because it forces the comparison of the template parameters of their - decls. */ - if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM) - SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t)); -} - - /* Makes a copy of BINFO and TYPE, which is to be inherited into a graph dominated by T. If BINFO is NULL, TYPE is a dependent base, and we do a shallow copy. If BINFO is non-NULL, we do a deep copy. diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 019c51e..5238a01 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1143,114 +1143,20 @@ comp_template_parms_position (tree t1, tree t2) || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM || TREE_CODE (t1) == TEMPLATE_TYPE_PARM)); - if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2) - || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2) - || (TEMPLATE_TYPE_PARAMETER_PACK (t1) - != TEMPLATE_TYPE_PARAMETER_PACK (t2))) - return false; - - return true; -} - -/* Subroutine of incompatible_dependent_types_p. - Return the template parameter of the dependent type T. - If T is a typedef, return the template parameters of - the _decl_ of the typedef. T must be a dependent type. */ - -static tree -get_template_parms_of_dependent_type (tree t) -{ - tree tinfo = NULL_TREE, tparms = NULL_TREE; - - /* First, try the obvious case of getting the - template info from T itself. */ - if ((tinfo = get_template_info (t))) - ; - else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM) - return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t); - else if (typedef_variant_p (t) - && !NAMESPACE_SCOPE_P (TYPE_NAME (t))) - tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t))); - /* If T is a TYPENAME_TYPE which context is a template type - parameter, get the template parameters from that context. */ - else if (TYPE_CONTEXT (t) - && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM) - return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t)); - else if (TYPE_CONTEXT (t) - && !NAMESPACE_SCOPE_P (t)) - tinfo = get_template_info (TYPE_CONTEXT (t)); - - if (tinfo) - tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo)); - - return tparms; -} - -/* Subroutine of structural_comptypes. - Compare the dependent types T1 and T2. - Return TRUE if we are sure they can't be equal, FALSE otherwise. - The whole point of this function is to support cases where either T1 or - T2 is a typedef. In those cases, we need to compare the template parameters - of the _decl_ of the typedef. If those don't match then we know T1 - and T2 cannot be equal. */ - -static bool -incompatible_dependent_types_p (tree t1, tree t2) -{ - tree tparms1 = NULL_TREE, tparms2 = NULL_TREE; - bool t1_typedef_variant_p, t2_typedef_variant_p; - - if (!uses_template_parms (t1) || !uses_template_parms (t2)) - return false; - - if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM) - { - /* If T1 and T2 don't have the same relative position in their - template parameters set, they can't be equal. */ - if (!comp_template_parms_position (t1, t2)) - return true; - } - - t1_typedef_variant_p = typedef_variant_p (t1); - t2_typedef_variant_p = typedef_variant_p (t2); - - /* Either T1 or T2 must be a typedef. */ - if (!t1_typedef_variant_p && !t2_typedef_variant_p) + /* If T1 and T2 belong to template parm lists of different size, + let's assume they are different. */ + if (TEMPLATE_NUM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1)) + != TEMPLATE_NUM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t2))) return false; - if (!t1_typedef_variant_p || !t2_typedef_variant_p) - /* Either T1 or T2 is not a typedef so we cannot compare the - template parms of the typedefs of T1 and T2. - At this point, if the main variant type of T1 and T2 are equal - it means the two types can't be incompatible, from the perspective - of this function. */ - if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) - return false; - - /* So if we reach this point, it means either T1 or T2 is a typedef variant. - Let's compare their template parameters. */ - - tparms1 = get_template_parms_of_dependent_type (t1); - tparms2 = get_template_parms_of_dependent_type (t2); - - /* If T2 is a template type parm and if we could not get the template - parms it belongs to, that means we have not finished parsing the - full set of template parameters of the template declaration it - belongs to yet. If we could get the template parms T1 belongs to, - that mostly means T1 and T2 belongs to templates that are - different and incompatible. */ - if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM - && (tparms1 == NULL_TREE || tparms2 == NULL_TREE) - && tparms1 != tparms2) - return true; - - if (tparms1 == NULL_TREE - || tparms2 == NULL_TREE - || tparms1 == tparms2) + /* Then compare their relative position. */ + if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2) + || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2) + || (TEMPLATE_TYPE_PARAMETER_PACK (t1) + != TEMPLATE_TYPE_PARAMETER_PACK (t2))) return false; - /* And now compare the mighty template parms! */ - return !comp_template_parms (tparms1, tparms2); + return true; } /* Subroutine in comptypes. */ @@ -1295,12 +1201,6 @@ structural_comptypes (tree t1, tree t2, int strict) if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2)) return false; - /* If T1 and T2 are dependent typedefs then check upfront that - the template parameters of their typedef DECLs match before - going down checking their subtypes. */ - if (incompatible_dependent_types_p (t1, t2)) - return false; - /* Allow for two different type nodes which have essentially the same definition. Note that we already checked for equality of the type qualifiers (just above). */ @@ -1345,6 +1245,7 @@ structural_comptypes (tree t1, tree t2, int strict) (DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t1)), DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t2)))) return false; + if (TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM) break; /* Don't check inheritance. */ @@ -1401,8 +1302,10 @@ structural_comptypes (tree t1, tree t2, int strict) break; case TEMPLATE_TYPE_PARM: - /* If incompatible_dependent_types_p called earlier didn't decide - T1 and T2 were different, they might be equal. */ + /* If T1 and T2 don't have the same relative position in their + template parameters set, they can't be equal. */ + if (!comp_template_parms_position (t1, t2)) + return false; break; case TYPENAME_TYPE: diff --git a/gcc/testsuite/g++.dg/template/typedef36.C b/gcc/testsuite/g++.dg/template/typedef36.C new file mode 100644 index 0000000..f6155c1 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typedef36.C @@ -0,0 +1,23 @@ +// Origin: PR c++/45606 +// { dg-do compile } + +#include + +template +class Test +{ +protected: + typedef std::list ListAlias; + ListAlias list; +public: + typedef typename ListAlias::const_iterator const_iterator; + inline const_iterator begin() const; + +}; + +template +inline typename std::list::const_iterator Test::begin() const +{ + return list.begin(); +} +