#include "rtl.h"
#include "timevar.h"
#include "tree-iterator.h"
+#include "vecprim.h"
/* The type of functions taking a tree, and some additional data, and
returning an int. */
static int template_header_count;
static GTY(()) tree saved_trees;
-static GTY(()) varray_type inline_parm_levels;
-static size_t inline_parm_levels_used;
+static VEC(int,heap) *inline_parm_levels;
static GTY(()) tree current_tinst_level;
unification_kind_t, int, bool);
static int unify (tree, tree, tree, tree, int);
static void add_pending_template (tree);
+static int push_tinst_level (tree);
+static void pop_tinst_level (void);
static void reopen_tinst_level (tree);
static tree classtype_mangled_name (tree);
static char* mangle_class_name_for_template (const char *, tree, tree);
static tree tsubst_initializer_list (tree, tree);
static tree get_class_bindings (tree, tree, tree);
-static tree coerce_template_parms (tree, tree, tree, tsubst_flags_t, int);
+static tree coerce_template_parms (tree, tree, tree, tsubst_flags_t,
+ bool, bool);
static void tsubst_enum (tree, tree, tree);
static tree add_to_template_args (tree, tree);
static tree add_outermost_template_args (tree, tree);
static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
static void regenerate_decl_from_template (tree, tree);
-static tree most_specialized (tree, tree, tree);
static tree most_specialized_class (tree, tree);
static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int);
static tree tsubst_arg_types (tree, tree, tsubst_flags_t, tree);
static tree process_partial_specialization (tree);
static void set_current_access_from_decl (tree);
static void check_default_tmpl_args (tree, tree, int, int);
-static tree tsubst_call_declarator_parms (tree, tree, tsubst_flags_t, tree);
static tree get_template_base (tree, tree, tree, tree);
-static int verify_class_unification (tree, tree, tree);
static tree try_class_unification (tree, tree, tree, tree);
static int coerce_template_template_parms (tree, tree, tsubst_flags_t,
tree, tree);
-static tree determine_specialization (tree, tree, tree *, int, 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 int eq_local_specializations (const void *, const void *);
static bool dependent_type_p_r (tree);
static tree tsubst (tree, tree, tsubst_flags_t, tree);
-static tree tsubst_expr (tree, tree, tsubst_flags_t, tree);
+static tree tsubst_expr (tree, tree, tsubst_flags_t, tree, bool);
static tree tsubst_copy (tree, tree, tsubst_flags_t, tree);
/* Make the current scope suitable for access checking when we are
for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
{
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
+
+ if (parm == error_mark_node)
+ continue;
+
gcc_assert (DECL_P (parm));
switch (TREE_CODE (parm))
/* Remember how many levels of template parameters we pushed so that
we can pop them later. */
- if (!inline_parm_levels)
- VARRAY_INT_INIT (inline_parm_levels, 4, "inline_parm_levels");
- if (inline_parm_levels_used == inline_parm_levels->num_elements)
- VARRAY_GROW (inline_parm_levels, 2 * inline_parm_levels_used);
- VARRAY_INT (inline_parm_levels, inline_parm_levels_used) = levels;
- ++inline_parm_levels_used;
+ VEC_safe_push (int, heap, inline_parm_levels, levels);
}
/* Undo the effects of maybe_begin_member_template_processing. */
maybe_end_member_template_processing (void)
{
int i;
+ int last;
- if (!inline_parm_levels_used)
+ if (VEC_length (int, inline_parm_levels) == 0)
return;
- --inline_parm_levels_used;
- for (i = 0;
- i < VARRAY_INT (inline_parm_levels, inline_parm_levels_used);
- ++i)
+ last = VEC_pop (int, inline_parm_levels);
+ for (i = 0; i < last; ++i)
{
--processing_template_decl;
current_template_parms = TREE_CHAIN (current_template_parms);
tree ns;
/* DR 275: An explicit instantiation shall appear in an enclosing
- namespace of its template. */
+ namespace of its template. */
ns = decl_namespace_context (spec);
if (!is_ancestor (current_namespace, ns))
pedwarn ("explicit instantiation of %qD in namespace %qD "
/* The TYPE is being declared. If it is a template type, that means it
is a partial specialization. Do appropriate error-checking. */
-void
+tree
maybe_process_partial_specialization (tree type)
{
- /* TYPE maybe an ERROR_MARK_NODE. */
- tree context = TYPE_P (type) ? TYPE_CONTEXT (type) : NULL_TREE;
+ tree context;
+
+ if (type == error_mark_node)
+ return error_mark_node;
+
+ if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
+ {
+ error ("name of class shadows template template parameter %qD",
+ TYPE_NAME (type));
+ return error_mark_node;
+ }
+
+ context = TYPE_CONTEXT (type);
if (CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type))
{
}
}
else if (processing_specialization)
- error ("explicit specialization of non-template %qT", type);
+ {
+ error ("explicit specialization of non-template %qT", type);
+ return error_mark_node;
+ }
+
+ return type;
}
/* Returns nonzero if we can optimize the retrieval of specializations
retrieve_specialization (tree tmpl, tree args,
bool class_specializations_p)
{
+ if (args == error_mark_node)
+ return NULL_TREE;
+
gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
/* There should be as many levels of arguments as there are
static tree
retrieve_local_specialization (tree tmpl)
{
- tree spec = htab_find_with_hash (local_specializations, tmpl,
- htab_hash_pointer (tmpl));
+ tree spec = (tree) htab_find_with_hash (local_specializations, tmpl,
+ htab_hash_pointer (tmpl));
return spec ? TREE_PURPOSE (spec) : NULL_TREE;
}
{
error ("specialization of %qD after instantiation",
fn);
- return spec;
+ return error_mark_node;
}
else
{
DECL_INITIAL (fn) = NULL_TREE;
duplicate_decls (spec, fn, is_friend);
/* The call to duplicate_decls will have applied
- [temp.expl.spec]:
+ [temp.expl.spec]:
- An explicit specialization of a function template
+ An explicit specialization of a function template
is inline only if it is explicitly declared to be,
- and independently of whether its function tempalte
+ and independently of whether its function template
is.
to the primary function; now copy the inline bits to
- the various clones. */
+ the various clones. */
FOR_EACH_CLONE (clone, fn)
{
DECL_DECLARED_INLINE_P (clone)
template it is specializing. */
if (DECL_TEMPLATE_SPECIALIZATION (spec)
&& !check_specialization_namespace (tmpl))
- DECL_CONTEXT (spec) = decl_namespace_context (tmpl);
+ DECL_CONTEXT (spec) = FROB_CONTEXT (decl_namespace_context (tmpl));
if (!optimize_specialization_lookup_p (tmpl))
DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
template classes that appeared in the name of the function. See
check_explicit_specialization for a more accurate description.
+ TSK indicates what kind of template declaration (if any) is being
+ declared. TSK_TEMPLATE indicates that the declaration given by
+ DECL, though a FUNCTION_DECL, has template parameters, and is
+ therefore a template function.
+
The template args (those explicitly specified and those deduced)
are output in a newly created vector *TARGS_OUT.
tree decl,
tree* targs_out,
int need_member_template,
- int template_count)
+ int template_count,
+ tmpl_spec_kind tsk)
{
tree fns;
tree targs;
tree explicit_targs;
tree candidates = NULL_TREE;
+ /* A TREE_LIST of templates of which DECL may be a specialization.
+ The TREE_VALUE of each node is a TEMPLATE_DECL. The
+ corresponding TREE_PURPOSE is the set of template arguments that,
+ when used to instantiate the template, would produce a function
+ with the signature of DECL. */
tree templates = NULL_TREE;
int header_count;
struct cp_binding_level *b;
*targs_out = NULL_TREE;
- if (template_id == error_mark_node)
+ if (template_id == error_mark_node || decl == error_mark_node)
return error_mark_node;
fns = TREE_OPERAND (template_id, 0);
if (current_binding_level->kind == sk_template_parms
&& !current_binding_level->explicit_spec_p
&& (TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (fn))
- != TREE_VEC_LENGTH (TREE_VALUE (current_template_parms))))
+ != TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+ (current_template_parms))))
continue;
+ /* Function templates cannot be specializations; there are
+ no partial specializations of functions. Therefore, if
+ the type of DECL does not match FN, there is no
+ match. */
+ if (tsk == tsk_template)
+ {
+ if (compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
+ decl_arg_types))
+ candidates = tree_cons (NULL_TREE, fn, candidates);
+ continue;
+ }
+
/* See whether this function might be a specialization of this
template. */
targs = get_bindings (fn, decl, explicit_targs, /*check_ret=*/true);
the EDG front-end has that behavior, and John Spicer claims
that the committee simply forgot to delete the wording in
[temp.expl.spec]. */
- tree tmpl = most_specialized (templates, decl, explicit_targs);
- if (tmpl && tmpl != error_mark_node)
- {
- targs = get_bindings (tmpl, decl, explicit_targs, /*check_ret=*/true);
- templates = tree_cons (targs, tmpl, NULL_TREE);
- }
+ tree tmpl = most_specialized_instantiation (templates);
+ if (tmpl != error_mark_node)
+ {
+ templates = tmpl;
+ TREE_CHAIN (templates) = NULL_TREE;
+ }
}
if (templates == NULL_TREE && candidates == NULL_TREE)
/* We have one, and exactly one, match. */
if (candidates)
{
+ tree fn = TREE_VALUE (candidates);
+ /* DECL is a re-declaration of a template function. */
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ return fn;
/* It was a specialization of an ordinary member function in a
template class. */
- *targs_out = copy_node (DECL_TI_ARGS (TREE_VALUE (candidates)));
- return DECL_TI_TEMPLATE (TREE_VALUE (candidates));
+ *targs_out = copy_node (DECL_TI_ARGS (fn));
+ return DECL_TI_TEMPLATE (fn);
}
/* It was a specialization of a template. */
/* Find the namespace binding, using the declaration
context. */
- fns = namespace_binding (dname, CP_DECL_CONTEXT (decl));
+ fns = lookup_qualified_name (CP_DECL_CONTEXT (decl), dname,
+ false, true);
if (!fns || !is_overloaded_fn (fns))
{
error ("%qD is not a template function", dname);
fns = error_mark_node;
}
+ else
+ {
+ tree fn = OVL_CURRENT (fns);
+ if (!is_associated_namespace (CP_DECL_CONTEXT (decl),
+ CP_DECL_CONTEXT (fn)))
+ error ("%qD is not declared in %qD",
+ decl, current_namespace);
+ }
}
declarator = lookup_template_function (fns, NULL_TREE);
tmpl = determine_specialization (declarator, decl,
&targs,
member_specialization,
- template_count);
+ template_count,
+ tsk);
if (!tmpl || tmpl == error_mark_node)
/* We couldn't figure out what this declaration was
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,
- not the specialization of it. */
+ template class, we want to return the TEMPLATE_DECL, not
+ the specialization of it. */
if (tsk == tsk_template)
{
SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
template it specializes. */
TREE_PRIVATE (decl) = TREE_PRIVATE (gen_tmpl);
TREE_PROTECTED (decl) = TREE_PROTECTED (gen_tmpl);
- /* The specialization has the same visibility as the
- template it specializes. */
- if (DECL_VISIBILITY_SPECIFIED (gen_tmpl))
- {
- DECL_VISIBILITY_SPECIFIED (decl) = 1;
- DECL_VISIBILITY (decl) = DECL_VISIBILITY (gen_tmpl);
- }
+
/* If DECL is a friend declaration, declared using an
unqualified name, the namespace associated with DECL may
have been set incorrectly. For example, in:
-
- template <typename T> void f(T);
- namespace N {
- struct S { friend void f<int>(int); }
- }
-
- we will have set the DECL_CONTEXT for the friend
- declaration to N, rather than to the global namespace. */
+
+ template <typename T> void f(T);
+ namespace N {
+ struct S { friend void f<int>(int); }
+ }
+
+ we will have set the DECL_CONTEXT for the friend
+ declaration to N, rather than to the global namespace. */
if (DECL_NAMESPACE_SCOPE_P (decl))
DECL_CONTEXT (decl) = DECL_CONTEXT (tmpl);
for (i = 0; i < TREE_VEC_LENGTH (t2); ++i)
{
- tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i));
- tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i));
+ tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i));
+ tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i));
+
+ /* If either of the template parameters are invalid, assume
+ they match for the sake of error recovery. */
+ if (parm1 == error_mark_node || parm2 == error_mark_node)
+ return 1;
if (TREE_CODE (parm1) != TREE_CODE (parm2))
return 0;
return TEMPLATE_PARM_DESCENDANTS (index);
}
-/* Process information from new template parameter NEXT and append it to the
+/* Process information from new template parameter PARM and append it to the
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, bool is_non_type)
+process_template_parm (tree list, tree parm, bool is_non_type)
{
- tree parm;
tree decl = 0;
tree defval;
- int idx;
+ tree err_parm_list;
+ int idx = 0;
- parm = next;
gcc_assert (TREE_CODE (parm) == TREE_LIST);
defval = TREE_PURPOSE (parm);
if (list)
{
- tree p = TREE_VALUE (tree_last (list));
+ tree p = tree_last (list);
+
+ if (p && TREE_VALUE (p) != error_mark_node)
+ {
+ p = TREE_VALUE (p);
+ if (TREE_CODE (p) == TYPE_DECL || TREE_CODE (p) == TEMPLATE_DECL)
+ idx = TEMPLATE_TYPE_IDX (TREE_TYPE (p));
+ else
+ idx = TEMPLATE_PARM_IDX (DECL_INITIAL (p));
+ }
- if (TREE_CODE (p) == TYPE_DECL || TREE_CODE (p) == TEMPLATE_DECL)
- idx = TEMPLATE_TYPE_IDX (TREE_TYPE (p));
- else
- idx = TEMPLATE_PARM_IDX (DECL_INITIAL (p));
++idx;
}
else
SET_DECL_TEMPLATE_PARM_P (parm);
- /* [temp.param]
-
- The top-level cv-qualifiers on the template-parameter are
- ignored when determining its type. */
- TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
+ if (TREE_TYPE (parm) == error_mark_node)
+ {
+ err_parm_list = build_tree_list (defval, parm);
+ TREE_VALUE (err_parm_list) = error_mark_node;
+ return chainon (list, err_parm_list);
+ }
+ else
+ {
+ /* [temp.param]
+
+ The top-level cv-qualifiers on the template-parameter are
+ ignored when determining its type. */
+ TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
+ if (invalid_nontype_parm_type_p (TREE_TYPE (parm), 1))
+ {
+ err_parm_list = build_tree_list (defval, parm);
+ TREE_VALUE (err_parm_list) = error_mark_node;
+ return chainon (list, err_parm_list);
+ }
+ }
/* A template parameter is not modifiable. */
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) = 1;
TREE_INVARIANT (decl) = 1;
/* Given a template argument vector containing the template PARMS.
The innermost PARMS are given first. */
-tree
+static tree
current_template_args (void)
{
tree header;
{
t = TREE_VALUE (t);
- if (TREE_CODE (t) == TYPE_DECL
- || TREE_CODE (t) == TEMPLATE_DECL)
- t = TREE_TYPE (t);
- else
- t = DECL_INITIAL (t);
+ if (t != error_mark_node)
+ {
+ if (TREE_CODE (t) == TYPE_DECL
+ || TREE_CODE (t) == TEMPLATE_DECL)
+ t = TREE_TYPE (t);
+ else
+ t = DECL_INITIAL (t);
+ }
+
TREE_VEC_ELT (a, i) = t;
}
}
or some such would have been OK. */
tpd.level = TMPL_PARMS_DEPTH (current_template_parms);
- tpd.parms = alloca (sizeof (int) * ntparms);
+ tpd.parms = (int *) alloca (sizeof (int) * ntparms);
memset (tpd.parms, 0, sizeof (int) * ntparms);
- tpd.arg_uses_template_parms = alloca (sizeof (int) * nargs);
+ tpd.arg_uses_template_parms = (int *) alloca (sizeof (int) * nargs);
memset (tpd.arg_uses_template_parms, 0, sizeof (int) * nargs);
for (i = 0; i < nargs; ++i)
{
{
/* We haven't yet initialized TPD2. Do so now. */
tpd2.arg_uses_template_parms
- = alloca (sizeof (int) * nargs);
+ = (int *) alloca (sizeof (int) * nargs);
/* The number of parameters here is the number in the
main template, which, as checked in the assertion
above, is NARGS. */
- tpd2.parms = alloca (sizeof (int) * nargs);
+ tpd2.parms = (int *) alloca (sizeof (int) * nargs);
tpd2.level =
TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (maintmpl));
}
return decl;
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)
- = tree_cons (inner_args, inner_parms,
+ = tree_cons (specargs, inner_parms,
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
return decl;
for (i = 0; i < ntparms; ++i)
{
tree parm = TREE_VEC_ELT (inner_parms, i);
+
+ if (parm == error_mark_node)
+ continue;
+
if (TREE_PURPOSE (parm))
seen_def_arg_p = 1;
else if (seen_def_arg_p)
ntparms = TREE_VEC_LENGTH (inner_parms);
for (i = 0; i < ntparms; ++i)
- if (TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)))
- {
- if (msg)
- {
- error (msg, decl);
- msg = 0;
- }
+ {
+ if (TREE_VEC_ELT (inner_parms, i) == error_mark_node)
+ continue;
- /* Clear out the default argument so that we are not
- confused later. */
- TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)) = NULL_TREE;
- }
+ if (TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)))
+ {
+ if (msg)
+ {
+ error (msg, decl);
+ msg = 0;
+ }
+
+ /* Clear out the default argument so that we are not
+ confused later. */
+ TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)) = NULL_TREE;
+ }
+ }
/* At this point, if we're still interested in issuing messages,
they must apply to classes surrounding the object declared. */
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
/* See if this is a primary template. */
- primary = template_parm_scope_p ();
+ if (is_friend && ctx)
+ /* A friend template that specifies a class context, i.e.
+ template <typename T> friend void A<T>::f();
+ is not primary. */
+ primary = 0;
+ else
+ primary = template_parm_scope_p ();
if (primary)
{
template. ... Template allocation functions shall
have two or more parameters. */
error ("invalid template declaration of %qD", decl);
- return decl;
+ return error_mark_node;
}
}
else if (DECL_IMPLICIT_TYPEDEF_P (decl)
for (i = 0; i < TREE_VEC_LENGTH (tmpl_parms); ++i)
{
- tree tmpl_parm = TREE_VALUE (TREE_VEC_ELT (tmpl_parms, i));
- tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
- tree tmpl_default = TREE_PURPOSE (TREE_VEC_ELT (tmpl_parms, i));
- tree parm_default = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
+ tree tmpl_parm;
+ tree parm;
+ tree tmpl_default;
+ tree parm_default;
+
+ if (TREE_VEC_ELT (tmpl_parms, i) == error_mark_node
+ || TREE_VEC_ELT (parms, i) == error_mark_node)
+ continue;
+
+ tmpl_parm = TREE_VALUE (TREE_VEC_ELT (tmpl_parms, i));
+ parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
+ tmpl_default = TREE_PURPOSE (TREE_VEC_ELT (tmpl_parms, i));
+ parm_default = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
/* 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))))
+ if (tmpl_parm != error_mark_node
+ && (TREE_CODE (tmpl_parm) != TREE_CODE (parm)
+ || (TREE_CODE (tmpl_parm) != TYPE_DECL
+ && !same_type_p (TREE_TYPE (tmpl_parm), TREE_TYPE (parm)))))
{
error ("template parameter %q+#D", tmpl_parm);
error ("redeclared here as %q#D", parm);
/*args=*/NULL_TREE,
tf_error,
/*in_decl=*/NULL_TREE,
- /*function_p=*/false);
+ /*function_p=*/false,
+ /*integral_constant_expression_p=*/true);
processing_template_decl = saved_processing_template_decl;
}
return expr;
initializers can maintain a syntactic rather than semantic form
(even if they are non-dependent, for access-checking purposes). */
-tree
+static tree
fold_decl_constant_value (tree expr)
{
tree const_expr = expr;
fn_no_ptr = fn;
if (TREE_CODE (fn_no_ptr) == ADDR_EXPR)
fn_no_ptr = TREE_OPERAND (fn_no_ptr, 0);
-
+ if (TREE_CODE (fn_no_ptr) == BASELINK)
+ fn_no_ptr = BASELINK_FUNCTIONS (fn_no_ptr);
+
/* [temp.arg.nontype]/1
A template-argument for a non-type, non-template template-parameter
instantiated -- but here we need the resolved form so that we can
convert the argument. */
expr = fold_non_dependent_expr (expr);
+ if (error_operand_p (expr))
+ return error_mark_node;
expr_type = TREE_TYPE (expr);
/* HACK: Due to double coercion, we can get a
if (!constant_address_p)
{
- error ("%qE is not a valid template argument for type %qT "
- "because it is not a constant pointer", expr, type);
- return NULL_TREE;
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is not a constant pointer", expr, type);
+ return NULL_TREE;
}
}
/* [temp.arg.nontype]/5, bullet 3
if (!real_lvalue_p (expr))
{
error ("%qE is not a valid template argument for type %qT "
- "because it is not a lvalue", expr, type);
+ "because it is not an lvalue", expr, type);
return NULL_TREE;
}
vectors of TREE_LIST nodes containing TYPE_DECL, TEMPLATE_DECL
or PARM_DECL.
- ARG_PARMS may contain more parameters than PARM_PARMS. If this is
- the case, then extra parameters must have default arguments.
-
Consider the example:
- template <class T, class Allocator = allocator> class vector;
- template<template <class U> class TT> class C;
+ template <class T> class A;
+ template<template <class U> class TT> class B;
- C<vector> is a valid instantiation. PARM_PARMS for the above code
- contains a TYPE_DECL (for U), ARG_PARMS contains two TYPE_DECLs (for
- T and Allocator) and OUTER_ARGS contains the argument that is used to
- substitute the TT parameter. */
+ For B<A>, PARM_PARMS are the parameters to TT, while ARG_PARMS are
+ the parameters to A, and OUTER_ARGS contains A. */
static int
coerce_template_template_parms (tree parm_parms,
nparms = TREE_VEC_LENGTH (parm_parms);
nargs = TREE_VEC_LENGTH (arg_parms);
- /* The rule here is opposite of coerce_template_parms. */
- if (nargs < nparms
- || (nargs > nparms
- && TREE_PURPOSE (TREE_VEC_ELT (arg_parms, nparms)) == NULL_TREE))
+ if (nargs != nparms)
return 0;
for (i = 0; i < nparms; ++i)
{
+ if (TREE_VEC_ELT (parm_parms, i) == error_mark_node
+ || TREE_VEC_ELT (arg_parms, i) == error_mark_node)
+ continue;
+
parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, i));
arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
tree in_decl)
{
tree val;
- tree inner_args;
int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
- inner_args = INNERMOST_TEMPLATE_ARGS (args);
-
if (TREE_CODE (arg) == TREE_LIST
&& TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
{
if (coerce_template_template_parms (parmparm, argparm,
complain, in_decl,
- inner_args))
+ args))
{
val = arg;
val = arg;
/* We only form one instance of each template specialization.
Therefore, if we use a non-canonical variant (i.e., a
- typedef), any future messages referring to the type will use
+ typedef), any future messages referring to the type will use
the typedef, which is confusing if those future uses do not
themselves also use the typedef. */
if (TYPE_P (val))
arguments. If any error occurs, return error_mark_node. Error and
warning messages are issued under control of COMPLAIN.
- If REQUIRE_ALL_ARGUMENTS is nonzero, all arguments must be
- provided in ARGLIST, or else trailing parameters must have default
- values. If REQUIRE_ALL_ARGUMENTS is zero, we will attempt argument
- deduction for any unspecified trailing arguments. */
+ If REQUIRE_ALL_ARGS is false, argument deduction will be performed
+ for arguments not specified in ARGS. Otherwise, if
+ USE_DEFAULT_ARGS is true, default arguments will be used to fill in
+ unspecified arguments. If REQUIRE_ALL_ARGS is true, but
+ USE_DEFAULT_ARGS is false, then all arguments must be specified in
+ ARGS. */
static tree
coerce_template_parms (tree parms,
tree args,
tree in_decl,
tsubst_flags_t complain,
- int require_all_arguments)
+ bool require_all_args,
+ bool use_default_args)
{
int nparms, nargs, i, lost = 0;
tree inner_args;
if (nargs > nparms
|| (nargs < nparms
- && require_all_arguments
- && TREE_PURPOSE (TREE_VEC_ELT (parms, nargs)) == NULL_TREE))
+ && require_all_args
+ && (!use_default_args
+ || (TREE_VEC_ELT (parms, nargs) != error_mark_node
+ && !TREE_PURPOSE (TREE_VEC_ELT (parms, nargs))))))
{
if (complain & tf_error)
{
/* Get the Ith template parameter. */
parm = TREE_VEC_ELT (parms, i);
+
+ if (parm == error_mark_node)
+ {
+ TREE_VEC_ELT (new_inner_args, i) = error_mark_node;
+ continue;
+ }
/* Calculate the Ith argument. */
if (i < nargs)
arg = TREE_VEC_ELT (inner_args, i);
- else if (require_all_arguments)
+ else if (require_all_args)
/* There must be a default arg in this case. */
arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,
complain, in_decl);
gcc_obstack_init (&scratch_obstack);
else
obstack_free (&scratch_obstack, scratch_firstobj);
- scratch_firstobj = obstack_alloc (&scratch_obstack, 1);
+ scratch_firstobj = (char *) obstack_alloc (&scratch_obstack, 1);
#define ccat(C) obstack_1grow (&scratch_obstack, (C));
#define cat(S) obstack_grow (&scratch_obstack, (S), strlen (S))
gcc_assert (nparms == TREE_VEC_LENGTH (arglist));
for (i = 0; i < nparms; i++)
{
- tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
- tree arg = TREE_VEC_ELT (arglist, i);
+ tree parm;
+ tree arg;
+
+ parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
+ arg = TREE_VEC_ELT (arglist, i);
+
+ if (parm == error_mark_node)
+ continue;
if (i)
ccat (',');
arglist = add_to_template_args (current_template_args (), arglist);
arglist2 = coerce_template_parms (parmlist, arglist, template,
- complain, /*require_all_args=*/1);
+ complain,
+ /*require_all_args=*/true,
+ /*use_default_args=*/true);
if (arglist2 == error_mark_node
|| (!uses_template_parms (arglist2)
&& check_instantiated_args (template, arglist2, complain)))
{
tree a = coerce_template_parms (TREE_VALUE (t),
arglist, template,
- complain, /*require_all_args=*/1);
+ complain,
+ /*require_all_args=*/true,
+ /*use_default_args=*/true);
/* Don't process further if one of the levels fails. */
if (a == error_mark_node)
= coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
INNERMOST_TEMPLATE_ARGS (arglist),
template,
- complain, /*require_all_args=*/1);
+ complain,
+ /*require_all_args=*/true,
+ /*use_default_args=*/true);
if (arglist == error_mark_node)
/* We were unable to bind the arguments. */
code that generates debugging information will crash. */
DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;
+ /* Possibly limit visibility based on template args. */
+ TREE_PUBLIC (type_decl) = 1;
+ determine_visibility (type_decl);
+
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
timevar_pop (TV_NAME_LOOKUP);
/* We're starting to instantiate D; record the template instantiation context
for diagnostics and to restore it later. */
-int
+static int
push_tinst_level (tree d)
{
tree new;
/* We're done instantiating this template; return to the instantiation
context. */
-void
+static void
pop_tinst_level (void)
{
tree old = current_tinst_level;
current cless with same name. */
push_nested_namespace (ns);
fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
- tf_error | tf_warning, NULL_TREE);
+ tf_warning_or_error, NULL_TREE,
+ /*integral_constant_expression_p=*/false);
pop_nested_namespace (ns);
arglist = tsubst (DECL_TI_ARGS (decl), args,
- tf_error | tf_warning, NULL_TREE);
+ tf_warning_or_error, NULL_TREE);
template_id = lookup_template_function (fns, arglist);
- new_friend = tsubst (decl, args, tf_error | tf_warning, NULL_TREE);
+ new_friend = tsubst (decl, args, tf_warning_or_error, NULL_TREE);
tmpl = determine_specialization (template_id, new_friend,
&new_args,
/*need_member_template=*/0,
- TREE_VEC_LENGTH (args));
+ TREE_VEC_LENGTH (args),
+ tsk_none);
return instantiate_template (tmpl, new_args, tf_error);
}
- new_friend = tsubst (decl, args, tf_error | tf_warning, NULL_TREE);
+ new_friend = tsubst (decl, args, tf_warning_or_error, NULL_TREE);
/* The NEW_FRIEND will look like an instantiation, to the
compiler, but is not an instantiation from the point of view of
else
new_friend_result_template_info = NULL_TREE;
+ /* Make the init_value nonzero so pushdecl knows this is a defn. */
+ if (new_friend_is_defn)
+ DECL_INITIAL (new_friend) = error_mark_node;
+
/* Inside pushdecl_namespace_level, we will push into the
current namespace. However, the friend function should go
into the namespace of the template. */
old_decl = pushdecl_namespace_level (new_friend, /*is_friend=*/true);
pop_nested_namespace (ns);
+ if (old_decl == error_mark_node)
+ return error_mark_node;
+
if (old_decl != new_friend)
{
/* This new friend declaration matched an existing
push_nested_class (tsubst (context, args, tf_none, NULL_TREE));
}
- /* First, we look for a class template. */
- tmpl = lookup_name (DECL_NAME (friend_tmpl));
+ /* Look for a class template declaration. We look for hidden names
+ because two friend declarations of the same template are the
+ same. For example, in:
+
+ struct A {
+ template <typename> friend class F;
+ };
+ template <typename> struct B {
+ template <typename> friend class F;
+ };
+
+ both F templates are the same. */
+ tmpl = lookup_name_real (DECL_NAME (friend_tmpl), 0, 0,
+ /*block_p=*/true, 0,
+ LOOKUP_COMPLAIN | LOOKUP_HIDDEN);
/* But, if we don't find one, it might be because we're in a
situation like this:
{
tree parms;
parms = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_tmpl),
- args, tf_error | tf_warning);
+ args, tf_warning_or_error);
redeclare_class_template (TREE_TYPE (tmpl), parms);
}
/* The friend template has not already been declared. In this
case, the instantiation of the template class will cause the
injection of this template into the global scope. */
- tmpl = tsubst (friend_tmpl, args, tf_error | tf_warning, NULL_TREE);
+ tmpl = tsubst (friend_tmpl, args, tf_warning_or_error, NULL_TREE);
+ if (tmpl == error_mark_node)
+ return error_mark_node;
/* The new TMPL is not an instantiation of anything, so we
forget its origins. We don't reset CLASSTYPE_TI_TEMPLATE for
template = most_general_template (CLASSTYPE_TI_TEMPLATE (type));
gcc_assert (TREE_CODE (template) == TEMPLATE_DECL);
- /* Figure out which arguments are being used to do the
- instantiation. */
- args = CLASSTYPE_TI_ARGS (type);
-
/* Determine what specialization of the original template to
instantiate. */
- t = most_specialized_class (template, args);
+ t = most_specialized_class (type, template);
if (t == error_mark_node)
{
- const char *str = "candidates are:";
- error ("ambiguous class template instantiation for %q#T", type);
- for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t;
- t = TREE_CHAIN (t))
- {
- if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args))
- {
- error ("%s %+#T", str, TREE_TYPE (t));
- str = " ";
- }
- }
TYPE_BEING_DEFINED (type) = 1;
return error_mark_node;
}
+ else if (t)
+ {
+ /* This TYPE is actually an instantiation of a partial
+ specialization. We replace the innermost set of ARGS with
+ the arguments appropriate for substitution. For example,
+ given:
+
+ template <class T> struct S {};
+ template <class T> struct S<T*> {};
- if (t)
- pattern = TREE_TYPE (t);
+ and supposing that we are instantiating S<int*>, ARGS will
+ presently be {int*} -- but we need {int}. */
+ pattern = TREE_TYPE (t);
+ args = TREE_PURPOSE (t);
+ }
else
- pattern = TREE_TYPE (template);
+ {
+ pattern = TREE_TYPE (template);
+ args = CLASSTYPE_TI_ARGS (type);
+ }
/* If the template we're instantiating is incomplete, then clearly
there's nothing we can do. */
push_to_top_level ();
- if (t)
- {
- /* This TYPE is actually an instantiation of a partial
- specialization. We replace the innermost set of ARGS with
- the arguments appropriate for substitution. For example,
- given:
-
- template <class T> struct S {};
- template <class T> struct S<T*> {};
-
- and supposing that we are instantiating S<int*>, ARGS will
- present be {int*} but we need {int}. */
- tree inner_args
- = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
- args);
-
- /* If there were multiple levels in ARGS, replacing the
- innermost level would alter CLASSTYPE_TI_ARGS, which we don't
- want, so we make a copy first. */
- if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
- {
- args = copy_node (args);
- SET_TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args), inner_args);
- }
- else
- args = inner_args;
- }
-
SET_CLASSTYPE_INTERFACE_UNKNOWN (type);
/* Set the input location to the template definition. This is needed
{
/* Build new CLASSTYPE_NESTED_UTDS. */
- tree tag = t;
- tree name = TYPE_IDENTIFIER (tag);
tree newtag;
bool class_template_p;
- class_template_p = (TREE_CODE (tag) != ENUMERAL_TYPE
- && TYPE_LANG_SPECIFIC (tag)
- && CLASSTYPE_IS_TEMPLATE (tag));
+ class_template_p = (TREE_CODE (t) != ENUMERAL_TYPE
+ && TYPE_LANG_SPECIFIC (t)
+ && CLASSTYPE_IS_TEMPLATE (t));
/* If the member is a class template, then -- even after
substitution -- there may be dependent types in the
template argument list for the class. We increment
when outside of a template. */
if (class_template_p)
++processing_template_decl;
- newtag = tsubst (tag, args, tf_error, NULL_TREE);
+ newtag = tsubst (t, args, tf_error, NULL_TREE);
if (class_template_p)
--processing_template_decl;
if (newtag == error_mark_node)
if (TREE_CODE (newtag) != ENUMERAL_TYPE)
{
+ tree name = TYPE_IDENTIFIER (t);
+
if (class_template_p)
/* Unfortunately, lookup_template_class sets
CLASSTYPE_IMPLICIT_INSTANTIATION for a partial
if (TREE_CODE (t) == TEMPLATE_DECL)
--processing_template_decl;
set_current_access_from_decl (r);
- grok_special_member_properties (r);
finish_member_declaration (r);
}
else
if (TREE_CODE (t) == TEMPLATE_DECL)
++processing_template_decl;
- r = tsubst (t, args, tf_error | tf_warning, NULL_TREE);
+ r = tsubst (t, args, tf_warning_or_error, NULL_TREE);
if (TREE_CODE (t) == TEMPLATE_DECL)
--processing_template_decl;
if (TREE_CODE (r) == VAR_DECL)
not occur unless the static data member is
itself used in a way that requires the
definition of the static data member to
- exist.
+ exist.
Therefore, we do not substitute into the
- initialized for the static data member here. */
- finish_static_data_member_decl
- (r,
- /*init=*/NULL_TREE,
- /*asmspec_tree=*/NULL_TREE,
+ initialized for the static data member here. */
+ finish_static_data_member_decl
+ (r,
+ /*init=*/NULL_TREE,
+ /*init_const_expr_p=*/false,
+ /*asmspec_tree=*/NULL_TREE,
/*flags=*/0);
if (DECL_INITIALIZED_IN_CLASS_P (r))
check_static_variable_definition (r, TREE_TYPE (r));
{
/* template <class T> friend class C::D; */
friend_type = tsubst (friend_type, args,
- tf_error | tf_warning, NULL_TREE);
+ tf_warning_or_error, NULL_TREE);
if (TREE_CODE (friend_type) == TEMPLATE_DECL)
friend_type = TREE_TYPE (friend_type);
adjust_processing_template_decl = true;
otherwise. */
friend_type = tsubst (friend_type, args,
- tf_error | tf_warning, NULL_TREE);
+ tf_warning_or_error, NULL_TREE);
/* Bump processing_template_decl for correct
dependent_type_p calculation. */
++processing_template_decl;
else if (uses_template_parms (friend_type))
/* friend class C<T>; */
friend_type = tsubst (friend_type, args,
- tf_error | tf_warning, NULL_TREE);
+ tf_warning_or_error, NULL_TREE);
/* Otherwise it's
friend class C;
r = tsubst (t, args, complain, in_decl);
else
{
- r = tsubst_expr (t, args, complain, in_decl);
+ r = tsubst_expr (t, args, complain, in_decl,
+ /*integral_constant_expression_p=*/true);
r = fold_non_dependent_expr (r);
}
return r;
{
int len = TREE_VEC_LENGTH (t);
int need_new = 0, i;
- tree *elts = alloca (len * sizeof (tree));
+ tree *elts = (tree *) alloca (len * sizeof (tree));
for (i = 0; i < len; i++)
{
for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
{
- tree tuple = TREE_VEC_ELT (TREE_VALUE (parms), i);
- tree default_value = TREE_PURPOSE (tuple);
- tree parm_decl = TREE_VALUE (tuple);
+ tree tuple;
+ tree default_value;
+ tree parm_decl;
+
+ if (parms == error_mark_node)
+ continue;
+
+ tuple = TREE_VEC_ELT (TREE_VALUE (parms), i);
+
+ if (tuple == error_mark_node)
+ continue;
+
+ default_value = TREE_PURPOSE (tuple);
+ parm_decl = TREE_VALUE (tuple);
parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
if (TREE_CODE (parm_decl) == PARM_DECL
entering_scope, complain);
r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
}
-
+
skip_evaluation = saved_skip_evaluation;
return r;
}
push_deferring_access_checks(dk_no_deferred);
+ /* The default argument expression may cause implicitly defined
+ member functions to be synthesized, which will result in garbage
+ collection. We must treat this situation as if we were within
+ the body of function so as to avoid collecting live data on the
+ stack. */
+ ++function_depth;
arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
- tf_error | tf_warning, NULL_TREE);
+ tf_warning_or_error, NULL_TREE,
+ /*integral_constant_expression_p=*/false);
+ --function_depth;
pop_deferring_access_checks();
/* Restore the "this" pointer. */
tree new_type;
++processing_template_decl;
new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
- --processing_template_decl;
+ --processing_template_decl;
if (new_type == error_mark_node)
return error_mark_node;
DECL_TI_TEMPLATE (new_decl) = r;
TREE_TYPE (r) = TREE_TYPE (new_decl);
DECL_TI_ARGS (r) = DECL_TI_ARGS (new_decl);
- DECL_CONTEXT (r) = DECL_CONTEXT (new_decl);
+ DECL_CONTEXT (r) = DECL_CONTEXT (new_decl);
}
SET_DECL_IMPLICIT_INSTANTIATION (r);
if (PRIMARY_TEMPLATE_P (gen_tmpl))
clone_function_decl (r, /*update_method_vec_p=*/0);
}
- else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
- grok_op_properties (r, (complain & tf_error) != 0);
+ else if (IDENTIFIER_OPNAME_P (DECL_NAME (r))
+ && !grok_op_properties (r, (complain & tf_error) != 0))
+ return error_mark_node;
if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
SET_DECL_FRIEND_CONTEXT (r,
tsubst (DECL_FRIEND_CONTEXT (t),
args, complain, in_decl));
+
+ /* Possibly limit visibility based on template args. */
+ DECL_VISIBILITY (r) = VISIBILITY_DEFAULT;
+ if (DECL_VISIBILITY_SPECIFIED (t))
+ {
+ DECL_VISIBILITY_SPECIFIED (r) = 0;
+ DECL_ATTRIBUTES (r)
+ = remove_attribute ("visibility", DECL_ATTRIBUTES (r));
+ }
+ determine_visibility (r);
}
break;
TREE_TYPE (r) = type;
cp_apply_type_quals_to_decl (cp_type_quals (type), r);
+ /* DECL_INITIAL gives the number of bits in a bit-field. */
+ DECL_INITIAL (r)
+ = tsubst_expr (DECL_INITIAL (t), args,
+ complain, in_decl,
+ /*integral_constant_expression_p=*/true);
/* We don't have to set DECL_CONTEXT here; it is set by
finish_member_declaration. */
- DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args,
- complain, in_decl);
TREE_CHAIN (r) = NULL_TREE;
if (VOID_TYPE_P (type))
error ("instantiation of %q+D as type %qT", r, type);
tree tmpl = NULL_TREE;
tree ctx;
tree type = NULL_TREE;
- int local_p;
+ bool local_p;
if (TREE_CODE (t) == TYPE_DECL)
{
}
}
- /* Assume this is a non-local variable. */
- local_p = 0;
+ /* Check to see if we already have the specialization we
+ need. */
+ spec = NULL_TREE;
+ if (DECL_CLASS_SCOPE_P (t) || DECL_NAMESPACE_SCOPE_P (t))
+ {
+ /* T is a static data member or namespace-scope entity.
+ We have to substitute into namespace-scope variables
+ (even though such entities are never templates) because
+ of cases like:
+
+ template <class T> void f() { extern T t; }
+
+ where the entity referenced is not known until
+ instantiation time. */
+ local_p = false;
+ ctx = DECL_CONTEXT (t);
+ if (DECL_CLASS_SCOPE_P (t))
+ {
+ ctx = tsubst_aggr_type (ctx, args,
+ complain,
+ in_decl, /*entering_scope=*/1);
+ /* If CTX is unchanged, then T is in fact the
+ specialization we want. That situation occurs when
+ referencing a static data member within in its own
+ class. We can use pointer equality, rather than
+ same_type_p, because DECL_CONTEXT is always
+ canonical. */
+ if (ctx == DECL_CONTEXT (t))
+ spec = t;
+ }
- if (TYPE_P (CP_DECL_CONTEXT (t)))
- ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
- complain,
- in_decl, /*entering_scope=*/1);
- else if (DECL_NAMESPACE_SCOPE_P (t))
- ctx = DECL_CONTEXT (t);
+ if (!spec)
+ {
+ tmpl = DECL_TI_TEMPLATE (t);
+ gen_tmpl = most_general_template (tmpl);
+ argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
+ spec = (retrieve_specialization
+ (gen_tmpl, argvec,
+ /*class_specializations_p=*/false));
+ }
+ }
else
{
+ /* A local variable. */
+ local_p = true;
/* Subsequent calls to pushdecl will fill this in. */
ctx = NULL_TREE;
- local_p = 1;
+ spec = retrieve_local_specialization (t);
}
-
- /* Check to see if we already have this specialization. */
- if (!local_p)
- {
- tmpl = DECL_TI_TEMPLATE (t);
- gen_tmpl = most_general_template (tmpl);
- argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
- spec = retrieve_specialization (gen_tmpl, argvec,
- /*class_specializations_p=*/false);
- }
- else
- spec = retrieve_local_specialization (t);
-
+ /* If we already have the specialization we need, there is
+ nothing more to do. */
if (spec)
{
r = spec;
break;
}
+ /* Create a new node for the specialization we need. */
r = copy_decl (t);
if (TREE_CODE (r) == VAR_DECL)
{
if (DECL_HAS_VALUE_EXPR_P (t))
{
tree ve = DECL_VALUE_EXPR (t);
- ve = tsubst_expr (ve, args, complain, in_decl);
- SET_DECL_VALUE_EXPR (r, ve);
+ ve = tsubst_expr (ve, args, complain, in_decl,
+ /*constant_expression_p=*/false);
+ SET_DECL_VALUE_EXPR (r, ve);
}
}
else if (DECL_SELF_REFERENCE_P (t))
if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_WRTL))
SET_DECL_RTL (r, NULL_RTX);
DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0;
+ if (TREE_CODE (r) == VAR_DECL)
+ {
+ /* Possibly limit visibility based on template args. */
+ DECL_VISIBILITY (r) = VISIBILITY_DEFAULT;
+ if (DECL_VISIBILITY_SPECIFIED (t))
+ {
+ DECL_VISIBILITY_SPECIFIED (r) = 0;
+ DECL_ATTRIBUTES (r)
+ = remove_attribute ("visibility", DECL_ATTRIBUTES (r));
+ }
+ determine_visibility (r);
+ }
if (!local_p)
{
return new_specs;
}
-/* Substitute into the PARMS of a call-declarator. */
-
-static tree
-tsubst_call_declarator_parms (tree parms,
- tree args,
- tsubst_flags_t complain,
- tree in_decl)
-{
- tree new_parms;
- tree type;
- tree defarg;
-
- if (!parms || parms == void_list_node)
- return parms;
-
- new_parms = tsubst_call_declarator_parms (TREE_CHAIN (parms),
- args, complain, in_decl);
-
- /* Figure out the type of this parameter. */
- type = tsubst (TREE_VALUE (parms), args, complain, in_decl);
-
- /* Figure out the default argument as well. Note that we use
- tsubst_expr since the default argument is really an expression. */
- defarg = tsubst_expr (TREE_PURPOSE (parms), args, complain, in_decl);
-
- /* Chain this parameter on to the front of those we have already
- processed. We don't use hash_tree_cons because that function
- doesn't check TREE_PARMLIST. */
- new_parms = tree_cons (defarg, type, new_parms);
-
- return new_parms;
-}
-
/* Take the tree structure T and replace template parameters used
therein with the argument vector ARGS. IN_DECL is an associated
decl for diagnostics. If an error occurs, returns ERROR_MARK_NODE.
{
tree max, omax = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
- /* The array dimension behaves like a non-type template arg,
- in that we want to fold it as much as possible. */
- max = tsubst_template_arg (omax, args, complain, in_decl);
+ max = tsubst_expr (omax, args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+ max = fold_non_dependent_expr (max);
max = fold_decl_constant_value (max);
+ if (TREE_CODE (max) != INTEGER_CST
+ && TREE_CODE (max) != TEMPLATE_PARM_INDEX
+ && !at_function_scope_p ())
+ {
+ if (complain & tf_error)
+ error ("array bound is not an integer constant");
+ return error_mark_node;
+ }
+
/* [temp.deduct]
Type deduction may fail for any of the following
indicated by the state of complain), so that
another substitution can be found. */
return error_mark_node;
-
else if (TREE_CODE (max) == INTEGER_CST
&& INT_CST_LT (max, integer_zero_node))
{
{
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
{
+ int quals;
gcc_assert (TYPE_P (arg));
+
+ /* cv-quals from the template are discarded when
+ substituting in a function or reference type. */
+ if (TREE_CODE (arg) == FUNCTION_TYPE
+ || TREE_CODE (arg) == METHOD_TYPE
+ || TREE_CODE (arg) == REFERENCE_TYPE)
+ quals = cp_type_quals (arg);
+ else
+ quals = cp_type_quals (arg) | cp_type_quals (t);
+
return cp_build_qualified_type_real
- (arg, cp_type_quals (arg) | cp_type_quals (t),
- complain | tf_ignore_bad_quals);
+ (arg, quals, complain | tf_ignore_bad_quals);
}
else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
case ARRAY_REF:
{
tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
- tree e2 = tsubst_expr (TREE_OPERAND (t, 1), args, complain, in_decl);
+ tree e2 = tsubst_expr (TREE_OPERAND (t, 1), args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
if (e1 == error_mark_node || e2 == error_mark_node)
return error_mark_node;
{
tree type;
- type = finish_typeof (tsubst_expr (TYPEOF_TYPE_EXPR (t), args,
- complain, in_decl));
+ type = finish_typeof (tsubst_expr
+ (TYPEOF_TYPE_EXPR (t), args,
+ complain, in_decl,
+ /*integral_constant_expression_p=*/false));
return cp_build_qualified_type_real (type,
cp_type_quals (t)
| cp_type_quals (type),
tree name;
tree qualifying_scope;
tree fns;
+ tree optype;
tree template_args = 0;
bool template_id_p = false;
ambiguous now. Therefore, we perform the lookup again. */
qualifying_scope = BINFO_TYPE (BASELINK_ACCESS_BINFO (baselink));
fns = BASELINK_FUNCTIONS (baselink);
+ optype = BASELINK_OPTYPE (baselink);
if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
{
template_id_p = true;
= build_nt (TEMPLATE_ID_EXPR,
BASELINK_FUNCTIONS (baselink),
template_args);
+ /* Update the conversion operator type. */
+ BASELINK_OPTYPE (baselink)
+ = tsubst (optype, args, complain, in_decl);
if (!object_type)
object_type = current_class_type;
expr = name;
if (dependent_type_p (scope))
- return build_qualified_name (/*type=*/NULL_TREE,
- scope, expr,
+ return build_qualified_name (/*type=*/NULL_TREE,
+ scope, expr,
QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
if (!BASELINK_P (name) && !DECL_P (expr))
{
expr = (adjust_result_of_qualified_name_lookup
(expr, scope, current_class_type));
- expr = (finish_qualified_id_expr
+ expr = (finish_qualified_id_expr
(scope, expr, done, address_p,
QUALIFIED_NAME_IS_TEMPLATE (qualified_id),
/*template_arg_p=*/false));
}
- if (TREE_CODE (expr) != SCOPE_REF)
+ /* Expressions do not generally have reference type. */
+ if (TREE_CODE (expr) != SCOPE_REF
+ /* However, if we're about to form a pointer-to-member, we just
+ want the referenced member referenced. */
+ && TREE_CODE (expr) != OFFSET_REF)
expr = convert_from_reference (expr);
return expr;
complain, in_decl);
name = build1 (BIT_NOT_EXPR, NULL_TREE, name);
name = build_qualified_name (/*type=*/NULL_TREE,
- base, name,
+ base, name,
/*template_p=*/false);
}
else if (TREE_CODE (name) == BASELINK)
in response to the saved STMT_IS_FULL_EXPR_P setting. */
gcc_unreachable ();
+ case OFFSET_REF:
+ mark_used (TREE_OPERAND (t, 1));
+ return t;
+
default:
return t;
}
}
+/* Like tsubst_copy, but specifically for OpenMP clauses. */
+
+static tree
+tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain,
+ tree in_decl)
+{
+ tree new_clauses = NULL, nc, oc;
+
+ for (oc = clauses; oc ; oc = OMP_CLAUSE_CHAIN (oc))
+ {
+ nc = copy_node (oc);
+ OMP_CLAUSE_CHAIN (nc) = new_clauses;
+ new_clauses = nc;
+
+ switch (OMP_CLAUSE_CODE (nc))
+ {
+ case OMP_CLAUSE_PRIVATE:
+ case OMP_CLAUSE_SHARED:
+ case OMP_CLAUSE_FIRSTPRIVATE:
+ case OMP_CLAUSE_LASTPRIVATE:
+ case OMP_CLAUSE_REDUCTION:
+ case OMP_CLAUSE_COPYIN:
+ case OMP_CLAUSE_COPYPRIVATE:
+ case OMP_CLAUSE_IF:
+ case OMP_CLAUSE_NUM_THREADS:
+ case OMP_CLAUSE_SCHEDULE:
+ OMP_CLAUSE_OPERAND (nc, 0)
+ = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
+ break;
+ case OMP_CLAUSE_NOWAIT:
+ case OMP_CLAUSE_ORDERED:
+ case OMP_CLAUSE_DEFAULT:
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ return finish_omp_clauses (nreverse (new_clauses));
+}
+
/* Like tsubst_copy_and_build, but unshare TREE_LIST nodes. */
static tree
if (TREE_CODE (t) != TREE_LIST)
return tsubst_copy_and_build (t, args, complain, in_decl,
- /*function_p=*/false);
+ /*function_p=*/false,
+ /*integral_constant_expression_p=*/false);
if (t == void_list_node)
return t;
processing. */
static tree
-tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
+tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
+ bool integral_constant_expression_p)
{
+#define RECUR(NODE) \
+ tsubst_expr ((NODE), args, complain, in_decl, \
+ integral_constant_expression_p)
+
tree stmt, tmp;
if (t == NULL_TREE || t == error_mark_node)
{
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);
+ RECUR (tsi_stmt (i));
break;
}
break;
case RETURN_EXPR:
- finish_return_stmt (tsubst_expr (TREE_OPERAND (t, 0),
- args, complain, in_decl));
+ finish_return_stmt (RECUR (TREE_OPERAND (t, 0)));
break;
case EXPR_STMT:
- tmp = tsubst_expr (EXPR_STMT_EXPR (t), args, complain, in_decl);
+ tmp = RECUR (EXPR_STMT_EXPR (t));
if (EXPR_STMT_STMT_EXPR_RESULT (t))
finish_stmt_expr_expr (tmp, cur_stmt_expr);
else
break;
case USING_STMT:
- do_using_directive (tsubst_expr (USING_STMT_NAMESPACE (t),
- args, complain, in_decl));
+ do_using_directive (RECUR (USING_STMT_NAMESPACE (t)));
break;
case DECL_EXPR:
tree name = DECL_NAME (decl);
tree decl;
- scope = tsubst_expr (scope, args, complain, in_decl);
+ scope = RECUR (scope);
decl = lookup_qualified_name (scope, name,
/*is_type_p=*/false,
/*complain=*/false);
decl = tsubst (decl, args, complain, in_decl);
if (decl != error_mark_node)
{
- if (init)
- DECL_INITIAL (decl) = error_mark_node;
/* By marking the declaration as instantiated, we avoid
trying to instantiate it. Since instantiate_decl can't
handle local variables, and since we've already done
init = cp_fname_init (name, &TREE_TYPE (decl));
}
else
- init = tsubst_expr (init, args, complain, in_decl);
- cp_finish_decl (decl, init, NULL_TREE, 0);
+ init = RECUR (init);
+ finish_decl (decl, init, NULL_TREE);
}
}
}
case FOR_STMT:
stmt = begin_for_stmt ();
- tsubst_expr (FOR_INIT_STMT (t), args, complain, in_decl);
+ RECUR (FOR_INIT_STMT (t));
finish_for_init_stmt (stmt);
- tmp = tsubst_expr (FOR_COND (t), args, complain, in_decl);
+ tmp = RECUR (FOR_COND (t));
finish_for_cond (tmp, stmt);
- tmp = tsubst_expr (FOR_EXPR (t), args, complain, in_decl);
+ tmp = RECUR (FOR_EXPR (t));
finish_for_expr (tmp, stmt);
- tsubst_expr (FOR_BODY (t), args, complain, in_decl);
+ RECUR (FOR_BODY (t));
finish_for_stmt (stmt);
break;
case WHILE_STMT:
stmt = begin_while_stmt ();
- tmp = tsubst_expr (WHILE_COND (t), args, complain, in_decl);
+ tmp = RECUR (WHILE_COND (t));
finish_while_stmt_cond (tmp, stmt);
- tsubst_expr (WHILE_BODY (t), args, complain, in_decl);
+ RECUR (WHILE_BODY (t));
finish_while_stmt (stmt);
break;
case DO_STMT:
stmt = begin_do_stmt ();
- tsubst_expr (DO_BODY (t), args, complain, in_decl);
+ RECUR (DO_BODY (t));
finish_do_body (stmt);
- tmp = tsubst_expr (DO_COND (t), args, complain, in_decl);
+ tmp = RECUR (DO_COND (t));
finish_do_stmt (tmp, stmt);
break;
case IF_STMT:
stmt = begin_if_stmt ();
- tmp = tsubst_expr (IF_COND (t), args, complain, in_decl);
+ tmp = RECUR (IF_COND (t));
finish_if_stmt_cond (tmp, stmt);
- tsubst_expr (THEN_CLAUSE (t), args, complain, in_decl);
+ RECUR (THEN_CLAUSE (t));
finish_then_clause (stmt);
if (ELSE_CLAUSE (t))
{
begin_else_clause (stmt);
- tsubst_expr (ELSE_CLAUSE (t), args, complain, in_decl);
+ RECUR (ELSE_CLAUSE (t));
finish_else_clause (stmt);
}
stmt = begin_compound_stmt (BIND_EXPR_TRY_BLOCK (t)
? BCS_TRY_BLOCK : 0);
- tsubst_expr (BIND_EXPR_BODY (t), args, complain, in_decl);
+ RECUR (BIND_EXPR_BODY (t));
if (BIND_EXPR_BODY_BLOCK (t))
finish_function_body (stmt);
case SWITCH_STMT:
stmt = begin_switch_stmt ();
- tmp = tsubst_expr (SWITCH_STMT_COND (t), args, complain, in_decl);
+ tmp = RECUR (SWITCH_STMT_COND (t));
finish_switch_cond (tmp, stmt);
- tsubst_expr (SWITCH_STMT_BODY (t), args, complain, in_decl);
+ RECUR (SWITCH_STMT_BODY (t));
finish_switch_stmt (stmt);
break;
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));
+ finish_case_label (RECUR (CASE_LOW (t)),
+ RECUR (CASE_HIGH (t)));
break;
case LABEL_EXPR:
/* Computed goto's must be tsubst'd into. On the other hand,
non-computed gotos must not be; the identifier in question
will have no binding. */
- tmp = tsubst_expr (tmp, args, complain, in_decl);
+ tmp = RECUR (tmp);
else
tmp = DECL_NAME (tmp);
finish_goto_stmt (tmp);
case ASM_EXPR:
tmp = finish_asm_stmt
(ASM_VOLATILE_P (t),
- tsubst_expr (ASM_STRING (t), args, complain, in_decl),
+ RECUR (ASM_STRING (t)),
tsubst_copy_asm_operands (ASM_OUTPUTS (t), args, complain, in_decl),
tsubst_copy_asm_operands (ASM_INPUTS (t), args, complain, in_decl),
tsubst_copy_asm_operands (ASM_CLOBBERS (t), args, complain, in_decl));
if (CLEANUP_P (t))
{
stmt = begin_try_block ();
- tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
+ RECUR (TRY_STMTS (t));
finish_cleanup_try_block (stmt);
- finish_cleanup (tsubst_expr (TRY_HANDLERS (t), args,
- complain, in_decl),
- stmt);
+ finish_cleanup (RECUR (TRY_HANDLERS (t)), stmt);
}
else
{
+ tree compound_stmt = NULL_TREE;
+
if (FN_TRY_BLOCK_P (t))
- stmt = begin_function_try_block ();
+ stmt = begin_function_try_block (&compound_stmt);
else
stmt = begin_try_block ();
- tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
+ RECUR (TRY_STMTS (t));
if (FN_TRY_BLOCK_P (t))
finish_function_try_block (stmt);
else
finish_try_block (stmt);
- tsubst_expr (TRY_HANDLERS (t), args, complain, in_decl);
+ RECUR (TRY_HANDLERS (t));
if (FN_TRY_BLOCK_P (t))
- finish_function_handler_sequence (stmt);
+ finish_function_handler_sequence (stmt, compound_stmt);
else
finish_handler_sequence (stmt);
}
case HANDLER:
{
- tree decl;
+ tree decl = HANDLER_PARMS (t);
- stmt = begin_handler ();
- if (HANDLER_PARMS (t))
+ if (decl)
{
- 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
done. */
- DECL_TEMPLATE_INSTANTIATED (decl) = 1;
+ if (decl != error_mark_node)
+ DECL_TEMPLATE_INSTANTIATED (decl) = 1;
}
- else
- decl = NULL_TREE;
+ stmt = begin_handler ();
finish_handler_parms (decl, stmt);
- tsubst_expr (HANDLER_BODY (t), args, complain, in_decl);
+ RECUR (HANDLER_BODY (t));
finish_handler (stmt);
}
break;
tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
break;
+ case OMP_PARALLEL:
+ tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t),
+ args, complain, in_decl);
+ stmt = begin_omp_parallel ();
+ RECUR (OMP_PARALLEL_BODY (t));
+ OMP_PARALLEL_COMBINED (finish_omp_parallel (tmp, stmt))
+ = OMP_PARALLEL_COMBINED (t);
+ break;
+
+ case OMP_FOR:
+ {
+ tree clauses, decl, init, cond, incr, body, pre_body;
+
+ clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t),
+ args, complain, in_decl);
+ init = OMP_FOR_INIT (t);
+ gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
+ decl = RECUR (TREE_OPERAND (init, 0));
+ init = RECUR (TREE_OPERAND (init, 1));
+ cond = RECUR (OMP_FOR_COND (t));
+ incr = RECUR (OMP_FOR_INCR (t));
+
+ stmt = begin_omp_structured_block ();
+
+ pre_body = push_stmt_list ();
+ RECUR (OMP_FOR_PRE_BODY (t));
+ pre_body = pop_stmt_list (pre_body);
+
+ body = push_stmt_list ();
+ RECUR (OMP_FOR_BODY (t));
+ body = pop_stmt_list (body);
+
+ t = finish_omp_for (EXPR_LOCATION (t), decl, init, cond, incr, body,
+ pre_body);
+ if (t)
+ OMP_FOR_CLAUSES (t) = clauses;
+
+ add_stmt (finish_omp_structured_block (stmt));
+ }
+ break;
+
+ case OMP_SECTIONS:
+ case OMP_SINGLE:
+ tmp = tsubst_omp_clauses (OMP_CLAUSES (t), args, complain, in_decl);
+ stmt = push_stmt_list ();
+ RECUR (OMP_BODY (t));
+ stmt = pop_stmt_list (stmt);
+
+ t = copy_node (t);
+ OMP_BODY (t) = stmt;
+ OMP_CLAUSES (t) = tmp;
+ add_stmt (t);
+ break;
+
+ case OMP_SECTION:
+ case OMP_CRITICAL:
+ case OMP_MASTER:
+ case OMP_ORDERED:
+ stmt = push_stmt_list ();
+ RECUR (OMP_BODY (t));
+ stmt = pop_stmt_list (stmt);
+
+ t = copy_node (t);
+ OMP_BODY (t) = stmt;
+ add_stmt (t);
+ break;
+
+ case OMP_ATOMIC:
+ {
+ tree op0, op1;
+ op0 = RECUR (TREE_OPERAND (t, 0));
+ op1 = RECUR (TREE_OPERAND (t, 1));
+ finish_omp_atomic (OMP_ATOMIC_CODE (t), op0, op1);
+ }
+ break;
+
default:
gcc_assert (!STATEMENT_CODE_P (TREE_CODE (t)));
return tsubst_copy_and_build (t, args, complain, in_decl,
- /*function_p=*/false);
+ /*function_p=*/false,
+ integral_constant_expression_p);
}
return NULL_TREE;
+#undef RECUR
}
/* T is a postfix-expression that is not being used in a function
/*done=*/false, /*address_p=*/false);
else
t = tsubst_copy_and_build (t, args, complain, in_decl,
- /*function_p=*/false);
+ /*function_p=*/false,
+ /*integral_constant_expression_p=*/false);
return t;
}
tree args,
tsubst_flags_t complain,
tree in_decl,
- bool function_p)
+ bool function_p,
+ bool integral_constant_expression_p)
{
-#define RECUR(NODE) \
- tsubst_copy_and_build (NODE, args, complain, in_decl, /*function_p=*/false)
+#define RECUR(NODE) \
+ tsubst_copy_and_build (NODE, args, complain, in_decl, \
+ /*function_p=*/false, \
+ integral_constant_expression_p)
tree op1;
decl = finish_id_expression (t, decl, NULL_TREE,
&idk,
- /*integral_constant_expression_p=*/false,
+ integral_constant_expression_p,
/*allow_non_integral_constant_expression_p=*/false,
&non_integral_constant_expression_p,
/*template_p=*/false,
return build3 (COMPONENT_REF, TREE_TYPE (template),
object, template, NULL_TREE);
else
- return template;
+ return baselink_for_fns (template);
}
case INDIRECT_REF:
RECUR (TREE_OPERAND (t, 0)));
case CAST_EXPR:
- return build_functional_cast
- (tsubst (TREE_TYPE (t), args, complain, in_decl),
- RECUR (TREE_OPERAND (t, 0)));
-
case REINTERPRET_CAST_EXPR:
- return build_reinterpret_cast
- (tsubst (TREE_TYPE (t), args, complain, in_decl),
- RECUR (TREE_OPERAND (t, 0)));
-
case CONST_CAST_EXPR:
- return build_const_cast
- (tsubst (TREE_TYPE (t), args, complain, in_decl),
- RECUR (TREE_OPERAND (t, 0)));
-
case DYNAMIC_CAST_EXPR:
- return build_dynamic_cast
- (tsubst (TREE_TYPE (t), args, complain, in_decl),
- RECUR (TREE_OPERAND (t, 0)));
-
case STATIC_CAST_EXPR:
- return build_static_cast
- (tsubst (TREE_TYPE (t), args, complain, in_decl),
- RECUR (TREE_OPERAND (t, 0)));
+ {
+ tree type;
+ tree op;
+
+ type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ if (integral_constant_expression_p
+ && !cast_valid_in_integral_constant_expression_p (type))
+ {
+ error ("a cast to a type other than an integral or "
+ "enumeration type cannot appear in a constant-expression");
+ return error_mark_node;
+ }
+
+ op = RECUR (TREE_OPERAND (t, 0));
+
+ switch (TREE_CODE (t))
+ {
+ case CAST_EXPR:
+ return build_functional_cast (type, op);
+ case REINTERPRET_CAST_EXPR:
+ return build_reinterpret_cast (type, op);
+ case CONST_CAST_EXPR:
+ return build_const_cast (type, op);
+ case DYNAMIC_CAST_EXPR:
+ return build_dynamic_cast (type, op);
+ case STATIC_CAST_EXPR:
+ return build_static_cast (type, op);
+ default:
+ gcc_unreachable ();
+ }
+ }
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
else
{
++skip_evaluation;
- op1 = RECUR (op1);
+ op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
+ /*function_p=*/false,
+ /*integral_constant_expression_p=*/false);
--skip_evaluation;
}
if (TYPE_P (op1))
}
else
qualified_p = false;
-
+
function = tsubst_copy_and_build (function, args, complain,
in_decl,
- !qualified_p);
+ !qualified_p,
+ integral_constant_expression_p);
+
if (BASELINK_P (function))
qualified_p = true;
}
(TREE_OPERAND (function, 0),
TREE_OPERAND (function, 1),
call_args, NULL_TREE,
- qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL));
+ qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL,
+ /*fn_p=*/NULL));
}
return finish_call_expr (function, call_args,
/*disallow_virtual=*/qualified_p,
case COMPONENT_REF:
{
tree object;
+ tree object_type;
tree member;
object = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
/* Remember that there was a reference to this entity. */
if (DECL_P (object))
mark_used (object);
+ object_type = TREE_TYPE (object);
member = TREE_OPERAND (t, 1);
if (BASELINK_P (member))
args, complain, in_decl);
else
member = tsubst_copy (member, args, complain, in_decl);
-
if (member == error_mark_node)
return error_mark_node;
- else if (!CLASS_TYPE_P (TREE_TYPE (object)))
+
+ if (object_type && !CLASS_TYPE_P (object_type))
{
if (TREE_CODE (member) == BIT_NOT_EXPR)
return finish_pseudo_destructor_expr (object,
NULL_TREE,
- TREE_TYPE (object));
+ object_type);
else if (TREE_CODE (member) == SCOPE_REF
&& (TREE_CODE (TREE_OPERAND (member, 1)) == BIT_NOT_EXPR))
return finish_pseudo_destructor_expr (object,
object,
- TREE_TYPE (object));
+ object_type);
}
else if (TREE_CODE (member) == SCOPE_REF
&& TREE_CODE (TREE_OPERAND (member, 1)) == TEMPLATE_ID_EXPR)
args);
member = (adjust_result_of_qualified_name_lookup
(member, BINFO_TYPE (BASELINK_BINFO (member)),
- TREE_TYPE (object)));
+ object_type));
}
else
{
- qualified_name_lookup_error (TREE_TYPE (object), tmpl,
- member);
+ qualified_name_lookup_error (object_type, tmpl, member);
return error_mark_node;
}
}
tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
bool process_index_p;
+ if (type == error_mark_node)
+ return error_mark_node;
+
/* digest_init will do the wrong thing if we let it. */
if (type && TYPE_PTRMEMFUNC_P (type))
return t;
in_decl));
case OFFSETOF_EXPR:
- return fold_offsetof (RECUR (TREE_OPERAND (t, 0)));
+ return finish_offsetof (RECUR (TREE_OPERAND (t, 0)));
case STMT_EXPR:
{
tree stmt_expr = begin_stmt_expr ();
cur_stmt_expr = stmt_expr;
- tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl);
+ tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl,
+ integral_constant_expression_p);
stmt_expr = finish_stmt_expr (stmt_expr, false);
cur_stmt_expr = old_stmt_expr;
/* As in finish_id_expression, we resolve enumeration constants
to their underlying values. */
if (TREE_CODE (t) == CONST_DECL)
- return DECL_INITIAL (t);
+ {
+ used_types_insert (TREE_TYPE (t));
+ return DECL_INITIAL (t);
+ }
return t;
default:
if (nt)
{
/* DR 488 makes use of a type with no linkage cause
- type deduction to fail. */
+ type deduction to fail. */
if (complain & tf_error)
{
if (TYPE_ANONYMOUS_P (nt))
error ("%qT is/uses anonymous type", t);
else
error ("template argument for %qD uses local type %qT",
- tmpl, t);
+ tmpl, t);
}
result = true;
}
tree fndecl;
tree gen_tmpl;
tree spec;
+ HOST_WIDE_INT saved_processing_template_decl;
if (tmpl == error_mark_node)
return error_mark_node;
deferring all checks until we have the FUNCTION_DECL. */
push_deferring_access_checks (dk_deferred);
- /* Substitute template parameters. */
+ /* Although PROCESSING_TEMPLATE_DECL may be true at this point
+ (because, for example, we have encountered a non-dependent
+ function call in the body of a template function and must now
+ determine which of several overloaded functions will be called),
+ within the instantiation itself we are not processing a
+ template. */
+ saved_processing_template_decl = processing_template_decl;
+ processing_template_decl = 0;
+ /* Substitute template parameters to obtain the specialization. */
fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
targ_ptr, complain, gen_tmpl);
+ processing_template_decl = saved_processing_template_decl;
+ if (fndecl == error_mark_node)
+ return error_mark_node;
/* Now we know the specialization, compute access previously
deferred. */
converted_args
= (coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (fn),
explicit_targs, NULL_TREE, tf_none,
- /*require_all_arguments=*/0));
+ /*require_all_args=*/false,
+ /*use_default_args=*/false));
if (converted_args == error_mark_node)
return 1;
if (same_type_p (parm, type))
continue;
if (strict != DEDUCE_EXACT
- && can_convert_arg (parm, type, TYPE_P (arg) ? NULL_TREE : arg,
+ && can_convert_arg (parm, type, TYPE_P (arg) ? NULL_TREE : arg,
flags))
continue;
-
+
return 1;
}
for (i = 0; i < ntparms; i++)
if (!TREE_VEC_ELT (targs, i))
{
- tree tparm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
+ tree tparm;
+
+ if (TREE_VEC_ELT (tparms, i) == error_mark_node)
+ continue;
+
+ tparm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
/* If this is an undeduced nontype parameter that depends on
a type parameter, try another pass; its type may have been
return 1;
}
-/* Verify that nondeduce template argument agrees with the type
- obtained from argument deduction. Return nonzero if the
- verification fails.
-
- For example:
-
- struct A { typedef int X; };
- template <class T, class U> struct C {};
- template <class T> struct C<T, typename T::X> {};
-
- Then with the instantiation `C<A, int>', we can deduce that
- `T' is `A' but unify () does not check whether `typename T::X'
- is `int'. This function ensure that they agree.
-
- TARGS, PARMS are the same as the arguments of unify.
- ARGS contains template arguments from all levels. */
-
-static int
-verify_class_unification (tree targs, tree parms, tree args)
-{
- parms = tsubst (parms, add_outermost_template_args (args, targs),
- tf_none, NULL_TREE);
- if (parms == error_mark_node)
- return 1;
-
- return !comp_template_args (parms, INNERMOST_TEMPLATE_ARGS (args));
-}
-
/* PARM is a template class (perhaps with unbound template
parameters). ARG is a fully instantiated type. If ARG can be
bound to PARM, return ARG, otherwise return NULL_TREE. TPARMS and
return 1;
}
-/* Takes parameters as for type_unification. Returns 0 if the
- type deduction succeeds, 1 otherwise. The parameter STRICT is a
- bitwise or of the following flags:
+/* Deduce the value of template parameters. TPARMS is the (innermost)
+ set of template parameters to a template. TARGS is the bindings
+ for those template parameters, as determined thus far; TARGS may
+ include template arguments for outer levels of template parameters
+ as well. PARM is a parameter to a template function, or a
+ subcomponent of that parameter; ARG is the corresponding argument.
+ This function attempts to match PARM with ARG in a manner
+ consistent with the existing assignments in TARGS. If more values
+ are deduced, then TARGS is updated.
+
+ Returns 0 if the type deduction succeeds, 1 otherwise. The
+ parameter STRICT is a bitwise or of the following flags:
UNIFY_ALLOW_NONE:
Require an exact match between PARM and ARG.
return (TREE_CODE (arg) == TREE_CODE (parm)
&& same_type_p (parm, arg)) ? 0 : 1;
idx = TEMPLATE_TYPE_IDX (parm);
- targ = TREE_VEC_ELT (targs, idx);
+ targ = TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx);
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, idx));
/* Check for mixed types and values. */
/* ARG must be constructed from a template class or a template
template parameter. */
if (TREE_CODE (arg) != BOUND_TEMPLATE_TEMPLATE_PARM
- && (TREE_CODE (arg) != RECORD_TYPE || !CLASSTYPE_TEMPLATE_INFO (arg)))
+ && !CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P (arg))
return 1;
{
- tree parmtmpl = TYPE_TI_TEMPLATE (parm);
tree parmvec = TYPE_TI_ARGS (parm);
tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
tree argtmplvec
= DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (arg));
int i;
- /* The parameter and argument roles have to be switched here
- in order to handle default arguments properly. For example,
- template<template <class> class TT> void f(TT<int>)
- should be able to accept vector<int> which comes from
- template <class T, class Allocator = allocator>
- class vector. */
+ /* The resolution to DR150 makes clear that default
+ arguments for an N-argument may not be used to bind T
+ to a template template parameter with fewer than N
+ parameters. It is not safe to permit the binding of
+ default arguments as an extension, as that may change
+ the meaning of a conforming program. Consider:
+
+ struct Dense { static const unsigned int dim = 1; };
- if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 0, 1)
+ template <template <typename> class View,
+ typename Block>
+ void operator+(float, View<Block> const&);
+
+ template <typename Block,
+ unsigned int Dim = Block::dim>
+ struct Lvalue_proxy { operator float() const; };
+
+ void
+ test_1d (void) {
+ Lvalue_proxy<Dense> p;
+ float b;
+ b + p;
+ }
+
+ Here, if Lvalue_proxy is permitted to bind to View, then
+ the global operator+ will be used; if they are not, the
+ Lvalue_proxy will be converted to float. */
+ if (coerce_template_parms (argtmplvec, parmvec,
+ TYPE_TI_TEMPLATE (parm),
+ tf_none,
+ /*require_all_args=*/true,
+ /*use_default_args=*/false)
== error_mark_node)
return 1;
return 1;
}
- TREE_VEC_ELT (targs, idx) = arg;
+ TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
return 0;
case TEMPLATE_PARM_INDEX:
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0));
+ if (tparm == error_mark_node)
+ return 1;
if (TEMPLATE_PARM_LEVEL (parm)
!= template_decl_level (tparm))
&& cp_tree_equal (parm, arg));
idx = TEMPLATE_PARM_IDX (parm);
- targ = TREE_VEC_ELT (targs, idx);
+ targ = TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx);
if (targ)
return !cp_tree_equal (targ, arg);
else
return 1;
- TREE_VEC_ELT (targs, idx) = arg;
+ TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
return 0;
case PTRMEM_CST:
{
tree parm_max;
tree arg_max;
-
- parm_max = TYPE_MAX_VALUE (TYPE_DOMAIN (parm));
- arg_max = TYPE_MAX_VALUE (TYPE_DOMAIN (arg));
+ bool parm_cst;
+ bool arg_cst;
/* 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)
+ not an integer constant. We cannot unify arbitrarily
+ complex expressions, so we eliminate the MINUS_EXPRs
+ here. */
+ parm_max = TYPE_MAX_VALUE (TYPE_DOMAIN (parm));
+ parm_cst = TREE_CODE (parm_max) == INTEGER_CST;
+ if (!parm_cst)
{
- arg_max = fold_build2 (PLUS_EXPR,
- integer_type_node,
- arg_max,
- TREE_OPERAND (parm_max, 1));
+ gcc_assert (TREE_CODE (parm_max) == MINUS_EXPR);
parm_max = TREE_OPERAND (parm_max, 0);
}
+ arg_max = TYPE_MAX_VALUE (TYPE_DOMAIN (arg));
+ arg_cst = TREE_CODE (arg_max) == INTEGER_CST;
+ if (!arg_cst)
+ {
+ /* The ARG_MAX may not be a simple MINUS_EXPR, if we are
+ trying to unify the type of a variable with the type
+ of a template parameter. For example:
+
+ template <unsigned int N>
+ void f (char (&) [N]);
+ int g();
+ void h(int i) {
+ char a[g(i)];
+ f(a);
+ }
+
+ Here, the type of the ARG will be "int [g(i)]", and
+ may be a SAVE_EXPR, etc. */
+ if (TREE_CODE (arg_max) != MINUS_EXPR)
+ return 1;
+ arg_max = TREE_OPERAND (arg_max, 0);
+ }
+
+ /* If only one of the bounds used a MINUS_EXPR, compensate
+ by adding one to the other bound. */
+ if (parm_cst && !arg_cst)
+ parm_max = fold_build2 (PLUS_EXPR,
+ integer_type_node,
+ parm_max,
+ integer_one_node);
+ else if (arg_cst && !parm_cst)
+ arg_max = fold_build2 (PLUS_EXPR,
+ integer_type_node,
+ arg_max,
+ integer_one_node);
if (unify (tparms, targs, parm_max, arg_max, UNIFY_ALLOW_INTEGER))
return 1;
return 1;
/* CV qualifications for methods can never be deduced, they must
- match exactly. We need to check them explicitly here,
- because type_unification_real treats them as any other
- cvqualified parameter. */
+ match exactly. We need to check them explicitly here,
+ because type_unification_real treats them as any other
+ cvqualified parameter. */
if (TREE_CODE (parm) == METHOD_TYPE
&& (!check_cv_quals_for_unify
(UNIFY_ALLOW_NONE,
tree args2 = TYPE_ARG_TYPES (TREE_TYPE (decl2));
int better1 = 0;
int better2 = 0;
-
+
/* Remove the this parameter from non-static member functions. If
one is a non-static member function and the other is not a static
member function, remove the first parameter from that function
args1 = TREE_CHAIN (args1);
}
}
-
+
/* If only one is a conversion operator, they are unordered. */
if (DECL_CONV_FN_P (decl1) != DECL_CONV_FN_P (decl2))
return 0;
return (better1 > 0) - (better2 > 0);
}
-/* Given two class template specialization list nodes PAT1 and PAT2, return:
+/* Determine which of two partial specializations is more specialized.
- 1 if PAT1 is more specialized than PAT2 as described in [temp.class.order].
- -1 if PAT2 is more specialized than PAT1.
- 0 if neither is more specialized.
+ PAT1 is a TREE_LIST whose TREE_TYPE is the _TYPE node corresponding
+ to the first partial specialization. The TREE_VALUE is the
+ innermost set of template parameters for the partial
+ specialization. PAT2 is similar, but for the second template.
- FULL_ARGS is the full set of template arguments that triggers this
- partial ordering. */
+ Return 1 if the first partial specialization is more specialized;
+ -1 if the second is more specialized; 0 if neither is more
+ specialized.
-int
-more_specialized_class (tree pat1, tree pat2, tree full_args)
+ See [temp.class.order] for information about determining which of
+ two templates is more specialized. */
+
+static int
+more_specialized_class (tree pat1, tree pat2)
{
tree targs;
+ tree tmpl1, tmpl2;
int winner = 0;
+ tmpl1 = TREE_TYPE (pat1);
+ tmpl2 = TREE_TYPE (pat2);
+
/* 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)));
+ targs = get_class_bindings (TREE_VALUE (pat1),
+ CLASSTYPE_TI_ARGS (tmpl1),
+ CLASSTYPE_TI_ARGS (tmpl2));
if (targs)
--winner;
- targs = get_class_bindings (TREE_VALUE (pat2), TREE_PURPOSE (pat2),
- add_outermost_template_args (full_args, TREE_PURPOSE (pat1)));
+ targs = get_class_bindings (TREE_VALUE (pat2),
+ CLASSTYPE_TI_ARGS (tmpl2),
+ CLASSTYPE_TI_ARGS (tmpl1));
if (targs)
++winner;
--processing_template_decl;
return NULL_TREE;
converted_args
- = (coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
- explicit_args, NULL_TREE,
- tf_none, /*require_all_arguments=*/0));
+ = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
+ explicit_args, NULL_TREE,
+ tf_none,
+ /*require_all_args=*/false,
+ /*use_default_args=*/false);
if (converted_args == error_mark_node)
return NULL_TREE;
template <class T> struct S<T*, int> {};
Then, suppose we want to get `S<double*, int>'. The TPARMS will be
- {T}, the PARMS will be {T*, int} and the ARGS will be {double*,
+ {T}, the SPEC_ARGS will be {T*, int} and the ARGS will be {double*,
int}. The resulting vector will be {double}, indicating that `T'
is bound to `double'. */
static tree
-get_class_bindings (tree tparms, tree parms, tree args)
+get_class_bindings (tree tparms, tree spec_args, tree args)
{
int i, ntparms = TREE_VEC_LENGTH (tparms);
- tree vec = make_tree_vec (ntparms);
+ tree deduced_args;
+ tree innermost_deduced_args;
+
+ innermost_deduced_args = make_tree_vec (ntparms);
+ if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
+ {
+ deduced_args = copy_node (args);
+ SET_TMPL_ARGS_LEVEL (deduced_args,
+ TMPL_ARGS_DEPTH (deduced_args),
+ innermost_deduced_args);
+ }
+ else
+ deduced_args = innermost_deduced_args;
- if (unify (tparms, vec, parms, INNERMOST_TEMPLATE_ARGS (args),
+ if (unify (tparms, deduced_args,
+ INNERMOST_TEMPLATE_ARGS (spec_args),
+ INNERMOST_TEMPLATE_ARGS (args),
UNIFY_ALLOW_NONE))
return NULL_TREE;
for (i = 0; i < ntparms; ++i)
- if (! TREE_VEC_ELT (vec, i))
+ if (! TREE_VEC_ELT (innermost_deduced_args, i))
return NULL_TREE;
- if (verify_class_unification (vec, parms, args))
+ /* Verify that nondeduced template arguments agree with the type
+ obtained from argument deduction.
+
+ For example:
+
+ struct A { typedef int X; };
+ template <class T, class U> struct C {};
+ template <class T> struct C<T, typename T::X> {};
+
+ Then with the instantiation `C<A, int>', we can deduce that
+ `T' is `A' but unify () does not check whether `typename T::X'
+ is `int'. */
+ spec_args = tsubst (spec_args, deduced_args, tf_none, NULL_TREE);
+ if (spec_args == error_mark_node
+ /* We only need to check the innermost arguments; the other
+ arguments will always agree. */
+ || !comp_template_args (INNERMOST_TEMPLATE_ARGS (spec_args),
+ INNERMOST_TEMPLATE_ARGS (args)))
return NULL_TREE;
- return vec;
+ return deduced_args;
}
-/* In INSTANTIATIONS is a list of <INSTANTIATION, TEMPLATE> pairs.
- Pick the most specialized template, and return the corresponding
- instantiation, or if there is no corresponding instantiation, the
- template itself. If there is no most specialized template,
- error_mark_node is returned. If there are no templates at all,
- NULL_TREE is returned. */
+/* TEMPLATES is a TREE_LIST. Each TREE_VALUE is a TEMPLATE_DECL.
+ Return the TREE_LIST node with the most specialized template, if
+ any. If there is no most specialized template, the error_mark_node
+ is returned.
+
+ Note that this function does not look at, or modify, the
+ TREE_PURPOSE or TREE_TYPE of any of the nodes. Since the node
+ returned is one of the elements of INSTANTIATIONS, callers may
+ store information in the TREE_PURPOSE or TREE_TYPE of the nodes,
+ and retrieve it from the value returned. */
tree
-most_specialized_instantiation (tree instantiations)
+most_specialized_instantiation (tree templates)
{
tree fn, champ;
- if (!instantiations)
- return NULL_TREE;
-
++processing_template_decl;
- champ = instantiations;
- for (fn = TREE_CHAIN (instantiations); fn; fn = TREE_CHAIN (fn))
+ champ = templates;
+ for (fn = TREE_CHAIN (templates); fn; fn = TREE_CHAIN (fn))
{
int fate = 0;
/* Equally specialized, move to next function. If there
is no next function, nothing's most specialized. */
fn = TREE_CHAIN (fn);
+ champ = fn;
if (!fn)
break;
}
if (champ)
/* Now verify that champ is better than everything earlier in the
instantiation list. */
- for (fn = instantiations; fn != champ; fn = TREE_CHAIN (fn))
+ for (fn = templates; fn != champ; fn = TREE_CHAIN (fn))
if (get_bindings (TREE_VALUE (champ),
DECL_TEMPLATE_RESULT (TREE_VALUE (fn)),
NULL_TREE, /*check_ret=*/false)
if (!champ)
return error_mark_node;
- return TREE_PURPOSE (champ) ? TREE_PURPOSE (champ) : TREE_VALUE (champ);
-}
-
-/* Return the most specialized of the list of templates in FNS that can
- produce an instantiation matching DECL, given the explicit template
- arguments EXPLICIT_ARGS. */
-
-static tree
-most_specialized (tree fns, tree decl, tree explicit_args)
-{
- tree candidates = NULL_TREE;
- tree fn, args;
-
- for (fn = fns; fn; fn = TREE_CHAIN (fn))
- {
- tree candidate = TREE_VALUE (fn);
-
- args = get_bindings (candidate, decl, explicit_args, /*check_ret=*/true);
- if (args)
- candidates = tree_cons (NULL_TREE, candidate, candidates);
- }
-
- return most_specialized_instantiation (candidates);
+ return champ;
}
/* If DECL is a specialization of some template, return the most
return decl;
}
-/* Return the most specialized of the class template specializations
- of TMPL which can produce an instantiation matching ARGS, or
- error_mark_node if the choice is ambiguous. */
+/* Return the most specialized of the class template partial
+ specializations of TMPL which can produce TYPE, a specialization of
+ TMPL. The value returned is actually a TREE_LIST; the TREE_TYPE is
+ a _TYPE node corresponding to the partial specialization, while the
+ TREE_PURPOSE is the set of template arguments that must be
+ substituted into the TREE_TYPE in order to generate TYPE.
+
+ If the choice of partial specialization is ambiguous, a diagnostic
+ is issued, and the error_mark_node is returned. If there are no
+ partial specializations of TMPL matching TYPE, then NULL_TREE is
+ returned. */
static tree
-most_specialized_class (tree tmpl, tree args)
+most_specialized_class (tree type, tree tmpl)
{
tree list = NULL_TREE;
tree t;
tree champ;
int fate;
+ bool ambiguous_p;
+ tree args;
tmpl = most_general_template (tmpl);
+ args = CLASSTYPE_TI_ARGS (type);
for (t = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); t; t = TREE_CHAIN (t))
{
- tree spec_args
- = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args);
+ tree partial_spec_args;
+ tree spec_args;
+
+ partial_spec_args = CLASSTYPE_TI_ARGS (TREE_TYPE (t));
+ spec_args = get_class_bindings (TREE_VALUE (t),
+ partial_spec_args,
+ args);
if (spec_args)
{
- list = tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list);
+ list = tree_cons (spec_args, TREE_VALUE (t), list);
TREE_TYPE (list) = TREE_TYPE (t);
}
}
if (! list)
return NULL_TREE;
+ ambiguous_p = false;
t = list;
champ = t;
t = TREE_CHAIN (t);
for (; t; t = TREE_CHAIN (t))
{
- fate = more_specialized_class (champ, t, args);
+ fate = more_specialized_class (champ, t);
if (fate == 1)
;
else
{
t = TREE_CHAIN (t);
if (! t)
- return error_mark_node;
+ {
+ ambiguous_p = true;
+ break;
+ }
}
champ = t;
}
}
- for (t = list; t && t != champ; t = TREE_CHAIN (t))
+ if (!ambiguous_p)
+ for (t = list; t && t != champ; t = TREE_CHAIN (t))
+ {
+ fate = more_specialized_class (champ, t);
+ if (fate != 1)
+ {
+ ambiguous_p = true;
+ break;
+ }
+ }
+
+ if (ambiguous_p)
{
- fate = more_specialized_class (champ, t, args);
- if (fate != 1)
- return error_mark_node;
+ const char *str = "candidates are:";
+ error ("ambiguous class template instantiation for %q#T", type);
+ for (t = list; t; t = TREE_CHAIN (t))
+ {
+ error ("%s %+#T", str, TREE_TYPE (t));
+ str = " ";
+ }
+ return error_mark_node;
}
return champ;
tree result = NULL_TREE;
int extern_p = 0;
- if (!decl)
+ if (!decl || decl == error_mark_node)
/* An error occurred, for which grokdeclarator has already issued
an appropriate message. */
return;
}
else
error ("storage class %qD applied to template instantiation", storage);
-
+
check_explicit_instantiation_namespace (result);
mark_decl_instantiated (result, extern_p);
if (! extern_p)
- instantiate_decl (result, /*defer_ok=*/1,
+ instantiate_decl (result, /*defer_ok=*/1,
/*expl_inst_class_mem_p=*/false);
}
-void
+static void
mark_class_instantiated (tree t, int extern_p)
{
SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t);
{
mark_decl_instantiated (decl, extern_p);
if (! extern_p)
- instantiate_decl (decl, /*defer_ok=*/1,
+ instantiate_decl (decl, /*defer_ok=*/1,
/*expl_inst_class_mem_p=*/true);
}
else if (TREE_CODE (decl) == VAR_DECL)
DECL_INITIAL (decl) =
tsubst_expr (DECL_INITIAL (code_pattern), args,
- tf_error, DECL_TI_TEMPLATE (decl));
+ tf_error, DECL_TI_TEMPLATE (decl),
+ /*integral_constant_expression_p=*/false);
else
gcc_unreachable ();
explicitly instantiated class template. */
tree
-instantiate_decl (tree d, int defer_ok,
+instantiate_decl (tree d, int defer_ok,
bool expl_inst_class_mem_p)
{
tree tmpl = DECL_TI_TEMPLATE (d);
code_pattern = DECL_TEMPLATE_RESULT (td);
/* We should never be trying to instantiate a member of a class
- template or partial specialization. */
+ template or partial specialization. */
gcc_assert (d != code_pattern);
-
+
if ((DECL_NAMESPACE_SCOPE_P (d) && !DECL_INITIALIZED_IN_CLASS_P (d))
|| DECL_TEMPLATE_SPECIALIZATION (td))
/* In the case of a friend template whose definition is provided
/* If D is a member of an explicitly instantiated class template,
and no definition is available, treat it like an implicit
- instantiation. */
- if (!pattern_defined && expl_inst_class_mem_p
- && DECL_EXPLICIT_INSTANTIATION (d))
+ instantiation. */
+ if (!pattern_defined && expl_inst_class_mem_p
+ && DECL_EXPLICIT_INSTANTIATION (d))
{
DECL_NOT_REALLY_EXTERN (d) = 0;
DECL_INTERFACE_KNOWN (d) = 0;
if (TREE_CODE (gen) == FUNCTION_DECL)
{
- tsubst (DECL_ARGUMENTS (gen), gen_args, tf_error | tf_warning, d);
+ tsubst (DECL_ARGUMENTS (gen), gen_args, tf_warning_or_error, d);
tsubst (TYPE_RAISES_EXCEPTIONS (type), gen_args,
- tf_error | tf_warning, d);
+ tf_warning_or_error, d);
/* Don't simply tsubst the function type, as that will give
duplicate warnings about poor parameter qualifications.
The function arguments are the same as the decl_arguments
without the top level cv qualifiers. */
type = TREE_TYPE (type);
}
- tsubst (type, gen_args, tf_error | tf_warning, d);
+ tsubst (type, gen_args, tf_warning_or_error, d);
pop_access_scope (d);
}
&& ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d))
/* ... we instantiate static data members whose values are
needed in integral constant expressions. */
- && ! (TREE_CODE (d) == VAR_DECL
+ && ! (TREE_CODE (d) == VAR_DECL
&& DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (d)))
goto out;
/* Defer all other templates, unless we have been explicitly
forbidden from doing so. */
if (/* If there is no definition, we cannot instantiate the
template. */
- ! pattern_defined
+ ! pattern_defined
/* If it's OK to postpone instantiation, do so. */
|| defer_ok
/* If this is a static data member that will be defined
/* The definition of the static data member is now required so
we must substitute the initializer. */
if (TREE_CODE (d) == VAR_DECL
- && !DECL_INITIAL (d)
+ && !DECL_INITIAL (d)
&& DECL_INITIAL (code_pattern))
{
tree ns;
ns = decl_namespace_context (d);
push_nested_namespace (ns);
push_nested_class (DECL_CONTEXT (d));
- init = tsubst_expr (DECL_INITIAL (code_pattern),
+ init = tsubst_expr (DECL_INITIAL (code_pattern),
args,
- tf_error | tf_warning, NULL_TREE);
- DECL_INITIAL (d) = init;
- cp_finish_decl (d, init, /*asmspec_tree=*/NULL_TREE,
+ tf_warning_or_error, NULL_TREE,
+ /*integral_constant_expression_p=*/false);
+ cp_finish_decl (d, init, /*init_const_expr_p=*/false,
+ /*asmspec_tree=*/NULL_TREE,
LOOKUP_ONLYCONVERTING);
pop_nested_class ();
pop_nested_namespace (ns);
if (TREE_CODE (d) == VAR_DECL)
{
+ tree init;
+
/* 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;
+ /* The initializer is placed in DECL_INITIAL by
+ regenerate_decl_from_template. Pull it out so that
+ finish_decl can process it. */
+ init = DECL_INITIAL (d);
+ DECL_INITIAL (d) = NULL_TREE;
+ DECL_INITIALIZED_P (d) = 0;
+
/* 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. */
/* Enter the scope of D so that access-checking works correctly. */
push_nested_class (DECL_CONTEXT (d));
- cp_finish_decl (d, DECL_INITIAL (d), NULL_TREE, 0);
+ finish_decl (d, init, NULL_TREE);
pop_nested_class ();
}
else if (TREE_CODE (d) == FUNCTION_DECL)
/* Substitute into the body of the function. */
tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
- tf_error | tf_warning, tmpl);
+ tf_warning_or_error, tmpl,
+ /*integral_constant_expression_p=*/false);
/* We don't need the local specializations any more. */
htab_delete (local_specializations);
fn;
fn = TREE_CHAIN (fn))
if (! DECL_ARTIFICIAL (fn))
- instantiate_decl (fn,
+ instantiate_decl (fn,
/*defer_ok=*/0,
/*expl_inst_class_mem_p=*/false);
if (COMPLETE_TYPE_P (instantiation))
if (!DECL_TEMPLATE_SPECIALIZATION (instantiation)
&& !DECL_TEMPLATE_INSTANTIATED (instantiation))
{
- instantiation
+ instantiation
= instantiate_decl (instantiation,
/*defer_ok=*/0,
/*expl_inst_class_mem_p=*/false);
tree decl;
tree init;
- decl = tsubst_copy (TREE_PURPOSE (t), argvec, tf_error | tf_warning,
+ decl = tsubst_copy (TREE_PURPOSE (t), argvec, tf_warning_or_error,
NULL_TREE);
decl = expand_member_init (decl);
if (decl && !DECL_P (decl))
in_base_initializer = 1;
- init = tsubst_expr (TREE_VALUE (t), argvec, tf_error | tf_warning,
- NULL_TREE);
+ init = tsubst_expr (TREE_VALUE (t), argvec, tf_warning_or_error,
+ NULL_TREE,
+ /*integral_constant_expression_p=*/false);
in_base_initializer = 0;
if (decl)
/* Note that in a template enum, the TREE_VALUE is the
CONST_DECL, not the corresponding INTEGER_CST. */
value = tsubst_expr (DECL_INITIAL (decl),
- args, tf_error | tf_warning,
- NULL_TREE);
+ args, tf_warning_or_error, NULL_TREE,
+ /*integral_constant_expression_p=*/true);
/* Give this enumeration constant the correct access. */
set_current_access_from_decl (decl);
/* If there are no template parameters in scope, then there can't be
any dependent types. */
if (!processing_template_decl)
- return false;
+ {
+ /* If we are not processing a template, then nobody should be
+ providing us with a dependent type. */
+ gcc_assert (type);
+ gcc_assert (TREE_CODE (type) != TEMPLATE_TYPE_PARM);
+ return false;
+ }
/* If the type is NULL, we have not computed a type for the entity
in question; in that case, the type is dependent. */
}
/* Returns TRUE if the EXPRESSION is value-dependent, in the sense of
- [temp.dep.constexpr] */
+ [temp.dep.constexpr]. EXPRESSION is already known to be a constant
+ expression. */
bool
value_dependent_expression_p (tree expression)
|| value_dependent_expression_p (TREE_OPERAND (expression, 1)));
case CALL_EXPR:
- /* A CALL_EXPR is value-dependent if any argument is
- value-dependent. Why do we have to handle CALL_EXPRs in this
- function at all? First, some function calls, those for which
- value_dependent_expression_p is true, man appear in constant
- expressions. Second, there appear to be bugs which result in
- other CALL_EXPRs reaching this point. */
- {
- tree function = TREE_OPERAND (expression, 0);
- tree args = TREE_OPERAND (expression, 1);
-
- if (value_dependent_expression_p (function))
- return true;
-
- if (! args)
- return false;
-
- if (TREE_CODE (args) == TREE_LIST)
- {
- for (; args; args = TREE_CHAIN (args))
- if (value_dependent_expression_p (TREE_VALUE (args)))
- return true;
- return false;
- }
-
- return value_dependent_expression_p (args);
- }
+ /* A CALL_EXPR may appear in a constant expression if it is a
+ call to a builtin function, e.g., __builtin_constant_p. All
+ such calls are value-dependent. */
+ return true;
default:
/* A constant expression is value-dependent if any subexpression is
return false;
/* An unresolved name is always dependent. */
- if (TREE_CODE (expression) == IDENTIFIER_NODE)
+ if (TREE_CODE (expression) == IDENTIFIER_NODE
+ || TREE_CODE (expression) == USING_DECL)
return true;
/* Some expression forms are never type-dependent. */
}
gcc_assert (TREE_CODE (expression) != TYPE_DECL);
-
+
return (dependent_type_p (TREE_TYPE (expression)));
}
if (!args)
return false;
+ if (args == error_mark_node)
+ return true;
for (i = 0; i < TMPL_ARGS_DEPTH (args); ++i)
{
return expr;
/* Preserve OVERLOADs; the functions must be available to resolve
types. */
- inner_expr = (TREE_CODE (expr) == ADDR_EXPR ?
- TREE_OPERAND (expr, 0) :
- TREE_CODE (expr) == COMPONENT_REF ?
- TREE_OPERAND (expr, 1) : expr);
+ inner_expr = expr;
+ if (TREE_CODE (inner_expr) == ADDR_EXPR)
+ inner_expr = TREE_OPERAND (inner_expr, 0);
+ if (TREE_CODE (inner_expr) == COMPONENT_REF)
+ inner_expr = TREE_OPERAND (inner_expr, 1);
if (is_overloaded_fn (inner_expr)
|| TREE_CODE (inner_expr) == OFFSET_REF)
return expr;
/* If the type is unknown, it can't really be non-dependent */
gcc_assert (TREE_TYPE (expr) != unknown_type_node);
-
+
/* Otherwise, build a NON_DEPENDENT_EXPR.
REFERENCE_TYPEs are not stripped for expressions in templates