/* 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 (input_location, "specialization of %qD in different namespace", tmpl);
+ permerror (input_location, " from definition of %q+#D", tmpl);
return false;
}
}
namespace of its template. */
ns = decl_namespace_context (spec);
if (!is_ancestor (current_namespace, ns))
- pedwarn ("explicit instantiation of %qD in namespace %qD "
- "(which does not enclose namespace %qD)",
- spec, current_namespace, ns);
+ permerror (input_location, "explicit instantiation of %qD in namespace %qD "
+ "(which does not enclose namespace %qD)",
+ spec, current_namespace, ns);
}
/* The TYPE is being declared. If it is a template type, that means it
check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type));
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
if (processing_template_decl)
- push_template_decl (TYPE_MAIN_DECL (type));
+ {
+ if (push_template_decl (TYPE_MAIN_DECL (type))
+ == error_mark_node)
+ return error_mark_node;
+ }
}
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
error ("specialization of %qT after instantiation", type);
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 (input_location, "specializing %q#T in different namespace", type);
+ permerror (input_location, " 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;
to the primary function; now copy the inline bits to
the various clones. */
FOR_EACH_CLONE (clone, fn)
- {
- DECL_DECLARED_INLINE_P (clone)
- = DECL_DECLARED_INLINE_P (fn);
- DECL_INLINE (clone)
- = DECL_INLINE (fn);
- }
+ DECL_DECLARED_INLINE_P (clone)
+ = DECL_DECLARED_INLINE_P (fn);
check_specialization_namespace (fn);
return fn;
for (; t; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t))
{
- pedwarn
- ("default argument specified in explicit specialization");
+ permerror (input_location,
+ "default argument specified in explicit specialization");
break;
}
}
{
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]:
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;
};
tree t = *tp;
struct find_parameter_pack_data* ppd =
(struct find_parameter_pack_data*)data;
+ bool parameter_pack_p = false;
- if (TYPE_P (t))
+ /* Identify whether this is a parameter pack or not. */
+ switch (TREE_CODE (t))
+ {
+ case TEMPLATE_PARM_INDEX:
+ if (TEMPLATE_PARM_PARAMETER_PACK (t))
+ parameter_pack_p = true;
+ break;
+
+ case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
+ if (TEMPLATE_TYPE_PARAMETER_PACK (t))
+ parameter_pack_p = true;
+ break;
+
+ case PARM_DECL:
+ if (FUNCTION_PARAMETER_PACK_P (t))
+ {
+ /* We don't want to walk into the type of a PARM_DECL,
+ because we don't want to see the type parameter pack. */
+ *walk_subtrees = 0;
+ parameter_pack_p = true;
+ }
+ break;
+
+ default:
+ /* Not a parameter pack. */
+ break;
+ }
+
+ if (parameter_pack_p)
{
- tree context = TYPE_CONTEXT (t);
- cp_walk_tree (&context, &find_parameter_packs_r, ppd, ppd->visited);
+ /* Add this parameter pack to the list. */
+ *ppd->parameter_packs = tree_cons (NULL_TREE, t, *ppd->parameter_packs);
}
+ if (TYPE_P (t))
+ cp_walk_tree (&TYPE_CONTEXT (t),
+ &find_parameter_packs_r, ppd, ppd->visited);
+
/* This switch statement will return immediately if we don't find a
parameter pack. */
switch (TREE_CODE (t))
{
case TEMPLATE_PARM_INDEX:
- if (TEMPLATE_PARM_PARAMETER_PACK (t))
- break;
return NULL_TREE;
case BOUND_TEMPLATE_TEMPLATE_PARM:
+ /* Check the template itself. */
+ cp_walk_tree (&TREE_TYPE (TYPE_TI_TEMPLATE (t)),
+ &find_parameter_packs_r, ppd, ppd->visited);
/* Check the template arguments. */
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);
*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, ppd->visited);
*walk_subtrees = 0;
return NULL_TREE;
case TEMPLATE_DECL:
- if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)
- && TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (t)))
- break;
-
- *walk_subtrees = 0;
+ cp_walk_tree (&TREE_TYPE (t),
+ &find_parameter_packs_r, ppd, ppd->visited);
return NULL_TREE;
case TYPENAME_TYPE:
ppd, ppd->visited);
*walk_subtrees = 0;
return NULL_TREE;
-
case TYPE_PACK_EXPANSION:
case EXPR_PACK_EXPANSION:
*walk_subtrees = 0;
return NULL_TREE;
+ case IDENTIFIER_NODE:
+ cp_walk_tree (&TREE_TYPE (t), &find_parameter_packs_r, ppd,
+ ppd->visited);
+ *walk_subtrees = 0;
+ return NULL_TREE;
+
default:
return NULL_TREE;
}
-
- /* Add this parameter pack to the list. */
- *ppd->parameter_packs = tree_cons (NULL_TREE, t, *ppd->parameter_packs);
return NULL_TREE;
}
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)
{
struct find_parameter_pack_data ppd;
if (!processing_template_decl || !t || t == error_mark_node)
- return true;
+ return false;
if (TREE_CODE (t) == TYPE_DECL)
t = TREE_TYPE (t);
if (parameter_packs)
{
- error ("parameter packs not expanded with `...':");
+ error ("parameter packs not expanded with %<...%>:");
while (parameter_packs)
{
tree pack = TREE_VALUE (parameter_packs);
name = DECL_NAME (TEMPLATE_PARM_DECL (pack));
else
name = DECL_NAME (pack);
- inform (" %qD", name);
+
+ if (name)
+ inform (input_location, " %qD", name);
+ else
+ inform (input_location, " <anonymous>");
parameter_packs = TREE_CHAIN (parameter_packs);
}
- return false;
+ return true;
}
- return true;
+ return false;
}
/* Expand any parameter packs that occur in the template arguments in
return result_args;
}
-/* Complain if DECL shadows a template parameter.
+/* Checks if DECL shadows a template parameter.
[temp.local]: A template-parameter shall not be redeclared within its
- scope (including nested scopes). */
+ scope (including nested scopes).
-void
+ Emits an error and returns TRUE if the DECL shadows a parameter,
+ returns FALSE otherwise. */
+
+bool
check_template_shadow (tree decl)
{
tree olddecl;
/* If we're not in a template, we can't possibly shadow a template
parameter. */
if (!current_template_parms)
- return;
+ return true;
/* Figure out what we're shadowing. */
if (TREE_CODE (decl) == OVERLOAD)
/* If there's no previous binding for this name, we're not shadowing
anything, let alone a template parameter. */
if (!olddecl)
- return;
+ return true;
/* If we're not shadowing a template parameter, we're done. Note
that OLDDECL might be an OVERLOAD (or perhaps even an
ERROR_MARK), so we can't just blithely assume it to be a _DECL
node. */
if (!DECL_P (olddecl) || !DECL_TEMPLATE_PARM_P (olddecl))
- return;
+ return true;
/* We check for decl != olddecl to avoid bogus errors for using a
name inside a class. We check TPFI to avoid duplicate errors for
inline member templates. */
if (decl == olddecl
|| TEMPLATE_PARMS_FOR_INLINE (current_template_parms))
- return;
+ return true;
error ("declaration of %q+#D", decl);
error (" shadows template parm %q+#D", olddecl);
+ return false;
}
/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
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);
/* 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)
tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
tree specargs = CLASSTYPE_TI_ARGS (type);
tree inner_args = INNERMOST_TEMPLATE_ARGS (specargs);
- tree inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl);
+ tree inner_parms;
int nargs = TREE_VEC_LENGTH (inner_args);
- int ntparms = TREE_VEC_LENGTH (inner_parms);
+ int ntparms;
int i;
int did_error_intro = 0;
struct template_parm_data tpd;
struct template_parm_data tpd2;
+ gcc_assert (current_template_parms);
+
+ inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
+ ntparms = TREE_VEC_LENGTH (inner_parms);
+
/* We check that each of the template parameters given in the
partial specialization is used in the argument list to the
specialization. For example:
for_each_template_parm (TREE_VEC_ELT (inner_args, i),
&mark_template_parm,
&tpd,
- NULL);
+ NULL,
+ /*include_nondeduced_p=*/false);
}
for (i = 0; i < ntparms; ++i)
if (tpd.parms[i] == 0)
if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
error ("parameter pack argument %qE must be at the end of the template argument list", arg);
else
- error ("parameter pack argument %qT must be at the end of the template argument list", arg);
+ error ("parameter pack argument %qT must be at the end of the template argument list", arg);
+
+ if (packed_args)
+ TREE_VEC_ELT (packed_args, j) = error_mark_node;
}
}
for_each_template_parm (type,
&mark_template_parm,
&tpd2,
- NULL);
+ NULL,
+ /*include_nondeduced_p=*/false);
if (tpd2.arg_uses_template_parms [i])
{
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
if (TREE_PURPOSE (parm))
seen_def_arg_p = 1;
- else if (seen_def_arg_p)
+ else if (seen_def_arg_p
+ && !template_parameter_pack_p (TREE_VALUE (parm)))
{
error ("no default argument for %qD", TREE_VALUE (parm));
/* For better subsequent error-recovery, we indicate that
TREE_PURPOSE (parm) = error_mark_node;
no_errors = false;
}
+ else if (is_primary
+ && !is_partial
+ && !is_friend_decl
+ /* Don't complain about an enclosing partial
+ specialization. */
+ && parm_level == parms
+ && TREE_CODE (decl) == TYPE_DECL
+ && i < ntparms - 1
+ && template_parameter_pack_p (TREE_VALUE (parm)))
+ {
+ /* 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;
+ }
}
}
}
[temp.mem]. */
bool member_template_p = false;
- if (decl == error_mark_node)
- return decl;
+ if (decl == error_mark_node || !current_template_parms)
+ return error_mark_node;
/* See if this is a partial specialization. */
is_partial = (DECL_IMPLICIT_TYPEDEF_P (decl)
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));
- }
- }
- }
-
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);
template arguments to %qD do not match original template %qD",
decl, DECL_TEMPLATE_RESULT (tmpl));
if (!uses_template_parms (TI_ARGS (tinfo)))
- inform ("use template<> for an explicit specialization");
+ inform (input_location, "use template<> for an explicit specialization");
/* Avoid crash in import_export_decl. */
DECL_INTERFACE_KNOWN (decl) = 1;
return error_mark_node;
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 (input_location, "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 (input_location, "%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
{
error ("%qE is not a valid template argument for type %qT "
"because it is a pointer", expr, type);
- inform ("try using %qE instead", TREE_OPERAND (expr, 0));
+ inform (input_location, "try using %qE instead", TREE_OPERAND (expr, 0));
return NULL_TREE;
}
error ("%qE is not a valid template argument for type %qT "
"because it is of type %qT", expr, type,
TREE_TYPE (expr));
- inform ("standard conversions are not allowed in this context");
+ inform (input_location, "standard conversions are not allowed in this context");
return NULL_TREE;
}
}
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 (!uses_template_parms (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 (input_location, "to refer to a type member of a template parameter, "
+ "use %<typename %E%>", orig_arg);
orig_arg = make_typename_type (TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1),
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 (invalid_nontype_parm_type_p (t, complain))
return error_mark_node;
- if (!uses_template_parms (orig_arg) && !uses_template_parms (t))
+ if (template_parameter_pack_p (parm) && ARGUMENT_PACK_P (orig_arg))
+ {
+ if (same_type_p (t, TREE_TYPE (orig_arg)))
+ val = orig_arg;
+ else
+ {
+ /* Not sure if this is reachable, but it doesn't hurt
+ to be robust. */
+ error ("type mismatch in nontype parameter pack");
+ val = error_mark_node;
+ }
+ }
+ else if (!uses_template_parms (orig_arg) && !uses_template_parms (t))
/* We used to call digest_init here. However, digest_init
will report errors, which we don't want when complain
is zero. More importantly, digest_init will try too
{
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;
}
parameters. */
int variadic_p = 0;
- inner_args
- = expand_template_argument_pack (INNERMOST_TEMPLATE_ARGS (args));
-
- nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
nparms = TREE_VEC_LENGTH (parms);
/* Determine if there are any parameter packs. */
{
tree tparm = TREE_VALUE (TREE_VEC_ELT (parms, parm_idx));
if (template_parameter_pack_p (tparm))
- {
- variadic_p = 1;
- break;
- }
+ ++variadic_p;
}
- if ((nargs > nparms - variadic_p && !variadic_p)
+ inner_args = INNERMOST_TEMPLATE_ARGS (args);
+ /* If there are 0 or 1 parameter packs, we need to expand any argument
+ packs so that we can deduce a parameter pack from some non-packed args
+ followed by an argument pack, as in variadic85.C. If there are more
+ than that, we need to leave argument packs intact so the arguments are
+ assigned to the right parameter packs. This should only happen when
+ dealing with a nested class inside a partial specialization of a class
+ template, as in variadic92.C. */
+ if (variadic_p <= 1)
+ inner_args = expand_template_argument_pack (inner_args);
+
+ nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
+ if ((nargs > nparms && !variadic_p)
|| (nargs < nparms - variadic_p
&& require_all_args
&& (!use_default_args
}
/* Calculate the next argument. */
- if (template_parameter_pack_p (TREE_VALUE (parm)))
+ if (arg_idx < nargs)
+ arg = TREE_VEC_ELT (inner_args, arg_idx);
+ else
+ arg = NULL_TREE;
+
+ if (template_parameter_pack_p (TREE_VALUE (parm))
+ && !(arg && ARGUMENT_PACK_P (arg)))
{
- /* All remaining arguments will be placed in the
- template parameter pack PARM. */
- arg = coerce_template_parameter_pack (parms, parm_idx, args,
- inner_args, arg_idx,
- new_args, &lost,
- in_decl, complain);
-
+ /* All remaining arguments will be placed in the
+ template parameter pack PARM. */
+ arg = coerce_template_parameter_pack (parms, parm_idx, args,
+ inner_args, arg_idx,
+ new_args, &lost,
+ in_decl, complain);
+
/* Store this argument. */
if (arg == error_mark_node)
lost++;
TREE_VEC_ELT (new_inner_args, parm_idx) = arg;
- /* We are done with all of the arguments. */
- arg_idx = nargs;
-
+ /* We are done with all of the arguments. */
+ arg_idx = nargs;
+
continue;
}
- else if (arg_idx < nargs)
- {
- arg = TREE_VEC_ELT (inner_args, arg_idx);
-
- if (arg && PACK_EXPANSION_P (arg))
+ else if (arg)
+ {
+ if (PACK_EXPANSION_P (arg))
{
- /* If 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)
+ {
+ /* FIXME this restriction was removed by N2555; see
+ bug 35722. */
+ /* If ARG is a pack expansion, but PARM is not a
+ template parameter pack (if it were, we would have
+ handled it above), we're trying to expand into a
+ fixed-length argument list. */
+ if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
+ sorry ("cannot expand %<%E%> into a fixed-length "
+ "argument list", arg);
+ else
+ sorry ("cannot expand %<%T%> into a fixed-length "
+ "argument list", arg);
+ }
return error_mark_node;
}
}
return PACK_EXPANSION_P (nt)
&& template_args_equal (PACK_EXPANSION_PATTERN (ot),
PACK_EXPANSION_PATTERN (nt));
+ else if (ARGUMENT_PACK_P (ot))
+ {
+ int i, len;
+ tree opack, npack;
+
+ if (!ARGUMENT_PACK_P (nt))
+ return 0;
+
+ opack = ARGUMENT_PACK_ARGS (ot);
+ npack = ARGUMENT_PACK_ARGS (nt);
+ len = TREE_VEC_LENGTH (opack);
+ if (TREE_VEC_LENGTH (npack) != len)
+ return 0;
+ for (i = 0; i < len; ++i)
+ if (!template_args_equal (TREE_VEC_ELT (opack, i),
+ TREE_VEC_ELT (npack, i)))
+ return 0;
+ return 1;
+ }
else if (TYPE_P (nt))
return TYPE_P (ot) && same_type_p (ot, nt);
else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))
{
int i;
- oldargs = expand_template_argument_pack (oldargs);
- newargs = expand_template_argument_pack (newargs);
-
if (TREE_VEC_LENGTH (oldargs) != TREE_VEC_LENGTH (newargs))
return 0;
int entering_scope,
tsubst_flags_t complain)
{
- tree template = NULL_TREE, parmlist;
+ tree templ = NULL_TREE, parmlist;
tree t;
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
+ && DECL_TEMPLATE_RESULT (d1)
&& TREE_CODE (DECL_TEMPLATE_RESULT (d1)) == TYPE_DECL)
{
- template = d1;
- d1 = DECL_NAME (template);
- context = DECL_CONTEXT (template);
+ templ = d1;
+ d1 = DECL_NAME (templ);
+ context = DECL_CONTEXT (templ);
}
/* Issue an error message if we didn't find a template. */
- if (! template)
+ if (! templ)
{
if (complain & tf_error)
error ("%qT is not a template", d1);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
- if (TREE_CODE (template) != TEMPLATE_DECL
+ if (TREE_CODE (templ) != TEMPLATE_DECL
/* Make sure it's a user visible template, if it was named by
the user. */
- || ((complain & tf_user) && !DECL_TEMPLATE_PARM_P (template)
- && !PRIMARY_TEMPLATE_P (template)))
+ || ((complain & tf_user) && !DECL_TEMPLATE_PARM_P (templ)
+ && !PRIMARY_TEMPLATE_P (templ)))
{
if (complain & tf_error)
{
complain &= ~tf_user;
- if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))
+ if (DECL_TEMPLATE_TEMPLATE_PARM_P (templ))
{
/* Create a new TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM node to store
template arguments */
tree arglist2;
tree outer;
- parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
+ parmlist = DECL_INNERMOST_TEMPLATE_PARMS (templ);
/* Consider an example where a template template parameter declared as
level 1, and T at level 2, while the template arguments at level 1
becomes {std::vector} and the inner level 2 is {int}. */
- outer = DECL_CONTEXT (template);
+ outer = DECL_CONTEXT (templ);
if (outer)
outer = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (outer)));
else if (current_template_parms)
if (outer)
arglist = add_to_template_args (outer, arglist);
- arglist2 = coerce_template_parms (parmlist, arglist, template,
+ arglist2 = coerce_template_parms (parmlist, arglist, templ,
complain,
/*require_all_args=*/true,
/*use_default_args=*/true);
if (arglist2 == error_mark_node
|| (!uses_template_parms (arglist2)
- && check_instantiated_args (template, arglist2, complain)))
+ && check_instantiated_args (templ, arglist2, complain)))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- parm = bind_template_template_parm (TREE_TYPE (template), arglist2);
+ parm = bind_template_template_parm (TREE_TYPE (templ), arglist2);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, parm);
}
else
{
- tree template_type = TREE_TYPE (template);
+ tree template_type = TREE_TYPE (templ);
tree gen_tmpl;
tree type_decl;
tree found = NULL_TREE;
int parm_depth;
int is_partial_instantiation;
- gen_tmpl = most_general_template (template);
+ gen_tmpl = most_general_template (templ);
parmlist = DECL_TEMPLATE_PARMS (gen_tmpl);
parm_depth = TMPL_PARMS_DEPTH (parmlist);
arg_depth = TMPL_ARGS_DEPTH (arglist);
<class U> struct S1<T>::S2'. We must fill in the missing
arguments. */
arglist
- = add_outermost_template_args (TYPE_TI_ARGS (TREE_TYPE (template)),
+ = add_outermost_template_args (TYPE_TI_ARGS (TREE_TYPE (templ)),
arglist);
arg_depth = TMPL_ARGS_DEPTH (arglist);
}
/* From here on, we're only interested in the most general
template. */
- template = gen_tmpl;
+ 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;
if (!is_partial_instantiation)
{
set_current_access_from_decl (TYPE_NAME (template_type));
- t = start_enum (TYPE_IDENTIFIER (template_type));
+ t = start_enum (TYPE_IDENTIFIER (template_type),
+ tsubst (ENUM_UNDERLYING_TYPE (template_type),
+ arglist, complain, in_decl),
+ SCOPED_ENUM_P (template_type));
}
else
- /* We don't want to call start_enum for this type, since
- the values for the enumeration constants may involve
- template parameters. And, no one should be interested
- in the enumeration constants for such a type. */
- t = make_node (ENUMERAL_TYPE);
+ {
+ /* We don't want to call start_enum for this type, since
+ the values for the enumeration constants may involve
+ template parameters. And, no one should be interested
+ in the enumeration constants for such a type. */
+ t = make_node (ENUMERAL_TYPE);
+ SET_SCOPED_ENUM_P (t, SCOPED_ENUM_P (template_type));
+ }
}
else
{
- 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;
return level;
}
+/* Returns TRUE if PARM is a parameter of the template TEMPL. */
+
+bool
+parameter_of_template_p (tree parm, tree templ)
+{
+ tree parms;
+ int i;
+
+ if (!parm || !templ)
+ return false;
+
+ gcc_assert (DECL_TEMPLATE_PARM_P (parm));
+ gcc_assert (TREE_CODE (templ) == TEMPLATE_DECL);
+
+ parms = DECL_TEMPLATE_PARMS (templ);
+ parms = INNERMOST_TEMPLATE_PARMS (parms);
+
+ for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
+ if (parm == TREE_VALUE (TREE_VEC_ELT (parms, i)))
+ return true;
+
+ return false;
+}
+
/* DECL is a friend FUNCTION_DECL or TEMPLATE_DECL. ARGS is the
vector of template arguments, as for tsubst.
/* Friend functions are looked up in the containing namespace scope.
We must enter that scope, to avoid finding member functions of the
- current cless with same name. */
+ current class with same name. */
push_nested_namespace (ns);
fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
tf_warning_or_error, NULL_TREE,
> 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:
/* Clear out the mangled name and RTL for the instantiation. */
SET_DECL_ASSEMBLER_NAME (r, NULL_TREE);
SET_DECL_RTL (r, NULL_RTX);
- DECL_INITIAL (r) = NULL_TREE;
+ /* Leave DECL_INITIAL set on deleted instantiations. */
+ if (!DECL_DELETED_FN (r))
+ DECL_INITIAL (r) = NULL_TREE;
DECL_CONTEXT (r) = ctx;
if (member && DECL_CONV_FN_P (r))
DECL_PENDING_INLINE_INFO (r) = 0;
DECL_PENDING_INLINE_P (r) = 0;
DECL_SAVED_TREE (r) = NULL_TREE;
+ DECL_STRUCT_FUNCTION (r) = NULL;
TREE_USED (r) = 0;
if (DECL_CLONED_FUNCTION (r))
{
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);
{
tree type;
- type =
- finish_decltype_type (tsubst_expr
- (DECLTYPE_TYPE_EXPR (t), args,
- complain, in_decl,
- /*integral_constant_expression_p=*/false),
+ ++skip_evaluation;
+
+ type = tsubst_expr (DECLTYPE_TYPE_EXPR (t), args,
+ complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+
+ --skip_evaluation;
+
+ type =
+ finish_decltype_type (type,
DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t));
return cp_build_qualified_type_real (type,
cp_type_quals (t)
{
error ("dependent-name %qE is parsed as a non-type, but "
"instantiation yields a type", qualified_id);
- inform ("say %<typename %E%> if a type is meant", qualified_id);
+ inform (input_location, "say %<typename %E%> if a type is meant", qualified_id);
}
return error_mark_node;
}
if (complain & tf_error)
qualified_name_lookup_error (scope,
TREE_OPERAND (qualified_id, 1),
- expr);
+ expr, input_location);
return error_mark_node;
}
if (expr == error_mark_node && complain & tf_error)
qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1),
- expr);
+ expr, input_location);
else if (TYPE_P (scope))
{
expr = (adjust_result_of_qualified_name_lookup
{
case PARM_DECL:
r = retrieve_local_specialization (t);
- gcc_assert (r != NULL);
+
+ if (r == NULL)
+ {
+ /* This can happen for a parameter name used later in a function
+ declaration (such as in a late-specified return type).
+ Replace it with an arbitrary expression with the same type
+ (*(T*)0). This should only occur in an unevaluated context
+ (i.e. decltype). */
+ gcc_assert (skip_evaluation);
+ r = non_reference (TREE_TYPE (t));
+ r = tsubst (r, args, complain, in_decl);
+ r = build_pointer_type (r);
+ r = build_c_cast (r, null_node);
+ return cp_build_indirect_ref (r, NULL, tf_warning_or_error);
+ }
+
if (TREE_CODE (r) == ARGUMENT_PACK_SELECT)
r = ARGUMENT_PACK_SELECT_ARG (r);
mark_used (r);
/* 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 ();
if (t == void_list_node)
return t;
- purpose = TREE_PURPOSE (t);
- if (purpose)
- purpose = RECUR (purpose);
- value = TREE_VALUE (t);
- if (value)
- value = RECUR (value);
- chain = TREE_CHAIN (t);
- if (chain && chain != void_type_node)
- chain = RECUR (chain);
- return tree_cons (purpose, value, chain);
+ purpose = TREE_PURPOSE (t);
+ if (purpose)
+ purpose = RECUR (purpose);
+ value = TREE_VALUE (t);
+ if (value)
+ value = RECUR (value);
+ chain = TREE_CHAIN (t);
+ if (chain && chain != void_type_node)
+ chain = RECUR (chain);
+ return tree_cons (purpose, value, chain);
+#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, auto_node;
+
+ init = TREE_VEC_ELT (OMP_FOR_INIT (t), i);
+ gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
+ decl = RECUR (TREE_OPERAND (init, 0));
+ init = TREE_OPERAND (init, 1);
+ auto_node = type_uses_auto (TREE_TYPE (decl));
+ if (auto_node && init)
+ {
+ tree init_expr = init;
+ if (TREE_CODE (init_expr) == DECL_EXPR)
+ init_expr = DECL_INITIAL (DECL_EXPR_DECL (init_expr));
+ init_expr = RECUR (init_expr);
+ TREE_TYPE (decl)
+ = do_auto_deduction (TREE_TYPE (decl), init_expr, auto_node);
+ }
+ gcc_assert (!type_dependent_expression_p (decl));
+
+ if (!CLASS_TYPE_P (TREE_TYPE (decl)))
+ {
+ 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
}
/*is_type_p=*/false,
/*complain=*/false);
if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
- qualified_name_lookup_error (scope, name, decl);
+ qualified_name_lookup_error (scope, name, decl, input_location);
else
do_local_using_decl (decl, scope, name);
}
pack expansion where the parameter packs
used in that expansion were of length
zero. */
- init = build_default_init (TREE_TYPE (decl),
- NULL_TREE);
+ init = build_value_init (TREE_TYPE (decl));
else
init = t;
}
= 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);
op1 = tsubst_non_call_postfix_expression (op1, args, complain,
in_decl);
if (TREE_CODE (op1) == LABEL_DECL)
- return finish_label_address_expr (DECL_NAME (op1));
- return build_x_unary_op (ADDR_EXPR, op1);
+ return finish_label_address_expr (DECL_NAME (op1),
+ EXPR_LOCATION (op1));
+ return build_x_unary_op (ADDR_EXPR, op1, complain);
case PLUS_EXPR:
case 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
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)
}
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);
+ CONSTRUCTOR_IS_DIRECT_INIT (r) = CONSTRUCTOR_IS_DIRECT_INIT (t);
+
if (TREE_HAS_CONSTRUCTOR (t))
- return finish_compound_literal (type, n);
+ return finish_compound_literal (type, r);
- return build_constructor (NULL_TREE, n);
+ return r;
}
case TYPEID_EXPR:
Emit an error under control of COMPLAIN, and return TRUE on error. */
static bool
-check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain)
+check_instantiated_arg (tree tmpl, tree t, tsubst_flags_t complain)
{
- int ix, len = DECL_NTPARMS (tmpl);
- bool result = false;
-
- for (ix = 0; ix != len; ix++)
+ if (ARGUMENT_PACK_P (t))
{
- tree t = TREE_VEC_ELT (args, ix);
+ tree vec = ARGUMENT_PACK_ARGS (t);
+ int len = TREE_VEC_LENGTH (vec);
+ bool result = false;
+ int i;
- if (TYPE_P (t))
+ for (i = 0; i < len; ++i)
+ if (check_instantiated_arg (tmpl, TREE_VEC_ELT (vec, i), complain))
+ result = true;
+ return result;
+ }
+ else if (TYPE_P (t))
+ {
+ /* [basic.link]: A name with no linkage (notably, the name
+ of a class or enumeration declared in a local scope)
+ shall not be used to declare an entity with linkage.
+ This implies that names with no linkage cannot be used as
+ template arguments. */
+ tree nt = no_linkage_check (t, /*relaxed_p=*/false);
+
+ if (nt)
{
- /* [basic.link]: A name with no linkage (notably, the name
- of a class or enumeration declared in a local scope)
- shall not be used to declare an entity with linkage.
- This implies that names with no linkage cannot be used as
- template arguments. */
- tree nt = no_linkage_check (t, /*relaxed_p=*/false);
-
- if (nt)
- {
- /* DR 488 makes use of a type with no linkage cause
- type deduction to fail. */
- if (complain & tf_error)
- {
- if (TYPE_ANONYMOUS_P (nt))
- error ("%qT is/uses anonymous type", t);
- else
- error ("template argument for %qD uses local type %qT",
- tmpl, t);
- }
- result = true;
- }
- /* In order to avoid all sorts of complications, we do not
- allow variably-modified types as template arguments. */
- else if (variably_modified_type_p (t, NULL_TREE))
+ /* DR 488 makes use of a type with no linkage cause
+ type deduction to fail. */
+ if (complain & tf_error)
{
- if (complain & tf_error)
- error ("%qT is a variably modified type", t);
- result = true;
+ if (TYPE_ANONYMOUS_P (nt))
+ error ("%qT is/uses anonymous type", t);
+ else
+ error ("template argument for %qD uses local type %qT",
+ tmpl, t);
}
+ return true;
}
- /* A non-type argument of integral or enumerated type must be a
- constant. */
- else if (TREE_TYPE (t)
- && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t))
- && !TREE_CONSTANT (t))
+ /* In order to avoid all sorts of complications, we do not
+ allow variably-modified types as template arguments. */
+ else if (variably_modified_type_p (t, NULL_TREE))
{
if (complain & tf_error)
- error ("integral expression %qE is not constant", t);
- result = true;
+ error ("%qT is a variably modified type", t);
+ return true;
}
}
+ /* A non-type argument of integral or enumerated type must be a
+ constant. */
+ else if (TREE_TYPE (t)
+ && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t))
+ && !TREE_CONSTANT (t))
+ {
+ if (complain & tf_error)
+ error ("integral expression %qE is not constant", t);
+ return true;
+ }
+ return false;
+}
+
+static bool
+check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain)
+{
+ int ix, len = DECL_NTPARMS (tmpl);
+ bool result = false;
+
+ for (ix = 0; ix != len; ix++)
+ {
+ if (check_instantiated_arg (tmpl, TREE_VEC_ELT (args, ix), complain))
+ result = true;
+ }
if (result && (complain & tf_error))
error (" trying to instantiate %qD", tmpl);
return result;
}
}
+ /* 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
nodes. */
return 0;
+ case ERROR_MARK:
+ /* Unification fails if we hit an error node. */
+ return 1;
+
default:
gcc_assert (EXPR_P (parm));
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 (input_location, "duplicate explicit instantiation of %q#D", result);
/* If an "extern" explicit instantiation follows an ordinary
explicit instantiation, the template is instantiated. */
if (extern_p)
}
else if (!DECL_TEMPLATE_INFO (result))
{
- pedwarn ("explicit instantiation of non-template %q#D", result);
+ permerror (input_location, "explicit instantiation of non-template %q#D", result);
return;
}
;
else if (storage == ridpointers[(int) RID_EXTERN])
{
- if (pedantic && !in_system_header)
- pedwarn ("ISO C++ forbids the use of %<extern%> on explicit "
+ if (!in_system_header && (cxx_dialect == cxx98))
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C++ 1998 forbids the use of %<extern%> on explicit "
"instantiations");
extern_p = 1;
}
{
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 (!in_system_header)
+ {
+ if (storage == ridpointers[(int) RID_EXTERN])
+ {
+ if (cxx_dialect == cxx98)
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C++ 1998 forbids the use of %<extern%> on "
+ "explicit instantiations");
+ }
+ else
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C++ forbids the use of %qE"
+ " on explicit instantiations", storage);
+ }
if (storage == ridpointers[(int) RID_INLINE])
nomem_p = 1;
if (!previous_instantiation_extern_p && !extern_p
&& (complain & tf_error))
- pedwarn ("duplicate explicit instantiation of %q#T", t);
+ permerror (input_location, "duplicate explicit instantiation of %q#T", t);
/* If we've already instantiated the template, just return now. */
if (!CLASSTYPE_INTERFACE_ONLY (t))
if (DECL_DECLARED_INLINE_P (code_pattern)
&& !DECL_DECLARED_INLINE_P (decl))
DECL_DECLARED_INLINE_P (decl) = 1;
- if (DECL_INLINE (code_pattern) && !DECL_INLINE (decl))
- DECL_INLINE (decl) = 1;
}
else if (TREE_CODE (decl) == VAR_DECL)
DECL_INITIAL (decl) =
bool pattern_defined;
int need_push;
location_t saved_loc = input_location;
- int saved_in_system_header = in_system_header;
bool external_p;
/* This function should only be used to instantiate templates for
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
if (external_p
/* ... but we instantiate inline functions so that we can inline
them and ... */
- && ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d))
+ && ! (TREE_CODE (d) == FUNCTION_DECL
+ && possibly_inlined_p (d))
/* ... we instantiate static data members whose values are
needed in integral constant expressions. */
&& ! (TREE_CODE (d) == VAR_DECL
input_location = saved_loc;
if (at_eof && !pattern_defined
- && DECL_EXPLICIT_INSTANTIATION (d))
+ && DECL_EXPLICIT_INSTANTIATION (d)
+ && DECL_NOT_REALLY_EXTERN (d))
/* [temp.explicit]
The definition of a non-exported function template, a
member function or static data member of a class template
shall be present in every translation unit in which it is
explicitly instantiated. */
- pedwarn
- ("explicit instantiation of %qD but no definition available", d);
+ permerror (input_location, "explicit instantiation of %qD "
+ "but no definition available", d);
/* ??? Historically, we have instantiated inline functions, even
when marked as "extern template". */
/* Instantiate inline functions so that the inliner can do its
job, even though we'll not be emitting a copy of this
function. */
- if (!(TREE_CODE (d) == FUNCTION_DECL
- && flag_inline_trees
- && DECL_DECLARED_INLINE_P (d)))
+ if (!(TREE_CODE (d) == FUNCTION_DECL && possibly_inlined_p (d)))
goto out;
}
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 ... */
/* If we are not processing a template, then nobody should be
providing us with a dependent type. */
gcc_assert (type);
- gcc_assert (TREE_CODE (type) != TEMPLATE_TYPE_PARM);
+ gcc_assert (TREE_CODE (type) != TEMPLATE_TYPE_PARM || is_auto (type));
return false;
}
/* A non-type template parm. */
if (DECL_TEMPLATE_PARM_P (expression))
return true;
- return false;
+ return value_dependent_expression_p (DECL_INITIAL (expression));
case VAR_DECL:
/* A constant with integral or enumeration type and is initialized
if (TREE_CODE (expression) == STMT_EXPR)
expression = stmt_expr_value_expr (expression);
+ if (BRACE_ENCLOSED_INITIALIZER_P (expression))
+ {
+ tree elt;
+ unsigned i;
+
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expression), i, elt)
+ {
+ if (type_dependent_expression_p (elt))
+ return true;
+ }
+ return false;
+ }
+
if (TREE_TYPE (expression) == unknown_type_node)
{
if (TREE_CODE (expression) == ADDR_EXPR)
|| 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
return nreverse (new_args);
}
+/* Returns a type which represents 'auto'. We use a TEMPLATE_TYPE_PARM
+ with a level one deeper than the actual template parms. */
+
+tree
+make_auto (void)
+{
+ tree au;
+
+ /* ??? Is it worth caching this for multiple autos at the same level? */
+ au = cxx_make_type (TEMPLATE_TYPE_PARM);
+ TYPE_NAME (au) = build_decl (TYPE_DECL, get_identifier ("auto"), au);
+ TYPE_STUB_DECL (au) = TYPE_NAME (au);
+ TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
+ (0, processing_template_decl + 1, processing_template_decl + 1,
+ TYPE_NAME (au), NULL_TREE);
+ TYPE_CANONICAL (au) = canonical_type_parameter (au);
+ DECL_ARTIFICIAL (TYPE_NAME (au)) = 1;
+ SET_DECL_TEMPLATE_PARM_P (TYPE_NAME (au));
+
+ return au;
+}
+
+/* Replace auto in TYPE with std::initializer_list<auto>. */
+
+static tree
+listify_autos (tree type, tree auto_node)
+{
+ tree std_init_list = namespace_binding
+ (get_identifier ("initializer_list"), std_node);
+ tree argvec;
+ tree init_auto;
+ if (!std_init_list || !DECL_CLASS_TEMPLATE_P (std_init_list))
+ {
+ error ("deducing auto from brace-enclosed initializer list requires "
+ "#include <initializer_list>");
+ return error_mark_node;
+ }
+ argvec = make_tree_vec (1);
+ TREE_VEC_ELT (argvec, 0) = auto_node;
+ init_auto = lookup_template_class (std_init_list, argvec, NULL_TREE,
+ NULL_TREE, 0, tf_warning_or_error);
+
+ TREE_VEC_ELT (argvec, 0) = init_auto;
+ if (processing_template_decl)
+ argvec = add_to_template_args (current_template_args (), argvec);
+ return tsubst (type, argvec, tf_warning_or_error, NULL_TREE);
+}
+
+/* Replace occurrences of 'auto' in TYPE with the appropriate type deduced
+ from INIT. AUTO_NODE is the TEMPLATE_TYPE_PARM used for 'auto' in TYPE. */
+
+tree
+do_auto_deduction (tree type, tree init, tree auto_node)
+{
+ tree parms, args, tparms, targs;
+ int val;
+
+ /* [dcl.spec.auto]: Obtain P from T by replacing the occurrences of auto
+ with either a new invented type template parameter U or, if the
+ initializer is a braced-init-list (8.5.4), with
+ std::initializer_list<U>. */
+ if (BRACE_ENCLOSED_INITIALIZER_P (init))
+ type = listify_autos (type, auto_node);
+
+ parms = build_tree_list (NULL_TREE, type);
+ args = build_tree_list (NULL_TREE, init);
+ tparms = make_tree_vec (1);
+ targs = make_tree_vec (1);
+ TREE_VEC_ELT (tparms, 0)
+ = build_tree_list (NULL_TREE, TYPE_NAME (auto_node));
+ val = type_unification_real (tparms, targs, parms, args, 0,
+ DEDUCE_CALL, LOOKUP_NORMAL);
+ if (val > 0)
+ {
+ error ("unable to deduce %qT from %qE", type, init);
+ return error_mark_node;
+ }
+
+ if (processing_template_decl)
+ targs = add_to_template_args (current_template_args (), targs);
+ return tsubst (type, targs, tf_warning_or_error, NULL_TREE);
+}
+
+/* Substitutes LATE_RETURN_TYPE for 'auto' in TYPE and returns the
+ result. */
+
+tree
+splice_late_return_type (tree type, tree late_return_type)
+{
+ tree argvec;
+
+ if (late_return_type == NULL_TREE)
+ return type;
+ argvec = make_tree_vec (1);
+ TREE_VEC_ELT (argvec, 0) = late_return_type;
+ if (processing_template_decl)
+ argvec = add_to_template_args (current_template_args (), argvec);
+ return tsubst (type, argvec, tf_warning_or_error, NULL_TREE);
+}
+
+/* Returns true iff TYPE is a TEMPLATE_TYPE_PARM representing 'auto'. */
+
+bool
+is_auto (const_tree type)
+{
+ if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
+ && TYPE_IDENTIFIER (type) == get_identifier ("auto"))
+ return true;
+ else
+ return false;
+}
+
+/* Returns true iff TYPE contains a use of 'auto'. Since auto can only
+ appear as a type-specifier for the declaration in question, we don't
+ have to look through the whole type. */
+
+tree
+type_uses_auto (tree type)
+{
+ enum tree_code code;
+ if (is_auto (type))
+ return type;
+
+ code = TREE_CODE (type);
+
+ if (code == POINTER_TYPE || code == REFERENCE_TYPE
+ || code == OFFSET_TYPE || code == FUNCTION_TYPE
+ || code == METHOD_TYPE || code == ARRAY_TYPE)
+ return type_uses_auto (TREE_TYPE (type));
+
+ if (TYPE_PTRMEMFUNC_P (type))
+ return type_uses_auto (TREE_TYPE (TREE_TYPE
+ (TYPE_PTRMEMFUNC_FN_TYPE (type))));
+
+ return NULL_TREE;
+}
+
#include "gt-cp-pt.h"