static void perform_typedefs_access_check (tree tmpl, tree targs);
static void append_type_to_template_for_access_check_1 (tree, tree, tree);
static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
-static bool primary_template_instantiation_p (const_tree);
static tree listify (tree);
static tree listify_autos (tree, tree);
if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
tinfo = DECL_TEMPLATE_INFO (t);
- if (!tinfo && TREE_CODE (t) == TYPE_DECL)
+ if (!tinfo && DECL_IMPLICIT_TYPEDEF_P (t))
t = TREE_TYPE (t);
if (TAGGED_TYPE_P (t))
to the primary function; now copy the inline bits to
the various clones. */
FOR_EACH_CLONE (clone, fn)
- DECL_DECLARED_INLINE_P (clone)
- = DECL_DECLARED_INLINE_P (fn);
+ {
+ DECL_DECLARED_INLINE_P (clone)
+ = DECL_DECLARED_INLINE_P (fn);
+ DECL_SOURCE_LOCATION (clone)
+ = DECL_SOURCE_LOCATION (fn);
+ }
check_specialization_namespace (fn);
return fn;
}
case PARM_DECL:
- val = iterative_hash_object (DECL_PARM_INDEX (arg), val);
+ if (!DECL_ARTIFICIAL (arg))
+ val = iterative_hash_object (DECL_PARM_INDEX (arg), val);
return iterative_hash_template_arg (TREE_TYPE (arg), val);
case TARGET_EXPR:
print_candidates (tree fns)
{
tree fn;
+ tree f;
const char *str = "candidates are:";
- for (fn = fns; fn != NULL_TREE; fn = TREE_CHAIN (fn))
+ if (is_overloaded_fn (fns))
+ {
+ for (f = fns; f; f = OVL_NEXT (f))
+ {
+ error ("%s %+#D", str, OVL_CURRENT (f));
+ str = " ";
+ }
+ }
+ else for (fn = fns; fn != NULL_TREE; fn = TREE_CHAIN (fn))
{
- tree f;
-
for (f = TREE_VALUE (fn); f; f = OVL_NEXT (f))
error ("%s %+#D", str, OVL_CURRENT (f));
str = " ";
bool
function_parameter_expanded_from_pack_p (tree param_decl, tree pack)
{
- if (! function_parameter_pack_p (pack))
+ if (DECL_ARTIFICIAL (param_decl)
+ || !function_parameter_pack_p (pack))
return false;
gcc_assert (DECL_NAME (param_decl) && DECL_NAME (pack));
/* Return true if T is a primary function
or class template instantiation. */
-static bool
+bool
primary_template_instantiation_p (const_tree t)
{
if (!t)
pointer_set_destroy (ppd.visited);
/* Create the pack expansion type for the base type. */
- purpose = make_node (TYPE_PACK_EXPANSION);
+ purpose = cxx_make_type (TYPE_PACK_EXPANSION);
SET_PACK_EXPANSION_PATTERN (purpose, TREE_PURPOSE (arg));
PACK_EXPANSION_PARAMETER_PACKS (purpose) = parameter_packs;
for_types = true;
/* Build the PACK_EXPANSION_* node. */
- result = make_node (for_types ? TYPE_PACK_EXPANSION : EXPR_PACK_EXPANSION);
+ result = for_types
+ ? cxx_make_type (TYPE_PACK_EXPANSION)
+ : make_node (EXPR_PACK_EXPANSION);
SET_PACK_EXPANSION_PATTERN (result, arg);
if (TREE_CODE (result) == EXPR_PACK_EXPANSION)
{
tree vec = make_tree_vec (1);
TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
- t = make_node (TYPE_ARGUMENT_PACK);
+ t = cxx_make_type (TYPE_ARGUMENT_PACK);
SET_ARGUMENT_PACK_ARGS (t, vec);
}
}
else if (is_friend_decl)
msg = "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";
+ msg = ("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";
else
return fn;
}
+/* Subroutine of convert_nontype_argument.
+ Check if EXPR of type TYPE is a valid pointer-to-member constant.
+ Emit an error otherwise. */
+
+static bool
+check_valid_ptrmem_cst_expr (tree type, tree expr)
+{
+ STRIP_NOPS (expr);
+ if (expr && (null_ptr_cst_p (expr) || TREE_CODE (expr) == PTRMEM_CST))
+ return true;
+ error ("%qE is not a valid template argument for type %qT",
+ expr, type);
+ error ("it must be a pointer-to-member of the form `&X::Y'");
+ 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
shall be one of: [...]
-- the address of an object or function with external linkage. */
+ if (TREE_CODE (expr) == INDIRECT_REF
+ && TYPE_REF_OBJ_P (TREE_TYPE (TREE_OPERAND (expr, 0))))
+ {
+ expr = TREE_OPERAND (expr, 0);
+ if (DECL_P (expr))
+ {
+ error ("%q#D is not a valid template argument for type %qT "
+ "because a reference variable does not have a constant "
+ "address", expr, type);
+ return NULL_TREE;
+ }
+ }
+
+ if (!DECL_P (expr))
+ {
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is not an object with external linkage",
+ expr, type);
+ return NULL_TREE;
+ }
+
if (!DECL_EXTERNAL_LINKAGE_P (expr))
{
error ("%qE is not a valid template argument for type %qT "
if (expr == error_mark_node)
return error_mark_node;
+ /* [temp.arg.nontype] bullet 1 says the pointer to member
+ expression must be a pointer-to-member constant. */
+ if (!check_valid_ptrmem_cst_expr (type, expr))
+ return error_mark_node;
+
/* There is no way to disable standard conversions in
resolve_address_of_overloaded_function (called by
instantiate_type). It is possible that the call succeeded by
qualification conversions (_conv.qual_) are applied. */
else if (TYPE_PTRMEM_P (type))
{
+ /* [temp.arg.nontype] bullet 1 says the pointer to member
+ expression must be a pointer-to-member constant. */
+ if (!check_valid_ptrmem_cst_expr (type, expr))
+ return error_mark_node;
+
expr = perform_qualification_conversions (type, expr);
if (expr == error_mark_node)
return expr;
if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL
|| TREE_CODE (TREE_VALUE (parm)) == TEMPLATE_DECL)
- argument_pack = make_node (TYPE_ARGUMENT_PACK);
+ argument_pack = cxx_make_type (TYPE_ARGUMENT_PACK);
else
{
argument_pack = make_node (NONTYPE_ARGUMENT_PACK);
return 0;
return 1;
}
+ else if (ot && TREE_CODE (ot) == ARGUMENT_PACK_SELECT)
+ {
+ /* We get here probably because we are in the middle of substituting
+ into the pattern of a pack expansion. In that case the
+ ARGUMENT_PACK_SELECT temporarily replaces the pack argument we are
+ interested in. So we want to use the initial pack argument for
+ the comparison. */
+ ot = ARGUMENT_PACK_SELECT_FROM_PACK (ot);
+ if (nt && TREE_CODE (nt) == ARGUMENT_PACK_SELECT)
+ nt = ARGUMENT_PACK_SELECT_FROM_PACK (nt);
+ return template_args_equal (ot, nt);
+ }
else if (TYPE_P (nt))
return TYPE_P (ot) && same_type_p (ot, nt);
else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))
if (!is_partial_instantiation
&& !PRIMARY_TEMPLATE_P (gen_tmpl)
+ && !LAMBDA_TYPE_P (TREE_TYPE (gen_tmpl))
&& TREE_CODE (CP_DECL_CONTEXT (gen_tmpl)) == NAMESPACE_DECL)
{
found = xref_tag_from_type (TREE_TYPE (gen_tmpl),
the values for the enumeration constants may involve
template parameters. And, no one should be interested
in the enumeration constants for such a type. */
- t = make_node (ENUMERAL_TYPE);
+ t = cxx_make_type (ENUMERAL_TYPE);
SET_SCOPED_ENUM_P (t, SCOPED_ENUM_P (template_type));
}
}
type_decl = create_implicit_typedef (DECL_NAME (gen_tmpl), t);
DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
- TYPE_STUB_DECL (t) = type_decl;
DECL_SOURCE_LOCATION (type_decl)
= DECL_SOURCE_LOCATION (TYPE_STUB_DECL (template_type));
}
tree typedecl;
tree pbinfo;
tree base_list;
+ unsigned int saved_maximum_field_alignment;
if (type == error_mark_node)
return error_mark_node;
if (TYPE_BEING_DEFINED (type)
|| COMPLETE_TYPE_P (type)
- || dependent_type_p (type))
+ || uses_template_parms (type))
return type;
/* Figure out which template is being instantiated. */
push_deferring_access_checks (dk_no_deferred);
push_to_top_level ();
+ /* Use #pragma pack from the template context. */
+ saved_maximum_field_alignment = maximum_field_alignment;
+ maximum_field_alignment = TYPE_PRECISION (pattern);
SET_CLASSTYPE_INTERFACE_UNKNOWN (type);
perform_typedefs_access_check (pattern, args);
perform_deferred_access_checks ();
pop_nested_class ();
+ maximum_field_alignment = saved_maximum_field_alignment;
pop_from_top_level ();
pop_deferring_access_checks ();
pop_tinst_level ();
tree parmvec;
tree parmtypevec;
tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
- tree argtypepack = make_node (TYPE_ARGUMENT_PACK);
+ tree argtypepack = cxx_make_type (TYPE_ARGUMENT_PACK);
int i, len = list_length (spec_parm);
/* Fill in PARMVEC and PARMTYPEVEC with all of the parameters. */
}
else if (len != my_len)
{
+ if (incomplete)
+ /* We got explicit args for some packs but not others;
+ do nothing now and try again after deduction. */
+ return t;
if (TREE_CODE (t) == TYPE_PACK_EXPANSION)
error ("mismatched argument pack lengths while expanding "
"%<%T%>",
else if (ARGUMENT_PACK_P (orig_arg))
{
/* Substitute into each of the arguments. */
- new_arg = make_node (TREE_CODE (orig_arg));
+ new_arg = TYPE_P (orig_arg)
+ ? cxx_make_type (TREE_CODE (orig_arg))
+ : make_node (TREE_CODE (orig_arg));
SET_ARGUMENT_PACK_ARGS (
new_arg,
static tree
tsubst_decl (tree t, tree args, tsubst_flags_t complain)
{
+#define RETURN(EXP) do { r = (EXP); goto out; } while(0)
location_t saved_loc;
tree r = NULL_TREE;
tree in_decl = t;
/* Template template parameter is treated here. */
tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (new_type == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
r = copy_decl (t);
TREE_CHAIN (r) = NULL_TREE;
complain, in_decl);
--processing_template_decl;
if (full_args == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
/* If this is a default template template argument,
tsubst might not have changed anything. */
if (full_args == tmpl_args)
- return t;
+ RETURN (t);
hash = hash_tmpl_and_args (t, full_args);
spec = retrieve_specialization (t, full_args, hash);
new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
--processing_template_decl;
if (new_type == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
TREE_TYPE (r) = new_type;
CLASSTYPE_TI_TEMPLATE (new_type) = r;
new_decl = tsubst (decl, args, complain, in_decl);
--processing_template_decl;
if (new_decl == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
DECL_TEMPLATE_RESULT (r) = new_decl;
DECL_TI_TEMPLATE (new_decl) = r;
dependent_p = value_dependent_expression_p (t);
--processing_template_decl;
if (!dependent_p)
- return t;
+ RETURN (t);
/* Calculate the most general template of which R is a
specialization, and the complete set of arguments used to
}
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
/* We do NOT check for matching decls pushed separately at this
point, as they may not represent instantiations of this
/* We'll re-clone as appropriate in instantiate_template. */
DECL_CLONED_FUNCTION (r) = NULL_TREE;
+ /* If we aren't complaining now, return on error before we register
+ the specialization so that we'll complain eventually. */
+ if ((complain & tf_error) == 0
+ && IDENTIFIER_OPNAME_P (DECL_NAME (r))
+ && !grok_op_properties (r, /*complain=*/false))
+ RETURN (error_mark_node);
+
/* Set up the DECL_TEMPLATE_INFO for R. There's no need to do
this in the special friend case mentioned above where
GEN_TMPL is NULL. */
if (PRIMARY_TEMPLATE_P (gen_tmpl))
clone_function_decl (r, /*update_method_vec_p=*/0);
}
- else if (IDENTIFIER_OPNAME_P (DECL_NAME (r))
- && !grok_op_properties (r, (complain & tf_error) != 0))
- return error_mark_node;
+ else if ((complain & tf_error) != 0
+ && IDENTIFIER_OPNAME_P (DECL_NAME (r))
+ && !grok_op_properties (r, /*complain=*/true))
+ RETURN (error_mark_node);
if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
SET_DECL_FRIEND_CONTEXT (r,
= remove_attribute ("visibility", DECL_ATTRIBUTES (r));
}
determine_visibility (r);
+ if (DECL_DEFAULTED_OUTSIDE_CLASS_P (r)
+ && !processing_template_decl)
+ defaulted_late_check (r);
apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
args, complain, in_decl);
if (spec
&& TREE_CODE (spec) == PARM_DECL
&& TREE_CODE (TREE_TYPE (spec)) != TYPE_PACK_EXPANSION)
- return spec;
+ RETURN (spec);
/* Expand the TYPE_PACK_EXPANSION that provides the types for
the parameters in this function parameter pack. */
/* Zero-length parameter packs are boring. Just substitute
into the chain. */
if (len == 0)
- return tsubst (TREE_CHAIN (t), args, complain,
- TREE_CHAIN (t));
+ RETURN (tsubst (TREE_CHAIN (t), args, complain,
+ TREE_CHAIN (t)));
}
else
{
r = copy_decl (t);
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
TREE_TYPE (r) = type;
cp_apply_type_quals_to_decl (cp_type_quals (type), r);
we've copied the type for a typedef. */
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
r = TYPE_NAME (type);
break;
}
DECL_INITIALIZED_P (r) = 0;
DECL_TEMPLATE_INSTANTIATED (r) = 0;
if (type == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
if (TREE_CODE (type) == FUNCTION_TYPE)
{
/* It may seem that this case cannot occur, since:
/* R is not yet sufficiently initialized, so we
just use its name. */
DECL_NAME (r));
- return error_mark_node;
+ RETURN (error_mark_node);
}
type = complete_type (type);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)
DECL_TEMPLATE_INFO (r) = tree_cons (tmpl, argvec, NULL_TREE);
SET_DECL_IMPLICIT_INSTANTIATION (r);
}
+ else if (cp_unevaluated_operand)
+ {
+ /* We're substituting this var in a decltype outside of its
+ scope, such as for a lambda return type. Don't add it to
+ local_specializations, do perform auto deduction. */
+ tree auto_node = type_uses_auto (type);
+ tree init
+ = tsubst_expr (DECL_INITIAL (t), args, complain, in_decl,
+ /*constant_expression_p=*/false);
+
+ if (auto_node && init && describable_type (init))
+ {
+ type = do_auto_deduction (type, init, auto_node);
+ TREE_TYPE (r) = type;
+ }
+ }
else
register_local_specialization (r, t);
default:
gcc_unreachable ();
}
+#undef RETURN
+ out:
/* Restore the file and line information. */
input_location = saved_loc;
{
/* The type of the implicit object parameter gets its
cv-qualifiers from the FUNCTION_TYPE. */
- tree method_type;
- tree this_type = cp_build_qualified_type (TYPE_MAIN_VARIANT (r),
- cp_type_quals (type));
tree memptr;
- method_type = build_method_type_directly (this_type,
- TREE_TYPE (type),
- TYPE_ARG_TYPES (type));
+ tree method_type = build_memfn_type (type, r, cp_type_quals (type));
memptr = build_ptrmemfunc_type (build_pointer_type (method_type));
return cp_build_qualified_type_real (memptr, cp_type_quals (t),
complain);
{
tree type;
- type = finish_typeof (tsubst_expr
- (TYPEOF_TYPE_EXPR (t), args,
- complain, in_decl,
- /*integral_constant_expression_p=*/false));
+ ++cp_unevaluated_operand;
+ ++c_inhibit_evaluation_warnings;
+
+ type = tsubst_expr (TYPEOF_TYPE_EXPR (t), args,
+ complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+
+ --cp_unevaluated_operand;
+ --c_inhibit_evaluation_warnings;
+
+ type = finish_typeof (type);
return cp_build_qualified_type_real (type,
cp_type_quals (t)
| cp_type_quals (type),
--cp_unevaluated_operand;
--c_inhibit_evaluation_warnings;
- type =
- finish_decltype_type (type,
- DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t));
+ if (DECLTYPE_FOR_LAMBDA_CAPTURE (t))
+ type = lambda_capture_field_type (type);
+ else if (DECLTYPE_FOR_LAMBDA_RETURN (t))
+ type = lambda_return_type (type);
+ else
+ type = finish_decltype_type
+ (type, DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t));
return cp_build_qualified_type_real (type,
cp_type_quals (t)
| cp_type_quals (type),
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
{
- tree r = make_node (TREE_CODE (t));
+ tree r = TYPE_P (t)
+ ? cxx_make_type (TREE_CODE (t))
+ : make_node (TREE_CODE (t));
tree packed_out =
tsubst_template_args (ARGUMENT_PACK_ARGS (t),
args,
qualifying_scope = tsubst (qualifying_scope, args,
complain, in_decl);
fns = BASELINK_FUNCTIONS (baselink);
- optype = BASELINK_OPTYPE (baselink);
+ optype = tsubst (BASELINK_OPTYPE (baselink), args, complain, in_decl);
if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
{
template_id_p = true;
complain, in_decl);
}
name = DECL_NAME (get_first_fn (fns));
+ if (IDENTIFIER_TYPENAME_P (name))
+ name = mangle_conv_op_name_for_type (optype);
baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
/* If lookup found a single function, mark it as used at this
BASELINK_FUNCTIONS (baselink),
template_args);
/* Update the conversion operator type. */
- BASELINK_OPTYPE (baselink)
- = tsubst (optype, args, complain, in_decl);
+ BASELINK_OPTYPE (baselink) = optype;
if (!object_type)
object_type = current_class_type;
}
return t;
+ case LAMBDA_EXPR:
+ {
+ tree r = build_lambda_expr ();
+
+ tree type = tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
+ TREE_TYPE (r) = type;
+ CLASSTYPE_LAMBDA_EXPR (type) = r;
+
+ LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (r)
+ = LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (t);
+ LAMBDA_EXPR_MUTABLE_P (r) = LAMBDA_EXPR_MUTABLE_P (t);
+ LAMBDA_EXPR_DISCRIMINATOR (r)
+ = (LAMBDA_EXPR_DISCRIMINATOR (t));
+ LAMBDA_EXPR_CAPTURE_LIST (r)
+ = RECUR (LAMBDA_EXPR_CAPTURE_LIST (t));
+ LAMBDA_EXPR_THIS_CAPTURE (r)
+ = RECUR (LAMBDA_EXPR_THIS_CAPTURE (t));
+ LAMBDA_EXPR_EXTRA_SCOPE (r)
+ = RECUR (LAMBDA_EXPR_EXTRA_SCOPE (t));
+
+ /* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */
+ determine_visibility (TYPE_NAME (type));
+ /* Now that we know visibility, instantiate the type so we have a
+ declaration of the op() for later calls to lambda_function. */
+ complete_type (type);
+
+ type = tsubst (LAMBDA_EXPR_RETURN_TYPE (t), args, complain, in_decl);
+ if (type)
+ apply_lambda_return_type (r, type);
+
+ return build_lambda_object (r);
+ }
+
default:
/* Handle Objective-C++ constructs, if appropriate. */
{
}
/* Verify that the instantiated ARGS are valid. For type arguments,
- make sure that the type is not variably modified. For non-type arguments,
+ make sure that the type's linkage is ok. For non-type arguments,
make sure they are constants if they are integral or enumerations.
Emit an error under control of COMPLAIN, and return TRUE on error. */
}
else if (TYPE_P (t))
{
- if (variably_modified_type_p (t, NULL_TREE))
+ /* [basic.link]: A name with no linkage (notably, the name
+ of a class or enumeration declared in a local scope)
+ shall not be used to declare an entity with linkage.
+ This implies that names with no linkage cannot be used as
+ template arguments
+
+ DR 757 relaxes this restriction for C++0x. */
+ tree nt = (cxx_dialect > cxx98 ? NULL_TREE
+ : no_linkage_check (t, /*relaxed_p=*/false));
+
+ if (nt)
+ {
+ /* DR 488 makes use of a type with no linkage cause
+ type deduction to fail. */
+ if (complain & tf_error)
+ {
+ if (TYPE_ANONYMOUS_P (nt))
+ error ("%qT is/uses anonymous type", t);
+ else
+ error ("template argument for %qD uses local type %qT",
+ tmpl, t);
+ }
+ return true;
+ }
+ /* In order to avoid all sorts of complications, we do not
+ allow variably-modified types as template arguments. */
+ else if (variably_modified_type_p (t, NULL_TREE))
{
if (complain & tf_error)
error ("%qT is a variably modified type", t);
}
case DEDUCE_EXACT:
- /* There is nothing to do in this case. */
+ /* Core issue #873: Do the DR606 thing (see below) for these cases,
+ too, but here handle it by stripping the reference from PARM
+ rather than by adding it to ARG. */
+ if (TREE_CODE (*parm) == REFERENCE_TYPE
+ && TYPE_REF_IS_RVALUE (*parm)
+ && TREE_CODE (TREE_TYPE (*parm)) == TEMPLATE_TYPE_PARM
+ && cp_type_quals (TREE_TYPE (*parm)) == TYPE_UNQUALIFIED
+ && TREE_CODE (*arg) == REFERENCE_TYPE
+ && !TYPE_REF_IS_RVALUE (*arg))
+ *parm = TREE_TYPE (*parm);
+ /* Nothing else to do in this case. */
return 0;
default:
to explicitly check cxx_dialect here. */
if (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)))
{
- tree arg = tsubst_template_arg
- (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)),
- targs, tf_none, NULL_TREE);
+ tree parm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
+ tree arg = TREE_PURPOSE (TREE_VEC_ELT (tparms, i));
+ arg = tsubst_template_arg (arg, targs, tf_none, NULL_TREE);
+ arg = convert_template_argument (parm, arg, targs, tf_none,
+ i, NULL_TREE);
if (arg == error_mark_node)
return 1;
else
TREE_CONSTANT (arg) = 1;
}
else
- arg = make_node (TYPE_ARGUMENT_PACK);
+ arg = cxx_make_type (TYPE_ARGUMENT_PACK);
SET_ARGUMENT_PACK_ARGS (arg, make_tree_vec (0));
return false;
}
+/* Core DR 115: In contexts where deduction is done and fails, or in
+ contexts where deduction is not done, if a template argument list is
+ specified and it, along with any default template arguments, identifies
+ a single function template specialization, then the template-id is an
+ lvalue for the function template specialization. */
+
+tree
+resolve_nondeduced_context (tree orig_expr)
+{
+ tree expr, offset, baselink;
+ bool addr;
+
+ if (!type_unknown_p (orig_expr))
+ return orig_expr;
+
+ expr = orig_expr;
+ addr = false;
+ offset = NULL_TREE;
+ baselink = NULL_TREE;
+
+ if (TREE_CODE (expr) == ADDR_EXPR)
+ {
+ expr = TREE_OPERAND (expr, 0);
+ addr = true;
+ }
+ if (TREE_CODE (expr) == OFFSET_REF)
+ {
+ offset = expr;
+ expr = TREE_OPERAND (expr, 1);
+ }
+ if (TREE_CODE (expr) == BASELINK)
+ {
+ baselink = expr;
+ expr = BASELINK_FUNCTIONS (expr);
+ }
+
+ if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
+ {
+ int good = 0;
+ tree goodfn = NULL_TREE;
+
+ /* If we got some explicit template args, we need to plug them into
+ the affected templates before we try to unify, in case the
+ explicit args will completely resolve the templates in question. */
+
+ tree expl_subargs = TREE_OPERAND (expr, 1);
+ tree arg = TREE_OPERAND (expr, 0);
+ tree badfn = NULL_TREE;
+ tree badargs = NULL_TREE;
+
+ for (; arg; arg = OVL_NEXT (arg))
+ {
+ tree fn = OVL_CURRENT (arg);
+ tree subargs, elem;
+
+ if (TREE_CODE (fn) != TEMPLATE_DECL)
+ continue;
+
+ ++processing_template_decl;
+ subargs = get_bindings (fn, DECL_TEMPLATE_RESULT (fn),
+ expl_subargs, /*check_ret=*/false);
+ if (subargs && !any_dependent_template_arguments_p (subargs))
+ {
+ elem = instantiate_template (fn, subargs, tf_none);
+ if (elem == error_mark_node)
+ {
+ badfn = fn;
+ badargs = subargs;
+ }
+ else if (elem && (!goodfn || !decls_match (goodfn, elem)))
+ {
+ goodfn = elem;
+ ++good;
+ }
+ }
+ --processing_template_decl;
+ }
+ if (good == 1)
+ {
+ expr = goodfn;
+ if (baselink)
+ expr = build_baselink (BASELINK_BINFO (baselink),
+ BASELINK_ACCESS_BINFO (baselink),
+ expr, BASELINK_OPTYPE (baselink));
+ if (offset)
+ expr = build2 (OFFSET_REF, TREE_TYPE (expr),
+ TREE_OPERAND (offset, 0), expr);
+ if (addr)
+ expr = build_address (expr);
+ return expr;
+ }
+ else if (good == 0 && badargs)
+ /* There were no good options and at least one bad one, so let the
+ user know what the problem is. */
+ instantiate_template (badfn, badargs, tf_warning_or_error);
+ }
+ return orig_expr;
+}
+
/* Subroutine of resolve_overloaded_unification; does deduction for a single
overload. Fills TARGS with any deduced arguments, or error_mark_node if
different overloads deduce different arguments for a given parm.
TREE_CONSTANT (result) = 1;
}
else
- result = make_node (TYPE_ARGUMENT_PACK);
+ result = cxx_make_type (TYPE_ARGUMENT_PACK);
SET_ARGUMENT_PACK_ARGS (result, new_args);
DECL_INTERFACE_KNOWN (result) = 1;
}
+/* Subroutine of more_specialized_fn: check whether TARGS is missing any
+ important template arguments. If any are missing, we check whether
+ they're important by using error_mark_node for substituting into any
+ args that were used for partial ordering (the ones between ARGS and END)
+ and seeing if it bubbles up. */
+
+static bool
+check_undeduced_parms (tree targs, tree args, tree end)
+{
+ bool found = false;
+ int i;
+ for (i = TREE_VEC_LENGTH (targs) - 1; i >= 0; --i)
+ if (TREE_VEC_ELT (targs, i) == NULL_TREE)
+ {
+ found = true;
+ TREE_VEC_ELT (targs, i) = error_mark_node;
+ }
+ if (found)
+ {
+ for (; args != end; args = TREE_CHAIN (args))
+ {
+ tree substed = tsubst (TREE_VALUE (args), targs, tf_none, NULL_TREE);
+ if (substed == error_mark_node)
+ return true;
+ }
+ }
+ return false;
+}
+
/* Given two function templates PAT1 and PAT2, return:
1 if PAT1 is more specialized than PAT2 as described in [temp.func.order].
neither is more cv-qualified, they both are equal). Unlike regular
deduction, after all the arguments have been deduced in this way,
we do *not* verify the deduced template argument values can be
- substituted into non-deduced contexts, nor do we have to verify
- that all template arguments have been deduced. */
+ substituted into non-deduced contexts.
+
+ The logic can be a bit confusing here, because we look at deduce1 and
+ targs1 to see if pat2 is at least as specialized, and vice versa; if we
+ can find template arguments for pat1 to make arg1 look like arg2, that
+ means that arg2 is at least as specialized as arg1. */
int
more_specialized_fn (tree pat1, tree pat2, int len)
tree tparms2 = DECL_INNERMOST_TEMPLATE_PARMS (pat2);
tree args1 = TYPE_ARG_TYPES (TREE_TYPE (decl1));
tree args2 = TYPE_ARG_TYPES (TREE_TYPE (decl2));
- int better1 = 0;
- int better2 = 0;
+ tree origs1, origs2;
+ bool lose1 = false;
+ bool lose2 = false;
/* Remove the this parameter from non-static member functions. If
one is a non-static member function and the other is not a static
processing_template_decl++;
+ origs1 = args1;
+ origs2 = args2;
+
while (len--
/* Stop when an ellipsis is seen. */
&& args1 != NULL_TREE && args2 != NULL_TREE)
deduce2 = !unify (tparms2, targs2, arg2, arg1, UNIFY_ALLOW_NONE);
}
+ /* If we couldn't deduce arguments for tparms1 to make arg1 match
+ arg2, then arg2 is not as specialized as arg1. */
if (!deduce1)
- better2 = -1;
+ lose2 = true;
if (!deduce2)
- better1 = -1;
- if (better1 < 0 && better2 < 0)
- /* We've failed to deduce something in either direction.
- These must be unordered. */
- break;
-
- if (deduce1 && deduce2 && quals1 >= 0 && quals2 >= 0)
+ lose1 = true;
+
+ /* "If, for a given type, deduction succeeds in both directions
+ (i.e., the types are identical after the transformations above)
+ and if the type from the argument template is more cv-qualified
+ 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."
+
+ 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))
{
- /* Deduces in both directions, see if quals can
- disambiguate. Pretend the worse one failed to deduce. */
if ((quals1 & quals2) == quals2)
- deduce1 = 0;
+ lose2 = true;
if ((quals1 & quals2) == quals1)
- deduce2 = 0;
+ lose1 = true;
}
- if (deduce1 && !deduce2 && !better2)
- better2 = 1;
- if (deduce2 && !deduce1 && !better1)
- better1 = 1;
+
+ if (lose1 && lose2)
+ /* We've failed to deduce something in either direction.
+ These must be unordered. */
+ break;
if (TREE_CODE (arg1) == TYPE_PACK_EXPANSION
|| TREE_CODE (arg2) == TYPE_PACK_EXPANSION)
args2 = TREE_CHAIN (args2);
}
+ /* "In most cases, all template parameters must have values in order for
+ deduction to succeed, but for partial ordering purposes a template
+ parameter may remain without a value provided it is not used in the
+ types being used for partial ordering."
+
+ Thus, if we are missing any of the targs1 we need to substitute into
+ origs1, then pat2 is not as specialized as pat1. This can happen when
+ there is a nondeduced context. */
+ if (!lose2 && check_undeduced_parms (targs1, origs1, args1))
+ lose2 = true;
+ if (!lose1 && check_undeduced_parms (targs2, origs2, args2))
+ lose1 = true;
+
processing_template_decl--;
/* All things being equal, if the next argument is a pack expansion
for one function but not for the other, prefer the
- non-variadic function. */
- if ((better1 > 0) - (better2 > 0) == 0
+ non-variadic function. FIXME this is bogus; see c++/41958. */
+ if (lose1 == lose2
&& args1 && TREE_VALUE (args1)
&& args2 && TREE_VALUE (args2))
{
- if (TREE_CODE (TREE_VALUE (args1)) == TYPE_PACK_EXPANSION)
- return TREE_CODE (TREE_VALUE (args2)) == TYPE_PACK_EXPANSION ? 0 : -1;
- else if (TREE_CODE (TREE_VALUE (args2)) == TYPE_PACK_EXPANSION)
- return 1;
+ lose1 = TREE_CODE (TREE_VALUE (args1)) == TYPE_PACK_EXPANSION;
+ lose2 = TREE_CODE (TREE_VALUE (args2)) == TYPE_PACK_EXPANSION;
}
- return (better1 > 0) - (better2 > 0);
+ if (lose1 == lose2)
+ return 0;
+ else if (!lose1)
+ return 1;
+ else
+ return -1;
}
/* Determine which of two partial specializations is more specialized.
SET_DECL_IMPLICIT_INSTANTIATION (d);
}
- if (!defer_ok)
+ /* Recheck the substitutions to obtain any warning messages
+ about ignoring cv qualifiers. Don't do this for artificial decls,
+ as it breaks the context-sensitive substitution for lambda op(). */
+ if (!defer_ok && !DECL_ARTIFICIAL (d))
{
- /* Recheck the substitutions to obtain any warning messages
- about ignoring cv qualifiers. */
tree gen = DECL_TEMPLATE_RESULT (gen_tmpl);
tree type = TREE_TYPE (gen);
to look inside it. */
if (only_current_p && !currently_open_class (scope))
return type;
+ /* If this is a typedef, we don't want to look inside (c++/11987). */
+ if (typedef_variant_p (type))
+ return type;
/* If SCOPE isn't the template itself, it will not have a valid
TYPE_FIELDS list. */
if (same_type_p (scope, CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope)))
tree
make_auto (void)
{
- tree au;
-
- /* ??? Is it worth caching this for multiple autos at the same level? */
- au = cxx_make_type (TEMPLATE_TYPE_PARM);
+ tree au = cxx_make_type (TEMPLATE_TYPE_PARM);
TYPE_NAME (au) = build_decl (BUILTINS_LOCATION,
TYPE_DECL, get_identifier ("auto"), au);
TYPE_STUB_DECL (au) = TYPE_NAME (au);
return error_mark_node;
}
+ /* If the list of declarators contains more than one declarator, the type
+ of each declared variable is determined as described above. If the
+ type deduced for the template parameter U is not the same in each
+ deduction, the program is ill-formed. */
+ if (TREE_TYPE (auto_node)
+ && !same_type_p (TREE_TYPE (auto_node), TREE_VEC_ELT (targs, 0)))
+ {
+ error ("inconsistent deduction for %qT: %qT and then %qT",
+ auto_node, TREE_TYPE (auto_node), TREE_VEC_ELT (targs, 0));
+ return error_mark_node;
+ }
+ TREE_TYPE (auto_node) = TREE_VEC_ELT (targs, 0);
+
if (processing_template_decl)
targs = add_to_template_args (current_template_args (), targs);
return tsubst (type, targs, tf_warning_or_error, NULL_TREE);