/* Handle parameterized types (templates) for GNU C++.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
Rewritten by Jason Merrill (jason@cygnus.com).
#include "cp-tree.h"
#include "tree-inline.h"
#include "decl.h"
-#include "lex.h"
#include "output.h"
#include "except.h"
#include "toplev.h"
#include "rtl.h"
#include "timevar.h"
+#include "tree-iterator.h"
/* The type of functions taking a tree, and some additional data, and
returning an int. */
#define GTB_IGNORE_TYPE 2 /* We don't need to try to unify the current
type with the desired type. */
-static void push_access_scope_real (tree, tree, tree);
static void push_access_scope (tree);
static void pop_access_scope (tree);
static int resolve_overloaded_unification (tree, tree, tree, tree,
unification_kind_t, int);
static int try_one_overload (tree, tree, tree, tree, tree,
- unification_kind_t, int);
+ unification_kind_t, int, bool);
static int unify (tree, tree, tree, tree, int);
static void add_pending_template (tree);
static void reopen_tinst_level (tree);
static tree classtype_mangled_name (tree);
static char* mangle_class_name_for_template (const char *, tree, tree);
static tree tsubst_initializer_list (tree, tree);
-static int list_eq (tree, tree);
static tree get_class_bindings (tree, tree, tree);
static tree coerce_template_parms (tree, tree, tree, tsubst_flags_t, int);
static void tsubst_enum (tree, tree, tree);
static int type_unification_real (tree, tree, tree, tree,
int, unification_kind_t, int, int);
static void note_template_header (int);
-static tree maybe_fold_nontype_arg (tree);
-static void maybe_fold_nontype_args (tree);
static tree convert_nontype_argument (tree, tree);
static tree convert_template_argument (tree, tree, tree,
tsubst_flags_t, int, tree);
static tree retrieve_local_specialization (tree);
static tree register_specialization (tree, tree, tree);
static void register_local_specialization (tree, tree);
-static int unregister_specialization (tree, tree);
static tree reduce_template_parm_level (tree, tree, int);
static tree build_template_decl (tree, tree);
static int mark_template_parm (tree, void *);
static 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 int template_decl_level (tree);
static int check_cv_quals_for_unify (int, tree, tree);
-static tree tsubst_template_arg_vector (tree, tree, tsubst_flags_t);
+static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree);
+static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
static void regenerate_decl_from_template (tree, tree);
static tree most_specialized (tree, tree, tree);
static tree try_class_unification (tree, tree, tree, tree);
static int coerce_template_template_parms (tree, tree, tsubst_flags_t,
tree, tree);
-static tree determine_specialization (tree, tree, tree *, int);
+static tree determine_specialization (tree, tree, tree *, int, int);
static int template_args_equal (tree, tree);
static void tsubst_default_arguments (tree);
static tree for_each_template_parm_r (tree *, int *, void *);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
- template, TEMPLATE_DECL for uninstantiated one, or VAR_DECL for
- static member variable (need by instantiate_decl). ARGS is the
- template argument for TEMPLATE_DECL. If CONTEXT is not NULL_TREE,
- this is used instead of the context of T. */
+ template, or VAR_DECL for static member variable (need by
+ instantiate_decl). */
static void
-push_access_scope_real (tree t, tree args, tree context)
+push_access_scope (tree t)
{
- if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
- {
- /* When we are processing specialization `foo<Outer>' for code like
-
- template <class U> typename U::Inner foo ();
- class Outer {
- struct Inner {};
- friend Outer::Inner foo<Outer> ();
- };
-
- `T' is a TEMPLATE_DECL, but `Outer' is only a friend of one of
- its specialization. We can get the FUNCTION_DECL with the right
- information because this specialization has already been
- registered by the friend declaration above. */
-
- if (DECL_FUNCTION_TEMPLATE_P (t) && args)
- {
- tree full_args = tsubst_template_arg_vector
- (DECL_TI_ARGS (DECL_TEMPLATE_RESULT (t)), args, tf_none);
- tree spec = NULL_TREE;
- if (full_args != error_mark_node)
- spec = retrieve_specialization (t, full_args);
- if (spec)
- t = spec;
- }
- }
+ gcc_assert (TREE_CODE (t) == FUNCTION_DECL
+ || TREE_CODE (t) == VAR_DECL);
- if (!context)
- context = DECL_CONTEXT (t);
- if (context && TYPE_P (context))
- push_nested_class (context);
+ if (DECL_CLASS_SCOPE_P (t))
+ push_nested_class (DECL_CONTEXT (t));
else
push_to_top_level ();
- if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
+ if (TREE_CODE (t) == FUNCTION_DECL)
{
saved_access_scope = tree_cons
(NULL_TREE, current_function_decl, saved_access_scope);
}
}
-/* Like push_access_scope_real, but always uses DECL_CONTEXT. */
-
-static void
-push_access_scope (tree t)
-{
- push_access_scope_real (t, NULL_TREE, NULL_TREE);
-}
-
/* Restore the scope set up by push_access_scope. T is the node we
are processing. */
static void
pop_access_scope (tree t)
{
- if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
+ if (TREE_CODE (t) == FUNCTION_DECL)
{
current_function_decl = TREE_VALUE (saved_access_scope);
saved_access_scope = TREE_CHAIN (saved_access_scope);
if (decl == error_mark_node)
return error_mark_node;
- my_friendly_assert (DECL_P (decl), 20020812);
+ gcc_assert (DECL_P (decl));
if (TREE_CODE (decl) == TYPE_DECL)
{
parms, current_template_parms);
TEMPLATE_PARMS_FOR_INLINE (current_template_parms) = 1;
- pushlevel (0);
+ begin_scope (TREE_VEC_LENGTH (parms) ? sk_template_parms : sk_template_spec,
+ NULL);
for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
{
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
- my_friendly_assert (DECL_P (parm), 0);
+ gcc_assert (DECL_P (parm));
switch (TREE_CODE (parm))
{
tree decl = build_decl (CONST_DECL, DECL_NAME (parm),
TREE_TYPE (parm));
DECL_ARTIFICIAL (decl) = 1;
- TREE_CONSTANT (decl) = TREE_READONLY (decl) = 1;
+ TREE_CONSTANT (decl) = 1;
+ TREE_INVARIANT (decl) = 1;
+ TREE_READONLY (decl) = 1;
DECL_INITIAL (decl) = DECL_INITIAL (parm);
SET_DECL_TEMPLATE_PARM_P (decl);
pushdecl (decl);
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
}
/* If there are more levels of EXTRA_ARGS than there are ARGS,
something very fishy is going on. */
- my_friendly_assert (TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args),
- 0);
+ gcc_assert (TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args));
/* If *all* the new arguments will be the EXTRA_ARGS, just return
them. */
int extra_levels;
int i;
- my_friendly_assert (n >= 0, 20000603);
+ gcc_assert (n >= 0);
/* If N is 1, just return the innermost set of template arguments. */
if (n == 1)
/* If we're not removing anything, just return the arguments we were
given. */
extra_levels = TMPL_ARGS_DEPTH (args) - n;
- my_friendly_assert (extra_levels >= 0, 20000603);
+ gcc_assert (extra_levels >= 0);
if (extra_levels == 0)
return args;
pushtag contains special code to call pushdecl_with_scope on the
TEMPLATE_DECL for S2. */
- begin_scope (sk_template_parms);
+ begin_scope (sk_template_parms, NULL);
++processing_template_decl;
++processing_template_parmlist;
note_template_header (0);
void
begin_specialization (void)
{
- begin_scope (sk_template_spec);
+ begin_scope (sk_template_spec, NULL);
note_template_header (1);
check_specialization_scope ();
}
void
begin_explicit_instantiation (void)
{
- my_friendly_assert (!processing_explicit_instantiation, 20020913);
+ gcc_assert (!processing_explicit_instantiation);
processing_explicit_instantiation = true;
}
void
end_explicit_instantiation (void)
{
- my_friendly_assert(processing_explicit_instantiation, 20020913);
+ gcc_assert (processing_explicit_instantiation);
processing_explicit_instantiation = false;
}
+/* A explicit specialization or partial specialization TMPL is being
+ declared. Check that the namespace in which the specialization is
+ occurring is permissible. Returns false iff it is invalid to
+ specialize TMPL in the current namespace. */
+
+static bool
+check_specialization_namespace (tree tmpl)
+{
+ tree tpl_ns = decl_namespace_context (tmpl);
+
+ /* [tmpl.expl.spec]
+
+ An explicit specialization shall be declared in the namespace of
+ which the template is a member, or, for member templates, in the
+ namespace of which the enclosing class or enclosing class
+ template is a member. An explicit specialization of a member
+ function, member class or static data member of a class template
+ shall be declared in the namespace of which the class template is
+ a member. */
+ if (is_associated_namespace (current_namespace, tpl_ns))
+ /* Same or super-using namespace. */
+ return true;
+ else
+ {
+ pedwarn ("specialization of `%D' in different namespace", tmpl);
+ cp_pedwarn_at (" from definition of `%#D'", tmpl);
+ return false;
+ }
+}
+
/* The TYPE is being declared. If it is a template type, that means it
is a partial specialization. Do appropriate error-checking. */
if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
&& !COMPLETE_TYPE_P (type))
{
- if (current_namespace
- != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
- {
- pedwarn ("specializing `%#T' in different namespace", type);
- cp_pedwarn_at (" from definition of `%#D'",
- CLASSTYPE_TI_TEMPLATE (type));
- }
+ check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type));
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
if (processing_template_decl)
push_template_decl (TYPE_MAIN_DECL (type));
{
tree s;
- my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
+ gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
/* There should be as many levels of arguments as there are
levels of parameters. */
- my_friendly_assert (TMPL_ARGS_DEPTH (args)
- == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)),
- 0);
+ gcc_assert (TMPL_ARGS_DEPTH (args)
+ == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)));
for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
s != NULL_TREE;
static tree
retrieve_local_specialization (tree tmpl)
{
- tree spec =
- (tree) htab_find_with_hash (local_specializations, tmpl,
- htab_hash_pointer (tmpl));
+ tree spec = htab_find_with_hash (local_specializations, tmpl,
+ htab_hash_pointer (tmpl));
return spec ? TREE_PURPOSE (spec) : NULL_TREE;
}
}
else
{
- my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 0);
+ gcc_assert (TREE_CODE (decl) == TYPE_DECL);
for (t = TREE_TYPE (decl);
t != NULL_TREE;
return 0;
}
+/* Returns nonzero iff DECL is a specialization of friend declaration
+ FRIEND according to [temp.friend]. */
+
+bool
+is_specialization_of_friend (tree decl, tree friend)
+{
+ bool need_template = true;
+ int template_depth;
+
+ gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+
+ /* For [temp.friend/6] when FRIEND is an ordinary member function
+ of a template class, we want to check if DECL is a specialization
+ if this. */
+ if (TREE_CODE (friend) == FUNCTION_DECL
+ && DECL_TEMPLATE_INFO (friend)
+ && !DECL_USE_TEMPLATE (friend))
+ {
+ friend = DECL_TI_TEMPLATE (friend);
+ need_template = false;
+ }
+
+ /* There is nothing to do if this is not a template friend. */
+ if (TREE_CODE (friend) != TEMPLATE_DECL)
+ return 0;
+
+ if (is_specialization_of (decl, friend))
+ return 1;
+
+ /* [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();
+
+ the member function below is considered a friend
+
+ template <> struct A<int> {
+ void f();
+ };
+
+ For this type of template friend, TEMPLATE_DEPTH below will be
+ nonzero. To determine if DECL is a friend of FRIEND, we first
+ check if the enclosing class is a specialization of another. */
+
+ template_depth = template_class_depth (DECL_CONTEXT (friend));
+ if (template_depth
+ && DECL_CLASS_SCOPE_P (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
+
+ 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. */
+
+ tree context = DECL_CONTEXT (decl);
+ tree args = NULL_TREE;
+ int current_depth = 0;
+ while (current_depth < template_depth)
+ {
+ if (CLASSTYPE_TEMPLATE_INFO (context))
+ {
+ if (current_depth == 0)
+ args = TYPE_TI_ARGS (context);
+ else
+ args = add_to_template_args (TYPE_TI_ARGS (context), args);
+ current_depth++;
+ }
+ context = TYPE_CONTEXT (context);
+ }
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ bool is_template;
+ tree friend_type;
+ tree decl_type;
+ tree friend_args_type;
+ tree decl_args_type;
+
+ /* Make sure that both DECL and FRIEND are templates or
+ non-templates. */
+ is_template = DECL_TEMPLATE_INFO (decl)
+ && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl));
+ if (need_template ^ is_template)
+ return 0;
+ else if (is_template)
+ {
+ /* If both are templates, check template parameter list. */
+ tree friend_parms
+ = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend),
+ args, tf_none);
+ if (!comp_template_parms
+ (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl)),
+ friend_parms))
+ return 0;
+
+ decl_type = TREE_TYPE (DECL_TI_TEMPLATE (decl));
+ }
+ else
+ decl_type = TREE_TYPE (decl);
+
+ friend_type = tsubst_function_type (TREE_TYPE (friend), args,
+ tf_none, NULL_TREE);
+ if (friend_type == error_mark_node)
+ return 0;
+
+ /* Check if return types match. */
+ if (!same_type_p (TREE_TYPE (decl_type), TREE_TYPE (friend_type)))
+ return 0;
+
+ /* Check if function parameter types match, ignoring the
+ `this' parameter. */
+ friend_args_type = TYPE_ARG_TYPES (friend_type);
+ decl_args_type = TYPE_ARG_TYPES (decl_type);
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (friend))
+ 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 0;
+}
+
/* Register the specialization SPEC as a specialization of TMPL with
the indicated ARGS. Returns SPEC, or an equivalent prior
declaration, if available. */
{
tree s;
- my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
+ gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
if (TREE_CODE (spec) == FUNCTION_DECL
&& uses_template_parms (DECL_TI_ARGS (spec)))
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. */
- my_friendly_assert (TMPL_ARGS_DEPTH (args)
- == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)),
- 0);
+ gcc_assert (TMPL_ARGS_DEPTH (args)
+ == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)));
for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
s != NULL_TREE;
more convenient to simply allow this than to try to prevent it. */
if (fn == spec)
return spec;
- else if (comp_template_args (TREE_PURPOSE (s), args))
+ else if (DECL_TEMPLATE_SPECIALIZATION (spec)
+ && comp_template_args (TREE_PURPOSE (s), args))
{
- if (DECL_TEMPLATE_SPECIALIZATION (spec))
+ if (DECL_TEMPLATE_INSTANTIATION (fn))
{
- if (DECL_TEMPLATE_INSTANTIATION (fn))
+ if (TREE_USED (fn)
+ || DECL_EXPLICIT_INSTANTIATION (fn))
{
- if (TREE_USED (fn)
- || DECL_EXPLICIT_INSTANTIATION (fn))
- {
- error ("specialization of %D after instantiation",
- fn);
- return spec;
- }
- else
- {
- /* This situation should occur only if the first
- specialization is an implicit instantiation,
- the second is an explicit specialization, and
- the implicit instantiation has not yet been
- used. That situation can occur if we have
- implicitly instantiated a member function and
- then specialized it later.
-
- We can also wind up here if a friend
- declaration that looked like an instantiation
- turns out to be a specialization:
-
- template <class T> void foo(T);
- class S { friend void foo<>(int) };
- template <> void foo(int);
-
- We transform the existing DECL in place so that
- any pointers to it become pointers to the
- updated declaration.
-
- If there was a definition for the template, but
- not for the specialization, we want this to
- look as if there is no definition, and vice
- versa. */
- DECL_INITIAL (fn) = NULL_TREE;
- duplicate_decls (spec, fn);
-
- return fn;
- }
+ error ("specialization of %D after instantiation",
+ fn);
+ return spec;
}
- else if (DECL_TEMPLATE_SPECIALIZATION (fn))
+ else
{
- if (!duplicate_decls (spec, fn) && DECL_INITIAL (spec))
- /* Dup decl failed, but this is a new
- definition. Set the line number so any errors
- match this new definition. */
- DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (spec);
+ /* This situation should occur only if the first
+ specialization is an implicit instantiation, the
+ second is an explicit specialization, and the
+ implicit instantiation has not yet been used.
+ That situation can occur if we have implicitly
+ instantiated a member function and then
+ specialized it later.
+
+ We can also wind up here if a friend declaration
+ that looked like an instantiation turns out to be
+ a specialization:
+
+ template <class T> void foo(T);
+ class S { friend void foo<>(int) };
+ template <> void foo(int);
+
+ We transform the existing DECL in place so that
+ any pointers to it become pointers to the updated
+ declaration.
+
+ If there was a definition for the template, but
+ not for the specialization, we want this to look
+ as if there were no definition, and vice
+ versa. */
+ DECL_INITIAL (fn) = NULL_TREE;
+ duplicate_decls (spec, fn);
return fn;
}
}
+ else if (DECL_TEMPLATE_SPECIALIZATION (fn))
+ {
+ if (!duplicate_decls (spec, fn) && DECL_INITIAL (spec))
+ /* Dup decl failed, but this is a new definition. Set
+ the line number so any errors match this new
+ definition. */
+ DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (spec);
+
+ return fn;
+ }
}
- }
+ }
+
+ /* A specialization must be declared in the same namespace as the
+ template it is specializing. */
+ if (DECL_TEMPLATE_SPECIALIZATION (spec)
+ && !check_specialization_namespace (tmpl))
+ DECL_CONTEXT (spec) = decl_namespace_context (tmpl);
DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
= tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
}
/* Unregister the specialization SPEC as a specialization of TMPL.
- Returns nonzero if the SPEC was listed as a specialization of
- TMPL. */
+ Replace it with NEW_SPEC, if NEW_SPEC is non-NULL. Returns true
+ if the SPEC was listed as a specialization of TMPL. */
-static int
-unregister_specialization (tree spec, tree tmpl)
+bool
+reregister_specialization (tree spec, tree tmpl, tree new_spec)
{
tree* s;
s = &TREE_CHAIN (*s))
if (TREE_VALUE (*s) == spec)
{
- *s = TREE_CHAIN (*s);
+ if (!new_spec)
+ *s = TREE_CHAIN (*s);
+ else
+ TREE_VALUE (*s) = new_spec;
return 1;
}
If NEED_MEMBER_TEMPLATE is nonzero the function is known to be a
specialization of a member template.
+ The TEMPLATE_COUNT is the number of references to qualifying
+ template classes that appeared in the name of the function. See
+ check_explicit_specialization for a more accurate description.
+
The template args (those explicitly specified and those deduced)
are output in a newly created vector *TARGS_OUT.
determine_specialization (tree template_id,
tree decl,
tree* targs_out,
- int need_member_template)
+ int need_member_template,
+ int template_count)
{
tree fns;
tree targs;
tree explicit_targs;
tree candidates = NULL_TREE;
tree templates = NULL_TREE;
+ int header_count;
+ struct cp_binding_level *b;
*targs_out = NULL_TREE;
return error_mark_node;
}
+ /* Count the number of template headers specified for this
+ specialization. */
+ header_count = 0;
+ for (b = current_binding_level;
+ b->kind == sk_template_parms || b->kind == sk_template_spec;
+ b = b->level_chain)
+ ++header_count;
+
for (; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
{
tree decl_arg_types;
+ tree fn_arg_types;
/* DECL might be a specialization of FN. */
The specialization f<int> is invalid but is not caught
by get_bindings below. */
- if (list_length (TYPE_ARG_TYPES (TREE_TYPE (fn)))
- != list_length (decl_arg_types))
+ fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ if (list_length (fn_arg_types) != list_length (decl_arg_types))
+ continue;
+
+ /* For a non-static member function, we need to make sure that
+ 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),
+ TREE_VALUE (decl_arg_types)))
+ continue;
+
+ /* In case of explicit specialization, we need to check if
+ the number of template headers appearing in the specialization
+ is correct. This is usually done in check_explicit_specialization,
+ but the check done there cannot be exhaustive when specializing
+ member functions. Consider the following code:
+
+ template <> void A<int>::f(int);
+ template <> template <> void A<int>::f(int);
+
+ Assuming that A<int> is not itself an explicit specialization
+ already, the first line specializes "f" which is a non-template
+ member function, whilst the second line specializes "f" which
+ is a template member function. So both lines are syntactically
+ correct, and check_explicit_specialization does not reject
+ them.
+
+ Here, we can do better, as we are matching the specialization
+ against the declarations. We count the number of template
+ headers, and we check if they match TEMPLATE_COUNT + 1
+ (TEMPLATE_COUNT is the number of qualifying template classes,
+ plus there must be another header for the member template
+ itself).
+
+ Notice that if header_count is zero, this is not a
+ specialization but rather a template instantiation, so there
+ is no check we can perform here. */
+ if (header_count && header_count != template_count + 1)
continue;
/* See whether this function might be a specialization of this
TREE_VALUE (in_charge),
new_spec_types);
- new_type = build_cplus_method_type (object_type,
- TREE_TYPE (old_type),
- new_spec_types);
+ new_type = build_method_type_directly (object_type,
+ TREE_TYPE (old_type),
+ new_spec_types);
}
else
new_type = build_function_type (TREE_TYPE (old_type),
new_spec_types);
- new_type = build_type_attribute_variant (new_type,
- TYPE_ATTRIBUTES (old_type));
+ new_type = cp_build_type_attribute_variant (new_type,
+ TYPE_ATTRIBUTES (old_type));
new_type = build_exception_variant (new_type,
TYPE_RAISES_EXCEPTIONS (old_type));
TREE_TYPE (decl) = new_type;
break;
case tsk_excessive_parms:
- error ("too many template parameter lists in declaration of `%D'",
- decl);
- return error_mark_node;
+ case tsk_insufficient_parms:
+ if (tsk == tsk_excessive_parms)
+ error ("too many template parameter lists in declaration of `%D'",
+ decl);
+ else if (template_header_count)
+ error("too few template parameter lists in declaration of `%D'",
+ decl);
+ else
+ error("explicit specialization of `%D' must be introduced by "
+ "`template <>'", decl);
/* Fall through. */
case tsk_expl_spec:
else
specialization = 1;
break;
-
- case tsk_insufficient_parms:
- if (template_header_count)
- {
- error("too few template parameter lists in declaration of `%D'",
- decl);
- return decl;
- }
- else if (ctype != NULL_TREE
- && !TYPE_BEING_DEFINED (ctype)
- && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype)
- && !is_friend)
- {
- /* For backwards compatibility, we accept:
-
- template <class T> struct S { void f(); };
- void S<int>::f() {} // Missing template <>
-
- That used to be valid C++. */
- if (pedantic)
- pedwarn
- ("explicit specialization not preceded by `template <>'");
- specialization = 1;
- SET_DECL_TEMPLATE_SPECIALIZATION (decl);
- }
- break;
case tsk_template:
if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
template <class T> void f<int>(); */
if (uses_template_parms (declarator))
- error ("partial specialization `%D' of function template",
- declarator);
+ error ("function template partial specialization `%D' "
+ "is not allowed", declarator);
else
error ("template-id `%D' in declaration of primary template",
declarator);
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (specialization || member_specialization)
{
tree fns;
- my_friendly_assert (TREE_CODE (declarator) == IDENTIFIER_NODE, 0);
+ gcc_assert (TREE_CODE (declarator) == IDENTIFIER_NODE);
if (ctype)
fns = dname;
else
{
/* If there is no class context, the explicit instantiation
must be at namespace scope. */
- my_friendly_assert (DECL_NAMESPACE_SCOPE_P (decl), 20030625);
+ gcc_assert (DECL_NAMESPACE_SCOPE_P (decl));
/* Find the namespace binding, using the declaration
context. */
return decl;
}
- else if (TREE_CODE (TREE_OPERAND (declarator, 0)) == LOOKUP_EXPR)
- {
- /* A friend declaration. We can't do much, because we don't
- know what this resolves to, yet. */
- my_friendly_assert (is_friend != 0, 0);
- my_friendly_assert (!explicit_instantiation, 0);
- SET_DECL_IMPLICIT_INSTANTIATION (decl);
- return decl;
- }
else if (ctype != NULL_TREE
&& (TREE_CODE (TREE_OPERAND (declarator, 0)) ==
IDENTIFIER_NODE))
{
idx = lookup_fnfields_1 (ctype, name);
if (idx >= 0)
- fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (ctype), idx);
+ fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (ctype), idx);
}
else
{
- tree methods;
+ VEC(tree) *methods;
+ tree ovl;
/* For a type-conversion operator, we cannot do a
name-based lookup. We might be looking for `operator
methods = CLASSTYPE_METHOD_VEC (ctype);
if (methods)
for (idx = CLASSTYPE_FIRST_CONVERSION_SLOT;
- idx < TREE_VEC_LENGTH (methods); ++idx)
+ VEC_iterate (tree, methods, idx, ovl);
+ ++idx)
{
- tree ovl = TREE_VEC_ELT (methods, idx);
-
- if (!ovl || !DECL_CONV_FN_P (OVL_CURRENT (ovl)))
+ if (!DECL_CONV_FN_P (OVL_CURRENT (ovl)))
/* There are no more conversion functions. */
break;
declaration. */
tmpl = determine_specialization (declarator, decl,
&targs,
- member_specialization);
+ member_specialization,
+ template_count);
if (!tmpl || tmpl == error_mark_node)
/* We couldn't figure out what this declaration was
/* If we thought that the DECL was a member function, but it
turns out to be specializing a static member function,
- make DECL a static member function as well. We also have
- to adjust last_function_parms to avoid confusing
- start_function later. */
+ make DECL a static member function as well. */
if (DECL_STATIC_FUNCTION_P (tmpl)
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
- {
- revert_static_member_fn (decl);
- last_function_parms = TREE_CHAIN (last_function_parms);
- }
+ revert_static_member_fn (decl);
/* If this is a specialization of a member template of a
template class. In we want to return the TEMPLATE_DECL,
parameters. These are represented in the same format used for
DECL_TEMPLATE_PARMS. */
-int comp_template_parms (tree parms1, tree parms2)
+int
+comp_template_parms (tree parms1, tree parms2)
{
tree p1;
tree p2;
tree t2 = TREE_VALUE (p2);
int i;
- my_friendly_assert (TREE_CODE (t1) == TREE_VEC, 0);
- my_friendly_assert (TREE_CODE (t2) == TREE_VEC, 0);
+ gcc_assert (TREE_CODE (t1) == TREE_VEC);
+ gcc_assert (TREE_CODE (t2) == TREE_VEC);
if (TREE_VEC_LENGTH (t1) != TREE_VEC_LENGTH (t2))
return 0;
/* Figure out what we're shadowing. */
if (TREE_CODE (decl) == OVERLOAD)
decl = OVL_CURRENT (decl);
- olddecl = IDENTIFIER_VALUE (DECL_NAME (decl));
+ olddecl = innermost_non_namespace_value (DECL_NAME (decl));
/* If there's no previous binding for this name, we're not shadowing
anything, let alone a template parameter. */
TEMPLATE_PARM_DECL (t) = decl;
TREE_TYPE (t) = type;
TREE_CONSTANT (t) = TREE_CONSTANT (decl);
+ TREE_INVARIANT (t) = TREE_INVARIANT (decl);
TREE_READONLY (t) = TREE_READONLY (decl);
return t;
decl = build_decl (TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);
TREE_CONSTANT (decl) = TREE_CONSTANT (orig_decl);
+ TREE_INVARIANT (decl) = TREE_INVARIANT (orig_decl);
TREE_READONLY (decl) = TREE_READONLY (orig_decl);
DECL_ARTIFICIAL (decl) = 1;
SET_DECL_TEMPLATE_PARM_P (decl);
}
/* Process information from new template parameter NEXT and append it to the
- LIST being built. */
+ LIST being built. This new parameter is a non-type parameter iff
+ IS_NON_TYPE is true. */
tree
-process_template_parm (tree list, tree next)
+process_template_parm (tree list, tree next, bool is_non_type)
{
tree parm;
tree decl = 0;
tree defval;
- int is_type, idx;
+ int idx;
parm = next;
- my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259);
+ gcc_assert (TREE_CODE (parm) == TREE_LIST);
defval = TREE_PURPOSE (parm);
- parm = TREE_VALUE (parm);
- is_type = TREE_PURPOSE (parm) == class_type_node;
if (list)
{
else
idx = 0;
- if (!is_type)
+ if (is_non_type)
{
- my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);
- /* is a const-param */
- parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
- PARM, 0, NULL);
+ parm = TREE_VALUE (parm);
+
SET_DECL_TEMPLATE_PARM_P (parm);
/* [temp.param]
TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
/* A template parameter is not modifiable. */
- TREE_READONLY (parm) = TREE_CONSTANT (parm) = 1;
+ TREE_CONSTANT (parm) = 1;
+ TREE_INVARIANT (parm) = 1;
+ TREE_READONLY (parm) = 1;
if (invalid_nontype_parm_type_p (TREE_TYPE (parm), 1))
TREE_TYPE (parm) = void_type_node;
decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
- TREE_CONSTANT (decl) = TREE_READONLY (decl) = 1;
+ TREE_CONSTANT (decl) = 1;
+ TREE_INVARIANT (decl) = 1;
+ TREE_READONLY (decl) = 1;
DECL_INITIAL (parm) = DECL_INITIAL (decl)
= build_template_parm_index (idx, processing_template_decl,
processing_template_decl,
else
{
tree t;
- parm = TREE_VALUE (parm);
+ parm = TREE_VALUE (TREE_VALUE (parm));
if (parm && TREE_CODE (parm) == TEMPLATE_DECL)
{
else
{
t = make_aggr_type (TEMPLATE_TYPE_PARM);
- /* parm is either IDENTIFIER_NODE or NULL_TREE */
+ /* parm is either IDENTIFIER_NODE or NULL_TREE. */
decl = build_decl (TYPE_DECL, parm, t);
}
The type of a template parameter corresponding to a specialized
non-type argument shall not be dependent on a parameter of the
specialization. */
- my_friendly_assert (nargs == DECL_NTPARMS (maintmpl), 0);
+ gcc_assert (nargs == DECL_NTPARMS (maintmpl));
tpd2.parms = 0;
for (i = 0; i < nargs; ++i)
{
{
/* We haven't yet initialized TPD2. Do so now. */
tpd2.arg_uses_template_parms
- = (int*) alloca (sizeof (int) * nargs);
+ = 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 = (int*) alloca (sizeof (int) * nargs);
+ tpd2.parms = alloca (sizeof (int) * nargs);
tpd2.level =
TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (maintmpl));
}
int is_partial;
int new_template_p = 0;
+ if (decl == error_mark_node)
+ return decl;
+
/* See if this is a partial specialization. */
is_partial = (DECL_IMPLICIT_TYPEDEF_P (decl)
&& TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
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. */
+ error ("destructor `%D' declared as member template", decl);
+ return error_mark_node;
+ }
+ if (NEW_DELETE_OPNAME_P (DECL_NAME (decl))
+ && (!TYPE_ARG_TYPES (TREE_TYPE (decl))
+ || TYPE_ARG_TYPES (TREE_TYPE (decl)) == void_list_node
+ || !TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)))
+ || (TREE_CHAIN (TYPE_ARG_TYPES ((TREE_TYPE (decl))))
+ == void_list_node)))
+ {
+ /* [basic.stc.dynamic.allocation]
+
+ An allocation function can be a function
+ template. ... Template allocation functions shall
+ have two or more parameters. */
+ error ("invalid template declaration of `%D'", decl);
+ return decl;
+ }
+ }
else if ((DECL_IMPLICIT_TYPEDEF_P (decl)
&& CLASS_TYPE_P (TREE_TYPE (decl)))
- || (TREE_CODE (decl) == VAR_DECL && ctx && CLASS_TYPE_P (ctx))
- || TREE_CODE (decl) == FUNCTION_DECL)
+ || (TREE_CODE (decl) == VAR_DECL && ctx && CLASS_TYPE_P (ctx)))
/* OK */;
else
- error ("template declaration of `%#D'", decl);
+ {
+ error ("template declaration of `%#D'", decl);
+ return error_mark_node;
+ }
}
/* Check to see that the rules regarding the use of default
else
tmpl = DECL_TI_TEMPLATE (decl);
- if (is_member_template (tmpl)
- && DECL_FUNCTION_TEMPLATE_P (tmpl)
+ if (DECL_FUNCTION_TEMPLATE_P (tmpl)
&& DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl)
- && DECL_TEMPLATE_SPECIALIZATION (decl))
+ && DECL_TEMPLATE_SPECIALIZATION (decl)
+ && is_member_template (tmpl))
{
tree new_tmpl;
/* It is a conversion operator. See if the type converted to
depends on innermost template operands. */
- if (for_each_template_parm (TREE_TYPE (TREE_TYPE (tmpl)),
- template_parm_this_level_p,
- &depth,
- NULL))
+ if (uses_template_parms_level (TREE_TYPE (TREE_TYPE (tmpl)),
+ depth))
DECL_TEMPLATE_CONV_FN_P (tmpl) = 1;
}
}
+ /* The DECL_TI_ARGS of DECL contains full set of arguments referring
+ back to its most general template. If TMPL is a specialization,
+ ARGS may only have the innermost set of arguments. Add the missing
+ argument levels if necessary. */
+ if (DECL_TEMPLATE_INFO (tmpl))
+ args = add_outermost_template_args (DECL_TI_ARGS (tmpl), args);
+
info = tree_cons (tmpl, args, NULL_TREE);
if (DECL_IMPLICIT_TYPEDEF_P (decl))
tree tmpl_default = TREE_PURPOSE (TREE_VEC_ELT (tmpl_parms, i));
tree parm_default = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
- if (TREE_CODE (tmpl_parm) != TREE_CODE (parm))
+ /* TMPL_PARM and PARM can be either TYPE_DECL, PARM_DECL, or
+ TEMPLATE_DECL. */
+ if (TREE_CODE (tmpl_parm) != TREE_CODE (parm)
+ || (TREE_CODE (tmpl_parm) != TYPE_DECL
+ && !same_type_p (TREE_TYPE (tmpl_parm), TREE_TYPE (parm))))
{
cp_error_at ("template parameter `%#D'", tmpl_parm);
error ("redeclared here as `%#D'", parm);
A template-parameter may not be given default arguments
by two different declarations in the same scope. */
error ("redefinition of default argument for `%#D'", parm);
- error ("%H original definition appeared here",
- &DECL_SOURCE_LOCATION (tmpl_parm));
+ error ("%J original definition appeared here", tmpl_parm);
return;
}
}
}
+/* Simplify EXPR if it is a non-dependent expression. Returns the
+ (possibly simplified) expression. */
+
+tree
+fold_non_dependent_expr (tree expr)
+{
+ /* 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)
+ && !value_dependent_expression_p (expr))
+ {
+ HOST_WIDE_INT saved_processing_template_decl;
+
+ saved_processing_template_decl = processing_template_decl;
+ processing_template_decl = 0;
+ expr = tsubst_copy_and_build (expr,
+ /*args=*/NULL_TREE,
+ tf_error,
+ /*in_decl=*/NULL_TREE,
+ /*function_p=*/false);
+ processing_template_decl = saved_processing_template_decl;
+ }
+ return expr;
+}
+
/* 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
NULL_TREE if we issued an error message, or error_mark_node if we
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. By the time this
- function is called, neither TYPE nor EXPR may make use of template
- parameters. */
+ might be just trying to do argument deduction. Both TYPE and EXPR
+ must be non-dependent. */
static tree
convert_nontype_argument (tree type, tree expr)
{
- tree expr_type = TREE_TYPE (expr);
+ tree expr_type;
+
+ /* 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
+ SCOPE_REF refers. Preserving the qualifying scope is necessary
+ so that access checking can be performed when the template is
+ instantiated -- but here we need the resolved form so that we can
+ convert the argument. */
+ 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:
--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,
+. 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)
- expr = decl_constant_value (expr);
+ if (INTEGRAL_TYPE_P (expr_type) && TREE_CODE (type) != REFERENCE_TYPE)
+ while (true)
+ {
+ tree const_expr = decl_constant_value (expr);
+ /* In a template, the initializer for a VAR_DECL may not be
+ marked as TREE_CONSTANT, in which case decl_constant_value
+ will not return the initializer. Handle that special case
+ here. */
+ if (expr == const_expr
+ && DECL_INTEGRAL_CONSTANT_VAR_P (expr)
+ /* DECL_INITIAL can be NULL if we are processing a
+ variable initialized to an expression involving itself.
+ We know it is initialized to a constant -- but not what
+ constant, yet. */
+ && DECL_INITIAL (expr))
+ const_expr = DECL_INITIAL (expr);
+ if (expr == const_expr)
+ break;
+ expr = fold_non_dependent_expr (const_expr);
+ }
if (is_overloaded_fn (expr))
/* OK for now. We'll check that it has external linkage later.
Check this first since if expr_type is the unknown_type_node
we would otherwise complain below. */
;
- else if (TYPE_PTRMEM_P (expr_type)
- || TYPE_PTRMEMFUNC_P (expr_type))
+ else if (TYPE_PTR_TO_MEMBER_P (expr_type))
{
if (TREE_CODE (expr) != PTRMEM_CST)
goto bad_argument;
else
error ("it must be the address of an object with external linkage");
}
- else if (TYPE_PTRMEM_P (expr_type)
- || TYPE_PTRMEMFUNC_P (expr_type))
+ else if (TYPE_PTR_TO_MEMBER_P (expr_type))
error ("it must be a pointer-to-member of the form `&X::Y'");
return NULL_TREE;
return error_mark_node;
}
}
- else if (INTEGRAL_TYPE_P (expr_type)
- || TYPE_PTRMEM_P (expr_type)
- || TYPE_PTRMEMFUNC_P (expr_type))
+ else if (INTEGRAL_TYPE_P (expr_type) || TYPE_PTR_TO_MEMBER_P (expr_type))
{
if (! TREE_CONSTANT (expr))
{
}
else
{
- error ("object `%E' cannot be used as template argument", expr);
+ if (TYPE_P (expr))
+ error ("type '%T' cannot be used as a value for a non-type "
+ "template-parameter", expr);
+ else if (DECL_P (expr))
+ error ("invalid use of '%D' as a non-type template-argument", expr);
+ else
+ error ("invalid use of '%E' as a non-type template-argument", expr);
+
return NULL_TREE;
}
conversions (_conv.integral_) are applied. */
if (!INTEGRAL_TYPE_P (expr_type))
return error_mark_node;
-
+
+ /* [conv.integral] does not allow conversions between two different
+ enumeration types. */
+ if (TREE_CODE (type) == ENUMERAL_TYPE
+ && TREE_CODE (expr_type) == ENUMERAL_TYPE
+ && !same_type_ignoring_top_level_qualifiers_p (type, expr_type))
+ return error_mark_node;
+
/* It's safe to call digest_init in this case; we know we're
just converting one integral constant expression to another. */
expr = digest_init (type, expr, (tree*) 0);
goto non_constant;
return expr;
-
+
+ case OFFSET_TYPE:
+ {
+ tree e;
+
+ /* For a non-type template-parameter of type pointer to data
+ member, qualification conversions (_conv.qual_) are
+ applied. */
+ e = perform_qualification_conversions (type, expr);
+ if (TREE_CODE (e) == NOP_EXPR)
+ /* The call to perform_qualification_conversions will
+ insert a NOP_EXPR over EXPR to do express conversion,
+ if necessary. But, that will confuse us if we use
+ this (converted) template parameter to instantiate
+ another template; then the thing will not look like a
+ valid template argument. So, just make a new
+ constant, of the appropriate type. */
+ e = make_ptrmem_cst (type, PTRMEM_CST_MEMBER (expr));
+ return e;
+ }
+
case POINTER_TYPE:
{
tree type_pointed_to = TREE_TYPE (type);
- if (TYPE_PTRMEM_P (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;
- }
- else if (TREE_CODE (type_pointed_to) == FUNCTION_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
expr = build_unary_op (ADDR_EXPR, fn, 0);
- my_friendly_assert (same_type_p (type, TREE_TYPE (expr)),
- 0);
+ gcc_assert (same_type_p (type, TREE_TYPE (expr)));
return expr;
}
else
tree type_referred_to = TREE_TYPE (type);
/* If this expression already has reference type, get the
- underling object. */
+ underlying object. */
if (TREE_CODE (expr_type) == REFERENCE_TYPE)
{
- my_friendly_assert (TREE_CODE (expr) == ADDR_EXPR, 20000604);
+ 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);
}
goto bad_argument;
}
- my_friendly_assert (same_type_p (type_referred_to,
- TREE_TYPE (fn)),
- 0);
-
+ gcc_assert (same_type_p (type_referred_to, TREE_TYPE (fn)));
expr = fn;
}
else
}
cxx_mark_addressable (expr);
- return build1 (ADDR_EXPR, type, expr);
+ return build_nop (type, build_address (expr));
}
break;
case RECORD_TYPE:
{
- my_friendly_assert (TYPE_PTRMEMFUNC_P (type), 20010112);
+ gcc_assert (TYPE_PTRMEMFUNC_P (type));
/* For a non-type template-parameter of type pointer to member
function, no conversions apply. If the template-argument
if (expr == error_mark_node)
return error_mark_node;
- my_friendly_assert (same_type_p (type, TREE_TYPE (expr)),
- 0);
+ if (!same_type_p (type, TREE_TYPE (expr)))
+ return error_mark_node;
+
return expr;
}
break;
default:
/* All non-type parameters must have one of these types. */
- abort ();
- break;
+ gcc_unreachable ();
}
return error_mark_node;
int nparms, nargs, i;
tree parm, arg;
- my_friendly_assert (TREE_CODE (parm_parms) == TREE_VEC, 0);
- my_friendly_assert (TREE_CODE (arg_parms) == TREE_VEC, 0);
+ gcc_assert (TREE_CODE (parm_parms) == TREE_VEC);
+ gcc_assert (TREE_CODE (arg_parms) == TREE_VEC);
nparms = TREE_VEC_LENGTH (parm_parms);
nargs = TREE_VEC_LENGTH (arg_parms);
tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
- if (!coerce_template_template_parms (parmparm, argparm,
- complain, in_decl,
- outer_args))
+ if (!coerce_template_template_parms
+ (parmparm, argparm, complain, in_decl, outer_args))
return 0;
}
break;
case PARM_DECL:
/* The tsubst call is used to handle cases such as
- template <class T, template <T> class TT> class D;
+
+ template <int> class C {};
+ template <class T, template <T> class TT> class D {};
+ D<int, C> d;
+
i.e. the parameter list of TT depends on earlier parameters. */
- if (!same_type_p (tsubst (TREE_TYPE (parm), outer_args,
- complain, in_decl),
- TREE_TYPE (arg)))
+ if (!dependent_type_p (TREE_TYPE (arg))
+ && !same_type_p
+ (tsubst (TREE_TYPE (parm), outer_args, complain, in_decl),
+ TREE_TYPE (arg)))
return 0;
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
return 1;
inner_args = INNERMOST_TEMPLATE_ARGS (args);
if (TREE_CODE (arg) == TREE_LIST
- && TREE_TYPE (arg) != NULL_TREE
- && TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE)
+ && TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
{
/* The template argument was the name of some
member function. That's usually
requires_type = (TREE_CODE (parm) == TYPE_DECL
|| requires_tmpl_type);
- if (TREE_CODE (arg) != RECORD_TYPE)
- is_tmpl_type = ((TREE_CODE (arg) == TEMPLATE_DECL
- && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
- || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
- || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);
- else if (CLASSTYPE_TEMPLATE_INFO (arg) && !CLASSTYPE_USE_TEMPLATE (arg)
- && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (arg)))
- {
- if (is_base_of_enclosing_class (arg, current_class_type))
- /* This is a template name used within the scope of the
- template. It could be the template, or it could be the
- instantiation. Choose whichever makes sense. */
- is_tmpl_type = requires_tmpl_type;
- else
- is_tmpl_type = 1;
- }
- else
- /* It is a non-template class, or a specialization of a template
- class, or a non-template member of a template class. */
- is_tmpl_type = 0;
+ is_tmpl_type = ((TREE_CODE (arg) == TEMPLATE_DECL
+ && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
+ || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+ || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);
if (is_tmpl_type
&& (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE))
arg = TYPE_STUB_DECL (arg);
- else if (is_tmpl_type && TREE_CODE (arg) == RECORD_TYPE)
- arg = CLASSTYPE_TI_TEMPLATE (arg);
is_type = TYPE_P (arg) || is_tmpl_type;
}
}
else
- val = groktypename (arg);
+ val = arg;
}
else
{
tree new_inner_args;
inner_args = INNERMOST_TEMPLATE_ARGS (args);
- nargs = NUM_TMPL_ARGS (inner_args);
+ nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
nparms = TREE_VEC_LENGTH (parms);
if (nargs > nparms
parm = TREE_VEC_ELT (parms, i);
/* Calculate the Ith argument. */
- if (inner_args && TREE_CODE (inner_args) == TREE_LIST)
- {
- arg = TREE_VALUE (inner_args);
- inner_args = TREE_CHAIN (inner_args);
- }
- else if (i < nargs)
+ if (i < nargs)
arg = TREE_VEC_ELT (inner_args, i);
- /* If no template argument was supplied, look for a default
- value. */
- else if (TREE_PURPOSE (parm) == NULL_TREE)
- {
- /* There was no default value. */
- my_friendly_assert (!require_all_arguments, 0);
- break;
- }
- else if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
- arg = tsubst (TREE_PURPOSE (parm), new_args, complain, in_decl);
+ else if (require_all_arguments)
+ /* There must be a default arg in this case. */
+ arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,
+ complain, in_decl);
else
- arg = tsubst_expr (TREE_PURPOSE (parm), new_args, complain,
- in_decl);
-
- /* Now, convert the Ith argument, as necessary. */
- if (arg == NULL_TREE)
- /* We're out of arguments. */
- {
- my_friendly_assert (!require_all_arguments, 0);
- break;
- }
- else if (arg == error_mark_node)
- {
- error ("template argument %d is invalid", i + 1);
- arg = error_mark_node;
- }
+ 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),
arg, new_args, complain, i,
ccat ('<');
nparms = TREE_VEC_LENGTH (parms);
arglist = INNERMOST_TEMPLATE_ARGS (arglist);
- my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268);
+ gcc_assert (nparms == TREE_VEC_LENGTH (arglist));
for (i = 0; i < nparms; i++)
{
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
{
/* The template may be defined in a namespace, or
may be a member template. */
- my_friendly_assert (TREE_CODE (context) == NAMESPACE_DECL
- || CLASS_TYPE_P (context),
- 980422);
- cat(decl_as_string (DECL_CONTEXT (arg), TFF_PLAIN_IDENTIFIER));
- cat("::");
+ gcc_assert (TREE_CODE (context) == NAMESPACE_DECL
+ || CLASS_TYPE_P (context));
+ cat (decl_as_string (DECL_CONTEXT (arg),
+ TFF_PLAIN_IDENTIFIER));
+ cat ("::");
}
cat (IDENTIFIER_POINTER (DECL_NAME (arg)));
}
else
- /* Output the parameter declaration */
+ /* Output the parameter declaration. */
cat (type_as_string (arg, TFF_CHASE_TYPEDEF));
continue;
}
else
- my_friendly_assert (TREE_CODE (parm) == PARM_DECL, 269);
+ gcc_assert (TREE_CODE (parm) == PARM_DECL);
- if (TREE_CODE (arg) == TREE_LIST)
- {
- /* New list cell was built because old chain link was in
- use. */
- my_friendly_assert (TREE_PURPOSE (arg) == NULL_TREE, 270);
- arg = TREE_VALUE (arg);
- }
/* No need to check arglist against parmlist here; we did that
in coerce_template_parms, called from lookup_template_class. */
cat (expr_as_string (arg, TFF_PLAIN_IDENTIFIER));
if (fns == error_mark_node || arglist == error_mark_node)
return error_mark_node;
- if (fns == NULL_TREE)
+ 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;
}
- my_friendly_assert (TREE_CODE (fns) == TEMPLATE_DECL
- || TREE_CODE (fns) == OVERLOAD
- || BASELINK_P (fns)
- || TREE_CODE (fns) == IDENTIFIER_NODE
- || TREE_CODE (fns) == LOOKUP_EXPR,
- 20020730);
+ gcc_assert (TREE_CODE (fns) == TEMPLATE_DECL
+ || TREE_CODE (fns) == OVERLOAD
+ || BASELINK_P (fns)
+ || TREE_CODE (fns) == IDENTIFIER_NODE);
if (BASELINK_P (fns))
{
- BASELINK_FUNCTIONS (fns) = build (TEMPLATE_ID_EXPR,
- unknown_type_node,
- BASELINK_FUNCTIONS (fns),
- arglist);
+ BASELINK_FUNCTIONS (fns) = build2 (TEMPLATE_ID_EXPR,
+ unknown_type_node,
+ BASELINK_FUNCTIONS (fns),
+ arglist);
return fns;
}
if (TREE_CODE (fns) == OVERLOAD || !type)
type = unknown_type_node;
- return build (TEMPLATE_ID_EXPR, type, fns, arglist);
+ return build2 (TEMPLATE_ID_EXPR, type, fns, arglist);
}
/* Within the scope of a template class S<T>, the name S gets bound
parameters, find the desired type.
D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments.
- (Actually ARGLIST may be either a TREE_LIST or a TREE_VEC. It will
- be a TREE_LIST if called directly from the parser, and a TREE_VEC
- otherwise.)
IN_DECL, if non-NULL, is the template declaration we are trying to
instantiate.
{
tree template = NULL_TREE, parmlist;
tree t;
-
+
timevar_push (TV_NAME_LOOKUP);
+
if (TREE_CODE (d1) == IDENTIFIER_NODE)
{
- if (IDENTIFIER_VALUE (d1)
- && DECL_TEMPLATE_TEMPLATE_PARM_P (IDENTIFIER_VALUE (d1)))
- template = IDENTIFIER_VALUE (d1);
+ tree value = innermost_non_namespace_value (d1);
+ if (value && DECL_TEMPLATE_TEMPLATE_PARM_P (value))
+ template = value;
else
{
if (context)
context = DECL_CONTEXT (template);
}
- /* With something like `template <class T> class X class X { ... };'
- we could end up with D1 having nothing but an IDENTIFIER_VALUE.
- We don't want to do that, but we have to deal with the situation,
- so let's give them some syntax errors to chew on instead of a
- crash. Alternatively D1 might not be a template type at all. */
+ /* Issue an error message if we didn't find a template. */
if (! template)
{
if (complain & tf_error)
}
if (TREE_CODE (template) != TEMPLATE_DECL
- /* If we're called from the parser, make sure it's a user visible
- template. */
- || ((!arglist || TREE_CODE (arglist) == TREE_LIST)
- && !DECL_TEMPLATE_PARM_P (template)
- && !PRIMARY_TEMPLATE_P (template)))
+ /* 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)
{
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
}
/* Now we should have enough arguments. */
- my_friendly_assert (parm_depth == arg_depth, 0);
+ gcc_assert (parm_depth == arg_depth);
/* From here on, we're only interested in the most general
template. */
template,
complain, /*require_all_args=*/1);
- if (arglist == error_mark_node
- || (!uses_template_parms (INNERMOST_TEMPLATE_ARGS (arglist))
- && check_instantiated_args (template,
- INNERMOST_TEMPLATE_ARGS (arglist),
- complain)))
+ if (arglist == error_mark_node)
/* We were unable to bind the arguments. */
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
tree ctx;
for (ctx = current_class_type;
- ctx;
- ctx = TYPE_CONTEXT (ctx))
- {
- if (TREE_CODE (ctx) == NAMESPACE_DECL)
- break;
- if (same_type_p (ctx, template_type))
- goto found_ctx;
- }
+ 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. */
well. */
is_partial_instantiation = uses_template_parms (arglist);
+ /* If the deduced arguments are invalid, then the binding
+ failed. */
+ if (!is_partial_instantiation
+ && check_instantiated_args (template,
+ INNERMOST_TEMPLATE_ARGS (arglist),
+ complain))
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+
if (!is_partial_instantiation
&& !PRIMARY_TEMPLATE_P (template)
&& TREE_CODE (CP_DECL_CONTEXT (template)) == NAMESPACE_DECL)
t = make_aggr_type (TREE_CODE (template_type));
CLASSTYPE_DECLARED_CLASS (t)
= CLASSTYPE_DECLARED_CLASS (template_type);
- CLASSTYPE_GOT_SEMICOLON (t) = 1;
SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
TYPE_FOR_JAVA (t) = TYPE_FOR_JAVA (template_type);
is set up. */
if (TREE_CODE (t) != ENUMERAL_TYPE)
DECL_NAME (type_decl) = classtype_mangled_name (t);
- if (!is_partial_instantiation)
- {
- /* For backwards compatibility; code that uses
- -fexternal-templates expects looking up a template to
- instantiate it. I think DDD still relies on this.
- (jason 8/20/1998) */
- if (TREE_CODE (t) != ENUMERAL_TYPE
- && flag_external_templates
- && CLASSTYPE_INTERFACE_KNOWN (TREE_TYPE (template))
- && ! CLASSTYPE_INTERFACE_ONLY (TREE_TYPE (template)))
- add_pending_template (t);
- }
- else
+ if (is_partial_instantiation)
/* If the type makes use of template parameters, the
code that generates debugging information will crash. */
DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;
/* Called from for_each_template_parm via walk_tree. */
static tree
-for_each_template_parm_r (tree* tp, int* walk_subtrees, void* d)
+for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
{
tree t = *tp;
struct pair_fn_data *pfd = (struct pair_fn_data *) d;
tree_fn_t fn = pfd->fn;
void *data = pfd->data;
- void **slot;
-
- /* If we have already visited this tree, there's no need to walk
- subtrees. Otherwise, add it to the visited table. */
- slot = htab_find_slot (pfd->visited, *tp, INSERT);
- if (*slot)
- {
- *walk_subtrees = 0;
- return NULL_TREE;
- }
- *slot = *tp;
if (TYPE_P (t)
&& for_each_template_parm (TYPE_CONTEXT (t), fn, data, pfd->visited))
break;
case TEMPLATE_DECL:
- /* A template template parameter is encountered */
+ /* A template template parameter is encountered. */
if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)
&& for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited))
return error_mark_node;
case ARROW_EXPR:
case DOTSTAR_EXPR:
case TYPEID_EXPR:
- case LOOKUP_EXPR:
case PSEUDO_DTOR_EXPR:
if (!fn)
return error_mark_node;
result = walk_tree (&t,
for_each_template_parm_r,
&pfd,
- NULL) != NULL_TREE;
+ pfd.visited) != NULL_TREE;
/* Clean up. */
if (!visited)
return result;
}
+/* Returns true if T depends on any template parameter. */
+
int
uses_template_parms (tree t)
{
- return for_each_template_parm (t, 0, 0, NULL);
+ bool dependent_p;
+ int saved_processing_template_decl;
+
+ saved_processing_template_decl = processing_template_decl;
+ if (!saved_processing_template_decl)
+ processing_template_decl = 1;
+ if (TYPE_P (t))
+ dependent_p = dependent_type_p (t);
+ else if (TREE_CODE (t) == TREE_VEC)
+ dependent_p = any_dependent_template_arguments_p (t);
+ 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)
+ || TREE_CODE (t) == TEMPLATE_PARM_INDEX
+ || TREE_CODE (t) == OVERLOAD
+ || TREE_CODE (t) == BASELINK
+ || TREE_CODE_CLASS (TREE_CODE (t)) == 'c')
+ dependent_p = (type_dependent_expression_p (t)
+ || value_dependent_expression_p (t));
+ else
+ {
+ gcc_assert (t == error_mark_node);
+ dependent_p = false;
+ }
+
+ processing_template_decl = saved_processing_template_decl;
+
+ return dependent_p;
+}
+
+/* Returns true if T depends on any template parameter with level LEVEL. */
+
+int
+uses_template_parms_level (tree t, int level)
+{
+ return for_each_template_parm (t, template_parm_this_level_p, &level, NULL);
}
static int tinst_depth;
return 0;
}
- new = build_expr_wfl (d, input_filename, input_line, 0);
+ new = make_tinst_level (d, input_location);
TREE_CHAIN (new) = current_tinst_level;
current_tinst_level = new;
/* Restore the filename and line number stashed away when we started
this instantiation. */
- input_line = TINST_LINE (old);
- input_filename = TINST_FILE (old);
+ input_location = TINST_LOCATION (old);
extract_interface_info ();
current_tinst_level = TREE_CHAIN (old);
new_friend = tsubst (decl, args, tf_error | tf_warning, NULL_TREE);
tmpl = determine_specialization (template_id, new_friend,
&new_args,
- /*need_member_template=*/0);
+ /*need_member_template=*/0,
+ TREE_VEC_LENGTH (args));
new_friend = instantiate_template (tmpl, new_args, tf_error);
goto done;
}
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)
{
duplicate decls since that function will free NEW_FRIEND if
possible. */
new_friend_template_info = DECL_TEMPLATE_INFO (new_friend);
+ new_friend_is_defn =
+ (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_is_defn
- = DECL_INITIAL (DECL_TEMPLATE_RESULT (new_friend)) != NULL_TREE;
new_friend_result_template_info
= DECL_TEMPLATE_INFO (DECL_TEMPLATE_RESULT (new_friend));
}
else
- {
- new_friend_is_defn = DECL_INITIAL (new_friend) != NULL_TREE;
- new_friend_result_template_info = NULL_TREE;
- }
+ new_friend_result_template_info = NULL_TREE;
/* Inside pushdecl_namespace_level, we will push into the
current namespace. However, the friend function should go
DECL_TEMPLATE_INFO (old_decl) = new_friend_template_info;
if (TREE_CODE (old_decl) != TEMPLATE_DECL)
- /* duplicate_decls will take care of this case. */
- ;
+ reregister_specialization (new_friend,
+ most_general_template (old_decl),
+ old_decl);
else
{
tree t;
{
/* 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);
+ tree fn = check_classfn (DECL_CONTEXT (new_friend),
+ new_friend, NULL_TREE);
if (fn)
new_friend = fn;
DECL_USE_TEMPLATE (tmpl) = 0;
DECL_TEMPLATE_INFO (tmpl) = NULL_TREE;
CLASSTYPE_USE_TEMPLATE (TREE_TYPE (tmpl)) = 0;
+ CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl))
+ = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl)));
/* Inject this template into the global scope. */
friend_type = TREE_TYPE (pushdecl_top_level (tmpl));
return 1;
else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
return can_complete_type_without_circularity (TREE_TYPE (type));
- else if (CLASS_TYPE_P (type) && TYPE_BEING_DEFINED (TYPE_MAIN_VARIANT (type)))
+ else if (CLASS_TYPE_P (type)
+ && TYPE_BEING_DEFINED (TYPE_MAIN_VARIANT (type)))
return 0;
else
return 1;
tree template, args, pattern, t, member;
tree typedecl;
tree pbinfo;
+ tree base_list;
if (type == error_mark_node)
return error_mark_node;
/* Figure out which template is being instantiated. */
template = most_general_template (CLASSTYPE_TI_TEMPLATE (type));
- my_friendly_assert (TREE_CODE (template) == TEMPLATE_DECL, 279);
+ gcc_assert (TREE_CODE (template) == TEMPLATE_DECL);
/* Figure out which arguments are being used to do the
instantiation. */
for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t;
t = TREE_CHAIN (t))
{
- if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
- args))
+ if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args))
{
cp_error_at ("%s %+#T", str, TREE_TYPE (t));
str = " ";
it now. */
push_deferring_access_checks (dk_no_deferred);
- maybe_push_to_top_level (uses_template_parms (type));
+ push_to_top_level ();
if (t)
{
args = inner_args;
}
- if (flag_external_templates)
- {
- if (flag_alt_external_templates)
- {
- CLASSTYPE_INTERFACE_ONLY (type) = interface_only;
- SET_CLASSTYPE_INTERFACE_UNKNOWN_X (type, interface_unknown);
- }
- else
- {
- CLASSTYPE_INTERFACE_ONLY (type) = CLASSTYPE_INTERFACE_ONLY (pattern);
- SET_CLASSTYPE_INTERFACE_UNKNOWN_X
- (type, CLASSTYPE_INTERFACE_UNKNOWN (pattern));
- }
- }
- else
- {
- SET_CLASSTYPE_INTERFACE_UNKNOWN (type);
- }
+ SET_CLASSTYPE_INTERFACE_UNKNOWN (type);
+
+ /* Set the input location to the template definition. This is needed
+ if tsubsting causes an error. */
+ input_location = DECL_SOURCE_LOCATION (TYPE_NAME (pattern));
TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern);
TYPE_HAS_DESTRUCTOR (type) = TYPE_HAS_DESTRUCTOR (pattern);
- TYPE_OVERLOADS_CALL_EXPR (type) = TYPE_OVERLOADS_CALL_EXPR (pattern);
- TYPE_OVERLOADS_ARRAY_REF (type) = TYPE_OVERLOADS_ARRAY_REF (pattern);
- TYPE_OVERLOADS_ARROW (type) = TYPE_OVERLOADS_ARROW (pattern);
TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);
TYPE_HAS_ARRAY_NEW_OPERATOR (type) = TYPE_HAS_ARRAY_NEW_OPERATOR (pattern);
TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);
TYPE_HAS_ASSIGN_REF (type) = TYPE_HAS_ASSIGN_REF (pattern);
TYPE_HAS_CONST_ASSIGN_REF (type) = TYPE_HAS_CONST_ASSIGN_REF (pattern);
- TYPE_HAS_ABSTRACT_ASSIGN_REF (type) = TYPE_HAS_ABSTRACT_ASSIGN_REF (pattern);
TYPE_HAS_INIT_REF (type) = TYPE_HAS_INIT_REF (pattern);
TYPE_HAS_CONST_INIT_REF (type) = TYPE_HAS_CONST_INIT_REF (pattern);
TYPE_HAS_DEFAULT_CONSTRUCTOR (type) = TYPE_HAS_DEFAULT_CONSTRUCTOR (pattern);
SET_ANON_AGGR_TYPE_P (type);
pbinfo = TYPE_BINFO (pattern);
-
- if (BINFO_BASETYPES (pbinfo))
- {
- tree base_list = NULL_TREE;
- tree pbases = BINFO_BASETYPES (pbinfo);
- tree paccesses = BINFO_BASEACCESSES (pbinfo);
+
+ /* We should never instantiate a nested class before its enclosing
+ class; we need to look up the nested class by name before we can
+ instantiate it, and that lookup should instantiate the enclosing
+ class. */
+ gcc_assert (!DECL_CLASS_SCOPE_P (TYPE_MAIN_DECL (pattern))
+ || COMPLETE_TYPE_P (TYPE_CONTEXT (type))
+ || TYPE_BEING_DEFINED (TYPE_CONTEXT (type)));
+
+ base_list = NULL_TREE;
+ if (BINFO_N_BASE_BINFOS (pbinfo))
+ {
+ tree pbase_binfo;
+ tree context = TYPE_CONTEXT (type);
+ bool pop_p;
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);
+
/* Substitute into each of the bases to determine the actual
basetypes. */
- for (i = 0; i < TREE_VEC_LENGTH (pbases); ++i)
+ for (i = 0; BINFO_BASE_ITERATE (pbinfo, i, pbase_binfo); i++)
{
tree base;
- tree access;
- tree pbase;
-
- pbase = TREE_VEC_ELT (pbases, i);
- access = TREE_VEC_ELT (paccesses, i);
+ tree access = BINFO_BASE_ACCESS (pbinfo, i);
/* Substitute to figure out the base class. */
- base = tsubst (BINFO_TYPE (pbase), args, tf_error, NULL_TREE);
+ base = tsubst (BINFO_TYPE (pbase_binfo), args, tf_error, NULL_TREE);
if (base == error_mark_node)
continue;
base_list = tree_cons (access, base, base_list);
- TREE_VIA_VIRTUAL (base_list) = TREE_VIA_VIRTUAL (pbase);
+ 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);
- /* Now call xref_basetypes to set up all the base-class
- information. */
- xref_basetypes (type, base_list);
+ if (pop_p)
+ pop_scope (context ? context : global_namespace);
}
+ /* Now call xref_basetypes to set up all the base-class
+ information. */
+ xref_basetypes (type, base_list);
+
/* Now that our base classes are set up, enter the scope of the
class, so that name lookups into base classes, etc. will work
correctly. This is precisely analogous to what we do in
begin_class_definition when defining an ordinary non-template
class. */
- pushclass (type, true);
+ pushclass (type);
/* Now members are processed in the order of declaration. */
- for (member = CLASSTYPE_DECL_LIST (pattern); member; member = TREE_CHAIN (member))
+ for (member = CLASSTYPE_DECL_LIST (pattern);
+ member; member = TREE_CHAIN (member))
{
tree t = TREE_VALUE (member);
tree newtag;
newtag = tsubst (tag, args, tf_error, NULL_TREE);
- my_friendly_assert (newtag != error_mark_node, 20010206);
+ if (newtag == error_mark_node)
+ continue;
+
if (TREE_CODE (newtag) != ENUMERAL_TYPE)
{
if (TYPE_LANG_SPECIFIC (tag) && CLASSTYPE_IS_TEMPLATE (tag))
/* Unfortunately, lookup_template_class sets
CLASSTYPE_IMPLICIT_INSTANTIATION for a partial
- instantiation (i.e., for the type of a member template
- class nested within a template class.) This behavior is
- required for maybe_process_partial_specialization to work
- correctly, but is not accurate in this case; the TAG is not
- an instantiation of anything. (The corresponding
- TEMPLATE_DECL is an instantiation, but the TYPE is not.) */
+ instantiation (i.e., for the type of a member
+ template class nested within a template class.)
+ This behavior is required for
+ maybe_process_partial_specialization to work
+ correctly, but is not accurate in this case;
+ the TAG is not an instantiation of anything.
+ (The corresponding TEMPLATE_DECL is an
+ instantiation, but the TYPE is not.) */
CLASSTYPE_USE_TEMPLATE (newtag) = 0;
/* Now, we call pushtag to put this NEWTAG into the scope of
|| DECL_FUNCTION_TEMPLATE_P (t))
{
/* Build new TYPE_METHODS. */
-
- tree r = tsubst (t, args, tf_error, NULL_TREE);
+ tree r;
+
+ if (TREE_CODE (t) == TEMPLATE_DECL)
+ ++processing_template_decl;
+ r = tsubst (t, args, tf_error, NULL_TREE);
+ if (TREE_CODE (t) == TEMPLATE_DECL)
+ --processing_template_decl;
set_current_access_from_decl (r);
grok_special_member_properties (r);
finish_member_declaration (r);
restore these. */
input_location = DECL_SOURCE_LOCATION (t);
+ if (TREE_CODE (t) == TEMPLATE_DECL)
+ ++processing_template_decl;
r = tsubst (t, args, tf_error | tf_warning, NULL_TREE);
+ if (TREE_CODE (t) == TEMPLATE_DECL)
+ --processing_template_decl;
if (TREE_CODE (r) == VAR_DECL)
{
tree init;
else
init = NULL_TREE;
- finish_static_data_member_decl (r, init,
- /*asmspec_tree=*/NULL_TREE,
- /*flags=*/0);
+ finish_static_data_member_decl
+ (r, init, /*asmspec_tree=*/NULL_TREE, /*flags=*/0);
if (DECL_INITIALIZED_IN_CLASS_P (r))
check_static_variable_definition (r, TREE_TYPE (r));
++processing_template_decl;
if (new_friend_type != error_mark_node)
- make_friend_class (type, new_friend_type);
+ make_friend_class (type, new_friend_type,
+ /*complain=*/false);
if (TREE_CODE (friend_type) == TEMPLATE_DECL)
--processing_template_decl;
}
else
- /* Build new DECL_FRIENDLIST. */
- add_friend (type, tsubst_friend_function (t, args));
+ {
+ /* Build new DECL_FRIENDLIST. */
+ tree r;
+
+ 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)
+ {
+ pop_deferring_access_checks ();
+ --processing_template_decl;
+ }
+ }
}
}
that would be used for non-template classes. */
typedecl = TYPE_MAIN_DECL (type);
input_location = DECL_SOURCE_LOCATION (typedecl);
-
+
unreverse_member_declarations (type);
finish_struct_1 (type);
- CLASSTYPE_GOT_SEMICOLON (type) = 1;
-
- /* Clear this now so repo_template_used is happy. */
TYPE_BEING_DEFINED (type) = 0;
- repo_template_used (type);
/* Now that the class is complete, instantiate default arguments for
any member functions. We don't do this earlier because the
pop_deferring_access_checks ();
pop_tinst_level ();
- if (TYPE_CONTAINS_VPTR_P (type))
+ /* The vtable for a template class can be emitted in any translation
+ unit in which the class is instantiated. When there is no key
+ method, however, finish_struct_1 will already have added TYPE to
+ the keyed_classes list. */
+ if (TYPE_CONTAINS_VPTR_P (type) && CLASSTYPE_KEY_METHOD (type))
keyed_classes = tree_cons (NULL_TREE, type, keyed_classes);
return type;
}
-static int
-list_eq (tree t1, tree t2)
-{
- if (t1 == NULL_TREE)
- return t2 == NULL_TREE;
- if (t2 == NULL_TREE)
- return 0;
- /* Don't care if one declares its arg const and the other doesn't -- the
- main variant of the arg type is all that matters. */
- if (TYPE_MAIN_VARIANT (TREE_VALUE (t1))
- != TYPE_MAIN_VARIANT (TREE_VALUE (t2)))
- return 0;
- return list_eq (TREE_CHAIN (t1), TREE_CHAIN (t2));
-}
-
-/* If arg is a non-type template parameter that does not depend on template
- arguments, fold it like we weren't in the body of a template. */
-
static tree
-maybe_fold_nontype_arg (tree arg)
+tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
- if (arg && !TYPE_P (arg) && !uses_template_parms (arg))
+ tree r;
+
+ if (!t)
+ r = t;
+ else if (TYPE_P (t))
+ r = tsubst (t, args, complain, in_decl);
+ else
{
- /* Sometimes, one of the args was an expression involving a
- template constant parameter, like N - 1. Now that we've
- tsubst'd, we might have something like 2 - 1. This will
- confuse lookup_template_class, so we do constant folding
- here. We have to unset processing_template_decl, to fool
- tsubst_copy_and_build() into building an actual tree. */
+ r = tsubst_expr (t, args, complain, in_decl);
- /* If the TREE_TYPE of ARG is not NULL_TREE, ARG is already
- as simple as it's going to get, and trying to reprocess
- the trees will break. */
- if (!TREE_TYPE (arg))
+ if (!uses_template_parms (r))
{
- int saved_processing_template_decl = processing_template_decl;
- processing_template_decl = 0;
- arg = tsubst_copy_and_build (arg,
- /*args=*/NULL_TREE,
- tf_error,
- /*in_decl=*/NULL_TREE);
- processing_template_decl = saved_processing_template_decl;
- }
+ /* Sometimes, one of the args was an expression involving a
+ template constant parameter, like N - 1. Now that we've
+ tsubst'd, we might have something like 2 - 1. This will
+ confuse lookup_template_class, so we do constant folding
+ here. We have to unset processing_template_decl, to fool
+ tsubst_copy_and_build() into building an actual tree. */
- arg = fold (arg);
- }
- return arg;
-}
-
-/* Apply maybe_fold_nontype_arg on a list or vector of args. */
-
-static void
-maybe_fold_nontype_args (tree targs)
-{
- if (!targs)
- /*OK*/;
- else if (TREE_CODE (targs) == TREE_LIST)
- {
- tree chain;
- for (chain = targs; chain; chain = TREE_CHAIN (chain))
- TREE_VALUE (chain) = maybe_fold_nontype_arg (TREE_VALUE (chain));
- }
- else
- {
- int i;
- for (i = 0; i < TREE_VEC_LENGTH (targs); ++i)
- TREE_VEC_ELT (targs, i)
- = maybe_fold_nontype_arg (TREE_VEC_ELT (targs, i));
+ /* If the TREE_TYPE of ARG is not NULL_TREE, ARG is already
+ as simple as it's going to get, and trying to reprocess
+ the trees will break. Once tsubst_expr et al DTRT for
+ non-dependent exprs, this code can go away, as the type
+ will always be set. */
+ if (!TREE_TYPE (r))
+ {
+ 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;
+ }
+ r = fold (r);
+ }
}
+ return r;
}
-/* Substitute ARGS into the vector of template arguments T. */
+/* Substitute ARGS into the vector or list of template arguments T. */
static tree
-tsubst_template_arg_vector (tree t, tree args, tsubst_flags_t complain)
+tsubst_template_args (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
- int len = TREE_VEC_LENGTH (t), need_new = 0, i;
- tree *elts = (tree *) alloca (len * sizeof (tree));
-
- memset ((char *) elts, 0, len * sizeof (tree));
+ int len = TREE_VEC_LENGTH (t);
+ int need_new = 0, i;
+ tree *elts = alloca (len * sizeof (tree));
for (i = 0; i < len; i++)
{
- if (TREE_VEC_ELT (t, i) != NULL_TREE
- && TREE_CODE (TREE_VEC_ELT (t, i)) == TREE_VEC)
- elts[i] = tsubst_template_arg_vector (TREE_VEC_ELT (t, i),
- args, complain);
+ tree orig_arg = TREE_VEC_ELT (t, i);
+ tree new_arg;
+
+ if (TREE_CODE (orig_arg) == TREE_VEC)
+ new_arg = tsubst_template_args (orig_arg, args, complain, in_decl);
else
- elts[i] = maybe_fold_nontype_arg
- (tsubst_expr (TREE_VEC_ELT (t, i), args, complain,
- NULL_TREE));
+ new_arg = tsubst_template_arg (orig_arg, args, complain, in_decl);
- if (elts[i] == error_mark_node)
+ if (new_arg == error_mark_node)
return error_mark_node;
- if (elts[i] != TREE_VEC_ELT (t, i))
+ elts[i] = new_arg;
+ 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];
tree parm_decl = TREE_VALUE (tuple);
parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
- default_value = tsubst_expr (default_value, args,
- complain, NULL_TREE);
- tuple = build_tree_list (maybe_fold_nontype_arg (default_value),
- parm_decl);
+ 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;
}
if (TYPE_PTRMEMFUNC_P (t))
return tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, complain, in_decl);
- /* else fall through */
+ /* Else fall through. */
case ENUMERAL_TYPE:
case UNION_TYPE:
if (TYPE_TEMPLATE_INFO (t))
/* First, determine the context for the type we are looking
up. */
- if (TYPE_CONTEXT (t) != NULL_TREE)
- context = tsubst_aggr_type (TYPE_CONTEXT (t), args,
- complain,
+ context = TYPE_CONTEXT (t);
+ if (context)
+ context = tsubst_aggr_type (context, args, complain,
in_decl, /*entering_scope=*/1);
- else
- context = NULL_TREE;
/* Then, figure out what arguments are appropriate for the
type we are trying to find. For example, given:
and supposing that we are instantiating f<int, double>,
then our ARGS will be {int, double}, but, when looking up
S we only want {double}. */
- argvec = tsubst_template_arg_vector (TYPE_TI_ARGS (t), args,
- complain);
+ argvec = tsubst_template_args (TYPE_TI_ARGS (t), args,
+ complain, in_decl);
if (argvec == error_mark_node)
return error_mark_node;
tree
tsubst_default_argument (tree fn, tree type, tree arg)
{
+ tree saved_class_ptr = NULL_TREE;
+ tree saved_class_ref = NULL_TREE;
+
/* This default argument came from a template. Instantiate the
default argument here, not in tsubst. In the case of
something like:
};
we must be careful to do name lookup in the scope of S<T>,
- rather than in the current class.
-
- ??? current_class_type affects a lot more than name lookup. This is
- very fragile. Fortunately, it will go away when we do 2-phase name
- binding properly. */
-
- /* FN is already the desired FUNCTION_DECL. */
+ rather than in the current class. */
push_access_scope (fn);
+ /* The default argument expression should not be considered to be
+ within the scope of FN. Since push_access_scope sets
+ current_function_decl, we must explicitly clear it here. */
+ current_function_decl = NULL_TREE;
+ /* The "this" pointer is not valid in a default argument. */
+ if (cfun)
+ {
+ saved_class_ptr = current_class_ptr;
+ cp_function_chain->x_current_class_ptr = NULL_TREE;
+ saved_class_ref = current_class_ref;
+ cp_function_chain->x_current_class_ref = NULL_TREE;
+ }
+ push_deferring_access_checks(dk_no_deferred);
arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
tf_error | tf_warning, NULL_TREE);
-
+ pop_deferring_access_checks();
+
+ /* Restore the "this" pointer. */
+ if (cfun)
+ {
+ cp_function_chain->x_current_class_ptr = saved_class_ptr;
+ cp_function_chain->x_current_class_ref = saved_class_ref;
+ }
+
pop_access_scope (fn);
/* Make sure the default argument is reasonable. */
: DECL_TI_ARGS (DECL_TEMPLATE_RESULT (t));
tree full_args;
- full_args = tsubst_template_arg_vector (tmpl_args, args,
- complain);
+ full_args = tsubst_template_args (tmpl_args, args,
+ complain, in_decl);
- /* tsubst_template_arg_vector doesn't copy the vector if
+ /* tsubst_template_args doesn't copy the vector if
nothing changed. But, *something* should have
changed. */
- my_friendly_assert (full_args != tmpl_args, 0);
+ gcc_assert (full_args != tmpl_args);
spec = retrieve_specialization (t, full_args);
if (spec != NULL_TREE)
like the old one, but points to this new template, rather
than the old one. */
r = copy_decl (t);
- my_friendly_assert (DECL_LANG_SPECIFIC (r) != 0, 0);
+ gcc_assert (DECL_LANG_SPECIFIC (r) != 0);
TREE_CHAIN (r) = NULL_TREE;
if (is_template_template_parm)
if (TREE_CODE (decl) == TYPE_DECL)
{
tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ if (new_type == error_mark_node)
+ return error_mark_node;
+
TREE_TYPE (r) = new_type;
CLASSTYPE_TI_TEMPLATE (new_type) = r;
DECL_TEMPLATE_RESULT (r) = TYPE_MAIN_DECL (new_type);
else
{
tree new_decl = tsubst (decl, args, complain, in_decl);
+ if (new_decl == error_mark_node)
+ return error_mark_node;
DECL_TEMPLATE_RESULT (r) = new_decl;
DECL_TI_TEMPLATE (new_decl) = r;
if (PRIMARY_TEMPLATE_P (t))
DECL_PRIMARY_TEMPLATE (r) = r;
- /* We don't partially instantiate partial specializations. */
- if (TREE_CODE (decl) == TYPE_DECL)
- break;
-
- /* Record this partial instantiation. */
- register_specialization (r, t,
- DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)));
-
+ if (TREE_CODE (decl) != TYPE_DECL)
+ /* Record this non-type partial instantiation. */
+ register_specialization (r, t,
+ DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)));
}
break;
int parms_depth;
/* Nobody should be tsubst'ing into non-template functions. */
- my_friendly_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE, 0);
+ gcc_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE);
if (TREE_CODE (DECL_TI_TEMPLATE (t)) == TEMPLATE_DECL)
{
specialization, and the complete set of arguments used to
specialize R. */
gen_tmpl = most_general_template (DECL_TI_TEMPLATE (t));
- argvec
- = tsubst_template_arg_vector (DECL_TI_ARGS
- (DECL_TEMPLATE_RESULT (gen_tmpl)),
- args, complain);
+ argvec = tsubst_template_args (DECL_TI_ARGS
+ (DECL_TEMPLATE_RESULT (gen_tmpl)),
+ args, complain, in_decl);
/* Check to see if we already have this specialization. */
spec = retrieve_specialization (gen_tmpl, argvec);
};
Here, the DECL_TI_TEMPLATE for the friend declaration
- will be a LOOKUP_EXPR or an IDENTIFIER_NODE. We are
- being called from tsubst_friend_function, and we want
- only to create a new decl (R) with appropriate types so
- that we can call determine_specialization. */
+ will be an IDENTIFIER_NODE. We are being called from
+ tsubst_friend_function, and we want only to create a
+ new decl (R) with appropriate types so that we can call
+ determine_specialization. */
gen_tmpl = NULL_TREE;
}
else
member = 1;
ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
- complain, t,
- /*entering_scope=*/1);
+ complain, t, /*entering_scope=*/1);
}
else
{
/* Clear out the mangled name and RTL for the instantiation. */
SET_DECL_ASSEMBLER_NAME (r, NULL_TREE);
SET_DECL_RTL (r, NULL_RTX);
-
+ DECL_INITIAL (r) = NULL_TREE;
DECL_CONTEXT (r) = ctx;
if (member && DECL_CONV_FN_P (r))
TREE_STATIC (r) = 0;
TREE_PUBLIC (r) = TREE_PUBLIC (t);
DECL_EXTERNAL (r) = 1;
- DECL_INTERFACE_KNOWN (r) = 0;
+ /* If this is an instantiation of a function with internal
+ linkage, we already know what object file linkage will be
+ assigned to the instantiation. */
+ DECL_INTERFACE_KNOWN (r) = !TREE_PUBLIC (r);
DECL_DEFER_OUTPUT (r) = 0;
TREE_CHAIN (r) = NULL_TREE;
DECL_PENDING_INLINE_INFO (r) = 0;
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));
+ grok_op_properties (r, DECL_FRIEND_P (r),
+ (complain & tf_error) != 0);
+
+ if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
+ SET_DECL_FRIEND_CONTEXT (r,
+ tsubst (DECL_FRIEND_CONTEXT (t),
+ args, complain, in_decl));
}
break;
TREE_TYPE (r) = type;
c_apply_type_quals_to_decl (cp_type_quals (type), r);
- if (TREE_CODE (DECL_INITIAL (r)) != TEMPLATE_PARM_INDEX)
- DECL_INITIAL (r) = TREE_TYPE (r);
- else
- DECL_INITIAL (r) = tsubst (DECL_INITIAL (r), args,
- complain, in_decl);
+ if (DECL_INITIAL (r))
+ {
+ if (TREE_CODE (DECL_INITIAL (r)) != TEMPLATE_PARM_INDEX)
+ DECL_INITIAL (r) = TREE_TYPE (r);
+ else
+ DECL_INITIAL (r) = tsubst (DECL_INITIAL (r), args,
+ complain, in_decl);
+ }
DECL_CONTEXT (r) = NULL_TREE;
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;
}
break;
r = copy_decl (t);
if (TREE_CODE (r) == VAR_DECL)
- type = complete_type (type);
+ {
+ type = complete_type (type);
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)
+ = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t);
+ }
+ 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);
DECL_CONTEXT (r) = ctx;
break;
default:
- abort ();
+ gcc_unreachable ();
}
/* Restore the file and line information. */
tree fntype;
/* The TYPE_CONTEXT is not used for function/method types. */
- my_friendly_assert (TYPE_CONTEXT (t) == NULL_TREE, 0);
+ gcc_assert (TYPE_CONTEXT (t) == NULL_TREE);
/* Substitute the return type. */
return_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
return error_mark_node;
}
- fntype = build_cplus_method_type (r, return_type, TREE_CHAIN
- (arg_types));
+ fntype = build_method_type_directly (r, return_type,
+ TREE_CHAIN (arg_types));
}
fntype = cp_build_qualified_type_real (fntype, TYPE_QUALS (t), complain);
- fntype = build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
+ fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
return fntype;
}
doesn't check TREE_PARMLIST. */
new_parms = tree_cons (defarg, type, new_parms);
- /* And note that these are parameters. */
- TREE_PARMLIST (new_parms) = 1;
-
return new_parms;
}
|| t == integer_type_node
|| t == void_type_node
|| t == char_type_node
+ || t == unknown_type_node
|| TREE_CODE (t) == NAMESPACE_DECL)
return t;
type = IDENTIFIER_TYPE_VALUE (t);
else
type = TREE_TYPE (t);
- if (type == unknown_type_node)
- abort ();
+
+ gcc_assert (type != unknown_type_node);
if (type && TREE_CODE (t) != FUNCTION_DECL
&& TREE_CODE (t) != TYPENAME_TYPE
{
tree max, omax = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
- max = tsubst_expr (omax, args, complain, in_decl);
- if (max == error_mark_node)
- return error_mark_node;
-
- /* See if we can reduce this expression to something simpler. */
- max = maybe_fold_nontype_arg (max);
+ /* 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);
- if (processing_template_decl
- /* When providing explicit arguments to a template
- function, but leaving some arguments for subsequent
- deduction, MAX may be template-dependent even if we're
- not PROCESSING_TEMPLATE_DECL. We still need to check for
- template parms, though; MAX won't be an INTEGER_CST for
- dynamic arrays, either. */
- || (TREE_CODE (max) != INTEGER_CST
- && uses_template_parms (max)))
- {
- tree itype = make_node (INTEGER_TYPE);
- TYPE_MIN_VALUE (itype) = size_zero_node;
- TYPE_MAX_VALUE (itype) = build_min (MINUS_EXPR, sizetype, max,
- integer_one_node);
- return itype;
- }
-
if (integer_zerop (omax))
{
/* Still allow an explicit array of size zero. */
int idx;
int level;
int levels;
+ tree arg = NULL_TREE;
r = NULL_TREE;
+ gcc_assert (TREE_VEC_LENGTH (args) > 0);
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
|| TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
level = TEMPLATE_PARM_LEVEL (t);
}
- if (TREE_VEC_LENGTH (args) > 0)
- {
- tree arg = NULL_TREE;
-
- levels = TMPL_ARGS_DEPTH (args);
- if (level <= levels)
- arg = TMPL_ARG (args, level, idx);
+ levels = TMPL_ARGS_DEPTH (args);
+ if (level <= levels)
+ arg = TMPL_ARG (args, level, idx);
- if (arg == error_mark_node)
- return error_mark_node;
- else if (arg != NULL_TREE)
+ if (arg == error_mark_node)
+ return error_mark_node;
+ else if (arg != NULL_TREE)
+ {
+ if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
{
- if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
- {
- my_friendly_assert (TYPE_P (arg), 0);
- return cp_build_qualified_type_real
- (arg, cp_type_quals (arg) | cp_type_quals (t),
- complain | tf_ignore_bad_quals);
- }
- else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
- {
- /* We are processing a type constructed from
- a template template parameter */
- tree argvec = tsubst (TYPE_TI_ARGS (t),
- args, complain, in_decl);
- if (argvec == error_mark_node)
- return error_mark_node;
+ gcc_assert (TYPE_P (arg));
+ return cp_build_qualified_type_real
+ (arg, cp_type_quals (arg) | cp_type_quals (t),
+ complain | tf_ignore_bad_quals);
+ }
+ else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
+ {
+ /* We are processing a type constructed from a
+ template template parameter. */
+ tree argvec = tsubst (TYPE_TI_ARGS (t),
+ args, complain, in_decl);
+ if (argvec == error_mark_node)
+ return error_mark_node;
- /* We can get a TEMPLATE_TEMPLATE_PARM here when
- we are resolving nested-types in the signature of
- a member function templates.
- Otherwise ARG is a TEMPLATE_DECL and is the real
- template to be instantiated. */
- if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
- arg = TYPE_NAME (arg);
-
- r = lookup_template_class (arg,
- argvec, in_decl,
- DECL_CONTEXT (arg),
- /*entering_scope=*/0,
- complain);
- return cp_build_qualified_type_real
- (r, TYPE_QUALS (t), complain);
- }
- else
- /* TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX. */
- return arg;
+ /* We can get a TEMPLATE_TEMPLATE_PARM here when we
+ are resolving nested-types in the signature of a
+ member function templates. Otherwise ARG is a
+ TEMPLATE_DECL and is the real template to be
+ instantiated. */
+ if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+ arg = TYPE_NAME (arg);
+
+ r = lookup_template_class (arg,
+ argvec, in_decl,
+ DECL_CONTEXT (arg),
+ /*entering_scope=*/0,
+ complain);
+ return cp_build_qualified_type_real
+ (r, TYPE_QUALS (t), complain);
}
+ else
+ /* TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX. */
+ return arg;
}
- else
- abort ();
if (level == 1)
/* This can happen during the attempted tsubst'ing in
break;
default:
- abort ();
+ gcc_unreachable ();
}
return r;
case TREE_LIST:
{
- tree purpose, value, chain, result;
+ tree purpose, value, chain;
if (t == void_list_node)
return t;
&& value == TREE_VALUE (t)
&& chain == TREE_CHAIN (t))
return t;
- if (TREE_PARMLIST (t))
- {
- result = tree_cons (purpose, value, chain);
- TREE_PARMLIST (result) = 1;
- }
- else
- result = hash_tree_cons (purpose, value, chain);
- return result;
+ return hash_tree_cons (purpose, value, chain);
}
- case TREE_VEC:
- if (type != NULL_TREE)
- {
- /* A binfo node. We always need to make a copy, of the node
- itself and of its BINFO_BASETYPES. */
-
- t = copy_node (t);
-
- /* Make sure type isn't a typedef copy. */
- type = BINFO_TYPE (TYPE_BINFO (type));
-
- TREE_TYPE (t) = complete_type (type);
- if (IS_AGGR_TYPE (type))
- {
- BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (type);
- BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (type);
- if (TYPE_BINFO_BASETYPES (type) != NULL_TREE)
- BINFO_BASETYPES (t) = copy_node (TYPE_BINFO_BASETYPES (type));
- }
- return t;
- }
+
+ case TREE_BINFO:
+ /* We should never be tsubsting a binfo. */
+ gcc_unreachable ();
- /* Otherwise, a vector of template arguments. */
- return tsubst_template_arg_vector (t, args, complain);
+ case TREE_VEC:
+ /* A vector of template arguments. */
+ gcc_assert (!type);
+ return tsubst_template_args (t, args, complain, in_decl);
case POINTER_TYPE:
case REFERENCE_TYPE:
message to avoid spewing a ton of messages during a
single bad template instantiation. */
if (complain & tf_error
+#ifdef USE_MAPPED_LOCATION
+ && last_loc != input_location)
+#else
&& (last_loc.line != input_line
|| last_loc.file != input_filename))
+#endif
{
if (TREE_CODE (type) == VOID_TYPE)
error ("forming reference to void");
return error_mark_node;
}
- my_friendly_assert (TREE_CODE (type) != METHOD_TYPE, 20011231);
+ gcc_assert (TREE_CODE (type) != METHOD_TYPE);
if (TREE_CODE (type) == FUNCTION_TYPE)
- /* This is really a method type. The cv qualifiers of the
- this pointer should _not_ be determined by the cv
- qualifiers of the class type. They should be held
- somewhere in the FUNCTION_TYPE, but we don't do that at
- the moment. Consider
- typedef void (Func) () const;
-
- template <typename T1> void Foo (Func T1::*);
-
- */
- return build_cplus_method_type (TYPE_MAIN_VARIANT (r),
- TREE_TYPE (type),
- TYPE_ARG_TYPES (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::*);
+
+ */
+ tree method_type;
+
+ method_type = build_method_type_directly (TYPE_MAIN_VARIANT (r),
+ TREE_TYPE (type),
+ TYPE_ARG_TYPES (type));
+ return build_ptrmemfunc_type (build_pointer_type (method_type));
+ }
else
- return build_offset_type (r, type);
+ return cp_build_qualified_type_real (build_ptrmem_type (r, type),
+ TYPE_QUALS (t),
+ complain);
}
case FUNCTION_TYPE:
case METHOD_TYPE:
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. */
+ is void, a function type, or a reference type, or [DR337]
+ an abstract class type. */
if (TREE_CODE (type) == VOID_TYPE
|| TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == REFERENCE_TYPE)
error ("creating array of `%T'", type);
return error_mark_node;
}
+ if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type))
+ {
+ if (complain & tf_error)
+ error ("creating array of `%T', which is an abstract class type",
+ type);
+ return error_mark_node;
+ }
r = build_cplus_array_type (type, domain);
return r;
if (e1 == error_mark_node || e2 == error_mark_node)
return error_mark_node;
- return fold (build (TREE_CODE (t), TREE_TYPE (t), e1, e2));
+ return fold (build2 (TREE_CODE (t), TREE_TYPE (t), e1, e2));
}
case NEGATE_EXPR:
if (e == error_mark_node)
return error_mark_node;
- return fold (build (TREE_CODE (t), TREE_TYPE (t), e));
+ return fold (build1 (TREE_CODE (t), TREE_TYPE (t), e));
}
case TYPENAME_TYPE:
}
case INDIRECT_REF:
- {
- tree e = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
- if (e == error_mark_node)
- return error_mark_node;
- return make_pointer_declarator (type, e);
- }
-
case ADDR_EXPR:
- {
- tree e = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
- if (e == error_mark_node)
- return error_mark_node;
- return make_reference_declarator (type, e);
- }
+ case CALL_EXPR:
+ gcc_unreachable ();
case ARRAY_REF:
{
if (e1 == error_mark_node || e2 == error_mark_node)
return error_mark_node;
- return build_nt (ARRAY_REF, e1, e2, tsubst_expr);
- }
-
- case CALL_EXPR:
- {
- tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
- tree e2 = (tsubst_call_declarator_parms
- (CALL_DECLARATOR_PARMS (t), args, complain, in_decl));
- tree e3 = tsubst (CALL_DECLARATOR_EXCEPTION_SPEC (t), args,
- complain, in_decl);
-
- if (e1 == error_mark_node || e2 == error_mark_node
- || e3 == error_mark_node)
- return error_mark_node;
-
- return make_call_declarator (e1, e2, CALL_DECLARATOR_QUALS (t), e3);
+ return build_nt (ARRAY_REF, e1, e2, NULL_TREE, NULL_TREE);
}
case SCOPE_REF:
case TYPEOF_TYPE:
{
- tree e1 = tsubst_expr (TYPE_FIELDS (t), args, complain, in_decl);
- if (e1 == error_mark_node)
- return error_mark_node;
+ tree type;
- return cp_build_qualified_type_real (TREE_TYPE (e1),
+ type = finish_typeof (tsubst_expr (TYPEOF_TYPE_EXPR (t), args,
+ complain, in_decl));
+ return cp_build_qualified_type_real (type,
cp_type_quals (t)
- | cp_type_quals (TREE_TYPE (e1)),
+ | cp_type_quals (type),
complain);
}
class, rather than the instantiated class.
In addition, lookups that were not ambiguous before may be
- ambiguous now. Therefore, we perform the lookup again. */
+ ambiguous now. Therefore, we perform the lookup again. */
qualifying_scope = BINFO_TYPE (BASELINK_ACCESS_BINFO (baselink));
fns = BASELINK_FUNCTIONS (baselink);
if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
template_id_p = true;
template_args = TREE_OPERAND (fns, 1);
fns = TREE_OPERAND (fns, 0);
- template_args = tsubst_copy_and_build (template_args, args,
- complain, in_decl);
+ if (template_args)
+ template_args = tsubst_template_args (template_args, args,
+ complain, in_decl);
}
name = DECL_NAME (get_first_fn (fns));
baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
bool is_template;
tree template_args;
- my_friendly_assert (TREE_CODE (qualified_id) == SCOPE_REF, 20030706);
+ gcc_assert (TREE_CODE (qualified_id) == SCOPE_REF);
/* Figure out what name to look up. */
name = TREE_OPERAND (qualified_id, 1);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
is_template = true;
- template_args = tsubst_copy_and_build (TREE_OPERAND (name, 1),
- args, complain, in_decl);
+ template_args = TREE_OPERAND (name, 1);
+ if (template_args)
+ template_args = tsubst_template_args (template_args, args,
+ complain, in_decl);
name = TREE_OPERAND (name, 0);
}
else
}
else
expr = name;
- if (!BASELINK_P (name)
- && !DECL_P (expr))
- expr = lookup_qualified_name (scope, expr, /*is_type_p=*/0);
- if (DECL_P (expr))
- check_accessibility_of_qualified_id (expr,
- /*object_type=*/NULL_TREE,
- scope);
+
+ 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);
+ if (TREE_CODE (TREE_CODE (expr) == TEMPLATE_DECL
+ ? DECL_TEMPLATE_RESULT (expr) : expr) == TYPE_DECL)
+ {
+ if (complain & tf_error)
+ {
+ error ("dependent-name `%E' is parsed as a non-type, but "
+ "instantiation yields a type", qualified_id);
+ inform ("say `typename %E' if a type is meant", qualified_id);
+ }
+ return error_mark_node;
+ }
+ }
- /* Remember that there was a reference to this entity. */
if (DECL_P (expr))
{
+ check_accessibility_of_qualified_id (expr, /*object_type=*/NULL_TREE,
+ scope);
+ /* Remember that there was a reference to this entity. */
mark_used (expr);
- if (!args && TREE_CODE (expr) == VAR_DECL)
- expr = DECL_INITIAL (expr);
+ }
+
+ if (expr == error_mark_node || TREE_CODE (expr) == TREE_LIST)
+ {
+ if (complain & tf_error)
+ qualified_name_lookup_error (scope,
+ TREE_OPERAND (qualified_id, 1),
+ expr);
+ return error_mark_node;
}
if (is_template)
- lookup_template_function (expr, template_args);
+ expr = lookup_template_function (expr, template_args);
- if (TYPE_P (scope))
+ if (expr == error_mark_node && complain & tf_error)
+ qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1),
+ expr);
+ else if (TYPE_P (scope))
{
expr = (adjust_result_of_qualified_name_lookup
(expr, scope, current_class_type));
{
case PARM_DECL:
r = retrieve_local_specialization (t);
- my_friendly_assert (r != NULL, 20020903);
+ gcc_assert (r != NULL);
+ mark_used (r);
return r;
case CONST_DECL:
if (DECL_TEMPLATE_PARM_P (t))
return tsubst_copy (DECL_INITIAL (t), args, complain, in_decl);
- if (!DECL_CONTEXT (t))
- /* This is a global enumeration constant. */
+ /* There is no need to substitute into namespace-scope
+ enumerators. */
+ if (DECL_NAMESPACE_SCOPE_P (t))
return t;
+ /* If ARGS is NULL, then T is known to be non-dependent. */
+ if (args == NULL_TREE)
+ return decl_constant_value (t);
/* Unfortunately, we cannot just call lookup_name here.
Consider:
/* We didn't find the name. That should never happen; if
name-lookup found it during preliminary parsing, we
should find it again here during instantiation. */
- abort ();
+ gcc_unreachable ();
}
return t;
if (ctx != DECL_CONTEXT (t))
return lookup_field (ctx, DECL_NAME (t), 0, false);
}
+
return t;
case VAR_DECL:
/* Ordinary template template argument. */
return t;
- case LOOKUP_EXPR:
- {
- /* We must tsubst into a LOOKUP_EXPR in case the names to
- which it refers is a conversion operator; in that case the
- name will change. We avoid making unnecessary copies,
- however. */
-
- tree id = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
-
- if (id != TREE_OPERAND (t, 0))
- {
- r = build_nt (LOOKUP_EXPR, id);
- LOOKUP_EXPR_GLOBAL (r) = LOOKUP_EXPR_GLOBAL (t);
- t = r;
- }
-
- return t;
- }
-
case CAST_EXPR:
case REINTERPRET_CAST_EXPR:
case CONST_CAST_EXPR:
in_decl);
else
name = tsubst_copy (name, args, complain, in_decl);
- return build_nt (COMPONENT_REF, object, name);
+ return build_nt (COMPONENT_REF, object, name, NULL_TREE);
}
case PLUS_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
case BIT_AND_EXPR:
- case BIT_ANDTC_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
case TRUNC_MOD_EXPR:
in_decl),
NULL_TREE);
- case STMT_EXPR:
- /* This processing should really occur in tsubst_expr. However,
- tsubst_expr does not recurse into expressions, since it
- assumes that there aren't any statements inside them. So, we
- need to expand the STMT_EXPR here. */
- if (!processing_template_decl)
- {
- tree stmt_expr = begin_stmt_expr ();
- tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl);
- return finish_stmt_expr (stmt_expr);
- }
-
- return t;
-
case COND_EXPR:
case MODOP_EXPR:
case PSEUDO_DTOR_EXPR:
(code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl));
+ TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
return r;
}
case TEMPLATE_ID_EXPR:
{
/* Substituted template arguments */
- tree targs = tsubst_copy (TREE_OPERAND (t, 1), args, complain,
- in_decl);
+ tree fn = TREE_OPERAND (t, 0);
+ tree targs = TREE_OPERAND (t, 1);
- maybe_fold_nontype_args (targs);
- return lookup_template_function
- (tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl), targs);
+ 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 TREE_LIST:
in_decl),
tsubst (TREE_TYPE (t), args, complain, in_decl));
+ case CLEANUP_POINT_EXPR:
+ /* We shouldn't have built any of these during initial template
+ generation. Instead, they should be built during instantiation
+ in response to the saved STMT_IS_FULL_EXPR_P setting. */
+ gcc_unreachable ();
+
default:
return t;
}
static tree
tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
+ /* Live only within one (recursive) call to tsubst_expr. We use
+ this to pass the statement expression node from the STMT_EXPR
+ to the EXPR_STMT that is its result. */
+ static tree cur_stmt_expr;
+
tree stmt, tmp;
if (t == NULL_TREE || t == error_mark_node)
return t;
- if (processing_template_decl)
- return tsubst_copy (t, args, complain, in_decl);
+ if (EXPR_HAS_LOCATION (t))
+ input_location = EXPR_LOCATION (t);
+ if (STATEMENT_CODE_P (TREE_CODE (t)))
+ current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
- if (!STATEMENT_CODE_P (TREE_CODE (t)))
- return tsubst_copy_and_build (t, args, complain, in_decl);
-
switch (TREE_CODE (t))
{
+ case STATEMENT_LIST:
+ {
+ tree_stmt_iterator i;
+ for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
+ tsubst_expr (tsi_stmt (i), args, complain, in_decl);
+ break;
+ }
+
case CTOR_INITIALIZER:
- prep_stmt (t);
finish_mem_initializers (tsubst_initializer_list
(TREE_OPERAND (t, 0), args));
break;
- case RETURN_STMT:
- prep_stmt (t);
- finish_return_stmt (tsubst_expr (RETURN_STMT_EXPR (t),
+ case RETURN_EXPR:
+ finish_return_stmt (tsubst_expr (TREE_OPERAND (t, 0),
args, complain, in_decl));
break;
+ case STMT_EXPR:
+ {
+ tree old_stmt_expr = cur_stmt_expr;
+ tree stmt_expr = begin_stmt_expr ();
+
+ cur_stmt_expr = stmt_expr;
+ tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl);
+ stmt_expr = finish_stmt_expr (stmt_expr, false);
+ cur_stmt_expr = old_stmt_expr;
+
+ return stmt_expr;
+ }
+
case EXPR_STMT:
- prep_stmt (t);
- finish_expr_stmt (tsubst_expr (EXPR_STMT_EXPR (t),
- args, complain, in_decl));
+ tmp = tsubst_expr (EXPR_STMT_EXPR (t), args, complain, in_decl);
+ if (EXPR_STMT_STMT_EXPR_RESULT (t))
+ finish_stmt_expr_expr (tmp, cur_stmt_expr);
+ else
+ finish_expr_stmt (tmp);
break;
case USING_STMT:
- prep_stmt (t);
do_using_directive (tsubst_expr (USING_STMT_NAMESPACE (t),
args, complain, in_decl));
break;
- case DECL_STMT:
+ case DECL_EXPR:
{
tree decl;
tree init;
- prep_stmt (t);
- decl = DECL_STMT_DECL (t);
+ decl = DECL_EXPR_DECL (t);
if (TREE_CODE (decl) == LABEL_DECL)
finish_label_decl (DECL_NAME (decl));
else if (TREE_CODE (decl) == USING_DECL)
{
tree scope = DECL_INITIAL (decl);
tree name = DECL_NAME (decl);
+ tree decl;
scope = tsubst_expr (scope, args, complain, in_decl);
- do_local_using_decl (lookup_qualified_name (scope,
- name,
- /*is_type_p=*/0));
+ decl = lookup_qualified_name (scope, name,
+ /*is_type_p=*/false,
+ /*complain=*/false);
+ if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
+ qualified_name_lookup_error (scope, name, decl);
+ else
+ do_local_using_decl (decl, scope, name);
}
else
{
else
{
maybe_push_decl (decl);
- if (DECL_PRETTY_FUNCTION_P (decl))
+ if (TREE_CODE (decl) == VAR_DECL
+ && DECL_PRETTY_FUNCTION_P (decl))
{
/* For __PRETTY_FUNCTION__ we have to adjust the
initializer. */
const char *const name
= cxx_printable_name (current_function_decl, 2);
- init = cp_fname_init (name);
- TREE_TYPE (decl) = TREE_TYPE (init);
+ init = cp_fname_init (name, &TREE_TYPE (decl));
}
else
init = tsubst_expr (init, args, complain, in_decl);
}
}
- /* A DECL_STMT can also be used as an expression, in the condition
- clause of an if/for/while construct. If we aren't followed by
- another statement, return our decl. */
- if (TREE_CHAIN (t) == NULL_TREE)
- return decl;
+ /* A DECL_EXPR can also be used as an expression, in the condition
+ clause of an if/for/while construct. */
+ return decl;
}
- break;
case FOR_STMT:
- {
- prep_stmt (t);
-
- stmt = begin_for_stmt ();
- tsubst_expr (FOR_INIT_STMT (t), args, complain, in_decl);
- finish_for_init_stmt (stmt);
- finish_for_cond (tsubst_expr (FOR_COND (t),
- args, complain, in_decl),
- stmt);
- tmp = tsubst_expr (FOR_EXPR (t), args, complain, in_decl);
- finish_for_expr (tmp, stmt);
- tsubst_expr (FOR_BODY (t), args, complain, in_decl);
- finish_for_stmt (stmt);
- }
+ stmt = begin_for_stmt ();
+ tsubst_expr (FOR_INIT_STMT (t), args, complain, in_decl);
+ finish_for_init_stmt (stmt);
+ tmp = tsubst_expr (FOR_COND (t), args, complain, in_decl);
+ finish_for_cond (tmp, stmt);
+ tmp = tsubst_expr (FOR_EXPR (t), args, complain, in_decl);
+ finish_for_expr (tmp, stmt);
+ tsubst_expr (FOR_BODY (t), args, complain, in_decl);
+ finish_for_stmt (stmt);
break;
case WHILE_STMT:
- {
- prep_stmt (t);
- stmt = begin_while_stmt ();
- finish_while_stmt_cond (tsubst_expr (WHILE_COND (t),
- args, complain, in_decl),
- stmt);
- tsubst_expr (WHILE_BODY (t), args, complain, in_decl);
- finish_while_stmt (stmt);
- }
+ stmt = begin_while_stmt ();
+ tmp = tsubst_expr (WHILE_COND (t), args, complain, in_decl);
+ finish_while_stmt_cond (tmp, stmt);
+ tsubst_expr (WHILE_BODY (t), args, complain, in_decl);
+ finish_while_stmt (stmt);
break;
case DO_STMT:
- {
- prep_stmt (t);
- stmt = begin_do_stmt ();
- tsubst_expr (DO_BODY (t), args, complain, in_decl);
- finish_do_body (stmt);
- finish_do_stmt (tsubst_expr (DO_COND (t),
- args, complain, in_decl),
- stmt);
- }
+ stmt = begin_do_stmt ();
+ tsubst_expr (DO_BODY (t), args, complain, in_decl);
+ finish_do_body (stmt);
+ tmp = tsubst_expr (DO_COND (t), args, complain, in_decl);
+ finish_do_stmt (tmp, stmt);
break;
case IF_STMT:
- {
- prep_stmt (t);
- stmt = begin_if_stmt ();
- finish_if_stmt_cond (tsubst_expr (IF_COND (t),
- args, complain, in_decl),
- stmt);
-
- if (tmp = THEN_CLAUSE (t), tmp)
- {
- tsubst_expr (tmp, args, complain, in_decl);
- finish_then_clause (stmt);
- }
+ stmt = begin_if_stmt ();
+ tmp = tsubst_expr (IF_COND (t), args, complain, in_decl);
+ finish_if_stmt_cond (tmp, stmt);
+ tsubst_expr (THEN_CLAUSE (t), args, complain, in_decl);
+ finish_then_clause (stmt);
- if (tmp = ELSE_CLAUSE (t), tmp)
- {
- begin_else_clause ();
- tsubst_expr (tmp, args, complain, in_decl);
- finish_else_clause (stmt);
- }
+ if (ELSE_CLAUSE (t))
+ {
+ begin_else_clause (stmt);
+ tsubst_expr (ELSE_CLAUSE (t), args, complain, in_decl);
+ finish_else_clause (stmt);
+ }
- finish_if_stmt ();
- }
+ finish_if_stmt (stmt);
break;
- case COMPOUND_STMT:
- {
- prep_stmt (t);
- if (COMPOUND_STMT_BODY_BLOCK (t))
- stmt = begin_function_body ();
- else
- stmt = begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
+ case BIND_EXPR:
+ if (BIND_EXPR_BODY_BLOCK (t))
+ stmt = begin_function_body ();
+ else
+ stmt = begin_compound_stmt (BIND_EXPR_TRY_BLOCK (t)
+ ? BCS_TRY_BLOCK : 0);
- tsubst_expr (COMPOUND_BODY (t), args, complain, in_decl);
+ tsubst_expr (BIND_EXPR_BODY (t), args, complain, in_decl);
- if (COMPOUND_STMT_BODY_BLOCK (t))
- finish_function_body (stmt);
- else
- finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), stmt);
- }
+ if (BIND_EXPR_BODY_BLOCK (t))
+ finish_function_body (stmt);
+ else
+ finish_compound_stmt (stmt);
break;
case BREAK_STMT:
- prep_stmt (t);
finish_break_stmt ();
break;
case CONTINUE_STMT:
- prep_stmt (t);
finish_continue_stmt ();
break;
case SWITCH_STMT:
- {
- tree val;
-
- prep_stmt (t);
- stmt = begin_switch_stmt ();
- val = tsubst_expr (SWITCH_COND (t), args, complain, in_decl);
- finish_switch_cond (val, stmt);
- tsubst_expr (SWITCH_BODY (t), args, complain, in_decl);
- finish_switch_stmt (stmt);
- }
+ stmt = begin_switch_stmt ();
+ tmp = tsubst_expr (SWITCH_COND (t), args, complain, in_decl);
+ finish_switch_cond (tmp, stmt);
+ tsubst_expr (SWITCH_BODY (t), args, complain, in_decl);
+ finish_switch_stmt (stmt);
break;
- case CASE_LABEL:
- prep_stmt (t);
+ case CASE_LABEL_EXPR:
finish_case_label (tsubst_expr (CASE_LOW (t), args, complain, in_decl),
tsubst_expr (CASE_HIGH (t), args, complain,
in_decl));
break;
- case LABEL_STMT:
- input_line = STMT_LINENO (t);
- finish_label_stmt (DECL_NAME (LABEL_STMT_LABEL (t)));
+ case LABEL_EXPR:
+ finish_label_stmt (DECL_NAME (LABEL_EXPR_LABEL (t)));
break;
- case FILE_STMT:
- input_filename = FILE_STMT_FILENAME (t);
- add_stmt (build_nt (FILE_STMT, FILE_STMT_FILENAME_NODE (t)));
- break;
-
- case GOTO_STMT:
- prep_stmt (t);
+ case GOTO_EXPR:
tmp = GOTO_DESTINATION (t);
if (TREE_CODE (tmp) != LABEL_DECL)
/* Computed goto's must be tsubst'd into. On the other hand,
finish_goto_stmt (tmp);
break;
- case ASM_STMT:
- prep_stmt (t);
+ case ASM_EXPR:
tmp = finish_asm_stmt
- (ASM_CV_QUAL (t),
+ (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),
break;
case TRY_BLOCK:
- prep_stmt (t);
if (CLEANUP_P (t))
{
stmt = begin_try_block ();
{
tree decl;
- prep_stmt (t);
stmt = begin_handler ();
if (HANDLER_PARMS (t))
{
- decl = DECL_STMT_DECL (HANDLER_PARMS (t));
+ decl = HANDLER_PARMS (t);
decl = tsubst (decl, args, complain, in_decl);
/* Prevent instantiate_decl from trying to instantiate
this variable. We've already done all that needs to be
break;
case TAG_DEFN:
- prep_stmt (t);
tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
break;
+ case OFFSETOF_EXPR:
+ t = tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
+ in_decl, false);
+ return fold_offsetof (t);
+
default:
- abort ();
+ gcc_assert (!STATEMENT_CODE_P (TREE_CODE (t)));
+
+ return tsubst_copy_and_build (t, args, complain, in_decl,
+ /*function_p=*/false);
}
- return tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
+ return NULL_TREE;
+}
+
+/* T is a postfix-expression that is not being used in a function
+ call. Return the substituted version of T. */
+
+static tree
+tsubst_non_call_postfix_expression (tree t, tree args,
+ tsubst_flags_t complain,
+ tree in_decl)
+{
+ if (TREE_CODE (t) == SCOPE_REF)
+ t = tsubst_qualified_id (t, args, complain, in_decl,
+ /*done=*/false, /*address_p=*/false);
+ else
+ t = tsubst_copy_and_build (t, args, complain, in_decl,
+ /*function_p=*/false);
+
+ return t;
}
/* Like tsubst but deals with expressions and performs semantic
- analysis. */
+ 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)
+ tree in_decl,
+ bool function_p)
{
+#define RECUR(NODE) \
+ tsubst_copy_and_build (NODE, args, complain, in_decl, /*function_p=*/false)
+
tree op1;
if (t == NULL_TREE || t == error_mark_node)
switch (TREE_CODE (t))
{
+ case USING_DECL:
+ t = DECL_NAME (t);
+ /* Fall through. */
case IDENTIFIER_NODE:
- if (IDENTIFIER_TYPENAME_P (t))
- {
- tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
- return do_identifier (mangle_conv_op_name_for_type (new_type),
- NULL_TREE);
- }
- else
- return do_identifier (t, NULL_TREE);
-
- case LOOKUP_EXPR:
{
- if (LOOKUP_EXPR_GLOBAL (t))
- {
- tree token
- = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
- return do_scoped_id (token, IDENTIFIER_GLOBAL_VALUE (token));
- }
- else
+ tree decl;
+ cp_id_kind idk;
+ tree qualifying_class;
+ bool non_integral_constant_expression_p;
+ const char *error_msg;
+
+ if (IDENTIFIER_TYPENAME_P (t))
{
- t = do_identifier
- (tsubst_copy
- (TREE_OPERAND (t, 0), args, complain, in_decl),
- NULL_TREE);
- if (TREE_CODE (t) == ALIAS_DECL)
- t = DECL_INITIAL (t);
- return t;
+ tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ t = mangle_conv_op_name_for_type (new_type);
}
+
+ /* Look up the name. */
+ decl = lookup_name (t, 0);
+
+ /* By convention, expressions use ERROR_MARK_NODE to indicate
+ failure, not NULL_TREE. */
+ if (decl == NULL_TREE)
+ decl = error_mark_node;
+
+ decl = finish_id_expression (t, decl, NULL_TREE,
+ &idk,
+ &qualifying_class,
+ /*integral_constant_expression_p=*/false,
+ /*allow_non_integral_constant_expression_p=*/false,
+ &non_integral_constant_expression_p,
+ &error_msg);
+ if (error_msg)
+ error (error_msg);
+ if (!function_p && TREE_CODE (decl) == IDENTIFIER_NODE)
+ decl = unqualified_name_lookup_error (decl);
+ return decl;
}
case TEMPLATE_ID_EXPR:
{
tree object;
- tree template
- = tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
- in_decl);
- tree targs
- = tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
- in_decl);
+ tree template = RECUR (TREE_OPERAND (t, 0));
+ tree targs = TREE_OPERAND (t, 1);
+
+ if (targs)
+ targs = tsubst_template_args (targs, args, complain, in_decl);
if (TREE_CODE (template) == COMPONENT_REF)
{
template = lookup_template_function (template, targs);
if (object)
- return build (COMPONENT_REF, TREE_TYPE (template),
- object, template);
+ return build3 (COMPONENT_REF, TREE_TYPE (template),
+ object, template, NULL_TREE);
else
return template;
}
case INDIRECT_REF:
- return build_x_indirect_ref
- (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
- "unary *");
+ return build_x_indirect_ref (RECUR (TREE_OPERAND (t, 0)), "unary *");
+
+ case NOP_EXPR:
+ return build_nop
+ (tsubst (TREE_TYPE (t), args, complain, in_decl),
+ RECUR (TREE_OPERAND (t, 0)));
case CAST_EXPR:
return build_functional_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
- tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+ RECUR (TREE_OPERAND (t, 0)));
case REINTERPRET_CAST_EXPR:
return build_reinterpret_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
- tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+ RECUR (TREE_OPERAND (t, 0)));
case CONST_CAST_EXPR:
return build_const_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
- tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+ RECUR (TREE_OPERAND (t, 0)));
case DYNAMIC_CAST_EXPR:
return build_dynamic_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
- tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+ RECUR (TREE_OPERAND (t, 0)));
case STATIC_CAST_EXPR:
return build_static_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
- tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+ RECUR (TREE_OPERAND (t, 0)));
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
- op1 = TREE_OPERAND (t, 0);
- if (TREE_CODE (op1) == SCOPE_REF)
- op1 = tsubst_qualified_id (TREE_OPERAND (t, 0),
- args, complain,
- in_decl,
- /*done=*/false,
- /*address_p=*/false);
- else
- op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
+ op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
+ args, complain, in_decl);
return build_x_unary_op (TREE_CODE (t), op1);
case PREDECREMENT_EXPR:
case CONVERT_EXPR: /* Unary + */
case REALPART_EXPR:
case IMAGPART_EXPR:
- return (build_x_unary_op
- (TREE_CODE (t),
- tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
- in_decl)));
+ return build_x_unary_op (TREE_CODE (t), RECUR (TREE_OPERAND (t, 0)));
case ADDR_EXPR:
op1 = TREE_OPERAND (t, 0);
op1 = tsubst_qualified_id (op1, args, complain, in_decl,
/*done=*/true, /*address_p=*/true);
else
- op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
+ op1 = tsubst_non_call_postfix_expression (op1, args, complain,
+ in_decl);
+ if (TREE_CODE (op1) == LABEL_DECL)
+ return finish_label_address_expr (DECL_NAME (op1));
return build_x_unary_op (ADDR_EXPR, op1);
case PLUS_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
case BIT_AND_EXPR:
- case BIT_ANDTC_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
case TRUNC_MOD_EXPR:
case LT_EXPR:
case GT_EXPR:
case MEMBER_REF:
+ case DOTSTAR_EXPR:
return build_x_binary_op
(TREE_CODE (t),
- tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl));
-
- case DOTSTAR_EXPR:
- return build_m_component_ref
- (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl));
+ 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,
if (tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl)
== NULL_TREE)
/* new-type-id */
- return build_nt
- (ARRAY_REF, NULL_TREE,
- tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
- in_decl));
+ return build_nt (ARRAY_REF, NULL_TREE, RECUR (TREE_OPERAND (t, 1)),
+ NULL_TREE, NULL_TREE);
- op1 = TREE_OPERAND (t, 0);
- if (TREE_CODE (op1) == SCOPE_REF)
- op1 = tsubst_qualified_id (op1, args, complain, in_decl,
- /*done=*/false, /*address_p=*/false);
- else
- op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
+ 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,
- tsubst_copy_and_build (TREE_OPERAND (t, 1),
- args, complain,
- in_decl));
+ return grok_array_decl (op1, RECUR (TREE_OPERAND (t, 1)));
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
else
{
++skip_evaluation;
- op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
+ op1 = RECUR (op1);
--skip_evaluation;
}
- if (TREE_CODE (t) == SIZEOF_EXPR)
- return finish_sizeof (op1);
+ if (TYPE_P (op1))
+ return cxx_sizeof_or_alignof_type (op1, TREE_CODE (t), true);
else
- return finish_alignof (op1);
+ return cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t));
case MODOP_EXPR:
- return build_x_modify_expr
- (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
- TREE_CODE (TREE_OPERAND (t, 1)),
- tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
+ {
+ tree r = build_x_modify_expr
+ (RECUR (TREE_OPERAND (t, 0)),
+ TREE_CODE (TREE_OPERAND (t, 1)),
+ RECUR (TREE_OPERAND (t, 2)));
+ /* TREE_NO_WARNING must be set if either the expression was
+ parenthesized or it uses an operator such as >>= rather
+ than plain assignment. In the former case, it was already
+ set and must be copied. In the latter case,
+ build_x_modify_expr sets it and it must not be reset
+ here. */
+ if (TREE_NO_WARNING (t))
+ TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
+ return r;
+ }
case ARROW_EXPR:
- op1 = TREE_OPERAND (t, 0);
- if (TREE_CODE (op1) == SCOPE_REF)
- op1 = tsubst_qualified_id (op1, args, complain, in_decl,
- /*done=*/false, /*address_p=*/false);
- else
- op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
+ 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);
case NEW_EXPR:
return build_new
- (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
- tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl),
+ (RECUR (TREE_OPERAND (t, 0)),
+ RECUR (TREE_OPERAND (t, 1)),
+ RECUR (TREE_OPERAND (t, 2)),
+ RECUR (TREE_OPERAND (t, 3)),
NEW_EXPR_USE_GLOBAL (t));
case DELETE_EXPR:
return delete_sanity
- (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
+ (RECUR (TREE_OPERAND (t, 0)),
+ RECUR (TREE_OPERAND (t, 1)),
DELETE_EXPR_USE_VEC (t),
DELETE_EXPR_USE_GLOBAL (t));
case COMPOUND_EXPR:
- return (build_x_compound_expr
- (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
- in_decl),
- tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
- in_decl)));
+ return build_x_compound_expr (RECUR (TREE_OPERAND (t, 0)),
+ RECUR (TREE_OPERAND (t, 1)));
case CALL_EXPR:
{
tree function;
tree call_args;
- tree koenig_name;
bool qualified_p;
+ bool koenig_p;
function = TREE_OPERAND (t, 0);
- if (TREE_CODE (function) == LOOKUP_EXPR
- && !LOOKUP_EXPR_GLOBAL (function))
- koenig_name = TREE_OPERAND (function, 0);
- else
- koenig_name = NULL_TREE;
+ /* When we parsed the expression, we determined whether or
+ not Koenig lookup should be performed. */
+ koenig_p = KOENIG_LOOKUP_P (t);
if (TREE_CODE (function) == SCOPE_REF)
{
qualified_p = true;
&& (TREE_CODE (TREE_OPERAND (function, 1))
== SCOPE_REF));
function = tsubst_copy_and_build (function, args, complain,
- in_decl);
- function = convert_from_reference (function);
+ in_decl,
+ !qualified_p);
+ if (BASELINK_P (function))
+ qualified_p = true;
+ }
+
+ call_args = RECUR (TREE_OPERAND (t, 1));
+
+ /* We do not perform argument-dependent lookup if normal
+ lookup finds a non-function, in accordance with the
+ expected resolution of DR 218. */
+ if (koenig_p
+ && (is_overloaded_fn (function)
+ || TREE_CODE (function) == IDENTIFIER_NODE))
+ function = perform_koenig_lookup (function, call_args);
+
+ if (TREE_CODE (function) == IDENTIFIER_NODE)
+ {
+ unqualified_name_lookup_error (function);
+ return error_mark_node;
}
/* Remember that there was a reference to this entity. */
if (DECL_P (function))
mark_used (function);
- call_args = tsubst_copy_and_build (TREE_OPERAND (t, 1), args,
- complain, in_decl);
-
- if (BASELINK_P (function))
- qualified_p = 1;
-
- if (call_args != NULL_TREE && koenig_name)
- function = lookup_arg_dependent (koenig_name,
- function,
- call_args);
+ 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)
- return (build_new_method_call
- (TREE_OPERAND (function, 0),
- TREE_OPERAND (function, 1),
- call_args, NULL_TREE,
- qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL));
+ {
+ if (!BASELINK_P (TREE_OPERAND (function, 1)))
+ return finish_call_expr (function, call_args,
+ /*disallow_virtual=*/false,
+ /*koenig_p=*/false);
+ else
+ return (build_new_method_call
+ (TREE_OPERAND (function, 0),
+ TREE_OPERAND (function, 1),
+ call_args, NULL_TREE,
+ qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL));
+ }
return finish_call_expr (function, call_args,
- /*disallow_virtual=*/qualified_p);
+ /*disallow_virtual=*/qualified_p,
+ koenig_p);
}
case COND_EXPR:
return build_x_conditional_expr
- (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
- tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
+ (RECUR (TREE_OPERAND (t, 0)),
+ RECUR (TREE_OPERAND (t, 1)),
+ RECUR (TREE_OPERAND (t, 2)));
case PSEUDO_DTOR_EXPR:
return finish_pseudo_destructor_expr
- (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
- tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
+ (RECUR (TREE_OPERAND (t, 0)),
+ RECUR (TREE_OPERAND (t, 1)),
+ RECUR (TREE_OPERAND (t, 2)));
case TREE_LIST:
{
purpose = TREE_PURPOSE (t);
if (purpose)
- purpose = tsubst_copy_and_build (purpose, args, complain, in_decl);
+ purpose = RECUR (purpose);
value = TREE_VALUE (t);
if (value)
- value = tsubst_copy_and_build (value, args, complain, in_decl);
+ value = RECUR (value);
chain = TREE_CHAIN (t);
if (chain && chain != void_type_node)
- chain = tsubst_copy_and_build (chain, args, complain, in_decl);
+ chain = RECUR (chain);
if (purpose == TREE_PURPOSE (t)
&& value == TREE_VALUE (t)
&& chain == TREE_CHAIN (t))
case COMPONENT_REF:
{
tree object;
- tree member;
-
- object = TREE_OPERAND (t, 0);
- if (TREE_CODE (object) == SCOPE_REF)
- object = tsubst_qualified_id (object, args, complain, in_decl,
- /*done=*/false, /*address_p=*/false);
- else
- object = tsubst_copy_and_build (object, args, complain, in_decl);
+ tree member;
+ object = 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 (object))
mark_used (object);
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,
- /*is_type=*/0);
+ 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);
else
{
- error ("`%D' is not a member of `%T'",
- tmpl, TREE_TYPE (object));
+ qualified_name_lookup_error (TREE_TYPE (object), tmpl,
+ member);
return error_mark_node;
}
}
+ else if (TREE_CODE (member) == SCOPE_REF
+ && !CLASS_TYPE_P (TREE_OPERAND (member, 0))
+ && TREE_CODE (TREE_OPERAND (member, 0)) != NAMESPACE_DECL)
+ {
+ if (complain & tf_error)
+ {
+ if (TYPE_P (TREE_OPERAND (member, 0)))
+ error ("`%T' is not a class or namespace",
+ TREE_OPERAND (member, 0));
+ else
+ error ("`%D' is not a class or namespace",
+ TREE_OPERAND (member, 0));
+ }
+ return error_mark_node;
+ }
+ else if (TREE_CODE (member) == FIELD_DECL)
+ return finish_non_static_data_member (member, object, NULL_TREE);
return finish_class_member_access_expr (object, member);
}
case THROW_EXPR:
return build_throw
- (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+ (RECUR (TREE_OPERAND (t, 0)));
case CONSTRUCTOR:
{
tree value = TREE_VALUE (elts);
if (purpose && purpose_p)
- purpose
- = tsubst_copy_and_build (purpose, args, complain, in_decl);
- value = tsubst_copy_and_build (value, args, complain, in_decl);
+ purpose = RECUR (purpose);
+ value = RECUR (value);
r = tree_cons (purpose, value, r);
}
case TYPEID_EXPR:
{
- tree operand_0
- = tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
- in_decl);
-
+ tree operand_0 = RECUR (TREE_OPERAND (t, 0));
if (TYPE_P (operand_0))
return get_typeid (operand_0);
return build_typeid (operand_0);
case VAR_DECL:
if (args)
t = tsubst_copy (t, args, complain, in_decl);
- else
- /* If there are no ARGS, then we are evaluating a
- non-dependent expression. If the expression is
- non-dependent, the variable must be a constant. */
- t = DECL_INITIAL (t);
return convert_from_reference (t);
case VA_ARG_EXPR:
- return build_x_va_arg
- (tsubst_copy_and_build
- (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy (TREE_TYPE (t), args, complain, in_decl));
+ return build_x_va_arg (RECUR (TREE_OPERAND (t, 0)),
+ tsubst_copy (TREE_TYPE (t), args, complain,
+ in_decl));
default:
return tsubst_copy (t, args, complain, in_decl);
}
+
+#undef RECUR
}
/* Verify that the instantiated ARGS are valid. For type arguments,
shall not be used to declare an entity with linkage.
This implies that names with no linkage cannot be used as
template arguments. */
- tree nt = no_linkage_check (t);
+ tree nt = no_linkage_check (t, /*relaxed_p=*/false);
if (nt)
{
}
/* In order to avoid all sorts of complications, we do not
allow variably-modified types as template arguments. */
- else if (variably_modified_type_p (t))
+ else if (variably_modified_type_p (t, NULL_TREE))
{
if (complain & tf_error)
error ("`%T' is a variably modified type", t);
if (tmpl == error_mark_node)
return error_mark_node;
- my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
+ gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
/* If this function is a clone, handle it specially. */
if (DECL_CLONED_FUNCTION_P (tmpl))
{
- tree spec = instantiate_template (DECL_CLONED_FUNCTION (tmpl), targ_ptr,
- complain);
+ tree spec;
tree clone;
+ spec = instantiate_template (DECL_CLONED_FUNCTION (tmpl), targ_ptr,
+ complain);
+ if (spec == error_mark_node)
+ return error_mark_node;
+
/* Look for the clone. */
- for (clone = TREE_CHAIN (spec);
- clone && DECL_CLONED_FUNCTION_P (clone);
- clone = TREE_CHAIN (clone))
+ FOR_EACH_CLONE (clone, spec)
if (DECL_NAME (clone) == DECL_NAME (tmpl))
return clone;
/* We should always have found the clone by now. */
- abort ();
+ gcc_unreachable ();
return NULL_TREE;
}
complain))
return error_mark_node;
- /* Make sure that we can see identifiers, and compute access
- correctly. The desired FUNCTION_DECL for FNDECL may or may not be
- created earlier. Let push_access_scope_real figure that out. */
- push_access_scope_real
- (gen_tmpl, targ_ptr, tsubst (DECL_CONTEXT (gen_tmpl), targ_ptr,
- complain, gen_tmpl));
-
- /* substitute template parameters */
+ /* 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
+ is not built yet. We solve this chicken-and-egg problem by
+ deferring all checks until we have the FUNCTION_DECL. */
+ push_deferring_access_checks (dk_deferred);
+
+ /* Substitute template parameters. */
fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
targ_ptr, complain, gen_tmpl);
- pop_access_scope (gen_tmpl);
+ /* Now we know the specialization, compute access previously
+ deferred. */
+ push_access_scope (fndecl);
+ perform_deferred_access_checks ();
+ pop_access_scope (fndecl);
+ pop_deferring_access_checks ();
/* The DECL_TI_TEMPLATE should always be the immediate parent
template, not the most general template. */
DECL_TI_TEMPLATE (fndecl) = tmpl;
- if (flag_external_templates)
- add_pending_template (fndecl);
-
/* If we've just instantiated the main entry point for a function,
instantiate all the alternate entry points as well. We do this
by cloning the instantiation of the main entry point, not by
tree fntype;
int result;
- my_friendly_assert (TREE_CODE (fn) == TEMPLATE_DECL, 0);
+ gcc_assert (TREE_CODE (fn) == TEMPLATE_DECL);
fntype = TREE_TYPE (fn);
if (explicit_targs)
template results in an invalid type, type deduction fails. */
int i;
tree converted_args;
+ bool incomplete;
converted_args
= (coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (fn),
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. */
+ 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;
/* Place the explicitly specified arguments in TARGS. */
- for (i = 0; i < TREE_VEC_LENGTH (targs); i++)
+ for (i = NUM_TMPL_ARGS (converted_args); i--;)
TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (converted_args, i);
}
}
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (TREE_CODE (*parm) != REFERENCE_TYPE)
tree parms, args;
int len;
- my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
- my_friendly_assert (xparms == NULL_TREE
- || TREE_CODE (xparms) == TREE_LIST, 290);
- /* ARGS could be NULL. */
- if (xargs)
- my_friendly_assert (TREE_CODE (xargs) == TREE_LIST, 291);
- my_friendly_assert (ntparms > 0, 292);
+ gcc_assert (TREE_CODE (tparms) == TREE_VEC);
+ gcc_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST);
+ gcc_assert (!xargs || TREE_CODE (xargs) == TREE_LIST);
+ gcc_assert (ntparms > 0);
switch (strict)
{
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (xlen == 0)
corresponds with a function parameter that contains only
non-deducible template parameters and explicitly specified
template parameters. */
- if (! uses_template_parms (parm))
+ if (!uses_template_parms (parm))
{
tree type;
if (!TYPE_P (arg))
type = TREE_TYPE (arg);
else
- {
- type = arg;
- arg = NULL_TREE;
- }
+ type = arg;
if (strict == DEDUCE_EXACT || strict == DEDUCE_ORDER)
{
if (!TYPE_P (arg))
{
- my_friendly_assert (TREE_TYPE (arg) != NULL_TREE, 293);
+ gcc_assert (TREE_TYPE (arg) != NULL_TREE);
if (type_unknown_p (arg))
{
/* [temp.deduct.type] A template-argument can be deduced from
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. */
+ /* Fail if parms are left and they don't have default values. */
if (parms
&& parms != void_list_node
&& TREE_PURPOSE (parms) == NULL_TREE)
{
tree tempargs = copy_node (targs);
int good = 0;
+ bool addr_p;
if (TREE_CODE (arg) == ADDR_EXPR)
- arg = TREE_OPERAND (arg, 0);
+ {
+ arg = TREE_OPERAND (arg, 0);
+ addr_p = true;
+ }
+ else
+ addr_p = false;
if (TREE_CODE (arg) == COMPONENT_REF)
/* Handle `&x' where `x' is some static or non-static member
if (subargs)
{
elem = tsubst (TREE_TYPE (fn), subargs, tf_none, NULL_TREE);
- if (TREE_CODE (elem) == METHOD_TYPE)
- elem = build_ptrmemfunc_type (build_pointer_type (elem));
- good += try_one_overload (tparms, targs, tempargs, parm, elem,
- strict, sub_strict);
+ good += try_one_overload (tparms, targs, tempargs, parm,
+ elem, strict, sub_strict, addr_p);
}
}
}
- else if (TREE_CODE (arg) == OVERLOAD
- || TREE_CODE (arg) == FUNCTION_DECL)
+ else
{
+ gcc_assert (TREE_CODE (arg) == OVERLOAD
+ || TREE_CODE (arg) == FUNCTION_DECL);
+
for (; arg; arg = OVL_NEXT (arg))
- {
- tree type = TREE_TYPE (OVL_CURRENT (arg));
- if (TREE_CODE (type) == METHOD_TYPE)
- type = build_ptrmemfunc_type (build_pointer_type (type));
- good += try_one_overload (tparms, targs, tempargs, parm,
- type,
- strict, sub_strict);
- }
+ good += try_one_overload (tparms, targs, tempargs, parm,
+ TREE_TYPE (OVL_CURRENT (arg)),
+ strict, sub_strict, addr_p);
}
- else
- abort ();
/* [temp.deduct.type] A template-argument can be deduced from a pointer
to function or pointer to member function argument if the set of
/* Subroutine of resolve_overloaded_unification; does deduction for a single
overload. Fills TARGS with any deduced arguments, or error_mark_node if
different overloads deduce different arguments for a given parm.
+ ADDR_P is true if the expression for which deduction is being
+ performed was of the form "& fn" rather than simply "fn".
+
Returns 1 on success. */
static int
tree parm,
tree arg,
unification_kind_t strict,
- int sub_strict)
+ int sub_strict,
+ bool addr_p)
{
int nargs;
tree tempargs;
if (uses_template_parms (arg))
return 1;
+ if (TREE_CODE (arg) == METHOD_TYPE)
+ arg = build_ptrmemfunc_type (build_pointer_type (arg));
+ else if (addr_p)
+ arg = build_pointer_type (arg);
+
sub_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg);
/* We don't copy orig_targs for this because if we have already deduced
tree rval,
int flags)
{
- tree binfos;
- int i, n_baselinks;
+ tree base_binfo;
+ int i;
tree arg = BINFO_TYPE (arg_binfo);
if (!(flags & GTB_IGNORE_TYPE))
rval = r;
}
- binfos = BINFO_BASETYPES (arg_binfo);
- n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
/* Process base types. */
- for (i = 0; i < n_baselinks; i++)
+ for (i = 0; BINFO_BASE_ITERATE (arg_binfo, i, base_binfo); i++)
{
- tree base_binfo = TREE_VEC_ELT (binfos, i);
int this_virtual;
/* Skip this base, if we've already seen it. */
continue;
this_virtual =
- (flags & GTB_VIA_VIRTUAL) || TREE_VIA_VIRTUAL (base_binfo);
+ (flags & GTB_VIA_VIRTUAL) || BINFO_VIRTUAL_P (base_binfo);
/* When searching for a non-virtual, we cannot mark virtually
found binfos. */
tree rval;
tree arg_binfo;
- my_friendly_assert (IS_AGGR_TYPE_CODE (TREE_CODE (arg)), 92);
+ gcc_assert (IS_AGGR_TYPE_CODE (TREE_CODE (arg)));
arg_binfo = TYPE_BINFO (complete_type (arg));
+ if (!arg_binfo)
+ /* The type could not be completed. */
+ return NULL_TREE;
+
rval = get_template_base_recursive (tparms, targs,
parm, arg_binfo,
NULL_TREE,
return TEMPLATE_PARM_LEVEL (DECL_INITIAL (decl));
default:
- abort ();
- return 0;
+ gcc_unreachable ();
}
+ return 0;
}
/* Decide whether ARG can be unified with PARM, considering only the
cv-qualifiers of each type, given STRICT as documented for unify.
- Returns nonzero iff the unification is OK on that basis.*/
+ Returns nonzero iff the unification is OK on that basis. */
static int
check_cv_quals_for_unify (int strict, tree arg, tree parm)
int arg_quals = cp_type_quals (arg);
int parm_quals = cp_type_quals (parm);
- if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM)
- {
- /* If the cvr quals of parm will not unify with ARG, they'll be
- ignored in instantiation, so we have to do the same here. */
- if (TREE_CODE (arg) == REFERENCE_TYPE)
- parm_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
- if (!POINTER_TYPE_P (arg) &&
- TREE_CODE (arg) != TEMPLATE_TYPE_PARM)
- parm_quals &= ~TYPE_QUAL_RESTRICT;
+ if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM
+ && !(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. */
+ if ((TREE_CODE (arg) == REFERENCE_TYPE
+ || TREE_CODE (arg) == FUNCTION_TYPE
+ || TREE_CODE (arg) == METHOD_TYPE)
+ && (parm_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)))
+ return 0;
+
+ if ((!POINTER_TYPE_P (arg) && TREE_CODE (arg) != TEMPLATE_TYPE_PARM)
+ && (parm_quals & TYPE_QUAL_RESTRICT))
+ return 0;
}
-
+
if (!(strict & (UNIFY_ALLOW_MORE_CV_QUAL | UNIFY_ALLOW_OUTER_MORE_CV_QUAL))
&& (arg_quals & parm_quals) != parm_quals)
return 0;
qualified at this point.
UNIFY_ALLOW_OUTER_LESS_CV_QUAL:
This is the outermost level of a deduction, and PARM can be less CV
- qualified at this point.
- UNIFY_ALLOW_MAX_CORRECTION:
- This is an INTEGER_TYPE's maximum value. Used if the range may
- have been derived from a size specification, such as an array size.
- If the size was given by a nontype template parameter N, the maximum
- value will have the form N-1. The flag says that we can (and indeed
- must) unify N with (ARG + 1), an exception to the normal rules on
- folding PARM. */
+ qualified at this point. */
static int
unify (tree tparms, tree targs, tree parm, tree arg, int strict)
strict &= ~UNIFY_ALLOW_DERIVED;
strict &= ~UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
strict &= ~UNIFY_ALLOW_OUTER_LESS_CV_QUAL;
- strict &= ~UNIFY_ALLOW_MAX_CORRECTION;
switch (TREE_CODE (parm))
{
{
tree parmtmpl = TYPE_TI_TEMPLATE (parm);
tree parmvec = TYPE_TI_ARGS (parm);
- tree argvec = TYPE_TI_ARGS (arg);
+ tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
tree argtmplvec
= DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (arg));
int i;
for (i = 0; i < TREE_VEC_LENGTH (parmvec); ++i)
{
- tree t = TREE_VEC_ELT (parmvec, i);
-
- if (unify (tparms, targs, t,
+ if (unify (tparms, targs,
+ TREE_VEC_ELT (parmvec, i),
TREE_VEC_ELT (argvec, i),
UNIFY_ALLOW_NONE))
return 1;
}
else
{
- /* If ARG is an offset type, we're trying to unify '*T' with
- 'U C::*', which is ill-formed. See the comment in the
- POINTER_TYPE case about this ugliness. */
- if (TREE_CODE (arg) == OFFSET_TYPE)
- return 1;
-
/* If PARM is `const T' and ARG is only `int', we don't have
a match unless we are allowing additional qualification.
If ARG is `const int' and PARM is just `T' that's OK;
the bound of the array will not be computable in an
instantiation. Besides, such types are not allowed in
ISO C++, so we can do as we please here. */
- if (variably_modified_type_p (arg))
+ if (variably_modified_type_p (arg, NULL_TREE))
return 1;
}
else if ((strict & UNIFY_ALLOW_INTEGER)
&& (TREE_CODE (tparm) == INTEGER_TYPE
|| TREE_CODE (tparm) == BOOLEAN_TYPE))
- /* OK */;
+ /* Convert the ARG to the type of PARM; the deduced non-type
+ template argument must exactly match the types of the
+ corresponding parameter. */
+ arg = fold (build_nop (TREE_TYPE (parm), arg));
else if (uses_template_parms (tparm))
/* We haven't deduced the type of this parameter yet. Try again
later. */
TREE_VEC_ELT (targs, idx) = arg;
return 0;
+ case PTRMEM_CST:
+ {
+ /* A pointer-to-member constant can be unified only with
+ another constant. */
+ if (TREE_CODE (arg) != PTRMEM_CST)
+ 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:
+
+ struct A { int x; };
+ struct B : A { };
+
+ Unification of &A::x and &B::x must succeed. */
+ return unify (tparms, targs, PTRMEM_CST_MEMBER (parm),
+ PTRMEM_CST_MEMBER (arg), strict);
+ }
+
case POINTER_TYPE:
{
if (TREE_CODE (arg) != POINTER_TYPE)
level of pointers. */
strict |= (strict_in & UNIFY_ALLOW_DERIVED);
- if (TREE_CODE (TREE_TYPE (parm)) == OFFSET_TYPE
- && TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE)
- {
- /* Avoid getting confused about cv-quals; don't recurse here.
- Pointers to members should really be just OFFSET_TYPE, not
- this two-level nonsense... */
-
- parm = TREE_TYPE (parm);
- arg = TREE_TYPE (arg);
- goto offset;
- }
-
return unify (tparms, targs, TREE_TYPE (parm),
TREE_TYPE (arg), strict);
}
if ((TYPE_DOMAIN (parm) == NULL_TREE)
!= (TYPE_DOMAIN (arg) == NULL_TREE))
return 1;
- if (TYPE_DOMAIN (parm) != NULL_TREE
- && unify (tparms, targs, TYPE_DOMAIN (parm),
- TYPE_DOMAIN (arg), UNIFY_ALLOW_NONE) != 0)
- return 1;
+ if (TYPE_DOMAIN (parm) != NULL_TREE)
+ {
+ tree parm_max;
+ tree arg_max;
+
+ parm_max = TYPE_MAX_VALUE (TYPE_DOMAIN (parm));
+ arg_max = TYPE_MAX_VALUE (TYPE_DOMAIN (arg));
+
+ /* Our representation of array types uses "N - 1" as the
+ TYPE_MAX_VALUE for an array with "N" elements, if "N" is
+ not an integer constant. */
+ if (TREE_CODE (parm_max) == MINUS_EXPR)
+ {
+ arg_max = fold (build2 (PLUS_EXPR,
+ integer_type_node,
+ arg_max,
+ TREE_OPERAND (parm_max, 1)));
+ parm_max = TREE_OPERAND (parm_max, 0);
+ }
+
+ if (unify (tparms, targs, parm_max, arg_max, UNIFY_ALLOW_INTEGER))
+ return 1;
+ }
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
strict & UNIFY_ALLOW_MORE_CV_QUAL);
case VOID_TYPE:
if (TREE_CODE (arg) != TREE_CODE (parm))
return 1;
-
- if (TREE_CODE (parm) == INTEGER_TYPE
- && TREE_CODE (TYPE_MAX_VALUE (parm)) != INTEGER_CST)
- {
- if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg)
- && unify (tparms, targs, TYPE_MIN_VALUE (parm),
- TYPE_MIN_VALUE (arg), UNIFY_ALLOW_INTEGER))
- return 1;
- if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg)
- && unify (tparms, targs, TYPE_MAX_VALUE (parm),
- TYPE_MAX_VALUE (arg),
- UNIFY_ALLOW_INTEGER | UNIFY_ALLOW_MAX_CORRECTION))
- return 1;
- }
+
/* We have already checked cv-qualification at the top of the
function. */
- else if (!same_type_ignoring_top_level_qualifiers_p (arg, parm))
+ if (!same_type_ignoring_top_level_qualifiers_p (arg, parm))
return 1;
/* As far as unification is concerned, this wins. Later checks
DEDUCE_EXACT, 0, -1);
case OFFSET_TYPE:
- offset:
if (TREE_CODE (arg) != OFFSET_TYPE)
return 1;
if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
return 1;
return 0;
+ case FIELD_DECL:
case TEMPLATE_DECL:
/* Matched cases are handled by the ARG == PARM test above. */
return 1;
- case MINUS_EXPR:
- if (tree_int_cst_equal (TREE_OPERAND (parm, 1), integer_one_node)
- && (strict_in & UNIFY_ALLOW_MAX_CORRECTION))
- {
- /* We handle this case specially, since it comes up with
- arrays. In particular, something like:
-
- template <int N> void f(int (&x)[N]);
-
- Here, we are trying to unify the range type, which
- looks like [0 ... (N - 1)]. */
- tree t, t1, t2;
- t1 = TREE_OPERAND (parm, 0);
- t2 = TREE_OPERAND (parm, 1);
-
- t = fold (build (PLUS_EXPR, integer_type_node, arg, t2));
-
- return unify (tparms, targs, t1, t, strict);
- }
- /* else fall through */
-
default:
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (parm))))
{
}
}
\f
+/* Note that DECL can be defined in this translation unit, if
+ required. */
+
+static void
+mark_definable (tree decl)
+{
+ tree clone;
+ DECL_NOT_REALLY_EXTERN (decl) = 1;
+ FOR_EACH_CLONE (clone, decl)
+ DECL_NOT_REALLY_EXTERN (clone) = 1;
+}
+
/* Called if RESULT is explicitly instantiated, or is a member of an
- explicitly instantiated class, or if using -frepo and the
- instantiation of RESULT has been assigned to this file. */
+ explicitly instantiated class. */
void
mark_decl_instantiated (tree result, int extern_p)
{
- /* We used to set this unconditionally; we moved that to
- do_decl_instantiation so it wouldn't get set on members of
- explicit class template instantiations. But we still need to set
- it here for the 'extern template' case in order to suppress
- implicit instantiations. */
- if (extern_p)
- SET_DECL_EXPLICIT_INSTANTIATION (result);
+ SET_DECL_EXPLICIT_INSTANTIATION (result);
/* If this entity has already been written out, it's too late to
make any modifications. */
/* This might have been set by an earlier implicit instantiation. */
DECL_COMDAT (result) = 0;
- if (! extern_p)
+ if (extern_p)
+ DECL_NOT_REALLY_EXTERN (result) = 0;
+ else
{
- DECL_INTERFACE_KNOWN (result) = 1;
- DECL_NOT_REALLY_EXTERN (result) = 1;
-
+ mark_definable (result);
/* Always make artificials weak. */
if (DECL_ARTIFICIAL (result) && flag_weak)
comdat_linkage (result);
else if (TREE_PUBLIC (result))
maybe_make_one_only (result);
}
-
- if (TREE_CODE (result) == FUNCTION_DECL)
- defer_fn (result);
+
+ /* If EXTERN_P, then this function will not be emitted -- unless
+ followed by an explicit instantiation, at which point its linkage
+ will be adjusted. If !EXTERN_P, then this function will be
+ emitted here. In neither circumstance do we want
+ import_export_decl to adjust the linkage. */
+ DECL_INTERFACE_KNOWN (result) = 1;
}
/* Given two function templates PAT1 and PAT2, return:
tree targs;
int winner = 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)
NULL_TREE, 0, deduce, len);
if (targs)
++winner;
+ --processing_template_decl;
return winner;
}
1 if PAT1 is more specialized than PAT2 as described in [temp.class.order].
-1 if PAT2 is more specialized than PAT1.
- 0 if neither is more specialized. */
+ 0 if neither is more specialized.
+
+ FULL_ARGS is the full set of template arguments that triggers this
+ partial ordering. */
int
-more_specialized_class (tree pat1, tree pat2)
+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
+ different class template specializations, we may encounter dependent
+ types in the arguments, and we need our dependency check functions
+ to behave correctly. */
+ ++processing_template_decl;
targs = get_class_bindings (TREE_VALUE (pat1), TREE_PURPOSE (pat1),
- TREE_PURPOSE (pat2));
+ add_outermost_template_args (full_args, TREE_PURPOSE (pat2)));
if (targs)
--winner;
targs = get_class_bindings (TREE_VALUE (pat2), TREE_PURPOSE (pat2),
- TREE_PURPOSE (pat1));
+ add_outermost_template_args (full_args, TREE_PURPOSE (pat1)));
if (targs)
++winner;
+ --processing_template_decl;
return winner;
}
/* For most uses, we want to check the return type. */
-tree
+static tree
get_bindings (tree fn, tree decl, tree explicit_args)
{
return get_bindings_real (fn, decl, explicit_args, 1, DEDUCE_EXACT, -1);
/* Look for more and more general templates. */
while (DECL_TEMPLATE_INFO (decl))
{
- /* The DECL_TI_TEMPLATE can be a LOOKUP_EXPR or IDENTIFIER_NODE
- in some cases. (See cp-tree.h for details.) */
+ /* The DECL_TI_TEMPLATE can be an IDENTIFIER_NODE in some cases.
+ (See cp-tree.h for details.) */
if (TREE_CODE (DECL_TI_TEMPLATE (decl)) != TEMPLATE_DECL)
break;
t = TREE_CHAIN (t);
for (; t; t = TREE_CHAIN (t))
{
- fate = more_specialized_class (champ, t);
+ fate = more_specialized_class (champ, t, args);
if (fate == 1)
;
else
for (t = list; t && t != champ; t = TREE_CHAIN (t))
{
- fate = more_specialized_class (champ, t);
+ fate = more_specialized_class (champ, t, args);
if (fate != 1)
return error_mark_node;
}
No program shall explicitly instantiate any template more
than once.
- We check DECL_INTERFACE_KNOWN so as not to complain when the first
- instantiation was `extern' and the second is not, and EXTERN_P for
- the opposite case. If -frepo, chances are we already got marked
- as an explicit instantiation because of the repo file. */
- if (DECL_INTERFACE_KNOWN (result) && !extern_p && !flag_use_repository)
+ We check DECL_NOT_REALLY_EXTERN so as not to complain when
+ the first instantiation was `extern' and the second is not,
+ and EXTERN_P for the opposite case. */
+ if (DECL_NOT_REALLY_EXTERN (result) && !extern_p)
pedwarn ("duplicate explicit instantiation of `%#D'", result);
-
- /* If we've already instantiated the template, just return now. */
- if (DECL_INTERFACE_KNOWN (result))
+ /* If an "extern" explicit instantiation follows an ordinary
+ explicit instantiation, the template is instantiated. */
+ if (extern_p)
return;
}
else if (!DECL_IMPLICIT_INSTANTIATION (result))
return;
}
- if (flag_external_templates)
- return;
-
if (storage == NULL_TREE)
;
else if (storage == ridpointers[(int) RID_EXTERN])
error ("storage class `%D' applied to template instantiation",
storage);
- SET_DECL_EXPLICIT_INSTANTIATION (result);
mark_decl_instantiated (result, extern_p);
- repo_template_instantiated (result, extern_p);
if (! extern_p)
- instantiate_decl (result, /*defer_ok=*/1);
+ instantiate_decl (result, /*defer_ok=*/1, /*undefined_ok=*/0);
}
void
do_type_instantiation (TYPE_MAIN_DECL (entry->type), storage, 0);
}
+/* Called from do_type_instantiation to instantiate a member
+ (a member function or a static member variable) of an
+ explicitly instantiated class template. */
+static void
+instantiate_class_member (tree decl, int extern_p)
+{
+ mark_decl_instantiated (decl, extern_p);
+ if (! extern_p)
+ instantiate_decl (decl, /*defer_ok=*/1, /* undefined_ok=*/1);
+}
+
/* Perform an explicit instantiation of template class T. STORAGE, if
non-null, is the RID for extern, inline or static. COMPLAIN is
nonzero if this is called from the parser, zero if called recursively,
int extern_p = 0;
int nomem_p = 0;
int static_p = 0;
+ int previous_instantiation_extern_p = 0;
if (TREE_CODE (t) == TYPE_DECL)
t = TREE_TYPE (t);
complete_type (t);
- /* With -fexternal-templates, explicit instantiations are treated the same
- as implicit ones. */
- if (flag_external_templates)
- return;
-
if (!COMPLETE_TYPE_P (t))
{
if (complain & tf_error)
if (storage != NULL_TREE)
{
if (pedantic && !in_system_header)
- pedwarn("ISO C++ forbids the use of `%s' on explicit instantiations",
- IDENTIFIER_POINTER (storage));
+ pedwarn("ISO C++ forbids the use of `%E' on explicit instantiations",
+ storage);
if (storage == ridpointers[(int) RID_INLINE])
nomem_p = 1;
No program shall explicitly instantiate any template more
than once.
- If CLASSTYPE_INTERFACE_ONLY, then the first explicit instantiation
- was `extern'. If EXTERN_P then the second is. If -frepo, chances
- are we already got marked as an explicit instantiation because of the
- repo file. All these cases are OK. */
- if (!CLASSTYPE_INTERFACE_ONLY (t) && !extern_p && !flag_use_repository
+ 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 `%#T'", t);
}
mark_class_instantiated (t, extern_p);
- repo_template_instantiated (t, extern_p);
if (nomem_p)
return;
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. We choose to be generous,
- and not set DECL_EXPLICIT_INSTANTIATION. Therefore, we allow
- the explicit instantiation of a class where some of the members
- have no definition in the current translation unit. */
+ *explicit* instantiations or not. However, the most natural
+ interpretation is that it should be an explicit instantiation. */
if (! static_p)
for (tmp = TYPE_METHODS (t); tmp; tmp = TREE_CHAIN (tmp))
if (TREE_CODE (tmp) == FUNCTION_DECL
&& DECL_TEMPLATE_INSTANTIATION (tmp))
- {
- mark_decl_instantiated (tmp, extern_p);
- repo_template_instantiated (tmp, extern_p);
- if (! extern_p)
- instantiate_decl (tmp, /*defer_ok=*/1);
- }
+ instantiate_class_member (tmp, extern_p);
for (tmp = TYPE_FIELDS (t); tmp; tmp = TREE_CHAIN (tmp))
if (TREE_CODE (tmp) == VAR_DECL && DECL_TEMPLATE_INSTANTIATION (tmp))
- {
- mark_decl_instantiated (tmp, extern_p);
- repo_template_instantiated (tmp, extern_p);
- if (! extern_p)
- instantiate_decl (tmp, /*defer_ok=*/1);
- }
+ instantiate_class_member (tmp, extern_p);
if (CLASSTYPE_NESTED_UTDS (t))
binding_table_foreach (CLASSTYPE_NESTED_UTDS (t),
tree args;
tree code_pattern;
tree new_decl;
- int unregistered;
+ bool unregistered;
args = DECL_TI_ARGS (decl);
code_pattern = DECL_TEMPLATE_RESULT (tmpl);
instantiation of a specialization, which it isn't: it's a full
instantiation. */
gen_tmpl = most_general_template (tmpl);
- push_access_scope_real (gen_tmpl, args, DECL_CONTEXT (decl));
- unregistered = unregister_specialization (decl, gen_tmpl);
+ unregistered = reregister_specialization (decl, gen_tmpl,
+ /*new_spec=*/NULL_TREE);
/* If the DECL was not unregistered then something peculiar is
happening: we created a specialization but did not call
register_specialization for it. */
- my_friendly_assert (unregistered, 0);
+ gcc_assert (unregistered);
+
+ /* Make sure that we can see identifiers, and compute access
+ correctly. */
+ push_access_scope (decl);
/* Do the substitution to get the new declaration. */
new_decl = tsubst (code_pattern, args, tf_error, NULL_TREE);
cannot restructure the loop to just keep going until we find
a template with a definition, since that might go too far if
a specialization was declared, but not defined. */
- my_friendly_assert (!(TREE_CODE (decl) == VAR_DECL
- && !DECL_IN_AGGR_P (DECL_TEMPLATE_RESULT (tmpl))),
- 0);
+ gcc_assert (TREE_CODE (decl) != VAR_DECL
+ || DECL_IN_AGGR_P (DECL_TEMPLATE_RESULT (tmpl)));
/* Fetch the more general template. */
tmpl = DECL_TI_TEMPLATE (tmpl);
/* Produce the definition of D, a _DECL generated from a template. If
DEFER_OK is nonzero, then we don't have to actually do the
- instantiation now; we just have to do it sometime. */
+ instantiation now; we just have to do it sometime. Normally it is
+ an error if this is an explicit instantiation but D is undefined.
+ 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. */
+
tree
-instantiate_decl (tree d, int defer_ok)
+instantiate_decl (tree d, int defer_ok, int undefined_ok)
{
tree tmpl = DECL_TI_TEMPLATE (d);
tree gen_args;
/* This function should only be used to instantiate templates for
functions and static member variables. */
- my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL
- || TREE_CODE (d) == VAR_DECL, 0);
+ gcc_assert (TREE_CODE (d) == FUNCTION_DECL
+ || TREE_CODE (d) == VAR_DECL);
/* Variables are never deferred; if instantiation is required, they
are instantiated right away. That allows for better code in the
timevar_push (TV_PARSE);
- /* We may be in the middle of deferred access check. Disable
- it now. */
+ /* We may be in the middle of deferred access check. Disable it now. */
push_deferring_access_checks (dk_no_deferred);
/* Set TD to the template whose DECL_TEMPLATE_RESULT is the pattern
pattern_defined = (DECL_SAVED_TREE (code_pattern) != NULL_TREE);
else
pattern_defined = ! DECL_IN_AGGR_P (code_pattern);
+ /* Unless an explicit instantiation directive has already determined
+ the linkage of D, remember that a definition is available for
+ this entity. */
+ if (pattern_defined
+ && !DECL_INTERFACE_KNOWN (d)
+ && !DECL_NOT_REALLY_EXTERN (d))
+ mark_definable (d);
input_location = DECL_SOURCE_LOCATION (d);
- if (pattern_defined)
+ if (! pattern_defined && DECL_EXPLICIT_INSTANTIATION (d) && undefined_ok)
{
- /* Let the repository code that this template definition is
- available.
-
- The repository doesn't need to know about cloned functions
- because they never actually show up in the object file. It
- does need to know about the clones; those are the symbols
- that the linker will be emitting error messages about. */
- if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (d)
- || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (d))
- {
- tree t;
-
- for (t = TREE_CHAIN (d);
- t && DECL_CLONED_FUNCTION_P (t);
- t = TREE_CHAIN (t))
- repo_template_used (t);
- }
- else
- repo_template_used (d);
-
- if (flag_external_templates && ! DECL_INTERFACE_KNOWN (d))
- {
- if (flag_alt_external_templates)
- {
- if (interface_unknown)
- warn_if_unknown_interface (d);
- }
- else if (DECL_INTERFACE_KNOWN (code_pattern))
- {
- DECL_INTERFACE_KNOWN (d) = 1;
- DECL_NOT_REALLY_EXTERN (d) = ! DECL_EXTERNAL (code_pattern);
- }
- else
- warn_if_unknown_interface (code_pattern);
- }
-
- if (at_eof)
- import_export_decl (d);
+ DECL_NOT_REALLY_EXTERN (d) = 0;
+ SET_DECL_IMPLICIT_INSTANTIATION (d);
}
if (!defer_ok)
pop_access_scope (d);
}
- if (TREE_CODE (d) == VAR_DECL && DECL_INITIALIZED_IN_CLASS_P (d)
- && DECL_INITIAL (d) == NULL_TREE)
- /* We should have set up DECL_INITIAL in instantiate_class_template. */
- abort ();
- /* Reject all external templates except inline functions. */
- else if (DECL_INTERFACE_KNOWN (d)
- && ! DECL_NOT_REALLY_EXTERN (d)
- && ! (TREE_CODE (d) == FUNCTION_DECL
- && DECL_INLINE (d)))
+ /* We should have set up DECL_INITIAL in instantiate_class_template
+ for in-class definitions of static data members. */
+ gcc_assert (!(TREE_CODE (d) == VAR_DECL
+ && DECL_INITIALIZED_IN_CLASS_P (d)
+ && DECL_INITIAL (d) == NULL_TREE));
+
+ /* Do not instantiate templates that we know will be defined
+ elsewhere. */
+ if (DECL_INTERFACE_KNOWN (d)
+ && DECL_REALLY_EXTERN (d)
+ && ! (TREE_CODE (d) == FUNCTION_DECL
+ && DECL_INLINE (d)))
goto out;
/* Defer all other templates, unless we have been explicitly
forbidden from doing so. We restore the source position here
add_pending_template (d);
goto out;
}
+ /* Tell the repository that D is available in this translation unit
+ -- and see if it is supposed to be instantiated here. */
+ if (TREE_PUBLIC (d) && !DECL_REALLY_EXTERN (d) && !repo_emit_p (d))
+ {
+ /* In a PCH file, despite the fact that the repository hasn't
+ requested instantiation in the PCH it is still possible that
+ an instantiation will be required in a file that includes the
+ PCH. */
+ if (pch_file)
+ add_pending_template (d);
+ /* Instantiate inline functions so that the inliner can do its
+ job, even though we'll not be emitting a copy of this
+ function. */
+ if (!(TREE_CODE (d) == FUNCTION_DECL
+ && flag_inline_trees
+ && DECL_DECLARED_INLINE_P (d)))
+ goto out;
+ }
- need_push = !global_bindings_p ();
+ need_push = !cfun || !global_bindings_p ();
if (need_push)
push_to_top_level ();
+ /* Mark D as instantiated so that recursive calls to
+ instantiate_decl do not try to instantiate it again. */
+ DECL_TEMPLATE_INSTANTIATED (d) = 1;
+
/* Regenerate the declaration in case the template has been modified
by a subsequent redeclaration. */
regenerate_decl_from_template (d, td);
-
+
/* We already set the file and line above. Reset them now in case
- they changed as a result of calling
- regenerate_decl_from_template. */
+ they changed as a result of calling regenerate_decl_from_template. */
input_location = DECL_SOURCE_LOCATION (d);
if (TREE_CODE (d) == VAR_DECL)
/* Clear out DECL_RTL; whatever was there before may not be right
since we've reset the type of the declaration. */
SET_DECL_RTL (d, NULL_RTX);
-
DECL_IN_AGGR_P (d) = 0;
- import_export_decl (d);
- DECL_EXTERNAL (d) = ! DECL_NOT_REALLY_EXTERN (d);
-
- if (DECL_EXTERNAL (d))
- {
- /* The fact that this code is executing indicates that:
-
- (1) D is a template static data member, for which a
- definition is available.
- (2) An implicit or explicit instantiation has occurred.
+ /* Clear DECL_EXTERNAL so that cp_finish_decl will process the
+ initializer. That function will defer actual emission until
+ we have a chance to determine linkage. */
+ DECL_EXTERNAL (d) = 0;
- (3) We are not going to emit a definition of the static
- data member at this time.
-
- This situation is peculiar, but it occurs on platforms
- without weak symbols when performing an implicit
- instantiation. There, we cannot implicitly instantiate a
- defined static data member in more than one translation
- unit, so import_export_decl marks the declaration as
- external; we must rely on explicit instantiation. */
- }
- else
- {
- /* Mark D as instantiated so that recursive calls to
- instantiate_decl do not try to instantiate it again. */
- DECL_TEMPLATE_INSTANTIATED (d) = 1;
- cp_finish_decl (d,
- (!DECL_INITIALIZED_IN_CLASS_P (d)
- ? DECL_INITIAL (d) : NULL_TREE),
- NULL_TREE, 0);
- }
+ /* Enter the scope of D so that access-checking works correctly. */
+ push_nested_class (DECL_CONTEXT (d));
+ cp_finish_decl (d,
+ (!DECL_INITIALIZED_IN_CLASS_P (d)
+ ? DECL_INITIAL (d) : NULL_TREE),
+ NULL_TREE, 0);
+ pop_nested_class ();
}
else if (TREE_CODE (d) == FUNCTION_DECL)
{
tree tmpl_parm;
tree spec_parm;
- /* Mark D as instantiated so that recursive calls to
- instantiate_decl do not try to instantiate it again. */
- DECL_TEMPLATE_INSTANTIATED (d) = 1;
-
/* Save away the current list, in case we are instantiating one
template from within the body of another. */
saved_local_specializations = local_specializations;
NULL);
/* Set up context. */
- import_export_decl (d);
- start_function (NULL_TREE, d, NULL_TREE, SF_PRE_PARSED);
+ start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
/* Create substitution entries for the parameters. */
subst_decl = DECL_TEMPLATE_RESULT (template_for_substitution (d));
tmpl_parm = TREE_CHAIN (tmpl_parm);
spec_parm = TREE_CHAIN (spec_parm);
}
- my_friendly_assert (!spec_parm, 20020813);
+ gcc_assert (!spec_parm);
/* Substitute into the body of the function. */
tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
}
/* Run through the list of templates that we wish we could
- instantiate, and instantiate any we can. */
+ instantiate, and instantiate any we can. RETRIES is the
+ number of times we retry pending template instantiation. */
-int
-instantiate_pending_templates (void)
+void
+instantiate_pending_templates (int retries)
{
tree *t;
tree last = NULL_TREE;
- int instantiated_something = 0;
int reconsider;
-
+ location_t saved_loc = input_location;
+
+ /* Instantiating templates may trigger vtable generation. This in turn
+ may require further template instantiations. We place a limit here
+ to avoid infinite loop. */
+ if (pending_templates && retries >= max_tinst_depth)
+ {
+ cp_error_at ("template instantiation depth exceeds maximum of %d"
+ " (use -ftemplate-depth-NN to increase the maximum)"
+ " instantiating `%+D', possibly from virtual table"
+ " generation",
+ max_tinst_depth, TREE_VALUE (pending_templates));
+ return;
+ }
+
do
{
reconsider = 0;
fn;
fn = TREE_CHAIN (fn))
if (! DECL_ARTIFICIAL (fn))
- instantiate_decl (fn, /*defer_ok=*/0);
+ instantiate_decl (fn, /*defer_ok=*/0,
+ /*undefined_ok=*/0);
if (COMPLETE_TYPE_P (instantiation))
- {
- instantiated_something = 1;
- reconsider = 1;
- }
+ reconsider = 1;
}
if (COMPLETE_TYPE_P (instantiation))
&& !DECL_TEMPLATE_INSTANTIATED (instantiation))
{
instantiation = instantiate_decl (instantiation,
- /*defer_ok=*/0);
+ /*defer_ok=*/0,
+ /*undefined_ok=*/0);
if (DECL_TEMPLATE_INSTANTIATED (instantiation))
- {
- instantiated_something = 1;
- reconsider = 1;
- }
+ reconsider = 1;
}
if (DECL_TEMPLATE_SPECIALIZATION (instantiation)
}
while (reconsider);
- return instantiated_something;
+ input_location = saved_loc;
}
/* Substitute ARGVEC into T, which is a list of initializers for
for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
{
tree value;
-
+ tree 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 (TREE_VALUE (e)),
+ value = tsubst_expr (DECL_INITIAL (decl),
args, tf_error | tf_warning,
NULL_TREE);
/* Give this enumeration constant the correct access. */
- set_current_access_from_decl (TREE_VALUE (e));
+ set_current_access_from_decl (decl);
/* Actually build the enumerator itself. */
- build_enumerator (TREE_PURPOSE (e), value, newtag);
+ build_enumerator (DECL_NAME (decl), value, newtag);
}
finish_enum (newtag);
/* There should be as many levels of arguments as there are levels
of parameters. */
- my_friendly_assert (parm_depth == TMPL_ARGS_DEPTH (targs), 0);
+ gcc_assert (parm_depth == TMPL_ARGS_DEPTH (targs));
fn_type = TREE_TYPE (tmpl);
specialized or not. */
push_access_scope (decl);
+ ++processing_template_decl;
/* Now, do the (partial) substitution to figure out the
appropriate function type. */
fn_type = tsubst (fn_type, partial_args, tf_error, NULL_TREE);
+ --processing_template_decl;
/* Substitute into the template parameters to obtain the real
innermost set of parameters. This step is important if the
return 0;
else if (POINTER_TYPE_P (type))
return 0;
- else if (TYPE_PTRMEM_P (type))
- return 0;
- else if (TYPE_PTRMEMFUNC_P (type))
+ else if (TYPE_PTR_TO_MEMBER_P (type))
return 0;
else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
return 0;
A type is dependent if it is:
- -- a template parameter. */
- if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+ -- a template parameter. Template template parameters are
+ types for us (since TYPE_P holds true for them) so we
+ handle them here. */
+ if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
return true;
/* -- a qualified-id with a nested-name-specifier which contains a
class-name that names a dependent type or whose unqualified-id
dependent. */
type = TYPE_MAIN_VARIANT (type);
/* -- a compound type constructed from any dependent type. */
- if (TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (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
(type)));
return true;
return dependent_type_p (TREE_TYPE (type));
}
+
/* -- a template-id in which either the template name is a template
- parameter or any of the template arguments is a dependent type or
- an expression that is type-dependent or value-dependent.
-
- This language seems somewhat confused; for example, it does not
- discuss template template arguments. Therefore, we use the
- definition for dependent template arguments in [temp.dep.temp]. */
- if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INFO (type)
- && (dependent_template_id_p
- (CLASSTYPE_TI_TEMPLATE (type),
- CLASSTYPE_TI_ARGS (type))))
+ parameter ... */
+ if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
return true;
- else 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
+ (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:
return TYPE_DEPENDENT_P (type);
}
+/* Returns TRUE if EXPRESSION is dependent, according to CRITERION. */
+
+static bool
+dependent_scope_ref_p (tree expression, bool criterion (tree))
+{
+ tree scope;
+ tree name;
+
+ gcc_assert (TREE_CODE (expression) == SCOPE_REF);
+
+ if (!TYPE_P (TREE_OPERAND (expression, 0)))
+ return true;
+
+ scope = TREE_OPERAND (expression, 0);
+ name = TREE_OPERAND (expression, 1);
+
+ /* [temp.dep.expr]
+
+ An id-expression is type-dependent if it contains a
+ nested-name-specifier that contains a class-name that names a
+ dependent type. */
+ /* 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)
+ && currently_open_class (scope)
+ && !criterion (name))
+ return false;
+ if (dependent_type_p (scope))
+ return true;
+
+ return false;
+}
+
/* Returns TRUE if the EXPRESSION is value-dependent, in the sense of
[temp.dep.constexpr] */
return false;
/* A name declared with a dependent type. */
- if (TREE_CODE (expression) == LOOKUP_EXPR
+ if (TREE_CODE (expression) == IDENTIFIER_NODE
|| (DECL_P (expression)
&& type_dependent_expression_p (expression)))
return true;
|| TREE_CODE (expression) == REINTERPRET_CAST_EXPR
|| TREE_CODE (expression) == CAST_EXPR)
{
- if (dependent_type_p (TREE_TYPE (expression)))
+ 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)
{
do
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 (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expression))))
if (expression == error_mark_node)
return false;
+
+ /* 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
return dependent_type_p (type);
}
- /* [temp.dep.expr]
-
- An id-expression is type-dependent if it contains a
- nested-name-specifier that contains a class-name that names a
- dependent type. */
if (TREE_CODE (expression) == SCOPE_REF
- && TYPE_P (TREE_OPERAND (expression, 0)))
- {
- tree scope;
- tree name;
-
- scope = TREE_OPERAND (expression, 0);
- name = TREE_OPERAND (expression, 1);
-
- /* 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)
- && currently_open_class (scope)
- && !type_dependent_expression_p (name))
- return false;
- if (dependent_type_p (scope))
- return true;
- }
+ && dependent_scope_ref_p (expression,
+ type_dependent_expression_p))
+ return true;
if (TREE_CODE (expression) == FUNCTION_DECL
&& DECL_LANG_SPECIFIC (expression)
&& DECL_TEMPLATE_INFO (expression)
- && (dependent_template_id_p
- (DECL_TI_TEMPLATE (expression),
- INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression)))))
+ && (any_dependent_template_arguments_p
+ (INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression)))))
return true;
+ if (TREE_CODE (expression) == TEMPLATE_DECL
+ && !DECL_TEMPLATE_TEMPLATE_PARM_P (expression))
+ return false;
+
if (TREE_TYPE (expression) == unknown_type_node)
{
if (TREE_CODE (expression) == ADDR_EXPR)
return type_dependent_expression_p (TREE_OPERAND (expression, 0));
+ if (TREE_CODE (expression) == COMPONENT_REF
+ || TREE_CODE (expression) == OFFSET_REF)
+ {
+ if (type_dependent_expression_p (TREE_OPERAND (expression, 0)))
+ return true;
+ expression = TREE_OPERAND (expression, 1);
+ if (TREE_CODE (expression) == IDENTIFIER_NODE)
+ return false;
+ }
+ /* 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 (TREE_OPERAND (expression,
- 1)))
+ if (any_dependent_template_arguments_p
+ (TREE_OPERAND (expression, 1)))
return true;
expression = TREE_OPERAND (expression, 0);
}
- if (TREE_CODE (expression) == OVERLOAD)
+ gcc_assert (TREE_CODE (expression) == OVERLOAD);
+
+ while (expression)
{
- while (expression)
- {
- if (type_dependent_expression_p (OVL_CURRENT (expression)))
- return true;
- expression = OVL_NEXT (expression);
- }
- return false;
+ if (type_dependent_expression_p (OVL_CURRENT (expression)))
+ return true;
+ expression = OVL_NEXT (expression);
}
- abort ();
+ return false;
}
return (dependent_type_p (TREE_TYPE (expression)));
bool
any_dependent_template_arguments_p (tree args)
{
+ int i;
+ int j;
+
if (!args)
return false;
- my_friendly_assert (TREE_CODE (args) == TREE_LIST
- || TREE_CODE (args) == TREE_VEC,
- 20030707);
-
- if (TREE_CODE (args) == TREE_LIST)
- {
- while (args)
- {
- if (dependent_template_arg_p (TREE_VALUE (args)))
- return true;
- args = TREE_CHAIN (args);
- }
- }
- else
+ for (i = 0; i < TMPL_ARGS_DEPTH (args); ++i)
{
- int i;
- for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
- if (dependent_template_arg_p (TREE_VEC_ELT (args, i)))
+ tree level = TMPL_ARGS_LEVEL (args, i + 1);
+ for (j = 0; j < TREE_VEC_LENGTH (level); ++j)
+ if (dependent_template_arg_p (TREE_VEC_ELT (level, j)))
return true;
}
bool
dependent_template_p (tree tmpl)
{
+ if (TREE_CODE (tmpl) == OVERLOAD)
+ {
+ while (tmpl)
+ {
+ if (dependent_template_p (OVL_FUNCTION (tmpl)))
+ return true;
+ tmpl = OVL_CHAIN (tmpl);
+ }
+ return false;
+ }
+
/* Template template parameters are dependent. */
if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)
|| TREE_CODE (tmpl) == TEMPLATE_TEMPLATE_PARM)
return true;
- /* So are qualified names that have not been looked up. */
- if (TREE_CODE (tmpl) == SCOPE_REF)
+ /* So are names that have not been looked up. */
+ if (TREE_CODE (tmpl) == SCOPE_REF
+ || TREE_CODE (tmpl) == IDENTIFIER_NODE)
return true;
/* So are member templates of dependent classes. */
if (TYPE_P (CP_DECL_CONTEXT (tmpl)))
tree name;
tree decl;
int quals;
+ bool pop_p;
- my_friendly_assert (TREE_CODE (type) == TYPENAME_TYPE,
- 20010702);
+ gcc_assert (TREE_CODE (type) == TYPENAME_TYPE);
scope = TYPE_CONTEXT (type);
name = TYPE_IDENTIFIER (type);
/* Enter the SCOPE so that name lookup will be resolved as if we
were in the class definition. In particular, SCOPE will no
longer be considered a dependent type. */
- push_scope (scope);
+ pop_p = 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. */
args = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 1);
/* Instantiate the template. */
type = lookup_template_class (tmpl, args, NULL_TREE, NULL_TREE,
- /*entering_scope=*/0,
- tf_error);
+ /*entering_scope=*/0, tf_error | tf_user);
}
else
type = error_mark_node;
if (type != error_mark_node && quals)
type = cp_build_qualified_type (type, quals);
/* Leave the SCOPE. */
- pop_scope (scope);
+ if (pop_p)
+ pop_scope (scope);
return type;
}
tree
build_non_dependent_expr (tree expr)
{
+ tree inner_expr;
+
/* 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. */
- if (TREE_CODE (expr) == OVERLOAD)
+ 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)
+ return expr;
+ /* Preserve string constants; conversions from string constants to
+ "char *" are allowed, even though normally a "const char *"
+ cannot be used to initialize a "char *". */
+ if (TREE_CODE (expr) == STRING_CST)
return expr;
+ /* Preserve arithmetic constants, as an optimization -- there is no
+ reason to create a new node. */
+ if (TREE_CODE (expr) == INTEGER_CST || TREE_CODE (expr) == REAL_CST)
+ return expr;
+ /* Preserve THROW_EXPRs -- all throw-expressions have type "void".
+ There is at least one place where we want to know that a
+ particular expression is a throw-expression: when checking a ?:
+ expression, there are special rules if the second or third
+ argument is a throw-expression. */
+ if (TREE_CODE (expr) == THROW_EXPR)
+ return expr;
+
+ if (TREE_CODE (expr) == COND_EXPR)
+ return build3 (COND_EXPR,
+ TREE_TYPE (expr),
+ TREE_OPERAND (expr, 0),
+ (TREE_OPERAND (expr, 1)
+ ? build_non_dependent_expr (TREE_OPERAND (expr, 1))
+ : build_non_dependent_expr (TREE_OPERAND (expr, 0))),
+ build_non_dependent_expr (TREE_OPERAND (expr, 2)));
+ if (TREE_CODE (expr) == COMPOUND_EXPR
+ && !COMPOUND_EXPR_OVERLOADED (expr))
+ return build2 (COMPOUND_EXPR,
+ TREE_TYPE (expr),
+ TREE_OPERAND (expr, 0),
+ build_non_dependent_expr (TREE_OPERAND (expr, 1)));
+
/* Otherwise, build a NON_DEPENDENT_EXPR.
REFERENCE_TYPEs are not stripped for expressions in templates
the expression so that mangling (say) "f<g>" inside the body of
"f" works out correctly. Therefore, the REFERENCE_TYPE is
stripped here. */
- return build (NON_DEPENDENT_EXPR, non_reference (TREE_TYPE (expr)));
+ return build1 (NON_DEPENDENT_EXPR, non_reference (TREE_TYPE (expr)), expr);
}
/* ARGS is a TREE_LIST of expressions as arguments to a function call.