/* Handle parameterized types (templates) for GNU C++.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+ Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
Rewritten by Jason Merrill (jason@cygnus.com).
/* The PENDING_TEMPLATES is a TREE_LIST of templates whose
instantiations have been deferred, either because their definitions
were not yet available, or because we were putting off doing the work. */
-struct pending_template GTY (()) {
+struct GTY (()) pending_template {
struct pending_template *next;
struct tinst_level *tinst;
};
local variables. */
static htab_t local_specializations;
+typedef struct GTY(()) spec_entry
+{
+ tree tmpl;
+ tree args;
+ tree spec;
+} spec_entry;
+
+static GTY ((param_is (spec_entry)))
+ htab_t decl_specializations;
+
+static GTY ((param_is (spec_entry)))
+ htab_t type_specializations;
+
/* Contains canonical template parameter types. The vector is indexed by
the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
TREE_LIST, whose TREE_VALUEs contain the canonical template
static bool check_instantiated_args (tree, tree, tsubst_flags_t);
static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*,
tree);
-static int type_unification_real (tree, tree, tree, tree,
- int, unification_kind_t, int);
+static int type_unification_real (tree, tree, tree, const tree *,
+ unsigned int, int, unification_kind_t, int);
static void note_template_header (int);
static tree convert_nontype_argument_function (tree, tree);
static tree convert_nontype_argument (tree, tree);
static void push_inline_template_parms_recursive (tree, int);
static tree retrieve_local_specialization (tree);
static void register_local_specialization (tree, tree);
+static hashval_t hash_specialization (const void *p);
static tree reduce_template_parm_level (tree, tree, int, tree, tsubst_flags_t);
static int mark_template_parm (tree, void *);
static int template_parm_this_level_p (tree, void *);
static bool dependent_template_arg_p (tree);
static bool any_template_arguments_need_structural_equality_p (tree);
static bool dependent_type_p_r (tree);
-static tree tsubst (tree, tree, tsubst_flags_t, tree);
static tree tsubst_expr (tree, tree, tsubst_flags_t, tree, bool);
static tree tsubst_copy (tree, tree, tsubst_flags_t, tree);
static tree tsubst_pack_expansion (tree, tree, tsubst_flags_t, tree);
+static tree tsubst_decl (tree, tree, tsubst_flags_t);
+static void perform_typedefs_access_check (tree tmpl, tree targs);
+static void append_type_to_template_for_access_check_1 (tree, tree, tree);
+static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
It is ugly that we recreate this here; the original
version built in process_template_parm is no longer
available. */
- tree decl = build_decl (CONST_DECL, DECL_NAME (parm),
+ tree decl = build_decl (DECL_SOURCE_LOCATION (parm),
+ CONST_DECL, DECL_NAME (parm),
TREE_TYPE (parm));
DECL_ARTIFICIAL (decl) = 1;
TREE_CONSTANT (decl) = 1;
return true;
else
{
- pedwarn ("specialization of %qD in different namespace", tmpl);
- pedwarn (" from definition of %q+#D", tmpl);
+ permerror (input_location, "specialization of %qD in different namespace", tmpl);
+ permerror (input_location, " from definition of %q+#D", tmpl);
return false;
}
}
namespace of its template. */
ns = decl_namespace_context (spec);
if (!is_ancestor (current_namespace, ns))
- pedwarn ("explicit instantiation of %qD in namespace %qD "
- "(which does not enclose namespace %qD)",
- spec, current_namespace, ns);
+ permerror (input_location, "explicit instantiation of %qD in namespace %qD "
+ "(which does not enclose namespace %qD)",
+ spec, current_namespace, ns);
}
/* The TYPE is being declared. If it is a template type, that means it
check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type));
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
if (processing_template_decl)
- push_template_decl (TYPE_MAIN_DECL (type));
+ {
+ if (push_template_decl (TYPE_MAIN_DECL (type))
+ == error_mark_node)
+ return error_mark_node;
+ }
}
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
error ("specialization of %qT after instantiation", type);
&& !COMPLETE_TYPE_P (type))
{
tree t;
+ tree tmpl = CLASSTYPE_TI_TEMPLATE (type);
if (current_namespace
- != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
+ != decl_namespace_context (tmpl))
{
- pedwarn ("specializing %q#T in different namespace", type);
- pedwarn (" from definition of %q+#D",
- CLASSTYPE_TI_TEMPLATE (type));
+ permerror (input_location, "specializing %q#T in different namespace", type);
+ permerror (input_location, " from definition of %q+#D", tmpl);
}
/* Check for invalid specialization after instantiation:
template <> template <> class C<int>::D<int>;
template <> template <class U> class C<int>::D; */
- for (t = DECL_TEMPLATE_INSTANTIATIONS
- (most_general_template (CLASSTYPE_TI_TEMPLATE (type)));
+ for (t = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
t; t = TREE_CHAIN (t))
- if (TREE_VALUE (t) != type
- && TYPE_CONTEXT (TREE_VALUE (t)) == context)
- error ("specialization %qT after instantiation %qT",
- type, TREE_VALUE (t));
+ {
+ tree inst = TREE_VALUE (t);
+ if (CLASSTYPE_TEMPLATE_SPECIALIZATION (inst))
+ {
+ /* We already have a full specialization of this partial
+ instantiation. Reassign it to the new member
+ specialization template. */
+ spec_entry elt;
+ spec_entry **slot;
+
+ elt.tmpl = most_general_template (tmpl);
+ elt.args = CLASSTYPE_TI_ARGS (inst);
+ elt.spec = inst;
+
+ htab_remove_elt (type_specializations, &elt);
+
+ elt.tmpl = tmpl;
+ elt.args = INNERMOST_TEMPLATE_ARGS (elt.args);
+
+ slot = (spec_entry **)
+ htab_find_slot (type_specializations, &elt, INSERT);
+ *slot = GGC_NEW (spec_entry);
+ **slot = elt;
+ }
+ else if (COMPLETE_TYPE_P (inst) || TYPE_BEING_DEFINED (inst))
+ /* But if we've had an implicit instantiation, that's a
+ problem ([temp.expl.spec]/6). */
+ error ("specialization %qT after instantiation %qT",
+ type, inst);
+ }
/* Mark TYPE as a specialization. And as a result, we only
have one level of template argument for the innermost
parameter is ignored if TMPL is not a class template. */
static tree
-retrieve_specialization (tree tmpl, tree args,
- bool class_specializations_p)
+retrieve_specialization (tree tmpl, tree args, hashval_t hash)
{
if (args == error_mark_node)
return NULL_TREE;
arguments. */
class_template = CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (tmpl));
class_specialization
- = retrieve_specialization (class_template, args,
- /*class_specializations_p=*/false);
+ = retrieve_specialization (class_template, args, 0);
if (!class_specialization)
return NULL_TREE;
/* Now, find the appropriate entry in the CLASSTYPE_METHOD_VEC
for (fns = VEC_index (tree, methods, idx); fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
- if (DECL_TEMPLATE_INFO (fn) && DECL_TI_TEMPLATE (fn) == tmpl)
+ if (DECL_TEMPLATE_INFO (fn) && DECL_TI_TEMPLATE (fn) == tmpl
+ /* using-declarations can add base methods to the method vec,
+ and we don't want those here. */
+ && DECL_CONTEXT (fn) == class_specialization)
return fn;
}
return NULL_TREE;
}
else
{
- tree *sp;
- tree *head;
+ spec_entry *found;
+ spec_entry elt;
+ htab_t specializations;
+
+ elt.tmpl = tmpl;
+ elt.args = args;
+ elt.spec = NULL_TREE;
- /* Class templates store their instantiations on the
- DECL_TEMPLATE_INSTANTIATIONS list; other templates use the
- DECL_TEMPLATE_SPECIALIZATIONS list. */
- if (!class_specializations_p
- && TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL
- && TAGGED_TYPE_P (TREE_TYPE (tmpl)))
- sp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
+ if (DECL_CLASS_TEMPLATE_P (tmpl))
+ specializations = type_specializations;
else
- sp = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
- head = sp;
- /* Iterate through the list until we find a matching template. */
- while (*sp != NULL_TREE)
- {
- tree spec = *sp;
+ specializations = decl_specializations;
- if (comp_template_args (TREE_PURPOSE (spec), args))
- {
- /* Use the move-to-front heuristic to speed up future
- searches. */
- if (spec != *head)
- {
- *sp = TREE_CHAIN (*sp);
- TREE_CHAIN (spec) = *head;
- *head = spec;
- }
- return TREE_VALUE (spec);
- }
- sp = &TREE_CHAIN (spec);
- }
+ if (hash == 0)
+ hash = hash_specialization (&elt);
+ found = (spec_entry *) htab_find_with_hash (specializations, &elt, hash);
+ if (found)
+ return found->spec;
}
return NULL_TREE;
}
/* Returns nonzero iff DECL is a specialization of friend declaration
- FRIEND according to [temp.friend]. */
+ FRIEND_DECL according to [temp.friend]. */
bool
-is_specialization_of_friend (tree decl, tree friend)
+is_specialization_of_friend (tree decl, tree friend_decl)
{
bool need_template = true;
int template_depth;
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == TYPE_DECL);
- /* For [temp.friend/6] when FRIEND is an ordinary member function
+ /* For [temp.friend/6] when FRIEND_DECL is an ordinary member function
of a template class, we want to check if DECL is a specialization
if this. */
- if (TREE_CODE (friend) == FUNCTION_DECL
- && DECL_TEMPLATE_INFO (friend)
- && !DECL_USE_TEMPLATE (friend))
+ if (TREE_CODE (friend_decl) == FUNCTION_DECL
+ && DECL_TEMPLATE_INFO (friend_decl)
+ && !DECL_USE_TEMPLATE (friend_decl))
{
/* We want a TEMPLATE_DECL for `is_specialization_of'. */
- friend = DECL_TI_TEMPLATE (friend);
+ friend_decl = DECL_TI_TEMPLATE (friend_decl);
need_template = false;
}
- else if (TREE_CODE (friend) == TEMPLATE_DECL
- && !PRIMARY_TEMPLATE_P (friend))
+ else if (TREE_CODE (friend_decl) == TEMPLATE_DECL
+ && !PRIMARY_TEMPLATE_P (friend_decl))
need_template = false;
/* There is nothing to do if this is not a template friend. */
- if (TREE_CODE (friend) != TEMPLATE_DECL)
+ if (TREE_CODE (friend_decl) != TEMPLATE_DECL)
return false;
- if (is_specialization_of (decl, friend))
+ if (is_specialization_of (decl, friend_decl))
return true;
/* [temp.friend/6]
nonzero. To determine if DECL is a friend of FRIEND, we first
check if the enclosing class is a specialization of another. */
- template_depth = template_class_depth (DECL_CONTEXT (friend));
+ template_depth = template_class_depth (DECL_CONTEXT (friend_decl));
if (template_depth
&& DECL_CLASS_SCOPE_P (decl)
&& is_specialization_of (TYPE_NAME (DECL_CONTEXT (decl)),
- CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (friend))))
+ CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (friend_decl))))
{
/* Next, we check the members themselves. In order to handle
- a few tricky cases, such as when FRIEND's are
+ a few tricky cases, such as when FRIEND_DECL's are
template <class T> friend void A<T>::g(T t);
template <class T> template <T t> friend void A<T>::h();
tree friend_args_type;
tree decl_args_type;
- /* Make sure that both DECL and FRIEND are templates or
+ /* Make sure that both DECL and FRIEND_DECL are templates or
non-templates. */
is_template = DECL_TEMPLATE_INFO (decl)
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl));
{
/* If both are templates, check template parameter list. */
tree friend_parms
- = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend),
+ = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_decl),
args, tf_none);
if (!comp_template_parms
(DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl)),
else
decl_type = TREE_TYPE (decl);
- friend_type = tsubst_function_type (TREE_TYPE (friend), args,
+ friend_type = tsubst_function_type (TREE_TYPE (friend_decl), args,
tf_none, NULL_TREE);
if (friend_type == error_mark_node)
return false;
`this' parameter. */
friend_args_type = TYPE_ARG_TYPES (friend_type);
decl_args_type = TYPE_ARG_TYPES (decl_type);
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (friend))
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (friend_decl))
friend_args_type = TREE_CHAIN (friend_args_type);
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
decl_args_type = TREE_CHAIN (decl_args_type);
bool is_template;
tree decl_type = TREE_TYPE (decl);
- /* Make sure that both DECL and FRIEND are templates or
+ /* Make sure that both DECL and FRIEND_DECL are templates or
non-templates. */
is_template
= CLASSTYPE_TEMPLATE_INFO (decl_type)
/* If both are templates, check the name of the two
TEMPLATE_DECL's first because is_friend didn't. */
if (DECL_NAME (CLASSTYPE_TI_TEMPLATE (decl_type))
- != DECL_NAME (friend))
+ != DECL_NAME (friend_decl))
return false;
/* Now check template parameter list. */
friend_parms
- = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend),
+ = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_decl),
args, tf_none);
return comp_template_parms
(DECL_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (decl_type)),
}
else
return (DECL_NAME (decl)
- == DECL_NAME (friend));
+ == DECL_NAME (friend_decl));
}
}
return false;
equivalent prior declaration, if available. */
static tree
-register_specialization (tree spec, tree tmpl, tree args, bool is_friend)
+register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
+ hashval_t hash)
{
tree fn;
+ spec_entry **slot = NULL;
+ spec_entry elt;
- gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
+ gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL && DECL_P (spec));
if (TREE_CODE (spec) == FUNCTION_DECL
&& uses_template_parms (DECL_TI_ARGS (spec)))
instantiation unless and until it is actually needed. */
return spec;
- fn = retrieve_specialization (tmpl, args,
- /*class_specializations_p=*/false);
+ if (optimize_specialization_lookup_p (tmpl))
+ /* We don't put these specializations in the hash table, but we might
+ want to give an error about a mismatch. */
+ fn = retrieve_specialization (tmpl, args, 0);
+ else
+ {
+ elt.tmpl = tmpl;
+ elt.args = args;
+ elt.spec = spec;
+
+ if (hash == 0)
+ hash = hash_specialization (&elt);
+
+ slot = (spec_entry **)
+ htab_find_slot_with_hash (decl_specializations, &elt, hash, INSERT);
+ if (*slot)
+ fn = (*slot)->spec;
+ else
+ fn = NULL_TREE;
+ }
+
/* We can sometimes try to re-register a specialization that we've
already got. In particular, regenerate_decl_from_template calls
duplicate_decls which will update the specialization list. But,
to the primary function; now copy the inline bits to
the various clones. */
FOR_EACH_CLONE (clone, fn)
- {
- DECL_DECLARED_INLINE_P (clone)
- = DECL_DECLARED_INLINE_P (fn);
- DECL_INLINE (clone)
- = DECL_INLINE (fn);
- }
+ DECL_DECLARED_INLINE_P (clone)
+ = DECL_DECLARED_INLINE_P (fn);
check_specialization_namespace (fn);
return fn;
return fn;
}
}
+ else if (fn)
+ return duplicate_decls (spec, fn, is_friend);
/* A specialization must be declared in the same namespace as the
template it is specializing. */
if (DECL_TEMPLATE_SPECIALIZATION (spec)
&& !check_specialization_namespace (tmpl))
- DECL_CONTEXT (spec) = FROB_CONTEXT (decl_namespace_context (tmpl));
+ DECL_CONTEXT (spec) = DECL_CONTEXT (tmpl);
if (!optimize_specialization_lookup_p (tmpl))
- DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
- = tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
+ {
+ gcc_assert (tmpl && args && spec);
+ *slot = GGC_NEW (spec_entry);
+ **slot = elt;
+ if (TREE_CODE (spec) == FUNCTION_DECL && DECL_NAMESPACE_SCOPE_P (spec)
+ && PRIMARY_TEMPLATE_P (tmpl)
+ && DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (tmpl)) == NULL_TREE)
+ /* TMPL is a forward declaration of a template function; keep a list
+ of all specializations in case we need to reassign them to a friend
+ template later in tsubst_friend_function. */
+ DECL_TEMPLATE_INSTANTIATIONS (tmpl)
+ = tree_cons (args, spec, DECL_TEMPLATE_INSTANTIATIONS (tmpl));
+ }
return spec;
}
+/* Returns true iff two spec_entry nodes are equivalent. Only compares the
+ TMPL and ARGS members, ignores SPEC. */
+
+static int
+eq_specializations (const void *p1, const void *p2)
+{
+ const spec_entry *e1 = (const spec_entry *)p1;
+ const spec_entry *e2 = (const spec_entry *)p2;
+
+ return (e1->tmpl == e2->tmpl
+ && comp_template_args (e1->args, e2->args));
+}
+
+/* Returns a hash for a template TMPL and template arguments ARGS. */
+
+static hashval_t
+hash_tmpl_and_args (tree tmpl, tree args)
+{
+ hashval_t val = DECL_UID (tmpl);
+ return iterative_hash_template_arg (args, val);
+}
+
+/* Returns a hash for a spec_entry node based on the TMPL and ARGS members,
+ ignoring SPEC. */
+
+static hashval_t
+hash_specialization (const void *p)
+{
+ const spec_entry *e = (const spec_entry *)p;
+ return hash_tmpl_and_args (e->tmpl, e->args);
+}
+
+/* Recursively calculate a hash value for a template argument ARG, for use
+ in the hash tables of template specializations. */
+
+static hashval_t
+iterative_hash_template_arg (tree arg, hashval_t val)
+{
+ unsigned HOST_WIDE_INT i;
+ enum tree_code code;
+ char tclass;
+
+ if (arg == NULL_TREE)
+ return iterative_hash_object (arg, val);
+
+ if (!TYPE_P (arg))
+ STRIP_NOPS (arg);
+
+ code = TREE_CODE (arg);
+ tclass = TREE_CODE_CLASS (code);
+
+ val = iterative_hash_object (code, val);
+
+ switch (code)
+ {
+ case ERROR_MARK:
+ return val;
+
+ case IDENTIFIER_NODE:
+ return iterative_hash_object (IDENTIFIER_HASH_VALUE (arg), val);
+
+ case TREE_VEC:
+ {
+ int i, len = TREE_VEC_LENGTH (arg);
+ for (i = 0; i < len; ++i)
+ val = iterative_hash_template_arg (TREE_VEC_ELT (arg, i), val);
+ return val;
+ }
+
+ case TYPE_PACK_EXPANSION:
+ case EXPR_PACK_EXPANSION:
+ return iterative_hash_template_arg (PACK_EXPANSION_PATTERN (arg), val);
+
+ case ARGUMENT_PACK_SELECT:
+ /* We can get one of these when re-hashing a previous entry in the middle
+ of substituting into a pack expansion. Just look through it... */
+ arg = ARGUMENT_PACK_SELECT_FROM_PACK (arg);
+ /* ...and fall through. */
+ case TYPE_ARGUMENT_PACK:
+ case NONTYPE_ARGUMENT_PACK:
+ return iterative_hash_template_arg (ARGUMENT_PACK_ARGS (arg), val);
+
+ case TREE_LIST:
+ for (; arg; arg = TREE_CHAIN (arg))
+ val = iterative_hash_template_arg (TREE_VALUE (arg), val);
+ return val;
+
+ case OVERLOAD:
+ for (; arg; arg = OVL_CHAIN (arg))
+ val = iterative_hash_template_arg (OVL_FUNCTION (arg), val);
+ return val;
+
+ case CONSTRUCTOR:
+ {
+ tree field, value;
+ FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (arg), i, field, value)
+ {
+ val = iterative_hash_template_arg (field, val);
+ val = iterative_hash_template_arg (value, val);
+ }
+ return val;
+ }
+
+ case PARM_DECL:
+ val = iterative_hash_object (DECL_PARM_INDEX (arg), val);
+ return iterative_hash_template_arg (TREE_TYPE (arg), val);
+
+ case TARGET_EXPR:
+ return iterative_hash_template_arg (TARGET_EXPR_INITIAL (arg), val);
+
+ case PTRMEM_CST:
+ val = iterative_hash_template_arg (PTRMEM_CST_CLASS (arg), val);
+ return iterative_hash_template_arg (PTRMEM_CST_MEMBER (arg), val);
+
+ case TEMPLATE_PARM_INDEX:
+ val = iterative_hash_template_arg
+ (TREE_TYPE (TEMPLATE_PARM_DECL (arg)), val);
+ val = iterative_hash_object (TEMPLATE_PARM_LEVEL (arg), val);
+ return iterative_hash_object (TEMPLATE_PARM_IDX (arg), val);
+
+ case TRAIT_EXPR:
+ val = iterative_hash_object (TRAIT_EXPR_KIND (arg), val);
+ val = iterative_hash_template_arg (TRAIT_EXPR_TYPE1 (arg), val);
+ return iterative_hash_template_arg (TRAIT_EXPR_TYPE2 (arg), val);
+
+ case BASELINK:
+ val = iterative_hash_template_arg (BINFO_TYPE (BASELINK_BINFO (arg)),
+ val);
+ return iterative_hash_template_arg (DECL_NAME (get_first_fn (arg)),
+ val);
+
+ case MODOP_EXPR:
+ val = iterative_hash_template_arg (TREE_OPERAND (arg, 0), val);
+ code = TREE_CODE (TREE_OPERAND (arg, 1));
+ val = iterative_hash_object (code, val);
+ return iterative_hash_template_arg (TREE_OPERAND (arg, 2), val);
+
+ default:
+ switch (tclass)
+ {
+ case tcc_type:
+ if (TYPE_CANONICAL (arg))
+ return iterative_hash_object (TYPE_HASH (TYPE_CANONICAL (arg)),
+ val);
+ else if (TREE_CODE (arg) == DECLTYPE_TYPE)
+ return iterative_hash_template_arg (DECLTYPE_TYPE_EXPR (arg), val);
+ /* Otherwise just compare the types during lookup. */
+ return val;
+
+ case tcc_declaration:
+ case tcc_constant:
+ return iterative_hash_expr (arg, val);
+
+ default:
+ gcc_assert (IS_EXPR_CODE_CLASS (tclass));
+ {
+ unsigned n = TREE_OPERAND_LENGTH (arg);
+ for (i = 0; i < n; ++i)
+ val = iterative_hash_template_arg (TREE_OPERAND (arg, i), val);
+ return val;
+ }
+ }
+ }
+ gcc_unreachable ();
+ return 0;
+}
+
/* Unregister the specialization SPEC as a specialization of TMPL.
Replace it with NEW_SPEC, if NEW_SPEC is non-NULL. Returns true
- if the SPEC was listed as a specialization of TMPL. */
+ if the SPEC was listed as a specialization of TMPL.
+
+ Note that SPEC has been ggc_freed, so we can't look inside it. */
bool
-reregister_specialization (tree spec, tree tmpl, tree new_spec)
+reregister_specialization (tree spec, tree tinfo, tree new_spec)
{
- tree* s;
+ spec_entry **slot;
+ spec_entry elt;
- for (s = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
- *s != NULL_TREE;
- s = &TREE_CHAIN (*s))
- if (TREE_VALUE (*s) == spec)
- {
- if (!new_spec)
- *s = TREE_CHAIN (*s);
- else
- TREE_VALUE (*s) = new_spec;
- return 1;
- }
+ elt.tmpl = most_general_template (TI_TEMPLATE (tinfo));
+ elt.args = TI_ARGS (tinfo);
+ elt.spec = NULL_TREE;
+
+ slot = (spec_entry **) htab_find_slot (decl_specializations, &elt, INSERT);
+ if (*slot)
+ {
+ gcc_assert ((*slot)->spec == spec || (*slot)->spec == new_spec);
+ gcc_assert (new_spec != NULL_TREE);
+ (*slot)->spec = new_spec;
+ return 1;
+ }
return 0;
}
if (candidates)
{
tree fn = TREE_VALUE (candidates);
- /* DECL is a re-declaration of a template function. */
+ *targs_out = copy_node (DECL_TI_ARGS (fn));
+ /* DECL is a re-declaration or partial instantiation of a template
+ function. */
if (TREE_CODE (fn) == TEMPLATE_DECL)
return fn;
/* It was a specialization of an ordinary member function in a
template class. */
- *targs_out = copy_node (DECL_TI_ARGS (fn));
return DECL_TI_TEMPLATE (fn);
}
for (; t; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t))
{
- pedwarn
- ("default argument specified in explicit specialization");
+ permerror (input_location,
+ "default argument specified in explicit specialization");
break;
}
}
the specialization of it. */
if (tsk == tsk_template)
{
+ tree result = DECL_TEMPLATE_RESULT (tmpl);
SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
- DECL_INITIAL (DECL_TEMPLATE_RESULT (tmpl)) = NULL_TREE;
+ DECL_INITIAL (result) = NULL_TREE;
if (have_def)
{
+ tree parm;
DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
- DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (tmpl))
+ DECL_SOURCE_LOCATION (result)
= DECL_SOURCE_LOCATION (decl);
/* We want to use the argument list specified in the
definition, not in the original declaration. */
- DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (tmpl))
- = DECL_ARGUMENTS (decl);
+ DECL_ARGUMENTS (result) = DECL_ARGUMENTS (decl);
+ for (parm = DECL_ARGUMENTS (result); parm;
+ parm = TREE_CHAIN (parm))
+ DECL_CONTEXT (parm) = result;
}
- return tmpl;
+ return register_specialization (tmpl, gen_tmpl, targs,
+ is_friend, 0);
}
/* Set up the DECL_TEMPLATE_INFO for DECL. */
/* Register this specialization so that we can find it
again. */
- decl = register_specialization (decl, gen_tmpl, targs, is_friend);
+ decl = register_specialization (decl, gen_tmpl, targs, is_friend, 0);
}
}
name = DECL_NAME (pack);
if (name)
- inform (" %qD", name);
+ inform (input_location, " %qD", name);
else
- inform (" <anonymous>");
+ inform (input_location, " <anonymous>");
parameter_packs = TREE_CHAIN (parameter_packs);
}
return result_args;
}
-/* Complain if DECL shadows a template parameter.
+/* Checks if DECL shadows a template parameter.
[temp.local]: A template-parameter shall not be redeclared within its
- scope (including nested scopes). */
+ scope (including nested scopes).
-void
+ Emits an error and returns TRUE if the DECL shadows a parameter,
+ returns FALSE otherwise. */
+
+bool
check_template_shadow (tree decl)
{
tree olddecl;
/* If we're not in a template, we can't possibly shadow a template
parameter. */
if (!current_template_parms)
- return;
+ return true;
/* Figure out what we're shadowing. */
if (TREE_CODE (decl) == OVERLOAD)
/* If there's no previous binding for this name, we're not shadowing
anything, let alone a template parameter. */
if (!olddecl)
- return;
+ return true;
/* If we're not shadowing a template parameter, we're done. Note
that OLDDECL might be an OVERLOAD (or perhaps even an
ERROR_MARK), so we can't just blithely assume it to be a _DECL
node. */
if (!DECL_P (olddecl) || !DECL_TEMPLATE_PARM_P (olddecl))
- return;
+ return true;
/* We check for decl != olddecl to avoid bogus errors for using a
name inside a class. We check TPFI to avoid duplicate errors for
inline member templates. */
if (decl == olddecl
|| TEMPLATE_PARMS_FOR_INLINE (current_template_parms))
- return;
+ return true;
error ("declaration of %q+#D", decl);
error (" shadows template parm %q+#D", olddecl);
+ return false;
}
/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
tree orig_decl = TEMPLATE_PARM_DECL (index);
tree decl, t;
- decl = build_decl (TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);
+ decl = build_decl (DECL_SOURCE_LOCATION (orig_decl),
+ TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);
TREE_CONSTANT (decl) = TREE_CONSTANT (orig_decl);
TREE_READONLY (decl) = TREE_READONLY (orig_decl);
DECL_ARTIFICIAL (decl) = 1;
/* Process information from new template parameter PARM and append it to the
LIST being built. This new parameter is a non-type parameter iff
IS_NON_TYPE is true. This new parameter is a parameter
- pack iff IS_PARAMETER_PACK is true. */
+ pack iff IS_PARAMETER_PACK is true. The location of PARM is in
+ PARM_LOC. */
tree
-process_template_parm (tree list, tree parm, bool is_non_type,
+process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type,
bool is_parameter_pack)
{
tree decl = 0;
/* A template parameter is not modifiable. */
TREE_CONSTANT (parm) = 1;
TREE_READONLY (parm) = 1;
- decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
+ decl = build_decl (parm_loc,
+ CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
TREE_CONSTANT (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_INITIAL (parm) = DECL_INITIAL (decl)
{
t = cxx_make_type (TEMPLATE_TYPE_PARM);
/* parm is either IDENTIFIER_NODE or NULL_TREE. */
- decl = build_decl (TYPE_DECL, parm, t);
+ decl = build_decl (parm_loc,
+ TYPE_DECL, parm, t);
}
TYPE_NAME (t) = decl;
DECL_TEMPLATE_PARMS (tmpl) = parms;
DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p;
- if (DECL_LANG_SPECIFIC (decl))
- {
- DECL_STATIC_FUNCTION_P (tmpl) = DECL_STATIC_FUNCTION_P (decl);
- DECL_CONSTRUCTOR_P (tmpl) = DECL_CONSTRUCTOR_P (decl);
- DECL_DESTRUCTOR_P (tmpl) = DECL_DESTRUCTOR_P (decl);
- DECL_NONCONVERTING_P (tmpl) = DECL_NONCONVERTING_P (decl);
- DECL_ASSIGNMENT_OPERATOR_P (tmpl) = DECL_ASSIGNMENT_OPERATOR_P (decl);
- if (DECL_OVERLOADED_OPERATOR_P (decl))
- SET_OVERLOADED_OPERATOR_CODE (tmpl,
- DECL_OVERLOADED_OPERATOR_P (decl));
- }
return tmpl;
}
tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
tree specargs = CLASSTYPE_TI_ARGS (type);
tree inner_args = INNERMOST_TEMPLATE_ARGS (specargs);
- tree inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl);
+ tree inner_parms;
int nargs = TREE_VEC_LENGTH (inner_args);
- int ntparms = TREE_VEC_LENGTH (inner_parms);
+ int ntparms;
int i;
int did_error_intro = 0;
struct template_parm_data tpd;
struct template_parm_data tpd2;
+ gcc_assert (current_template_parms);
+
+ inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
+ ntparms = TREE_VEC_LENGTH (inner_parms);
+
/* We check that each of the template parameters given in the
partial specialization is used in the argument list to the
specialization. For example:
}
}
- if (retrieve_specialization (maintmpl, specargs,
- /*class_specializations_p=*/true))
- /* We've already got this specialization. */
- return decl;
+ /* We should only get here once. */
+ gcc_assert (!COMPLETE_TYPE_P (type));
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)
= tree_cons (specargs, inner_parms,
if (current_class_type
&& !TYPE_BEING_DEFINED (current_class_type)
&& DECL_LANG_SPECIFIC (decl)
+ && DECL_DECLARES_FUNCTION_P (decl)
/* If this is either a friend defined in the scope of the class
or a member function. */
&& (DECL_FUNCTION_MEMBER_P (decl)
if (TREE_PURPOSE (parm))
seen_def_arg_p = 1;
- else if (seen_def_arg_p)
+ else if (seen_def_arg_p
+ && !template_parameter_pack_p (TREE_VALUE (parm)))
{
error ("no default argument for %qD", TREE_VALUE (parm));
/* For better subsequent error-recovery, we indicate that
else if (is_primary
&& !is_partial
&& !is_friend_decl
+ /* Don't complain about an enclosing partial
+ specialization. */
+ && parm_level == parms
&& TREE_CODE (decl) == TYPE_DECL
&& i < ntparms - 1
&& template_parameter_pack_p (TREE_VALUE (parm)))
[temp.mem]. */
bool member_template_p = false;
- if (decl == error_mark_node)
- return decl;
+ if (decl == error_mark_node || !current_template_parms)
+ return error_mark_node;
/* See if this is a partial specialization. */
is_partial = (DECL_IMPLICIT_TYPEDEF_P (decl)
register_specialization (new_tmpl,
most_general_template (tmpl),
args,
- is_friend);
+ is_friend, 0);
return decl;
}
template arguments to %qD do not match original template %qD",
decl, DECL_TEMPLATE_RESULT (tmpl));
if (!uses_template_parms (TI_ARGS (tinfo)))
- inform ("use template<> for an explicit specialization");
+ inform (input_location, "use template<> for an explicit specialization");
/* Avoid crash in import_export_decl. */
DECL_INTERFACE_KNOWN (decl) = 1;
return error_mark_node;
{
error ("redeclared with %d template parameter(s)",
TREE_VEC_LENGTH (parms));
- inform ("previous declaration %q+D used %d template parameter(s)",
+ inform (input_location, "previous declaration %q+D used %d template parameter(s)",
tmpl, TREE_VEC_LENGTH (tmpl_parms));
return false;
}
A template-parameter may not be given default arguments
by two different declarations in the same scope. */
- error ("redefinition of default argument for %q#D", parm);
- inform ("%Joriginal definition appeared here", tmpl_parm);
+ error_at (input_location, "redefinition of default argument for %q#D", parm);
+ inform (DECL_SOURCE_LOCATION (tmpl_parm),
+ "original definition appeared here");
return false;
}
/* EXPR is an expression which is used in a constant-expression context.
For instance, it could be a VAR_DECL with a constant initializer.
- Extract the innest constant expression.
+ Extract the innermost constant expression.
This is basically a more powerful version of
integral_constant_value, which can be used also in templates where
For a non-type template-parameter of integral or enumeration type,
integral promotions (_conv.prom_) and integral conversions
(_conv.integral_) are applied. */
- if (INTEGRAL_TYPE_P (type))
+ if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
{
- if (!INTEGRAL_TYPE_P (expr_type))
+ if (!INTEGRAL_OR_ENUMERATION_TYPE_P (expr_type))
return error_mark_node;
expr = fold_decl_constant_value (expr);
expr = convert_nontype_argument_function (type, expr);
if (!expr || expr == error_mark_node)
return expr;
+
+ if (TREE_CODE (expr) != ADDR_EXPR)
+ {
+ error ("%qE is not a valid template argument for type %qT", expr, type);
+ error ("it must be the address of a function with external linkage");
+ return NULL_TREE;
+ }
}
/* [temp.arg.nontype]/5, bullet 5
{
error ("%qE is not a valid template argument for type %qT "
"because it is a pointer", expr, type);
- inform ("try using %qE instead", TREE_OPERAND (expr, 0));
+ inform (input_location, "try using %qE instead", TREE_OPERAND (expr, 0));
return NULL_TREE;
}
error ("%qE is not a valid template argument for type %qT "
"because it is of type %qT", expr, type,
TREE_TYPE (expr));
- inform ("standard conversions are not allowed in this context");
+ inform (input_location, "standard conversions are not allowed in this context");
return NULL_TREE;
}
}
D<int, C> d;
i.e. the parameter list of TT depends on earlier parameters. */
- if (!dependent_type_p (TREE_TYPE (arg))
+ if (!uses_template_parms (TREE_TYPE (arg))
&& !same_type_p
(tsubst (TREE_TYPE (parm), outer_args, complain, in_decl),
TREE_TYPE (arg)))
{
parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, nparms - 1));
+ if (parm == error_mark_node)
+ return 0;
+
switch (TREE_CODE (parm))
{
case TEMPLATE_DECL:
if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
&& TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
{
- pedwarn ("to refer to a type member of a template parameter, "
- "use %<typename %E%>", orig_arg);
+ permerror (input_location, "to refer to a type member of a template parameter, "
+ "use %<typename %E%>", orig_arg);
orig_arg = make_typename_type (TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1),
the typedef, which is confusing if those future uses do not
themselves also use the typedef. */
if (TYPE_P (val))
- val = canonical_type_variant (val);
+ val = strip_typedefs (val);
}
else
{
if (invalid_nontype_parm_type_p (t, complain))
return error_mark_node;
- if (!uses_template_parms (orig_arg) && !uses_template_parms (t))
+ if (template_parameter_pack_p (parm) && ARGUMENT_PACK_P (orig_arg))
+ {
+ if (same_type_p (t, TREE_TYPE (orig_arg)))
+ val = orig_arg;
+ else
+ {
+ /* Not sure if this is reachable, but it doesn't hurt
+ to be robust. */
+ error ("type mismatch in nontype parameter pack");
+ val = error_mark_node;
+ }
+ }
+ else if (!uses_template_parms (orig_arg) && !uses_template_parms (t))
/* We used to call digest_init here. However, digest_init
will report errors, which we don't want when complain
is zero. More importantly, digest_init will try too
tree inner_args;
tree new_args;
tree new_inner_args;
- bool saved_skip_evaluation;
+ int saved_unevaluated_operand;
+ int saved_inhibit_evaluation_warnings;
/* When used as a boolean value, indicates whether this is a
variadic template parameter list. Since it's an int, we can also
parameters. */
int variadic_p = 0;
- inner_args
- = expand_template_argument_pack (INNERMOST_TEMPLATE_ARGS (args));
-
- nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
nparms = TREE_VEC_LENGTH (parms);
/* Determine if there are any parameter packs. */
{
tree tparm = TREE_VALUE (TREE_VEC_ELT (parms, parm_idx));
if (template_parameter_pack_p (tparm))
- {
- variadic_p = 1;
- break;
- }
+ ++variadic_p;
}
- if ((nargs > nparms - variadic_p && !variadic_p)
+ inner_args = INNERMOST_TEMPLATE_ARGS (args);
+ /* If there are 0 or 1 parameter packs, we need to expand any argument
+ packs so that we can deduce a parameter pack from some non-packed args
+ followed by an argument pack, as in variadic85.C. If there are more
+ than that, we need to leave argument packs intact so the arguments are
+ assigned to the right parameter packs. This should only happen when
+ dealing with a nested class inside a partial specialization of a class
+ template, as in variadic92.C. */
+ if (variadic_p <= 1)
+ inner_args = expand_template_argument_pack (inner_args);
+
+ nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
+ if ((nargs > nparms && !variadic_p)
|| (nargs < nparms - variadic_p
&& require_all_args
&& (!use_default_args
/* We need to evaluate the template arguments, even though this
template-id may be nested within a "sizeof". */
- saved_skip_evaluation = skip_evaluation;
- skip_evaluation = false;
+ saved_unevaluated_operand = cp_unevaluated_operand;
+ cp_unevaluated_operand = 0;
+ saved_inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
+ c_inhibit_evaluation_warnings = 0;
new_inner_args = make_tree_vec (nparms);
new_args = add_outermost_template_args (args, new_inner_args);
for (parm_idx = 0, arg_idx = 0; parm_idx < nparms; parm_idx++, arg_idx++)
}
/* Calculate the next argument. */
- if (template_parameter_pack_p (TREE_VALUE (parm)))
+ if (arg_idx < nargs)
+ arg = TREE_VEC_ELT (inner_args, arg_idx);
+ else
+ arg = NULL_TREE;
+
+ if (template_parameter_pack_p (TREE_VALUE (parm))
+ && !(arg && ARGUMENT_PACK_P (arg)))
{
- /* All remaining arguments will be placed in the
- template parameter pack PARM. */
- arg = coerce_template_parameter_pack (parms, parm_idx, args,
- inner_args, arg_idx,
- new_args, &lost,
- in_decl, complain);
-
+ /* All remaining arguments will be placed in the
+ template parameter pack PARM. */
+ arg = coerce_template_parameter_pack (parms, parm_idx, args,
+ inner_args, arg_idx,
+ new_args, &lost,
+ in_decl, complain);
+
/* Store this argument. */
if (arg == error_mark_node)
lost++;
TREE_VEC_ELT (new_inner_args, parm_idx) = arg;
- /* We are done with all of the arguments. */
- arg_idx = nargs;
-
+ /* We are done with all of the arguments. */
+ arg_idx = nargs;
+
continue;
}
- else if (arg_idx < nargs)
- {
- arg = TREE_VEC_ELT (inner_args, arg_idx);
-
- if (arg && PACK_EXPANSION_P (arg))
+ else if (arg)
+ {
+ if (PACK_EXPANSION_P (arg))
{
if (complain & tf_error)
{
+ /* FIXME this restriction was removed by N2555; see
+ bug 35722. */
/* If ARG is a pack expansion, but PARM is not a
template parameter pack (if it were, we would have
handled it above), we're trying to expand into a
fixed-length argument list. */
if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
- error ("cannot expand %<%E%> into a fixed-length "
+ sorry ("cannot expand %<%E%> into a fixed-length "
"argument list", arg);
else
- error ("cannot expand %<%T%> into a fixed-length "
+ sorry ("cannot expand %<%T%> into a fixed-length "
"argument list", arg);
}
return error_mark_node;
lost++;
TREE_VEC_ELT (new_inner_args, arg_idx) = arg;
}
- skip_evaluation = saved_skip_evaluation;
+ cp_unevaluated_operand = saved_unevaluated_operand;
+ c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
if (lost)
return error_mark_node;
return PACK_EXPANSION_P (nt)
&& template_args_equal (PACK_EXPANSION_PATTERN (ot),
PACK_EXPANSION_PATTERN (nt));
+ else if (ARGUMENT_PACK_P (ot))
+ {
+ int i, len;
+ tree opack, npack;
+
+ if (!ARGUMENT_PACK_P (nt))
+ return 0;
+
+ opack = ARGUMENT_PACK_ARGS (ot);
+ npack = ARGUMENT_PACK_ARGS (nt);
+ len = TREE_VEC_LENGTH (opack);
+ if (TREE_VEC_LENGTH (npack) != len)
+ return 0;
+ for (i = 0; i < len; ++i)
+ if (!template_args_equal (TREE_VEC_ELT (opack, i),
+ TREE_VEC_ELT (npack, i)))
+ return 0;
+ return 1;
+ }
else if (TYPE_P (nt))
return TYPE_P (ot) && same_type_p (ot, nt);
else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))
{
int i;
- oldargs = expand_template_argument_pack (oldargs);
- newargs = expand_template_argument_pack (newargs);
-
if (TREE_VEC_LENGTH (oldargs) != TREE_VEC_LENGTH (newargs))
return 0;
int entering_scope,
tsubst_flags_t complain)
{
- tree template = NULL_TREE, parmlist;
+ tree templ = NULL_TREE, parmlist;
tree t;
+ spec_entry **slot;
+ spec_entry *entry;
+ spec_entry elt;
+ hashval_t hash;
timevar_push (TV_NAME_LOOKUP);
{
tree value = innermost_non_namespace_value (d1);
if (value && DECL_TEMPLATE_TEMPLATE_PARM_P (value))
- template = value;
+ templ = value;
else
{
if (context)
push_decl_namespace (context);
- template = lookup_name (d1);
- template = maybe_get_template_decl_from_type_decl (template);
+ templ = lookup_name (d1);
+ templ = maybe_get_template_decl_from_type_decl (templ);
if (context)
pop_decl_namespace ();
}
- if (template)
- context = DECL_CONTEXT (template);
+ if (templ)
+ context = DECL_CONTEXT (templ);
}
else if (TREE_CODE (d1) == TYPE_DECL && MAYBE_CLASS_TYPE_P (TREE_TYPE (d1)))
{
if (CLASSTYPE_TEMPLATE_INFO (type))
{
- template = CLASSTYPE_TI_TEMPLATE (type);
- d1 = DECL_NAME (template);
+ templ = CLASSTYPE_TI_TEMPLATE (type);
+ d1 = DECL_NAME (templ);
}
}
else if (TREE_CODE (d1) == ENUMERAL_TYPE
|| (TYPE_P (d1) && MAYBE_CLASS_TYPE_P (d1)))
{
- template = TYPE_TI_TEMPLATE (d1);
- d1 = DECL_NAME (template);
+ templ = TYPE_TI_TEMPLATE (d1);
+ d1 = DECL_NAME (templ);
}
else if (TREE_CODE (d1) == TEMPLATE_DECL
+ && DECL_TEMPLATE_RESULT (d1)
&& TREE_CODE (DECL_TEMPLATE_RESULT (d1)) == TYPE_DECL)
{
- template = d1;
- d1 = DECL_NAME (template);
- context = DECL_CONTEXT (template);
+ templ = d1;
+ d1 = DECL_NAME (templ);
+ context = DECL_CONTEXT (templ);
}
/* Issue an error message if we didn't find a template. */
- if (! template)
+ if (! templ)
{
if (complain & tf_error)
error ("%qT is not a template", d1);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
- if (TREE_CODE (template) != TEMPLATE_DECL
+ if (TREE_CODE (templ) != TEMPLATE_DECL
/* Make sure it's a user visible template, if it was named by
the user. */
- || ((complain & tf_user) && !DECL_TEMPLATE_PARM_P (template)
- && !PRIMARY_TEMPLATE_P (template)))
+ || ((complain & tf_user) && !DECL_TEMPLATE_PARM_P (templ)
+ && !PRIMARY_TEMPLATE_P (templ)))
{
if (complain & tf_error)
{
complain &= ~tf_user;
- if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))
+ if (DECL_TEMPLATE_TEMPLATE_PARM_P (templ))
{
/* Create a new TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM node to store
template arguments */
tree arglist2;
tree outer;
- parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
+ parmlist = DECL_INNERMOST_TEMPLATE_PARMS (templ);
/* Consider an example where a template template parameter declared as
level 1, and T at level 2, while the template arguments at level 1
becomes {std::vector} and the inner level 2 is {int}. */
- outer = DECL_CONTEXT (template);
+ outer = DECL_CONTEXT (templ);
if (outer)
outer = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (outer)));
else if (current_template_parms)
if (outer)
arglist = add_to_template_args (outer, arglist);
- arglist2 = coerce_template_parms (parmlist, arglist, template,
+ arglist2 = coerce_template_parms (parmlist, arglist, templ,
complain,
/*require_all_args=*/true,
/*use_default_args=*/true);
if (arglist2 == error_mark_node
|| (!uses_template_parms (arglist2)
- && check_instantiated_args (template, arglist2, complain)))
+ && check_instantiated_args (templ, arglist2, complain)))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- parm = bind_template_template_parm (TREE_TYPE (template), arglist2);
+ parm = bind_template_template_parm (TREE_TYPE (templ), arglist2);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, parm);
}
else
{
- tree template_type = TREE_TYPE (template);
+ tree template_type = TREE_TYPE (templ);
tree gen_tmpl;
tree type_decl;
tree found = NULL_TREE;
int parm_depth;
int is_partial_instantiation;
- gen_tmpl = most_general_template (template);
+ gen_tmpl = most_general_template (templ);
parmlist = DECL_TEMPLATE_PARMS (gen_tmpl);
parm_depth = TMPL_PARMS_DEPTH (parmlist);
arg_depth = TMPL_ARGS_DEPTH (arglist);
<class U> struct S1<T>::S2'. We must fill in the missing
arguments. */
arglist
- = add_outermost_template_args (TYPE_TI_ARGS (TREE_TYPE (template)),
+ = add_outermost_template_args (TYPE_TI_ARGS (TREE_TYPE (templ)),
arglist);
arg_depth = TMPL_ARGS_DEPTH (arglist);
}
/* From here on, we're only interested in the most general
template. */
- template = gen_tmpl;
/* Calculate the BOUND_ARGS. These will be the args that are
actually tsubst'd into the definition to create the
tree bound_args = make_tree_vec (parm_depth);
for (i = saved_depth,
- t = DECL_TEMPLATE_PARMS (template);
+ t = DECL_TEMPLATE_PARMS (gen_tmpl);
i > 0 && t != NULL_TREE;
--i, t = TREE_CHAIN (t))
{
tree a = coerce_template_parms (TREE_VALUE (t),
- arglist, template,
+ arglist, gen_tmpl,
complain,
/*require_all_args=*/true,
/*use_default_args=*/true);
arglist
= coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
INNERMOST_TEMPLATE_ARGS (arglist),
- template,
+ gen_tmpl,
complain,
/*require_all_args=*/true,
/*use_default_args=*/true);
the `C<T>' is just the same as `C'. Outside of the
class, however, such a reference is an instantiation. */
- if (comp_template_args (TYPE_TI_ARGS (template_type),
- arglist))
- {
- found = template_type;
-
- if (!entering_scope && PRIMARY_TEMPLATE_P (template))
- {
- tree ctx;
-
- for (ctx = current_class_type;
- ctx && TREE_CODE (ctx) != NAMESPACE_DECL;
- ctx = (TYPE_P (ctx)
- ? TYPE_CONTEXT (ctx)
- : DECL_CONTEXT (ctx)))
- if (TYPE_P (ctx) && same_type_p (ctx, template_type))
- goto found_ctx;
-
- /* We're not in the scope of the class, so the
- TEMPLATE_TYPE is not the type we want after all. */
- found = NULL_TREE;
- found_ctx:;
- }
- }
- if (found)
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
+ if ((entering_scope
+ || !PRIMARY_TEMPLATE_P (gen_tmpl)
+ || currently_open_class (template_type))
+ /* comp_template_args is expensive, check it last. */
+ && comp_template_args (TYPE_TI_ARGS (template_type),
+ arglist))
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, template_type);
/* If we already have this specialization, return it. */
- found = retrieve_specialization (template, arglist,
- /*class_specializations_p=*/false);
- if (found)
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
+ elt.tmpl = gen_tmpl;
+ elt.args = arglist;
+ hash = hash_specialization (&elt);
+ entry = (spec_entry *) htab_find_with_hash (type_specializations,
+ &elt, hash);
+
+ if (entry)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->spec);
/* This type is a "partial instantiation" if any of the template
arguments still involve template parameters. Note that we set
/* If the deduced arguments are invalid, then the binding
failed. */
if (!is_partial_instantiation
- && check_instantiated_args (template,
+ && check_instantiated_args (gen_tmpl,
INNERMOST_TEMPLATE_ARGS (arglist),
complain))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
if (!is_partial_instantiation
- && !PRIMARY_TEMPLATE_P (template)
- && TREE_CODE (CP_DECL_CONTEXT (template)) == NAMESPACE_DECL)
+ && !PRIMARY_TEMPLATE_P (gen_tmpl)
+ && TREE_CODE (CP_DECL_CONTEXT (gen_tmpl)) == NAMESPACE_DECL)
{
- found = xref_tag_from_type (TREE_TYPE (template),
- DECL_NAME (template),
+ found = xref_tag_from_type (TREE_TYPE (gen_tmpl),
+ DECL_NAME (gen_tmpl),
/*tag_scope=*/ts_global);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
}
- context = tsubst (DECL_CONTEXT (template), arglist,
+ context = tsubst (DECL_CONTEXT (gen_tmpl), arglist,
complain, in_decl);
if (!context)
context = global_namespace;
if (!is_partial_instantiation)
{
set_current_access_from_decl (TYPE_NAME (template_type));
- t = start_enum (TYPE_IDENTIFIER (template_type));
+ t = start_enum (TYPE_IDENTIFIER (template_type),
+ tsubst (ENUM_UNDERLYING_TYPE (template_type),
+ arglist, complain, in_decl),
+ SCOPED_ENUM_P (template_type));
}
else
- /* We don't want to call start_enum for this type, since
- the values for the enumeration constants may involve
- template parameters. And, no one should be interested
- in the enumeration constants for such a type. */
- t = make_node (ENUMERAL_TYPE);
+ {
+ /* We don't want to call start_enum for this type, since
+ the values for the enumeration constants may involve
+ template parameters. And, no one should be interested
+ in the enumeration constants for such a type. */
+ t = make_node (ENUMERAL_TYPE);
+ SET_SCOPED_ENUM_P (t, SCOPED_ENUM_P (template_type));
+ }
}
else
{
/* A local class. Make sure the decl gets registered properly. */
if (context == current_function_decl)
- pushtag (DECL_NAME (template), t, /*tag_scope=*/ts_current);
+ pushtag (DECL_NAME (gen_tmpl), t, /*tag_scope=*/ts_current);
if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
/* This instantiation is another name for the primary
{
TYPE_CONTEXT (t) = FROB_CONTEXT (context);
- type_decl = create_implicit_typedef (DECL_NAME (template), t);
+ type_decl = create_implicit_typedef (DECL_NAME (gen_tmpl), t);
DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
TYPE_STUB_DECL (t) = type_decl;
DECL_SOURCE_LOCATION (type_decl)
= TREE_PRIVATE (TYPE_STUB_DECL (template_type));
TREE_PROTECTED (type_decl)
= TREE_PROTECTED (TYPE_STUB_DECL (template_type));
- DECL_IN_SYSTEM_HEADER (type_decl)
- = DECL_IN_SYSTEM_HEADER (template);
if (CLASSTYPE_VISIBILITY_SPECIFIED (template_type))
{
DECL_VISIBILITY_SPECIFIED (type_decl) = 1;
template is the immediate parent if this is a full
instantiation. */
if (parm_depth == 1 || is_partial_instantiation
- || !PRIMARY_TEMPLATE_P (template))
+ || !PRIMARY_TEMPLATE_P (gen_tmpl))
/* This case is easy; there are no member templates involved. */
- found = template;
+ found = gen_tmpl;
else
{
- /* This is a full instantiation of a member template. Look
- for a partial instantiation of which this is an instance. */
-
- for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
- found; found = TREE_CHAIN (found))
- {
- int success;
- tree tmpl = CLASSTYPE_TI_TEMPLATE (TREE_VALUE (found));
-
- /* We only want partial instantiations, here, not
- specializations or full instantiations. */
- if (CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_VALUE (found))
- || !uses_template_parms (TREE_VALUE (found)))
- continue;
-
- /* Temporarily reduce by one the number of levels in the
- ARGLIST and in FOUND so as to avoid comparing the
- last set of arguments. */
- TREE_VEC_LENGTH (arglist)--;
- TREE_VEC_LENGTH (TREE_PURPOSE (found)) --;
-
- /* See if the arguments match. If they do, then TMPL is
- the partial instantiation we want. */
- success = comp_template_args (TREE_PURPOSE (found), arglist);
-
- /* Restore the argument vectors to their full size. */
- TREE_VEC_LENGTH (arglist)++;
- TREE_VEC_LENGTH (TREE_PURPOSE (found))++;
-
- if (success)
- {
- found = tmpl;
- break;
- }
- }
-
- if (!found)
- {
- /* There was no partial instantiation. This happens
- where C<T> is a member template of A<T> and it's used
- in something like
-
- template <typename T> struct B { A<T>::C<int> m; };
- B<float>;
-
- Create the partial instantiation.
- */
- TREE_VEC_LENGTH (arglist)--;
- found = tsubst (template, arglist, complain, NULL_TREE);
- TREE_VEC_LENGTH (arglist)++;
- }
+ /* This is a full instantiation of a member template. Find
+ the partial instantiation of which this is an instance. */
+
+ /* Temporarily reduce by one the number of levels in the ARGLIST
+ so as to avoid comparing the last set of arguments. */
+ TREE_VEC_LENGTH (arglist)--;
+ found = tsubst (gen_tmpl, arglist, complain, NULL_TREE);
+ TREE_VEC_LENGTH (arglist)++;
+ found = CLASSTYPE_TI_TEMPLATE (found);
}
SET_TYPE_TEMPLATE_INFO (t, tree_cons (found, arglist, NULL_TREE));
- DECL_TEMPLATE_INSTANTIATIONS (template)
+
+ elt.spec = t;
+ slot = (spec_entry **) htab_find_slot_with_hash (type_specializations,
+ &elt, hash, INSERT);
+ *slot = GGC_NEW (spec_entry);
+ **slot = elt;
+
+ /* Note this use of the partial instantiation so we can check it
+ later in maybe_process_partial_specialization. */
+ DECL_TEMPLATE_INSTANTIATIONS (templ)
= tree_cons (arglist, t,
- DECL_TEMPLATE_INSTANTIATIONS (template));
+ DECL_TEMPLATE_INSTANTIATIONS (templ));
if (TREE_CODE (t) == ENUMERAL_TYPE
&& !is_partial_instantiation)
|| TREE_CODE (t) == BASELINK
|| TREE_CODE (t) == IDENTIFIER_NODE
|| TREE_CODE (t) == TRAIT_EXPR
+ || TREE_CODE (t) == CONSTRUCTOR
|| CONSTANT_CLASS_P (t))
dependent_p = (type_dependent_expression_p (t)
|| value_dependent_expression_p (t));
static int
push_tinst_level (tree d)
{
- struct tinst_level *new;
+ struct tinst_level *new_level;
if (tinst_depth >= max_tinst_depth)
{
return 0;
}
- new = GGC_NEW (struct tinst_level);
- new->decl = d;
- new->locus = input_location;
- new->in_system_header_p = in_system_header;
- new->next = current_tinst_level;
- current_tinst_level = new;
+ new_level = GGC_NEW (struct tinst_level);
+ new_level->decl = d;
+ new_level->locus = input_location;
+ new_level->in_system_header_p = in_system_header;
+ new_level->next = current_tinst_level;
+ current_tinst_level = new_level;
++tinst_depth;
#ifdef GATHER_STATISTICS
/* Restore the filename and line number stashed away when we started
this instantiation. */
input_location = current_tinst_level->locus;
- in_system_header = current_tinst_level->in_system_header_p;
current_tinst_level = current_tinst_level->next;
--tinst_depth;
++tinst_level_tick;
return level;
}
+/* Returns TRUE if PARM is a parameter of the template TEMPL. */
+
+bool
+parameter_of_template_p (tree parm, tree templ)
+{
+ tree parms;
+ int i;
+
+ if (!parm || !templ)
+ return false;
+
+ gcc_assert (DECL_TEMPLATE_PARM_P (parm));
+ gcc_assert (TREE_CODE (templ) == TEMPLATE_DECL);
+
+ parms = DECL_TEMPLATE_PARMS (templ);
+ parms = INNERMOST_TEMPLATE_PARMS (parms);
+
+ for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
+ if (parm == TREE_VALUE (TREE_VEC_ELT (parms, i)))
+ return true;
+
+ return false;
+}
+
/* DECL is a friend FUNCTION_DECL or TEMPLATE_DECL. ARGS is the
vector of template arguments, as for tsubst.
/* Friend functions are looked up in the containing namespace scope.
We must enter that scope, to avoid finding member functions of the
- current cless with same name. */
+ current class with same name. */
push_nested_namespace (ns);
fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
tf_warning_or_error, NULL_TREE,
;
else
{
+ tree new_template = TI_TEMPLATE (new_friend_template_info);
+ tree new_args = TI_ARGS (new_friend_template_info);
+
/* Overwrite whatever template info was there before, if
any, with the new template information pertaining to
the declaration. */
DECL_TEMPLATE_INFO (old_decl) = new_friend_template_info;
if (TREE_CODE (old_decl) != TEMPLATE_DECL)
- reregister_specialization (new_friend,
- most_general_template (old_decl),
- old_decl);
+ /* We should have called reregister_specialization in
+ duplicate_decls. */
+ gcc_assert (retrieve_specialization (new_template,
+ new_args, 0)
+ == old_decl);
else
{
tree t;
- tree new_friend_args;
+ /* Indicate that the old function template is a partial
+ instantiation. */
DECL_TEMPLATE_INFO (DECL_TEMPLATE_RESULT (old_decl))
= new_friend_result_template_info;
- new_friend_args = TI_ARGS (new_friend_template_info);
- for (t = DECL_TEMPLATE_SPECIALIZATIONS (old_decl);
+ gcc_assert (new_template
+ == most_general_template (new_template));
+ gcc_assert (new_template != old_decl);
+
+ /* Reassign any specializations already in the hash table
+ to the new more general template, and add the
+ additional template args. */
+ for (t = DECL_TEMPLATE_INSTANTIATIONS (old_decl);
t != NULL_TREE;
t = TREE_CHAIN (t))
{
tree spec = TREE_VALUE (t);
+ spec_entry elt;
+
+ elt.tmpl = old_decl;
+ elt.args = DECL_TI_ARGS (spec);
+ elt.spec = NULL_TREE;
+
+ htab_remove_elt (decl_specializations, &elt);
DECL_TI_ARGS (spec)
- = add_outermost_template_args (new_friend_args,
+ = add_outermost_template_args (new_args,
DECL_TI_ARGS (spec));
- }
- /* Now, since specializations are always supposed to
- hang off of the most general template, we must move
- them. */
- t = most_general_template (old_decl);
- if (t != old_decl)
- {
- DECL_TEMPLATE_SPECIALIZATIONS (t)
- = chainon (DECL_TEMPLATE_SPECIALIZATIONS (t),
- DECL_TEMPLATE_SPECIALIZATIONS (old_decl));
- DECL_TEMPLATE_SPECIALIZATIONS (old_decl) = NULL_TREE;
+ register_specialization
+ (spec, new_template, DECL_TI_ARGS (spec), true, 0);
+
}
+ DECL_TEMPLATE_INSTANTIATIONS (old_decl) = NULL_TREE;
}
}
}
}
+/* Perform (or defer) access check for typedefs that were referenced
+ from within the template TMPL code.
+ This is a subroutine of instantiate_template and instantiate_class_template.
+ TMPL is the template to consider and TARGS is the list of arguments of
+ that template. */
+
+static void
+perform_typedefs_access_check (tree tmpl, tree targs)
+{
+ tree t;
+
+ if (!tmpl
+ || (!CLASS_TYPE_P (tmpl)
+ && TREE_CODE (tmpl) != FUNCTION_DECL))
+ return;
+
+ for (t = get_types_needing_access_check (tmpl); t; t = TREE_CHAIN (t))
+ {
+ tree type_decl = TREE_PURPOSE (t);
+ tree type_scope = TREE_VALUE (t);
+
+ if (!type_decl || !type_scope || !CLASS_TYPE_P (type_scope))
+ continue;
+
+ if (uses_template_parms (type_decl))
+ type_decl = tsubst (type_decl, targs, tf_error, NULL_TREE);
+ if (uses_template_parms (type_scope))
+ type_scope = tsubst (type_scope, targs, tf_error, NULL_TREE);
+
+ perform_or_defer_access_check (TYPE_BINFO (type_scope),
+ type_decl, type_decl);
+ }
+}
+
tree
instantiate_class_template (tree type)
{
- tree template, args, pattern, t, member;
+ tree templ, args, pattern, t, member;
tree typedecl;
tree pbinfo;
tree base_list;
return type;
/* Figure out which template is being instantiated. */
- template = most_general_template (CLASSTYPE_TI_TEMPLATE (type));
- gcc_assert (TREE_CODE (template) == TEMPLATE_DECL);
+ templ = most_general_template (CLASSTYPE_TI_TEMPLATE (type));
+ gcc_assert (TREE_CODE (templ) == TEMPLATE_DECL);
/* Determine what specialization of the original template to
instantiate. */
- t = most_specialized_class (type, template);
+ t = most_specialized_class (type, templ);
if (t == error_mark_node)
{
TYPE_BEING_DEFINED (type) = 1;
}
else
{
- pattern = TREE_TYPE (template);
+ pattern = TREE_TYPE (templ);
args = CLASSTYPE_TI_ARGS (type);
}
SET_CLASSTYPE_INTERFACE_UNKNOWN (type);
- /* Set the input location to the template definition. This is needed
- if tsubsting causes an error. */
- typedecl = TYPE_MAIN_DECL (type);
+ /* Set the input location to the most specialized template definition.
+ This is needed if tsubsting causes an error. */
+ typedecl = TYPE_MAIN_DECL (pattern);
input_location = DECL_SOURCE_LOCATION (typedecl);
- in_system_header = DECL_IN_SYSTEM_HEADER (typedecl);
TYPE_HAS_USER_CONSTRUCTOR (type) = TYPE_HAS_USER_CONSTRUCTOR (pattern);
TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);
{
tree r;
- /* The the file and line for this declaration, to
+ /* The file and line for this declaration, to
assist in error message reporting. Since we
called push_tinst_level above, we don't need to
restore these. */
/* Build new DECL_FRIENDLIST. */
tree r;
- /* The the file and line for this declaration, to
+ /* The file and line for this declaration, to
assist in error message reporting. Since we
called push_tinst_level above, we don't need to
restore these. */
/* Now that the class is complete, instantiate default arguments for
any member functions. We don't do this earlier because the
default arguments may reference members of the class. */
- if (!PRIMARY_TEMPLATE_P (template))
+ if (!PRIMARY_TEMPLATE_P (templ))
for (t = TYPE_METHODS (type); t; t = TREE_CHAIN (t))
if (TREE_CODE (t) == FUNCTION_DECL
/* Implicitly generated member functions will not have template
&& DECL_TEMPLATE_INFO (t))
tsubst_default_arguments (t);
+ /* Some typedefs referenced from within the template code need to be access
+ checked at template instantiation time, i.e now. These types were
+ added to the template at parsing time. Let's get those and perform
+ the access checks then. */
+ perform_typedefs_access_check (pattern, args);
+ perform_deferred_access_checks ();
pop_nested_class ();
pop_from_top_level ();
pop_deferring_access_checks ();
return r;
}
+/* Give a chain SPEC_PARM of PARM_DECLs, pack them into a
+ NONTYPE_ARGUMENT_PACK. */
+
+static tree
+make_fnparm_pack (tree spec_parm)
+{
+ /* Collect all of the extra "packed" parameters into an
+ argument pack. */
+ tree parmvec;
+ tree parmtypevec;
+ tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
+ tree argtypepack = make_node (TYPE_ARGUMENT_PACK);
+ int i, len = list_length (spec_parm);
+
+ /* Fill in PARMVEC and PARMTYPEVEC with all of the parameters. */
+ parmvec = make_tree_vec (len);
+ parmtypevec = make_tree_vec (len);
+ for (i = 0; i < len; i++, spec_parm = TREE_CHAIN (spec_parm))
+ {
+ TREE_VEC_ELT (parmvec, i) = spec_parm;
+ TREE_VEC_ELT (parmtypevec, i) = TREE_TYPE (spec_parm);
+ }
+
+ /* Build the argument packs. */
+ SET_ARGUMENT_PACK_ARGS (argpack, parmvec);
+ SET_ARGUMENT_PACK_ARGS (argtypepack, parmtypevec);
+ TREE_TYPE (argpack) = argtypepack;
+
+ return argpack;
+}
+
/* Substitute ARGS into T, which is an pack expansion
(i.e. TYPE_PACK_EXPANSION or EXPR_PACK_EXPANSION). Returns a
TREE_VEC with the substituted arguments, a PACK_EXPANSION_* node
tree first_arg_pack; int i, len = -1;
tree result;
int incomplete = 0;
+ bool very_local_specializations = false;
gcc_assert (PACK_EXPANSION_P (t));
pattern = PACK_EXPANSION_PATTERN (t);
tree orig_arg = NULL_TREE;
if (TREE_CODE (parm_pack) == PARM_DECL)
- arg_pack = retrieve_local_specialization (parm_pack);
+ {
+ arg_pack = retrieve_local_specialization (parm_pack);
+ if (arg_pack == NULL_TREE)
+ {
+ /* This can happen for a parameter name used later in a function
+ declaration (such as in a late-specified return type). Just
+ make a dummy decl, since it's only used for its type. */
+ gcc_assert (cp_unevaluated_operand != 0);
+ arg_pack = tsubst_decl (parm_pack, args, complain);
+ arg_pack = make_fnparm_pack (arg_pack);
+ }
+ }
else
{
int level, idx, levels;
and return a PACK_EXPANSION_*. The caller will need to deal with
that. */
if (unsubstituted_packs)
- return make_pack_expansion (tsubst (pattern, args, complain,
- in_decl));
+ {
+ tree new_pat;
+ if (TREE_CODE (t) == EXPR_PACK_EXPANSION)
+ new_pat = tsubst_expr (pattern, args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+ else
+ new_pat = tsubst (pattern, args, complain, in_decl);
+ return make_pack_expansion (new_pat);
+ }
/* We could not find any argument packs that work. */
if (len < 0)
return error_mark_node;
+ if (!local_specializations)
+ {
+ /* We're in a late-specified return type, so we don't have a local
+ specializations table. Create one for doing this expansion. */
+ very_local_specializations = true;
+ local_specializations = htab_create (37,
+ hash_local_specialization,
+ eq_local_specializations,
+ NULL);
+ }
+
/* For each argument in each argument pack, substitute into the
pattern. */
result = make_tree_vec (len + incomplete);
break;
}
}
-
+
/* Update ARGS to restore the substitution from parameter packs to
their argument packs. */
for (pack = packs; pack; pack = TREE_CHAIN (pack))
}
}
+ if (very_local_specializations)
+ {
+ htab_delete (local_specializations);
+ local_specializations = NULL;
+ }
+
return result;
}
tree argvec;
tree context;
tree r;
- bool saved_skip_evaluation;
+ int saved_unevaluated_operand;
+ int saved_inhibit_evaluation_warnings;
/* In "sizeof(X<I>)" we need to evaluate "I". */
- saved_skip_evaluation = skip_evaluation;
- skip_evaluation = false;
+ saved_unevaluated_operand = cp_unevaluated_operand;
+ cp_unevaluated_operand = 0;
+ saved_inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
+ c_inhibit_evaluation_warnings = 0;
/* First, determine the context for the type we are looking
up. */
r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
}
- skip_evaluation = saved_skip_evaluation;
+ cp_unevaluated_operand = saved_unevaluated_operand;
+ c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
return r;
}
cp_function_chain->x_current_class_ref = saved_class_ref;
}
- pop_access_scope (fn);
-
/* Make sure the default argument is reasonable. */
arg = check_default_argument (type, arg);
+ pop_access_scope (fn);
+
return arg;
}
location_t saved_loc;
tree r = NULL_TREE;
tree in_decl = t;
+ hashval_t hash = 0;
/* Set the filename and linenumber to improve error-reporting. */
saved_loc = input_location;
case TEMPLATE_DECL:
{
/* We can get here when processing a member function template,
- member class template, and template template parameter of
- a template class. */
+ member class template, or template template parameter. */
tree decl = DECL_TEMPLATE_RESULT (t);
tree spec;
tree tmpl_args;
TREE_CHAIN (r) = NULL_TREE;
TREE_TYPE (r) = new_type;
DECL_TEMPLATE_RESULT (r)
- = build_decl (TYPE_DECL, DECL_NAME (decl), new_type);
+ = build_decl (DECL_SOURCE_LOCATION (decl),
+ TYPE_DECL, DECL_NAME (decl), new_type);
DECL_TEMPLATE_PARMS (r)
= tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args,
complain);
if (full_args == error_mark_node)
return error_mark_node;
- /* tsubst_template_args doesn't copy the vector if
- nothing changed. But, *something* should have
- changed. */
- gcc_assert (full_args != tmpl_args);
+ /* If this is a default template template argument,
+ tsubst might not have changed anything. */
+ if (full_args == tmpl_args)
+ return t;
- spec = retrieve_specialization (t, full_args,
- /*class_specializations_p=*/true);
+ hash = hash_tmpl_and_args (t, full_args);
+ spec = retrieve_specialization (t, full_args, hash);
if (spec != NULL_TREE)
{
r = spec;
/* Record this non-type partial instantiation. */
register_specialization (r, t,
DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)),
- false);
+ false, hash);
}
break;
args, complain, in_decl);
/* Check to see if we already have this specialization. */
- spec = retrieve_specialization (gen_tmpl, argvec,
- /*class_specializations_p=*/false);
+ hash = hash_tmpl_and_args (gen_tmpl, argvec);
+ spec = retrieve_specialization (gen_tmpl, argvec, hash);
if (spec)
{
/* Clear out the mangled name and RTL for the instantiation. */
SET_DECL_ASSEMBLER_NAME (r, NULL_TREE);
SET_DECL_RTL (r, NULL_RTX);
- DECL_INITIAL (r) = NULL_TREE;
+ /* Leave DECL_INITIAL set on deleted instantiations. */
+ if (!DECL_DELETED_FN (r))
+ DECL_INITIAL (r) = NULL_TREE;
DECL_CONTEXT (r) = ctx;
if (member && DECL_CONV_FN_P (r))
DECL_PENDING_INLINE_INFO (r) = 0;
DECL_PENDING_INLINE_P (r) = 0;
DECL_SAVED_TREE (r) = NULL_TREE;
+ DECL_STRUCT_FUNCTION (r) = NULL;
TREE_USED (r) = 0;
- if (DECL_CLONED_FUNCTION (r))
- {
- DECL_CLONED_FUNCTION (r) = tsubst (DECL_CLONED_FUNCTION (t),
- args, complain, t);
- TREE_CHAIN (r) = TREE_CHAIN (DECL_CLONED_FUNCTION (r));
- TREE_CHAIN (DECL_CLONED_FUNCTION (r)) = r;
- }
+ /* We'll re-clone as appropriate in instantiate_template. */
+ DECL_CLONED_FUNCTION (r) = NULL_TREE;
/* Set up the DECL_TEMPLATE_INFO for R. There's no need to do
this in the special friend case mentioned above where
DECL_TEMPLATE_INFO (r)
= tree_cons (gen_tmpl, argvec, NULL_TREE);
SET_DECL_IMPLICIT_INSTANTIATION (r);
- register_specialization (r, gen_tmpl, argvec, false);
+ register_specialization (r, gen_tmpl, argvec, false, hash);
/* We're not supposed to instantiate default arguments
until they are called, for a template. But, for a
tsubst_copy (DECL_NAME (t), args, complain, in_decl));
if (!r)
r = error_mark_node;
+ else
+ {
+ TREE_PROTECTED (r) = TREE_PROTECTED (t);
+ TREE_PRIVATE (r) = TREE_PRIVATE (t);
+ }
}
else
{
tmpl = DECL_TI_TEMPLATE (t);
gen_tmpl = most_general_template (tmpl);
argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
- spec = (retrieve_specialization
- (gen_tmpl, argvec,
- /*class_specializations_p=*/false));
+ hash = hash_tmpl_and_args (gen_tmpl, argvec);
+ spec = retrieve_specialization (gen_tmpl, argvec, hash);
}
}
else
processing here. */
DECL_EXTERNAL (r) = 1;
- register_specialization (r, gen_tmpl, argvec, false);
+ register_specialization (r, gen_tmpl, argvec, false, hash);
DECL_TEMPLATE_INFO (r) = tree_cons (tmpl, argvec, NULL_TREE);
SET_DECL_IMPLICIT_INSTANTIATION (r);
}
if (arg_types == error_mark_node)
return error_mark_node;
- if (TYPE_QUALS (return_type) != TYPE_UNQUALIFIED
- && in_decl != NULL_TREE
- && !TREE_NO_WARNING (in_decl)
- && (SCALAR_TYPE_P (return_type) || VOID_TYPE_P (return_type)))
- warning (OPT_Wignored_qualifiers,
- "type qualifiers ignored on function return type");
-
/* Construct a new type node and return it. */
if (TREE_CODE (t) == FUNCTION_TYPE)
fntype = build_function_type (return_type, arg_types);
This function is used for dealing with types, decls and the like;
for expressions, use tsubst_expr or tsubst_copy. */
-static tree
+tree
tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
tree type, r;
if (DECL_P (t))
return tsubst_decl (t, args, complain);
+ if (args == NULL_TREE)
+ return t;
+
if (TREE_CODE (t) == IDENTIFIER_NODE)
type = IDENTIFIER_TYPE_VALUE (t);
else
{
tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
- r = retrieve_specialization (tmpl, gen_args, false);
+ r = retrieve_specialization (tmpl, gen_args, 0);
}
else if (DECL_FUNCTION_SCOPE_P (decl)
&& DECL_TEMPLATE_INFO (DECL_CONTEXT (decl))
max = tsubst_expr (omax, args, complain, in_decl,
/*integral_constant_expression_p=*/false);
+
+ /* Fix up type of the magic NOP_EXPR with TREE_SIDE_EFFECTS if
+ needed. */
+ if (TREE_CODE (max) == NOP_EXPR
+ && TREE_SIDE_EFFECTS (omax)
+ && !TREE_TYPE (max))
+ TREE_TYPE (max) = TREE_TYPE (TREE_OPERAND (max, 0));
+
max = fold_decl_constant_value (max);
+ /* If we're in a partial instantiation, preserve the magic NOP_EXPR
+ with TREE_SIDE_EFFECTS that indicates this is not an integral
+ constant expression. */
+ if (processing_template_decl
+ && TREE_SIDE_EFFECTS (omax) && TREE_CODE (omax) == NOP_EXPR)
+ {
+ gcc_assert (TREE_CODE (max) == NOP_EXPR);
+ TREE_SIDE_EFFECTS (max) = 1;
+ }
+
if (TREE_CODE (max) != INTEGER_CST
&& !at_function_scope_p ()
+ && !TREE_SIDE_EFFECTS (max)
&& !value_dependent_expression_p (max))
{
if (complain & tf_error)
if (e1 == error_mark_node || e2 == error_mark_node)
return error_mark_node;
- return fold_build2 (TREE_CODE (t), TREE_TYPE (t), e1, e2);
+ return fold_build2_loc (input_location,
+ TREE_CODE (t), TREE_TYPE (t), e1, e2);
}
case NEGATE_EXPR:
if (e == error_mark_node)
return error_mark_node;
- return fold_build1 (TREE_CODE (t), TREE_TYPE (t), e);
+ return fold_build1_loc (input_location, TREE_CODE (t), TREE_TYPE (t), e);
}
case TYPENAME_TYPE:
But, such constructs have already been resolved by this
point, so here CTX really should have complete type, unless
it's a partial instantiation. */
- ctx = complete_type (ctx);
+ if (!(complain & tf_no_class_instantiations))
+ ctx = complete_type (ctx);
if (!COMPLETE_TYPE_P (ctx))
{
if (complain & tf_error)
{
tree type;
- type =
- finish_decltype_type (tsubst_expr
- (DECLTYPE_TYPE_EXPR (t), args,
- complain, in_decl,
- /*integral_constant_expression_p=*/false),
+ ++cp_unevaluated_operand;
+ ++c_inhibit_evaluation_warnings;
+
+ type = tsubst_expr (DECLTYPE_TYPE_EXPR (t), args,
+ complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+
+ --cp_unevaluated_operand;
+ --c_inhibit_evaluation_warnings;
+
+ type =
+ finish_decltype_type (type,
DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t));
return cp_build_qualified_type_real (type,
cp_type_quals (t)
expr = name;
if (dependent_type_p (scope))
- return build_qualified_name (/*type=*/NULL_TREE,
- scope, expr,
- QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
+ {
+ tree type = NULL_TREE;
+ if (DECL_P (expr) && !dependent_scope_p (scope))
+ type = TREE_TYPE (expr);
+ return build_qualified_name (type, scope, expr,
+ QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
+ }
if (!BASELINK_P (name) && !DECL_P (expr))
{
if (TREE_CODE (expr) == BIT_NOT_EXPR)
- /* If this were actually a destructor call, it would have been
- parsed as such by the parser. */
- expr = error_mark_node;
+ {
+ /* A BIT_NOT_EXPR is used to represent a destructor. */
+ if (!check_dtor_name (scope, TREE_OPERAND (expr, 0)))
+ {
+ error ("qualifying type %qT does not match destructor name ~%qT",
+ scope, TREE_OPERAND (expr, 0));
+ expr = error_mark_node;
+ }
+ else
+ expr = lookup_qualified_name (scope, complete_dtor_identifier,
+ /*is_type_p=*/0, false);
+ }
else
expr = lookup_qualified_name (scope, expr, /*is_type_p=*/0, false);
if (TREE_CODE (TREE_CODE (expr) == TEMPLATE_DECL
{
error ("dependent-name %qE is parsed as a non-type, but "
"instantiation yields a type", qualified_id);
- inform ("say %<typename %E%> if a type is meant", qualified_id);
+ inform (input_location, "say %<typename %E%> if a type is meant", qualified_id);
}
return error_mark_node;
}
if (complain & tf_error)
qualified_name_lookup_error (scope,
TREE_OPERAND (qualified_id, 1),
- expr);
+ expr, input_location);
return error_mark_node;
}
if (expr == error_mark_node && complain & tf_error)
qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1),
- expr);
+ expr, input_location);
else if (TYPE_P (scope))
{
expr = (adjust_result_of_qualified_name_lookup
enum tree_code code;
tree r;
- if (t == NULL_TREE || t == error_mark_node)
+ if (t == NULL_TREE || t == error_mark_node || args == NULL_TREE)
return t;
code = TREE_CODE (t);
{
case PARM_DECL:
r = retrieve_local_specialization (t);
- gcc_assert (r != NULL);
+
+ if (r == NULL)
+ {
+ tree c;
+ /* This can happen for a parameter name used later in a function
+ declaration (such as in a late-specified return type). Just
+ make a dummy decl, since it's only used for its type. */
+ gcc_assert (cp_unevaluated_operand != 0);
+ /* We copy T because want to tsubst the PARM_DECL only,
+ not the following PARM_DECLs that are chained to T. */
+ c = copy_node (t);
+ r = tsubst_decl (c, args, complain);
+ /* Give it the template pattern as its context; its true context
+ hasn't been instantiated yet and this is good enough for
+ mangling. */
+ DECL_CONTEXT (r) = DECL_CONTEXT (t);
+ }
+
if (TREE_CODE (r) == ARGUMENT_PACK_SELECT)
r = ARGUMENT_PACK_SELECT_ARG (r);
mark_used (r);
#define RECUR(NODE) \
tsubst_expr ((NODE), args, complain, in_decl, \
integral_constant_expression_p)
- tree decl, init, cond, incr;
+ tree decl, init, cond, incr, auto_node;
init = TREE_VEC_ELT (OMP_FOR_INIT (t), i);
gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
decl = RECUR (TREE_OPERAND (init, 0));
init = TREE_OPERAND (init, 1);
+ auto_node = type_uses_auto (TREE_TYPE (decl));
+ if (auto_node && init)
+ {
+ tree init_expr = init;
+ if (TREE_CODE (init_expr) == DECL_EXPR)
+ init_expr = DECL_INITIAL (DECL_EXPR_DECL (init_expr));
+ init_expr = RECUR (init_expr);
+ TREE_TYPE (decl)
+ = do_auto_deduction (TREE_TYPE (decl), init_expr, auto_node);
+ }
gcc_assert (!type_dependent_expression_p (decl));
if (!CLASS_TYPE_P (TREE_TYPE (decl)))
}
if (c == NULL)
{
- c = build_omp_clause (OMP_CLAUSE_PRIVATE);
+ c = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
OMP_CLAUSE_DECL (c) = decl;
c = finish_omp_clauses (c);
if (c)
/*is_type_p=*/false,
/*complain=*/false);
if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
- qualified_name_lookup_error (scope, name, decl);
+ qualified_name_lookup_error (scope, name, decl, input_location);
else
do_local_using_decl (decl, scope, name);
}
pack expansion where the parameter packs
used in that expansion were of length
zero. */
- init = build_default_init (TREE_TYPE (decl),
- NULL_TREE);
+ init = build_value_init (TREE_TYPE (decl));
else
init = t;
}
- finish_decl (decl, init, NULL_TREE);
+ cp_finish_decl (decl, init, false, NULL_TREE, 0);
}
}
}
break;
case CASE_LABEL_EXPR:
- finish_case_label (RECUR (CASE_LOW (t)),
+ finish_case_label (EXPR_LOCATION (t),
+ RECUR (CASE_LOW (t)),
RECUR (CASE_HIGH (t)));
break;
case LABEL_EXPR:
- finish_label_stmt (DECL_NAME (LABEL_EXPR_LABEL (t)));
+ {
+ tree decl = LABEL_EXPR_LABEL (t);
+ tree label;
+
+ label = finish_label_stmt (DECL_NAME (decl));
+ if (DECL_ATTRIBUTES (decl) != NULL_TREE)
+ cplus_decl_attributes (&label, DECL_ATTRIBUTES (decl), 0);
+ }
break;
case GOTO_EXPR:
/*done=*/true,
/*address_p=*/false,
/*template_arg_p=*/false,
- &error_msg);
+ &error_msg,
+ input_location);
if (error_msg)
error (error_msg);
if (!function_p && TREE_CODE (decl) == IDENTIFIER_NODE)
case TEMPLATE_ID_EXPR:
{
tree object;
- tree template = RECUR (TREE_OPERAND (t, 0));
+ tree templ = RECUR (TREE_OPERAND (t, 0));
tree targs = TREE_OPERAND (t, 1);
if (targs)
targs = tsubst_template_args (targs, args, complain, in_decl);
- if (TREE_CODE (template) == COMPONENT_REF)
+ if (TREE_CODE (templ) == COMPONENT_REF)
{
- object = TREE_OPERAND (template, 0);
- template = TREE_OPERAND (template, 1);
+ object = TREE_OPERAND (templ, 0);
+ templ = TREE_OPERAND (templ, 1);
}
else
object = NULL_TREE;
- template = lookup_template_function (template, targs);
+ templ = lookup_template_function (templ, targs);
if (object)
- return build3 (COMPONENT_REF, TREE_TYPE (template),
- object, template, NULL_TREE);
+ return build3 (COMPONENT_REF, TREE_TYPE (templ),
+ object, templ, NULL_TREE);
else
- return baselink_for_fns (template);
+ return baselink_for_fns (templ);
}
case INDIRECT_REF:
op1 = tsubst_non_call_postfix_expression (op1, args, complain,
in_decl);
if (TREE_CODE (op1) == LABEL_DECL)
- return finish_label_address_expr (DECL_NAME (op1));
+ return finish_label_address_expr (DECL_NAME (op1),
+ EXPR_LOCATION (op1));
return build_x_unary_op (ADDR_EXPR, op1, complain);
case PLUS_EXPR:
case ARRAY_REF:
op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
args, complain, in_decl);
- return build_x_binary_op (ARRAY_REF, op1,
- (TREE_NO_WARNING (TREE_OPERAND (t, 0))
- ? ERROR_MARK
- : TREE_CODE (TREE_OPERAND (t, 0))),
- RECUR (TREE_OPERAND (t, 1)),
- (TREE_NO_WARNING (TREE_OPERAND (t, 1))
- ? ERROR_MARK
- : TREE_CODE (TREE_OPERAND (t, 1))),
- /*overloaded_p=*/NULL,
- complain);
+ return build_x_array_ref (op1, RECUR (TREE_OPERAND (t, 1)), complain);
case SIZEOF_EXPR:
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
}
else
{
- ++skip_evaluation;
+ ++cp_unevaluated_operand;
+ ++c_inhibit_evaluation_warnings;
op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
/*function_p=*/false,
/*integral_constant_expression_p=*/false);
- --skip_evaluation;
+ --cp_unevaluated_operand;
+ --c_inhibit_evaluation_warnings;
}
if (TYPE_P (op1))
return cxx_sizeof_or_alignof_type (op1, TREE_CODE (t),
case NEW_EXPR:
{
+ tree placement = RECUR (TREE_OPERAND (t, 0));
tree init = RECUR (TREE_OPERAND (t, 3));
+ VEC(tree,gc) *placement_vec;
+ VEC(tree,gc) *init_vec;
+ tree ret;
- if (TREE_OPERAND (t, 3) && !init)
- /* If there was an initializer in the the original tree, but
- it instantiated to an empty list, then we should pass on
- VOID_ZERO_NODE to tell build_new that it was an empty
- initializer () rather than no initializer. This can only
- happen when the initializer is a pack expansion whose
- parameter packs are of length zero. */
- init = void_zero_node;
+ if (placement == NULL_TREE)
+ placement_vec = NULL;
+ else
+ {
+ placement_vec = make_tree_vector ();
+ for (; placement != NULL_TREE; placement = TREE_CHAIN (placement))
+ VEC_safe_push (tree, gc, placement_vec, TREE_VALUE (placement));
+ }
- return build_new
- (RECUR (TREE_OPERAND (t, 0)),
- RECUR (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2)),
- init,
- NEW_EXPR_USE_GLOBAL (t),
- complain);
+ /* If there was an initializer in the original tree, but it
+ instantiated to an empty list, then we should pass a
+ non-NULL empty vector to tell build_new that it was an
+ empty initializer() rather than no initializer. This can
+ only happen when the initializer is a pack expansion whose
+ parameter packs are of length zero. */
+ if (init == NULL_TREE && TREE_OPERAND (t, 3) == NULL_TREE)
+ init_vec = NULL;
+ else
+ {
+ init_vec = make_tree_vector ();
+ if (init == void_zero_node)
+ gcc_assert (init_vec != NULL);
+ else
+ {
+ for (; init != NULL_TREE; init = TREE_CHAIN (init))
+ VEC_safe_push (tree, gc, init_vec, TREE_VALUE (init));
+ }
+ }
+
+ ret = build_new (&placement_vec,
+ RECUR (TREE_OPERAND (t, 1)),
+ RECUR (TREE_OPERAND (t, 2)),
+ &init_vec,
+ NEW_EXPR_USE_GLOBAL (t),
+ complain);
+
+ if (placement_vec != NULL)
+ release_tree_vector (placement_vec);
+ if (init_vec != NULL)
+ release_tree_vector (init_vec);
+
+ return ret;
}
case DELETE_EXPR:
case CALL_EXPR:
{
tree function;
- tree call_args;
+ VEC(tree,gc) *call_args;
+ unsigned int nargs, i;
bool qualified_p;
bool koenig_p;
+ tree ret;
function = CALL_EXPR_FN (t);
/* When we parsed the expression, we determined whether or
qualified_p = true;
}
- /* FIXME: Rewrite this so as not to construct an arglist. */
- call_args = RECUR (CALL_EXPR_ARGS (t));
+ nargs = call_expr_nargs (t);
+ call_args = make_tree_vector ();
+ for (i = 0; i < nargs; ++i)
+ {
+ tree arg = CALL_EXPR_ARG (t, i);
+
+ if (!PACK_EXPANSION_P (arg))
+ VEC_safe_push (tree, gc, call_args,
+ RECUR (CALL_EXPR_ARG (t, i)));
+ else
+ {
+ /* Expand the pack expansion and push each entry onto
+ CALL_ARGS. */
+ arg = tsubst_pack_expansion (arg, args, complain, in_decl);
+ if (TREE_CODE (arg) == TREE_VEC)
+ {
+ unsigned int len, j;
+
+ len = TREE_VEC_LENGTH (arg);
+ for (j = 0; j < len; ++j)
+ {
+ tree value = TREE_VEC_ELT (arg, j);
+ if (value != NULL_TREE)
+ value = convert_from_reference (value);
+ VEC_safe_push (tree, gc, call_args, value);
+ }
+ }
+ else
+ {
+ /* A partial substitution. Add one entry. */
+ VEC_safe_push (tree, gc, call_args, arg);
+ }
+ }
+ }
/* We do not perform argument-dependent lookup if normal
lookup finds a non-function, in accordance with the
not appropriate, even if an unqualified-name was used
to denote the function. */
&& !DECL_FUNCTION_MEMBER_P (get_first_fn (function)))
- || TREE_CODE (function) == IDENTIFIER_NODE))
+ || TREE_CODE (function) == IDENTIFIER_NODE)
+ /* Only do this when substitution turns a dependent call
+ into a non-dependent call. */
+ && type_dependent_expression_p_push (t)
+ && !any_type_dependent_arguments_p (call_args))
function = perform_koenig_lookup (function, call_args);
if (TREE_CODE (function) == IDENTIFIER_NODE)
{
unqualified_name_lookup_error (function);
+ release_tree_vector (call_args);
return error_mark_node;
}
mark_used (function);
if (TREE_CODE (function) == OFFSET_REF)
- return build_offset_ref_call_from_tree (function, call_args);
- if (TREE_CODE (function) == COMPONENT_REF)
+ ret = build_offset_ref_call_from_tree (function, &call_args);
+ else if (TREE_CODE (function) == COMPONENT_REF)
{
if (!BASELINK_P (TREE_OPERAND (function, 1)))
- return finish_call_expr (function, call_args,
+ ret = finish_call_expr (function, &call_args,
/*disallow_virtual=*/false,
/*koenig_p=*/false,
complain);
else
- return (build_new_method_call
+ ret = (build_new_method_call
(TREE_OPERAND (function, 0),
TREE_OPERAND (function, 1),
- call_args, NULL_TREE,
+ &call_args, NULL_TREE,
qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL,
/*fn_p=*/NULL,
complain));
}
- return finish_call_expr (function, call_args,
- /*disallow_virtual=*/qualified_p,
- koenig_p,
- complain);
+ else
+ ret = finish_call_expr (function, &call_args,
+ /*disallow_virtual=*/qualified_p,
+ koenig_p,
+ complain);
+
+ release_tree_vector (call_args);
+
+ return ret;
}
case COND_EXPR:
}
else
{
- qualified_name_lookup_error (object_type, tmpl, member);
+ qualified_name_lookup_error (object_type, tmpl, member,
+ input_location);
return error_mark_node;
}
}
bool process_index_p;
int newlen;
bool need_copy_p = false;
+ tree r;
if (type == error_mark_node)
return error_mark_node;
}
}
+ r = build_constructor (init_list_type_node, n);
+ CONSTRUCTOR_IS_DIRECT_INIT (r) = CONSTRUCTOR_IS_DIRECT_INIT (t);
+
if (TREE_HAS_CONSTRUCTOR (t))
- return finish_compound_literal (type, n);
+ return finish_compound_literal (type, r);
- return build_constructor (NULL_TREE, n);
+ return r;
}
case TYPEID_EXPR:
}
/* Verify that the instantiated ARGS are valid. For type arguments,
- make sure that the type's linkage is ok. For non-type arguments,
+ make sure that the type is not variably modified. For non-type arguments,
make sure they are constants if they are integral or enumerations.
Emit an error under control of COMPLAIN, and return TRUE on error. */
static bool
+check_instantiated_arg (tree tmpl, tree t, tsubst_flags_t complain)
+{
+ if (ARGUMENT_PACK_P (t))
+ {
+ tree vec = ARGUMENT_PACK_ARGS (t);
+ int len = TREE_VEC_LENGTH (vec);
+ bool result = false;
+ int i;
+
+ for (i = 0; i < len; ++i)
+ if (check_instantiated_arg (tmpl, TREE_VEC_ELT (vec, i), complain))
+ result = true;
+ return result;
+ }
+ else if (TYPE_P (t))
+ {
+ if (variably_modified_type_p (t, NULL_TREE))
+ {
+ if (complain & tf_error)
+ error ("%qT is a variably modified type", t);
+ return true;
+ }
+ }
+ /* A non-type argument of integral or enumerated type must be a
+ constant. */
+ else if (TREE_TYPE (t)
+ && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t))
+ && !TREE_CONSTANT (t))
+ {
+ if (complain & tf_error)
+ error ("integral expression %qE is not constant", t);
+ return true;
+ }
+ return false;
+}
+
+static bool
check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain)
{
int ix, len = DECL_NTPARMS (tmpl);
for (ix = 0; ix != len; ix++)
{
- tree t = TREE_VEC_ELT (args, ix);
-
- if (TYPE_P (t))
- {
- /* [basic.link]: A name with no linkage (notably, the name
- of a class or enumeration declared in a local scope)
- shall not be used to declare an entity with linkage.
- This implies that names with no linkage cannot be used as
- template arguments. */
- tree nt = no_linkage_check (t, /*relaxed_p=*/false);
-
- if (nt)
- {
- /* DR 488 makes use of a type with no linkage cause
- type deduction to fail. */
- if (complain & tf_error)
- {
- if (TYPE_ANONYMOUS_P (nt))
- error ("%qT is/uses anonymous type", t);
- else
- error ("template argument for %qD uses local type %qT",
- tmpl, t);
- }
- result = true;
- }
- /* In order to avoid all sorts of complications, we do not
- allow variably-modified types as template arguments. */
- else if (variably_modified_type_p (t, NULL_TREE))
- {
- if (complain & tf_error)
- error ("%qT is a variably modified type", t);
- result = true;
- }
- }
- /* A non-type argument of integral or enumerated type must be a
- constant. */
- else if (TREE_TYPE (t)
- && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t))
- && !TREE_CONSTANT (t))
- {
- if (complain & tf_error)
- error ("integral expression %qE is not constant", t);
- result = true;
- }
+ if (check_instantiated_arg (tmpl, TREE_VEC_ELT (args, ix), complain))
+ result = true;
}
if (result && (complain & tf_error))
error (" trying to instantiate %qD", tmpl);
the template arguments in TARG_PTR. */
tree
-instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
+instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain)
{
+ tree targ_ptr = orig_args;
tree fndecl;
tree gen_tmpl;
tree spec;
tree spec;
tree clone;
- spec = instantiate_template (DECL_CLONED_FUNCTION (tmpl), targ_ptr,
- complain);
+ /* Use DECL_ABSTRACT_ORIGIN because only FUNCTION_DECLs have
+ DECL_CLONED_FUNCTION. */
+ spec = instantiate_template (DECL_ABSTRACT_ORIGIN (tmpl),
+ targ_ptr, complain);
if (spec == error_mark_node)
return error_mark_node;
}
/* Check to see if we already have this specialization. */
- spec = retrieve_specialization (tmpl, targ_ptr,
- /*class_specializations_p=*/false);
- if (spec != NULL_TREE)
- return spec;
-
gen_tmpl = most_general_template (tmpl);
if (tmpl != gen_tmpl)
- {
- /* The TMPL is a partial instantiation. To get a full set of
- arguments we must add the arguments used to perform the
- partial instantiation. */
- targ_ptr = add_outermost_template_args (DECL_TI_ARGS (tmpl),
- targ_ptr);
+ /* The TMPL is a partial instantiation. To get a full set of
+ arguments we must add the arguments used to perform the
+ partial instantiation. */
+ targ_ptr = add_outermost_template_args (DECL_TI_ARGS (tmpl),
+ targ_ptr);
- /* Check to see if we already have this specialization. */
- spec = retrieve_specialization (gen_tmpl, targ_ptr,
- /*class_specializations_p=*/false);
- if (spec != NULL_TREE)
- return spec;
- }
+ /* It would be nice to avoid hashing here and then again in tsubst_decl,
+ but it doesn't seem to be on the hot path. */
+ spec = retrieve_specialization (gen_tmpl, targ_ptr, 0);
+
+ gcc_assert (tmpl == gen_tmpl
+ || ((fndecl = retrieve_specialization (tmpl, orig_args, 0))
+ == spec)
+ || fndecl == NULL_TREE);
+
+ if (spec != NULL_TREE)
+ return spec;
if (check_instantiated_args (gen_tmpl, INNERMOST_TEMPLATE_ARGS (targ_ptr),
complain))
/* Now we know the specialization, compute access previously
deferred. */
push_access_scope (fndecl);
+
+ /* Some typedefs referenced from within the template code need to be access
+ checked at template instantiation time, i.e now. These types were
+ added to the template at parsing time. Let's get those and perfom
+ the acces checks then. */
+ perform_typedefs_access_check (DECL_TEMPLATE_RESULT (tmpl), targ_ptr);
perform_deferred_access_checks ();
pop_access_scope (fndecl);
pop_deferring_access_checks ();
return fndecl;
}
-/* 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.
+/* The FN is a TEMPLATE_DECL for a function. ARGS is an array with
+ NARGS elements of the arguments that are being used when calling
+ it. TARGS is a vector into which the deduced template arguments
+ are placed.
Return zero for success, 2 for an incomplete match that doesn't resolve
all the types, and 1 for complete failure. An error message will be
fn_type_unification (tree fn,
tree explicit_targs,
tree targs,
- tree args,
+ const tree *args,
+ unsigned int nargs,
tree return_type,
unification_kind_t strict,
int flags)
if (return_type)
{
+ tree *new_args;
+
parms = tree_cons (NULL_TREE, TREE_TYPE (fntype), parms);
- args = tree_cons (NULL_TREE, return_type, args);
+ new_args = XALLOCAVEC (tree, nargs + 1);
+ new_args[0] = return_type;
+ memcpy (new_args + 1, args, nargs * sizeof (tree));
+ args = new_args;
+ ++nargs;
}
/* We allow incomplete unification without an error message here
callers must be ready to deal with unification failures in any
event. */
result = type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
- targs, parms, args, /*subr=*/0,
+ targs, parms, args, nargs, /*subr=*/0,
strict, flags);
if (result == 0 && incomplete_argument_packs_p)
the corresponding deduced argument values. If the
substitution results in an invalid type, as described above,
type deduction fails. */
- if (tsubst (TREE_TYPE (fn), targs, tf_none, NULL_TREE)
- == error_mark_node)
- return 1;
+ {
+ tree substed = tsubst (TREE_TYPE (fn), targs, tf_none, NULL_TREE);
+ if (substed == error_mark_node)
+ return 1;
+
+ /* If we're looking for an exact match, check that what we got
+ is indeed an exact match. It might not be if some template
+ parameters are used in non-deduced contexts. */
+ if (strict == DEDUCE_EXACT)
+ {
+ unsigned int i;
+
+ tree sarg
+ = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (substed));
+ if (return_type)
+ sarg = tree_cons (NULL_TREE, TREE_TYPE (substed), sarg);
+ for (i = 0; i < nargs && sarg; ++i, sarg = TREE_CHAIN (sarg))
+ if (!same_type_p (args[i], TREE_VALUE (sarg)))
+ return 1;
+ }
+ }
return result;
}
type_unification_real (tree tparms,
tree targs,
tree xparms,
- tree xargs,
+ const tree *xargs,
+ unsigned int xnargs,
int subr,
unification_kind_t strict,
int flags)
int ntparms = TREE_VEC_LENGTH (tparms);
int sub_strict;
int saw_undeduced = 0;
- tree parms, args;
+ tree parms;
+ const tree *args;
+ unsigned int nargs;
+ unsigned int ia;
gcc_assert (TREE_CODE (tparms) == TREE_VEC);
gcc_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST);
- gcc_assert (!xargs || TREE_CODE (xargs) == TREE_LIST);
gcc_assert (ntparms > 0);
switch (strict)
again:
parms = xparms;
args = xargs;
+ nargs = xnargs;
+ ia = 0;
while (parms && parms != void_list_node
- && args && args != void_list_node)
+ && ia < nargs)
{
if (TREE_CODE (TREE_VALUE (parms)) == TYPE_PACK_EXPANSION)
break;
parm = TREE_VALUE (parms);
parms = TREE_CHAIN (parms);
- arg = TREE_VALUE (args);
- args = TREE_CHAIN (args);
+ arg = args[ia];
+ ++ia;
arg_expr = NULL;
if (arg == error_mark_node)
arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg,
arg_expr);
+ if (arg == init_list_type_node && arg_expr)
+ arg = arg_expr;
if (unify (tparms, targs, parm, arg, arg_strict))
return 1;
}
/* Unify the remaining arguments with the pack expansion type. */
tree argvec;
tree parmvec = make_tree_vec (1);
- int len = 0;
- tree t;
- /* Count the number of arguments that remain. */
- for (t = args; t && t != void_list_node; t = TREE_CHAIN (t))
- len++;
-
/* Allocate a TREE_VEC and copy in all of the arguments */
- argvec = make_tree_vec (len);
- for (i = 0; args && args != void_list_node; args = TREE_CHAIN (args))
- {
- TREE_VEC_ELT (argvec, i) = TREE_VALUE (args);
- ++i;
- }
+ argvec = make_tree_vec (nargs - ia);
+ for (i = 0; ia < nargs; ++ia, ++i)
+ TREE_VEC_ELT (argvec, i) = args[ia];
/* Copy the parameter into parmvec. */
TREE_VEC_ELT (parmvec, 0) = TREE_VALUE (parms);
/* Fail if we've reached the end of the parm list, and more args
are present, and the parm list isn't variadic. */
- if (args && args != void_list_node && parms == void_list_node)
+ if (ia < nargs && parms == void_list_node)
return 1;
/* Fail if parms are left and they don't have default values. */
if (parms && parms != void_list_node
to explicitly check cxx_dialect here. */
if (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)))
{
- tree arg = tsubst (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)),
- targs, tf_none, NULL_TREE);
+ tree arg = tsubst_template_arg
+ (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)),
+ targs, tf_none, NULL_TREE);
if (arg == error_mark_node)
return 1;
else
{
tree tempargs = copy_node (targs);
int good = 0;
+ tree goodfn = NULL_TREE;
bool addr_p;
if (TREE_CODE (arg) == ADDR_EXPR)
if (subargs)
{
elem = tsubst (TREE_TYPE (fn), subargs, tf_none, NULL_TREE);
- good += try_one_overload (tparms, targs, tempargs, parm,
- elem, strict, sub_strict, addr_p);
+ if (try_one_overload (tparms, targs, tempargs, parm,
+ elem, strict, sub_strict, addr_p)
+ && (!goodfn || !decls_match (goodfn, elem)))
+ {
+ goodfn = elem;
+ ++good;
+ }
}
--processing_template_decl;
}
return false;
else
for (; arg; arg = OVL_NEXT (arg))
- good += try_one_overload (tparms, targs, tempargs, parm,
- TREE_TYPE (OVL_CURRENT (arg)),
- strict, sub_strict, addr_p);
+ if (try_one_overload (tparms, targs, tempargs, parm,
+ TREE_TYPE (OVL_CURRENT (arg)),
+ strict, sub_strict, addr_p)
+ && (!goodfn || !decls_match (goodfn, OVL_CURRENT (arg))))
+ {
+ goodfn = OVL_CURRENT (arg);
+ ++good;
+ }
/* [temp.deduct.type] A template-argument can be deduced from a pointer
to function or pointer to member function argument if the set of
match. */
if (resolve_overloaded_unification
- (tparms, targs, parm, arg, strict, sub_strict)
+ (tparms, targs, parm, arg,
+ (unification_kind_t) strict,
+ sub_strict)
!= 0)
return 1;
skip_arg_p = true;
if (!subr)
arg_strict |=
- maybe_adjust_types_for_deduction (strict, &parm, &arg,
- arg_expr);
+ maybe_adjust_types_for_deduction ((unification_kind_t) strict,
+ &parm, &arg, arg_expr);
}
if (!skip_arg_p)
if (arg == error_mark_node)
return 1;
- if (arg == unknown_type_node)
+ if (arg == unknown_type_node
+ || arg == init_list_type_node)
/* We can't deduce anything from this, but we might get all the
template args from other function args. */
return 0;
if (arg == parm && !uses_template_parms (parm))
return 0;
+ /* Handle init lists early, so the rest of the function can assume
+ we're dealing with a type. */
+ if (BRACE_ENCLOSED_INITIALIZER_P (arg))
+ {
+ tree elt, elttype;
+ unsigned i;
+
+ if (!is_std_init_list (parm))
+ /* We can only deduce from an initializer list argument if the
+ parameter is std::initializer_list; otherwise this is a
+ non-deduced context. */
+ return 0;
+
+ elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (parm), 0);
+
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
+ {
+ int elt_strict = strict;
+ if (!BRACE_ENCLOSED_INITIALIZER_P (elt))
+ {
+ tree type = TREE_TYPE (elt);
+ /* It should only be possible to get here for a call. */
+ gcc_assert (elt_strict & UNIFY_ALLOW_OUTER_LEVEL);
+ elt_strict |= maybe_adjust_types_for_deduction
+ (DEDUCE_CALL, &elttype, &type, elt);
+ elt = type;
+ }
+
+ if (unify (tparms, targs, elttype, elt, elt_strict))
+ return 1;
+ }
+ return 0;
+ }
+
/* Immediately reject some pairs that won't unify because of
cv-qualification mismatches. */
if (TREE_CODE (arg) == TREE_CODE (parm)
ISO C++, so we can do as we please here. */
if (variably_modified_type_p (arg, NULL_TREE))
return 1;
+
+ /* Strip typedefs as in convert_template_argument. */
+ arg = strip_typedefs (arg);
}
/* If ARG is a parameter pack or an expansion, we cannot unify
&& !template_parameter_pack_p (parm))
return 1;
+ /* If the argument deduction results is a METHOD_TYPE,
+ then there is a problem.
+ METHOD_TYPE doesn't map to any real C++ type the result of
+ the deduction can not be of that type. */
+ if (TREE_CODE (arg) == METHOD_TYPE)
+ return 1;
+
TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
return 0;
/* Convert the ARG to the type of PARM; the deduced non-type
template argument must exactly match the types of the
corresponding parameter. */
- arg = fold (build_nop (TREE_TYPE (parm), arg));
+ arg = fold (build_nop (tparm, arg));
else if (uses_template_parms (tparm))
/* We haven't deduced the type of this parameter yet. Try again
later. */
/* If only one of the bounds used a MINUS_EXPR, compensate
by adding one to the other bound. */
if (parm_cst && !arg_cst)
- parm_max = fold_build2 (PLUS_EXPR,
+ parm_max = fold_build2_loc (input_location, PLUS_EXPR,
integer_type_node,
parm_max,
integer_one_node);
else if (arg_cst && !parm_cst)
- arg_max = fold_build2 (PLUS_EXPR,
+ arg_max = fold_build2_loc (input_location, PLUS_EXPR,
integer_type_node,
arg_max,
integer_one_node);
case METHOD_TYPE:
case FUNCTION_TYPE:
- if (TREE_CODE (arg) != TREE_CODE (parm))
- return 1;
+ {
+ unsigned int nargs;
+ tree *args;
+ tree a;
+ unsigned int i;
- /* CV qualifications for methods can never be deduced, they must
- match exactly. We need to check them explicitly here,
- because type_unification_real treats them as any other
- cvqualified parameter. */
- if (TREE_CODE (parm) == METHOD_TYPE
- && (!check_cv_quals_for_unify
- (UNIFY_ALLOW_NONE,
- TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (arg))),
- TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (parm))))))
- return 1;
+ if (TREE_CODE (arg) != TREE_CODE (parm))
+ return 1;
- if (unify (tparms, targs, TREE_TYPE (parm),
- TREE_TYPE (arg), UNIFY_ALLOW_NONE))
- return 1;
- return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
- TYPE_ARG_TYPES (arg), 1, DEDUCE_EXACT,
- LOOKUP_NORMAL);
+ /* CV qualifications for methods can never be deduced, they must
+ match exactly. We need to check them explicitly here,
+ because type_unification_real treats them as any other
+ cv-qualified parameter. */
+ if (TREE_CODE (parm) == METHOD_TYPE
+ && (!check_cv_quals_for_unify
+ (UNIFY_ALLOW_NONE,
+ TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (arg))),
+ TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (parm))))))
+ return 1;
+
+ if (unify (tparms, targs, TREE_TYPE (parm),
+ TREE_TYPE (arg), UNIFY_ALLOW_NONE))
+ return 1;
+
+ nargs = list_length (TYPE_ARG_TYPES (arg));
+ args = XALLOCAVEC (tree, nargs);
+ for (a = TYPE_ARG_TYPES (arg), i = 0;
+ a != NULL_TREE && a != void_list_node;
+ a = TREE_CHAIN (a), ++i)
+ args[i] = TREE_VALUE (a);
+ nargs = i;
+
+ return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
+ args, nargs, 1, DEDUCE_EXACT,
+ LOOKUP_NORMAL);
+ }
case OFFSET_TYPE:
/* Unify a pointer to member with a pointer to member function, which
tree targs = make_tree_vec (ntparms);
tree decl_type;
tree decl_arg_types;
+ tree *args;
+ unsigned int nargs, ix;
+ tree arg;
/* Substitute the explicit template arguments into the type of DECL.
The call to fn_type_unification will handle substitution into the
decl_arg_types = skip_artificial_parms_for (decl,
TYPE_ARG_TYPES (decl_type));
+ nargs = list_length (decl_arg_types);
+ args = XALLOCAVEC (tree, nargs);
+ for (arg = decl_arg_types, ix = 0;
+ arg != NULL_TREE && arg != void_list_node;
+ arg = TREE_CHAIN (arg), ++ix)
+ args[ix] = TREE_VALUE (arg);
+
if (fn_type_unification (fn, explicit_args, targs,
- decl_arg_types,
+ args, ix,
(check_rettype || DECL_CONV_FN_P (fn)
? TREE_TYPE (decl_type) : NULL_TREE),
DEDUCE_EXACT, LOOKUP_NORMAL))
/* Return the innermost template arguments that, when applied to a
template specialization whose innermost template parameters are
- TPARMS, and whose specialization arguments are PARMS, yield the
+ TPARMS, and whose specialization arguments are SPEC_ARGS, yield the
ARGS.
For example, suppose we have:
the first instantiation was `extern' and the second is not,
and EXTERN_P for the opposite case. */
if (DECL_NOT_REALLY_EXTERN (result) && !extern_p)
- pedwarn ("duplicate explicit instantiation of %q#D", result);
+ permerror (input_location, "duplicate explicit instantiation of %q#D", result);
/* If an "extern" explicit instantiation follows an ordinary
explicit instantiation, the template is instantiated. */
if (extern_p)
}
else if (!DECL_TEMPLATE_INFO (result))
{
- pedwarn ("explicit instantiation of non-template %q#D", result);
+ permerror (input_location, "explicit instantiation of non-template %q#D", result);
return;
}
;
else if (storage == ridpointers[(int) RID_EXTERN])
{
- if (pedantic && !in_system_header)
- pedwarn ("ISO C++ forbids the use of %<extern%> on explicit "
+ if (!in_system_header && (cxx_dialect == cxx98))
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C++ 1998 forbids the use of %<extern%> on explicit "
"instantiations");
extern_p = 1;
}
if (storage != NULL_TREE)
{
- if (pedantic && !in_system_header)
- pedwarn("ISO C++ forbids the use of %qE on explicit instantiations",
- storage);
+ if (!in_system_header)
+ {
+ if (storage == ridpointers[(int) RID_EXTERN])
+ {
+ if (cxx_dialect == cxx98)
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C++ 1998 forbids the use of %<extern%> on "
+ "explicit instantiations");
+ }
+ else
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C++ forbids the use of %qE"
+ " on explicit instantiations", storage);
+ }
if (storage == ridpointers[(int) RID_INLINE])
nomem_p = 1;
if (!previous_instantiation_extern_p && !extern_p
&& (complain & tf_error))
- pedwarn ("duplicate explicit instantiation of %q#T", t);
+ permerror (input_location, "duplicate explicit instantiation of %q#T", t);
/* If we've already instantiated the template, just return now. */
if (!CLASSTYPE_INTERFACE_ONLY (t))
if (DECL_DECLARED_INLINE_P (code_pattern)
&& !DECL_DECLARED_INLINE_P (decl))
DECL_DECLARED_INLINE_P (decl) = 1;
- if (DECL_INLINE (code_pattern) && !DECL_INLINE (decl))
- DECL_INLINE (decl) = 1;
}
else if (TREE_CODE (decl) == VAR_DECL)
DECL_INITIAL (decl) =
bool pattern_defined;
int need_push;
location_t saved_loc = input_location;
- int saved_in_system_header = in_system_header;
bool external_p;
/* This function should only be used to instantiate templates for
if (TREE_CODE (d) == FUNCTION_DECL && DECL_CLONED_FUNCTION_P (d))
d = DECL_CLONED_FUNCTION (d);
- if (DECL_TEMPLATE_INSTANTIATED (d))
- /* D has already been instantiated. It might seem reasonable to
- check whether or not D is an explicit instantiation, and, if so,
- stop here. But when an explicit instantiation is deferred
- until the end of the compilation, DECL_EXPLICIT_INSTANTIATION
- is set, even though we still need to do the instantiation. */
+ if (DECL_TEMPLATE_INSTANTIATED (d)
+ || DECL_TEMPLATE_SPECIALIZATION (d))
+ /* D has already been instantiated or explicitly specialized, so
+ there's nothing for us to do here.
+
+ It might seem reasonable to check whether or not D is an explicit
+ instantiation, and, if so, stop here. But when an explicit
+ instantiation is deferred until the end of the compilation,
+ DECL_EXPLICIT_INSTANTIATION is set, even though we still need to do
+ the instantiation. */
return d;
- /* If we already have a specialization of this declaration, then
- there's no reason to instantiate it. Note that
- retrieve_specialization gives us both instantiations and
- specializations, so we must explicitly check
- DECL_TEMPLATE_SPECIALIZATION. */
gen_tmpl = most_general_template (tmpl);
gen_args = DECL_TI_ARGS (d);
- spec = retrieve_specialization (gen_tmpl, gen_args,
- /*class_specializations_p=*/false);
- if (spec != NULL_TREE && DECL_TEMPLATE_SPECIALIZATION (spec))
- return spec;
+
+ if (tmpl != gen_tmpl)
+ /* We should already have the extra args. */
+ gcc_assert (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (gen_tmpl))
+ == TMPL_ARGS_DEPTH (gen_args));
+ /* And what's in the hash table should match D. */
+ gcc_assert ((spec = retrieve_specialization (gen_tmpl, gen_args, 0)) == d
+ || spec == NULL_TREE);
/* This needs to happen before any tsubsting. */
if (! push_tinst_level (d))
mark_definable (d);
input_location = DECL_SOURCE_LOCATION (d);
- in_system_header = DECL_IN_SYSTEM_HEADER (d);
/* If D is a member of an explicitly instantiated class template,
and no definition is available, treat it like an implicit
/* In general, we do not instantiate such templates... */
if (external_p
/* ... but we instantiate inline functions so that we can inline
- them and ... */
- && ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d))
+ them. An explicit instantiation declaration prohibits implicit
+ instantiation of non-inline functions. With high levels of
+ optimization, we would normally inline non-inline functions
+ -- but we're not allowed to do that for "extern template" functions.
+ Therefore, we check DECL_DECLARED_INLINE_P, rather than
+ possibly_inlined_p. And ... */
+ && ! (TREE_CODE (d) == FUNCTION_DECL
+ && DECL_DECLARED_INLINE_P (d))
/* ... we instantiate static data members whose values are
needed in integral constant expressions. */
&& ! (TREE_CODE (d) == VAR_DECL
input_location = saved_loc;
if (at_eof && !pattern_defined
- && DECL_EXPLICIT_INSTANTIATION (d))
+ && DECL_EXPLICIT_INSTANTIATION (d)
+ && DECL_NOT_REALLY_EXTERN (d))
/* [temp.explicit]
The definition of a non-exported function template, a
member function or static data member of a class template
shall be present in every translation unit in which it is
explicitly instantiated. */
- pedwarn
- ("explicit instantiation of %qD but no definition available", d);
+ permerror (input_location, "explicit instantiation of %qD "
+ "but no definition available", d);
/* ??? Historically, we have instantiated inline functions, even
when marked as "extern template". */
/* Instantiate inline functions so that the inliner can do its
job, even though we'll not be emitting a copy of this
function. */
- if (!(TREE_CODE (d) == FUNCTION_DECL
- && flag_inline_trees
- && DECL_DECLARED_INLINE_P (d)))
+ if (!(TREE_CODE (d) == FUNCTION_DECL && possibly_inlined_p (d)))
goto out;
}
/* The initializer is placed in DECL_INITIAL by
regenerate_decl_from_template. Pull it out so that
- finish_decl can process it. */
+ cp_finish_decl can process it. */
init = DECL_INITIAL (d);
DECL_INITIAL (d) = NULL_TREE;
DECL_INITIALIZED_P (d) = 0;
/* Enter the scope of D so that access-checking works correctly. */
push_nested_class (DECL_CONTEXT (d));
- finish_decl (d, init, NULL_TREE);
+ cp_finish_decl (d, init, false, NULL_TREE, 0);
pop_nested_class ();
}
else if (TREE_CODE (d) == FUNCTION_DECL)
}
if (tmpl_parm && FUNCTION_PARAMETER_PACK_P (tmpl_parm))
{
- /* Collect all of the extra "packed" parameters into an
- argument pack. */
- tree parmvec;
- tree parmtypevec;
- tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
- tree argtypepack = make_node (TYPE_ARGUMENT_PACK);
- int i, len = 0;
- tree t;
-
- /* Count how many parameters remain. */
- for (t = spec_parm; t; t = TREE_CHAIN (t))
- len++;
-
- /* Fill in PARMVEC and PARMTYPEVEC with all of the parameters. */
- parmvec = make_tree_vec (len);
- parmtypevec = make_tree_vec (len);
- for(i = 0; i < len; i++, spec_parm = TREE_CHAIN (spec_parm))
- {
- TREE_VEC_ELT (parmvec, i) = spec_parm;
- TREE_VEC_ELT (parmtypevec, i) = TREE_TYPE (spec_parm);
- }
-
- /* Build the argument packs. */
- SET_ARGUMENT_PACK_ARGS (argpack, parmvec);
- SET_ARGUMENT_PACK_ARGS (argtypepack, parmtypevec);
- TREE_TYPE (argpack) = argtypepack;
-
/* Register the (value) argument pack as a specialization of
TMPL_PARM, then move on. */
+ tree argpack = make_fnparm_pack (spec_parm);
register_local_specialization (argpack, tmpl_parm);
tmpl_parm = TREE_CHAIN (tmpl_parm);
+ spec_parm = NULL_TREE;
}
gcc_assert (!spec_parm);
out:
input_location = saved_loc;
- in_system_header = saved_in_system_header;
pop_deferring_access_checks ();
pop_tinst_level ();
{
int reconsider;
location_t saved_loc = input_location;
- int saved_in_system_header = in_system_header;
/* Instantiating templates may trigger vtable generation. This in turn
may require further template instantiations. We place a limit here
while (reconsider);
input_location = saved_loc;
- in_system_header = saved_in_system_header;
}
/* Substitute ARGVEC into T, which is a list of initializers for
static int
invalid_nontype_parm_type_p (tree type, tsubst_flags_t complain)
{
- if (INTEGRAL_TYPE_P (type))
+ if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
return 0;
else if (POINTER_TYPE_P (type))
return 0;
&& !TREE_CONSTANT (TYPE_MAX_VALUE (type)))
{
/* If this is the TYPE_DOMAIN of an array type, consider it
- dependent. */
- return (value_dependent_expression_p (TYPE_MAX_VALUE (type))
- || type_dependent_expression_p (TYPE_MAX_VALUE (type)));
+ dependent. We already checked for value-dependence in
+ compute_array_index_type. */
+ return type_dependent_expression_p (TYPE_MAX_VALUE (type));
}
/* -- a template-id in which either the template name is a template
/* If we are not processing a template, then nobody should be
providing us with a dependent type. */
gcc_assert (type);
- gcc_assert (TREE_CODE (type) != TEMPLATE_TYPE_PARM);
+ gcc_assert (TREE_CODE (type) != TEMPLATE_TYPE_PARM || is_auto (type));
return false;
}
return TYPE_DEPENDENT_P (type);
}
+/* Returns TRUE if SCOPE is a dependent scope, in which we can't do any
+ lookup. In other words, a dependent type that is not the current
+ instantiation. */
+
+bool
+dependent_scope_p (tree scope)
+{
+ return (scope && TYPE_P (scope) && dependent_type_p (scope)
+ && !currently_open_class (scope));
+}
+
/* Returns TRUE if EXPRESSION is dependent, according to CRITERION. */
static bool
An id-expression is type-dependent if it contains a
nested-name-specifier that contains a class-name that names a
dependent type. */
- /* The suggested resolution to Core Issue 2 implies that if the
+ /* The suggested resolution to Core Issue 224 implies that if the
qualifying type is the current class, then we must peek
inside it. */
if (DECL_P (name)
if (TREE_CODE (expression) == STMT_EXPR)
expression = stmt_expr_value_expr (expression);
+ if (BRACE_ENCLOSED_INITIALIZER_P (expression))
+ {
+ tree elt;
+ unsigned i;
+
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expression), i, elt)
+ {
+ if (type_dependent_expression_p (elt))
+ return true;
+ }
+ return false;
+ }
+
if (TREE_TYPE (expression) == unknown_type_node)
{
if (TREE_CODE (expression) == ADDR_EXPR)
return (dependent_type_p (TREE_TYPE (expression)));
}
-/* Returns TRUE if ARGS (a TREE_LIST of arguments to a function call)
- contains a type-dependent expression. */
+/* Like type_dependent_expression_p, but it also works while not processing
+ a template definition, i.e. during substitution or mangling. */
bool
-any_type_dependent_arguments_p (const_tree args)
+type_dependent_expression_p_push (tree expr)
{
- while (args)
- {
- tree arg = TREE_VALUE (args);
+ bool b;
+ ++processing_template_decl;
+ b = type_dependent_expression_p (expr);
+ --processing_template_decl;
+ return b;
+}
+
+/* Returns TRUE if ARGS contains a type-dependent expression. */
+bool
+any_type_dependent_arguments_p (const VEC(tree,gc) *args)
+{
+ unsigned int i;
+ tree arg;
+
+ for (i = 0; VEC_iterate (tree, args, i, arg); ++i)
+ {
if (type_dependent_expression_p (arg))
return true;
- args = TREE_CHAIN (args);
}
return false;
}
gcc_assert (TREE_CODE (type) == TYPENAME_TYPE);
scope = TYPE_CONTEXT (type);
- name = TYPE_IDENTIFIER (type);
+ /* Usually the non-qualified identifier of a TYPENAME_TYPE is
+ TYPE_IDENTIFIER (type). But when 'type' is a typedef variant of
+ a TYPENAME_TYPE node, then TYPE_NAME (type) is set to the TYPE_DECL representing
+ the typedef. In that case TYPE_IDENTIFIER (type) is not the non-qualified
+ identifier of the TYPENAME_TYPE anymore.
+ So by getting the TYPE_IDENTIFIER of the _main declaration_ of the
+ TYPENAME_TYPE instead, we avoid messing up with a possible
+ typedef variant case. */
+ name = TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (type));
/* If the SCOPE is itself a TYPENAME_TYPE, then we need to resolve
it first before we can figure out what NAME refers to. */
return build1 (NON_DEPENDENT_EXPR, non_reference (TREE_TYPE (expr)), expr);
}
-/* ARGS is a TREE_LIST of expressions as arguments to a function call.
- Return a new TREE_LIST with the various arguments replaced with
- equivalent non-dependent expressions. */
+/* ARGS is a vector of expressions as arguments to a function call.
+ Replace the arguments with equivalent non-dependent expressions.
+ This modifies ARGS in place. */
+
+void
+make_args_non_dependent (VEC(tree,gc) *args)
+{
+ unsigned int ix;
+ tree arg;
+
+ for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix)
+ {
+ tree newarg = build_non_dependent_expr (arg);
+ if (newarg != arg)
+ VEC_replace (tree, args, ix, newarg);
+ }
+}
+
+/* Returns a type which represents 'auto'. We use a TEMPLATE_TYPE_PARM
+ with a level one deeper than the actual template parms. */
tree
-build_non_dependent_args (tree args)
+make_auto (void)
{
- tree a;
- tree new_args;
+ tree au;
+
+ /* ??? Is it worth caching this for multiple autos at the same level? */
+ au = cxx_make_type (TEMPLATE_TYPE_PARM);
+ TYPE_NAME (au) = build_decl (BUILTINS_LOCATION,
+ TYPE_DECL, get_identifier ("auto"), au);
+ TYPE_STUB_DECL (au) = TYPE_NAME (au);
+ TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
+ (0, processing_template_decl + 1, processing_template_decl + 1,
+ TYPE_NAME (au), NULL_TREE);
+ TYPE_CANONICAL (au) = canonical_type_parameter (au);
+ DECL_ARTIFICIAL (TYPE_NAME (au)) = 1;
+ SET_DECL_TEMPLATE_PARM_P (TYPE_NAME (au));
+
+ return au;
+}
+
+/* Replace auto in TYPE with std::initializer_list<auto>. */
- new_args = NULL_TREE;
- for (a = args; a; a = TREE_CHAIN (a))
- new_args = tree_cons (NULL_TREE,
- build_non_dependent_expr (TREE_VALUE (a)),
- new_args);
- return nreverse (new_args);
+static tree
+listify_autos (tree type, tree auto_node)
+{
+ tree std_init_list = namespace_binding
+ (get_identifier ("initializer_list"), std_node);
+ tree argvec;
+ tree init_auto;
+ if (!std_init_list || !DECL_CLASS_TEMPLATE_P (std_init_list))
+ {
+ error ("deducing auto from brace-enclosed initializer list requires "
+ "#include <initializer_list>");
+ return error_mark_node;
+ }
+ argvec = make_tree_vec (1);
+ TREE_VEC_ELT (argvec, 0) = auto_node;
+ init_auto = lookup_template_class (std_init_list, argvec, NULL_TREE,
+ NULL_TREE, 0, tf_warning_or_error);
+
+ TREE_VEC_ELT (argvec, 0) = init_auto;
+ if (processing_template_decl)
+ argvec = add_to_template_args (current_template_args (), argvec);
+ return tsubst (type, argvec, tf_warning_or_error, NULL_TREE);
+}
+
+/* Replace occurrences of 'auto' in TYPE with the appropriate type deduced
+ from INIT. AUTO_NODE is the TEMPLATE_TYPE_PARM used for 'auto' in TYPE. */
+
+tree
+do_auto_deduction (tree type, tree init, tree auto_node)
+{
+ tree parms, tparms, targs;
+ tree args[1];
+ int val;
+
+ /* [dcl.spec.auto]: Obtain P from T by replacing the occurrences of auto
+ with either a new invented type template parameter U or, if the
+ initializer is a braced-init-list (8.5.4), with
+ std::initializer_list<U>. */
+ if (BRACE_ENCLOSED_INITIALIZER_P (init))
+ type = listify_autos (type, auto_node);
+
+ parms = build_tree_list (NULL_TREE, type);
+ args[0] = init;
+ tparms = make_tree_vec (1);
+ targs = make_tree_vec (1);
+ TREE_VEC_ELT (tparms, 0)
+ = build_tree_list (NULL_TREE, TYPE_NAME (auto_node));
+ val = type_unification_real (tparms, targs, parms, args, 1, 0,
+ DEDUCE_CALL, LOOKUP_NORMAL);
+ if (val > 0)
+ {
+ error ("unable to deduce %qT from %qE", type, init);
+ return error_mark_node;
+ }
+
+ if (processing_template_decl)
+ targs = add_to_template_args (current_template_args (), targs);
+ return tsubst (type, targs, tf_warning_or_error, NULL_TREE);
+}
+
+/* Substitutes LATE_RETURN_TYPE for 'auto' in TYPE and returns the
+ result. */
+
+tree
+splice_late_return_type (tree type, tree late_return_type)
+{
+ tree argvec;
+
+ if (late_return_type == NULL_TREE)
+ return type;
+ argvec = make_tree_vec (1);
+ TREE_VEC_ELT (argvec, 0) = late_return_type;
+ if (processing_template_decl)
+ argvec = add_to_template_args (current_template_args (), argvec);
+ return tsubst (type, argvec, tf_warning_or_error, NULL_TREE);
+}
+
+/* Returns true iff TYPE is a TEMPLATE_TYPE_PARM representing 'auto'. */
+
+bool
+is_auto (const_tree type)
+{
+ if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
+ && TYPE_IDENTIFIER (type) == get_identifier ("auto"))
+ return true;
+ else
+ return false;
+}
+
+/* Returns true iff TYPE contains a use of 'auto'. Since auto can only
+ appear as a type-specifier for the declaration in question, we don't
+ have to look through the whole type. */
+
+tree
+type_uses_auto (tree type)
+{
+ enum tree_code code;
+ if (is_auto (type))
+ return type;
+
+ code = TREE_CODE (type);
+
+ if (code == POINTER_TYPE || code == REFERENCE_TYPE
+ || code == OFFSET_TYPE || code == FUNCTION_TYPE
+ || code == METHOD_TYPE || code == ARRAY_TYPE)
+ return type_uses_auto (TREE_TYPE (type));
+
+ if (TYPE_PTRMEMFUNC_P (type))
+ return type_uses_auto (TREE_TYPE (TREE_TYPE
+ (TYPE_PTRMEMFUNC_FN_TYPE (type))));
+
+ return NULL_TREE;
+}
+
+/* For a given template T, return the list of typedefs referenced
+ in T for which access check is needed at T instantiation time.
+ T is either a FUNCTION_DECL or a RECORD_TYPE.
+ Those typedefs were added to T by the function
+ append_type_to_template_for_access_check. */
+
+tree
+get_types_needing_access_check (tree t)
+{
+ tree ti, result = NULL_TREE;
+
+ if (!t || t == error_mark_node)
+ return t;
+
+ if (!(ti = get_template_info (t)))
+ return NULL_TREE;
+
+ if (CLASS_TYPE_P (t)
+ || TREE_CODE (t) == FUNCTION_DECL)
+ {
+ if (!TI_TEMPLATE (ti))
+ return NULL_TREE;
+
+ result = TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti);
+ }
+
+ return result;
+}
+
+/* Append the typedef TYPE_DECL used in template T to a list of typedefs
+ tied to T. That list of typedefs will be access checked at
+ T instantiation time.
+ T is either a FUNCTION_DECL or a RECORD_TYPE.
+ TYPE_DECL is a TYPE_DECL node representing a typedef.
+ SCOPE is the scope through which TYPE_DECL is accessed.
+
+ This function is a subroutine of
+ append_type_to_template_for_access_check. */
+
+static void
+append_type_to_template_for_access_check_1 (tree t,
+ tree type_decl,
+ tree scope)
+{
+ tree ti;
+
+ if (!t || t == error_mark_node)
+ return;
+
+ gcc_assert ((TREE_CODE (t) == FUNCTION_DECL
+ || CLASS_TYPE_P (t))
+ && type_decl
+ && TREE_CODE (type_decl) == TYPE_DECL
+ && scope);
+
+ if (!(ti = get_template_info (t)))
+ return;
+
+ gcc_assert (TI_TEMPLATE (ti));
+
+ TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti) =
+ tree_cons (type_decl, scope, TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti));
+}
+
+/* Append TYPE_DECL to the template TEMPL.
+ TEMPL is either a class type, a FUNCTION_DECL or a a TEMPLATE_DECL.
+ At TEMPL instanciation time, TYPE_DECL will be checked to see
+ if it can be accessed through SCOPE.
+
+ e.g. consider the following code snippet:
+
+ class C
+ {
+ typedef int myint;
+ };
+
+ template<class U> struct S
+ {
+ C::myint mi;
+ };
+
+ S<char> s;
+
+ At S<char> instantiation time, we need to check the access of C::myint
+ In other words, we need to check the access of the myint typedef through
+ the C scope. For that purpose, this function will add the myint typedef
+ and the scope C through which its being accessed to a list of typedefs
+ tied to the template S. That list will be walked at template instantiation
+ time and access check performed on each typedefs it contains.
+ Note that this particular code snippet should yield an error because
+ myint is private to C. */
+
+void
+append_type_to_template_for_access_check (tree templ,
+ tree type_decl,
+ tree scope)
+{
+ tree node;
+
+ gcc_assert (type_decl && (TREE_CODE (type_decl) == TYPE_DECL));
+
+ /* Make sure we don't append the type to the template twice. */
+ for (node = get_types_needing_access_check (templ);
+ node;
+ node = TREE_CHAIN (node))
+ {
+ tree decl = TREE_PURPOSE (node);
+ tree type_scope = TREE_VALUE (node);
+
+ if (decl == type_decl && type_scope == scope)
+ return;
+ }
+
+ append_type_to_template_for_access_check_1 (templ, type_decl, scope);
+}
+
+/* Set up the hash tables for template instantiations. */
+
+void
+init_template_processing (void)
+{
+ decl_specializations = htab_create_ggc (37,
+ hash_specialization,
+ eq_specializations,
+ ggc_free);
+ type_specializations = htab_create_ggc (37,
+ hash_specialization,
+ eq_specializations,
+ ggc_free);
}
#include "gt-cp-pt.h"