/* Handle parameterized types (templates) for GNU C++.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2007 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).
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 bool inline_needs_template_parms (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 (IS_AGGR_TYPE (type)
+ if (type == error_mark_node)
+ return error_mark_node;
+ if (MAYBE_CLASS_TYPE_P (type)
&& CLASSTYPE_TEMPLATE_INFO (type)
&& !CLASSTYPE_TEMPLATE_SPECIALIZATION (type))
{
TREE_TYPE (parm));
DECL_ARTIFICIAL (decl) = 1;
TREE_CONSTANT (decl) = 1;
- TREE_INVARIANT (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_INITIAL (decl) = DECL_INITIAL (parm);
SET_DECL_TEMPLATE_PARM_P (decl);
return true;
else
{
- pedwarn ("specialization of %qD in different namespace", tmpl);
- pedwarn (" from definition of %q+#D", tmpl);
+ permerror ("specialization of %qD in different namespace", tmpl);
+ permerror (" from definition of %q+#D", tmpl);
return false;
}
}
namespace of its template. */
ns = decl_namespace_context (spec);
if (!is_ancestor (current_namespace, ns))
- pedwarn ("explicit instantiation of %qD in namespace %qD "
- "(which does not enclose namespace %qD)",
- spec, current_namespace, ns);
+ permerror ("explicit instantiation of %qD in namespace %qD "
+ "(which does not enclose namespace %qD)",
+ spec, current_namespace, ns);
}
/* The TYPE is being declared. If it is a template type, that means it
check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type));
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
if (processing_template_decl)
- push_template_decl (TYPE_MAIN_DECL (type));
+ {
+ if (push_template_decl (TYPE_MAIN_DECL (type))
+ == error_mark_node)
+ return error_mark_node;
+ }
}
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
error ("specialization of %qT after instantiation", type);
if (current_namespace
!= decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
{
- pedwarn ("specializing %q#T in different namespace", type);
- pedwarn (" from definition of %q+#D",
- CLASSTYPE_TI_TEMPLATE (type));
+ permerror ("specializing %q#T in different namespace", type);
+ permerror (" from definition of %q+#D",
+ CLASSTYPE_TI_TEMPLATE (type));
}
/* Check for invalid specialization after instantiation:
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;
}
}
/* Returns nonzero iff DECL is a specialization of friend declaration
- FRIEND according to [temp.friend]. */
+ FRIEND_DECL according to [temp.friend]. */
bool
-is_specialization_of_friend (tree decl, tree friend)
+is_specialization_of_friend (tree decl, tree friend_decl)
{
bool need_template = true;
int template_depth;
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == TYPE_DECL);
- /* For [temp.friend/6] when FRIEND is an ordinary member function
+ /* For [temp.friend/6] when FRIEND_DECL is an ordinary member function
of a template class, we want to check if DECL is a specialization
if this. */
- if (TREE_CODE (friend) == FUNCTION_DECL
- && DECL_TEMPLATE_INFO (friend)
- && !DECL_USE_TEMPLATE (friend))
+ if (TREE_CODE (friend_decl) == FUNCTION_DECL
+ && DECL_TEMPLATE_INFO (friend_decl)
+ && !DECL_USE_TEMPLATE (friend_decl))
{
/* We want a TEMPLATE_DECL for `is_specialization_of'. */
- friend = DECL_TI_TEMPLATE (friend);
+ friend_decl = DECL_TI_TEMPLATE (friend_decl);
need_template = false;
}
- else if (TREE_CODE (friend) == TEMPLATE_DECL
- && !PRIMARY_TEMPLATE_P (friend))
+ else if (TREE_CODE (friend_decl) == TEMPLATE_DECL
+ && !PRIMARY_TEMPLATE_P (friend_decl))
need_template = false;
/* There is nothing to do if this is not a template friend. */
- if (TREE_CODE (friend) != TEMPLATE_DECL)
+ if (TREE_CODE (friend_decl) != TEMPLATE_DECL)
return false;
- if (is_specialization_of (decl, friend))
+ if (is_specialization_of (decl, friend_decl))
return true;
/* [temp.friend/6]
nonzero. To determine if DECL is a friend of FRIEND, we first
check if the enclosing class is a specialization of another. */
- template_depth = template_class_depth (DECL_CONTEXT (friend));
+ template_depth = template_class_depth (DECL_CONTEXT (friend_decl));
if (template_depth
&& DECL_CLASS_SCOPE_P (decl)
&& is_specialization_of (TYPE_NAME (DECL_CONTEXT (decl)),
- CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (friend))))
+ CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (friend_decl))))
{
/* Next, we check the members themselves. In order to handle
- a few tricky cases, such as when FRIEND's are
+ a few tricky cases, such as when FRIEND_DECL's are
template <class T> friend void A<T>::g(T t);
template <class T> template <T t> friend void A<T>::h();
tree friend_args_type;
tree decl_args_type;
- /* Make sure that both DECL and FRIEND are templates or
+ /* Make sure that both DECL and FRIEND_DECL are templates or
non-templates. */
is_template = DECL_TEMPLATE_INFO (decl)
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl));
{
/* If both are templates, check template parameter list. */
tree friend_parms
- = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend),
+ = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_decl),
args, tf_none);
if (!comp_template_parms
(DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl)),
else
decl_type = TREE_TYPE (decl);
- friend_type = tsubst_function_type (TREE_TYPE (friend), args,
+ friend_type = tsubst_function_type (TREE_TYPE (friend_decl), args,
tf_none, NULL_TREE);
if (friend_type == error_mark_node)
return false;
`this' parameter. */
friend_args_type = TYPE_ARG_TYPES (friend_type);
decl_args_type = TYPE_ARG_TYPES (decl_type);
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (friend))
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (friend_decl))
friend_args_type = TREE_CHAIN (friend_args_type);
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
decl_args_type = TREE_CHAIN (decl_args_type);
bool is_template;
tree decl_type = TREE_TYPE (decl);
- /* Make sure that both DECL and FRIEND are templates or
+ /* Make sure that both DECL and FRIEND_DECL are templates or
non-templates. */
is_template
= CLASSTYPE_TEMPLATE_INFO (decl_type)
/* If both are templates, check the name of the two
TEMPLATE_DECL's first because is_friend didn't. */
if (DECL_NAME (CLASSTYPE_TI_TEMPLATE (decl_type))
- != DECL_NAME (friend))
+ != DECL_NAME (friend_decl))
return false;
/* Now check template parameter list. */
friend_parms
- = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend),
+ = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_decl),
args, tf_none);
return comp_template_parms
(DECL_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (decl_type)),
}
else
return (DECL_NAME (decl)
- == DECL_NAME (friend));
+ == DECL_NAME (friend_decl));
}
}
return false;
for (; t; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t))
{
- pedwarn
+ permerror
("default argument specified in explicit specialization");
break;
}
{
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]:
/* 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
(struct find_parameter_pack_data*)data;
bool parameter_pack_p = false;
- /* Don't visit nodes twice, except when we're clearing out parameter
- packs. */
- if (pointer_set_contains (ppd->visited, *tp))
- {
- *walk_subtrees = 0;
- return NULL_TREE;
- }
-
/* Identify whether this is a parameter pack or not. */
switch (TREE_CODE (t))
{
{
/* 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);
+ &find_parameter_packs_r, ppd, ppd->visited);
/* This switch statement will return immediately if we don't find a
parameter pack. */
case BOUND_TEMPLATE_TEMPLATE_PARM:
/* Check the template itself. */
cp_walk_tree (&TREE_TYPE (TYPE_TI_TEMPLATE (t)),
- &find_parameter_packs_r, ppd, NULL);
+ &find_parameter_packs_r, ppd, ppd->visited);
/* Check the template arguments. */
cp_walk_tree (&TYPE_TI_ARGS (t), &find_parameter_packs_r, ppd,
- NULL);
+ ppd->visited);
*walk_subtrees = 0;
return NULL_TREE;
case ENUMERAL_TYPE:
if (TYPE_TEMPLATE_INFO (t))
cp_walk_tree (&TREE_VALUE (TYPE_TEMPLATE_INFO (t)),
- &find_parameter_packs_r, ppd, NULL);
+ &find_parameter_packs_r, ppd, ppd->visited);
*walk_subtrees = 0;
return NULL_TREE;
case TEMPLATE_DECL:
cp_walk_tree (&TREE_TYPE (t),
- &find_parameter_packs_r, ppd, NULL);
+ &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, NULL);
+ ppd, ppd->visited);
*walk_subtrees = 0;
return NULL_TREE;
-
case TYPE_PACK_EXPANSION:
case EXPR_PACK_EXPANSION:
case INTEGER_TYPE:
cp_walk_tree (&TYPE_MAX_VALUE (t), &find_parameter_packs_r,
- ppd, NULL);
+ 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;
struct find_parameter_pack_data ppd;
ppd.parameter_packs = ¶meter_packs;
ppd.visited = pointer_set_create ();
- ppd.set_packs_to_error = false;
- cp_walk_tree (&t, &find_parameter_packs_r, &ppd, NULL);
+ cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
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, NULL);
+ &ppd, ppd.visited);
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, NULL);
+ &ppd, ppd.visited);
}
}
/* 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, NULL);
+ cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, ppd.visited);
pointer_set_destroy (ppd.visited);
/* Make sure we found some parameter packs. */
g(h(args)), or f(g(h(args))), because we would produce erroneous
error messages.
- Returns TRUE if there were no bare parameter packs, returns FALSE
- (and emits an error) if there were bare parameter packs.*/
+ Returns TRUE and emits an error if there were bare parameter packs,
+ returns FALSE otherwise. */
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 || *t == error_mark_node)
- return true;
+ if (!processing_template_decl || !t || t == error_mark_node)
+ return false;
- 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 ();
- ppd.set_packs_to_error = false;
- cp_walk_tree (t, &find_parameter_packs_r, &ppd, NULL);
+ 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 `...':");
+ error ("parameter packs not expanded with %<...%>:");
while (parameter_packs)
{
tree pack = TREE_VALUE (parameter_packs);
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;
+ return true;
}
- return true;
+ return false;
}
/* Expand any parameter packs that occur in the template arguments in
TEMPLATE_PARM_DECL (t) = decl;
TREE_TYPE (t) = type;
TREE_CONSTANT (t) = TREE_CONSTANT (decl);
- TREE_INVARIANT (t) = TREE_INVARIANT (decl);
TREE_READONLY (t) = TREE_READONLY (decl);
return t;
decl = build_decl (TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);
TREE_CONSTANT (decl) = TREE_CONSTANT (orig_decl);
- TREE_INVARIANT (decl) = TREE_INVARIANT (orig_decl);
TREE_READONLY (decl) = TREE_READONLY (orig_decl);
DECL_ARTIFICIAL (decl) = 1;
SET_DECL_TEMPLATE_PARM_P (decl);
{
/* 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;
/* A template parameter is not modifiable. */
TREE_CONSTANT (parm) = 1;
- TREE_INVARIANT (parm) = 1;
TREE_READONLY (parm) = 1;
decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
TREE_CONSTANT (decl) = 1;
- TREE_INVARIANT (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_INITIAL (parm) = DECL_INITIAL (decl)
= build_template_parm_index (idx, processing_template_decl,
if (parm && TREE_CODE (parm) == TEMPLATE_DECL)
{
- t = make_aggr_type (TEMPLATE_TEMPLATE_PARM);
+ t = cxx_make_type (TEMPLATE_TEMPLATE_PARM);
/* This is for distinguishing between real templates and template
template parameters */
TREE_TYPE (parm) = t;
}
else
{
- t = make_aggr_type (TEMPLATE_TYPE_PARM);
+ t = cxx_make_type (TEMPLATE_TYPE_PARM);
/* parm is either IDENTIFIER_NODE or NULL_TREE. */
decl = build_decl (TYPE_DECL, parm, t);
}
{
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)
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)
for_each_template_parm (type,
&mark_template_parm,
&tpd2,
- NULL);
+ NULL,
+ /*include_nondeduced_p=*/false);
if (tpd2.arg_uses_template_parms [i])
{
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.
IS_FRIEND_DECL is nonzero if DECL is a friend function template
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;
+ }
}
}
}
member_template_p = true;
if (TREE_CODE (decl) == TYPE_DECL
&& ANON_AGGRNAME_P (DECL_NAME (decl)))
- error ("template class without a name");
+ {
+ error ("template class without a name");
+ return error_mark_node;
+ }
else if (TREE_CODE (decl) == FUNCTION_DECL)
{
if (DECL_DESTRUCTOR_P (decl))
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));
+ 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;
}
- else
- 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)
- {
- tree inner_parms
- = INNERMOST_TEMPLATE_PARMS (current_template_parms);
- int i, len = TREE_VEC_LENGTH (inner_parms);
- for (i = 0; i < len - 1; i++)
- {
- tree parm = TREE_VALUE (TREE_VEC_ELT (inner_parms, i));
-
- 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));
-
- TREE_VALUE (TREE_VEC_ELT (inner_parms, i)) = error_mark_node;
- }
- }
- }
-
args = current_template_args ();
if (!ctx
if (!tinfo)
{
error ("template definition of non-template %q#D", decl);
- return decl;
+ return error_mark_node;
}
tmpl = TI_TEMPLATE (tinfo);
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;
}
/* EXPR is an expression which is used in a constant-expression context.
For instance, it could be a VAR_DECL with a constant initializer.
- Extract the innest constant expression.
+ Extract the innermost constant expression.
This is basically a more powerful version of
integral_constant_value, which can be used also in templates where
return expr;
}
+/* Subroutine of coerce_template_template_parms, which returns 1 if
+ PARM_PARM and ARG_PARM match using the rule for the template
+ parameters of template template parameters. Both PARM and ARG are
+ template parameters; the rest of the arguments are the same as for
+ coerce_template_template_parms.
+ */
+static int
+coerce_template_template_parm (tree parm,
+ tree arg,
+ tsubst_flags_t complain,
+ tree in_decl,
+ tree outer_args)
+{
+ if (arg == NULL_TREE || arg == error_mark_node
+ || parm == NULL_TREE || parm == error_mark_node)
+ return 0;
+
+ if (TREE_CODE (arg) != TREE_CODE (parm))
+ return 0;
+
+ switch (TREE_CODE (parm))
+ {
+ case TEMPLATE_DECL:
+ /* We encounter instantiations of templates like
+ template <template <template <class> class> class TT>
+ class C; */
+ {
+ tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
+ tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+
+ if (!coerce_template_template_parms
+ (parmparm, argparm, complain, in_decl, outer_args))
+ return 0;
+ }
+ /* Fall through. */
+
+ case TYPE_DECL:
+ if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (arg))
+ && !TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm)))
+ /* Argument is a parameter pack but parameter is not. */
+ return 0;
+ break;
+
+ case PARM_DECL:
+ /* The tsubst call is used to handle cases such as
+
+ template <int> class C {};
+ template <class T, template <T> class TT> class D {};
+ D<int, C> d;
+
+ i.e. the parameter list of TT depends on earlier parameters. */
+ if (!dependent_type_p (TREE_TYPE (arg))
+ && !same_type_p
+ (tsubst (TREE_TYPE (parm), outer_args, complain, in_decl),
+ TREE_TYPE (arg)))
+ return 0;
+
+ if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (arg))
+ && !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
+ /* Argument is a parameter pack but parameter is not. */
+ return 0;
+
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return 1;
+}
+
/* Return 1 if PARM_PARMS and ARG_PARMS matches using rule for
template template parameters. Both PARM_PARMS and ARG_PARMS are
{
int nparms, nargs, i;
tree parm, arg;
+ int variadic_p = 0;
gcc_assert (TREE_CODE (parm_parms) == TREE_VEC);
gcc_assert (TREE_CODE (arg_parms) == TREE_VEC);
nparms = TREE_VEC_LENGTH (parm_parms);
nargs = TREE_VEC_LENGTH (arg_parms);
- if (nargs != nparms)
+ /* Determine whether we have a parameter pack at the end of the
+ template template parameter's template parameter list. */
+ if (TREE_VEC_ELT (parm_parms, nparms - 1) != error_mark_node)
+ {
+ parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, nparms - 1));
+
+ switch (TREE_CODE (parm))
+ {
+ case TEMPLATE_DECL:
+ case TYPE_DECL:
+ if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm)))
+ variadic_p = 1;
+ break;
+
+ case PARM_DECL:
+ if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
+ variadic_p = 1;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ if (nargs != nparms
+ && !(variadic_p && nargs >= nparms - 1))
return 0;
- for (i = 0; i < nparms; ++i)
+ /* Check all of the template parameters except the parameter pack at
+ the end (if any). */
+ for (i = 0; i < nparms - variadic_p; ++i)
{
if (TREE_VEC_ELT (parm_parms, i) == error_mark_node
|| TREE_VEC_ELT (arg_parms, i) == error_mark_node)
parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, i));
arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
- if (arg == NULL_TREE || arg == error_mark_node
- || parm == NULL_TREE || parm == error_mark_node)
+ if (!coerce_template_template_parm (parm, arg, complain, in_decl,
+ outer_args))
return 0;
- if (TREE_CODE (arg) != TREE_CODE (parm))
+ }
+
+ if (variadic_p)
+ {
+ /* Check each of the template parameters in the template
+ argument against the template parameter pack at the end of
+ the template template parameter. */
+ if (TREE_VEC_ELT (parm_parms, i) == error_mark_node)
return 0;
- switch (TREE_CODE (parm))
- {
- case TEMPLATE_DECL:
- /* We encounter instantiations of templates like
- template <template <template <class> class> class TT>
- class C; */
- {
- tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
- tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+ parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, i));
- if (!coerce_template_template_parms
- (parmparm, argparm, complain, in_decl, outer_args))
- return 0;
- }
- /* Fall through. */
+ for (; i < nargs; ++i)
+ {
+ if (TREE_VEC_ELT (arg_parms, i) == error_mark_node)
+ continue;
+
+ arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
+
+ if (!coerce_template_template_parm (parm, arg, complain, in_decl,
+ outer_args))
+ return 0;
+ }
+ }
- case TYPE_DECL:
- if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm))
- != TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (arg)))
- /* One is a parameter pack, the other is not. */
- return 0;
- break;
+ return 1;
+}
- case PARM_DECL:
- /* The tsubst call is used to handle cases such as
+/* 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);
+ bool ret = true;
- template <int> class C {};
- template <class T, template <T> class TT> class D {};
- D<int, C> d;
+ /* We're dealing with template parms in this process. */
+ ++processing_template_decl;
- i.e. the parameter list of TT depends on earlier parameters. */
- if (!dependent_type_p (TREE_TYPE (arg))
- && !same_type_p
- (tsubst (TREE_TYPE (parm), outer_args, complain, in_decl),
- TREE_TYPE (arg)))
- return 0;
+ targs = INNERMOST_TEMPLATE_ARGS (targs);
- if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))
- != TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (arg)))
- /* One is a parameter pack, the other is not. */
- return 0;
- break;
+ for (i = 0; i < ntparms; ++i)
+ {
+ tree tparm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
+ tree targ = TREE_VEC_ELT (targs, i);
- default:
- gcc_unreachable ();
+ 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))
+ {
+ ret = false;
+ goto out;
+ }
+ }
}
}
- return 1;
+
+ out:
+
+ --processing_template_decl;
+ return ret;
}
/* Convert the indicated template ARG as necessary to match the
if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
&& TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
{
- pedwarn ("to refer to a type member of a template parameter, "
- "use %<typename %E%>", orig_arg);
+ permerror ("to refer to a type member of a template parameter, "
+ "use %<typename %E%>", orig_arg);
orig_arg = make_typename_type (TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1),
{
argument_pack = make_node (NONTYPE_ARGUMENT_PACK);
TREE_TYPE (argument_pack)
- = tsubst (TREE_TYPE (TREE_VALUE (parm)), args, complain, in_decl);
+ = tsubst (TREE_TYPE (TREE_VALUE (parm)), new_args, complain, in_decl);
TREE_CONSTANT (argument_pack) = 1;
}
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;
}
}
int entering_scope,
tsubst_flags_t complain)
{
- tree template = NULL_TREE, parmlist;
+ tree templ = NULL_TREE, parmlist;
tree t;
timevar_push (TV_NAME_LOOKUP);
{
tree value = innermost_non_namespace_value (d1);
if (value && DECL_TEMPLATE_TEMPLATE_PARM_P (value))
- template = value;
+ templ = value;
else
{
if (context)
push_decl_namespace (context);
- template = lookup_name (d1);
- template = maybe_get_template_decl_from_type_decl (template);
+ templ = lookup_name (d1);
+ templ = maybe_get_template_decl_from_type_decl (templ);
if (context)
pop_decl_namespace ();
}
- if (template)
- context = DECL_CONTEXT (template);
+ if (templ)
+ context = DECL_CONTEXT (templ);
}
- else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
+ else if (TREE_CODE (d1) == TYPE_DECL && MAYBE_CLASS_TYPE_P (TREE_TYPE (d1)))
{
tree type = TREE_TYPE (d1);
if (CLASSTYPE_TEMPLATE_INFO (type))
{
- template = CLASSTYPE_TI_TEMPLATE (type);
- d1 = DECL_NAME (template);
+ templ = CLASSTYPE_TI_TEMPLATE (type);
+ d1 = DECL_NAME (templ);
}
}
else if (TREE_CODE (d1) == ENUMERAL_TYPE
- || (TYPE_P (d1) && IS_AGGR_TYPE (d1)))
+ || (TYPE_P (d1) && MAYBE_CLASS_TYPE_P (d1)))
{
- template = TYPE_TI_TEMPLATE (d1);
- d1 = DECL_NAME (template);
+ templ = TYPE_TI_TEMPLATE (d1);
+ d1 = DECL_NAME (templ);
}
else if (TREE_CODE (d1) == TEMPLATE_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (d1)) == TYPE_DECL)
{
- template = d1;
- d1 = DECL_NAME (template);
- context = DECL_CONTEXT (template);
+ templ = d1;
+ d1 = DECL_NAME (templ);
+ context = DECL_CONTEXT (templ);
}
/* Issue an error message if we didn't find a template. */
- if (! template)
+ if (! templ)
{
if (complain & tf_error)
error ("%qT is not a template", d1);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
- if (TREE_CODE (template) != TEMPLATE_DECL
+ if (TREE_CODE (templ) != TEMPLATE_DECL
/* Make sure it's a user visible template, if it was named by
the user. */
- || ((complain & tf_user) && !DECL_TEMPLATE_PARM_P (template)
- && !PRIMARY_TEMPLATE_P (template)))
+ || ((complain & tf_user) && !DECL_TEMPLATE_PARM_P (templ)
+ && !PRIMARY_TEMPLATE_P (templ)))
{
if (complain & tf_error)
{
complain &= ~tf_user;
- if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))
+ if (DECL_TEMPLATE_TEMPLATE_PARM_P (templ))
{
/* Create a new TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM node to store
template arguments */
tree arglist2;
tree outer;
- parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
+ parmlist = DECL_INNERMOST_TEMPLATE_PARMS (templ);
/* Consider an example where a template template parameter declared as
level 1, and T at level 2, while the template arguments at level 1
becomes {std::vector} and the inner level 2 is {int}. */
- outer = DECL_CONTEXT (template);
+ outer = DECL_CONTEXT (templ);
if (outer)
outer = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (outer)));
else if (current_template_parms)
if (outer)
arglist = add_to_template_args (outer, arglist);
- arglist2 = coerce_template_parms (parmlist, arglist, template,
+ arglist2 = coerce_template_parms (parmlist, arglist, templ,
complain,
/*require_all_args=*/true,
/*use_default_args=*/true);
if (arglist2 == error_mark_node
|| (!uses_template_parms (arglist2)
- && check_instantiated_args (template, arglist2, complain)))
+ && check_instantiated_args (templ, arglist2, complain)))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- parm = bind_template_template_parm (TREE_TYPE (template), arglist2);
+ parm = bind_template_template_parm (TREE_TYPE (templ), arglist2);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, parm);
}
else
{
- tree template_type = TREE_TYPE (template);
+ tree template_type = TREE_TYPE (templ);
tree gen_tmpl;
tree type_decl;
tree found = NULL_TREE;
int parm_depth;
int is_partial_instantiation;
- gen_tmpl = most_general_template (template);
+ gen_tmpl = most_general_template (templ);
parmlist = DECL_TEMPLATE_PARMS (gen_tmpl);
parm_depth = TMPL_PARMS_DEPTH (parmlist);
arg_depth = TMPL_ARGS_DEPTH (arglist);
<class U> struct S1<T>::S2'. We must fill in the missing
arguments. */
arglist
- = add_outermost_template_args (TYPE_TI_ARGS (TREE_TYPE (template)),
+ = add_outermost_template_args (TYPE_TI_ARGS (TREE_TYPE (templ)),
arglist);
arg_depth = TMPL_ARGS_DEPTH (arglist);
}
/* From here on, we're only interested in the most general
template. */
- template = gen_tmpl;
+ templ = gen_tmpl;
/* Calculate the BOUND_ARGS. These will be the args that are
actually tsubst'd into the definition to create the
tree bound_args = make_tree_vec (parm_depth);
for (i = saved_depth,
- t = DECL_TEMPLATE_PARMS (template);
+ t = DECL_TEMPLATE_PARMS (templ);
i > 0 && t != NULL_TREE;
--i, t = TREE_CHAIN (t))
{
tree a = coerce_template_parms (TREE_VALUE (t),
- arglist, template,
+ arglist, templ,
complain,
/*require_all_args=*/true,
/*use_default_args=*/true);
arglist
= coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
INNERMOST_TEMPLATE_ARGS (arglist),
- template,
+ templ,
complain,
/*require_all_args=*/true,
/*use_default_args=*/true);
{
found = template_type;
- if (!entering_scope && PRIMARY_TEMPLATE_P (template))
+ if (!entering_scope && PRIMARY_TEMPLATE_P (templ))
{
tree ctx;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
/* If we already have this specialization, return it. */
- found = retrieve_specialization (template, arglist,
+ found = retrieve_specialization (templ, arglist,
/*class_specializations_p=*/false);
if (found)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
/* If the deduced arguments are invalid, then the binding
failed. */
if (!is_partial_instantiation
- && check_instantiated_args (template,
+ && check_instantiated_args (templ,
INNERMOST_TEMPLATE_ARGS (arglist),
complain))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
if (!is_partial_instantiation
- && !PRIMARY_TEMPLATE_P (template)
- && TREE_CODE (CP_DECL_CONTEXT (template)) == NAMESPACE_DECL)
+ && !PRIMARY_TEMPLATE_P (templ)
+ && TREE_CODE (CP_DECL_CONTEXT (templ)) == NAMESPACE_DECL)
{
- found = xref_tag_from_type (TREE_TYPE (template),
- DECL_NAME (template),
+ found = xref_tag_from_type (TREE_TYPE (templ),
+ DECL_NAME (templ),
/*tag_scope=*/ts_global);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
}
- context = tsubst (DECL_CONTEXT (template), arglist,
+ context = tsubst (DECL_CONTEXT (templ), arglist,
complain, in_decl);
if (!context)
context = global_namespace;
}
else
{
- t = make_aggr_type (TREE_CODE (template_type));
+ t = make_class_type (TREE_CODE (template_type));
CLASSTYPE_DECLARED_CLASS (t)
= CLASSTYPE_DECLARED_CLASS (template_type);
SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
/* A local class. Make sure the decl gets registered properly. */
if (context == current_function_decl)
- pushtag (DECL_NAME (template), t, /*tag_scope=*/ts_current);
+ pushtag (DECL_NAME (templ), t, /*tag_scope=*/ts_current);
if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
/* This instantiation is another name for the primary
{
TYPE_CONTEXT (t) = FROB_CONTEXT (context);
- type_decl = create_implicit_typedef (DECL_NAME (template), t);
+ type_decl = create_implicit_typedef (DECL_NAME (templ), t);
DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
TYPE_STUB_DECL (t) = type_decl;
DECL_SOURCE_LOCATION (type_decl)
= TREE_PRIVATE (TYPE_STUB_DECL (template_type));
TREE_PROTECTED (type_decl)
= TREE_PROTECTED (TYPE_STUB_DECL (template_type));
- DECL_IN_SYSTEM_HEADER (type_decl)
- = DECL_IN_SYSTEM_HEADER (template);
if (CLASSTYPE_VISIBILITY_SPECIFIED (template_type))
{
DECL_VISIBILITY_SPECIFIED (type_decl) = 1;
template is the immediate parent if this is a full
instantiation. */
if (parm_depth == 1 || is_partial_instantiation
- || !PRIMARY_TEMPLATE_P (template))
+ || !PRIMARY_TEMPLATE_P (templ))
/* This case is easy; there are no member templates involved. */
- found = template;
+ found = templ;
else
{
/* This is a full instantiation of a member template. Look
for a partial instantiation of which this is an instance. */
- for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
+ for (found = DECL_TEMPLATE_INSTANTIATIONS (templ);
found; found = TREE_CHAIN (found))
{
int success;
Create the partial instantiation.
*/
TREE_VEC_LENGTH (arglist)--;
- found = tsubst (template, arglist, complain, NULL_TREE);
+ found = tsubst (templ, arglist, complain, NULL_TREE);
TREE_VEC_LENGTH (arglist)++;
}
}
SET_TYPE_TEMPLATE_INFO (t, tree_cons (found, arglist, NULL_TREE));
- DECL_TEMPLATE_INSTANTIATIONS (template)
+ DECL_TEMPLATE_INSTANTIATIONS (templ)
= tree_cons (arglist, t,
- DECL_TEMPLATE_INSTANTIATIONS (template));
+ DECL_TEMPLATE_INSTANTIATIONS (templ));
if (TREE_CODE (t) == ENUMERAL_TYPE
&& !is_partial_instantiation)
{
tree_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
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)
{
- struct tinst_level *new;
+ struct tinst_level *new_level;
if (tinst_depth >= max_tinst_depth)
{
return 0;
}
- new = GGC_NEW (struct tinst_level);
- new->decl = d;
- new->locus = input_location;
- new->in_system_header_p = in_system_header;
- new->next = current_tinst_level;
- current_tinst_level = new;
+ new_level = GGC_NEW (struct tinst_level);
+ new_level->decl = d;
+ new_level->locus = input_location;
+ new_level->in_system_header_p = in_system_header;
+ new_level->next = current_tinst_level;
+ current_tinst_level = new_level;
++tinst_depth;
#ifdef GATHER_STATISTICS
/* Restore the filename and line number stashed away when we started
this instantiation. */
input_location = current_tinst_level->locus;
- in_system_header = current_tinst_level->in_system_header_p;
current_tinst_level = current_tinst_level->next;
--tinst_depth;
++tinst_level_tick;
/* Friend functions are looked up in the containing namespace scope.
We must enter that scope, to avoid finding member functions of the
- current cless with same name. */
+ current class with same name. */
push_nested_namespace (ns);
fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
tf_warning_or_error, NULL_TREE,
> 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);
{
*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);
+ /* If the first attribute argument is an identifier, don't
+ pass it through tsubst. Attributes like mode, format,
+ cleanup and several target specific attributes expect it
+ unmodified. */
+ if (TREE_VALUE (t)
+ && TREE_CODE (TREE_VALUE (t)) == TREE_LIST
+ && TREE_VALUE (TREE_VALUE (t))
+ && (TREE_CODE (TREE_VALUE (TREE_VALUE (t)))
+ == IDENTIFIER_NODE))
+ {
+ tree chain
+ = tsubst_expr (TREE_CHAIN (TREE_VALUE (t)), args, complain,
+ in_decl,
+ /*integral_constant_expression_p=*/false);
+ if (chain != TREE_CHAIN (TREE_VALUE (t)))
+ TREE_VALUE (t)
+ = tree_cons (NULL_TREE, TREE_VALUE (TREE_VALUE (t)),
+ chain);
+ }
+ else
+ TREE_VALUE (t)
+ = tsubst_expr (TREE_VALUE (t), args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
*q = t;
q = &TREE_CHAIN (t);
}
tree
instantiate_class_template (tree type)
{
- tree template, args, pattern, t, member;
+ tree templ, args, pattern, t, member;
tree typedecl;
tree pbinfo;
tree base_list;
return type;
/* Figure out which template is being instantiated. */
- template = most_general_template (CLASSTYPE_TI_TEMPLATE (type));
- gcc_assert (TREE_CODE (template) == TEMPLATE_DECL);
+ templ = most_general_template (CLASSTYPE_TI_TEMPLATE (type));
+ gcc_assert (TREE_CODE (templ) == TEMPLATE_DECL);
/* Determine what specialization of the original template to
instantiate. */
- t = most_specialized_class (type, template);
+ t = most_specialized_class (type, templ);
if (t == error_mark_node)
{
TYPE_BEING_DEFINED (type) = 1;
}
else
{
- pattern = TREE_TYPE (template);
+ pattern = TREE_TYPE (templ);
args = CLASSTYPE_TI_ARGS (type);
}
if tsubsting causes an error. */
typedecl = TYPE_MAIN_DECL (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);
{
tree r;
- /* The the file and line for this declaration, to
+ /* The file and line for this declaration, to
assist in error message reporting. Since we
called push_tinst_level above, we don't need to
restore these. */
/* Build new DECL_FRIENDLIST. */
tree r;
- /* The the file and line for this declaration, to
+ /* The file and line for this declaration, to
assist in error message reporting. Since we
called push_tinst_level above, we don't need to
restore these. */
/* Now that the class is complete, instantiate default arguments for
any member functions. We don't do this earlier because the
default arguments may reference members of the class. */
- if (!PRIMARY_TEMPLATE_P (template))
+ if (!PRIMARY_TEMPLATE_P (templ))
for (t = TYPE_METHODS (type); t; t = TREE_CHAIN (t))
if (TREE_CODE (t) == FUNCTION_DECL
/* Implicitly generated member functions will not have template
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;
/* 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:
substitution from inside tsubst_pack_expansion. Just
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 (arg_types == error_mark_node)
return error_mark_node;
- if (TYPE_QUALS (return_type) != TYPE_UNQUALIFIED
- && in_decl != NULL_TREE
- && !TREE_NO_WARNING (in_decl)
- && (SCALAR_TYPE_P (return_type) || VOID_TYPE_P (return_type)))
- warning (OPT_Wreturn_type,
- "type qualifiers ignored on function return type");
-
/* Construct a new type node and return it. */
if (TREE_CODE (t) == FUNCTION_TYPE)
fntype = build_function_type (return_type, arg_types);
else
{
tree r = TREE_TYPE (TREE_VALUE (arg_types));
- if (! IS_AGGR_TYPE (r))
+ if (! MAYBE_CLASS_TYPE_P (r))
{
/* [temp.deduct]
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)
tree decl = TYPE_NAME (t);
if (DECL_CLASS_SCOPE_P (decl)
- && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (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))
+ 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
- r = NULL_TREE;
-
+ /* The typedef is from a non-template context. */
+ return t;
+
if (r)
{
r = TREE_TYPE (r);
/*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");
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");
case OFFSET_TYPE:
{
r = tsubst (TYPE_OFFSET_BASETYPE (t), args, complain, in_decl);
- if (r == error_mark_node || !IS_AGGR_TYPE (r))
+ if (r == error_mark_node || !MAYBE_CLASS_TYPE_P (r))
{
/* [temp.deduct]
if (ctx == error_mark_node || f == error_mark_node)
return error_mark_node;
- if (!IS_AGGR_TYPE (ctx))
+ if (!MAYBE_CLASS_TYPE_P (ctx))
{
if (complain & tf_error)
error ("%qT is not a class, struct, or union type", ctx);
if (complain & tf_error)
qualified_name_lookup_error (scope,
TREE_OPERAND (qualified_id, 1),
- expr);
+ expr, input_location);
return error_mark_node;
}
if (expr == error_mark_node && complain & tf_error)
qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1),
- expr);
+ expr, input_location);
else if (TYPE_P (scope))
{
expr = (adjust_result_of_qualified_name_lookup
/* We only want to compute the number of arguments. */
tree expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args,
complain, in_decl);
+ int len = 0;
+
+ if (TREE_CODE (expanded) == TREE_VEC)
+ len = TREE_VEC_LENGTH (expanded);
+
if (expanded == error_mark_node)
return error_mark_node;
- return build_int_cst (size_type_node, TREE_VEC_LENGTH (expanded));
+ else if (PACK_EXPANSION_P (expanded)
+ || (TREE_CODE (expanded) == TREE_VEC
+ && len > 0
+ && PACK_EXPANSION_P (TREE_VEC_ELT (expanded, len-1))))
+ {
+ if (TREE_CODE (expanded) == TREE_VEC)
+ expanded = TREE_VEC_ELT (expanded, len - 1);
+
+ if (TYPE_P (expanded))
+ return cxx_sizeof_or_alignof_type (expanded, SIZEOF_EXPR,
+ complain & tf_error);
+ else
+ return cxx_sizeof_or_alignof_expr (expanded, SIZEOF_EXPR,
+ complain & tf_error);
+ }
+ else
+ return build_int_cst (size_type_node, len);
}
/* Fall through */
switch (OMP_CLAUSE_CODE (nc))
{
+ case OMP_CLAUSE_LASTPRIVATE:
+ if (OMP_CLAUSE_LASTPRIVATE_STMT (oc))
+ {
+ OMP_CLAUSE_LASTPRIVATE_STMT (nc) = push_stmt_list ();
+ tsubst_expr (OMP_CLAUSE_LASTPRIVATE_STMT (oc), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
+ OMP_CLAUSE_LASTPRIVATE_STMT (nc)
+ = pop_stmt_list (OMP_CLAUSE_LASTPRIVATE_STMT (nc));
+ }
+ /* FALLTHRU */
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_SHARED:
case OMP_CLAUSE_FIRSTPRIVATE:
- case OMP_CLAUSE_LASTPRIVATE:
case OMP_CLAUSE_REDUCTION:
case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_COPYPRIVATE:
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_SCHEDULE:
+ case OMP_CLAUSE_COLLAPSE:
OMP_CLAUSE_OPERAND (nc, 0)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
+ case OMP_CLAUSE_UNTIED:
break;
default:
gcc_unreachable ();
#undef RECUR
}
+/* Substitute one OMP_FOR iterator. */
+
+static void
+tsubst_omp_for_iterator (tree t, int i, tree declv, tree initv,
+ tree condv, tree incrv, tree *clauses,
+ tree args, tsubst_flags_t complain, tree in_decl,
+ bool integral_constant_expression_p)
+{
+#define RECUR(NODE) \
+ tsubst_expr ((NODE), args, complain, in_decl, \
+ integral_constant_expression_p)
+ tree decl, init, cond, incr;
+
+ init = TREE_VEC_ELT (OMP_FOR_INIT (t), i);
+ gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
+ decl = RECUR (TREE_OPERAND (init, 0));
+ init = TREE_OPERAND (init, 1);
+ gcc_assert (!type_dependent_expression_p (decl));
+
+ if (!CLASS_TYPE_P (TREE_TYPE (decl)))
+ {
+ cond = RECUR (TREE_VEC_ELT (OMP_FOR_COND (t), i));
+ incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i);
+ if (TREE_CODE (incr) == MODIFY_EXPR)
+ incr = build_x_modify_expr (RECUR (TREE_OPERAND (incr, 0)), NOP_EXPR,
+ RECUR (TREE_OPERAND (incr, 1)),
+ complain);
+ else
+ incr = RECUR (incr);
+ TREE_VEC_ELT (declv, i) = decl;
+ TREE_VEC_ELT (initv, i) = init;
+ TREE_VEC_ELT (condv, i) = cond;
+ TREE_VEC_ELT (incrv, i) = incr;
+ return;
+ }
+
+ if (init && TREE_CODE (init) != DECL_EXPR)
+ {
+ tree c;
+ for (c = *clauses; c ; c = OMP_CLAUSE_CHAIN (c))
+ {
+ if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
+ && OMP_CLAUSE_DECL (c) == decl)
+ break;
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+ && OMP_CLAUSE_DECL (c) == decl)
+ error ("iteration variable %qD should not be firstprivate", decl);
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_DECL (c) == decl)
+ error ("iteration variable %qD should not be reduction", decl);
+ }
+ if (c == NULL)
+ {
+ c = build_omp_clause (OMP_CLAUSE_PRIVATE);
+ OMP_CLAUSE_DECL (c) = decl;
+ c = finish_omp_clauses (c);
+ if (c)
+ {
+ OMP_CLAUSE_CHAIN (c) = *clauses;
+ *clauses = c;
+ }
+ }
+ }
+ cond = TREE_VEC_ELT (OMP_FOR_COND (t), i);
+ if (COMPARISON_CLASS_P (cond))
+ cond = build2 (TREE_CODE (cond), boolean_type_node,
+ RECUR (TREE_OPERAND (cond, 0)),
+ RECUR (TREE_OPERAND (cond, 1)));
+ else
+ cond = RECUR (cond);
+ incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i);
+ switch (TREE_CODE (incr))
+ {
+ case PREINCREMENT_EXPR:
+ case PREDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ incr = build2 (TREE_CODE (incr), TREE_TYPE (decl),
+ RECUR (TREE_OPERAND (incr, 0)), NULL_TREE);
+ break;
+ case MODIFY_EXPR:
+ if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
+ || TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR)
+ {
+ tree rhs = TREE_OPERAND (incr, 1);
+ incr = build2 (MODIFY_EXPR, TREE_TYPE (decl),
+ RECUR (TREE_OPERAND (incr, 0)),
+ build2 (TREE_CODE (rhs), TREE_TYPE (decl),
+ RECUR (TREE_OPERAND (rhs, 0)),
+ RECUR (TREE_OPERAND (rhs, 1))));
+ }
+ else
+ incr = RECUR (incr);
+ break;
+ case MODOP_EXPR:
+ if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
+ || TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR)
+ {
+ tree lhs = RECUR (TREE_OPERAND (incr, 0));
+ incr = build2 (MODIFY_EXPR, TREE_TYPE (decl), lhs,
+ build2 (TREE_CODE (TREE_OPERAND (incr, 1)),
+ TREE_TYPE (decl), lhs,
+ RECUR (TREE_OPERAND (incr, 2))));
+ }
+ else if (TREE_CODE (TREE_OPERAND (incr, 1)) == NOP_EXPR
+ && (TREE_CODE (TREE_OPERAND (incr, 2)) == PLUS_EXPR
+ || (TREE_CODE (TREE_OPERAND (incr, 2)) == MINUS_EXPR)))
+ {
+ tree rhs = TREE_OPERAND (incr, 2);
+ incr = build2 (MODIFY_EXPR, TREE_TYPE (decl),
+ RECUR (TREE_OPERAND (incr, 0)),
+ build2 (TREE_CODE (rhs), TREE_TYPE (decl),
+ RECUR (TREE_OPERAND (rhs, 0)),
+ RECUR (TREE_OPERAND (rhs, 1))));
+ }
+ else
+ incr = RECUR (incr);
+ break;
+ default:
+ incr = RECUR (incr);
+ break;
+ }
+
+ TREE_VEC_ELT (declv, i) = decl;
+ TREE_VEC_ELT (initv, i) = init;
+ TREE_VEC_ELT (condv, i) = cond;
+ TREE_VEC_ELT (incrv, i) = incr;
+#undef RECUR
+}
+
/* Like tsubst_copy for expressions, etc. but also does semantic
processing. */
/*is_type_p=*/false,
/*complain=*/false);
if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
- qualified_name_lookup_error (scope, name, decl);
+ qualified_name_lookup_error (scope, name, decl, input_location);
else
do_local_using_decl (decl, scope, name);
}
= OMP_PARALLEL_COMBINED (t);
break;
+ case OMP_TASK:
+ tmp = tsubst_omp_clauses (OMP_TASK_CLAUSES (t),
+ args, complain, in_decl);
+ stmt = begin_omp_task ();
+ RECUR (OMP_TASK_BODY (t));
+ finish_omp_task (tmp, stmt);
+ break;
+
case OMP_FOR:
{
- tree clauses, decl, init, cond, incr, body, pre_body;
+ tree clauses, body, pre_body;
+ tree declv, initv, condv, incrv;
+ int i;
clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t),
args, complain, in_decl);
- init = OMP_FOR_INIT (t);
- gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
- decl = RECUR (TREE_OPERAND (init, 0));
- init = RECUR (TREE_OPERAND (init, 1));
- cond = RECUR (OMP_FOR_COND (t));
- incr = RECUR (OMP_FOR_INCR (t));
+ declv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ initv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ condv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ incrv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+
+ for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++)
+ tsubst_omp_for_iterator (t, i, declv, initv, condv, incrv,
+ &clauses, args, complain, in_decl,
+ integral_constant_expression_p);
stmt = begin_omp_structured_block ();
+ for (i = 0; i < TREE_VEC_LENGTH (initv); i++)
+ if (TREE_VEC_ELT (initv, i) == NULL
+ || TREE_CODE (TREE_VEC_ELT (initv, i)) != DECL_EXPR)
+ TREE_VEC_ELT (initv, i) = RECUR (TREE_VEC_ELT (initv, i));
+ else if (CLASS_TYPE_P (TREE_TYPE (TREE_VEC_ELT (initv, i))))
+ {
+ tree init = RECUR (TREE_VEC_ELT (initv, i));
+ gcc_assert (init == TREE_VEC_ELT (declv, i));
+ TREE_VEC_ELT (initv, i) = NULL_TREE;
+ }
+ else
+ {
+ tree decl_expr = TREE_VEC_ELT (initv, i);
+ tree init = DECL_INITIAL (DECL_EXPR_DECL (decl_expr));
+ gcc_assert (init != NULL);
+ TREE_VEC_ELT (initv, i) = RECUR (init);
+ DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = NULL;
+ RECUR (decl_expr);
+ DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = init;
+ }
+
pre_body = push_stmt_list ();
RECUR (OMP_FOR_PRE_BODY (t));
pre_body = pop_stmt_list (pre_body);
RECUR (OMP_FOR_BODY (t));
body = pop_stmt_list (body);
- t = finish_omp_for (EXPR_LOCATION (t), decl, init, cond, incr, body,
- pre_body);
- if (t)
- OMP_FOR_CLAUSES (t) = clauses;
+ t = finish_omp_for (EXPR_LOCATION (t), declv, initv, condv, incrv,
+ body, pre_body, clauses);
add_stmt (finish_omp_structured_block (stmt));
}
/*done=*/true,
/*address_p=*/false,
/*template_arg_p=*/false,
- &error_msg);
+ &error_msg,
+ input_location);
if (error_msg)
error (error_msg);
if (!function_p && TREE_CODE (decl) == IDENTIFIER_NODE)
case TEMPLATE_ID_EXPR:
{
tree object;
- tree template = RECUR (TREE_OPERAND (t, 0));
+ tree templ = RECUR (TREE_OPERAND (t, 0));
tree targs = TREE_OPERAND (t, 1);
if (targs)
targs = tsubst_template_args (targs, args, complain, in_decl);
- if (TREE_CODE (template) == COMPONENT_REF)
+ if (TREE_CODE (templ) == COMPONENT_REF)
{
- object = TREE_OPERAND (template, 0);
- template = TREE_OPERAND (template, 1);
+ object = TREE_OPERAND (templ, 0);
+ templ = TREE_OPERAND (templ, 1);
}
else
object = NULL_TREE;
- template = lookup_template_function (template, targs);
+ templ = lookup_template_function (templ, targs);
if (object)
- return build3 (COMPONENT_REF, TREE_TYPE (template),
- object, template, NULL_TREE);
+ return build3 (COMPONENT_REF, TREE_TYPE (templ),
+ object, templ, NULL_TREE);
else
- return baselink_for_fns (template);
+ return baselink_for_fns (templ);
}
case INDIRECT_REF:
r = convert_from_reference (r);
}
else
- r = build_x_indirect_ref (r, "unary *");
+ r = build_x_indirect_ref (r, "unary *", complain);
return r;
}
if (integral_constant_expression_p
&& !cast_valid_in_integral_constant_expression_p (type))
{
- error ("a cast to a type other than an integral or "
- "enumeration type cannot appear in a constant-expression");
+ if (complain & tf_error)
+ error ("a cast to a type other than an integral or "
+ "enumeration type cannot appear in a constant-expression");
return error_mark_node;
}
switch (TREE_CODE (t))
{
case CAST_EXPR:
- return build_functional_cast (type, op);
+ return build_functional_cast (type, op, complain);
case REINTERPRET_CAST_EXPR:
- return build_reinterpret_cast (type, op);
+ return build_reinterpret_cast (type, op, complain);
case CONST_CAST_EXPR:
- return build_const_cast (type, op);
+ return build_const_cast (type, op, complain);
case DYNAMIC_CAST_EXPR:
- return build_dynamic_cast (type, op);
+ return build_dynamic_cast (type, op, complain);
case STATIC_CAST_EXPR:
- return build_static_cast (type, op);
+ return build_static_cast (type, op, complain);
default:
gcc_unreachable ();
}
case POSTINCREMENT_EXPR:
op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
args, complain, in_decl);
- return build_x_unary_op (TREE_CODE (t), op1);
+ return build_x_unary_op (TREE_CODE (t), op1, complain);
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
case UNARY_PLUS_EXPR: /* Unary + */
case REALPART_EXPR:
case IMAGPART_EXPR:
- return build_x_unary_op (TREE_CODE (t), RECUR (TREE_OPERAND (t, 0)));
+ return build_x_unary_op (TREE_CODE (t), RECUR (TREE_OPERAND (t, 0)),
+ complain);
case ADDR_EXPR:
op1 = TREE_OPERAND (t, 0);
in_decl);
if (TREE_CODE (op1) == LABEL_DECL)
return finish_label_address_expr (DECL_NAME (op1));
- return build_x_unary_op (ADDR_EXPR, op1);
+ return build_x_unary_op (ADDR_EXPR, op1, complain);
case PLUS_EXPR:
case MINUS_EXPR:
(TREE_NO_WARNING (TREE_OPERAND (t, 1))
? ERROR_MARK
: TREE_CODE (TREE_OPERAND (t, 1))),
- /*overloaded_p=*/NULL);
+ /*overloaded_p=*/NULL,
+ complain);
case SCOPE_REF:
return tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
(TREE_NO_WARNING (TREE_OPERAND (t, 1))
? ERROR_MARK
: TREE_CODE (TREE_OPERAND (t, 1))),
- /*overloaded_p=*/NULL);
+ /*overloaded_p=*/NULL,
+ complain);
case SIZEOF_EXPR:
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
- {
- /* 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));
- }
+ return tsubst_copy (t, args, complain, in_decl);
/* Fall through */
case ALIGNOF_EXPR:
--skip_evaluation;
}
if (TYPE_P (op1))
- return cxx_sizeof_or_alignof_type (op1, TREE_CODE (t), true);
+ return cxx_sizeof_or_alignof_type (op1, TREE_CODE (t),
+ complain & tf_error);
else
- return cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t));
+ return cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
+ complain & tf_error);
case MODOP_EXPR:
{
tree r = build_x_modify_expr
(RECUR (TREE_OPERAND (t, 0)),
TREE_CODE (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2)));
+ RECUR (TREE_OPERAND (t, 2)),
+ complain);
/* TREE_NO_WARNING must be set if either the expression was
parenthesized or it uses an operator such as >>= rather
than plain assignment. In the former case, it was already
tree init = RECUR (TREE_OPERAND (t, 3));
if (TREE_OPERAND (t, 3) && !init)
- /* If there was an initializer in the the original tree, but
+ /* If there was an initializer in 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
RECUR (TREE_OPERAND (t, 1)),
RECUR (TREE_OPERAND (t, 2)),
init,
- NEW_EXPR_USE_GLOBAL (t));
+ NEW_EXPR_USE_GLOBAL (t),
+ complain);
}
case DELETE_EXPR:
case COMPOUND_EXPR:
return build_x_compound_expr (RECUR (TREE_OPERAND (t, 0)),
- RECUR (TREE_OPERAND (t, 1)));
+ RECUR (TREE_OPERAND (t, 1)),
+ complain);
case CALL_EXPR:
{
if (!BASELINK_P (TREE_OPERAND (function, 1)))
return finish_call_expr (function, call_args,
/*disallow_virtual=*/false,
- /*koenig_p=*/false);
+ /*koenig_p=*/false,
+ complain);
else
return (build_new_method_call
(TREE_OPERAND (function, 0),
TREE_OPERAND (function, 1),
call_args, NULL_TREE,
qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL,
- /*fn_p=*/NULL));
+ /*fn_p=*/NULL,
+ complain));
}
return finish_call_expr (function, call_args,
/*disallow_virtual=*/qualified_p,
- koenig_p);
+ koenig_p,
+ complain);
}
case COND_EXPR:
return build_x_conditional_expr
(RECUR (TREE_OPERAND (t, 0)),
RECUR (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2)));
+ RECUR (TREE_OPERAND (t, 2)),
+ complain);
case PSEUDO_DTOR_EXPR:
return finish_pseudo_destructor_expr
}
else
{
- qualified_name_lookup_error (object_type, tmpl, member);
+ qualified_name_lookup_error (object_type, tmpl, member,
+ input_location);
return error_mark_node;
}
}
return finish_non_static_data_member (member, object, NULL_TREE);
return finish_class_member_access_expr (object, member,
- /*template_p=*/false);
+ /*template_p=*/false,
+ complain);
}
case THROW_EXPR:
bool process_index_p;
int newlen;
bool need_copy_p = false;
+ tree r;
if (type == error_mark_node)
return error_mark_node;
/* We do not want to process the index of aggregate
initializers as they are identifier nodes which will be
looked up by digest_init. */
- process_index_p = !(type && IS_AGGR_TYPE (type));
+ process_index_p = !(type && MAYBE_CLASS_TYPE_P (type));
n = VEC_copy (constructor_elt, gc, CONSTRUCTOR_ELTS (t));
newlen = VEC_length (constructor_elt, n);
}
}
+ r = build_constructor (init_list_type_node, n);
+
if (TREE_HAS_CONSTRUCTOR (t))
- return finish_compound_literal (type, n);
+ return finish_compound_literal (type, r);
- return build_constructor (NULL_TREE, n);
+ return r;
}
case TYPEID_EXPR:
}
}
+ /* 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:
arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg,
arg_expr);
+ if (arg == init_list_type_node && arg_expr)
+ arg = arg_expr;
if (unify (tparms, targs, parm, arg, arg_strict))
return 1;
}
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 rval = NULL_TREE;
tree binfo;
- gcc_assert (IS_AGGR_TYPE_CODE (TREE_CODE (arg)));
+ gcc_assert (RECORD_OR_UNION_CODE_P (TREE_CODE (arg)));
binfo = TYPE_BINFO (complete_type (arg));
if (!binfo)
{
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))
{
if (arg == error_mark_node)
return 1;
- if (arg == unknown_type_node)
+ if (arg == unknown_type_node
+ || arg == init_list_type_node)
/* We can't deduce anything from this, but we might get all the
template args from other function args. */
return 0;
if (arg == parm && !uses_template_parms (parm))
return 0;
+ /* Handle init lists early, so the rest of the function can assume
+ we're dealing with a type. */
+ if (BRACE_ENCLOSED_INITIALIZER_P (arg))
+ {
+ tree elt, elttype;
+ unsigned i;
+
+ if (!is_std_init_list (parm))
+ /* We can only deduce from an initializer list argument if the
+ parameter is std::initializer_list; otherwise this is a
+ non-deduced context. */
+ return 0;
+
+ elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (parm), 0);
+
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
+ {
+ if (!BRACE_ENCLOSED_INITIALIZER_P (elt))
+ elt = TREE_TYPE (elt);
+ if (unify (tparms, targs, elttype, elt, UNIFY_ALLOW_NONE))
+ return 1;
+ }
+ return 0;
+ }
+
/* Immediately reject some pairs that won't unify because of
cv-qualification mismatches. */
if (TREE_CODE (arg) == TREE_CODE (parm)
{
tree parmvec = TYPE_TI_ARGS (parm);
tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
- tree argtmplvec
- = DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (arg));
- int i;
+ tree parm_parms
+ = DECL_INNERMOST_TEMPLATE_PARMS
+ (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm));
+ 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
Here, if Lvalue_proxy is permitted to bind to View, then
the global operator+ will be used; if they are not, the
Lvalue_proxy will be converted to float. */
- if (coerce_template_parms (argtmplvec, parmvec,
+ if (coerce_template_parms (parm_parms,
+ argvec,
TYPE_TI_TEMPLATE (parm),
tf_none,
/*require_all_args=*/true,
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);
/* CV qualifications for methods can never be deduced, they must
match exactly. We need to check them explicitly here,
because type_unification_real treats them as any other
- cvqualified parameter. */
+ cv-qualified parameter. */
if (TREE_CODE (parm) == METHOD_TYPE
&& (!check_cv_quals_for_unify
(UNIFY_ALLOW_NONE,
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
processing_template_decl++;
- while (len--)
+ while (len--
+ /* Stop when an ellipsis is seen. */
+ && args1 != NULL_TREE && args2 != NULL_TREE)
{
tree arg1 = TREE_VALUE (args1);
tree arg2 = TREE_VALUE (args2);
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;
}
the first instantiation was `extern' and the second is not,
and EXTERN_P for the opposite case. */
if (DECL_NOT_REALLY_EXTERN (result) && !extern_p)
- pedwarn ("duplicate explicit instantiation of %q#D", result);
+ permerror ("duplicate explicit instantiation of %q#D", result);
/* If an "extern" explicit instantiation follows an ordinary
explicit instantiation, the template is instantiated. */
if (extern_p)
}
else if (!DECL_TEMPLATE_INFO (result))
{
- pedwarn ("explicit instantiation of non-template %q#D", result);
+ permerror ("explicit instantiation of non-template %q#D", result);
return;
}
;
else if (storage == ridpointers[(int) RID_EXTERN])
{
- if (pedantic && !in_system_header)
- pedwarn ("ISO C++ forbids the use of %<extern%> on explicit "
+ if (pedantic && !in_system_header && (cxx_dialect == cxx98))
+ pedwarn ("ISO C++ 1998 forbids the use of %<extern%> on explicit "
"instantiations");
extern_p = 1;
}
{
tree storage = *(tree *) data;
- if (IS_AGGR_TYPE (entry->type)
+ if (MAYBE_CLASS_TYPE_P (entry->type)
&& !uses_template_parms (CLASSTYPE_TI_ARGS (entry->type)))
do_type_instantiation (TYPE_MAIN_DECL (entry->type), storage, 0);
}
if (storage != NULL_TREE)
{
if (pedantic && !in_system_header)
- pedwarn("ISO C++ forbids the use of %qE on explicit instantiations",
- storage);
+ {
+ if (storage == ridpointers[(int) RID_EXTERN])
+ {
+ if (cxx_dialect == cxx98)
+ pedwarn("ISO C++ 1998 forbids the use of %<extern%> on "
+ "explicit instantiations");
+ }
+ else
+ pedwarn("ISO C++ forbids the use of %qE on explicit "
+ "instantiations", storage);
+ }
if (storage == ridpointers[(int) RID_INLINE])
nomem_p = 1;
if (!previous_instantiation_extern_p && !extern_p
&& (complain & tf_error))
- pedwarn ("duplicate explicit instantiation of %q#T", t);
+ permerror ("duplicate explicit instantiation of %q#T", t);
/* If we've already instantiated the template, just return now. */
if (!CLASSTYPE_INTERFACE_ONLY (t))
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
member function or static data member of a class template
shall be present in every translation unit in which it is
explicitly instantiated. */
- pedwarn
+ permerror
("explicit instantiation of %qD but no definition available", d);
/* ??? Historically, we have instantiated inline functions, even
out:
input_location = saved_loc;
- in_system_header = saved_in_system_header;
pop_deferring_access_checks ();
pop_tinst_level ();
{
int reconsider;
location_t saved_loc = input_location;
- int saved_in_system_header = in_system_header;
/* Instantiating templates may trigger vtable generation. This in turn
may require further template instantiations. We place a limit here
while (reconsider);
input_location = saved_loc;
- in_system_header = saved_in_system_header;
}
/* Substitute ARGVEC into T, which is a list of initializers for
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);
+ if (expanded_exprs == error_mark_node)
+ continue;
+
+ /* 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)
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 ... */
/* 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
|| any_dependent_template_arguments_p (args));
}
+/* Returns TRUE if OMP_FOR with DECLV, INITV, CONDV and INCRV vectors
+ is dependent. */
+
+bool
+dependent_omp_for_p (tree declv, tree initv, tree condv, tree incrv)
+{
+ int i;
+
+ if (!processing_template_decl)
+ return false;
+
+ for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
+ {
+ tree decl = TREE_VEC_ELT (declv, i);
+ tree init = TREE_VEC_ELT (initv, i);
+ tree cond = TREE_VEC_ELT (condv, i);
+ tree incr = TREE_VEC_ELT (incrv, i);
+
+ if (type_dependent_expression_p (decl))
+ return true;
+
+ if (init && type_dependent_expression_p (init))
+ return true;
+
+ if (type_dependent_expression_p (cond))
+ return true;
+
+ if (COMPARISON_CLASS_P (cond)
+ && (type_dependent_expression_p (TREE_OPERAND (cond, 0))
+ || type_dependent_expression_p (TREE_OPERAND (cond, 1))))
+ return true;
+
+ if (TREE_CODE (incr) == MODOP_EXPR)
+ {
+ if (type_dependent_expression_p (TREE_OPERAND (incr, 0))
+ || type_dependent_expression_p (TREE_OPERAND (incr, 2)))
+ return true;
+ }
+ else if (type_dependent_expression_p (incr))
+ return true;
+ else if (TREE_CODE (incr) == MODIFY_EXPR)
+ {
+ if (type_dependent_expression_p (TREE_OPERAND (incr, 0)))
+ return true;
+ else if (BINARY_CLASS_P (TREE_OPERAND (incr, 1)))
+ {
+ tree t = TREE_OPERAND (incr, 1);
+ if (type_dependent_expression_p (TREE_OPERAND (t, 0))
+ || type_dependent_expression_p (TREE_OPERAND (t, 1)))
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
/* TYPE is a TYPENAME_TYPE. Returns the ordinary TYPE to which the
TYPENAME_TYPE corresponds. Returns the original TYPENAME_TYPE if
no such TYPE can be found. Note that this function peers inside