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 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 *);
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;
+
+ /* Whether we should replace parameter packs with
+ ERROR_MARK_NODE. Used by check_for_bare_parameter_packs. */
+ bool set_packs_to_error;
};
/* Identifies all of the argument packs that occur in a template
tree t = *tp;
struct find_parameter_pack_data* ppd =
(struct find_parameter_pack_data*)data;
+ bool parameter_pack_p = false;
- if (TYPE_P (t))
+ /* Don't visit nodes twice, except when we're clearing out parameter
+ packs. */
+ if (pointer_set_contains (ppd->visited, *tp))
{
- tree context = TYPE_CONTEXT (t);
- cp_walk_tree (&context, &find_parameter_packs_r, ppd, ppd->visited);
+ *walk_subtrees = 0;
+ return NULL_TREE;
}
+recheck:
+ /* Identify whether this is a parameter pack or not. */
+ switch (TREE_CODE (t))
+ {
+ 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;
+
+ case POINTER_TYPE:
+ if (ppd->set_packs_to_error)
+ /* Pointer types are shared, set in that case the outermost
+ POINTER_TYPE to error_mark_node rather than the parameter pack. */
+ {
+ t = TREE_TYPE (t);
+ goto recheck;
+ }
+ 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 (ppd->set_packs_to_error)
+ /* The caller requested that we set the parameter packs to
+ ERROR_MARK_NODE so that they will not trip up the compiler
+ later. The caller is responsible for emitting an error. */
+ *tp = error_mark_node;
+ else
+ /* Make sure we do not visit this node again. */
+ pointer_set_insert (ppd->visited, *tp);
+ }
+ else
+ /* Make sure we do not visit this node again. */
+ pointer_set_insert (ppd->visited, *tp);
+
+ if (TYPE_P (t))
+ cp_walk_tree (&TYPE_CONTEXT (t),
+ &find_parameter_packs_r, ppd, NULL);
+
/* 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, NULL);
/* Check the template arguments. */
cp_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);
+ NULL);
*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));
- cp_walk_tree (&args, &find_parameter_packs_r, ppd, ppd->visited);
- }
+ cp_walk_tree (&TREE_VALUE (TYPE_TEMPLATE_INFO (t)),
+ &find_parameter_packs_r, ppd, NULL);
*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, NULL);
+ return NULL_TREE;
+
+ case TYPENAME_TYPE:
+ cp_walk_tree (&TYPENAME_TYPE_FULLNAME (t), &find_parameter_packs_r,
+ ppd, NULL);
*walk_subtrees = 0;
return NULL_TREE;
-
+
case TYPE_PACK_EXPANSION:
case EXPR_PACK_EXPANSION:
*walk_subtrees = 0;
case INTEGER_TYPE:
cp_walk_tree (&TYPE_MAX_VALUE (t), &find_parameter_packs_r,
- ppd, ppd->visited);
+ ppd, NULL);
*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 ();
- cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
+ ppd.set_packs_to_error = false;
+ cp_walk_tree (&t, &find_parameter_packs_r, &ppd, NULL);
pointer_set_destroy (ppd.visited);
return parameter_packs != NULL_TREE;
}
bool for_types = false;
struct find_parameter_pack_data ppd;
+ ppd.set_packs_to_error = false;
+
if (!arg || arg == error_mark_node)
return arg;
ppd.visited = pointer_set_create ();
ppd.parameter_packs = ¶meter_packs;
cp_walk_tree (&TREE_PURPOSE (arg), &find_parameter_packs_r,
- &ppd, ppd.visited);
+ &ppd, NULL);
if (parameter_packs == NULL_TREE)
{
/* Determine which parameter packs will be expanded in this
argument. */
cp_walk_tree (&TREE_VALUE (value), &find_parameter_packs_r,
- &ppd, ppd.visited);
+ &ppd, NULL);
}
}
/* Determine which parameter packs will be expanded. */
ppd.parameter_packs = ¶meter_packs;
ppd.visited = pointer_set_create ();
- cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, ppd.visited);
+ cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, NULL);
pointer_set_destroy (ppd.visited);
/* Make sure we found some parameter packs. */
Returns TRUE if there were no bare parameter packs, returns FALSE
(and emits an error) if there were bare parameter packs.*/
bool
-check_for_bare_parameter_packs (tree t)
+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)
+ if (!processing_template_decl || !t || !*t || *t == error_mark_node)
return true;
- if (TREE_CODE (t) == TYPE_DECL)
- t = TREE_TYPE (t);
+ if (TREE_CODE (*t) == TYPE_DECL)
+ t = &TREE_TYPE (*t);
ppd.parameter_packs = ¶meter_packs;
ppd.visited = pointer_set_create ();
- cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
+ ppd.set_packs_to_error = false;
+ cp_walk_tree (t, &find_parameter_packs_r, &ppd, NULL);
pointer_set_destroy (ppd.visited);
if (parameter_packs)
name = DECL_NAME (TEMPLATE_PARM_DECL (pack));
else
name = DECL_NAME (pack);
- inform (" %qD", name);
+
+ if (name)
+ inform (" %qD", name);
+ else
+ inform (" <anonymous>");
parameter_packs = TREE_CHAIN (parameter_packs);
}
+ /* Clean up any references to these parameter packs within the
+ tree. */
+ ppd.parameter_packs = ¶meter_packs;
+ ppd.visited = pointer_set_create ();
+ ppd.set_packs_to_error = true;
+ cp_walk_tree (t, &find_parameter_packs_r, &ppd, NULL);
+ pointer_set_destroy (ppd.visited);
+
return false;
}
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);
{
/* This template parameter is not a parameter pack, but it
should be. Complain about "bare" parameter packs. */
- check_for_bare_parameter_packs (TREE_TYPE (parm));
+ check_for_bare_parameter_packs (&TREE_TYPE (parm));
/* Recover by calling this a parameter pack. */
is_parameter_pack = true;
{
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)
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;
}
}
while (arg && argtype)
{
if (!FUNCTION_PARAMETER_PACK_P (arg)
- && !check_for_bare_parameter_packs (TREE_TYPE (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 in the return type and the
exception specifiers. */
- check_for_bare_parameter_packs (TREE_TYPE (type));
- check_for_bare_parameter_packs (TYPE_RAISES_EXCEPTIONS (type));
- }
- else
- check_for_bare_parameter_packs (TREE_TYPE (decl));
+ 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;
+ check_for_bare_parameter_packs (&TYPE_RAISES_EXCEPTIONS (type));
+ }
+ else if (!check_for_bare_parameter_packs (&TREE_TYPE (decl)))
+ return error_mark_node;
if (is_partial)
return process_partial_specialization (decl);
else
error ("parameter pack %qT must be at the end of the"
" template parameter list", TREE_TYPE (parm));
+
+ TREE_VALUE (TREE_VEC_ELT (inner_parms, i)) = error_mark_node;
}
}
}
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;
}
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
if (is_type)
error (" expected a constant of type %qT, got %qT",
TREE_TYPE (parm),
- (is_tmpl_type ? DECL_NAME (arg) : orig_arg));
+ (DECL_P (arg) ? DECL_NAME (arg) : orig_arg));
else if (requires_tmpl_type)
error (" expected a class template, got %qE", orig_arg);
else
if (arg && PACK_EXPANSION_P (arg))
{
- /* 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);
+ 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;
}
}
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,
> 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);
}
if (DECL_P (*decl_p))
- p = &DECL_ATTRIBUTES (*decl_p);
+ {
+ if (TREE_TYPE (*decl_p) == error_mark_node)
+ return;
+ p = &DECL_ATTRIBUTES (*decl_p);
+ }
else
p = &TYPE_ATTRIBUTES (*decl_p);
/* 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;
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)
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:
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:
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)
}
}
+ /* 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:
/* 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, NULL);
+ 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))
{
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
nodes. */
return 0;
+ case ERROR_MARK:
+ /* Unification fails if we hit an error node. */
+ return 1;
+
default:
gcc_assert (EXPR_P (parm));
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;
}
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 ... */