/* Handle parameterized types (templates) for GNU C++.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+ 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
Rewritten by Jason Merrill (jason@cygnus.com).
#include "system.h"
#include "coretypes.h"
#include "tm.h"
-#include "obstack.h"
#include "tree.h"
#include "intl.h"
#include "pointer-set.h"
#include "flags.h"
-#include "c-common.h"
#include "cp-tree.h"
+#include "c-family/c-common.h"
#include "cp-objcp-common.h"
#include "tree-inline.h"
#include "decl.h"
#include "output.h"
-#include "except.h"
#include "toplev.h"
-#include "rtl.h"
#include "timevar.h"
#include "tree-iterator.h"
#include "vecprim.h"
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 tree reopen_tinst_level (struct tinst_level *);
static tree tsubst_initializer_list (tree, tree);
static tree get_class_bindings (tree, tree, tree);
unsigned int, int, unification_kind_t, int);
static void note_template_header (int);
static tree convert_nontype_argument_function (tree, tree);
-static tree convert_nontype_argument (tree, tree);
+static tree convert_nontype_argument (tree, tree, tsubst_flags_t);
static tree convert_template_argument (tree, tree, tree,
tsubst_flags_t, int, tree);
static int for_each_template_parm (tree, tree_fn_t, void*,
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_class (tree, tree);
+static tree most_specialized_class (tree, tree, tsubst_flags_t);
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 tsubst_function_type (tree, tree, tsubst_flags_t, tree);
if (TAGGED_TYPE_P (t))
tinfo = TYPE_TEMPLATE_INFO (t);
+ else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
+ tinfo = TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t);
return tinfo;
}
int i;
int j;
+ if (args == NULL_TREE)
+ return extra_args;
+
extra_depth = TMPL_ARGS_DEPTH (extra_args);
new_args = make_tree_vec (TMPL_ARGS_DEPTH (args) + extra_depth);
slot = (spec_entry **)
htab_find_slot (type_specializations, &elt, INSERT);
- *slot = GGC_NEW (spec_entry);
+ *slot = ggc_alloc_spec_entry ();
**slot = elt;
}
- else if (COMPLETE_TYPE_P (inst) || TYPE_BEING_DEFINED (inst))
+ else if (COMPLETE_OR_OPEN_TYPE_P (inst))
/* But if we've had an implicit instantiation, that's a
problem ([temp.expl.spec]/6). */
error ("specialization %qT after instantiation %qT",
if (!optimize_specialization_lookup_p (tmpl))
{
gcc_assert (tmpl && args && spec);
- *slot = GGC_NEW (spec_entry);
+ *slot = ggc_alloc_spec_entry ();
**slot = elt;
if (TREE_CODE (spec) == FUNCTION_DECL && DECL_NAMESPACE_SCOPE_P (spec)
&& PRIMARY_TEMPLATE_P (tmpl)
val = iterative_hash_object (code, val);
return iterative_hash_template_arg (TREE_OPERAND (arg, 2), val);
+ case ARRAY_TYPE:
+ /* layout_type sets structural equality for arrays of
+ incomplete type, so we can't rely on the canonical type
+ for hashing. */
+ val = iterative_hash_template_arg (TREE_TYPE (arg), val);
+ return iterative_hash_template_arg (TYPE_DOMAIN (arg), val);
+
+ case LAMBDA_EXPR:
+ /* A lambda can't appear in a template arg, but don't crash on
+ erroneous input. */
+ gcc_assert (seen_error ());
+ return val;
+
+ case CAST_EXPR:
+ case STATIC_CAST_EXPR:
+ case REINTERPRET_CAST_EXPR:
+ case CONST_CAST_EXPR:
+ case DYNAMIC_CAST_EXPR:
+ case NEW_EXPR:
+ val = iterative_hash_template_arg (TREE_TYPE (arg), val);
+ /* Now hash operands as usual. */
+ break;
+
default:
- switch (tclass)
- {
- case tcc_type:
- if (TYPE_CANONICAL (arg))
- return iterative_hash_object (TYPE_HASH (TYPE_CANONICAL (arg)),
- val);
- else if (TREE_CODE (arg) == DECLTYPE_TYPE)
- return iterative_hash_template_arg (DECLTYPE_TYPE_EXPR (arg), val);
- /* Otherwise just compare the types during lookup. */
- return val;
+ break;
+ }
- case tcc_declaration:
- case tcc_constant:
- return iterative_hash_expr (arg, val);
+ switch (tclass)
+ {
+ case tcc_type:
+ if (TYPE_CANONICAL (arg))
+ return iterative_hash_object (TYPE_HASH (TYPE_CANONICAL (arg)),
+ val);
+ else if (TREE_CODE (arg) == DECLTYPE_TYPE)
+ return iterative_hash_template_arg (DECLTYPE_TYPE_EXPR (arg), val);
+ /* Otherwise just compare the types during lookup. */
+ return val;
- default:
- gcc_assert (IS_EXPR_CODE_CLASS (tclass));
- {
- unsigned n = TREE_OPERAND_LENGTH (arg);
- for (i = 0; i < n; ++i)
- val = iterative_hash_template_arg (TREE_OPERAND (arg, i), val);
- return val;
- }
- }
+ case tcc_declaration:
+ case tcc_constant:
+ return iterative_hash_expr (arg, val);
+
+ default:
+ gcc_assert (IS_EXPR_CODE_CLASS (tclass));
+ {
+ unsigned n = TREE_OPERAND_LENGTH (arg);
+ for (i = 0; i < n; ++i)
+ val = iterative_hash_template_arg (TREE_OPERAND (arg, i), val);
+ return val;
+ }
}
gcc_unreachable ();
return 0;
definition, not in the original declaration. */
DECL_ARGUMENTS (result) = DECL_ARGUMENTS (decl);
for (parm = DECL_ARGUMENTS (result); parm;
- parm = TREE_CHAIN (parm))
+ parm = DECL_CHAIN (parm))
DECL_CONTEXT (parm) = result;
}
return register_specialization (tmpl, gen_tmpl, targs,
return parms;
}
+/* Return the template parameters of the LEVELth level from the full list
+ of template parameters PARMS. */
+
+tree
+get_template_parms_at_level (tree parms, int level)
+{
+ tree p;
+ if (!parms
+ || TREE_CODE (parms) != TREE_LIST
+ || level > TMPL_PARMS_DEPTH (parms))
+ return NULL_TREE;
+
+ for (p = parms; p; p = TREE_CHAIN (p))
+ if (TMPL_PARMS_DEPTH (p) == level)
+ return p;
+
+ return NULL_TREE;
+}
+
/* Returns the template arguments of T if T is a template instantiation,
NULL otherwise. */
tree result_args = NULL_TREE;
int in_arg, out_arg = 0, nargs = args ? TREE_VEC_LENGTH (args) : 0;
int num_result_args = -1;
+ int non_default_args_count = -1;
/* First, determine if we need to expand anything, and the number of
slots we'll need. */
/* Expand arguments. */
result_args = make_tree_vec (num_result_args);
+ if (NON_DEFAULT_TEMPLATE_ARGS_COUNT (args))
+ non_default_args_count =
+ GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (args);
for (in_arg = 0; in_arg < nargs; ++in_arg)
{
tree arg = TREE_VEC_ELT (args, in_arg);
int i, num_packed = TREE_VEC_LENGTH (packed);
for (i = 0; i < num_packed; ++i, ++out_arg)
TREE_VEC_ELT (result_args, out_arg) = TREE_VEC_ELT(packed, i);
+ if (non_default_args_count > 0)
+ non_default_args_count += num_packed;
}
else
{
++out_arg;
}
}
-
+ if (non_default_args_count >= 0)
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (result_args, non_default_args_count);
return result_args;
}
next = TREE_CHAIN (parm);
TREE_VEC_ELT (saved_parmlist, nparms) = parm;
TREE_CHAIN (parm) = NULL_TREE;
+ if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
+ TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
+ current_template_parms;
}
--processing_template_parmlist;
/* Turn this argument into a TYPE_ARGUMENT_PACK
with a single element, which expands T. */
tree vec = make_tree_vec (1);
+#ifdef ENABLE_CHECKING
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+ (vec, TREE_VEC_LENGTH (vec));
+#endif
TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
t = cxx_make_type (TYPE_ARGUMENT_PACK);
with a single element, which expands T. */
tree vec = make_tree_vec (1);
tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
+#ifdef ENABLE_CHECKING
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+ (vec, TREE_VEC_LENGTH (vec));
+#endif
TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
t = make_node (NONTYPE_ARGUMENT_PACK);
}
}
+#ifdef ENABLE_CHECKING
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, TREE_VEC_LENGTH (a));
+#endif
+
if (length > 1)
TREE_VEC_ELT (args, --l) = a;
else
return args;
}
+/* Update the declared TYPE by doing any lookups which were thought to be
+ dependent, but are not now that we know the SCOPE of the declarator. */
+
+tree
+maybe_update_decl_type (tree orig_type, tree scope)
+{
+ tree type = orig_type;
+
+ if (type == NULL_TREE)
+ return type;
+
+ if (TREE_CODE (orig_type) == TYPE_DECL)
+ type = TREE_TYPE (type);
+
+ if (scope && TYPE_P (scope) && dependent_type_p (scope)
+ && dependent_type_p (type)
+ /* Don't bother building up the args in this case. */
+ && TREE_CODE (type) != TEMPLATE_TYPE_PARM)
+ {
+ /* tsubst in the args corresponding to the template parameters,
+ including auto if present. Most things will be unchanged, but
+ make_typename_type and tsubst_qualified_id will resolve
+ TYPENAME_TYPEs and SCOPE_REFs that were previously dependent. */
+ tree args = current_template_args ();
+ tree auto_node = type_uses_auto (type);
+ tree pushed;
+ if (auto_node)
+ {
+ tree auto_vec = make_tree_vec (1);
+ TREE_VEC_ELT (auto_vec, 0) = auto_node;
+ args = add_to_template_args (args, auto_vec);
+ }
+ pushed = push_scope (scope);
+ type = tsubst (type, args, tf_warning_or_error, NULL_TREE);
+ if (pushed)
+ pop_scope (scope);
+ }
+
+ if (type == error_mark_node)
+ return orig_type;
+
+ if (TREE_CODE (orig_type) == TYPE_DECL)
+ {
+ if (same_type_p (type, TREE_TYPE (orig_type)))
+ type = orig_type;
+ else
+ type = TYPE_NAME (type);
+ }
+ return type;
+}
+
/* Return a TEMPLATE_DECL corresponding to DECL, using the indicated
template PARMS. If MEMBER_TEMPLATE_P is true, the new template is
a member template. Used by push_template_decl below. */
tree inner_args = INNERMOST_TEMPLATE_ARGS (specargs);
tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl);
tree inner_parms;
+ tree inst;
int nargs = TREE_VEC_LENGTH (inner_args);
int ntparms;
int i;
- int did_error_intro = 0;
+ bool did_error_intro = false;
struct template_parm_data tpd;
struct template_parm_data tpd2;
or some such would have been OK. */
tpd.level = TMPL_PARMS_DEPTH (current_template_parms);
- tpd.parms = (int *) alloca (sizeof (int) * ntparms);
+ tpd.parms = XALLOCAVEC (int, ntparms);
memset (tpd.parms, 0, sizeof (int) * ntparms);
- tpd.arg_uses_template_parms = (int *) alloca (sizeof (int) * nargs);
+ tpd.arg_uses_template_parms = XALLOCAVEC (int, nargs);
memset (tpd.arg_uses_template_parms, 0, sizeof (int) * nargs);
for (i = 0; i < nargs; ++i)
{
if (!did_error_intro)
{
error ("template parameters not used in partial specialization:");
- did_error_intro = 1;
+ did_error_intro = true;
}
error (" %qD", TREE_VALUE (TREE_VEC_ELT (inner_parms, i)));
}
+ if (did_error_intro)
+ return error_mark_node;
+
/* [temp.class.spec]
The argument list of the specialization shall not be identical to
if (!tpd2.parms)
{
/* We haven't yet initialized TPD2. Do so now. */
- tpd2.arg_uses_template_parms
- = (int *) alloca (sizeof (int) * nargs);
+ tpd2.arg_uses_template_parms = XALLOCAVEC (int, nargs);
/* The number of parameters here is the number in the
main template, which, as checked in the assertion
above, is NARGS. */
- tpd2.parms = (int *) alloca (sizeof (int) * nargs);
+ tpd2.parms = XALLOCAVEC (int, nargs);
tpd2.level =
TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (maintmpl));
}
If they are fully specialized in the
specialization, that's OK. */
int j;
+ int count = 0;
for (j = 0; j < nargs; ++j)
if (tpd2.parms[j] != 0
&& tpd.arg_uses_template_parms [j])
- {
- error ("type %qT of template argument %qE depends "
- "on template parameter(s)",
- type,
- arg);
- break;
- }
+ ++count;
+ if (count != 0)
+ error_n (input_location, count,
+ "type %qT of template argument %qE depends "
+ "on a template parameter",
+ "type %qT of template argument %qE depends "
+ "on template parameters",
+ type,
+ arg);
}
}
}
= tree_cons (specargs, inner_parms,
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
+
+ for (inst = DECL_TEMPLATE_INSTANTIATIONS (maintmpl); inst;
+ inst = TREE_CHAIN (inst))
+ {
+ tree inst_type = TREE_VALUE (inst);
+ if (COMPLETE_TYPE_P (inst_type)
+ && CLASSTYPE_IMPLICIT_INSTANTIATION (inst_type))
+ {
+ tree spec = most_specialized_class (inst_type, maintmpl, tf_none);
+ if (spec && TREE_TYPE (spec) == type)
+ permerror (input_location,
+ "partial specialization of %qT after instantiation "
+ "of %qT", type, inst_type);
+ }
+ }
+
return decl;
}
/* Figure out what error message to issue. */
if (is_friend_decl == 2)
- msg = "default template arguments may not be used in function template friend re-declaration";
+ msg = G_("default template arguments may not be used in function template "
+ "friend re-declaration");
else if (is_friend_decl)
- msg = "default template arguments may not be used in function template friend declarations";
+ msg = G_("default template arguments may not be used in function template "
+ "friend declarations");
else if (TREE_CODE (decl) == FUNCTION_DECL && (cxx_dialect == cxx98))
- msg = ("default template arguments may not be used in function templates "
- "without -std=c++0x or -std=gnu++0x");
+ msg = G_("default template arguments may not be used in function templates "
+ "without -std=c++0x or -std=gnu++0x");
else if (is_partial)
- msg = "default template arguments may not be used in partial specializations";
+ msg = G_("default template arguments may not be used in "
+ "partial specializations");
else
- msg = "default argument for template parameter for class enclosing %qD";
+ msg = G_("default argument for template parameter for class enclosing %qD");
if (current_class_type && TYPE_BEING_DEFINED (current_class_type))
/* If we're inside a class definition, there's no need to
/* At this point, if we're still interested in issuing messages,
they must apply to classes surrounding the object declared. */
if (msg)
- msg = "default argument for template parameter for class enclosing %qD";
+ msg = G_("default argument for template parameter for class "
+ "enclosing %qD");
}
return no_errors;
TREE_VALUE (argtype) = error_mark_node;
}
- arg = TREE_CHAIN (arg);
+ arg = DECL_CHAIN (arg);
argtype = TREE_CHAIN (argtype);
}
if (current == decl)
current = ctx;
+ else if (current == NULL_TREE)
+ /* Can happen in erroneous input. */
+ break;
else
current = (TYPE_P (current)
? TYPE_CONTEXT (current)
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
if (TREE_CODE (parm) == TEMPLATE_DECL)
DECL_CONTEXT (parm) = tmpl;
-
- if (TREE_CODE (TREE_TYPE (parm)) == TEMPLATE_TYPE_PARM)
- DECL_CONTEXT (TYPE_NAME (TREE_TYPE (parm))) = tmpl;
}
}
if (TREE_VEC_LENGTH (parms) != TREE_VEC_LENGTH (tmpl_parms))
{
- error ("redeclared with %d template parameter(s)",
- TREE_VEC_LENGTH (parms));
- inform (input_location, "previous declaration %q+D used %d template parameter(s)",
- tmpl, TREE_VEC_LENGTH (tmpl_parms));
+ error_n (input_location, TREE_VEC_LENGTH (parms),
+ "redeclared with %d template parameter",
+ "redeclared with %d template parameters",
+ TREE_VEC_LENGTH (parms));
+ inform_n (input_location, TREE_VEC_LENGTH (tmpl_parms),
+ "previous declaration %q+D used %d template parameter",
+ "previous declaration %q+D used %d template parameters",
+ tmpl, TREE_VEC_LENGTH (tmpl_parms));
return false;
}
continue;
tmpl_parm = TREE_VALUE (TREE_VEC_ELT (tmpl_parms, i));
+ if (tmpl_parm == error_mark_node)
+ return false;
+
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 (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)))
- || (TREE_CODE (tmpl_parm) != PARM_DECL
- && (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (tmpl_parm))
- != TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm))))
- || (TREE_CODE (tmpl_parm) == PARM_DECL
- && (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (tmpl_parm))
- != TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))))))
+ if (TREE_CODE (tmpl_parm) != TREE_CODE (parm)
+ || (TREE_CODE (tmpl_parm) != TYPE_DECL
+ && !same_type_p (TREE_TYPE (tmpl_parm), TREE_TYPE (parm)))
+ || (TREE_CODE (tmpl_parm) != PARM_DECL
+ && (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (tmpl_parm))
+ != TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm))))
+ || (TREE_CODE (tmpl_parm) == PARM_DECL
+ && (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (tmpl_parm))
+ != TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))))
{
error ("template parameter %q+#D", tmpl_parm);
error ("redeclared here as %q#D", parm);
/* Simplify EXPR if it is a non-dependent expression. Returns the
(possibly simplified) expression. */
-tree
-fold_non_dependent_expr (tree expr)
+static tree
+fold_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain)
{
if (expr == NULL_TREE)
return NULL_TREE;
processing_template_decl = 0;
expr = tsubst_copy_and_build (expr,
/*args=*/NULL_TREE,
- tf_error,
+ complain,
/*in_decl=*/NULL_TREE,
/*function_p=*/false,
/*integral_constant_expression_p=*/true);
return expr;
}
+tree
+fold_non_dependent_expr (tree expr)
+{
+ return fold_non_dependent_expr_sfinae (expr, tf_error);
+}
+
/* EXPR is an expression which is used in a constant-expression context.
For instance, it could be a VAR_DECL with a constant initializer.
Extract the innermost constant expression.
return false;
}
+/* Returns TRUE iff the address of OP is value-dependent.
+
+ 14.6.2.4 [temp.dep.temp]:
+ A non-integral non-type template-argument is dependent if its type is
+ dependent or it has either of the following forms
+ qualified-id
+ & qualified-id
+ and contains a nested-name-specifier which specifies a class-name that
+ names a dependent type.
+
+ We generalize this to just say that the address of a member of a
+ dependent class is value-dependent; the above doesn't cover the
+ address of a static data member named with an unqualified-id. */
+
+static bool
+has_value_dependent_address (tree op)
+{
+ /* We could use get_inner_reference here, but there's no need;
+ this is only relevant for template non-type arguments, which
+ can only be expressed as &id-expression. */
+ if (DECL_P (op))
+ {
+ tree ctx = CP_DECL_CONTEXT (op);
+ if (TYPE_P (ctx) && dependent_type_p (ctx))
+ return true;
+ }
+
+ return false;
+}
+
/* 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
hacks can go away after we fix the double coercion problem. */
static tree
-convert_nontype_argument (tree type, tree expr)
+convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
{
tree expr_type;
catch this later), but only to provide better diagnostic for this
common user mistake. As suggested by DR 100, we do not mention
linkage issues in the diagnostic as this is not the point. */
+ /* FIXME we're making this OK. */
if (TREE_CODE (expr) == STRING_CST)
{
- error ("%qE is not a valid template argument for type %qT "
- "because string literals can never be used in this context",
- expr, type);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument for type %qT "
+ "because string literals can never be used in this context",
+ expr, type);
return NULL_TREE;
}
+ /* Add the ADDR_EXPR now for the benefit of
+ value_dependent_expression_p. */
+ if (TYPE_PTROBV_P (type))
+ expr = decay_conversion (expr);
+
/* 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
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);
+ if (TYPE_REF_OBJ_P (type)
+ && has_value_dependent_address (expr))
+ /* If we want the address and it's value-dependent, don't fold. */;
+ else if (!type_unknown_p (expr))
+ expr = fold_non_dependent_expr_sfinae (expr, complain);
if (error_operand_p (expr))
return error_mark_node;
expr_type = TREE_TYPE (expr);
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ expr = mark_lvalue_use (expr);
+ else
+ expr = mark_rvalue_use (expr);
/* HACK: Due to double coercion, we can get a
NOP_EXPR<REFERENCE_TYPE>(ADDR_EXPR<POINTER_TYPE> (arg)) here,
do not fold into integer constants. */
if (TREE_CODE (expr) != INTEGER_CST)
{
- error ("%qE is not a valid template argument for type %qT "
- "because it is a non-constant expression", expr, type);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is a non-constant expression", expr, type);
return NULL_TREE;
}
/* At this point, an implicit conversion does what we want,
because we already know that the expression is of integral
type. */
- expr = ocp_convert (type, expr, CONV_IMPLICIT, LOOKUP_PROTECT);
+ expr = perform_implicit_conversion (type, expr, complain);
if (expr == error_mark_node)
return error_mark_node;
provide a superior diagnostic. */
if (!same_type_p (TREE_TYPE (expr), type))
{
- /* Make sure we are just one standard conversion off. */
- gcc_assert (can_convert (type, TREE_TYPE (expr)));
error ("%qE is not a valid template argument for type %qT "
"because it is of type %qT", expr, type,
TREE_TYPE (expr));
- inform (input_location, "standard conversions are not allowed in this context");
+ /* If we are just one standard conversion off, explain. */
+ if (can_convert (type, TREE_TYPE (expr)))
+ inform (input_location,
+ "standard conversions are not allowed in this context");
return NULL_TREE;
}
}
/* Sanity check: did we actually convert the argument to the
right type? */
- gcc_assert (same_type_p (type, TREE_TYPE (expr)));
+ gcc_assert (same_type_ignoring_top_level_qualifiers_p
+ (type, TREE_TYPE (expr)));
return expr;
}
conversions can occur is part of determining which
function template to call, or whether a given explicit
argument specification is valid. */
- val = convert_nontype_argument (t, orig_arg);
+ val = convert_nontype_argument (t, orig_arg, complain);
else
val = orig_arg;
}
SET_ARGUMENT_PACK_ARGS (argument_pack, packed_args);
+#ifdef ENABLE_CHECKING
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (packed_args,
+ TREE_VEC_LENGTH (packed_args));
+#endif
return argument_pack;
}
{
if (complain & tf_error)
{
- const char *or_more = "";
if (variadic_p)
{
- or_more = " or more";
--nparms;
+ error ("wrong number of template arguments "
+ "(%d, should be %d or more)", nargs, nparms);
}
-
- error ("wrong number of template arguments (%d, should be %d%s)",
- nargs, nparms, or_more);
+ else
+ error ("wrong number of template arguments "
+ "(%d, should be %d)", nargs, nparms);
if (in_decl)
error ("provided for %q+D", in_decl);
}
}
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);
+ {
+ /* There must be a default arg in this case. */
+ arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,
+ complain, in_decl);
+ /* The position of the first default template argument,
+ is also the number of non-defaulted arguments in NEW_INNER_ARGS.
+ Record that. */
+ if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args))
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args, arg_idx);
+ }
else
break;
if (lost)
return error_mark_node;
+#ifdef ENABLE_CHECKING
+ if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args))
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args,
+ TREE_VEC_LENGTH (new_inner_args));
+#endif
+
return new_inner_args;
}
if (level)
push_tinst_level (d);
- pt = GGC_NEW (struct pending_template);
+ pt = ggc_alloc_pending_template ();
pt->next = NULL;
pt->tinst = current_tinst_level;
if (last_pending_template)
tree found = NULL_TREE;
int arg_depth;
int parm_depth;
- int is_partial_instantiation;
+ int is_dependent_type;
+ int use_partial_inst_tmpl = false;
gen_tmpl = most_general_template (templ);
parmlist = DECL_TEMPLATE_PARMS (gen_tmpl);
i > 0 && t != NULL_TREE;
--i, t = TREE_CHAIN (t))
{
- tree a = coerce_template_parms (TREE_VALUE (t),
- arglist, gen_tmpl,
- complain,
- /*require_all_args=*/true,
- /*use_default_args=*/true);
+ tree a;
+ if (i == saved_depth)
+ a = coerce_template_parms (TREE_VALUE (t),
+ arglist, gen_tmpl,
+ complain,
+ /*require_all_args=*/true,
+ /*use_default_args=*/true);
+ else
+ /* Outer levels should have already been coerced. */
+ a = TMPL_ARGS_LEVEL (arglist, i);
/* Don't process further if one of the levels fails. */
if (a == error_mark_node)
if (entry)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->spec);
- /* This type is a "partial instantiation" if any of the template
- arguments still involve template parameters. Note that we set
- IS_PARTIAL_INSTANTIATION for partial specializations as
- well. */
- is_partial_instantiation = uses_template_parms (arglist);
+ is_dependent_type = uses_template_parms (arglist);
/* If the deduced arguments are invalid, then the binding
failed. */
- if (!is_partial_instantiation
+ if (!is_dependent_type
&& check_instantiated_args (gen_tmpl,
INNERMOST_TEMPLATE_ARGS (arglist),
complain))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- if (!is_partial_instantiation
+ if (!is_dependent_type
&& !PRIMARY_TEMPLATE_P (gen_tmpl)
&& !LAMBDA_TYPE_P (TREE_TYPE (gen_tmpl))
&& TREE_CODE (CP_DECL_CONTEXT (gen_tmpl)) == NAMESPACE_DECL)
/* Create the type. */
if (TREE_CODE (template_type) == ENUMERAL_TYPE)
{
- if (!is_partial_instantiation)
+ if (!is_dependent_type)
{
set_current_access_from_decl (TYPE_NAME (template_type));
t = start_enum (TYPE_IDENTIFIER (template_type),
DECL_VISIBILITY (type_decl) = CLASSTYPE_VISIBILITY (template_type);
}
- /* Set up the template information. We have to figure out which
- template is the immediate parent if this is a full
- instantiation. */
- if (parm_depth == 1 || is_partial_instantiation
- || !PRIMARY_TEMPLATE_P (gen_tmpl))
+ /* Let's consider the explicit specialization of a member
+ of a class template specialization that is implicitely instantiated,
+ e.g.:
+ template<class T>
+ struct S
+ {
+ template<class U> struct M {}; //#0
+ };
+
+ template<>
+ template<>
+ struct S<int>::M<char> //#1
+ {
+ int i;
+ };
+ [temp.expl.spec]/4 says this is valid.
+
+ In this case, when we write:
+ S<int>::M<char> m;
+
+ M is instantiated from the CLASSTYPE_TI_TEMPLATE of #1, not from
+ the one of #0.
+
+ When we encounter #1, we want to store the partial instantiation
+ of M (template<class T> S<int>::M<T>) in it's CLASSTYPE_TI_TEMPLATE.
+
+ For all cases other than this "explicit specialization of member of a
+ class template", we just want to store the most general template into
+ the CLASSTYPE_TI_TEMPLATE of M.
+
+ This case of "explicit specialization of member of a class template"
+ only happens when:
+ 1/ the enclosing class is an instantiation of, and therefore not
+ the same as, the context of the most general template, and
+ 2/ we aren't looking at the partial instantiation itself, i.e.
+ the innermost arguments are not the same as the innermost parms of
+ the most general template.
+
+ So it's only when 1/ and 2/ happens that we want to use the partial
+ instantiation of the member template in lieu of its most general
+ template. */
+
+ if (PRIMARY_TEMPLATE_P (gen_tmpl)
+ && TMPL_ARGS_HAVE_MULTIPLE_LEVELS (arglist)
+ /* the enclosing class must be an instantiation... */
+ && CLASS_TYPE_P (context)
+ && !same_type_p (context, DECL_CONTEXT (gen_tmpl)))
+ {
+ tree partial_inst_args;
+ TREE_VEC_LENGTH (arglist)--;
+ ++processing_template_decl;
+ partial_inst_args =
+ tsubst (INNERMOST_TEMPLATE_ARGS
+ (CLASSTYPE_TI_ARGS (TREE_TYPE (gen_tmpl))),
+ arglist, complain, NULL_TREE);
+ --processing_template_decl;
+ TREE_VEC_LENGTH (arglist)++;
+ use_partial_inst_tmpl =
+ /*...and we must not be looking at the partial instantiation
+ itself. */
+ !comp_template_args (INNERMOST_TEMPLATE_ARGS (arglist),
+ partial_inst_args);
+ }
+
+ if (!use_partial_inst_tmpl)
/* This case is easy; there are no member templates involved. */
found = gen_tmpl;
else
elt.spec = t;
slot = (spec_entry **) htab_find_slot_with_hash (type_specializations,
&elt, hash, INSERT);
- *slot = GGC_NEW (spec_entry);
+ *slot = ggc_alloc_spec_entry ();
**slot = elt;
/* Note this use of the partial instantiation so we can check it
= tree_cons (arglist, t,
DECL_TEMPLATE_INSTANTIATIONS (templ));
- if (TREE_CODE (t) == ENUMERAL_TYPE
- && !is_partial_instantiation)
+ if (TREE_CODE (t) == ENUMERAL_TYPE && !is_dependent_type)
/* Now that the type has been registered on the instantiations
list, we set up the enumerators. Because the enumeration
constants may involve the enumeration type itself, we make
the instantiation and exit above. */
tsubst_enum (template_type, t, arglist);
- if (is_partial_instantiation)
+ if (is_dependent_type)
/* If the type makes use of template parameters, the
code that generates debugging information will crash. */
DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;
/* We're starting to instantiate D; record the template instantiation context
for diagnostics and to restore it later. */
-static int
+int
push_tinst_level (tree d)
{
struct tinst_level *new_level;
last_template_error_tick = tinst_level_tick;
error ("template instantiation depth exceeds maximum of %d (use "
- "-ftemplate-depth-NN to increase the maximum) instantiating %qD",
+ "-ftemplate-depth= to increase the maximum) instantiating %qD",
max_tinst_depth, d);
print_instantiation_context ();
return 0;
}
- new_level = GGC_NEW (struct tinst_level);
+ new_level = ggc_alloc_tinst_level ();
new_level->decl = d;
new_level->locus = input_location;
new_level->in_system_header_p = in_system_header;
/* We're done instantiating this template; return to the instantiation
context. */
-static void
+void
pop_tinst_level (void)
{
/* Restore the filename and line number stashed away when we started
later if we need it. */
if (TREE_CODE (new_friend) != TEMPLATE_DECL)
{
- SET_DECL_RTL (new_friend, NULL_RTX);
+ SET_DECL_RTL (new_friend, NULL);
SET_DECL_ASSEMBLER_NAME (new_friend, NULL_TREE);
}
DECL_TEMPLATE_INFO (old_decl) = new_friend_template_info;
if (TREE_CODE (old_decl) != TEMPLATE_DECL)
- /* We should have called reregister_specialization in
- duplicate_decls. */
- gcc_assert (retrieve_specialization (new_template,
- new_args, 0)
- == old_decl);
+ {
+ /* We should have called reregister_specialization in
+ duplicate_decls. */
+ gcc_assert (retrieve_specialization (new_template,
+ new_args, 0)
+ == old_decl);
+
+ /* Instantiate it if the global has already been used. */
+ if (DECL_ODR_USED (old_decl))
+ instantiate_decl (old_decl, /*defer_ok=*/true,
+ /*expl_inst_class_mem_p=*/false);
+ }
else
{
tree t;
return;
saved_location = input_location;
- for (i = 0;
- VEC_iterate (qualified_typedef_usage_t,
+ FOR_EACH_VEC_ELT (qualified_typedef_usage_t,
get_types_needing_access_check (tmpl),
- i, iter);
- ++i)
+ i, iter)
{
tree type_decl = iter->typedef_decl;
tree type_scope = iter->context;
if (type == error_mark_node)
return error_mark_node;
- if (TYPE_BEING_DEFINED (type)
- || COMPLETE_TYPE_P (type)
+ if (COMPLETE_OR_OPEN_TYPE_P (type)
|| uses_template_parms (type))
return type;
/* Determine what specialization of the original template to
instantiate. */
- t = most_specialized_class (type, templ);
+ t = most_specialized_class (type, templ, tf_warning_or_error);
if (t == error_mark_node)
{
TYPE_BEING_DEFINED (type) = 1;
/* Set the input location to the most specialized template definition.
This is needed if tsubsting causes an error. */
typedecl = TYPE_MAIN_DECL (pattern);
- input_location = DECL_SOURCE_LOCATION (typedecl);
+ input_location = DECL_SOURCE_LOCATION (TYPE_NAME (type)) =
+ DECL_SOURCE_LOCATION (typedecl);
TYPE_HAS_USER_CONSTRUCTOR (type) = TYPE_HAS_USER_CONSTRUCTOR (pattern);
TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);
TYPE_HAS_ARRAY_NEW_OPERATOR (type) = TYPE_HAS_ARRAY_NEW_OPERATOR (pattern);
TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);
- TYPE_HAS_ASSIGN_REF (type) = TYPE_HAS_ASSIGN_REF (pattern);
- TYPE_HAS_CONST_ASSIGN_REF (type) = TYPE_HAS_CONST_ASSIGN_REF (pattern);
- TYPE_HAS_INIT_REF (type) = TYPE_HAS_INIT_REF (pattern);
- TYPE_HAS_CONST_INIT_REF (type) = TYPE_HAS_CONST_INIT_REF (pattern);
+ TYPE_HAS_COPY_ASSIGN (type) = TYPE_HAS_COPY_ASSIGN (pattern);
+ TYPE_HAS_CONST_COPY_ASSIGN (type) = TYPE_HAS_CONST_COPY_ASSIGN (pattern);
+ TYPE_HAS_COPY_CTOR (type) = TYPE_HAS_COPY_CTOR (pattern);
+ TYPE_HAS_CONST_COPY_CTOR (type) = TYPE_HAS_CONST_COPY_CTOR (pattern);
TYPE_HAS_DEFAULT_CONSTRUCTOR (type) = TYPE_HAS_DEFAULT_CONSTRUCTOR (pattern);
TYPE_HAS_CONVERSION (type) = TYPE_HAS_CONVERSION (pattern);
TYPE_PACKED (type) = TYPE_PACKED (pattern);
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)));
+ || COMPLETE_OR_OPEN_TYPE_P (TYPE_CONTEXT (type)));
base_list = NULL_TREE;
if (BINFO_N_BASE_BINFOS (pbinfo))
any member functions. We don't do this earlier because the
default arguments may reference members of the class. */
if (!PRIMARY_TEMPLATE_P (templ))
- for (t = TYPE_METHODS (type); t; t = TREE_CHAIN (t))
+ for (t = TYPE_METHODS (type); t; t = DECL_CHAIN (t))
if (TREE_CODE (t) == FUNCTION_DECL
/* Implicitly generated member functions will not have template
information; they are not instantiations, but instead are
r = tsubst (t, args, complain, in_decl);
else
{
+ if (!(complain & tf_warning))
+ ++c_inhibit_evaluation_warnings;
r = tsubst_expr (t, args, complain, in_decl,
/*integral_constant_expression_p=*/true);
- r = fold_non_dependent_expr (r);
+ if (!(complain & tf_warning))
+ --c_inhibit_evaluation_warnings;
}
return r;
}
/* Fill in PARMVEC and PARMTYPEVEC with all of the parameters. */
parmvec = make_tree_vec (len);
parmtypevec = make_tree_vec (len);
- for (i = 0; i < len; i++, spec_parm = TREE_CHAIN (spec_parm))
+ for (i = 0; i < len; i++, spec_parm = DECL_CHAIN (spec_parm))
{
TREE_VEC_ELT (parmvec, i) = spec_parm;
TREE_VEC_ELT (parmtypevec, i) = TREE_TYPE (spec_parm);
int i, len = -1;
tree result;
int incomplete = 0;
- bool very_local_specializations = false;
+ htab_t saved_local_specializations = NULL;
gcc_assert (PACK_EXPANSION_P (t));
pattern = PACK_EXPANSION_PATTERN (t);
if (TREE_CODE (parm_pack) == PARM_DECL)
{
- arg_pack = retrieve_local_specialization (parm_pack);
- if (arg_pack == NULL_TREE)
+ if (!cp_unevaluated_operand)
+ arg_pack = retrieve_local_specialization (parm_pack);
+ else
{
- /* This can happen for a parameter name used later in a function
- declaration (such as in a late-specified return type). Just
- make a dummy decl, since it's only used for its type. */
- gcc_assert (cp_unevaluated_operand != 0);
+ /* We can't rely on local_specializations for a parameter
+ name used later in a function declaration (such as in a
+ late-specified return type). Even if it exists, it might
+ have the wrong value for a recursive call. Just make a
+ dummy decl, since it's only used for its type. */
arg_pack = tsubst_decl (parm_pack, args, complain);
arg_pack = make_fnparm_pack (arg_pack);
}
if (len < 0)
return error_mark_node;
- if (!local_specializations)
+ if (cp_unevaluated_operand)
{
- /* We're in a late-specified return type, so we don't have a local
- specializations table. Create one for doing this expansion. */
- very_local_specializations = true;
+ /* We're in a late-specified return type, so create our own local
+ specializations table; the current table is either NULL or (in the
+ case of recursive unification) might have bindings that we don't
+ want to use or alter. */
+ saved_local_specializations = local_specializations;
local_specializations = htab_create (37,
hash_local_specialization,
eq_local_specializations,
}
}
- if (very_local_specializations)
+ if (saved_local_specializations)
{
htab_delete (local_specializations);
- local_specializations = NULL;
+ local_specializations = saved_local_specializations;
}
return result;
if (DECL_ARTIFICIAL (parm))
{
for (patparm = DECL_ARGUMENTS (pattern);
- patparm; patparm = TREE_CHAIN (patparm))
+ patparm; patparm = DECL_CHAIN (patparm))
if (DECL_ARTIFICIAL (patparm)
&& DECL_NAME (parm) == DECL_NAME (patparm))
break;
tree orig_t = t;
int len = TREE_VEC_LENGTH (t);
int need_new = 0, i, expanded_len_adjust = 0, out;
- tree *elts = (tree *) alloca (len * sizeof (tree));
+ tree *elts = XALLOCAVEC (tree, len);
for (i = 0; i < len; i++)
{
/* Make space for the expanded arguments coming from template
argument packs. */
t = make_tree_vec (len + expanded_len_adjust);
+ /* ORIG_T can contain TREE_VECs. That happens if ORIG_T contains the
+ arguments for a member template.
+ In that case each TREE_VEC in ORIG_T represents a level of template
+ arguments, and ORIG_T won't carry any non defaulted argument count.
+ It will rather be the nested TREE_VECs that will carry one.
+ In other words, ORIG_T carries a non defaulted argument count only
+ if it doesn't contain any nested TREE_VEC. */
+ if (NON_DEFAULT_TEMPLATE_ARGS_COUNT (orig_t))
+ {
+ int count = GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (orig_t);
+ count += expanded_len_adjust;
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (t, count);
+ }
for (i = 0, out = 0; i < len; i++)
{
if ((PACK_EXPANSION_P (TREE_VEC_ELT (orig_t, i))
{
r = lookup_template_class (t, argvec, in_decl, context,
entering_scope, complain);
- r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
+ r = cp_build_qualified_type_real (r, cp_type_quals (t), complain);
}
cp_unevaluated_operand = saved_unevaluated_operand;
RETURN (error_mark_node);
r = copy_decl (t);
- TREE_CHAIN (r) = NULL_TREE;
+ DECL_CHAIN (r) = NULL_TREE;
TREE_TYPE (r) = new_type;
DECL_TEMPLATE_RESULT (r)
= build_decl (DECL_SOURCE_LOCATION (decl),
than the old one. */
r = copy_decl (t);
gcc_assert (DECL_LANG_SPECIFIC (r) != 0);
- TREE_CHAIN (r) = NULL_TREE;
+ DECL_CHAIN (r) = NULL_TREE;
DECL_TEMPLATE_INFO (r) = build_template_info (t, args);
specialize R. */
gen_tmpl = most_general_template (DECL_TI_TEMPLATE (t));
argvec = tsubst_template_args (DECL_TI_ARGS
- (DECL_TEMPLATE_RESULT (gen_tmpl)),
+ (DECL_TEMPLATE_RESULT
+ (DECL_TI_TEMPLATE (t))),
args, complain, in_decl);
/* Check to see if we already have this specialization. */
TREE_TYPE (r) = type;
/* Clear out the mangled name and RTL for the instantiation. */
SET_DECL_ASSEMBLER_NAME (r, NULL_TREE);
- SET_DECL_RTL (r, NULL_RTX);
+ SET_DECL_RTL (r, NULL);
/* Leave DECL_INITIAL set on deleted instantiations. */
if (!DECL_DELETED_FN (r))
DECL_INITIAL (r) = NULL_TREE;
assigned to the instantiation. */
DECL_INTERFACE_KNOWN (r) = !TREE_PUBLIC (r);
DECL_DEFER_OUTPUT (r) = 0;
- TREE_CHAIN (r) = NULL_TREE;
+ DECL_CHAIN (r) = NULL_TREE;
DECL_PENDING_INLINE_INFO (r) = 0;
DECL_PENDING_INLINE_P (r) = 0;
DECL_SAVED_TREE (r) = NULL_TREE;
/* Build a proper chain of parameters when substituting
into a function parameter pack. */
if (prev_r)
- TREE_CHAIN (prev_r) = r;
+ DECL_CHAIN (prev_r) = r;
}
- if (TREE_CHAIN (t))
- TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args,
- complain, TREE_CHAIN (t));
+ if (DECL_CHAIN (t))
+ DECL_CHAIN (r) = tsubst (DECL_CHAIN (t), args,
+ complain, DECL_CHAIN (t));
/* FIRST_R contains the start of the chain we've built. */
r = first_r;
/*integral_constant_expression_p=*/true);
/* We don't have to set DECL_CONTEXT here; it is set by
finish_member_declaration. */
- TREE_CHAIN (r) = NULL_TREE;
+ DECL_CHAIN (r) = NULL_TREE;
if (VOID_TYPE_P (type))
error ("instantiation of %q+D as type %qT", r, type);
else
{
r = copy_node (t);
- TREE_CHAIN (r) = NULL_TREE;
+ DECL_CHAIN (r) = NULL_TREE;
}
break;
type = DECL_ORIGINAL_TYPE (t);
else
type = TREE_TYPE (t);
+ if (TREE_CODE (t) == VAR_DECL && VAR_HAD_UNKNOWN_BOUND (t))
+ type = strip_array_domain (type);
type = tsubst (type, args, complain, in_decl);
}
if (TREE_CODE (r) == VAR_DECL)
/* Clear out the mangled name and RTL for the instantiation. */
SET_DECL_ASSEMBLER_NAME (r, NULL_TREE);
if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_WRTL))
- SET_DECL_RTL (r, NULL_RTX);
+ SET_DECL_RTL (r, NULL);
/* The initializer must not be expanded until it is required;
see [temp.inst]. */
DECL_INITIAL (r) = NULL_TREE;
if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_WRTL))
- SET_DECL_RTL (r, NULL_RTX);
+ SET_DECL_RTL (r, NULL);
DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0;
if (TREE_CODE (r) == VAR_DECL)
{
else
register_local_specialization (r, t);
- TREE_CHAIN (r) = NULL_TREE;
+ DECL_CHAIN (r) = NULL_TREE;
apply_late_template_attributes (&r, DECL_ATTRIBUTES (r),
- (int) ATTR_FLAG_TYPE_IN_PLACE,
+ /*flags=*/0,
args, complain, in_decl);
/* Preserve a typedef that names a type. */
/* Construct a new type node and return it. */
if (TREE_CODE (t) == FUNCTION_TYPE)
- fntype = build_function_type (return_type, arg_types);
+ {
+ fntype = build_function_type (return_type, arg_types);
+ fntype = apply_memfn_quals (fntype, type_memfn_quals (t));
+ }
else
{
tree r = TREE_TYPE (TREE_VALUE (arg_types));
fntype = build_method_type_directly (r, return_type,
TREE_CHAIN (arg_types));
}
- fntype = cp_build_qualified_type_real (fntype, TYPE_QUALS (t), complain);
fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
return fntype;
specs = TYPE_RAISES_EXCEPTIONS (fntype);
new_specs = NULL_TREE;
- if (specs)
+ if (specs && TREE_PURPOSE (specs))
+ {
+ /* A noexcept-specifier. */
+ new_specs = tsubst_copy_and_build
+ (TREE_PURPOSE (specs), args, complain, in_decl, /*function_p=*/false,
+ /*integral_constant_expression_p=*/true);
+ new_specs = build_noexcept_spec (new_specs, complain);
+ }
+ else if (specs)
{
if (! TREE_VALUE (specs))
new_specs = specs;
tree
tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
+ enum tree_code code;
tree type, r;
if (t == NULL_TREE || t == error_mark_node
if (args == NULL_TREE)
return t;
- if (TREE_CODE (t) == IDENTIFIER_NODE)
+ code = TREE_CODE (t);
+
+ if (code == IDENTIFIER_NODE)
type = IDENTIFIER_TYPE_VALUE (t);
else
type = TREE_TYPE (t);
}
if (type
- && TREE_CODE (t) != TYPENAME_TYPE
- && TREE_CODE (t) != IDENTIFIER_NODE
- && TREE_CODE (t) != FUNCTION_TYPE
- && TREE_CODE (t) != METHOD_TYPE)
+ && code != TYPENAME_TYPE
+ && code != TEMPLATE_TYPE_PARM
+ && code != IDENTIFIER_NODE
+ && code != FUNCTION_TYPE
+ && code != METHOD_TYPE)
type = tsubst (type, args, complain, in_decl);
if (type == error_mark_node)
return error_mark_node;
- switch (TREE_CODE (t))
+ switch (code)
{
case RECORD_TYPE:
case UNION_TYPE:
&& !TREE_TYPE (max))
TREE_TYPE (max) = TREE_TYPE (TREE_OPERAND (max, 0));
+ max = mark_rvalue_use (max);
max = fold_decl_constant_value (max);
/* If we're in a partial instantiation, preserve the magic NOP_EXPR
}; */
return t;
- if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+ if (code == 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);
+ quals = cp_type_quals (arg) | cp_type_quals (t);
return cp_build_qualified_type_real
(arg, quals, complain | tf_ignore_bad_quals);
}
- else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
+ else if (code == BOUND_TEMPLATE_TEMPLATE_PARM)
{
/* We are processing a type constructed from a
template template parameter. */
/*entering_scope=*/0,
complain);
return cp_build_qualified_type_real
- (r, TYPE_QUALS (t), complain);
+ (r, cp_type_quals (t), complain);
}
else
/* TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX. */
- return arg;
+ return unshare_expr (arg);
}
if (level == 1)
/* If we get here, we must have been looking at a parm for a
more deeply nested template. Make a new version of this
template parameter, but with a lower level. */
- switch (TREE_CODE (t))
+ switch (code)
{
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
r = cp_build_qualified_type_real
(r, cp_type_quals (t),
- complain | (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+ complain | (code == TEMPLATE_TYPE_PARM
? tf_ignore_bad_quals : 0));
}
else
else
TYPE_CANONICAL (r) = canonical_type_parameter (r);
- if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
+ if (code == BOUND_TEMPLATE_TEMPLATE_PARM)
{
tree argvec = tsubst (TYPE_TI_ARGS (t), args,
complain, in_decl);
case POINTER_TYPE:
case REFERENCE_TYPE:
{
- enum tree_code code;
-
if (type == TREE_TYPE (t) && TREE_CODE (type) != METHOD_TYPE)
return t;
- code = TREE_CODE (t);
-
-
/* [temp.deduct]
Type deduction may fail for any of the following
TYPE_REF_IS_RVALUE (t) && TYPE_REF_IS_RVALUE (type));
else
r = cp_build_reference_type (type, TYPE_REF_IS_RVALUE (t));
- r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
+ r = cp_build_qualified_type_real (r, cp_type_quals (t), complain);
if (r != error_mark_node)
/* Will this ever be needed for TYPE_..._TO values? */
/* The type of the implicit object parameter gets its
cv-qualifiers from the FUNCTION_TYPE. */
tree memptr;
- tree method_type = build_memfn_type (type, r, cp_type_quals (type));
+ tree method_type = build_memfn_type (type, r, type_memfn_quals (type));
memptr = build_ptrmemfunc_type (build_pointer_type (method_type));
return cp_build_qualified_type_real (memptr, cp_type_quals (t),
complain);
}
else
return cp_build_qualified_type_real (build_ptrmem_type (r, type),
- TYPE_QUALS (t),
+ cp_type_quals (t),
complain);
}
case FUNCTION_TYPE:
return error_mark_node;
return fold_build2_loc (input_location,
- TREE_CODE (t), TREE_TYPE (t), e1, e2);
+ code, TREE_TYPE (t), e1, e2);
}
case NEGATE_EXPR:
if (e == error_mark_node)
return error_mark_node;
- return fold_build1_loc (input_location, TREE_CODE (t), TREE_TYPE (t), e);
+ return fold_build1_loc (input_location, code, TREE_TYPE (t), e);
}
case TYPENAME_TYPE:
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
{
- tree r = TYPE_P (t)
- ? cxx_make_type (TREE_CODE (t))
- : make_node (TREE_CODE (t));
+ tree r = TYPE_P (t) ? cxx_make_type (code) : make_node (code);
tree packed_out =
tsubst_template_args (ARGUMENT_PACK_ARGS (t),
args,
/* For template nontype argument packs, also substitute into
the type. */
- if (TREE_CODE (t) == NONTYPE_ARGUMENT_PACK)
+ if (code == NONTYPE_ARGUMENT_PACK)
TREE_TYPE (r) = tsubst (TREE_TYPE (t), args, complain, in_decl);
return r;
break;
default:
- sorry ("use of %qs in template",
- tree_code_name [(int) TREE_CODE (t)]);
+ sorry ("use of %qs in template", tree_code_name [(int) code]);
return error_mark_node;
}
}
if (IDENTIFIER_TYPENAME_P (name))
name = mangle_conv_op_name_for_type (optype);
baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
+ if (!baselink)
+ return error_mark_node;
/* If lookup found a single function, mark it as used at this
point. (If it lookup found multiple functions the one selected
else
expr = name;
- if (dependent_type_p (scope))
- {
- tree type = NULL_TREE;
- if (DECL_P (expr) && !dependent_scope_p (scope))
- type = TREE_TYPE (expr);
- return build_qualified_name (type, scope, expr,
- QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
- }
+ if (dependent_scope_p (scope))
+ return build_qualified_name (NULL_TREE, scope, expr,
+ QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
if (!BASELINK_P (name) && !DECL_P (expr))
{
gcc_unreachable ();
case OFFSET_REF:
- mark_used (TREE_OPERAND (t, 1));
- return t;
+ r = build2
+ (code, tsubst (TREE_TYPE (t), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
+ PTRMEM_OK_P (r) = PTRMEM_OK_P (t);
+ mark_used (TREE_OPERAND (r, 1));
+ return r;
case EXPR_PACK_EXPANSION:
error ("invalid use of pack expansion expression");
tree t = RECUR (init);
if (init && !t)
- /* If we had an initializer but it
- instantiated to nothing,
- value-initialize the object. This will
- only occur when the initializer was a
- pack expansion where the parameter packs
- used in that expansion were of length
- zero. */
- init = build_value_init (TREE_TYPE (decl));
+ {
+ /* If we had an initializer but it
+ instantiated to nothing,
+ value-initialize the object. This will
+ only occur when the initializer was a
+ pack expansion where the parameter packs
+ used in that expansion were of length
+ zero. */
+ init = build_value_init (TREE_TYPE (decl),
+ complain);
+ if (TREE_CODE (init) == AGGR_INIT_EXPR)
+ init = get_target_expr (init);
+ }
else
init = t;
}
return cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
complain & tf_error);
+ case NOEXCEPT_EXPR:
+ op1 = TREE_OPERAND (t, 0);
+ ++cp_unevaluated_operand;
+ ++c_inhibit_evaluation_warnings;
+ op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
+ /*function_p=*/false,
+ /*integral_constant_expression_p=*/false);
+ --cp_unevaluated_operand;
+ --c_inhibit_evaluation_warnings;
+ return finish_noexcept_expr (op1, complain);
+
case MODOP_EXPR:
{
tree r = build_x_modify_expr
ret = build_offset_ref_call_from_tree (function, &call_args);
else if (TREE_CODE (function) == COMPONENT_REF)
{
- if (!BASELINK_P (TREE_OPERAND (function, 1)))
+ tree instance = TREE_OPERAND (function, 0);
+ tree fn = TREE_OPERAND (function, 1);
+
+ if (processing_template_decl
+ && (type_dependent_expression_p (instance)
+ || (!BASELINK_P (fn)
+ && TREE_CODE (fn) != FIELD_DECL)
+ || type_dependent_expression_p (fn)
+ || any_type_dependent_arguments_p (call_args)))
+ ret = build_nt_call_vec (function, call_args);
+ else if (!BASELINK_P (fn))
ret = finish_call_expr (function, &call_args,
/*disallow_virtual=*/false,
/*koenig_p=*/false,
complain);
else
ret = (build_new_method_call
- (TREE_OPERAND (function, 0),
- TREE_OPERAND (function, 1),
+ (instance, fn,
&call_args, NULL_TREE,
qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL,
/*fn_p=*/NULL,
n = VEC_copy (constructor_elt, gc, CONSTRUCTOR_ELTS (t));
newlen = VEC_length (constructor_elt, n);
- for (idx = 0; VEC_iterate (constructor_elt, n, idx, ce); idx++)
+ FOR_EACH_VEC_ELT (constructor_elt, n, idx, ce)
{
if (ce->index && process_index_p)
ce->index = RECUR (ce->index);
VEC(constructor_elt,gc) *old_n = n;
n = VEC_alloc (constructor_elt, gc, newlen);
- for (idx = 0; VEC_iterate (constructor_elt, old_n, idx, ce);
- idx++)
+ FOR_EACH_VEC_ELT (constructor_elt, old_n, idx, ce)
{
if (TREE_CODE (ce->value) == TREE_VEC)
{
TREE_TYPE (r) = type;
CLASSTYPE_LAMBDA_EXPR (type) = r;
+ LAMBDA_EXPR_LOCATION (r)
+ = LAMBDA_EXPR_LOCATION (t);
LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (r)
= LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (t);
LAMBDA_EXPR_MUTABLE_P (r) = LAMBDA_EXPR_MUTABLE_P (t);
instantiate all the alternate entry points as well. We do this
by cloning the instantiation of the main entry point, not by
instantiating the template clones. */
- if (TREE_CHAIN (gen_tmpl) && DECL_CLONED_FUNCTION_P (TREE_CHAIN (gen_tmpl)))
+ if (DECL_CHAIN (gen_tmpl) && DECL_CLONED_FUNCTION_P (DECL_CHAIN (gen_tmpl)))
clone_function_decl (fndecl, /*update_method_vec_p=*/0);
return fndecl;
gcc_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST);
gcc_assert (ntparms > 0);
+ /* Reset the number of non-defaulted template arguments contained
+ in in TARGS. */
+ NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs) = NULL_TREE;
+
switch (strict)
{
case DEDUCE_CALL:
else
{
TREE_VEC_ELT (targs, i) = arg;
+ /* The position of the first default template argument,
+ is also the number of non-defaulted arguments in TARGS.
+ Record that. */
+ if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs))
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, i);
continue;
}
}
return 2;
}
+#ifdef ENABLE_CHECKING
+ if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs))
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, TREE_VEC_LENGTH (targs));
+#endif
return 0;
}
{
/* 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
+ does not allow us to unify "const T" with "int&" because both
+ types are not of the form "cv-list T" [14.8.2.5 temp.deduct.type].
+ It is ok 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
if (!skip_arg_p)
{
+ /* For deduction from an init-list we need the actual list. */
+ if (arg_expr && BRACE_ENCLOSED_INITIALIZER_P (arg_expr))
+ arg = arg_expr;
if (unify (tparms, targs, parm, arg, arg_strict))
return 1;
}
tree old_pack = TREE_VALUE (pack);
tree new_args = TREE_TYPE (pack);
int i, len = TREE_VEC_LENGTH (new_args);
+ int idx, level;
bool nondeduced_p = false;
+ /* By default keep the original deduced argument pack.
+ If necessary, more specific code is going to update the
+ resulting deduced argument later down in this function. */
+ template_parm_level_and_index (TREE_PURPOSE (pack), &level, &idx);
+ TMPL_ARG (targs, level, idx) = old_pack;
+
/* If NEW_ARGS contains any NULL_TREE entries, we didn't
actually deduce anything. */
for (i = 0; i < len && !nondeduced_p; ++i)
if (!old_pack)
{
tree result;
- int idx, level;
-
- template_parm_level_and_index (TREE_PURPOSE (pack), &level, &idx);
-
/* Build the deduced *_ARGUMENT_PACK. */
if (TREE_CODE (TREE_PURPOSE (pack)) == TEMPLATE_PARM_INDEX)
{
{
/* We only had the explicitly-provided arguments before, but
now we have a complete set of arguments. */
- int idx, level;
tree explicit_args = ARGUMENT_PACK_EXPLICIT_ARGS (old_pack);
- template_parm_level_and_index (TREE_PURPOSE (pack), &level, &idx);
-
- /* Keep the original deduced argument pack. */
- TMPL_ARG (targs, level, idx) = old_pack;
SET_ARGUMENT_PACK_ARGS (old_pack, new_args);
ARGUMENT_PACK_INCOMPLETE_P (old_pack) = 1;
new_args))
/* Inconsistent unification of this parameter pack. */
return 1;
- else
- {
- int idx, level;
-
- template_parm_level_and_index (TREE_PURPOSE (pack), &level, &idx);
-
- /* Keep the original deduced argument pack. */
- TMPL_ARG (targs, level, idx) = old_pack;
- }
}
return 0;
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
{
int elt_strict = strict;
+
+ if (elt == error_mark_node)
+ return 1;
+
if (!BRACE_ENCLOSED_INITIALIZER_P (elt))
{
tree type = TREE_TYPE (elt);
{
tree method_type;
tree fntype;
- cp_cv_quals cv_quals;
/* Check top-level cv qualifiers */
if (!check_cv_quals_for_unify (UNIFY_ALLOW_NONE, arg, parm))
/* Extract the cv-qualifiers of the member function from the
implicit object parameter and place them on the function
type to be restored later. */
- cv_quals =
- cp_type_quals(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (method_type))));
- fntype = build_qualified_type (fntype, cv_quals);
+ fntype = apply_memfn_quals (fntype, type_memfn_quals (method_type));
return unify (tparms, targs, TREE_TYPE (parm), fntype, strict);
}
/* Matched cases are handled by the ARG == PARM test above. */
return 1;
+ case VAR_DECL:
+ /* A non-type template parameter that is a variable should be a
+ an integral constant, in which case, it whould have been
+ folded into its (constant) value. So we should not be getting
+ a variable here. */
+ gcc_unreachable ();
+
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
{
than the type from the parameter template (as described above)
that type is considered to be more specialized than the other. If
neither type is more cv-qualified than the other then neither type
- is more specialized than the other."
+ is more specialized than the other." */
- We check same_type_p explicitly because deduction can also succeed
- in both directions when there is a nondeduced context. */
if (deduce1 && deduce2
- && quals1 != quals2 && quals1 >= 0 && quals2 >= 0
- && same_type_p (arg1, arg2))
+ && quals1 != quals2 && quals1 >= 0 && quals2 >= 0)
{
if ((quals1 & quals2) == quals2)
lose2 = true;
returned. */
static tree
-most_specialized_class (tree type, tree tmpl)
+most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
{
tree list = NULL_TREE;
tree t;
tree parms = TREE_VALUE (t);
partial_spec_args = CLASSTYPE_TI_ARGS (TREE_TYPE (t));
+
+ ++processing_template_decl;
+
if (outer_args)
{
int i;
- ++processing_template_decl;
-
/* Discard the outer levels of args, and then substitute in the
template args from the enclosing class. */
partial_spec_args = INNERMOST_TEMPLATE_ARGS (partial_spec_args);
TREE_VEC_ELT (parms, i) =
tsubst (TREE_VEC_ELT (parms, i), outer_args, tf_none, NULL_TREE);
- --processing_template_decl;
}
+
+ partial_spec_args =
+ coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
+ add_to_template_args (outer_args,
+ partial_spec_args),
+ tmpl, tf_none,
+ /*require_all_args=*/true,
+ /*use_default_args=*/true);
+
+ --processing_template_decl;
+
+ if (partial_spec_args == error_mark_node)
+ return error_mark_node;
+
spec_args = get_class_bindings (parms,
partial_spec_args,
args);
{
const char *str;
char *spaces = NULL;
+ if (!(complain & tf_error))
+ return error_mark_node;
error ("ambiguous class template instantiation for %q#T", type);
str = TREE_CHAIN (list) ? _("candidates are:") : _("candidate is:");
for (t = list; t; t = TREE_CHAIN (t))
interpretation is that it should be an explicit instantiation. */
if (! static_p)
- for (tmp = TYPE_METHODS (t); tmp; tmp = TREE_CHAIN (tmp))
+ for (tmp = TYPE_METHODS (t); tmp; tmp = DECL_CHAIN (tmp))
if (TREE_CODE (tmp) == FUNCTION_DECL
&& DECL_TEMPLATE_INSTANTIATION (tmp))
instantiate_class_member (tmp, extern_p);
- for (tmp = TYPE_FIELDS (t); tmp; tmp = TREE_CHAIN (tmp))
+ for (tmp = TYPE_FIELDS (t); tmp; tmp = DECL_CHAIN (tmp))
if (TREE_CODE (tmp) == VAR_DECL && DECL_TEMPLATE_INSTANTIATION (tmp))
instantiate_class_member (tmp, extern_p);
DECL_ATTRIBUTES (decl_parm) = attributes;
cplus_decl_attributes (&decl_parm, attributes, /*flags=*/0);
}
- decl_parm = TREE_CHAIN (decl_parm);
- pattern_parm = TREE_CHAIN (pattern_parm);
+ decl_parm = DECL_CHAIN (decl_parm);
+ pattern_parm = DECL_CHAIN (pattern_parm);
}
/* Merge any parameters that match with the function parameter
pack. */
DECL_ATTRIBUTES (decl_parm) = attributes;
cplus_decl_attributes (&decl_parm, attributes, /*flags=*/0);
}
- decl_parm = TREE_CHAIN (decl_parm);
+ decl_parm = DECL_CHAIN (decl_parm);
}
}
/* Merge additional specifiers from the CODE_PATTERN. */
DECL_DECLARED_INLINE_P (decl) = 1;
}
else if (TREE_CODE (decl) == VAR_DECL)
- DECL_INITIAL (decl) =
- tsubst_expr (DECL_INITIAL (code_pattern), args,
- tf_error, DECL_TI_TEMPLATE (decl),
- /*integral_constant_expression_p=*/false);
+ {
+ DECL_INITIAL (decl) =
+ tsubst_expr (DECL_INITIAL (code_pattern), args,
+ tf_error, DECL_TI_TEMPLATE (decl),
+ /*integral_constant_expression_p=*/false);
+ if (VAR_HAD_UNKNOWN_BOUND (decl))
+ TREE_TYPE (decl) = tsubst (TREE_TYPE (code_pattern), args,
+ tf_error, DECL_TI_TEMPLATE (decl));
+ }
else
gcc_unreachable ();
/* 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);
+ SET_DECL_RTL (d, NULL);
DECL_IN_AGGR_P (d) = 0;
/* The initializer is placed in DECL_INITIAL by
while (tmpl_parm && !FUNCTION_PARAMETER_PACK_P (tmpl_parm))
{
register_local_specialization (spec_parm, tmpl_parm);
- tmpl_parm = TREE_CHAIN (tmpl_parm);
- spec_parm = TREE_CHAIN (spec_parm);
+ tmpl_parm = DECL_CHAIN (tmpl_parm);
+ spec_parm = DECL_CHAIN (spec_parm);
}
if (tmpl_parm && FUNCTION_PARAMETER_PACK_P (tmpl_parm))
{
TMPL_PARM, then move on. */
tree argpack = make_fnparm_pack (spec_parm);
register_local_specialization (argpack, tmpl_parm);
- tmpl_parm = TREE_CHAIN (tmpl_parm);
+ tmpl_parm = DECL_CHAIN (tmpl_parm);
spec_parm = NULL_TREE;
}
gcc_assert (!spec_parm);
error ("template instantiation depth exceeds maximum of %d"
" instantiating %q+D, possibly from virtual table generation"
- " (use -ftemplate-depth-NN to increase the maximum)",
+ " (use -ftemplate-depth= to increase the maximum)",
max_tinst_depth, decl);
if (TREE_CODE (decl) == FUNCTION_DECL)
/* Pretend that we defined it. */
set_current_access_from_decl (decl);
/* Actually build the enumerator itself. */
- build_enumerator (DECL_NAME (decl), value, newtag);
+ build_enumerator
+ (DECL_NAME (decl), value, newtag, DECL_SOURCE_LOCATION (decl));
}
finish_enum (newtag);
&& !currently_open_class (scope));
}
-/* Returns TRUE if EXPRESSION is dependent, according to CRITERION. */
-
-static bool
-dependent_scope_ref_p (tree expression, bool criterion (tree))
-{
- tree scope;
- tree name;
-
- gcc_assert (TREE_CODE (expression) == SCOPE_REF);
-
- if (!TYPE_P (TREE_OPERAND (expression, 0)))
- return true;
-
- scope = TREE_OPERAND (expression, 0);
- name = TREE_OPERAND (expression, 1);
-
- /* [temp.dep.expr]
-
- An id-expression is type-dependent if it contains a
- nested-name-specifier that contains a class-name that names a
- dependent type. */
- /* The suggested resolution to Core Issue 224 implies that if the
- qualifying type is the current class, then we must peek
- inside it. */
- if (DECL_P (name)
- && currently_open_class (scope)
- && !criterion (name))
- return false;
- if (dependent_type_p (scope))
- return true;
-
- return false;
-}
-
/* Returns TRUE if the EXPRESSION is value-dependent, in the sense of
[temp.dep.constexpr]. EXPRESSION is already known to be a constant
expression. */
return dependent_type_p (expression);
return type_dependent_expression_p (expression);
+ case NOEXCEPT_EXPR:
+ expression = TREE_OPERAND (expression, 0);
+ /* FIXME why check value-dependency? */
+ return (type_dependent_expression_p (expression)
+ || value_dependent_expression_p (expression));
+
case SCOPE_REF:
- return dependent_scope_ref_p (expression, value_dependent_expression_p);
+ {
+ tree name = TREE_OPERAND (expression, 1);
+ return value_dependent_expression_p (name);
+ }
case COMPONENT_REF:
return (value_dependent_expression_p (TREE_OPERAND (expression, 0))
return ((value_dependent_expression_p (TREE_OPERAND (expression, 0)))
|| (value_dependent_expression_p (TREE_OPERAND (expression, 2))));
+ case ADDR_EXPR:
+ {
+ tree op = TREE_OPERAND (expression, 0);
+ return (value_dependent_expression_p (op)
+ || has_value_dependent_address (op));
+ }
+
default:
/* A constant expression is value-dependent if any subexpression is
value-dependent. */
if (TREE_CODE (expression) == PSEUDO_DTOR_EXPR
|| TREE_CODE (expression) == SIZEOF_EXPR
|| TREE_CODE (expression) == ALIGNOF_EXPR
+ || TREE_CODE (expression) == NOEXCEPT_EXPR
|| TREE_CODE (expression) == TRAIT_EXPR
|| TREE_CODE (expression) == TYPEID_EXPR
|| TREE_CODE (expression) == DELETE_EXPR
return dependent_type_p (type);
}
- if (TREE_CODE (expression) == SCOPE_REF
- && dependent_scope_ref_p (expression,
- type_dependent_expression_p))
- return true;
+ if (TREE_CODE (expression) == SCOPE_REF)
+ {
+ tree scope = TREE_OPERAND (expression, 0);
+ tree name = TREE_OPERAND (expression, 1);
+
+ /* 14.6.2.2 [temp.dep.expr]: An id-expression is type-dependent if it
+ contains an identifier associated by name lookup with one or more
+ declarations declared with a dependent type, or...a
+ nested-name-specifier or qualified-id that names a member of an
+ unknown specialization. */
+ return (type_dependent_expression_p (name)
+ || dependent_scope_p (scope));
+ }
if (TREE_CODE (expression) == FUNCTION_DECL
&& DECL_LANG_SPECIFIC (expression)
return false;
}
+ /* A static data member of the current instantiation with incomplete
+ array type is type-dependent, as the definition and specializations
+ can have different bounds. */
+ if (TREE_CODE (expression) == VAR_DECL
+ && DECL_CLASS_SCOPE_P (expression)
+ && dependent_type_p (DECL_CONTEXT (expression))
+ && VAR_HAD_UNKNOWN_BOUND (expression))
+ return true;
+
if (TREE_TYPE (expression) == unknown_type_node)
{
if (TREE_CODE (expression) == ADDR_EXPR)
unsigned int i;
tree arg;
- for (i = 0; VEC_iterate (tree, args, i, arg); ++i)
+ FOR_EACH_VEC_ELT (tree, args, i, arg)
{
if (type_dependent_expression_p (arg))
return true;
unsigned int ix;
tree arg;
- for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix)
+ FOR_EACH_VEC_ELT (tree, args, ix, arg)
{
tree newarg = build_non_dependent_expr (arg);
if (newarg != arg)
return tsubst (type, argvec, tf_warning_or_error, NULL_TREE);
}
+/* walk_tree helper for do_auto_deduction. */
+
+static tree
+contains_auto_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *type)
+{
+ /* Is this a variable with the type we're looking for? */
+ if (DECL_P (*tp)
+ && TREE_TYPE (*tp) == type)
+ return *tp;
+ else
+ return NULL_TREE;
+}
+
/* Replace occurrences of 'auto' in TYPE with the appropriate type deduced
from INIT. AUTO_NODE is the TEMPLATE_TYPE_PARM used for 'auto' in TYPE. */
{
tree parms, tparms, targs;
tree args[1];
+ tree decl;
int val;
+ /* The name of the object being declared shall not appear in the
+ initializer expression. */
+ decl = cp_walk_tree_without_duplicates (&init, contains_auto_r, type);
+ if (decl)
+ {
+ error ("variable %q#D with %<auto%> type used in its own "
+ "initializer", decl);
+ return error_mark_node;
+ }
+
/* [dcl.spec.auto]: Obtain P from T by replacing the occurrences of auto
with either a new invented type template parameter U or, if the
initializer is a braced-init-list (8.5.4), with
gcc_assert (type_decl && (TREE_CODE (type_decl) == TYPE_DECL));
/* Make sure we don't append the type to the template twice. */
- for (i = 0;
- VEC_iterate (qualified_typedef_usage_t,
+ FOR_EACH_VEC_ELT (qualified_typedef_usage_t,
get_types_needing_access_check (templ),
- i, iter);
- ++i)
+ i, iter)
if (iter->typedef_decl == type_decl && scope == iter->context)
return;
ggc_free);
}
+/* Print stats about the template hash tables for -fstats. */
+
+void
+print_template_statistics (void)
+{
+ fprintf (stderr, "decl_specializations: size %ld, %ld elements, "
+ "%f collisions\n", (long) htab_size (decl_specializations),
+ (long) htab_elements (decl_specializations),
+ htab_collisions (decl_specializations));
+ fprintf (stderr, "type_specializations: size %ld, %ld elements, "
+ "%f collisions\n", (long) htab_size (type_specializations),
+ (long) htab_elements (type_specializations),
+ htab_collisions (type_specializations));
+}
+
#include "gt-cp-pt.h"