/* 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. */
static tree try_class_unification (tree, tree, tree, tree);
static int coerce_template_template_parms (tree, tree, tsubst_flags_t,
tree, tree);
-static tree determine_specialization (tree, tree, tree *, int);
+static tree determine_specialization (tree, tree, tree *, int, int);
static int template_args_equal (tree, tree);
static void tsubst_default_arguments (tree);
static tree for_each_template_parm_r (tree *, int *, void *);
static void
push_access_scope (tree t)
{
- my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL
- || TREE_CODE (t) == VAR_DECL,
- 0);
+ gcc_assert (TREE_CODE (t) == FUNCTION_DECL
+ || TREE_CODE (t) == VAR_DECL);
if (DECL_CLASS_SCOPE_P (t))
push_nested_class (DECL_CONTEXT (t));
if (decl == error_mark_node)
return error_mark_node;
- my_friendly_assert (DECL_P (decl), 20020812);
+ gcc_assert (DECL_P (decl));
if (TREE_CODE (decl) == TYPE_DECL)
{
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;
}
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));
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
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. */
{
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)
{
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
- && DECL_DESTRUCTOR_P (decl))
+ else if (TREE_CODE (decl) == FUNCTION_DECL)
{
- /* [temp.mem]
-
- A destructor shall not be a member template. */
- error ("destructor `%D' declared as member template", decl);
- return error_mark_node;
+ if (DECL_DESTRUCTOR_P (decl))
+ {
+ /* [temp.mem]
+
+ A destructor shall not be a member template. */
+ error ("destructor `%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.
conversions (_conv.integral_) are applied. */
if (!INTEGRAL_TYPE_P (expr_type))
return error_mark_node;
-
+
+ /* [conv.integral] does not allow conversions between two different
+ enumeration types. */
+ if (TREE_CODE (type) == ENUMERAL_TYPE
+ && TREE_CODE (expr_type) == ENUMERAL_TYPE
+ && !same_type_ignoring_top_level_qualifiers_p (type, expr_type))
+ return error_mark_node;
+
/* It's safe to call digest_init in this case; we know we're
just converting one integral constant expression to another. */
expr = digest_init (type, expr, (tree*) 0);
expr = build_unary_op (ADDR_EXPR, fn, 0);
- my_friendly_assert (same_type_p (type, TREE_TYPE (expr)),
- 0);
+ gcc_assert (same_type_p (type, TREE_TYPE (expr)));
return expr;
}
else
if (TREE_CODE (expr) == NOP_EXPR
&& TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR)
STRIP_NOPS (expr);
- my_friendly_assert (TREE_CODE (expr) == ADDR_EXPR, 20000604);
+ gcc_assert (TREE_CODE (expr) == ADDR_EXPR);
expr = TREE_OPERAND (expr, 0);
expr_type = TREE_TYPE (expr);
}
goto bad_argument;
}
- my_friendly_assert (same_type_p (type_referred_to,
- TREE_TYPE (fn)),
- 0);
-
+ gcc_assert (same_type_p (type_referred_to, TREE_TYPE (fn)));
expr = fn;
}
else
case RECORD_TYPE:
{
- my_friendly_assert (TYPE_PTRMEMFUNC_P (type), 20010112);
+ gcc_assert (TYPE_PTRMEMFUNC_P (type));
/* For a non-type template-parameter of type pointer to member
function, no conversions apply. If the template-argument
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);
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;
}
}
else
- val = groktypename (arg);
+ val = arg;
}
else
{
if (i < nargs)
arg = TREE_VEC_ELT (inner_args, i);
else if (require_all_arguments)
- /* There must be a default arg in this case. */
+ /* There must be a default arg in this case. */
arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,
complain, in_decl);
else
break;
- my_friendly_assert (arg, 20030727);
+ gcc_assert (arg);
if (arg == error_mark_node)
error ("template argument %d is invalid", i + 1);
else
ccat ('<');
nparms = TREE_VEC_LENGTH (parms);
arglist = INNERMOST_TEMPLATE_ARGS (arglist);
- my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268);
+ gcc_assert (nparms == TREE_VEC_LENGTH (arglist));
for (i = 0; i < nparms; i++)
{
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
{
/* The template may be defined in a namespace, or
may be a member template. */
- my_friendly_assert (TREE_CODE (context) == NAMESPACE_DECL
- || CLASS_TYPE_P (context),
- 980422);
- cat(decl_as_string (DECL_CONTEXT (arg), TFF_PLAIN_IDENTIFIER));
- cat("::");
+ gcc_assert (TREE_CODE (context) == NAMESPACE_DECL
+ || CLASS_TYPE_P (context));
+ cat (decl_as_string (DECL_CONTEXT (arg),
+ TFF_PLAIN_IDENTIFIER));
+ cat ("::");
}
cat (IDENTIFIER_POINTER (DECL_NAME (arg)));
}
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);
/* No need to check arglist against parmlist here; we did that
in coerce_template_parms, called from lookup_template_class. */
if (fns == error_mark_node || arglist == error_mark_node)
return error_mark_node;
- my_friendly_assert (!arglist || TREE_CODE (arglist) == TREE_VEC, 20030726);
+ gcc_assert (!arglist || TREE_CODE (arglist) == TREE_VEC);
if (fns == NULL_TREE
|| TREE_CODE (fns) == FUNCTION_DECL)
{
return error_mark_node;
}
- my_friendly_assert (TREE_CODE (fns) == TEMPLATE_DECL
- || TREE_CODE (fns) == OVERLOAD
- || BASELINK_P (fns)
- || TREE_CODE (fns) == IDENTIFIER_NODE,
- 20020730);
+ gcc_assert (TREE_CODE (fns) == TEMPLATE_DECL
+ || TREE_CODE (fns) == OVERLOAD
+ || BASELINK_P (fns)
+ || TREE_CODE (fns) == IDENTIFIER_NODE);
if (BASELINK_P (fns))
{
- BASELINK_FUNCTIONS (fns) = build (TEMPLATE_ID_EXPR,
- unknown_type_node,
- BASELINK_FUNCTIONS (fns),
- arglist);
+ BASELINK_FUNCTIONS (fns) = build2 (TEMPLATE_ID_EXPR,
+ unknown_type_node,
+ BASELINK_FUNCTIONS (fns),
+ arglist);
return fns;
}
if (TREE_CODE (fns) == OVERLOAD || !type)
type = unknown_type_node;
- return build (TEMPLATE_ID_EXPR, type, fns, arglist);
+ return build2 (TEMPLATE_ID_EXPR, type, fns, arglist);
}
/* Within the scope of a template class S<T>, the name S gets bound
if (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)
}
/* 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)
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;
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
{
/* 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));
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. */
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. */
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))
+
+ /* 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 base_list = NULL_TREE;
- tree pbases = BINFO_BASETYPES (pbinfo);
- tree paccesses = BINFO_BASEACCESSES (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. */
- push_scope (context ? context : global_namespace);
+ 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);
-
- pop_scope (context ? context : global_namespace);
+ 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
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);
input_location = DECL_SOURCE_LOCATION (t);
if (TREE_CODE (t) == TEMPLATE_DECL)
- processing_template_decl++;
+ ++processing_template_decl;
r = tsubst (t, args, tf_error | tf_warning, NULL_TREE);
if (TREE_CODE (t) == TEMPLATE_DECL)
- processing_template_decl--;
+ --processing_template_decl;
if (TREE_CODE (r) == VAR_DECL)
{
tree init;
--processing_template_decl;
}
else
- /* Build new DECL_FRIENDLIST. */
- add_friend (type, tsubst_friend_function (t, args),
- /*complain=*/false);
+ {
+ /* 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);
-
- /* 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;
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))
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. */
/* 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);
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)
{
/* 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;
else if (IDENTIFIER_OPNAME_P (DECL_NAME (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) = 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;
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);
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;
else
type = TREE_TYPE (t);
- my_friendly_assert (type != unknown_type_node, 20030716);
+ gcc_assert (type != unknown_type_node);
if (type && TREE_CODE (t) != FUNCTION_DECL
&& TREE_CODE (t) != TYPENAME_TYPE
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. */
+ case TREE_VEC:
+ /* A vector of template arguments. */
+ gcc_assert (!type);
return tsubst_template_args (t, args, complain, in_decl);
case POINTER_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
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)
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);
else
expr = name;
- my_friendly_assert (!dependent_type_p (scope), 20030729);
+ if (dependent_type_p (scope))
+ return build_nt (SCOPE_REF, scope, expr);
if (!BASELINK_P (name) && !DECL_P (expr))
{
? DECL_TEMPLATE_RESULT (expr) : expr) == TYPE_DECL)
{
if (complain & tf_error)
- error ("`%E' names a type, but a non-type is expected",
- qualified_id);
+ {
+ 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;
}
}
if (DECL_P (expr))
- check_accessibility_of_qualified_id (expr, /*object_type=*/NULL_TREE,
- scope);
-
- /* Remember that there was a reference to this entity. */
- if (DECL_P (expr))
{
+ 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)
expr = lookup_template_function (expr, template_args);
if (expr == error_mark_node && complain & tf_error)
- qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1));
+ qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1),
+ expr);
else if (TYPE_P (scope))
{
expr = (adjust_result_of_qualified_name_lookup
{
case PARM_DECL:
r = retrieve_local_specialization (t);
- my_friendly_assert (r != NULL, 20020903);
+ gcc_assert (r != NULL);
+ mark_used (r);
return r;
case CONST_DECL:
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:
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:
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 | tf_stmt_expr_cmpd, in_decl);
- return finish_stmt_expr (stmt_expr, false);
- }
-
- 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;
}
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;
- tsubst_flags_t stmt_expr
- = complain & (tf_stmt_expr_cmpd | tf_stmt_expr_body);
- complain ^= stmt_expr;
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,
- /*function_p=*/false);
-
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 EXPR_STMT:
+ case STMT_EXPR:
{
- tree r;
-
- prep_stmt (t);
+ tree old_stmt_expr = cur_stmt_expr;
+ tree stmt_expr = begin_stmt_expr ();
- r = tsubst_expr (EXPR_STMT_EXPR (t), args, complain, in_decl);
- if (stmt_expr & tf_stmt_expr_body && !TREE_CHAIN (t))
- finish_stmt_expr_expr (r);
- else
- finish_expr_stmt (r);
- break;
+ cur_stmt_expr = stmt_expr;
+ tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl);
+ stmt_expr = finish_stmt_expr (stmt_expr, false);
+ cur_stmt_expr = old_stmt_expr;
+
+ return stmt_expr;
}
+ case EXPR_STMT:
+ tmp = tsubst_expr (EXPR_STMT_EXPR (t), args, complain, in_decl);
+ if (EXPR_STMT_STMT_EXPR_RESULT (t))
+ 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)
decl = lookup_qualified_name (scope, name,
/*is_type_p=*/false,
/*complain=*/false);
- if (decl == error_mark_node)
- qualified_name_lookup_error (scope, name);
+ if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
+ qualified_name_lookup_error (scope, name, decl);
else
- do_local_using_decl (decl);
+ do_local_using_decl (decl, scope, name);
}
else
{
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);
+ 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 = THEN_CLAUSE (t), tmp)
- {
- tsubst_expr (tmp, 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 | ((stmt_expr & tf_stmt_expr_cmpd) << 1),
- 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 (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 | stmt_expr, in_decl);
+ return NULL_TREE;
}
/* T is a postfix-expression that is not being used in a function
{
case USING_DECL:
t = DECL_NAME (t);
- /* Fallthrough. */
+ /* Fall through. */
case IDENTIFIER_NODE:
{
tree decl;
cp_id_kind idk;
tree qualifying_class;
- bool non_constant_expression_p;
+ bool non_integral_constant_expression_p;
const char *error_msg;
if (IDENTIFIER_TYPENAME_P (t))
decl = finish_id_expression (t, decl, NULL_TREE,
&idk,
&qualifying_class,
- /*constant_expression_p=*/false,
- /*allow_non_constant_expression_p=*/false,
- &non_constant_expression_p,
+ /*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);
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 (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),
return build_x_binary_op
(TREE_CODE (t),
RECUR (TREE_OPERAND (t, 0)),
- RECUR (TREE_OPERAND (t, 1)));
+ 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, RECUR (TREE_OPERAND (t, 1)));
+ return build_nt (ARRAY_REF, NULL_TREE, RECUR (TREE_OPERAND (t, 1)),
+ NULL_TREE, NULL_TREE);
op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
args, complain, in_decl);
return cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t));
case MODOP_EXPR:
- return build_x_modify_expr
- (RECUR (TREE_OPERAND (t, 0)),
- TREE_CODE (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2)));
+ {
+ tree r = build_x_modify_expr
+ (RECUR (TREE_OPERAND (t, 0)),
+ TREE_CODE (TREE_OPERAND (t, 1)),
+ RECUR (TREE_OPERAND (t, 2)));
+ /* TREE_NO_WARNING must be set if either the expression was
+ parenthesized or it uses an operator such as >>= rather
+ than plain assignment. In the former case, it was already
+ set and must be copied. In the latter case,
+ build_x_modify_expr sets it and it must not be reset
+ here. */
+ if (TREE_NO_WARNING (t))
+ TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
+ return r;
+ }
case ARROW_EXPR:
op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
(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:
}
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)
- || DECL_P (function)
|| TREE_CODE (function) == IDENTIFIER_NODE))
function = perform_koenig_lookup (function, call_args);
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,
koenig_p);
args);
else
{
- qualified_name_lookup_error (TREE_TYPE (object), tmpl);
+ qualified_name_lookup_error (TREE_TYPE (object), tmpl,
+ member);
return error_mark_node;
}
}
+ else if (TREE_CODE (member) == SCOPE_REF
+ && !CLASS_TYPE_P (TREE_OPERAND (member, 0))
+ && TREE_CODE (TREE_OPERAND (member, 0)) != NAMESPACE_DECL)
+ {
+ if (complain & tf_error)
+ {
+ if (TYPE_P (TREE_OPERAND (member, 0)))
+ error ("`%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);
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:
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;
}
deferring all checks until we have the FUNCTION_DECL. */
push_deferring_access_checks (dk_deferred);
- /* substitute template parameters */
+ /* Substitute template parameters. */
fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
targ_ptr, complain, gen_tmpl);
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)
}
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (TREE_CODE (*parm) != REFERENCE_TYPE)
tree parms, args;
int len;
- my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
- my_friendly_assert (xparms == NULL_TREE
- || TREE_CODE (xparms) == TREE_LIST, 290);
- my_friendly_assert (!xargs || TREE_CODE (xargs) == TREE_LIST, 291);
- my_friendly_assert (ntparms > 0, 292);
+ gcc_assert (TREE_CODE (tparms) == TREE_VEC);
+ gcc_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST);
+ gcc_assert (!xargs || TREE_CODE (xargs) == TREE_LIST);
+ gcc_assert (ntparms > 0);
switch (strict)
{
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (xlen == 0)
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)
}
}
}
- else if (TREE_CODE (arg) == OVERLOAD
- || TREE_CODE (arg) == FUNCTION_DECL)
+ else
{
+ gcc_assert (TREE_CODE (arg) == OVERLOAD
+ || TREE_CODE (arg) == FUNCTION_DECL);
+
for (; arg; arg = OVL_NEXT (arg))
good += try_one_overload (tparms, targs, tempargs, parm,
TREE_TYPE (OVL_CURRENT (arg)),
strict, sub_strict, addr_p);
}
- else
- abort ();
/* [temp.deduct.type] A template-argument can be deduced from a pointer
to function or pointer to member function argument if the set of
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;
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)
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
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;
+ /* 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),
add_outermost_template_args (full_args, TREE_PURPOSE (pat2)));
if (targs)
add_outermost_template_args (full_args, TREE_PURPOSE (pat1)));
if (targs)
++winner;
+ --processing_template_decl;
return winner;
}
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),
/* 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. */
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
/* We may be in the middle of deferred access check. Disable it now. */
push_deferring_access_checks (dk_no_deferred);
- /* Our caller does not expect collection to happen, which it might if
- we decide to compile the function to rtl now. Arrange for a new
- gc context to be created if so. */
- function_depth++;
-
/* Set TD to the template whose DECL_TEMPLATE_RESULT is the pattern
for the instantiation. */
td = template_for_substitution (d);
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.
- (3) We are not going to emit a definition of the static
- data member at this time.
+ /* 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;
- 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,
input_location = saved_loc;
pop_deferring_access_checks ();
pop_tinst_level ();
- function_depth--;
timevar_pop (TV_PARSE);
}
/* 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
/* 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
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
if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
return true;
/* ... or any of the template arguments is a dependent type or
- an expression that is type-dependent or value-dependent. */
+ 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)))))
tree scope;
tree name;
- my_friendly_assert (TREE_CODE (expression) == SCOPE_REF, 20030714);
+ gcc_assert (TREE_CODE (expression) == SCOPE_REF);
if (!TYPE_P (TREE_OPERAND (expression, 0)))
return true;
|| 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
}
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))))
(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)
+ if (TREE_CODE (expression) == COMPONENT_REF
+ || TREE_CODE (expression) == OFFSET_REF)
{
if (type_dependent_expression_p (TREE_OPERAND (expression, 0)))
return true;
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
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)));
any_dependent_template_arguments_p (tree args)
{
int i;
-
+ int j;
+
if (!args)
return false;
- for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
- if (dependent_template_arg_p (TREE_VEC_ELT (args, i)))
- return true;
+ for (i = 0; i < TMPL_ARGS_DEPTH (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;
+ }
return false;
}
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. */
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 build (COND_EXPR,
- TREE_TYPE (expr),
- TREE_OPERAND (expr, 0),
- build_non_dependent_expr (TREE_OPERAND (expr, 1)),
- build_non_dependent_expr (TREE_OPERAND (expr, 2)));
+ return build3 (COND_EXPR,
+ TREE_TYPE (expr),
+ TREE_OPERAND (expr, 0),
+ (TREE_OPERAND (expr, 1)
+ ? build_non_dependent_expr (TREE_OPERAND (expr, 1))
+ : build_non_dependent_expr (TREE_OPERAND (expr, 0))),
+ build_non_dependent_expr (TREE_OPERAND (expr, 2)));
if (TREE_CODE (expr) == COMPOUND_EXPR
&& !COMPOUND_EXPR_OVERLOADED (expr))
- return build (COMPOUND_EXPR,
- TREE_TYPE (expr),
- TREE_OPERAND (expr, 0),
- build_non_dependent_expr (TREE_OPERAND (expr, 1)));
+ return build2 (COMPOUND_EXPR,
+ TREE_TYPE (expr),
+ TREE_OPERAND (expr, 0),
+ build_non_dependent_expr (TREE_OPERAND (expr, 1)));
/* Otherwise, build a NON_DEPENDENT_EXPR.