/* 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 void push_inline_template_parms_recursive (tree, int);
static tree retrieve_local_specialization (tree);
static void register_local_specialization (tree, tree);
-static tree reduce_template_parm_level (tree, tree, int);
+static tree reduce_template_parm_level (tree, tree, int, tree, tsubst_flags_t);
static int mark_template_parm (tree, void *);
static int template_parm_this_level_p (tree, void *);
static tree tsubst_friend_function (tree, tree);
static tree try_class_unification (tree, tree, tree, tree);
static int coerce_template_template_parms (tree, tree, tsubst_flags_t,
tree, tree);
+static bool template_template_parm_bindings_ok_p (tree, tree);
static int template_args_equal (tree, tree);
static void tsubst_default_arguments (tree);
static tree for_each_template_parm_r (tree *, int *, void *);
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))
{
return error_mark_node;
}
+/* Return the template info node corresponding to T, whatever T is. */
+
+tree
+get_template_info (tree t)
+{
+ tree tinfo = NULL_TREE;
+
+ if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
+ tinfo = DECL_TEMPLATE_INFO (t);
+
+ if (!tinfo && TREE_CODE (t) == TYPE_DECL)
+ t = TREE_TYPE (t);
+
+ if (TAGGED_TYPE_P (t))
+ tinfo = TYPE_TEMPLATE_INFO (t);
+
+ return tinfo;
+}
+
/* Returns the template nesting level of the indicated class TYPE.
For example, in:
type = (TREE_CODE (type) == FUNCTION_DECL)
? CP_DECL_CONTEXT (type) : TYPE_CONTEXT (type))
{
- if (TREE_CODE (type) != FUNCTION_DECL)
- {
- if (CLASSTYPE_TEMPLATE_INFO (type)
- && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
- && uses_template_parms (CLASSTYPE_TI_ARGS (type)))
- ++depth;
- }
- else
- {
- if (DECL_TEMPLATE_INFO (type)
- && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (type))
- && uses_template_parms (DECL_TI_ARGS (type)))
- ++depth;
- }
+ tree tinfo = get_template_info (type);
+
+ if (tinfo && PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo))
+ && uses_template_parms (INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo))))
+ ++depth;
}
return depth;
TREE_TYPE (parm));
DECL_ARTIFICIAL (decl) = 1;
TREE_CONSTANT (decl) = 1;
- TREE_INVARIANT (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_INITIAL (decl) = DECL_INITIAL (parm);
SET_DECL_TEMPLATE_PARM_P (decl);
return true;
else
{
- pedwarn ("specialization of %qD in different namespace", tmpl);
- pedwarn (" from definition of %q+#D", tmpl);
+ permerror ("specialization of %qD in different namespace", tmpl);
+ permerror (" from definition of %q+#D", tmpl);
return false;
}
}
namespace of its template. */
ns = decl_namespace_context (spec);
if (!is_ancestor (current_namespace, ns))
- pedwarn ("explicit instantiation of %qD in namespace %qD "
- "(which does not enclose namespace %qD)",
- spec, current_namespace, ns);
+ permerror ("explicit instantiation of %qD in namespace %qD "
+ "(which does not enclose namespace %qD)",
+ spec, current_namespace, ns);
}
/* The TYPE is being declared. If it is a template type, that means it
check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type));
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
if (processing_template_decl)
- push_template_decl (TYPE_MAIN_DECL (type));
+ {
+ if (push_template_decl (TYPE_MAIN_DECL (type))
+ == error_mark_node)
+ return error_mark_node;
+ }
}
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
error ("specialization of %qT after instantiation", type);
if (current_namespace
!= decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
{
- pedwarn ("specializing %q#T in different namespace", type);
- pedwarn (" from definition of %q+#D",
- CLASSTYPE_TI_TEMPLATE (type));
+ permerror ("specializing %q#T in different namespace", type);
+ permerror (" from definition of %q+#D",
+ CLASSTYPE_TI_TEMPLATE (type));
}
/* Check for invalid specialization after instantiation:
DECL_TEMPLATE_INSTANTIATIONS list; other templates use the
DECL_TEMPLATE_SPECIALIZATIONS list. */
if (!class_specializations_p
- && TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL)
+ && TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL
+ && TAGGED_TYPE_P (TREE_TYPE (tmpl)))
sp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
else
sp = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
static tree
retrieve_local_specialization (tree tmpl)
{
- tree spec = (tree) htab_find_with_hash (local_specializations, tmpl,
- htab_hash_pointer (tmpl));
+ tree spec;
+
+ if (local_specializations == NULL)
+ return NULL_TREE;
+
+ spec = (tree) htab_find_with_hash (local_specializations, tmpl,
+ htab_hash_pointer (tmpl));
return spec ? TREE_PURPOSE (spec) : NULL_TREE;
}
}
/* Returns nonzero iff DECL is a specialization of friend declaration
- FRIEND according to [temp.friend]. */
+ FRIEND_DECL according to [temp.friend]. */
bool
-is_specialization_of_friend (tree decl, tree friend)
+is_specialization_of_friend (tree decl, tree friend_decl)
{
bool need_template = true;
int template_depth;
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == TYPE_DECL);
- /* For [temp.friend/6] when FRIEND is an ordinary member function
+ /* For [temp.friend/6] when FRIEND_DECL is an ordinary member function
of a template class, we want to check if DECL is a specialization
if this. */
- if (TREE_CODE (friend) == FUNCTION_DECL
- && DECL_TEMPLATE_INFO (friend)
- && !DECL_USE_TEMPLATE (friend))
+ if (TREE_CODE (friend_decl) == FUNCTION_DECL
+ && DECL_TEMPLATE_INFO (friend_decl)
+ && !DECL_USE_TEMPLATE (friend_decl))
{
/* We want a TEMPLATE_DECL for `is_specialization_of'. */
- friend = DECL_TI_TEMPLATE (friend);
+ friend_decl = DECL_TI_TEMPLATE (friend_decl);
need_template = false;
}
- else if (TREE_CODE (friend) == TEMPLATE_DECL
- && !PRIMARY_TEMPLATE_P (friend))
+ else if (TREE_CODE (friend_decl) == TEMPLATE_DECL
+ && !PRIMARY_TEMPLATE_P (friend_decl))
need_template = false;
/* There is nothing to do if this is not a template friend. */
- if (TREE_CODE (friend) != TEMPLATE_DECL)
+ if (TREE_CODE (friend_decl) != TEMPLATE_DECL)
return false;
- if (is_specialization_of (decl, friend))
+ if (is_specialization_of (decl, friend_decl))
return true;
/* [temp.friend/6]
nonzero. To determine if DECL is a friend of FRIEND, we first
check if the enclosing class is a specialization of another. */
- template_depth = template_class_depth (DECL_CONTEXT (friend));
+ template_depth = template_class_depth (DECL_CONTEXT (friend_decl));
if (template_depth
&& DECL_CLASS_SCOPE_P (decl)
&& is_specialization_of (TYPE_NAME (DECL_CONTEXT (decl)),
- CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (friend))))
+ CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (friend_decl))))
{
/* Next, we check the members themselves. In order to handle
- a few tricky cases, such as when FRIEND's are
+ a few tricky cases, such as when FRIEND_DECL's are
template <class T> friend void A<T>::g(T t);
template <class T> template <T t> friend void A<T>::h();
tree friend_args_type;
tree decl_args_type;
- /* Make sure that both DECL and FRIEND are templates or
+ /* Make sure that both DECL and FRIEND_DECL are templates or
non-templates. */
is_template = DECL_TEMPLATE_INFO (decl)
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl));
{
/* If both are templates, check template parameter list. */
tree friend_parms
- = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend),
+ = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_decl),
args, tf_none);
if (!comp_template_parms
(DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl)),
else
decl_type = TREE_TYPE (decl);
- friend_type = tsubst_function_type (TREE_TYPE (friend), args,
+ friend_type = tsubst_function_type (TREE_TYPE (friend_decl), args,
tf_none, NULL_TREE);
if (friend_type == error_mark_node)
return false;
`this' parameter. */
friend_args_type = TYPE_ARG_TYPES (friend_type);
decl_args_type = TYPE_ARG_TYPES (decl_type);
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (friend))
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (friend_decl))
friend_args_type = TREE_CHAIN (friend_args_type);
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
decl_args_type = TREE_CHAIN (decl_args_type);
bool is_template;
tree decl_type = TREE_TYPE (decl);
- /* Make sure that both DECL and FRIEND are templates or
+ /* Make sure that both DECL and FRIEND_DECL are templates or
non-templates. */
is_template
= CLASSTYPE_TEMPLATE_INFO (decl_type)
/* If both are templates, check the name of the two
TEMPLATE_DECL's first because is_friend didn't. */
if (DECL_NAME (CLASSTYPE_TI_TEMPLATE (decl_type))
- != DECL_NAME (friend))
+ != DECL_NAME (friend_decl))
return false;
/* Now check template parameter list. */
friend_parms
- = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend),
+ = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_decl),
args, tf_none);
return comp_template_parms
(DECL_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (decl_type)),
}
else
return (DECL_NAME (decl)
- == DECL_NAME (friend));
+ == DECL_NAME (friend_decl));
}
}
return false;
for (; t; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t))
{
- pedwarn
+ permerror
("default argument specified in explicit specialization");
break;
}
{
int is_constructor = DECL_CONSTRUCTOR_P (decl);
- if (is_constructor ? !TYPE_HAS_CONSTRUCTOR (ctype)
+ if (is_constructor ? !TYPE_HAS_USER_CONSTRUCTOR (ctype)
: !CLASSTYPE_DESTRUCTORS (ctype))
{
/* From [temp.expl.spec]:
return get_identifier (newname);
}
-/* Structure used to track the progress of find_parameter_pack_r. */
+/* Structure used to track the progress of find_parameter_packs_r. */
struct find_parameter_pack_data
{
+ /* TREE_LIST that will contain all of the parameter packs found by
+ the traversal. */
tree* parameter_packs;
+
+ /* Set of AST nodes that have been visited by the traversal. */
struct pointer_set_t *visited;
};
-/* Identifiers all of the argument packs that occur in a template
+/* Identifies all of the argument packs that occur in a template
argument and appends them to the TREE_LIST inside DATA, which is a
- find_parameter_pack_Data structure. This is a subroutine of
+ find_parameter_pack_data structure. This is a subroutine of
make_pack_expansion and uses_parameter_packs. */
static tree
find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
tree t = *tp;
struct find_parameter_pack_data* ppd =
(struct find_parameter_pack_data*)data;
+ bool parameter_pack_p = false;
- if (TYPE_P (t))
+ /* Identify whether this is a parameter pack or not. */
+ switch (TREE_CODE (t))
+ {
+ 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;
-
+ cp_walk_tree (&TREE_TYPE (t),
+ &find_parameter_packs_r, ppd, ppd->visited);
+ return NULL_TREE;
+
+ case TYPENAME_TYPE:
+ cp_walk_tree (&TYPENAME_TYPE_FULLNAME (t), &find_parameter_packs_r,
+ ppd, ppd->visited);
*walk_subtrees = 0;
return NULL_TREE;
-
+
case TYPE_PACK_EXPANSION:
case EXPR_PACK_EXPANSION:
*walk_subtrees = 0;
*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 (" %qD", name);
+ else
+ inform (" <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
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;
new one is created. */
static tree
-reduce_template_parm_level (tree index, tree type, int levels)
+reduce_template_parm_level (tree index, tree type, int levels, tree args,
+ tsubst_flags_t complain)
{
if (TEMPLATE_PARM_DESCENDANTS (index) == NULL_TREE
|| (TEMPLATE_PARM_LEVEL (TEMPLATE_PARM_DESCENDANTS (index))
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);
= TEMPLATE_PARM_PARAMETER_PACK (index);
/* Template template parameters need this. */
- if (TREE_CODE (decl) != CONST_DECL)
- DECL_TEMPLATE_PARMS (decl)
- = DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index));
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ DECL_TEMPLATE_PARMS (decl) = tsubst_template_parms
+ (DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index)),
+ args, complain);
}
return TEMPLATE_PARM_DESCENDANTS (index);
/* 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_TYPE (t) = type;
}
}
+ TREE_VEC_ELT (a, i) = t;
}
- TREE_VEC_ELT (a, i) = t;
}
}
for_each_template_parm (TREE_VEC_ELT (inner_args, i),
&mark_template_parm,
&tpd,
- NULL);
+ NULL,
+ /*include_nondeduced_p=*/false);
}
for (i = 0; i < ntparms; ++i)
if (tpd.parms[i] == 0)
if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
error ("parameter pack argument %qE must be at the end of the template argument list", arg);
else
- error ("parameter pack argument %qT must be at the end of the template argument list", arg);
+ error ("parameter pack argument %qT must be at the end of the template argument list", arg);
+
+ if (packed_args)
+ TREE_VEC_ELT (packed_args, j) = error_mark_node;
}
}
for_each_template_parm (type,
&mark_template_parm,
&tpd2,
- NULL);
+ NULL,
+ /*include_nondeduced_p=*/false);
if (tpd2.arg_uses_template_parms [i])
{
return decl;
}
-/* Check that a template declaration's use of default arguments is not
- invalid. Here, PARMS are the template parameters. IS_PRIMARY is
- nonzero if DECL is the thing declared by a primary template.
- IS_PARTIAL is nonzero if DECL is a partial specialization.
+/* Check that a template declaration's use of default arguments and
+ parameter packs is not invalid. Here, PARMS are the template
+ parameters. IS_PRIMARY is nonzero if DECL is the thing declared by
+ a primary template. IS_PARTIAL is nonzero if DECL is a partial
+ specialization.
IS_FRIEND_DECL is nonzero if DECL is a friend function template
TREE_PURPOSE (parm) = error_mark_node;
no_errors = false;
}
+ else if (is_primary
+ && !is_partial
+ && !is_friend_decl
+ && TREE_CODE (decl) == TYPE_DECL
+ && i < ntparms - 1
+ && template_parameter_pack_p (TREE_VALUE (parm)))
+ {
+ /* A primary class template can only have one
+ parameter pack, at the end of the template
+ parameter list. */
+
+ if (TREE_CODE (TREE_VALUE (parm)) == PARM_DECL)
+ error ("parameter pack %qE must be at the end of the"
+ " template parameter list", TREE_VALUE (parm));
+ else
+ error ("parameter pack %qT must be at the end of the"
+ " template parameter list",
+ TREE_TYPE (TREE_VALUE (parm)));
+
+ TREE_VALUE (TREE_VEC_ELT (inner_parms, i))
+ = error_mark_node;
+ no_errors = false;
+ }
}
}
}
member_template_p = true;
if (TREE_CODE (decl) == TYPE_DECL
&& ANON_AGGRNAME_P (DECL_NAME (decl)))
- error ("template class without a name");
+ {
+ error ("template class without a name");
+ return error_mark_node;
+ }
else if (TREE_CODE (decl) == FUNCTION_DECL)
{
if (DECL_DESTRUCTOR_P (decl))
while (arg && argtype)
{
if (!FUNCTION_PARAMETER_PACK_P (arg)
- && !check_for_bare_parameter_packs (TREE_TYPE (arg)))
+ && check_for_bare_parameter_packs (TREE_TYPE (arg)))
{
/* This is a PARM_DECL that contains unexpanded parameter
packs. We have already complained about this in the
/* Check for bare parameter packs in the return type and the
exception specifiers. */
- check_for_bare_parameter_packs (TREE_TYPE (type));
- check_for_bare_parameter_packs (TYPE_RAISES_EXCEPTIONS (type));
+ if (check_for_bare_parameter_packs (TREE_TYPE (type)))
+ /* Errors were already issued, set return type to int
+ as the frontend doesn't expect error_mark_node as
+ the return type. */
+ TREE_TYPE (type) = integer_type_node;
+ if (check_for_bare_parameter_packs (TYPE_RAISES_EXCEPTIONS (type)))
+ TYPE_RAISES_EXCEPTIONS (type) = NULL_TREE;
+ }
+ else if (check_for_bare_parameter_packs (TREE_TYPE (decl)))
+ {
+ TREE_TYPE (decl) = error_mark_node;
+ return error_mark_node;
}
- else
- check_for_bare_parameter_packs (TREE_TYPE (decl));
if (is_partial)
return process_partial_specialization (decl);
- /* A primary class template can only have one parameter pack, at the
- end of the template parameter list. */
- if (primary && TREE_CODE (decl) == TYPE_DECL)
- {
- tree inner_parms
- = INNERMOST_TEMPLATE_PARMS (current_template_parms);
- int i, len = TREE_VEC_LENGTH (inner_parms);
- for (i = 0; i < len - 1; i++)
- {
- tree parm = TREE_VALUE (TREE_VEC_ELT (inner_parms, i));
-
- if (template_parameter_pack_p (parm))
- {
- if (TREE_CODE (parm) == PARM_DECL)
- error ("parameter pack %qE must be at the end of the"
- " template parameter list", parm);
- else
- error ("parameter pack %qT must be at the end of the"
- " template parameter list", TREE_TYPE (parm));
- }
- }
- }
-
args = current_template_args ();
if (!ctx
{
tree a, t, current, parms;
int i;
+ tree tinfo = get_template_info (decl);
- if (TREE_CODE (decl) == TYPE_DECL)
- {
- if ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (decl)))
- || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
- && TYPE_TEMPLATE_INFO (TREE_TYPE (decl))
- && TYPE_TI_TEMPLATE (TREE_TYPE (decl)))
- tmpl = TYPE_TI_TEMPLATE (TREE_TYPE (decl));
- else
- {
- error ("%qD does not declare a template type", decl);
- return decl;
- }
- }
- else if (!DECL_LANG_SPECIFIC (decl) || !DECL_TEMPLATE_INFO (decl))
+ if (!tinfo)
{
error ("template definition of non-template %q#D", decl);
- return decl;
+ return error_mark_node;
}
- else
- tmpl = DECL_TI_TEMPLATE (decl);
+
+ tmpl = TI_TEMPLATE (tinfo);
if (DECL_FUNCTION_TEMPLATE_P (tmpl)
&& DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl)
return error_mark_node;
}
- /* Perhaps we should also check that the parms are used in the
- appropriate qualifying scopes in the declarator? */
-
if (current == decl)
current = ctx;
else
? TYPE_CONTEXT (current)
: DECL_CONTEXT (current));
}
+
+ /* Check that the parms are used in the appropriate qualifying scopes
+ in the declarator. */
+ if (!comp_template_args
+ (TI_ARGS (tinfo),
+ TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (tmpl)))))
+ {
+ error ("\
+template arguments to %qD do not match original template %qD",
+ decl, DECL_TEMPLATE_RESULT (tmpl));
+ if (!uses_template_parms (TI_ARGS (tinfo)))
+ inform ("use template<> for an explicit specialization");
+ /* Avoid crash in import_export_decl. */
+ DECL_INTERFACE_KNOWN (decl) = 1;
+ return error_mark_node;
+ }
}
DECL_TEMPLATE_RESULT (tmpl) = decl;
if (primary)
{
+ tree parms = DECL_TEMPLATE_PARMS (tmpl);
+ int i;
+
DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
if (DECL_CONV_FN_P (tmpl))
{
- int depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
+ int depth = TMPL_PARMS_DEPTH (parms);
/* It is a conversion operator. See if the type converted to
depends on innermost template operands. */
depth))
DECL_TEMPLATE_CONV_FN_P (tmpl) = 1;
}
+
+ /* Give template template parms a DECL_CONTEXT of the template
+ for which they are a parameter. */
+ parms = INNERMOST_TEMPLATE_PARMS (parms);
+ for (i = TREE_VEC_LENGTH (parms) - 1; i >= 0; --i)
+ {
+ tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
+ if (TREE_CODE (parm) == TEMPLATE_DECL)
+ DECL_CONTEXT (parm) = tmpl;
+ }
}
/* The DECL_TI_ARGS of DECL contains full set of arguments referring
if (TREE_VEC_LENGTH (parms) != TREE_VEC_LENGTH (tmpl_parms))
{
- error ("previous declaration %q+D", tmpl);
- error ("used %d template parameter(s) instead of %d",
- TREE_VEC_LENGTH (tmpl_parms),
- TREE_VEC_LENGTH (parms));
+ error ("redeclared with %d template parameter(s)",
+ TREE_VEC_LENGTH (parms));
+ inform ("previous declaration %q+D used %d template parameter(s)",
+ tmpl, TREE_VEC_LENGTH (tmpl_parms));
return false;
}
/* TMPL_PARM and PARM can be either TYPE_DECL, PARM_DECL, or
TEMPLATE_DECL. */
if (tmpl_parm != error_mark_node
- && (TREE_CODE (tmpl_parm) != TREE_CODE (parm)
- || (TREE_CODE (tmpl_parm) != TYPE_DECL
- && !same_type_p (TREE_TYPE (tmpl_parm), TREE_TYPE (parm)))))
+ && (TREE_CODE (tmpl_parm) != TREE_CODE (parm)
+ || (TREE_CODE (tmpl_parm) != TYPE_DECL
+ && !same_type_p (TREE_TYPE (tmpl_parm), TREE_TYPE (parm)))
+ || (TREE_CODE (tmpl_parm) != PARM_DECL
+ && (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (tmpl_parm))
+ != TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm))))
+ || (TREE_CODE (tmpl_parm) == PARM_DECL
+ && (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (tmpl_parm))
+ != TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))))))
{
error ("template parameter %q+#D", tmpl_parm);
error ("redeclared here as %q#D", parm);
A template-parameter may not be given default arguments
by two different declarations in the same scope. */
error ("redefinition of default argument for %q#D", parm);
- error ("%J original definition appeared here", tmpl_parm);
+ inform ("%Joriginal definition appeared here", tmpl_parm);
return false;
}
/* EXPR is an expression which is used in a constant-expression context.
For instance, it could be a VAR_DECL with a constant initializer.
- Extract the innest constant expression.
+ Extract the innermost constant expression.
This is basically a more powerful version of
integral_constant_value, which can be used also in templates where
return expr;
}
+/* Subroutine of coerce_template_template_parms, which returns 1 if
+ PARM_PARM and ARG_PARM match using the rule for the template
+ parameters of template template parameters. Both PARM and ARG are
+ template parameters; the rest of the arguments are the same as for
+ coerce_template_template_parms.
+ */
+static int
+coerce_template_template_parm (tree parm,
+ tree arg,
+ tsubst_flags_t complain,
+ tree in_decl,
+ tree outer_args)
+{
+ if (arg == NULL_TREE || arg == error_mark_node
+ || parm == NULL_TREE || parm == error_mark_node)
+ return 0;
+
+ if (TREE_CODE (arg) != TREE_CODE (parm))
+ return 0;
+
+ switch (TREE_CODE (parm))
+ {
+ case TEMPLATE_DECL:
+ /* We encounter instantiations of templates like
+ template <template <template <class> class> class TT>
+ class C; */
+ {
+ tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
+ tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+
+ if (!coerce_template_template_parms
+ (parmparm, argparm, complain, in_decl, outer_args))
+ return 0;
+ }
+ /* Fall through. */
+
+ case TYPE_DECL:
+ if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (arg))
+ && !TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm)))
+ /* Argument is a parameter pack but parameter is not. */
+ return 0;
+ break;
+
+ case PARM_DECL:
+ /* The tsubst call is used to handle cases such as
+
+ template <int> class C {};
+ template <class T, template <T> class TT> class D {};
+ D<int, C> d;
+
+ i.e. the parameter list of TT depends on earlier parameters. */
+ if (!dependent_type_p (TREE_TYPE (arg))
+ && !same_type_p
+ (tsubst (TREE_TYPE (parm), outer_args, complain, in_decl),
+ TREE_TYPE (arg)))
+ return 0;
+
+ if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (arg))
+ && !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
+ /* Argument is a parameter pack but parameter is not. */
+ return 0;
+
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return 1;
+}
+
/* Return 1 if PARM_PARMS and ARG_PARMS matches using rule for
template template parameters. Both PARM_PARMS and ARG_PARMS are
{
int nparms, nargs, i;
tree parm, arg;
+ int variadic_p = 0;
gcc_assert (TREE_CODE (parm_parms) == TREE_VEC);
gcc_assert (TREE_CODE (arg_parms) == TREE_VEC);
nparms = TREE_VEC_LENGTH (parm_parms);
nargs = TREE_VEC_LENGTH (arg_parms);
- if (nargs != nparms)
+ /* Determine whether we have a parameter pack at the end of the
+ template template parameter's template parameter list. */
+ if (TREE_VEC_ELT (parm_parms, nparms - 1) != error_mark_node)
+ {
+ parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, nparms - 1));
+
+ switch (TREE_CODE (parm))
+ {
+ case TEMPLATE_DECL:
+ case TYPE_DECL:
+ if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm)))
+ variadic_p = 1;
+ break;
+
+ case PARM_DECL:
+ if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
+ variadic_p = 1;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ if (nargs != nparms
+ && !(variadic_p && nargs >= nparms - 1))
return 0;
- for (i = 0; i < nparms; ++i)
+ /* Check all of the template parameters except the parameter pack at
+ the end (if any). */
+ for (i = 0; i < nparms - variadic_p; ++i)
{
if (TREE_VEC_ELT (parm_parms, i) == error_mark_node
|| TREE_VEC_ELT (arg_parms, i) == error_mark_node)
parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, i));
arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
- if (arg == NULL_TREE || arg == error_mark_node
- || parm == NULL_TREE || parm == error_mark_node)
+ if (!coerce_template_template_parm (parm, arg, complain, in_decl,
+ outer_args))
return 0;
- if (TREE_CODE (arg) != TREE_CODE (parm))
+ }
+
+ if (variadic_p)
+ {
+ /* Check each of the template parameters in the template
+ argument against the template parameter pack at the end of
+ the template template parameter. */
+ if (TREE_VEC_ELT (parm_parms, i) == error_mark_node)
return 0;
- switch (TREE_CODE (parm))
- {
- case TEMPLATE_DECL:
- /* We encounter instantiations of templates like
- template <template <template <class> class> class TT>
- class C; */
- {
- tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
- tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+ parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, i));
- if (!coerce_template_template_parms
- (parmparm, argparm, complain, in_decl, outer_args))
- return 0;
- }
- /* Fall through. */
+ for (; i < nargs; ++i)
+ {
+ if (TREE_VEC_ELT (arg_parms, i) == error_mark_node)
+ continue;
+
+ arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
+
+ if (!coerce_template_template_parm (parm, arg, complain, in_decl,
+ outer_args))
+ return 0;
+ }
+ }
- case TYPE_DECL:
- if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm))
- != TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (arg)))
- /* One is a parameter pack, the other is not. */
- return 0;
- break;
+ return 1;
+}
- case PARM_DECL:
- /* The tsubst call is used to handle cases such as
+/* Verifies that the deduced template arguments (in TARGS) for the
+ template template parameters (in TPARMS) represent valid bindings,
+ by comparing the template parameter list of each template argument
+ to the template parameter list of its corresponding template
+ template parameter, in accordance with DR150. This
+ routine can only be called after all template arguments have been
+ deduced. It will return TRUE if all of the template template
+ parameter bindings are okay, FALSE otherwise. */
+bool
+template_template_parm_bindings_ok_p (tree tparms, tree targs)
+{
+ int i, ntparms = TREE_VEC_LENGTH (tparms);
+ bool ret = true;
- template <int> class C {};
- template <class T, template <T> class TT> class D {};
- D<int, C> d;
+ /* We're dealing with template parms in this process. */
+ ++processing_template_decl;
- i.e. the parameter list of TT depends on earlier parameters. */
- if (!dependent_type_p (TREE_TYPE (arg))
- && !same_type_p
- (tsubst (TREE_TYPE (parm), outer_args, complain, in_decl),
- TREE_TYPE (arg)))
- return 0;
+ targs = INNERMOST_TEMPLATE_ARGS (targs);
- if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))
- != TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (arg)))
- /* One is a parameter pack, the other is not. */
- return 0;
- break;
+ for (i = 0; i < ntparms; ++i)
+ {
+ tree tparm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
+ tree targ = TREE_VEC_ELT (targs, i);
- default:
- gcc_unreachable ();
+ if (TREE_CODE (tparm) == TEMPLATE_DECL && targ)
+ {
+ tree packed_args = NULL_TREE;
+ int idx, len = 1;
+
+ if (ARGUMENT_PACK_P (targ))
+ {
+ /* Look inside the argument pack. */
+ packed_args = ARGUMENT_PACK_ARGS (targ);
+ len = TREE_VEC_LENGTH (packed_args);
+ }
+
+ for (idx = 0; idx < len; ++idx)
+ {
+ tree targ_parms = NULL_TREE;
+
+ if (packed_args)
+ /* Extract the next argument from the argument
+ pack. */
+ targ = TREE_VEC_ELT (packed_args, idx);
+
+ if (PACK_EXPANSION_P (targ))
+ /* Look at the pattern of the pack expansion. */
+ targ = PACK_EXPANSION_PATTERN (targ);
+
+ /* Extract the template parameters from the template
+ argument. */
+ if (TREE_CODE (targ) == TEMPLATE_DECL)
+ targ_parms = DECL_INNERMOST_TEMPLATE_PARMS (targ);
+ else if (TREE_CODE (targ) == TEMPLATE_TEMPLATE_PARM)
+ targ_parms = DECL_INNERMOST_TEMPLATE_PARMS (TYPE_NAME (targ));
+
+ /* Verify that we can coerce the template template
+ parameters from the template argument to the template
+ parameter. This requires an exact match. */
+ if (targ_parms
+ && !coerce_template_template_parms
+ (DECL_INNERMOST_TEMPLATE_PARMS (tparm),
+ targ_parms,
+ tf_none,
+ tparm,
+ targs))
+ {
+ ret = false;
+ goto out;
+ }
+ }
}
}
- return 1;
+
+ out:
+
+ --processing_template_decl;
+ return ret;
}
/* Convert the indicated template ARG as necessary to match the
int i,
tree in_decl)
{
+ tree orig_arg;
tree val;
int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
- tree check_arg = arg;
if (TREE_CODE (arg) == TREE_LIST
&& TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
invalid, but static members are OK. In any
case, grab the underlying fields/functions
and issue an error later if required. */
- arg = TREE_VALUE (arg);
+ orig_arg = TREE_VALUE (arg);
TREE_TYPE (arg) = unknown_type_node;
}
+ orig_arg = arg;
+
requires_tmpl_type = TREE_CODE (parm) == TEMPLATE_DECL;
requires_type = (TREE_CODE (parm) == TYPE_DECL
|| requires_tmpl_type);
/* When determining whether an argument pack expansion is a template,
look at the pattern. */
- if (TREE_CODE (check_arg) == TYPE_PACK_EXPANSION)
- check_arg = PACK_EXPANSION_PATTERN (check_arg);
+ if (TREE_CODE (arg) == TYPE_PACK_EXPANSION)
+ arg = PACK_EXPANSION_PATTERN (arg);
is_tmpl_type =
- ((TREE_CODE (check_arg) == TEMPLATE_DECL
- && TREE_CODE (DECL_TEMPLATE_RESULT (check_arg)) == TYPE_DECL)
- || TREE_CODE (check_arg) == TEMPLATE_TEMPLATE_PARM
- || TREE_CODE (check_arg) == UNBOUND_CLASS_TEMPLATE);
+ ((TREE_CODE (arg) == TEMPLATE_DECL
+ && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
+ || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+ || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);
if (is_tmpl_type
&& (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
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%>", arg);
-
- arg = make_typename_type (TREE_OPERAND (arg, 0),
- TREE_OPERAND (arg, 1),
- typename_type,
- complain & tf_error);
+ permerror ("to refer to a type member of a template parameter, "
+ "use %<typename %E%>", orig_arg);
+
+ orig_arg = make_typename_type (TREE_OPERAND (arg, 0),
+ TREE_OPERAND (arg, 1),
+ typename_type,
+ complain & tf_error);
+ arg = orig_arg;
is_type = 1;
}
if (is_type != requires_type)
if (is_type)
error (" expected a constant of type %qT, got %qT",
TREE_TYPE (parm),
- (is_tmpl_type ? DECL_NAME (arg) : arg));
+ (DECL_P (arg) ? DECL_NAME (arg) : orig_arg));
else if (requires_tmpl_type)
- error (" expected a class template, got %qE", arg);
+ error (" expected a class template, got %qE", orig_arg);
else
- error (" expected a type, got %qE", arg);
+ error (" expected a type, got %qE", orig_arg);
}
}
return error_mark_node;
if (is_tmpl_type)
error (" expected a type, got %qT", DECL_NAME (arg));
else
- error (" expected a class template, got %qT", arg);
+ error (" expected a class template, got %qT", orig_arg);
}
return error_mark_node;
}
tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
tree argparm;
- check_arg = arg;
- /* When determining whether a pack expansion is a template,
- look at the pattern. */
- if (TREE_CODE (check_arg) == TYPE_PACK_EXPANSION)
- check_arg = PACK_EXPANSION_PATTERN (check_arg);
-
- argparm = DECL_INNERMOST_TEMPLATE_PARMS (check_arg);
+ argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
if (coerce_template_template_parms (parmparm, argparm,
complain, in_decl,
args))
{
- val = arg;
+ val = orig_arg;
/* TEMPLATE_TEMPLATE_PARM node is preferred over
TEMPLATE_DECL. */
if (DECL_TEMPLATE_TEMPLATE_PARM_P (val))
val = TREE_TYPE (val);
else if (TREE_CODE (val) == TYPE_PACK_EXPANSION
- && DECL_TEMPLATE_TEMPLATE_PARM_P (check_arg))
+ && DECL_TEMPLATE_TEMPLATE_PARM_P (arg))
{
- val = TREE_TYPE (check_arg);
+ val = TREE_TYPE (arg);
val = make_pack_expansion (val);
}
}
"template parameter list for %qD",
i + 1, in_decl);
error (" expected a template of type %qD, got %qD",
- parm, arg);
+ parm, orig_arg);
}
val = error_mark_node;
}
}
else
- val = arg;
+ val = orig_arg;
/* We only form one instance of each template specialization.
Therefore, if we use a non-canonical variant (i.e., a
typedef), any future messages referring to the type will use
if (invalid_nontype_parm_type_p (t, complain))
return error_mark_node;
- if (!uses_template_parms (arg) && !uses_template_parms (t))
+ if (!uses_template_parms (orig_arg) && !uses_template_parms (t))
/* We used to call digest_init here. However, digest_init
will report errors, which we don't want when complain
is zero. More importantly, digest_init will try too
conversions can occur is part of determining which
function template to call, or whether a given explicit
argument specification is valid. */
- val = convert_nontype_argument (t, arg);
+ val = convert_nontype_argument (t, orig_arg);
else
- val = arg;
+ val = orig_arg;
if (val == NULL_TREE)
val = error_mark_node;
else if (val == error_mark_node && (complain & tf_error))
- error ("could not convert template argument %qE to %qT", arg, t);
+ error ("could not convert template argument %qE to %qT", orig_arg, t);
}
return val;
TREE_VEC_ELT (packed_types, arg_idx - parm_idx);
}
- arg = convert_template_argument (actual_parm,
- arg, new_args, complain, parm_idx,
- in_decl);
+ if (arg != error_mark_node)
+ arg = convert_template_argument (actual_parm,
+ arg, new_args, complain, parm_idx,
+ in_decl);
if (arg == error_mark_node)
(*lost)++;
TREE_VEC_ELT (packed_args, arg_idx - parm_idx) = arg;
else
{
argument_pack = make_node (NONTYPE_ARGUMENT_PACK);
- TREE_TYPE (argument_pack) = TREE_TYPE (TREE_VALUE (parm));
+ TREE_TYPE (argument_pack)
+ = tsubst (TREE_TYPE (TREE_VALUE (parm)), new_args, complain, in_decl);
TREE_CONSTANT (argument_pack) = 1;
}
if (arg && PACK_EXPANSION_P (arg))
{
- /* If ARG is a pack expansion, but PARM is not a
- template parameter pack (if it were, we would have
- handled it above), we're trying to expand into a
- fixed-length argument list. */
- if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
- error ("cannot expand %<%E%> into a fixed-length "
- "argument list", arg);
- else
- error ("cannot expand %<%T%> into a fixed-length "
- "argument list", arg);
+ if (complain & tf_error)
+ {
+ /* If ARG is a pack expansion, but PARM is not a
+ template parameter pack (if it were, we would have
+ handled it above), we're trying to expand into a
+ fixed-length argument list. */
+ if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
+ error ("cannot expand %<%E%> into a fixed-length "
+ "argument list", arg);
+ else
+ error ("cannot expand %<%T%> into a fixed-length "
+ "argument list", arg);
+ }
+ return error_mark_node;
}
}
else if (require_all_args)
int entering_scope,
tsubst_flags_t complain)
{
- tree template = NULL_TREE, parmlist;
+ tree templ = NULL_TREE, parmlist;
tree t;
timevar_push (TV_NAME_LOOKUP);
{
tree value = innermost_non_namespace_value (d1);
if (value && DECL_TEMPLATE_TEMPLATE_PARM_P (value))
- template = value;
+ templ = value;
else
{
if (context)
push_decl_namespace (context);
- template = lookup_name (d1);
- template = maybe_get_template_decl_from_type_decl (template);
+ templ = lookup_name (d1);
+ templ = maybe_get_template_decl_from_type_decl (templ);
if (context)
pop_decl_namespace ();
}
- if (template)
- context = DECL_CONTEXT (template);
+ if (templ)
+ context = DECL_CONTEXT (templ);
}
- else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
+ else if (TREE_CODE (d1) == TYPE_DECL && MAYBE_CLASS_TYPE_P (TREE_TYPE (d1)))
{
tree type = TREE_TYPE (d1);
if (CLASSTYPE_TEMPLATE_INFO (type))
{
- template = CLASSTYPE_TI_TEMPLATE (type);
- d1 = DECL_NAME (template);
+ templ = CLASSTYPE_TI_TEMPLATE (type);
+ d1 = DECL_NAME (templ);
}
}
else if (TREE_CODE (d1) == ENUMERAL_TYPE
- || (TYPE_P (d1) && IS_AGGR_TYPE (d1)))
+ || (TYPE_P (d1) && MAYBE_CLASS_TYPE_P (d1)))
{
- template = TYPE_TI_TEMPLATE (d1);
- d1 = DECL_NAME (template);
+ templ = TYPE_TI_TEMPLATE (d1);
+ d1 = DECL_NAME (templ);
}
else if (TREE_CODE (d1) == TEMPLATE_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (d1)) == TYPE_DECL)
{
- template = d1;
- d1 = DECL_NAME (template);
- context = DECL_CONTEXT (template);
+ templ = d1;
+ d1 = DECL_NAME (templ);
+ context = DECL_CONTEXT (templ);
}
/* Issue an error message if we didn't find a template. */
- if (! template)
+ if (! templ)
{
if (complain & tf_error)
error ("%qT is not a template", d1);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
- if (TREE_CODE (template) != TEMPLATE_DECL
+ if (TREE_CODE (templ) != TEMPLATE_DECL
/* Make sure it's a user visible template, if it was named by
the user. */
- || ((complain & tf_user) && !DECL_TEMPLATE_PARM_P (template)
- && !PRIMARY_TEMPLATE_P (template)))
+ || ((complain & tf_user) && !DECL_TEMPLATE_PARM_P (templ)
+ && !PRIMARY_TEMPLATE_P (templ)))
{
if (complain & tf_error)
{
complain &= ~tf_user;
- if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))
+ if (DECL_TEMPLATE_TEMPLATE_PARM_P (templ))
{
/* Create a new TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM node to store
template arguments */
tree parm;
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
instantiation `TT<int>' is seen, we need to build the full
arguments containing {int} as the innermost level. Outer levels,
available when not appearing as default template argument, can be
- obtained from `current_template_args ()'.
+ obtained from the arguments of the enclosing template.
Suppose that TT is later substituted with std::vector. The above
instantiation is `TT<int, std::allocator<T> >' with TT at
level 1, and T at level 2, while the template arguments at level 1
becomes {std::vector} and the inner level 2 is {int}. */
- if (current_template_parms)
- arglist = add_to_template_args (current_template_args (), arglist);
+ outer = DECL_CONTEXT (templ);
+ if (outer)
+ outer = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (outer)));
+ else if (current_template_parms)
+ /* This is an argument of the current template, so we haven't set
+ DECL_CONTEXT yet. */
+ outer = current_template_args ();
- arglist2 = coerce_template_parms (parmlist, arglist, template,
+ if (outer)
+ arglist = add_to_template_args (outer, arglist);
+
+ arglist2 = coerce_template_parms (parmlist, arglist, templ,
complain,
/*require_all_args=*/true,
/*use_default_args=*/true);
if (arglist2 == error_mark_node
|| (!uses_template_parms (arglist2)
- && check_instantiated_args (template, arglist2, complain)))
+ && check_instantiated_args (templ, arglist2, complain)))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- parm = bind_template_template_parm (TREE_TYPE (template), arglist2);
+ parm = bind_template_template_parm (TREE_TYPE (templ), arglist2);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, parm);
}
else
{
- tree template_type = TREE_TYPE (template);
+ tree template_type = TREE_TYPE (templ);
tree gen_tmpl;
tree type_decl;
tree found = NULL_TREE;
int parm_depth;
int is_partial_instantiation;
- gen_tmpl = most_general_template (template);
+ gen_tmpl = most_general_template (templ);
parmlist = DECL_TEMPLATE_PARMS (gen_tmpl);
parm_depth = TMPL_PARMS_DEPTH (parmlist);
arg_depth = TMPL_ARGS_DEPTH (arglist);
<class U> struct S1<T>::S2'. We must fill in the missing
arguments. */
arglist
- = add_outermost_template_args (TYPE_TI_ARGS (TREE_TYPE (template)),
+ = add_outermost_template_args (TYPE_TI_ARGS (TREE_TYPE (templ)),
arglist);
arg_depth = TMPL_ARGS_DEPTH (arglist);
}
/* From here on, we're only interested in the most general
template. */
- template = gen_tmpl;
+ templ = gen_tmpl;
/* Calculate the BOUND_ARGS. These will be the args that are
actually tsubst'd into the definition to create the
tree bound_args = make_tree_vec (parm_depth);
for (i = saved_depth,
- t = DECL_TEMPLATE_PARMS (template);
+ t = DECL_TEMPLATE_PARMS (templ);
i > 0 && t != NULL_TREE;
--i, t = TREE_CHAIN (t))
{
tree a = coerce_template_parms (TREE_VALUE (t),
- arglist, template,
+ arglist, templ,
complain,
/*require_all_args=*/true,
/*use_default_args=*/true);
arglist
= coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
INNERMOST_TEMPLATE_ARGS (arglist),
- template,
+ templ,
complain,
/*require_all_args=*/true,
/*use_default_args=*/true);
{
found = template_type;
- if (!entering_scope && PRIMARY_TEMPLATE_P (template))
+ if (!entering_scope && PRIMARY_TEMPLATE_P (templ))
{
tree ctx;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
/* If we already have this specialization, return it. */
- found = retrieve_specialization (template, arglist,
+ found = retrieve_specialization (templ, arglist,
/*class_specializations_p=*/false);
if (found)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
/* If the deduced arguments are invalid, then the binding
failed. */
if (!is_partial_instantiation
- && check_instantiated_args (template,
+ && check_instantiated_args (templ,
INNERMOST_TEMPLATE_ARGS (arglist),
complain))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
if (!is_partial_instantiation
- && !PRIMARY_TEMPLATE_P (template)
- && TREE_CODE (CP_DECL_CONTEXT (template)) == NAMESPACE_DECL)
+ && !PRIMARY_TEMPLATE_P (templ)
+ && TREE_CODE (CP_DECL_CONTEXT (templ)) == NAMESPACE_DECL)
{
- found = xref_tag_from_type (TREE_TYPE (template),
- DECL_NAME (template),
+ found = xref_tag_from_type (TREE_TYPE (templ),
+ DECL_NAME (templ),
/*tag_scope=*/ts_global);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
}
- context = tsubst (DECL_CONTEXT (template), arglist,
+ context = tsubst (DECL_CONTEXT (templ), arglist,
complain, in_decl);
if (!context)
context = global_namespace;
}
else
{
- t = make_aggr_type (TREE_CODE (template_type));
+ t = make_class_type (TREE_CODE (template_type));
CLASSTYPE_DECLARED_CLASS (t)
= CLASSTYPE_DECLARED_CLASS (template_type);
SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
/* A local class. Make sure the decl gets registered properly. */
if (context == current_function_decl)
- pushtag (DECL_NAME (template), t, /*tag_scope=*/ts_current);
+ pushtag (DECL_NAME (templ), t, /*tag_scope=*/ts_current);
if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
/* This instantiation is another name for the primary
{
TYPE_CONTEXT (t) = FROB_CONTEXT (context);
- type_decl = create_implicit_typedef (DECL_NAME (template), t);
+ type_decl = create_implicit_typedef (DECL_NAME (templ), t);
DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
TYPE_STUB_DECL (t) = type_decl;
DECL_SOURCE_LOCATION (type_decl)
= TREE_PRIVATE (TYPE_STUB_DECL (template_type));
TREE_PROTECTED (type_decl)
= TREE_PROTECTED (TYPE_STUB_DECL (template_type));
- DECL_IN_SYSTEM_HEADER (type_decl)
- = DECL_IN_SYSTEM_HEADER (template);
if (CLASSTYPE_VISIBILITY_SPECIFIED (template_type))
{
DECL_VISIBILITY_SPECIFIED (type_decl) = 1;
template is the immediate parent if this is a full
instantiation. */
if (parm_depth == 1 || is_partial_instantiation
- || !PRIMARY_TEMPLATE_P (template))
+ || !PRIMARY_TEMPLATE_P (templ))
/* This case is easy; there are no member templates involved. */
- found = template;
+ found = templ;
else
{
/* This is a full instantiation of a member template. Look
for a partial instantiation of which this is an instance. */
- for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
+ for (found = DECL_TEMPLATE_INSTANTIATIONS (templ);
found; found = TREE_CHAIN (found))
{
int success;
Create the partial instantiation.
*/
TREE_VEC_LENGTH (arglist)--;
- found = tsubst (template, arglist, complain, NULL_TREE);
+ found = tsubst (templ, arglist, complain, NULL_TREE);
TREE_VEC_LENGTH (arglist)++;
}
}
SET_TYPE_TEMPLATE_INFO (t, tree_cons (found, arglist, NULL_TREE));
- DECL_TEMPLATE_INSTANTIATIONS (template)
+ DECL_TEMPLATE_INSTANTIATIONS (templ)
= tree_cons (arglist, t,
- DECL_TEMPLATE_INSTANTIATIONS (template));
+ DECL_TEMPLATE_INSTANTIATIONS (templ));
if (TREE_CODE (t) == ENUMERAL_TYPE
&& !is_partial_instantiation)
{
tree_fn_t fn;
void *data;
+ /* True when we should also visit template parameters that occur in
+ non-deduced contexts. */
+ bool include_nondeduced_p;
struct pointer_set_t *visited;
};
void *data = pfd->data;
if (TYPE_P (t)
- && for_each_template_parm (TYPE_CONTEXT (t), fn, data, pfd->visited))
+ && (pfd->include_nondeduced_p || TREE_CODE (t) != TYPENAME_TYPE)
+ && for_each_template_parm (TYPE_CONTEXT (t), fn, data, pfd->visited,
+ pfd->include_nondeduced_p))
return error_mark_node;
switch (TREE_CODE (t))
if (!TYPE_TEMPLATE_INFO (t))
*walk_subtrees = 0;
else if (for_each_template_parm (TREE_VALUE (TYPE_TEMPLATE_INFO (t)),
- fn, data, pfd->visited))
+ fn, data, pfd->visited,
+ pfd->include_nondeduced_p))
return error_mark_node;
break;
case INTEGER_TYPE:
if (for_each_template_parm (TYPE_MIN_VALUE (t),
- fn, data, pfd->visited)
+ fn, data, pfd->visited,
+ pfd->include_nondeduced_p)
|| for_each_template_parm (TYPE_MAX_VALUE (t),
- fn, data, pfd->visited))
+ fn, data, pfd->visited,
+ pfd->include_nondeduced_p))
return error_mark_node;
break;
/* Since we're not going to walk subtrees, we have to do this
explicitly here. */
if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data,
- pfd->visited))
+ pfd->visited, pfd->include_nondeduced_p))
return error_mark_node;
/* Fall through. */
case FUNCTION_TYPE:
/* Check the return type. */
- if (for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited))
+ if (for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited,
+ pfd->include_nondeduced_p))
return error_mark_node;
/* Check the parameter types. Since default arguments are not
for (parm = TYPE_ARG_TYPES (t); parm; parm = TREE_CHAIN (parm))
if (for_each_template_parm (TREE_VALUE (parm), fn, data,
- pfd->visited))
+ pfd->visited, pfd->include_nondeduced_p))
return error_mark_node;
/* Since we've already handled the TYPE_ARG_TYPES, we don't
break;
case TYPEOF_TYPE:
- if (for_each_template_parm (TYPE_FIELDS (t), fn, data,
- pfd->visited))
+ if (pfd->include_nondeduced_p
+ && for_each_template_parm (TYPE_FIELDS (t), fn, data,
+ pfd->visited,
+ pfd->include_nondeduced_p))
return error_mark_node;
break;
case VAR_DECL:
if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)
&& for_each_template_parm (DECL_TI_ARGS (t), fn, data,
- pfd->visited))
+ pfd->visited, pfd->include_nondeduced_p))
return error_mark_node;
/* Fall through. */
case CONST_DECL:
if (TREE_CODE (t) == CONST_DECL && DECL_TEMPLATE_PARM_P (t)
&& for_each_template_parm (DECL_INITIAL (t), fn, data,
- pfd->visited))
+ pfd->visited, pfd->include_nondeduced_p))
return error_mark_node;
if (DECL_CONTEXT (t)
+ && pfd->include_nondeduced_p
&& for_each_template_parm (DECL_CONTEXT (t), fn, data,
- pfd->visited))
+ pfd->visited, pfd->include_nondeduced_p))
return error_mark_node;
break;
case BOUND_TEMPLATE_TEMPLATE_PARM:
/* Record template parameters such as `T' inside `TT<T>'. */
- if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data, pfd->visited))
+ if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data, pfd->visited,
+ pfd->include_nondeduced_p))
return error_mark_node;
/* Fall through. */
case TEMPLATE_DECL:
/* A template template parameter is encountered. */
if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)
- && for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited))
+ && for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited,
+ pfd->include_nondeduced_p))
return error_mark_node;
/* Already substituted template template parameter */
case TYPENAME_TYPE:
if (!fn
|| for_each_template_parm (TYPENAME_TYPE_FULLNAME (t), fn,
- data, pfd->visited))
+ data, pfd->visited,
+ pfd->include_nondeduced_p))
return error_mark_node;
break;
case CONSTRUCTOR:
if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))
+ && pfd->include_nondeduced_p
&& for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE
(TREE_TYPE (t)), fn, data,
- pfd->visited))
+ pfd->visited, pfd->include_nondeduced_p))
return error_mark_node;
break;
for_each_template_parm returns 1. Otherwise, the iteration
continues. If FN never returns a nonzero value, the value
returned by for_each_template_parm is 0. If FN is NULL, it is
- considered to be the function which always returns 1. */
+ considered to be the function which always returns 1.
+
+ If INCLUDE_NONDEDUCED_P, then this routine will also visit template
+ parameters that occur in non-deduced contexts. When false, only
+ visits those template parameters that can be deduced. */
static int
for_each_template_parm (tree t, tree_fn_t fn, void* data,
- struct pointer_set_t *visited)
+ struct pointer_set_t *visited,
+ bool include_nondeduced_p)
{
struct pair_fn_data pfd;
int result;
/* Set up. */
pfd.fn = fn;
pfd.data = data;
+ pfd.include_nondeduced_p = include_nondeduced_p;
/* Walk the tree. (Conceptually, we would like to walk without
duplicates, but for_each_template_parm_r recursively calls
int
uses_template_parms_level (tree t, int level)
{
- return for_each_template_parm (t, template_parm_this_level_p, &level, NULL);
+ return for_each_template_parm (t, template_parm_this_level_p, &level, NULL,
+ /*include_nondeduced_p=*/true);
}
static int tinst_depth;
static int
push_tinst_level (tree d)
{
- struct tinst_level *new;
+ struct tinst_level *new_level;
if (tinst_depth >= max_tinst_depth)
{
return 0;
}
- new = GGC_NEW (struct tinst_level);
- new->decl = d;
- new->locus = input_location;
- new->in_system_header_p = in_system_header;
- new->next = current_tinst_level;
- current_tinst_level = new;
+ new_level = GGC_NEW (struct tinst_level);
+ new_level->decl = d;
+ new_level->locus = input_location;
+ new_level->in_system_header_p = in_system_header;
+ new_level->next = current_tinst_level;
+ current_tinst_level = new_level;
++tinst_depth;
#ifdef GATHER_STATISTICS
/* Restore the filename and line number stashed away when we started
this instantiation. */
input_location = current_tinst_level->locus;
- in_system_header = current_tinst_level->in_system_header_p;
current_tinst_level = current_tinst_level->next;
--tinst_depth;
++tinst_level_tick;
/* Friend functions are looked up in the containing namespace scope.
We must enter that scope, to avoid finding member functions of the
- current cless with same name. */
+ current class with same name. */
push_nested_namespace (ns);
fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
tf_warning_or_error, NULL_TREE,
> TMPL_ARGS_DEPTH (args))
{
tree parms;
+ location_t saved_input_location;
parms = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_tmpl),
args, tf_warning_or_error);
+
+ saved_input_location = input_location;
+ input_location = DECL_SOURCE_LOCATION (friend_tmpl);
redeclare_class_template (TREE_TYPE (tmpl), parms);
+ input_location = saved_input_location;
+
}
friend_type = TREE_TYPE (tmpl);
return 1;
}
+/* Apply any attributes which had to be deferred until instantiation
+ time. DECL_P, ATTRIBUTES and ATTR_FLAGS are as cplus_decl_attributes;
+ ARGS, COMPLAIN, IN_DECL are as tsubst. */
+
+static void
+apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
+ tree args, tsubst_flags_t complain, tree in_decl)
+{
+ tree last_dep = NULL_TREE;
+ tree t;
+ tree *p;
+
+ for (t = attributes; t; t = TREE_CHAIN (t))
+ if (ATTR_IS_DEPENDENT (t))
+ {
+ last_dep = t;
+ attributes = copy_list (attributes);
+ break;
+ }
+
+ if (DECL_P (*decl_p))
+ {
+ if (TREE_TYPE (*decl_p) == error_mark_node)
+ return;
+ p = &DECL_ATTRIBUTES (*decl_p);
+ }
+ else
+ p = &TYPE_ATTRIBUTES (*decl_p);
+
+ if (last_dep)
+ {
+ tree late_attrs = NULL_TREE;
+ tree *q = &late_attrs;
+
+ for (*p = attributes; *p; )
+ {
+ t = *p;
+ if (ATTR_IS_DEPENDENT (t))
+ {
+ *p = TREE_CHAIN (t);
+ TREE_CHAIN (t) = NULL_TREE;
+ /* 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);
+ }
+ else
+ p = &TREE_CHAIN (t);
+ }
+
+ cplus_decl_attributes (decl_p, late_attrs, attr_flags);
+ }
+}
+
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);
information. */
xref_basetypes (type, base_list);
+ apply_late_template_attributes (&type, TYPE_ATTRIBUTES (pattern),
+ (int) ATTR_FLAG_TYPE_IN_PLACE,
+ args, tf_error, NULL_TREE);
/* Now that our base classes are set up, enter the scope of the
class, so that name lookups into base classes, etc. will work
correctly. This is precisely analogous to what we do in
begin_class_definition when defining an ordinary non-template
- class. */
- pushclass (type);
+ class, except we also need to push the enclosing classes. */
+ push_nested_class (type);
/* Now members are processed in the order of declaration. */
for (member = CLASSTYPE_DECL_LIST (pattern);
{
tree r;
- /* The the file and line for this declaration, to
+ /* The file and line for this declaration, to
assist in error message reporting. Since we
called push_tinst_level above, we don't need to
restore these. */
/* Build new DECL_FRIENDLIST. */
tree r;
- /* The the file and line for this declaration, to
+ /* The file and line for this declaration, to
assist in error message reporting. Since we
called push_tinst_level above, we don't need to
restore these. */
/* Now that the class is complete, instantiate default arguments for
any member functions. We don't do this earlier because the
default arguments may reference members of the class. */
- if (!PRIMARY_TEMPLATE_P (template))
+ if (!PRIMARY_TEMPLATE_P (templ))
for (t = TYPE_METHODS (type); t; t = TREE_CHAIN (t))
if (TREE_CODE (t) == FUNCTION_DECL
/* Implicitly generated member functions will not have template
&& DECL_TEMPLATE_INFO (t))
tsubst_default_arguments (t);
- popclass ();
+ pop_nested_class ();
pop_from_top_level ();
pop_deferring_access_checks ();
pop_tinst_level ();
tree orig_arg = NULL_TREE;
if (TREE_CODE (parm_pack) == PARM_DECL)
- {
- if (local_specializations)
- arg_pack = retrieve_local_specialization (parm_pack);
- }
+ arg_pack = retrieve_local_specialization (parm_pack);
else
{
int level, idx, levels;
return result;
}
+ if (arg_pack
+ && TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack)) == 1
+ && PACK_EXPANSION_P (TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack), 0)))
+ {
+ tree expansion = TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack), 0);
+ tree pattern = PACK_EXPANSION_PATTERN (expansion);
+ if ((TYPE_P (pattern) && same_type_p (pattern, parm_pack))
+ || (!TYPE_P (pattern) && cp_tree_equal (parm_pack, pattern)))
+ /* The argument pack that the parameter maps to is just an
+ expansion of the parameter itself, such as one would
+ find in the implicit typedef of a class inside the
+ class itself. Consider this parameter "unsubstituted",
+ so that we will maintain the outer pack expansion. */
+ arg_pack = NULL_TREE;
+ }
+
if (arg_pack)
{
int my_len =
/* Else fall through. */
case ENUMERAL_TYPE:
case UNION_TYPE:
- if (TYPE_TEMPLATE_INFO (t))
+ if (TYPE_TEMPLATE_INFO (t) && uses_template_parms (t))
{
tree argvec;
tree context;
up. */
context = TYPE_CONTEXT (t);
if (context)
- context = tsubst_aggr_type (context, args, complain,
- in_decl, /*entering_scope=*/1);
+ {
+ context = tsubst_aggr_type (context, args, complain,
+ in_decl, /*entering_scope=*/1);
+ /* If context is a nested class inside a class template,
+ it may still need to be instantiated (c++/33959). */
+ if (TYPE_P (context))
+ context = complete_type (context);
+ }
/* Then, figure out what arguments are appropriate for the
type we are trying to find. For example, given:
= remove_attribute ("visibility", DECL_ATTRIBUTES (r));
}
determine_visibility (r);
+
+ apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+ args, complain, in_decl);
}
break;
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 (!DECL_TEMPLATE_PARM_P (r))
DECL_ARG_TYPE (r) = type_passed_as (type);
+ apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+ args, complain, in_decl);
+
/* Keep track of the first new parameter we
generate. That's what will be returned to the
caller. */
TREE_CHAIN (r) = NULL_TREE;
if (VOID_TYPE_P (type))
error ("instantiation of %q+D as type %qT", r, type);
+
+ apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+ args, complain, in_decl);
}
break;
tree type = NULL_TREE;
bool local_p;
- if (TREE_CODE (t) == TYPE_DECL)
+ if (TREE_CODE (t) == TYPE_DECL
+ && t == TYPE_MAIN_DECL (TREE_TYPE (t)))
{
+ /* If this is the canonical decl, we don't have to
+ mess with instantiations, and often we can't (for
+ typename, template type parms and such). Note that
+ TYPE_NAME is not correct for the above test if
+ we've copied the type for a typedef. */
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
- if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
- || t == TYPE_MAIN_DECL (TREE_TYPE (t)))
- {
- /* If this is the canonical decl, we don't have to
- mess with instantiations, and often we can't (for
- typename, template type parms and such). Note that
- TYPE_NAME is not correct for the above test if
- we've copied the type for a typedef. */
- r = TYPE_NAME (type);
- break;
- }
+ if (type == error_mark_node)
+ return error_mark_node;
+ r = TYPE_NAME (type);
+ break;
}
/* Check to see if we already have the specialization we
/* Create a new node for the specialization we need. */
r = copy_decl (t);
+ if (type == NULL_TREE)
+ type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (TREE_CODE (r) == VAR_DECL)
{
/* Even if the original location is out of scope, the
DECL_DEAD_FOR_LOCAL (r) = 0;
DECL_INITIALIZED_P (r) = 0;
DECL_TEMPLATE_INSTANTIATED (r) = 0;
- type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node)
return error_mark_node;
if (TREE_CODE (type) == FUNCTION_TYPE)
}
determine_visibility (r);
}
+ /* Preserve a typedef that names a type. */
+ else if (TREE_CODE (r) == TYPE_DECL
+ && DECL_ORIGINAL_TYPE (t)
+ && type != error_mark_node)
+ {
+ DECL_ORIGINAL_TYPE (r) = tsubst (DECL_ORIGINAL_TYPE (t),
+ args, complain, in_decl);
+ TREE_TYPE (r) = type = build_variant_type_copy (type);
+ TYPE_NAME (type) = r;
+ }
if (!local_p)
{
register_local_specialization (r, t);
TREE_CHAIN (r) = NULL_TREE;
+
+ apply_late_template_attributes (&r, DECL_ATTRIBUTES (r),
+ (int) ATTR_FLAG_TYPE_IN_PLACE,
+ args, complain, in_decl);
layout_decl (r, 0);
}
break;
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)
gcc_assert (type != unknown_type_node);
+ /* Reuse typedefs. We need to do this to handle dependent attributes,
+ such as attribute aligned. */
+ if (TYPE_P (t)
+ && TYPE_NAME (t)
+ && TYPE_NAME (t) != TYPE_MAIN_DECL (t))
+ {
+ tree decl = TYPE_NAME (t);
+
+ if (DECL_CLASS_SCOPE_P (decl)
+ && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
+ && uses_template_parms (DECL_CONTEXT (decl)))
+ {
+ tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
+ tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
+ r = retrieve_specialization (tmpl, gen_args, false);
+ }
+ else if (DECL_FUNCTION_SCOPE_P (decl)
+ && DECL_TEMPLATE_INFO (DECL_CONTEXT (decl))
+ && uses_template_parms (DECL_TI_ARGS (DECL_CONTEXT (decl))))
+ r = retrieve_local_specialization (decl);
+ else
+ /* The typedef is from a non-template context. */
+ return t;
+
+ if (r)
+ {
+ r = TREE_TYPE (r);
+ r = cp_build_qualified_type_real
+ (r, cp_type_quals (t) | cp_type_quals (r),
+ complain | tf_ignore_bad_quals);
+ return r;
+ }
+ /* Else we must be instantiating the typedef, so fall through. */
+ }
+
if (type
&& TREE_CODE (t) != TYPENAME_TYPE
&& TREE_CODE (t) != IDENTIFIER_NODE
/*integral_constant_expression_p=*/false);
max = fold_decl_constant_value (max);
- if (TREE_CODE (max) != INTEGER_CST
- && TREE_CODE (max) != TEMPLATE_PARM_INDEX
- && !at_function_scope_p ())
+ if (TREE_CODE (max) != INTEGER_CST
+ && !at_function_scope_p ()
+ && !value_dependent_expression_p (max))
{
if (complain & tf_error)
error ("array bound is not an integer constant");
r = NULL_TREE;
gcc_assert (TREE_VEC_LENGTH (args) > 0);
- if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
- || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
- || TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
- {
- idx = TEMPLATE_TYPE_IDX (t);
- level = TEMPLATE_TYPE_LEVEL (t);
- }
- else
- {
- idx = TEMPLATE_PARM_IDX (t);
- level = TEMPLATE_PARM_LEVEL (t);
- }
+ template_parm_level_and_index (t, &level, &idx);
levels = TMPL_ARGS_DEPTH (args);
if (level <= levels)
r = copy_type (t);
TEMPLATE_TYPE_PARM_INDEX (r)
= reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
- r, levels);
+ r, levels, args, complain);
TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
TYPE_MAIN_VARIANT (r) = r;
TYPE_POINTER_TO (r) = NULL_TREE;
break;
case TEMPLATE_PARM_INDEX:
- r = reduce_template_parm_level (t, type, levels);
+ r = reduce_template_parm_level (t, type, levels, args, complain);
break;
default:
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]
}
r = build_cplus_array_type (type, domain);
+
+ if (TYPE_USER_ALIGN (t))
+ {
+ TYPE_ALIGN (r) = TYPE_ALIGN (t);
+ TYPE_USER_ALIGN (r) = 1;
+ }
+
return r;
}
if (ctx == error_mark_node || f == error_mark_node)
return error_mark_node;
- if (!IS_AGGR_TYPE (ctx))
+ if (!MAYBE_CLASS_TYPE_P (ctx))
{
if (complain & tf_error)
error ("%qT is not a class, struct, or union type", ctx);
if (complain & tf_error)
qualified_name_lookup_error (scope,
TREE_OPERAND (qualified_id, 1),
- expr);
+ expr, input_location);
return error_mark_node;
}
if (expr == error_mark_node && complain & tf_error)
qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1),
- expr);
+ expr, input_location);
else if (TYPE_P (scope))
{
expr = (adjust_result_of_qualified_name_lookup
/* We only want to compute the number of arguments. */
tree expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args,
complain, in_decl);
- return build_int_cst (size_type_node, TREE_VEC_LENGTH (expanded));
+ int len = 0;
+
+ if (TREE_CODE (expanded) == TREE_VEC)
+ len = TREE_VEC_LENGTH (expanded);
+
+ if (expanded == error_mark_node)
+ return error_mark_node;
+ else if (PACK_EXPANSION_P (expanded)
+ || (TREE_CODE (expanded) == TREE_VEC
+ && len > 0
+ && PACK_EXPANSION_P (TREE_VEC_ELT (expanded, len-1))))
+ {
+ if (TREE_CODE (expanded) == TREE_VEC)
+ expanded = TREE_VEC_ELT (expanded, len - 1);
+
+ if (TYPE_P (expanded))
+ return cxx_sizeof_or_alignof_type (expanded, SIZEOF_EXPR,
+ complain & tf_error);
+ else
+ return cxx_sizeof_or_alignof_expr (expanded, SIZEOF_EXPR,
+ complain & tf_error);
+ }
+ else
+ return build_int_cst (size_type_node, len);
}
/* Fall through */
switch (OMP_CLAUSE_CODE (nc))
{
+ case OMP_CLAUSE_LASTPRIVATE:
+ if (OMP_CLAUSE_LASTPRIVATE_STMT (oc))
+ {
+ OMP_CLAUSE_LASTPRIVATE_STMT (nc) = push_stmt_list ();
+ tsubst_expr (OMP_CLAUSE_LASTPRIVATE_STMT (oc), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
+ OMP_CLAUSE_LASTPRIVATE_STMT (nc)
+ = pop_stmt_list (OMP_CLAUSE_LASTPRIVATE_STMT (nc));
+ }
+ /* FALLTHRU */
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_SHARED:
case OMP_CLAUSE_FIRSTPRIVATE:
- case OMP_CLAUSE_LASTPRIVATE:
case OMP_CLAUSE_REDUCTION:
case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_COPYPRIVATE:
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_SCHEDULE:
+ case OMP_CLAUSE_COLLAPSE:
OMP_CLAUSE_OPERAND (nc, 0)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
+ case OMP_CLAUSE_UNTIED:
break;
default:
gcc_unreachable ();
#undef RECUR
}
+/* Substitute one OMP_FOR iterator. */
+
+static void
+tsubst_omp_for_iterator (tree t, int i, tree declv, tree initv,
+ tree condv, tree incrv, tree *clauses,
+ tree args, tsubst_flags_t complain, tree in_decl,
+ bool integral_constant_expression_p)
+{
+#define RECUR(NODE) \
+ tsubst_expr ((NODE), args, complain, in_decl, \
+ integral_constant_expression_p)
+ tree decl, init, cond, incr;
+
+ init = TREE_VEC_ELT (OMP_FOR_INIT (t), i);
+ gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
+ decl = RECUR (TREE_OPERAND (init, 0));
+ init = TREE_OPERAND (init, 1);
+ gcc_assert (!type_dependent_expression_p (decl));
+
+ if (!CLASS_TYPE_P (TREE_TYPE (decl)))
+ {
+ cond = RECUR (TREE_VEC_ELT (OMP_FOR_COND (t), i));
+ incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i);
+ if (TREE_CODE (incr) == MODIFY_EXPR)
+ incr = build_x_modify_expr (RECUR (TREE_OPERAND (incr, 0)), NOP_EXPR,
+ RECUR (TREE_OPERAND (incr, 1)),
+ complain);
+ else
+ incr = RECUR (incr);
+ TREE_VEC_ELT (declv, i) = decl;
+ TREE_VEC_ELT (initv, i) = init;
+ TREE_VEC_ELT (condv, i) = cond;
+ TREE_VEC_ELT (incrv, i) = incr;
+ return;
+ }
+
+ if (init && TREE_CODE (init) != DECL_EXPR)
+ {
+ tree c;
+ for (c = *clauses; c ; c = OMP_CLAUSE_CHAIN (c))
+ {
+ if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
+ && OMP_CLAUSE_DECL (c) == decl)
+ break;
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+ && OMP_CLAUSE_DECL (c) == decl)
+ error ("iteration variable %qD should not be firstprivate", decl);
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_DECL (c) == decl)
+ error ("iteration variable %qD should not be reduction", decl);
+ }
+ if (c == NULL)
+ {
+ c = build_omp_clause (OMP_CLAUSE_PRIVATE);
+ OMP_CLAUSE_DECL (c) = decl;
+ c = finish_omp_clauses (c);
+ if (c)
+ {
+ OMP_CLAUSE_CHAIN (c) = *clauses;
+ *clauses = c;
+ }
+ }
+ }
+ cond = TREE_VEC_ELT (OMP_FOR_COND (t), i);
+ if (COMPARISON_CLASS_P (cond))
+ cond = build2 (TREE_CODE (cond), boolean_type_node,
+ RECUR (TREE_OPERAND (cond, 0)),
+ RECUR (TREE_OPERAND (cond, 1)));
+ else
+ cond = RECUR (cond);
+ incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i);
+ switch (TREE_CODE (incr))
+ {
+ case PREINCREMENT_EXPR:
+ case PREDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ incr = build2 (TREE_CODE (incr), TREE_TYPE (decl),
+ RECUR (TREE_OPERAND (incr, 0)), NULL_TREE);
+ break;
+ case MODIFY_EXPR:
+ if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
+ || TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR)
+ {
+ tree rhs = TREE_OPERAND (incr, 1);
+ incr = build2 (MODIFY_EXPR, TREE_TYPE (decl),
+ RECUR (TREE_OPERAND (incr, 0)),
+ build2 (TREE_CODE (rhs), TREE_TYPE (decl),
+ RECUR (TREE_OPERAND (rhs, 0)),
+ RECUR (TREE_OPERAND (rhs, 1))));
+ }
+ else
+ incr = RECUR (incr);
+ break;
+ case MODOP_EXPR:
+ if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
+ || TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR)
+ {
+ tree lhs = RECUR (TREE_OPERAND (incr, 0));
+ incr = build2 (MODIFY_EXPR, TREE_TYPE (decl), lhs,
+ build2 (TREE_CODE (TREE_OPERAND (incr, 1)),
+ TREE_TYPE (decl), lhs,
+ RECUR (TREE_OPERAND (incr, 2))));
+ }
+ else if (TREE_CODE (TREE_OPERAND (incr, 1)) == NOP_EXPR
+ && (TREE_CODE (TREE_OPERAND (incr, 2)) == PLUS_EXPR
+ || (TREE_CODE (TREE_OPERAND (incr, 2)) == MINUS_EXPR)))
+ {
+ tree rhs = TREE_OPERAND (incr, 2);
+ incr = build2 (MODIFY_EXPR, TREE_TYPE (decl),
+ RECUR (TREE_OPERAND (incr, 0)),
+ build2 (TREE_CODE (rhs), TREE_TYPE (decl),
+ RECUR (TREE_OPERAND (rhs, 0)),
+ RECUR (TREE_OPERAND (rhs, 1))));
+ }
+ else
+ incr = RECUR (incr);
+ break;
+ default:
+ incr = RECUR (incr);
+ break;
+ }
+
+ TREE_VEC_ELT (declv, i) = decl;
+ TREE_VEC_ELT (initv, i) = init;
+ TREE_VEC_ELT (condv, i) = cond;
+ TREE_VEC_ELT (incrv, i) = incr;
+#undef RECUR
+}
+
/* Like tsubst_copy for expressions, etc. but also does semantic
processing. */
/*is_type_p=*/false,
/*complain=*/false);
if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
- qualified_name_lookup_error (scope, name, decl);
+ qualified_name_lookup_error (scope, name, decl, input_location);
else
do_local_using_decl (decl, scope, name);
}
= OMP_PARALLEL_COMBINED (t);
break;
+ case OMP_TASK:
+ tmp = tsubst_omp_clauses (OMP_TASK_CLAUSES (t),
+ args, complain, in_decl);
+ stmt = begin_omp_task ();
+ RECUR (OMP_TASK_BODY (t));
+ finish_omp_task (tmp, stmt);
+ break;
+
case OMP_FOR:
{
- tree clauses, decl, init, cond, incr, body, pre_body;
+ tree clauses, body, pre_body;
+ tree declv, initv, condv, incrv;
+ int i;
clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t),
args, complain, in_decl);
- init = OMP_FOR_INIT (t);
- gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
- decl = RECUR (TREE_OPERAND (init, 0));
- init = RECUR (TREE_OPERAND (init, 1));
- cond = RECUR (OMP_FOR_COND (t));
- incr = RECUR (OMP_FOR_INCR (t));
+ declv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ initv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ condv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ incrv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+
+ for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++)
+ tsubst_omp_for_iterator (t, i, declv, initv, condv, incrv,
+ &clauses, args, complain, in_decl,
+ integral_constant_expression_p);
stmt = begin_omp_structured_block ();
+ for (i = 0; i < TREE_VEC_LENGTH (initv); i++)
+ if (TREE_VEC_ELT (initv, i) == NULL
+ || TREE_CODE (TREE_VEC_ELT (initv, i)) != DECL_EXPR)
+ TREE_VEC_ELT (initv, i) = RECUR (TREE_VEC_ELT (initv, i));
+ else if (CLASS_TYPE_P (TREE_TYPE (TREE_VEC_ELT (initv, i))))
+ {
+ tree init = RECUR (TREE_VEC_ELT (initv, i));
+ gcc_assert (init == TREE_VEC_ELT (declv, i));
+ TREE_VEC_ELT (initv, i) = NULL_TREE;
+ }
+ else
+ {
+ tree decl_expr = TREE_VEC_ELT (initv, i);
+ tree init = DECL_INITIAL (DECL_EXPR_DECL (decl_expr));
+ gcc_assert (init != NULL);
+ TREE_VEC_ELT (initv, i) = RECUR (init);
+ DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = NULL;
+ RECUR (decl_expr);
+ DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = init;
+ }
+
pre_body = push_stmt_list ();
RECUR (OMP_FOR_PRE_BODY (t));
pre_body = pop_stmt_list (pre_body);
RECUR (OMP_FOR_BODY (t));
body = pop_stmt_list (body);
- t = finish_omp_for (EXPR_LOCATION (t), decl, init, cond, incr, body,
- pre_body);
- if (t)
- OMP_FOR_CLAUSES (t) = clauses;
+ t = finish_omp_for (EXPR_LOCATION (t), declv, initv, condv, incrv,
+ body, pre_body, clauses);
add_stmt (finish_omp_structured_block (stmt));
}
break;
case OMP_ATOMIC:
- if (OMP_ATOMIC_DEPENDENT_P (t))
- {
- tree op1 = TREE_OPERAND (t, 1);
- tree lhs = RECUR (TREE_OPERAND (op1, 0));
- tree rhs = RECUR (TREE_OPERAND (op1, 1));
- finish_omp_atomic (TREE_CODE (op1), lhs, rhs);
- }
+ gcc_assert (OMP_ATOMIC_DEPENDENT_P (t));
+ {
+ tree op1 = TREE_OPERAND (t, 1);
+ tree lhs = RECUR (TREE_OPERAND (op1, 0));
+ tree rhs = RECUR (TREE_OPERAND (op1, 1));
+ finish_omp_atomic (TREE_CODE (op1), lhs, rhs);
+ }
break;
case EXPR_PACK_EXPANSION:
/*done=*/true,
/*address_p=*/false,
/*template_arg_p=*/false,
- &error_msg);
+ &error_msg,
+ input_location);
if (error_msg)
error (error_msg);
if (!function_p && TREE_CODE (decl) == IDENTIFIER_NODE)
case TEMPLATE_ID_EXPR:
{
tree object;
- tree template = RECUR (TREE_OPERAND (t, 0));
+ tree templ = RECUR (TREE_OPERAND (t, 0));
tree targs = TREE_OPERAND (t, 1);
if (targs)
targs = tsubst_template_args (targs, args, complain, in_decl);
- if (TREE_CODE (template) == COMPONENT_REF)
+ if (TREE_CODE (templ) == COMPONENT_REF)
{
- object = TREE_OPERAND (template, 0);
- template = TREE_OPERAND (template, 1);
+ object = TREE_OPERAND (templ, 0);
+ templ = TREE_OPERAND (templ, 1);
}
else
object = NULL_TREE;
- template = lookup_template_function (template, targs);
+ templ = lookup_template_function (templ, targs);
if (object)
- return build3 (COMPONENT_REF, TREE_TYPE (template),
- object, template, NULL_TREE);
+ return build3 (COMPONENT_REF, TREE_TYPE (templ),
+ object, templ, NULL_TREE);
else
- return baselink_for_fns (template);
+ return baselink_for_fns (templ);
}
case INDIRECT_REF:
r = convert_from_reference (r);
}
else
- r = build_x_indirect_ref (r, "unary *");
+ r = build_x_indirect_ref (r, "unary *", complain);
return r;
}
if (integral_constant_expression_p
&& !cast_valid_in_integral_constant_expression_p (type))
{
- error ("a cast to a type other than an integral or "
- "enumeration type cannot appear in a constant-expression");
+ if (complain & tf_error)
+ error ("a cast to a type other than an integral or "
+ "enumeration type cannot appear in a constant-expression");
return error_mark_node;
}
switch (TREE_CODE (t))
{
case CAST_EXPR:
- return build_functional_cast (type, op);
+ return build_functional_cast (type, op, complain);
case REINTERPRET_CAST_EXPR:
- return build_reinterpret_cast (type, op);
+ return build_reinterpret_cast (type, op, complain);
case CONST_CAST_EXPR:
- return build_const_cast (type, op);
+ return build_const_cast (type, op, complain);
case DYNAMIC_CAST_EXPR:
- return build_dynamic_cast (type, op);
+ return build_dynamic_cast (type, op, complain);
case STATIC_CAST_EXPR:
- return build_static_cast (type, op);
+ return build_static_cast (type, op, complain);
default:
gcc_unreachable ();
}
case POSTINCREMENT_EXPR:
op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
args, complain, in_decl);
- return build_x_unary_op (TREE_CODE (t), op1);
+ return build_x_unary_op (TREE_CODE (t), op1, complain);
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
case UNARY_PLUS_EXPR: /* Unary + */
case REALPART_EXPR:
case IMAGPART_EXPR:
- return build_x_unary_op (TREE_CODE (t), RECUR (TREE_OPERAND (t, 0)));
+ return build_x_unary_op (TREE_CODE (t), RECUR (TREE_OPERAND (t, 0)),
+ complain);
case ADDR_EXPR:
op1 = TREE_OPERAND (t, 0);
in_decl);
if (TREE_CODE (op1) == LABEL_DECL)
return finish_label_address_expr (DECL_NAME (op1));
- return build_x_unary_op (ADDR_EXPR, op1);
+ return build_x_unary_op (ADDR_EXPR, op1, complain);
case PLUS_EXPR:
case MINUS_EXPR:
(TREE_NO_WARNING (TREE_OPERAND (t, 1))
? ERROR_MARK
: TREE_CODE (TREE_OPERAND (t, 1))),
- /*overloaded_p=*/NULL);
+ /*overloaded_p=*/NULL,
+ complain);
case SCOPE_REF:
return tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
(TREE_NO_WARNING (TREE_OPERAND (t, 1))
? ERROR_MARK
: TREE_CODE (TREE_OPERAND (t, 1))),
- /*overloaded_p=*/NULL);
+ /*overloaded_p=*/NULL,
+ complain);
case SIZEOF_EXPR:
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
- {
- /* We only want to compute the number of arguments. */
- tree expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args,
- complain, in_decl);
- 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);
ce->value = tsubst_pack_expansion (ce->value, args, complain,
in_decl);
- if (TREE_VEC_LENGTH (ce->value) == 1)
+ if (ce->value == error_mark_node)
+ ;
+ else if (TREE_VEC_LENGTH (ce->value) == 1)
/* Just move the argument into place. */
ce->value = TREE_VEC_ELT (ce->value, 0);
else
}
}
+ r = build_constructor (init_list_type_node, n);
+
if (TREE_HAS_CONSTRUCTOR (t))
- return finish_compound_literal (type, n);
+ return finish_compound_literal (type, r);
- return build_constructor (NULL_TREE, n);
+ return r;
}
case TYPEID_EXPR:
}
}
+ /* Now that we have bindings for all of the template arguments,
+ ensure that the arguments deduced for the template template
+ parameters have compatible template parameter lists. We cannot
+ check this property before we have deduced all template
+ arguments, because the template parameter types of a template
+ template parameter might depend on prior template parameters
+ deduced after the template template parameter. The following
+ ill-formed example illustrates this issue:
+
+ template<typename T, template<T> class C> void f(C<5>, T);
+
+ template<int N> struct X {};
+
+ void g() {
+ f(X<5>(), 5l); // error: template argument deduction fails
+ }
+
+ The template parameter list of 'C' depends on the template type
+ parameter 'T', but 'C' is deduced to 'X' before 'T' is deduced to
+ 'long'. Thus, we can't check that 'C' cannot bind to 'X' at the
+ time that we deduce 'C'. */
+ if (result == 0
+ && !template_template_parm_bindings_ok_p
+ (DECL_INNERMOST_TEMPLATE_PARMS (fn), targs))
+ return 1;
+
if (result == 0)
/* All is well so far. Now, check:
arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg,
arg_expr);
+ if (arg == init_list_type_node && arg_expr)
+ arg = arg_expr;
if (unify (tparms, targs, parm, arg, arg_strict))
return 1;
}
if (TREE_CODE (fn) != TEMPLATE_DECL)
continue;
+ ++processing_template_decl;
subargs = get_bindings (fn, DECL_TEMPLATE_RESULT (fn),
expl_subargs, /*check_ret=*/false);
if (subargs)
good += try_one_overload (tparms, targs, tempargs, parm,
elem, strict, sub_strict, addr_p);
}
+ --processing_template_decl;
}
}
else if (TREE_CODE (arg) != OVERLOAD
tree rval = NULL_TREE;
tree binfo;
- gcc_assert (IS_AGGR_TYPE_CODE (TREE_CODE (arg)));
+ gcc_assert (RECORD_OR_UNION_CODE_P (TREE_CODE (arg)));
binfo = TYPE_BINFO (complete_type (arg));
if (!binfo)
/* Unify the pattern with the current argument. */
{
tree arg = TREE_VEC_ELT (packed_args, i);
+ tree arg_expr = NULL_TREE;
int arg_strict = strict;
bool skip_arg_p = false;
if (!skip_arg_p)
{
- arg = TREE_TYPE (arg);
+ arg_expr = arg;
+ arg = unlowered_expr_type (arg);
if (arg == error_mark_node)
return 1;
}
if (!subr)
arg_strict |=
- maybe_adjust_types_for_deduction (strict, &parm, &arg, NULL);
+ maybe_adjust_types_for_deduction (strict, &parm, &arg,
+ arg_expr);
}
if (!skip_arg_p)
{
tree old_pack = TREE_VALUE (pack);
tree new_args = TREE_TYPE (pack);
+ int i, len = TREE_VEC_LENGTH (new_args);
+ bool nondeduced_p = false;
+
+ /* If NEW_ARGS contains any NULL_TREE entries, we didn't
+ actually deduce anything. */
+ for (i = 0; i < len && !nondeduced_p; ++i)
+ if (TREE_VEC_ELT (new_args, i) == NULL_TREE)
+ nondeduced_p = true;
+ if (nondeduced_p)
+ continue;
if (old_pack && ARGUMENT_PACK_INCOMPLETE_P (old_pack))
{
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;
}
{
int i;
+ ++processing_template_decl;
+
/* Discard the outer levels of args, and then substitute in the
template args from the enclosing class. */
partial_spec_args = INNERMOST_TEMPLATE_ARGS (partial_spec_args);
for (i = TREE_VEC_LENGTH (parms) - 1; i >= 0; --i)
TREE_VEC_ELT (parms, i) =
tsubst (TREE_VEC_ELT (parms, i), outer_args, tf_none, NULL_TREE);
+
+ --processing_template_decl;
}
spec_args = get_class_bindings (parms,
partial_spec_args,
VAR_DECLs so we do the lookup here. Probably, grokdeclarator
should handle VAR_DECLs as it currently handles
FUNCTION_DECLs. */
+ if (!DECL_CLASS_SCOPE_P (decl))
+ {
+ error ("%qD is not a static data member of a class template", decl);
+ return;
+ }
result = lookup_field (DECL_CONTEXT (decl), DECL_NAME (decl), 0, false);
if (!result || TREE_CODE (result) != VAR_DECL)
{
the first instantiation was `extern' and the second is not,
and EXTERN_P for the opposite case. */
if (DECL_NOT_REALLY_EXTERN (result) && !extern_p)
- pedwarn ("duplicate explicit instantiation of %q#D", result);
+ permerror ("duplicate explicit instantiation of %q#D", result);
/* If an "extern" explicit instantiation follows an ordinary
explicit instantiation, the template is instantiated. */
if (extern_p)
}
else if (!DECL_TEMPLATE_INFO (result))
{
- pedwarn ("explicit instantiation of non-template %q#D", result);
+ permerror ("explicit instantiation of non-template %q#D", result);
return;
}
;
else if (storage == ridpointers[(int) RID_EXTERN])
{
- if (pedantic && !in_system_header)
- pedwarn ("ISO C++ forbids the use of %<extern%> on explicit "
+ if (pedantic && !in_system_header && (cxx_dialect == cxx98))
+ pedwarn ("ISO C++ 1998 forbids the use of %<extern%> on explicit "
"instantiations");
extern_p = 1;
}
{
tree storage = *(tree *) data;
- if (IS_AGGR_TYPE (entry->type)
+ if (MAYBE_CLASS_TYPE_P (entry->type)
&& !uses_template_parms (CLASSTYPE_TI_ARGS (entry->type)))
do_type_instantiation (TYPE_MAIN_DECL (entry->type), storage, 0);
}
if (storage != NULL_TREE)
{
if (pedantic && !in_system_header)
- pedwarn("ISO C++ forbids the use of %qE on explicit instantiations",
- storage);
+ {
+ if (storage == ridpointers[(int) RID_EXTERN])
+ {
+ if (cxx_dialect == cxx98)
+ pedwarn("ISO C++ 1998 forbids the use of %<extern%> on "
+ "explicit instantiations");
+ }
+ else
+ pedwarn("ISO C++ forbids the use of %qE on explicit "
+ "instantiations", storage);
+ }
if (storage == ridpointers[(int) RID_INLINE])
nomem_p = 1;
if (!previous_instantiation_extern_p && !extern_p
&& (complain & tf_error))
- pedwarn ("duplicate explicit instantiation of %q#T", t);
+ permerror ("duplicate explicit instantiation of %q#T", t);
/* If we've already instantiated the template, just return now. */
if (!CLASSTYPE_INTERFACE_ONLY (t))
bool pattern_defined;
int need_push;
location_t saved_loc = input_location;
- int saved_in_system_header = in_system_header;
bool external_p;
/* This function should only be used to instantiate templates for
mark_definable (d);
input_location = DECL_SOURCE_LOCATION (d);
- in_system_header = DECL_IN_SYSTEM_HEADER (d);
/* If D is a member of an explicitly instantiated class template,
and no definition is available, treat it like an implicit
member function or static data member of a class template
shall be present in every translation unit in which it is
explicitly instantiated. */
- pedwarn
+ permerror
("explicit instantiation of %qD but no definition available", d);
/* ??? Historically, we have instantiated inline functions, even
out:
input_location = saved_loc;
- in_system_header = saved_in_system_header;
pop_deferring_access_checks ();
pop_tinst_level ();
{
int reconsider;
location_t saved_loc = input_location;
- int saved_in_system_header = in_system_header;
/* Instantiating templates may trigger vtable generation. This in turn
may require further template instantiations. We place a limit here
while (reconsider);
input_location = saved_loc;
- in_system_header = saved_in_system_header;
}
/* Substitute ARGVEC into T, which is a list of initializers for
PACK_EXPANSION_PARAMETER_PACKS (expr) =
PACK_EXPANSION_PARAMETER_PACKS (TREE_PURPOSE (t));
- /* Substitute parameter packs into each argument in the
- TREE_LIST. */
- in_base_initializer = 1;
- for (arg = TREE_VALUE (t); arg; arg = TREE_CHAIN (arg))
- {
- tree expanded_exprs;
-
- /* Expand the argument. */
- SET_PACK_EXPANSION_PATTERN (expr, TREE_VALUE (arg));
- expanded_exprs = tsubst_pack_expansion (expr, argvec,
- tf_warning_or_error,
- NULL_TREE);
-
- /* Prepend each of the expanded expressions to the
- corresponding TREE_LIST in EXPANDED_ARGUMENTS. */
- for (i = 0; i < len; i++)
- {
- TREE_VEC_ELT (expanded_arguments, i) =
- tree_cons (NULL_TREE, TREE_VEC_ELT (expanded_exprs, i),
- TREE_VEC_ELT (expanded_arguments, i));
- }
- }
- in_base_initializer = 0;
+ if (TREE_VALUE (t) == void_type_node)
+ /* VOID_TYPE_NODE is used to indicate
+ value-initialization. */
+ {
+ for (i = 0; i < len; i++)
+ TREE_VEC_ELT (expanded_arguments, i) = void_type_node;
+ }
+ else
+ {
+ /* Substitute parameter packs into each argument in the
+ TREE_LIST. */
+ in_base_initializer = 1;
+ for (arg = TREE_VALUE (t); arg; arg = TREE_CHAIN (arg))
+ {
+ tree expanded_exprs;
+
+ /* Expand the argument. */
+ SET_PACK_EXPANSION_PATTERN (expr, TREE_VALUE (arg));
+ expanded_exprs
+ = tsubst_pack_expansion (expr, argvec,
+ tf_warning_or_error,
+ NULL_TREE);
+ if (expanded_exprs == error_mark_node)
+ continue;
+
+ /* Prepend each of the expanded expressions to the
+ corresponding TREE_LIST in EXPANDED_ARGUMENTS. */
+ for (i = 0; i < len; i++)
+ {
+ TREE_VEC_ELT (expanded_arguments, i) =
+ tree_cons (NULL_TREE,
+ TREE_VEC_ELT (expanded_exprs, i),
+ TREE_VEC_ELT (expanded_arguments, i));
+ }
+ }
+ in_base_initializer = 0;
- /* Reverse all of the TREE_LISTs in EXPANDED_ARGUMENTS,
- since we built them backwards. */
- for (i = 0; i < len; i++)
- {
- TREE_VEC_ELT (expanded_arguments, i) =
- nreverse (TREE_VEC_ELT (expanded_arguments, i));
- }
+ /* Reverse all of the TREE_LISTs in EXPANDED_ARGUMENTS,
+ since we built them backwards. */
+ for (i = 0; i < len; i++)
+ {
+ TREE_VEC_ELT (expanded_arguments, i) =
+ nreverse (TREE_VEC_ELT (expanded_arguments, i));
+ }
+ }
}
for (i = 0; i < len; ++i)
if (TREE_CODE (type) == ARRAY_TYPE)
{
if (TYPE_DOMAIN (type)
- && ((value_dependent_expression_p
- (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
- || (type_dependent_expression_p
- (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))))
+ && dependent_type_p (TYPE_DOMAIN (type)))
return true;
return dependent_type_p (TREE_TYPE (type));
}
+ else if (TREE_CODE (type) == INTEGER_TYPE
+ && !TREE_CONSTANT (TYPE_MAX_VALUE (type)))
+ {
+ /* If this is the TYPE_DOMAIN of an array type, consider it
+ dependent. */
+ return (value_dependent_expression_p (TYPE_MAX_VALUE (type))
+ || type_dependent_expression_p (TYPE_MAX_VALUE (type)));
+ }
/* -- a template-id in which either the template name is a template
parameter ... */
/* A non-type template parm. */
if (DECL_TEMPLATE_PARM_P (expression))
return true;
- return false;
+ return value_dependent_expression_p (DECL_INITIAL (expression));
case VAR_DECL:
/* A constant with integral or enumeration type and is initialized
|| any_dependent_template_arguments_p (args));
}
+/* Returns TRUE if OMP_FOR with DECLV, INITV, CONDV and INCRV vectors
+ is dependent. */
+
+bool
+dependent_omp_for_p (tree declv, tree initv, tree condv, tree incrv)
+{
+ int i;
+
+ if (!processing_template_decl)
+ return false;
+
+ for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
+ {
+ tree decl = TREE_VEC_ELT (declv, i);
+ tree init = TREE_VEC_ELT (initv, i);
+ tree cond = TREE_VEC_ELT (condv, i);
+ tree incr = TREE_VEC_ELT (incrv, i);
+
+ if (type_dependent_expression_p (decl))
+ return true;
+
+ if (init && type_dependent_expression_p (init))
+ return true;
+
+ if (type_dependent_expression_p (cond))
+ return true;
+
+ if (COMPARISON_CLASS_P (cond)
+ && (type_dependent_expression_p (TREE_OPERAND (cond, 0))
+ || type_dependent_expression_p (TREE_OPERAND (cond, 1))))
+ return true;
+
+ if (TREE_CODE (incr) == MODOP_EXPR)
+ {
+ if (type_dependent_expression_p (TREE_OPERAND (incr, 0))
+ || type_dependent_expression_p (TREE_OPERAND (incr, 2)))
+ return true;
+ }
+ else if (type_dependent_expression_p (incr))
+ return true;
+ else if (TREE_CODE (incr) == MODIFY_EXPR)
+ {
+ if (type_dependent_expression_p (TREE_OPERAND (incr, 0)))
+ return true;
+ else if (BINARY_CLASS_P (TREE_OPERAND (incr, 1)))
+ {
+ tree t = TREE_OPERAND (incr, 1);
+ if (type_dependent_expression_p (TREE_OPERAND (t, 0))
+ || type_dependent_expression_p (TREE_OPERAND (t, 1)))
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
/* TYPE is a TYPENAME_TYPE. Returns the ordinary TYPE to which the
TYPENAME_TYPE corresponds. Returns the original TYPENAME_TYPE if
no such TYPE can be found. Note that this function peers inside
to look inside it. */
if (only_current_p && !currently_open_class (scope))
return type;
- /* If SCOPE is a partial instantiation, it will not have a valid
- TYPE_FIELDS list, so use the original template. */
- scope = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope);
+ /* If SCOPE isn't the template itself, it will not have a valid
+ TYPE_FIELDS list. */
+ if (same_type_p (scope, CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope)))
+ /* scope is either the template itself or a compatible instantiation
+ like X<T>, so look up the name in the original template. */
+ scope = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope);
+ else
+ /* scope is a partial instantiation, so we can't do the lookup or we
+ will lose the template arguments. */
+ return type;
/* Enter the SCOPE so that name lookup will be resolved as if we
were in the class definition. In particular, SCOPE will no
longer be considered a dependent type. */