/* Handle parameterized types (templates) for GNU C++.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
Rewritten by Jason Merrill (jason@cygnus.com).
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* Known bugs or deficiencies include:
/* 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.
- The TREE_PURPOSE of each entry is either a DECL (for a function or
- static data member), or a TYPE (for a class) indicating what we are
- hoping to instantiate. The TREE_VALUE is not used. */
-static GTY(()) tree pending_templates;
-static GTY(()) tree last_pending_template;
+ were not yet available, or because we were putting off doing the work. */
+struct pending_template GTY (()) {
+ struct pending_template *next;
+ struct tinst_level *tinst;
+};
+
+static GTY(()) struct pending_template *pending_templates;
+static GTY(()) struct pending_template *last_pending_template;
int processing_template_parmlist;
static int template_header_count;
static GTY(()) tree saved_trees;
static VEC(int,heap) *inline_parm_levels;
-static GTY(()) tree current_tinst_level;
+static GTY(()) struct tinst_level *current_tinst_level;
static GTY(()) tree saved_access_scope;
static void push_access_scope (tree);
static void pop_access_scope (tree);
-static int resolve_overloaded_unification (tree, tree, tree, tree,
- unification_kind_t, int);
+static bool resolve_overloaded_unification (tree, tree, tree, tree,
+ unification_kind_t, int);
static int try_one_overload (tree, tree, tree, tree, tree,
unification_kind_t, int, bool);
static int unify (tree, tree, tree, tree, int);
static void add_pending_template (tree);
static int push_tinst_level (tree);
static void pop_tinst_level (void);
-static void reopen_tinst_level (tree);
+static tree reopen_tinst_level (struct tinst_level *);
static tree tsubst_initializer_list (tree, tree);
static tree get_class_bindings (tree, tree, tree);
static tree coerce_template_parms (tree, tree, tree, tsubst_flags_t,
static tree add_to_template_args (tree, tree);
static tree add_outermost_template_args (tree, tree);
static bool check_instantiated_args (tree, tree, tsubst_flags_t);
-static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*);
+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 void note_template_header (int);
static tree convert_template_argument (tree, tree, tree,
tsubst_flags_t, int, tree);
static int for_each_template_parm (tree, tree_fn_t, void*,
- struct pointer_set_t*);
+ struct pointer_set_t*, bool);
static tree expand_template_argument_pack (tree);
static tree build_template_parm_index (int, int, int, tree, tree);
-static int inline_needs_template_parms (tree);
+static bool inline_needs_template_parms (tree);
static void push_inline_template_parms_recursive (tree, int);
static tree retrieve_local_specialization (tree);
static void register_local_specialization (tree, tree);
-static tree reduce_template_parm_level (tree, tree, int);
+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 tree tsubst_friend_function (tree, tree);
static bool check_specialization_scope (void);
static tree process_partial_specialization (tree);
static void set_current_access_from_decl (tree);
-static void check_default_tmpl_args (tree, tree, int, int);
static tree get_template_base (tree, tree, tree, tree);
static tree try_class_unification (tree, tree, tree, tree);
static int coerce_template_template_parms (tree, tree, tsubst_flags_t,
tree, tree);
+static bool template_template_parm_bindings_ok_p (tree, tree);
static int template_args_equal (tree, tree);
static void tsubst_default_arguments (tree);
static tree for_each_template_parm_r (tree *, int *, void *);
tree type;
type = TREE_TYPE (decl);
+ if (type == error_mark_node)
+ return error_mark_node;
if (IS_AGGR_TYPE (type)
&& CLASSTYPE_TEMPLATE_INFO (type)
&& !CLASSTYPE_TEMPLATE_SPECIALIZATION (type))
return error_mark_node;
}
+/* Return the template info node corresponding to T, whatever T is. */
+
+tree
+get_template_info (tree t)
+{
+ tree tinfo = NULL_TREE;
+
+ if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
+ tinfo = DECL_TEMPLATE_INFO (t);
+
+ if (!tinfo && TREE_CODE (t) == TYPE_DECL)
+ t = TREE_TYPE (t);
+
+ if (TAGGED_TYPE_P (t))
+ tinfo = TYPE_TEMPLATE_INFO (t);
+
+ return tinfo;
+}
+
/* Returns the template nesting level of the indicated class TYPE.
For example, in:
type = (TREE_CODE (type) == FUNCTION_DECL)
? CP_DECL_CONTEXT (type) : TYPE_CONTEXT (type))
{
- if (TREE_CODE (type) != FUNCTION_DECL)
- {
- if (CLASSTYPE_TEMPLATE_INFO (type)
- && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
- && uses_template_parms (CLASSTYPE_TI_ARGS (type)))
- ++depth;
- }
- else
- {
- if (DECL_TEMPLATE_INFO (type)
- && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (type))
- && uses_template_parms (DECL_TI_ARGS (type)))
- ++depth;
- }
+ tree tinfo = get_template_info (type);
+
+ if (tinfo && PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo))
+ && uses_template_parms (INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo))))
+ ++depth;
}
return depth;
}
-/* Returns 1 if processing DECL as part of do_pending_inlines
- needs us to push template parms. */
+/* Subroutine of maybe_begin_member_template_processing.
+ Returns true if processing DECL needs us to push template parms. */
-static int
+static bool
inline_needs_template_parms (tree decl)
{
if (! DECL_TEMPLATE_INFO (decl))
- return 0;
+ return false;
return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (most_general_template (decl)))
> (processing_template_decl + DECL_TEMPLATE_SPECIALIZATION (decl)));
return new_args;
}
+/* The inverse of get_innermost_template_args: Return all but the innermost
+ EXTRA_LEVELS levels of template arguments from the ARGS. */
+
+static tree
+strip_innermost_template_args (tree args, int extra_levels)
+{
+ tree new_args;
+ int n = TMPL_ARGS_DEPTH (args) - extra_levels;
+ int i;
+
+ gcc_assert (n >= 0);
+
+ /* If N is 1, just return the outermost set of template arguments. */
+ if (n == 1)
+ return TMPL_ARGS_LEVEL (args, 1);
+
+ /* If we're not removing anything, just return the arguments we were
+ given. */
+ gcc_assert (extra_levels >= 0);
+ if (extra_levels == 0)
+ return args;
+
+ /* Make a new set of arguments, not containing the inner arguments. */
+ new_args = make_tree_vec (n);
+ for (i = 1; i <= n; ++i)
+ SET_TMPL_ARGS_LEVEL (new_args, i,
+ TMPL_ARGS_LEVEL (args, i));
+
+ return new_args;
+}
+
/* We've got a template header coming up; push to a new level for storing
the parms. */
DECL_TEMPLATE_INSTANTIATIONS list; other templates use the
DECL_TEMPLATE_SPECIALIZATIONS list. */
if (!class_specializations_p
- && TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL)
+ && TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL
+ && TAGGED_TYPE_P (TREE_TYPE (tmpl)))
sp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
else
sp = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
static tree
retrieve_local_specialization (tree tmpl)
{
- tree spec = (tree) htab_find_with_hash (local_specializations, tmpl,
- htab_hash_pointer (tmpl));
+ tree spec;
+
+ if (local_specializations == NULL)
+ return NULL_TREE;
+
+ spec = (tree) htab_find_with_hash (local_specializations, tmpl,
+ htab_hash_pointer (tmpl));
return spec ? TREE_PURPOSE (spec) : NULL_TREE;
}
static int
eq_local_specializations (const void *p1, const void *p2)
{
- return TREE_VALUE ((tree) p1) == (tree) p2;
+ return TREE_VALUE ((const_tree) p1) == (const_tree) p2;
}
/* Hash P1, an entry in the local specializations table. */
static hashval_t
hash_local_specialization (const void* p1)
{
- return htab_hash_pointer (TREE_VALUE ((tree) p1));
+ return htab_hash_pointer (TREE_VALUE ((const_tree) p1));
}
/* Like register_specialization, but for local declarations. We are
context. */
fns = lookup_qualified_name (CP_DECL_CONTEXT (decl), dname,
false, true);
- if (!fns || !is_overloaded_fn (fns))
+ if (fns == error_mark_node || !is_overloaded_fn (fns))
{
error ("%qD is not a template function", dname);
fns = error_mark_node;
{
int is_constructor = DECL_CONSTRUCTOR_P (decl);
- if (is_constructor ? !TYPE_HAS_CONSTRUCTOR (ctype)
+ if (is_constructor ? !TYPE_HAS_USER_CONSTRUCTOR (ctype)
: !CLASSTYPE_DESTRUCTORS (ctype))
{
/* From [temp.expl.spec]:
TREE_PRIVATE (decl) = TREE_PRIVATE (gen_tmpl);
TREE_PROTECTED (decl) = TREE_PROTECTED (gen_tmpl);
+ /* 7.1.1-1 [dcl.stc]
+
+ A storage-class-specifier shall not be specified in an
+ explicit specialization...
+
+ The parser rejects these, so unless action is taken here,
+ explicit function specializations will always appear with
+ global linkage.
+
+ The action recommended by the C++ CWG in response to C++
+ defect report 605 is to make the storage class and linkage
+ of the explicit specialization match the templated function:
+
+ http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#605
+ */
+ if (tsk == tsk_expl_spec && DECL_FUNCTION_TEMPLATE_P (gen_tmpl))
+ {
+ tree tmpl_func = DECL_TEMPLATE_RESULT (gen_tmpl);
+ gcc_assert (TREE_CODE (tmpl_func) == FUNCTION_DECL);
+
+ /* This specialization has the same linkage and visibility as
+ the function template it specializes. */
+ TREE_PUBLIC (decl) = TREE_PUBLIC (tmpl_func);
+ if (! TREE_PUBLIC (decl))
+ {
+ DECL_INTERFACE_KNOWN (decl) = 1;
+ DECL_NOT_REALLY_EXTERN (decl) = 1;
+ }
+ DECL_THIS_STATIC (decl) = DECL_THIS_STATIC (tmpl_func);
+ if (DECL_VISIBILITY_SPECIFIED (tmpl_func))
+ {
+ DECL_VISIBILITY_SPECIFIED (decl) = 1;
+ DECL_VISIBILITY (decl) = DECL_VISIBILITY (tmpl_func);
+ }
+ }
+
/* If DECL is a friend declaration, declared using an
unqualified name, the namespace associated with DECL may
have been set incorrectly. For example, in:
DECL_TEMPLATE_PARMS. */
int
-comp_template_parms (tree parms1, tree parms2)
+comp_template_parms (const_tree parms1, const_tree parms2)
{
- tree p1;
- tree p2;
+ const_tree p1;
+ const_tree p2;
if (parms1 == parms2)
return 1;
/* Determine whether PARM is a parameter pack. */
bool
-template_parameter_pack_p (tree parm)
+template_parameter_pack_p (const_tree parm)
{
/* Determine if we have a non-type template parameter pack. */
if (TREE_CODE (parm) == PARM_DECL)
&& TEMPLATE_TYPE_PARAMETER_PACK (parm));
}
-/* Determine whether PARMS describes a variadic template parameter
- list, i.e., one that is terminated by a template parameter pack. */
-bool
-template_parms_variadic_p (tree parms)
-{
- int nparms = TREE_VEC_LENGTH (parms);
- tree last_parm = TREE_VALUE (TREE_VEC_ELT (parms, nparms - 1));
-
- return template_parameter_pack_p (last_parm);
-}
-
/* Determine whether ARGS describes a variadic template args list,
i.e., one that is terminated by a template argument pack. */
static bool
return get_identifier (newname);
}
-/* Structure used to track the progress of find_parameter_pack_r. */
+/* Structure used to track the progress of find_parameter_packs_r. */
struct find_parameter_pack_data
{
+ /* TREE_LIST that will contain all of the parameter packs found by
+ the traversal. */
tree* parameter_packs;
+
+ /* Set of AST nodes that have been visited by the traversal. */
struct pointer_set_t *visited;
};
-/* Identifiers all of the argument packs that occur in a template
+/* Identifies all of the argument packs that occur in a template
argument and appends them to the TREE_LIST inside DATA, which is a
- find_parameter_pack_Data structure. This is a subroutine of
+ find_parameter_pack_data structure. This is a subroutine of
make_pack_expansion and uses_parameter_packs. */
static tree
find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
tree t = *tp;
struct find_parameter_pack_data* ppd =
(struct find_parameter_pack_data*)data;
+ bool parameter_pack_p = false;
- if (TYPE_P (t))
+ /* Identify whether this is a parameter pack or not. */
+ switch (TREE_CODE (t))
{
- tree context = TYPE_CONTEXT (t);
- walk_tree (&context, &find_parameter_packs_r, ppd, ppd->visited);
+ case TEMPLATE_PARM_INDEX:
+ if (TEMPLATE_PARM_PARAMETER_PACK (t))
+ parameter_pack_p = true;
+ break;
+
+ case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
+ if (TEMPLATE_TYPE_PARAMETER_PACK (t))
+ parameter_pack_p = true;
+ break;
+
+ case PARM_DECL:
+ if (FUNCTION_PARAMETER_PACK_P (t))
+ {
+ /* We don't want to walk into the type of a PARM_DECL,
+ because we don't want to see the type parameter pack. */
+ *walk_subtrees = 0;
+ parameter_pack_p = true;
+ }
+ break;
+
+ default:
+ /* Not a parameter pack. */
+ break;
}
+ if (parameter_pack_p)
+ {
+ /* Add this parameter pack to the list. */
+ *ppd->parameter_packs = tree_cons (NULL_TREE, t, *ppd->parameter_packs);
+ }
+
+ if (TYPE_P (t))
+ cp_walk_tree (&TYPE_CONTEXT (t),
+ &find_parameter_packs_r, ppd, ppd->visited);
+
/* This switch statement will return immediately if we don't find a
parameter pack. */
switch (TREE_CODE (t))
{
case TEMPLATE_PARM_INDEX:
- if (TEMPLATE_PARM_PARAMETER_PACK (t))
- break;
return NULL_TREE;
case BOUND_TEMPLATE_TEMPLATE_PARM:
+ /* Check the template itself. */
+ cp_walk_tree (&TREE_TYPE (TYPE_TI_TEMPLATE (t)),
+ &find_parameter_packs_r, ppd, ppd->visited);
/* Check the template arguments. */
- walk_tree (&TYPE_TI_ARGS (t), &find_parameter_packs_r, ppd,
- ppd->visited);
-
- /* Dig out the underlying TEMPLATE_TEMPLATE_PARM. */
- t = TYPE_TI_TEMPLATE (t);
- if (DECL_P (t) && TREE_TYPE (t))
- t = TREE_TYPE (t);
+ cp_walk_tree (&TYPE_TI_ARGS (t), &find_parameter_packs_r, ppd,
+ ppd->visited);
*walk_subtrees = 0;
-
- /* Fall through. */
+ return NULL_TREE;
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
- if (TEMPLATE_TYPE_PARAMETER_PACK (t))
- break;
return NULL_TREE;
case PARM_DECL:
- if (FUNCTION_PARAMETER_PACK_P (t))
- {
- /* We don't want to walk into the type of a PARM_DECL,
- because we don't want to see the type parameter pack.*/
- *walk_subtrees = 0;
- break;
- }
return NULL_TREE;
case RECORD_TYPE:
case UNION_TYPE:
case ENUMERAL_TYPE:
if (TYPE_TEMPLATE_INFO (t))
- {
- tree args = TREE_VALUE (TYPE_TEMPLATE_INFO (t));
- walk_tree (&args, &find_parameter_packs_r, ppd, ppd->visited);
- }
+ cp_walk_tree (&TREE_VALUE (TYPE_TEMPLATE_INFO (t)),
+ &find_parameter_packs_r, ppd, ppd->visited);
*walk_subtrees = 0;
return NULL_TREE;
case TEMPLATE_DECL:
- if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)
- && TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (t)))
- break;
-
+ cp_walk_tree (&TREE_TYPE (t),
+ &find_parameter_packs_r, ppd, ppd->visited);
+ return NULL_TREE;
+
+ case TYPENAME_TYPE:
+ cp_walk_tree (&TYPENAME_TYPE_FULLNAME (t), &find_parameter_packs_r,
+ ppd, ppd->visited);
*walk_subtrees = 0;
return NULL_TREE;
-
+
case TYPE_PACK_EXPANSION:
case EXPR_PACK_EXPANSION:
*walk_subtrees = 0;
return NULL_TREE;
+ case INTEGER_TYPE:
+ cp_walk_tree (&TYPE_MAX_VALUE (t), &find_parameter_packs_r,
+ ppd, ppd->visited);
+ *walk_subtrees = 0;
+ return NULL_TREE;
+
+ case IDENTIFIER_NODE:
+ cp_walk_tree (&TREE_TYPE (t), &find_parameter_packs_r, ppd,
+ ppd->visited);
+ *walk_subtrees = 0;
+ return NULL_TREE;
+
default:
return NULL_TREE;
}
-
- /* Add this parameter pack to the list. */
- *ppd->parameter_packs = tree_cons (NULL_TREE, t, *ppd->parameter_packs);
return NULL_TREE;
}
struct find_parameter_pack_data ppd;
ppd.parameter_packs = ¶meter_packs;
ppd.visited = pointer_set_create ();
- walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
+ cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
+ pointer_set_destroy (ppd.visited);
return parameter_packs != NULL_TREE;
}
class expansion. */
ppd.visited = pointer_set_create ();
ppd.parameter_packs = ¶meter_packs;
- walk_tree (&TREE_PURPOSE (arg), &find_parameter_packs_r,
- &ppd, ppd.visited);
+ cp_walk_tree (&TREE_PURPOSE (arg), &find_parameter_packs_r,
+ &ppd, ppd.visited);
if (parameter_packs == NULL_TREE)
{
error ("base initializer expansion %<%T%> contains no parameter packs", arg);
+ pointer_set_destroy (ppd.visited);
return error_mark_node;
}
{
/* Determine which parameter packs will be expanded in this
argument. */
- walk_tree (&TREE_VALUE (value), &find_parameter_packs_r,
- &ppd, ppd.visited);
+ cp_walk_tree (&TREE_VALUE (value), &find_parameter_packs_r,
+ &ppd, ppd.visited);
}
}
+ pointer_set_destroy (ppd.visited);
+
/* Create the pack expansion type for the base type. */
purpose = make_node (TYPE_PACK_EXPANSION);
SET_PACK_EXPANSION_PATTERN (purpose, TREE_PURPOSE (arg));
/* Determine which parameter packs will be expanded. */
ppd.parameter_packs = ¶meter_packs;
ppd.visited = pointer_set_create ();
- walk_tree (&arg, &find_parameter_packs_r, &ppd, ppd.visited);
+ cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, ppd.visited);
+ pointer_set_destroy (ppd.visited);
/* Make sure we found some parameter packs. */
if (parameter_packs == NULL_TREE)
where "args" is a parameter pack. check_for_bare_parameter_packs
should not be called for the subexpressions args, h(args),
g(h(args)), or f(g(h(args))), because we would produce erroneous
- error messages. */
-void
+ error messages.
+
+ Returns TRUE and emits an error if there were bare parameter packs,
+ returns FALSE otherwise. */
+bool
check_for_bare_parameter_packs (tree t)
{
tree parameter_packs = NULL_TREE;
struct find_parameter_pack_data ppd;
if (!processing_template_decl || !t || t == error_mark_node)
- return;
+ return false;
if (TREE_CODE (t) == TYPE_DECL)
t = TREE_TYPE (t);
ppd.parameter_packs = ¶meter_packs;
ppd.visited = pointer_set_create ();
- walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
+ cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
+ pointer_set_destroy (ppd.visited);
- if (parameter_packs) {
- error ("parameter packs not expanded with `...':");
- while (parameter_packs)
- {
- tree pack = TREE_VALUE (parameter_packs);
- tree name = NULL_TREE;
+ if (parameter_packs)
+ {
+ error ("parameter packs not expanded with `...':");
+ while (parameter_packs)
+ {
+ tree pack = TREE_VALUE (parameter_packs);
+ tree name = NULL_TREE;
+
+ if (TREE_CODE (pack) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (pack) == TEMPLATE_TEMPLATE_PARM)
+ name = TYPE_NAME (pack);
+ else if (TREE_CODE (pack) == TEMPLATE_PARM_INDEX)
+ name = DECL_NAME (TEMPLATE_PARM_DECL (pack));
+ else
+ name = DECL_NAME (pack);
- if (TREE_CODE (pack) == TEMPLATE_TYPE_PARM
- || TREE_CODE (pack) == TEMPLATE_TEMPLATE_PARM)
- name = TYPE_NAME (pack);
- else
- name = DECL_NAME (pack);
- inform (" %qD", name);
+ if (name)
+ inform (" %qD", name);
+ else
+ inform (" <anonymous>");
- parameter_packs = TREE_CHAIN (parameter_packs);
- }
- }
+ parameter_packs = TREE_CHAIN (parameter_packs);
+ }
+
+ return true;
+ }
+
+ return false;
}
/* Expand any parameter packs that occur in the template arguments in
VEC_safe_push (tree, gc, canonical_template_parms, NULL_TREE);
list = VEC_index (tree, canonical_template_parms, idx);
- while (list && !comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
+ while (list && !cp_comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
list = TREE_CHAIN (list);
if (list)
new one is created. */
static tree
-reduce_template_parm_level (tree index, tree type, int levels)
+reduce_template_parm_level (tree index, tree type, int levels, tree args,
+ tsubst_flags_t complain)
{
if (TEMPLATE_PARM_DESCENDANTS (index) == NULL_TREE
|| (TEMPLATE_PARM_LEVEL (TEMPLATE_PARM_DESCENDANTS (index))
= TEMPLATE_PARM_PARAMETER_PACK (index);
/* Template template parameters need this. */
- if (TREE_CODE (decl) != CONST_DECL)
- DECL_TEMPLATE_PARMS (decl)
- = DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index));
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ DECL_TEMPLATE_PARMS (decl) = tsubst_template_parms
+ (DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index)),
+ args, complain);
}
return TEMPLATE_PARM_DESCENDANTS (index);
current_template_parms = TREE_CHAIN (current_template_parms);
}
-/* Given a template argument vector containing the template PARMS.
- The innermost PARMS are given first. */
+/* Within the declaration of a template, return all levels of template
+ parameters that apply. The template parameters are represented as
+ a TREE_VEC, in the form documented in cp-tree.h for template
+ arguments. */
static tree
current_template_args (void)
{
t = TREE_VALUE (t);
- if (t != error_mark_node)
+ if (!error_operand_p (t))
{
if (TREE_CODE (t) == TYPE_DECL
|| TREE_CODE (t) == TEMPLATE_DECL)
TREE_TYPE (t) = type;
}
}
+ TREE_VEC_ELT (a, i) = t;
}
- TREE_VEC_ELT (a, i) = t;
}
}
for_each_template_parm (TREE_VEC_ELT (inner_args, i),
&mark_template_parm,
&tpd,
- NULL);
+ NULL,
+ /*include_nondeduced_p=*/false);
}
for (i = 0; i < ntparms; ++i)
if (tpd.parms[i] == 0)
if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
error ("parameter pack argument %qE must be at the end of the template argument list", arg);
else
- error ("parameter pack argument %qT must be at the end of the template argument list", arg);
+ error ("parameter pack argument %qT must be at the end of the template argument list", arg);
+
+ if (packed_args)
+ TREE_VEC_ELT (packed_args, j) = error_mark_node;
}
}
for_each_template_parm (type,
&mark_template_parm,
&tpd2,
- NULL);
+ NULL,
+ /*include_nondeduced_p=*/false);
if (tpd2.arg_uses_template_parms [i])
{
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)
= tree_cons (specargs, inner_parms,
- DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
+ DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
return decl;
}
-/* Check that a template declaration's use of default arguments is not
- invalid. Here, PARMS are the template parameters. IS_PRIMARY is
- nonzero if DECL is the thing declared by a primary template.
- IS_PARTIAL is nonzero if DECL is a partial specialization. */
+/* Check that a template declaration's use of default arguments and
+ parameter packs is not invalid. Here, PARMS are the template
+ parameters. IS_PRIMARY is nonzero if DECL is the thing declared by
+ a primary template. IS_PARTIAL is nonzero if DECL is a partial
+ specialization.
+
-static void
-check_default_tmpl_args (tree decl, tree parms, int is_primary, int is_partial)
+ IS_FRIEND_DECL is nonzero if DECL is a friend function template
+ declaration (but not a definition); 1 indicates a declaration, 2
+ indicates a redeclaration. When IS_FRIEND_DECL=2, no errors are
+ emitted for extraneous default arguments.
+
+ Returns TRUE if there were no errors found, FALSE otherwise. */
+
+bool
+check_default_tmpl_args (tree decl, tree parms, int is_primary,
+ int is_partial, int is_friend_decl)
{
const char *msg;
int last_level_to_check;
tree parm_level;
+ bool no_errors = true;
/* [temp.param]
/* You can't have a function template declaration in a local
scope, nor you can you define a member of a class template in a
local scope. */
- return;
+ return true;
if (current_class_type
&& !TYPE_BEING_DEFINED (current_class_type)
declared, so there's no need to do it again now. This function
was defined in class scope, but we're processing it's body now
that the class is complete. */
- return;
-
- /* [temp.param]
+ return true;
- If a template-parameter has a default template-argument, all
- subsequent template-parameters shall have a default
- template-argument supplied. */
- for (parm_level = parms; parm_level; parm_level = TREE_CHAIN (parm_level))
+ /* Core issue 226 (C++0x only): the following only applies to class
+ templates. */
+ if ((cxx_dialect == cxx98) || TREE_CODE (decl) != FUNCTION_DECL)
{
- tree inner_parms = TREE_VALUE (parm_level);
- int ntparms = TREE_VEC_LENGTH (inner_parms);
- int seen_def_arg_p = 0;
- int i;
+ /* [temp.param]
- for (i = 0; i < ntparms; ++i)
- {
- tree parm = TREE_VEC_ELT (inner_parms, i);
+ If a template-parameter has a default template-argument, all
+ subsequent template-parameters shall have a default
+ template-argument supplied. */
+ for (parm_level = parms; parm_level; parm_level = TREE_CHAIN (parm_level))
+ {
+ tree inner_parms = TREE_VALUE (parm_level);
+ int ntparms = TREE_VEC_LENGTH (inner_parms);
+ int seen_def_arg_p = 0;
+ int i;
- if (parm == error_mark_node)
- continue;
+ for (i = 0; i < ntparms; ++i)
+ {
+ tree parm = TREE_VEC_ELT (inner_parms, i);
- if (TREE_PURPOSE (parm))
- seen_def_arg_p = 1;
- else if (seen_def_arg_p)
- {
- error ("no default argument for %qD", TREE_VALUE (parm));
- /* For better subsequent error-recovery, we indicate that
- there should have been a default argument. */
- TREE_PURPOSE (parm) = error_mark_node;
- }
- }
+ if (parm == error_mark_node)
+ continue;
+
+ if (TREE_PURPOSE (parm))
+ seen_def_arg_p = 1;
+ else if (seen_def_arg_p)
+ {
+ error ("no default argument for %qD", TREE_VALUE (parm));
+ /* For better subsequent error-recovery, we indicate that
+ there should have been a default argument. */
+ TREE_PURPOSE (parm) = error_mark_node;
+ no_errors = false;
+ }
+ else if (is_primary
+ && !is_partial
+ && !is_friend_decl
+ && TREE_CODE (decl) == TYPE_DECL
+ && i < ntparms - 1
+ && template_parameter_pack_p (TREE_VALUE (parm)))
+ {
+ /* A primary class template can only have one
+ parameter pack, at the end of the template
+ parameter list. */
+
+ if (TREE_CODE (TREE_VALUE (parm)) == PARM_DECL)
+ error ("parameter pack %qE must be at the end of the"
+ " template parameter list", TREE_VALUE (parm));
+ else
+ error ("parameter pack %qT must be at the end of the"
+ " template parameter list",
+ TREE_TYPE (TREE_VALUE (parm)));
+
+ TREE_VALUE (TREE_VEC_ELT (inner_parms, i))
+ = error_mark_node;
+ no_errors = false;
+ }
+ }
+ }
}
- if (TREE_CODE (decl) != TYPE_DECL || is_partial || !is_primary)
+ if (((cxx_dialect == cxx98) && TREE_CODE (decl) != TYPE_DECL)
+ || is_partial
+ || !is_primary
+ || is_friend_decl)
/* For an ordinary class template, default template arguments are
allowed at the innermost level, e.g.:
template <class T = int>
The template parameter list of a specialization shall not
contain default template argument values.
- So, for a partial specialization, or for a function template,
- we look at all of them. */
+ So, for a partial specialization, or for a function template
+ (in C++98/C++03), we look at all of them. */
;
else
/* But, for a primary class template that is not a partial
parms = TREE_CHAIN (parms);
/* Figure out what error message to issue. */
- if (TREE_CODE (decl) == FUNCTION_DECL)
+ if (is_friend_decl == 2)
+ msg = "default template arguments may not be used in function template friend re-declaration";
+ else if (is_friend_decl)
+ msg = "default template arguments may not be used in function template friend declarations";
+ else if (TREE_CODE (decl) == FUNCTION_DECL && (cxx_dialect == cxx98))
msg = "default template arguments may not be used in function templates";
else if (is_partial)
msg = "default template arguments may not be used in partial specializations";
{
if (msg)
{
+ no_errors = false;
+ if (is_friend_decl == 2)
+ return no_errors;
+
error (msg, decl);
msg = 0;
}
if (msg)
msg = "default argument for template parameter for class enclosing %qD";
}
+
+ return no_errors;
}
/* Worker for push_template_decl_real, called via
/* Check to see that the rules regarding the use of default
arguments are not being violated. */
check_default_tmpl_args (decl, current_template_parms,
- primary, is_partial);
+ primary, is_partial, /*is_friend_decl=*/0);
/* Ensure that there are no parameter packs in the type of this
declaration that have not been expanded. */
- check_for_bare_parameter_packs (TREE_TYPE (decl));
-
- if (is_partial)
- return process_partial_specialization (decl);
-
- /* A primary class template can only have one parameter pack, at the
- end of the template parameter list. */
- if (primary && TREE_CODE (decl) == TYPE_DECL)
+ if (TREE_CODE (decl) == FUNCTION_DECL)
{
- tree inner_parms
- = INNERMOST_TEMPLATE_PARMS (current_template_parms);
- int i, len = TREE_VEC_LENGTH (inner_parms);
- for (i = 0; i < len - 1; i++)
+ /* Check each of the arguments individually to see if there are
+ any bare parameter packs. */
+ tree type = TREE_TYPE (decl);
+ tree arg = DECL_ARGUMENTS (decl);
+ tree argtype = TYPE_ARG_TYPES (type);
+
+ while (arg && argtype)
{
- tree parm = TREE_VALUE (TREE_VEC_ELT (inner_parms, i));
+ if (!FUNCTION_PARAMETER_PACK_P (arg)
+ && check_for_bare_parameter_packs (TREE_TYPE (arg)))
+ {
+ /* This is a PARM_DECL that contains unexpanded parameter
+ packs. We have already complained about this in the
+ check_for_bare_parameter_packs call, so just replace
+ these types with ERROR_MARK_NODE. */
+ TREE_TYPE (arg) = error_mark_node;
+ TREE_VALUE (argtype) = error_mark_node;
+ }
- if (template_parameter_pack_p (parm))
- {
- if (TREE_CODE (parm) == PARM_DECL)
- error ("parameter pack %qE must be at the end of the"
- " template parameter list", parm);
- else
- error ("parameter pack %qT must be at the end of the"
- " template parameter list", TREE_TYPE (parm));
- }
+ arg = TREE_CHAIN (arg);
+ argtype = TREE_CHAIN (argtype);
}
+
+ /* Check for bare parameter packs in the return type and the
+ exception specifiers. */
+ if (check_for_bare_parameter_packs (TREE_TYPE (type)))
+ /* Errors were already issued, set return type to int
+ as the frontend doesn't expect error_mark_node as
+ the return type. */
+ TREE_TYPE (type) = integer_type_node;
+ if (check_for_bare_parameter_packs (TYPE_RAISES_EXCEPTIONS (type)))
+ TYPE_RAISES_EXCEPTIONS (type) = NULL_TREE;
+ }
+ else if (check_for_bare_parameter_packs (TREE_TYPE (decl)))
+ {
+ TREE_TYPE (decl) = error_mark_node;
+ return error_mark_node;
}
+ if (is_partial)
+ return process_partial_specialization (decl);
+
args = current_template_args ();
if (!ctx
{
tree a, t, current, parms;
int i;
+ tree tinfo = get_template_info (decl);
- if (TREE_CODE (decl) == TYPE_DECL)
- {
- if ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (decl)))
- || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
- && TYPE_TEMPLATE_INFO (TREE_TYPE (decl))
- && TYPE_TI_TEMPLATE (TREE_TYPE (decl)))
- tmpl = TYPE_TI_TEMPLATE (TREE_TYPE (decl));
- else
- {
- error ("%qD does not declare a template type", decl);
- return decl;
- }
- }
- else if (!DECL_LANG_SPECIFIC (decl) || !DECL_TEMPLATE_INFO (decl))
+ if (!tinfo)
{
error ("template definition of non-template %q#D", decl);
- return decl;
+ return error_mark_node;
}
- else
- tmpl = DECL_TI_TEMPLATE (decl);
+
+ tmpl = TI_TEMPLATE (tinfo);
if (DECL_FUNCTION_TEMPLATE_P (tmpl)
&& DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl)
return error_mark_node;
}
- /* Perhaps we should also check that the parms are used in the
- appropriate qualifying scopes in the declarator? */
-
if (current == decl)
current = ctx;
else
- current = TYPE_CONTEXT (current);
+ current = (TYPE_P (current)
+ ? TYPE_CONTEXT (current)
+ : DECL_CONTEXT (current));
}
+
+ /* Check that the parms are used in the appropriate qualifying scopes
+ in the declarator. */
+ if (!comp_template_args
+ (TI_ARGS (tinfo),
+ TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (tmpl)))))
+ {
+ error ("\
+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");
+ /* Avoid crash in import_export_decl. */
+ DECL_INTERFACE_KNOWN (decl) = 1;
+ return error_mark_node;
+ }
}
DECL_TEMPLATE_RESULT (tmpl) = decl;
if (primary)
{
+ tree parms = DECL_TEMPLATE_PARMS (tmpl);
+ int i;
+
DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
if (DECL_CONV_FN_P (tmpl))
{
- int depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
+ int depth = TMPL_PARMS_DEPTH (parms);
/* It is a conversion operator. See if the type converted to
depends on innermost template operands. */
depth))
DECL_TEMPLATE_CONV_FN_P (tmpl) = 1;
}
+
+ /* Give template template parms a DECL_CONTEXT of the template
+ for which they are a parameter. */
+ parms = INNERMOST_TEMPLATE_PARMS (parms);
+ for (i = TREE_VEC_LENGTH (parms) - 1; i >= 0; --i)
+ {
+ tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
+ if (TREE_CODE (parm) == TEMPLATE_DECL)
+ DECL_CONTEXT (parm) = tmpl;
+ }
}
/* The DECL_TI_ARGS of DECL contains full set of arguments referring
if (TREE_VEC_LENGTH (parms) != TREE_VEC_LENGTH (tmpl_parms))
{
- error ("previous declaration %q+D", tmpl);
- error ("used %d template parameter(s) instead of %d",
- TREE_VEC_LENGTH (tmpl_parms),
- TREE_VEC_LENGTH (parms));
+ error ("redeclared with %d template parameter(s)",
+ TREE_VEC_LENGTH (parms));
+ inform ("previous declaration %q+D used %d template parameter(s)",
+ tmpl, TREE_VEC_LENGTH (tmpl_parms));
return false;
}
/* TMPL_PARM and PARM can be either TYPE_DECL, PARM_DECL, or
TEMPLATE_DECL. */
if (tmpl_parm != error_mark_node
- && (TREE_CODE (tmpl_parm) != TREE_CODE (parm)
- || (TREE_CODE (tmpl_parm) != TYPE_DECL
- && !same_type_p (TREE_TYPE (tmpl_parm), TREE_TYPE (parm)))))
+ && (TREE_CODE (tmpl_parm) != TREE_CODE (parm)
+ || (TREE_CODE (tmpl_parm) != TYPE_DECL
+ && !same_type_p (TREE_TYPE (tmpl_parm), TREE_TYPE (parm)))
+ || (TREE_CODE (tmpl_parm) != PARM_DECL
+ && (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (tmpl_parm))
+ != TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm))))
+ || (TREE_CODE (tmpl_parm) == PARM_DECL
+ && (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (tmpl_parm))
+ != TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))))))
{
error ("template parameter %q+#D", tmpl_parm);
error ("redeclared here as %q#D", parm);
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);
- error ("%J original definition appeared here", tmpl_parm);
+ inform ("%Joriginal definition appeared here", tmpl_parm);
return false;
}
return 1;
}
+/* Verifies that the deduced template arguments (in TARGS) for the
+ template template parameters (in TPARMS) represent valid bindings,
+ by comparing the template parameter list of each template argument
+ to the template parameter list of its corresponding template
+ template parameter, in accordance with DR150. This
+ routine can only be called after all template arguments have been
+ deduced. It will return TRUE if all of the template template
+ parameter bindings are okay, FALSE otherwise. */
+bool
+template_template_parm_bindings_ok_p (tree tparms, tree targs)
+{
+ int i, ntparms = TREE_VEC_LENGTH (tparms);
+
+ targs = INNERMOST_TEMPLATE_ARGS (targs);
+
+ for (i = 0; i < ntparms; ++i)
+ {
+ tree tparm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
+ tree targ = TREE_VEC_ELT (targs, i);
+
+ if (TREE_CODE (tparm) == TEMPLATE_DECL && targ)
+ {
+ tree packed_args = NULL_TREE;
+ int idx, len = 1;
+
+ if (ARGUMENT_PACK_P (targ))
+ {
+ /* Look inside the argument pack. */
+ packed_args = ARGUMENT_PACK_ARGS (targ);
+ len = TREE_VEC_LENGTH (packed_args);
+ }
+
+ for (idx = 0; idx < len; ++idx)
+ {
+ tree targ_parms = NULL_TREE;
+
+ if (packed_args)
+ /* Extract the next argument from the argument
+ pack. */
+ targ = TREE_VEC_ELT (packed_args, idx);
+
+ if (PACK_EXPANSION_P (targ))
+ /* Look at the pattern of the pack expansion. */
+ targ = PACK_EXPANSION_PATTERN (targ);
+
+ /* Extract the template parameters from the template
+ argument. */
+ if (TREE_CODE (targ) == TEMPLATE_DECL)
+ targ_parms = DECL_INNERMOST_TEMPLATE_PARMS (targ);
+ else if (TREE_CODE (targ) == TEMPLATE_TEMPLATE_PARM)
+ targ_parms = DECL_INNERMOST_TEMPLATE_PARMS (TYPE_NAME (targ));
+
+ /* Verify that we can coerce the template template
+ parameters from the template argument to the template
+ parameter. This requires an exact match. */
+ if (targ_parms
+ && !coerce_template_template_parms
+ (DECL_INNERMOST_TEMPLATE_PARMS (tparm),
+ targ_parms,
+ tf_none,
+ tparm,
+ targs))
+ return false;
+ }
+ }
+ }
+
+ /* Everything is okay. */
+ return true;
+}
+
/* Convert the indicated template ARG as necessary to match the
indicated template PARM. Returns the converted ARG, or
error_mark_node if the conversion was unsuccessful. Error and
int i,
tree in_decl)
{
+ tree orig_arg;
tree val;
int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
- tree check_arg = arg;
if (TREE_CODE (arg) == TREE_LIST
&& TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
invalid, but static members are OK. In any
case, grab the underlying fields/functions
and issue an error later if required. */
- arg = TREE_VALUE (arg);
+ orig_arg = TREE_VALUE (arg);
TREE_TYPE (arg) = unknown_type_node;
}
+ orig_arg = arg;
+
requires_tmpl_type = TREE_CODE (parm) == TEMPLATE_DECL;
requires_type = (TREE_CODE (parm) == TYPE_DECL
|| requires_tmpl_type);
- /* When determining whether a argument pack expansion is a template,
+ /* When determining whether an argument pack expansion is a template,
look at the pattern. */
- if (TREE_CODE (check_arg) == TYPE_PACK_EXPANSION)
- check_arg = PACK_EXPANSION_PATTERN (check_arg);
+ if (TREE_CODE (arg) == TYPE_PACK_EXPANSION)
+ arg = PACK_EXPANSION_PATTERN (arg);
is_tmpl_type =
- ((TREE_CODE (check_arg) == TEMPLATE_DECL
- && TREE_CODE (DECL_TEMPLATE_RESULT (check_arg)) == TYPE_DECL)
- || TREE_CODE (check_arg) == TEMPLATE_TEMPLATE_PARM
- || TREE_CODE (check_arg) == UNBOUND_CLASS_TEMPLATE);
+ ((TREE_CODE (arg) == TEMPLATE_DECL
+ && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
+ || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+ || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);
if (is_tmpl_type
&& (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
&& TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
{
pedwarn ("to refer to a type member of a template parameter, "
- "use %<typename %E%>", arg);
+ "use %<typename %E%>", orig_arg);
- arg = make_typename_type (TREE_OPERAND (arg, 0),
- TREE_OPERAND (arg, 1),
- typename_type,
- complain & tf_error);
+ orig_arg = make_typename_type (TREE_OPERAND (arg, 0),
+ TREE_OPERAND (arg, 1),
+ typename_type,
+ complain & tf_error);
+ arg = orig_arg;
is_type = 1;
}
if (is_type != requires_type)
if (is_type)
error (" expected a constant of type %qT, got %qT",
TREE_TYPE (parm),
- (is_tmpl_type ? DECL_NAME (arg) : arg));
+ (DECL_P (arg) ? DECL_NAME (arg) : orig_arg));
else if (requires_tmpl_type)
- error (" expected a class template, got %qE", arg);
+ error (" expected a class template, got %qE", orig_arg);
else
- error (" expected a type, got %qE", arg);
+ error (" expected a type, got %qE", orig_arg);
}
}
return error_mark_node;
if (is_tmpl_type)
error (" expected a type, got %qT", DECL_NAME (arg));
else
- error (" expected a class template, got %qT", arg);
+ error (" expected a class template, got %qT", orig_arg);
}
return error_mark_node;
}
tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
tree argparm;
- check_arg = arg;
- /* When determining whether a pack expansion is a template,
- look at the pattern. */
- if (TREE_CODE (check_arg) == TYPE_PACK_EXPANSION)
- check_arg = PACK_EXPANSION_PATTERN (check_arg);
-
- argparm = DECL_INNERMOST_TEMPLATE_PARMS (check_arg);
+ argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
if (coerce_template_template_parms (parmparm, argparm,
complain, in_decl,
args))
{
- val = arg;
+ val = orig_arg;
/* TEMPLATE_TEMPLATE_PARM node is preferred over
TEMPLATE_DECL. */
if (DECL_TEMPLATE_TEMPLATE_PARM_P (val))
val = TREE_TYPE (val);
else if (TREE_CODE (val) == TYPE_PACK_EXPANSION
- && DECL_TEMPLATE_TEMPLATE_PARM_P (check_arg))
+ && DECL_TEMPLATE_TEMPLATE_PARM_P (arg))
{
- val = TREE_TYPE (check_arg);
+ val = TREE_TYPE (arg);
val = make_pack_expansion (val);
}
}
"template parameter list for %qD",
i + 1, in_decl);
error (" expected a template of type %qD, got %qD",
- parm, arg);
+ parm, orig_arg);
}
val = error_mark_node;
}
}
else
- val = arg;
+ val = orig_arg;
/* We only form one instance of each template specialization.
Therefore, if we use a non-canonical variant (i.e., a
typedef), any future messages referring to the type will use
if (invalid_nontype_parm_type_p (t, complain))
return error_mark_node;
- if (!uses_template_parms (arg) && !uses_template_parms (t))
+ 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
conversions can occur is part of determining which
function template to call, or whether a given explicit
argument specification is valid. */
- val = convert_nontype_argument (t, arg);
+ val = convert_nontype_argument (t, orig_arg);
else
- val = arg;
+ val = orig_arg;
if (val == NULL_TREE)
val = error_mark_node;
else if (val == error_mark_node && (complain & tf_error))
- error ("could not convert template argument %qE to %qT", arg, t);
+ error ("could not convert template argument %qE to %qT", orig_arg, t);
}
return val;
}
+/* Coerces the remaining template arguments in INNER_ARGS (from
+ ARG_IDX to the end) into the parameter pack at PARM_IDX in PARMS.
+ Returns the coerced argument pack. PARM_IDX is the position of this
+ parameter in the template parameter list. ARGS is the original
+ template argument list. */
+static tree
+coerce_template_parameter_pack (tree parms,
+ int parm_idx,
+ tree args,
+ tree inner_args,
+ int arg_idx,
+ tree new_args,
+ int* lost,
+ tree in_decl,
+ tsubst_flags_t complain)
+{
+ tree parm = TREE_VEC_ELT (parms, parm_idx);
+ int nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
+ tree packed_args;
+ tree argument_pack;
+ tree packed_types = NULL_TREE;
+
+ if (arg_idx > nargs)
+ arg_idx = nargs;
+
+ packed_args = make_tree_vec (nargs - arg_idx);
+
+ if (TREE_CODE (TREE_VALUE (parm)) == PARM_DECL
+ && uses_parameter_packs (TREE_TYPE (TREE_VALUE (parm))))
+ {
+ /* When the template parameter is a non-type template
+ parameter pack whose type uses parameter packs, we need
+ to look at each of the template arguments
+ separately. Build a vector of the types for these
+ non-type template parameters in PACKED_TYPES. */
+ tree expansion
+ = make_pack_expansion (TREE_TYPE (TREE_VALUE (parm)));
+ packed_types = tsubst_pack_expansion (expansion, args,
+ complain, in_decl);
+
+ if (packed_types == error_mark_node)
+ return error_mark_node;
+
+ /* Check that we have the right number of arguments. */
+ if (arg_idx < nargs
+ && !PACK_EXPANSION_P (TREE_VEC_ELT (inner_args, arg_idx))
+ && nargs - arg_idx != TREE_VEC_LENGTH (packed_types))
+ {
+ int needed_parms
+ = TREE_VEC_LENGTH (parms) - 1 + TREE_VEC_LENGTH (packed_types);
+ error ("wrong number of template arguments (%d, should be %d)",
+ nargs, needed_parms);
+ return error_mark_node;
+ }
+
+ /* If we aren't able to check the actual arguments now
+ (because they haven't been expanded yet), we can at least
+ verify that all of the types used for the non-type
+ template parameter pack are, in fact, valid for non-type
+ template parameters. */
+ if (arg_idx < nargs
+ && PACK_EXPANSION_P (TREE_VEC_ELT (inner_args, arg_idx)))
+ {
+ int j, len = TREE_VEC_LENGTH (packed_types);
+ for (j = 0; j < len; ++j)
+ {
+ tree t = TREE_VEC_ELT (packed_types, j);
+ if (invalid_nontype_parm_type_p (t, complain))
+ return error_mark_node;
+ }
+ }
+ }
+
+ /* Convert the remaining arguments, which will be a part of the
+ parameter pack "parm". */
+ for (; arg_idx < nargs; ++arg_idx)
+ {
+ tree arg = TREE_VEC_ELT (inner_args, arg_idx);
+ tree actual_parm = TREE_VALUE (parm);
+
+ if (packed_types && !PACK_EXPANSION_P (arg))
+ {
+ /* When we have a vector of types (corresponding to the
+ non-type template parameter pack that uses parameter
+ packs in its type, as mention above), and the
+ argument is not an expansion (which expands to a
+ currently unknown number of arguments), clone the
+ parm and give it the next type in PACKED_TYPES. */
+ actual_parm = copy_node (actual_parm);
+ TREE_TYPE (actual_parm) =
+ TREE_VEC_ELT (packed_types, arg_idx - parm_idx);
+ }
+
+ if (arg != error_mark_node)
+ arg = convert_template_argument (actual_parm,
+ arg, new_args, complain, parm_idx,
+ in_decl);
+ if (arg == error_mark_node)
+ (*lost)++;
+ TREE_VEC_ELT (packed_args, arg_idx - parm_idx) = arg;
+ }
+
+ if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL
+ || TREE_CODE (TREE_VALUE (parm)) == TEMPLATE_DECL)
+ argument_pack = make_node (TYPE_ARGUMENT_PACK);
+ else
+ {
+ argument_pack = make_node (NONTYPE_ARGUMENT_PACK);
+ TREE_TYPE (argument_pack)
+ = tsubst (TREE_TYPE (TREE_VALUE (parm)), new_args, complain, in_decl);
+ TREE_CONSTANT (argument_pack) = 1;
+ }
+
+ SET_ARGUMENT_PACK_ARGS (argument_pack, packed_args);
+ return argument_pack;
+}
+
/* Convert all template arguments to their appropriate types, and
return a vector containing the innermost resulting template
arguments. If any error occurs, return error_mark_node. Error and
bool require_all_args,
bool use_default_args)
{
- int nparms, nargs, i, lost = 0;
+ int nparms, nargs, parm_idx, arg_idx, lost = 0;
tree inner_args;
tree new_args;
tree new_inner_args;
variadic template parameter list. Since it's an int, we can also
subtract it from nparms to get the number of non-variadic
parameters. */
- int variadic_p = template_parms_variadic_p (parms) ? 1 : 0;
+ 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. */
+ for (parm_idx = 0; parm_idx < nparms; ++parm_idx)
+ {
+ tree tparm = TREE_VALUE (TREE_VEC_ELT (parms, parm_idx));
+ if (template_parameter_pack_p (tparm))
+ {
+ variadic_p = 1;
+ break;
+ }
+ }
+
if ((nargs > nparms - variadic_p && !variadic_p)
|| (nargs < nparms - variadic_p
&& require_all_args
skip_evaluation = false;
new_inner_args = make_tree_vec (nparms);
new_args = add_outermost_template_args (args, new_inner_args);
- for (i = 0; i < nparms - variadic_p; i++)
+ for (parm_idx = 0, arg_idx = 0; parm_idx < nparms; parm_idx++, arg_idx++)
{
tree arg;
tree parm;
/* Get the Ith template parameter. */
- parm = TREE_VEC_ELT (parms, i);
+ parm = TREE_VEC_ELT (parms, parm_idx);
if (parm == error_mark_node)
{
- TREE_VEC_ELT (new_inner_args, i) = error_mark_node;
+ TREE_VEC_ELT (new_inner_args, arg_idx) = error_mark_node;
continue;
}
- /* Calculate the Ith argument. */
- if (i < nargs)
+ /* Calculate the next argument. */
+ if (template_parameter_pack_p (TREE_VALUE (parm)))
{
- arg = TREE_VEC_ELT (inner_args, i);
-
- if (PACK_EXPANSION_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);
+
+ /* 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;
+
+ continue;
+ }
+ else if (arg_idx < nargs)
+ {
+ arg = TREE_VEC_ELT (inner_args, arg_idx);
+
+ if (arg && PACK_EXPANSION_P (arg))
{
- /* If ARG is a pack expansion, then PARM must be
- a template parameter pack. We can't expand into a
- fixed-length argument list. */
- tree actual_parm = TREE_VALUE (parm);
- bool parm_is_parameter_pack
- = template_parameter_pack_p (actual_parm);
-
- if (!parm_is_parameter_pack)
- {
- if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
- error ("cannot expand %<%E%> into a fixed-length "
- "argument list", arg);
- else
- error ("cannot expand %<%T%> into a fixed-length "
- "argument list", arg);
- }
+ if (complain & tf_error)
+ {
+ /* 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 "
+ "argument list", arg);
+ else
+ error ("cannot expand %<%T%> into a fixed-length "
+ "argument list", arg);
+ }
+ return error_mark_node;
}
}
else if (require_all_args)
- /* There must be a default arg in this case. */
- arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,
- complain, in_decl);
+ /* There must be a default arg in this case. */
+ arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,
+ complain, in_decl);
else
break;
- gcc_assert (arg);
if (arg == error_mark_node)
{
if (complain & tf_error)
- error ("template argument %d is invalid", i + 1);
- }
+ error ("template argument %d is invalid", arg_idx + 1);
+ }
+ else if (!arg)
+ /* This only occurs if there was an error in the template
+ parameter list itself (which we would already have
+ reported) that we are trying to recover from, e.g., a class
+ template with a parameter list such as
+ template<typename..., typename>. */
+ return error_mark_node;
else
arg = convert_template_argument (TREE_VALUE (parm),
- arg, new_args, complain, i,
- in_decl);
+ arg, new_args, complain,
+ parm_idx, in_decl);
if (arg == error_mark_node)
lost++;
- TREE_VEC_ELT (new_inner_args, i) = arg;
+ TREE_VEC_ELT (new_inner_args, arg_idx) = arg;
}
skip_evaluation = saved_skip_evaluation;
- if (variadic_p)
- {
- int expected_len = nargs - nparms + 1;
- tree parm = TREE_VEC_ELT (parms, nparms - 1);
- tree packed_args;
- tree argument_pack;
- tree packed_types = NULL_TREE;
-
- packed_args = make_tree_vec (expected_len >= 0 ? expected_len : 0);
-
- if (TREE_CODE (TREE_VALUE (parm)) == PARM_DECL
- && uses_parameter_packs (TREE_TYPE (TREE_VALUE (parm))))
- {
- /* When the template parameter is a non-type template
- parameter pack whose type uses parameter packs, we need
- to look at each of the template arguments
- separately. Build a vector of the types for these
- non-type template parameters in PACKED_TYPES. */
- tree expansion
- = make_pack_expansion (TREE_TYPE (TREE_VALUE (parm)));
- packed_types = tsubst_pack_expansion (expansion, args,
- complain, in_decl);
-
- if (packed_types == error_mark_node)
- return error_mark_node;
-
- /* Check that we have the right number of arguments. */
- if (i < nargs
- && !PACK_EXPANSION_P (TREE_VEC_ELT (inner_args, i))
- && nargs - i != TREE_VEC_LENGTH (packed_types))
- {
- error ("wrong number of template arguments (%d, should be %d)",
- nargs, nparms - 1 + TREE_VEC_LENGTH (packed_types));
- return error_mark_node;
- }
-
- /* If we aren't able to check the actual arguments now
- (because they haven't been expanded yet), we can at least
- verify that all of the types used for the non-type
- template parameter pack are, in fact, valid for non-type
- template parameters. */
- if (i < nargs && PACK_EXPANSION_P (TREE_VEC_ELT (inner_args, i)))
- {
- int j, len = TREE_VEC_LENGTH (packed_types);
- for (j = 0; j < len; ++j)
- {
- tree t = TREE_VEC_ELT (packed_types, j);
- if (invalid_nontype_parm_type_p (t, complain))
- return error_mark_node;
- }
- }
- }
-
- /* Convert the remaining arguments, which will be a part of the
- parameter pack "parm". */
- for (; i < nargs; ++i)
- {
- tree arg = TREE_VEC_ELT (inner_args, i);
- tree actual_parm = TREE_VALUE (parm);
-
- if (packed_types && !PACK_EXPANSION_P (arg))
- {
- /* When we have a vector of types (corresponding to the
- non-type template parameter pack that uses parameter
- packs in its type, as mention above), and the
- argument is not an expansion (which expands to a
- currently unknown number of arguments), clone the
- parm and give it the next type in PACKED_TYPES. */
- actual_parm = copy_node (actual_parm);
- TREE_TYPE (actual_parm) =
- TREE_VEC_ELT (packed_types, i - nparms + 1);
- }
-
- arg = convert_template_argument (actual_parm,
- arg, new_args, complain, i,
- in_decl);
- if (arg == error_mark_node)
- lost++;
- TREE_VEC_ELT (packed_args, i - nparms + 1) = arg;
- }
-
- if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL
- || TREE_CODE (TREE_VALUE (parm)) == TEMPLATE_DECL)
- argument_pack = make_node (TYPE_ARGUMENT_PACK);
- else
- {
- argument_pack = make_node (NONTYPE_ARGUMENT_PACK);
- TREE_TYPE (argument_pack) = TREE_TYPE (TREE_VALUE (parm));
- TREE_CONSTANT (argument_pack) = 1;
- }
-
- SET_ARGUMENT_PACK_ARGS (argument_pack, packed_args);
- TREE_VEC_ELT (new_inner_args, nparms - 1) = argument_pack;
- }
-
if (lost)
return error_mark_node;
tree ti = (TYPE_P (d)
? CLASSTYPE_TEMPLATE_INFO (d)
: DECL_TEMPLATE_INFO (d));
- tree pt;
+ struct pending_template *pt;
int level;
if (TI_PENDING_TEMPLATE_FLAG (ti))
/* We are called both from instantiate_decl, where we've already had a
tinst_level pushed, and instantiate_template, where we haven't.
Compensate. */
- level = !(current_tinst_level && TINST_DECL (current_tinst_level) == d);
+ level = !current_tinst_level || current_tinst_level->decl != d;
if (level)
push_tinst_level (d);
- pt = tree_cons (current_tinst_level, d, NULL_TREE);
+ pt = GGC_NEW (struct pending_template);
+ pt->next = NULL;
+ pt->tinst = current_tinst_level;
if (last_pending_template)
- TREE_CHAIN (last_pending_template) = pt;
+ last_pending_template->next = pt;
else
pending_templates = pt;
tree parm;
tree arglist2;
+ tree outer;
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
instantiation `TT<int>' is seen, we need to build the full
arguments containing {int} as the innermost level. Outer levels,
available when not appearing as default template argument, can be
- obtained from `current_template_args ()'.
+ obtained from the arguments of the enclosing template.
Suppose that TT is later substituted with std::vector. The above
instantiation is `TT<int, std::allocator<T> >' with TT at
level 1, and T at level 2, while the template arguments at level 1
becomes {std::vector} and the inner level 2 is {int}. */
- if (current_template_parms)
- arglist = add_to_template_args (current_template_args (), arglist);
+ outer = DECL_CONTEXT (template);
+ if (outer)
+ outer = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (outer)));
+ else if (current_template_parms)
+ /* This is an argument of the current template, so we haven't set
+ DECL_CONTEXT yet. */
+ outer = current_template_args ();
+
+ if (outer)
+ arglist = add_to_template_args (outer, arglist);
arglist2 = coerce_template_parms (parmlist, arglist, template,
complain,
{
tree_fn_t fn;
void *data;
+ /* True when we should also visit template parameters that occur in
+ non-deduced contexts. */
+ bool include_nondeduced_p;
struct pointer_set_t *visited;
};
void *data = pfd->data;
if (TYPE_P (t)
- && for_each_template_parm (TYPE_CONTEXT (t), fn, data, pfd->visited))
+ && (pfd->include_nondeduced_p || TREE_CODE (t) != TYPENAME_TYPE)
+ && for_each_template_parm (TYPE_CONTEXT (t), fn, data, pfd->visited,
+ pfd->include_nondeduced_p))
return error_mark_node;
switch (TREE_CODE (t))
if (!TYPE_TEMPLATE_INFO (t))
*walk_subtrees = 0;
else if (for_each_template_parm (TREE_VALUE (TYPE_TEMPLATE_INFO (t)),
- fn, data, pfd->visited))
+ fn, data, pfd->visited,
+ pfd->include_nondeduced_p))
return error_mark_node;
break;
case INTEGER_TYPE:
if (for_each_template_parm (TYPE_MIN_VALUE (t),
- fn, data, pfd->visited)
+ fn, data, pfd->visited,
+ pfd->include_nondeduced_p)
|| for_each_template_parm (TYPE_MAX_VALUE (t),
- fn, data, pfd->visited))
+ fn, data, pfd->visited,
+ pfd->include_nondeduced_p))
return error_mark_node;
break;
/* Since we're not going to walk subtrees, we have to do this
explicitly here. */
if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data,
- pfd->visited))
+ pfd->visited, pfd->include_nondeduced_p))
return error_mark_node;
/* Fall through. */
case FUNCTION_TYPE:
/* Check the return type. */
- if (for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited))
+ if (for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited,
+ pfd->include_nondeduced_p))
return error_mark_node;
/* Check the parameter types. Since default arguments are not
for (parm = TYPE_ARG_TYPES (t); parm; parm = TREE_CHAIN (parm))
if (for_each_template_parm (TREE_VALUE (parm), fn, data,
- pfd->visited))
+ pfd->visited, pfd->include_nondeduced_p))
return error_mark_node;
/* Since we've already handled the TYPE_ARG_TYPES, we don't
break;
case TYPEOF_TYPE:
- if (for_each_template_parm (TYPE_FIELDS (t), fn, data,
- pfd->visited))
+ if (pfd->include_nondeduced_p
+ && for_each_template_parm (TYPE_FIELDS (t), fn, data,
+ pfd->visited,
+ pfd->include_nondeduced_p))
return error_mark_node;
break;
case VAR_DECL:
if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)
&& for_each_template_parm (DECL_TI_ARGS (t), fn, data,
- pfd->visited))
+ pfd->visited, pfd->include_nondeduced_p))
return error_mark_node;
/* Fall through. */
case CONST_DECL:
if (TREE_CODE (t) == CONST_DECL && DECL_TEMPLATE_PARM_P (t)
&& for_each_template_parm (DECL_INITIAL (t), fn, data,
- pfd->visited))
+ pfd->visited, pfd->include_nondeduced_p))
return error_mark_node;
if (DECL_CONTEXT (t)
+ && pfd->include_nondeduced_p
&& for_each_template_parm (DECL_CONTEXT (t), fn, data,
- pfd->visited))
+ pfd->visited, pfd->include_nondeduced_p))
return error_mark_node;
break;
case BOUND_TEMPLATE_TEMPLATE_PARM:
/* Record template parameters such as `T' inside `TT<T>'. */
- if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data, pfd->visited))
+ if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data, pfd->visited,
+ pfd->include_nondeduced_p))
return error_mark_node;
/* Fall through. */
case TEMPLATE_DECL:
/* A template template parameter is encountered. */
if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)
- && for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited))
+ && for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited,
+ pfd->include_nondeduced_p))
return error_mark_node;
/* Already substituted template template parameter */
case TYPENAME_TYPE:
if (!fn
|| for_each_template_parm (TYPENAME_TYPE_FULLNAME (t), fn,
- data, pfd->visited))
+ data, pfd->visited,
+ pfd->include_nondeduced_p))
return error_mark_node;
break;
case CONSTRUCTOR:
if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))
+ && pfd->include_nondeduced_p
&& for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE
(TREE_TYPE (t)), fn, data,
- pfd->visited))
+ pfd->visited, pfd->include_nondeduced_p))
return error_mark_node;
break;
for_each_template_parm returns 1. Otherwise, the iteration
continues. If FN never returns a nonzero value, the value
returned by for_each_template_parm is 0. If FN is NULL, it is
- considered to be the function which always returns 1. */
+ considered to be the function which always returns 1.
+
+ If INCLUDE_NONDEDUCED_P, then this routine will also visit template
+ parameters that occur in non-deduced contexts. When false, only
+ visits those template parameters that can be deduced. */
static int
for_each_template_parm (tree t, tree_fn_t fn, void* data,
- struct pointer_set_t *visited)
+ struct pointer_set_t *visited,
+ bool include_nondeduced_p)
{
struct pair_fn_data pfd;
int result;
/* Set up. */
pfd.fn = fn;
pfd.data = data;
+ pfd.include_nondeduced_p = include_nondeduced_p;
/* Walk the tree. (Conceptually, we would like to walk without
duplicates, but for_each_template_parm_r recursively calls
pfd.visited = visited;
else
pfd.visited = pointer_set_create ();
- result = walk_tree (&t,
- for_each_template_parm_r,
- &pfd,
- pfd.visited) != NULL_TREE;
+ result = cp_walk_tree (&t,
+ for_each_template_parm_r,
+ &pfd,
+ pfd.visited) != NULL_TREE;
/* Clean up. */
if (!visited)
|| TREE_CODE (t) == OVERLOAD
|| TREE_CODE (t) == BASELINK
|| TREE_CODE (t) == IDENTIFIER_NODE
+ || TREE_CODE (t) == TRAIT_EXPR
|| CONSTANT_CLASS_P (t))
dependent_p = (type_dependent_expression_p (t)
|| value_dependent_expression_p (t));
int
uses_template_parms_level (tree t, int level)
{
- return for_each_template_parm (t, template_parm_this_level_p, &level, NULL);
+ return for_each_template_parm (t, template_parm_this_level_p, &level, NULL,
+ /*include_nondeduced_p=*/true);
}
static int tinst_depth;
static int
push_tinst_level (tree d)
{
- tree new;
+ struct tinst_level *new;
if (tinst_depth >= max_tinst_depth)
{
return 0;
}
- new = make_node (TINST_LEVEL);
- TINST_DECL (new) = d;
- TINST_LOCATION (new) = input_location;
- TINST_IN_SYSTEM_HEADER_P (new) = in_system_header;
- TREE_CHAIN (new) = current_tinst_level;
+ 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;
++tinst_depth;
static void
pop_tinst_level (void)
{
- tree old = current_tinst_level;
-
/* Restore the filename and line number stashed away when we started
this instantiation. */
- input_location = TINST_LOCATION (old);
- in_system_header = TINST_IN_SYSTEM_HEADER_P (old);
- current_tinst_level = TREE_CHAIN (old);
+ 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;
}
/* We're instantiating a deferred template; restore the template
instantiation context in which the instantiation was requested, which
- is one step out from LEVEL. */
+ is one step out from LEVEL. Return the corresponding DECL or TYPE. */
-static void
-reopen_tinst_level (tree level)
+static tree
+reopen_tinst_level (struct tinst_level *level)
{
- tree t;
+ struct tinst_level *t;
tinst_depth = 0;
- for (t = level; t; t = TREE_CHAIN (t))
+ for (t = level; t; t = t->next)
++tinst_depth;
current_tinst_level = level;
pop_tinst_level ();
+ return level->decl;
+}
+
+/* Returns the TINST_LEVEL which gives the original instantiation
+ context. */
+
+struct tinst_level *
+outermost_tinst_level (void)
+{
+ struct tinst_level *level = current_tinst_level;
+ if (level)
+ while (level->next)
+ level = level->next;
+ return level;
}
/* DECL is a friend FUNCTION_DECL or TEMPLATE_DECL. ARGS is the
> TMPL_ARGS_DEPTH (args))
{
tree parms;
+ location_t saved_input_location;
parms = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_tmpl),
args, tf_warning_or_error);
+
+ saved_input_location = input_location;
+ input_location = DECL_SOURCE_LOCATION (friend_tmpl);
redeclare_class_template (TREE_TYPE (tmpl), parms);
+ input_location = saved_input_location;
+
}
friend_type = TREE_TYPE (tmpl);
return 1;
}
+/* Apply any attributes which had to be deferred until instantiation
+ time. DECL_P, ATTRIBUTES and ATTR_FLAGS are as cplus_decl_attributes;
+ ARGS, COMPLAIN, IN_DECL are as tsubst. */
+
+static void
+apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
+ tree args, tsubst_flags_t complain, tree in_decl)
+{
+ tree last_dep = NULL_TREE;
+ tree t;
+ tree *p;
+
+ for (t = attributes; t; t = TREE_CHAIN (t))
+ if (ATTR_IS_DEPENDENT (t))
+ {
+ last_dep = t;
+ attributes = copy_list (attributes);
+ break;
+ }
+
+ if (DECL_P (*decl_p))
+ {
+ if (TREE_TYPE (*decl_p) == error_mark_node)
+ return;
+ p = &DECL_ATTRIBUTES (*decl_p);
+ }
+ else
+ p = &TYPE_ATTRIBUTES (*decl_p);
+
+ if (last_dep)
+ {
+ tree late_attrs = NULL_TREE;
+ tree *q = &late_attrs;
+
+ for (*p = attributes; *p; )
+ {
+ t = *p;
+ if (ATTR_IS_DEPENDENT (t))
+ {
+ *p = TREE_CHAIN (t);
+ TREE_CHAIN (t) = NULL_TREE;
+ TREE_VALUE (t)
+ = tsubst_expr (TREE_VALUE (t), args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+ *q = t;
+ q = &TREE_CHAIN (t);
+ }
+ else
+ p = &TREE_CHAIN (t);
+ }
+
+ cplus_decl_attributes (decl_p, late_attrs, attr_flags);
+ }
+}
+
tree
instantiate_class_template (tree type)
{
input_location = DECL_SOURCE_LOCATION (typedecl);
in_system_header = DECL_IN_SYSTEM_HEADER (typedecl);
- TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern);
+ TYPE_HAS_USER_CONSTRUCTOR (type) = TYPE_HAS_USER_CONSTRUCTOR (pattern);
TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);
TYPE_HAS_ARRAY_NEW_OPERATOR (type) = TYPE_HAS_ARRAY_NEW_OPERATOR (pattern);
TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);
information. */
xref_basetypes (type, base_list);
+ apply_late_template_attributes (&type, TYPE_ATTRIBUTES (pattern),
+ (int) ATTR_FLAG_TYPE_IN_PLACE,
+ args, tf_error, NULL_TREE);
/* Now that our base classes are set up, enter the scope of the
class, so that name lookups into base classes, etc. will work
correctly. This is precisely analogous to what we do in
begin_class_definition when defining an ordinary non-template
- class. */
- pushclass (type);
+ class, except we also need to push the enclosing classes. */
+ push_nested_class (type);
/* Now members are processed in the order of declaration. */
for (member = CLASSTYPE_DECL_LIST (pattern);
&& DECL_TEMPLATE_INFO (t))
tsubst_default_arguments (t);
- popclass ();
+ pop_nested_class ();
pop_from_top_level ();
pop_deferring_access_checks ();
pop_tinst_level ();
tree orig_arg = NULL_TREE;
if (TREE_CODE (parm_pack) == PARM_DECL)
- {
- if (local_specializations)
- arg_pack = retrieve_local_specialization (parm_pack);
- }
+ arg_pack = retrieve_local_specialization (parm_pack);
else
{
int level, idx, levels;
if (arg_pack && TREE_CODE (arg_pack) == ARGUMENT_PACK_SELECT)
arg_pack = ARGUMENT_PACK_SELECT_FROM_PACK (arg_pack);
+ if (arg_pack && !ARGUMENT_PACK_P (arg_pack))
+ /* This can only happen if we forget to expand an argument
+ pack somewhere else. Just return an error, silently. */
+ {
+ result = make_tree_vec (1);
+ TREE_VEC_ELT (result, 0) = error_mark_node;
+ return result;
+ }
+
+ if (arg_pack
+ && TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack)) == 1
+ && PACK_EXPANSION_P (TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack), 0)))
+ {
+ tree expansion = TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack), 0);
+ tree pattern = PACK_EXPANSION_PATTERN (expansion);
+ if ((TYPE_P (pattern) && same_type_p (pattern, parm_pack))
+ || (!TYPE_P (pattern) && cp_tree_equal (parm_pack, pattern)))
+ /* The argument pack that the parameter maps to is just an
+ expansion of the parameter itself, such as one would
+ find in the implicit typedef of a class inside the
+ class itself. Consider this parameter "unsubstituted",
+ so that we will maintain the outer pack expansion. */
+ arg_pack = NULL_TREE;
+ }
+
if (arg_pack)
{
int my_len =
/* Else fall through. */
case ENUMERAL_TYPE:
case UNION_TYPE:
- if (TYPE_TEMPLATE_INFO (t))
+ if (TYPE_TEMPLATE_INFO (t) && uses_template_parms (t))
{
tree argvec;
tree context;
up. */
context = TYPE_CONTEXT (t);
if (context)
- context = tsubst_aggr_type (context, args, complain,
- in_decl, /*entering_scope=*/1);
+ {
+ context = tsubst_aggr_type (context, args, complain,
+ in_decl, /*entering_scope=*/1);
+ /* If context is a nested class inside a class template,
+ it may still need to be instantiated (c++/33959). */
+ if (TYPE_P (context))
+ context = complete_type (context);
+ }
/* Then, figure out what arguments are appropriate for the
type we are trying to find. For example, given:
= remove_attribute ("visibility", DECL_ATTRIBUTES (r));
}
determine_visibility (r);
+
+ apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+ args, complain, in_decl);
}
break;
/* If there is a local specialization that isn't a
parameter pack, it means that we're doing a "simple"
substitution from inside tsubst_pack_expansion. Just
- return the local specialiation (which will be a single
+ return the local specialization (which will be a single
parm). */
- tree spec = NULL_TREE;
- if (local_specializations)
- spec = retrieve_local_specialization (t);
+ tree spec = retrieve_local_specialization (t);
if (spec
&& TREE_CODE (spec) == PARM_DECL
&& TREE_CODE (TREE_TYPE (spec)) != TYPE_PACK_EXPANSION)
if (!DECL_TEMPLATE_PARM_P (r))
DECL_ARG_TYPE (r) = type_passed_as (type);
+ apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+ args, complain, in_decl);
+
/* Keep track of the first new parameter we
generate. That's what will be returned to the
caller. */
TREE_CHAIN (r) = NULL_TREE;
if (VOID_TYPE_P (type))
error ("instantiation of %q+D as type %qT", r, type);
+
+ apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+ args, complain, in_decl);
}
break;
tree type = NULL_TREE;
bool local_p;
- if (TREE_CODE (t) == TYPE_DECL)
+ if (TREE_CODE (t) == TYPE_DECL
+ && t == TYPE_MAIN_DECL (TREE_TYPE (t)))
{
+ /* If this is the canonical decl, we don't have to
+ mess with instantiations, and often we can't (for
+ typename, template type parms and such). Note that
+ TYPE_NAME is not correct for the above test if
+ we've copied the type for a typedef. */
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
- if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
- || t == TYPE_MAIN_DECL (TREE_TYPE (t)))
- {
- /* If this is the canonical decl, we don't have to
- mess with instantiations, and often we can't (for
- typename, template type parms and such). Note that
- TYPE_NAME is not correct for the above test if
- we've copied the type for a typedef. */
- r = TYPE_NAME (type);
- break;
- }
+ if (type == error_mark_node)
+ return error_mark_node;
+ r = TYPE_NAME (type);
+ break;
}
/* Check to see if we already have the specialization we
/* Create a new node for the specialization we need. */
r = copy_decl (t);
+ if (type == NULL_TREE)
+ type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (TREE_CODE (r) == VAR_DECL)
{
/* Even if the original location is out of scope, the
DECL_DEAD_FOR_LOCAL (r) = 0;
DECL_INITIALIZED_P (r) = 0;
DECL_TEMPLATE_INSTANTIATED (r) = 0;
- type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node)
return error_mark_node;
if (TREE_CODE (type) == FUNCTION_TYPE)
}
determine_visibility (r);
}
+ /* Preserve a typedef that names a type. */
+ else if (TREE_CODE (r) == TYPE_DECL
+ && DECL_ORIGINAL_TYPE (t)
+ && type != error_mark_node)
+ {
+ DECL_ORIGINAL_TYPE (r) = tsubst (DECL_ORIGINAL_TYPE (t),
+ args, complain, in_decl);
+ TREE_TYPE (r) = type = build_variant_type_copy (type);
+ TYPE_NAME (type) = r;
+ }
if (!local_p)
{
register_local_specialization (r, t);
TREE_CHAIN (r) = NULL_TREE;
+
+ apply_late_template_attributes (&r, DECL_ATTRIBUTES (r),
+ (int) ATTR_FLAG_TYPE_IN_PLACE,
+ args, complain, in_decl);
layout_decl (r, 0);
}
break;
&& in_decl != NULL_TREE
&& !TREE_NO_WARNING (in_decl)
&& (SCALAR_TYPE_P (return_type) || VOID_TYPE_P (return_type)))
- warning (OPT_Wreturn_type,
+ warning (OPT_Wignored_qualifiers,
"type qualifiers ignored on function return type");
/* Construct a new type node and return it. */
expanded_specs = tsubst_pack_expansion (TREE_VALUE (specs),
args, complain,
in_decl);
- len = TREE_VEC_LENGTH (expanded_specs);
+
+ if (expanded_specs == error_mark_node)
+ return error_mark_node;
+ else if (TREE_CODE (expanded_specs) == TREE_VEC)
+ len = TREE_VEC_LENGTH (expanded_specs);
+ else
+ {
+ /* We're substituting into a member template, so
+ we got a TYPE_PACK_EXPANSION back. Add that
+ expansion and move on. */
+ gcc_assert (TREE_CODE (expanded_specs)
+ == TYPE_PACK_EXPANSION);
+ new_specs = add_exception_specifier (new_specs,
+ expanded_specs,
+ complain);
+ specs = TREE_CHAIN (specs);
+ continue;
+ }
}
for (i = 0; i < len; ++i)
gcc_assert (type != unknown_type_node);
+ /* Reuse typedefs. We need to do this to handle dependent attributes,
+ such as attribute aligned. */
+ if (TYPE_P (t)
+ && TYPE_NAME (t)
+ && TYPE_NAME (t) != TYPE_MAIN_DECL (t))
+ {
+ tree decl = TYPE_NAME (t);
+
+ if (DECL_CLASS_SCOPE_P (decl)
+ && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
+ && uses_template_parms (DECL_CONTEXT (decl)))
+ {
+ 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);
+ }
+ else if (DECL_FUNCTION_SCOPE_P (decl)
+ && DECL_TEMPLATE_INFO (DECL_CONTEXT (decl))
+ && uses_template_parms (DECL_TI_ARGS (DECL_CONTEXT (decl))))
+ r = retrieve_local_specialization (decl);
+ else
+ /* The typedef is from a non-template context. */
+ return t;
+
+ if (r)
+ {
+ r = TREE_TYPE (r);
+ r = cp_build_qualified_type_real
+ (r, cp_type_quals (t) | cp_type_quals (r),
+ complain | tf_ignore_bad_quals);
+ return r;
+ }
+ /* Else we must be instantiating the typedef, so fall through. */
+ }
+
if (type
&& TREE_CODE (t) != TYPENAME_TYPE
&& TREE_CODE (t) != IDENTIFIER_NODE
/*integral_constant_expression_p=*/false);
max = fold_decl_constant_value (max);
- if (TREE_CODE (max) != INTEGER_CST
- && TREE_CODE (max) != TEMPLATE_PARM_INDEX
- && !at_function_scope_p ())
+ if (TREE_CODE (max) != INTEGER_CST
+ && !at_function_scope_p ()
+ && !value_dependent_expression_p (max))
{
if (complain & tf_error)
error ("array bound is not an integer constant");
r = NULL_TREE;
gcc_assert (TREE_VEC_LENGTH (args) > 0);
- if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
- || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
- || TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
- {
- idx = TEMPLATE_TYPE_IDX (t);
- level = TEMPLATE_TYPE_LEVEL (t);
- }
- else
- {
- idx = TEMPLATE_PARM_IDX (t);
- level = TEMPLATE_PARM_LEVEL (t);
- }
+ template_parm_level_and_index (t, &level, &idx);
levels = TMPL_ARGS_DEPTH (args);
if (level <= levels)
r = copy_type (t);
TEMPLATE_TYPE_PARM_INDEX (r)
= reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
- r, levels);
+ r, levels, args, complain);
TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
TYPE_MAIN_VARIANT (r) = r;
TYPE_POINTER_TO (r) = NULL_TREE;
break;
case TEMPLATE_PARM_INDEX:
- r = reduce_template_parm_level (t, type, levels);
+ r = reduce_template_parm_level (t, type, levels, args, complain);
break;
default:
-- Attempting to create a pointer to reference type.
-- Attempting to create a reference to a reference type or
- a reference to void. */
- if (TREE_CODE (type) == REFERENCE_TYPE
+ a reference to void.
+
+ Core issue 106 says that creating a reference to a reference
+ during instantiation is no longer a cause for failure. We
+ only enforce this check in strict C++98 mode. */
+ if ((TREE_CODE (type) == REFERENCE_TYPE
+ && (((cxx_dialect == cxx98) && flag_iso) || code != REFERENCE_TYPE))
|| (code == REFERENCE_TYPE && TREE_CODE (type) == VOID_TYPE))
{
static location_t last_loc;
message to avoid spewing a ton of messages during a
single bad template instantiation. */
if (complain & tf_error
-#ifdef USE_MAPPED_LOCATION
- && last_loc != input_location
-#else
- && (last_loc.line != input_line
- || last_loc.file != input_filename)
-#endif
- )
+ && last_loc != input_location)
{
if (TREE_CODE (type) == VOID_TYPE)
error ("forming reference to void");
if (TREE_CODE (type) == METHOD_TYPE)
r = build_ptrmemfunc_type (r);
}
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
+ /* In C++0x, during template argument substitution, when there is an
+ attempt to create a reference to a reference type, reference
+ collapsing is applied as described in [14.3.1/4 temp.arg.type]:
+
+ "If a template-argument for a template-parameter T names a type
+ that is a reference to a type A, an attempt to create the type
+ 'lvalue reference to cv T' creates the type 'lvalue reference to
+ A,' while an attempt to create the type type rvalue reference to
+ cv T' creates the type T"
+ */
+ r = cp_build_reference_type
+ (TREE_TYPE (type),
+ TYPE_REF_IS_RVALUE (t) && TYPE_REF_IS_RVALUE (type));
else
- r = build_reference_type (type);
+ r = cp_build_reference_type (type, TYPE_REF_IS_RVALUE (t));
r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
if (r != error_mark_node)
}
r = build_cplus_array_type (type, domain);
+
+ if (TYPE_USER_ALIGN (t))
+ {
+ TYPE_ALIGN (r) = TYPE_ALIGN (t);
+ TYPE_USER_ALIGN (r) = 1;
+ }
+
return r;
}
complain);
}
+ case DECLTYPE_TYPE:
+ {
+ tree type;
+
+ type =
+ finish_decltype_type (tsubst_expr
+ (DECLTYPE_TYPE_EXPR (t), args,
+ complain, in_decl,
+ /*integral_constant_expression_p=*/false),
+ DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t));
+ return cp_build_qualified_type_real (type,
+ cp_type_quals (t)
+ | cp_type_quals (type),
+ complain);
+ }
+
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
{
/* We only want to compute the number of arguments. */
tree expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args,
complain, in_decl);
+ if (expanded == error_mark_node)
+ return error_mark_node;
return build_int_cst (size_type_node, TREE_VEC_LENGTH (expanded));
}
/* Fall through */
case TYPENAME_TYPE:
case UNBOUND_CLASS_TEMPLATE:
case TYPEOF_TYPE:
+ case DECLTYPE_TYPE:
case TYPE_DECL:
return tsubst (t, args, complain, in_decl);
init = cp_fname_init (name, &TREE_TYPE (decl));
}
else
- init = RECUR (init);
+ {
+ tree t = RECUR (init);
+
+ if (init && !t)
+ /* If we had an initializer but it
+ instantiated to nothing,
+ value-initialize the object. This will
+ only occur when the initializer was a
+ pack expansion where the parameter packs
+ used in that expansion were of length
+ zero. */
+ init = build_default_init (TREE_TYPE (decl),
+ NULL_TREE);
+ else
+ init = t;
+ }
+
finish_decl (decl, init, NULL_TREE);
}
}
break;
case OMP_ATOMIC:
- if (OMP_ATOMIC_DEPENDENT_P (t))
- {
- tree op1 = TREE_OPERAND (t, 1);
- tree lhs = RECUR (TREE_OPERAND (op1, 0));
- tree rhs = RECUR (TREE_OPERAND (op1, 1));
- finish_omp_atomic (TREE_CODE (op1), lhs, rhs);
- }
+ gcc_assert (OMP_ATOMIC_DEPENDENT_P (t));
+ {
+ tree op1 = TREE_OPERAND (t, 1);
+ tree lhs = RECUR (TREE_OPERAND (op1, 0));
+ tree rhs = RECUR (TREE_OPERAND (op1, 1));
+ finish_omp_atomic (TREE_CODE (op1), lhs, rhs);
+ }
break;
case EXPR_PACK_EXPANSION:
/* We only want to compute the number of arguments. */
tree expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args,
complain, in_decl);
+ if (expanded == error_mark_node)
+ return error_mark_node;
return build_int_cst (size_type_node, TREE_VEC_LENGTH (expanded));
}
/* Fall through */
return build_x_arrow (op1);
case NEW_EXPR:
- return build_new
- (RECUR (TREE_OPERAND (t, 0)),
- RECUR (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2)),
- RECUR (TREE_OPERAND (t, 3)),
- NEW_EXPR_USE_GLOBAL (t));
+ {
+ tree init = RECUR (TREE_OPERAND (t, 3));
+
+ 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;
+
+ return build_new
+ (RECUR (TREE_OPERAND (t, 0)),
+ RECUR (TREE_OPERAND (t, 1)),
+ RECUR (TREE_OPERAND (t, 2)),
+ init,
+ NEW_EXPR_USE_GLOBAL (t));
+ }
case DELETE_EXPR:
return delete_sanity
if (object_type && !CLASS_TYPE_P (object_type))
{
- if (TREE_CODE (member) == BIT_NOT_EXPR)
- return finish_pseudo_destructor_expr (object,
- NULL_TREE,
- object_type);
- else if (TREE_CODE (member) == SCOPE_REF
- && (TREE_CODE (TREE_OPERAND (member, 1)) == BIT_NOT_EXPR))
- return finish_pseudo_destructor_expr (object,
- object,
- object_type);
+ if (SCALAR_TYPE_P (object_type))
+ {
+ tree s = NULL_TREE;
+ tree dtor = member;
+
+ if (TREE_CODE (dtor) == SCOPE_REF)
+ {
+ s = TREE_OPERAND (dtor, 0);
+ dtor = TREE_OPERAND (dtor, 1);
+ }
+ if (TREE_CODE (dtor) == BIT_NOT_EXPR)
+ {
+ dtor = TREE_OPERAND (dtor, 0);
+ if (TYPE_P (dtor))
+ return finish_pseudo_destructor_expr (object, s, dtor);
+ }
+ }
}
else if (TREE_CODE (member) == SCOPE_REF
&& TREE_CODE (TREE_OPERAND (member, 1)) == TEMPLATE_ID_EXPR)
ce->value = tsubst_pack_expansion (ce->value, args, complain,
in_decl);
- if (TREE_VEC_LENGTH (ce->value) == 1)
+ if (ce->value == error_mark_node)
+ ;
+ else if (TREE_VEC_LENGTH (ce->value) == 1)
/* Just move the argument into place. */
ce->value = TREE_VEC_ELT (ce->value, 0);
else
case OFFSETOF_EXPR:
return finish_offsetof (RECUR (TREE_OPERAND (t, 0)));
+ case TRAIT_EXPR:
+ {
+ tree type1 = tsubst_copy (TRAIT_EXPR_TYPE1 (t), args,
+ complain, in_decl);
+
+ tree type2 = TRAIT_EXPR_TYPE2 (t);
+ if (type2)
+ type2 = tsubst_copy (type2, args, complain, in_decl);
+
+ return finish_trait_expr (TRAIT_EXPR_KIND (t), type1, type2);
+ }
+
case STMT_EXPR:
{
tree old_stmt_expr = cur_stmt_expr;
/* Mark the argument pack as "incomplete". We could
still deduce more arguments during unification. */
targ = TMPL_ARG (converted_args, level, idx);
- ARGUMENT_PACK_INCOMPLETE_P(targ) = 1;
- ARGUMENT_PACK_EXPLICIT_ARGS (targ) = ARGUMENT_PACK_ARGS (targ);
+ if (targ)
+ {
+ ARGUMENT_PACK_INCOMPLETE_P(targ) = 1;
+ ARGUMENT_PACK_EXPLICIT_ARGS (targ)
+ = ARGUMENT_PACK_ARGS (targ);
+ }
/* We have some incomplete argument packs. */
incomplete_argument_packs_p = true;
}
}
+ /* Now that we have bindings for all of the template arguments,
+ ensure that the arguments deduced for the template template
+ parameters have compatible template parameter lists. We cannot
+ check this property before we have deduced all template
+ arguments, because the template parameter types of a template
+ template parameter might depend on prior template parameters
+ deduced after the template template parameter. The following
+ ill-formed example illustrates this issue:
+
+ template<typename T, template<T> class C> void f(C<5>, T);
+
+ template<int N> struct X {};
+
+ void g() {
+ f(X<5>(), 5l); // error: template argument deduction fails
+ }
+
+ The template parameter list of 'C' depends on the template type
+ parameter 'T', but 'C' is deduced to 'X' before 'T' is deduced to
+ 'long'. Thus, we can't check that 'C' cannot bind to 'X' at the
+ time that we deduce 'C'. */
+ if (result == 0
+ && !template_template_parm_bindings_ok_p
+ (DECL_INNERMOST_TEMPLATE_PARMS (fn), targs))
+ return 1;
+
if (result == 0)
/* All is well so far. Now, check:
sections are symmetric. PARM is the type of a function parameter
or the return type of the conversion function. ARG is the type of
the argument passed to the call, or the type of the value
- initialized with the result of the conversion function. */
+ initialized with the result of the conversion function.
+ ARG_EXPR is the original argument expression, which may be null. */
static int
maybe_adjust_types_for_deduction (unification_kind_t strict,
tree* parm,
- tree* arg)
+ tree* arg,
+ tree arg_expr)
{
int result = 0;
*arg = TYPE_MAIN_VARIANT (*arg);
}
+ /* From C++0x [14.8.2.1/3 temp.deduct.call] (after DR606), "If P is
+ of the form T&&, where T is a template parameter, and the argument
+ is an lvalue, T is deduced as A& */
+ if (TREE_CODE (*parm) == REFERENCE_TYPE
+ && TYPE_REF_IS_RVALUE (*parm)
+ && TREE_CODE (TREE_TYPE (*parm)) == TEMPLATE_TYPE_PARM
+ && cp_type_quals (TREE_TYPE (*parm)) == TYPE_UNQUALIFIED
+ && arg_expr && real_lvalue_p (arg_expr))
+ *arg = build_reference_type (*arg);
+
/* [temp.deduct.call]
If P is a cv-qualified type, the top level cv-qualifiers
unification_kind_t strict,
int flags)
{
- tree parm, arg;
+ tree parm, arg, arg_expr;
int i;
int ntparms = TREE_VEC_LENGTH (tparms);
int sub_strict;
parms = TREE_CHAIN (parms);
arg = TREE_VALUE (args);
args = TREE_CHAIN (args);
+ arg_expr = NULL;
if (arg == error_mark_node)
return 1;
gcc_assert (TREE_TYPE (arg) != NULL_TREE);
if (type_unknown_p (arg))
{
- /* [temp.deduct.type] A template-argument can be deduced from
- a pointer to function or pointer to member function
- argument if the set of overloaded functions does not
- contain function templates and at most one of a set of
- overloaded functions provides a unique match. */
+ /* [temp.deduct.type]
+ A template-argument can be deduced from a pointer to
+ function or pointer to member function argument if
+ the set of overloaded functions does not contain
+ function templates and at most one of a set of
+ overloaded functions provides a unique match. */
if (resolve_overloaded_unification
- (tparms, targs, parm, arg, strict, sub_strict)
- != 0)
- return 1;
- continue;
+ (tparms, targs, parm, arg, strict, sub_strict))
+ continue;
+
+ return 1;
}
- arg = TREE_TYPE (arg);
+ arg_expr = arg;
+ arg = unlowered_expr_type (arg);
if (arg == error_mark_node)
return 1;
}
int arg_strict = sub_strict;
if (!subr)
- arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg);
+ arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg,
+ arg_expr);
if (unify (tparms, targs, parm, arg, arg_strict))
return 1;
&& !saw_undeduced++)
goto again;
+ /* Core issue #226 (C++0x) [temp.deduct]:
+
+ If a template argument has not been deduced, its
+ default template argument, if any, is used.
+
+ When we are in C++98 mode, TREE_PURPOSE will either
+ be NULL_TREE or ERROR_MARK_NODE, so we do not need
+ 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);
+ if (arg == error_mark_node)
+ return 1;
+ else
+ {
+ TREE_VEC_ELT (targs, i) = arg;
+ continue;
+ }
+ }
+
+ /* If the type parameter is a parameter pack, then it will
+ be deduced to an empty parameter pack. */
+ if (template_parameter_pack_p (tparm))
+ {
+ tree arg;
+
+ if (TREE_CODE (tparm) == TEMPLATE_PARM_INDEX)
+ {
+ arg = make_node (NONTYPE_ARGUMENT_PACK);
+ TREE_TYPE (arg) = TREE_TYPE (TEMPLATE_PARM_DECL (tparm));
+ TREE_CONSTANT (arg) = 1;
+ }
+ else
+ arg = make_node (TYPE_ARGUMENT_PACK);
+
+ SET_ARGUMENT_PACK_ARGS (arg, make_tree_vec (0));
+
+ TREE_VEC_ELT (targs, i) = arg;
+ continue;
+ }
+
return 2;
}
return 0;
}
-/* Subroutine of type_unification_real. Args are like the variables at the
- call site. ARG is an overloaded function (or template-id); we try
- deducing template args from each of the overloads, and if only one
- succeeds, we go with that. Modifies TARGS and returns 0 on success. */
+/* Subroutine of type_unification_real. Args are like the variables
+ at the call site. ARG is an overloaded function (or template-id);
+ we try deducing template args from each of the overloads, and if
+ only one succeeds, we go with that. Modifies TARGS and returns
+ true on success. */
-static int
+static bool
resolve_overloaded_unification (tree tparms,
tree targs,
tree parm,
if (TREE_CODE (fn) != TEMPLATE_DECL)
continue;
+ ++processing_template_decl;
subargs = get_bindings (fn, DECL_TEMPLATE_RESULT (fn),
expl_subargs, /*check_ret=*/false);
if (subargs)
good += try_one_overload (tparms, targs, tempargs, parm,
elem, strict, sub_strict, addr_p);
}
+ --processing_template_decl;
}
}
+ else if (TREE_CODE (arg) != OVERLOAD
+ && TREE_CODE (arg) != FUNCTION_DECL)
+ /* If ARG is, for example, "(0, &f)" then its type will be unknown
+ -- but the deduction does not succeed because the expression is
+ not just the function on its own. */
+ return false;
else
- {
- gcc_assert (TREE_CODE (arg) == OVERLOAD
- || TREE_CODE (arg) == FUNCTION_DECL);
-
- for (; arg; arg = OVL_NEXT (arg))
- good += try_one_overload (tparms, targs, tempargs, parm,
- TREE_TYPE (OVL_CURRENT (arg)),
- strict, sub_strict, addr_p);
- }
+ for (; arg; arg = OVL_NEXT (arg))
+ good += try_one_overload (tparms, targs, tempargs, parm,
+ TREE_TYPE (OVL_CURRENT (arg)),
+ strict, sub_strict, addr_p);
/* [temp.deduct.type] A template-argument can be deduced from a pointer
to function or pointer to member function argument if the set of
TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (tempargs, i);
}
if (good)
- return 0;
+ return true;
- return 1;
+ return false;
}
/* Subroutine of resolve_overloaded_unification; does deduction for a single
else if (addr_p)
arg = build_pointer_type (arg);
- sub_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg);
+ sub_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg, NULL);
/* We don't copy orig_targs for this because if we have already deduced
some template args from previous args, unify would complain when we
/* Unify the pattern with the current argument. */
{
tree arg = TREE_VEC_ELT (packed_args, i);
+ tree arg_expr = NULL_TREE;
int arg_strict = strict;
bool skip_arg_p = false;
if (!skip_arg_p)
{
- arg = TREE_TYPE (arg);
+ arg_expr = arg;
+ arg = unlowered_expr_type (arg);
if (arg == error_mark_node)
return 1;
}
if (!subr)
arg_strict |=
- maybe_adjust_types_for_deduction (strict, &parm, &arg);
+ maybe_adjust_types_for_deduction (strict, &parm, &arg,
+ arg_expr);
}
if (!skip_arg_p)
{
tree old_pack = TREE_VALUE (pack);
tree new_args = TREE_TYPE (pack);
+ int i, len = TREE_VEC_LENGTH (new_args);
+ bool nondeduced_p = false;
+
+ /* If NEW_ARGS contains any NULL_TREE entries, we didn't
+ actually deduce anything. */
+ for (i = 0; i < len && !nondeduced_p; ++i)
+ if (TREE_VEC_ELT (new_args, i) == NULL_TREE)
+ nondeduced_p = true;
+ if (nondeduced_p)
+ continue;
if (old_pack && ARGUMENT_PACK_INCOMPLETE_P (old_pack))
{
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0));
+ if (tparm == error_mark_node)
+ return 1;
if (TEMPLATE_TYPE_LEVEL (parm)
!= template_decl_level (tparm))
tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
tree argtmplvec
= DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (arg));
- int i;
+ int i, len;
+ int parm_variadic_p = 0;
/* The resolution to DR150 makes clear that default
arguments for an N-argument may not be used to bind T
rather than the whole TREE_VEC since they can have
different number of elements. */
- for (i = 0; i < TREE_VEC_LENGTH (parmvec); ++i)
+ parmvec = expand_template_argument_pack (parmvec);
+ argvec = expand_template_argument_pack (argvec);
+
+ len = TREE_VEC_LENGTH (parmvec);
+
+ /* Check if the parameters end in a pack, making them
+ variadic. */
+ if (len > 0
+ && PACK_EXPANSION_P (TREE_VEC_ELT (parmvec, len - 1)))
+ parm_variadic_p = 1;
+
+ if (TREE_VEC_LENGTH (argvec) < len - parm_variadic_p)
+ return 1;
+
+ for (i = 0; i < len - parm_variadic_p; ++i)
{
if (unify (tparms, targs,
TREE_VEC_ELT (parmvec, i),
UNIFY_ALLOW_NONE))
return 1;
}
+
+ if (parm_variadic_p
+ && unify_pack_expansion (tparms, targs,
+ parmvec, argvec,
+ UNIFY_ALLOW_NONE,
+ /*call_args_p=*/false,
+ /*subr=*/false))
+ return 1;
}
arg = TYPE_TI_TEMPLATE (arg);
int argslen = TREE_VEC_LENGTH (packed_args);
int parm_variadic_p = 0;
- /* Check if the parameters end in a pack, making them variadic. */
- if (len > 0
- && PACK_EXPANSION_P (TREE_VEC_ELT (packed_parms, len - 1)))
- parm_variadic_p = 1;
+ for (i = 0; i < len; ++i)
+ {
+ if (PACK_EXPANSION_P (TREE_VEC_ELT (packed_parms, i)))
+ {
+ if (i == len - 1)
+ /* We can unify against something with a trailing
+ parameter pack. */
+ parm_variadic_p = 1;
+ else
+ /* Since there is something following the pack
+ expansion, we cannot unify this template argument
+ list. */
+ return 0;
+ }
+ }
+
/* If we don't have enough arguments to satisfy the parameters
(not counting the pack expression at the end), or we have
break;
+ case TYPEOF_TYPE:
+ case DECLTYPE_TYPE:
+ /* Cannot deduce anything from TYPEOF_TYPE or DECLTYPE_TYPE
+ nodes. */
+ return 0;
+
+ case ERROR_MARK:
+ /* Unification fails if we hit an error node. */
+ return 1;
+
default:
gcc_assert (EXPR_P (parm));
if (TREE_CODE (arg1) == TYPE_PACK_EXPANSION)
{
- int i, len2 = len + 1;
+ int i, len2 = list_length (args2);
tree parmvec = make_tree_vec (1);
tree argvec = make_tree_vec (len2);
tree ta = args2;
}
else if (TREE_CODE (arg2) == TYPE_PACK_EXPANSION)
{
- int i, len1 = len + 1;
+ int i, len1 = list_length (args1);
tree parmvec = make_tree_vec (1);
tree argvec = make_tree_vec (len1);
tree ta = args1;
args1 = TREE_CHAIN (args1);
args2 = TREE_CHAIN (args2);
+
+ /* Stop when an ellipsis is seen. */
+ if (args1 == NULL_TREE || args2 == NULL_TREE)
+ break;
}
processing_template_decl--;
INNERMOST_TEMPLATE_ARGS (args)))
return NULL_TREE;
+ /* Now that we have bindings for all of the template arguments,
+ ensure that the arguments deduced for the template template
+ parameters have compatible template parameter lists. See the use
+ of template_template_parm_bindings_ok_p in fn_type_unification
+ for more information. */
+ if (!template_template_parm_bindings_ok_p (tparms, deduced_args))
+ return NULL_TREE;
+
return deduced_args;
}
int fate;
bool ambiguous_p;
tree args;
+ tree outer_args = NULL_TREE;
tmpl = most_general_template (tmpl);
args = CLASSTYPE_TI_ARGS (type);
+
+ /* For determining which partial specialization to use, only the
+ innermost args are interesting. */
+ if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
+ {
+ outer_args = strip_innermost_template_args (args, 1);
+ args = INNERMOST_TEMPLATE_ARGS (args);
+ }
+
for (t = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); t; t = TREE_CHAIN (t))
{
tree partial_spec_args;
tree spec_args;
+ tree parms = TREE_VALUE (t);
partial_spec_args = CLASSTYPE_TI_ARGS (TREE_TYPE (t));
- spec_args = get_class_bindings (TREE_VALUE (t),
+ if (outer_args)
+ {
+ int i;
+
+ ++processing_template_decl;
+
+ /* Discard the outer levels of args, and then substitute in the
+ template args from the enclosing class. */
+ partial_spec_args = INNERMOST_TEMPLATE_ARGS (partial_spec_args);
+ partial_spec_args = tsubst_template_args
+ (partial_spec_args, outer_args, tf_none, NULL_TREE);
+
+ /* PARMS already refers to just the innermost parms, but the
+ template parms in partial_spec_args had their levels lowered
+ by tsubst, so we need to do the same for the parm list. We
+ can't just tsubst the TREE_VEC itself, as tsubst wants to
+ treat a TREE_VEC as an argument vector. */
+ parms = copy_node (parms);
+ for (i = TREE_VEC_LENGTH (parms) - 1; i >= 0; --i)
+ TREE_VEC_ELT (parms, i) =
+ tsubst (TREE_VEC_ELT (parms, i), outer_args, tf_none, NULL_TREE);
+
+ --processing_template_decl;
+ }
+ spec_args = get_class_bindings (parms,
partial_spec_args,
args);
if (spec_args)
{
+ if (outer_args)
+ spec_args = add_to_template_args (outer_args, spec_args);
list = tree_cons (spec_args, TREE_VALUE (t), list);
TREE_TYPE (list) = TREE_TYPE (t);
}
VAR_DECLs so we do the lookup here. Probably, grokdeclarator
should handle VAR_DECLs as it currently handles
FUNCTION_DECLs. */
+ if (!DECL_CLASS_SCOPE_P (decl))
+ {
+ error ("%qD is not a static data member of a class template", decl);
+ return;
+ }
result = lookup_field (DECL_CONTEXT (decl), DECL_NAME (decl), 0, false);
if (!result || TREE_CODE (result) != VAR_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
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
tf_warning_or_error, tmpl,
/*integral_constant_expression_p=*/false);
+ /* Set the current input_location to the end of the function
+ so that finish_function knows where we are. */
+ input_location = DECL_STRUCT_FUNCTION (code_pattern)->function_end_locus;
+
/* We don't need the local specializations any more. */
htab_delete (local_specializations);
local_specializations = saved_local_specializations;
out:
input_location = saved_loc;
+ in_system_header = saved_in_system_header;
pop_deferring_access_checks ();
pop_tinst_level ();
void
instantiate_pending_templates (int retries)
{
- tree *t;
- tree last = NULL_TREE;
int reconsider;
location_t saved_loc = input_location;
int saved_in_system_header = in_system_header;
to avoid infinite loop. */
if (pending_templates && retries >= max_tinst_depth)
{
- tree decl = TREE_VALUE (pending_templates);
+ tree decl = pending_templates->tinst->decl;
error ("template instantiation depth exceeds maximum of %d"
" instantiating %q+D, possibly from virtual table generation"
do
{
+ struct pending_template **t = &pending_templates;
+ struct pending_template *last = NULL;
reconsider = 0;
-
- t = &pending_templates;
while (*t)
{
- tree instantiation = TREE_VALUE (*t);
-
- reopen_tinst_level (TREE_PURPOSE (*t));
+ tree instantiation = reopen_tinst_level ((*t)->tinst);
+ bool complete = false;
if (TYPE_P (instantiation))
{
reconsider = 1;
}
- if (COMPLETE_TYPE_P (instantiation))
- /* If INSTANTIATION has been instantiated, then we don't
- need to consider it again in the future. */
- *t = TREE_CHAIN (*t);
- else
- {
- last = *t;
- t = &TREE_CHAIN (*t);
- }
+ complete = COMPLETE_TYPE_P (instantiation);
}
else
{
reconsider = 1;
}
- if (DECL_TEMPLATE_SPECIALIZATION (instantiation)
- || DECL_TEMPLATE_INSTANTIATED (instantiation))
- /* If INSTANTIATION has been instantiated, then we don't
- need to consider it again in the future. */
- *t = TREE_CHAIN (*t);
- else
- {
- last = *t;
- t = &TREE_CHAIN (*t);
- }
+ complete = (DECL_TEMPLATE_SPECIALIZATION (instantiation)
+ || DECL_TEMPLATE_INSTANTIATED (instantiation));
+ }
+
+ if (complete)
+ /* If INSTANTIATION has been instantiated, then we don't
+ need to consider it again in the future. */
+ *t = (*t)->next;
+ else
+ {
+ last = *t;
+ t = &(*t)->next;
}
tinst_depth = 0;
- current_tinst_level = NULL_TREE;
+ current_tinst_level = NULL;
}
last_pending_template = last;
}
PACK_EXPANSION_PARAMETER_PACKS (expr) =
PACK_EXPANSION_PARAMETER_PACKS (TREE_PURPOSE (t));
- /* Substitute parameter packs into each argument in the
- TREE_LIST. */
- in_base_initializer = 1;
- for (arg = TREE_VALUE (t); arg; arg = TREE_CHAIN (arg))
- {
- tree expanded_exprs;
-
- /* Expand the argument. */
- SET_PACK_EXPANSION_PATTERN (expr, TREE_VALUE (arg));
- expanded_exprs = tsubst_pack_expansion (expr, argvec,
- tf_warning_or_error,
- NULL_TREE);
-
- /* Prepend each of the expanded expressions to the
- corresponding TREE_LIST in EXPANDED_ARGUMENTS. */
- for (i = 0; i < len; i++)
- {
- TREE_VEC_ELT (expanded_arguments, i) =
- tree_cons (NULL_TREE, TREE_VEC_ELT (expanded_exprs, i),
- TREE_VEC_ELT (expanded_arguments, i));
- }
- }
- in_base_initializer = 0;
+ if (TREE_VALUE (t) == void_type_node)
+ /* VOID_TYPE_NODE is used to indicate
+ value-initialization. */
+ {
+ for (i = 0; i < len; i++)
+ TREE_VEC_ELT (expanded_arguments, i) = void_type_node;
+ }
+ else
+ {
+ /* Substitute parameter packs into each argument in the
+ TREE_LIST. */
+ in_base_initializer = 1;
+ for (arg = TREE_VALUE (t); arg; arg = TREE_CHAIN (arg))
+ {
+ tree expanded_exprs;
+
+ /* Expand the argument. */
+ SET_PACK_EXPANSION_PATTERN (expr, TREE_VALUE (arg));
+ expanded_exprs
+ = tsubst_pack_expansion (expr, argvec,
+ tf_warning_or_error,
+ NULL_TREE);
+
+ /* Prepend each of the expanded expressions to the
+ corresponding TREE_LIST in EXPANDED_ARGUMENTS. */
+ for (i = 0; i < len; i++)
+ {
+ TREE_VEC_ELT (expanded_arguments, i) =
+ tree_cons (NULL_TREE,
+ TREE_VEC_ELT (expanded_exprs, i),
+ TREE_VEC_ELT (expanded_arguments, i));
+ }
+ }
+ in_base_initializer = 0;
- /* Reverse all of the TREE_LISTs in EXPANDED_ARGUMENTS,
- since we built them backwards. */
- for (i = 0; i < len; i++)
- {
- TREE_VEC_ELT (expanded_arguments, i) =
- nreverse (TREE_VEC_ELT (expanded_arguments, i));
- }
+ /* Reverse all of the TREE_LISTs in EXPANDED_ARGUMENTS,
+ since we built them backwards. */
+ for (i = 0; i < len; i++)
+ {
+ TREE_VEC_ELT (expanded_arguments, i) =
+ nreverse (TREE_VEC_ELT (expanded_arguments, i));
+ }
+ }
}
for (i = 0; i < len; ++i)
last_template_error_tick = tinst_level_tick;
}
-tree
+struct tinst_level *
current_instantiation (void)
{
return current_tinst_level;
if (TREE_CODE (type) == ARRAY_TYPE)
{
if (TYPE_DOMAIN (type)
- && ((value_dependent_expression_p
- (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
- || (type_dependent_expression_p
- (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))))
+ && dependent_type_p (TYPE_DOMAIN (type)))
return true;
return dependent_type_p (TREE_TYPE (type));
}
+ else if (TREE_CODE (type) == INTEGER_TYPE
+ && !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)));
+ }
/* -- a template-id in which either the template name is a template
parameter ... */
(INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type)))))
return true;
- /* All TYPEOF_TYPEs are dependent; if the argument of the `typeof'
- expression is not type-dependent, then it should already been
- have resolved. */
- if (TREE_CODE (type) == TYPEOF_TYPE)
+ /* All TYPEOF_TYPEs and DECLTYPE_TYPEs are dependent; if the
+ argument of the `typeof' expression is not type-dependent, then
+ it should already been have resolved. */
+ if (TREE_CODE (type) == TYPEOF_TYPE
+ || TREE_CODE (type) == DECLTYPE_TYPE)
return true;
/* A template argument pack is dependent if any of its packed
/* A non-type template parm. */
if (DECL_TEMPLATE_PARM_P (expression))
return true;
- return false;
+ return value_dependent_expression_p (DECL_INITIAL (expression));
case VAR_DECL:
/* A constant with integral or enumeration type and is initialized
}
if (TREE_CODE (expression) == TREE_LIST)
- {
- for (; expression; expression = TREE_CHAIN (expression))
- if (value_dependent_expression_p (TREE_VALUE (expression)))
- return true;
- return false;
- }
+ return any_value_dependent_elements_p (expression);
return value_dependent_expression_p (expression);
}
return false;
}
+ case TRAIT_EXPR:
+ {
+ tree type2 = TRAIT_EXPR_TYPE2 (expression);
+ return (dependent_type_p (TRAIT_EXPR_TYPE1 (expression))
+ || (type2 ? dependent_type_p (type2) : false));
+ }
+
+ case MODOP_EXPR:
+ return ((value_dependent_expression_p (TREE_OPERAND (expression, 0)))
+ || (value_dependent_expression_p (TREE_OPERAND (expression, 2))));
+
default:
/* A constant expression is value-dependent if any subexpression is
value-dependent. */
if (TREE_CODE (expression) == PSEUDO_DTOR_EXPR
|| TREE_CODE (expression) == SIZEOF_EXPR
|| TREE_CODE (expression) == ALIGNOF_EXPR
+ || TREE_CODE (expression) == TRAIT_EXPR
|| TREE_CODE (expression) == TYPEID_EXPR
|| TREE_CODE (expression) == DELETE_EXPR
|| TREE_CODE (expression) == VEC_DELETE_EXPR
&& !DECL_TEMPLATE_TEMPLATE_PARM_P (expression))
return false;
+ if (TREE_CODE (expression) == STMT_EXPR)
+ expression = stmt_expr_value_expr (expression);
+
if (TREE_TYPE (expression) == unknown_type_node)
{
if (TREE_CODE (expression) == ADDR_EXPR)
contains a type-dependent expression. */
bool
-any_type_dependent_arguments_p (tree args)
+any_type_dependent_arguments_p (const_tree args)
{
while (args)
{
return false;
}
+/* Returns TRUE if LIST (a TREE_LIST whose TREE_VALUEs are
+ expressions) contains any value-dependent expressions. */
+
+bool
+any_value_dependent_elements_p (const_tree list)
+{
+ for (; list; list = TREE_CHAIN (list))
+ if (value_dependent_expression_p (TREE_VALUE (list)))
+ return true;
+
+ return false;
+}
+
/* Returns TRUE if the ARG (a template argument) is dependent. */
bool
any dependent arguments. */
bool
-any_dependent_template_arguments_p (tree args)
+any_dependent_template_arguments_p (const_tree args)
{
int i;
int j;
for (i = 0; i < TMPL_ARGS_DEPTH (args); ++i)
{
- tree level = TMPL_ARGS_LEVEL (args, i + 1);
+ const_tree level = TMPL_ARGS_LEVEL (args, i + 1);
for (j = 0; j < TREE_VEC_LENGTH (level); ++j)
if (dependent_template_arg_p (TREE_VEC_ELT (level, j)))
return true;
}
/* TYPE is a TYPENAME_TYPE. Returns the ordinary TYPE to which the
- TYPENAME_TYPE corresponds. Returns ERROR_MARK_NODE if no such TYPE
- can be found. Note that this function peers inside uninstantiated
- templates and therefore should be used only in extremely limited
- situations. ONLY_CURRENT_P restricts this peering to the currently
- open classes hierarchy (which is required when comparing types). */
+ TYPENAME_TYPE corresponds. Returns the original TYPENAME_TYPE if
+ no such TYPE can be found. Note that this function peers inside
+ uninstantiated templates and therefore should be used only in
+ extremely limited situations. ONLY_CURRENT_P restricts this
+ peering to the currently open classes hierarchy (which is required
+ when comparing types). */
tree
resolve_typename_type (tree type, bool only_current_p)
tree decl;
int quals;
tree pushed_scope;
+ tree result;
gcc_assert (TREE_CODE (type) == TYPENAME_TYPE);
scope = resolve_typename_type (scope, only_current_p);
/* If we don't know what SCOPE refers to, then we cannot resolve the
TYPENAME_TYPE. */
- if (scope == error_mark_node || TREE_CODE (scope) == TYPENAME_TYPE)
- return error_mark_node;
+ if (TREE_CODE (scope) == TYPENAME_TYPE)
+ return type;
/* If the SCOPE is a template type parameter, we have no way of
resolving the name. */
if (TREE_CODE (scope) == TEMPLATE_TYPE_PARM)
/* If the SCOPE is not the current instantiation, there's no reason
to look inside it. */
if (only_current_p && !currently_open_class (scope))
- return error_mark_node;
- /* If SCOPE is a partial instantiation, it will not have a valid
- TYPE_FIELDS list, so use the original template. */
- scope = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope);
+ return type;
+ /* If SCOPE isn't the template itself, it will not have a valid
+ TYPE_FIELDS list. */
+ if (same_type_p (scope, CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope)))
+ /* scope is either the template itself or a compatible instantiation
+ like X<T>, so look up the name in the original template. */
+ scope = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope);
+ else
+ /* scope is a partial instantiation, so we can't do the lookup or we
+ will lose the template arguments. */
+ return type;
/* Enter the SCOPE so that name lookup will be resolved as if we
were in the class definition. In particular, SCOPE will no
longer be considered a dependent type. */
pushed_scope = push_scope (scope);
/* Look up the declaration. */
decl = lookup_member (scope, name, /*protect=*/0, /*want_type=*/true);
- /* Obtain the set of qualifiers applied to the TYPE. */
- quals = cp_type_quals (type);
+
+ result = NULL_TREE;
+
/* For a TYPENAME_TYPE like "typename X::template Y<T>", we want to
find a TEMPLATE_DECL. Otherwise, we want to find a TYPE_DECL. */
if (!decl)
- type = error_mark_node;
+ /*nop*/;
else if (TREE_CODE (TYPENAME_TYPE_FULLNAME (type)) == IDENTIFIER_NODE
&& TREE_CODE (decl) == TYPE_DECL)
- type = TREE_TYPE (decl);
+ {
+ result = TREE_TYPE (decl);
+ if (result == error_mark_node)
+ result = NULL_TREE;
+ }
else if (TREE_CODE (TYPENAME_TYPE_FULLNAME (type)) == TEMPLATE_ID_EXPR
&& DECL_CLASS_TEMPLATE_P (decl))
{
tmpl = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 0);
args = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 1);
/* Instantiate the template. */
- type = lookup_template_class (tmpl, args, NULL_TREE, NULL_TREE,
- /*entering_scope=*/0, tf_error | tf_user);
+ result = lookup_template_class (tmpl, args, NULL_TREE, NULL_TREE,
+ /*entering_scope=*/0,
+ tf_error | tf_user);
+ if (result == error_mark_node)
+ result = NULL_TREE;
}
- else
- type = error_mark_node;
- /* Qualify the resulting type. */
- if (type != error_mark_node && quals)
- type = cp_build_qualified_type (type, quals);
+
/* Leave the SCOPE. */
if (pushed_scope)
pop_scope (pushed_scope);
- return type;
+ /* If we failed to resolve it, return the original typename. */
+ if (!result)
+ return type;
+
+ /* If lookup found a typename type, resolve that too. */
+ if (TREE_CODE (result) == TYPENAME_TYPE && !TYPENAME_IS_RESOLVING_P (result))
+ {
+ /* Ill-formed programs can cause infinite recursion here, so we
+ must catch that. */
+ TYPENAME_IS_RESOLVING_P (type) = 1;
+ result = resolve_typename_type (result, only_current_p);
+ TYPENAME_IS_RESOLVING_P (type) = 0;
+ }
+
+ /* Qualify the resulting type. */
+ quals = cp_type_quals (type);
+ if (quals)
+ result = cp_build_qualified_type (result, cp_type_quals (result) | quals);
+
+ return result;
}
/* EXPR is an expression which is not type-dependent. Return a proxy
/* Preserve OVERLOADs; the functions must be available to resolve
types. */
inner_expr = expr;
+ if (TREE_CODE (inner_expr) == STMT_EXPR)
+ inner_expr = stmt_expr_value_expr (inner_expr);
if (TREE_CODE (inner_expr) == ADDR_EXPR)
inner_expr = TREE_OPERAND (inner_expr, 0);
if (TREE_CODE (inner_expr) == COMPONENT_REF)