As presented in the cover message, this patch replaces the BOUND_TEMPLATE_TEMPLATE_PARM tree with a TEMPLATE_ID_TYPE tree that represents a template-id whose arguments haven't yet been applied to its template. The template itself might have not been resolved to a TEMPLATE_DECL yet, in which case it's just an IDENTIFIER_NODE.
The functionality of representing BOUND_TEMPLATE_TEMPLATE_PARM then gets expressed by using a TEMPLATE_ID_TYPE in which the template validates the DECL_TEMPLATE_TEMPLATE_PARAMETER_P predicate. Additionally, the TYPENAME_TYPE_FULLNAME of a TYPENAME_TYPE is also represented using a TEMPLATE_ID_TYPE, rather than a TEMPLATE_ID_EXPR - even when make_typename_type is passed a TEMPLATE_ID_EXPR. Note that the TEMPLATE_ID_TYPE yielded by TYPENAME_TYPE_FULLNAME can either have a TEMPLATE_DECL or just an IDENTIFIER_NODE, depending on if the template name of the template-id could be resolved to a template at the point where the typename was formed or not. Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk. gcc/cp/ PR c++/51239 * cp_tree.def (TEMPLATE_TYPE_PARM): Rename BOUND_TEMPLATE_TEMPLATE_PARM into TEMPLATE_ID_TYPE in comments. (TEMPLATE_ID_TYPE): Renamed BOUND_TEMPLATE_TEMPLATE_PARM into this. Update comments. * cp-tree.h (build_template_id_type): (TEMPLATE_ID_TYPE_TYPE_CHECK): Turn BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK into this. (BOUND_TEMPLATE_TEMPLATE_PARM_P): New predicate macro. (MAYBE_CLASS_TYPE_P): Rename BOUND_TEMPLATE_TEMPLATE_PARM into TEMPLATE_ID_TYPE. (TEMPLATE_ID_TYPE_TEMPLATE_INFO): Turn TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO into this. (TYPE_TEMPLATE_INFO): Support TEMPLATE_ID_TYPE. (SET_TYPE_TEMPLATE_INFO): Update to support TEMPLATE_ID_TYPE, and to better support type aliases. (TYPENAME_TYPE_FULLNAME): Replace TEMPLATE_ID_EXPR with TEMPLATE_ID_TYPE in comments. (TEMPLATE_TYPE_PARM_INDEX): Rename BOUND_TEMPLATE_TEMPLATE_PARM into TEMPLATE_ID_TYPE in the definition of this macro. (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL): Use BOUND_TEMPLATE_TEMPLATE_PARM_P instead of BOUND_TEMPLATE_TEMPLATE_PARM. * cp-objcp-common.c (cp_common_init_ts): Rename BOUND_TEMPLATE_TEMPLATE_PARM into TEMPLATE_ID_TYPE. * cxx-pretty-print.c (pp_cxx_unqualified_id)<TEMPLATE_ID_TYPE>: Renamed BOUND_TEMPLATE_TEMPLATE_PARM into this. (pp_cxx_type_specifier_seq)<TEMPLATE_ID_TYPE>: Likewise. (pp_cxx_direct_abstract_declarator)<TEMPLATE_ID_TYPE>>: Likewise. (pp_cxx_type_id)<TEMPLATE_ID_TYPE>: Likewise. (pp_cxx_canonical_template_parameter): Use BOUND_TEMPLATE_TEMPLATE_PARM_P instead of BOUND_TEMPLATE_TEMPLATE_PARM. * decl.c (make_typename_type): Store unbound template-id in a TEMPLATE_ID_TYPE instead of in a TEMPLATE_ID_EXPR. (check_elaborated_type_specifier): Use BOUND_TEMPLATE_TEMPLATE_PARM_P instead of BOUND_TEMPLATE_TEMPLATE_PARM. * decl2.c (is_late_template_attribute): Use BOUND_TEMPLATE_TEMPLATE_PARM_P instead of BOUND_TEMPLATE_TEMPLATE_PARM. * error.c (dump_type)<TEMPLATE_ID_TYPE>: Replace BOUND_TEMPLATE_TEMPLATE_PARM with this. (dump_typename): Use dump_type on TYPENAME_TYPE_FULLNAME rather than dump_decl. (dump_type_prefix, dump_type_suffix, dump_expr)<TEMPLATE_ID_TYPE>: Replace BOUND_TEMPLATE_TEMPLATE_PARM with this. * lex.c (cxx_make_type): Replace BOUND_TEMPLATE_TEMPLATE_PARM with TEMPLATE_ID_TYPE. * mangle.c (CLASSTYPE_TEMPLATE_ID_P): Replace use of BOUND_TEMPLATE_TEMPLATE_PARM with BOUND_TEMPLATE_TEMPLATE_PARM_P. (write_nested_name, write_prefix): Replace use of TEMPLATE_ID_EXPR with TEMPLATE_ID_TYPE. Use TYPE_TI_ARGS on the TYPENAME_TYPE_FULLNAME rather than TREE_OPERAND. (write_type)<TEMPLATE_ID_TYPE>: Replace BOUND_TEMPLATE_TEMPLATE_PARM with this. Use TYPE_TI_ARGS rather than TI_ARGS of TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO. (write_expression): USe BOUND_TEMPLATE_TEMPLATE_PARM_P instead of BOUND_TEMPLATE_TEMPLATE_PARM. (write_template_param)<TEMPLATE_ID_TYPE>: Replace BOUND_TEMPLATE_TEMPLATE_PARM with this. (write_template_template_param): Use BOUND_TEMPLATE_TEMPLATE_PARM_P instead of BOUND_TEMPLATE_TEMPLATE_PARM, TYPE_TEMPLATE_INFO instead of TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO. * name-lookup.c (arg_assoc_type)<TEMPLATE_ID_TYPE>: Rename BOUND_TEMPLATE_TEMPLATE_PARM into this. * parser.c (cp_parser_nested_name_specifier_opt): Replace TEMPLATE_ID_EXPR with TEMPLATE_ID_TYPE. * pt.c (get_template_info): Use TYPE_TEMPLATE_INFO to get TEMPLATE_INFO from types in general. (maybe_process_partial_specialization): Use BOUND_TEMPLATE_TEMPLATE_PARM_P instead of BOUND_TEMPLATE_TEMPLATE_PARM. (find_parameter_packs_r): Replaced case BOUND_TEMPLATE_TEMPLATE_PARM with case TEMPLATE_ID_TYPE. Check for TYPE_TI_TEMPLATE before walking it. (lookup_template_class_1): Propagate error if arglist is erroneous. (for_each_template_parm_r)<TEMPLATE_ID_TYPE>: Replaced BOUND_TEMPLATE_TEMPLATE_PARM with this. Use BOUND_TEMPLATE_TEMPLATE_PARM_P. (for_each_template_parm): Replace BOUND_TEMPLATE_TEMPLATE_PARM with TEMPLATE_ID_TYPE in comments. (tsubst)<TEMPLATE_ID_TYPE>: Replace BOUND_TEMPLATE_TEMPLATE_PARM with this. Handle TEMPLATE_ID_TYPE. Replace use of TEMPLATE_ID_EXPR in make_typename_type with build_template_id_type. Use BOUND_TEMPLATE_TEMPLATE_PARM_P. (tsubst_copy)<TEMPLATE_ID_TYPE>: Replace use of BOUND_TEMPLATE_TEMPLATE_PARM with this. (template_parm_level_and_index): Replace use of BOUND_TEMPLATE_TEMPLATE_PARM with BOUND_TEMPLATE_TEMPLATE_PARM_P. (unify)<TEMPLATE_ID_TYPE>: Replace use of BOUND_TEMPLATE_TEMPLATE_PARM with this. Use BOUND_TEMPLATE_TEMPLATE_PARM_P. (dependent_type_p_r): Replace use of BOUND_TEMPLATE_TEMPLATE_PARM with BOUND_TEMPLATE_TEMPLATE_PARM_P. (resolve_typename_type): TYPENAME_TYPE_FULLNAME now yields TEMPLATE_ID_TYPE, no more TEMPLATE_ID_EXPR. * ptree.c (cxx_print_type)<TEMPLATE_ID_TYPE>: Replace BOUND_TEMPLATE_TEMPLATE_PARM with this. * search.c (lookup_field_1): Replace use of BOUND_TEMPLATE_TEMPLATE_PARM with BOUND_TEMPLATE_TEMPLATE_PARM_P. * tree.c (build_template_id_type): Define new function. (bind_template_template_parm): Use the new build_template_id_type. (cp_walk_tree)<TEMPLATE_ID_TYPE>: Replace BOUND_TEMPLATE_TEMPLATE_PARM with this. * typeck.c (comp_template_parms_position): Replace use of BOUND_TEMPLATE_TEMPLATE_PARM with BOUND_TEMPLATE_TEMPLATE_PARM_P. (structural_comptypes): Compare TEMPLATE_ID_TYPE nodes not BOUND_TEMPLATE_TEMPLATE_PARM. * typeck2.c (cxx_incomplete_type_diagnostic)<TEMPLATE_ID_TYPE>: Replace BOUND_TEMPLATE_TEMPLATE_PARM with this. Adjust diagnostic. --- gcc/cp/cp-objcp-common.c | 2 +- gcc/cp/cp-tree.def | 17 ++++--- gcc/cp/cp-tree.h | 55 ++++++++++++++-------- gcc/cp/cxx-pretty-print.c | 10 ++-- gcc/cp/decl.c | 22 ++++++--- gcc/cp/decl2.c | 4 +- gcc/cp/error.c | 10 ++-- gcc/cp/lex.c | 2 +- gcc/cp/mangle.c | 26 +++++----- gcc/cp/name-lookup.c | 2 +- gcc/cp/parser.c | 2 +- gcc/cp/pt.c | 114 ++++++++++++++++++++++++++++++--------------- gcc/cp/ptree.c | 6 ++- gcc/cp/search.c | 2 +- gcc/cp/tree.c | 64 +++++++++++++++++-------- gcc/cp/typeck.c | 18 ++++++- gcc/cp/typeck2.c | 13 ++++-- 17 files changed, 237 insertions(+), 132 deletions(-) diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c index a957a03..719ec77 100644 --- a/gcc/cp/cp-objcp-common.c +++ b/gcc/cp/cp-objcp-common.c @@ -246,7 +246,7 @@ cp_common_init_ts (void) MARK_TS_COMMON (TYPE_PACK_EXPANSION); MARK_TS_COMMON (TYPE_ARGUMENT_PACK); MARK_TS_COMMON (DECLTYPE_TYPE); - MARK_TS_COMMON (BOUND_TEMPLATE_TEMPLATE_PARM); + MARK_TS_COMMON (TEMPLATE_ID_TYPE); MARK_TS_COMMON (UNBOUND_CLASS_TEMPLATE); MARK_TS_TYPED (EXPR_PACK_EXPANSION); diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 5fc5496..c68274c 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -172,7 +172,7 @@ DEFTREECODE (TEMPLATE_TEMPLATE_PARM, "template_template_parm", tcc_type, 0) /* The ordering of the following codes is optimized for the checking macros in tree.h. Changing the order will degrade the speed of the compiler. TEMPLATE_TYPE_PARM, TYPENAME_TYPE, TYPEOF_TYPE, - BOUND_TEMPLATE_TEMPLATE_PARM. */ + TEMPLATE_ID_TYPE. */ /* Index into a template parameter list. This parameter must be a type. The type.values field will be a TEMPLATE_PARM_INDEX. */ @@ -180,7 +180,7 @@ DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", tcc_type, 0) /* A type designated by `typename T::t'. TYPE_CONTEXT is `T', TYPE_NAME is an IDENTIFIER_NODE for `t'. If the type was named via - template-id, TYPENAME_TYPE_FULLNAME will hold the TEMPLATE_ID_EXPR. + template-id, TYPENAME_TYPE_FULLNAME will hold the TEMPLATE_ID_TYPE. TREE_TYPE is always NULL. */ DEFTREECODE (TYPENAME_TYPE, "typename_type", tcc_type, 0) @@ -188,12 +188,13 @@ DEFTREECODE (TYPENAME_TYPE, "typename_type", tcc_type, 0) expression in question. */ DEFTREECODE (TYPEOF_TYPE, "typeof_type", tcc_type, 0) -/* Like TEMPLATE_TEMPLATE_PARM it is used with bound template arguments - like TT<int>. - In this case, TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO contains the - template name and its bound arguments. TYPE_NAME is a TYPE_DECL. */ -DEFTREECODE (BOUND_TEMPLATE_TEMPLATE_PARM, "bound_template_template_parm", - tcc_type, 0) +/* A generic type for a template-id (templatename<arguments>) in which + the arguments have not yet been applied to the template. The + TEMPLATE_ID_TYPE_TEMPLATE_INFO accessor returns the TEMPLATE_INFO + of the type, TYPE_TI_TEMPLATE returns the TEMPLATE_DECL of the + type, and TYPE_TI_ARGS returns the arguments. TYPE_NAME is a + TYPE_DECL. */ +DEFTREECODE (TEMPLATE_ID_TYPE, "template_id_type", tcc_type, 0) /* For template template argument of the form `T::template C'. TYPE_CONTEXT is `T', the template parameter dependent object. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 955d0eb..fa5bf7f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -206,8 +206,8 @@ c-common.h, not after. #define VAR_TEMPL_TYPE_FIELD_OR_FUNCTION_DECL_CHECK(NODE) \ TREE_CHECK5(NODE,VAR_DECL,FIELD_DECL,FUNCTION_DECL,TYPE_DECL,TEMPLATE_DECL) -#define BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK(NODE) \ - TREE_CHECK(NODE,BOUND_TEMPLATE_TEMPLATE_PARM) +#define TEMPLATE_ID_TYPE_TYPE_CHECK(NODE) \ + TREE_CHECK(NODE,TEMPLATE_ID_TYPE) #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) #define THUNK_FUNCTION_CHECK(NODE) __extension__ \ @@ -1191,11 +1191,11 @@ enum languages { lang_c, lang_cplusplus, lang_java }; template template parameters. Keep these checks in ascending code order. */ #define MAYBE_CLASS_TYPE_P(T) \ - (TREE_CODE (T) == TEMPLATE_TYPE_PARM \ - || TREE_CODE (T) == TYPENAME_TYPE \ - || TREE_CODE (T) == TYPEOF_TYPE \ - || TREE_CODE (T) == BOUND_TEMPLATE_TEMPLATE_PARM \ - || TREE_CODE (T) == DECLTYPE_TYPE \ + (TREE_CODE (T) == TEMPLATE_TYPE_PARM \ + || TREE_CODE (T) == TYPENAME_TYPE \ + || TREE_CODE (T) == TYPEOF_TYPE \ + || TREE_CODE (T) == TEMPLATE_ID_TYPE \ + || TREE_CODE (T) == DECLTYPE_TYPE \ || CLASS_TYPE_P (T)) /* Set CLASS_TYPE_P for T to VAL. T must be a class, struct, or @@ -2604,8 +2604,8 @@ extern void decl_shadowed_for_var_insert (tree, tree); (TYPE_LANG_SLOT_1 (ENUMERAL_TYPE_CHECK (NODE))) /* Template information for a template template parameter. */ -#define TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO(NODE) \ - (LANG_TYPE_CLASS_CHECK (BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK (NODE)) \ +#define TEMPLATE_ID_TYPE_TEMPLATE_INFO(NODE) \ + (LANG_TYPE_CLASS_CHECK (TEMPLATE_ID_TYPE_TYPE_CHECK (NODE)) \ ->template_info) /* Template information for an ENUMERAL_, RECORD_, UNION_TYPE, or @@ -2620,21 +2620,26 @@ extern void decl_shadowed_for_var_insert (tree, tree); : NULL_TREE) \ : ((TREE_CODE (NODE) == ENUMERAL_TYPE) \ ? ENUM_TEMPLATE_INFO (NODE) \ - : ((TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM) \ - ? TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE) \ + : ((TREE_CODE (NODE) == TEMPLATE_ID_TYPE) \ + ? TEMPLATE_ID_TYPE_TEMPLATE_INFO (NODE) \ : (CLASS_TYPE_P (NODE) \ ? CLASSTYPE_TEMPLATE_INFO (NODE) \ : NULL_TREE)))) - /* Set the template information for an ENUMERAL_, RECORD_, or UNION_TYPE to VAL. */ #define SET_TYPE_TEMPLATE_INFO(NODE, VAL) \ - (TREE_CODE (NODE) == ENUMERAL_TYPE \ - ? (ENUM_TEMPLATE_INFO (NODE) = (VAL)) \ - : ((CLASS_TYPE_P (NODE) && !TYPE_ALIAS_P (NODE)) \ - ? (CLASSTYPE_TEMPLATE_INFO (NODE) = (VAL)) \ - : (DECL_TEMPLATE_INFO (TYPE_NAME (NODE)) = (VAL)))) + (TYPE_ALIAS_P (NODE) \ + ? ((TYPE_NAME (NODE) && DECL_LANG_SPECIFIC (TYPE_NAME (NODE))) \ + ? DECL_TEMPLATE_INFO (TYPE_NAME (NODE)) = (VAL) \ + : NULL_TREE) \ + : ((TREE_CODE (NODE) == ENUMERAL_TYPE) \ + ? ENUM_TEMPLATE_INFO (NODE) = (VAL) \ + : ((TREE_CODE (NODE) == TEMPLATE_ID_TYPE) \ + ? TEMPLATE_ID_TYPE_TEMPLATE_INFO (NODE) = (VAL) \ + : (CLASS_TYPE_P (NODE) \ + ? CLASSTYPE_TEMPLATE_INFO (NODE) = (VAL) \ + : NULL_TREE)))) #define TI_TEMPLATE(NODE) TREE_TYPE (TEMPLATE_INFO_CHECK (NODE)) #define TI_ARGS(NODE) TREE_CHAIN (TEMPLATE_INFO_CHECK (NODE)) @@ -3028,7 +3033,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) /* The name used by the user to name the typename type. Typically, this is an IDENTIFIER_NODE, and the same as the DECL_NAME on the corresponding TYPE_DECL. However, this may also be a - TEMPLATE_ID_EXPR if we had something like `typename X::Y<T>'. */ + TEMPLATE_ID_TYPE if we had something like `typename X::Y<T>'. */ #define TYPENAME_TYPE_FULLNAME(NODE) \ (TYPE_VALUES_RAW (TYPENAME_TYPE_CHECK (NODE))) @@ -3650,6 +3655,15 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define DECL_UNBOUND_CLASS_TEMPLATE_P(NODE) \ (TREE_CODE (NODE) == TEMPLATE_DECL && !DECL_TEMPLATE_RESULT (NODE)) +/* Nonzero if NODE is a TEMPLATE_ID_TYPE representing a bound template + template parameter; that is a template-id whose template is a + template template parameter. */ +#define BOUND_TEMPLATE_TEMPLATE_PARM_P(NODE) \ + ((NODE) != NULL_TREE \ + && TREE_CODE (NODE) == TEMPLATE_ID_TYPE \ + && TYPE_TI_TEMPLATE (NODE) != NULL_TREE \ + && DECL_TEMPLATE_TEMPLATE_PARM_P (TYPE_TI_TEMPLATE (NODE))) + #define DECL_FUNCTION_TEMPLATE_P(NODE) \ (TREE_CODE (NODE) == TEMPLATE_DECL \ && !DECL_UNBOUND_CLASS_TEMPLATE_P (NODE) \ @@ -4503,7 +4517,7 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG }; #define TEMPLATE_TYPE_PARM_INDEX(NODE) \ (TYPE_VALUES_RAW (TREE_CHECK3 ((NODE), TEMPLATE_TYPE_PARM, \ TEMPLATE_TEMPLATE_PARM, \ - BOUND_TEMPLATE_TEMPLATE_PARM))) + TEMPLATE_ID_TYPE))) #define TEMPLATE_TYPE_IDX(NODE) \ (TEMPLATE_PARM_IDX (TEMPLATE_TYPE_PARM_INDEX (NODE))) #define TEMPLATE_TYPE_LEVEL(NODE) \ @@ -4554,7 +4568,7 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG }; /* Returns the TEMPLATE_DECL associated to a TEMPLATE_TEMPLATE_PARM node. */ #define TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL(NODE) \ - ((TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM) \ + (BOUND_TEMPLATE_TEMPLATE_PARM_P (NODE) \ ? TYPE_TI_TEMPLATE (NODE) \ : TYPE_NAME (NODE)) @@ -5666,6 +5680,7 @@ extern bool non_static_member_function_p (tree); extern const char *cxx_printable_name (tree, int); extern const char *cxx_printable_name_translate (tree, int); extern tree build_exception_variant (tree, tree); +extern tree build_template_id_type (tree, tree); extern tree bind_template_template_parm (tree, tree); extern tree array_type_nelts_total (tree); extern tree array_type_nelts_top (tree); diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c index 55cb64b..c71ca0e 100644 --- a/gcc/cp/cxx-pretty-print.c +++ b/gcc/cp/cxx-pretty-print.c @@ -225,7 +225,7 @@ pp_cxx_unqualified_id (cxx_pretty_printer *pp, tree t) pp_cxx_unqualified_id (pp, TEMPLATE_PARM_DECL (t)); break; - case BOUND_TEMPLATE_TEMPLATE_PARM: + case TEMPLATE_ID_TYPE: pp_cxx_cv_qualifier_seq (pp, t); pp_cxx_unqualified_id (pp, TYPE_IDENTIFIER (t)); pp_cxx_begin_template_argument_list (pp); @@ -1295,7 +1295,7 @@ pp_cxx_type_specifier_seq (cxx_pretty_printer *pp, tree t) case TEMPLATE_TYPE_PARM: case TEMPLATE_TEMPLATE_PARM: case TYPE_DECL: - case BOUND_TEMPLATE_TEMPLATE_PARM: + case TEMPLATE_ID_TYPE: pp_cxx_cv_qualifier_seq (pp, t); pp_cxx_simple_type_specifier (pp, t); break; @@ -1687,7 +1687,7 @@ pp_cxx_direct_abstract_declarator (cxx_pretty_printer *pp, tree t) case TYPENAME_TYPE: case TEMPLATE_TYPE_PARM: case TEMPLATE_TEMPLATE_PARM: - case BOUND_TEMPLATE_TEMPLATE_PARM: + case TEMPLATE_ID_TYPE: case UNBOUND_CLASS_TEMPLATE: break; @@ -1713,7 +1713,7 @@ pp_cxx_type_id (cxx_pretty_printer *pp, tree t) case RECORD_TYPE: case ENUMERAL_TYPE: case TYPENAME_TYPE: - case BOUND_TEMPLATE_TEMPLATE_PARM: + case TEMPLATE_ID_TYPE: case UNBOUND_CLASS_TEMPLATE: case TEMPLATE_TEMPLATE_PARM: case TEMPLATE_TYPE_PARM: @@ -2140,7 +2140,7 @@ pp_cxx_canonical_template_parameter (cxx_pretty_printer *pp, tree parm) /* Brings type template parameters to the canonical forms. */ if (code == TEMPLATE_TYPE_PARM || code == TEMPLATE_TEMPLATE_PARM - || code == BOUND_TEMPLATE_TEMPLATE_PARM) + || BOUND_TEMPLATE_TEMPLATE_PARM_P (parm)) parm = TEMPLATE_TYPE_PARM_INDEX (parm); pp_cxx_begin_template_argument_list (pp); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 5a4e027..4b6e903 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3190,15 +3190,16 @@ make_typename_type (tree context, tree name, enum tag_types tag_type, if (TYPE_P (name)) { - if (!(TYPE_LANG_SPECIFIC (name) + if (TREE_CODE (name) == TEMPLATE_ID_TYPE) + /* We use instances of TEMPLATE_ID_TYPE as is. */; + else if (!(TYPE_LANG_SPECIFIC (name) && (CLASSTYPE_IS_TEMPLATE (name) || CLASSTYPE_USE_TEMPLATE (name)))) name = TYPE_IDENTIFIER (name); else - /* Create a TEMPLATE_ID_EXPR for the type. */ - name = build_nt (TEMPLATE_ID_EXPR, - CLASSTYPE_TI_TEMPLATE (name), - CLASSTYPE_TI_ARGS (name)); + /* Create a TEMPLATE_ID_TYPE for the type. */ + name = build_template_id_type (CLASSTYPE_TI_TEMPLATE (name), + CLASSTYPE_TI_ARGS (name)); } else if (TREE_CODE (name) == TYPE_DECL) name = DECL_NAME (name); @@ -3215,12 +3216,17 @@ make_typename_type (tree context, tree name, enum tag_types tag_type, error ("%qD is not a type", name); return error_mark_node; } + fullname = build_template_id_type (TREE_OPERAND (fullname, 0), + TREE_OPERAND (fullname, 1)); } if (TREE_CODE (name) == TEMPLATE_DECL) { error ("%qD used without template parameters", name); return error_mark_node; } + if (TREE_CODE (name) == TEMPLATE_ID_TYPE) + name = TYPE_IDENTIFIER (name); + gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); gcc_assert (TYPE_P (context)); @@ -3246,7 +3252,7 @@ make_typename_type (tree context, tree name, enum tag_types tag_type, if ((!t || TREE_CODE (t) == TREE_LIST) && dependent_type_p (context)) return build_typename_type (context, name, fullname, tag_type); - want_template = TREE_CODE (fullname) == TEMPLATE_ID_EXPR; + want_template = TREE_CODE (fullname) == TEMPLATE_ID_TYPE; if (!t) { @@ -3294,7 +3300,7 @@ make_typename_type (tree context, tree name, enum tag_types tag_type, add_typedef_to_current_template_for_access_check (t, context, input_location); if (want_template) - return lookup_template_class (t, TREE_OPERAND (fullname, 1), + return lookup_template_class (t, TYPE_TI_ARGS (fullname), NULL_TREE, context, /*entering_scope=*/0, tf_warning_or_error | tf_user); @@ -11377,7 +11383,7 @@ check_elaborated_type_specifier (enum tag_types tag_code, } /* Accept bound template template parameters. */ else if (allow_template_p - && TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM) + && BOUND_TEMPLATE_TEMPLATE_PARM_P (type)) ; /* [dcl.type.elab] diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 05f4b42..b677104 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1130,8 +1130,8 @@ is_late_template_attribute (tree attr, tree decl) /* We can't apply any attributes to a completely unknown type until instantiation time. */ enum tree_code code = TREE_CODE (type); - if (code == TEMPLATE_TYPE_PARM - || code == BOUND_TEMPLATE_TEMPLATE_PARM + if (BOUND_TEMPLATE_TEMPLATE_PARM_P (type) + ||code == TEMPLATE_TYPE_PARM || code == TYPENAME_TYPE) return true; /* Also defer most attributes on dependent types. This is not diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 21d6781..20c158f 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -451,7 +451,7 @@ dump_type (tree t, int flags) pp_cxx_canonical_template_parameter (cxx_pp, t); break; - case BOUND_TEMPLATE_TEMPLATE_PARM: + case TEMPLATE_ID_TYPE: { tree args = TYPE_TI_ARGS (t); pp_cxx_cv_qualifier_seq (cxx_pp, t); @@ -570,7 +570,7 @@ dump_typename (tree t, int flags) else dump_type (ctx, flags & ~TFF_CLASS_KEY_OR_ENUM); pp_cxx_colon_colon (cxx_pp); - dump_decl (TYPENAME_TYPE_FULLNAME (t), flags); + dump_type (TYPENAME_TYPE_FULLNAME (t), flags); } /* Return the name of the supplied aggregate, or enumeral type. */ @@ -766,7 +766,7 @@ dump_type_prefix (tree t, int flags) case RECORD_TYPE: case TEMPLATE_TYPE_PARM: case TEMPLATE_TEMPLATE_PARM: - case BOUND_TEMPLATE_TEMPLATE_PARM: + case TEMPLATE_ID_TYPE: case TREE_LIST: case TYPE_DECL: case TREE_VEC: @@ -869,7 +869,7 @@ dump_type_suffix (tree t, int flags) case RECORD_TYPE: case TEMPLATE_TYPE_PARM: case TEMPLATE_TEMPLATE_PARM: - case BOUND_TEMPLATE_TEMPLATE_PARM: + case TEMPLATE_ID_TYPE: case TREE_LIST: case TYPE_DECL: case TREE_VEC: @@ -2407,7 +2407,7 @@ dump_expr (tree t, int flags) case TEMPLATE_TYPE_PARM: case TEMPLATE_TEMPLATE_PARM: - case BOUND_TEMPLATE_TEMPLATE_PARM: + case TEMPLATE_ID_TYPE: dump_type (t, flags); break; diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index c11e3b3..4320e33 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -664,7 +664,7 @@ cxx_make_type (enum tree_code code) /* Create lang_type structure. */ if (RECORD_OR_UNION_CODE_P (code) - || code == BOUND_TEMPLATE_TEMPLATE_PARM) + || code == TEMPLATE_ID_TYPE) { struct lang_type *pi = ggc_alloc_cleared_lang_type (sizeof (struct lang_type)); diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 548998a..7235660 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -83,7 +83,7 @@ along with GCC; see the file COPYING3. If not see without parameters inside the template. */ #define CLASSTYPE_TEMPLATE_ID_P(NODE) \ (TYPE_LANG_SPECIFIC (NODE) != NULL \ - && (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM \ + && (BOUND_TEMPLATE_TEMPLATE_PARM_P (NODE) \ || (CLASSTYPE_TEMPLATE_INFO (NODE) != NULL \ && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE)))))) @@ -935,10 +935,10 @@ write_nested_name (const tree decl) else if (TREE_CODE (TREE_TYPE (decl)) == TYPENAME_TYPE) { tree name = TYPENAME_TYPE_FULLNAME (TREE_TYPE (decl)); - if (TREE_CODE (name) == TEMPLATE_ID_EXPR) + if (TREE_CODE (name) == TEMPLATE_ID_TYPE) { write_template_prefix (decl); - write_template_args (TREE_OPERAND (name, 1)); + write_template_args (TYPE_TI_ARGS (name)); } else { @@ -1023,10 +1023,10 @@ write_prefix (const tree node) else if (TREE_CODE (TREE_TYPE (decl)) == TYPENAME_TYPE) { tree name = TYPENAME_TYPE_FULLNAME (TREE_TYPE (decl)); - if (TREE_CODE (name) == TEMPLATE_ID_EXPR) + if (TREE_CODE (name) == TEMPLATE_ID_TYPE) { write_template_prefix (decl); - write_template_args (TREE_OPERAND (name, 1)); + write_template_args (TYPE_TI_ARGS (name)); } else { @@ -1943,10 +1943,10 @@ write_type (tree type) write_template_template_param (type); break; - case BOUND_TEMPLATE_TEMPLATE_PARM: + case TEMPLATE_ID_TYPE: + gcc_assert (BOUND_TEMPLATE_TEMPLATE_PARM_P (type)); write_template_template_param (type); - write_template_args - (TI_ARGS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (type))); + write_template_args (TYPE_TI_ARGS (type)); break; case VECTOR_TYPE: @@ -2521,7 +2521,7 @@ write_expression (tree expr) /* Handle template parameters. */ if (code == TEMPLATE_TYPE_PARM || code == TEMPLATE_TEMPLATE_PARM - || code == BOUND_TEMPLATE_TEMPLATE_PARM + || BOUND_TEMPLATE_TEMPLATE_PARM_P (expr) || code == TEMPLATE_PARM_INDEX) write_template_param (expr); /* Handle literals. */ @@ -2995,9 +2995,10 @@ write_template_param (const tree parm) switch (TREE_CODE (parm)) { + case TEMPLATE_ID_TYPE: + gcc_assert (BOUND_TEMPLATE_TEMPLATE_PARM_P (parm)); case TEMPLATE_TYPE_PARM: case TEMPLATE_TEMPLATE_PARM: - case BOUND_TEMPLATE_TEMPLATE_PARM: parm_index = TEMPLATE_TYPE_IDX (parm); break; @@ -3027,10 +3028,9 @@ write_template_template_param (const tree parm) /* PARM, a TEMPLATE_TEMPLATE_PARM, is an instantiation of the template template parameter. The substitution candidate here is only the template. */ - if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM) + if (BOUND_TEMPLATE_TEMPLATE_PARM_P (parm)) { - templ - = TI_TEMPLATE (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (parm)); + templ = TI_TEMPLATE (TYPE_TEMPLATE_INFO (parm)); if (find_substitution (templ)) return; } diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index ceecdef..56ee569 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -5330,7 +5330,7 @@ arg_assoc_type (struct arg_lookup *k, tree type) /* Associate the return type. */ return arg_assoc_type (k, TREE_TYPE (type)); case TEMPLATE_TYPE_PARM: - case BOUND_TEMPLATE_TEMPLATE_PARM: + case TEMPLATE_ID_TYPE: return false; case TYPENAME_TYPE: return false; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 5952a0f..97de50f 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -5093,7 +5093,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, || CLASSTYPE_IS_TEMPLATE (new_scope))) && !(TREE_CODE (new_scope) == TYPENAME_TYPE && (TREE_CODE (TYPENAME_TYPE_FULLNAME (new_scope)) - == TEMPLATE_ID_EXPR))) + == TEMPLATE_ID_TYPE))) permerror (input_location, TYPE_P (new_scope) ? G_("%qT is not a template") : G_("%qD is not a template"), diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index bb5aa0c..7d00770 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -328,10 +328,8 @@ get_template_info (const_tree t) if (!tinfo && DECL_IMPLICIT_TYPEDEF_P (t)) t = TREE_TYPE (t); - if (TAGGED_TYPE_P (t)) + if (TYPE_P (t)) tinfo = TYPE_TEMPLATE_INFO (t); - else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM) - tinfo = TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t); return tinfo; } @@ -805,7 +803,7 @@ maybe_process_partial_specialization (tree type) if (type == error_mark_node) return error_mark_node; - if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM) + if (BOUND_TEMPLATE_TEMPLATE_PARM_P (type)) { error ("name of class shadows template template parameter %qD", TYPE_NAME (type)); @@ -3040,10 +3038,15 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data) case TEMPLATE_PARM_INDEX: return NULL_TREE; - case BOUND_TEMPLATE_TEMPLATE_PARM: + case TEMPLATE_ID_TYPE: /* Check the template itself. */ - cp_walk_tree (&TREE_TYPE (TYPE_TI_TEMPLATE (t)), - &find_parameter_packs_r, ppd, ppd->visited); + if (TYPE_TI_TEMPLATE (t) == NULL_TREE) + /* This can happen when the name of the template can not yet + be resolved to a TEMPLATE_DECL. So we don't have any + template tree to walk, yet. */; + else + cp_walk_tree (&TREE_TYPE (TYPE_TI_TEMPLATE (t)), + &find_parameter_packs_r, ppd, ppd->visited); /* Check the template arguments. */ cp_walk_tree (&TYPE_TI_ARGS (t), &find_parameter_packs_r, ppd, ppd->visited); @@ -7303,10 +7306,11 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, int is_dependent_type; int use_partial_inst_tmpl = false; - if (template_type == error_mark_node) - /* An error occured while building the template TEMPL, and a - diagnostic has most certainly been emitted for that - already. Let's propagate that error. */ + if (template_type == error_mark_node + || arglist == error_mark_node) + /* An error occured while building the template TEMPL or its + argument list, and a diagnostic has most certainly been + emitted for that already. Let's propagate that error. */ return error_mark_node; gen_tmpl = most_general_template (templ); @@ -7812,11 +7816,15 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d) return error_mark_node; break; - case BOUND_TEMPLATE_TEMPLATE_PARM: + case TEMPLATE_ID_TYPE: /* Record template parameters such as `T' inside `TT<T>'. */ if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data, pfd->visited, pfd->include_nondeduced_p)) return error_mark_node; + + if (!BOUND_TEMPLATE_TEMPLATE_PARM_P (t)) + break; + /* Fall through. */ case TEMPLATE_TEMPLATE_PARM: @@ -7888,7 +7896,7 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d) } /* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, - BOUND_TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX in T, + TEMPLATE_ID_TYPE 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 @@ -11221,7 +11229,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) case TEMPLATE_TYPE_PARM: case TEMPLATE_TEMPLATE_PARM: - case BOUND_TEMPLATE_TEMPLATE_PARM: + case TEMPLATE_ID_TYPE: case TEMPLATE_PARM_INDEX: { int idx; @@ -11231,6 +11239,34 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) r = NULL_TREE; + if (code == TEMPLATE_ID_TYPE + && !BOUND_TEMPLATE_TEMPLATE_PARM_P (t)) + { + /* We are processing a type constructed from a + template-id. Bound template template parameters are a + particular case of TEMPLATE_ID_TYPE, and they are + handled in an 'else' clause a bit later in this + function. */ + tree argvec = tsubst (TYPE_TI_ARGS (t), + args, complain, in_decl); + + if (TYPE_TI_TEMPLATE (t) != NULL_TREE) + /* The template name of the TEMPLATE_ID_TYPE resolved to + a TEMPLATE_DECL, so we can try to build a class type + for it. */ + r = lookup_template_class (TYPE_TI_TEMPLATE (t), + argvec, in_decl, NULL_TREE, + /*entering_scope=*/0, complain); + else + /* The template name of the TEMPLATE_ID_TYPE hasn't yet + resolved to a TEMPLATE_DECL, so we can't build a + class type from it yet. */ + r = build_template_id_type (TYPE_IDENTIFIER (t), + argvec); + return cp_build_qualified_type_real + (r, cp_type_quals (t), complain); + } + gcc_assert (TREE_VEC_LENGTH (args) > 0); template_parm_level_and_index (t, &level, &idx); @@ -11272,12 +11308,13 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) return cp_build_qualified_type_real (arg, quals, complain | tf_ignore_bad_quals); } - else if (code == BOUND_TEMPLATE_TEMPLATE_PARM) + else if (code == TEMPLATE_ID_TYPE) { /* We are processing a type constructed from a template template parameter. */ tree argvec = tsubst (TYPE_TI_ARGS (t), args, complain, in_decl); + if (argvec == error_mark_node) return error_mark_node; @@ -11302,10 +11339,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) Instantiate<Internal<Template>::template Bind, Argument>; //#1 - When #1 is parsed, the - BOUND_TEMPLATE_TEMPLATE_PARM representing the - parameter `Template' in #0 matches the - UNBOUND_CLASS_TEMPLATE representing the argument + When #1 is parsed, the template of the + TEMPLATE_ID_TYPE representing the `Template' in + #0 matches the UNBOUND_CLASS_TEMPLATE + representing the argument `Internal<Template>::template Bind'; We then want to assemble the type `Bind<Argument>' that can't be fully created right now, because @@ -11315,9 +11352,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) when the context of Bind becomes complete. Let's store that in a TYPENAME_TYPE. */ return make_typename_type (TYPE_CONTEXT (arg), - build_nt (TEMPLATE_ID_EXPR, - TYPE_IDENTIFIER (arg), - argvec), + build_template_id_type + (TYPE_IDENTIFIER (arg), + argvec), typename_type, complain); @@ -11353,9 +11390,12 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) template parameter, but with a lower level. */ switch (code) { + case TEMPLATE_ID_TYPE: + /* This must be a bound template template parm, otherwise, + it would have been handled earlier. */ + gcc_assert (BOUND_TEMPLATE_TEMPLATE_PARM_P (t)); case TEMPLATE_TYPE_PARM: case TEMPLATE_TEMPLATE_PARM: - case BOUND_TEMPLATE_TEMPLATE_PARM: if (cp_type_quals (t)) { r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl); @@ -11389,14 +11429,14 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) else TYPE_CANONICAL (r) = canonical_type_parameter (r); - if (code == BOUND_TEMPLATE_TEMPLATE_PARM) + if (BOUND_TEMPLATE_TEMPLATE_PARM_P (t)) { tree argvec = tsubst (TYPE_TI_ARGS (t), args, complain, in_decl); if (argvec == error_mark_node) return error_mark_node; - TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (r) + TEMPLATE_ID_TYPE_TEMPLATE_INFO (r) = build_template_info (TYPE_TI_TEMPLATE (t), argvec); } } @@ -12424,7 +12464,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) case INTEGER_TYPE: case TEMPLATE_TYPE_PARM: case TEMPLATE_TEMPLATE_PARM: - case BOUND_TEMPLATE_TEMPLATE_PARM: + case TEMPLATE_ID_TYPE: case TEMPLATE_PARM_INDEX: case POINTER_TYPE: case REFERENCE_TYPE: @@ -15851,7 +15891,7 @@ template_parm_level_and_index (tree parm, int* level, int* index) { if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM || TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM - || TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM) + || BOUND_TEMPLATE_TEMPLATE_PARM_P (parm)) { *index = TEMPLATE_TYPE_IDX (parm); *level = TEMPLATE_TYPE_LEVEL (parm); @@ -16216,9 +16256,10 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, within the nested-name-specifier. */ return unify_success (explain_p); + case TEMPLATE_ID_TYPE: + gcc_assert (BOUND_TEMPLATE_TEMPLATE_PARM_P (parm)); case TEMPLATE_TYPE_PARM: case TEMPLATE_TEMPLATE_PARM: - case BOUND_TEMPLATE_TEMPLATE_PARM: tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0)); if (tparm == error_mark_node) return unify_invalid (explain_p); @@ -16245,11 +16286,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, && TREE_CODE (tparm) != TEMPLATE_DECL)) gcc_unreachable (); - if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM) + if (BOUND_TEMPLATE_TEMPLATE_PARM_P (parm)) { /* ARG must be constructed from a template class or a template template parameter. */ - if (TREE_CODE (arg) != BOUND_TEMPLATE_TEMPLATE_PARM + if (!BOUND_TEMPLATE_TEMPLATE_PARM_P (arg) && !CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P (arg)) return unify_template_deduction_failure (explain_p, parm, arg); @@ -16342,7 +16383,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, } if (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM - || TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM) + || BOUND_TEMPLATE_TEMPLATE_PARM_P (parm)) { /* Deduce template name TT from TT, TT<>, TT<T> and TT<i>. */ @@ -19183,7 +19224,7 @@ dependent_type_p_r (tree type) /* -- a template-id in which either the template name is a template parameter ... */ - if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM) + if (BOUND_TEMPLATE_TEMPLATE_PARM_P (type)) return true; /* ... or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent. */ @@ -20030,15 +20071,14 @@ resolve_typename_type (tree type, bool only_current_p) if (result == error_mark_node) result = NULL_TREE; } - else if (TREE_CODE (TYPENAME_TYPE_FULLNAME (type)) == TEMPLATE_ID_EXPR - && DECL_CLASS_TEMPLATE_P (decl)) + else if (TREE_CODE (TYPENAME_TYPE_FULLNAME (type)) == TEMPLATE_ID_TYPE) { + tree fullname = TYPENAME_TYPE_FULLNAME (type); tree tmpl; tree args; /* Obtain the template and the arguments. */ - tmpl = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 0); - args = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 1); - /* Instantiate the template. */ + tmpl = TYPE_IDENTIFIER (fullname); + args = TYPE_TI_ARGS (fullname); result = lookup_template_class (tmpl, args, NULL_TREE, NULL_TREE, /*entering_scope=*/0, tf_error | tf_user); diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c index a66e695..4d0331a 100644 --- a/gcc/cp/ptree.c +++ b/gcc/cp/ptree.c @@ -76,9 +76,13 @@ cxx_print_type (FILE *file, tree node, int indent) { switch (TREE_CODE (node)) { + case TEMPLATE_ID_TYPE: + if (BOUND_TEMPLATE_TEMPLATE_PARM_P (node)) + /* Fall through. */; + else + break; case TEMPLATE_TYPE_PARM: case TEMPLATE_TEMPLATE_PARM: - case BOUND_TEMPLATE_TEMPLATE_PARM: indent_to (file, indent + 3); fprintf (file, "index %d level %d orig_level %d", TEMPLATE_TYPE_IDX (node), TEMPLATE_TYPE_LEVEL (node), diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 3894c68..431c935 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -385,7 +385,7 @@ lookup_field_1 (tree type, tree name, bool want_type) tree field; if (TREE_CODE (type) == TEMPLATE_TYPE_PARM - || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM + || BOUND_TEMPLATE_TEMPLATE_PARM_P (type) || TREE_CODE (type) == TYPENAME_TYPE) /* The TYPE_FIELDS of a TEMPLATE_TYPE_PARM and BOUND_TEMPLATE_TEMPLATE_PARM are not fields at all; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 8d179d8..250e616 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1624,32 +1624,54 @@ build_exception_variant (tree type, tree raises) return v; } +/* Given a TEMPLATE_DECL or an IDENTIFIER_NODE, create a + TEMPLATE_ID_TYPE with args as its arguments. + + The TEMPLATE_INFO of the resulting TEMPLATE_ID_TYPE can be + retrieved using the TEMPLATE_ID_TYPE_TEMPLATE_INFO accessor. The + template arguments ARGS can be retrieved from the TEMLATE_ID_TYPE by + using the TYPE_TI_ARGS accessor, and the TEMPLATE_DECL can be + retrieved using TYPE_TI_TEMPLATE. + + Note that if TMPL is an IDENTIFIER_NODE (rather than a + TEMPLATE_DECL), the TYPE_TI_TEMPLATE accessor will yield + NULL_TREE. That IDENTIFIER_NODE can be retrieved by using the + TYPE_IDENTIFIER accessor instead. */ + +tree +build_template_id_type (tree tmpl, tree args) +{ + tree result, decl, name; + + gcc_assert (tmpl && (TREE_CODE (tmpl) == TEMPLATE_DECL + || TREE_CODE (tmpl) == IDENTIFIER_NODE)); + + name = (TREE_CODE (tmpl) == TEMPLATE_DECL )? DECL_NAME (tmpl) : tmpl; + if (TREE_CODE (tmpl) == IDENTIFIER_NODE) + tmpl = NULL_TREE; + + result = cxx_make_type (TEMPLATE_ID_TYPE); + decl = build_decl (input_location, TYPE_DECL, + name, NULL_TREE); + TREE_TYPE (decl) = result; + TYPE_NAME (result) = decl; + TYPE_STUB_DECL (result) = decl; + SET_TYPE_TEMPLATE_INFO (result, build_template_info (tmpl, args)); + TYPE_SIZE (result) = 0; + SET_TYPE_STRUCTURAL_EQUALITY (result); + return result; +} + /* Given a TEMPLATE_TEMPLATE_PARM node T, create a new - BOUND_TEMPLATE_TEMPLATE_PARM bound with NEWARGS as its template - arguments. */ + TEMPLATE_ID_TYPE bound with NEWARGS as its template arguments. */ tree bind_template_template_parm (tree t, tree newargs) { - tree decl = TYPE_NAME (t); - tree t2; - - t2 = cxx_make_type (BOUND_TEMPLATE_TEMPLATE_PARM); - decl = build_decl (input_location, - TYPE_DECL, DECL_NAME (decl), NULL_TREE); - - /* These nodes have to be created to reflect new TYPE_DECL and template - arguments. */ + tree t2 = build_template_id_type (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t), + newargs); TEMPLATE_TYPE_PARM_INDEX (t2) = copy_node (TEMPLATE_TYPE_PARM_INDEX (t)); - TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (t2)) = decl; - TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2) - = build_template_info (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t), newargs); - - TREE_TYPE (decl) = t2; - TYPE_NAME (t2) = decl; - TYPE_STUB_DECL (t2) = decl; - TYPE_SIZE (t2) = 0; - SET_TYPE_STRUCTURAL_EQUALITY (t2); + TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (t2)) = TYPE_NAME (t2); return t2; } @@ -2937,7 +2959,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, { case DEFAULT_ARG: case TEMPLATE_TEMPLATE_PARM: - case BOUND_TEMPLATE_TEMPLATE_PARM: + case TEMPLATE_ID_TYPE: case UNBOUND_CLASS_TEMPLATE: case TEMPLATE_PARM_INDEX: case TEMPLATE_TYPE_PARM: diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 4973d7d..9200cfe 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1129,7 +1129,7 @@ comp_template_parms_position (tree t1, tree t2) tree index1, index2; gcc_assert (t1 && t2 && TREE_CODE (t1) == TREE_CODE (t2) - && (TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM + && (BOUND_TEMPLATE_TEMPLATE_PARM_P (t1) || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM || TREE_CODE (t1) == TEMPLATE_TYPE_PARM)); @@ -1230,8 +1230,20 @@ structural_comptypes (tree t1, tree t2, int strict) track of equivalence in this case, so we fall back on it. */ return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2); + case TEMPLATE_ID_TYPE: + if (!BOUND_TEMPLATE_TEMPLATE_PARM_P (t1)) + { + if (!cp_tree_equal (TYPE_TI_TEMPLATE (t1), + TYPE_TI_TEMPLATE (t2))) + return false; + return comp_template_args (TYPE_TI_ARGS (t1), + TYPE_TI_ARGS (t2)); + } + else + { + /* Fall through. */; + } case TEMPLATE_TEMPLATE_PARM: - case BOUND_TEMPLATE_TEMPLATE_PARM: if (!comp_template_parms_position (t1, t2)) return false; if (!comp_template_parms @@ -1248,7 +1260,7 @@ structural_comptypes (tree t1, tree t2, int strict) case UNION_TYPE: if (TYPE_TEMPLATE_INFO (t1) && TYPE_TEMPLATE_INFO (t2) && (TYPE_TI_TEMPLATE (t1) == TYPE_TI_TEMPLATE (t2) - || TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM) + || BOUND_TEMPLATE_TEMPLATE_PARM_P (t1)) && comp_template_args (TYPE_TI_ARGS (t1), TYPE_TI_ARGS (t2))) break; diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 4648e75..61f0c4d 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -453,10 +453,15 @@ cxx_incomplete_type_diagnostic (const_tree value, const_tree type, "invalid use of template type parameter %qT", type); break; - case BOUND_TEMPLATE_TEMPLATE_PARM: - emit_diagnostic (diag_kind, input_location, 0, - "invalid use of template template parameter %qT", - TYPE_NAME (type)); + case TEMPLATE_ID_TYPE: + if (BOUND_TEMPLATE_TEMPLATE_PARM_P (type)) + emit_diagnostic (diag_kind, input_location, 0, + "invalid use of template template parameter %qT", + TYPE_NAME (type)); + else + emit_diagnostic (diag_kind, input_location, 0, + "invalid use of template-id %qT", + TYPE_NAME (type)); break; case TYPENAME_TYPE: -- 1.7.6.4 -- Dodji