static int for_each_template_parm (tree, tree_fn_t, void*,
struct pointer_set_t*, bool);
static tree expand_template_argument_pack (tree);
-static tree build_template_parm_index (int, int, int, tree, tree);
+static tree build_template_parm_index (int, int, int, int, tree, tree);
static bool inline_needs_template_parms (tree);
static void push_inline_template_parms_recursive (tree, int);
static tree retrieve_local_specialization (tree);
static void perform_typedefs_access_check (tree tmpl, tree targs);
static void append_type_to_template_for_access_check_1 (tree, tree, tree,
location_t);
-static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
static tree listify (tree);
static tree listify_autos (tree, tree);
+static tree template_parm_to_arg (tree t);
+static tree current_template_args (void);
+static tree fixup_template_type_parm_type (tree, int);
+static tree fixup_template_parm_index (tree, tree, int);
+static void fixup_template_parms (void);
+static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
int i;
int j;
- if (args == NULL_TREE)
+ if (args == NULL_TREE || extra_args == error_mark_node)
return extra_args;
extra_depth = TMPL_ARGS_DEPTH (extra_args);
}
else if (processing_specialization)
{
- error ("explicit specialization of non-template %qT", type);
- return error_mark_node;
+ /* Someday C++0x may allow for enum template specialization. */
+ if (cxx_dialect > cxx98 && TREE_CODE (type) == ENUMERAL_TYPE
+ && CLASS_TYPE_P (context) && CLASSTYPE_USE_TEMPLATE (context))
+ pedwarn (input_location, OPT_pedantic, "template specialization "
+ "of %qD not allowed by ISO C++", type);
+ else
+ {
+ error ("explicit specialization of non-template %qT", type);
+ return error_mark_node;
+ }
}
return type;
/* Recursively calculate a hash value for a template argument ARG, for use
in the hash tables of template specializations. */
-static hashval_t
+hashval_t
iterative_hash_template_arg (tree arg, hashval_t val)
{
unsigned HOST_WIDE_INT i;
}
/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
- ORIG_LEVEL, DECL, and TYPE. */
+ ORIG_LEVEL, DECL, and TYPE. NUM_SIBLINGS is the total number of
+ template parameters. */
static tree
build_template_parm_index (int index,
int level,
int orig_level,
+ int num_siblings,
tree decl,
tree type)
{
TEMPLATE_PARM_IDX (t) = index;
TEMPLATE_PARM_LEVEL (t) = level;
TEMPLATE_PARM_ORIG_LEVEL (t) = orig_level;
+ TEMPLATE_PARM_NUM_SIBLINGS (t) = num_siblings;
TEMPLATE_PARM_DECL (t) = decl;
TREE_TYPE (t) = type;
TREE_CONSTANT (t) = TREE_CONSTANT (decl);
/* Find the canonical type parameter for the given template type
parameter. Returns the canonical type parameter, which may be TYPE
if no such parameter existed. */
+
static tree
canonical_type_parameter (tree type)
{
t = build_template_parm_index (TEMPLATE_PARM_IDX (index),
TEMPLATE_PARM_LEVEL (index) - levels,
TEMPLATE_PARM_ORIG_LEVEL (index),
+ TEMPLATE_PARM_NUM_SIBLINGS (index),
decl, type);
TEMPLATE_PARM_DESCENDANTS (index) = t;
TEMPLATE_PARM_PARAMETER_PACK (t)
return TEMPLATE_PARM_DESCENDANTS (index);
}
-/* 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. This new parameter is a parameter
- pack iff IS_PARAMETER_PACK is true. The location of PARM is in
- PARM_LOC. */
+/* 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. This new parameter is a
+ parameter pack iff IS_PARAMETER_PACK is true. The location of PARM
+ is in PARM_LOC. NUM_TEMPLATE_PARMS is the size of the template
+ parameter list PARM belongs to. This is used used to create a
+ proper canonical type for the type of PARM that is to be created,
+ iff PARM is a type. If the size is not known, this parameter shall
+ be set to 0. */
tree
-process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type,
- bool is_parameter_pack)
+process_template_parm (tree list, location_t parm_loc, tree parm,
+ bool is_non_type, bool is_parameter_pack,
+ unsigned num_template_parms)
{
tree decl = 0;
tree defval;
DECL_INITIAL (parm) = DECL_INITIAL (decl)
= build_template_parm_index (idx, processing_template_decl,
processing_template_decl,
+ num_template_parms,
decl, TREE_TYPE (parm));
TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))
TEMPLATE_TYPE_PARM_INDEX (t)
= build_template_parm_index (idx, processing_template_decl,
processing_template_decl,
+ num_template_parms,
decl, TREE_TYPE (parm));
TEMPLATE_TYPE_PARAMETER_PACK (t) = is_parameter_pack;
TYPE_CANONICAL (t) = canonical_type_parameter (t);
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;
}
+ fixup_template_parms ();
+
--processing_template_parmlist;
return saved_parmlist;
}
+/* Create a new type almost identical to TYPE but which has the
+ following differences:
+
+ 1/ T has a new TEMPLATE_PARM_INDEX that carries the new number of
+ template sibling parameters of T.
+
+ 2/ T has a new canonical type that matches the new number
+ of sibling parms.
+
+ 3/ From now on, T is going to be what lookups referring to the
+ name of TYPE will return. No lookup should return TYPE anymore.
+
+ NUM_PARMS is the new number of sibling parms TYPE belongs to.
+
+ This is a subroutine of fixup_template_parms. */
+
+static tree
+fixup_template_type_parm_type (tree type, int num_parms)
+{
+ tree orig_idx = TEMPLATE_TYPE_PARM_INDEX (type), idx;
+ tree t;
+ /* This is the decl which name is inserted into the symbol table for
+ the template parm type. So whenever we lookup the type name, this
+ is the DECL we get. */
+ tree decl;
+
+ /* Do not fix up the type twice. */
+ if (orig_idx && TEMPLATE_PARM_NUM_SIBLINGS (orig_idx) != 0)
+ return type;
+
+ t = copy_type (type);
+ decl = TYPE_NAME (t);
+
+ TYPE_MAIN_VARIANT (t) = t;
+ TYPE_NEXT_VARIANT (t)= NULL_TREE;
+ TYPE_POINTER_TO (t) = 0;
+ TYPE_REFERENCE_TO (t) = 0;
+
+ idx = build_template_parm_index (TEMPLATE_PARM_IDX (orig_idx),
+ TEMPLATE_PARM_LEVEL (orig_idx),
+ TEMPLATE_PARM_ORIG_LEVEL (orig_idx),
+ num_parms,
+ decl, t);
+ TEMPLATE_PARM_DESCENDANTS (idx) = TEMPLATE_PARM_DESCENDANTS (orig_idx);
+ TEMPLATE_PARM_PARAMETER_PACK (idx) = TEMPLATE_PARM_PARAMETER_PACK (orig_idx);
+ TEMPLATE_TYPE_PARM_INDEX (t) = idx;
+
+ TYPE_STUB_DECL (t) = decl;
+ TEMPLATE_TYPE_DECL (t) = decl;
+ if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
+ TREE_TYPE (DECL_TEMPLATE_RESULT (decl)) = t;
+
+ /* Update the type associated to the type name stored in the symbol
+ table. Now, whenever the type name is looked up, the resulting
+ type is properly fixed up. */
+ TREE_TYPE (decl) = t;
+
+ TYPE_CANONICAL (t) = canonical_type_parameter (t);
+
+ return t;
+}
+
+/* Create and return a new TEMPLATE_PARM_INDEX that is almost
+ identical to I, but that is fixed up as to:
+
+ 1/ carry the number of sibling parms (NUM_PARMS) of the template
+ parm represented by I.
+
+ 2/ replace all references to template parm types declared before I
+ (in the same template parm list as I) by references to template
+ parm types contained in ARGS. ARGS should contain the list of
+ template parms that have been fixed up so far, in a form suitable
+ to be passed to tsubst.
+
+ This is a subroutine of fixup_template_parms. */
+
+static tree
+fixup_template_parm_index (tree i, tree args, int num_parms)
+{
+ tree index, decl, type;
+
+ if (i == NULL_TREE
+ || TREE_CODE (i) != TEMPLATE_PARM_INDEX
+ /* Do not fix up the index twice. */
+ || (TEMPLATE_PARM_NUM_SIBLINGS (i) != 0))
+ return i;
+
+ decl = TEMPLATE_PARM_DECL (i);
+ type = TREE_TYPE (decl);
+
+ index = build_template_parm_index (TEMPLATE_PARM_IDX (i),
+ TEMPLATE_PARM_LEVEL (i),
+ TEMPLATE_PARM_ORIG_LEVEL (i),
+ num_parms,
+ decl, type);
+
+ TEMPLATE_PARM_DESCENDANTS (index) = TEMPLATE_PARM_DESCENDANTS (i);
+ TEMPLATE_PARM_PARAMETER_PACK (index) = TEMPLATE_PARM_PARAMETER_PACK (i);
+
+ type = tsubst (type, args, tf_none, NULL_TREE);
+
+ TREE_TYPE (decl) = type;
+ TREE_TYPE (index) = type;
+
+ return index;
+}
+
+/*
+ This is a subroutine of fixup_template_parms.
+
+ It computes the canonical type of the type of the template
+ parameter PARM_DESC and update all references to that type so that
+ they use the newly computed canonical type. No access check is
+ performed during the fixup. PARM_DESC is a TREE_LIST which
+ TREE_VALUE is the template parameter and its TREE_PURPOSE is the
+ default argument of the template parm if any. IDX is the index of
+ the template parameter, starting at 0. NUM_PARMS is the number of
+ template parameters in the set PARM_DESC belongs to. ARGLIST is a
+ TREE_VEC containing the full set of template parameters in a form
+ suitable to be passed to substs functions as their ARGS
+ argument. This is what current_template_args returns for a given
+ template. The innermost vector of args in ARGLIST is the set of
+ template parms that have been fixed up so far. This function adds
+ the fixed up parameter into that vector. */
+
+static void
+fixup_template_parm (tree parm_desc,
+ int idx,
+ int num_parms,
+ tree arglist)
+{
+ tree parm = TREE_VALUE (parm_desc);
+ tree fixedup_args = INNERMOST_TEMPLATE_ARGS (arglist);
+
+ push_deferring_access_checks (dk_no_check);
+
+ if (TREE_CODE (parm) == TYPE_DECL)
+ {
+ /* PARM is a template type parameter. Fix up its type, add
+ the fixed-up template parm to the vector of fixed-up
+ template parms so far, and substitute the fixed-up
+ template parms into the default argument of this
+ parameter. */
+ tree t =
+ fixup_template_type_parm_type (TREE_TYPE (parm), num_parms);
+ TREE_TYPE (parm) = t;
+
+ TREE_VEC_ELT (fixedup_args, idx) = template_parm_to_arg (parm_desc);
+ }
+ else if (TREE_CODE (parm) == TEMPLATE_DECL)
+ {
+ /* PARM is a template template parameter. This is going to
+ be interesting. */
+ tree tparms, targs, innermost_args;
+ int j;
+
+ /* First, fix up the type of the parm. */
+
+ tree t =
+ fixup_template_type_parm_type (TREE_TYPE (parm), num_parms);
+ TREE_TYPE (parm) = t;
+
+ TREE_VEC_ELT (fixedup_args, idx) =
+ template_parm_to_arg (parm_desc);
+
+ /* Now we need to substitute the template parm types that
+ have been fixed up so far into the non-type template
+ parms of this template template parm. E.g, consider this:
+
+ template<class T, template<T u> class TT> class S;
+
+ In this case we want to substitute T into the
+ template parameters of TT.
+
+ So let's walk the template parms of PARM here, and
+ tsubst ARGLIST into into each of the template
+ parms. */
+
+ /* For this substitution we need to build the full set of
+ template parameters and use that as arguments for the
+ tsubsting function. */
+ tparms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (parm));
+
+ /* This will contain the innermost parms of PARM into which
+ we have substituted so far. */
+ innermost_args = make_tree_vec (TREE_VEC_LENGTH (tparms));
+ targs = add_to_template_args (arglist, innermost_args);
+ for (j = 0; j < TREE_VEC_LENGTH (tparms); ++j)
+ {
+ tree parameter;
+
+ parameter = TREE_VEC_ELT (tparms, j);
+
+ /* INNERMOST_ARGS needs to have at least the same number
+ of elements as the index PARAMETER, ortherwise
+ tsubsting into PARAMETER will result in partially
+ instantiating it, reducing its tempate parm
+ level. Let's tactically fill INNERMOST_ARGS for that
+ purpose. */
+ TREE_VEC_ELT (innermost_args, j) =
+ template_parm_to_arg (parameter);
+
+ fixup_template_parm (parameter, j,
+ TREE_VEC_LENGTH (tparms),
+ targs);
+ }
+ }
+ else if (TREE_CODE (parm) == PARM_DECL)
+ {
+ /* PARM is a non-type template parameter. We need to:
+
+ * Fix up its TEMPLATE_PARM_INDEX to make it carry the
+ proper number of sibling parameters.
+
+ * Make lookups of the template parameter return a reference
+ to the fixed-up index. No lookup should return references
+ to the former index anymore.
+
+ * Substitute the template parms that got fixed up so far
+
+ * into the type of PARM. */
+
+ tree index = DECL_INITIAL (parm);
+
+ /* PUSHED_DECL is the decl added to the symbol table with
+ the name of the parameter. E,g:
+
+ template<class T, T u> //#0
+ auto my_function(T t) -> decltype(u); //#1
+
+ Here, when looking up u at //#1, we get the decl of u
+ resulting from the declaration in #0. This is what
+ PUSHED_DECL is. We need to replace the reference to the
+ old TEMPLATE_PARM_INDEX carried by PUSHED_DECL by the
+ fixed-up TEMPLATE_PARM_INDEX. */
+ tree pushed_decl = TEMPLATE_PARM_DECL (index);
+
+ /* Let's fix up the TEMPLATE_PARM_INDEX then. Note that we must
+ fixup the type of PUSHED_DECL as well and luckily
+ fixup_template_parm_index does it for us too. */
+ tree fixed_up_index =
+ fixup_template_parm_index (index, arglist, num_parms);
+
+ DECL_INITIAL (pushed_decl) = DECL_INITIAL (parm) = fixed_up_index;
+
+ /* Add this fixed up PARM to the template parms we've fixed
+ up so far and use that to substitute the fixed-up
+ template parms into the type of PARM. */
+ TREE_VEC_ELT (fixedup_args, idx) =
+ template_parm_to_arg (parm_desc);
+ TREE_TYPE (parm) = tsubst (TREE_TYPE (parm), arglist,
+ tf_none, NULL_TREE);
+ }
+
+ TREE_PURPOSE (parm_desc) =
+ tsubst_template_arg (TREE_PURPOSE (parm_desc),
+ arglist, tf_none, parm);
+
+ pop_deferring_access_checks ();
+}
+
+/* Walk current the template parms and properly compute the canonical
+ types of the dependent types created during
+ cp_parser_template_parameter_list. */
+
+static void
+fixup_template_parms (void)
+{
+ tree arglist;
+ tree parameter_vec;
+ tree fixedup_args;
+ int i, num_parms;
+
+ parameter_vec = INNERMOST_TEMPLATE_PARMS (current_template_parms);
+ if (parameter_vec == NULL_TREE)
+ return;
+
+ num_parms = TREE_VEC_LENGTH (parameter_vec);
+
+ /* This vector contains the current innermost template parms that
+ have been fixed up so far. The form of FIXEDUP_ARGS is suitable
+ to be passed to tsubst* functions as their ARGS argument. */
+ fixedup_args = make_tree_vec (num_parms);
+
+ /* This vector contains the full set of template parms in a form
+ suitable to be passed to substs functions as their ARGS
+ argument. */
+ arglist = current_template_args ();
+ arglist = add_outermost_template_args (arglist, fixedup_args);
+
+ fixedup_args = INNERMOST_TEMPLATE_ARGS (arglist);
+
+ /* Let's do the proper fixup now. */
+ for (i = 0; i < num_parms; ++i)
+ fixup_template_parm (TREE_VEC_ELT (parameter_vec, i),
+ i, num_parms, arglist);
+}
+
/* end_template_decl is called after a template declaration is seen. */
void
current_template_parms = TREE_CHAIN (current_template_parms);
}
+/* Takes a TREE_LIST representing a template parameter and convert it
+ into an argument suitable to be passed to the type substitution
+ functions. Note that If the TREE_LIST contains an error_mark
+ node, the returned argument is error_mark_node. */
+
+static tree
+template_parm_to_arg (tree t)
+{
+
+ if (t == NULL_TREE
+ || TREE_CODE (t) != TREE_LIST)
+ return t;
+
+ if (error_operand_p (TREE_VALUE (t)))
+ return error_mark_node;
+
+ t = TREE_VALUE (t);
+
+ if (TREE_CODE (t) == TYPE_DECL
+ || TREE_CODE (t) == TEMPLATE_DECL)
+ {
+ t = TREE_TYPE (t);
+
+ if (TEMPLATE_TYPE_PARAMETER_PACK (t))
+ {
+ /* 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);
+ SET_ARGUMENT_PACK_ARGS (t, vec);
+ }
+ }
+ else
+ {
+ t = DECL_INITIAL (t);
+
+ if (TEMPLATE_PARM_PARAMETER_PACK (t))
+ {
+ /* Turn this argument into a NONTYPE_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);
+ SET_ARGUMENT_PACK_ARGS (t, vec);
+ TREE_TYPE (t) = type;
+ }
+ }
+ return t;
+}
+
/* Within the declaration of a template, return all levels of template
parameters that apply. The template parameters are represented as
a TREE_VEC, in the form documented in cp-tree.h for template
TREE_TYPE (a) = NULL_TREE;
for (i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i)
- {
- tree t = TREE_VEC_ELT (a, i);
-
- /* T will be a list if we are called from within a
- begin/end_template_parm_list pair, but a vector directly
- if within a begin/end_member_template_processing pair. */
- if (TREE_CODE (t) == TREE_LIST)
- {
- t = TREE_VALUE (t);
-
- if (!error_operand_p (t))
- {
- if (TREE_CODE (t) == TYPE_DECL
- || TREE_CODE (t) == TEMPLATE_DECL)
- {
- t = TREE_TYPE (t);
-
- if (TEMPLATE_TYPE_PARAMETER_PACK (t))
- {
- /* 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);
- SET_ARGUMENT_PACK_ARGS (t, vec);
- }
- }
- else
- {
- t = DECL_INITIAL (t);
-
- if (TEMPLATE_PARM_PARAMETER_PACK (t))
- {
- /* Turn this argument into a NONTYPE_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);
- SET_ARGUMENT_PACK_ARGS (t, vec);
- TREE_TYPE (t) = type;
- }
- }
- TREE_VEC_ELT (a, i) = t;
- }
- }
- }
+ TREE_VEC_ELT (a, i) = template_parm_to_arg (TREE_VEC_ELT (a, i));
#ifdef ENABLE_CHECKING
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, TREE_VEC_LENGTH (a));
args = a;
}
+ if (length > 1 && TREE_VEC_ELT (args, 0) == NULL_TREE)
+ /* This can happen for template parms of a template template
+ parameter, e.g:
+
+ template<template<class T, class U> class TT> struct S;
+
+ Consider the level of the parms of TT; T and U both have
+ level 2; TT has no template parm of level 1. So in this case
+ the first element of full_template_args is NULL_TREE. If we
+ leave it like this TMPL_ARG_DEPTH on args returns 1 instead
+ of 2. This will make tsubst wrongly consider that T and U
+ have level 1. Instead, let's create a dummy vector as the
+ first element of full_template_args so that TMPL_ARG_DEPTH
+ returns the correct depth for args. */
+ TREE_VEC_ELT (args, 0) = make_tree_vec (1);
return args;
}
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.
-
- This is basically a more powerful version of
- integral_constant_value, which can be used also in templates where
- initializers can maintain a syntactic rather than semantic form
- (even if they are non-dependent, for access-checking purposes). */
-
-static tree
-fold_decl_constant_value (tree expr)
-{
- tree const_expr = expr;
- do
- {
- expr = fold_non_dependent_expr (const_expr);
- const_expr = integral_constant_value (expr);
- }
- while (expr != const_expr);
-
- return expr;
-}
-
/* Subroutine of convert_nontype_argument. Converts EXPR to TYPE, which
must be a function or a pointer-to-function type, as specified
in [temp.arg.nontype]: disambiguate EXPR if it is an overload set,
(_conv.integral_) are applied. */
if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
{
- if (!INTEGRAL_OR_ENUMERATION_TYPE_P (expr_type))
+ tree t = build_integral_nontype_arg_conv (type, expr, complain);
+ t = maybe_constant_value (t);
+ if (t != error_mark_node)
+ expr = t;
+
+ if (!same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (expr)))
return error_mark_node;
- expr = fold_decl_constant_value (expr);
/* Notice that there are constant expressions like '4 % 0' which
do not fold into integer constants. */
if (TREE_CODE (expr) != INTEGER_CST)
{
if (complain & tf_error)
- error ("%qE is not a valid template argument for type %qT "
- "because it is a non-constant expression", expr, type);
+ {
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is a non-constant expression", expr, type);
+ cxx_constant_value (expr);
+ }
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 = perform_implicit_conversion (type, expr, complain);
- if (expr == error_mark_node)
- return error_mark_node;
-
- /* Conversion was allowed: fold it to a bare integer constant. */
- expr = fold (expr);
}
/* [temp.arg.nontype]/5, bullet 2
parameters. */
int variadic_p = 0;
+ if (args == error_mark_node)
+ return error_mark_node;
+
nparms = TREE_VEC_LENGTH (parms);
/* Determine if there are any parameter packs. */
if (!is_dependent_type)
{
set_current_access_from_decl (TYPE_NAME (template_type));
- t = start_enum (TYPE_IDENTIFIER (template_type),
- tsubst (ENUM_UNDERLYING_TYPE (template_type),
- arglist, complain, in_decl),
- SCOPED_ENUM_P (template_type));
+ t = start_enum (TYPE_IDENTIFIER (template_type), NULL_TREE,
+ tsubst (ENUM_UNDERLYING_TYPE (template_type),
+ arglist, complain, in_decl),
+ SCOPED_ENUM_P (template_type), NULL);
}
else
{
t = cxx_make_type (ENUMERAL_TYPE);
SET_SCOPED_ENUM_P (t, SCOPED_ENUM_P (template_type));
}
+ SET_OPAQUE_ENUM_P (t, OPAQUE_ENUM_P (template_type));
}
else
{
apply_late_template_attributes (&type, TYPE_ATTRIBUTES (pattern),
(int) ATTR_FLAG_TYPE_IN_PLACE,
args, tf_error, NULL_TREE);
+ fixup_attribute_variants (type);
/* Now that our base classes are set up, enter the scope of the
class, so that name lookups into base classes, etc. will work
finish_struct_1 (type);
TYPE_BEING_DEFINED (type) = 0;
- /* Now that the class is complete, instantiate default arguments for
- 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 = 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
- created "fresh" for each instantiation. */
- && DECL_TEMPLATE_INFO (t))
- tsubst_default_arguments (t);
+ /* We don't instantiate default arguments for member functions. 14.7.1:
+
+ The implicit instantiation of a class template specialization causes
+ the implicit instantiation of the declarations, but not of the
+ definitions or default arguments, of the class member functions,
+ member classes, static data members and member templates.... */
/* Some typedefs referenced from within the template code need to be access
checked at template instantiation time, i.e now. These types were
for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
{
tree tuple;
- tree default_value;
- tree parm_decl;
if (parms == error_mark_node)
continue;
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
- && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
- parm_decl = error_mark_node;
- default_value = tsubst_template_arg (default_value, args,
- complain, NULL_TREE);
-
- tuple = build_tree_list (default_value, parm_decl);
- TREE_VEC_ELT (new_vec, i) = tuple;
+ TREE_VEC_ELT (new_vec, i) =
+ tsubst_template_parm (tuple, args, complain);
}
*new_parms =
return r;
}
+/* Return the result of substituting ARGS into one template parameter
+ given by T. T Must be a TREE_LIST which TREE_VALUE is the template
+ parameter and which TREE_PURPOSE is the default argument of the
+ template parameter. */
+
+static tree
+tsubst_template_parm (tree t, tree args, tsubst_flags_t complain)
+{
+ tree default_value, parm_decl;
+
+ if (args == NULL_TREE
+ || t == NULL_TREE
+ || t == error_mark_node)
+ return t;
+
+ gcc_assert (TREE_CODE (t) == TREE_LIST);
+
+ default_value = TREE_PURPOSE (t);
+ parm_decl = TREE_VALUE (t);
+
+ parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
+ if (TREE_CODE (parm_decl) == PARM_DECL
+ && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
+ parm_decl = error_mark_node;
+ default_value = tsubst_template_arg (default_value, args,
+ complain, NULL_TREE);
+
+ return build_tree_list (default_value, parm_decl);
+}
+
/* Substitute the ARGS into the indicated aggregate (or enumeration)
type T. If T is not an aggregate or enumeration type, it is
handled as if by tsubst. IN_DECL is as for tsubst. If
tree saved_class_ptr = NULL_TREE;
tree saved_class_ref = NULL_TREE;
+ /* This can happen in invalid code. */
+ if (TREE_CODE (arg) == DEFAULT_ARG)
+ return arg;
+
/* This default argument came from a template. Instantiate the
default argument here, not in tsubst. In the case of
something like:
its default arguments. */
if (uses_template_parms (tmpl_args))
return;
+ /* Don't do this again for clones. */
+ if (DECL_CLONED_FUNCTION_P (fn))
+ return;
for (arg = TYPE_ARG_TYPES (TREE_TYPE (fn));
arg;
RETURN (error_mark_node);
}
type = complete_type (type);
- DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)
- = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t);
+ /* Wait until cp_finish_decl to set this again, to handle
+ circular dependency (template/instantiate6.C). */
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r) = 0;
type = check_var_type (DECL_NAME (r), type);
if (DECL_HAS_VALUE_EXPR_P (t))
/* Reuse typedefs. We need to do this to handle dependent attributes,
such as attribute aligned. */
if (TYPE_P (t)
- && TYPE_NAME (t)
- && TYPE_NAME (t) != TYPE_MAIN_DECL (t))
+ && typedef_variant_p (t))
{
tree decl = TYPE_NAME (t);
case COMPLEX_TYPE:
case VECTOR_TYPE:
case BOOLEAN_TYPE:
- case INTEGER_CST:
- case REAL_CST:
- case STRING_CST:
+ case NULLPTR_TYPE:
+ case LANG_TYPE:
return t;
case INTEGER_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
with TREE_SIDE_EFFECTS that indicates this is not an integral
constant expression. */
TREE_SIDE_EFFECTS (max) = 1;
}
- if (TREE_CODE (max) != INTEGER_CST
- && !at_function_scope_p ()
- && !TREE_SIDE_EFFECTS (max)
- && !value_dependent_expression_p (max))
- {
- 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
- reasons:
-
- Attempting to create an array with a size that is
- zero or negative. */
- if (integer_zerop (max) && !(complain & tf_error))
- /* We must fail if performing argument deduction (as
- 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 (complain & tf_error)
- error ("creating array with negative size (%qE)", max);
-
- return error_mark_node;
- }
-
- return compute_array_index_type (NULL_TREE, max);
+ return compute_array_index_type (NULL_TREE, max, complain);
}
case TEMPLATE_TYPE_PARM:
return r;
}
- case PLUS_EXPR:
- case MINUS_EXPR:
- {
- tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
- tree e2 = tsubst (TREE_OPERAND (t, 1), args, complain, in_decl);
-
- if (e1 == error_mark_node || e2 == error_mark_node)
- return error_mark_node;
-
- return fold_build2_loc (input_location,
- code, TREE_TYPE (t), e1, e2);
- }
-
- case NEGATE_EXPR:
- case NOP_EXPR:
- {
- tree e = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
- if (e == error_mark_node)
- return error_mark_node;
-
- return fold_build1_loc (input_location, code, TREE_TYPE (t), e);
- }
-
case TYPENAME_TYPE:
{
tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, complain,
return make_unbound_class_template (ctx, name, parm_list, complain);
}
- case INDIRECT_REF:
- case ADDR_EXPR:
- case CALL_EXPR:
- gcc_unreachable ();
-
- 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,
- /*integral_constant_expression_p=*/false);
- if (e1 == error_mark_node || e2 == error_mark_node)
- return error_mark_node;
-
- return build_nt (ARRAY_REF, e1, e2, NULL_TREE, NULL_TREE);
- }
-
- case SCOPE_REF:
- {
- tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
- tree e2 = tsubst (TREE_OPERAND (t, 1), args, complain, in_decl);
- if (e1 == error_mark_node || e2 == error_mark_node)
- return error_mark_node;
-
- return build_qualified_name (/*type=*/NULL_TREE,
- e1, e2, QUALIFIED_NAME_IS_TEMPLATE (t));
- }
-
case TYPEOF_TYPE:
{
tree type;
}
break;
+ case INTEGER_CST:
+ case REAL_CST:
+ case STRING_CST:
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case NEGATE_EXPR:
+ case NOP_EXPR:
+ case INDIRECT_REF:
+ case ADDR_EXPR:
+ case CALL_EXPR:
+ case ARRAY_REF:
+ case SCOPE_REF:
+ /* We should use one of the expression tsubsts for these codes. */
+ gcc_unreachable ();
+
default:
sorry ("use of %qs in template", tree_code_name [(int) code]);
return error_mark_node;
mark_used (t);
return t;
+ case OVERLOAD:
+ /* An OVERLOAD will always be a non-dependent overload set; an
+ overload set from function scope will just be represented with an
+ IDENTIFIER_NODE, and from class scope with a BASELINK. */
+ gcc_assert (!uses_template_parms (t));
+ return t;
+
case BASELINK:
return tsubst_baselink (t, current_class_type, args, complain, in_decl);
error ("use %<...%> to expand argument pack");
return error_mark_node;
- default:
+ case INTEGER_CST:
+ case REAL_CST:
+ case STRING_CST:
+ {
+ /* Instantiate any typedefs in the type. */
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ r = fold_convert (type, t);
+ gcc_assert (TREE_CODE (r) == code);
+ return r;
+ }
+
+ case PTRMEM_CST:
+ /* These can sometimes show up in a partial instantiation, but never
+ involve template parms. */
+ gcc_assert (!uses_template_parms (t));
return t;
+
+ default:
+ gcc_unreachable ();
}
}
break;
case USING_STMT:
- do_using_directive (RECUR (USING_STMT_NAMESPACE (t)));
+ do_using_directive (USING_STMT_NAMESPACE (t));
break;
case DECL_EXPR:
{
- tree decl;
+ tree decl, pattern_decl;
tree init;
- decl = DECL_EXPR_DECL (t);
+ pattern_decl = decl = DECL_EXPR_DECL (t);
if (TREE_CODE (decl) == LABEL_DECL)
finish_label_decl (DECL_NAME (decl));
else if (TREE_CODE (decl) == USING_DECL)
tree name = DECL_NAME (decl);
tree decl;
- scope = RECUR (scope);
+ scope = tsubst (scope, args, complain, in_decl);
decl = lookup_qualified_name (scope, name,
/*is_type_p=*/false,
/*complain=*/false);
finish_anon_union (decl);
else
{
+ int const_init = false;
maybe_push_decl (decl);
if (TREE_CODE (decl) == VAR_DECL
&& DECL_PRETTY_FUNCTION_P (decl))
init = t;
}
- cp_finish_decl (decl, init, false, NULL_TREE, 0);
+ if (TREE_CODE (decl) == VAR_DECL)
+ const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P
+ (pattern_decl));
+ cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
}
}
}
case ADDR_EXPR:
op1 = TREE_OPERAND (t, 0);
+ if (TREE_CODE (op1) == LABEL_DECL)
+ return finish_label_address_expr (DECL_NAME (op1),
+ EXPR_LOCATION (op1));
if (TREE_CODE (op1) == SCOPE_REF)
op1 = tsubst_qualified_id (op1, args, complain, in_decl,
/*done=*/true, /*address_p=*/true);
else
op1 = tsubst_non_call_postfix_expression (op1, args, complain,
in_decl);
- if (TREE_CODE (op1) == LABEL_DECL)
- return finish_label_address_expr (DECL_NAME (op1),
- EXPR_LOCATION (op1));
return build_x_unary_op (ADDR_EXPR, op1, complain);
case PLUS_EXPR:
}
ret = build_new (&placement_vec,
- RECUR (TREE_OPERAND (t, 1)),
+ tsubst (TREE_OPERAND (t, 1), args, complain, in_decl),
RECUR (TREE_OPERAND (t, 2)),
&init_vec,
NEW_EXPR_USE_GLOBAL (t),
case TYPEID_EXPR:
{
- tree operand_0 = RECUR (TREE_OPERAND (t, 0));
+ tree operand_0 = TREE_OPERAND (t, 0);
if (TYPE_P (operand_0))
- return get_typeid (operand_0);
- return build_typeid (operand_0);
+ {
+ operand_0 = tsubst (operand_0, args, complain, in_decl);
+ return get_typeid (operand_0);
+ }
+ else
+ {
+ operand_0 = RECUR (operand_0);
+ return build_typeid (operand_0);
+ }
}
case VAR_DECL:
{
tree parmvec = TYPE_TI_ARGS (parm);
tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
+ tree full_argvec = add_to_template_args (targs, argvec);
tree parm_parms
= DECL_INNERMOST_TEMPLATE_PARMS
(TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm));
the global operator+ will be used; if they are not, the
Lvalue_proxy will be converted to float. */
if (coerce_template_parms (parm_parms,
- argvec,
+ full_argvec,
TYPE_TI_TEMPLATE (parm),
tf_none,
/*require_all_args=*/true,
their initializers are available in integral constant
expressions. */
|| (TREE_CODE (decl) == VAR_DECL
- && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)));
+ && decl_maybe_constant_var_p (decl)));
}
/* Produce the definition of D, a _DECL generated from a template. If
case that an expression refers to the value of the variable --
if the variable has a constant value the referring expression can
take advantage of that fact. */
- if (TREE_CODE (d) == VAR_DECL)
+ if (TREE_CODE (d) == VAR_DECL
+ || DECL_DECLARED_CONSTEXPR_P (d))
defer_ok = 0;
/* Don't instantiate cloned functions. Instead, instantiate the
{
tree ns;
tree init;
+ bool const_init = false;
ns = decl_namespace_context (d);
push_nested_namespace (ns);
args,
tf_warning_or_error, NULL_TREE,
/*integral_constant_expression_p=*/false);
- cp_finish_decl (d, init, /*init_const_expr_p=*/false,
+ /* Make sure the initializer is still constant, in case of
+ circular dependency (template/instantiate6.C). */
+ const_init
+ = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (code_pattern);
+ cp_finish_decl (d, init, /*init_const_expr_p=*/const_init,
/*asmspec_tree=*/NULL_TREE,
LOOKUP_ONLYCONVERTING);
pop_nested_class ();
permerror (input_location, "explicit instantiation of %qD "
"but no definition available", d);
+ /* If we're in unevaluated context, we just wanted to get the
+ constant value; this isn't an odr use, so don't queue
+ a full instantiation. */
+ if (cp_unevaluated_operand != 0)
+ goto out;
/* ??? Historically, we have instantiated inline functions, even
when marked as "extern template". */
if (!(external_p && TREE_CODE (d) == VAR_DECL))
if (TREE_CODE (d) == VAR_DECL)
{
tree init;
+ bool const_init = false;
/* Clear out DECL_RTL; whatever was there before may not be right
since we've reset the type of the declaration. */
DECL_IN_AGGR_P (d) = 0;
/* The initializer is placed in DECL_INITIAL by
- regenerate_decl_from_template. Pull it out so that
+ regenerate_decl_from_template so we don't need to
+ push/pop_access_scope again here. Pull it out so that
cp_finish_decl can process it. */
init = DECL_INITIAL (d);
DECL_INITIAL (d) = NULL_TREE;
/* Enter the scope of D so that access-checking works correctly. */
push_nested_class (DECL_CONTEXT (d));
- cp_finish_decl (d, init, false, NULL_TREE, 0);
+ const_init = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (code_pattern);
+ cp_finish_decl (d, init, const_init, NULL_TREE, 0);
pop_nested_class ();
}
else if (TREE_CODE (d) == FUNCTION_DECL)
if (decl && !DECL_P (decl))
in_base_initializer = 1;
- init = tsubst_expr (TREE_VALUE (t), argvec,
- tf_warning_or_error, NULL_TREE,
- /*integral_constant_expression_p=*/false);
+ init = TREE_VALUE (t);
+ if (init != void_type_node)
+ init = tsubst_expr (init, argvec,
+ tf_warning_or_error, NULL_TREE,
+ /*integral_constant_expression_p=*/false);
in_base_initializer = 0;
}
{
tree e;
+ if (SCOPED_ENUM_P (newtag))
+ begin_scope (sk_scoped_enum, newtag);
+
for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
{
tree value;
(DECL_NAME (decl), value, newtag, DECL_SOURCE_LOCATION (decl));
}
+ if (SCOPED_ENUM_P (newtag))
+ finish_scope ();
+
+ finish_enum_value_list (newtag);
finish_enum (newtag);
+
DECL_SOURCE_LOCATION (TYPE_NAME (newtag))
= DECL_SOURCE_LOCATION (TYPE_NAME (tag));
}
[temp.dep.constexpr]. EXPRESSION is already known to be a constant
expression. */
+/* FIXME this predicate is not appropriate for general expressions; the
+ predicates we want instead are "valid constant expression, value
+ dependent or not?", "really constant expression, not value dependent?"
+ and "instantiation-dependent?". Try to integrate with
+ potential_constant_expression?
+
+ fold_non_dependent_expr: fold if constant and not type-dependent and not value-dependent.
+ (what about instantiation-dependent constant-expressions?)
+ is_late_template_attribute: defer if instantiation-dependent.
+ compute_array_index_type: proceed if constant and not t- or v-dependent
+ if instantiation-dependent, need to remember full expression
+ uses_template_parms: FIXME - need to audit callers
+ tsubst_decl [function_decl]: Why is this using value_dependent_expression_p?
+ dependent_type_p [array_type]: dependent if index type is dependent
+ (or non-constant?)
+ static_assert - instantiation-dependent */
+
bool
value_dependent_expression_p (tree expression)
{
/* If there are no operands, it must be an expression such
as "int()". This should not happen for aggregate types
because it would form non-constant expressions. */
- gcc_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type));
+ gcc_assert (cxx_dialect >= cxx0x
+ || INTEGRAL_OR_ENUMERATION_TYPE_P (type));
return false;
}
return (value_dependent_expression_p (TREE_OPERAND (expression, 0))
|| value_dependent_expression_p (TREE_OPERAND (expression, 1)));
- case CALL_EXPR:
- /* 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;
-
case NONTYPE_ARGUMENT_PACK:
/* A NONTYPE_ARGUMENT_PACK is value-dependent if any packed argument
is value-dependent. */
|| has_value_dependent_address (op));
}
+ case CALL_EXPR:
+ {
+ tree fn = get_callee_fndecl (expression);
+ int i, nargs;
+ if (!fn && value_dependent_expression_p (CALL_EXPR_FN (expression)))
+ return true;
+ nargs = call_expr_nargs (expression);
+ for (i = 0; i < nargs; ++i)
+ {
+ tree op = CALL_EXPR_ARG (expression, i);
+ /* In a call to a constexpr member function, look through the
+ implicit ADDR_EXPR on the object argument so that it doesn't
+ cause the call to be considered value-dependent. We also
+ look through it in potential_constant_expression. */
+ if (i == 0 && fn && DECL_DECLARED_CONSTEXPR_P (fn)
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+ && TREE_CODE (op) == ADDR_EXPR)
+ op = TREE_OPERAND (op, 0);
+ if (value_dependent_expression_p (op))
+ return true;
+ }
+ return false;
+ }
+
default:
/* A constant expression is value-dependent if any subexpression is
value-dependent. */
if (!processing_template_decl)
return false;
+ /* Assume a template argument that was wrongly written by the user
+ is dependent. This is consistent with what
+ any_dependent_template_arguments_p [that calls this function]
+ does. */
+ if (arg == error_mark_node)
+ return true;
+
if (TREE_CODE (arg) == TEMPLATE_DECL
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
return dependent_template_p (arg);
TYPE_STUB_DECL (au) = TYPE_NAME (au);
TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
(0, processing_template_decl + 1, processing_template_decl + 1,
- TYPE_NAME (au), NULL_TREE);
+ 0, TYPE_NAME (au), NULL_TREE);
TYPE_CANONICAL (au) = canonical_type_parameter (au);
DECL_ARTIFICIAL (TYPE_NAME (au)) = 1;
SET_DECL_TEMPLATE_PARM_P (TYPE_NAME (au));