static GTY(()) tree saved_access_scope;
+/* Live only within one (recursive) call to tsubst_expr. We use
+ this to pass the statement expression node from the STMT_EXPR
+ to the EXPR_STMT that is its result. */
+static tree cur_stmt_expr;
+
/* A map from local variable declarations in the body of the template
presently being instantiated to the corresponding instantiated
local variables. */
#define UNIFY_ALLOW_OUTER_LESS_CV_QUAL 64
#define UNIFY_ALLOW_MAX_CORRECTION 128
-#define GTB_VIA_VIRTUAL 1 /* The base class we are examining is
- virtual, or a base class of a virtual
- base. */
-#define GTB_IGNORE_TYPE 2 /* We don't need to try to unify the current
- type with the desired type. */
-
static void push_access_scope (tree);
static void pop_access_scope (tree);
static int resolve_overloaded_unification (tree, tree, tree, tree,
static tree build_template_parm_index (int, int, int, tree, tree);
static int inline_needs_template_parms (tree);
static void push_inline_template_parms_recursive (tree, int);
-static tree retrieve_specialization (tree, tree);
static tree retrieve_local_specialization (tree);
-static tree register_specialization (tree, tree, tree);
static void register_local_specialization (tree, tree);
static tree reduce_template_parm_level (tree, tree, int);
-static tree build_template_decl (tree, tree);
static int mark_template_parm (tree, void *);
static int template_parm_this_level_p (tree, void *);
static tree tsubst_friend_function (tree, tree);
static void set_current_access_from_decl (tree);
static void check_default_tmpl_args (tree, tree, int, int);
static tree tsubst_call_declarator_parms (tree, tree, tsubst_flags_t, tree);
-static tree get_template_base_recursive (tree, tree, tree, tree, tree, int);
static tree get_template_base (tree, tree, tree, tree);
static int verify_class_unification (tree, tree, tree);
static tree try_class_unification (tree, tree, tree, tree);
static int coerce_template_template_parms (tree, tree, tsubst_flags_t,
tree, tree);
-static tree determine_specialization (tree, tree, tree *, int);
+static tree determine_specialization (tree, tree, tree *, int, int);
static int template_args_equal (tree, tree);
static void tsubst_default_arguments (tree);
static tree for_each_template_parm_r (tree *, int *, void *);
static void
push_access_scope (tree t)
{
- my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL
- || TREE_CODE (t) == VAR_DECL,
- 0);
+ gcc_assert (TREE_CODE (t) == FUNCTION_DECL
+ || TREE_CODE (t) == VAR_DECL);
if (DECL_CLASS_SCOPE_P (t))
push_nested_class (DECL_CONTEXT (t));
if (decl == error_mark_node)
return error_mark_node;
- my_friendly_assert (DECL_P (decl), 20020812);
+ gcc_assert (DECL_P (decl));
if (TREE_CODE (decl) == TYPE_DECL)
{
return NULL_TREE;
}
else if (TREE_CODE (decl) == FIELD_DECL)
- error ("data member `%D' cannot be a member template", decl);
+ error ("data member %qD cannot be a member template", decl);
else if (DECL_TEMPLATE_INFO (decl))
{
if (!DECL_TEMPLATE_SPECIALIZATION (decl))
return decl;
}
else
- error ("invalid member template declaration `%D'", decl);
+ error ("invalid member template declaration %qD", decl);
return error_mark_node;
}
for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
{
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
- my_friendly_assert (DECL_P (parm), 0);
+ gcc_assert (DECL_P (parm));
switch (TREE_CODE (parm))
{
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
}
}
}
-/* Returns nonzero iff T is a member template function. We must be
- careful as in
-
- template <class T> class C { void f(); }
-
- Here, f is a template function, and a member, but not a member
- template. This function does not concern itself with the origin of
- T, only its present state. So if we have
-
- template <class T> class C { template <class U> void f(U); }
-
- then neither C<int>::f<char> nor C<T>::f<double> is considered
- to be a member template. But, `template <class U> void
- C<int>::f(U)' is considered a member template. */
-
-int
-is_member_template (tree t)
-{
- if (!DECL_FUNCTION_TEMPLATE_P (t))
- /* Anything that isn't a function or a template function is
- certainly not a member template. */
- return 0;
-
- /* A local class can't have member templates. */
- if (decl_function_context (t))
- return 0;
-
- return (DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))
- /* If there are more levels of template parameters than
- there are template classes surrounding the declaration,
- then we have a member template. */
- && (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) >
- template_class_depth (DECL_CONTEXT (t))));
-}
-
-#if 0 /* UNUSED */
-/* Returns nonzero iff T is a member template class. See
- is_member_template for a description of what precisely constitutes
- a member template. */
-
-int
-is_member_template_class (tree t)
-{
- if (!DECL_CLASS_TEMPLATE_P (t))
- /* Anything that isn't a class template, is certainly not a member
- template. */
- return 0;
-
- if (!DECL_CLASS_SCOPE_P (t))
- /* Anything whose context isn't a class type is surely not a
- member template. */
- return 0;
-
- /* If there are more levels of template parameters than there are
- template classes surrounding the declaration, then we have a
- member template. */
- return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) >
- template_class_depth (DECL_CONTEXT (t)));
-}
-#endif
-
/* Return a new template argument vector which contains all of ARGS,
but has as its innermost set of arguments the EXTRA_ARGS. */
/* If there are more levels of EXTRA_ARGS than there are ARGS,
something very fishy is going on. */
- my_friendly_assert (TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args),
- 0);
+ gcc_assert (TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args));
/* If *all* the new arguments will be the EXTRA_ARGS, just return
them. */
int extra_levels;
int i;
- my_friendly_assert (n >= 0, 20000603);
+ gcc_assert (n >= 0);
/* If N is 1, just return the innermost set of template arguments. */
if (n == 1)
/* If we're not removing anything, just return the arguments we were
given. */
extra_levels = TMPL_ARGS_DEPTH (args) - n;
- my_friendly_assert (extra_levels >= 0, 20000603);
+ gcc_assert (extra_levels >= 0);
if (extra_levels == 0)
return args;
shall be declared in the namespace of which the class template
is a member. */
if (scope && TREE_CODE (scope) != NAMESPACE_DECL)
- error ("explicit specialization in non-namespace scope `%D'",
- scope);
+ error ("explicit specialization in non-namespace scope %qD", scope);
/* [temp.expl.spec]
void
begin_explicit_instantiation (void)
{
- my_friendly_assert (!processing_explicit_instantiation, 20020913);
+ gcc_assert (!processing_explicit_instantiation);
processing_explicit_instantiation = true;
}
void
end_explicit_instantiation (void)
{
- my_friendly_assert(processing_explicit_instantiation, 20020913);
+ gcc_assert (processing_explicit_instantiation);
processing_explicit_instantiation = false;
}
+/* A explicit specialization or partial specialization TMPL is being
+ declared. Check that the namespace in which the specialization is
+ occurring is permissible. Returns false iff it is invalid to
+ specialize TMPL in the current namespace. */
+
+static bool
+check_specialization_namespace (tree tmpl)
+{
+ tree tpl_ns = decl_namespace_context (tmpl);
+
+ /* [tmpl.expl.spec]
+
+ An explicit specialization shall be declared in the namespace of
+ which the template is a member, or, for member templates, in the
+ namespace of which the enclosing class or enclosing class
+ template is a member. An explicit specialization of a member
+ function, member class or static data member of a class template
+ shall be declared in the namespace of which the class template is
+ a member. */
+ if (is_associated_namespace (current_namespace, tpl_ns))
+ /* Same or super-using namespace. */
+ return true;
+ else
+ {
+ pedwarn ("specialization of %qD in different namespace", tmpl);
+ cp_pedwarn_at (" from definition of %q#D", tmpl);
+ return false;
+ }
+}
+
/* The TYPE is being declared. If it is a template type, that means it
is a partial specialization. Do appropriate error-checking. */
if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
&& !COMPLETE_TYPE_P (type))
{
- tree tpl_ns = decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type));
- if (is_associated_namespace (current_namespace, tpl_ns))
- /* Same or super-using namespace. */;
- else
- {
- pedwarn ("specializing `%#T' in different namespace", type);
- cp_pedwarn_at (" from definition of `%#D'",
- CLASSTYPE_TI_TEMPLATE (type));
- }
+ check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type));
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
if (processing_template_decl)
push_template_decl (TYPE_MAIN_DECL (type));
}
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
- error ("specialization of `%T' after instantiation", type);
+ error ("specialization of %qT after instantiation", type);
}
else if (CLASS_TYPE_P (type)
&& !CLASSTYPE_USE_TEMPLATE (type)
if (current_namespace
!= decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
{
- pedwarn ("specializing `%#T' in different namespace", type);
- cp_pedwarn_at (" from definition of `%#D'",
+ pedwarn ("specializing %q#T in different namespace", type);
+ cp_pedwarn_at (" from definition of %q#D",
CLASSTYPE_TI_TEMPLATE (type));
}
t; t = TREE_CHAIN (t))
if (TREE_VALUE (t) != type
&& TYPE_CONTEXT (TREE_VALUE (t)) == context)
- error ("specialization `%T' after instantiation `%T'",
+ error ("specialization %qT after instantiation %qT",
type, TREE_VALUE (t));
/* Mark TYPE as a specialization. And as a result, we only
}
}
else if (processing_specialization)
- error ("explicit specialization of non-template `%T'", type);
+ error ("explicit specialization of non-template %qT", type);
+}
+
+/* Returns onzero if we can optimize the retrieval of specializations
+ for TMPL, a TEMPLATE_DECL. In particular, for such a template, we
+ do not use DECL_TEMPLATE_SPECIALIZATIONS at all. */
+
+static inline bool
+optimize_specialization_lookup_p (tree tmpl)
+{
+ return (DECL_FUNCTION_TEMPLATE_P (tmpl)
+ && DECL_CLASS_SCOPE_P (tmpl)
+ /* DECL_CLASS_SCOPE_P holds of T::f even if T is a template
+ parameter. */
+ && CLASS_TYPE_P (DECL_CONTEXT (tmpl))
+ && !DECL_MEMBER_TEMPLATE_P (tmpl)
+ && !DECL_CONV_FN_P (tmpl)
+ /* It is possible to have a template that is not a member
+ template and is not a member of a template class:
+
+ template <typename T>
+ struct S { friend A::f(); };
+
+ Here, the friend function is a template, but the context does
+ not have template information. The optimized lookup relies
+ on having ARGS be the template arguments for both the class
+ and the function template. */
+ && !DECL_FRIEND_P (DECL_TEMPLATE_RESULT (tmpl)));
}
/* Retrieve the specialization (in the sense of [temp.spec] - a
specialization) of TMPL for the given template ARGS. If there is
no such specialization, return NULL_TREE. The ARGS are a vector of
arguments, or a vector of vectors of arguments, in the case of
- templates with more than one level of parameters. */
+ templates with more than one level of parameters.
+
+ If TMPL is a type template and CLASS_SPECIALIZATIONS_P is true,
+ then we search for a partial specialization matching ARGS. This
+ parameter is ignored if TMPL is not a class template. */
static tree
-retrieve_specialization (tree tmpl, tree args)
+retrieve_specialization (tree tmpl, tree args,
+ bool class_specializations_p)
{
- tree s;
-
- my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
+ gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
/* There should be as many levels of arguments as there are
levels of parameters. */
- my_friendly_assert (TMPL_ARGS_DEPTH (args)
- == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)),
- 0);
-
- for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
- s != NULL_TREE;
- s = TREE_CHAIN (s))
- if (comp_template_args (TREE_PURPOSE (s), args))
- return TREE_VALUE (s);
+ gcc_assert (TMPL_ARGS_DEPTH (args)
+ == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)));
+
+ if (optimize_specialization_lookup_p (tmpl))
+ {
+ tree class_template;
+ tree class_specialization;
+ VEC(tree) *methods;
+ tree fns;
+ int idx;
+
+ /* The template arguments actually apply to the containing
+ class. Find the class specialization with those
+ arguments. */
+ class_template = CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (tmpl));
+ class_specialization
+ = retrieve_specialization (class_template, args,
+ /*class_specializations_p=*/false);
+ if (!class_specialization)
+ return NULL_TREE;
+ /* Now, find the appropriate entry in the CLASSTYPE_METHOD_VEC
+ for the specialization. */
+ idx = class_method_index_for_fn (class_specialization, tmpl);
+ if (idx == -1)
+ return NULL_TREE;
+ /* Iterate through the methods with the indicated name, looking
+ for the one that has an instance of TMPL. */
+ methods = CLASSTYPE_METHOD_VEC (class_specialization);
+ for (fns = VEC_index (tree, methods, idx); fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+ if (DECL_TEMPLATE_INFO (fn) && DECL_TI_TEMPLATE (fn) == tmpl)
+ return fn;
+ }
+ return NULL_TREE;
+ }
+ else
+ {
+ tree *sp;
+ tree *head;
+
+ /* Class templates store their instantiations on the
+ DECL_TEMPLATE_INSTANTIATIONS list; other templates use the
+ DECL_TEMPLATE_SPECIALIZATIONS list. */
+ if (!class_specializations_p
+ && TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL)
+ sp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
+ else
+ sp = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
+ head = sp;
+ /* Iterate through the list until we find a matching template. */
+ while (*sp != NULL_TREE)
+ {
+ tree spec = *sp;
+
+ if (comp_template_args (TREE_PURPOSE (spec), args))
+ {
+ /* Use the move-to-front heuristic to speed up future
+ searches. */
+ if (spec != *head)
+ {
+ *sp = TREE_CHAIN (*sp);
+ TREE_CHAIN (spec) = *head;
+ *head = spec;
+ }
+ return TREE_VALUE (spec);
+ }
+ sp = &TREE_CHAIN (spec);
+ }
+ }
return NULL_TREE;
}
}
else
{
- my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 0);
+ gcc_assert (TREE_CODE (decl) == TYPE_DECL);
for (t = TREE_TYPE (decl);
t != NULL_TREE;
bool need_template = true;
int template_depth;
- my_friendly_assert (TREE_CODE (decl) == FUNCTION_DECL, 0);
+ gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
/* For [temp.friend/6] when FRIEND is an ordinary member function
of a template class, we want to check if DECL is a specialization
static tree
register_specialization (tree spec, tree tmpl, tree args)
{
- tree s;
+ tree fn;
- my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
+ gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
if (TREE_CODE (spec) == FUNCTION_DECL
&& uses_template_parms (DECL_TI_ARGS (spec)))
/* There should be as many levels of arguments as there are
levels of parameters. */
- my_friendly_assert (TMPL_ARGS_DEPTH (args)
- == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)),
- 0);
-
- for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
- s != NULL_TREE;
- s = TREE_CHAIN (s))
- {
- tree fn = TREE_VALUE (s);
-
- /* We can sometimes try to re-register a specialization that we've
- already got. In particular, regenerate_decl_from_template
- calls duplicate_decls which will update the specialization
- list. But, we'll still get called again here anyhow. It's
- more convenient to simply allow this than to try to prevent it. */
- if (fn == spec)
- return spec;
- else if (comp_template_args (TREE_PURPOSE (s), args))
+ gcc_assert (TMPL_ARGS_DEPTH (args)
+ == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)));
+
+ fn = retrieve_specialization (tmpl, args,
+ /*class_specializations_p=*/false);
+ /* We can sometimes try to re-register a specialization that we've
+ already got. In particular, regenerate_decl_from_template calls
+ duplicate_decls which will update the specialization list. But,
+ we'll still get called again here anyhow. It's more convenient
+ to simply allow this than to try to prevent it. */
+ if (fn == spec)
+ return spec;
+ else if (fn && DECL_TEMPLATE_SPECIALIZATION (spec))
+ {
+ if (DECL_TEMPLATE_INSTANTIATION (fn))
{
- if (DECL_TEMPLATE_SPECIALIZATION (spec))
+ if (TREE_USED (fn)
+ || DECL_EXPLICIT_INSTANTIATION (fn))
{
- if (DECL_TEMPLATE_INSTANTIATION (fn))
- {
- if (TREE_USED (fn)
- || DECL_EXPLICIT_INSTANTIATION (fn))
- {
- error ("specialization of %D after instantiation",
- fn);
- return spec;
- }
- else
- {
- /* This situation should occur only if the first
- specialization is an implicit instantiation,
- the second is an explicit specialization, and
- the implicit instantiation has not yet been
- used. That situation can occur if we have
- implicitly instantiated a member function and
- then specialized it later.
-
- We can also wind up here if a friend
- declaration that looked like an instantiation
- turns out to be a specialization:
-
- template <class T> void foo(T);
- class S { friend void foo<>(int) };
- template <> void foo(int);
-
- We transform the existing DECL in place so that
- any pointers to it become pointers to the
- updated declaration.
-
- If there was a definition for the template, but
- not for the specialization, we want this to
- look as if there were no definition, and vice
- versa. */
- DECL_INITIAL (fn) = NULL_TREE;
- duplicate_decls (spec, fn);
-
- return fn;
- }
- }
- else if (DECL_TEMPLATE_SPECIALIZATION (fn))
- {
- if (!duplicate_decls (spec, fn) && DECL_INITIAL (spec))
- /* Dup decl failed, but this is a new
- definition. Set the line number so any errors
- match this new definition. */
- DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (spec);
-
- return fn;
- }
+ error ("specialization of %qD after instantiation",
+ fn);
+ return spec;
+ }
+ else
+ {
+ /* This situation should occur only if the first
+ specialization is an implicit instantiation, the
+ second is an explicit specialization, and the
+ implicit instantiation has not yet been used. That
+ situation can occur if we have implicitly
+ instantiated a member function and then specialized
+ it later.
+
+ We can also wind up here if a friend declaration that
+ looked like an instantiation turns out to be a
+ specialization:
+
+ template <class T> void foo(T);
+ class S { friend void foo<>(int) };
+ template <> void foo(int);
+
+ We transform the existing DECL in place so that any
+ pointers to it become pointers to the updated
+ declaration.
+
+ If there was a definition for the template, but not
+ for the specialization, we want this to look as if
+ there were no definition, and vice versa. */
+ DECL_INITIAL (fn) = NULL_TREE;
+ duplicate_decls (spec, fn);
+
+ return fn;
}
}
- }
+ else if (DECL_TEMPLATE_SPECIALIZATION (fn))
+ {
+ if (!duplicate_decls (spec, fn) && DECL_INITIAL (spec))
+ /* Dup decl failed, but this is a new definition. Set the
+ line number so any errors match this new
+ definition. */
+ DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (spec);
+
+ return fn;
+ }
+ }
- DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
- = tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
+ /* A specialization must be declared in the same namespace as the
+ template it is specializing. */
+ if (DECL_TEMPLATE_SPECIALIZATION (spec)
+ && !check_specialization_namespace (tmpl))
+ DECL_CONTEXT (spec) = decl_namespace_context (tmpl);
+
+ if (!optimize_specialization_lookup_p (tmpl))
+ DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
+ = tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
return spec;
}
If NEED_MEMBER_TEMPLATE is nonzero the function is known to be a
specialization of a member template.
+ The TEMPLATE_COUNT is the number of references to qualifying
+ template classes that appeared in the name of the function. See
+ check_explicit_specialization for a more accurate description.
+
The template args (those explicitly specified and those deduced)
are output in a newly created vector *TARGS_OUT.
determine_specialization (tree template_id,
tree decl,
tree* targs_out,
- int need_member_template)
+ int need_member_template,
+ int template_count)
{
tree fns;
tree targs;
tree explicit_targs;
tree candidates = NULL_TREE;
tree templates = NULL_TREE;
+ int header_count;
+ struct cp_binding_level *b;
*targs_out = NULL_TREE;
if (!is_overloaded_fn (fns))
{
- error ("`%D' is not a function template", fns);
+ error ("%qD is not a function template", fns);
return error_mark_node;
}
+ /* Count the number of template headers specified for this
+ specialization. */
+ header_count = 0;
+ for (b = current_binding_level;
+ b->kind == sk_template_parms || b->kind == sk_template_spec;
+ b = b->level_chain)
+ ++header_count;
+
for (; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
TREE_VALUE (decl_arg_types)))
continue;
+ /* In case of explicit specialization, we need to check if
+ the number of template headers appearing in the specialization
+ is correct. This is usually done in check_explicit_specialization,
+ but the check done there cannot be exhaustive when specializing
+ member functions. Consider the following code:
+
+ template <> void A<int>::f(int);
+ template <> template <> void A<int>::f(int);
+
+ Assuming that A<int> is not itself an explicit specialization
+ already, the first line specializes "f" which is a non-template
+ member function, whilst the second line specializes "f" which
+ is a template member function. So both lines are syntactically
+ correct, and check_explicit_specialization does not reject
+ them.
+
+ Here, we can do better, as we are matching the specialization
+ against the declarations. We count the number of template
+ headers, and we check if they match TEMPLATE_COUNT + 1
+ (TEMPLATE_COUNT is the number of qualifying template classes,
+ plus there must be another header for the member template
+ itself).
+
+ Notice that if header_count is zero, this is not a
+ specialization but rather a template instantiation, so there
+ is no check we can perform here. */
+ if (header_count && header_count != template_count + 1)
+ continue;
+
/* See whether this function might be a specialization of this
template. */
targs = get_bindings (fn, decl, explicit_targs);
if (templates == NULL_TREE && candidates == NULL_TREE)
{
- cp_error_at ("template-id `%D' for `%+D' does not match any template declaration",
+ cp_error_at ("template-id %qD for %q+D does not match any template "
+ "declaration",
template_id, decl);
return error_mark_node;
}
|| (candidates && TREE_CHAIN (candidates))
|| (templates && candidates))
{
- cp_error_at ("ambiguous template specialization `%D' for `%+D'",
+ cp_error_at ("ambiguous template specialization %qD for %q+D",
template_id, decl);
chainon (candidates, templates);
print_candidates (candidates);
/* This case handles bogus declarations like template <>
template <class T> void f<int>(); */
- error ("template-id `%D' in declaration of primary template",
- declarator);
+ error ("template-id %qD in declaration of primary template",
+ declarator);
return decl;
}
}
break;
case tsk_excessive_parms:
- error ("too many template parameter lists in declaration of `%D'",
- decl);
- return error_mark_node;
+ case tsk_insufficient_parms:
+ if (tsk == tsk_excessive_parms)
+ error ("too many template parameter lists in declaration of %qD",
+ decl);
+ else if (template_header_count)
+ error("too few template parameter lists in declaration of %qD", decl);
+ else
+ error("explicit specialization of %qD must be introduced by "
+ "`template <>'", decl);
/* Fall through. */
case tsk_expl_spec:
else
specialization = 1;
break;
-
- case tsk_insufficient_parms:
- if (template_header_count)
- {
- error("too few template parameter lists in declaration of `%D'",
- decl);
- return decl;
- }
- else if (ctype != NULL_TREE
- && !TYPE_BEING_DEFINED (ctype)
- && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype)
- && !is_friend)
- {
- /* For backwards compatibility, we accept:
-
- template <class T> struct S { void f(); };
- void S<int>::f() {} // Missing template <>
-
- That used to be valid C++. */
- if (pedantic)
- pedwarn
- ("explicit specialization not preceded by `template <>'");
- specialization = 1;
- SET_DECL_TEMPLATE_SPECIALIZATION (decl);
- }
- break;
case tsk_template:
if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
template <class T> void f<int>(); */
if (uses_template_parms (declarator))
- error ("function template partial specialization `%D' "
+ error ("function template partial specialization %qD "
"is not allowed", declarator);
else
- error ("template-id `%D' in declaration of primary template",
- declarator);
+ error ("template-id %qD in declaration of primary template",
+ declarator);
return decl;
}
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (specialization || member_specialization)
{
tree fns;
- my_friendly_assert (TREE_CODE (declarator) == IDENTIFIER_NODE, 0);
+ gcc_assert (TREE_CODE (declarator) == IDENTIFIER_NODE);
if (ctype)
fns = dname;
else
{
/* If there is no class context, the explicit instantiation
must be at namespace scope. */
- my_friendly_assert (DECL_NAMESPACE_SCOPE_P (decl), 20030625);
+ gcc_assert (DECL_NAMESPACE_SCOPE_P (decl));
/* Find the namespace binding, using the declaration
context. */
methods = CLASSTYPE_METHOD_VEC (ctype);
if (methods)
for (idx = CLASSTYPE_FIRST_CONVERSION_SLOT;
- (ovl = VEC_iterate (tree, methods, idx));
+ VEC_iterate (tree, methods, idx, ovl);
++idx)
{
if (!DECL_CONV_FN_P (OVL_CURRENT (ovl)))
if (fns == NULL_TREE)
{
- error ("no member function `%D' declared in `%T'",
- name, ctype);
+ error ("no member function %qD declared in %qT", name, ctype);
return error_mark_node;
}
else
declaration. */
tmpl = determine_specialization (declarator, decl,
&targs,
- member_specialization);
+ member_specialization,
+ template_count);
if (!tmpl || tmpl == error_mark_node)
/* We couldn't figure out what this declaration was
;
else if (template_header_count > context_depth + 1)
/* There are two many template parameter lists. */
- error ("too many template parameter lists in declaration of `%T'", type);
+ error ("too many template parameter lists in declaration of %qT", type);
}
}
parameters. These are represented in the same format used for
DECL_TEMPLATE_PARMS. */
-int comp_template_parms (tree parms1, tree parms2)
+int
+comp_template_parms (tree parms1, tree parms2)
{
tree p1;
tree p2;
tree t2 = TREE_VALUE (p2);
int i;
- my_friendly_assert (TREE_CODE (t1) == TREE_VEC, 0);
- my_friendly_assert (TREE_CODE (t2) == TREE_VEC, 0);
+ gcc_assert (TREE_CODE (t1) == TREE_VEC);
+ gcc_assert (TREE_CODE (t2) == TREE_VEC);
if (TREE_VEC_LENGTH (t1) != TREE_VEC_LENGTH (t2))
return 0;
|| TEMPLATE_PARMS_FOR_INLINE (current_template_parms))
return;
- cp_error_at ("declaration of `%#D'", decl);
- cp_error_at (" shadows template parm `%#D'", olddecl);
+ cp_error_at ("declaration of %q#D", decl);
+ cp_error_at (" shadows template parm %q#D", olddecl);
}
/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
int idx;
parm = next;
- my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259);
+ gcc_assert (TREE_CODE (parm) == TREE_LIST);
defval = TREE_PURPOSE (parm);
if (list)
}
/* Return a TEMPLATE_DECL corresponding to DECL, using the indicated
- template PARMS. Used by push_template_decl below. */
+ template PARMS. If MEMBER_TEMPLATE_P is true, the new template is
+ a mebmer template. Used by push_template_decl below. */
static tree
-build_template_decl (tree decl, tree parms)
+build_template_decl (tree decl, tree parms, bool member_template_p)
{
tree tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
DECL_TEMPLATE_PARMS (tmpl) = parms;
DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
+ DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p;
if (DECL_LANG_SPECIFIC (decl))
{
DECL_STATIC_FUNCTION_P (tmpl) = DECL_STATIC_FUNCTION_P (decl);
did_error_intro = 1;
}
- error (" `%D'",
- TREE_VALUE (TREE_VEC_ELT (inner_parms, i)));
+ error (" %qD", TREE_VALUE (TREE_VEC_ELT (inner_parms, i)));
}
/* [temp.class.spec]
(inner_args,
INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (TREE_TYPE
(maintmpl)))))
- error ("partial specialization `%T' does not specialize any template arguments", type);
+ error ("partial specialization %qT does not specialize any template arguments", type);
/* [temp.class.spec]
The type of a template parameter corresponding to a specialized
non-type argument shall not be dependent on a parameter of the
specialization. */
- my_friendly_assert (nargs == DECL_NTPARMS (maintmpl), 0);
+ gcc_assert (nargs == DECL_NTPARMS (maintmpl));
tpd2.parms = 0;
for (i = 0; i < nargs; ++i)
{
&& TREE_CODE (arg) != TEMPLATE_PARM_INDEX)
{
if (tpd.arg_uses_template_parms[i])
- error ("template argument `%E' involves template parameter(s)", arg);
+ error ("template argument %qE involves template parameter(s)", arg);
else
{
/* Look at the corresponding template parameter,
if (tpd2.parms[j] != 0
&& tpd.arg_uses_template_parms [j])
{
- error ("type `%T' of template argument `%E' depends on template parameter(s)",
- type,
- arg);
+ error ("type %qT of template argument %qE depends "
+ "on template parameter(s)",
+ type,
+ arg);
break;
}
}
}
}
- if (retrieve_specialization (maintmpl, specargs))
+ if (retrieve_specialization (maintmpl, specargs,
+ /*class_specializations_p=*/true))
/* We've already got this specialization. */
return decl;
seen_def_arg_p = 1;
else if (seen_def_arg_p)
{
- error ("no default argument for `%D'", TREE_VALUE (parm));
+ error ("no default argument for %qD", TREE_VALUE (parm));
/* For better subsequent error-recovery, we indicate that
there should have been a default argument. */
TREE_PURPOSE (parm) = error_mark_node;
else if (is_partial)
msg = "default template arguments may not be used in partial specializations";
else
- msg = "default argument for template parameter for class enclosing `%D'";
+ msg = "default argument for template parameter for class enclosing %qD";
if (current_class_type && TYPE_BEING_DEFINED (current_class_type))
/* If we're inside a class definition, there's no need to
/* At this point, if we're still interested in issuing messages,
they must apply to classes surrounding the object declared. */
if (msg)
- msg = "default argument for template parameter for class enclosing `%D'";
+ msg = "default argument for template parameter for class enclosing %qD";
}
}
int primary;
int is_partial;
int new_template_p = 0;
+ /* True if the template is a member template, in the sense of
+ [temp.mem]. */
+ bool member_template_p = false;
if (decl == error_mark_node)
return decl;
if (primary)
{
+ if (DECL_CLASS_SCOPE_P (decl))
+ member_template_p = true;
if (current_lang_name == lang_name_c)
error ("template with C linkage");
else if (TREE_CODE (decl) == TYPE_DECL
&& ANON_AGGRNAME_P (DECL_NAME (decl)))
error ("template class without a name");
- else if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_DESTRUCTOR_P (decl))
+ else if (TREE_CODE (decl) == FUNCTION_DECL)
{
- /* [temp.mem]
-
- A destructor shall not be a member template. */
- error ("destructor `%D' declared as member template", decl);
- return error_mark_node;
+ if (DECL_DESTRUCTOR_P (decl))
+ {
+ /* [temp.mem]
+
+ A destructor shall not be a member template. */
+ error ("destructor %qD declared as member template", decl);
+ return error_mark_node;
+ }
+ if (NEW_DELETE_OPNAME_P (DECL_NAME (decl))
+ && (!TYPE_ARG_TYPES (TREE_TYPE (decl))
+ || TYPE_ARG_TYPES (TREE_TYPE (decl)) == void_list_node
+ || !TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)))
+ || (TREE_CHAIN (TYPE_ARG_TYPES ((TREE_TYPE (decl))))
+ == void_list_node)))
+ {
+ /* [basic.stc.dynamic.allocation]
+
+ An allocation function can be a function
+ template. ... Template allocation functions shall
+ have two or more parameters. */
+ error ("invalid template declaration of %qD", decl);
+ return decl;
+ }
}
else if ((DECL_IMPLICIT_TYPEDEF_P (decl)
&& CLASS_TYPE_P (TREE_TYPE (decl)))
- || (TREE_CODE (decl) == VAR_DECL && ctx && CLASS_TYPE_P (ctx))
- || TREE_CODE (decl) == FUNCTION_DECL)
+ || (TREE_CODE (decl) == VAR_DECL && ctx && CLASS_TYPE_P (ctx)))
/* OK */;
else
{
- error ("template declaration of `%#D'", decl);
+ error ("template declaration of %q#D", decl);
return error_mark_node;
}
}
}
else
{
- tmpl = build_template_decl (decl, current_template_parms);
+ tmpl = build_template_decl (decl, current_template_parms,
+ member_template_p);
new_template_p = 1;
if (DECL_LANG_SPECIFIC (decl)
tmpl = TYPE_TI_TEMPLATE (TREE_TYPE (decl));
else
{
- error ("`%D' does not declare a template type", decl);
+ error ("%qD does not declare a template type", decl);
return decl;
}
}
else if (!DECL_LANG_SPECIFIC (decl) || !DECL_TEMPLATE_INFO (decl))
{
- error ("template definition of non-template `%#D'", decl);
+ error ("template definition of non-template %q#D", decl);
return decl;
}
else
if (DECL_FUNCTION_TEMPLATE_P (tmpl)
&& DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl)
&& DECL_TEMPLATE_SPECIALIZATION (decl)
- && is_member_template (tmpl))
+ && DECL_MEMBER_TEMPLATE_P (tmpl))
{
tree new_tmpl;
args = DECL_TI_ARGS (decl);
new_tmpl
- = build_template_decl (decl, current_template_parms);
+ = build_template_decl (decl, current_template_parms,
+ member_template_p);
DECL_TEMPLATE_RESULT (new_tmpl) = decl;
TREE_TYPE (new_tmpl) = TREE_TYPE (decl);
DECL_TI_TEMPLATE (decl) = new_tmpl;
i = TMPL_PARMS_DEPTH (parms);
if (TMPL_ARGS_DEPTH (args) != i)
{
- error ("expected %d levels of template parms for `%#D', got %d",
- i, decl, TMPL_ARGS_DEPTH (args));
+ error ("expected %d levels of template parms for %q#D, got %d",
+ i, decl, TMPL_ARGS_DEPTH (args));
}
else
for (current = decl; i > 0; --i, parms = TREE_CHAIN (parms))
if (TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a))
{
if (current == decl)
- error ("got %d template parameters for `%#D'",
- TREE_VEC_LENGTH (a), decl);
+ error ("got %d template parameters for %q#D",
+ TREE_VEC_LENGTH (a), decl);
else
- error ("got %d template parameters for `%#T'",
- TREE_VEC_LENGTH (a), current);
+ error ("got %d template parameters for %q#T",
+ TREE_VEC_LENGTH (a), current);
error (" but %d required", TREE_VEC_LENGTH (t));
}
if (!TYPE_TEMPLATE_INFO (type))
{
- error ("`%T' is not a template type", type);
+ error ("%qT is not a template type", type);
return;
}
if (TREE_VEC_LENGTH (parms) != TREE_VEC_LENGTH (tmpl_parms))
{
- cp_error_at ("previous declaration `%D'", tmpl);
+ cp_error_at ("previous declaration %qD", tmpl);
error ("used %d template parameter%s instead of %d",
TREE_VEC_LENGTH (tmpl_parms),
TREE_VEC_LENGTH (tmpl_parms) == 1 ? "" : "s",
tree tmpl_default = TREE_PURPOSE (TREE_VEC_ELT (tmpl_parms, i));
tree parm_default = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
- if (TREE_CODE (tmpl_parm) != TREE_CODE (parm))
+ /* TMPL_PARM and PARM can be either TYPE_DECL, PARM_DECL, or
+ TEMPLATE_DECL. */
+ if (TREE_CODE (tmpl_parm) != TREE_CODE (parm)
+ || (TREE_CODE (tmpl_parm) != TYPE_DECL
+ && !same_type_p (TREE_TYPE (tmpl_parm), TREE_TYPE (parm))))
{
- cp_error_at ("template parameter `%#D'", tmpl_parm);
- error ("redeclared here as `%#D'", parm);
+ cp_error_at ("template parameter %q#D", tmpl_parm);
+ error ("redeclared here as %q#D", parm);
return;
}
A template-parameter may not be given default arguments
by two different declarations in the same scope. */
- error ("redefinition of default argument for `%#D'", parm);
+ error ("redefinition of default argument for %q#D", parm);
error ("%J original definition appeared here", tmpl_parm);
return;
}
will not return the initializer. Handle that special case
here. */
if (expr == const_expr
- && TREE_CODE (expr) == VAR_DECL
- && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (expr)
- && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (expr))
+ && DECL_INTEGRAL_CONSTANT_VAR_P (expr)
/* DECL_INITIAL can be NULL if we are processing a
variable initialized to an expression involving itself.
We know it is initialized to a constant -- but not what
if (TREE_CODE (e) != ADDR_EXPR)
{
bad_argument:
- error ("`%E' is not a valid template argument", expr);
+ error ("%qE is not a valid template argument", expr);
if (TYPE_PTR_P (expr_type))
{
if (TREE_CODE (TREE_TYPE (expr_type)) == FUNCTION_TYPE)
error ("it must be the address of an object with external linkage");
}
else if (TYPE_PTR_TO_MEMBER_P (expr_type))
- error ("it must be a pointer-to-member of the form `&X::Y'");
+ error ("it must be a pointer-to-member of the form %<&X::Y%>");
return NULL_TREE;
}
if (TREE_CODE (referent) == STRING_CST)
{
- error ("string literal %E is not a valid template argument because it is the address of an object with static linkage",
- referent);
+ error ("string literal %qE is not a valid template argument "
+ "because it is the address of an object with static linkage",
+ referent);
return NULL_TREE;
}
goto bad_argument;
else if (!DECL_EXTERNAL_LINKAGE_P (referent))
{
- error ("address of non-extern `%E' cannot be used as template argument", referent);
+ error ("address of non-extern %qE cannot be used as "
+ "template argument", referent);
return error_mark_node;
}
}
if (! TREE_CONSTANT (expr))
{
non_constant:
- error ("non-constant `%E' cannot be used as template argument",
- expr);
+ error ("non-constant %qE cannot be used as template argument", expr);
return NULL_TREE;
}
}
else
{
if (TYPE_P (expr))
- error ("type '%T' cannot be used as a value for a non-type "
+ error ("type %qT cannot be used as a value for a non-type "
"template-parameter", expr);
else if (DECL_P (expr))
- error ("invalid use of '%D' as a non-type template-argument", expr);
+ error ("invalid use of %qD as a non-type template-argument", expr);
else
- error ("invalid use of '%E' as a non-type template-argument", expr);
+ error ("invalid use of %qE as a non-type template-argument", expr);
return NULL_TREE;
}
switch (TREE_CODE (type))
{
+ HOST_WIDE_INT saved_processing_template_decl;
+
case INTEGER_TYPE:
case BOOLEAN_TYPE:
case ENUMERAL_TYPE:
return error_mark_node;
/* It's safe to call digest_init in this case; we know we're
- just converting one integral constant expression to another. */
+ just converting one integral constant expression to another.
+ */
+ saved_processing_template_decl = processing_template_decl;
+ processing_template_decl = 0;
expr = digest_init (type, expr, (tree*) 0);
+ processing_template_decl = saved_processing_template_decl;
if (TREE_CODE (expr) != INTEGER_CST)
/* Curiously, some TREE_CONSTANT integral expressions do not
expr = build_unary_op (ADDR_EXPR, fn, 0);
- my_friendly_assert (same_type_p (type, TREE_TYPE (expr)),
- 0);
+ gcc_assert (same_type_p (type, TREE_TYPE (expr)));
return expr;
}
else
if (TREE_CODE (expr) == NOP_EXPR
&& TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR)
STRIP_NOPS (expr);
- my_friendly_assert (TREE_CODE (expr) == ADDR_EXPR, 20000604);
+ gcc_assert (TREE_CODE (expr) == ADDR_EXPR);
expr = TREE_OPERAND (expr, 0);
expr_type = TREE_TYPE (expr);
}
goto bad_argument;
}
- my_friendly_assert (same_type_p (type_referred_to,
- TREE_TYPE (fn)),
- 0);
-
+ gcc_assert (same_type_p (type_referred_to, TREE_TYPE (fn)));
expr = fn;
}
else
case RECORD_TYPE:
{
- my_friendly_assert (TYPE_PTRMEMFUNC_P (type), 20010112);
+ gcc_assert (TYPE_PTRMEMFUNC_P (type));
/* For a non-type template-parameter of type pointer to member
function, no conversions apply. If the template-argument
default:
/* All non-type parameters must have one of these types. */
- abort ();
- break;
+ gcc_unreachable ();
}
return error_mark_node;
int nparms, nargs, i;
tree parm, arg;
- my_friendly_assert (TREE_CODE (parm_parms) == TREE_VEC, 0);
- my_friendly_assert (TREE_CODE (arg_parms) == TREE_VEC, 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);
case PARM_DECL:
/* The tsubst call is used to handle cases such as
- template <class T, template <T> class TT> class D;
+
+ 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 (!same_type_p
- (tsubst (TREE_TYPE (parm), outer_args, complain, in_decl),
- TREE_TYPE (arg)))
+ if (!dependent_type_p (TREE_TYPE (arg))
+ && !same_type_p
+ (tsubst (TREE_TYPE (parm), outer_args, complain, in_decl),
+ TREE_TYPE (arg)))
return 0;
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
return 1;
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);
+ 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),
{
if (complain & tf_error)
{
- error ("type/value mismatch at argument %d in template parameter list for `%D'",
- i + 1, in_decl);
+ error ("type/value mismatch at argument %d in template "
+ "parameter list for %qD",
+ i + 1, in_decl);
if (is_type)
- error (" expected a constant of type `%T', got `%T'",
- TREE_TYPE (parm),
- (is_tmpl_type ? DECL_NAME (arg) : arg));
+ error (" expected a constant of type %qT, got %qT",
+ TREE_TYPE (parm),
+ (is_tmpl_type ? DECL_NAME (arg) : arg));
else if (requires_tmpl_type)
- error (" expected a class template, got `%E'", arg);
+ error (" expected a class template, got %qE", arg);
else
- error (" expected a type, got `%E'", arg);
+ error (" expected a type, got %qE", arg);
}
}
return error_mark_node;
{
if (in_decl && (complain & tf_error))
{
- error ("type/value mismatch at argument %d in template parameter list for `%D'",
- i + 1, in_decl);
+ error ("type/value mismatch at argument %d in template "
+ "parameter list for %qD",
+ i + 1, in_decl);
if (is_tmpl_type)
- error (" expected a type, got `%T'", DECL_NAME (arg));
+ error (" expected a type, got %qT", DECL_NAME (arg));
else
- error (" expected a class template, got `%T'", arg);
+ error (" expected a class template, got %qT", arg);
}
return error_mark_node;
}
{
if (in_decl && (complain & tf_error))
{
- error ("type/value mismatch at argument %d in template parameter list for `%D'",
- i + 1, in_decl);
- error (" expected a template of type `%D', got `%D'", parm, arg);
+ error ("type/value mismatch at argument %d in "
+ "template parameter list for %qD",
+ i + 1, in_decl);
+ error (" expected a template of type %qD, got %qD",
+ parm, arg);
}
val = error_mark_node;
if (val == NULL_TREE)
val = error_mark_node;
else if (val == error_mark_node && (complain & tf_error))
- error ("could not convert template argument `%E' to `%T'",
- arg, t);
+ error ("could not convert template argument %qE to %qT", arg, t);
}
return val;
if (complain & tf_error)
{
error ("wrong number of template arguments (%d, should be %d)",
- nargs, nparms);
+ nargs, nparms);
if (in_decl)
- cp_error_at ("provided for `%D'", in_decl);
+ cp_error_at ("provided for %qD", in_decl);
}
return error_mark_node;
else
break;
- my_friendly_assert (arg, 20030727);
+ gcc_assert (arg);
if (arg == error_mark_node)
error ("template argument %d is invalid", i + 1);
else
ccat ('<');
nparms = TREE_VEC_LENGTH (parms);
arglist = INNERMOST_TEMPLATE_ARGS (arglist);
- my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268);
+ gcc_assert (nparms == TREE_VEC_LENGTH (arglist));
for (i = 0; i < nparms; i++)
{
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
{
/* The template may be defined in a namespace, or
may be a member template. */
- my_friendly_assert (TREE_CODE (context) == NAMESPACE_DECL
- || CLASS_TYPE_P (context),
- 980422);
- cat(decl_as_string (DECL_CONTEXT (arg), TFF_PLAIN_IDENTIFIER));
- cat("::");
+ gcc_assert (TREE_CODE (context) == NAMESPACE_DECL
+ || CLASS_TYPE_P (context));
+ cat (decl_as_string (DECL_CONTEXT (arg),
+ TFF_PLAIN_IDENTIFIER));
+ cat ("::");
}
cat (IDENTIFIER_POINTER (DECL_NAME (arg)));
}
continue;
}
else
- my_friendly_assert (TREE_CODE (parm) == PARM_DECL, 269);
+ gcc_assert (TREE_CODE (parm) == PARM_DECL);
/* No need to check arglist against parmlist here; we did that
in coerce_template_parms, called from lookup_template_class. */
if (fns == error_mark_node || arglist == error_mark_node)
return error_mark_node;
- my_friendly_assert (!arglist || TREE_CODE (arglist) == TREE_VEC, 20030726);
+ gcc_assert (!arglist || TREE_CODE (arglist) == TREE_VEC);
if (fns == NULL_TREE
|| TREE_CODE (fns) == FUNCTION_DECL)
{
return error_mark_node;
}
- my_friendly_assert (TREE_CODE (fns) == TEMPLATE_DECL
- || TREE_CODE (fns) == OVERLOAD
- || BASELINK_P (fns)
- || TREE_CODE (fns) == IDENTIFIER_NODE,
- 20020730);
+ gcc_assert (TREE_CODE (fns) == TEMPLATE_DECL
+ || TREE_CODE (fns) == OVERLOAD
+ || BASELINK_P (fns)
+ || TREE_CODE (fns) == IDENTIFIER_NODE);
if (BASELINK_P (fns))
{
- BASELINK_FUNCTIONS (fns) = build (TEMPLATE_ID_EXPR,
- unknown_type_node,
- BASELINK_FUNCTIONS (fns),
- arglist);
+ BASELINK_FUNCTIONS (fns) = build2 (TEMPLATE_ID_EXPR,
+ unknown_type_node,
+ BASELINK_FUNCTIONS (fns),
+ arglist);
return fns;
}
if (TREE_CODE (fns) == OVERLOAD || !type)
type = unknown_type_node;
- return build (TEMPLATE_ID_EXPR, type, fns, arglist);
+ return build2 (TEMPLATE_ID_EXPR, type, fns, arglist);
}
/* Within the scope of a template class S<T>, the name S gets bound
if (! template)
{
if (complain & tf_error)
- error ("`%T' is not a template", d1);
+ error ("%qT is not a template", d1);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
{
if (complain & tf_error)
{
- error ("non-template type `%T' used as a template", d1);
+ error ("non-template type %qT used as a template", d1);
if (in_decl)
- cp_error_at ("for template declaration `%D'", in_decl);
+ cp_error_at ("for template declaration %qD", in_decl);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
tree gen_tmpl;
tree type_decl;
tree found = NULL_TREE;
- tree *tp;
int arg_depth;
int parm_depth;
int is_partial_instantiation;
}
/* Now we should have enough arguments. */
- my_friendly_assert (parm_depth == arg_depth, 0);
+ gcc_assert (parm_depth == arg_depth);
/* From here on, we're only interested in the most general
template. */
if (found)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
- for (tp = &DECL_TEMPLATE_INSTANTIATIONS (template);
- *tp;
- tp = &TREE_CHAIN (*tp))
- if (comp_template_args (TREE_PURPOSE (*tp), arglist))
- {
- found = *tp;
-
- /* Use the move-to-front heuristic to speed up future
- searches. */
- *tp = TREE_CHAIN (*tp);
- TREE_CHAIN (found)
- = DECL_TEMPLATE_INSTANTIATIONS (template);
- DECL_TEMPLATE_INSTANTIATIONS (template) = found;
-
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_VALUE (found));
- }
+ /* If we already have this specialization, return it. */
+ found = retrieve_specialization (template, arglist,
+ /*class_specializations_p=*/false);
+ if (found)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
/* This type is a "partial instantiation" if any of the template
arguments still involve template parameters. Note that we set
|| TREE_CODE (t) == TEMPLATE_PARM_INDEX
|| TREE_CODE (t) == OVERLOAD
|| TREE_CODE (t) == BASELINK
- || TREE_CODE_CLASS (TREE_CODE (t)) == 'c')
+ || CONSTANT_CLASS_P (t))
dependent_p = (type_dependent_expression_p (t)
|| value_dependent_expression_p (t));
- else if (t == error_mark_node)
- dependent_p = false;
- else
- abort ();
+ else
+ {
+ gcc_assert (t == error_mark_node);
+ dependent_p = false;
+ }
+
processing_template_decl = saved_processing_template_decl;
return dependent_p;
return 0;
last_template_error_tick = tinst_level_tick;
- error ("template instantiation depth exceeds maximum of %d (use -ftemplate-depth-NN to increase the maximum) instantiating `%D'",
+ error ("template instantiation depth exceeds maximum of %d (use "
+ "-ftemplate-depth-NN to increase the maximum) instantiating %qD",
max_tinst_depth, d);
print_instantiation_context ();
return 0;
}
- new = make_node (TINST_LEVEL);
- SET_EXPR_LOCATION (new, input_location);
- TINST_DECL (new) = d;
+ new = make_tinst_level (d, input_location);
TREE_CHAIN (new) = current_tinst_level;
current_tinst_level = new;
/* Restore the filename and line number stashed away when we started
this instantiation. */
- input_location = EXPR_LOCATION (old);
- extract_interface_info ();
-
+ input_location = TINST_LOCATION (old);
current_tinst_level = TREE_CHAIN (old);
--tinst_depth;
++tinst_level_tick;
new_friend = tsubst (decl, args, tf_error | tf_warning, NULL_TREE);
tmpl = determine_specialization (template_id, new_friend,
&new_args,
- /*need_member_template=*/0);
+ /*need_member_template=*/0,
+ TREE_VEC_LENGTH (args));
new_friend = instantiate_template (tmpl, new_args, tf_error);
goto done;
}
/* Figure out which template is being instantiated. */
template = most_general_template (CLASSTYPE_TI_TEMPLATE (type));
- my_friendly_assert (TREE_CODE (template) == TEMPLATE_DECL, 279);
+ gcc_assert (TREE_CODE (template) == TEMPLATE_DECL);
/* Figure out which arguments are being used to do the
instantiation. */
if (t == error_mark_node)
{
const char *str = "candidates are:";
- error ("ambiguous class template instantiation for `%#T'", type);
+ error ("ambiguous class template instantiation for %q#T", type);
for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t;
t = TREE_CHAIN (t))
{
TYPE_HAS_CONST_INIT_REF (type) = TYPE_HAS_CONST_INIT_REF (pattern);
TYPE_HAS_DEFAULT_CONSTRUCTOR (type) = TYPE_HAS_DEFAULT_CONSTRUCTOR (pattern);
TYPE_HAS_CONVERSION (type) = TYPE_HAS_CONVERSION (pattern);
- TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (type)
- = TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (pattern);
- TYPE_USES_MULTIPLE_INHERITANCE (type)
- = TYPE_USES_MULTIPLE_INHERITANCE (pattern);
- TYPE_USES_VIRTUAL_BASECLASSES (type)
- = TYPE_USES_VIRTUAL_BASECLASSES (pattern);
TYPE_PACKED (type) = TYPE_PACKED (pattern);
TYPE_ALIGN (type) = TYPE_ALIGN (pattern);
TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (pattern);
pbinfo = TYPE_BINFO (pattern);
-#ifdef ENABLE_CHECKING
- if (DECL_CLASS_SCOPE_P (TYPE_MAIN_DECL (pattern))
- && ! COMPLETE_TYPE_P (TYPE_CONTEXT (type))
- && ! TYPE_BEING_DEFINED (TYPE_CONTEXT (type)))
- /* We should never instantiate a nested class before its enclosing
- class; we need to look up the nested class by name before we can
- instantiate it, and that lookup should instantiate the enclosing
- class. */
- abort ();
-#endif
+ /* We should never instantiate a nested class before its enclosing
+ class; we need to look up the nested class by name before we can
+ instantiate it, and that lookup should instantiate the enclosing
+ class. */
+ gcc_assert (!DECL_CLASS_SCOPE_P (TYPE_MAIN_DECL (pattern))
+ || COMPLETE_TYPE_P (TYPE_CONTEXT (type))
+ || TYPE_BEING_DEFINED (TYPE_CONTEXT (type)));
base_list = NULL_TREE;
- if (BINFO_BASE_BINFOS (pbinfo))
+ if (BINFO_N_BASE_BINFOS (pbinfo))
{
- tree pbases = BINFO_BASE_BINFOS (pbinfo);
- tree paccesses = BINFO_BASE_ACCESSES (pbinfo);
+ tree pbase_binfo;
tree context = TYPE_CONTEXT (type);
bool pop_p;
int i;
/* Substitute into each of the bases to determine the actual
basetypes. */
- for (i = 0; i < TREE_VEC_LENGTH (pbases); ++i)
+ for (i = 0; BINFO_BASE_ITERATE (pbinfo, i, pbase_binfo); i++)
{
tree base;
- tree access;
- tree pbase;
-
- pbase = TREE_VEC_ELT (pbases, i);
- access = TREE_VEC_ELT (paccesses, i);
+ tree access = BINFO_BASE_ACCESS (pbinfo, i);
/* Substitute to figure out the base class. */
- base = tsubst (BINFO_TYPE (pbase), args, tf_error, NULL_TREE);
+ base = tsubst (BINFO_TYPE (pbase_binfo), args, tf_error, NULL_TREE);
if (base == error_mark_node)
continue;
base_list = tree_cons (access, base, base_list);
- if (BINFO_VIRTUAL_P (pbase))
+ if (BINFO_VIRTUAL_P (pbase_binfo))
TREE_TYPE (base_list) = integer_type_node;
}
unreverse_member_declarations (type);
finish_struct_1 (type);
-
- /* Clear this now so repo_template_used is happy. */
TYPE_BEING_DEFINED (type) = 0;
- repo_template_used (type);
/* Now that the class is complete, instantiate default arguments for
any member functions. We don't do this earlier because the
pop_deferring_access_checks ();
pop_tinst_level ();
- if (TYPE_CONTAINS_VPTR_P (type))
+ /* The vtable for a template class can be emitted in any translation
+ unit in which the class is instantiated. When there is no key
+ method, however, finish_struct_1 will already have added TYPE to
+ the keyed_classes list. */
+ if (TYPE_CONTAINS_VPTR_P (type) && CLASSTYPE_KEY_METHOD (type))
keyed_classes = tree_cons (NULL_TREE, type, keyed_classes);
return type;
tree
tsubst_default_argument (tree fn, tree type, tree arg)
{
+ tree saved_class_ptr = NULL_TREE;
+ tree saved_class_ref = NULL_TREE;
+
/* This default argument came from a template. Instantiate the
default argument here, not in tsubst. In the case of
something like:
within the scope of FN. Since push_access_scope sets
current_function_decl, we must explicitly clear it here. */
current_function_decl = NULL_TREE;
+ /* The "this" pointer is not valid in a default argument. */
+ if (cfun)
+ {
+ saved_class_ptr = current_class_ptr;
+ cp_function_chain->x_current_class_ptr = NULL_TREE;
+ saved_class_ref = current_class_ref;
+ cp_function_chain->x_current_class_ref = NULL_TREE;
+ }
push_deferring_access_checks(dk_no_deferred);
arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
tf_error | tf_warning, NULL_TREE);
pop_deferring_access_checks();
+ /* Restore the "this" pointer. */
+ if (cfun)
+ {
+ cp_function_chain->x_current_class_ptr = saved_class_ptr;
+ cp_function_chain->x_current_class_ref = saved_class_ref;
+ }
+
pop_access_scope (fn);
/* Make sure the default argument is reasonable. */
/* tsubst_template_args doesn't copy the vector if
nothing changed. But, *something* should have
changed. */
- my_friendly_assert (full_args != tmpl_args, 0);
+ gcc_assert (full_args != tmpl_args);
- spec = retrieve_specialization (t, full_args);
+ spec = retrieve_specialization (t, full_args,
+ /*class_specializations_p=*/true);
if (spec != NULL_TREE)
{
r = spec;
like the old one, but points to this new template, rather
than the old one. */
r = copy_decl (t);
- my_friendly_assert (DECL_LANG_SPECIFIC (r) != 0, 0);
+ gcc_assert (DECL_LANG_SPECIFIC (r) != 0);
TREE_CHAIN (r) = NULL_TREE;
if (is_template_template_parm)
int parms_depth;
/* Nobody should be tsubst'ing into non-template functions. */
- my_friendly_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE, 0);
+ gcc_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE);
if (TREE_CODE (DECL_TI_TEMPLATE (t)) == TEMPLATE_DECL)
{
args, complain, in_decl);
/* Check to see if we already have this specialization. */
- spec = retrieve_specialization (gen_tmpl, argvec);
+ spec = retrieve_specialization (gen_tmpl, argvec,
+ /*class_specializations_p=*/false);
if (spec)
{
TREE_STATIC (r) = 0;
TREE_PUBLIC (r) = TREE_PUBLIC (t);
DECL_EXTERNAL (r) = 1;
- DECL_INTERFACE_KNOWN (r) = 0;
+ /* If this is an instantiation of a function with internal
+ linkage, we already know what object file linkage will be
+ assigned to the instantiation. */
+ DECL_INTERFACE_KNOWN (r) = !TREE_PUBLIC (r);
DECL_DEFER_OUTPUT (r) = 0;
TREE_CHAIN (r) = NULL_TREE;
DECL_PENDING_INLINE_INFO (r) = 0;
complain, in_decl);
TREE_CHAIN (r) = NULL_TREE;
if (VOID_TYPE_P (type))
- cp_error_at ("instantiation of `%D' as type `%T'", r, type);
+ cp_error_at ("instantiation of %qD as type %qT", r, type);
}
break;
tmpl = DECL_TI_TEMPLATE (t);
gen_tmpl = most_general_template (tmpl);
argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
- spec = retrieve_specialization (gen_tmpl, argvec);
+ spec = retrieve_specialization (gen_tmpl, argvec,
+ /*class_specializations_p=*/false);
}
else
spec = retrieve_local_specialization (t);
TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (r) == VAR_DECL && VOID_TYPE_P (type))
- cp_error_at ("instantiation of `%D' as type `%T'", r, type);
+ cp_error_at ("instantiation of %qD as type %qT", r, type);
/* Compute the size, alignment, etc. of R. */
layout_decl (r, 0);
}
break;
default:
- abort ();
+ gcc_unreachable ();
}
/* Restore the file and line information. */
{
if (complain & tf_error)
{
- error ("invalid parameter type `%T'", type);
+ error ("invalid parameter type %qT", type);
if (in_decl)
- cp_error_at ("in declaration `%D'", in_decl);
+ cp_error_at ("in declaration %qD", in_decl);
}
return error_mark_node;
}
tree fntype;
/* The TYPE_CONTEXT is not used for function/method types. */
- my_friendly_assert (TYPE_CONTEXT (t) == NULL_TREE, 0);
+ gcc_assert (TYPE_CONTEXT (t) == NULL_TREE);
/* Substitute the return type. */
return_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
-- Attempting to create "pointer to member of T" when T
is not a class type. */
if (complain & tf_error)
- error ("creating pointer to member function of non-class type `%T'",
+ error ("creating pointer to member function of non-class type %qT",
r);
return error_mark_node;
}
return fntype;
}
+/* FNTYPE is a FUNCTION_TYPE or METHOD_TYPE. Substitute the template
+ ARGS into that specification, and return the substituted
+ specification. If there is no specification, return NULL_TREE. */
+
+static tree
+tsubst_exception_specification (tree fntype,
+ tree args,
+ tsubst_flags_t complain,
+ tree in_decl)
+{
+ tree specs;
+ tree new_specs;
+
+ specs = TYPE_RAISES_EXCEPTIONS (fntype);
+ new_specs = NULL_TREE;
+ if (specs)
+ {
+ if (! TREE_VALUE (specs))
+ new_specs = specs;
+ else
+ while (specs)
+ {
+ tree spec;
+ spec = tsubst (TREE_VALUE (specs), args, complain, in_decl);
+ if (spec == error_mark_node)
+ return spec;
+ new_specs = add_exception_specifier (new_specs, spec, complain);
+ specs = TREE_CHAIN (specs);
+ }
+ }
+ return new_specs;
+}
+
/* Substitute into the PARMS of a call-declarator. */
static tree
|| t == integer_type_node
|| t == void_type_node
|| t == char_type_node
+ || t == unknown_type_node
|| TREE_CODE (t) == NAMESPACE_DECL)
return t;
else
type = TREE_TYPE (t);
- my_friendly_assert (type != unknown_type_node, 20030716);
+ gcc_assert (type != unknown_type_node);
if (type && TREE_CODE (t) != FUNCTION_DECL
&& TREE_CODE (t) != TYPENAME_TYPE
Attempting to create an array with a size that is
zero or negative. */
if (complain & tf_error)
- error ("creating array with size zero (`%E')", max);
+ error ("creating array with size zero (%qE)", max);
return error_mark_node;
}
int idx;
int level;
int levels;
+ tree arg = NULL_TREE;
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)
level = TEMPLATE_PARM_LEVEL (t);
}
- if (TREE_VEC_LENGTH (args) > 0)
- {
- tree arg = NULL_TREE;
-
- levels = TMPL_ARGS_DEPTH (args);
- if (level <= levels)
- arg = TMPL_ARG (args, level, idx);
+ levels = TMPL_ARGS_DEPTH (args);
+ if (level <= levels)
+ arg = TMPL_ARG (args, level, idx);
- if (arg == error_mark_node)
- return error_mark_node;
- else if (arg != NULL_TREE)
+ if (arg == error_mark_node)
+ return error_mark_node;
+ else if (arg != NULL_TREE)
+ {
+ if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
{
- if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
- {
- my_friendly_assert (TYPE_P (arg), 0);
- return cp_build_qualified_type_real
- (arg, cp_type_quals (arg) | cp_type_quals (t),
- complain | tf_ignore_bad_quals);
- }
- else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
- {
- /* We are processing a type constructed from
- a template template parameter. */
- tree argvec = tsubst (TYPE_TI_ARGS (t),
- args, complain, in_decl);
- if (argvec == error_mark_node)
- return error_mark_node;
+ gcc_assert (TYPE_P (arg));
+ return cp_build_qualified_type_real
+ (arg, cp_type_quals (arg) | cp_type_quals (t),
+ complain | tf_ignore_bad_quals);
+ }
+ else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
+ {
+ /* We are processing a type constructed from a
+ template template parameter. */
+ tree argvec = tsubst (TYPE_TI_ARGS (t),
+ args, complain, in_decl);
+ if (argvec == error_mark_node)
+ return error_mark_node;
- /* We can get a TEMPLATE_TEMPLATE_PARM here when
- we are resolving nested-types in the signature of
- a member function templates.
- Otherwise ARG is a TEMPLATE_DECL and is the real
- template to be instantiated. */
- if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
- arg = TYPE_NAME (arg);
-
- r = lookup_template_class (arg,
- argvec, in_decl,
- DECL_CONTEXT (arg),
- /*entering_scope=*/0,
- complain);
- return cp_build_qualified_type_real
- (r, TYPE_QUALS (t), complain);
- }
- else
- /* TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX. */
- return arg;
+ /* We can get a TEMPLATE_TEMPLATE_PARM here when we
+ are resolving nested-types in the signature of a
+ member function templates. Otherwise ARG is a
+ TEMPLATE_DECL and is the real template to be
+ instantiated. */
+ if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+ arg = TYPE_NAME (arg);
+
+ r = lookup_template_class (arg,
+ argvec, in_decl,
+ DECL_CONTEXT (arg),
+ /*entering_scope=*/0,
+ complain);
+ return cp_build_qualified_type_real
+ (r, TYPE_QUALS (t), complain);
}
+ else
+ /* TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX. */
+ return arg;
}
- else
- abort ();
if (level == 1)
/* This can happen during the attempted tsubst'ing in
break;
default:
- abort ();
+ gcc_unreachable ();
}
return r;
case TREE_BINFO:
/* We should never be tsubsting a binfo. */
- abort ();
+ gcc_unreachable ();
case TREE_VEC:
/* A vector of template arguments. */
- my_friendly_assert (!type, 20040628);
+ gcc_assert (!type);
return tsubst_template_args (t, args, complain, in_decl);
case POINTER_TYPE:
single bad template instantiation. */
if (complain & tf_error
#ifdef USE_MAPPED_LOCATION
- && last_loc != input_location)
+ && last_loc != input_location
#else
&& (last_loc.line != input_line
- || last_loc.file != input_filename))
+ || last_loc.file != input_filename)
#endif
+ )
{
if (TREE_CODE (type) == VOID_TYPE)
error ("forming reference to void");
else
- error ("forming %s to reference type `%T'",
- (code == POINTER_TYPE) ? "pointer" : "reference",
- type);
+ error ("forming %s to reference type %qT",
+ (code == POINTER_TYPE) ? "pointer" : "reference",
+ type);
last_loc = input_location;
}
-- Attempting to create "pointer to member of T" when T
is not a class type. */
if (complain & tf_error)
- error ("creating pointer to member of non-class type `%T'", r);
+ error ("creating pointer to member of non-class type %qT", r);
return error_mark_node;
}
if (TREE_CODE (type) == REFERENCE_TYPE)
{
if (complain & tf_error)
- error ("creating pointer to member reference type `%T'", type);
+ error ("creating pointer to member reference type %qT", type);
return error_mark_node;
}
- my_friendly_assert (TREE_CODE (type) != METHOD_TYPE, 20011231);
+ gcc_assert (TREE_CODE (type) != METHOD_TYPE);
if (TREE_CODE (type) == FUNCTION_TYPE)
{
/* This is really a method type. The cv qualifiers of the
case METHOD_TYPE:
{
tree fntype;
- tree raises;
-
+ tree specs;
fntype = tsubst_function_type (t, args, complain, in_decl);
if (fntype == error_mark_node)
return error_mark_node;
/* Substitute the exception specification. */
- raises = TYPE_RAISES_EXCEPTIONS (t);
- if (raises)
- {
- tree list = NULL_TREE;
-
- if (! TREE_VALUE (raises))
- list = raises;
- else
- for (; raises != NULL_TREE; raises = TREE_CHAIN (raises))
- {
- tree spec = TREE_VALUE (raises);
-
- spec = tsubst (spec, args, complain, in_decl);
- if (spec == error_mark_node)
- return spec;
- list = add_exception_specifier (list, spec, complain);
- }
- fntype = build_exception_variant (fntype, list);
- }
+ specs = tsubst_exception_specification (t, args, complain,
+ in_decl);
+ if (specs)
+ fntype = build_exception_variant (fntype, specs);
return fntype;
}
case ARRAY_TYPE:
|| TREE_CODE (type) == REFERENCE_TYPE)
{
if (complain & tf_error)
- error ("creating array of `%T'", type);
+ error ("creating array of %qT", type);
return error_mark_node;
}
if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type))
{
if (complain & tf_error)
- error ("creating array of `%T', which is an abstract class type",
+ error ("creating array of %qT, which is an abstract class type",
type);
return error_mark_node;
}
if (e1 == error_mark_node || e2 == error_mark_node)
return error_mark_node;
- return fold (build (TREE_CODE (t), TREE_TYPE (t), e1, e2));
+ return fold (build2 (TREE_CODE (t), TREE_TYPE (t), e1, e2));
}
case NEGATE_EXPR:
if (e == error_mark_node)
return error_mark_node;
- return fold (build (TREE_CODE (t), TREE_TYPE (t), e));
+ return fold (build1 (TREE_CODE (t), TREE_TYPE (t), e));
}
case TYPENAME_TYPE:
if (!IS_AGGR_TYPE (ctx))
{
if (complain & tf_error)
- error ("`%T' is not a class, struct, or union type",
- ctx);
+ error ("%qT is not a class, struct, or union type", ctx);
return error_mark_node;
}
else if (!uses_template_parms (ctx) && !TYPE_BEING_DEFINED (ctx))
case INDIRECT_REF:
case ADDR_EXPR:
case CALL_EXPR:
- abort ();
+ gcc_unreachable ();
case ARRAY_REF:
{
}
name = DECL_NAME (get_first_fn (fns));
baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
+
+ /* If lookup found a single function, mark it as used at this
+ point. (If it lookup found multiple functions the one selected
+ later by overload resolution will be marked as used at that
+ point.) */
+ if (BASELINK_P (baselink))
+ fns = BASELINK_FUNCTIONS (baselink);
+ if (!template_id_p && !really_overloaded_fn (fns))
+ mark_used (OVL_CURRENT (fns));
+
+ /* Add back the template arguments, if present. */
if (BASELINK_P (baselink) && template_id_p)
BASELINK_FUNCTIONS (baselink)
= build_nt (TEMPLATE_ID_EXPR,
BASELINK_FUNCTIONS (baselink),
template_args);
+
if (!object_type)
object_type = current_class_type;
return adjust_result_of_qualified_name_lookup (baselink,
bool is_template;
tree template_args;
- my_friendly_assert (TREE_CODE (qualified_id) == SCOPE_REF, 20030706);
+ gcc_assert (TREE_CODE (qualified_id) == SCOPE_REF);
/* Figure out what name to look up. */
name = TREE_OPERAND (qualified_id, 1);
{
if (complain & tf_error)
{
- error ("dependent-name `%E' is parsed as a non-type, but "
+ error ("dependent-name %qE is parsed as a non-type, but "
"instantiation yields a type", qualified_id);
- inform ("say `typename %E' if a type is meant", qualified_id);
+ inform ("say %<typename %E%> if a type is meant", qualified_id);
}
return error_mark_node;
}
}
if (DECL_P (expr))
- check_accessibility_of_qualified_id (expr, /*object_type=*/NULL_TREE,
- scope);
-
- /* Remember that there was a reference to this entity. */
- if (DECL_P (expr))
- mark_used (expr);
+ {
+ check_accessibility_of_qualified_id (expr, /*object_type=*/NULL_TREE,
+ scope);
+ /* Remember that there was a reference to this entity. */
+ mark_used (expr);
+ }
+
+ if (expr == error_mark_node || TREE_CODE (expr) == TREE_LIST)
+ {
+ if (complain & tf_error)
+ qualified_name_lookup_error (scope,
+ TREE_OPERAND (qualified_id, 1),
+ expr);
+ return error_mark_node;
+ }
if (is_template)
expr = lookup_template_function (expr, template_args);
if (expr == error_mark_node && complain & tf_error)
- qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1));
+ qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1),
+ expr);
else if (TYPE_P (scope))
{
expr = (adjust_result_of_qualified_name_lookup
{
case PARM_DECL:
r = retrieve_local_specialization (t);
- my_friendly_assert (r != NULL, 20020903);
+ gcc_assert (r != NULL);
mark_used (r);
return r;
/* We didn't find the name. That should never happen; if
name-lookup found it during preliminary parsing, we
should find it again here during instantiation. */
- abort ();
+ gcc_unreachable ();
}
return t;
if (ctx != DECL_CONTEXT (t))
return lookup_field (ctx, DECL_NAME (t), 0, false);
}
+
return t;
case VAR_DECL:
if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
return tsubst (TREE_TYPE (DECL_TEMPLATE_RESULT (t)),
args, complain, in_decl);
- else if (is_member_template (t))
+ else if (DECL_FUNCTION_TEMPLATE_P (t) && DECL_MEMBER_TEMPLATE_P (t))
return tsubst (t, args, complain, in_decl);
else if (DECL_CLASS_SCOPE_P (t)
&& uses_template_parms (DECL_CONTEXT (t)))
(code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl));
+ TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
return r;
}
/* We shouldn't have built any of these during initial template
generation. Instead, they should be built during instantiation
in response to the saved STMT_IS_FULL_EXPR_P setting. */
- abort ();
+ gcc_unreachable ();
default:
return t;
static tree
tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
- /* Live only within one (recursive) call to tsubst_expr. We use
- this to pass the statement expression node from the STMT_EXPR
- to the EXPR_STMT that is its result. */
- static tree cur_stmt_expr;
-
tree stmt, tmp;
if (t == NULL_TREE || t == error_mark_node)
args, complain, in_decl));
break;
- case STMT_EXPR:
- {
- tree old_stmt_expr = cur_stmt_expr;
- tree stmt_expr = begin_stmt_expr ();
-
- cur_stmt_expr = stmt_expr;
- tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl);
- stmt_expr = finish_stmt_expr (stmt_expr, false);
- cur_stmt_expr = old_stmt_expr;
-
- return stmt_expr;
- }
-
case EXPR_STMT:
tmp = tsubst_expr (EXPR_STMT_EXPR (t), args, complain, in_decl);
if (EXPR_STMT_STMT_EXPR_RESULT (t))
decl = lookup_qualified_name (scope, name,
/*is_type_p=*/false,
/*complain=*/false);
- if (decl == error_mark_node)
- qualified_name_lookup_error (scope, name);
+ if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
+ qualified_name_lookup_error (scope, name, decl);
else
do_local_using_decl (decl, scope, name);
}
break;
default:
- if (!STATEMENT_CODE_P (TREE_CODE (t)))
- return tsubst_copy_and_build (t, args, complain, in_decl,
- /*function_p=*/false);
- abort ();
+ gcc_assert (!STATEMENT_CODE_P (TREE_CODE (t)));
+
+ return tsubst_copy_and_build (t, args, complain, in_decl,
+ /*function_p=*/false);
}
return NULL_TREE;
template = lookup_template_function (template, targs);
if (object)
- return build (COMPONENT_REF, TREE_TYPE (template),
- object, template, NULL_TREE);
+ return build3 (COMPONENT_REF, TREE_TYPE (template),
+ object, template, NULL_TREE);
else
return template;
}
return cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t));
case MODOP_EXPR:
- return build_x_modify_expr
- (RECUR (TREE_OPERAND (t, 0)),
- TREE_CODE (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2)));
+ {
+ tree r = build_x_modify_expr
+ (RECUR (TREE_OPERAND (t, 0)),
+ TREE_CODE (TREE_OPERAND (t, 1)),
+ RECUR (TREE_OPERAND (t, 2)));
+ /* 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
+ set and must be copied. In the latter case,
+ build_x_modify_expr sets it and it must not be reset
+ here. */
+ if (TREE_NO_WARNING (t))
+ TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
+ return r;
+ }
case ARROW_EXPR:
op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
args);
else
{
- qualified_name_lookup_error (TREE_TYPE (object), tmpl);
+ qualified_name_lookup_error (TREE_TYPE (object), tmpl,
+ member);
return error_mark_node;
}
}
+ else if (TREE_CODE (member) == SCOPE_REF
+ && !CLASS_TYPE_P (TREE_OPERAND (member, 0))
+ && TREE_CODE (TREE_OPERAND (member, 0)) != NAMESPACE_DECL)
+ {
+ if (complain & tf_error)
+ {
+ if (TYPE_P (TREE_OPERAND (member, 0)))
+ error ("%qT is not a class or namespace",
+ TREE_OPERAND (member, 0));
+ else
+ error ("%qD is not a class or namespace",
+ TREE_OPERAND (member, 0));
+ }
+ return error_mark_node;
+ }
else if (TREE_CODE (member) == FIELD_DECL)
return finish_non_static_data_member (member, object, NULL_TREE);
tsubst_copy (TREE_TYPE (t), args, complain,
in_decl));
+ case OFFSETOF_EXPR:
+ return fold_offsetof (RECUR (TREE_OPERAND (t, 0)));
+
+ case STMT_EXPR:
+ {
+ tree old_stmt_expr = cur_stmt_expr;
+ tree stmt_expr = begin_stmt_expr ();
+
+ cur_stmt_expr = stmt_expr;
+ tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl);
+ stmt_expr = finish_stmt_expr (stmt_expr, false);
+ cur_stmt_expr = old_stmt_expr;
+
+ return stmt_expr;
+ }
+
default:
return tsubst_copy (t, args, complain, in_decl);
}
shall not be used to declare an entity with linkage.
This implies that names with no linkage cannot be used as
template arguments. */
- tree nt = no_linkage_check (t);
+ tree nt = no_linkage_check (t, /*relaxed_p=*/false);
if (nt)
{
if (!(complain & tf_error))
/*OK*/;
else if (TYPE_ANONYMOUS_P (nt))
- error ("`%T' uses anonymous type", t);
+ error ("%qT uses anonymous type", t);
else
- error ("`%T' uses local type `%T'", t, nt);
+ error ("%qT uses local type %qT", t, nt);
result = true;
}
/* In order to avoid all sorts of complications, we do not
else if (variably_modified_type_p (t, NULL_TREE))
{
if (complain & tf_error)
- error ("`%T' is a variably modified type", t);
+ error ("%qT is a variably modified type", t);
result = true;
}
}
&& !TREE_CONSTANT (t))
{
if (complain & tf_error)
- error ("integral expression `%E' is not constant", t);
+ error ("integral expression %qE is not constant", t);
result = true;
}
}
if (result && complain & tf_error)
- error (" trying to instantiate `%D'", tmpl);
+ error (" trying to instantiate %qD", tmpl);
return result;
}
if (tmpl == error_mark_node)
return error_mark_node;
- my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
+ gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
/* If this function is a clone, handle it specially. */
if (DECL_CLONED_FUNCTION_P (tmpl))
return error_mark_node;
/* Look for the clone. */
- for (clone = TREE_CHAIN (spec);
- clone && DECL_CLONED_FUNCTION_P (clone);
- clone = TREE_CHAIN (clone))
+ FOR_EACH_CLONE (clone, spec)
if (DECL_NAME (clone) == DECL_NAME (tmpl))
return clone;
/* We should always have found the clone by now. */
- abort ();
+ gcc_unreachable ();
return NULL_TREE;
}
/* Check to see if we already have this specialization. */
- spec = retrieve_specialization (tmpl, targ_ptr);
+ spec = retrieve_specialization (tmpl, targ_ptr,
+ /*class_specializations_p=*/false);
if (spec != NULL_TREE)
return spec;
targ_ptr);
/* Check to see if we already have this specialization. */
- spec = retrieve_specialization (gen_tmpl, targ_ptr);
+ spec = retrieve_specialization (gen_tmpl, targ_ptr,
+ /*class_specializations_p=*/false);
if (spec != NULL_TREE)
return spec;
}
tree fntype;
int result;
- my_friendly_assert (TREE_CODE (fn) == TEMPLATE_DECL, 0);
+ gcc_assert (TREE_CODE (fn) == TEMPLATE_DECL);
fntype = TREE_TYPE (fn);
if (explicit_targs)
}
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (TREE_CODE (*parm) != REFERENCE_TYPE)
tree parms, args;
int len;
- my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
- my_friendly_assert (xparms == NULL_TREE
- || TREE_CODE (xparms) == TREE_LIST, 290);
- my_friendly_assert (!xargs || TREE_CODE (xargs) == TREE_LIST, 291);
- my_friendly_assert (ntparms > 0, 292);
+ gcc_assert (TREE_CODE (tparms) == TREE_VEC);
+ gcc_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST);
+ gcc_assert (!xargs || TREE_CODE (xargs) == TREE_LIST);
+ gcc_assert (ntparms > 0);
switch (strict)
{
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (xlen == 0)
if (!TYPE_P (arg))
{
- my_friendly_assert (TREE_TYPE (arg) != NULL_TREE, 293);
+ gcc_assert (TREE_TYPE (arg) != NULL_TREE);
if (type_unknown_p (arg))
{
/* [temp.deduct.type] A template-argument can be deduced from
}
}
}
- else if (TREE_CODE (arg) == OVERLOAD
- || TREE_CODE (arg) == FUNCTION_DECL)
+ else
{
+ gcc_assert (TREE_CODE (arg) == OVERLOAD
+ || TREE_CODE (arg) == FUNCTION_DECL);
+
for (; arg; arg = OVL_NEXT (arg))
good += try_one_overload (tparms, targs, tempargs, parm,
TREE_TYPE (OVL_CURRENT (arg)),
strict, sub_strict, addr_p);
}
- else
- abort ();
/* [temp.deduct.type] A template-argument can be deduced from a pointer
to function or pointer to member function argument if the set of
return arg;
}
-/* Subroutine of get_template_base. RVAL, if non-NULL, is a base we
- have already discovered to be satisfactory. ARG_BINFO is the binfo
- for the base class of ARG that we are currently examining. */
+/* Given a template type PARM and a class type ARG, find the unique
+ base type in ARG that is an instance of PARM. We do not examine
+ ARG itself; only its base-classes. If there is not exactly one
+ appropriate base class, return NULL_TREE. PARM may be the type of
+ a partial specialization, as well as a plain template type. Used
+ by unify. */
static tree
-get_template_base_recursive (tree tparms,
- tree targs,
- tree parm,
- tree arg_binfo,
- tree rval,
- int flags)
+get_template_base (tree tparms, tree targs, tree parm, tree arg)
{
- tree binfos;
- int i, n_baselinks;
- tree arg = BINFO_TYPE (arg_binfo);
-
- if (!(flags & GTB_IGNORE_TYPE))
- {
- tree r = try_class_unification (tparms, targs,
- parm, arg);
-
- /* If there is more than one satisfactory baseclass, then:
+ tree rval = NULL_TREE;
+ tree binfo;
- [temp.deduct.call]
-
- If they yield more than one possible deduced A, the type
- deduction fails.
-
- applies. */
- if (r && rval && !same_type_p (r, rval))
- return error_mark_node;
- else if (r)
- rval = r;
- }
-
- binfos = BINFO_BASE_BINFOS (arg_binfo);
- n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ gcc_assert (IS_AGGR_TYPE_CODE (TREE_CODE (arg)));
+
+ binfo = TYPE_BINFO (complete_type (arg));
+ if (!binfo)
+ /* The type could not be completed. */
+ return NULL_TREE;
- /* Process base types. */
- for (i = 0; i < n_baselinks; i++)
+ /* Walk in inheritance graph order. The search order is not
+ important, and this avoids multiple walks of virtual bases. */
+ for (binfo = TREE_CHAIN (binfo); binfo; binfo = TREE_CHAIN (binfo))
{
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- int this_virtual;
-
- /* Skip this base, if we've already seen it. */
- if (BINFO_MARKED (base_binfo))
- continue;
+ tree r = try_class_unification (tparms, targs, parm, BINFO_TYPE (binfo));
- this_virtual =
- (flags & GTB_VIA_VIRTUAL) || BINFO_VIRTUAL_P (base_binfo);
-
- /* When searching for a non-virtual, we cannot mark virtually
- found binfos. */
- if (! this_virtual)
- BINFO_MARKED (base_binfo) = 1;
-
- rval = get_template_base_recursive (tparms, targs,
- parm,
- base_binfo,
- rval,
- GTB_VIA_VIRTUAL * this_virtual);
-
- /* If we discovered more than one matching base class, we can
- stop now. */
- if (rval == error_mark_node)
- return error_mark_node;
- }
-
- return rval;
-}
-
-/* Given a template type PARM and a class type ARG, find the unique
- base type in ARG that is an instance of PARM. We do not examine
- ARG itself; only its base-classes. If there is no appropriate base
- class, return NULL_TREE. If there is more than one, return
- error_mark_node. PARM may be the type of a partial specialization,
- as well as a plain template type. Used by unify. */
+ if (r)
+ {
+ /* If there is more than one satisfactory baseclass, then:
-static tree
-get_template_base (tree tparms, tree targs, tree parm, tree arg)
-{
- tree rval;
- tree arg_binfo;
+ [temp.deduct.call]
- my_friendly_assert (IS_AGGR_TYPE_CODE (TREE_CODE (arg)), 92);
-
- arg_binfo = TYPE_BINFO (complete_type (arg));
- rval = get_template_base_recursive (tparms, targs,
- parm, arg_binfo,
- NULL_TREE,
- GTB_IGNORE_TYPE);
+ If they yield more than one possible deduced A, the type
+ deduction fails.
- /* Since get_template_base_recursive marks the bases classes, we
- must unmark them here. */
- dfs_walk (arg_binfo, dfs_unmark, markedp, 0);
+ applies. */
+ if (rval && !same_type_p (r, rval))
+ return NULL_TREE;
+
+ rval = r;
+ }
+ }
return rval;
}
return TEMPLATE_PARM_LEVEL (DECL_INITIAL (decl));
default:
- abort ();
- return 0;
+ gcc_unreachable ();
}
+ return 0;
}
/* Decide whether ARG can be unified with PARM, considering only the
qualified at this point.
UNIFY_ALLOW_OUTER_LESS_CV_QUAL:
This is the outermost level of a deduction, and PARM can be less CV
- qualified at this point.
- UNIFY_ALLOW_MAX_CORRECTION:
- This is an INTEGER_TYPE's maximum value. Used if the range may
- have been derived from a size specification, such as an array size.
- If the size was given by a nontype template parameter N, the maximum
- value will have the form N-1. The flag says that we can (and indeed
- must) unify N with (ARG + 1), an exception to the normal rules on
- folding PARM. */
+ qualified at this point. */
static int
unify (tree tparms, tree targs, tree parm, tree arg, int strict)
strict &= ~UNIFY_ALLOW_DERIVED;
strict &= ~UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
strict &= ~UNIFY_ALLOW_OUTER_LESS_CV_QUAL;
- strict &= ~UNIFY_ALLOW_MAX_CORRECTION;
switch (TREE_CODE (parm))
{
{
tree parmtmpl = TYPE_TI_TEMPLATE (parm);
tree parmvec = TYPE_TI_ARGS (parm);
- tree argvec = TYPE_TI_ARGS (arg);
+ tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
tree argtmplvec
= DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (arg));
int i;
for (i = 0; i < TREE_VEC_LENGTH (parmvec); ++i)
{
- tree t = TREE_VEC_ELT (parmvec, i);
-
- if (unify (tparms, targs, t,
+ if (unify (tparms, targs,
+ TREE_VEC_ELT (parmvec, i),
TREE_VEC_ELT (argvec, i),
UNIFY_ALLOW_NONE))
return 1;
else if ((strict & UNIFY_ALLOW_INTEGER)
&& (TREE_CODE (tparm) == INTEGER_TYPE
|| TREE_CODE (tparm) == BOOLEAN_TYPE))
- /* OK */;
+ /* Convert the ARG to the type of PARM; the deduced non-type
+ template argument must exactly match the types of the
+ corresponding parameter. */
+ arg = fold (build_nop (TREE_TYPE (parm), arg));
else if (uses_template_parms (tparm))
/* We haven't deduced the type of this parameter yet. Try again
later. */
if ((TYPE_DOMAIN (parm) == NULL_TREE)
!= (TYPE_DOMAIN (arg) == NULL_TREE))
return 1;
- if (TYPE_DOMAIN (parm) != NULL_TREE
- && unify (tparms, targs, TYPE_DOMAIN (parm),
- TYPE_DOMAIN (arg), UNIFY_ALLOW_NONE) != 0)
- return 1;
+ if (TYPE_DOMAIN (parm) != NULL_TREE)
+ {
+ tree parm_max;
+ tree arg_max;
+
+ parm_max = TYPE_MAX_VALUE (TYPE_DOMAIN (parm));
+ arg_max = TYPE_MAX_VALUE (TYPE_DOMAIN (arg));
+
+ /* Our representation of array types uses "N - 1" as the
+ TYPE_MAX_VALUE for an array with "N" elements, if "N" is
+ not an integer constant. */
+ if (TREE_CODE (parm_max) == MINUS_EXPR)
+ {
+ arg_max = fold (build2 (PLUS_EXPR,
+ integer_type_node,
+ arg_max,
+ TREE_OPERAND (parm_max, 1)));
+ parm_max = TREE_OPERAND (parm_max, 0);
+ }
+
+ if (unify (tparms, targs, parm_max, arg_max, UNIFY_ALLOW_INTEGER))
+ return 1;
+ }
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
strict & UNIFY_ALLOW_MORE_CV_QUAL);
case VECTOR_TYPE:
case INTEGER_TYPE:
case BOOLEAN_TYPE:
+ case ENUMERAL_TYPE:
case VOID_TYPE:
if (TREE_CODE (arg) != TREE_CODE (parm))
return 1;
-
- if (TREE_CODE (parm) == INTEGER_TYPE
- && TREE_CODE (TYPE_MAX_VALUE (parm)) != INTEGER_CST)
- {
- if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg)
- && unify (tparms, targs, TYPE_MIN_VALUE (parm),
- TYPE_MIN_VALUE (arg), UNIFY_ALLOW_INTEGER))
- return 1;
- if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg)
- && unify (tparms, targs, TYPE_MAX_VALUE (parm),
- TYPE_MAX_VALUE (arg),
- UNIFY_ALLOW_INTEGER | UNIFY_ALLOW_MAX_CORRECTION))
- return 1;
- }
+
/* We have already checked cv-qualification at the top of the
function. */
- else if (!same_type_ignoring_top_level_qualifiers_p (arg, parm))
+ if (!same_type_ignoring_top_level_qualifiers_p (arg, parm))
return 1;
/* As far as unification is concerned, this wins. Later checks
a class of the form template-id, A can be a
pointer to a derived class pointed to by the
deduced A. */
- t = get_template_base (tparms, targs,
- parm, arg);
+ t = get_template_base (tparms, targs, parm, arg);
- if (! t || t == error_mark_node)
+ if (!t)
return 1;
}
}
/* Matched cases are handled by the ARG == PARM test above. */
return 1;
- case MINUS_EXPR:
- if (tree_int_cst_equal (TREE_OPERAND (parm, 1), integer_one_node)
- && (strict_in & UNIFY_ALLOW_MAX_CORRECTION))
- {
- /* We handle this case specially, since it comes up with
- arrays. In particular, something like:
-
- template <int N> void f(int (&x)[N]);
-
- Here, we are trying to unify the range type, which
- looks like [0 ... (N - 1)]. */
- tree t, t1, t2;
- t1 = TREE_OPERAND (parm, 0);
- t2 = TREE_OPERAND (parm, 1);
-
- t = fold (build (PLUS_EXPR, integer_type_node, arg, t2));
-
- return unify (tparms, targs, t1, t, strict);
- }
- /* Else fall through. */
-
default:
- if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (parm))))
- {
-
- /* We're looking at an expression. This can happen with
- something like:
+ gcc_assert (EXPR_P (parm));
+
+ /* We must be looking at an expression. This can happen with
+ something like:
- template <int I>
- void foo(S<I>, S<I + 2>);
+ template <int I>
+ void foo(S<I>, S<I + 2>);
- This is a "nondeduced context":
+ This is a "nondeduced context":
- [deduct.type]
+ [deduct.type]
- The nondeduced contexts are:
+ The nondeduced contexts are:
- --A type that is a template-id in which one or more of
- the template-arguments is an expression that references
- a template-parameter.
+ --A type that is a template-id in which one or more of
+ the template-arguments is an expression that references
+ a template-parameter.
- In these cases, we assume deduction succeeded, but don't
- actually infer any unifications. */
+ In these cases, we assume deduction succeeded, but don't
+ actually infer any unifications. */
- if (!uses_template_parms (parm)
- && !template_args_equal (parm, arg))
- return 1;
- else
- return 0;
- }
+ if (!uses_template_parms (parm)
+ && !template_args_equal (parm, arg))
+ return 1;
else
- sorry ("use of `%s' in template type unification",
- tree_code_name [(int) TREE_CODE (parm)]);
-
- return 1;
+ return 0;
}
}
\f
+/* Note that DECL can be defined in this translation unit, if
+ required. */
+
+static void
+mark_definable (tree decl)
+{
+ tree clone;
+ DECL_NOT_REALLY_EXTERN (decl) = 1;
+ FOR_EACH_CLONE (clone, decl)
+ DECL_NOT_REALLY_EXTERN (clone) = 1;
+}
+
/* Called if RESULT is explicitly instantiated, or is a member of an
- explicitly instantiated class, or if using -frepo and the
- instantiation of RESULT has been assigned to this file. */
+ explicitly instantiated class. */
void
mark_decl_instantiated (tree result, int extern_p)
/* This might have been set by an earlier implicit instantiation. */
DECL_COMDAT (result) = 0;
- if (! extern_p)
+ if (extern_p)
+ DECL_NOT_REALLY_EXTERN (result) = 0;
+ else
{
- DECL_INTERFACE_KNOWN (result) = 1;
- DECL_NOT_REALLY_EXTERN (result) = 1;
-
+ mark_definable (result);
/* Always make artificials weak. */
if (DECL_ARTIFICIAL (result) && flag_weak)
comdat_linkage (result);
else if (TREE_PUBLIC (result))
maybe_make_one_only (result);
}
+
+ /* If EXTERN_P, then this function will not be emitted -- unless
+ followed by an explicit instantiation, at which point its linkage
+ will be adjusted. If !EXTERN_P, then this function will be
+ emitted here. In neither circumstance do we want
+ import_export_decl to adjust the linkage. */
+ DECL_INTERFACE_KNOWN (result) = 1;
}
/* Given two function templates PAT1 and PAT2, return:
return;
else if (! DECL_LANG_SPECIFIC (decl))
{
- error ("explicit instantiation of non-template `%#D'", decl);
+ error ("explicit instantiation of non-template %q#D", decl);
return;
}
else if (TREE_CODE (decl) == VAR_DECL)
result = lookup_field (DECL_CONTEXT (decl), DECL_NAME (decl), 0, false);
if (!result || TREE_CODE (result) != VAR_DECL)
{
- error ("no matching template for `%D' found", decl);
+ error ("no matching template for %qD found", decl);
return;
}
}
else if (TREE_CODE (decl) != FUNCTION_DECL)
{
- error ("explicit instantiation of `%#D'", decl);
+ error ("explicit instantiation of %q#D", decl);
return;
}
else
No program shall explicitly instantiate any template more
than once.
- We check DECL_INTERFACE_KNOWN so as not to complain when the first
- instantiation was `extern' and the second is not, and EXTERN_P for
- the opposite case. If -frepo, chances are we already got marked
- as an explicit instantiation because of the repo file. */
- if (DECL_INTERFACE_KNOWN (result) && !extern_p && !flag_use_repository)
- pedwarn ("duplicate explicit instantiation of `%#D'", result);
-
- /* If we've already instantiated the template, just return now. */
- if (DECL_INTERFACE_KNOWN (result))
+ We check DECL_NOT_REALLY_EXTERN so as not to complain when
+ 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);
+ /* If an "extern" explicit instantiation follows an ordinary
+ explicit instantiation, the template is instantiated. */
+ if (extern_p)
return;
}
else if (!DECL_IMPLICIT_INSTANTIATION (result))
{
- error ("no matching template for `%D' found", result);
+ error ("no matching template for %qD found", result);
return;
}
else if (!DECL_TEMPLATE_INFO (result))
{
- pedwarn ("explicit instantiation of non-template `%#D'", result);
+ pedwarn ("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 instantiations");
+ pedwarn ("ISO C++ forbids the use of %<extern%> on explicit "
+ "instantiations");
extern_p = 1;
}
else
- error ("storage class `%D' applied to template instantiation",
- storage);
+ error ("storage class %qD applied to template instantiation", storage);
mark_decl_instantiated (result, extern_p);
- repo_template_instantiated (result, extern_p);
if (! extern_p)
instantiate_decl (result, /*defer_ok=*/1, /*undefined_ok=*/0);
}
instantiate_class_member (tree decl, int extern_p)
{
mark_decl_instantiated (decl, extern_p);
- repo_template_instantiated (decl, extern_p);
if (! extern_p)
instantiate_decl (decl, /*defer_ok=*/1, /* undefined_ok=*/1);
}
if (! CLASS_TYPE_P (t) || ! CLASSTYPE_TEMPLATE_INFO (t))
{
- error ("explicit instantiation of non-template type `%T'", t);
+ error ("explicit instantiation of non-template type %qT", t);
return;
}
if (!COMPLETE_TYPE_P (t))
{
if (complain & tf_error)
- error ("explicit instantiation of `%#T' before definition of template",
- t);
+ error ("explicit instantiation of %q#T before definition of template",
+ t);
return;
}
static_p = 1;
else
{
- error ("storage class `%D' applied to template instantiation",
- storage);
+ error ("storage class %qD applied to template instantiation",
+ storage);
extern_p = 0;
}
}
If PREVIOUS_INSTANTIATION_EXTERN_P, then the first explicit
instantiation was `extern'. If EXTERN_P then the second is.
- If -frepo, chances are we already got marked as an explicit
- instantiation because of the repo file. All these cases are
- OK. */
-
+ These cases are OK. */
previous_instantiation_extern_p = CLASSTYPE_INTERFACE_ONLY (t);
if (!previous_instantiation_extern_p && !extern_p
- && !flag_use_repository
&& (complain & tf_error))
- pedwarn ("duplicate explicit instantiation of `%#T'", t);
+ pedwarn ("duplicate explicit instantiation of %q#T", t);
/* If we've already instantiated the template, just return now. */
if (!CLASSTYPE_INTERFACE_ONLY (t))
}
mark_class_instantiated (t, extern_p);
- repo_template_instantiated (t, extern_p);
if (nomem_p)
return;
static void
regenerate_decl_from_template (tree decl, tree tmpl)
{
- /* The most general version of TMPL. */
- tree gen_tmpl;
/* The arguments used to instantiate DECL, from the most general
template. */
tree args;
tree code_pattern;
- tree new_decl;
- bool unregistered;
args = DECL_TI_ARGS (decl);
code_pattern = DECL_TEMPLATE_RESULT (tmpl);
- /* Unregister the specialization so that when we tsubst we will not
- just return DECL. We don't have to unregister DECL from TMPL
- because if would only be registered there if it were a partial
- instantiation of a specialization, which it isn't: it's a full
- instantiation. */
- gen_tmpl = most_general_template (tmpl);
- unregistered = reregister_specialization (decl, gen_tmpl,
- /*new_spec=*/NULL_TREE);
-
- /* If the DECL was not unregistered then something peculiar is
- happening: we created a specialization but did not call
- register_specialization for it. */
- my_friendly_assert (unregistered, 0);
-
/* Make sure that we can see identifiers, and compute access
correctly. */
push_access_scope (decl);
- /* Do the substitution to get the new declaration. */
- new_decl = tsubst (code_pattern, args, tf_error, NULL_TREE);
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ tree decl_parm;
+ tree pattern_parm;
+ tree specs;
+ int args_depth;
+ int parms_depth;
+
+ args_depth = TMPL_ARGS_DEPTH (args);
+ parms_depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
+ if (args_depth > parms_depth)
+ args = get_innermost_template_args (args, parms_depth);
+
+ specs = tsubst_exception_specification (TREE_TYPE (code_pattern),
+ args, tf_error, NULL_TREE);
+ if (specs)
+ TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl),
+ specs);
+
+ /* Merge parameter declarations. */
+ decl_parm = skip_artificial_parms_for (decl,
+ DECL_ARGUMENTS (decl));
+ pattern_parm
+ = skip_artificial_parms_for (code_pattern,
+ DECL_ARGUMENTS (code_pattern));
+ while (decl_parm)
+ {
+ tree parm_type;
+
+ if (DECL_NAME (decl_parm) != DECL_NAME (pattern_parm))
+ DECL_NAME (decl_parm) = DECL_NAME (pattern_parm);
+ parm_type = tsubst (TREE_TYPE (pattern_parm), args, tf_error,
+ NULL_TREE);
+ if (!same_type_p (TREE_TYPE (decl_parm), parm_type))
+ TREE_TYPE (decl_parm) = parm_type;
+ decl_parm = TREE_CHAIN (decl_parm);
+ pattern_parm = TREE_CHAIN (pattern_parm);
+ }
- if (TREE_CODE (decl) == VAR_DECL)
+ /* Merge additional specifiers from the CODE_PATTERN. */
+ if (DECL_DECLARED_INLINE_P (code_pattern)
+ && !DECL_DECLARED_INLINE_P (decl))
+ DECL_DECLARED_INLINE_P (decl) = 1;
+ if (DECL_INLINE (code_pattern) && !DECL_INLINE (decl))
+ DECL_INLINE (decl) = 1;
+ }
+ else if (TREE_CODE (decl) == VAR_DECL)
{
- /* Set up DECL_INITIAL, since tsubst doesn't. */
- if (!DECL_INITIALIZED_IN_CLASS_P (decl))
- DECL_INITIAL (new_decl) =
+ if (!DECL_INITIALIZED_IN_CLASS_P (decl)
+ && DECL_INITIAL (code_pattern))
+ DECL_INITIAL (decl) =
tsubst_expr (DECL_INITIAL (code_pattern), args,
tf_error, DECL_TI_TEMPLATE (decl));
}
- else if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- /* Convince duplicate_decls to use the DECL_ARGUMENTS from the
- new decl. */
- DECL_INITIAL (new_decl) = error_mark_node;
- /* And don't complain about a duplicate definition. */
- DECL_INITIAL (decl) = NULL_TREE;
- }
+ else
+ gcc_unreachable ();
pop_access_scope (decl);
-
- /* The immediate parent of the new template is still whatever it was
- before, even though tsubst sets DECL_TI_TEMPLATE up as the most
- general template. We also reset the DECL_ASSEMBLER_NAME since
- tsubst always calculates the name as if the function in question
- were really a template instance, and sometimes, with friend
- functions, this is not so. See tsubst_friend_function for
- details. */
- DECL_TI_TEMPLATE (new_decl) = DECL_TI_TEMPLATE (decl);
- COPY_DECL_ASSEMBLER_NAME (decl, new_decl);
- COPY_DECL_RTL (decl, new_decl);
- DECL_USE_TEMPLATE (new_decl) = DECL_USE_TEMPLATE (decl);
-
- /* Call duplicate decls to merge the old and new declarations. */
- duplicate_decls (new_decl, decl);
-
- /* Now, re-register the specialization. */
- register_specialization (decl, gen_tmpl, args);
}
/* Return the TEMPLATE_DECL into which DECL_TI_ARGS(DECL) should be
cannot restructure the loop to just keep going until we find
a template with a definition, since that might go too far if
a specialization was declared, but not defined. */
- my_friendly_assert (!(TREE_CODE (decl) == VAR_DECL
- && !DECL_IN_AGGR_P (DECL_TEMPLATE_RESULT (tmpl))),
- 0);
+ gcc_assert (TREE_CODE (decl) != VAR_DECL
+ || DECL_IN_AGGR_P (DECL_TEMPLATE_RESULT (tmpl)));
/* Fetch the more general template. */
tmpl = DECL_TI_TEMPLATE (tmpl);
/* This function should only be used to instantiate templates for
functions and static member variables. */
- my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL
- || TREE_CODE (d) == VAR_DECL, 0);
+ gcc_assert (TREE_CODE (d) == FUNCTION_DECL
+ || TREE_CODE (d) == VAR_DECL);
/* Variables are never deferred; if instantiation is required, they
are instantiated right away. That allows for better code in the
DECL_TEMPLATE_SPECIALIZATION. */
gen_tmpl = most_general_template (tmpl);
gen_args = DECL_TI_ARGS (d);
- spec = retrieve_specialization (gen_tmpl, gen_args);
+ spec = retrieve_specialization (gen_tmpl, gen_args,
+ /*class_specializations_p=*/false);
if (spec != NULL_TREE && DECL_TEMPLATE_SPECIALIZATION (spec))
return spec;
pattern_defined = (DECL_SAVED_TREE (code_pattern) != NULL_TREE);
else
pattern_defined = ! DECL_IN_AGGR_P (code_pattern);
+ /* Unless an explicit instantiation directive has already determined
+ the linkage of D, remember that a definition is available for
+ this entity. */
+ if (pattern_defined
+ && !DECL_INTERFACE_KNOWN (d)
+ && !DECL_NOT_REALLY_EXTERN (d))
+ mark_definable (d);
input_location = DECL_SOURCE_LOCATION (d);
- if (pattern_defined)
+ if (! pattern_defined && DECL_EXPLICIT_INSTANTIATION (d) && undefined_ok)
{
- /* Let the repository code that this template definition is
- available.
-
- The repository doesn't need to know about cloned functions
- because they never actually show up in the object file. It
- does need to know about the clones; those are the symbols
- that the linker will be emitting error messages about. */
- if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (d)
- || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (d))
- {
- tree t;
-
- for (t = TREE_CHAIN (d);
- t && DECL_CLONED_FUNCTION_P (t);
- t = TREE_CHAIN (t))
- repo_template_used (t);
- }
- else
- repo_template_used (d);
-
- if (at_eof)
- import_export_decl (d);
+ DECL_NOT_REALLY_EXTERN (d) = 0;
+ SET_DECL_IMPLICIT_INSTANTIATION (d);
}
- if (! pattern_defined && DECL_EXPLICIT_INSTANTIATION (d) && undefined_ok)
- SET_DECL_IMPLICIT_INSTANTIATION (d);
-
if (!defer_ok)
{
/* Recheck the substitutions to obtain any warning messages
pop_access_scope (d);
}
- if (TREE_CODE (d) == VAR_DECL && DECL_INITIALIZED_IN_CLASS_P (d)
- && DECL_INITIAL (d) == NULL_TREE)
- /* We should have set up DECL_INITIAL in instantiate_class_template. */
- abort ();
- /* Reject all external templates except inline functions. */
- else if (DECL_INTERFACE_KNOWN (d)
- && ! DECL_NOT_REALLY_EXTERN (d)
- && ! (TREE_CODE (d) == FUNCTION_DECL
- && DECL_INLINE (d)))
+ /* We should have set up DECL_INITIAL in instantiate_class_template
+ for in-class definitions of static data members. */
+ gcc_assert (!(TREE_CODE (d) == VAR_DECL
+ && DECL_INITIALIZED_IN_CLASS_P (d)
+ && DECL_INITIAL (d) == NULL_TREE));
+
+ /* Do not instantiate templates that we know will be defined
+ elsewhere. */
+ if (DECL_INTERFACE_KNOWN (d)
+ && DECL_REALLY_EXTERN (d)
+ && ! (TREE_CODE (d) == FUNCTION_DECL
+ && DECL_INLINE (d)))
goto out;
/* Defer all other templates, unless we have been explicitly
forbidden from doing so. We restore the source position here
shall be present in every translation unit in which it is
explicitly instantiated. */
pedwarn
- ("explicit instantiation of `%D' but no definition available", d);
+ ("explicit instantiation of %qD but no definition available", d);
add_pending_template (d);
goto out;
}
+ /* Tell the repository that D is available in this translation unit
+ -- and see if it is supposed to be instantiated here. */
+ if (TREE_PUBLIC (d) && !DECL_REALLY_EXTERN (d) && !repo_emit_p (d))
+ {
+ /* In a PCH file, despite the fact that the repository hasn't
+ requested instantiation in the PCH it is still possible that
+ an instantiation will be required in a file that includes the
+ PCH. */
+ if (pch_file)
+ add_pending_template (d);
+ /* Instantiate inline functions so that the inliner can do its
+ job, even though we'll not be emitting a copy of this
+ function. */
+ if (!(TREE_CODE (d) == FUNCTION_DECL
+ && flag_inline_trees
+ && DECL_DECLARED_INLINE_P (d)))
+ goto out;
+ }
need_push = !cfun || !global_bindings_p ();
if (need_push)
/* Regenerate the declaration in case the template has been modified
by a subsequent redeclaration. */
regenerate_decl_from_template (d, td);
-
+
/* We already set the file and line above. Reset them now in case
they changed as a result of calling regenerate_decl_from_template. */
input_location = DECL_SOURCE_LOCATION (d);
/* Clear out DECL_RTL; whatever was there before may not be right
since we've reset the type of the declaration. */
SET_DECL_RTL (d, NULL_RTX);
-
DECL_IN_AGGR_P (d) = 0;
- import_export_decl (d);
- DECL_EXTERNAL (d) = ! DECL_NOT_REALLY_EXTERN (d);
- if (DECL_EXTERNAL (d))
- {
- /* The fact that this code is executing indicates that:
-
- (1) D is a template static data member, for which a
- definition is available.
+ /* Clear DECL_EXTERNAL so that cp_finish_decl will process the
+ initializer. That function will defer actual emission until
+ we have a chance to determine linkage. */
+ DECL_EXTERNAL (d) = 0;
- (2) An implicit or explicit instantiation has occurred.
-
- (3) We are not going to emit a definition of the static
- data member at this time.
-
- This situation is peculiar, but it occurs on platforms
- without weak symbols when performing an implicit
- instantiation. There, we cannot implicitly instantiate a
- defined static data member in more than one translation
- unit, so import_export_decl marks the declaration as
- external; we must rely on explicit instantiation.
-
- Reset instantiated marker to make sure that later
- explicit instantiation will be processed. */
- DECL_TEMPLATE_INSTANTIATED (d) = 0;
- }
- else
- {
- /* This is done in analogous to `start_decl'. It is
- required for correct access checking. */
- push_nested_class (DECL_CONTEXT (d));
- cp_finish_decl (d,
- (!DECL_INITIALIZED_IN_CLASS_P (d)
- ? DECL_INITIAL (d) : NULL_TREE),
- NULL_TREE, 0);
- /* Normally, pop_nested_class is called by cp_finish_decl
- above. But when instantiate_decl is triggered during
- instantiate_class_template processing, its DECL_CONTEXT
- is still not completed yet, and pop_nested_class isn't
- called. */
- if (!COMPLETE_TYPE_P (DECL_CONTEXT (d)))
- pop_nested_class ();
- }
+ /* Enter the scope of D so that access-checking works correctly. */
+ push_nested_class (DECL_CONTEXT (d));
+ cp_finish_decl (d,
+ (!DECL_INITIALIZED_IN_CLASS_P (d)
+ ? DECL_INITIAL (d) : NULL_TREE),
+ NULL_TREE, 0);
+ pop_nested_class ();
}
else if (TREE_CODE (d) == FUNCTION_DECL)
{
tree tmpl_parm;
tree spec_parm;
- /* Mark D as instantiated so that recursive calls to
- instantiate_decl do not try to instantiate it again. */
- DECL_TEMPLATE_INSTANTIATED (d) = 1;
-
/* Save away the current list, in case we are instantiating one
template from within the body of another. */
saved_local_specializations = local_specializations;
NULL);
/* Set up context. */
- import_export_decl (d);
start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
/* Create substitution entries for the parameters. */
tmpl_parm = TREE_CHAIN (tmpl_parm);
spec_parm = TREE_CHAIN (spec_parm);
}
- my_friendly_assert (!spec_parm, 20020813);
+ gcc_assert (!spec_parm);
/* Substitute into the body of the function. */
tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
}
/* Run through the list of templates that we wish we could
- instantiate, and instantiate any we can. */
+ instantiate, and instantiate any we can. RETRIES is the
+ number of times we retry pending template instantiation. */
-int
-instantiate_pending_templates (void)
+void
+instantiate_pending_templates (int retries)
{
tree *t;
tree last = NULL_TREE;
- int instantiated_something = 0;
int reconsider;
location_t saved_loc = input_location;
-
+
+ /* Instantiating templates may trigger vtable generation. This in turn
+ may require further template instantiations. We place a limit here
+ to avoid infinite loop. */
+ if (pending_templates && retries >= max_tinst_depth)
+ {
+ cp_error_at ("template instantiation depth exceeds maximum of %d"
+ " (use -ftemplate-depth-NN to increase the maximum)"
+ " instantiating %q+D, possibly from virtual table"
+ " generation",
+ max_tinst_depth, TREE_VALUE (pending_templates));
+ return;
+ }
+
do
{
reconsider = 0;
instantiate_decl (fn, /*defer_ok=*/0,
/*undefined_ok=*/0);
if (COMPLETE_TYPE_P (instantiation))
- {
- instantiated_something = 1;
- reconsider = 1;
- }
+ reconsider = 1;
}
if (COMPLETE_TYPE_P (instantiation))
/*defer_ok=*/0,
/*undefined_ok=*/0);
if (DECL_TEMPLATE_INSTANTIATED (instantiation))
- {
- instantiated_something = 1;
- reconsider = 1;
- }
+ reconsider = 1;
}
if (DECL_TEMPLATE_SPECIALIZATION (instantiation)
while (reconsider);
input_location = saved_loc;
- return instantiated_something;
}
/* Substitute ARGVEC into T, which is a list of initializers for
/* There should be as many levels of arguments as there are levels
of parameters. */
- my_friendly_assert (parm_depth == TMPL_ARGS_DEPTH (targs), 0);
+ gcc_assert (parm_depth == TMPL_ARGS_DEPTH (targs));
fn_type = TREE_TYPE (tmpl);
return 0;
if (complain & tf_error)
- error ("`%#T' is not a valid type for a template constant parameter",
- type);
+ error ("%q#T is not a valid type for a template constant parameter", type);
return 1;
}
A type is dependent if it is:
- -- a template parameter. Template template parameters are
- types for us (since TYPE_P holds true for them) so we
- handle them here. */
+ -- a template parameter. Template template parameters are types
+ for us (since TYPE_P holds true for them) so we handle
+ them here. */
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
|| TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
return true;
tree scope;
tree name;
- my_friendly_assert (TREE_CODE (expression) == SCOPE_REF, 20030714);
+ gcc_assert (TREE_CODE (expression) == SCOPE_REF);
if (!TYPE_P (TREE_OPERAND (expression, 0)))
return true;
/* If there are no operands, it must be an expression such
as "int()". This should not happen for aggregate types
because it would form non-constant expressions. */
- my_friendly_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type),
- 20040318);
+ gcc_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type));
return false;
}
|| value_dependent_expression_p (TREE_OPERAND (expression, 1)));
/* A constant expression is value-dependent if any subexpression is
value-dependent. */
- if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expression))))
+ if (EXPR_P (expression))
{
switch (TREE_CODE_CLASS (TREE_CODE (expression)))
{
- case '1':
+ case tcc_unary:
return (value_dependent_expression_p
(TREE_OPERAND (expression, 0)));
- case '<':
- case '2':
+ case tcc_comparison:
+ case tcc_binary:
return ((value_dependent_expression_p
(TREE_OPERAND (expression, 0)))
|| (value_dependent_expression_p
(TREE_OPERAND (expression, 1))));
- case 'e':
+ case tcc_expression:
{
int i;
for (i = 0; i < first_rtl_op (TREE_CODE (expression)); ++i)
return true;
return false;
}
+ case tcc_reference:
+ case tcc_statement:
+ /* These cannot be value dependent. */
+ return false;
+
+ default:
+ gcc_unreachable ();
}
}
if (TREE_CODE (expression) == BASELINK)
expression = BASELINK_FUNCTIONS (expression);
+
if (TREE_CODE (expression) == TEMPLATE_ID_EXPR)
{
if (any_dependent_template_arguments_p
return true;
expression = TREE_OPERAND (expression, 0);
}
- if (TREE_CODE (expression) == OVERLOAD)
+ gcc_assert (TREE_CODE (expression) == OVERLOAD);
+
+ while (expression)
{
- while (expression)
- {
- if (type_dependent_expression_p (OVL_CURRENT (expression)))
- return true;
- expression = OVL_NEXT (expression);
- }
- return false;
+ if (type_dependent_expression_p (OVL_CURRENT (expression)))
+ return true;
+ expression = OVL_NEXT (expression);
}
- abort ();
+ return false;
}
return (dependent_type_p (TREE_TYPE (expression)));
if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)
|| TREE_CODE (tmpl) == TEMPLATE_TEMPLATE_PARM)
return true;
- /* So are qualified names that have not been looked up. */
- if (TREE_CODE (tmpl) == SCOPE_REF)
+ /* So are names that have not been looked up. */
+ if (TREE_CODE (tmpl) == SCOPE_REF
+ || TREE_CODE (tmpl) == IDENTIFIER_NODE)
return true;
/* So are member templates of dependent classes. */
if (TYPE_P (CP_DECL_CONTEXT (tmpl)))
int quals;
bool pop_p;
- my_friendly_assert (TREE_CODE (type) == TYPENAME_TYPE,
- 20010702);
+ gcc_assert (TREE_CODE (type) == TYPENAME_TYPE);
scope = TYPE_CONTEXT (type);
name = TYPE_IDENTIFIER (type);
return expr;
if (TREE_CODE (expr) == COND_EXPR)
- return build (COND_EXPR,
- TREE_TYPE (expr),
- TREE_OPERAND (expr, 0),
- (TREE_OPERAND (expr, 1)
- ? build_non_dependent_expr (TREE_OPERAND (expr, 1))
- : build_non_dependent_expr (TREE_OPERAND (expr, 0))),
- build_non_dependent_expr (TREE_OPERAND (expr, 2)));
+ return build3 (COND_EXPR,
+ TREE_TYPE (expr),
+ TREE_OPERAND (expr, 0),
+ (TREE_OPERAND (expr, 1)
+ ? build_non_dependent_expr (TREE_OPERAND (expr, 1))
+ : build_non_dependent_expr (TREE_OPERAND (expr, 0))),
+ build_non_dependent_expr (TREE_OPERAND (expr, 2)));
if (TREE_CODE (expr) == COMPOUND_EXPR
&& !COMPOUND_EXPR_OVERLOADED (expr))
- return build (COMPOUND_EXPR,
- TREE_TYPE (expr),
- TREE_OPERAND (expr, 0),
- build_non_dependent_expr (TREE_OPERAND (expr, 1)));
+ return build2 (COMPOUND_EXPR,
+ TREE_TYPE (expr),
+ TREE_OPERAND (expr, 0),
+ build_non_dependent_expr (TREE_OPERAND (expr, 1)));
/* Otherwise, build a NON_DEPENDENT_EXPR.