/* 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, 2010, 2011
+ 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
Rewritten by Jason Merrill (jason@cygnus.com).
case TYPE_PACK_EXPANSION:
case EXPR_PACK_EXPANSION:
- return iterative_hash_template_arg (PACK_EXPANSION_PATTERN (arg), val);
+ val = iterative_hash_template_arg (PACK_EXPANSION_PATTERN (arg), val);
+ return iterative_hash_template_arg (PACK_EXPANSION_EXTRA_ARGS (arg), val);
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
(struct find_parameter_pack_data*)data;
bool parameter_pack_p = false;
+ /* Handle type aliases/typedefs. */
+ if (TYPE_P (t)
+ && TYPE_NAME (t)
+ && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
+ && TYPE_DECL_ALIAS_P (TYPE_NAME (t)))
+ {
+ if (TYPE_TEMPLATE_INFO (t))
+ cp_walk_tree (&TYPE_TI_ARGS (t),
+ &find_parameter_packs_r,
+ ppd, ppd->visited);
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+
/* Identify whether this is a parameter pack or not. */
switch (TREE_CODE (t))
{
}
PACK_EXPANSION_PARAMETER_PACKS (result) = parameter_packs;
+ PACK_EXPANSION_LOCAL_P (result) = at_function_scope_p ();
+
return result;
}
if (check_for_bare_parameter_packs (TYPE_RAISES_EXCEPTIONS (type)))
TYPE_RAISES_EXCEPTIONS (type) = NULL_TREE;
}
- else if (check_for_bare_parameter_packs (TREE_TYPE (decl)))
+ else if (check_for_bare_parameter_packs ((TREE_CODE (decl) == TYPE_DECL
+ && TYPE_DECL_ALIAS_P (decl))
+ ? DECL_ORIGINAL_TYPE (decl)
+ : TREE_TYPE (decl)))
{
TREE_TYPE (decl) = error_mark_node;
return error_mark_node;
unify_inconsistency (bool explain_p, tree parm, tree first, tree second)
{
if (explain_p)
- inform (input_location,
- " conflicting deductions for parameter %qE (%qE and %qE)",
- parm, first, second);
+ {
+ if (TYPE_P (parm))
+ inform (input_location,
+ " deduced conflicting types for parameter %qT (%qT and %qT)",
+ parm, first, second);
+ else
+ inform (input_location,
+ " deduced conflicting values for non-type parameter "
+ "%qE (%qE and %qE)", parm, first, second);
+ }
return 1;
}
to a null value, but otherwise still need to be of a specific form. */
if (cxx_dialect >= cxx0x)
{
- if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+ if (TREE_CODE (expr) == PTRMEM_CST)
+ /* A PTRMEM_CST is already constant, and a valid template
+ argument for a parameter of pointer to member type, we just want
+ to leave it in that form rather than lower it to a
+ CONSTRUCTOR. */;
+ else if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
expr = maybe_constant_value (expr);
else if (TYPE_PTR_P (type)
- || (TYPE_PTR_TO_MEMBER_P (type)
- && TREE_CODE (expr) != PTRMEM_CST))
+ || TYPE_PTR_TO_MEMBER_P (type))
{
tree folded = maybe_constant_value (expr);
if (TYPE_PTR_P (type) ? integer_zerop (folded)
if (complain & tf_error)
{
int errs = errorcount, warns = warningcount;
+ if (processing_template_decl
+ && !require_potential_constant_expression (expr))
+ return NULL_TREE;
expr = cxx_constant_value (expr);
if (errorcount > errs || warningcount > warns)
inform (EXPR_LOC_OR_HERE (expr),
if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
&& TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
{
- permerror (input_location, "to refer to a type member of a template parameter, "
- "use %<typename %E%>", orig_arg);
+ if (TREE_CODE (TREE_OPERAND (arg, 1)) == BIT_NOT_EXPR)
+ {
+ if (complain & tf_error)
+ error ("invalid use of destructor %qE as a type", orig_arg);
+ return error_mark_node;
+ }
+
+ permerror (input_location,
+ "to refer to a type member of a template parameter, "
+ "use %<typename %E%>", orig_arg);
orig_arg = make_typename_type (TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1),
return argument_pack;
}
+/* Returns true if the template argument vector ARGS contains
+ any pack expansions, false otherwise. */
+
+static bool
+any_pack_expanson_args_p (tree args)
+{
+ int i;
+ if (args)
+ for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
+ if (PACK_EXPANSION_P (TREE_VEC_ELT (args, i)))
+ return true;
+ return false;
+}
+
/* Convert all template arguments to their appropriate types, and
return a vector containing the innermost resulting template
arguments. If any error occurs, return error_mark_node. Error and
if ((nargs > nparms && !variadic_p)
|| (nargs < nparms - variadic_p
&& require_all_args
+ && !any_pack_expanson_args_p (inner_args)
&& (!use_default_args
|| (TREE_VEC_ELT (parms, nargs) != error_mark_node
&& !TREE_PURPOSE (TREE_VEC_ELT (parms, nargs))))))
/* For member templates */
return TREE_CODE (ot) == TREE_VEC && comp_template_args (ot, nt);
else if (PACK_EXPANSION_P (ot))
- return PACK_EXPANSION_P (nt)
- && template_args_equal (PACK_EXPANSION_PATTERN (ot),
- PACK_EXPANSION_PATTERN (nt));
+ return (PACK_EXPANSION_P (nt)
+ && template_args_equal (PACK_EXPANSION_PATTERN (ot),
+ PACK_EXPANSION_PATTERN (nt))
+ && template_args_equal (PACK_EXPANSION_EXTRA_ARGS (ot),
+ PACK_EXPANSION_EXTRA_ARGS (nt)));
else if (ARGUMENT_PACK_P (ot))
{
int i, len;
{
int i;
+ if (oldargs == newargs)
+ return 1;
+
+ if (!oldargs || !newargs)
+ return 0;
+
if (TREE_VEC_LENGTH (oldargs) != TREE_VEC_LENGTH (newargs))
return 0;
context = tsubst (DECL_CONTEXT (gen_tmpl), arglist,
complain, in_decl);
+ if (context == error_mark_node)
+ return error_mark_node;
+
if (!context)
context = global_namespace;
for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
{
tree p = TREE_VALUE (TREE_VEC_ELT (parms, i));
+ if (p == error_mark_node)
+ continue;
+
if (parm == p
|| (DECL_INITIAL (parm)
&& DECL_INITIAL (parm) == DECL_INITIAL (p)))
if (CLASSTYPE_LAMBDA_EXPR (type))
{
- tree lambda = CLASSTYPE_LAMBDA_EXPR (type);
- if (LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda))
+ tree decl = lambda_function (type);
+ if (decl)
{
- apply_lambda_return_type (lambda, void_type_node);
- LAMBDA_EXPR_RETURN_TYPE (lambda) = NULL_TREE;
+ tree lambda = CLASSTYPE_LAMBDA_EXPR (type);
+ if (LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda))
+ {
+ apply_lambda_return_type (lambda, void_type_node);
+ LAMBDA_EXPR_RETURN_TYPE (lambda) = NULL_TREE;
+ }
+ instantiate_decl (decl, false, false);
+ maybe_add_lambda_conv_op (type);
}
- instantiate_decl (lambda_function (type), false, false);
- maybe_add_lambda_conv_op (type);
+ else
+ gcc_assert (errorcount);
}
/* Set the file and line number information to whatever is given for
tree pattern;
tree pack, packs = NULL_TREE;
bool unsubstituted_packs = false;
+ bool real_packs = false;
+ int missing_level = 0;
int i, len = -1;
tree result;
htab_t saved_local_specializations = NULL;
+ bool need_local_specializations = false;
+ int levels;
gcc_assert (PACK_EXPANSION_P (t));
pattern = PACK_EXPANSION_PATTERN (t);
+ /* Add in any args remembered from an earlier partial instantiation. */
+ args = add_to_template_args (PACK_EXPANSION_EXTRA_ARGS (t), args);
+
+ levels = TMPL_ARGS_DEPTH (args);
+
/* Determine the argument packs that will instantiate the parameter
packs used in the expansion expression. While we're at it,
compute the number of arguments to be expanded and make sure it
tree parm_pack = TREE_VALUE (pack);
tree arg_pack = NULL_TREE;
tree orig_arg = NULL_TREE;
+ int level = 0;
if (TREE_CODE (parm_pack) == BASES)
{
}
if (TREE_CODE (parm_pack) == PARM_DECL)
{
- if (!cp_unevaluated_operand)
+ if (PACK_EXPANSION_LOCAL_P (t))
arg_pack = retrieve_local_specialization (parm_pack);
else
{
arg_pack = NULL_TREE;
else
arg_pack = make_fnparm_pack (arg_pack);
+ need_local_specializations = true;
}
}
else
{
- int level, idx, levels;
+ int idx;
template_parm_level_and_index (parm_pack, &level, &idx);
- levels = TMPL_ARGS_DEPTH (args);
if (level <= levels)
arg_pack = TMPL_ARG (args, level, idx);
}
len = my_len;
else if (len != my_len)
{
- if (TREE_CODE (t) == TYPE_PACK_EXPANSION)
+ if (!(complain & tf_error))
+ /* Fail quietly. */;
+ else if (TREE_CODE (t) == TYPE_PACK_EXPANSION)
error ("mismatched argument pack lengths while expanding "
"%<%T%>",
pattern);
return error_mark_node;
}
+ if (TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack)) == 1
+ && PACK_EXPANSION_P (TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack),
+ 0)))
+ /* This isn't a real argument pack yet. */;
+ else
+ real_packs = true;
+
/* Keep track of the parameter packs and their corresponding
argument packs. */
packs = tree_cons (parm_pack, arg_pack, packs);
}
else
{
- /* We can't substitute for this parameter pack. */
+ /* We can't substitute for this parameter pack. We use a flag as
+ well as the missing_level counter because function parameter
+ packs don't have a level. */
unsubstituted_packs = true;
- break;
+ if (!missing_level || missing_level > level)
+ missing_level = level;
}
}
/* We cannot expand this expansion expression, because we don't have
- all of the argument packs we need. Substitute into the pattern
- and return a PACK_EXPANSION_*. The caller will need to deal with
- that. */
+ all of the argument packs we need. */
if (unsubstituted_packs)
{
- tree new_pat;
- if (TREE_CODE (t) == EXPR_PACK_EXPANSION)
- new_pat = tsubst_expr (pattern, args, complain, in_decl,
- /*integral_constant_expression_p=*/false);
+ if (real_packs)
+ {
+ /* We got some full packs, but we can't substitute them in until we
+ have values for all the packs. So remember these until then. */
+ tree save_args;
+
+ t = make_pack_expansion (pattern);
+
+ /* The call to add_to_template_args above assumes no overlap
+ between saved args and new args, so prune away any fake
+ args, i.e. those that satisfied arg_from_parm_pack_p above. */
+ if (missing_level && levels >= missing_level)
+ {
+ gcc_assert (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)
+ && missing_level > 1);
+ TREE_VEC_LENGTH (args) = missing_level - 1;
+ save_args = copy_node (args);
+ TREE_VEC_LENGTH (args) = levels;
+ }
+ else
+ save_args = args;
+
+ PACK_EXPANSION_EXTRA_ARGS (t) = save_args;
+ }
else
- new_pat = tsubst (pattern, args, complain, in_decl);
- return make_pack_expansion (new_pat);
+ {
+ /* There were no real arguments, we're just replacing a parameter
+ pack with another version of itself. Substitute into the
+ pattern and return a PACK_EXPANSION_*. The caller will need to
+ deal with that. */
+ if (TREE_CODE (t) == EXPR_PACK_EXPANSION)
+ t = tsubst_expr (pattern, args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+ else
+ t = tsubst (pattern, args, complain, in_decl);
+ t = make_pack_expansion (t);
+ }
+ return t;
}
/* We could not find any argument packs that work. */
if (len < 0)
return error_mark_node;
- if (cp_unevaluated_operand)
+ if (need_local_specializations)
{
/* We're in a late-specified return type, so create our own local
specializations table; the current table is either NULL or (in the
}
}
- if (saved_local_specializations)
+ if (need_local_specializations)
{
htab_delete (local_specializations);
local_specializations = saved_local_specializations;
type = DECL_ORIGINAL_TYPE (t);
else
type = TREE_TYPE (t);
- if (TREE_CODE (t) == VAR_DECL && VAR_HAD_UNKNOWN_BOUND (t))
+ if (TREE_CODE (t) == VAR_DECL
+ && VAR_HAD_UNKNOWN_BOUND (t)
+ && type != error_mark_node)
type = strip_array_domain (type);
type = tsubst (type, args, complain, in_decl);
}
complain | tf_ignore_bad_quals);
return r;
}
- /* Else we must be instantiating the typedef, so fall through. */
+ else
+ /* We don't have an instantiation yet, so drop the typedef. */
+ t = DECL_ORIGINAL_TYPE (decl);
}
if (type
tree optype;
tree template_args = 0;
bool template_id_p = false;
+ bool qualified = BASELINK_QUALIFIED_P (baselink);
/* A baselink indicates a function from a base class. Both the
BASELINK_ACCESS_BINFO and the base class referenced may
if (!object_type)
object_type = current_class_type;
- return adjust_result_of_qualified_name_lookup (baselink,
- qualifying_scope,
- object_type);
+
+ if (qualified)
+ baselink = adjust_result_of_qualified_name_lookup (baselink,
+ qualifying_scope,
+ object_type);
+ return baselink;
}
/* Like tsubst_expr for a SCOPE_REF, given by QUALIFIED_ID. DONE is
if (purpose)
purpose = RECUR (purpose);
value = TREE_VALUE (t);
- if (value && TREE_CODE (value) != LABEL_DECL)
- value = RECUR (value);
+ if (value)
+ {
+ if (TREE_CODE (value) != LABEL_DECL)
+ value = RECUR (value);
+ else
+ {
+ value = lookup_label (DECL_NAME (value));
+ gcc_assert (TREE_CODE (value) == LABEL_DECL);
+ TREE_USED (value) = 1;
+ }
+ }
chain = TREE_CHAIN (t);
if (chain && chain != void_type_node)
chain = RECUR (chain);
&& ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
/* Anonymous aggregates are a special case. */
finish_anon_union (decl);
+ else if (is_capture_proxy (DECL_EXPR_DECL (t)))
+ {
+ DECL_CONTEXT (decl) = current_function_decl;
+ insert_capture_proxy (decl);
+ }
else
{
int const_init = false;
if (TRANSACTION_EXPR_IS_STMT (t))
{
+ tree body = TRANSACTION_EXPR_BODY (t);
+ tree noex = NULL_TREE;
+ if (TREE_CODE (body) == MUST_NOT_THROW_EXPR)
+ {
+ noex = MUST_NOT_THROW_COND (body);
+ if (noex == NULL_TREE)
+ noex = boolean_true_node;
+ body = TREE_OPERAND (body, 0);
+ }
stmt = begin_transaction_stmt (input_location, NULL, flags);
- RECUR (TRANSACTION_EXPR_BODY (t));
- finish_transaction_stmt (stmt, NULL, flags);
+ RECUR (body);
+ finish_transaction_stmt (stmt, NULL, flags, RECUR (noex));
}
else
{
stmt = build_transaction_expr (EXPR_LOCATION (t),
RECUR (TRANSACTION_EXPR_BODY (t)),
- flags);
+ flags, NULL_TREE);
return stmt;
}
}
break;
+ case MUST_NOT_THROW_EXPR:
+ return build_must_not_throw_expr (RECUR (TREE_OPERAND (t, 0)),
+ RECUR (MUST_NOT_THROW_COND (t)));
+
case EXPR_PACK_EXPANSION:
error ("invalid use of pack expansion expression");
return error_mark_node;
case GT_EXPR:
case MEMBER_REF:
case DOTSTAR_EXPR:
- return build_x_binary_op
- (TREE_CODE (t),
- RECUR (TREE_OPERAND (t, 0)),
- (TREE_NO_WARNING (TREE_OPERAND (t, 0))
- ? ERROR_MARK
- : TREE_CODE (TREE_OPERAND (t, 0))),
- RECUR (TREE_OPERAND (t, 1)),
- (TREE_NO_WARNING (TREE_OPERAND (t, 1))
- ? ERROR_MARK
- : TREE_CODE (TREE_OPERAND (t, 1))),
- /*overload=*/NULL,
- complain);
+ {
+ tree r = build_x_binary_op
+ (TREE_CODE (t),
+ RECUR (TREE_OPERAND (t, 0)),
+ (TREE_NO_WARNING (TREE_OPERAND (t, 0))
+ ? ERROR_MARK
+ : TREE_CODE (TREE_OPERAND (t, 0))),
+ RECUR (TREE_OPERAND (t, 1)),
+ (TREE_NO_WARNING (TREE_OPERAND (t, 1))
+ ? ERROR_MARK
+ : TREE_CODE (TREE_OPERAND (t, 1))),
+ /*overload=*/NULL,
+ complain);
+ if (EXPR_P (r) && TREE_NO_WARNING (t))
+ TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
+ return r;
+ }
case SCOPE_REF:
return tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
return r;
}
+ case TRANSACTION_EXPR:
+ return tsubst_expr(t, args, complain, in_decl,
+ integral_constant_expression_p);
+
default:
/* Handle Objective-C++ constructs, if appropriate. */
{
tree fndecl;
tree gen_tmpl;
tree spec;
- HOST_WIDE_INT saved_processing_template_decl;
if (tmpl == error_mark_node)
return error_mark_node;
deferring all checks until we have the FUNCTION_DECL. */
push_deferring_access_checks (dk_deferred);
- /* Although PROCESSING_TEMPLATE_DECL may be true at this point
- (because, for example, we have encountered a non-dependent
- function call in the body of a template function and must now
- determine which of several overloaded functions will be called),
- within the instantiation itself we are not processing a
- template. */
- saved_processing_template_decl = processing_template_decl;
- processing_template_decl = 0;
+ /* Instantiation of the function happens in the context of the function
+ template, not the context of the overload resolution we're doing. */
+ push_to_top_level ();
+ if (DECL_CLASS_SCOPE_P (gen_tmpl))
+ {
+ tree ctx = tsubst (DECL_CONTEXT (gen_tmpl), targ_ptr,
+ complain, gen_tmpl);
+ push_nested_class (ctx);
+ }
/* Substitute template parameters to obtain the specialization. */
fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
targ_ptr, complain, gen_tmpl);
- processing_template_decl = saved_processing_template_decl;
+ if (DECL_CLASS_SCOPE_P (gen_tmpl))
+ pop_nested_class ();
+ pop_from_top_level ();
+
if (fndecl == error_mark_node)
return error_mark_node;
{
tree parm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
tree arg = TREE_PURPOSE (TREE_VEC_ELT (tparms, i));
+ location_t save_loc = input_location;
+ if (DECL_P (parm))
+ input_location = DECL_SOURCE_LOCATION (parm);
arg = tsubst_template_arg (arg, targs, complain, NULL_TREE);
arg = convert_template_argument (parm, arg, targs, complain,
i, NULL_TREE);
+ input_location = save_loc;
if (arg == error_mark_node)
return 1;
else
elem = tsubst (TREE_TYPE (fn), subargs, tf_none, NULL_TREE);
if (try_one_overload (tparms, targs, tempargs, parm,
elem, strict, sub_strict, addr_p, explain_p)
- && (!goodfn || !decls_match (goodfn, elem)))
+ && (!goodfn || !same_type_p (goodfn, elem)))
{
goodfn = elem;
++good;
idx = TEMPLATE_TYPE_IDX (parm);
targ = TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx);
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, idx));
+ if (tparm == error_mark_node)
+ return unify_invalid (explain_p);
/* Check for mixed types and values. */
if ((TREE_CODE (parm) == TEMPLATE_TYPE_PARM
case BOOLEAN_TYPE:
case ENUMERAL_TYPE:
case VOID_TYPE:
+ case NULLPTR_TYPE:
if (TREE_CODE (arg) != TREE_CODE (parm))
return unify_type_mismatch (explain_p, parm, arg);
default:
/* An unresolved overload is a nondeduced context. */
- if (type_unknown_p (parm))
+ if (is_overloaded_fn (parm) || type_unknown_p (parm))
return unify_success (explain_p);
gcc_assert (EXPR_P (parm));
/* Build a dummy EXPR_PACK_EXPANSION that will be used to
expand each argument in the TREE_VALUE of t. */
expr = make_node (EXPR_PACK_EXPANSION);
+ PACK_EXPANSION_LOCAL_P (expr) = true;
PACK_EXPANSION_PARAMETER_PACKS (expr) =
PACK_EXPANSION_PARAMETER_PACKS (TREE_PURPOSE (t));
}
else
{
+ tree tmp;
decl = tsubst_copy (TREE_PURPOSE (t), argvec,
tf_warning_or_error, NULL_TREE);
in_base_initializer = 1;
init = TREE_VALUE (t);
+ tmp = init;
if (init != void_type_node)
init = tsubst_expr (init, argvec,
tf_warning_or_error, NULL_TREE,
/*integral_constant_expression_p=*/false);
+ if (init == NULL_TREE && tmp != NULL_TREE)
+ /* 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 = void_type_node;
in_base_initializer = 0;
}
return false;
}
+ case STMT_EXPR:
+ /* Treat a GNU statement expression as dependent to avoid crashing
+ under fold_non_dependent_expr; it can't be constant. */
+ return true;
+
default:
/* A constant expression is value-dependent if any subexpression is
value-dependent. */