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);
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,
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;
= 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;
}
TREE_VALUE (argtype) = error_mark_node;
}
- arg = TREE_CHAIN (arg);
+ arg = DECL_CHAIN (arg);
argtype = TREE_CHAIN (argtype);
}
/* 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.
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;
}
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
- expr = fold_non_dependent_expr (expr);
+ 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);
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;
/* 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;
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)
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;
/* 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);
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);
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;
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);
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;
else
register_local_specialization (r, t);
- TREE_CHAIN (r) = NULL_TREE;
+ DECL_CHAIN (r) = NULL_TREE;
apply_late_template_attributes (&r, DECL_ATTRIBUTES (r),
/*flags=*/0,
&& !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
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;
}
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)
{
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;
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;
{
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. */
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);
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);
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)
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;