/* Handle parameterized types (templates) for GNU C++.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
Rewritten by Jason Merrill (jason@cygnus.com).
#include "tm.h"
#include "obstack.h"
#include "tree.h"
+#include "pointer-set.h"
#include "flags.h"
#include "cp-tree.h"
#include "tree-inline.h"
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 int type_unification_real (tree, tree, tree, tree,
int, unification_kind_t, int, int);
static void note_template_header (int);
+static tree convert_nontype_argument_function (tree, tree);
static tree convert_nontype_argument (tree, tree);
static tree convert_template_argument (tree, tree, tree,
tsubst_flags_t, int, tree);
static tree get_bindings_overload (tree, tree, tree);
-static int for_each_template_parm (tree, tree_fn_t, void*, htab_t);
+static int for_each_template_parm (tree, tree_fn_t, void*,
+ struct pointer_set_t*);
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 tree most_specialized_class (tree, tree);
static int template_class_depth_real (tree, int);
static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int);
-static tree tsubst_decl (tree, tree, tree, tsubst_flags_t);
static tree tsubst_arg_types (tree, tree, tsubst_flags_t, tree);
static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree);
static void check_specialization_scope (void);
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 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))
+ if (DECL_FRIEND_CONTEXT (t))
+ push_nested_class (DECL_FRIEND_CONTEXT (t));
+ else if (DECL_CLASS_SCOPE_P (t))
push_nested_class (DECL_CONTEXT (t));
else
push_to_top_level ();
saved_access_scope = TREE_CHAIN (saved_access_scope);
}
- if (DECL_CLASS_SCOPE_P (t))
+ if (DECL_FRIEND_CONTEXT (t) || DECL_CLASS_SCOPE_P (t))
pop_nested_class ();
else
pop_from_top_level ();
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;
}
return true;
else
{
- pedwarn ("specialization of `%D' in different namespace", tmpl);
- cp_pedwarn_at (" from definition of `%#D'", tmpl);
+ pedwarn ("specialization of %qD in different namespace", tmpl);
+ cp_pedwarn_at (" from definition of %q#D", tmpl);
return false;
}
}
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 nonzero 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))
+ /* The optimized lookup depends on the fact that the
+ template arguments for the member function template apply
+ purely to the containing class, which is not true if the
+ containing class is an explicit or partial
+ specialization. */
+ && !CLASSTYPE_TEMPLATE_SPECIALIZATION (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
+ || TREE_CODE (decl) == TYPE_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
&& DECL_TEMPLATE_INFO (friend)
&& !DECL_USE_TEMPLATE (friend))
{
+ /* We want a TEMPLATE_DECL for `is_specialization_of'. */
friend = DECL_TI_TEMPLATE (friend);
need_template = false;
}
+ else if (TREE_CODE (friend) == TEMPLATE_DECL
+ && !PRIMARY_TEMPLATE_P (friend))
+ need_template = false;
/* There is nothing to do if this is not a template friend. */
if (TREE_CODE (friend) != TEMPLATE_DECL)
- return 0;
+ return false;
if (is_specialization_of (decl, friend))
- return 1;
+ return true;
/* [temp.friend/6]
A member of a class template may be declared to be a friend of a
CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (friend))))
{
/* Next, we check the members themselves. In order to handle
- a few tricky cases like
+ a few tricky cases, such as when FRIEND's are
template <class T> friend void A<T>::g(T t);
template <class T> template <T t> friend void A<T>::h();
- we need to figure out what ARGS is (corresponding to `T' in above
- examples) from DECL for later processing. */
+ and DECL's are
+
+ void A<int>::g(int);
+ template <int> void A<int>::h();
+
+ we need to figure out ARGS, the template arguments from
+ the context of DECL. This is required for template substitution
+ of `T' in the function parameter of `g' and template parameter
+ of `h' in the above examples. Here ARGS corresponds to `int'. */
tree context = DECL_CONTEXT (decl);
tree args = NULL_TREE;
int current_depth = 0;
+
while (current_depth < template_depth)
{
if (CLASSTYPE_TEMPLATE_INFO (context))
is_template = DECL_TEMPLATE_INFO (decl)
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl));
if (need_template ^ is_template)
- return 0;
+ return false;
else if (is_template)
{
/* If both are templates, check template parameter list. */
if (!comp_template_parms
(DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl)),
friend_parms))
- return 0;
+ return false;
decl_type = TREE_TYPE (DECL_TI_TEMPLATE (decl));
}
friend_type = tsubst_function_type (TREE_TYPE (friend), args,
tf_none, NULL_TREE);
if (friend_type == error_mark_node)
- return 0;
+ return false;
/* Check if return types match. */
if (!same_type_p (TREE_TYPE (decl_type), TREE_TYPE (friend_type)))
- return 0;
+ return false;
/* Check if function parameter types match, ignoring the
`this' parameter. */
friend_args_type = TREE_CHAIN (friend_args_type);
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
decl_args_type = TREE_CHAIN (decl_args_type);
- if (compparms (decl_args_type, friend_args_type))
- return 1;
+
+ return compparms (decl_args_type, friend_args_type);
+ }
+ else
+ {
+ /* DECL is a TYPE_DECL */
+ bool is_template;
+ tree decl_type = TREE_TYPE (decl);
+
+ /* Make sure that both DECL and FRIEND are templates or
+ non-templates. */
+ is_template
+ = CLASSTYPE_TEMPLATE_INFO (decl_type)
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (decl_type));
+
+ if (need_template ^ is_template)
+ return false;
+ else if (is_template)
+ {
+ tree friend_parms;
+ /* If both are templates, check the name of the two
+ TEMPLATE_DECL's first because is_friend didn't. */
+ if (DECL_NAME (CLASSTYPE_TI_TEMPLATE (decl_type))
+ != DECL_NAME (friend))
+ return false;
+
+ /* Now check template parameter list. */
+ friend_parms
+ = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend),
+ args, tf_none);
+ return comp_template_parms
+ (DECL_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (decl_type)),
+ friend_parms);
+ }
+ else
+ return (DECL_NAME (decl)
+ == DECL_NAME (friend));
}
}
- return 0;
+ return false;
}
/* Register the specialization SPEC as a specialization of TMPL with
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)
- && DECL_TEMPLATE_SPECIALIZATION (spec))
+ 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_INSTANTIATION (fn))
+ if (TREE_USED (fn)
+ || DECL_EXPLICIT_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;
- }
+ error ("specialization of %qD after instantiation",
+ fn);
+ return spec;
}
- else if (DECL_TEMPLATE_SPECIALIZATION (fn))
+ else
{
- 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);
+ /* 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;
+ }
}
/* A specialization must be declared in the same namespace as the
&& !check_specialization_namespace (tmpl))
DECL_CONTEXT (spec) = decl_namespace_context (tmpl);
- DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
- = tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
+ if (!optimize_specialization_lookup_p (tmpl))
+ DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
+ = tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
return spec;
}
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;
}
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);
tree dname = DECL_NAME (decl);
tmpl_spec_kind tsk;
- tsk = current_tmpl_spec_kind (template_count);
+ if (is_friend)
+ {
+ if (!processing_specialization)
+ tsk = tsk_none;
+ else
+ tsk = tsk_excessive_parms;
+ }
+ else
+ tsk = current_tmpl_spec_kind (template_count);
switch (tsk)
{
/* 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;
}
}
case tsk_excessive_parms:
case tsk_insufficient_parms:
if (tsk == tsk_excessive_parms)
- error ("too many template parameter lists in declaration of `%D'",
+ 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 `%D'",
- decl);
+ error("too few template parameter lists in declaration of %qD", decl);
else
- error("explicit specialization of `%D' must be introduced by "
- "`template <>'", decl);
+ error("explicit specialization of %qD must be introduced by "
+ "%<template <>%>", decl);
/* Fall through. */
case tsk_expl_spec:
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. */
fns = namespace_binding (dname, CP_DECL_CONTEXT (decl));
+ if (!fns || !is_overloaded_fn (fns))
+ {
+ error ("%qD is not a template function", dname);
+ fns = error_mark_node;
+ }
}
declarator = lookup_template_function (fns, NULL_TREE);
int is_constructor = DECL_CONSTRUCTOR_P (decl);
if (is_constructor ? !TYPE_HAS_CONSTRUCTOR (ctype)
- : !TYPE_HAS_DESTRUCTOR (ctype))
+ : !CLASSTYPE_DESTRUCTORS (ctype))
{
/* From [temp.expl.spec]:
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
DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (tmpl))
= DECL_SOURCE_LOCATION (decl);
+ /* We want to use the argument list specified in the
+ definition, not in the original declaration. */
+ DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (tmpl))
+ = DECL_ARGUMENTS (decl);
}
return tmpl;
}
return decl;
}
-/* TYPE is being declared. Verify that the use of template headers
- and such is reasonable. Issue error messages if not. */
-
-void
-maybe_check_template_type (tree type)
-{
- if (template_header_count)
- {
- /* We are in the scope of some `template <...>' header. */
-
- int context_depth
- = template_class_depth_real (TYPE_CONTEXT (type),
- /*count_specializations=*/1);
-
- if (template_header_count <= context_depth)
- /* This is OK; the template headers are for the context. We
- are actually too lenient here; like
- check_explicit_specialization we should consider the number
- of template types included in the actual declaration. For
- example,
-
- template <class T> struct S {
- template <class U> template <class V>
- struct I {};
- };
-
- is invalid, but:
-
- template <class T> struct S {
- template <class U> struct I;
- };
-
- template <class T> template <class U.
- struct S<T>::I {};
-
- is not. */
- ;
- 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);
- }
-}
-
/* Returns 1 iff PARMS1 and PARMS2 are identical sets of template
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 member 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));
}
parameters of the class. */
if (new_template_p && !ctx
&& !(is_friend && template_class_depth (current_class_type) > 0))
- tmpl = pushdecl_namespace_level (tmpl);
+ {
+ tmpl = pushdecl_namespace_level (tmpl);
+ if (tmpl == error_mark_node)
+ return error_mark_node;
+ }
if (primary)
{
if (!TYPE_TEMPLATE_INFO (type))
{
- error ("`%T' is not a template type", type);
+ error ("%qT is not a template type", type);
return;
}
type. */
return;
+ if (!parms)
+ {
+ error ("template specifiers not specified in declaration of %qD",
+ tmpl);
+ return;
+ }
+
parms = INNERMOST_TEMPLATE_PARMS (parms);
tmpl_parms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl);
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;
}
}
}
+/* Return true if non-dependent expressions EXPR contains within it a
+ cast expression with a dependent argument. */
+
+static bool
+contains_dependent_cast_p (tree expr)
+{
+ switch (TREE_CODE (expr))
+ {
+ case CAST_EXPR:
+ case REINTERPRET_CAST_EXPR:
+ case STATIC_CAST_EXPR:
+ case DYNAMIC_CAST_EXPR:
+ case CONST_CAST_EXPR:
+ {
+ tree op = TREE_OPERAND (expr, 0);
+
+ if (op && (type_dependent_expression_p (op)
+ || value_dependent_expression_p (op)))
+ return true;
+ }
+ break;
+
+ case TREE_LIST:
+ /* The operands of a CALL_EXPR are held as a list. */
+ for (; expr; expr = TREE_CHAIN (expr))
+ if (contains_dependent_cast_p (TREE_VALUE (expr)))
+ return true;
+ return false;
+
+ default:
+ break;
+ }
+
+ if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expr))))
+ {
+ int ix;
+
+ for (ix = TREE_CODE_LENGTH (TREE_CODE (expr)); ix--;)
+ if (TREE_OPERAND (expr, ix)
+ && contains_dependent_cast_p (TREE_OPERAND (expr, ix)))
+ return true;
+ }
+
+ return false;
+}
+
/* Simplify EXPR if it is a non-dependent expression. Returns the
(possibly simplified) expression. */
as two declarations of the same function, for example. */
if (processing_template_decl
&& !type_dependent_expression_p (expr)
- && !value_dependent_expression_p (expr))
+ && !value_dependent_expression_p (expr)
+ && !contains_dependent_cast_p (expr))
{
HOST_WIDE_INT saved_processing_template_decl;
return expr;
}
+/* EXPR is an expression which is used in a constant-expression context.
+ For instance, it could be a VAR_DECL with a constant initializer.
+ Extract the innest constant expression.
+
+ This is basically a more powerful version of
+ integral_constant_value, which can be used also in templates where
+ initializers can maintain a syntactic rather than semantic form
+ (even if they are non-dependent, for access-checking purposes). */
+
+tree
+fold_decl_constant_value (tree expr)
+{
+ tree const_expr = expr;
+ do
+ {
+ expr = fold_non_dependent_expr (const_expr);
+ const_expr = integral_constant_value (expr);
+ }
+ while (expr != const_expr);
+
+ return expr;
+}
+
+/* Subroutine of convert_nontype_argument. Converts EXPR to TYPE, which
+ must be a function or a pointer-to-function type, as specified
+ in [temp.arg.nontype]: disambiguate EXPR if it is an overload set,
+ and check that the resulting function has external linkage. */
+
+static tree
+convert_nontype_argument_function (tree type, tree expr)
+{
+ tree fns = expr;
+ tree fn, fn_no_ptr;
+
+ fn = instantiate_type (type, fns, tf_none);
+ if (fn == error_mark_node)
+ return error_mark_node;
+
+ fn_no_ptr = fn;
+ if (TREE_CODE (fn_no_ptr) == ADDR_EXPR)
+ fn_no_ptr = TREE_OPERAND (fn_no_ptr, 0);
+
+ /* [temp.arg.nontype]/1
+
+ A template-argument for a non-type, non-template template-parameter
+ shall be one of:
+ [...]
+ -- the address of an object or function with external linkage. */
+ if (!DECL_EXTERNAL_LINKAGE_P (fn_no_ptr))
+ {
+ error ("%qE is not a valid template argument for type %qT "
+ "because function %qD has not external linkage",
+ expr, type, fn_no_ptr);
+ return NULL_TREE;
+ }
+
+ return fn;
+}
+
/* Attempt to convert the non-type template parameter EXPR to the
indicated TYPE. If the conversion is successful, return the
converted value. If the conversion is unsuccessful, return
did not. We issue error messages for out-and-out bad template
parameters, but not simply because the conversion failed, since we
might be just trying to do argument deduction. Both TYPE and EXPR
- must be non-dependent. */
+ must be non-dependent.
+
+ The conversion follows the special rules described in
+ [temp.arg.nontype], and it is much more strict than an implicit
+ conversion.
+
+ This function is called twice for each template argument (see
+ lookup_template_class for a more accurate description of this
+ problem). This means that we need to handle expressions which
+ are not valid in a C++ source, but can be created from the
+ first call (for instance, casts to perform conversions). These
+ hacks can go away after we fix the double coercion problem. */
static tree
convert_nontype_argument (tree type, tree expr)
{
tree expr_type;
+ /* Detect immediately string literals as invalid non-type argument.
+ This special-case is not needed for correctness (we would easily
+ catch this later), but only to provide better diagnostic for this
+ common user mistake. As suggested by DR 100, we do not mention
+ linkage issues in the diagnostic as this is not the point. */
+ if (TREE_CODE (expr) == STRING_CST)
+ {
+ error ("%qE is not a valid template argument for type %qT "
+ "because string literals can never be used in this context",
+ expr, type);
+ return NULL_TREE;
+ }
+
/* If we are in a template, EXPR may be non-dependent, but still
have a syntactic, rather than semantic, form. For example, EXPR
might be a SCOPE_REF, rather than the VAR_DECL to which the
expr = fold_non_dependent_expr (expr);
expr_type = TREE_TYPE (expr);
- /* A template-argument for a non-type, non-template
- template-parameter shall be one of:
-
- --an integral constant-expression of integral or enumeration
- type; or
-
- --the name of a non-type template-parameter; or
-
- --the name of an object or function with external linkage,
- including function templates and function template-ids but
- excluding non-static class members, expressed as id-expression;
- or
-
- --the address of an object or function with external linkage,
- including function templates and function template-ids but
- excluding non-static class members, expressed as & id-expression
- where the & is optional if the name refers to a function or
- array; or
-
- --a pointer to member expressed as described in _expr.unary.op_. */
-
- /* An integral constant-expression can include const variables or
-. enumerators. Simplify things by folding them to their values,
- unless we're about to bind the declaration to a reference
- parameter. */
- if (INTEGRAL_TYPE_P (expr_type) && TREE_CODE (type) != REFERENCE_TYPE)
- while (true)
- {
- tree const_expr = decl_constant_value (expr);
- /* In a template, the initializer for a VAR_DECL may not be
- marked as TREE_CONSTANT, in which case decl_constant_value
- will not return the initializer. Handle that special case
- here. */
- if (expr == const_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
- constant, yet. */
- && DECL_INITIAL (expr))
- const_expr = DECL_INITIAL (expr);
- if (expr == const_expr)
- break;
- expr = fold_non_dependent_expr (const_expr);
- }
-
- if (is_overloaded_fn (expr))
- /* OK for now. We'll check that it has external linkage later.
- Check this first since if expr_type is the unknown_type_node
- we would otherwise complain below. */
- ;
- else if (TYPE_PTR_TO_MEMBER_P (expr_type))
- {
- if (TREE_CODE (expr) != PTRMEM_CST)
- goto bad_argument;
- }
- else if (TYPE_PTR_P (expr_type)
- || TREE_CODE (expr_type) == ARRAY_TYPE
- || TREE_CODE (type) == REFERENCE_TYPE
- /* If expr is the address of an overloaded function, we
- will get the unknown_type_node at this point. */
- || expr_type == unknown_type_node)
- {
- tree referent;
- tree e = expr;
- STRIP_NOPS (e);
-
- if (TREE_CODE (expr_type) == ARRAY_TYPE
- || (TREE_CODE (type) == REFERENCE_TYPE
- && TREE_CODE (e) != ADDR_EXPR))
- referent = e;
- else
- {
- if (TREE_CODE (e) != ADDR_EXPR)
- {
- bad_argument:
- error ("`%E' 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 a function with external linkage");
- else
- 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'");
-
- return NULL_TREE;
- }
-
- referent = TREE_OPERAND (e, 0);
- STRIP_NOPS (referent);
- }
-
- if (TREE_CODE (referent) == STRING_CST)
+ /* HACK: Due to double coercion, we can get a
+ NOP_EXPR<REFERENCE_TYPE>(ADDR_EXPR<POINTER_TYPE> (arg)) here,
+ which is the tree that we built on the first call (see
+ below when coercing to reference to object or to reference to
+ function). We just strip everything and get to the arg.
+ See g++.old-deja/g++.oliva/template4.C and g++.dg/template/nontype9.C
+ for examples. */
+ if (TREE_CODE (expr) == NOP_EXPR)
+ {
+ if (TYPE_REF_OBJ_P (type) || TYPE_REFFN_P (type))
{
- error ("string literal %E is not a valid template argument because it is the address of an object with static linkage",
- referent);
- return NULL_TREE;
+ /* ??? Maybe we could use convert_from_reference here, but we
+ would need to relax its constraints because the NOP_EXPR
+ could actually change the type to something more cv-qualified,
+ and this is not folded by convert_from_reference. */
+ tree addr = TREE_OPERAND (expr, 0);
+ gcc_assert (TREE_CODE (expr_type) == REFERENCE_TYPE);
+ gcc_assert (TREE_CODE (addr) == ADDR_EXPR);
+ gcc_assert (TREE_CODE (TREE_TYPE (addr)) == POINTER_TYPE);
+ gcc_assert (same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (expr_type),
+ TREE_TYPE (TREE_TYPE (addr))));
+
+ expr = TREE_OPERAND (addr, 0);
+ expr_type = TREE_TYPE (expr);
}
- if (TREE_CODE (referent) == SCOPE_REF)
- referent = TREE_OPERAND (referent, 1);
-
- if (is_overloaded_fn (referent))
- /* We'll check that it has external linkage later. */
- ;
- else if (TREE_CODE (referent) != VAR_DECL)
- goto bad_argument;
- else if (!DECL_EXTERNAL_LINKAGE_P (referent))
- {
- error ("address of non-extern `%E' cannot be used as template argument", referent);
- return error_mark_node;
- }
- }
- else if (INTEGRAL_TYPE_P (expr_type) || TYPE_PTR_TO_MEMBER_P (expr_type))
- {
- if (! TREE_CONSTANT (expr))
+ /* We could also generate a NOP_EXPR(ADDR_EXPR()) when the
+ parameter is a pointer to object, through decay and
+ qualification conversion. Let's strip everything. */
+ else if (TYPE_PTROBV_P (type))
{
- non_constant:
- error ("non-constant `%E' cannot be used as template argument",
- expr);
- return NULL_TREE;
+ STRIP_NOPS (expr);
+ gcc_assert (TREE_CODE (expr) == ADDR_EXPR);
+ gcc_assert (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE);
+ /* Skip the ADDR_EXPR only if it is part of the decay for
+ an array. Otherwise, it is part of the original argument
+ in the source code. */
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == ARRAY_TYPE)
+ expr = TREE_OPERAND (expr, 0);
+ expr_type = TREE_TYPE (expr);
}
}
- else
- {
- if (TYPE_P (expr))
- error ("type '%T' 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);
- else
- error ("invalid use of '%E' as a non-type template-argument", expr);
- return NULL_TREE;
- }
+ /* [temp.arg.nontype]/5, bullet 1
- switch (TREE_CODE (type))
+ For a non-type template-parameter of integral or enumeration type,
+ integral promotions (_conv.prom_) and integral conversions
+ (_conv.integral_) are applied. */
+ if (INTEGRAL_TYPE_P (type))
{
- case INTEGER_TYPE:
- case BOOLEAN_TYPE:
- case ENUMERAL_TYPE:
- /* For a non-type template-parameter of integral or enumeration
- type, integral promotions (_conv.prom_) and integral
- conversions (_conv.integral_) are applied. */
if (!INTEGRAL_TYPE_P (expr_type))
return error_mark_node;
- /* [conv.integral] does not allow conversions between two different
- enumeration types. */
- if (TREE_CODE (type) == ENUMERAL_TYPE
- && TREE_CODE (expr_type) == ENUMERAL_TYPE
- && !same_type_ignoring_top_level_qualifiers_p (type, expr_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. */
- expr = digest_init (type, expr, (tree*) 0);
-
+ expr = fold_decl_constant_value (expr);
+ /* Notice that there are constant expressions like '4 % 0' which
+ do not fold into integer constants. */
if (TREE_CODE (expr) != INTEGER_CST)
- /* Curiously, some TREE_CONSTANT integral expressions do not
- simplify to integer constants. For example, `3 % 0',
- remains a TRUNC_MOD_EXPR. */
- goto non_constant;
-
- return expr;
-
- case OFFSET_TYPE:
- {
- tree e;
-
- /* For a non-type template-parameter of type pointer to data
- member, qualification conversions (_conv.qual_) are
- applied. */
- e = perform_qualification_conversions (type, expr);
- if (TREE_CODE (e) == NOP_EXPR)
- /* The call to perform_qualification_conversions will
- insert a NOP_EXPR over EXPR to do express conversion,
- if necessary. But, that will confuse us if we use
- this (converted) template parameter to instantiate
- another template; then the thing will not look like a
- valid template argument. So, just make a new
- constant, of the appropriate type. */
- e = make_ptrmem_cst (type, PTRMEM_CST_MEMBER (expr));
- return e;
- }
-
- case POINTER_TYPE:
- {
- tree type_pointed_to = TREE_TYPE (type);
-
- if (TREE_CODE (type_pointed_to) == FUNCTION_TYPE)
- {
- /* For a non-type template-parameter of type pointer to
- function, only the function-to-pointer conversion
- (_conv.func_) is applied. If the template-argument
- represents a set of overloaded functions (or a pointer to
- such), the matching function is selected from the set
- (_over.over_). */
- tree fns;
- tree fn;
-
- if (TREE_CODE (expr) == ADDR_EXPR)
- fns = TREE_OPERAND (expr, 0);
- else
- fns = expr;
+ {
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is a non-constant expression", expr, type);
+ return NULL_TREE;
+ }
- fn = instantiate_type (type_pointed_to, fns, tf_none);
+ /* At this point, an implicit conversion does what we want,
+ because we already know that the expression is of integral
+ type. */
+ expr = ocp_convert (type, expr, CONV_IMPLICIT, LOOKUP_PROTECT);
+ if (expr == error_mark_node)
+ return error_mark_node;
- if (fn == error_mark_node)
- return error_mark_node;
+ /* Conversion was allowed: fold it to a bare integer constant. */
+ expr = fold (expr);
+ }
+ /* [temp.arg.nontype]/5, bullet 2
- if (!DECL_EXTERNAL_LINKAGE_P (fn))
- {
- if (really_overloaded_fn (fns))
- return error_mark_node;
- else
- goto bad_argument;
- }
+ For a non-type template-parameter of type pointer to object,
+ qualification conversions (_conv.qual_) and the array-to-pointer
+ conversion (_conv.array_) are applied. */
+ else if (TYPE_PTROBV_P (type))
+ {
+ /* [temp.arg.nontype]/1 (TC1 version, DR 49):
- expr = build_unary_op (ADDR_EXPR, fn, 0);
+ A template-argument for a non-type, non-template template-parameter
+ shall be one of: [...]
- my_friendly_assert (same_type_p (type, TREE_TYPE (expr)),
- 0);
- return expr;
- }
- else
- {
- /* For a non-type template-parameter of type pointer to
- object, qualification conversions (_conv.qual_) and the
- array-to-pointer conversion (_conv.array_) are applied.
- [Note: In particular, neither the null pointer conversion
- (_conv.ptr_) nor the derived-to-base conversion
- (_conv.ptr_) are applied. Although 0 is a valid
- template-argument for a non-type template-parameter of
- integral type, it is not a valid template-argument for a
- non-type template-parameter of pointer type.]
+ -- the name of a non-type template-parameter;
+ -- the address of an object or function with external linkage, [...]
+ expressed as "& id-expression" where the & is optional if the name
+ refers to a function or array, or if the corresponding
+ template-parameter is a reference.
- The call to decay_conversion performs the
- array-to-pointer conversion, if appropriate. */
- expr = decay_conversion (expr);
-
- if (expr == error_mark_node)
- return error_mark_node;
- else
- return perform_qualification_conversions (type, expr);
- }
- }
- break;
+ Here, we do not care about functions, as they are invalid anyway
+ for a parameter of type pointer-to-object. */
+ bool constant_address_p =
+ (TREE_CODE (expr) == ADDR_EXPR
+ || TREE_CODE (expr_type) == ARRAY_TYPE
+ || (DECL_P (expr) && DECL_TEMPLATE_PARM_P (expr)));
+
+ expr = decay_conversion (expr);
+ if (expr == error_mark_node)
+ return error_mark_node;
- case REFERENCE_TYPE:
- {
- tree type_referred_to = TREE_TYPE (type);
+ expr = perform_qualification_conversions (type, expr);
+ if (expr == error_mark_node)
+ return error_mark_node;
- /* If this expression already has reference type, get the
- underlying object. */
- if (TREE_CODE (expr_type) == REFERENCE_TYPE)
- {
- 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);
- expr = TREE_OPERAND (expr, 0);
- expr_type = TREE_TYPE (expr);
- }
+ if (!constant_address_p)
+ {
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is not a constant pointer", expr, type);
+ return NULL_TREE;
+ }
+ }
+ /* [temp.arg.nontype]/5, bullet 3
- if (TREE_CODE (type_referred_to) == FUNCTION_TYPE)
- {
- /* For a non-type template-parameter of type reference to
- function, no conversions apply. If the
- template-argument represents a set of overloaded
- functions, the matching function is selected from the
- set (_over.over_). */
- tree fn;
+ For a non-type template-parameter of type reference to object, no
+ conversions apply. The type referred to by the reference may be more
+ cv-qualified than the (otherwise identical) type of the
+ template-argument. The template-parameter is bound directly to the
+ template-argument, which must be an lvalue. */
+ else if (TYPE_REF_OBJ_P (type))
+ {
+ if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type),
+ expr_type))
+ return error_mark_node;
- fn = instantiate_type (type_referred_to, expr, tf_none);
+ if (!at_least_as_qualified_p (TREE_TYPE (type), expr_type))
+ {
+ error ("%qE is not a valid template argument for type %qT "
+ "because of conflicts in cv-qualification", expr, type);
+ return NULL_TREE;
+ }
+
+ if (!real_lvalue_p (expr))
+ {
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is not a lvalue", expr, type);
+ return NULL_TREE;
+ }
- if (fn == error_mark_node)
- return error_mark_node;
+ /* [temp.arg.nontype]/1
- if (!DECL_EXTERNAL_LINKAGE_P (fn))
- {
- if (really_overloaded_fn (expr))
- /* Don't issue an error here; we might get a different
- function if the overloading had worked out
- differently. */
- return error_mark_node;
- else
- goto bad_argument;
- }
+ A template-argument for a non-type, non-template template-parameter
+ shall be one of: [...]
- my_friendly_assert (same_type_p (type_referred_to,
- TREE_TYPE (fn)),
- 0);
+ -- the address of an object or function with external linkage. */
+ if (!DECL_EXTERNAL_LINKAGE_P (expr))
+ {
+ error ("%qE is not a valid template argument for type %qT "
+ "because object %qD has not external linkage",
+ expr, type, expr);
+ return NULL_TREE;
+ }
- expr = fn;
- }
- else
- {
- /* For a non-type template-parameter of type reference to
- object, no conversions apply. The type referred to by the
- reference may be more cv-qualified than the (otherwise
- identical) type of the template-argument. The
- template-parameter is bound directly to the
- template-argument, which must be an lvalue. */
- if (!same_type_p (TYPE_MAIN_VARIANT (expr_type),
- TYPE_MAIN_VARIANT (type_referred_to))
- || !at_least_as_qualified_p (type_referred_to,
- expr_type)
- || !real_lvalue_p (expr))
- return error_mark_node;
- }
+ expr = build_nop (type, build_address (expr));
+ }
+ /* [temp.arg.nontype]/5, bullet 4
- cxx_mark_addressable (expr);
- return build_nop (type, build_address (expr));
- }
- break;
+ For a non-type template-parameter of type pointer to function, only
+ the function-to-pointer conversion (_conv.func_) is applied. If the
+ template-argument represents a set of overloaded functions (or a
+ pointer to such), the matching function is selected from the set
+ (_over.over_). */
+ else if (TYPE_PTRFN_P (type))
+ {
+ /* If the argument is a template-id, we might not have enough
+ context information to decay the pointer.
+ ??? Why static5.C requires decay and subst1.C works fine
+ even without it? */
+ if (!type_unknown_p (expr_type))
+ {
+ expr = decay_conversion (expr);
+ if (expr == error_mark_node)
+ return error_mark_node;
+ }
- case RECORD_TYPE:
- {
- my_friendly_assert (TYPE_PTRMEMFUNC_P (type), 20010112);
+ expr = convert_nontype_argument_function (type, expr);
+ if (!expr || expr == error_mark_node)
+ return expr;
+ }
+ /* [temp.arg.nontype]/5, bullet 5
- /* For a non-type template-parameter of type pointer to member
- function, no conversions apply. If the template-argument
- represents a set of overloaded member functions, the
- matching member function is selected from the set
- (_over.over_). */
+ For a non-type template-parameter of type reference to function, no
+ conversions apply. If the template-argument represents a set of
+ overloaded functions, the matching function is selected from the set
+ (_over.over_). */
+ else if (TYPE_REFFN_P (type))
+ {
+ if (TREE_CODE (expr) == ADDR_EXPR)
+ {
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is a pointer", expr, type);
+ inform ("try using %qE instead", TREE_OPERAND (expr, 0));
+ return NULL_TREE;
+ }
- if (!TYPE_PTRMEMFUNC_P (expr_type) &&
- expr_type != unknown_type_node)
- return error_mark_node;
+ expr = convert_nontype_argument_function (TREE_TYPE (type), expr);
+ if (!expr || expr == error_mark_node)
+ return expr;
- if (TREE_CODE (expr) == PTRMEM_CST)
- {
- /* A ptr-to-member constant. */
- if (!same_type_p (type, expr_type))
- return error_mark_node;
- else
- return expr;
- }
+ expr = build_nop(type, build_address (expr));
+ }
+ /* [temp.arg.nontype]/5, bullet 6
- if (TREE_CODE (expr) != ADDR_EXPR)
- return error_mark_node;
+ For a non-type template-parameter of type pointer to member function,
+ no conversions apply. If the template-argument represents a set of
+ overloaded member functions, the matching member function is selected
+ from the set (_over.over_). */
+ else if (TYPE_PTRMEMFUNC_P (type))
+ {
+ expr = instantiate_type (type, expr, tf_none);
+ if (expr == error_mark_node)
+ return error_mark_node;
- expr = instantiate_type (type, expr, tf_none);
-
- if (expr == error_mark_node)
- return error_mark_node;
+ /* There is no way to disable standard conversions in
+ resolve_address_of_overloaded_function (called by
+ instantiate_type). It is possible that the call succeeded by
+ converting &B::I to &D::I (where B is a base of D), so we need
+ to reject this conversion here.
- if (!same_type_p (type, TREE_TYPE (expr)))
- return error_mark_node;
+ Actually, even if there was a way to disable standard conversions,
+ it would still be better to reject them here so that we can
+ provide a superior diagnostic. */
+ if (!same_type_p (TREE_TYPE (expr), type))
+ {
+ /* Make sure we are just one standard conversion off. */
+ gcc_assert (can_convert (type, TREE_TYPE (expr)));
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is of type %qT", expr, type,
+ TREE_TYPE (expr));
+ inform ("standard conversions are not allowed in this context");
+ return NULL_TREE;
+ }
+ }
+ /* [temp.arg.nontype]/5, bullet 7
+ For a non-type template-parameter of type pointer to data member,
+ qualification conversions (_conv.qual_) are applied. */
+ else if (TYPE_PTRMEM_P (type))
+ {
+ expr = perform_qualification_conversions (type, expr);
+ if (expr == error_mark_node)
return expr;
- }
- break;
-
- default:
- /* All non-type parameters must have one of these types. */
- abort ();
- break;
}
+ /* A template non-type parameter must be one of the above. */
+ else
+ gcc_unreachable ();
- return error_mark_node;
+ /* Sanity check: did we actually convert the argument to the
+ right type? */
+ gcc_assert (same_type_p (type, TREE_TYPE (expr)));
+ return expr;
}
+
/* Return 1 if PARM_PARMS and ARG_PARMS matches using rule for
template template parameters. Both PARM_PARMS and ARG_PARMS are
vectors of TREE_LIST nodes containing TYPE_DECL, TEMPLATE_DECL
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);
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),
+ typename_type,
complain & tf_error);
is_type = 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);
+ {
+ if (complain & tf_error)
+ error ("template argument %d is invalid", i + 1);
+ }
else
arg = convert_template_argument (TREE_VALUE (parm),
arg, new_args, complain, i,
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);
- if (fns == NULL_TREE
- || TREE_CODE (fns) == FUNCTION_DECL)
- {
- error ("non-template used as template");
- 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 (!arglist || TREE_CODE (arglist) == TREE_VEC);
+ gcc_assert (fns && (is_overloaded_fn (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 the template class is really a local class in a template
function, then the FUNCTION_CONTEXT is the function in which it is
- being instantiated. */
+ being instantiated.
+
+ ??? Note that this function is currently called *twice* for each
+ template-id: the first time from the parser, while creating the
+ incomplete type (finish_template_type), and the second type during the
+ real instantiation (instantiate_template_class). This is surely something
+ that we want to avoid. It also causes some problems with argument
+ coercion (see convert_nontype_argument for more information on this). */
tree
lookup_template_class (tree d1,
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
{
found = xref_tag_from_type (TREE_TYPE (template),
DECL_NAME (template),
- /*globalize=*/1);
+ /*tag_scope=*/ts_global);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
}
{
tree_fn_t fn;
void *data;
- htab_t visited;
+ struct pointer_set_t *visited;
};
/* Called from for_each_template_parm via walk_tree. */
considered to be the function which always returns 1. */
static int
-for_each_template_parm (tree t, tree_fn_t fn, void* data, htab_t visited)
+for_each_template_parm (tree t, tree_fn_t fn, void* data,
+ struct pointer_set_t *visited)
{
struct pair_fn_data pfd;
int result;
if (visited)
pfd.visited = visited;
else
- pfd.visited = htab_create (37, htab_hash_pointer, htab_eq_pointer,
- NULL);
+ pfd.visited = pointer_set_create ();
result = walk_tree (&t,
for_each_template_parm_r,
&pfd,
/* Clean up. */
if (!visited)
- htab_delete (pfd.visited);
+ {
+ pointer_set_destroy (pfd.visited);
+ pfd.visited = 0;
+ }
return result;
}
|| 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 ();
/* Restore the filename and line number stashed away when we started
this instantiation. */
input_location = TINST_LOCATION (old);
- extract_interface_info ();
-
current_tinst_level = TREE_CHAIN (old);
--tinst_depth;
++tinst_level_tick;
pop_tinst_level ();
}
-/* Return the outermost template instantiation context, for use with
- -falt-external-templates. */
-
-tree
-tinst_for_decl (void)
-{
- tree p = current_tinst_level;
-
- if (p)
- for (; TREE_CHAIN (p) ; p = TREE_CHAIN (p))
- ;
- return p;
-}
-
/* DECL is a friend FUNCTION_DECL or TEMPLATE_DECL. ARGS is the
vector of template arguments, as for tsubst.
tsubst_friend_function (tree decl, tree args)
{
tree new_friend;
- location_t saved_loc = input_location;
-
- input_location = DECL_SOURCE_LOCATION (decl);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_TEMPLATE_INSTANTIATION (decl)
&new_args,
/*need_member_template=*/0,
TREE_VEC_LENGTH (args));
- new_friend = instantiate_template (tmpl, new_args, tf_error);
- goto done;
+ return instantiate_template (tmpl, new_args, tf_error);
}
new_friend = tsubst (decl, args, tf_error | tf_warning, NULL_TREE);
new_friend = old_decl;
}
}
- else if (COMPLETE_TYPE_P (DECL_CONTEXT (new_friend)))
+ else
{
- /* Check to see that the declaration is really present, and,
- possibly obtain an improved declaration. */
- tree fn = check_classfn (DECL_CONTEXT (new_friend),
- new_friend, NULL_TREE);
-
- if (fn)
- new_friend = fn;
+ tree context = DECL_CONTEXT (new_friend);
+ bool dependent_p;
+
+ /* In the code
+ template <class T> class C {
+ template <class U> friend void C1<U>::f (); // case 1
+ friend void C2<T>::f (); // case 2
+ };
+ we only need to make sure CONTEXT is a complete type for
+ case 2. To distinguish between the two cases, we note that
+ CONTEXT of case 1 remains dependent type after tsubst while
+ this isn't true for case 2. */
+ ++processing_template_decl;
+ dependent_p = dependent_type_p (context);
+ --processing_template_decl;
+
+ if (!dependent_p
+ && !complete_type_or_else (context, NULL_TREE))
+ return error_mark_node;
+
+ if (COMPLETE_TYPE_P (context))
+ {
+ /* Check to see that the declaration is really present, and,
+ possibly obtain an improved declaration. */
+ tree fn = check_classfn (context,
+ new_friend, NULL_TREE);
+
+ if (fn)
+ new_friend = fn;
+ }
}
- done:
- input_location = saved_loc;
return new_friend;
}
/* 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))
{
input_location = DECL_SOURCE_LOCATION (TYPE_NAME (pattern));
TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern);
- TYPE_HAS_DESTRUCTOR (type) = TYPE_HAS_DESTRUCTOR (pattern);
TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);
TYPE_HAS_ARRAY_NEW_OPERATOR (type) = TYPE_HAS_ARRAY_NEW_OPERATOR (pattern);
TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);
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_N_BASE_BINFOS (pbinfo))
{
tree pbase_binfo;
tree context = TYPE_CONTEXT (type);
- bool pop_p;
+ tree pushed_scope;
int i;
/* We must enter the scope containing the type, as that is where
the accessibility of types named in dependent bases are
looked up from. */
- pop_p = push_scope (context ? context : global_namespace);
+ pushed_scope = push_scope (context ? context : global_namespace);
/* Substitute into each of the bases to determine the actual
basetypes. */
/* The list is now in reverse order; correct that. */
base_list = nreverse (base_list);
- if (pop_p)
- pop_scope (context ? context : global_namespace);
+ if (pushed_scope)
+ pop_scope (pushed_scope);
}
/* Now call xref_basetypes to set up all the base-class
information. */
tree tag = t;
tree name = TYPE_IDENTIFIER (tag);
tree newtag;
-
+ bool class_template_p;
+
+ class_template_p = (TREE_CODE (tag) != ENUMERAL_TYPE
+ && TYPE_LANG_SPECIFIC (tag)
+ && CLASSTYPE_IS_TEMPLATE (tag));
+ /* If the member is a class template, then -- even after
+ substitution -- there may be dependent types in the
+ template argument list for the class. We increment
+ PROCESSING_TEMPLATE_DECL so that dependent_type_p, as
+ that function will assume that no types are dependent
+ when outside of a template. */
+ if (class_template_p)
+ ++processing_template_decl;
newtag = tsubst (tag, args, tf_error, NULL_TREE);
+ if (class_template_p)
+ --processing_template_decl;
if (newtag == error_mark_node)
continue;
if (TREE_CODE (newtag) != ENUMERAL_TYPE)
{
- if (TYPE_LANG_SPECIFIC (tag) && CLASSTYPE_IS_TEMPLATE (tag))
+ if (class_template_p)
/* Unfortunately, lookup_template_class sets
CLASSTYPE_IMPLICIT_INSTANTIATION for a partial
instantiation (i.e., for the type of a member
/* Build new CLASSTYPE_FRIEND_CLASSES. */
tree friend_type = t;
- tree new_friend_type;
+ bool adjust_processing_template_decl = false;
if (TREE_CODE (friend_type) == TEMPLATE_DECL)
- new_friend_type = tsubst_friend_class (friend_type, args);
+ {
+ friend_type = tsubst_friend_class (friend_type, args);
+ adjust_processing_template_decl = true;
+ }
+ else if (TREE_CODE (friend_type) == UNBOUND_CLASS_TEMPLATE)
+ {
+ friend_type = tsubst (friend_type, args,
+ tf_error | tf_warning, NULL_TREE);
+ if (TREE_CODE (friend_type) == TEMPLATE_DECL)
+ friend_type = TREE_TYPE (friend_type);
+ adjust_processing_template_decl = true;
+ }
+ else if (TREE_CODE (friend_type) == TYPENAME_TYPE)
+ {
+ friend_type = tsubst (friend_type, args,
+ tf_error | tf_warning, NULL_TREE);
+ /* Bump processing_template_decl for correct
+ dependent_type_p calculation. */
+ ++processing_template_decl;
+ if (dependent_type_p (friend_type))
+ adjust_processing_template_decl = true;
+ --processing_template_decl;
+ }
else if (uses_template_parms (friend_type))
- new_friend_type = tsubst (friend_type, args,
- tf_error | tf_warning, NULL_TREE);
+ friend_type = tsubst (friend_type, args,
+ tf_error | tf_warning, NULL_TREE);
else if (CLASSTYPE_USE_TEMPLATE (friend_type))
- new_friend_type = friend_type;
+ friend_type = friend_type;
else
{
tree ns = decl_namespace_context (TYPE_MAIN_DECL (friend_type));
/* The call to xref_tag_from_type does injection for friend
classes. */
push_nested_namespace (ns);
- new_friend_type =
- xref_tag_from_type (friend_type, NULL_TREE, 1);
+ friend_type =
+ xref_tag_from_type (friend_type, NULL_TREE,
+ /*tag_scope=*/ts_global);
pop_nested_namespace (ns);
}
- if (TREE_CODE (friend_type) == TEMPLATE_DECL)
+ if (adjust_processing_template_decl)
/* Trick make_friend_class into realizing that the friend
we're adding is a template, not an ordinary class. It's
important that we use make_friend_class since it will
information. */
++processing_template_decl;
- if (new_friend_type != error_mark_node)
- make_friend_class (type, new_friend_type,
- /*complain=*/false);
+ if (friend_type != error_mark_node)
+ make_friend_class (type, friend_type, /*complain=*/false);
- if (TREE_CODE (friend_type) == TEMPLATE_DECL)
+ if (adjust_processing_template_decl)
--processing_template_decl;
}
else
/* Build new DECL_FRIENDLIST. */
tree r;
+ /* The the file and line for this declaration, to
+ assist in error message reporting. Since we
+ called push_tinst_level above, we don't need to
+ restore these. */
+ input_location = DECL_SOURCE_LOCATION (t);
+
if (TREE_CODE (t) == TEMPLATE_DECL)
{
++processing_template_decl;
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. */
TREE_PURPOSE (arg));
}
-/* Substitute the ARGS into the T, which is a _DECL. TYPE is the
- (already computed) substitution of ARGS into TREE_TYPE (T), if
- appropriate. Return the result of the substitution. Issue error
- and warning messages under control of COMPLAIN. */
+/* Substitute the ARGS into the T, which is a _DECL. Return the
+ result of the substitution. Issue error and warning messages under
+ control of COMPLAIN. */
static tree
-tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
+tsubst_decl (tree t, tree args, tsubst_flags_t complain)
{
location_t saved_loc;
tree r = NULL_TREE;
{
case TEMPLATE_DECL:
{
- /* We can get here when processing a member template function
- of a template class. */
+ /* We can get here when processing a member function template,
+ member class template, and template template parameter of
+ a template class. */
tree decl = DECL_TEMPLATE_RESULT (t);
tree spec;
- int is_template_template_parm = DECL_TEMPLATE_TEMPLATE_PARM_P (t);
+ tree tmpl_args;
+ tree full_args;
- if (!is_template_template_parm)
+ if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
{
- /* We might already have an instance of this template.
- The ARGS are for the surrounding class type, so the
- full args contain the tsubst'd args for the context,
- plus the innermost args from the template decl. */
- tree tmpl_args = DECL_CLASS_TEMPLATE_P (t)
- ? CLASSTYPE_TI_ARGS (TREE_TYPE (t))
- : DECL_TI_ARGS (DECL_TEMPLATE_RESULT (t));
- tree full_args;
-
- full_args = tsubst_template_args (tmpl_args, args,
- complain, in_decl);
+ /* Template template parameter is treated here. */
+ tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ if (new_type == error_mark_node)
+ return error_mark_node;
- /* tsubst_template_args doesn't copy the vector if
- nothing changed. But, *something* should have
- changed. */
- my_friendly_assert (full_args != tmpl_args, 0);
+ r = copy_decl (t);
+ TREE_CHAIN (r) = NULL_TREE;
+ TREE_TYPE (r) = new_type;
+ DECL_TEMPLATE_RESULT (r)
+ = build_decl (TYPE_DECL, DECL_NAME (decl), new_type);
+ DECL_TEMPLATE_PARMS (r)
+ = tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args,
+ complain);
+ TYPE_NAME (new_type) = r;
+ break;
+ }
- spec = retrieve_specialization (t, full_args);
- if (spec != NULL_TREE)
- {
- r = spec;
- break;
- }
+ /* We might already have an instance of this template.
+ The ARGS are for the surrounding class type, so the
+ full args contain the tsubst'd args for the context,
+ plus the innermost args from the template decl. */
+ tmpl_args = DECL_CLASS_TEMPLATE_P (t)
+ ? CLASSTYPE_TI_ARGS (TREE_TYPE (t))
+ : DECL_TI_ARGS (DECL_TEMPLATE_RESULT (t));
+ full_args = tsubst_template_args (tmpl_args, args,
+ complain, in_decl);
+
+ /* tsubst_template_args doesn't copy the vector if
+ nothing changed. But, *something* should have
+ changed. */
+ gcc_assert (full_args != tmpl_args);
+
+ spec = retrieve_specialization (t, full_args,
+ /*class_specializations_p=*/true);
+ if (spec != NULL_TREE)
+ {
+ r = spec;
+ break;
}
/* Make a new template decl. It will be similar to the
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)
- {
- tree new_decl = tsubst (decl, args, complain, in_decl);
- DECL_TEMPLATE_RESULT (r) = new_decl;
- TREE_TYPE (r) = TREE_TYPE (new_decl);
- break;
- }
-
DECL_CONTEXT (r)
= tsubst_aggr_type (DECL_CONTEXT (t), args,
complain, in_decl,
tree argvec = NULL_TREE;
tree *friends;
tree gen_tmpl;
+ tree type;
int member;
int args_depth;
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)
{
member = 0;
ctx = DECL_CONTEXT (t);
}
- type = tsubst (type, args, complain, in_decl);
+ type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node)
return error_mark_node;
case PARM_DECL:
{
+ tree type;
+
r = copy_node (t);
if (DECL_TEMPLATE_PARM_P (t))
SET_DECL_TEMPLATE_PARM_P (r);
+ type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ type = type_decays_to (type);
TREE_TYPE (r) = type;
- c_apply_type_quals_to_decl (cp_type_quals (type), r);
+ cp_apply_type_quals_to_decl (cp_type_quals (type), r);
if (DECL_INITIAL (r))
{
case FIELD_DECL:
{
+ tree type;
+
r = copy_decl (t);
+ type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ if (type == error_mark_node)
+ return error_mark_node;
TREE_TYPE (r) = type;
- c_apply_type_quals_to_decl (cp_type_quals (type), r);
+ cp_apply_type_quals_to_decl (cp_type_quals (type), r);
/* We don't have to set DECL_CONTEXT here; it is set by
finish_member_declaration. */
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;
break;
case TYPE_DECL:
- if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
- || t == TYPE_MAIN_DECL (TREE_TYPE (t)))
- {
- /* If this is the canonical decl, we don't have to mess with
- instantiations, and often we can't (for typename, template
- type parms and such). Note that TYPE_NAME is not correct for
- the above test if we've copied the type for a typedef. */
- r = TYPE_NAME (type);
- break;
- }
-
- /* Fall through. */
-
case VAR_DECL:
{
tree argvec = NULL_TREE;
tree spec;
tree tmpl = NULL_TREE;
tree ctx;
+ tree type = NULL_TREE;
int local_p;
+ if (TREE_CODE (t) == TYPE_DECL)
+ {
+ type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
+ || t == TYPE_MAIN_DECL (TREE_TYPE (t)))
+ {
+ /* If this is the canonical decl, we don't have to
+ mess with instantiations, and often we can't (for
+ typename, template type parms and such). Note that
+ TYPE_NAME is not correct for the above test if
+ we've copied the type for a typedef. */
+ r = TYPE_NAME (type);
+ break;
+ }
+ }
+
/* Assume this is a non-local variable. */
local_p = 0;
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);
r = copy_decl (t);
if (TREE_CODE (r) == VAR_DECL)
{
+ type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ if (type == error_mark_node)
+ return error_mark_node;
type = complete_type (type);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)
= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t);
+ type = check_var_type (DECL_NAME (r), type);
}
else if (DECL_SELF_REFERENCE_P (t))
SET_DECL_SELF_REFERENCE_P (r);
TREE_TYPE (r) = type;
- c_apply_type_quals_to_decl (cp_type_quals (type), r);
+ cp_apply_type_quals_to_decl (cp_type_quals (type), r);
DECL_CONTEXT (r) = ctx;
/* Clear out the mangled name and RTL for the instantiation. */
SET_DECL_ASSEMBLER_NAME (r, NULL_TREE);
register_local_specialization (r, 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);
- /* 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);
if (return_type == error_mark_node)
return error_mark_node;
+ /* The standard does not presently indicate that creation of a
+ function type with an invalid return type is a deduction failure.
+ However, that is clearly analogous to creating an array of "void"
+ or a reference to a reference. This is core issue #486. */
+ if (TREE_CODE (return_type) == ARRAY_TYPE
+ || TREE_CODE (return_type) == FUNCTION_TYPE)
+ {
+ if (complain & tf_error)
+ {
+ if (TREE_CODE (return_type) == ARRAY_TYPE)
+ error ("function returning an array");
+ else
+ error ("function returning a function");
+ }
+ return error_mark_node;
+ }
/* Substitute the argument types. */
arg_types = tsubst_arg_types (TYPE_ARG_TYPES (t), args,
-- 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;
+ if (DECL_P (t))
+ return tsubst_decl (t, args, complain);
+
if (TREE_CODE (t) == IDENTIFIER_NODE)
type = IDENTIFIER_TYPE_VALUE (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
+ if (type
&& TREE_CODE (t) != TYPENAME_TYPE
- && TREE_CODE (t) != TEMPLATE_DECL
&& TREE_CODE (t) != IDENTIFIER_NODE
&& TREE_CODE (t) != FUNCTION_TYPE
&& TREE_CODE (t) != METHOD_TYPE)
if (type == error_mark_node)
return error_mark_node;
- if (DECL_P (t))
- return tsubst_decl (t, args, type, complain);
-
switch (TREE_CODE (t))
{
case RECORD_TYPE:
/* The array dimension behaves like a non-type template arg,
in that we want to fold it as much as possible. */
max = tsubst_template_arg (omax, args, complain, in_decl);
- if (!processing_template_decl)
- max = decl_constant_value (max);
+ max = fold_decl_constant_value (max);
if (integer_zerop (omax))
{
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
- this pointer should _not_ be determined by the cv
- qualifiers of the class type. They should be held
- somewhere in the FUNCTION_TYPE, but we don't do that at
- the moment. Consider
- typedef void (Func) () const;
-
- template <typename T1> void Foo (Func T1::*);
-
- */
+ /* The type of the implicit object parameter gets its
+ cv-qualifiers from the FUNCTION_TYPE. */
tree method_type;
-
- method_type = build_method_type_directly (TYPE_MAIN_VARIANT (r),
+ tree this_type = cp_build_qualified_type (TYPE_MAIN_VARIANT (r),
+ cp_type_quals (type));
+ tree memptr;
+ method_type = build_method_type_directly (this_type,
TREE_TYPE (type),
TYPE_ARG_TYPES (type));
- return build_ptrmemfunc_type (build_pointer_type (method_type));
+ memptr = build_ptrmemfunc_type (build_pointer_type (method_type));
+ return cp_build_qualified_type_real (memptr, cp_type_quals (t),
+ complain);
}
else
return cp_build_qualified_type_real (build_ptrmem_type (r, type),
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))
}
}
- f = make_typename_type (ctx, f,
+ f = make_typename_type (ctx, f, typename_type,
(complain & tf_error) | tf_keep_type_decl);
if (f == error_mark_node)
return f;
f = TREE_TYPE (f);
}
+ if (TREE_CODE (f) != TYPENAME_TYPE)
+ {
+ if (TYPENAME_IS_ENUM_P (t) && TREE_CODE (f) != ENUMERAL_TYPE)
+ error ("%qT resolves to %qT, which is not an enumeration type",
+ t, f);
+ else if (TYPENAME_IS_CLASS_P (t) && !CLASS_TYPE_P (f))
+ error ("%qT resolves to %qT, which is is not a class type",
+ t, f);
+ }
+
return cp_build_qualified_type_real
(f, cp_type_quals (f) | cp_type_quals (t), complain);
}
tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, complain,
in_decl, /*entering_scope=*/1);
tree name = TYPE_IDENTIFIER (t);
+ tree parm_list = DECL_TEMPLATE_PARMS (TYPE_NAME (t));
if (ctx == error_mark_node || name == error_mark_node)
return error_mark_node;
- return make_unbound_class_template (ctx, name, complain);
+ if (parm_list)
+ parm_list = tsubst_template_parms (parm_list, args, complain);
+ return make_unbound_class_template (ctx, name, parm_list, complain);
}
case INDIRECT_REF:
case ADDR_EXPR:
case CALL_EXPR:
- abort ();
+ gcc_unreachable ();
case ARRAY_REF:
{
}
default:
- sorry ("use of `%s' in template",
+ sorry ("use of %qs in template",
tree_code_name [(int) TREE_CODE (t)]);
return error_mark_node;
}
}
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
(expr, scope, current_class_type));
expr = finish_qualified_id_expr (scope, expr, done, address_p);
}
+
+ expr = convert_from_reference (expr);
return expr;
}
{
case PARM_DECL:
r = retrieve_local_specialization (t);
- my_friendly_assert (r != NULL, 20020903);
+ gcc_assert (r != NULL);
mark_used (r);
return r;
return t;
/* If ARGS is NULL, then T is known to be non-dependent. */
if (args == NULL_TREE)
- return decl_constant_value (t);
+ return integral_constant_value (t);
/* Unfortunately, we cannot just call lookup_name here.
Consider:
/* 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;
ctx = tsubst_aggr_type (DECL_CONTEXT (t), args, complain, in_decl,
/*entering_scope=*/1);
if (ctx != DECL_CONTEXT (t))
- return lookup_field (ctx, DECL_NAME (t), 0, false);
+ {
+ tree r = lookup_field (ctx, DECL_NAME (t), 0, false);
+ if (!r)
+ {
+ if (complain & tf_error)
+ error ("using invalid field %qD", t);
+ return error_mark_node;
+ }
+ return r;
+ }
}
return t;
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)))
case GE_EXPR:
case LT_EXPR:
case GT_EXPR:
- case ARRAY_REF:
case COMPOUND_EXPR:
case SCOPE_REF:
case DOTSTAR_EXPR:
(code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
+ case ARRAY_REF:
+ return build_nt
+ (ARRAY_REF,
+ tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
+ NULL_TREE, NULL_TREE);
+
case CALL_EXPR:
return build_nt (code,
tsubst_copy (TREE_OPERAND (t, 0), args,
(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);
}
case SWITCH_STMT:
stmt = begin_switch_stmt ();
- tmp = tsubst_expr (SWITCH_COND (t), args, complain, in_decl);
+ tmp = tsubst_expr (SWITCH_STMT_COND (t), args, complain, in_decl);
finish_switch_cond (tmp, stmt);
- tsubst_expr (SWITCH_BODY (t), args, complain, in_decl);
+ tsubst_expr (SWITCH_STMT_BODY (t), args, complain, in_decl);
finish_switch_stmt (stmt);
break;
tsubst_expr (ASM_OUTPUTS (t), args, complain, in_decl),
tsubst_expr (ASM_INPUTS (t), args, complain, in_decl),
tsubst_expr (ASM_CLOBBERS (t), args, complain, in_decl));
- ASM_INPUT_P (tmp) = ASM_INPUT_P (t);
+ {
+ tree asm_expr = tmp;
+ if (TREE_CODE (asm_expr) == CLEANUP_POINT_EXPR)
+ asm_expr = TREE_OPERAND (asm_expr, 0);
+ ASM_INPUT_P (asm_expr) = ASM_INPUT_P (t);
+ }
break;
case TRY_BLOCK:
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;
}
case INDIRECT_REF:
- return build_x_indirect_ref (RECUR (TREE_OPERAND (t, 0)), "unary *");
+ {
+ tree r = RECUR (TREE_OPERAND (t, 0));
+
+ if (REFERENCE_REF_P (t))
+ {
+ /* A type conversion to reference type will be enclosed in
+ such an indirect ref, but the substitution of the cast
+ will have also added such an indirect ref. */
+ if (TREE_CODE (TREE_TYPE (r)) == REFERENCE_TYPE)
+ r = convert_from_reference (r);
+ }
+ else
+ r = build_x_indirect_ref (r, "unary *");
+ return r;
+ }
case NOP_EXPR:
return build_nop
case SCOPE_REF:
return tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
/*address_p=*/false);
-
case ARRAY_REF:
- if (tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl)
- == NULL_TREE)
- /* new-type-id */
- return build_nt (ARRAY_REF, NULL_TREE, RECUR (TREE_OPERAND (t, 1)),
- NULL_TREE, NULL_TREE);
-
op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
args, complain, in_decl);
- /* Remember that there was a reference to this entity. */
- if (DECL_P (op1))
- mark_used (op1);
- return grok_array_decl (op1, RECUR (TREE_OPERAND (t, 1)));
-
+ return build_x_binary_op (ARRAY_REF, op1, RECUR (TREE_OPERAND (t, 1)),
+ /*overloaded_p=*/NULL);
+
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
op1 = TREE_OPERAND (t, 0);
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),
lookup finds a non-function, in accordance with the
expected resolution of DR 218. */
if (koenig_p
- && (is_overloaded_fn (function)
+ && ((is_overloaded_fn (function)
+ /* If lookup found a member function, the Koenig lookup is
+ not appropriate, even if an unqualified-name was used
+ to denote the function. */
+ && !DECL_FUNCTION_MEMBER_P (get_first_fn (function)))
|| TREE_CODE (function) == IDENTIFIER_NODE))
function = perform_koenig_lookup (function, call_args);
if (DECL_P (function))
mark_used (function);
- function = convert_from_reference (function);
-
if (TREE_CODE (function) == OFFSET_REF)
return build_offset_ref_call_from_tree (function, call_args);
if (TREE_CODE (function) == COMPONENT_REF)
else
member = tsubst_copy (member, args, complain, in_decl);
- if (!CLASS_TYPE_P (TREE_TYPE (object)))
+ if (member == error_mark_node)
+ return error_mark_node;
+ else if (!CLASS_TYPE_P (TREE_TYPE (object)))
{
if (TREE_CODE (member) == BIT_NOT_EXPR)
return finish_pseudo_destructor_expr (object,
/*is_type_p=*/false,
/*complain=*/false);
if (BASELINK_P (member))
- BASELINK_FUNCTIONS (member)
- = build_nt (TEMPLATE_ID_EXPR, BASELINK_FUNCTIONS (member),
- args);
+ {
+ BASELINK_FUNCTIONS (member)
+ = build_nt (TEMPLATE_ID_EXPR, BASELINK_FUNCTIONS (member),
+ args);
+ member = (adjust_result_of_qualified_name_lookup
+ (member, BINFO_TYPE (BASELINK_BINFO (member)),
+ TREE_TYPE (object)));
+ }
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);
return build_typeid (operand_0);
}
- case PARM_DECL:
- return convert_from_reference (tsubst_copy (t, args, complain, in_decl));
-
case VAR_DECL:
- if (args)
- t = tsubst_copy (t, args, complain, in_decl);
- return convert_from_reference (t);
+ if (!args)
+ return t;
+ /* Fall through */
+
+ case PARM_DECL:
+ {
+ tree r = tsubst_copy (t, args, complain, in_decl);
+
+ if (TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE)
+ /* If the original type was a reference, we'll be wrapped in
+ the appropriate INDIRECT_REF. */
+ r = convert_from_reference (r);
+ return r;
+ }
case VA_ARG_EXPR:
return build_x_va_arg (RECUR (TREE_OPERAND (t, 0)),
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;
+ }
+
+ case CONST_DECL:
+ t = tsubst_copy (t, args, complain, in_decl);
+ /* As in finish_id_expression, we resolve enumeration constants
+ to their underlying values. */
+ if (TREE_CODE (t) == CONST_DECL)
+ return DECL_INITIAL (t);
+ return t;
+
default:
return tsubst_copy (t, args, complain, in_decl);
}
{
int ix, len = DECL_NTPARMS (tmpl);
bool result = false;
+ bool error_p = complain & tf_error;
for (ix = 0; ix != len; ix++)
{
if (nt)
{
- if (!(complain & tf_error))
- /*OK*/;
- else if (TYPE_ANONYMOUS_P (nt))
- error ("`%T' uses anonymous type", t);
+ if (TYPE_ANONYMOUS_P (nt))
+ error ("%qT is/uses anonymous type", t);
else
- error ("`%T' uses local type `%T'", t, nt);
+ error ("%qT uses local type %qT", t, nt);
result = true;
+ error_p = true;
}
/* In order to avoid all sorts of complications, we do not
allow variably-modified types as template arguments. */
else if (variably_modified_type_p (t, NULL_TREE))
{
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);
+ if (result && error_p)
+ 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))
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)
tree converted_args;
bool incomplete;
+ if (explicit_targs == error_mark_node)
+ return 1;
+
converted_args
= (coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (fn),
explicit_targs, NULL_TREE, tf_none,
}
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. */
-
-static tree
-get_template_base_recursive (tree tparms,
- tree targs,
- tree parm,
- tree arg_binfo,
- tree rval,
- int flags)
-{
- tree base_binfo;
- int i;
- 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:
-
- [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;
- }
-
- /* Process base types. */
- for (i = 0; BINFO_BASE_ITERATE (arg_binfo, i, base_binfo); i++)
- {
- int this_virtual;
-
- /* Skip this base, if we've already seen it. */
- if (BINFO_MARKED (base_binfo))
- continue;
-
- 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. */
+ 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 (tree tparms, tree targs, tree parm, tree arg)
{
- tree rval;
- tree arg_binfo;
+ tree rval = NULL_TREE;
+ tree binfo;
- my_friendly_assert (IS_AGGR_TYPE_CODE (TREE_CODE (arg)), 92);
+ gcc_assert (IS_AGGR_TYPE_CODE (TREE_CODE (arg)));
- arg_binfo = TYPE_BINFO (complete_type (arg));
- if (!arg_binfo)
+ binfo = TYPE_BINFO (complete_type (arg));
+ if (!binfo)
/* The type could not be completed. */
return NULL_TREE;
-
- rval = get_template_base_recursive (tparms, targs,
- parm, arg_binfo,
- NULL_TREE,
- GTB_IGNORE_TYPE);
- /* Since get_template_base_recursive marks the bases classes, we
- must unmark them here. */
- dfs_walk (arg_binfo, dfs_unmark, markedp, 0);
+ /* 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 r = try_class_unification (tparms, targs, parm, BINFO_TYPE (binfo));
+
+ if (r)
+ {
+ /* If there is more than one satisfactory baseclass, then:
+
+ [temp.deduct.call]
+
+ If they yield more than one possible deduced A, the type
+ deduction fails.
+
+ 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))
{
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;
}
}
DEDUCE_EXACT, 0, -1);
case OFFSET_TYPE:
+ /* Unify a pointer to member with a pointer to member function, which
+ deduces the type of the member as a function type. */
+ if (TYPE_PTRMEMFUNC_P (arg))
+ {
+ tree method_type;
+ tree fntype;
+ cp_cv_quals cv_quals;
+
+ /* Check top-level cv qualifiers */
+ if (!check_cv_quals_for_unify (UNIFY_ALLOW_NONE, arg, parm))
+ return 1;
+
+ if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
+ TYPE_PTRMEMFUNC_OBJECT_TYPE (arg), UNIFY_ALLOW_NONE))
+ return 1;
+
+ /* Determine the type of the function we are unifying against. */
+ method_type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (arg));
+ fntype =
+ build_function_type (TREE_TYPE (method_type),
+ TREE_CHAIN (TYPE_ARG_TYPES (method_type)));
+
+ /* Extract the cv-qualifiers of the member function from the
+ implicit object parameter and place them on the function
+ type to be restored later. */
+ cv_quals =
+ cp_type_quals(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (method_type))));
+ fntype = build_qualified_type (fntype, cv_quals);
+ return unify (tparms, targs, TREE_TYPE (parm), fntype, strict);
+ }
+
if (TREE_CODE (arg) != OFFSET_TYPE)
return 1;
if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
case CONST_DECL:
if (DECL_TEMPLATE_PARM_P (parm))
return unify (tparms, targs, DECL_INITIAL (parm), arg, strict);
- if (arg != decl_constant_value (parm))
+ if (arg != integral_constant_value (parm))
return 1;
return 0;
/* 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
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
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 `%#D'", result);
+ 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)
}
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);
if (! extern_p)
/* Called from do_type_instantiation to instantiate a member
(a member function or a static member variable) of an
- explicitly instantiated class template. */
+ explicitly instantiated class template. */
static void
instantiate_class_member (tree decl, int extern_p)
{
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;
}
if (storage != NULL_TREE)
{
if (pedantic && !in_system_header)
- pedwarn("ISO C++ forbids the use of `%E' on explicit instantiations",
+ pedwarn("ISO C++ forbids the use of %qE on explicit instantiations",
storage);
if (storage == ridpointers[(int) RID_INLINE])
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 && !extern_p
&& (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))
we don't have any arguments for them. Note that the standard
is unclear on whether the instantiation of the members are
*explicit* instantiations or not. However, the most natural
- interpretation is that it should be an explicit instantiation. */
+ interpretation is that it should be an explicit instantiation. */
if (! static_p)
for (tmp = TYPE_METHODS (t); tmp; tmp = TREE_CHAIN (tmp))
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);
+ parm_type = type_decays_to (parm_type);
+ 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);
If UNDEFINED_OK is nonzero, then instead we treat it as an implicit
instantiation. UNDEFINED_OK is nonzero only if we are being used
to instantiate the members of an explicitly instantiated class
- template. */
+ template. */
tree
/* 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;
/* We should have set up DECL_INITIAL in instantiate_class_template
for in-class definitions of static data members. */
- my_friendly_assert (!(TREE_CODE (d) == VAR_DECL
- && DECL_INITIALIZED_IN_CLASS_P (d)
- && DECL_INITIAL (d) == NULL_TREE),
- 20040726);
+ 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. */
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;
/* Instantiate inline functions so that the inliner can do its
job, even though we'll not be emitting a copy of this
function. */
- if (!flag_inline_trees || !DECL_DECLARED_INLINE_P (d))
+ if (!(TREE_CODE (d) == FUNCTION_DECL
+ && flag_inline_trees
+ && DECL_DECLARED_INLINE_P (d)))
goto out;
}
we have a chance to determine linkage. */
DECL_EXTERNAL (d) = 0;
- /* This is done in analogous to `start_decl'. It is required
- for correct access checking. */
+ /* 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);
- /* 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 ();
+ pop_nested_class ();
}
else if (TREE_CODE (d) == FUNCTION_DECL)
{
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
{
tree decl;
tree init;
- tree val;
decl = tsubst_copy (TREE_PURPOSE (t), argvec, tf_error | tf_warning,
NULL_TREE);
init = tsubst_expr (TREE_VALUE (t), argvec, tf_error | tf_warning,
NULL_TREE);
- if (!init)
- ;
- else if (TREE_CODE (init) == TREE_LIST)
- for (val = init; val; val = TREE_CHAIN (val))
- TREE_VALUE (val) = convert_from_reference (TREE_VALUE (val));
- else if (init != void_type_node)
- init = convert_from_reference (init);
-
in_base_initializer = 0;
if (decl)
/* 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);
;
else
{
- int i;
+ int i, save_access_control;
tree partial_args;
/* Replace the innermost level of the TARGS with NULL_TREEs to
TMPL_ARGS_DEPTH (targs),
make_tree_vec (DECL_NTPARMS (tmpl)));
- /* Make sure that we can see identifiers, and compute access
- correctly. We can just use the context of DECL for the
- partial substitution here. It depends only on outer template
- parameters, regardless of whether the innermost level is
- specialized or not. */
- push_access_scope (decl);
+ /* Disable access control as this function is used only during
+ name-mangling. */
+ save_access_control = flag_access_control;
+ flag_access_control = 0;
++processing_template_decl;
/* Now, do the (partial) substitution to figure out the
TREE_VEC_LENGTH (partial_args)--;
tparms = tsubst_template_parms (tparms, partial_args, tf_error);
- pop_access_scope (decl);
+ flag_access_control = save_access_control;
}
return fn_type;
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;
}
if (TREE_CODE (expression) == COMPONENT_REF)
return (value_dependent_expression_p (TREE_OPERAND (expression, 0))
|| value_dependent_expression_p (TREE_OPERAND (expression, 1)));
+
+ /* A CALL_EXPR is value-dependent if any argument is
+ value-dependent. Why do we have to handle CALL_EXPRs in this
+ function at all? First, some function calls, those for which
+ value_dependent_expression_p is true, man appear in constant
+ expressions. Second, there appear to be bugs which result in
+ other CALL_EXPRs reaching this point. */
+ if (TREE_CODE (expression) == CALL_EXPR)
+ {
+ tree function = TREE_OPERAND (expression, 0);
+ tree args = TREE_OPERAND (expression, 1);
+
+ if (value_dependent_expression_p (function))
+ return true;
+ else if (! args)
+ return false;
+ else if (TREE_CODE (args) == TREE_LIST)
+ {
+ do
+ {
+ if (value_dependent_expression_p (TREE_VALUE (args)))
+ return true;
+ args = TREE_CHAIN (args);
+ }
+ while (args);
+ return false;
+ }
+ else
+ return value_dependent_expression_p (args);
+ }
/* 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)
+ for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (expression)); ++i)
/* In some cases, some of the operands may be missing.
(For example, in the case of PREDECREMENT_EXPR, the
amount to increment by may be missing.) That doesn't
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)))
tree name;
tree decl;
int quals;
- bool pop_p;
+ tree pushed_scope;
- my_friendly_assert (TREE_CODE (type) == TYPENAME_TYPE,
- 20010702);
+ gcc_assert (TREE_CODE (type) == TYPENAME_TYPE);
scope = TYPE_CONTEXT (type);
name = TYPE_IDENTIFIER (type);
/* Enter the SCOPE so that name lookup will be resolved as if we
were in the class definition. In particular, SCOPE will no
longer be considered a dependent type. */
- pop_p = push_scope (scope);
+ pushed_scope = push_scope (scope);
/* Look up the declaration. */
decl = lookup_member (scope, name, /*protect=*/0, /*want_type=*/true);
/* Obtain the set of qualifiers applied to the TYPE. */
if (type != error_mark_node && quals)
type = cp_build_qualified_type (type, quals);
/* Leave the SCOPE. */
- if (pop_p)
- pop_scope (scope);
+ if (pushed_scope)
+ pop_scope (pushed_scope);
return type;
}
if (TREE_CODE (inner_expr) == OVERLOAD
|| TREE_CODE (inner_expr) == FUNCTION_DECL
|| TREE_CODE (inner_expr) == TEMPLATE_DECL
- || TREE_CODE (inner_expr) == TEMPLATE_ID_EXPR)
+ || TREE_CODE (inner_expr) == TEMPLATE_ID_EXPR
+ || TREE_CODE (inner_expr) == OFFSET_REF)
+ return expr;
+ /* There is no need to return a proxy for a variable. */
+ if (TREE_CODE (expr) == VAR_DECL)
return expr;
/* Preserve string constants; conversions from string constants to
"char *" are allowed, even though normally a "const char *"
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.