/* 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).
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Known bugs or deficiencies include:
#include "tm.h"
#include "obstack.h"
#include "tree.h"
+#include "pointer-set.h"
#include "flags.h"
+#include "c-common.h"
#include "cp-tree.h"
+#include "cp-objcp-common.h"
#include "tree-inline.h"
#include "decl.h"
#include "output.h"
#define UNIFY_ALLOW_OUTER_LEVEL 16
#define UNIFY_ALLOW_OUTER_MORE_CV_QUAL 32
#define UNIFY_ALLOW_OUTER_LESS_CV_QUAL 64
-#define UNIFY_ALLOW_MAX_CORRECTION 128
static void push_access_scope (tree);
static void pop_access_scope (tree);
static tree add_to_template_args (tree, tree);
static tree add_outermost_template_args (tree, tree);
static bool check_instantiated_args (tree, tree, tsubst_flags_t);
-static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*);
+static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*);
static int type_unification_real (tree, tree, tree, tree,
- int, unification_kind_t, int, int);
+ int, unification_kind_t, 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 tsubst_friend_function (tree, tree);
static tree tsubst_friend_class (tree, tree);
static int can_complete_type_without_circularity (tree);
-static tree get_bindings (tree, tree, tree);
-static tree get_bindings_real (tree, tree, tree, int, int, int);
+static tree get_bindings (tree, tree, tree, bool);
static int template_decl_level (tree);
static int check_cv_quals_for_unify (int, tree, tree);
static tree tsubst_template_arg (tree, tree, tsubst_flags_t, 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);
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 ();
-
+
if (TREE_CODE (t) == FUNCTION_DECL)
{
saved_access_scope = tree_cons
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 ();
tree type;
type = TREE_TYPE (decl);
- if (IS_AGGR_TYPE (type)
+ if (IS_AGGR_TYPE (type)
&& CLASSTYPE_TEMPLATE_INFO (type)
&& !CLASSTYPE_TEMPLATE_SPECIALIZATION (type))
{
}
else
return decl;
- }
+ }
else
error ("invalid member template declaration %qD", decl);
}
/* Returns the template nesting level of the indicated class TYPE.
-
+
For example, in:
template <class T>
struct A
struct B {};
};
- A<T>::B<U> has depth two, while A<T> has depth one.
+ A<T>::B<U> has depth two, while A<T> has depth one.
Both A<T>::B<int> and A<int>::B<U> have depth one, if
COUNT_SPECIALIZATIONS is 0 or if they are instantiations, not
- specializations.
+ specializations.
This function is guaranteed to return 0 if passed NULL_TREE so
that, for example, `template_class_depth (current_class_type)' is
always safe. */
-static int
+static int
template_class_depth_real (tree type, int count_specializations)
{
int depth;
- for (depth = 0;
+ for (depth = 0;
type && TREE_CODE (type) != NAMESPACE_DECL;
- type = (TREE_CODE (type) == FUNCTION_DECL)
+ type = (TREE_CODE (type) == FUNCTION_DECL)
? CP_DECL_CONTEXT (type) : TYPE_CONTEXT (type))
{
if (TREE_CODE (type) != FUNCTION_DECL)
|| uses_template_parms (CLASSTYPE_TI_ARGS (type))))
++depth;
}
- else
+ else
{
if (DECL_TEMPLATE_INFO (type)
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (type))
Like template_class_depth_real, but instantiations do not count in
the depth. */
-int
+int
template_class_depth (tree type)
{
return template_class_depth_real (type, /*count_specializations=*/0);
TEMPLATE_PARMS_FOR_INLINE (current_template_parms) = 1;
begin_scope (TREE_VEC_LENGTH (parms) ? sk_template_parms : sk_template_spec,
- NULL);
- for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
+ NULL);
+ for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
{
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
gcc_assert (DECL_P (parm));
++inline_parm_levels_used;
}
-/* Undo the effects of begin_member_template_processing. */
+/* Undo the effects of maybe_begin_member_template_processing. */
-void
+void
maybe_end_member_template_processing (void)
{
int i;
return;
--inline_parm_levels_used;
- for (i = 0;
+ for (i = 0;
i < VARRAY_INT (inline_parm_levels, inline_parm_levels_used);
- ++i)
+ ++i)
{
--processing_template_decl;
current_template_parms = TREE_CHAIN (current_template_parms);
for (j = 1; j <= extra_depth; ++j, ++i)
SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (extra_args, j));
-
+
return new_args;
}
/* For the moment, we make ARGS look like it contains fewer levels. */
TREE_VEC_LENGTH (args) -= TMPL_ARGS_DEPTH (extra_args);
-
+
new_args = add_to_template_args (args, extra_args);
/* Now, we restore ARGS to its full dimensions. */
/* If N is 1, just return the innermost set of template arguments. */
if (n == 1)
return TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args));
-
+
/* If we're not removing anything, just return the arguments we were
given. */
extra_levels = TMPL_ARGS_DEPTH (args) - n;
/* Make a new set of arguments, not containing the outer arguments. */
new_args = make_tree_vec (n);
for (i = 1; i <= n; ++i)
- SET_TMPL_ARGS_LEVEL (new_args, i,
+ SET_TMPL_ARGS_LEVEL (new_args, i,
TMPL_ARGS_LEVEL (args, i + extra_levels));
return new_args;
e.g.:
template <class T> struct S1 {
- template <class T> struct S2 {};
+ template <class T> struct S2 {};
};
pushtag contains special code to call pushdecl_with_scope on the
{
tree scope = current_scope ();
- /* [temp.expl.spec]
-
+ /* [temp.expl.spec]
+
An explicit specialization shall be declared in the namespace of
which the template is a member, or, for member templates, in the
namespace of which the enclosing class or enclosing class
if (scope && TREE_CODE (scope) != NAMESPACE_DECL)
error ("explicit specialization in non-namespace scope %qD", scope);
- /* [temp.expl.spec]
+ /* [temp.expl.spec]
In an explicit specialization declaration for a member of a class
template or a member template that appears in namespace scope,
remain unspecialized, except that the declaration shall not
explicitly specialize a class member template if its enclosing
class templates are not explicitly specialized as well. */
- if (current_template_parms)
+ if (current_template_parms)
error ("enclosing class templates are not explicitly specialized");
}
/* Called at then end of processing a declaration preceded by
template<>. */
-void
+void
end_specialization (void)
{
finish_scope ();
/* We've just seen a template header. If SPECIALIZATION is nonzero,
it was of the form template <>. */
-static void
+static void
note_template_header (int specialization)
{
processing_specialization = specialization;
declared. Check that the namespace in which the specialization is
occurring is permissible. Returns false iff it is invalid to
specialize TMPL in the current namespace. */
-
+
static bool
check_specialization_namespace (tree tmpl)
{
tree tpl_ns = decl_namespace_context (tmpl);
/* [tmpl.expl.spec]
-
+
An explicit specialization shall be declared in the namespace of
which the template is a member, or, for member templates, in the
namespace of which the enclosing class or enclosing class
/* The TYPE is being declared. If it is a template type, that means it
is a partial specialization. Do appropriate error-checking. */
-void
+void
maybe_process_partial_specialization (tree type)
{
/* TYPE maybe an ERROR_MARK_NODE. */
for TMPL, a TEMPLATE_DECL. In particular, for such a template, we
do not use DECL_TEMPLATE_SPECIALIZATIONS at all. */
-static inline bool
+static inline bool
optimize_specialization_lookup_p (tree tmpl)
{
return (DECL_FUNCTION_TEMPLATE_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>
+
+ 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
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)
{
gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
/* There should be as many levels of arguments as there are
levels of parameters. */
- gcc_assert (TMPL_ARGS_DEPTH (args)
+ 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;
+ VEC(tree,gc) *methods;
tree fns;
int idx;
class. Find the class specialization with those
arguments. */
class_template = CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (tmpl));
- class_specialization
+ class_specialization
= retrieve_specialization (class_template, args,
/*class_specializations_p=*/false);
if (!class_specialization)
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. */
+ searches. */
if (spec != *head)
{
*sp = TREE_CHAIN (*sp);
if (TREE_CODE (decl) == FUNCTION_DECL)
{
- for (t = decl;
+ for (t = decl;
t != NULL_TREE;
t = DECL_TEMPLATE_INFO (t) ? DECL_TI_TEMPLATE (t) : NULL_TREE)
if (t == tmpl)
return 1;
}
- else
+ else
{
gcc_assert (TREE_CODE (decl) == TYPE_DECL);
? TREE_TYPE (CLASSTYPE_TI_TEMPLATE (t)) : NULL_TREE)
if (same_type_ignoring_top_level_qualifiers_p (t, TREE_TYPE (tmpl)))
return 1;
- }
+ }
return 0;
}
bool need_template = true;
int template_depth;
- gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+ 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
non-template class. In this case, the corresponding member of
every specialization of the class template is a friend of the
class granting friendship.
-
+
For example, given a template friend declaration
template <class T> friend void A<T>::f();
template_depth = template_class_depth (DECL_CONTEXT (friend));
if (template_depth
&& DECL_CLASS_SCOPE_P (decl)
- && is_specialization_of (TYPE_NAME (DECL_CONTEXT (decl)),
+ && is_specialization_of (TYPE_NAME (DECL_CONTEXT (decl)),
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
gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
- if (TREE_CODE (spec) == FUNCTION_DECL
+ if (TREE_CODE (spec) == FUNCTION_DECL
&& uses_template_parms (DECL_TI_ARGS (spec)))
/* This is the FUNCTION_DECL for a partial instantiation. Don't
register it; we want the corresponding TEMPLATE_DECL instead.
with default function arguments. In particular, given
something like this:
- template <class T> void f(T t1, T t = T())
+ template <class T> void f(T t1, T t = T())
the default argument expression is not substituted for in an
instantiation unless and until it is actually needed. */
return spec;
- /* There should be as many levels of arguments as there are
- levels of parameters. */
- gcc_assert (TMPL_ARGS_DEPTH (args)
- == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)));
-
- fn = retrieve_specialization (tmpl, args,
+ 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
{
if (DECL_TEMPLATE_INSTANTIATION (fn))
{
- if (TREE_USED (fn)
+ if (TREE_USED (fn)
|| DECL_EXPLICIT_INSTANTIATION (fn))
{
error ("specialization of %qD after instantiation",
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);
-
+ template <> void foo(int);
+
We transform the existing DECL in place so that any
pointers to it become pointers to the updated
declaration.
there were no definition, and vice versa. */
DECL_INITIAL (fn) = NULL_TREE;
duplicate_decls (spec, fn);
-
+
return fn;
}
}
line number so any errors match this new
definition. */
DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (spec);
-
+
return fn;
}
}
{
void **slot;
- slot = htab_find_slot_with_hash (local_specializations, tmpl,
+ slot = htab_find_slot_with_hash (local_specializations, tmpl,
htab_hash_pointer (tmpl), INSERT);
*slot = build_tree_list (spec, tmpl);
}
issued. The error_mark_node is returned to indicate failure. */
static tree
-determine_specialization (tree template_id,
- tree decl,
- tree* targs_out,
+determine_specialization (tree template_id,
+ tree decl,
+ tree* targs_out,
int need_member_template,
int template_count)
{
specialization. */
header_count = 0;
for (b = current_binding_level;
- b->kind == sk_template_parms || b->kind == sk_template_spec;
+ b->kind == sk_template_parms;
b = b->level_chain)
++header_count;
/* Adjust the type of DECL in case FN is a static member. */
decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
- if (DECL_STATIC_FUNCTION_P (fn)
+ if (DECL_STATIC_FUNCTION_P (fn)
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
decl_arg_types = TREE_CHAIN (decl_arg_types);
the const qualification is the same. This can be done by
checking the 'this' in the argument list. */
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
- && !same_type_p (TREE_VALUE (fn_arg_types),
+ && !same_type_p (TREE_VALUE (fn_arg_types),
TREE_VALUE (decl_arg_types)))
continue;
is a template member function. So both lines are syntactically
correct, and check_explicit_specialization does not reject
them.
-
+
Here, we can do better, as we are matching the specialization
against the declarations. We count the number of template
headers, and we check if they match TEMPLATE_COUNT + 1
(TEMPLATE_COUNT is the number of qualifying template classes,
plus there must be another header for the member template
itself).
-
+
Notice that if header_count is zero, this is not a
specialization but rather a template instantiation, so there
is no check we can perform here. */
if (header_count && header_count != template_count + 1)
continue;
+ /* Check that the number of template arguments at the
+ innermost level for DECL is the same as for FN. */
+ if (current_binding_level->kind == sk_template_parms
+ && !current_binding_level->explicit_spec_p
+ && (TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (fn))
+ != TREE_VEC_LENGTH (TREE_VALUE (current_template_parms))))
+ continue;
+
/* See whether this function might be a specialization of this
template. */
- targs = get_bindings (fn, decl, explicit_targs);
+ targs = get_bindings (fn, decl, explicit_targs, /*check_ret=*/true);
if (!targs)
/* We cannot deduce template arguments that when used to
/* This is an ordinary member function. However, since
we're here, we can assume it's enclosing class is a
template class. For example,
-
+
template <typename T> struct S { void f(); };
template <> void S<int>::f() {}
/* Adjust the type of DECL in case FN is a static member. */
decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
- if (DECL_STATIC_FUNCTION_P (fn)
+ if (DECL_STATIC_FUNCTION_P (fn)
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
decl_arg_types = TREE_CHAIN (decl_arg_types);
- if (compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
+ if (compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
decl_arg_types))
/* They match! */
candidates = tree_cons (NULL_TREE, fn, candidates);
if (templates && TREE_CHAIN (templates))
{
/* We have:
-
+
[temp.expl.spec]
It is possible for a specialization with a given function
Partial ordering of overloaded function template
declarations is used in the following contexts to select
the function template to which a function template
- specialization refers:
+ specialization refers:
- -- when an explicit specialization refers to a function
- template.
+ -- when an explicit specialization refers to a function
+ template.
So, we do use the partial ordering rules, at least for now.
This extension can only serve to make invalid programs valid,
tree tmpl = most_specialized (templates, decl, explicit_targs);
if (tmpl && tmpl != error_mark_node)
{
- targs = get_bindings (tmpl, decl, explicit_targs);
+ targs = get_bindings (tmpl, decl, explicit_targs, /*check_ret=*/true);
templates = tree_cons (targs, tmpl, NULL_TREE);
}
}
if (templates == NULL_TREE && candidates == NULL_TREE)
{
cp_error_at ("template-id %qD for %q+D does not match any template "
- "declaration",
+ "declaration",
template_id, decl);
return error_mark_node;
}
if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (targs))
{
*targs_out = copy_node (targs);
- SET_TMPL_ARGS_LEVEL (*targs_out,
+ SET_TMPL_ARGS_LEVEL (*targs_out,
TMPL_ARGS_DEPTH (*targs_out),
TREE_PURPOSE (templates));
}
/* Returns a chain of parameter types, exactly like the SPEC_TYPES,
but with the default argument values filled in from those in the
TMPL_TYPES. */
-
+
static tree
copy_default_args_to_explicit_spec_1 (tree spec_types,
tree tmpl_types)
new_spec_types =
copy_default_args_to_explicit_spec_1 (TREE_CHAIN (spec_types),
TREE_CHAIN (tmpl_types));
-
+
/* Add the default argument for this parameter. */
return hash_tree_cons (TREE_PURPOSE (tmpl_types),
TREE_VALUE (spec_types),
template <class T> void f(T = 3);
template <> void f(double);
- void g () { f (); }
+ void g () { f (); }
works, as required.) An alternative approach would be to look up
the correct default arguments at the call-site, but this approach
old_type = TREE_TYPE (decl);
spec_types = TYPE_ARG_TYPES (old_type);
-
+
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
{
/* Remove the this pointer, but remember the object's type for
- CV quals. */
+ CV quals. */
object_type = TREE_TYPE (TREE_VALUE (spec_types));
spec_types = TREE_CHAIN (spec_types);
tmpl_types = TREE_CHAIN (tmpl_types);
-
+
if (DECL_HAS_IN_CHARGE_PARM_P (decl))
- {
- /* DECL may contain more parameters than TMPL due to the extra
- in-charge parameter in constructors and destructors. */
- in_charge = spec_types;
+ {
+ /* DECL may contain more parameters than TMPL due to the extra
+ in-charge parameter in constructors and destructors. */
+ in_charge = spec_types;
spec_types = TREE_CHAIN (spec_types);
}
if (DECL_HAS_VTT_PARM_P (decl))
}
/* Compute the merged default arguments. */
- new_spec_types =
+ new_spec_types =
copy_default_args_to_explicit_spec_1 (spec_types, tmpl_types);
/* Compute the new FUNCTION_TYPE. */
if (object_type)
{
if (vtt)
- new_spec_types = hash_tree_cons (TREE_PURPOSE (vtt),
- TREE_VALUE (vtt),
- new_spec_types);
+ new_spec_types = hash_tree_cons (TREE_PURPOSE (vtt),
+ TREE_VALUE (vtt),
+ new_spec_types);
if (in_charge)
- /* Put the in-charge parameter back. */
- new_spec_types = hash_tree_cons (TREE_PURPOSE (in_charge),
- TREE_VALUE (in_charge),
- new_spec_types);
+ /* Put the in-charge parameter back. */
+ new_spec_types = hash_tree_cons (TREE_PURPOSE (in_charge),
+ TREE_VALUE (in_charge),
+ new_spec_types);
new_type = build_method_type_directly (object_type,
TREE_TYPE (old_type),
instead if all goes well. Issues an error message if something is
amiss. Returns error_mark_node if the error is not easily
recoverable.
-
- FLAGS is a bitmask consisting of the following flags:
+
+ FLAGS is a bitmask consisting of the following flags:
2: The function has a definition.
4: The function is a friend.
template <class T> struct S { void f(); };
void S<int>::f();
-
+
the TEMPLATE_COUNT would be 1. However, explicitly specialized
classes are not counted in the TEMPLATE_COUNT, so that in
If the function is a specialization, it is marked as such via
DECL_TEMPLATE_SPECIALIZATION. Furthermore, its DECL_TEMPLATE_INFO
- is set up correctly, and it is added to the list of specializations
+ is set up correctly, and it is added to the list of specializations
for that template. */
tree
-check_explicit_specialization (tree declarator,
- tree decl,
- int template_count,
- int flags)
+check_explicit_specialization (tree declarator,
+ tree decl,
+ int template_count,
+ int flags)
{
int have_def = flags & 2;
int is_friend = flags & 4;
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)
{
case tsk_none:
- if (processing_specialization)
+ if (processing_specialization)
{
specialization = 1;
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
template <class T> void f<int>(); */
error ("template-id %qD in declaration of primary template",
- declarator);
+ declarator);
return decl;
}
}
case tsk_expl_inst:
if (have_def)
error ("definition provided for explicit instantiation");
-
+
explicit_instantiation = 1;
break;
case tsk_excessive_parms:
case tsk_insufficient_parms:
if (tsk == tsk_excessive_parms)
- error ("too many template parameter lists in declaration of %qD",
+ error ("too many template parameter lists in declaration of %qD",
decl);
else if (template_header_count)
error("too few template parameter lists in declaration of %qD", decl);
else
error("explicit specialization of %qD must be introduced by "
- "`template <>'", decl);
+ "%<template <>%>", decl);
/* Fall through. */
case tsk_expl_spec:
"is not allowed", declarator);
else
error ("template-id %qD in declaration of primary template",
- declarator);
+ declarator);
return decl;
}
specialization the containing class. Something like:
template <class T> struct S {
- template <class U> void f (U);
- };
+ template <class U> void f (U);
+ };
template <> template <class U> void S<int>::f(U) {}
-
+
That's a specialization -- but of the entire template. */
specialization = 1;
break;
else
{
/* If there is no class context, the explicit instantiation
- must be at namespace scope. */
+ must be at namespace scope. */
gcc_assert (DECL_NAMESPACE_SCOPE_P (decl));
/* Find the namespace binding, using the declaration
- context. */
+ 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);
/* It's not valid to write an explicit instantiation in
class scope, e.g.:
- class C { template void f(); }
+ class C { template void f(); }
This case is caught by the parser. However, on
something like:
-
+
template class C { void f(); };
(which is invalid) we can get here. The error will be
return decl;
}
- else if (ctype != NULL_TREE
+ else if (ctype != NULL_TREE
&& (TREE_CODE (TREE_OPERAND (declarator, 0)) ==
IDENTIFIER_NODE))
{
if (constructor_name_p (name, ctype))
{
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 such an explicit specialization for the member
of a class template names an implicitly-declared
special member function (clause _special_), the
- program is ill-formed.
+ program is ill-formed.
Similar language is found in [temp.explicit]. */
error ("specialization of implicitly-declared special member function");
}
else
{
- VEC(tree) *methods;
+ VEC(tree,gc) *methods;
tree ovl;
/* For a type-conversion operator, we cannot do a
fns = ovl_cons (OVL_CURRENT (ovl), fns);
}
}
-
- if (fns == NULL_TREE)
+
+ if (fns == NULL_TREE)
{
error ("no member function %qD declared in %qT", name, ctype);
return error_mark_node;
else
TREE_OPERAND (declarator, 0) = fns;
}
-
+
/* Figure out what exactly is being specialized at this point.
Note that for an explicit instantiation, even one for a
member function, we cannot tell apriori whether the
elided if they can be deduced from the rest of the
declaration. */
tmpl = determine_specialization (declarator, decl,
- &targs,
+ &targs,
member_specialization,
template_count);
-
+
if (!tmpl || tmpl == error_mark_node)
/* We couldn't figure out what this declaration was
specializing. */
if (explicit_instantiation)
{
/* We don't set DECL_EXPLICIT_INSTANTIATION here; that
- is done by do_decl_instantiation later. */
+ is done by do_decl_instantiation later. */
int arg_depth = TMPL_ARGS_DEPTH (targs);
int parm_depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
= TREE_VEC_ELT (targs, i);
targs = new_targs;
}
-
+
return instantiate_template (tmpl, targs, tf_error);
}
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;
}
decl = register_specialization (decl, gen_tmpl, targs);
}
}
-
- 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 %qT", type);
- }
+ return decl;
}
/* Returns 1 iff PARMS1 and PARMS2 are identical sets of template
if (parms1 == parms2)
return 1;
- for (p1 = parms1, p2 = parms2;
+ for (p1 = parms1, p2 = parms2;
p1 != NULL_TREE && p2 != NULL_TREE;
p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2))
{
if (TREE_VEC_LENGTH (t1) != TREE_VEC_LENGTH (t2))
return 0;
- for (i = 0; i < TREE_VEC_LENGTH (t2); ++i)
+ for (i = 0; i < TREE_VEC_LENGTH (t2); ++i)
{
tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i));
tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i));
/* We check for decl != olddecl to avoid bogus errors for using a
name inside a class. We check TPFI to avoid duplicate errors for
inline member templates. */
- if (decl == olddecl
+ if (decl == olddecl
|| TEMPLATE_PARMS_FOR_INLINE (current_template_parms))
return;
ORIG_LEVEL, DECL, and TYPE. */
static tree
-build_template_parm_index (int index,
- int level,
- int orig_level,
- tree decl,
- tree type)
+build_template_parm_index (int index,
+ int level,
+ int orig_level,
+ tree decl,
+ tree type)
{
tree t = make_node (TEMPLATE_PARM_INDEX);
TEMPLATE_PARM_IDX (t) = index;
TEMPLATE_PARM_INDEX already exists, it is returned; otherwise, a
new one is created. */
-static tree
+static tree
reduce_template_parm_level (tree index, tree type, int levels)
{
if (TEMPLATE_PARM_DESCENDANTS (index) == NULL_TREE
{
tree orig_decl = TEMPLATE_PARM_DECL (index);
tree decl, t;
-
+
decl = build_decl (TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);
TREE_CONSTANT (decl) = TREE_CONSTANT (orig_decl);
TREE_INVARIANT (decl) = TREE_INVARIANT (orig_decl);
TREE_READONLY (decl) = TREE_READONLY (orig_decl);
DECL_ARTIFICIAL (decl) = 1;
SET_DECL_TEMPLATE_PARM_P (decl);
-
+
t = build_template_parm_index (TEMPLATE_PARM_IDX (index),
TEMPLATE_PARM_LEVEL (index) - levels,
TEMPLATE_PARM_ORIG_LEVEL (index),
TREE_INVARIANT (parm) = 1;
TREE_READONLY (parm) = 1;
if (invalid_nontype_parm_type_p (TREE_TYPE (parm), 1))
- TREE_TYPE (parm) = void_type_node;
+ TREE_TYPE (parm) = void_type_node;
decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
TREE_CONSTANT (decl) = 1;
TREE_INVARIANT (decl) = 1;
TREE_READONLY (decl) = 1;
- DECL_INITIAL (parm) = DECL_INITIAL (decl)
+ DECL_INITIAL (parm) = DECL_INITIAL (decl)
= build_template_parm_index (idx, processing_template_decl,
processing_template_decl,
decl, TREE_TYPE (parm));
{
tree t;
parm = TREE_VALUE (TREE_VALUE (parm));
-
+
if (parm && TREE_CODE (parm) == TEMPLATE_DECL)
{
t = make_aggr_type (TEMPLATE_TEMPLATE_PARM);
- /* This is for distinguishing between real templates and template
+ /* This is for distinguishing between real templates and template
template parameters */
TREE_TYPE (parm) = t;
TREE_TYPE (DECL_TEMPLATE_RESULT (parm)) = t;
/* parm is either IDENTIFIER_NODE or NULL_TREE. */
decl = build_decl (TYPE_DECL, parm, t);
}
-
+
TYPE_NAME (t) = decl;
TYPE_STUB_DECL (t) = decl;
parm = decl;
TEMPLATE_TYPE_PARM_INDEX (t)
- = build_template_parm_index (idx, processing_template_decl,
+ = build_template_parm_index (idx, processing_template_decl,
processing_template_decl,
decl, TREE_TYPE (parm));
}
/* T will be a list if we are called from within a
begin/end_template_parm_list pair, but a vector directly
if within a begin/end_member_template_processing pair. */
- if (TREE_CODE (t) == TREE_LIST)
+ if (TREE_CODE (t) == TREE_LIST)
{
t = TREE_VALUE (t);
-
- if (TREE_CODE (t) == TYPE_DECL
+
+ if (TREE_CODE (t) == TYPE_DECL
|| TREE_CODE (t) == TEMPLATE_DECL)
t = TREE_TYPE (t);
else
DECL_NONCONVERTING_P (tmpl) = DECL_NONCONVERTING_P (decl);
DECL_ASSIGNMENT_OPERATOR_P (tmpl) = DECL_ASSIGNMENT_OPERATOR_P (decl);
if (DECL_OVERLOADED_OPERATOR_P (decl))
- SET_OVERLOADED_OPERATOR_CODE (tmpl,
+ SET_OVERLOADED_OPERATOR_CODE (tmpl,
DECL_OVERLOADED_OPERATOR_P (decl));
}
};
The S2<T> declaration is actually invalid; it is a
- full-specialization. Of course,
+ full-specialization. Of course,
template <class U>
struct S2<T (*)(U)>;
The argument list of the specialization shall not be identical to
the implicit argument list of the primary template. */
- if (comp_template_args
- (inner_args,
+ if (comp_template_args
+ (inner_args,
INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (TREE_TYPE
(maintmpl)))))
error ("partial specialization %qT does not specialize any template arguments", type);
{
if (tpd.arg_uses_template_parms[i])
error ("template argument %qE involves template parameter(s)", arg);
- else
+ else
{
/* Look at the corresponding template parameter,
marking which template parameters its type depends
upon. */
- tree type =
- TREE_TYPE (TREE_VALUE (TREE_VEC_ELT (main_inner_parms,
+ tree type =
+ TREE_TYPE (TREE_VALUE (TREE_VEC_ELT (main_inner_parms,
i)));
if (!tpd2.parms)
{
/* We haven't yet initialized TPD2. Do so now. */
- tpd2.arg_uses_template_parms
+ tpd2.arg_uses_template_parms
= alloca (sizeof (int) * nargs);
/* The number of parameters here is the number in the
main template, which, as checked in the assertion
above, is NARGS. */
tpd2.parms = alloca (sizeof (int) * nargs);
- tpd2.level =
+ tpd2.level =
TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (maintmpl));
}
&mark_template_parm,
&tpd2,
NULL);
-
+
if (tpd2.arg_uses_template_parms [i])
{
/* The type depended on some template parameters.
&& tpd.arg_uses_template_parms [j])
{
error ("type %qT of template argument %qE depends "
- "on template parameter(s)",
- type,
- arg);
+ "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;
int last_level_to_check;
tree parm_level;
- /* [temp.param]
+ /* [temp.param]
A default template-argument shall not be specified in a
function template declaration or a function template definition, nor
return;
/* [temp.param]
-
+
If a template-parameter has a default template-argument, all
subsequent template-parameters shall have a default
template-argument supplied. */
{
tree inner_parms = TREE_VALUE (parm_level);
int ntparms = TREE_VEC_LENGTH (inner_parms);
- int seen_def_arg_p = 0;
+ int seen_def_arg_p = 0;
int i;
- for (i = 0; i < ntparms; ++i)
+ for (i = 0; i < ntparms; ++i)
{
tree parm = TREE_VEC_ELT (inner_parms, i);
if (TREE_PURPOSE (parm))
if (TREE_CODE (decl) != TYPE_DECL || is_partial || !is_primary)
/* For an ordinary class template, default template arguments are
allowed at the innermost level, e.g.:
- template <class T = int>
+ template <class T = int>
struct S {};
but, in a partial specialization, they're not allowed even
there, as we have in [temp.class.spec]:
-
+
The template parameter list of a specialization shall not
- contain default template argument values.
+ contain default template argument values.
So, for a partial specialization, or for a function template,
we look at all of them. */
examine the parameters to the class itself. On the one
hand, they will be checked when the class is defined, and,
on the other, default arguments are valid in things like:
- template <class T = double>
- struct S { template <class U> void f(U); };
+ template <class T = double>
+ struct S { template <class U> void f(U); };
Here the default argument for `S' has no bearing on the
declaration of `f'. */
last_level_to_check = template_class_depth (current_class_type) + 1;
/* Check everything. */
last_level_to_check = 0;
- for (parm_level = parms;
- parm_level && TMPL_PARMS_DEPTH (parm_level) >= last_level_to_check;
+ for (parm_level = parms;
+ parm_level && TMPL_PARMS_DEPTH (parm_level) >= last_level_to_check;
parm_level = TREE_CHAIN (parm_level))
{
tree inner_parms = TREE_VALUE (parm_level);
int ntparms;
ntparms = TREE_VEC_LENGTH (inner_parms);
- for (i = 0; i < ntparms; ++i)
+ for (i = 0; i < ntparms; ++i)
if (TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)))
{
if (msg)
/* 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 %qD";
+ msg = "default argument for template parameter for class enclosing %qD";
}
}
/* Creates a TEMPLATE_DECL for the indicated DECL using the template
parameters given by current_template_args, or reuses a
previously existing one, if appropriate. Returns the DECL, or an
- equivalent one, if it is replaced via a call to duplicate_decls.
+ equivalent one, if it is replaced via a call to duplicate_decls.
If IS_FRIEND is nonzero, DECL is a friend declaration. */
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)))
+ 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)
{
if (DECL_DESTRUCTOR_P (decl))
{
/* [temp.mem]
-
- A destructor shall not be a member template. */
+
+ A destructor shall not be a member template. */
error ("destructor %qD declared as member template", decl);
return error_mark_node;
}
|| (TREE_CHAIN (TYPE_ARG_TYPES ((TREE_TYPE (decl))))
== void_list_node)))
{
- /* [basic.stc.dynamic.allocation]
+ /* [basic.stc.dynamic.allocation]
- An allocation function can be a function
+ An allocation function can be a function
template. ... Template allocation functions shall
have two or more parameters. */
error ("invalid template declaration of %qD", decl);
/* Check to see that the rules regarding the use of default
arguments are not being violated. */
- check_default_tmpl_args (decl, current_template_parms,
+ check_default_tmpl_args (decl, current_template_parms,
primary, is_partial);
if (is_partial)
args = current_template_args ();
- if (!ctx
+ if (!ctx
|| TREE_CODE (ctx) == FUNCTION_DECL
|| (CLASS_TYPE_P (ctx) && TYPE_BEING_DEFINED (ctx))
|| (is_friend && !DECL_TEMPLATE_INFO (decl)))
/* If DECL is a TYPE_DECL for a class-template, then there won't
be DECL_LANG_SPECIFIC. The information equivalent to
DECL_TEMPLATE_INFO is found in TYPE_TEMPLATE_INFO instead. */
- else if (DECL_IMPLICIT_TYPEDEF_P (decl)
+ else if (DECL_IMPLICIT_TYPEDEF_P (decl)
&& TYPE_TEMPLATE_INFO (TREE_TYPE (decl))
&& TYPE_TI_TEMPLATE (TREE_TYPE (decl)))
{
}
else
tmpl = DECL_TI_TEMPLATE (decl);
-
+
if (DECL_FUNCTION_TEMPLATE_P (tmpl)
- && DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl)
+ && DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl)
&& DECL_TEMPLATE_SPECIALIZATION (decl)
&& DECL_MEMBER_TEMPLATE_P (tmpl))
{
earlier call to check_explicit_specialization. */
args = DECL_TI_ARGS (decl);
- new_tmpl
+ new_tmpl
= 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;
SET_DECL_TEMPLATE_SPECIALIZATION (new_tmpl);
- DECL_TEMPLATE_INFO (new_tmpl)
+ DECL_TEMPLATE_INFO (new_tmpl)
= tree_cons (tmpl, args, NULL_TREE);
- register_specialization (new_tmpl,
- most_general_template (tmpl),
+ register_specialization (new_tmpl,
+ most_general_template (tmpl),
args);
return decl;
}
if (TMPL_ARGS_DEPTH (args) != i)
{
error ("expected %d levels of template parms for %q#D, got %d",
- i, decl, TMPL_ARGS_DEPTH (args));
+ i, decl, TMPL_ARGS_DEPTH (args));
}
else
for (current = decl; i > 0; --i, parms = TREE_CHAIN (parms))
{
if (current == decl)
error ("got %d template parameters for %q#D",
- TREE_VEC_LENGTH (a), decl);
+ TREE_VEC_LENGTH (a), decl);
else
error ("got %d template parameters for %q#T",
- TREE_VEC_LENGTH (a), current);
+ TREE_VEC_LENGTH (a), current);
error (" but %d required", TREE_VEC_LENGTH (t));
}
/* Perhaps we should also check that the parms are used in the
- appropriate qualifying scopes in the declarator? */
+ appropriate qualifying scopes in the declarator? */
if (current == decl)
current = ctx;
that we do not try to push a global template friend declared in a
template class; such a thing may well depend on the template
parameters of the class. */
- if (new_template_p && !ctx
+ 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;
+
+ /* Hide template friend classes that haven't been declared yet. */
+ if (is_friend && TREE_CODE (decl) == TYPE_DECL)
+ {
+ DECL_ANTICIPATED (tmpl) = 1;
+ DECL_FRIEND_P (tmpl) = 1;
+ }
+ }
if (primary)
{
/* It is a conversion operator. See if the type converted to
depends on innermost template operands. */
-
+
if (uses_template_parms_level (TREE_TYPE (TREE_TYPE (tmpl)),
depth))
DECL_TEMPLATE_CONV_FN_P (tmpl) = 1;
template <class T> struct S;
template <class T> struct S {}; */
-void
+void
redeclare_class_template (tree type, tree parms)
{
tree tmpl;
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 %qD", tmpl);
- error ("used %d template parameter%s instead of %d",
- TREE_VEC_LENGTH (tmpl_parms),
- TREE_VEC_LENGTH (tmpl_parms) == 1 ? "" : "s",
- TREE_VEC_LENGTH (parms));
+ error ("used %d template parameter(s) instead of %d",
+ TREE_VEC_LENGTH (tmpl_parms),
+ TREE_VEC_LENGTH (parms));
return;
}
{
/* If we're in a template, but EXPR isn't value dependent, simplify
it. We're supposed to treat:
-
+
template <typename T> void f(T[1 + 1]);
template <typename T> void f(T[2]);
-
+
as two declarations of the same function, for example. */
if (processing_template_decl
&& !type_dependent_expression_p (expr)
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);
- }
+ /* 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))
+ {
+ /* ??? 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 (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
+ /* 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))
{
- if (TREE_CODE (e) != ADDR_EXPR)
- {
- bad_argument:
- error ("%qE is not a valid template argument", expr);
- if (TYPE_PTR_P (expr_type))
- {
- if (TREE_CODE (TREE_TYPE (expr_type)) == FUNCTION_TYPE)
- error ("it must be the address of 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%>");
+ 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);
+ }
+ }
- return NULL_TREE;
- }
+ /* [temp.arg.nontype]/5, bullet 1
- referent = TREE_OPERAND (e, 0);
- STRIP_NOPS (referent);
- }
+ 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))
+ {
+ if (!INTEGRAL_TYPE_P (expr_type))
+ return error_mark_node;
- if (TREE_CODE (referent) == STRING_CST)
+ 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)
{
- error ("string literal %qE is not a valid template argument "
- "because it is the address of an object with static linkage",
- referent);
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is a non-constant expression", expr, type);
return NULL_TREE;
}
- if (TREE_CODE (referent) == SCOPE_REF)
- referent = TREE_OPERAND (referent, 1);
+ /* 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 (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))
+ /* Conversion was allowed: fold it to a bare integer constant. */
+ expr = fold (expr);
+ }
+ /* [temp.arg.nontype]/5, bullet 2
+
+ 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):
+
+ A template-argument for a non-type, non-template template-parameter
+ shall be one of: [...]
+
+ -- 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.
+
+ 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;
+
+ expr = perform_qualification_conversions (type, expr);
+ if (expr == error_mark_node)
+ return error_mark_node;
+
+ if (!constant_address_p)
{
- error ("address of non-extern %qE cannot be used as "
- "template argument", referent);
- return error_mark_node;
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is not a constant pointer", expr, type);
+ return NULL_TREE;
}
}
- else if (INTEGRAL_TYPE_P (expr_type) || TYPE_PTR_TO_MEMBER_P (expr_type))
+ /* [temp.arg.nontype]/5, bullet 3
+
+ 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 (! TREE_CONSTANT (expr))
+ if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type),
+ expr_type))
+ return error_mark_node;
+
+ 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;
+ }
+
+ /* [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 (expr))
{
- non_constant:
- error ("non-constant %qE cannot be used as template argument", 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 = build_nop (type, build_address (expr));
}
- else
+ /* [temp.arg.nontype]/5, bullet 4
+
+ 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 (TYPE_P (expr))
- error ("type %qT cannot be used as a value for a non-type "
- "template-parameter", expr);
- else if (DECL_P (expr))
- error ("invalid use of %qD as a non-type template-argument", expr);
- else
- error ("invalid use of %qE as a non-type template-argument", expr);
+ /* 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;
+ }
- return NULL_TREE;
+ expr = convert_nontype_argument_function (type, expr);
+ if (!expr || expr == error_mark_node)
+ return expr;
}
+ /* [temp.arg.nontype]/5, bullet 5
- switch (TREE_CODE (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_). */
+ else if (TYPE_REFFN_P (type))
{
- HOST_WIDE_INT saved_processing_template_decl;
-
- 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;
+ 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;
+ }
- /* [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;
+ expr = convert_nontype_argument_function (TREE_TYPE (type), expr);
+ if (!expr || expr == error_mark_node)
+ return expr;
- /* It's safe to call digest_init in this case; we know we're
- just converting one integral constant expression to another.
- */
- saved_processing_template_decl = processing_template_decl;
- processing_template_decl = 0;
- expr = digest_init (type, expr, (tree*) 0);
- processing_template_decl = saved_processing_template_decl;
+ expr = build_nop (type, build_address (expr));
+ }
+ /* [temp.arg.nontype]/5, bullet 6
- 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;
+ 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;
- 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;
- }
+ /* 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.
- 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;
-
- fn = instantiate_type (type_pointed_to, fns, tf_none);
-
- if (fn == error_mark_node)
- return error_mark_node;
-
- if (!DECL_EXTERNAL_LINKAGE_P (fn))
- {
- if (really_overloaded_fn (fns))
- return error_mark_node;
- else
- goto bad_argument;
- }
-
- expr = build_unary_op (ADDR_EXPR, fn, 0);
-
- gcc_assert (same_type_p (type, TREE_TYPE (expr)));
- 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 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;
-
- case REFERENCE_TYPE:
- {
- tree type_referred_to = TREE_TYPE (type);
-
- /* 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);
- gcc_assert (TREE_CODE (expr) == ADDR_EXPR);
- expr = TREE_OPERAND (expr, 0);
- expr_type = TREE_TYPE (expr);
- }
-
- 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;
-
- fn = instantiate_type (type_referred_to, expr, tf_none);
-
- if (fn == error_mark_node)
- return error_mark_node;
-
- 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;
- }
-
- gcc_assert (same_type_p (type_referred_to, TREE_TYPE (fn)));
- 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;
- }
-
- cxx_mark_addressable (expr);
- return build_nop (type, build_address (expr));
- }
- break;
-
- case RECORD_TYPE:
- {
- gcc_assert (TYPE_PTRMEMFUNC_P (type));
-
- /* For a non-type template-parameter of type pointer to member
- function, no conversions apply. If the template-argument
- represents a set of overloaded member functions, the
- matching member function is selected from the set
- (_over.over_). */
-
- if (!TYPE_PTRMEMFUNC_P (expr_type) &&
- expr_type != unknown_type_node)
- return error_mark_node;
-
- 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;
- }
-
- if (TREE_CODE (expr) != ADDR_EXPR)
- return error_mark_node;
-
- expr = instantiate_type (type, expr, tf_none);
-
- if (expr == error_mark_node)
- return error_mark_node;
-
- 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. */
- gcc_unreachable ();
}
+ /* 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
+
+/* 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
or PARM_DECL.
-
- ARG_PARMS may contain more parameters than PARM_PARMS. If this is
+
+ ARG_PARMS may contain more parameters than PARM_PARMS. If this is
the case, then extra parameters must have default arguments.
Consider the example:
template <class T, class Allocator = allocator> class vector;
template<template <class U> class TT> class C;
- C<vector> is a valid instantiation. PARM_PARMS for the above code
- contains a TYPE_DECL (for U), ARG_PARMS contains two TYPE_DECLs (for
- T and Allocator) and OUTER_ARGS contains the argument that is used to
+ C<vector> is a valid instantiation. PARM_PARMS for the above code
+ contains a TYPE_DECL (for U), ARG_PARMS contains two TYPE_DECLs (for
+ T and Allocator) and OUTER_ARGS contains the argument that is used to
substitute the TT parameter. */
static int
-coerce_template_template_parms (tree parm_parms,
- tree arg_parms,
- tsubst_flags_t complain,
+coerce_template_template_parms (tree parm_parms,
+ tree arg_parms,
+ tsubst_flags_t complain,
tree in_decl,
- tree outer_args)
+ tree outer_args)
{
int nparms, nargs, i;
tree parm, arg;
arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
if (arg == NULL_TREE || arg == error_mark_node
- || parm == NULL_TREE || parm == error_mark_node)
+ || parm == NULL_TREE || parm == error_mark_node)
return 0;
if (TREE_CODE (arg) != TREE_CODE (parm))
- return 0;
+ return 0;
switch (TREE_CODE (parm))
{
TREE_TYPE (arg)))
return 0;
break;
-
+
default:
gcc_unreachable ();
}
the full set of template arguments deduced so far. */
static tree
-convert_template_argument (tree parm,
- tree arg,
- tree args,
- tsubst_flags_t complain,
- int i,
- tree in_decl)
+convert_template_argument (tree parm,
+ tree arg,
+ tree args,
+ tsubst_flags_t complain,
+ int i,
+ tree in_decl)
{
tree val;
tree inner_args;
int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
-
+
inner_args = INNERMOST_TEMPLATE_ARGS (args);
- if (TREE_CODE (arg) == TREE_LIST
+ if (TREE_CODE (arg) == TREE_LIST
&& TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
- {
+ {
/* The template argument was the name of some
member function. That's usually
invalid, but static members are OK. In any
&& TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);
-
+
if (is_tmpl_type
&& (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE))
&& TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
{
pedwarn ("to refer to a type member of a template parameter, "
- "use %<typename %E%>", arg);
-
+ "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 %qD",
- i + 1, in_decl);
+ "parameter list for %qD",
+ i + 1, in_decl);
if (is_type)
error (" expected a constant of type %qT, got %qT",
- TREE_TYPE (parm),
- (is_tmpl_type ? DECL_NAME (arg) : arg));
+ TREE_TYPE (parm),
+ (is_tmpl_type ? DECL_NAME (arg) : arg));
else if (requires_tmpl_type)
error (" expected a class template, got %qE", arg);
else
if (in_decl && (complain & tf_error))
{
error ("type/value mismatch at argument %d in template "
- "parameter list for %qD",
- i + 1, in_decl);
+ "parameter list for %qD",
+ i + 1, in_decl);
if (is_tmpl_type)
error (" expected a type, got %qT", DECL_NAME (arg));
else
}
return error_mark_node;
}
-
+
if (is_type)
{
if (requires_tmpl_type)
inner_args))
{
val = arg;
-
- /* TEMPLATE_TEMPLATE_PARM node is preferred over
+
+ /* TEMPLATE_TEMPLATE_PARM node is preferred over
TEMPLATE_DECL. */
- if (val != error_mark_node
+ if (val != error_mark_node
&& DECL_TEMPLATE_TEMPLATE_PARM_P (val))
val = TREE_TYPE (val);
}
if (in_decl && (complain & tf_error))
{
error ("type/value mismatch at argument %d in "
- "template parameter list for %qD",
- i + 1, in_decl);
+ "template parameter list for %qD",
+ i + 1, in_decl);
error (" expected a template of type %qD, got %qD",
- parm, arg);
+ parm, arg);
}
-
+
val = error_mark_node;
}
}
tree t = tsubst (TREE_TYPE (parm), args, complain, in_decl);
if (invalid_nontype_parm_type_p (t, complain))
- return error_mark_node;
-
+ return error_mark_node;
+
if (!uses_template_parms (arg) && !uses_template_parms (t))
/* We used to call digest_init here. However, digest_init
will report errors, which we don't want when complain
provided in ARGLIST, or else trailing parameters must have default
values. If REQUIRE_ALL_ARGUMENTS is zero, we will attempt argument
deduction for any unspecified trailing arguments. */
-
+
static tree
-coerce_template_parms (tree parms,
- tree args,
- tree in_decl,
+coerce_template_parms (tree parms,
+ tree args,
+ tree in_decl,
tsubst_flags_t complain,
int require_all_arguments)
{
&& require_all_arguments
&& TREE_PURPOSE (TREE_VEC_ELT (parms, nargs)) == NULL_TREE))
{
- if (complain & tf_error)
+ 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 %qD", in_decl);
}
complain, in_decl);
else
break;
-
+
gcc_assert (arg);
if (arg == error_mark_node)
- error ("template argument %d is invalid", i + 1);
- else
- arg = convert_template_argument (TREE_VALUE (parm),
+ {
+ 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,
- in_decl);
-
+ in_decl);
+
if (arg == error_mark_node)
lost++;
TREE_VEC_ELT (new_inner_args, i) = arg;
{
if (TREE_CODE (arg) == TEMPLATE_DECL)
{
- /* Already substituted with real template. Just output
+ /* Already substituted with real template. Just output
the template name here */
- tree context = DECL_CONTEXT (arg);
- if (context)
- {
- /* The template may be defined in a namespace, or
- may be a member template. */
- gcc_assert (TREE_CODE (context) == NAMESPACE_DECL
+ tree context = DECL_CONTEXT (arg);
+ if (context)
+ {
+ /* The template may be defined in a namespace, or
+ may be a member template. */
+ gcc_assert (TREE_CODE (context) == NAMESPACE_DECL
|| CLASS_TYPE_P (context));
cat (decl_as_string (DECL_CONTEXT (arg),
TFF_PLAIN_IDENTIFIER));
{
tree name = DECL_NAME (tmpl);
char *mangled_name = mangle_class_name_for_template
- (IDENTIFIER_POINTER (name),
+ (IDENTIFIER_POINTER (name),
DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
CLASSTYPE_TI_ARGS (t));
tree id = get_identifier (mangled_name);
return error_mark_node;
gcc_assert (!arglist || TREE_CODE (arglist) == TREE_VEC);
- if (fns == NULL_TREE
- || TREE_CODE (fns) == FUNCTION_DECL)
- {
- error ("non-template used as template");
- return error_mark_node;
- }
-
- gcc_assert (TREE_CODE (fns) == TEMPLATE_DECL
- || TREE_CODE (fns) == OVERLOAD
- || BASELINK_P (fns)
- || TREE_CODE (fns) == IDENTIFIER_NODE);
+ gcc_assert (fns && (is_overloaded_fn (fns)
+ || TREE_CODE (fns) == IDENTIFIER_NODE));
if (BASELINK_P (fns))
{
type = TREE_TYPE (fns);
if (TREE_CODE (fns) == OVERLOAD || !type)
type = unknown_type_node;
-
+
return build2 (TEMPLATE_ID_EXPR, type, fns, arglist);
}
maybe_get_template_decl_from_type_decl (tree decl)
{
return (decl != NULL_TREE
- && TREE_CODE (decl) == TYPE_DECL
+ && TREE_CODE (decl) == TYPE_DECL
&& DECL_ARTIFICIAL (decl)
&& CLASS_TYPE_P (TREE_TYPE (decl))
- && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl)))
+ && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl)))
? CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)) : decl;
}
D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments.
IN_DECL, if non-NULL, is the template declaration we are trying to
- instantiate.
+ instantiate.
If ENTERING_SCOPE is nonzero, we are about to enter the scope of
the class we are looking up.
-
+
Issue error and warning messages under control of COMPLAIN.
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,
- tree arglist,
- tree in_decl,
- tree context,
- int entering_scope,
- tsubst_flags_t complain)
+lookup_template_class (tree d1,
+ tree arglist,
+ tree in_decl,
+ tree context,
+ int entering_scope,
+ tsubst_flags_t complain)
{
tree template = NULL_TREE, parmlist;
tree t;
-
+
timevar_push (TV_NAME_LOOKUP);
-
+
if (TREE_CODE (d1) == IDENTIFIER_NODE)
{
tree value = innermost_non_namespace_value (d1);
an implicit typename for the second A. Deal with it. */
if (TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))
type = TREE_TYPE (type);
-
+
if (CLASSTYPE_TEMPLATE_INFO (type))
{
template = CLASSTYPE_TI_TEMPLATE (type);
d1 = DECL_NAME (template);
}
}
- else if (TREE_CODE (d1) == ENUMERAL_TYPE
+ else if (TREE_CODE (d1) == ENUMERAL_TYPE
|| (TYPE_P (d1) && IS_AGGR_TYPE (d1)))
{
template = TYPE_TI_TEMPLATE (d1);
if (! template)
{
if (complain & tf_error)
- error ("%qT is not a template", d1);
+ error ("%qT is not a template", d1);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
if (TREE_CODE (template) != TEMPLATE_DECL
- /* Make sure it's a user visible template, if it was named by
+ /* Make sure it's a user visible template, if it was named by
the user. */
|| ((complain & tf_user) && !DECL_TEMPLATE_PARM_P (template)
&& !PRIMARY_TEMPLATE_P (template)))
{
if (complain & tf_error)
- {
- error ("non-template type %qT used as a template", d1);
- if (in_decl)
+ {
+ error ("non-template type %qT used as a template", d1);
+ if (in_decl)
cp_error_at ("for template declaration %qD", in_decl);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
complain &= ~tf_user;
-
+
if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))
{
/* Create a new TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM node to store
- template arguments */
+ template arguments */
tree parm;
tree arglist2;
template <class T, class U = std::allocator<T> > class TT
- The template parameter level of T and U are one level larger than
- of TT. To proper process the default argument of U, say when an
+ The template parameter level of T and U are one level larger than
+ of TT. To proper process the default argument of U, say when an
instantiation `TT<int>' is seen, we need to build the full
arguments containing {int} as the innermost level. Outer levels,
available when not appearing as default template argument, can be
arglist = add_to_template_args (current_template_args (), arglist);
arglist2 = coerce_template_parms (parmlist, arglist, template,
- complain, /*require_all_args=*/1);
+ complain, /*require_all_args=*/1);
if (arglist2 == error_mark_node
|| (!uses_template_parms (arglist2)
&& check_instantiated_args (template, arglist2, complain)))
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
parm = bind_template_template_parm (TREE_TYPE (template), arglist2);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, parm);
}
- else
+ else
{
tree template_type = TREE_TYPE (template);
tree gen_tmpl;
For example, given:
template <class T> struct S1 {
- template <class U> struct S2 {};
+ template <class U> struct S2 {};
template <class U> struct S2<U*> {};
- };
-
+ };
+
we will be called with an ARGLIST of `U*', but the
TEMPLATE will be `template <class T> template
<class U> struct S1<T>::S2'. We must fill in the missing
arguments. */
- arglist
+ arglist
= add_outermost_template_args (TYPE_TI_ARGS (TREE_TYPE (template)),
arglist);
arg_depth = TMPL_ARGS_DEPTH (arglist);
/* Now we should have enough arguments. */
gcc_assert (parm_depth == arg_depth);
-
+
/* From here on, we're only interested in the most general
template. */
template = gen_tmpl;
int saved_depth = TMPL_ARGS_DEPTH (arglist);
tree bound_args = make_tree_vec (parm_depth);
-
+
for (i = saved_depth,
- t = DECL_TEMPLATE_PARMS (template);
+ t = DECL_TEMPLATE_PARMS (template);
i > 0 && t != NULL_TREE;
--i, t = TREE_CHAIN (t))
{
tree a = coerce_template_parms (TREE_VALUE (t),
arglist, template,
- complain, /*require_all_args=*/1);
+ complain, /*require_all_args=*/1);
/* Don't process further if one of the levels fails. */
if (a == error_mark_node)
TREE_VEC_LENGTH (arglist) = saved_depth;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
-
+
SET_TMPL_ARGS_LEVEL (bound_args, i, a);
/* We temporarily reduce the length of the ARGLIST so
= coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
INNERMOST_TEMPLATE_ARGS (arglist),
template,
- complain, /*require_all_args=*/1);
+ complain, /*require_all_args=*/1);
if (arglist == error_mark_node)
/* We were unable to bind the arguments. */
/* In the scope of a template class, explicit references to the
template class refer to the type of the template, not any
instantiation of it. For example, in:
-
+
template <class T> class C { void f(C<T>); }
the `C<T>' is just the same as `C'. Outside of the
arglist))
{
found = template_type;
-
+
if (!entering_scope && PRIMARY_TEMPLATE_P (template))
{
tree ctx;
-
- for (ctx = current_class_type;
+
+ for (ctx = current_class_type;
ctx && TREE_CODE (ctx) != NAMESPACE_DECL;
ctx = (TYPE_P (ctx)
? TYPE_CONTEXT (ctx)
: DECL_CONTEXT (ctx)))
if (TYPE_P (ctx) && same_type_p (ctx, template_type))
goto found_ctx;
-
+
/* We're not in the scope of the class, so the
TEMPLATE_TYPE is not the type we want after all. */
found = NULL_TREE;
}
}
if (found)
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
/* If we already have this specialization, return it. */
found = retrieve_specialization (template, arglist,
INNERMOST_TEMPLATE_ARGS (arglist),
complain))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
-
- if (!is_partial_instantiation
+
+ if (!is_partial_instantiation
&& !PRIMARY_TEMPLATE_P (template)
&& TREE_CODE (CP_DECL_CONTEXT (template)) == NAMESPACE_DECL)
{
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);
}
-
+
context = tsubst (DECL_CONTEXT (template), arglist,
complain, in_decl);
if (!context)
else
{
t = make_aggr_type (TREE_CODE (template_type));
- CLASSTYPE_DECLARED_CLASS (t)
+ CLASSTYPE_DECLARED_CLASS (t)
= CLASSTYPE_DECLARED_CLASS (template_type);
SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
TYPE_FOR_JAVA (t) = TYPE_FOR_JAVA (template_type);
/* A local class. Make sure the decl gets registered properly. */
if (context == current_function_decl)
- pushtag (DECL_NAME (template), t, 0);
+ pushtag (DECL_NAME (template), t, /*tag_scope=*/ts_current);
}
/* If we called start_enum or pushtag above, this information
if (!TYPE_NAME (t))
{
TYPE_CONTEXT (t) = FROB_CONTEXT (context);
-
+
type_decl = create_implicit_typedef (DECL_NAME (template), t);
DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
TYPE_STUB_DECL (t) = type_decl;
- DECL_SOURCE_LOCATION (type_decl)
+ DECL_SOURCE_LOCATION (type_decl)
= DECL_SOURCE_LOCATION (TYPE_STUB_DECL (template_type));
}
else
= TREE_PRIVATE (TYPE_STUB_DECL (template_type));
TREE_PROTECTED (type_decl)
= TREE_PROTECTED (TYPE_STUB_DECL (template_type));
+ DECL_IN_SYSTEM_HEADER (type_decl)
+ = DECL_IN_SYSTEM_HEADER (template);
/* Set up the template information. We have to figure out which
template is the immediate parent if this is a full
if (!found)
{
/* There was no partial instantiation. This happens
- where C<T> is a member template of A<T> and it's used
- in something like
-
- template <typename T> struct B { A<T>::C<int> m; };
- B<float>;
-
- Create the partial instantiation.
- */
- TREE_VEC_LENGTH (arglist)--;
- found = tsubst (template, arglist, complain, NULL_TREE);
- TREE_VEC_LENGTH (arglist)++;
- }
- }
-
- SET_TYPE_TEMPLATE_INFO (t, tree_cons (found, arglist, NULL_TREE));
- DECL_TEMPLATE_INSTANTIATIONS (template)
- = tree_cons (arglist, t,
+ where C<T> is a member template of A<T> and it's used
+ in something like
+
+ template <typename T> struct B { A<T>::C<int> m; };
+ B<float>;
+
+ Create the partial instantiation.
+ */
+ TREE_VEC_LENGTH (arglist)--;
+ found = tsubst (template, arglist, complain, NULL_TREE);
+ TREE_VEC_LENGTH (arglist)++;
+ }
+ }
+
+ SET_TYPE_TEMPLATE_INFO (t, tree_cons (found, arglist, NULL_TREE));
+ DECL_TEMPLATE_INSTANTIATIONS (template)
+ = tree_cons (arglist, t,
DECL_TEMPLATE_INSTANTIATIONS (template));
- if (TREE_CODE (t) == ENUMERAL_TYPE
+ if (TREE_CODE (t) == ENUMERAL_TYPE
&& !is_partial_instantiation)
/* Now that the type has been registered on the instantiations
list, we set up the enumerators. Because the enumeration
timevar_pop (TV_NAME_LOOKUP);
}
\f
-struct pair_fn_data
+struct pair_fn_data
{
tree_fn_t fn;
void *data;
- htab_t visited;
+ struct pointer_set_t *visited;
};
/* Called from for_each_template_parm via walk_tree. */
break;
case TYPEOF_TYPE:
- if (for_each_template_parm (TYPE_FIELDS (t), fn, data,
+ if (for_each_template_parm (TYPE_FIELDS (t), fn, data,
pfd->visited))
return error_mark_node;
break;
&& for_each_template_parm (DECL_INITIAL (t), fn, data,
pfd->visited))
return error_mark_node;
- if (DECL_CONTEXT (t)
+ if (DECL_CONTEXT (t)
&& for_each_template_parm (DECL_CONTEXT (t), fn, data,
pfd->visited))
return error_mark_node;
break;
case TYPENAME_TYPE:
- if (!fn
+ if (!fn
|| for_each_template_parm (TYPENAME_TYPE_FULLNAME (t), fn,
data, pfd->visited))
return error_mark_node;
pfd->visited))
return error_mark_node;
break;
-
+
case INDIRECT_REF:
case COMPONENT_REF:
/* If there's no type, then this thing must be some expression
return NULL_TREE;
}
-/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM,
- BOUND_TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX in T,
+/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM,
+ BOUND_TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX in T,
call FN with the parameter and the DATA.
If FN returns nonzero, the iteration is terminated, and
for_each_template_parm returns 1. Otherwise, the iteration
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);
- result = walk_tree (&t,
- for_each_template_parm_r,
+ pfd.visited = pointer_set_create ();
+ result = walk_tree (&t,
+ for_each_template_parm_r,
&pfd,
pfd.visited) != NULL_TREE;
/* Clean up. */
if (!visited)
- htab_delete (pfd.visited);
+ {
+ pointer_set_destroy (pfd.visited);
+ pfd.visited = 0;
+ }
return result;
}
else if (TREE_CODE (t) == TREE_LIST)
dependent_p = (uses_template_parms (TREE_VALUE (t))
|| uses_template_parms (TREE_CHAIN (t)));
- else if (DECL_P (t)
- || EXPR_P (t)
+ else if (DECL_P (t)
+ || EXPR_P (t)
|| TREE_CODE (t) == TEMPLATE_PARM_INDEX
|| TREE_CODE (t) == OVERLOAD
|| TREE_CODE (t) == BASELINK
gcc_assert (t == error_mark_node);
dependent_p = false;
}
-
+
processing_template_decl = saved_processing_template_decl;
return dependent_p;
{
/* If the instantiation in question still has unbound template parms,
we don't really care if we can't instantiate it, so just return.
- This happens with base instantiation for implicit `typename'. */
+ This happens with base instantiation for implicit `typename'. */
if (uses_template_parms (d))
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 %qD",
+ "-ftemplate-depth-NN to increase the maximum) instantiating %qD",
max_tinst_depth, d);
print_instantiation_context ();
return 0;
}
- new = make_tinst_level (d, input_location);
+ new = make_node (TINST_LEVEL);
+ TINST_DECL (new) = d;
+ TINST_LOCATION (new) = input_location;
+ TINST_IN_SYSTEM_HEADER_P (new) = in_system_header;
TREE_CHAIN (new) = current_tinst_level;
current_tinst_level = new;
/* Restore the filename and line number stashed away when we started
this instantiation. */
input_location = TINST_LOCATION (old);
+ in_system_header = TINST_IN_SYSTEM_HEADER_P (old);
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
+ if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_TEMPLATE_INSTANTIATION (decl)
&& TREE_CODE (DECL_TI_TEMPLATE (decl)) != TEMPLATE_DECL)
/* This was a friend declared with an explicit template
argument list, e.g.:
-
+
friend void f<>(T);
-
+
to indicate that f was a template instantiation, not a new
function declaration. Now, we have to figure out what
instantiation of what template. */
tree new_args;
tree tmpl;
tree ns = decl_namespace_context (TYPE_MAIN_DECL (current_class_type));
-
+
/* Friend functions are looked up in the containing namespace scope.
- We must enter that scope, to avoid finding member functions of the
- current cless with same name. */
+ We must enter that scope, to avoid finding member functions of the
+ current cless with same name. */
push_nested_namespace (ns);
fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
- tf_error | tf_warning, NULL_TREE);
+ tf_error | tf_warning, NULL_TREE);
pop_nested_namespace (ns);
arglist = tsubst (DECL_TI_ARGS (decl), args,
- tf_error | tf_warning, NULL_TREE);
+ tf_error | tf_warning, NULL_TREE);
template_id = lookup_template_function (fns, arglist);
-
+
new_friend = tsubst (decl, args, tf_error | tf_warning, NULL_TREE);
tmpl = determine_specialization (template_id, new_friend,
- &new_args,
+ &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);
-
+
/* The NEW_FRIEND will look like an instantiation, to the
compiler, but is not an instantiation from the point of view of
the language. For example, we might have had:
-
+
template <class T> struct S {
template <class U> friend void f(T, U);
};
-
+
Then, in S<int>, template <class U> void f(int, U) is not an
instantiation of anything. */
if (new_friend == error_mark_node)
return error_mark_node;
-
+
DECL_USE_TEMPLATE (new_friend) = 0;
if (TREE_CODE (decl) == TEMPLATE_DECL)
{
SET_DECL_RTL (new_friend, NULL_RTX);
SET_DECL_ASSEMBLER_NAME (new_friend, NULL_TREE);
}
-
+
if (DECL_NAMESPACE_SCOPE_P (new_friend))
{
tree old_decl;
possible. */
new_friend_template_info = DECL_TEMPLATE_INFO (new_friend);
new_friend_is_defn =
- (DECL_INITIAL (DECL_TEMPLATE_RESULT
+ (DECL_INITIAL (DECL_TEMPLATE_RESULT
(template_for_substitution (new_friend)))
!= NULL_TREE);
if (TREE_CODE (new_friend) == TEMPLATE_DECL)
{
/* This declaration is a `primary' template. */
DECL_PRIMARY_TEMPLATE (new_friend) = new_friend;
-
+
new_friend_result_template_info
= DECL_TEMPLATE_INFO (DECL_TEMPLATE_RESULT (new_friend));
}
declaration. For example, given:
template <class T> void f(T);
- template <class U> class C {
- template <class T> friend void f(T) {}
+ template <class U> class C {
+ template <class T> friend void f(T) {}
};
the friend declaration actually provides the definition
run through all specialization of `f', adding to their
DECL_TI_ARGS appropriately. In particular, they need a
new set of outer arguments, corresponding to the
- arguments for this class instantiation.
+ arguments for this class instantiation.
The same situation can arise with something like this:
friend void f(int);
- template <class T> class C {
- friend void f(T) {}
- };
+ template <class T> class C {
+ friend void f(T) {}
+ };
when `C<int>' is instantiated. Now, `f(int)' is defined
in the class. */
reregister_specialization (new_friend,
most_general_template (old_decl),
old_decl);
- else
+ else
{
tree t;
tree new_friend_args;
- DECL_TEMPLATE_INFO (DECL_TEMPLATE_RESULT (old_decl))
+ DECL_TEMPLATE_INFO (DECL_TEMPLATE_RESULT (old_decl))
= new_friend_result_template_info;
-
+
new_friend_args = TI_ARGS (new_friend_template_info);
- for (t = DECL_TEMPLATE_SPECIALIZATIONS (old_decl);
+ for (t = DECL_TEMPLATE_SPECIALIZATIONS (old_decl);
t != NULL_TREE;
t = TREE_CHAIN (t))
{
tree spec = TREE_VALUE (t);
-
- DECL_TI_ARGS (spec)
+
+ DECL_TI_ARGS (spec)
= add_outermost_template_args (new_friend_args,
DECL_TI_ARGS (spec));
}
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;
}
if (TREE_CODE (context) == NAMESPACE_DECL)
push_nested_namespace (context);
else
- push_nested_class (tsubst (context, args, tf_none, NULL_TREE));
+ push_nested_class (tsubst (context, args, tf_none, NULL_TREE));
}
/* First, we look for a class template. */
- tmpl = lookup_name (DECL_NAME (friend_tmpl), /*prefer_type=*/0);
+ tmpl = lookup_name (DECL_NAME (friend_tmpl), /*prefer_type=*/0);
/* But, if we don't find one, it might be because we're in a
situation like this:
tmpl = tsubst (friend_tmpl, args, tf_error | tf_warning, NULL_TREE);
/* The new TMPL is not an instantiation of anything, so we
- forget its origins. We don't reset CLASSTYPE_TI_TEMPLATE for
+ forget its origins. We don't reset CLASSTYPE_TI_TEMPLATE for
the new type because that is supposed to be the corresponding
template decl, i.e., TMPL. */
DECL_USE_TEMPLATE (tmpl) = 0;
friend_type = TREE_TYPE (pushdecl_top_level (tmpl));
}
- if (context)
+ if (context)
{
if (TREE_CODE (context) == NAMESPACE_DECL)
pop_nested_namespace (context);
tree typedecl;
tree pbinfo;
tree base_list;
-
+
if (type == error_mark_node)
return error_mark_node;
- if (TYPE_BEING_DEFINED (type)
+ if (TYPE_BEING_DEFINED (type)
|| COMPLETE_TYPE_P (type)
|| dependent_type_p (type))
return type;
{
const char *str = "candidates are:";
error ("ambiguous class template instantiation for %q#T", type);
- for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t;
+ for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t;
t = TREE_CHAIN (t))
{
if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args))
template <class T> struct S {};
template <class T> struct S<T*> {};
-
+
and supposing that we are instantiating S<int*>, ARGS will
present be {int*} but we need {int}. */
- tree inner_args
+ tree inner_args
= get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
args);
/* Set the input location to the template definition. This is needed
if tsubsting causes an error. */
- input_location = DECL_SOURCE_LOCATION (TYPE_NAME (pattern));
+ typedecl = TYPE_MAIN_DECL (type);
+ input_location = DECL_SOURCE_LOCATION (typedecl);
+ in_system_header = DECL_IN_SYSTEM_HEADER (typedecl);
TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern);
- TYPE_HAS_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);
{
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. */
for (i = 0; BINFO_BASE_ITERATE (pbinfo, i, pbase_binfo); i++)
base = tsubst (BINFO_TYPE (pbase_binfo), args, tf_error, NULL_TREE);
if (base == error_mark_node)
continue;
-
+
base_list = tree_cons (access, base, base_list);
if (BINFO_VIRTUAL_P (pbase_binfo))
TREE_TYPE (base_list) = integer_type_node;
/* 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
tsubst_enum. */
if (name)
SET_IDENTIFIER_TYPE_VALUE (name, newtag);
- pushtag (name, newtag, /*globalize=*/0);
+ pushtag (name, newtag, /*tag_scope=*/ts_current);
}
}
- else if (TREE_CODE (t) == FUNCTION_DECL
+ else if (TREE_CODE (t) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (t))
{
/* Build new TYPE_METHODS. */
tree r;
-
+
if (TREE_CODE (t) == TEMPLATE_DECL)
++processing_template_decl;
r = tsubst (t, args, tf_error, NULL_TREE);
if (!COMPLETE_TYPE_P (rtype))
{
cxx_incomplete_type_error (r, rtype);
- r = error_mark_node;
+ r = error_mark_node;
}
}
set_current_access_from_decl (r);
finish_member_declaration (r);
}
- }
+ }
}
}
else
/* 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);
- else if (uses_template_parms (friend_type))
- new_friend_type = tsubst (friend_type, args,
- tf_error | tf_warning, NULL_TREE);
- else if (CLASSTYPE_USE_TEMPLATE (friend_type))
- new_friend_type = friend_type;
- else
{
+ /* template <class T> friend class C; */
+ friend_type = tsubst_friend_class (friend_type, args);
+ adjust_processing_template_decl = true;
+ }
+ else if (TREE_CODE (friend_type) == UNBOUND_CLASS_TEMPLATE)
+ {
+ /* template <class T> friend class C::D; */
+ 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)
+ {
+ /* This could be either
+
+ friend class T::C;
+
+ when dependent_type_p is false or
+
+ template <class U> friend class T::C;
+
+ otherwise. */
+ 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 (!CLASSTYPE_USE_TEMPLATE (friend_type)
+ && hidden_name_p (TYPE_NAME (friend_type)))
+ {
+ /* friend class C;
+
+ where C hasn't been declared yet. Let's lookup name
+ from namespace scope directly, bypassing any name that
+ come from dependent base class. */
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_current);
pop_nested_namespace (ns);
}
+ else if (uses_template_parms (friend_type))
+ /* friend class C<T>; */
+ friend_type = tsubst (friend_type, args,
+ tf_error | tf_warning, NULL_TREE);
+ /* Otherwise it's
- if (TREE_CODE (friend_type) == TEMPLATE_DECL)
+ friend class C;
+
+ where C is already declared or
+
+ friend class C<int>;
+
+ We don't have to do anything in these cases. */
+
+ 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;
push_deferring_access_checks (dk_no_check);
}
-
+
r = tsubst_friend_function (t, args);
add_friend (type, r, /*complain=*/false);
if (TREE_CODE (t) == TEMPLATE_DECL)
the class itself. This puts error messages involving generated
implicit functions at a predictable point, and the same point
that would be used for non-template classes. */
- typedecl = TYPE_MAIN_DECL (type);
input_location = DECL_SOURCE_LOCATION (typedecl);
unreverse_member_declarations (type);
default arguments may reference members of the class. */
if (!PRIMARY_TEMPLATE_P (template))
for (t = TYPE_METHODS (type); t; t = TREE_CHAIN (t))
- if (TREE_CODE (t) == FUNCTION_DECL
+ if (TREE_CODE (t) == FUNCTION_DECL
/* Implicitly generated member functions will not have template
information; they are not instantiations, but instead are
created "fresh" for each instantiation. */
tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
tree r;
-
+
if (!t)
r = t;
else if (TYPE_P (t))
will always be set. */
if (!TREE_TYPE (r))
{
- int saved_processing_template_decl = processing_template_decl;
+ int saved_processing_template_decl = processing_template_decl;
processing_template_decl = 0;
r = tsubst_copy_and_build (r, /*args=*/NULL_TREE,
tf_error, /*in_decl=*/NULL_TREE,
/*function_p=*/false);
- processing_template_decl = saved_processing_template_decl;
+ processing_template_decl = saved_processing_template_decl;
}
r = fold (r);
}
int len = TREE_VEC_LENGTH (t);
int need_new = 0, i;
tree *elts = alloca (len * sizeof (tree));
-
+
for (i = 0; i < len; i++)
{
tree orig_arg = TREE_VEC_ELT (t, i);
new_arg = tsubst_template_args (orig_arg, args, complain, in_decl);
else
new_arg = tsubst_template_arg (orig_arg, args, complain, in_decl);
-
+
if (new_arg == error_mark_node)
return error_mark_node;
if (new_arg != orig_arg)
need_new = 1;
}
-
+
if (!need_new)
return t;
t = make_tree_vec (len);
for (i = 0; i < len; i++)
TREE_VEC_ELT (t, i) = elts[i];
-
+
return t;
}
new_parms = &(TREE_CHAIN (*new_parms)),
parms = TREE_CHAIN (parms))
{
- tree new_vec =
+ tree new_vec =
make_tree_vec (TREE_VEC_LENGTH (TREE_VALUE (parms)));
int i;
-
+
for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
{
tree tuple = TREE_VEC_ELT (TREE_VALUE (parms), i);
parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
default_value = tsubst_template_arg (default_value, args,
complain, NULL_TREE);
-
+
tuple = build_tree_list (default_value, parm_decl);
TREE_VEC_ELT (new_vec, i) = tuple;
}
-
- *new_parms =
- tree_cons (size_int (TMPL_PARMS_DEPTH (parms)
+
+ *new_parms =
+ tree_cons (size_int (TMPL_PARMS_DEPTH (parms)
- TMPL_ARGS_DEPTH (args)),
new_vec, NULL_TREE);
}
we are presently tsubst'ing. Return the substituted value. */
static tree
-tsubst_aggr_type (tree t,
- tree args,
- tsubst_flags_t complain,
- tree in_decl,
- int entering_scope)
+tsubst_aggr_type (tree t,
+ tree args,
+ tsubst_flags_t complain,
+ tree in_decl,
+ int entering_scope)
{
if (t == NULL_TREE)
return NULL_TREE;
if (argvec == error_mark_node)
return error_mark_node;
- r = lookup_template_class (t, argvec, in_decl, context,
+ r = lookup_template_class (t, argvec, in_decl, context,
entering_scope, complain);
return cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
}
- else
+ else
/* This is not a template type, so there's nothing to do. */
return t;
/* This default argument came from a template. Instantiate the
default argument here, not in tsubst. In the case of
- something like:
-
+ something like:
+
template <class T>
struct S {
static T t();
void f(T = t());
};
-
+
we must be careful to do name lookup in the scope of S<T>,
rather than in the current class. */
push_access_scope (fn);
if (uses_template_parms (tmpl_args))
return;
- for (arg = TYPE_ARG_TYPES (TREE_TYPE (fn));
- arg;
+ for (arg = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ arg;
arg = TREE_CHAIN (arg))
if (TREE_PURPOSE (arg))
- TREE_PURPOSE (arg) = tsubst_default_argument (fn,
+ TREE_PURPOSE (arg) = tsubst_default_argument (fn,
TREE_VALUE (arg),
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. */
- gcc_assert (full_args != tmpl_args);
+ 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,
- /*class_specializations_p=*/true);
- 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
- original, but will record the current template arguments.
+ original, but will record the current template arguments.
We also create a new function declaration, which is just
like the old one, but points to this new template, rather
than the old one. */
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,
- /*entering_scope=*/1);
+ DECL_CONTEXT (r)
+ = tsubst_aggr_type (DECL_CONTEXT (t), args,
+ complain, in_decl,
+ /*entering_scope=*/1);
DECL_TEMPLATE_INFO (r) = build_tree_list (t, args);
if (TREE_CODE (decl) == TYPE_DECL)
/* The template parameters for this new template are all the
template parameters for the old template, except the
outermost level of parameters. */
- DECL_TEMPLATE_PARMS (r)
+ DECL_TEMPLATE_PARMS (r)
= tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args,
complain);
if (TREE_CODE (decl) != TYPE_DECL)
/* Record this non-type partial instantiation. */
- register_specialization (r, t,
+ register_specialization (r, t,
DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)));
}
break;
tree argvec = NULL_TREE;
tree *friends;
tree gen_tmpl;
+ tree type;
int member;
int args_depth;
int parms_depth;
specialization, and the complete set of arguments used to
specialize R. */
gen_tmpl = most_general_template (DECL_TI_TEMPLATE (t));
- argvec = tsubst_template_args (DECL_TI_ARGS
+ argvec = tsubst_template_args (DECL_TI_ARGS
(DECL_TEMPLATE_RESULT (gen_tmpl)),
- args, complain, in_decl);
+ args, complain, in_decl);
/* Check to see if we already have this specialization. */
spec = retrieve_specialization (gen_tmpl, argvec,
there was a specialization of a member template, like
this:
- template <class T> struct S { template <class U> void f(); }
- template <> template <class U> void S<int>::f(U);
+ template <class T> struct S { template <class U> void f(); }
+ template <> template <class U> void S<int>::f(U);
Here, we'll be substituting into the specialization,
because that's where we can find the code we actually
want to generate, but we'll have enough arguments for
- the most general template.
+ the most general template.
We also deal with the peculiar case:
- template <class T> struct S {
+ template <class T> struct S {
template <class U> friend void f();
};
template <class U> void f() {}
which we can spot because the pattern will be a
specialization in this case. */
args_depth = TMPL_ARGS_DEPTH (args);
- parms_depth =
- TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (t)));
+ parms_depth =
+ TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (t)));
if (args_depth > parms_depth
&& !DECL_TEMPLATE_SPECIALIZATION (t))
args = get_innermost_template_args (args, parms_depth);
{
/* This special case arises when we have something like this:
- template <class T> struct S {
- friend void f<int>(int, double);
+ template <class T> struct S {
+ friend void f<int>(int, double);
};
Here, the DECL_TI_TEMPLATE for the friend declaration
member = 2;
else
member = 1;
- ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
+ ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
complain, t, /*entering_scope=*/1);
}
else
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;
/* We do NOT check for matching decls pushed separately at this
- point, as they may not represent instantiations of this
- template, and in any case are considered separate under the
- discrete model. */
+ point, as they may not represent instantiations of this
+ template, and in any case are considered separate under the
+ discrete model. */
r = copy_decl (t);
DECL_USE_TEMPLATE (r) = 0;
TREE_TYPE (r) = type;
DECL_INITIAL (r) = NULL_TREE;
DECL_CONTEXT (r) = ctx;
- if (member && DECL_CONV_FN_P (r))
+ if (member && DECL_CONV_FN_P (r))
/* Type-conversion operator. Reconstruct the name, in
case it's the name of one of the template's parameters. */
DECL_NAME (r) = mangle_conv_op_name_for_type (TREE_TYPE (type));
GEN_TMPL is NULL. */
if (gen_tmpl)
{
- DECL_TEMPLATE_INFO (r)
+ DECL_TEMPLATE_INFO (r)
= tree_cons (gen_tmpl, argvec, NULL_TREE);
SET_DECL_IMPLICIT_INSTANTIATION (r);
register_specialization (r, gen_tmpl, argvec);
until they are called, for a template. But, for a
declaration like:
- template <class T> void f ()
- { extern void g(int i = T()); }
-
+ template <class T> void f ()
+ { extern void g(int i = T()); }
+
we should do the substitution when the template is
instantiated. We handle the member function case in
instantiate_class_template since the default arguments
/* Copy the list of befriending classes. */
for (friends = &DECL_BEFRIENDING_CLASSES (r);
*friends;
- friends = &TREE_CHAIN (*friends))
+ friends = &TREE_CHAIN (*friends))
{
*friends = copy_node (*friends);
TREE_VALUE (*friends) = tsubst (TREE_VALUE (*friends),
clone_function_decl (r, /*update_method_vec_p=*/0);
}
else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
- grok_op_properties (r, DECL_FRIEND_P (r),
- (complain & tf_error) != 0);
+ grok_op_properties (r, (complain & tf_error) != 0);
if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
SET_DECL_FRIEND_CONTEXT (r,
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. */
DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args,
complain, in_decl);
TREE_CHAIN (r) = NULL_TREE;
- if (VOID_TYPE_P (type))
+ if (VOID_TYPE_P (type))
cp_error_at ("instantiation of %qD as type %qT", r, type);
}
break;
case USING_DECL:
- {
- r = copy_node (t);
- /* It is not a dependent using decl any more. */
- TREE_TYPE (r) = void_type_node;
- DECL_INITIAL (r)
- = tsubst_copy (DECL_INITIAL (t), args, complain, in_decl);
- DECL_NAME (r)
- = tsubst_copy (DECL_NAME (t), args, complain, in_decl);
- TREE_CHAIN (r) = NULL_TREE;
- }
+ /* We reach here only for member using decls. */
+ if (DECL_DEPENDENT_P (t))
+ {
+ r = do_class_using_decl
+ (tsubst_copy (USING_DECL_SCOPE (t), args, complain, in_decl),
+ tsubst_copy (DECL_NAME (t), args, complain, in_decl));
+ if (!r)
+ r = error_mark_node;
+ }
+ else
+ {
+ r = copy_node (t);
+ TREE_CHAIN (r) = NULL_TREE;
+ }
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;
if (TYPE_P (CP_DECL_CONTEXT (t)))
- ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
+ ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
complain,
in_decl, /*entering_scope=*/1);
else if (DECL_NAMESPACE_SCOPE_P (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 %qD as type %qT", r, type);
- /* Compute the size, alignment, etc. of R. */
layout_decl (r, 0);
}
break;
default:
gcc_unreachable ();
- }
+ }
/* Restore the file and line information. */
input_location = saved_loc;
/* Substitute into the ARG_TYPES of a function type. */
static tree
-tsubst_arg_types (tree arg_types,
- tree args,
- tsubst_flags_t complain,
- tree in_decl)
+tsubst_arg_types (tree arg_types,
+ tree args,
+ tsubst_flags_t complain,
+ tree in_decl)
{
tree remaining_arg_types;
tree type;
+ tree default_arg;
+ tree result = NULL_TREE;
if (!arg_types || arg_types == void_list_node)
return arg_types;
-
+
remaining_arg_types = tsubst_arg_types (TREE_CHAIN (arg_types),
args, complain, in_decl);
if (remaining_arg_types == error_mark_node)
if (VOID_TYPE_P (type))
{
if (complain & tf_error)
- {
- error ("invalid parameter type %qT", type);
- if (in_decl)
- cp_error_at ("in declaration %qD", in_decl);
- }
+ {
+ error ("invalid parameter type %qT", type);
+ if (in_decl)
+ cp_error_at ("in declaration %qD", in_decl);
+ }
return error_mark_node;
}
top-level qualifiers as required. */
type = TYPE_MAIN_VARIANT (type_decays_to (type));
- /* Note that we do not substitute into default arguments here. The
- standard mandates that they be instantiated only when needed,
- which is done in build_over_call. */
- return hash_tree_cons (TREE_PURPOSE (arg_types), type,
- remaining_arg_types);
-
+ /* We do not substitute into default arguments here. The standard
+ mandates that they be instantiated only when needed, which is
+ done in build_over_call. */
+ default_arg = TREE_PURPOSE (arg_types);
+
+ if (default_arg && TREE_CODE (default_arg) == DEFAULT_ARG)
+ {
+ /* We've instantiated a template before its default arguments
+ have been parsed. This can happen for a nested template
+ class, and is not an error unless we require the default
+ argument in a call of this function. */
+ result = tree_cons (default_arg, type, remaining_arg_types);
+ VEC_safe_push (tree, gc, DEFARG_INSTANTIATIONS (default_arg), result);
+ }
+ else
+ result = hash_tree_cons (default_arg, type, remaining_arg_types);
+
+ return result;
}
/* Substitute into a FUNCTION_TYPE or METHOD_TYPE. This routine does
results in an invalid type.] */
static tree
-tsubst_function_type (tree t,
- tree args,
- tsubst_flags_t complain,
- tree in_decl)
+tsubst_function_type (tree t,
+ tree args,
+ tsubst_flags_t complain,
+ tree in_decl)
{
tree return_type;
tree arg_types;
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,
- complain, in_decl);
+ complain, in_decl);
if (arg_types == error_mark_node)
return error_mark_node;
-
+
/* Construct a new type node and return it. */
if (TREE_CODE (t) == FUNCTION_TYPE)
fntype = build_function_type (return_type, arg_types);
if (! IS_AGGR_TYPE (r))
{
/* [temp.deduct]
-
+
Type deduction may fail for any of the following
reasons:
-
+
-- Attempting to create "pointer to member of T" when T
is not a class type. */
if (complain & tf_error)
r);
return error_mark_node;
}
-
- fntype = build_method_type_directly (r, return_type,
+
+ fntype = build_method_type_directly (r, return_type,
TREE_CHAIN (arg_types));
}
fntype = cp_build_qualified_type_real (fntype, TYPE_QUALS (t), complain);
fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
-
- return fntype;
+
+ return fntype;
}
/* FNTYPE is a FUNCTION_TYPE or METHOD_TYPE. Substitute the template
specification. If there is no specification, return NULL_TREE. */
static tree
-tsubst_exception_specification (tree fntype,
- tree args,
+tsubst_exception_specification (tree fntype,
+ tree args,
tsubst_flags_t complain,
tree in_decl)
{
/* Substitute into the PARMS of a call-declarator. */
static tree
-tsubst_call_declarator_parms (tree parms,
- tree args,
- tsubst_flags_t complain,
- tree in_decl)
+tsubst_call_declarator_parms (tree parms,
+ tree args,
+ tsubst_flags_t complain,
+ tree in_decl)
{
tree new_parms;
tree type;
if (!parms || parms == void_list_node)
return parms;
-
+
new_parms = tsubst_call_declarator_parms (TREE_CHAIN (parms),
args, complain, in_decl);
/* Figure out the type of this parameter. */
type = tsubst (TREE_VALUE (parms), args, complain, in_decl);
-
+
/* Figure out the default argument as well. Note that we use
tsubst_expr since the default argument is really an expression. */
defarg = tsubst_expr (TREE_PURPOSE (parms), args, complain, in_decl);
|| 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
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))
{
if (pedantic)
pedwarn ("creating array with size zero");
}
- else if (integer_zerop (max)
- || (TREE_CODE (max) == INTEGER_CST
+ else if (integer_zerop (max)
+ || (TREE_CODE (max) == INTEGER_CST
&& INT_CST_LT (max, integer_zero_node)))
{
/* [temp.deduct]
Type deduction may fail for any of the following
- reasons:
+ reasons:
Attempting to create an array with a size that is
zero or negative. */
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
instantiated. */
if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
arg = TYPE_NAME (arg);
-
- r = lookup_template_class (arg,
- argvec, in_decl,
+
+ r = lookup_template_class (arg,
+ argvec, in_decl,
DECL_CONTEXT (arg),
/*entering_scope=*/0,
complain);
if (cp_type_quals (t))
{
r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
- r = cp_build_qualified_type_real
- (r, cp_type_quals (t),
+ r = cp_build_qualified_type_real
+ (r, cp_type_quals (t),
complain | (TREE_CODE (t) == TEMPLATE_TYPE_PARM
? tf_ignore_bad_quals : 0));
}
if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
tree argvec = tsubst (TYPE_TI_ARGS (t), args,
- complain, in_decl);
+ complain, in_decl);
if (argvec == error_mark_node)
return error_mark_node;
case TEMPLATE_PARM_INDEX:
r = reduce_template_parm_level (t, type, levels);
break;
-
+
default:
gcc_unreachable ();
}
return t;
return hash_tree_cons (purpose, value, chain);
}
-
+
case TREE_BINFO:
/* We should never be tsubsting a binfo. */
gcc_unreachable ();
/* [temp.deduct]
-
+
Type deduction may fail for any of the following
- reasons:
+ reasons:
-- Attempting to create a pointer to reference type.
-- Attempting to create a reference to a reference type or
error ("forming reference to void");
else
error ("forming %s to reference type %qT",
- (code == POINTER_TYPE) ? "pointer" : "reference",
- type);
+ (code == POINTER_TYPE) ? "pointer" : "reference",
+ type);
last_loc = input_location;
}
if (r != error_mark_node)
/* Will this ever be needed for TYPE_..._TO values? */
layout_type (r);
-
+
return r;
}
case OFFSET_TYPE:
Type deduction may fail for any of the following
reasons:
-
+
-- Attempting to create "pointer to member of T" when T
- is not a class type. */
+ is not a class type. */
if (complain & tf_error)
error ("creating pointer to member of non-class type %qT", r);
return error_mark_node;
{
if (complain & tf_error)
error ("creating pointer to member reference type %qT", type);
-
+ return error_mark_node;
+ }
+ if (TREE_CODE (type) == VOID_TYPE)
+ {
+ if (complain & tf_error)
+ error ("creating pointer to member of type void");
return error_mark_node;
}
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),
return error_mark_node;
/* Substitute the exception specification. */
- specs = tsubst_exception_specification (t, args, complain,
+ specs = tsubst_exception_specification (t, args, complain,
in_decl);
if (specs)
fntype = build_exception_variant (fntype, specs);
if (type == TREE_TYPE (t) && domain == TYPE_DOMAIN (t))
return t;
- /* These checks should match the ones in grokdeclarator.
+ /* These checks should match the ones in grokdeclarator.
+
+ [temp.deduct]
- [temp.deduct]
-
- The deduction may fail for any of the following reasons:
+ The deduction may fail for any of the following reasons:
-- Attempting to create an array with an element type that
- is void, a function type, or a reference type, or [DR337]
+ is void, a function type, or a reference type, or [DR337]
an abstract class type. */
- if (TREE_CODE (type) == VOID_TYPE
+ if (TREE_CODE (type) == VOID_TYPE
|| TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == REFERENCE_TYPE)
{
if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type))
{
if (complain & tf_error)
- error ("creating array of %qT, which is an abstract class type",
+ error ("creating array of %qT, which is an abstract class type",
type);
- return error_mark_node;
+ return error_mark_node;
}
r = build_cplus_array_type (type, domain);
if (e1 == error_mark_node || e2 == error_mark_node)
return error_mark_node;
- return fold (build2 (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 (build1 (TREE_CODE (t), TREE_TYPE (t), e));
+ return fold_build1 (TREE_CODE (t), TREE_TYPE (t), e);
}
case TYPENAME_TYPE:
tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, complain,
in_decl, /*entering_scope=*/1);
tree f = tsubst_copy (TYPENAME_TYPE_FULLNAME (t), args,
- complain, in_decl);
+ complain, in_decl);
if (ctx == error_mark_node || f == error_mark_node)
return error_mark_node;
{
/* Normally, make_typename_type does not require that the CTX
have complete type in order to allow things like:
-
- template <class T> struct S { typename S<T>::X Y; };
+
+ template <class T> struct S { typename S<T>::X Y; };
But, such constructs have already been resolved by this
point, so here CTX really should have complete type, unless
}
}
- 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;
- if (TREE_CODE (f) == TYPE_DECL)
- {
+ if (TREE_CODE (f) == TYPE_DECL)
+ {
complain |= tf_ignore_bad_quals;
- f = TREE_TYPE (f);
- }
-
- return cp_build_qualified_type_real
- (f, cp_type_quals (f) | cp_type_quals (t), complain);
+ 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);
}
-
+
case UNBOUND_CLASS_TEMPLATE:
{
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:
}
default:
- sorry ("use of `%s' in template",
+ sorry ("use of %qs in template",
tree_code_name [(int) TREE_CODE (t)]);
return error_mark_node;
}
BASELINK_ACCESS_BINFO and BASELINK_BINFO are going to have
non-dependent types; otherwise, the lookup could not have
succeeded. However, they may indicate bases of the template
- class, rather than the instantiated class.
+ class, rather than the instantiated class.
In addition, lookups that were not ambiguous before may be
ambiguous now. Therefore, we perform the lookup again. */
}
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
/* Add back the template arguments, if present. */
if (BASELINK_P (baselink) && template_id_p)
- BASELINK_FUNCTIONS (baselink)
+ 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,
+ return adjust_result_of_qualified_name_lookup (baselink,
qualifying_scope,
object_type);
}
of "&". */
static tree
-tsubst_qualified_id (tree qualified_id, tree args,
+tsubst_qualified_id (tree qualified_id, tree args,
tsubst_flags_t complain, tree in_decl,
bool done, bool address_p)
{
if (dependent_type_p (scope))
return build_nt (SCOPE_REF, scope, expr);
-
+
if (!BASELINK_P (name) && !DECL_P (expr))
{
expr = lookup_qualified_name (scope, expr, /*is_type_p=*/0, false);
return error_mark_node;
}
}
-
+
if (DECL_P (expr))
{
check_accessibility_of_qualified_id (expr, /*object_type=*/NULL_TREE,
if (expr == error_mark_node || TREE_CODE (expr) == TREE_LIST)
{
if (complain & tf_error)
- qualified_name_lookup_error (scope,
+ qualified_name_lookup_error (scope,
TREE_OPERAND (qualified_id, 1),
expr);
return error_mark_node;
expr);
else if (TYPE_P (scope))
{
- expr = (adjust_result_of_qualified_name_lookup
+ 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;
}
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:
-
+
template <int I> int f() {
enum E { a = I };
struct S { void g() { E e = a; } };
};
-
+
When we instantiate f<7>::S::g(), say, lookup_name is not
clever enough to find f<7>::a. */
- enum_type
- = tsubst_aggr_type (TREE_TYPE (t), args, complain, in_decl,
+ enum_type
+ = tsubst_aggr_type (TREE_TYPE (t), args, complain, in_decl,
/*entering_scope=*/0);
- for (v = TYPE_VALUES (enum_type);
- v != NULL_TREE;
+ for (v = TYPE_VALUES (enum_type);
+ v != NULL_TREE;
v = TREE_CHAIN (v))
if (TREE_PURPOSE (v) == DECL_NAME (t))
return TREE_VALUE (v);
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;
case VAR_DECL:
case TEMPLATE_DECL:
if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
- return tsubst (TREE_TYPE (DECL_TEMPLATE_RESULT (t)),
+ return tsubst (TREE_TYPE (DECL_TEMPLATE_RESULT (t)),
args, complain, in_decl);
else if (DECL_FUNCTION_TEMPLATE_P (t) && DECL_MEMBER_TEMPLATE_P (t))
return tsubst (t, args, complain, in_decl);
template <template <class> class TT> struct C {};
template <class T> struct D {
template <class U> struct E {};
- C<E> c; // #1
+ C<E> c; // #1
};
D<int> d; // #2
case TRUTH_NOT_EXPR:
case BIT_NOT_EXPR:
case ADDR_EXPR:
- case CONVERT_EXPR: /* Unary + */
+ case UNARY_PLUS_EXPR: /* Unary + */
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
case ARROW_EXPR:
object = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
name = TREE_OPERAND (t, 1);
- if (TREE_CODE (name) == BIT_NOT_EXPR)
+ if (TREE_CODE (name) == BIT_NOT_EXPR)
{
name = tsubst_copy (TREE_OPERAND (name, 0), args,
complain, in_decl);
name = build_nt (SCOPE_REF, base, name);
}
else if (TREE_CODE (name) == BASELINK)
- name = tsubst_baselink (name,
- non_reference (TREE_TYPE (object)),
- args, complain,
+ name = tsubst_baselink (name,
+ non_reference (TREE_TYPE (object)),
+ args, complain,
in_decl);
else
name = tsubst_copy (name, args, complain, in_decl);
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,
+ return build_nt (code,
tsubst_copy (TREE_OPERAND (t, 0), args,
complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 1), args, complain,
case TEMPLATE_ID_EXPR:
{
- /* Substituted template arguments */
+ /* Substituted template arguments */
tree fn = TREE_OPERAND (t, 0);
tree targs = TREE_OPERAND (t, 1);
fn = tsubst_copy (fn, args, complain, in_decl);
if (targs)
targs = tsubst_template_args (targs, args, complain, in_decl);
-
+
return lookup_template_function (fn, targs);
}
case CONSTRUCTOR:
{
r = build_constructor
- (tsubst (TREE_TYPE (t), args, complain, in_decl),
+ (tsubst (TREE_TYPE (t), args, complain, in_decl),
tsubst_copy (CONSTRUCTOR_ELTS (t), args, complain, in_decl));
TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t);
return r;
}
case CTOR_INITIALIZER:
- finish_mem_initializers (tsubst_initializer_list
+ finish_mem_initializers (tsubst_initializer_list
(TREE_OPERAND (t, 0), args));
break;
do_using_directive (tsubst_expr (USING_STMT_NAMESPACE (t),
args, complain, in_decl));
break;
-
+
case DECL_EXPR:
{
tree decl;
finish_label_decl (DECL_NAME (decl));
else if (TREE_CODE (decl) == USING_DECL)
{
- tree scope = DECL_INITIAL (decl);
+ tree scope = USING_DECL_SCOPE (decl);
tree name = DECL_NAME (decl);
tree decl;
-
+
scope = tsubst_expr (scope, args, complain, in_decl);
decl = lookup_qualified_name (scope, name,
/*is_type_p=*/false,
decl = tsubst (decl, args, complain, in_decl);
if (decl != error_mark_node)
{
- if (init)
- DECL_INITIAL (decl) = error_mark_node;
- /* By marking the declaration as instantiated, we avoid
- trying to instantiate it. Since instantiate_decl can't
- handle local variables, and since we've already done
- all that needs to be done, that's the right thing to
- do. */
- if (TREE_CODE (decl) == VAR_DECL)
- DECL_TEMPLATE_INSTANTIATED (decl) = 1;
+ if (init)
+ DECL_INITIAL (decl) = error_mark_node;
+ /* By marking the declaration as instantiated, we avoid
+ trying to instantiate it. Since instantiate_decl can't
+ handle local variables, and since we've already done
+ all that needs to be done, that's the right thing to
+ do. */
+ if (TREE_CODE (decl) == VAR_DECL)
+ DECL_TEMPLATE_INSTANTIATED (decl) = 1;
if (TREE_CODE (decl) == VAR_DECL
&& ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
/* Anonymous aggregates are a special case. */
finish_anon_union (decl);
- else
+ else
{
maybe_push_decl (decl);
if (TREE_CODE (decl) == VAR_DECL
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;
(ASM_VOLATILE_P (t),
tsubst_expr (ASM_STRING (t), args, complain, in_decl),
tsubst_expr (ASM_OUTPUTS (t), args, complain, in_decl),
- tsubst_expr (ASM_INPUTS (t), args, complain, in_decl),
+ tsubst_expr (ASM_INPUTS (t), args, complain, in_decl),
tsubst_expr (ASM_CLOBBERS (t), args, complain, in_decl));
{
tree asm_expr = tmp;
finish_handler_sequence (stmt);
}
break;
-
+
case HANDLER:
{
tree decl;
default:
gcc_assert (!STATEMENT_CODE_P (TREE_CODE (t)));
-
+
return tsubst_copy_and_build (t, args, complain, in_decl,
/*function_p=*/false);
}
call. Return the substituted version of T. */
static tree
-tsubst_non_call_postfix_expression (tree t, tree args,
+tsubst_non_call_postfix_expression (tree t, tree args,
tsubst_flags_t complain,
tree in_decl)
{
analysis. FUNCTION_P is true if T is the "F" in "F (ARGS)". */
tree
-tsubst_copy_and_build (tree t,
- tree args,
- tsubst_flags_t complain,
- tree in_decl,
+tsubst_copy_and_build (tree t,
+ tree args,
+ tsubst_flags_t complain,
+ tree in_decl,
bool function_p)
{
#define RECUR(NODE) \
if (targs)
targs = tsubst_template_args (targs, args, complain, in_decl);
-
+
if (TREE_CODE (template) == COMPONENT_REF)
{
object = TREE_OPERAND (template, 0);
else
object = NULL_TREE;
template = lookup_template_function (template, targs);
-
+
if (object)
- return build3 (COMPONENT_REF, TREE_TYPE (template),
+ 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 BIT_NOT_EXPR:
case ABS_EXPR:
case TRUTH_NOT_EXPR:
- case CONVERT_EXPR: /* Unary + */
+ case UNARY_PLUS_EXPR: /* Unary + */
case REALPART_EXPR:
case IMAGPART_EXPR:
return build_x_unary_op (TREE_CODE (t), RECUR (TREE_OPERAND (t, 0)));
case ADDR_EXPR:
op1 = TREE_OPERAND (t, 0);
if (TREE_CODE (op1) == SCOPE_REF)
- op1 = tsubst_qualified_id (op1, args, complain, in_decl,
+ op1 = tsubst_qualified_id (op1, args, complain, in_decl,
/*done=*/true, /*address_p=*/true);
else
- op1 = tsubst_non_call_postfix_expression (op1, args, complain,
+ op1 = tsubst_non_call_postfix_expression (op1, args, complain,
in_decl);
if (TREE_CODE (op1) == LABEL_DECL)
return finish_label_address_expr (DECL_NAME (op1));
case MEMBER_REF:
case DOTSTAR_EXPR:
return build_x_binary_op
- (TREE_CODE (t),
+ (TREE_CODE (t),
RECUR (TREE_OPERAND (t, 0)),
RECUR (TREE_OPERAND (t, 1)),
/*overloaded_p=*/NULL);
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:
{
qualified_p = true;
function = tsubst_qualified_id (function, args, complain, in_decl,
- /*done=*/false,
+ /*done=*/false,
/*address_p=*/false);
}
else
qualified_p = (TREE_CODE (function) == COMPONENT_REF
&& (TREE_CODE (TREE_OPERAND (function, 1))
== SCOPE_REF));
- function = tsubst_copy_and_build (function, args, complain,
+ function = tsubst_copy_and_build (function, args, complain,
in_decl,
!qualified_p);
if (BASELINK_P (function))
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)
/*disallow_virtual=*/false,
/*koenig_p=*/false);
else
- return (build_new_method_call
+ return (build_new_method_call
(TREE_OPERAND (function, 0),
TREE_OPERAND (function, 1),
- call_args, NULL_TREE,
+ call_args, NULL_TREE,
qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL));
}
- return finish_call_expr (function, call_args,
+ return finish_call_expr (function, call_args,
/*disallow_virtual=*/qualified_p,
koenig_p);
}
RECUR (TREE_OPERAND (t, 2)));
case PSEUDO_DTOR_EXPR:
- return finish_pseudo_destructor_expr
+ return finish_pseudo_destructor_expr
(RECUR (TREE_OPERAND (t, 0)),
RECUR (TREE_OPERAND (t, 1)),
RECUR (TREE_OPERAND (t, 2)));
member = TREE_OPERAND (t, 1);
if (BASELINK_P (member))
- member = tsubst_baselink (member,
+ member = tsubst_baselink (member,
non_reference (TREE_TYPE (object)),
args, complain, in_decl);
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,
+ return finish_pseudo_destructor_expr (object,
NULL_TREE,
TREE_TYPE (object));
else if (TREE_CODE (member) == SCOPE_REF
&& (TREE_CODE (TREE_OPERAND (member, 1)) == BIT_NOT_EXPR))
- return finish_pseudo_destructor_expr (object,
+ return finish_pseudo_destructor_expr (object,
object,
TREE_TYPE (object));
}
{
tree tmpl;
tree args;
-
+
/* Lookup the template functions now that we know what the
scope is. */
tmpl = TREE_OPERAND (TREE_OPERAND (member, 1), 0);
args = TREE_OPERAND (TREE_OPERAND (member, 1), 1);
- member = lookup_qualified_name (TREE_OPERAND (member, 0), tmpl,
+ member = lookup_qualified_name (TREE_OPERAND (member, 0), tmpl,
/*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,
if (complain & tf_error)
{
if (TYPE_P (TREE_OPERAND (member, 0)))
- error ("%qT is not a class or namespace",
+ error ("%qT is not a class or namespace",
TREE_OPERAND (member, 0));
else
- error ("%qD is not a class or namespace",
+ error ("%qD is not a class or namespace",
TREE_OPERAND (member, 0));
}
return error_mark_node;
{
tree purpose = TREE_PURPOSE (elts);
tree value = TREE_VALUE (elts);
-
+
if (purpose && purpose_p)
purpose = RECUR (purpose);
value = RECUR (value);
r = tree_cons (purpose, value, r);
}
-
+
r = build_constructor (NULL_TREE, nreverse (r));
TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t);
return build_typeid (operand_0);
}
+ case VAR_DECL:
+ if (!args)
+ return t;
+ /* Fall through */
+
case PARM_DECL:
- return convert_from_reference (tsubst_copy (t, args, complain, in_decl));
+ {
+ tree r = 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 (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,
+ tsubst_copy (TREE_TYPE (t), args, complain,
in_decl));
case OFFSETOF_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:
+ /* Handle Objective-C++ constructs, if appropriate. */
+ {
+ tree subst
+ = objcp_tsubst_copy_and_build (t, args, complain,
+ in_decl, /*function_p=*/false);
+ if (subst)
+ return subst;
+ }
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++)
{
tree t = TREE_VEC_ELT (args, ix);
-
+
if (TYPE_P (t))
{
/* [basic.link]: A name with no linkage (notably, the name
if (nt)
{
- if (!(complain & tf_error))
- /*OK*/;
- else if (TYPE_ANONYMOUS_P (nt))
- error ("%qT uses anonymous type", t);
+ if (TYPE_ANONYMOUS_P (nt))
+ error ("%qT is/uses anonymous type", t);
else
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. */
result = true;
}
}
- if (result && complain & tf_error)
+ if (result && error_p)
error (" trying to instantiate %qD", tmpl);
return result;
}
{
tree spec;
tree clone;
-
+
spec = instantiate_template (DECL_CLONED_FUNCTION (tmpl), targ_ptr,
complain);
if (spec == error_mark_node)
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;
if (check_instantiated_args (gen_tmpl, INNERMOST_TEMPLATE_ARGS (targ_ptr),
complain))
return error_mark_node;
-
+
/* We are building a FUNCTION_DECL, during which the access of its
parameters and return types have to be checked. However this
FUNCTION_DECL which is the desired context for access checking
/* The FN is a TEMPLATE_DECL for a function. The ARGS are the
arguments that are being used when calling it. TARGS is a vector
- into which the deduced template arguments are placed.
+ into which the deduced template arguments are placed.
Return zero for success, 2 for an incomplete match that doesn't resolve
all the types, and 1 for complete failure. An error message will be
The parameter STRICT is one of:
- DEDUCE_CALL:
+ DEDUCE_CALL:
We are deducing arguments for a function call, as in
[temp.deduct.call].
DEDUCE_CONV:
- We are deducing arguments for a conversion function, as in
+ We are deducing arguments for a conversion function, as in
[temp.deduct.conv].
DEDUCE_EXACT:
We are deducing arguments when doing an explicit instantiation
as in [temp.explicit], when determining an explicit specialization
as in [temp.expl.spec], or when taking the address of a function
- template, as in [temp.deduct.funcaddr].
-
- DEDUCE_ORDER:
- We are deducing arguments when calculating the partial
- ordering between specializations of function or class
- templates, as in [temp.func.order] and [temp.class.order].
-
- LEN is the number of parms to consider before returning success, or -1
- for all. This is used in partial ordering to avoid comparing parms for
- which no actual argument was passed, since they are not considered in
- overload resolution (and are explicitly excluded from consideration in
- partial ordering in [temp.func.order]/6). */
+ template, as in [temp.deduct.funcaddr]. */
int
-fn_type_unification (tree fn,
- tree explicit_targs,
- tree targs,
- tree args,
- tree return_type,
- unification_kind_t strict,
- int len)
+fn_type_unification (tree fn,
+ tree explicit_targs,
+ tree targs,
+ tree args,
+ tree return_type,
+ unification_kind_t strict)
{
tree parms;
tree fntype;
if (explicit_targs)
{
/* [temp.deduct]
-
+
The specified template arguments must match the template
parameters in kind (i.e., type, nontype, template), and there
must not be more arguments than there are parameters;
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,
+ = (coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (fn),
+ explicit_targs, NULL_TREE, tf_none,
/*require_all_arguments=*/0));
if (converted_args == error_mark_node)
return 1;
/* Substitute the explicit args into the function type. This is
- necessary so that, for instance, explicitly declared function
- arguments can match null pointed constants. If we were given
- an incomplete set of explicit args, we must not do semantic
- processing during substitution as we could create partial
- instantiations. */
+ necessary so that, for instance, explicitly declared function
+ arguments can match null pointed constants. If we were given
+ an incomplete set of explicit args, we must not do semantic
+ processing during substitution as we could create partial
+ instantiations. */
incomplete = NUM_TMPL_ARGS (explicit_targs) != NUM_TMPL_ARGS (targs);
processing_template_decl += incomplete;
fntype = tsubst (fntype, converted_args, tf_none, NULL_TREE);
processing_template_decl -= incomplete;
-
+
if (fntype == error_mark_node)
return 1;
for (i = NUM_TMPL_ARGS (converted_args); i--;)
TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (converted_args, i);
}
-
+
parms = TYPE_ARG_TYPES (fntype);
/* Never do unification on the 'this' parameter. */
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
parms = TREE_CHAIN (parms);
-
+
if (return_type)
{
/* We've been given a return type to match, prepend it. */
parms = tree_cons (NULL_TREE, TREE_TYPE (fntype), parms);
args = tree_cons (NULL_TREE, return_type, args);
- if (len >= 0)
- ++len;
}
/* We allow incomplete unification without an error message here
because the standard doesn't seem to explicitly prohibit it. Our
callers must be ready to deal with unification failures in any
event. */
- result = type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
+ result = type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
targs, parms, args, /*subr=*/0,
- strict, /*allow_incomplete*/1, len);
+ strict, /*allow_incomplete*/1);
- if (result == 0)
+ if (result == 0)
/* All is well so far. Now, check:
-
- [temp.deduct]
-
+
+ [temp.deduct]
+
When all template arguments have been deduced, all uses of
template parameters in nondeduced contexts are replaced with
the corresponding deduced argument values. If the
initialized with the result of the conversion function. */
static int
-maybe_adjust_types_for_deduction (unification_kind_t strict,
- tree* parm,
- tree* arg)
+maybe_adjust_types_for_deduction (unification_kind_t strict,
+ tree* parm,
+ tree* arg)
{
int result = 0;
-
+
switch (strict)
{
case DEDUCE_CALL:
/* There is nothing to do in this case. */
return 0;
- case DEDUCE_ORDER:
- /* DR 214. [temp.func.order] is underspecified, and leads to no
- ordering between things like `T *' and `T const &' for `U *'.
- The former has T=U and the latter T=U*. The former looks more
- specialized and John Spicer considers it well-formed (the EDG
- compiler accepts it).
-
- John also confirms that deduction should proceed as in a function
- call. Which implies the usual ARG and PARM conversions as DEDUCE_CALL.
- However, in ordering, ARG can have REFERENCE_TYPE, but no argument
- to an actual call can have such a type.
-
- If both ARG and PARM are REFERENCE_TYPE, we change neither.
- If only ARG is a REFERENCE_TYPE, we look through that and then
- proceed as with DEDUCE_CALL (which could further convert it). */
- if (TREE_CODE (*arg) == REFERENCE_TYPE)
- {
- if (TREE_CODE (*parm) == REFERENCE_TYPE)
- return 0;
- *arg = TREE_TYPE (*arg);
- }
- break;
default:
gcc_unreachable ();
}
if (TREE_CODE (*parm) != REFERENCE_TYPE)
{
/* [temp.deduct.call]
-
+
If P is not a reference type:
-
+
--If A is an array type, the pointer type produced by the
array-to-pointer standard conversion (_conv.array_) is
used in place of A for type deduction; otherwise,
-
+
--If A is a function type, the pointer type produced by
the function-to-pointer standard conversion
(_conv.func_) is used in place of A for type deduction;
otherwise,
-
+
--If A is a cv-qualified type, the top level
cv-qualifiers of A's type are ignored for type
deduction. */
else
*arg = TYPE_MAIN_VARIANT (*arg);
}
-
+
/* [temp.deduct.call]
-
+
If P is a cv-qualified type, the top level cv-qualifiers
of P's type are ignored for type deduction. If P is a
reference type, the type referred to by P is used for
too (which has been swapped into ARG). */
if (strict == DEDUCE_CONV && TREE_CODE (*arg) == REFERENCE_TYPE)
*arg = TREE_TYPE (*arg);
-
+
return result;
}
template). */
static int
-type_unification_real (tree tparms,
- tree targs,
- tree xparms,
- tree xargs,
- int subr,
- unification_kind_t strict,
- int allow_incomplete,
- int xlen)
+type_unification_real (tree tparms,
+ tree targs,
+ tree xparms,
+ tree xargs,
+ int subr,
+ unification_kind_t strict,
+ int allow_incomplete)
{
tree parm, arg;
int i;
int sub_strict;
int saw_undeduced = 0;
tree parms, args;
- int len;
gcc_assert (TREE_CODE (tparms) == TREE_VEC);
gcc_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST);
{
case DEDUCE_CALL:
sub_strict = (UNIFY_ALLOW_OUTER_LEVEL | UNIFY_ALLOW_MORE_CV_QUAL
- | UNIFY_ALLOW_DERIVED);
+ | UNIFY_ALLOW_DERIVED);
break;
-
+
case DEDUCE_CONV:
sub_strict = UNIFY_ALLOW_LESS_CV_QUAL;
break;
case DEDUCE_EXACT:
sub_strict = UNIFY_ALLOW_NONE;
break;
-
- case DEDUCE_ORDER:
- sub_strict = UNIFY_ALLOW_NONE;
- break;
-
+
default:
gcc_unreachable ();
}
- if (xlen == 0)
- return 0;
-
again:
parms = xparms;
args = xargs;
- len = xlen;
- while (parms
- && parms != void_list_node
- && args
- && args != void_list_node)
+ while (parms && parms != void_list_node
+ && args && args != void_list_node)
{
parm = TREE_VALUE (parms);
parms = TREE_CHAIN (parms);
else
type = arg;
- if (strict == DEDUCE_EXACT || strict == DEDUCE_ORDER)
- {
- if (same_type_p (parm, type))
- continue;
- }
- else
- /* It might work; we shouldn't check now, because we might
- get into infinite recursion. Overload resolution will
- handle it. */
+ if (same_type_p (parm, type))
continue;
-
+ if (strict != DEDUCE_EXACT
+ && can_convert_arg (parm, type, TYPE_P (arg) ? NULL_TREE : arg))
+ continue;
+
return 1;
}
-
+
if (!TYPE_P (arg))
{
gcc_assert (TREE_TYPE (arg) != NULL_TREE);
if (arg == error_mark_node)
return 1;
}
-
+
{
- int arg_strict = sub_strict;
-
- if (!subr)
+ int arg_strict = sub_strict;
+
+ if (!subr)
arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg);
- if (unify (tparms, targs, parm, arg, arg_strict))
- return 1;
+ if (unify (tparms, targs, parm, arg, arg_strict))
+ return 1;
}
-
- /* Are we done with the interesting parms? */
- if (--len == 0)
- goto done;
}
+
/* Fail if we've reached the end of the parm list, and more args
are present, and the parm list isn't variadic. */
if (args && args != void_list_node && parms == void_list_node)
return 1;
/* Fail if parms are left and they don't have default values. */
- if (parms
- && parms != void_list_node
+ if (parms && parms != void_list_node
&& TREE_PURPOSE (parms) == NULL_TREE)
return 1;
- done:
if (!subr)
for (i = 0; i < ntparms; i++)
- if (TREE_VEC_ELT (targs, i) == NULL_TREE)
+ if (!TREE_VEC_ELT (targs, i))
{
tree tparm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
error ("incomplete type unification");
return 2;
}
+
return 0;
}
succeeds, we go with that. Modifies TARGS and returns 0 on success. */
static int
-resolve_overloaded_unification (tree tparms,
- tree targs,
- tree parm,
- tree arg,
- unification_kind_t strict,
+resolve_overloaded_unification (tree tparms,
+ tree targs,
+ tree parm,
+ tree arg,
+ unification_kind_t strict,
int sub_strict)
{
tree tempargs = copy_node (targs);
if (TREE_CODE (fn) != TEMPLATE_DECL)
continue;
- subargs = get_bindings_overload (fn, DECL_TEMPLATE_RESULT (fn),
- expl_subargs);
+ subargs = get_bindings (fn, DECL_TEMPLATE_RESULT (fn),
+ expl_subargs, /*check_ret=*/false);
if (subargs)
{
elem = tsubst (TREE_TYPE (fn), subargs, tf_none, NULL_TREE);
- good += try_one_overload (tparms, targs, tempargs, parm,
+ good += try_one_overload (tparms, targs, tempargs, parm,
elem, strict, sub_strict, addr_p);
}
}
{
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)),
static int
try_one_overload (tree tparms,
- tree orig_targs,
- tree targs,
- tree parm,
- tree arg,
- unification_kind_t strict,
+ tree orig_targs,
+ tree targs,
+ tree parm,
+ tree arg,
+ unification_kind_t strict,
int sub_strict,
bool addr_p)
{
tree elt = TREE_VEC_ELT (tempargs, i);
tree oldelt = TREE_VEC_ELT (orig_targs, i);
- if (elt == NULL_TREE)
- continue;
+ if (!elt)
+ /*NOP*/;
else if (uses_template_parms (elt))
- {
- /* Since we're unifying against ourselves, we will fill in template
- args used in the function parm list with our own template parms.
- Discard them. */
- TREE_VEC_ELT (tempargs, i) = NULL_TREE;
- continue;
- }
- else if (oldelt && ! template_args_equal (oldelt, elt))
+ /* Since we're unifying against ourselves, we will fill in
+ template args used in the function parm list with our own
+ template parms. Discard them. */
+ TREE_VEC_ELT (tempargs, i) = NULL_TREE;
+ else if (oldelt && !template_args_equal (oldelt, elt))
return 0;
}
verify_class_unification (tree targs, tree parms, tree args)
{
parms = tsubst (parms, add_outermost_template_args (args, targs),
- tf_none, NULL_TREE);
+ tf_none, NULL_TREE);
if (parms == error_mark_node)
return 1;
tree copy_of_targs;
if (!CLASSTYPE_TEMPLATE_INFO (arg)
- || (most_general_template (CLASSTYPE_TI_TEMPLATE (arg))
+ || (most_general_template (CLASSTYPE_TI_TEMPLATE (arg))
!= most_general_template (CLASSTYPE_TI_TEMPLATE (parm))))
return NULL_TREE;
template <int I, int J, int K>
struct S {};
-
+
template <int I, int J>
struct S<I, J, 2> : public S<I, I, I>, S<J, J, J> {};
-
+
template <int I, int J, int K>
void f(S<I, J, K>, S<I, I, I>);
-
+
void g() {
- S<0, 0, 0> s0;
- S<0, 1, 2> s2;
-
- f(s0, s2);
+ S<0, 0, 0> s0;
+ S<0, 1, 2> s2;
+
+ f(s0, s2);
}
Now, by the time we consider the unification involving `s2', we
with S<I, I, I>. If we kept the already deduced knowledge, we
would reject the possibility I=1. */
copy_of_targs = make_tree_vec (TREE_VEC_LENGTH (targs));
-
+
/* If unification failed, we're done. */
if (unify (tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm),
CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE))
tree binfo;
gcc_assert (IS_AGGR_TYPE_CODE (TREE_CODE (arg)));
-
+
binfo = TYPE_BINFO (complete_type (arg));
if (!binfo)
/* The type could not be completed. */
applies. */
if (rval && !same_type_p (r, rval))
return NULL_TREE;
-
+
rval = r;
}
}
&& !(strict & UNIFY_ALLOW_OUTER_MORE_CV_QUAL))
{
/* Although a CVR qualifier is ignored when being applied to a
- substituted template parameter ([8.3.2]/1 for example), that
- does not apply during deduction [14.8.2.4]/1, (even though
- that is not explicitly mentioned, [14.8.2.4]/9 indicates
- this). Except when we're allowing additional CV qualifiers
- at the outer level [14.8.2.1]/3,1st bullet. */
+ substituted template parameter ([8.3.2]/1 for example), that
+ does not apply during deduction [14.8.2.4]/1, (even though
+ that is not explicitly mentioned, [14.8.2.4]/9 indicates
+ this). Except when we're allowing additional CV qualifiers
+ at the outer level [14.8.2.1]/3,1st bullet. */
if ((TREE_CODE (arg) == REFERENCE_TYPE
|| TREE_CODE (arg) == FUNCTION_TYPE
|| TREE_CODE (arg) == METHOD_TYPE)
ARG.
UNIFY_ALLOW_INTEGER:
Allow any integral type to be deduced. See the TEMPLATE_PARM_INDEX
- case for more information.
+ case for more information.
UNIFY_ALLOW_OUTER_LEVEL:
This is the outermost level of a deduction. Used to determine validity
of qualification conversions. A valid qualification conversion must
if (TREE_CODE (arg) == TREE_CODE (parm)
&& TYPE_P (arg)
/* It is the elements of the array which hold the cv quals of an array
- type, and the elements might be template type parms. We'll check
- when we recurse. */
+ type, and the elements might be template type parms. We'll check
+ when we recurse. */
&& TREE_CODE (arg) != ARRAY_TYPE
/* We check the cv-qualifiers when unifying with template type
parameters below. We want to allow ARG `const T' to unify with
strict &= ~UNIFY_ALLOW_DERIVED;
strict &= ~UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
strict &= ~UNIFY_ALLOW_OUTER_LESS_CV_QUAL;
-
+
switch (TREE_CODE (parm))
{
case TYPENAME_TYPE:
/* Check for mixed types and values. */
if ((TREE_CODE (parm) == TEMPLATE_TYPE_PARM
&& TREE_CODE (tparm) != TYPE_DECL)
- || (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM
+ || (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM
&& TREE_CODE (tparm) != TEMPLATE_DECL))
return 1;
= DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (arg));
int i;
- /* The parameter and argument roles have to be switched here
- in order to handle default arguments properly. For example,
- template<template <class> class TT> void f(TT<int>)
- should be able to accept vector<int> which comes from
- template <class T, class Allocator = allocator>
+ /* The parameter and argument roles have to be switched here
+ in order to handle default arguments properly. For example,
+ template<template <class> class TT> void f(TT<int>)
+ should be able to accept vector<int> which comes from
+ template <class T, class Allocator = allocator>
class vector. */
if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 0, 1)
- == error_mark_node)
+ == error_mark_node)
return 1;
-
- /* Deduce arguments T, i from TT<T> or TT<i>.
+
+ /* Deduce arguments T, i from TT<T> or TT<i>.
We check each element of PARMVEC and ARGVEC individually
rather than the whole TREE_VEC since they can have
different number of elements. */
for (i = 0; i < TREE_VEC_LENGTH (parmvec); ++i)
{
- if (unify (tparms, targs,
- TREE_VEC_ELT (parmvec, i),
- TREE_VEC_ELT (argvec, i),
+ if (unify (tparms, targs,
+ TREE_VEC_ELT (parmvec, i),
+ TREE_VEC_ELT (argvec, i),
UNIFY_ALLOW_NONE))
return 1;
}
a match unless we are allowing additional qualification.
If ARG is `const int' and PARM is just `T' that's OK;
that binds `const int' to `T'. */
- if (!check_cv_quals_for_unify (strict_in | UNIFY_ALLOW_LESS_CV_QUAL,
+ if (!check_cv_quals_for_unify (strict_in | UNIFY_ALLOW_LESS_CV_QUAL,
arg, parm))
return 1;
case TEMPLATE_PARM_INDEX:
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0));
- if (TEMPLATE_PARM_LEVEL (parm)
+ if (TEMPLATE_PARM_LEVEL (parm)
!= template_decl_level (tparm))
/* The PARM is not one we're trying to unify. Just check
to see if it matches ARG. */
parameter-list and, if the corresponding template-argument is
deduced, the template-argument type shall match the type of the
template-parameter exactly, except that a template-argument
- deduced from an array bound may be of any integral type.
+ deduced from an array bound may be of any integral type.
The non-type parameter might use already deduced type parameters. */
tparm = tsubst (TREE_TYPE (parm), targs, 0, NULL_TREE);
if (!TREE_TYPE (arg))
case PTRMEM_CST:
{
- /* A pointer-to-member constant can be unified only with
- another constant. */
+ /* A pointer-to-member constant can be unified only with
+ another constant. */
if (TREE_CODE (arg) != PTRMEM_CST)
- return 1;
+ return 1;
/* Just unify the class member. It would be useless (and possibly
- wrong, depending on the strict flags) to unify also
- PTRMEM_CST_CLASS, because we want to be sure that both parm and
- arg refer to the same variable, even if through different
- classes. For instance:
+ wrong, depending on the strict flags) to unify also
+ PTRMEM_CST_CLASS, because we want to be sure that both parm and
+ arg refer to the same variable, even if through different
+ classes. For instance:
- struct A { int x; };
- struct B : A { };
+ struct A { int x; };
+ struct B : A { };
- Unification of &A::x and &B::x must succeed. */
+ Unification of &A::x and &B::x must succeed. */
return unify (tparms, targs, PTRMEM_CST_MEMBER (parm),
- PTRMEM_CST_MEMBER (arg), strict);
+ PTRMEM_CST_MEMBER (arg), strict);
}
case POINTER_TYPE:
{
if (TREE_CODE (arg) != POINTER_TYPE)
return 1;
-
+
/* [temp.deduct.call]
A can be another pointer or pointer to member type that can
We pass down STRICT here rather than UNIFY_ALLOW_NONE.
This will allow for additional cv-qualification of the
pointed-to types if appropriate. */
-
+
if (TREE_CODE (TREE_TYPE (arg)) == RECORD_TYPE)
/* The derived-to-base conversion only persists through one
level of pointers. */
strict |= (strict_in & UNIFY_ALLOW_DERIVED);
- return unify (tparms, targs, TREE_TYPE (parm),
+ return unify (tparms, targs, TREE_TYPE (parm),
TREE_TYPE (arg), strict);
}
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)));
+ arg_max = fold_build2 (PLUS_EXPR,
+ integer_type_node,
+ arg_max,
+ TREE_OPERAND (parm_max, 1));
parm_max = TREE_OPERAND (parm_max, 0);
}
case VOID_TYPE:
if (TREE_CODE (arg) != TREE_CODE (parm))
return 1;
-
+
/* We have already checked cv-qualification at the top of the
function. */
if (!same_type_ignoring_top_level_qualifiers_p (arg, parm))
case UNION_TYPE:
if (TREE_CODE (arg) != TREE_CODE (parm))
return 1;
-
+
if (TYPE_PTRMEMFUNC_P (parm))
{
if (!TYPE_PTRMEMFUNC_P (arg))
return 1;
- return unify (tparms, targs,
+ return unify (tparms, targs,
TYPE_PTRMEMFUNC_FN_TYPE (parm),
TYPE_PTRMEMFUNC_FN_TYPE (arg),
strict);
{
/* Fallback to the special case allowed in
[temp.deduct.call]:
-
+
If P is a class, and P has the form
template-id, then A can be a derived class of
the deduced A. Likewise, if P is a pointer to
return 1;
}
}
- else if (CLASSTYPE_TEMPLATE_INFO (arg)
- && (CLASSTYPE_TI_TEMPLATE (parm)
+ else if (CLASSTYPE_TEMPLATE_INFO (arg)
+ && (CLASSTYPE_TI_TEMPLATE (parm)
== CLASSTYPE_TI_TEMPLATE (arg)))
/* Perhaps PARM is something like S<U> and ARG is S<int>.
Then, we should unify `int' and `U'. */
TREE_TYPE (arg), UNIFY_ALLOW_NONE))
return 1;
return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
- TYPE_ARG_TYPES (arg), 1,
- DEDUCE_EXACT, 0, -1);
+ TYPE_ARG_TYPES (arg), 1,
+ DEDUCE_EXACT, 0);
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;
default:
gcc_assert (EXPR_P (parm));
-
+
/* We must be looking at an expression. This can happen with
- something like:
-
+ something like:
+
template <int I>
void foo(S<I>, S<I + 2>);
This is a "nondeduced context":
[deduct.type]
-
+
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 template-parameter.
In these cases, we assume deduction succeeded, but don't
actually infer any unifications. */
else if (TREE_PUBLIC (result))
maybe_make_one_only (result);
}
-
+
/* If EXTERN_P, then this function will not be emitted -- unless
followed by an explicit instantiation, at which point its linkage
will be adjusted. If !EXTERN_P, then this function will be
emitted here. In neither circumstance do we want
import_export_decl to adjust the linkage. */
- DECL_INTERFACE_KNOWN (result) = 1;
+ DECL_INTERFACE_KNOWN (result) = 1;
}
/* Given two function templates PAT1 and PAT2, return:
- DEDUCE should be DEDUCE_EXACT or DEDUCE_ORDER.
-
1 if PAT1 is more specialized than PAT2 as described in [temp.func.order].
-1 if PAT2 is more specialized than PAT1.
0 if neither is more specialized.
- LEN is passed through to fn_type_unification. */
-
+ LEN indicates the number of parameters we should consider
+ (defaulted parameters should not be considered).
+
+ The 1998 std underspecified function template partial ordering, and
+ DR214 addresses the issue. We take pairs of arguments, one from
+ each of the templates, and deduce them against each other. One of
+ the templates will be more specialized if all the *other*
+ template's arguments deduce against its arguments and at least one
+ of its arguments *does* *not* deduce against the other template's
+ corresponding argument. Deduction is done as for class templates.
+ The arguments used in deduction have reference and top level cv
+ qualifiers removed. Iff both arguments were originally reference
+ types *and* deduction succeeds in both directions, the template
+ with the more cv-qualified argument wins for that pairing (if
+ neither is more cv-qualified, they both are equal). Unlike regular
+ deduction, after all the arguments have been deduced in this way,
+ we do *not* verify the deduced template argument values can be
+ substituted into non-deduced contexts, nor do we have to verify
+ that all template arguments have been deduced. */
+
int
-more_specialized (tree pat1, tree pat2, int deduce, int len)
-{
- tree targs;
- int winner = 0;
+more_specialized_fn (tree pat1, tree pat2, int len)
+{
+ tree decl1 = DECL_TEMPLATE_RESULT (pat1);
+ tree decl2 = DECL_TEMPLATE_RESULT (pat2);
+ tree targs1 = make_tree_vec (DECL_NTPARMS (pat1));
+ tree targs2 = make_tree_vec (DECL_NTPARMS (pat2));
+ tree tparms1 = DECL_INNERMOST_TEMPLATE_PARMS (pat1);
+ tree tparms2 = DECL_INNERMOST_TEMPLATE_PARMS (pat2);
+ tree args1 = TYPE_ARG_TYPES (TREE_TYPE (decl1));
+ tree args2 = TYPE_ARG_TYPES (TREE_TYPE (decl2));
+ int better1 = 0;
+ int better2 = 0;
+
+ /* If only one is a member function, they are unordered. */
+ if (DECL_FUNCTION_MEMBER_P (decl1) != DECL_FUNCTION_MEMBER_P (decl2))
+ return 0;
- /* If template argument deduction succeeds, we substitute the
- resulting arguments into non-deduced contexts. While doing that,
- we must be aware that we may encounter dependent types. */
- ++processing_template_decl;
- targs = get_bindings_real (pat1, DECL_TEMPLATE_RESULT (pat2),
- NULL_TREE, 0, deduce, len);
- if (targs)
- --winner;
+ /* Don't consider 'this' parameter. */
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl1))
+ args1 = TREE_CHAIN (args1);
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl2))
+ args2 = TREE_CHAIN (args2);
- targs = get_bindings_real (pat2, DECL_TEMPLATE_RESULT (pat1),
- NULL_TREE, 0, deduce, len);
- if (targs)
- ++winner;
- --processing_template_decl;
+ /* If only one is a conversion operator, they are unordered. */
+ if (DECL_CONV_FN_P (decl1) != DECL_CONV_FN_P (decl2))
+ return 0;
- return winner;
+ /* Consider the return type for a conversion function */
+ if (DECL_CONV_FN_P (decl1))
+ {
+ args1 = tree_cons (NULL_TREE, TREE_TYPE (TREE_TYPE (decl1)), args1);
+ args2 = tree_cons (NULL_TREE, TREE_TYPE (TREE_TYPE (decl2)), args2);
+ len++;
+ }
+
+ processing_template_decl++;
+
+ while (len--)
+ {
+ tree arg1 = TREE_VALUE (args1);
+ tree arg2 = TREE_VALUE (args2);
+ int deduce1, deduce2;
+ int quals1 = -1;
+ int quals2 = -1;
+
+ if (TREE_CODE (arg1) == REFERENCE_TYPE)
+ {
+ arg1 = TREE_TYPE (arg1);
+ quals1 = cp_type_quals (arg1);
+ }
+
+ if (TREE_CODE (arg2) == REFERENCE_TYPE)
+ {
+ arg2 = TREE_TYPE (arg2);
+ quals2 = cp_type_quals (arg2);
+ }
+
+ if ((quals1 < 0) != (quals2 < 0))
+ {
+ /* Only of the args is a reference, see if we should apply
+ array/function pointer decay to it. This is not part of
+ DR214, but is, IMHO, consistent with the deduction rules
+ for the function call itself, and with our earlier
+ implementation of the underspecified partial ordering
+ rules. (nathan). */
+ if (quals1 >= 0)
+ {
+ switch (TREE_CODE (arg1))
+ {
+ case ARRAY_TYPE:
+ arg1 = TREE_TYPE (arg1);
+ /* FALLTHROUGH. */
+ case FUNCTION_TYPE:
+ arg1 = build_pointer_type (arg1);
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch (TREE_CODE (arg2))
+ {
+ case ARRAY_TYPE:
+ arg2 = TREE_TYPE (arg2);
+ /* FALLTHROUGH. */
+ case FUNCTION_TYPE:
+ arg2 = build_pointer_type (arg2);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ arg1 = TYPE_MAIN_VARIANT (arg1);
+ arg2 = TYPE_MAIN_VARIANT (arg2);
+
+ deduce1 = !unify (tparms1, targs1, arg1, arg2, UNIFY_ALLOW_NONE);
+ deduce2 = !unify (tparms2, targs2, arg2, arg1, UNIFY_ALLOW_NONE);
+
+ if (!deduce1)
+ better2 = -1;
+ if (!deduce2)
+ better1 = -1;
+ if (better1 < 0 && better2 < 0)
+ /* We've failed to deduce something in either direction.
+ These must be unordered. */
+ break;
+
+ if (deduce1 && deduce2 && quals1 >= 0 && quals2 >= 0)
+ {
+ /* Deduces in both directions, see if quals can
+ disambiguate. Pretend the worse one failed to deduce. */
+ if ((quals1 & quals2) == quals2)
+ deduce1 = 0;
+ if ((quals1 & quals2) == quals1)
+ deduce2 = 0;
+ }
+ if (deduce1 && !deduce2 && !better2)
+ better2 = 1;
+ if (deduce2 && !deduce1 && !better1)
+ better1 = 1;
+
+ args1 = TREE_CHAIN (args1);
+ args2 = TREE_CHAIN (args2);
+ }
+
+ processing_template_decl--;
+
+ return (better1 > 0) - (better2 > 0);
}
/* Given two class template specialization list nodes PAT1 and PAT2, return:
FULL_ARGS is the full set of template arguments that triggers this
partial ordering. */
-
+
int
more_specialized_class (tree pat1, tree pat2, tree full_args)
{
tree targs;
int winner = 0;
- /* Just like what happens for functions, if we are ordering between
+ /* Just like what happens for functions, if we are ordering between
different class template specializations, we may encounter dependent
types in the arguments, and we need our dependency check functions
to behave correctly. */
/* Return the template arguments that will produce the function signature
DECL from the function template FN, with the explicit template
- arguments EXPLICIT_ARGS. If CHECK_RETTYPE is 1, the return type must
+ arguments EXPLICIT_ARGS. If CHECK_RETTYPE is true, the return type must
also match. Return NULL_TREE if no satisfactory arguments could be
- found. DEDUCE and LEN are passed through to fn_type_unification. */
-
+ found. */
+
static tree
-get_bindings_real (tree fn,
- tree decl,
- tree explicit_args,
- int check_rettype,
- int deduce,
- int len)
+get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
{
int ntparms = DECL_NTPARMS (fn);
tree targs = make_tree_vec (ntparms);
tree decl_type;
tree decl_arg_types;
- int i;
/* Substitute the explicit template arguments into the type of DECL.
The call to fn_type_unification will handle substitution into the
tf_none, /*require_all_arguments=*/0));
if (converted_args == error_mark_node)
return NULL_TREE;
-
- decl_type = tsubst (decl_type, converted_args, tf_none, NULL_TREE);
+
+ decl_type = tsubst (decl_type, converted_args, tf_none, NULL_TREE);
if (decl_type == error_mark_node)
return NULL_TREE;
}
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
decl_arg_types = TREE_CHAIN (decl_arg_types);
- i = fn_type_unification (fn, explicit_args, targs,
+ if (fn_type_unification (fn, explicit_args, targs,
decl_arg_types,
(check_rettype || DECL_CONV_FN_P (fn)
- ? TREE_TYPE (decl_type) : NULL_TREE),
- deduce, len);
-
- if (i != 0)
+ ? TREE_TYPE (decl_type) : NULL_TREE),
+ DEDUCE_EXACT))
return NULL_TREE;
return targs;
}
-/* For most uses, we want to check the return type. */
-
-static tree
-get_bindings (tree fn, tree decl, tree explicit_args)
-{
- return get_bindings_real (fn, decl, explicit_args, 1, DEDUCE_EXACT, -1);
-}
-
-/* But for resolve_overloaded_unification, we only care about the parameter
- types. */
-
-static tree
-get_bindings_overload (tree fn, tree decl, tree explicit_args)
-{
- return get_bindings_real (fn, decl, explicit_args, 0, DEDUCE_EXACT, -1);
-}
-
/* Return the innermost template arguments that, when applied to a
template specialization whose innermost template parameters are
TPARMS, and whose specialization arguments are PARMS, yield the
- ARGS.
+ ARGS.
For example, suppose we have:
tree vec = make_tree_vec (ntparms);
if (unify (tparms, vec, parms, INNERMOST_TEMPLATE_ARGS (args),
- UNIFY_ALLOW_NONE))
+ UNIFY_ALLOW_NONE))
return NULL_TREE;
for (i = 0; i < ntparms; ++i)
most_specialized_instantiation (tree instantiations)
{
tree fn, champ;
- int fate;
if (!instantiations)
return NULL_TREE;
+ ++processing_template_decl;
+
champ = instantiations;
for (fn = TREE_CHAIN (instantiations); fn; fn = TREE_CHAIN (fn))
{
- fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn),
- DEDUCE_EXACT, -1);
- if (fate == 1)
- ;
- else
+ int fate = 0;
+
+ if (get_bindings (TREE_VALUE (champ),
+ DECL_TEMPLATE_RESULT (TREE_VALUE (fn)),
+ NULL_TREE, /*check_ret=*/false))
+ fate--;
+
+ if (get_bindings (TREE_VALUE (fn),
+ DECL_TEMPLATE_RESULT (TREE_VALUE (champ)),
+ NULL_TREE, /*check_ret=*/false))
+ fate++;
+
+ if (fate != 1)
{
- if (fate == 0)
- {
- fn = TREE_CHAIN (fn);
- if (! fn)
- return error_mark_node;
- }
+ if (!fate)
+ /* Equally specialized, move to next function. If there
+ is no next function, nothing's most specialized. */
+ fn = TREE_CHAIN (fn);
champ = fn;
}
}
- for (fn = instantiations; fn && fn != champ; fn = TREE_CHAIN (fn))
- {
- fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn),
- DEDUCE_EXACT, -1);
- if (fate != 1)
- return error_mark_node;
- }
+ if (champ)
+ /* Now verify that champ is better than everything earlier in the
+ instantiation list. */
+ for (fn = instantiations; fn != champ; fn = TREE_CHAIN (fn))
+ if (get_bindings (TREE_VALUE (champ),
+ DECL_TEMPLATE_RESULT (TREE_VALUE (fn)),
+ NULL_TREE, /*check_ret=*/false)
+ || !get_bindings (TREE_VALUE (fn),
+ DECL_TEMPLATE_RESULT (TREE_VALUE (champ)),
+ NULL_TREE, /*check_ret=*/false))
+ {
+ champ = NULL_TREE;
+ break;
+ }
+
+ processing_template_decl--;
+
+ if (!champ)
+ return error_mark_node;
return TREE_PURPOSE (champ) ? TREE_PURPOSE (champ) : TREE_VALUE (champ);
}
{
tree candidate = TREE_VALUE (fn);
- args = get_bindings (candidate, decl, explicit_args);
+ args = get_bindings (candidate, decl, explicit_args, /*check_ret=*/true);
if (args)
candidates = tree_cons (NULL_TREE, candidate, candidates);
}
tmpl = most_general_template (tmpl);
for (t = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); t; t = TREE_CHAIN (t))
{
- tree spec_args
+ tree spec_args
= get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args);
if (spec_args)
{
/* [temp.spec]
No program shall explicitly instantiate any template more
- than once.
+ than once.
We check DECL_NOT_REALLY_EXTERN so as not to complain when
the first instantiation was `extern' and the second is not,
{
if (pedantic && !in_system_header)
pedwarn ("ISO C++ forbids the use of %<extern%> on explicit "
- "instantiations");
+ "instantiations");
extern_p = 1;
}
else
CLASSTYPE_DEBUG_REQUESTED (t) = 1;
rest_of_type_compilation (t, 1);
}
-}
+}
/* Called from do_type_instantiation through binding_table_foreach to
do recursive instantiation for the type bound in ENTRY. */
/* 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)
{
non-null, is the RID for extern, inline or static. COMPLAIN is
nonzero if this is called from the parser, zero if called recursively,
since the standard is unclear (as detailed below). */
-
+
void
do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
{
{
if (complain & tf_error)
error ("explicit instantiation of %q#T before definition of template",
- t);
+ t);
return;
}
if (storage != NULL_TREE)
{
if (pedantic && !in_system_header)
- pedwarn("ISO C++ forbids the use of `%E' on explicit instantiations",
- storage);
+ pedwarn("ISO C++ forbids the use of %qE on explicit instantiations",
+ storage);
if (storage == ridpointers[(int) RID_INLINE])
nomem_p = 1;
else
{
error ("storage class %qD applied to template instantiation",
- storage);
+ storage);
extern_p = 0;
}
}
/* [temp.spec]
No program shall explicitly instantiate any template more
- than once.
+ than once.
- If PREVIOUS_INSTANTIATION_EXTERN_P, then the first explicit
+ If PREVIOUS_INSTANTIATION_EXTERN_P, then the first explicit
instantiation was `extern'. If EXTERN_P then the second is.
These cases are OK. */
previous_instantiation_extern_p = CLASSTYPE_INTERFACE_ONLY (t);
if (!previous_instantiation_extern_p && !extern_p
&& (complain & tf_error))
pedwarn ("duplicate explicit instantiation of %q#T", t);
-
+
/* If we've already instantiated the template, just return now. */
if (!CLASSTYPE_INTERFACE_ONLY (t))
return;
declarations, and not the definitions, of members are
instantiated, we have here:
- [temp.explicit]
+ [temp.explicit]
The explicit instantiation of a class template specialization
implies the instantiation of all of its members not
previously explicitly specialized in the translation unit
- containing the explicit instantiation.
+ containing the explicit instantiation.
Of course, we can't instantiate member template classes, since
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))
if (CLASSTYPE_NESTED_UTDS (t))
binding_table_foreach (CLASSTYPE_NESTED_UTDS (t),
- bt_instantiate_type_proc, &storage);
+ bt_instantiate_type_proc, &storage);
}
}
tree specs;
int args_depth;
int parms_depth;
-
+
args_depth = TMPL_ARGS_DEPTH (args);
- parms_depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
+ parms_depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
if (args_depth > parms_depth)
args = get_innermost_template_args (args, parms_depth);
specs);
/* Merge parameter declarations. */
- decl_parm = skip_artificial_parms_for (decl,
+ decl_parm = skip_artificial_parms_for (decl,
DECL_ARGUMENTS (decl));
- pattern_parm
+ pattern_parm
= skip_artificial_parms_for (code_pattern,
DECL_ARGUMENTS (code_pattern));
while (decl_parm)
{
tree parm_type;
+ tree attributes;
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;
+ attributes = DECL_ATTRIBUTES (pattern_parm);
+ if (DECL_ATTRIBUTES (decl_parm) != attributes)
+ {
+ DECL_ATTRIBUTES (decl_parm) = attributes;
+ cplus_decl_attributes (&decl_parm, attributes, /*flags=*/0);
+ }
decl_parm = TREE_CHAIN (decl_parm);
pattern_parm = TREE_CHAIN (pattern_parm);
}
{
if (!DECL_INITIALIZED_IN_CLASS_P (decl)
&& DECL_INITIAL (code_pattern))
- DECL_INITIAL (decl) =
- tsubst_expr (DECL_INITIAL (code_pattern), args,
+ DECL_INITIAL (decl) =
+ tsubst_expr (DECL_INITIAL (code_pattern), args,
tf_error, DECL_TI_TEMPLATE (decl));
}
else
for the instantiation. This is not always the most general
template. Consider, for example:
- template <class T>
+ template <class T>
struct S { template <class U> void f();
- template <> void f<int>(); };
+ template <> void f<int>(); };
and an instantiation of S<double>::f<int>. We want TD to be the
specialization S<T>::f<int>, not the more general S<T>::f<U>. */
DECL_TEMPLATE_INSTANTIATION (tmpl)
/* We must also deal with friend templates. Given:
- template <class T> struct S {
+ template <class T> struct S {
template <class U> friend void f() {};
};
where we get the pattern for the instantiation from. On
other hand, if the definition comes outside the class, say:
- template <class T> struct S {
+ template <class T> struct S {
template <class U> friend void f();
};
template <class U> friend void f() {}
a specialization was declared, but not defined. */
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
int pattern_defined;
int need_push;
location_t saved_loc = input_location;
-
+
/* This function should only be used to instantiate templates for
functions and static member variables. */
gcc_assert (TREE_CODE (d) == FUNCTION_DECL
/* Unless an explicit instantiation directive has already determined
the linkage of D, remember that a definition is available for
this entity. */
- if (pattern_defined
+ if (pattern_defined
&& !DECL_INTERFACE_KNOWN (d)
&& !DECL_NOT_REALLY_EXTERN (d))
mark_definable (d);
pop_access_scope (d);
}
-
+
/* We should have set up DECL_INITIAL in instantiate_class_template
for in-class definitions of static data members. */
- gcc_assert (!(TREE_CODE (d) == VAR_DECL
+ gcc_assert (!(TREE_CODE (d) == VAR_DECL
&& DECL_INITIALIZED_IN_CLASS_P (d)
&& DECL_INITIAL (d) == NULL_TREE));
elsewhere. */
if (DECL_INTERFACE_KNOWN (d)
&& DECL_REALLY_EXTERN (d)
- && ! (TREE_CODE (d) == FUNCTION_DECL
+ && ! (TREE_CODE (d) == FUNCTION_DECL
&& DECL_INLINE (d)))
goto out;
/* Defer all other templates, unless we have been explicitly
{
input_location = saved_loc;
- if (at_eof && !pattern_defined
+ if (at_eof && !pattern_defined
&& DECL_EXPLICIT_INSTANTIATION (d))
/* [temp.explicit]
job, even though we'll not be emitting a copy of this
function. */
if (!(TREE_CODE (d) == FUNCTION_DECL
- && flag_inline_trees
+ && flag_inline_trees
&& DECL_DECLARED_INLINE_P (d)))
goto out;
}
/* 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)
+ cp_finish_decl (d,
+ (!DECL_INITIALIZED_IN_CLASS_P (d)
? DECL_INITIAL (d) : NULL_TREE),
NULL_TREE, 0);
pop_nested_class ();
saved_local_specializations = local_specializations;
/* Set up the list of local specializations. */
- local_specializations = htab_create (37,
+ local_specializations = htab_create (37,
hash_local_specialization,
eq_local_specializations,
NULL);
tree last = NULL_TREE;
int reconsider;
location_t saved_loc = input_location;
+ int saved_in_system_header = in_system_header;
/* Instantiating templates may trigger vtable generation. This in turn
may require further template instantiations. We place a limit here
return;
}
- do
+ do
{
reconsider = 0;
{
instantiate_class_template (instantiation);
if (CLASSTYPE_TEMPLATE_INSTANTIATION (instantiation))
- for (fn = TYPE_METHODS (instantiation);
+ for (fn = TYPE_METHODS (instantiation);
fn;
fn = TREE_CHAIN (fn))
if (! DECL_ARTIFICIAL (fn))
current_tinst_level = NULL_TREE;
}
last_pending_template = last;
- }
+ }
while (reconsider);
input_location = saved_loc;
+ in_system_header = saved_in_system_header;
}
/* 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);
decl = expand_member_init (decl);
if (decl && !DECL_P (decl))
in_base_initializer = 1;
-
+
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)
decl = TREE_VALUE (e);
/* Note that in a template enum, the TREE_VALUE is the
CONST_DECL, not the corresponding INTEGER_CST. */
- value = tsubst_expr (DECL_INITIAL (decl),
+ value = tsubst_expr (DECL_INITIAL (decl),
args, tf_error | tf_warning,
NULL_TREE);
set_current_access_from_decl (decl);
/* Actually build the enumerator itself. */
- build_enumerator (DECL_NAME (decl), value, newtag);
+ build_enumerator (DECL_NAME (decl), value, newtag);
}
finish_enum (newtag);
arguments. So, innermost set of template parameters will appear in
the type. */
-tree
+tree
get_mostly_instantiated_function_type (tree decl)
{
tree fn_type;
;
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;
else if (TREE_CODE (type) == TYPENAME_TYPE)
return 0;
-
+
if (complain & tf_error)
error ("%q#T is not a valid type for a template constant parameter", type);
return 1;
-- 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
+ if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
|| TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
return true;
/* -- a qualified-id with a nested-name-specifier which contains a
- class-name that names a dependent type or whose unqualified-id
+ class-name that names a dependent type or whose unqualified-id
names a dependent type. */
if (TREE_CODE (type) == TYPENAME_TYPE)
return true;
/* -- a cv-qualified type where the cv-unqualified type is
- dependent. */
+ dependent. */
type = TYPE_MAIN_VARIANT (type);
/* -- a compound type constructed from any dependent type. */
if (TYPE_PTR_TO_MEMBER_P (type))
return (dependent_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
- || dependent_type_p (TYPE_PTRMEM_POINTED_TO_TYPE
+ || dependent_type_p (TYPE_PTRMEM_POINTED_TO_TYPE
(type)));
else if (TREE_CODE (type) == POINTER_TYPE
|| TREE_CODE (type) == REFERENCE_TYPE)
if (dependent_type_p (TREE_TYPE (type)))
return true;
- for (arg_type = TYPE_ARG_TYPES (type);
- arg_type;
+ for (arg_type = TYPE_ARG_TYPES (type);
+ arg_type;
arg_type = TREE_CHAIN (arg_type))
if (dependent_type_p (TREE_VALUE (arg_type)))
return true;
return false;
}
/* -- an array type constructed from any dependent type or whose
- size is specified by a constant expression that is
+ size is specified by a constant expression that is
value-dependent. */
if (TREE_CODE (type) == ARRAY_TYPE)
{
if (TYPE_DOMAIN (type)
- && ((value_dependent_expression_p
+ && ((value_dependent_expression_p
(TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
|| (type_dependent_expression_p
(TYPE_MAX_VALUE (TYPE_DOMAIN (type))))))
return true;
return dependent_type_p (TREE_TYPE (type));
}
-
+
/* -- a template-id in which either the template name is a template
parameter ... */
if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
/* ... or any of the template arguments is a dependent type or
an expression that is type-dependent or value-dependent. */
else if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INFO (type)
- && (any_dependent_template_arguments_p
+ && (any_dependent_template_arguments_p
(INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type)))))
return true;
-
+
/* All TYPEOF_TYPEs are dependent; if the argument of the `typeof'
expression is not type-dependent, then it should already been
have resolved. */
if (TREE_CODE (type) == TYPEOF_TYPE)
return true;
-
+
/* The standard does not specifically mention types that are local
to template functions or local classes, but they should be
considered dependent too. For example:
- template <int I> void f() {
- enum E { a = I };
+ template <int I> void f() {
+ enum E { a = I };
S<sizeof (E)> s;
}
/* The suggested resolution to Core Issue 2 implies that if the
qualifying type is the current class, then we must peek
inside it. */
- if (DECL_P (name)
+ if (DECL_P (name)
&& currently_open_class (scope)
&& !criterion (name))
return false;
return false;
/* A name declared with a dependent type. */
- if (TREE_CODE (expression) == IDENTIFIER_NODE
- || (DECL_P (expression)
- && type_dependent_expression_p (expression)))
+ if (DECL_P (expression) && type_dependent_expression_p (expression))
return true;
- /* A non-type template parameter. */
- if ((TREE_CODE (expression) == CONST_DECL
- && DECL_TEMPLATE_PARM_P (expression))
- || TREE_CODE (expression) == TEMPLATE_PARM_INDEX)
- return true;
- /* A constant with integral or enumeration type and is initialized
- with an expression that is value-dependent. */
- if (TREE_CODE (expression) == VAR_DECL
- && DECL_INITIAL (expression)
- && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (expression))
- && value_dependent_expression_p (DECL_INITIAL (expression)))
- return true;
- /* These expressions are value-dependent if the type to which the
- cast occurs is dependent or the expression being casted is
- value-dependent. */
- if (TREE_CODE (expression) == DYNAMIC_CAST_EXPR
- || TREE_CODE (expression) == STATIC_CAST_EXPR
- || TREE_CODE (expression) == CONST_CAST_EXPR
- || TREE_CODE (expression) == REINTERPRET_CAST_EXPR
- || TREE_CODE (expression) == CAST_EXPR)
+
+ switch (TREE_CODE (expression))
{
- tree type = TREE_TYPE (expression);
- if (dependent_type_p (type))
+ case IDENTIFIER_NODE:
+ /* A name that has not been looked up -- must be dependent. */
+ return true;
+
+ case TEMPLATE_PARM_INDEX:
+ /* A non-type template parm. */
+ return true;
+
+ case CONST_DECL:
+ /* A non-type template parm. */
+ if (DECL_TEMPLATE_PARM_P (expression))
return true;
- /* A functional cast has a list of operands. */
- expression = TREE_OPERAND (expression, 0);
- if (!expression)
- {
- /* 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. */
- gcc_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type));
+ return false;
- return false;
- }
- if (TREE_CODE (expression) == TREE_LIST)
- {
- do
- {
+ case VAR_DECL:
+ /* A constant with integral or enumeration type and is initialized
+ with an expression that is value-dependent. */
+ if (DECL_INITIAL (expression)
+ && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (expression))
+ && value_dependent_expression_p (DECL_INITIAL (expression)))
+ return true;
+ return false;
+
+ case DYNAMIC_CAST_EXPR:
+ case STATIC_CAST_EXPR:
+ case CONST_CAST_EXPR:
+ case REINTERPRET_CAST_EXPR:
+ case CAST_EXPR:
+ /* These expressions are value-dependent if the type to which
+ the cast occurs is dependent or the expression being casted
+ is value-dependent. */
+ {
+ tree type = TREE_TYPE (expression);
+
+ if (dependent_type_p (type))
+ return true;
+
+ /* A functional cast has a list of operands. */
+ expression = TREE_OPERAND (expression, 0);
+ if (!expression)
+ {
+ /* 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. */
+ gcc_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type));
+
+ return false;
+ }
+
+ if (TREE_CODE (expression) == TREE_LIST)
+ {
+ for (; expression; expression = TREE_CHAIN (expression))
if (value_dependent_expression_p (TREE_VALUE (expression)))
return true;
- expression = TREE_CHAIN (expression);
- }
- while (expression);
- return false;
- }
- else
+ return false;
+ }
+
return value_dependent_expression_p (expression);
- }
- /* A `sizeof' expression is value-dependent if the operand is
- type-dependent. */
- if (TREE_CODE (expression) == SIZEOF_EXPR
- || TREE_CODE (expression) == ALIGNOF_EXPR)
- {
+ }
+
+ case SIZEOF_EXPR:
+ case ALIGNOF_EXPR:
+ /* A `sizeof' expression is value-dependent if the operand is
+ type-dependent. */
expression = TREE_OPERAND (expression, 0);
if (TYPE_P (expression))
return dependent_type_p (expression);
return type_dependent_expression_p (expression);
- }
- if (TREE_CODE (expression) == SCOPE_REF)
- return dependent_scope_ref_p (expression, value_dependent_expression_p);
- if (TREE_CODE (expression) == COMPONENT_REF)
- return (value_dependent_expression_p (TREE_OPERAND (expression, 0))
- || value_dependent_expression_p (TREE_OPERAND (expression, 1)));
- /* A constant expression is value-dependent if any subexpression is
- value-dependent. */
- if (EXPR_P (expression))
- {
+
+ case SCOPE_REF:
+ return dependent_scope_ref_p (expression, value_dependent_expression_p);
+
+ case COMPONENT_REF:
+ return (value_dependent_expression_p (TREE_OPERAND (expression, 0))
+ || value_dependent_expression_p (TREE_OPERAND (expression, 1)));
+
+ case CALL_EXPR:
+ /* 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. */
+ {
+ tree function = TREE_OPERAND (expression, 0);
+ tree args = TREE_OPERAND (expression, 1);
+
+ if (value_dependent_expression_p (function))
+ return true;
+
+ if (! args)
+ return false;
+
+ if (TREE_CODE (args) == TREE_LIST)
+ {
+ for (; args; args = TREE_CHAIN (args))
+ if (value_dependent_expression_p (TREE_VALUE (args)))
+ return true;
+ return false;
+ }
+
+ return value_dependent_expression_p (args);
+ }
+
+ default:
+ /* A constant expression is value-dependent if any subexpression is
+ value-dependent. */
switch (TREE_CODE_CLASS (TREE_CODE (expression)))
{
+ case tcc_reference:
case tcc_unary:
- return (value_dependent_expression_p
+ return (value_dependent_expression_p
(TREE_OPERAND (expression, 0)));
+
case tcc_comparison:
case tcc_binary:
- return ((value_dependent_expression_p
+ return ((value_dependent_expression_p
(TREE_OPERAND (expression, 0)))
- || (value_dependent_expression_p
+ || (value_dependent_expression_p
(TREE_OPERAND (expression, 1))));
+
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 ();
+ break;
}
}
/* An unresolved name is always dependent. */
if (TREE_CODE (expression) == IDENTIFIER_NODE)
return true;
-
+
/* Some expression forms are never type-dependent. */
if (TREE_CODE (expression) == PSEUDO_DTOR_EXPR
|| TREE_CODE (expression) == SIZEOF_EXPR
/* SCOPE_REF with non-null TREE_TYPE is always non-dependent. */
if (TREE_CODE (expression) == SCOPE_REF)
return false;
-
+
if (TREE_CODE (expression) == BASELINK)
expression = BASELINK_FUNCTIONS (expression);
-
+
if (TREE_CODE (expression) == TEMPLATE_ID_EXPR)
{
if (any_dependent_template_arguments_p
expression = TREE_OPERAND (expression, 0);
}
gcc_assert (TREE_CODE (expression) == OVERLOAD);
-
+
while (expression)
{
if (type_dependent_expression_p (OVL_CURRENT (expression)))
}
return false;
}
-
+
return (dependent_type_p (TREE_TYPE (expression)));
}
TYPENAME_TYPE corresponds. Returns ERROR_MARK_NODE if no such TYPE
can be found. Note that this function peers inside uninstantiated
templates and therefore should be used only in extremely limited
- situations. */
+ situations. ONLY_CURRENT_P restricts this peering to the currently
+ open classes hierarchy (which is required when comparing types). */
tree
resolve_typename_type (tree type, bool only_current_p)
tree name;
tree decl;
int quals;
- bool pop_p;
+ tree pushed_scope;
gcc_assert (TREE_CODE (type) == TYPENAME_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;
}
{
tree inner_expr;
- /* Preserve null pointer constants so that the type of things like
+ /* Preserve null pointer constants so that the type of things like
"p == 0" where "p" is a pointer can be determined. */
if (null_ptr_cst_p (expr))
return expr;
/* Preserve OVERLOADs; the functions must be available to resolve
types. */
- inner_expr = (TREE_CODE (expr) == ADDR_EXPR ?
+ inner_expr = (TREE_CODE (expr) == ADDR_EXPR ?
TREE_OPERAND (expr, 0) : expr);
- 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)
+ if (is_overloaded_fn (inner_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 build3 (COND_EXPR,
TREE_TYPE (expr),
TREE_OPERAND (expr, 0),
- (TREE_OPERAND (expr, 1)
+ (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)));
TREE_TYPE (expr),
TREE_OPERAND (expr, 0),
build_non_dependent_expr (TREE_OPERAND (expr, 1)));
-
- /* Otherwise, build a NON_DEPENDENT_EXPR.
+
+ /* Otherwise, build a NON_DEPENDENT_EXPR.
REFERENCE_TYPEs are not stripped for expressions in templates
because doing so would play havoc with mangling. Consider, for
example:
- template <typename T> void f<T& g>() { g(); }
+ template <typename T> void f<T& g>() { g(); }
In the body of "f", the expression for "g" will have
REFERENCE_TYPE, even though the standard says that it should
new_args = NULL_TREE;
for (a = args; a; a = TREE_CHAIN (a))
- new_args = tree_cons (NULL_TREE,
+ new_args = tree_cons (NULL_TREE,
build_non_dependent_expr (TREE_VALUE (a)),
new_args);
return nreverse (new_args);