/* Handle parameterized types (templates) for GNU C++.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001 Free Software Foundation, Inc.
+ 2001, 2002 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
Rewritten by Jason Merrill (jason@cygnus.com).
unification_kind_t, int));
static int unify PARAMS ((tree, tree, tree, tree, int));
static void add_pending_template PARAMS ((tree));
-static int push_tinst_level PARAMS ((tree));
static void reopen_tinst_level PARAMS ((tree));
static tree classtype_mangled_name PARAMS ((tree));
static char *mangle_class_name_for_template PARAMS ((const char *, tree, tree));
static int template_args_equal PARAMS ((tree, tree));
static void tsubst_default_arguments PARAMS ((tree));
static tree for_each_template_parm_r PARAMS ((tree *, int *, void *));
-static tree instantiate_clone PARAMS ((tree, tree));
static tree copy_default_args_to_explicit_spec_1 PARAMS ((tree, tree));
static void copy_default_args_to_explicit_spec PARAMS ((tree));
static int invalid_nontype_parm_type_p PARAMS ((tree, int));
return NULL_TREE;
}
else if (TREE_CODE (decl) == FIELD_DECL)
- cp_error ("data member `%D' cannot be a member template", decl);
+ error ("data member `%D' cannot be a member template", decl);
else if (DECL_TEMPLATE_INFO (decl))
{
if (!DECL_TEMPLATE_SPECIALIZATION (decl))
return decl;
}
else
- cp_error ("invalid member template declaration `%D'", decl);
+ error ("invalid member template declaration `%D'", decl);
return error_mark_node;
}
shall be declared in the namespace of which the class template
is a member. */
if (scope && TREE_CODE (scope) != NAMESPACE_DECL)
- cp_error ("explicit specialization in non-namespace scope `%D'",
+ error ("explicit specialization in non-namespace scope `%D'",
scope);
/* [temp.expl.spec]
explicitly specialize a class member template if its enclosing
class templates are not explicitly specialized as well. */
if (current_template_parms)
- cp_error ("enclosing class templates are not explicitly specialized");
+ error ("enclosing class templates are not explicitly specialized");
}
/* We've just seen template <>. */
if (current_namespace
!= decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
{
- cp_pedwarn ("specializing `%#T' in different namespace", type);
+ pedwarn ("specializing `%#T' in different namespace", type);
cp_pedwarn_at (" from definition of `%#D'",
CLASSTYPE_TI_TEMPLATE (type));
}
push_template_decl (TYPE_MAIN_DECL (type));
}
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
- cp_error ("specialization of `%T' after instantiation", type);
+ error ("specialization of `%T' after instantiation", type);
}
else if (processing_specialization)
- cp_error ("explicit specialization of non-template `%T'", type);
+ error ("explicit specialization of non-template `%T'", type);
}
/* Retrieve the specialization (in the sense of [temp.spec] - a
if (TREE_USED (fn)
|| DECL_EXPLICIT_INSTANTIATION (fn))
{
- cp_error ("specialization of %D after instantiation",
+ error ("specialization of %D after instantiation",
fn);
return spec;
}
if (!is_overloaded_fn (fns))
{
- cp_error ("`%D' is not a function template", fns);
+ error ("`%D' is not a function template", fns);
return error_mark_node;
}
/* This case handles bogus declarations like template <>
template <class T> void f<int>(); */
- cp_error ("template-id `%D' in declaration of primary template",
+ error ("template-id `%D' in declaration of primary template",
declarator);
return decl;
}
return error_mark_node;
case tsk_invalid_expl_inst:
- cp_error ("template parameter list used in explicit instantiation");
+ error ("template parameter list used in explicit instantiation");
/* Fall through. */
case tsk_expl_inst:
if (have_def)
- cp_error ("definition provided for explicit instantiation");
+ error ("definition provided for explicit instantiation");
explicit_instantiation = 1;
break;
case tsk_excessive_parms:
- cp_error ("too many template parameter lists in declaration of `%D'",
+ error ("too many template parameter lists in declaration of `%D'",
decl);
return error_mark_node;
case tsk_insufficient_parms:
if (template_header_count)
{
- cp_error("too few template parameter lists in declaration of `%D'",
+ error("too few template parameter lists in declaration of `%D'",
decl);
return decl;
}
That used to be legal C++. */
if (pedantic)
- cp_pedwarn
+ pedwarn
("explicit specialization not preceded by `template <>'");
specialization = 1;
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
template <class T> void f<int>(); */
if (uses_template_parms (declarator))
- cp_error ("partial specialization `%D' of function template",
+ error ("partial specialization `%D' of function template",
declarator);
else
- cp_error ("template-id `%D' in declaration of primary template",
+ error ("template-id `%D' in declaration of primary template",
declarator);
return decl;
}
for (; t; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t))
{
- cp_pedwarn
+ pedwarn
("default argument specified in explicit specialization");
break;
}
if (current_lang_name == lang_name_c)
- cp_error ("template specialization with C linkage");
+ error ("template specialization with C linkage");
}
if (specialization || member_specialization || explicit_instantiation)
program is ill-formed.
Similar language is found in [temp.explicit]. */
- cp_error ("specialization of implicitly-declared special member function");
+ error ("specialization of implicitly-declared special member function");
return error_mark_node;
}
if (fns == NULL_TREE)
{
- cp_error ("no member function `%D' declared in `%T'",
+ error ("no member function `%D' declared in `%T'",
name, ctype);
return error_mark_node;
}
;
else if (template_header_count > context_depth + 1)
/* There are two many template parameter lists. */
- cp_error ("too many template parameter lists in declaration of `%T'", type);
+ error ("too many template parameter lists in declaration of `%T'", type);
}
}
/* is a const-param */
parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
PARM, 0, NULL);
+ SET_DECL_TEMPLATE_PARM_P (parm);
/* [temp.param]
tree parms;
{
int nparms;
- tree parm;
+ tree parm, next;
tree saved_parmlist = make_tree_vec (list_length (parms));
current_template_parms
= tree_cons (size_int (processing_template_decl),
saved_parmlist, current_template_parms);
- for (parm = parms, nparms = 0;
- parm;
- parm = TREE_CHAIN (parm), nparms++)
- TREE_VEC_ELT (saved_parmlist, nparms) = parm;
+ for (parm = parms, nparms = 0; parm; parm = next, nparms++)
+ {
+ next = TREE_CHAIN (parm);
+ TREE_VEC_ELT (saved_parmlist, nparms) = parm;
+ TREE_CHAIN (parm) = NULL_TREE;
+ }
--processing_template_parmlist;
specialization. */
if (!did_error_intro)
{
- cp_error ("template parameters not used in partial specialization:");
+ error ("template parameters not used in partial specialization:");
did_error_intro = 1;
}
- cp_error (" `%D'",
+ error (" `%D'",
TREE_VALUE (TREE_VEC_ELT (inner_parms, i)));
}
(inner_args,
INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (TREE_TYPE
(maintmpl)))))
- cp_error ("partial specialization `%T' does not specialize any template arguments", type);
+ error ("partial specialization `%T' does not specialize any template arguments", type);
/* [temp.class.spec]
&& TREE_CODE (arg) != TEMPLATE_PARM_INDEX)
{
if (tpd.arg_uses_template_parms[i])
- cp_error ("template argument `%E' involves template parameter(s)", arg);
+ error ("template argument `%E' involves template parameter(s)", arg);
else
{
/* Look at the corresponding template parameter,
if (tpd2.parms[j] != 0
&& tpd.arg_uses_template_parms [j])
{
- cp_error ("type `%T' of template argument `%E' depends on template parameter(s)",
+ error ("type `%T' of template argument `%E' depends on template parameter(s)",
type,
arg);
break;
seen_def_arg_p = 1;
else if (seen_def_arg_p)
{
- cp_error ("no default argument for `%D'", TREE_VALUE (parm));
+ error ("no default argument for `%D'", TREE_VALUE (parm));
/* For better subsequent error-recovery, we indicate that
there should have been a default argument. */
TREE_PURPOSE (parm) = error_mark_node;
{
if (msg)
{
- cp_error (msg, decl);
+ error (msg, decl);
msg = 0;
}
if (primary)
{
if (current_lang_name == lang_name_c)
- cp_error ("template with C linkage");
+ error ("template with C linkage");
else if (TREE_CODE (decl) == TYPE_DECL
&& ANON_AGGRNAME_P (DECL_NAME (decl)))
- cp_error ("template class without a name");
+ error ("template class without a name");
else if ((DECL_IMPLICIT_TYPEDEF_P (decl)
&& CLASS_TYPE_P (TREE_TYPE (decl)))
|| (TREE_CODE (decl) == VAR_DECL && ctx && CLASS_TYPE_P (ctx))
|| TREE_CODE (decl) == FUNCTION_DECL)
/* OK */;
else
- cp_error ("template declaration of `%#D'", decl);
+ error ("template declaration of `%#D'", decl);
}
/* Check to see that the rules regarding the use of default
tmpl = TYPE_TI_TEMPLATE (TREE_TYPE (decl));
else
{
- cp_error ("`%D' does not declare a template type", decl);
+ error ("`%D' does not declare a template type", decl);
return decl;
}
}
- else if (! DECL_TEMPLATE_INFO (decl))
+ else if (!DECL_LANG_SPECIFIC (decl) || !DECL_TEMPLATE_INFO (decl))
{
- cp_error ("template definition of non-template `%#D'", decl);
+ error ("template definition of non-template `%#D'", decl);
return decl;
}
else
i = TMPL_PARMS_DEPTH (parms);
if (TMPL_ARGS_DEPTH (args) != i)
{
- cp_error ("expected %d levels of template parms for `%#D', got %d",
+ error ("expected %d levels of template parms for `%#D', got %d",
i, decl, TMPL_ARGS_DEPTH (args));
}
else
if (TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a))
{
if (current == decl)
- cp_error ("got %d template parameters for `%#D'",
+ error ("got %d template parameters for `%#D'",
TREE_VEC_LENGTH (a), decl);
else
- cp_error ("got %d template parameters for `%#T'",
+ error ("got %d template parameters for `%#T'",
TREE_VEC_LENGTH (a), current);
- cp_error (" but %d required", TREE_VEC_LENGTH (t));
+ error (" but %d required", TREE_VEC_LENGTH (t));
}
/* Perhaps we should also check that the parms are used in the
if (!TYPE_TEMPLATE_INFO (type))
{
- cp_error ("`%T' is not a template type", type);
+ error ("`%T' is not a template type", type);
return;
}
if (TREE_VEC_LENGTH (parms) != TREE_VEC_LENGTH (tmpl_parms))
{
cp_error_at ("previous declaration `%D'", tmpl);
- cp_error ("used %d template parameter%s instead of %d",
+ error ("used %d template parameter%s instead of %d",
TREE_VEC_LENGTH (tmpl_parms),
TREE_VEC_LENGTH (tmpl_parms) == 1 ? "" : "s",
TREE_VEC_LENGTH (parms));
if (TREE_CODE (tmpl_parm) != TREE_CODE (parm))
{
cp_error_at ("template parameter `%#D'", tmpl_parm);
- cp_error ("redeclared here as `%#D'", parm);
+ error ("redeclared here as `%#D'", parm);
return;
}
A template-parameter may not be given default arguments
by two different declarations in the same scope. */
- cp_error ("redefinition of default argument for `%#D'", parm);
+ error ("redefinition of default argument for `%#D'", parm);
cp_error_at (" original definition appeared here", tmpl_parm);
return;
}
if (TREE_CODE (e) != ADDR_EXPR)
{
bad_argument:
- cp_error ("`%E' is not a valid template argument", expr);
+ error ("`%E' is not a valid template argument", expr);
if (TYPE_PTR_P (expr_type))
{
if (TREE_CODE (TREE_TYPE (expr_type)) == FUNCTION_TYPE)
- cp_error ("it must be the address of a function with external linkage");
+ error ("it must be the address of a function with external linkage");
else
- cp_error ("it must be the address of an object with external linkage");
+ error ("it must be the address of an object with external linkage");
}
else if (TYPE_PTRMEM_P (expr_type)
|| TYPE_PTRMEMFUNC_P (expr_type))
- cp_error ("it must be a pointer-to-member of the form `&X::Y'");
+ error ("it must be a pointer-to-member of the form `&X::Y'");
return NULL_TREE;
}
if (TREE_CODE (referent) == STRING_CST)
{
- cp_error ("string literal %E is not a valid template argument because it is the address of an object with static linkage",
+ error ("string literal %E is not a valid template argument because it is the address of an object with static linkage",
referent);
return NULL_TREE;
}
goto bad_argument;
else if (!DECL_EXTERNAL_LINKAGE_P (referent))
{
- cp_error ("address of non-extern `%E' cannot be used as template argument", referent);
+ error ("address of non-extern `%E' cannot be used as template argument", referent);
return error_mark_node;
}
}
if (! TREE_CONSTANT (expr))
{
non_constant:
- cp_error ("non-constant `%E' cannot be used as template argument",
+ error ("non-constant `%E' cannot be used as template argument",
expr);
return NULL_TREE;
}
}
else
{
- cp_error ("object `%E' cannot be used as template argument", expr);
+ error ("object `%E' cannot be used as template argument", expr);
return NULL_TREE;
}
requires_type = (TREE_CODE (parm) == TYPE_DECL
|| requires_tmpl_type);
- /* Check if it is a class template. If REQUIRES_TMPL_TYPE is true,
- we also accept implicitly created TYPE_DECL as a valid argument.
- This is necessary to handle the case where we pass a template name
- to a template template parameter in a scope where we've derived from
- in instantiation of that template, so the template name refers to that
- instantiation. We really ought to handle this better. */
- is_tmpl_type
- = ((TREE_CODE (arg) == TEMPLATE_DECL
- && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
- || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
- || (TREE_CODE (arg) == RECORD_TYPE
- && CLASSTYPE_TEMPLATE_INFO (arg)
- && TREE_CODE (TYPE_NAME (arg)) == TYPE_DECL
- && DECL_ARTIFICIAL (TYPE_NAME (arg))
- && requires_tmpl_type
- && is_base_of_enclosing_class (arg, current_class_type)));
- if (is_tmpl_type && TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+ if (TREE_CODE (arg) != RECORD_TYPE)
+ is_tmpl_type = ((TREE_CODE (arg) == TEMPLATE_DECL
+ && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
+ || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+ || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);
+ else if (CLASSTYPE_TEMPLATE_INFO (arg) && !CLASSTYPE_USE_TEMPLATE (arg)
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (arg)))
+ {
+ if (is_base_of_enclosing_class (arg, current_class_type))
+ /* This is a template name used within the scope of the
+ template. It could be the template, or it could be the
+ instantiation. Choose whichever makes sense. */
+ is_tmpl_type = requires_tmpl_type;
+ else
+ is_tmpl_type = 1;
+ }
+ else
+ /* It is a non-template class, or a specialization of a template
+ class, or a non-template member of a template class. */
+ is_tmpl_type = 0;
+
+ if (is_tmpl_type
+ && (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+ || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE))
arg = TYPE_STUB_DECL (arg);
else if (is_tmpl_type && TREE_CODE (arg) == RECORD_TYPE)
arg = CLASSTYPE_TI_TEMPLATE (arg);
if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
&& TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
{
- cp_pedwarn ("to refer to a type member of a template parameter, use `typename %E'", arg);
+ pedwarn ("to refer to a type member of a template parameter, use `typename %E'", arg);
arg = make_typename_type (TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1),
{
if (complain)
{
- cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
+ error ("type/value mismatch at argument %d in template parameter list for `%D'",
i + 1, in_decl);
if (is_type)
- cp_error (" expected a constant of type `%T', got `%T'",
+ error (" expected a constant of type `%T', got `%T'",
TREE_TYPE (parm),
(is_tmpl_type ? DECL_NAME (arg) : arg));
else
- cp_error (" expected a type, got `%E'", arg);
+ error (" expected a type, got `%E'", arg);
}
}
return error_mark_node;
{
if (in_decl && complain)
{
- cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
+ error ("type/value mismatch at argument %d in template parameter list for `%D'",
i + 1, in_decl);
if (is_tmpl_type)
- cp_error (" expected a type, got `%T'", DECL_NAME (arg));
+ error (" expected a type, got `%T'", DECL_NAME (arg));
else
- cp_error (" expected a class template, got `%T'", arg);
+ error (" expected a class template, got `%T'", arg);
}
return error_mark_node;
}
{
if (requires_tmpl_type)
{
- tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
- tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
-
- if (coerce_template_template_parms (parmparm, argparm, complain,
- in_decl, inner_args))
- {
- val = arg;
-
- /* TEMPLATE_TEMPLATE_PARM node is preferred over
- TEMPLATE_DECL. */
- if (val != error_mark_node
- && DECL_TEMPLATE_TEMPLATE_PARM_P (val))
- val = TREE_TYPE (val);
- }
+ if (TREE_CODE (TREE_TYPE (arg)) == UNBOUND_CLASS_TEMPLATE)
+ /* The number of argument required is not known yet.
+ Just accept it for now. */
+ val = TREE_TYPE (arg);
else
{
- if (in_decl && complain)
+ tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
+ tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+
+ if (coerce_template_template_parms (parmparm, argparm,
+ complain, in_decl,
+ inner_args))
{
- cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
- i + 1, in_decl);
- cp_error (" expected a template of type `%D', got `%D'", parm, arg);
+ val = arg;
+
+ /* TEMPLATE_TEMPLATE_PARM node is preferred over
+ TEMPLATE_DECL. */
+ if (val != error_mark_node
+ && DECL_TEMPLATE_TEMPLATE_PARM_P (val))
+ val = TREE_TYPE (val);
}
+ else
+ {
+ if (in_decl && complain)
+ {
+ error ("type/value mismatch at argument %d in template parameter list for `%D'",
+ i + 1, in_decl);
+ error (" expected a template of type `%D', got `%D'", parm, arg);
+ }
- val = error_mark_node;
+ val = error_mark_node;
+ }
}
}
else
if (t)
{
if (TYPE_ANONYMOUS_P (t))
- cp_pedwarn
+ pedwarn
("template-argument `%T' uses anonymous type", val);
else
- cp_error
+ error
("template-argument `%T' uses local type `%T'",
val, t);
return error_mark_node;
if (val == NULL_TREE)
val = error_mark_node;
else if (val == error_mark_node && complain)
- cp_error ("could not convert template argument `%E' to `%T'",
+ error ("could not convert template argument `%E' to `%T'",
arg, t);
}
{
if (complain)
{
- cp_error ("wrong number of template arguments (%d, should be %d)",
+ error ("wrong number of template arguments (%d, should be %d)",
nargs, nparms);
if (in_decl)
}
else if (arg == error_mark_node)
{
- cp_error ("template argument %d is invalid", i + 1);
+ error ("template argument %d is invalid", i + 1);
arg = error_mark_node;
}
else
if (fns == NULL_TREE)
{
- cp_error ("non-template used as template");
+ error ("non-template used as template");
return error_mark_node;
}
if (! template)
{
if (complain)
- cp_error ("`%T' is not a template", d1);
+ error ("`%T' is not a template", d1);
return error_mark_node;
}
{
if (complain)
{
- cp_error ("non-template type `%T' used as a template", d1);
+ error ("non-template type `%T' used as a template", d1);
if (in_decl)
cp_error_at ("for template declaration `%D'", in_decl);
}
arg_depth = TMPL_ARGS_DEPTH (arglist);
}
- /* Now we should enough arguments. */
+ /* Now we should have enough arguments. */
my_friendly_assert (parm_depth == arg_depth, 0);
/* From here on, we're only interested in the most general
Create the partial instantiation.
*/
TREE_VEC_LENGTH (arglist)--;
- template = tsubst (template, arglist, /*complain=*/0, NULL_TREE);
+ found = tsubst (template, arglist, /*complain=*/0, NULL_TREE);
TREE_VEC_LENGTH (arglist)++;
- found = template;
}
}
/* We're starting to instantiate D; record the template instantiation context
for diagnostics and to restore it later. */
-static int
+int
push_tinst_level (d)
tree d;
{
return 0;
last_template_error_tick = tinst_level_tick;
- cp_error ("template instantiation depth exceeds maximum of %d (use -ftemplate-depth-NN to increase the maximum) instantiating `%D'",
+ error ("template instantiation depth exceeds maximum of %d (use -ftemplate-depth-NN to increase the maximum) instantiating `%D'",
max_tinst_depth, d);
print_instantiation_context ();
if (t == error_mark_node)
{
const char *str = "candidates are:";
- cp_error ("ambiguous class template instantiation for `%#T'", type);
+ error ("ambiguous class template instantiation for `%#T'", type);
for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t;
t = TREE_CHAIN (t))
{
{
tree r = tsubst (t, args, /*complain=*/1, NULL_TREE);
set_current_access_from_decl (r);
+ grok_special_member_properties (r);
finish_member_declaration (r);
}
for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
{
- tree default_value =
- TREE_PURPOSE (TREE_VEC_ELT (TREE_VALUE (parms), i));
- tree parm_decl =
- TREE_VALUE (TREE_VEC_ELT (TREE_VALUE (parms), i));
-
- TREE_VEC_ELT (new_vec, i)
- = build_tree_list (maybe_fold_nontype_arg (
- tsubst_expr (default_value, args, complain,
- NULL_TREE)),
- tsubst (parm_decl, args, complain,
- NULL_TREE));
+ tree tuple = TREE_VEC_ELT (TREE_VALUE (parms), i);
+ tree default_value = TREE_PURPOSE (tuple);
+ tree parm_decl = TREE_VALUE (tuple);
+
+ parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
+ default_value = tsubst_expr (default_value, args,
+ complain, NULL_TREE);
+ tuple = build_tree_list (maybe_fold_nontype_arg (default_value),
+ parm_decl);
+ TREE_VEC_ELT (new_vec, i) = tuple;
}
*new_parms =
{
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
- {
- tree r = build_ptrmemfunc_type
- (tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, complain, in_decl));
- return cp_build_qualified_type_real (r, TYPE_QUALS (t),
- complain);
- }
+ return tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, complain, in_decl);
/* else fall through */
case ENUMERAL_TYPE:
If it isn't, that'll be handled by
clone_constructors_and_destructors. */
if (PRIMARY_TEMPLATE_P (gen_tmpl))
- clone_function_decl(r, /*update_method_vec_p=*/0);
+ clone_function_decl (r, /*update_method_vec_p=*/0);
}
else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
- grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
+ grok_op_properties (r, DECL_FRIEND_P (r));
}
break;
case PARM_DECL:
{
r = copy_node (t);
+ if (DECL_TEMPLATE_PARM_P (t))
+ SET_DECL_TEMPLATE_PARM_P (r);
+
TREE_TYPE (r) = type;
- c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);
+ c_apply_type_quals_to_decl (cp_type_quals (type), r);
if (TREE_CODE (DECL_INITIAL (r)) != TEMPLATE_PARM_INDEX)
DECL_INITIAL (r) = TREE_TYPE (r);
/*complain=*/1, in_decl);
DECL_CONTEXT (r) = NULL_TREE;
- if (PROMOTE_PROTOTYPES
+ if (!DECL_TEMPLATE_PARM_P (r) && PROMOTE_PROTOTYPES
&& INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (r) = integer_type_node;
{
r = copy_decl (t);
TREE_TYPE (r) = type;
- c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);
+ c_apply_type_quals_to_decl (cp_type_quals (type), r);
/* We don't have to set DECL_CONTEXT here; it is set by
finish_member_declaration. */
r = copy_decl (t);
TREE_TYPE (r) = type;
- c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);
+ c_apply_type_quals_to_decl (cp_type_quals (type), r);
DECL_CONTEXT (r) = ctx;
/* Clear out the mangled name and RTL for the instantiation. */
SET_DECL_ASSEMBLER_NAME (r, NULL_TREE);
{
if (complain)
{
- cp_error ("invalid parameter type `%T'", type);
+ error ("invalid parameter type `%T'", type);
if (in_decl)
cp_error_at ("in declaration `%D'", in_decl);
}
/* The TYPE_CONTEXT is not used for function/method types. */
my_friendly_assert (TYPE_CONTEXT (t) == NULL_TREE, 0);
- /* Substitue the return type. */
+ /* Substitute the return type. */
return_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (return_type == error_mark_node)
return error_mark_node;
-- Attempting to create "pointer to member of T" when T
is not a class type. */
if (complain)
- cp_error ("creating pointer to member function of non-class type `%T'",
+ error ("creating pointer to member function of non-class type `%T'",
r);
return error_mark_node;
}
Attempting to create an array with a size that is
zero or negative. */
if (complain)
- cp_error ("creating array with size zero (`%E')", max);
+ error ("creating array with size zero (`%E')", max);
return error_mark_node;
}
{
my_friendly_assert (TYPE_P (arg), 0);
return cp_build_qualified_type_real
- (arg, CP_TYPE_QUALS (arg) | CP_TYPE_QUALS (t),
+ (arg, cp_type_quals (arg) | cp_type_quals (t),
complain);
}
else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
- if (CP_TYPE_QUALS (t))
+ if (cp_type_quals (t))
{
r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
- r = cp_build_qualified_type_real (r, CP_TYPE_QUALS (t),
+ r = cp_build_qualified_type_real (r, cp_type_quals (t),
complain);
}
else
{
enum tree_code code;
- if (type == TREE_TYPE (t))
+ if (type == TREE_TYPE (t) && TREE_CODE (type) != METHOD_TYPE)
return t;
code = TREE_CODE (t);
last_file != input_filename))
{
if (TREE_CODE (type) == VOID_TYPE)
- cp_error ("forming reference to void");
+ error ("forming reference to void");
else
- cp_error ("forming %s to reference type `%T'",
+ error ("forming %s to reference type `%T'",
(code == POINTER_TYPE) ? "pointer" : "reference",
type);
last_line = lineno;
return error_mark_node;
}
else if (code == POINTER_TYPE)
- r = build_pointer_type (type);
+ {
+ r = build_pointer_type (type);
+ if (TREE_CODE (type) == METHOD_TYPE)
+ r = build_ptrmemfunc_type (r);
+ }
else
r = build_reference_type (type);
r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
-- Attempting to create "pointer to member of T" when T
is not a class type. */
if (complain)
- cp_error ("creating pointer to member of non-class type `%T'",
+ error ("creating pointer to member of non-class type `%T'",
r);
return error_mark_node;
}
- return build_offset_type (r, type);
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ if (complain)
+ error ("creating pointer to member reference type `%T'", type);
+
+ return error_mark_node;
+ }
+ my_friendly_assert (TREE_CODE (type) != METHOD_TYPE, 20011231);
+ if (TREE_CODE (type) == FUNCTION_TYPE)
+ /* This is really a method type. The cv qualifiers of the
+ this pointer should _not_ be determined by the cv
+ qualifiers of the class type. They should be held
+ somewhere in the FUNCTION_TYPE, but we don't do that at
+ the moment. Consider
+ typedef void (Func) () const;
+
+ template <typename T1> void Foo (Func T1::*);
+
+ */
+ return build_cplus_method_type (TYPE_MAIN_VARIANT (r),
+ TREE_TYPE (type),
+ TYPE_ARG_TYPES (type));
+ else
+ return build_offset_type (r, type);
}
case FUNCTION_TYPE:
case METHOD_TYPE:
|| TREE_CODE (type) == REFERENCE_TYPE)
{
if (complain)
- cp_error ("creating array of `%T'", type);
+ error ("creating array of `%T'", type);
return error_mark_node;
}
if (!IS_AGGR_TYPE (ctx))
{
if (complain)
- cp_error ("`%T' is not a class, struct, or union type",
+ error ("`%T' is not a class, struct, or union type",
ctx);
return error_mark_node;
}
if (f == error_mark_node)
return f;
return cp_build_qualified_type_real (f,
- CP_TYPE_QUALS (f)
- | CP_TYPE_QUALS (t),
+ cp_type_quals (f)
+ | cp_type_quals (t),
complain);
}
+ case UNBOUND_CLASS_TEMPLATE:
+ {
+ tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, complain,
+ in_decl, /*entering_scope=*/1);
+ tree name = TYPE_IDENTIFIER (t);
+
+ if (ctx == error_mark_node || name == error_mark_node)
+ return error_mark_node;
+
+ return make_unbound_class_template (ctx, name, complain);
+ }
+
case INDIRECT_REF:
{
tree e = tsubst (TREE_OPERAND (t, 0), args, complain,
case METHOD_TYPE:
case ARRAY_TYPE:
case TYPENAME_TYPE:
+ case UNBOUND_CLASS_TEMPLATE:
+ case TYPEOF_TYPE:
case TYPE_DECL:
return tsubst (t, args, complain, in_decl);
case COMPOUND_STMT:
{
prep_stmt (t);
- stmt = begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
+ if (COMPOUND_STMT_BODY_BLOCK (t))
+ stmt = begin_function_body ();
+ else
+ stmt = begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
+
tsubst_expr (COMPOUND_BODY (t), args, complain, in_decl);
- finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), stmt);
+
+ if (COMPOUND_STMT_BODY_BLOCK (t))
+ finish_function_body (stmt);
+ else
+ finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), stmt);
}
break;
case CTOR_STMT:
add_stmt (copy_node (t));
break;
-
+
default:
abort ();
}
return tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
}
-/* TMPL is a TEMPLATE_DECL for a cloned constructor or destructor.
- Instantiate it with the ARGS. */
-
-static tree
-instantiate_clone (tmpl, args)
- tree tmpl;
- tree args;
-{
- tree spec;
- tree clone;
-
- /* Instantiated the cloned function, rather than the clone. */
- spec = instantiate_template (DECL_CLONED_FUNCTION (tmpl), args);
-
- /* Then, see if we've already cloned the instantiation. */
- for (clone = TREE_CHAIN (spec);
- clone && DECL_CLONED_FUNCTION_P (clone);
- clone = TREE_CHAIN (clone))
- if (DECL_NAME (clone) == DECL_NAME (tmpl))
- return clone;
-
- /* If we haven't, do so know. */
- if (!clone)
- clone_function_decl (spec, /*update_method_vec_p=*/0);
-
- /* Look again. */
- for (clone = TREE_CHAIN (spec);
- clone && DECL_CLONED_FUNCTION_P (clone);
- clone = TREE_CHAIN (clone))
- if (DECL_NAME (clone) == DECL_NAME (tmpl))
- return clone;
-
- /* We should always have found the clone by now. */
- my_friendly_abort (20000411);
- return NULL_TREE;
-}
-
/* Instantiate the indicated variable or function template TMPL with
the template arguments in TARG_PTR. */
instantiate_template (tmpl, targ_ptr)
tree tmpl, targ_ptr;
{
- tree clone;
tree fndecl;
tree gen_tmpl;
tree spec;
/* If this function is a clone, handle it specially. */
if (DECL_CLONED_FUNCTION_P (tmpl))
- return instantiate_clone (tmpl, targ_ptr);
-
+ {
+ tree spec = instantiate_template (DECL_CLONED_FUNCTION (tmpl), targ_ptr);
+ tree clone;
+
+ /* Look for the clone. */
+ for (clone = TREE_CHAIN (spec);
+ clone && DECL_CLONED_FUNCTION_P (clone);
+ clone = TREE_CHAIN (clone))
+ if (DECL_NAME (clone) == DECL_NAME (tmpl))
+ return clone;
+ /* We should always have found the clone by now. */
+ my_friendly_abort (20000411);
+ return NULL_TREE;
+ }
+
/* Check to see if we already have this specialization. */
spec = retrieve_specialization (tmpl, targ_ptr);
if (spec != NULL_TREE)
tree nt = target_type (t);
if (IS_AGGR_TYPE (nt) && decl_function_context (TYPE_MAIN_DECL (nt)))
{
- cp_error ("type `%T' composed from a local class is not a valid template-argument", t);
- cp_error (" trying to instantiate `%D'", gen_tmpl);
+ error ("type `%T' composed from a local class is not a valid template-argument", t);
+ error (" trying to instantiate `%D'", gen_tmpl);
return error_mark_node;
}
}
add_pending_template (fndecl);
/* If we've just instantiated the main entry point for a function,
- instantiate all the alternate entry points as well. */
- for (clone = TREE_CHAIN (gen_tmpl);
- clone && DECL_CLONED_FUNCTION_P (clone);
- clone = TREE_CHAIN (clone))
- instantiate_template (clone, targ_ptr);
+ instantiate all the alternate entry points as well. We do this
+ by cloning the instantiation of the main entry point, not by
+ instantiating the template clones. */
+ if (TREE_CHAIN (gen_tmpl) && DECL_CLONED_FUNCTION_P (TREE_CHAIN (gen_tmpl)))
+ clone_function_decl (fndecl, /*update_method_vec_p=*/0);
return fndecl;
}
switch (TREE_CODE (parm))
{
case TYPENAME_TYPE:
+ case SCOPE_REF:
+ case UNBOUND_CLASS_TEMPLATE:
/* In a type which contains a nested-name-specifier, template
argument values cannot be deduced for template parameters used
within the nested-name-specifier. */
PARM is `const T'. Then, T should be `volatile int'. */
arg =
cp_build_qualified_type_real (arg,
- CP_TYPE_QUALS (arg)
- & ~CP_TYPE_QUALS (parm),
+ cp_type_quals (arg)
+ & ~cp_type_quals (parm),
/*complain=*/0);
if (arg == error_mark_node)
return 1;
/* Return the innermost template arguments that, when applied to a
template specialization whose innermost template parameters are
- TPARMS, and whose specialization arguments are ARGS, yield the
+ TPARMS, and whose specialization arguments are PARMS, yield the
ARGS.
For example, suppose we have:
return;
else if (! DECL_LANG_SPECIFIC (decl))
{
- cp_error ("explicit instantiation of non-template `%#D'", decl);
+ error ("explicit instantiation of non-template `%#D'", decl);
return;
}
else if (TREE_CODE (decl) == VAR_DECL)
result = lookup_field (DECL_CONTEXT (decl), DECL_NAME (decl), 0, 0);
if (result && TREE_CODE (result) != VAR_DECL)
{
- cp_error ("no matching template for `%D' found", result);
+ error ("no matching template for `%D' found", result);
return;
}
}
else if (TREE_CODE (decl) != FUNCTION_DECL)
{
- cp_error ("explicit instantiation of `%#D'", decl);
+ error ("explicit instantiation of `%#D'", decl);
return;
}
else
No program shall both explicitly instantiate and explicitly
specialize a template. */
- cp_pedwarn ("explicit instantiation of `%#D' after", result);
+ pedwarn ("explicit instantiation of `%#D' after", result);
cp_pedwarn_at ("explicit specialization here", result);
return;
}
the opposite case. If -frepo, chances are we already got marked
as an explicit instantiation because of the repo file. */
if (DECL_INTERFACE_KNOWN (result) && !extern_p && !flag_use_repository)
- cp_pedwarn ("duplicate explicit instantiation of `%#D'", result);
+ pedwarn ("duplicate explicit instantiation of `%#D'", result);
/* If we've already instantiated the template, just return now. */
if (DECL_INTERFACE_KNOWN (result))
}
else if (!DECL_IMPLICIT_INSTANTIATION (result))
{
- cp_error ("no matching template for `%D' found", result);
+ error ("no matching template for `%D' found", result);
return;
}
else if (!DECL_TEMPLATE_INFO (result))
{
- cp_pedwarn ("explicit instantiation of non-template `%#D'", result);
+ pedwarn ("explicit instantiation of non-template `%#D'", result);
return;
}
else if (storage == ridpointers[(int) RID_EXTERN])
{
if (pedantic)
- cp_pedwarn ("ISO C++ forbids the use of `extern' on explicit instantiations");
+ pedwarn ("ISO C++ forbids the use of `extern' on explicit instantiations");
extern_p = 1;
}
else
- cp_error ("storage class `%D' applied to template instantiation",
+ error ("storage class `%D' applied to template instantiation",
storage);
SET_DECL_EXPLICIT_INSTANTIATION (result);
if (! CLASS_TYPE_P (t) || ! CLASSTYPE_TEMPLATE_INFO (t))
{
- cp_error ("explicit instantiation of non-template type `%T'", t);
+ error ("explicit instantiation of non-template type `%T'", t);
return;
}
if (!COMPLETE_TYPE_P (t))
{
if (complain)
- cp_error ("explicit instantiation of `%#T' before definition of template",
+ error ("explicit instantiation of `%#T' before definition of template",
t);
return;
}
if (storage != NULL_TREE)
{
if (pedantic)
- cp_pedwarn("ISO C++ forbids the use of `%s' on explicit instantiations",
+ pedwarn("ISO C++ forbids the use of `%s' on explicit instantiations",
IDENTIFIER_POINTER (storage));
if (storage == ridpointers[(int) RID_INLINE])
static_p = 1;
else
{
- cp_error ("storage class `%D' applied to template instantiation",
+ error ("storage class `%D' applied to template instantiation",
storage);
extern_p = 0;
}
specialize a template. */
if (complain)
{
- cp_error ("explicit instantiation of `%#T' after", t);
+ error ("explicit instantiation of `%#T' after", t);
cp_error_at ("explicit specialization here", t);
}
return;
If CLASSTYPE_INTERFACE_ONLY, then the first explicit instantiation
was `extern'. If EXTERN_P then the second is. If -frepo, chances
- are we already got marked as an explicit instantion because of the
+ are we already got marked as an explicit instantiation because of the
repo file. All these cases are OK. */
if (!CLASSTYPE_INTERFACE_ONLY (t) && !extern_p && !flag_use_repository
&& complain)
- cp_pedwarn ("duplicate explicit instantiation of `%#T'", t);
+ pedwarn ("duplicate explicit instantiation of `%#T'", t);
/* If we've already instantiated the template, just return now. */
if (!CLASSTYPE_INTERFACE_ONLY (t))
member function or static data member of a class template
shall be present in every translation unit in which it is
explicitly instantiated. */
- cp_pedwarn
+ pedwarn
("explicit instantiation of `%D' but no definition available", d);
add_pending_template (d);
return 0;
if (complain)
- cp_error ("`%#T' is not a valid type for a template constant parameter",
+ error ("`%#T' is not a valid type for a template constant parameter",
type);
return 1;
}