@@ -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);
@@ -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.
@@ -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);
@@ -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);
@@ -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]
@@ -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
@@ -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;
@@ -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));
@@ -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;
}
@@ -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;
@@ -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"),
@@ -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);
@@ -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),
@@ -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;
@@ -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:
@@ -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;
@@ -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: