/* Handle parameterized types (templates) for GNU C++.
- Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
- Free Software Foundation, Inc.
+ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ 2001 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
Rewritten by Jason Merrill (jason@cygnus.com).
#include "config.h"
#include "system.h"
#include "obstack.h"
-
#include "tree.h"
#include "flags.h"
#include "cp-tree.h"
+#include "tree-inline.h"
#include "decl.h"
#include "parse.h"
#include "lex.h"
#include "output.h"
-#include "defaults.h"
#include "except.h"
#include "toplev.h"
#include "rtl.h"
-#include "defaults.h"
#include "ggc.h"
#include "timevar.h"
(for a function or static data member), or a TYPE (for a class)
indicating what we are hoping to instantiate. */
static tree pending_templates;
-static tree *template_tail = &pending_templates;
-
-static tree maybe_templates;
-static tree *maybe_template_tail = &maybe_templates;
+static tree last_pending_template;
int processing_template_parmlist;
static int template_header_count;
#define UNIFY_ALLOW_LESS_CV_QUAL 2
#define UNIFY_ALLOW_DERIVED 4
#define UNIFY_ALLOW_INTEGER 8
+#define UNIFY_ALLOW_OUTER_LEVEL 16
+#define UNIFY_ALLOW_OUTER_MORE_CV_QUAL 32
+#define UNIFY_ALLOW_OUTER_LESS_CV_QUAL 64
+#define UNIFY_ALLOW_MAX_CORRECTION 128
#define GTB_VIA_VIRTUAL 1 /* The base class we are examining is
virtual, or a base class of a virtual
static void tsubst_enum PARAMS ((tree, tree, tree));
static tree add_to_template_args PARAMS ((tree, tree));
static tree add_outermost_template_args PARAMS ((tree, tree));
-static void maybe_adjust_types_for_deduction PARAMS ((unification_kind_t, tree*,
+static int maybe_adjust_types_for_deduction PARAMS ((unification_kind_t, tree*,
tree*));
static int type_unification_real PARAMS ((tree, tree, tree, tree,
- int, unification_kind_t, int));
+ int, unification_kind_t, int, int));
static void note_template_header PARAMS ((int));
static tree maybe_fold_nontype_arg PARAMS ((tree));
static tree convert_nontype_argument PARAMS ((tree, tree));
static tree retrieve_specialization PARAMS ((tree, tree));
static tree retrieve_local_specialization PARAMS ((tree));
static tree register_specialization PARAMS ((tree, tree, tree));
-static tree register_local_specialization PARAMS ((tree, tree));
+static void register_local_specialization PARAMS ((tree, tree));
static int unregister_specialization PARAMS ((tree, tree));
static tree reduce_template_parm_level PARAMS ((tree, tree, int));
static tree build_template_decl PARAMS ((tree, tree));
static int mark_template_parm PARAMS ((tree, void *));
static tree tsubst_friend_function PARAMS ((tree, tree));
static tree tsubst_friend_class PARAMS ((tree, tree));
-static tree get_bindings_real PARAMS ((tree, tree, tree, int));
+static tree get_bindings_real PARAMS ((tree, tree, tree, int, int, int));
static int template_decl_level PARAMS ((tree));
static tree maybe_get_template_decl_from_type_decl PARAMS ((tree));
static int check_cv_quals_for_unify PARAMS ((int, tree, tree));
static void regenerate_decl_from_template PARAMS ((tree, tree));
static tree most_specialized PARAMS ((tree, tree, tree));
static tree most_specialized_class PARAMS ((tree, tree));
-static void set_mangled_name_for_template_decl PARAMS ((tree));
static int template_class_depth_real PARAMS ((tree, int));
static tree tsubst_aggr_type PARAMS ((tree, tree, int, tree, int));
-static tree tsubst_decl PARAMS ((tree, tree, tree, tree));
+static tree tsubst_decl PARAMS ((tree, tree, tree));
static tree tsubst_arg_types PARAMS ((tree, tree, int, tree));
static tree tsubst_function_type PARAMS ((tree, tree, int, tree));
static void check_specialization_scope PARAMS ((void));
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));
/* Called once to initialize pt.c. */
init_pt ()
{
ggc_add_tree_root (&pending_templates, 1);
- ggc_add_tree_root (&maybe_templates, 1);
ggc_add_tree_root (&saved_trees, 1);
ggc_add_tree_root (¤t_tinst_level, 1);
}
++processing_template_decl;
current_template_parms
- = tree_cons (build_int_2 (0, processing_template_decl),
+ = tree_cons (size_int (processing_template_decl),
parms, current_template_parms);
TEMPLATE_PARMS_FOR_INLINE (current_template_parms) = 1;
/* Like register_specialization, but for local declarations. We are
registering SPEC, an instantiation of TMPL. */
-static tree
+static void
register_local_specialization (spec, tmpl)
tree spec;
tree tmpl;
slot = htab_find_slot (local_specializations, tmpl, INSERT);
*slot = spec;
-
- return spec;
}
/* Print the list of candidate FNS in an error message. */
/* This is just an ordinary non-member function. Nothing can
be a specialization of that. */
continue;
+ else if (DECL_ARTIFICIAL (fn))
+ /* Cannot specialize functions that are created implicitly. */
+ continue;
else
{
tree decl_arg_types;
Here, S<int>::f is a non-template, but S<int> is a
template class. If FN has the same type as DECL, we
might be in business. */
+
+ if (!DECL_TEMPLATE_INFO (fn))
+ /* Its enclosing class is an explicit specialization
+ of a template class. This is not a candidate. */
+ continue;
+
if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
TREE_TYPE (TREE_TYPE (fn))))
/* The return types differ. */
*targs_out = TREE_PURPOSE (templates);
return TREE_VALUE (templates);
}
+
+/* Returns a chain of parameter types, exactly like the SPEC_TYPES,
+ but with the default argument values filled in from those in the
+ TMPL_TYPES. */
+static tree
+copy_default_args_to_explicit_spec_1 (spec_types,
+ tmpl_types)
+ tree spec_types;
+ tree tmpl_types;
+{
+ tree new_spec_types;
+
+ if (!spec_types)
+ return NULL_TREE;
+
+ if (spec_types == void_list_node)
+ return void_list_node;
+
+ /* Substitute into the rest of the list. */
+ new_spec_types =
+ copy_default_args_to_explicit_spec_1 (TREE_CHAIN (spec_types),
+ TREE_CHAIN (tmpl_types));
+
+ /* Add the default argument for this parameter. */
+ return hash_tree_cons (TREE_PURPOSE (tmpl_types),
+ TREE_VALUE (spec_types),
+ new_spec_types);
+}
+
+/* DECL is an explicit specialization. Replicate default arguments
+ from the template it specializes. (That way, code like:
+
+ template <class T> void f(T = 3);
+ template <> void f(double);
+ void g () { f (); }
+
+ works, as required.) An alternative approach would be to look up
+ the correct default arguments at the call-site, but this approach
+ is consistent with how implicit instantiations are handled. */
+
+static void
+copy_default_args_to_explicit_spec (decl)
+ tree decl;
+{
+ tree tmpl;
+ tree spec_types;
+ tree tmpl_types;
+ tree new_spec_types;
+ tree old_type;
+ tree new_type;
+ tree t;
+ tree object_type = NULL_TREE;
+ tree in_charge = NULL_TREE;
+ tree vtt = NULL_TREE;
+
+ /* See if there's anything we need to do. */
+ tmpl = DECL_TI_TEMPLATE (decl);
+ tmpl_types = TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (tmpl)));
+ for (t = tmpl_types; t; t = TREE_CHAIN (t))
+ if (TREE_PURPOSE (t))
+ break;
+ if (!t)
+ return;
+
+ old_type = TREE_TYPE (decl);
+ spec_types = TYPE_ARG_TYPES (old_type);
+
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+ {
+ /* Remove the this pointer, but remember the object's type for
+ CV quals. */
+ object_type = TREE_TYPE (TREE_VALUE (spec_types));
+ spec_types = TREE_CHAIN (spec_types);
+ tmpl_types = TREE_CHAIN (tmpl_types);
+
+ if (DECL_HAS_IN_CHARGE_PARM_P (decl))
+ {
+ /* DECL may contain more parameters than TMPL due to the extra
+ in-charge parameter in constructors and destructors. */
+ in_charge = spec_types;
+ spec_types = TREE_CHAIN (spec_types);
+ }
+ if (DECL_HAS_VTT_PARM_P (decl))
+ {
+ vtt = spec_types;
+ spec_types = TREE_CHAIN (spec_types);
+ }
+ }
+
+ /* Compute the merged default arguments. */
+ new_spec_types =
+ copy_default_args_to_explicit_spec_1 (spec_types, tmpl_types);
+
+ /* Compute the new FUNCTION_TYPE. */
+ if (object_type)
+ {
+ if (vtt)
+ new_spec_types = hash_tree_cons (TREE_PURPOSE (vtt),
+ TREE_VALUE (vtt),
+ new_spec_types);
+
+ if (in_charge)
+ /* Put the in-charge parameter back. */
+ new_spec_types = hash_tree_cons (TREE_PURPOSE (in_charge),
+ TREE_VALUE (in_charge),
+ new_spec_types);
+
+ new_type = build_cplus_method_type (object_type,
+ TREE_TYPE (old_type),
+ new_spec_types);
+ }
+ else
+ new_type = build_function_type (TREE_TYPE (old_type),
+ new_spec_types);
+ new_type = build_type_attribute_variant (new_type,
+ TYPE_ATTRIBUTES (old_type));
+ new_type = build_exception_variant (new_type,
+ TYPE_RAISES_EXCEPTIONS (old_type));
+ TREE_TYPE (decl) = new_type;
+}
+
/* Check to see if the function just declared, as indicated in
DECLARATOR, and in DECL, is a specialization of a function
template. We may also discover that the declaration is an explicit
else if (TREE_CODE (TREE_OPERAND (declarator, 0)) == LOOKUP_EXPR)
{
/* A friend declaration. We can't do much, because we don't
- know what this resolves to, yet. */
+ know what this resolves to, yet. */
my_friendly_assert (is_friend != 0, 0);
my_friendly_assert (!explicit_instantiation, 0);
SET_DECL_IMPLICIT_INSTANTIATION (decl);
return tmpl;
}
- /* If we though that the DECL was a member function, but it
+ /* If we thought that the DECL was a member function, but it
turns out to be specializing a static member function,
make DECL a static member function as well. */
if (DECL_STATIC_FUNCTION_P (tmpl)
/* Set up the DECL_TEMPLATE_INFO for DECL. */
DECL_TEMPLATE_INFO (decl) = tree_cons (tmpl, targs, NULL_TREE);
- /* Mangle the function name appropriately. Note that we do
- not mangle specializations of non-template member
- functions of template classes, e.g. with
-
- template <class T> struct S { void f(); }
-
- and given the specialization
-
- template <> void S<int>::f() {}
+ /* Inherit default function arguments from the template
+ DECL is specializing. */
+ copy_default_args_to_explicit_spec (decl);
- we do not mangle S<int>::f() here. That's because it's
- just an ordinary member function and doesn't need special
- treatment. We do this here so that the ordinary,
- non-template, name-mangling algorithm will not be used
- later. */
- if ((is_member_template (tmpl) || ctype == NULL_TREE)
- && name_mangling_version >= 1)
- set_mangled_name_for_template_decl (decl);
+ /* This specialization has the same protection as the
+ template it specializes. */
+ TREE_PRIVATE (decl) = TREE_PRIVATE (gen_tmpl);
+ TREE_PROTECTED (decl) = TREE_PROTECTED (gen_tmpl);
if (is_friend && !have_def)
/* This is not really a declaration of a specialization.
It's just the name of an instantiation. But, it's not
a request for an instantiation, either. */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
+ else if (DECL_CONSTRUCTOR_P (decl) || DECL_DESTRUCTOR_P (decl))
+ /* This is indeed a specialization. In case of constructors
+ and destructors, we need in-charge and not-in-charge
+ versions in V3 ABI. */
+ clone_function_decl (decl, /*update_method_vec_p=*/0);
/* Register this specialization so that we can find it
again. */
decl, type);
TEMPLATE_PARM_DESCENDANTS (index) = t;
+ DECL_ARTIFICIAL (decl) = 1;
+ SET_DECL_TEMPLATE_PARM_P (decl);
+
/* Template template parameters need this. */
DECL_TEMPLATE_PARMS (decl)
= DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index));
my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);
/* is a const-param */
parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
- PARM, 0, NULL_TREE);
+ PARM, 0, NULL);
/* [temp.param]
/* A template parameter is not modifiable. */
TREE_READONLY (parm) = 1;
- if (IS_AGGR_TYPE (TREE_TYPE (parm))
- && TREE_CODE (TREE_TYPE (parm)) != TEMPLATE_TYPE_PARM
- && TREE_CODE (TREE_TYPE (parm)) != TYPENAME_TYPE)
- {
- cp_error ("`%#T' is not a valid type for a template constant parameter",
- TREE_TYPE (parm));
- if (DECL_NAME (parm) == NULL_TREE)
- error (" a template type parameter must begin with `class' or `typename'");
- TREE_TYPE (parm) = void_type_node;
- }
- else if (pedantic
- && (TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE
- || TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE))
- cp_pedwarn ("`%T' is not a valid type for a template constant parameter",
- TREE_TYPE (parm));
+ if (invalid_nontype_parm_type_p (TREE_TYPE (parm), 1))
+ TREE_TYPE (parm) = void_type_node;
decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
DECL_INITIAL (parm) = DECL_INITIAL (decl)
= build_template_parm_index (idx, processing_template_decl,
tree saved_parmlist = make_tree_vec (list_length (parms));
current_template_parms
- = tree_cons (build_int_2 (0, processing_template_decl),
+ = tree_cons (size_int (processing_template_decl),
saved_parmlist, current_template_parms);
for (parm = parms, nparms = 0;
current_class_type)))
/* And, if it was a member function, it really was defined in
the scope of the class. */
- && (!DECL_FUNCTION_MEMBER_P (decl) || DECL_DEFINED_IN_CLASS_P (decl)))
+ && (!DECL_FUNCTION_MEMBER_P (decl) || DECL_INITIALIZED_IN_CLASS_P (decl)))
/* We already checked these parameters when the template was
declared, so there's no need to do it again now. This function
was defined in class scope, but we're processing it's body now
/* Figure out what error message to issue. */
if (TREE_CODE (decl) == FUNCTION_DECL)
- msg = "default argument for template parameter in function template `%D'";
+ msg = "default template arguments may not be used in function templates";
else if (is_partial)
- msg = "default argument in partial specialization `%D'";
+ msg = "default template arguments may not be used in partial specializations";
else
msg = "default argument for template parameter for class enclosing `%D'";
{
SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
if ((!ctx || TREE_CODE (ctx) != FUNCTION_DECL)
- && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
+ && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
+ /* Don't change the name if we've already set it up. */
+ && !IDENTIFIER_TEMPLATE (DECL_NAME (decl)))
DECL_NAME (decl) = classtype_mangled_name (TREE_TYPE (decl));
}
else if (DECL_LANG_SPECIFIC (decl))
}
else if (INTEGRAL_TYPE_P (expr_type)
|| TYPE_PTRMEM_P (expr_type)
- || TYPE_PTRMEMFUNC_P (expr_type)
- /* The next two are g++ extensions. */
- || TREE_CODE (expr_type) == REAL_TYPE
- || TREE_CODE (expr_type) == COMPLEX_TYPE)
+ || TYPE_PTRMEMFUNC_P (expr_type))
{
if (! TREE_CONSTANT (expr))
{
return expr;
- case REAL_TYPE:
- case COMPLEX_TYPE:
- /* These are g++ extensions. */
- if (TREE_CODE (expr_type) != TREE_CODE (type))
- return error_mark_node;
-
- expr = digest_init (type, expr, (tree*) 0);
-
- if (TREE_CODE (expr) != REAL_CST)
- goto non_constant;
-
- return expr;
-
case POINTER_TYPE:
{
tree type_pointed_to = TREE_TYPE (type);
case RECORD_TYPE:
{
- if (!TYPE_PTRMEMFUNC_P (type))
- /* This handles templates like
- template<class T, T t> void f();
- when T is substituted with any class. The second template
- parameter becomes invalid and the template candidate is
- rejected. */
- return error_mark_node;
+ my_friendly_assert (TYPE_PTRMEMFUNC_P (type), 20010112);
/* For a non-type template-parameter of type pointer to member
function, no conversions apply. If the template-argument
tree t = no_linkage_check (val);
if (t)
{
- if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+ if (TYPE_ANONYMOUS_P (t))
cp_pedwarn
("template-argument `%T' uses anonymous type", val);
else
{
tree t = tsubst (TREE_TYPE (parm), args, complain, in_decl);
+ if (invalid_nontype_parm_type_p (t, complain))
+ return error_mark_node;
+
if (processing_template_decl)
arg = maybe_fold_nontype_arg (arg);
tree ti = (TYPE_P (d)
? CLASSTYPE_TEMPLATE_INFO (d)
: DECL_TEMPLATE_INFO (d));
+ tree pt;
int level;
if (TI_PENDING_TEMPLATE_FLAG (ti))
if (level)
push_tinst_level (d);
- *template_tail = tree_cons (current_tinst_level, d, NULL_TREE);
- template_tail = &TREE_CHAIN (*template_tail);
+ pt = tree_cons (current_tinst_level, d, NULL_TREE);
+ if (last_pending_template)
+ TREE_CHAIN (last_pending_template) = pt;
+ else
+ pending_templates = pt;
+
+ last_pending_template = pt;
+
TI_PENDING_TEMPLATE_FLAG (ti) = 1;
if (level)
If ENTERING_SCOPE is non-zero, we are about to enter the scope of
the class we are looking up.
+
+ If COMPLAIN is non-zero, issue error messages.
If the template class is really a local class in a template
function, then the FUNCTION_CONTEXT is the function in which it is
being instantiated. */
tree
-lookup_template_class (d1, arglist, in_decl, context, entering_scope)
+lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
tree d1, arglist;
tree in_decl;
tree context;
int entering_scope;
+ int complain;
{
tree template = NULL_TREE, parmlist;
tree t;
crash. Alternatively D1 might not be a template type at all. */
if (! template)
{
- cp_error ("`%T' is not a template", d1);
+ if (complain)
+ cp_error ("`%T' is not a template", d1);
return error_mark_node;
}
- if (TREE_CODE (template) != TEMPLATE_DECL)
+ if (TREE_CODE (template) != TEMPLATE_DECL
+ /* If we're called from the parser, make sure it's a user visible
+ template. */
+ || ((!arglist || TREE_CODE (arglist) == TREE_LIST)
+ && !DECL_TEMPLATE_PARM_P (template)
+ && !PRIMARY_TEMPLATE_P (template)))
{
- cp_error ("non-template type `%T' used as a template", d1);
- if (in_decl)
- cp_error_at ("for template declaration `%D'", in_decl);
+ if (complain)
+ {
+ cp_error ("non-template type `%T' used as a template", d1);
+ if (in_decl)
+ cp_error_at ("for template declaration `%D'", in_decl);
+ }
return error_mark_node;
}
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
- arglist2 = coerce_template_parms (parmlist, arglist, template, 1, 1);
+ /* Consider an example where a template template parameter declared as
+
+ template <class T, class U = std::allocator<T> > class TT
+
+ The template parameter level of T and U are one level larger than
+ of TT. To proper process the default argument of U, say when an
+ instantiation `TT<int>' is seen, we need to build the full
+ arguments containing {int} as the innermost level. Outer levels
+ can be obtained from `current_template_args ()'. */
+
+ if (processing_template_decl)
+ arglist = add_to_template_args (current_template_args (), arglist);
+
+ arglist2 = coerce_template_parms (parmlist, arglist, template,
+ complain, /*require_all_args=*/1);
if (arglist2 == error_mark_node)
return error_mark_node;
- parm = copy_template_template_parm (TREE_TYPE (template), arglist2);
- TYPE_SIZE (parm) = 0;
+ parm = bind_template_template_parm (TREE_TYPE (template), arglist2);
return parm;
}
else
tree gen_tmpl;
tree type_decl;
tree found = NULL_TREE;
+ tree *tp;
int arg_depth;
int parm_depth;
int is_partial_instantiation;
--i, t = TREE_CHAIN (t))
{
tree a = coerce_template_parms (TREE_VALUE (t),
- arglist, template, 1, 1);
+ arglist, template,
+ complain, /*require_all_args=*/1);
SET_TMPL_ARGS_LEVEL (bound_args, i, a);
/* We temporarily reduce the length of the ARGLIST so
arglist
= coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
INNERMOST_TEMPLATE_ARGS (arglist),
- template, 1, 1);
+ template,
+ complain, /*require_all_args=*/1);
if (arglist == error_mark_node)
/* We were unable to bind the arguments. */
}
if (found)
return found;
-
- for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
- found; found = TREE_CHAIN (found))
- if (comp_template_args (TREE_PURPOSE (found), arglist))
- return TREE_VALUE (found);
+
+ for (tp = &DECL_TEMPLATE_INSTANTIATIONS (template);
+ *tp;
+ tp = &TREE_CHAIN (*tp))
+ if (comp_template_args (TREE_PURPOSE (*tp), arglist))
+ {
+ found = *tp;
+
+ /* Use the move-to-front heuristic to speed up future
+ searches. */
+ *tp = TREE_CHAIN (*tp);
+ TREE_CHAIN (found)
+ = DECL_TEMPLATE_INSTANTIATIONS (template);
+ DECL_TEMPLATE_INSTANTIATIONS (template) = found;
+
+ return TREE_VALUE (found);
+ }
/* This type is a "partial instantiation" if any of the template
arguments still involve template parameters. Note that we set
is set up. */
if (TREE_CODE (t) != ENUMERAL_TYPE)
DECL_NAME (type_decl) = classtype_mangled_name (t);
- DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl);
if (!is_partial_instantiation)
{
- if (flag_new_abi)
- DECL_ASSEMBLER_NAME (type_decl) = mangle_decl (type_decl);
- else
- DECL_ASSEMBLER_NAME (type_decl)
- = get_identifier (build_overload_name (t, 1, 1));
-
/* For backwards compatibility; code that uses
-fexternal-templates expects looking up a template to
instantiate it. I think DDD still relies on this.
explicitly here. */
if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data))
return error_mark_node;
+ /* Fall through. */
case FUNCTION_TYPE:
/* Check the return type. */
pfd.fn = fn;
pfd.data = data;
- /* Walk the tree. */
- return walk_tree_without_duplicates (&t,
- for_each_template_parm_r,
- &pfd) != NULL_TREE;
+ /* Walk the tree. (Conceptually, we would like to walk without
+ duplicates, but for_each_template_parm_r recursively calls
+ for_each_template_parm, so we would need to reorganize a fair
+ bit to use walk_tree_without_duplicates.) */
+ return walk_tree (&t,
+ for_each_template_parm_r,
+ &pfd,
+ NULL) != NULL_TREE;
}
int
= DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (decl));
}
- /* The mangled name for the NEW_FRIEND is incorrect. The call to
- tsubst will have resulted in a call to
- set_mangled_name_for_template_decl. But, the function is not a
- template instantiation and should not be mangled like one.
- Therefore, we remangle the function name. We don't have to do
- this if the NEW_FRIEND is a template since
- set_mangled_name_for_template_decl doesn't do anything if the
- function declaration still uses template arguments. */
+ /* The mangled name for the NEW_FRIEND is incorrect. The function
+ is not a template instantiation and should not be mangled like
+ one. Therefore, we forget the mangling here; we'll recompute it
+ later if we need it. */
if (TREE_CODE (new_friend) != TEMPLATE_DECL)
{
- set_mangled_name_for_decl (new_friend);
- DECL_RTL (new_friend) = 0;
- make_decl_rtl (new_friend, NULL_PTR, 1);
+ SET_DECL_RTL (new_friend, NULL_RTX);
+ SET_DECL_ASSEMBLER_NAME (new_friend, NULL_TREE);
}
if (DECL_NAMESPACE_SCOPE_P (new_friend))
{
CLASSTYPE_INTERFACE_ONLY (type) = interface_only;
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (type, interface_unknown);
- CLASSTYPE_VTABLE_NEEDS_WRITING (type)
- = (! CLASSTYPE_INTERFACE_ONLY (type)
- && CLASSTYPE_INTERFACE_KNOWN (type));
}
else
{
CLASSTYPE_INTERFACE_ONLY (type) = CLASSTYPE_INTERFACE_ONLY (pattern);
SET_CLASSTYPE_INTERFACE_UNKNOWN_X
(type, CLASSTYPE_INTERFACE_UNKNOWN (pattern));
- CLASSTYPE_VTABLE_NEEDS_WRITING (type)
- = (! CLASSTYPE_INTERFACE_ONLY (type)
- && CLASSTYPE_INTERFACE_KNOWN (type));
}
}
else
{
SET_CLASSTYPE_INTERFACE_UNKNOWN (type);
- CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1;
}
TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern);
TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);
TYPE_HAS_ARRAY_NEW_OPERATOR (type) = TYPE_HAS_ARRAY_NEW_OPERATOR (pattern);
TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);
- TYPE_VEC_DELETE_TAKES_SIZE (type) = TYPE_VEC_DELETE_TAKES_SIZE (pattern);
TYPE_HAS_ASSIGN_REF (type) = TYPE_HAS_ASSIGN_REF (pattern);
TYPE_HAS_CONST_ASSIGN_REF (type) = TYPE_HAS_CONST_ASSIGN_REF (pattern);
TYPE_HAS_ABSTRACT_ASSIGN_REF (type) = TYPE_HAS_ABSTRACT_ASSIGN_REF (pattern);
tree newtag;
newtag = tsubst (tag, args, /*complain=*/1, NULL_TREE);
+ my_friendly_assert (newtag != error_mark_node, 20010206);
if (TREE_CODE (newtag) != ENUMERAL_TYPE)
{
if (TYPE_LANG_SPECIFIC (tag) && CLASSTYPE_IS_TEMPLATE (tag))
{
tree init;
- if (DECL_DEFINED_IN_CLASS_P (r))
+ if (DECL_INITIALIZED_IN_CLASS_P (r))
init = tsubst_expr (DECL_INITIAL (t), args,
/*complain=*/1, NULL_TREE);
else
/*asmspec_tree=*/NULL_TREE,
/*flags=*/0);
- if (DECL_DEFINED_IN_CLASS_P (r))
+ if (DECL_INITIALIZED_IN_CLASS_P (r))
check_static_variable_definition (r, TREE_TYPE (r));
}
maybe_fold_nontype_arg (arg)
tree arg;
{
- /* If we're not in a template, ARG is already as simple as it's going to
- get, and trying to reprocess the trees will break. */
- if (! processing_template_decl)
- return arg;
-
- if (!TYPE_P (arg) && !uses_template_parms (arg))
+ if (arg && !TYPE_P (arg) && !uses_template_parms (arg))
{
/* Sometimes, one of the args was an expression involving a
template constant parameter, like N - 1. Now that we've
fool build_expr_from_tree() into building an actual
tree. */
- int saved_processing_template_decl = processing_template_decl;
- processing_template_decl = 0;
- arg = fold (build_expr_from_tree (arg));
- processing_template_decl = saved_processing_template_decl;
+ /* If the TREE_TYPE of ARG is not NULL_TREE, ARG is already
+ as simple as it's going to get, and trying to reprocess
+ the trees will break. */
+ if (!TREE_TYPE (arg))
+ {
+ int saved_processing_template_decl = processing_template_decl;
+ processing_template_decl = 0;
+ arg = build_expr_from_tree (arg);
+ processing_template_decl = saved_processing_template_decl;
+ }
+
+ arg = fold (arg);
}
return arg;
}
TREE_VALUE (TREE_VEC_ELT (TREE_VALUE (parms), i));
TREE_VEC_ELT (new_vec, i)
- = build_tree_list (tsubst (default_value, args, complain,
- NULL_TREE),
+ = build_tree_list (maybe_fold_nontype_arg (
+ tsubst_expr (default_value, args, complain,
+ NULL_TREE)),
tsubst (parm_decl, args, complain,
NULL_TREE));
}
*new_parms =
- tree_cons (build_int_2 (0, (TMPL_PARMS_DEPTH (parms)
- - TMPL_ARGS_DEPTH (args))),
+ tree_cons (size_int (TMPL_PARMS_DEPTH (parms)
+ - TMPL_ARGS_DEPTH (args)),
new_vec, NULL_TREE);
}
return error_mark_node;
r = lookup_template_class (t, argvec, in_decl, context,
- entering_scope);
+ entering_scope, complain);
return cp_build_qualified_type_real (r, TYPE_QUALS (t),
complain);
/* Substitute the ARGS into the T, which is a _DECL. TYPE is the
(already computed) substitution of ARGS into TREE_TYPE (T), if
- appropriate. Return the result of the substitution. IN_DECL is as
- for tsubst. */
+ appropriate. Return the result of the substitution. */
static tree
-tsubst_decl (t, args, type, in_decl)
+tsubst_decl (t, args, type)
tree t;
tree args;
tree type;
- tree in_decl;
{
int saved_lineno;
const char *saved_filename;
tree r = NULL_TREE;
+ tree in_decl = t;
/* Set the filename and linenumber to improve error-reporting. */
saved_lineno = lineno;
r = copy_decl (t);
DECL_USE_TEMPLATE (r) = 0;
TREE_TYPE (r) = type;
+ /* Clear out the mangled name and RTL for the instantiation. */
+ SET_DECL_ASSEMBLER_NAME (r, NULL_TREE);
+ SET_DECL_RTL (r, NULL_RTX);
DECL_CONTEXT (r) = ctx;
DECL_VIRTUAL_CONTEXT (r)
/*entering_scope=*/1);
if (member && DECL_CONV_FN_P (r))
- {
- /* Type-conversion operator. Reconstruct the name, in
- case it's the name of one of the template's parameters. */
- if (flag_new_abi)
- DECL_NAME (r) = mangle_conv_op_name_for_type (TREE_TYPE (type));
- else
- DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
- }
+ /* Type-conversion operator. Reconstruct the name, in
+ case it's the name of one of the template's parameters. */
+ DECL_NAME (r) = mangle_conv_op_name_for_type (TREE_TYPE (type));
DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args,
/*complain=*/1, t);
- DECL_TEMPLATE_RESULT (r) = NULL_TREE;
+ DECL_RESULT (r) = NULL_TREE;
TREE_STATIC (r) = 0;
TREE_PUBLIC (r) = TREE_PUBLIC (t);
TREE_CHAIN (DECL_CLONED_FUNCTION (r)) = r;
}
- /* Set up the DECL_TEMPLATE_INFO for R and compute its mangled
- name. There's no need to do this in the special friend
- case mentioned above where GEN_TMPL is NULL. */
+ /* Set up the DECL_TEMPLATE_INFO for R. There's no need to do
+ this in the special friend case mentioned above where
+ GEN_TMPL is NULL. */
if (gen_tmpl)
{
DECL_TEMPLATE_INFO (r)
SET_DECL_IMPLICIT_INSTANTIATION (r);
register_specialization (r, gen_tmpl, argvec);
- /* Set the mangled name for R. */
- if (DECL_DESTRUCTOR_P (t))
- {
- if (flag_new_abi)
- set_mangled_name_for_decl (r);
- else
- DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx);
- }
- else
- {
- /* Instantiations of template functions must be mangled
- specially, in order to conform to 14.5.5.1
- [temp.over.link]. */
- tree tmpl = DECL_TI_TEMPLATE (t);
-
- /* TMPL will be NULL if this is a specialization of a
- member function of a template class. */
- if (name_mangling_version < 1
- || tmpl == NULL_TREE
- || (member && !is_member_template (tmpl)
- && !DECL_TEMPLATE_INFO (tmpl)))
- set_mangled_name_for_decl (r);
- else
- set_mangled_name_for_template_decl (r);
- }
-
- DECL_RTL (r) = 0;
- make_decl_rtl (r, NULL_PTR, 1);
-
- /* Like grokfndecl. If we don't do this, pushdecl will
- mess up our TREE_CHAIN because it doesn't find a
- previous decl. Sigh. */
- if (member
- && ! uses_template_parms (r)
- && (IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r))
- == NULL_TREE))
- SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
-
/* We're not supposed to instantiate default arguments
until they are called, for a template. But, for a
declaration like:
maybe_retrofit_in_chrg (r);
if (DECL_CONSTRUCTOR_P (r))
grok_ctor_properties (ctx, r);
+ /* If this is an instantiation of a member template, clone it.
+ 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);
}
else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
DECL_CONTEXT (r) = NULL_TREE;
if (PROMOTE_PROTOTYPES
- && (TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE)
+ && INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (r) = integer_type_node;
if (TREE_CHAIN (t))
DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args,
/*complain=*/1, in_decl);
TREE_CHAIN (r) = NULL_TREE;
- if (TREE_CODE (type) == VOID_TYPE)
- cp_error_at ("instantiation of `%D' as type void", r);
+ if (VOID_TYPE_P (type))
+ cp_error_at ("instantiation of `%D' as type `%T'", r, type);
}
break;
ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
/*complain=*/1,
in_decl, /*entering_scope=*/1);
+ else if (DECL_NAMESPACE_SCOPE_P (t))
+ ctx = DECL_CONTEXT (t);
else
{
/* Subsequent calls to pushdecl will fill this in. */
ctx = NULL_TREE;
- if (!DECL_NAMESPACE_SCOPE_P (t))
- local_p = 1;
+ local_p = 1;
}
/* Check to see if we already have this specialization. */
TREE_TYPE (r) = type;
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);
+ SET_DECL_RTL (r, NULL_RTX);
/* Don't try to expand the initializer until someone tries to use
this variable; otherwise we run into circular dependencies. */
DECL_INITIAL (r) = NULL_TREE;
- DECL_RTL (r) = 0;
+ SET_DECL_RTL (r, NULL_RTX);
DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0;
/* For __PRETTY_FUNCTION__ we have to adjust the initializer. */
if (DECL_PRETTY_FUNCTION_P (r))
{
- DECL_INITIAL (r) = tsubst (DECL_INITIAL (t),
- args,
- /*complain=*/1,
- NULL_TREE);
+ const char *const name = (*decl_printable_name)
+ (current_function_decl, 2);
+ DECL_INITIAL (r) = cp_fname_init (name);
TREE_TYPE (r) = TREE_TYPE (DECL_INITIAL (r));
}
register_local_specialization (r, t);
TREE_CHAIN (r) = NULL_TREE;
- if (TREE_CODE (r) == VAR_DECL && TREE_CODE (type) == VOID_TYPE)
- cp_error_at ("instantiation of `%D' as type void", r);
+ if (TREE_CODE (r) == VAR_DECL && VOID_TYPE_P (type))
+ cp_error_at ("instantiation of `%D' as type `%T'", r, type);
}
break;
type = tsubst (TREE_VALUE (arg_types), args, complain, in_decl);
if (type == error_mark_node)
return error_mark_node;
+ if (VOID_TYPE_P (type))
+ {
+ if (complain)
+ {
+ cp_error ("invalid parameter type `%T'", type);
+ if (in_decl)
+ cp_error_at ("in declaration `%D'", in_decl);
+ }
+ return error_mark_node;
+ }
/* Do array-to-pointer, function-to-pointer conversion, and ignore
top-level qualifiers as required. */
return error_mark_node;
if (DECL_P (t))
- return tsubst_decl (t, args, type, in_decl);
+ return tsubst_decl (t, args, type);
switch (TREE_CODE (t))
{
case ERROR_MARK:
case IDENTIFIER_NODE:
- case OP_IDENTIFIER:
case VOID_TYPE:
case REAL_TYPE:
case COMPLEX_TYPE:
r = lookup_template_class (arg,
argvec, in_decl,
DECL_CONTEXT (arg),
- /*entering_scope=*/0);
+ /*entering_scope=*/0,
+ complain);
return cp_build_qualified_type_real (r,
TYPE_QUALS (t),
complain);
}
else
{
- r = copy_node (t);
+ r = copy_type (t);
TEMPLATE_TYPE_PARM_INDEX (r)
= reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
r, levels);
&& value == TREE_VALUE (t)
&& chain == TREE_CHAIN (t))
return t;
- result = hash_tree_cons (purpose, value, chain);
- TREE_PARMLIST (result) = TREE_PARMLIST (t);
+ if (TREE_PARMLIST (t))
+ {
+ result = tree_cons (purpose, value, chain);
+ TREE_PARMLIST (result) = 1;
+ }
+ else
+ result = hash_tree_cons (purpose, value, chain);
return result;
}
case TREE_VEC:
if (e1 == error_mark_node || e2 == error_mark_node)
return error_mark_node;
- return build_parse_node (ARRAY_REF, e1, e2, tsubst_expr);
+ return build_nt (ARRAY_REF, e1, e2, tsubst_expr);
}
case CALL_EXPR:
if (e1 == error_mark_node || e2 == error_mark_node)
return error_mark_node;
- return build_parse_node (TREE_CODE (t), e1, e2);
+ return build_nt (TREE_CODE (t), e1, e2);
}
case TYPEOF_TYPE:
return TREE_TYPE (e1);
}
- case FUNCTION_NAME:
- {
- const char *name;
- int len;
- tree type;
- tree str;
-
- /* This code should match declare_hidden_char_array in
- c-common.c. */
- name = (*decl_printable_name) (current_function_decl, 2);
- len = strlen (name) + 1;
- type = build_array_type (char_type_node,
- build_index_type (build_int_2 (len, 0)));
- str = build_string (len, name);
- TREE_TYPE (str) = type;
- return str;
- }
-
default:
sorry ("use of `%s' in template",
tree_code_name [(int) TREE_CODE (t)]);
case LOOKUP_EXPR:
{
- /* We must tsbust into a LOOKUP_EXPR in case the names to
+ /* We must tsubst into a LOOKUP_EXPR in case the names to
which it refers is a conversion operator; in that case the
name will change. We avoid making unnecessary copies,
however. */
tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl));
case INDIRECT_REF:
- case PREDECREMENT_EXPR:
- case PREINCREMENT_EXPR:
- case POSTDECREMENT_EXPR:
- case POSTINCREMENT_EXPR:
case NEGATE_EXPR:
case TRUTH_NOT_EXPR:
case BIT_NOT_EXPR:
case SCOPE_REF:
case DOTSTAR_EXPR:
case MEMBER_REF:
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
return build_nt
(code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
if (IDENTIFIER_TYPENAME_P (t))
{
tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
- if (flag_new_abi)
- return mangle_conv_op_name_for_type (new_type);
- else
- return (build_typename_overload (new_type));
+ return mangle_conv_op_name_for_type (new_type);
}
else
return t;
in_decl),
tsubst (TREE_TYPE (t), args, complain, in_decl));
- case FUNCTION_NAME:
- return tsubst (t, args, complain, in_decl);
-
default:
return t;
}
int complain;
tree in_decl;
{
- tree stmt;
+ tree stmt, tmp;
if (t == NULL_TREE || t == error_mark_node)
return t;
if (processing_template_decl)
return tsubst_copy (t, args, complain, in_decl);
+ if (!statement_code_p (TREE_CODE (t)))
+ return build_expr_from_tree (tsubst_copy (t, args, complain, in_decl));
+
switch (TREE_CODE (t))
{
case RETURN_INIT:
finish_named_return_value
(TREE_OPERAND (t, 0),
tsubst_expr (TREE_OPERAND (t, 1), args, /*complain=*/1, in_decl));
- tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
break;
case CTOR_INITIALIZER:
base_init_list
= tsubst_initializer_list (TREE_OPERAND (t, 1), args);
setup_vtbl_ptr (member_init_list, base_init_list);
- tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
break;
}
args, complain, in_decl));
break;
+ case USING_STMT:
+ prep_stmt (t);
+ do_using_directive (tsubst_expr (USING_STMT_NAMESPACE (t),
+ args, complain, in_decl));
+ break;
+
case DECL_STMT:
{
tree decl;
decl = DECL_STMT_DECL (t);
if (TREE_CODE (decl) == LABEL_DECL)
finish_label_decl (DECL_NAME (decl));
+ else if (TREE_CODE (decl) == USING_DECL)
+ {
+ tree scope = DECL_INITIAL (decl);
+ tree name = DECL_NAME (decl);
+
+ scope = tsubst_expr (scope, args, complain, in_decl);
+ do_local_using_decl (build_nt (SCOPE_REF, scope, name));
+ }
else
{
init = DECL_INITIAL (decl);
decl = tsubst (decl, args, complain, in_decl);
- init = tsubst_expr (init, args, complain, in_decl);
+ if (DECL_PRETTY_FUNCTION_P (decl))
+ init = DECL_INITIAL (decl);
+ else
+ init = tsubst_expr (init, args, complain, in_decl);
if (decl != error_mark_node)
{
if (TREE_CODE (decl) != TYPE_DECL)
cp_finish_decl (decl, init, NULL_TREE, 0);
}
}
- return decl;
+
+ /* A DECL_STMT can also be used as an expression, in the condition
+ clause of a if/for/while construct. If we aren't followed by
+ another statement, return our decl. */
+ if (TREE_CHAIN (t) == NULL_TREE)
+ return decl;
}
+ break;
case FOR_STMT:
{
- tree tmp;
prep_stmt (t);
stmt = begin_for_stmt ();
- for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp))
- tsubst_expr (tmp, args, complain, in_decl);
+ tsubst_expr (FOR_INIT_STMT (t), args, complain, in_decl);
finish_for_init_stmt (stmt);
finish_for_cond (tsubst_expr (FOR_COND (t), args,
complain, in_decl),
case IF_STMT:
{
- tree tmp;
-
prep_stmt (t);
stmt = begin_if_stmt ();
finish_if_stmt_cond (tsubst_expr (IF_COND (t),
case COMPOUND_STMT:
{
- tree substmt;
-
prep_stmt (t);
stmt = begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
- for (substmt = COMPOUND_BODY (t);
- substmt != NULL_TREE;
- substmt = TREE_CHAIN (substmt))
- tsubst_expr (substmt, args, complain, in_decl);
- return finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), stmt);
+ tsubst_expr (COMPOUND_BODY (t), args, complain, in_decl);
+ finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), stmt);
}
break;
case GOTO_STMT:
prep_stmt (t);
- t = GOTO_DESTINATION (t);
- if (TREE_CODE (t) != LABEL_DECL)
+ tmp = GOTO_DESTINATION (t);
+ if (TREE_CODE (tmp) != LABEL_DECL)
/* Computed goto's must be tsubst'd into. On the other hand,
non-computed gotos must not be; the identifier in question
will have no binding. */
- t = tsubst_expr (t, args, complain, in_decl);
+ tmp = tsubst_expr (tmp, args, complain, in_decl);
else
- t = DECL_NAME (t);
- finish_goto_stmt (t);
+ tmp = DECL_NAME (tmp);
+ finish_goto_stmt (tmp);
break;
case ASM_STMT:
}
else
{
- tree handler;
-
if (FN_TRY_BLOCK_P (t))
stmt = begin_function_try_block ();
else
else
finish_try_block (stmt);
- handler = TRY_HANDLERS (t);
- for (; handler; handler = TREE_CHAIN (handler))
- tsubst_expr (handler, args, complain, in_decl);
+ tsubst_expr (TRY_HANDLERS (t), args, complain, in_decl);
if (FN_TRY_BLOCK_P (t))
finish_function_handler_sequence (stmt);
else
case HANDLER:
{
tree decl;
- tree blocks;
prep_stmt (t);
stmt = begin_handler ();
}
else
decl = NULL_TREE;
- blocks = finish_handler_parms (decl, stmt);
+ finish_handler_parms (decl, stmt);
tsubst_expr (HANDLER_BODY (t), args, complain, in_decl);
- finish_handler (blocks, stmt);
+ finish_handler (stmt);
}
break;
case TAG_DEFN:
prep_stmt (t);
- t = TREE_TYPE (t);
- tsubst (t, args, complain, NULL_TREE);
+ tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
break;
+ case CTOR_STMT:
+ add_stmt (copy_node (t));
+ break;
+
default:
- return build_expr_from_tree (tsubst_copy (t, args, complain, in_decl));
+ abort ();
}
- return NULL_TREE;
+
+ return tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
}
/* TMPL is a TEMPLATE_DECL for a cloned constructor or destructor.
return fndecl;
}
-/* Push the name of the class template into the scope of the instantiation. */
-
-void
-overload_template_name (type)
- tree type;
-{
- tree id = DECL_NAME (CLASSTYPE_TI_TEMPLATE (type));
- tree decl;
-
- if (IDENTIFIER_CLASS_VALUE (id)
- && TREE_TYPE (IDENTIFIER_CLASS_VALUE (id)) == type)
- return;
-
- decl = build_decl (TYPE_DECL, id, type);
- DECL_ARTIFICIAL (decl) = 1;
- pushdecl_class_level (decl);
-}
-
/* The FN is a TEMPLATE_DECL for a function. The ARGS are the
arguments that are being used when calling it. TARGS is a vector
into which the deduced template arguments are placed.
all the types, and 1 for complete failure. An error message will be
printed only for an incomplete match.
- If FN is a conversion operator, RETURN_TYPE is the type desired as
- the result of the conversion operator.
-
- TPARMS is a vector of template parameters.
+ If FN is a conversion operator, or we are trying to produce a specific
+ specialization, RETURN_TYPE is the return type desired.
The EXPLICIT_TARGS are explicit template arguments provided via a
template-id.
[temp.deduct.conv].
DEDUCE_EXACT:
+ We are deducing arguments when doing an explicit instantiation
+ as in [temp.explicit], when determining an explicit specialization
+ as in [temp.expl.spec], or when taking the address of a function
+ template, as in [temp.deduct.funcaddr].
+
+ DEDUCE_ORDER:
We are deducing arguments when calculating the partial
ordering between specializations of function or class
- templates, as in [temp.func.order] and [temp.class.order],
- when doing an explicit instantiation as in [temp.explicit],
- when determining an explicit specialization as in
- [temp.expl.spec], or when taking the address of a function
- template, as in [temp.deduct.funcaddr].
+ templates, as in [temp.func.order] and [temp.class.order].
- The other arguments are as for type_unification. */
+ LEN is the number of parms to consider before returning success, or -1
+ for all. This is used in partial ordering to avoid comparing parms for
+ which no actual argument was passed, since they are not considered in
+ overload resolution (and are explicitly excluded from consideration in
+ partial ordering in [temp.func.order]/6). */
int
fn_type_unification (fn, explicit_targs, targs, args, return_type,
- strict)
+ strict, len)
tree fn, explicit_targs, targs, args, return_type;
unification_kind_t strict;
+ int len;
{
tree parms;
tree fntype;
}
parms = TYPE_ARG_TYPES (fntype);
-
- if (DECL_CONV_FN_P (fn))
- {
- /* This is a template conversion operator. Remove `this', since
- we could be comparing conversions from different classes. */
- parms = TREE_CHAIN (parms);
- args = TREE_CHAIN (args);
- my_friendly_assert (return_type != NULL_TREE, 20000227);
- }
+ /* Never do unification on the 'this' parameter. */
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+ parms = TREE_CHAIN (parms);
if (return_type)
{
/* We've been given a return type to match, prepend it. */
parms = tree_cons (NULL_TREE, TREE_TYPE (fntype), parms);
args = tree_cons (NULL_TREE, return_type, args);
+ if (len >= 0)
+ ++len;
}
/* We allow incomplete unification without an error message here
event. */
result = type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
targs, parms, args, /*subr=*/0,
- strict, /*allow_incomplete*/1);
+ strict, /*allow_incomplete*/1, len);
if (result == 0)
/* All is well so far. Now, check:
the argument passed to the call, or the type of the value
initialized with the result of the conversion function. */
-static void
+static int
maybe_adjust_types_for_deduction (strict, parm, arg)
unification_kind_t strict;
tree* parm;
tree* arg;
{
+ int result = 0;
+
switch (strict)
{
case DEDUCE_CALL:
case DEDUCE_EXACT:
/* There is nothing to do in this case. */
- return;
+ return 0;
+ case DEDUCE_ORDER:
+ /* DR 214. [temp.func.order] is underspecified, and leads to no
+ ordering between things like `T *' and `T const &' for `U *'.
+ The former has T=U and the latter T=U*. The former looks more
+ specialized and John Spicer considers it well-formed (the EDG
+ compiler accepts it).
+
+ John also confirms that deduction should proceed as in a function
+ call. Which implies the usual ARG and PARM conversions as DEDUCE_CALL.
+ However, in ordering, ARG can have REFERENCE_TYPE, but no argument
+ to an actual call can have such a type.
+
+ If both ARG and PARM are REFERENCE_TYPE, we change neither.
+ If only ARG is a REFERENCE_TYPE, we look through that and then
+ proceed as with DEDUCE_CALL (which could further convert it). */
+ if (TREE_CODE (*arg) == REFERENCE_TYPE)
+ {
+ if (TREE_CODE (*parm) == REFERENCE_TYPE)
+ return 0;
+ *arg = TREE_TYPE (*arg);
+ }
+ break;
default:
my_friendly_abort (0);
}
type deduction. */
*parm = TYPE_MAIN_VARIANT (*parm);
if (TREE_CODE (*parm) == REFERENCE_TYPE)
- *parm = TREE_TYPE (*parm);
+ {
+ *parm = TREE_TYPE (*parm);
+ result |= UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
+ }
+ return result;
}
-/* Like type_unification.
+/* Most parms like fn_type_unification.
If SUBR is 1, we're being called recursively (to unify the
arguments of a function or method parameter of a function
template). */
static int
-type_unification_real (tparms, targs, parms, args, subr,
- strict, allow_incomplete)
- tree tparms, targs, parms, args;
+type_unification_real (tparms, targs, xparms, xargs, subr,
+ strict, allow_incomplete, xlen)
+ tree tparms, targs, xparms, xargs;
int subr;
unification_kind_t strict;
- int allow_incomplete;
+ int allow_incomplete, xlen;
{
tree parm, arg;
int i;
int ntparms = TREE_VEC_LENGTH (tparms);
int sub_strict;
+ int saw_undeduced = 0;
+ tree parms, args;
+ int len;
my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
- my_friendly_assert (parms == NULL_TREE
- || TREE_CODE (parms) == TREE_LIST, 290);
+ my_friendly_assert (xparms == NULL_TREE
+ || TREE_CODE (xparms) == TREE_LIST, 290);
/* ARGS could be NULL (via a call from parse.y to
build_x_function_call). */
- if (args)
- my_friendly_assert (TREE_CODE (args) == TREE_LIST, 291);
+ if (xargs)
+ my_friendly_assert (TREE_CODE (xargs) == TREE_LIST, 291);
my_friendly_assert (ntparms > 0, 292);
switch (strict)
{
case DEDUCE_CALL:
- sub_strict = UNIFY_ALLOW_MORE_CV_QUAL | UNIFY_ALLOW_DERIVED;
+ sub_strict = (UNIFY_ALLOW_OUTER_LEVEL | UNIFY_ALLOW_MORE_CV_QUAL
+ | UNIFY_ALLOW_DERIVED);
break;
case DEDUCE_CONV:
case DEDUCE_EXACT:
sub_strict = UNIFY_ALLOW_NONE;
break;
+
+ case DEDUCE_ORDER:
+ sub_strict = UNIFY_ALLOW_NONE;
+ break;
default:
my_friendly_abort (0);
}
+ if (xlen == 0)
+ return 0;
+
+ again:
+ parms = xparms;
+ args = xargs;
+ len = xlen;
+
while (parms
&& parms != void_list_node
&& args
arg = NULL_TREE;
}
- if (strict == DEDUCE_EXACT)
+ if (strict == DEDUCE_EXACT || strict == DEDUCE_ORDER)
{
if (same_type_p (parm, type))
continue;
}
arg = TREE_TYPE (arg);
}
+
+ {
+ int arg_strict = sub_strict;
+
+ if (!subr)
+ arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg);
- if (!subr)
- maybe_adjust_types_for_deduction (strict, &parm, &arg);
+ if (unify (tparms, targs, parm, arg, arg_strict))
+ return 1;
+ }
- if (unify (tparms, targs, parm, arg, sub_strict))
- return 1;
+ /* Are we done with the interesting parms? */
+ if (--len == 0)
+ goto done;
}
/* Fail if we've reached the end of the parm list, and more args
are present, and the parm list isn't variadic. */
&& parms != void_list_node
&& TREE_PURPOSE (parms) == NULL_TREE)
return 1;
+
+ done:
if (!subr)
for (i = 0; i < ntparms; i++)
if (TREE_VEC_ELT (targs, i) == NULL_TREE)
{
+ tree tparm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
+
+ /* If this is an undeduced nontype parameter that depends on
+ a type parameter, try another pass; its type may have been
+ deduced from a later argument than the one from which
+ this parameter can be deduced. */
+ if (TREE_CODE (tparm) == PARM_DECL
+ && uses_template_parms (TREE_TYPE (tparm))
+ && !saw_undeduced++)
+ goto again;
+
if (!allow_incomplete)
error ("incomplete type unification");
return 2;
if (uses_template_parms (arg))
return 1;
- maybe_adjust_types_for_deduction (strict, &parm, &arg);
+ sub_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg);
/* We don't copy orig_targs for this because if we have already deduced
some template args from previous args, unify would complain when we
tree arg;
tree parm;
{
- if (!(strict & UNIFY_ALLOW_MORE_CV_QUAL)
+ if (!(strict & (UNIFY_ALLOW_MORE_CV_QUAL | UNIFY_ALLOW_OUTER_MORE_CV_QUAL))
&& !at_least_as_qualified_p (arg, parm))
return 0;
- if (!(strict & UNIFY_ALLOW_LESS_CV_QUAL)
+ if (!(strict & (UNIFY_ALLOW_LESS_CV_QUAL | UNIFY_ALLOW_OUTER_LESS_CV_QUAL))
&& !at_least_as_qualified_p (parm, arg))
return 0;
UNIFY_ALLOW_NONE:
Require an exact match between PARM and ARG.
UNIFY_ALLOW_MORE_CV_QUAL:
- Allow the deduced ARG to be more cv-qualified than ARG.
+ Allow the deduced ARG to be more cv-qualified (by qualification
+ conversion) than ARG.
UNIFY_ALLOW_LESS_CV_QUAL:
Allow the deduced ARG to be less cv-qualified than ARG.
UNIFY_ALLOW_DERIVED:
ARG.
UNIFY_ALLOW_INTEGER:
Allow any integral type to be deduced. See the TEMPLATE_PARM_INDEX
- case for more information. */
+ case for more information.
+ UNIFY_ALLOW_OUTER_LEVEL:
+ This is the outermost level of a deduction. Used to determine validity
+ of qualification conversions. A valid qualification conversion must
+ have const qualified pointers leading up to the inner type which
+ requires additional CV quals, except at the outer level, where const
+ is not required [conv.qual]. It would be normal to set this flag in
+ addition to setting UNIFY_ALLOW_MORE_CV_QUAL.
+ UNIFY_ALLOW_OUTER_MORE_CV_QUAL:
+ This is the outermost level of a deduction, and PARM can be more CV
+ qualified at this point.
+ UNIFY_ALLOW_OUTER_LESS_CV_QUAL:
+ This is the outermost level of a deduction, and PARM can be less CV
+ qualified at this point.
+ UNIFY_ALLOW_MAX_CORRECTION:
+ This is an INTEGER_TYPE's maximum value. Used if the range may
+ have been derived from a size specification, such as an array size.
+ If the size was given by a nontype template parameter N, the maximum
+ value will have the form N-1. The flag says that we can (and indeed
+ must) unify N with (ARG + 1), an exception to the normal rules on
+ folding PARM. */
static int
unify (tparms, targs, parm, arg, strict)
int idx;
tree targ;
tree tparm;
+ int strict_in = strict;
/* I don't think this will do the right thing with respect to types.
But the only case I've seen it in so far has been array bounds, where
cv-qualification mismatches. */
if (TREE_CODE (arg) == TREE_CODE (parm)
&& TYPE_P (arg)
+ /* It is the elements of the array which hold the cv quals of an array
+ type, and the elements might be template type parms. We'll check
+ when we recurse. */
+ && TREE_CODE (arg) != ARRAY_TYPE
/* We check the cv-qualifiers when unifying with template type
parameters below. We want to allow ARG `const T' to unify with
PARM `T' for example, when computing which of two templates
is more specialized, for example. */
&& TREE_CODE (arg) != TEMPLATE_TYPE_PARM
- && !check_cv_quals_for_unify (strict, arg, parm))
+ && !check_cv_quals_for_unify (strict_in, arg, parm))
return 1;
+ if (!(strict & UNIFY_ALLOW_OUTER_LEVEL)
+ && TYPE_P (parm) && !CP_TYPE_CONST_P (parm))
+ strict &= ~UNIFY_ALLOW_MORE_CV_QUAL;
+ strict &= ~UNIFY_ALLOW_OUTER_LEVEL;
+ strict &= ~UNIFY_ALLOW_DERIVED;
+ strict &= ~UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
+ strict &= ~UNIFY_ALLOW_OUTER_LESS_CV_QUAL;
+ strict &= ~UNIFY_ALLOW_MAX_CORRECTION;
+
switch (TREE_CODE (parm))
{
case TYPENAME_TYPE:
if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
- /* ARG must be constructed from a template class. */
- if (TREE_CODE (arg) != RECORD_TYPE || !CLASSTYPE_TEMPLATE_INFO (arg))
+ /* ARG must be constructed from a template class or a template
+ template parameter. */
+ if (TREE_CODE (arg) != BOUND_TEMPLATE_TEMPLATE_PARM
+ && (TREE_CODE (arg) != RECORD_TYPE || !CLASSTYPE_TEMPLATE_INFO (arg)))
return 1;
{
tree parmtmpl = TYPE_TI_TEMPLATE (parm);
tree parmvec = TYPE_TI_ARGS (parm);
- tree argvec = CLASSTYPE_TI_ARGS (arg);
+ tree argvec = TYPE_TI_ARGS (arg);
tree argtmplvec
- = DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (arg));
+ = DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (arg));
int i;
/* The parameter and argument roles have to be switched here
return 1;
}
}
- arg = CLASSTYPE_TI_TEMPLATE (arg);
+ arg = TYPE_TI_TEMPLATE (arg);
/* Fall through to deduce template name. */
}
a match unless we are allowing additional qualification.
If ARG is `const int' and PARM is just `T' that's OK;
that binds `const int' to `T'. */
- if (!check_cv_quals_for_unify (strict | UNIFY_ALLOW_LESS_CV_QUAL,
+ if (!check_cv_quals_for_unify (strict_in | UNIFY_ALLOW_LESS_CV_QUAL,
arg, parm))
return 1;
here. */
if (TREE_CODE (arg) == ARRAY_TYPE
&& !uses_template_parms (arg)
+ && TYPE_DOMAIN (arg)
&& (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (arg)))
!= INTEGER_CST))
return 1;
template-parameter exactly, except that a template-argument
deduced from an array bound may be of any integral type.
The non-type parameter might use already deduced type parameters. */
- if (same_type_p (TREE_TYPE (arg),
- tsubst (TREE_TYPE (parm), targs, 0, NULL_TREE)))
- /* OK */;
+ tparm = tsubst (TREE_TYPE (parm), targs, 0, NULL_TREE);
+ if (same_type_p (TREE_TYPE (arg), tparm))
+ /* OK */;
else if ((strict & UNIFY_ALLOW_INTEGER)
- && (TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE
- || TREE_CODE (TREE_TYPE (parm)) == BOOLEAN_TYPE))
+ && (TREE_CODE (tparm) == INTEGER_TYPE
+ || TREE_CODE (tparm) == BOOLEAN_TYPE))
/* OK */;
+ else if (uses_template_parms (tparm))
+ /* We haven't deduced the type of this parameter yet. Try again
+ later. */
+ return 0;
else
return 1;
case POINTER_TYPE:
{
- int sub_strict;
-
if (TREE_CODE (arg) != POINTER_TYPE)
return 1;
We pass down STRICT here rather than UNIFY_ALLOW_NONE.
This will allow for additional cv-qualification of the
- pointed-to types if appropriate. In general, this is a bit
- too generous; we are only supposed to allow qualification
- conversions and this method will allow an ARG of char** and
- a deduced ARG of const char**. However, overload
- resolution will subsequently invalidate the candidate, so
- this is probably OK. */
- sub_strict = strict;
+ pointed-to types if appropriate. */
- if (TREE_CODE (TREE_TYPE (arg)) != RECORD_TYPE)
+ if (TREE_CODE (TREE_TYPE (arg)) == RECORD_TYPE)
/* The derived-to-base conversion only persists through one
level of pointers. */
- sub_strict &= ~UNIFY_ALLOW_DERIVED;
+ strict |= (strict_in & UNIFY_ALLOW_DERIVED);
+
+ if (TREE_CODE (TREE_TYPE (parm)) == OFFSET_TYPE
+ && TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE)
+ {
+ /* Avoid getting confused about cv-quals; don't recurse here.
+ Pointers to members should really be just OFFSET_TYPE, not
+ this two-level nonsense... */
+
+ parm = TREE_TYPE (parm);
+ arg = TREE_TYPE (arg);
+ goto offset;
+ }
return unify (tparms, targs, TREE_TYPE (parm),
- TREE_TYPE (arg), sub_strict);
+ TREE_TYPE (arg), strict);
}
case REFERENCE_TYPE:
if (TREE_CODE (arg) != REFERENCE_TYPE)
return 1;
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
- UNIFY_ALLOW_NONE);
+ strict & UNIFY_ALLOW_MORE_CV_QUAL);
case ARRAY_TYPE:
if (TREE_CODE (arg) != ARRAY_TYPE)
return 1;
if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg)
&& unify (tparms, targs, TYPE_MAX_VALUE (parm),
- TYPE_MAX_VALUE (arg), UNIFY_ALLOW_INTEGER))
+ TYPE_MAX_VALUE (arg),
+ UNIFY_ALLOW_INTEGER | UNIFY_ALLOW_MAX_CORRECTION))
return 1;
}
/* We have already checked cv-qualification at the top of the
{
tree t = NULL_TREE;
- if (strict & UNIFY_ALLOW_DERIVED)
+ if (strict_in & UNIFY_ALLOW_DERIVED)
{
/* First, we try to unify the PARM and ARG directly. */
t = try_class_unification (tparms, targs,
return 1;
return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
TYPE_ARG_TYPES (arg), 1,
- DEDUCE_EXACT, 0);
+ DEDUCE_EXACT, 0, -1);
case OFFSET_TYPE:
+ offset:
if (TREE_CODE (arg) != OFFSET_TYPE)
return 1;
if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
return 1;
case MINUS_EXPR:
- if (TREE_CODE (TREE_OPERAND (parm, 1)) == INTEGER_CST)
+ if (tree_int_cst_equal (TREE_OPERAND (parm, 1), integer_one_node)
+ && (strict_in & UNIFY_ALLOW_MAX_CORRECTION))
{
/* We handle this case specially, since it comes up with
arrays. In particular, something like:
defer_fn (result);
}
-/* Given two function templates PAT1 and PAT2, and explicit template
- arguments EXPLICIT_ARGS return:
+/* Given two function templates PAT1 and PAT2, return:
+ DEDUCE should be DEDUCE_EXACT or DEDUCE_ORDER.
+
1 if PAT1 is more specialized than PAT2 as described in [temp.func.order].
-1 if PAT2 is more specialized than PAT1.
- 0 if neither is more specialized. */
+ 0 if neither is more specialized.
+
+ LEN is passed through to fn_type_unification. */
int
-more_specialized (pat1, pat2, explicit_args)
- tree pat1, pat2, explicit_args;
+more_specialized (pat1, pat2, deduce, len)
+ tree pat1, pat2;
+ int deduce;
+ int len;
{
tree targs;
int winner = 0;
- targs
- = get_bindings_overload (pat1, DECL_TEMPLATE_RESULT (pat2), explicit_args);
+ targs = get_bindings_real (pat1, DECL_TEMPLATE_RESULT (pat2),
+ NULL_TREE, 0, deduce, len);
if (targs)
--winner;
- targs
- = get_bindings_overload (pat2, DECL_TEMPLATE_RESULT (pat1), explicit_args);
+ targs = get_bindings_real (pat2, DECL_TEMPLATE_RESULT (pat1),
+ NULL_TREE, 0, deduce, len);
if (targs)
++winner;
DECL from the function template FN, with the explicit template
arguments EXPLICIT_ARGS. If CHECK_RETTYPE is 1, the return type must
also match. Return NULL_TREE if no satisfactory arguments could be
- found. */
-
+ found. DEDUCE and LEN are passed through to fn_type_unification. */
+
static tree
-get_bindings_real (fn, decl, explicit_args, check_rettype)
+get_bindings_real (fn, decl, explicit_args, check_rettype, deduce, len)
tree fn, decl, explicit_args;
- int check_rettype;
+ int check_rettype, deduce, len;
{
int ntparms = DECL_NTPARMS (fn);
tree targs = make_tree_vec (ntparms);
return NULL_TREE;
}
- /* If FN is a static member function, adjust the type of DECL
- appropriately. */
decl_arg_types = TYPE_ARG_TYPES (decl_type);
- if (DECL_STATIC_FUNCTION_P (fn)
- && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+ /* Never do unification on the 'this' parameter. */
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
decl_arg_types = TREE_CHAIN (decl_arg_types);
i = fn_type_unification (fn, explicit_args, targs,
decl_arg_types,
(check_rettype || DECL_CONV_FN_P (fn)
? TREE_TYPE (decl_type) : NULL_TREE),
- DEDUCE_EXACT);
+ deduce, len);
if (i != 0)
return NULL_TREE;
get_bindings (fn, decl, explicit_args)
tree fn, decl, explicit_args;
{
- return get_bindings_real (fn, decl, explicit_args, 1);
+ return get_bindings_real (fn, decl, explicit_args, 1, DEDUCE_EXACT, -1);
}
-/* But for more_specialized, we only care about the parameter types. */
+/* But for resolve_overloaded_unification, we only care about the parameter
+ types. */
static tree
get_bindings_overload (fn, decl, explicit_args)
tree fn, decl, explicit_args;
{
- return get_bindings_real (fn, decl, explicit_args, 0);
+ return get_bindings_real (fn, decl, explicit_args, 0, DEDUCE_EXACT, -1);
}
/* Return the innermost template arguments that, when applied to a
/* In INSTANTIATIONS is a list of <INSTANTIATION, TEMPLATE> pairs.
Pick the most specialized template, and return the corresponding
instantiation, or if there is no corresponding instantiation, the
- template itself. EXPLICIT_ARGS is any template arguments explicitly
- mentioned in a template-id. If there is no most specialized
- template, error_mark_node is returned. If there are no templates
- at all, NULL_TREE is returned. */
+ template itself. If there is no most specialized template,
+ error_mark_node is returned. If there are no templates at all,
+ NULL_TREE is returned. */
tree
-most_specialized_instantiation (instantiations, explicit_args)
+most_specialized_instantiation (instantiations)
tree instantiations;
- tree explicit_args;
{
tree fn, champ;
int fate;
champ = instantiations;
for (fn = TREE_CHAIN (instantiations); fn; fn = TREE_CHAIN (fn))
{
- fate = more_specialized (TREE_VALUE (champ),
- TREE_VALUE (fn), explicit_args);
+ fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn),
+ DEDUCE_EXACT, -1);
if (fate == 1)
;
else
for (fn = instantiations; fn && fn != champ; fn = TREE_CHAIN (fn))
{
- fate = more_specialized (TREE_VALUE (champ),
- TREE_VALUE (fn), explicit_args);
+ fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn),
+ DEDUCE_EXACT, -1);
if (fate != 1)
return error_mark_node;
}
candidates = tree_cons (NULL_TREE, candidate, candidates);
}
- return most_specialized_instantiation (candidates, explicit_args);
+ return most_specialized_instantiation (candidates);
}
/* If DECL is a specialization of some template, return the most
do_decl_instantiation (declspecs, declarator, storage)
tree declspecs, declarator, storage;
{
- tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, NULL_TREE);
+ tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, NULL);
tree result = NULL_TREE;
int extern_p = 0;
cp_error ("storage class `%D' applied to template instantiation",
storage);
- /* Under the new ABI, we need to make sure to instantiate all the
- cloned versions of constructors or destructors. */
- if (flag_new_abi &&
- (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (result) ||
- DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (result)) &&
- !(TREE_CHAIN (result) &&
- DECL_CLONED_FUNCTION (TREE_CHAIN (result))))
- clone_function_decl(result, /*update_method_vec_p=*/0);
-
SET_DECL_EXPLICIT_INSTANTIATION (result);
mark_decl_instantiated (result, extern_p);
repo_template_instantiated (result, extern_p);
SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t);
SET_CLASSTYPE_INTERFACE_KNOWN (t);
CLASSTYPE_INTERFACE_ONLY (t) = extern_p;
- CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! extern_p;
TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = extern_p;
if (! extern_p)
{
functions, this is not so. See tsubst_friend_function for
details. */
DECL_TI_TEMPLATE (new_decl) = DECL_TI_TEMPLATE (decl);
- DECL_ASSEMBLER_NAME (new_decl) = DECL_ASSEMBLER_NAME (decl);
- DECL_RTL (new_decl) = DECL_RTL (decl);
+ COPY_DECL_ASSEMBLER_NAME (decl, new_decl);
+ COPY_DECL_RTL (decl, new_decl);
DECL_USE_TEMPLATE (new_decl) = DECL_USE_TEMPLATE (decl);
/* Call duplicate decls to merge the old and new declarations. */
tree gen_tmpl;
int pattern_defined;
int line = lineno;
+ int need_push;
const char *file = input_filename;
/* This function should only be used to instantiate templates for
else
pattern_defined = ! DECL_IN_AGGR_P (code_pattern);
- push_to_top_level ();
lineno = DECL_SOURCE_LINE (d);
input_filename = DECL_SOURCE_FILE (d);
if (pattern_defined)
{
- repo_template_used (d);
+ /* Let the repository code that this template definition is
+ available.
+
+ The repository doesn't need to know about cloned functions
+ because they never actually show up in the object file. It
+ does need to know about the clones; those are the symbols
+ that the linker will be emitting error messages about. */
+ if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (d)
+ || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (d))
+ {
+ tree t;
+
+ for (t = TREE_CHAIN (d);
+ t && DECL_CLONED_FUNCTION_P (t);
+ t = TREE_CHAIN (t))
+ repo_template_used (t);
+ }
+ else
+ repo_template_used (d);
if (flag_external_templates && ! DECL_INTERFACE_KNOWN (d))
{
import_export_decl (d);
}
- /* We need to set up DECL_INITIAL regardless of pattern_defined if
- the variable is a static const initialized in the class body. */
- if (TREE_CODE (d) == VAR_DECL
- && TREE_READONLY (d)
- && DECL_INITIAL (d) == NULL_TREE
- && DECL_INITIAL (code_pattern) != NULL_TREE)
- ;
+ if (TREE_CODE (d) == VAR_DECL && DECL_INITIALIZED_IN_CLASS_P (d)
+ && DECL_INITIAL (d) == NULL_TREE)
+ /* We should have set up DECL_INITIAL in instantiate_class_template. */
+ abort ();
/* Reject all external templates except inline functions. */
else if (DECL_INTERFACE_KNOWN (d)
&& ! DECL_NOT_REALLY_EXTERN (d)
- && ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d)))
+ && ! (TREE_CODE (d) == FUNCTION_DECL
+ && DECL_INLINE (d)))
goto out;
/* Defer all other templates, unless we have been explicitly
forbidden from doing so. We restore the source position here
member function or static data member of a class template
shall be present in every translation unit in which it is
explicitly instantiated. */
- cp_error ("explicit instantiation of `%D' but no definition available",
- d);
+ cp_pedwarn
+ ("explicit instantiation of `%D' but no definition available", d);
add_pending_template (d);
goto out;
}
+ need_push = !global_bindings_p ();
+ if (need_push)
+ push_to_top_level ();
+
/* We're now committed to instantiating this template. Mark it as
instantiated so that recursive calls to instantiate_decl do not
try to instantiate it again. */
/* Set up context. */
start_function (NULL_TREE, d, NULL_TREE, SF_PRE_PARSED);
- /* We already set up __FUNCTION__, etc., so we don't want to do
- it again now. */
- function_name_declared_p = 1;
-
/* Substitute into the body of the function. */
tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
/*complain=*/1, tmpl);
/* We're not deferring instantiation any more. */
TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (d)) = 0;
+ if (need_push)
+ pop_from_top_level ();
+
out:
lineno = line;
input_filename = file;
- pop_from_top_level ();
pop_tinst_level ();
timevar_pop (TV_PARSE);
instantiate_pending_templates ()
{
tree *t;
+ tree last = NULL_TREE;
int instantiated_something = 0;
int reconsider;
/* If INSTANTIATION has been instantiated, then we don't
need to consider it again in the future. */
*t = TREE_CHAIN (*t);
- else
- t = &TREE_CHAIN (*t);
+ else
+ {
+ last = *t;
+ t = &TREE_CHAIN (*t);
+ }
}
else
{
/* If INSTANTIATION has been instantiated, then we don't
need to consider it again in the future. */
*t = TREE_CHAIN (*t);
- else
- t = &TREE_CHAIN (*t);
+ else
+ {
+ last = *t;
+ t = &TREE_CHAIN (*t);
+ }
}
tinst_depth = 0;
current_tinst_level = NULL_TREE;
}
- template_tail = t;
-
- /* Go through the things that are template instantiations if we are
- using guiding declarations. */
- t = &maybe_templates;
- while (*t)
- {
- tree template;
- tree fn;
- tree args;
-
- fn = TREE_VALUE (*t);
-
- if (DECL_INITIAL (fn))
- /* If the FN is already defined, then it was either already
- instantiated or, even though guiding declarations were
- allowed, a non-template definition was provided. */
- ;
- else
- {
- template = TREE_PURPOSE (*t);
- args = get_bindings (template, fn, NULL_TREE);
- fn = instantiate_template (template, args);
- instantiate_decl (fn, /*defer_ok=*/0);
- reconsider = 1;
- }
-
- /* Remove this entry from the chain. */
- *t = TREE_CHAIN (*t);
- }
- maybe_template_tail = t;
+ last_pending_template = last;
}
while (reconsider);
return fn_type;
}
-/* Set the DECL_ASSEMBLER_NAME for DECL, which is a FUNCTION_DECL that
- is either an instantiation or specialization of a template
- function. */
-
-static void
-set_mangled_name_for_template_decl (decl)
- tree decl;
-{
- tree context = NULL_TREE;
- tree fn_type;
- tree ret_type;
- tree parm_types;
- tree tparms;
- tree targs;
-
- my_friendly_assert (TREE_CODE (decl) == FUNCTION_DECL, 0);
- my_friendly_assert (DECL_TEMPLATE_INFO (decl) != NULL_TREE, 0);
-
- /* Under the new ABI, we don't need special machinery. */
- if (flag_new_abi)
- {
- set_mangled_name_for_decl (decl);
- return;
- }
-
- /* The names of template functions must be mangled so as to indicate
- what template is being specialized with what template arguments.
- For example, each of the following three functions must get
- different mangled names:
-
- void f(int);
- template <> void f<7>(int);
- template <> void f<8>(int); */
-
- targs = DECL_TI_ARGS (decl);
- if (uses_template_parms (targs))
- /* This DECL is for a partial instantiation. There's no need to
- mangle the name of such an entity. */
- return;
-
- /* We now compute the PARMS and RET_TYPE to give to
- build_decl_overload_real. The PARMS and RET_TYPE are the
- parameter and return types of the template, after all but the
- innermost template arguments have been substituted, not the
- parameter and return types of the function DECL. For example,
- given:
-
- template <class T> T f(T);
-
- both PARMS and RET_TYPE should be `T' even if DECL is `int f(int)'.
- A more subtle example is:
-
- template <class T> struct S { template <class U> void f(T, U); }
-
- Here, if DECL is `void S<int>::f(int, double)', PARMS should be
- {int, U}. Thus, the args that we want to subsitute into the
- return and parameter type for the function are those in TARGS,
- with the innermost level omitted. */
- fn_type = get_mostly_instantiated_function_type (decl, &context, &tparms);
-
- /* Now, get the innermost parameters and arguments, and figure out
- the parameter and return types. */
- tparms = INNERMOST_TEMPLATE_PARMS (tparms);
- targs = INNERMOST_TEMPLATE_ARGS (targs);
- ret_type = TREE_TYPE (fn_type);
- parm_types = TYPE_ARG_TYPES (fn_type);
-
- /* For a static member function, we generate a fake `this' pointer,
- for the purposes of mangling. This indicates of which class the
- function is a member. Because of:
-
- [class.static]
-
- There shall not be a static and a nonstatic member function
- with the same name and the same parameter types
-
- we don't have to worry that this will result in a clash with a
- non-static member function. */
- if (DECL_STATIC_FUNCTION_P (decl))
- parm_types = hash_tree_chain (build_pointer_type (context), parm_types);
-
- /* There should be the same number of template parameters as
- template arguments. */
- my_friendly_assert (TREE_VEC_LENGTH (tparms) == TREE_VEC_LENGTH (targs),
- 0);
-
- /* Actually set the DECL_ASSEMBLER_NAME. */
- DECL_ASSEMBLER_NAME (decl)
- = build_decl_overload_real (decl, parm_types, ret_type,
- tparms, targs,
- DECL_FUNCTION_MEMBER_P (decl)
- + DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl));
-}
-
/* Return truthvalue if we're processing a template different from
the last one involved in diagnostics. */
int
{
return current_tinst_level;
}
+
+/* [temp.param] Check that template non-type parm TYPE is of an allowable
+ type. Return zero for ok, non-zero for disallowed. If COMPLAIN is
+ non-zero, then complain. */
+
+static int
+invalid_nontype_parm_type_p (type, complain)
+ tree type;
+ int complain;
+{
+ if (INTEGRAL_TYPE_P (type))
+ return 0;
+ else if (POINTER_TYPE_P (type))
+ return 0;
+ else if (TYPE_PTRMEM_P (type))
+ return 0;
+ else if (TYPE_PTRMEMFUNC_P (type))
+ return 0;
+ else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+ return 0;
+ else if (TREE_CODE (type) == TYPENAME_TYPE)
+ return 0;
+
+ if (complain)
+ cp_error ("`%#T' is not a valid type for a template constant parameter",
+ type);
+ return 1;
+}