#include "tm.h"
#include "obstack.h"
#include "tree.h"
+#include "intl.h"
#include "pointer-set.h"
#include "flags.h"
#include "c-common.h"
static tree tsubst_pack_expansion (tree, tree, tsubst_flags_t, tree);
static tree tsubst_decl (tree, tree, tsubst_flags_t);
static void perform_typedefs_access_check (tree tmpl, tree targs);
-static void append_type_to_template_for_access_check_1 (tree, tree, tree);
+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 bool primary_template_instantiation_p (const_tree);
static tree listify (tree);
static tree listify_autos (tree, tree);
return error_mark_node;
}
+/* Create a template info node. */
+
+tree
+build_template_info (tree template_decl, tree template_args)
+{
+ tree result = make_node (TEMPLATE_INFO);
+ TI_TEMPLATE (result) = template_decl;
+ TI_ARGS (result) = template_args;
+ return result;
+}
+
/* Return the template info node corresponding to T, whatever T is. */
tree
function, member class or static data member of a class template
shall be declared in the namespace of which the class template is
a member. */
+ if (current_scope() != DECL_CONTEXT (tmpl)
+ && !at_namespace_scope_p ())
+ {
+ error ("specialization of %qD must appear at namespace scope", tmpl);
+ return false;
+ }
if (is_associated_namespace (current_namespace, tpl_ns))
/* Same or super-using namespace. */
return true;
if (!TYPE_P (arg))
STRIP_NOPS (arg);
+ if (TREE_CODE (arg) == ARGUMENT_PACK_SELECT)
+ /* We can get one of these when re-hashing a previous entry in the middle
+ of substituting into a pack expansion. Just look through it. */
+ arg = ARGUMENT_PACK_SELECT_FROM_PACK (arg);
+
code = TREE_CODE (arg);
tclass = TREE_CODE_CLASS (code);
case EXPR_PACK_EXPANSION:
return iterative_hash_template_arg (PACK_EXPANSION_PATTERN (arg), val);
- case ARGUMENT_PACK_SELECT:
- /* We can get one of these when re-hashing a previous entry in the middle
- of substituting into a pack expansion. Just look through it... */
- arg = ARGUMENT_PACK_SELECT_FROM_PACK (arg);
- /* ...and fall through. */
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
return iterative_hash_template_arg (ARGUMENT_PACK_ARGS (arg), val);
}
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:
val = iterative_hash_object (code, val);
return iterative_hash_template_arg (TREE_OPERAND (arg, 2), val);
+ case ARRAY_TYPE:
+ /* layout_type sets structural equality for arrays of
+ incomplete type, so we can't rely on the canonical type
+ for hashing. */
+ val = iterative_hash_template_arg (TREE_TYPE (arg), val);
+ return iterative_hash_template_arg (TYPE_DOMAIN (arg), val);
+
default:
switch (tclass)
{
return !uses_template_parms (CLASSTYPE_TI_ARGS (type));
}
-/* Print the list of candidate FNS in an error message. */
+/* Print the list of functions at FNS, going through all the overloads
+ for each element of the list. Alternatively, FNS can not be a
+ TREE_LIST, in which case it will be printed together with all the
+ overloads.
-void
-print_candidates (tree fns)
+ MORE and *STR should respectively be FALSE and NULL when the function
+ is called from the outside. They are used internally on recursive
+ calls. print_candidates manages the two parameters and leaves NULL
+ in *STR when it ends. */
+
+static void
+print_candidates_1 (tree fns, bool more, const char **str)
{
- tree fn;
+ tree fn, fn2;
+ char *spaces = NULL;
- const char *str = "candidates are:";
+ for (fn = fns; fn; fn = OVL_NEXT (fn))
+ if (TREE_CODE (fn) == TREE_LIST)
+ {
+ gcc_assert (!OVL_NEXT (fn) && !is_overloaded_fn (fn));
+ for (fn2 = fn; fn2 != NULL_TREE; fn2 = TREE_CHAIN (fn2))
+ print_candidates_1 (TREE_VALUE (fn2),
+ TREE_CHAIN (fn2) || more, str);
+ }
+ else
+ {
+ if (!*str)
+ {
+ /* Pick the prefix string. */
+ if (!more && !OVL_NEXT (fns))
+ {
+ error ("candidate is: %+#D", OVL_CURRENT (fn));
+ continue;
+ }
- for (fn = fns; fn != NULL_TREE; fn = TREE_CHAIN (fn))
- {
- tree f;
+ *str = _("candidates are:");
+ spaces = get_spaces (*str);
+ }
+ error ("%s %+#D", *str, OVL_CURRENT (fn));
+ *str = spaces ? spaces : *str;
+ }
- for (f = TREE_VALUE (fn); f; f = OVL_NEXT (f))
- error ("%s %+#D", str, OVL_CURRENT (f));
- str = " ";
+ if (!more)
+ {
+ free (spaces);
+ *str = NULL;
}
}
+/* Print the list of candidate FNS in an error message. */
+
+void
+print_candidates (tree fns)
+{
+ const char *str = NULL;
+ print_candidates_1 (fns, false, &str);
+ gcc_assert (str == NULL);
+}
+
/* Returns the template (one of the functions given by TEMPLATE_ID)
which can be specialized to match the indicated DECL with the
explicit template args given in TEMPLATE_ID. The DECL may be
{
error ("template-id %qD for %q+D does not match any template "
"declaration", template_id, decl);
+ if (header_count && header_count != template_count + 1)
+ inform (input_location, "saw %d %<template<>%>, need %d for "
+ "specializing a member function template",
+ header_count, template_count + 1);
return error_mark_node;
}
else if ((templates && TREE_CHAIN (templates))
{
error ("ambiguous template specialization %qD for %q+D",
template_id, decl);
- chainon (candidates, templates);
+ candidates = chainon (candidates, templates);
print_candidates (candidates);
return error_mark_node;
}
}
/* Set up the DECL_TEMPLATE_INFO for DECL. */
- DECL_TEMPLATE_INFO (decl) = tree_cons (tmpl, targs, NULL_TREE);
+ DECL_TEMPLATE_INFO (decl) = build_template_info (tmpl, targs);
/* Inherit default function arguments from the template
DECL is specializing. */
bool
function_parameter_expanded_from_pack_p (tree param_decl, tree pack)
{
- if (DECL_ARTIFICIAL (param_decl)
- || !function_parameter_pack_p (pack))
- return false;
-
- gcc_assert (DECL_NAME (param_decl) && DECL_NAME (pack));
+ if (DECL_ARTIFICIAL (param_decl)
+ || !function_parameter_pack_p (pack))
+ return false;
- /* The parameter pack and its pack arguments have the same
- DECL_PARM_INDEX. */
- return DECL_PARM_INDEX (pack) == DECL_PARM_INDEX (param_decl);
+ /* The parameter pack and its pack arguments have the same
+ DECL_PARM_INDEX. */
+ return DECL_PARM_INDEX (pack) == DECL_PARM_INDEX (param_decl);
}
/* Determine whether ARGS describes a variadic template args list,
/* Return true if T is a primary function
or class template instantiation. */
-static bool
+bool
primary_template_instantiation_p (const_tree t)
{
if (!t)
case UNION_TYPE:
case ENUMERAL_TYPE:
if (TYPE_TEMPLATE_INFO (t))
- cp_walk_tree (&TREE_VALUE (TYPE_TEMPLATE_INFO (t)),
+ cp_walk_tree (&TI_ARGS (TYPE_TEMPLATE_INFO (t)),
&find_parameter_packs_r, ppd, ppd->visited);
*walk_subtrees = 0;
for (in_arg = 0; in_arg < nargs; ++in_arg)
{
tree arg = TREE_VEC_ELT (args, in_arg);
+ if (arg == NULL_TREE)
+ return args;
if (ARGUMENT_PACK_P (arg))
{
int num_packed = TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg));
{
if (TEMPLATE_PARM_DESCENDANTS (index) == NULL_TREE
|| (TEMPLATE_PARM_LEVEL (TEMPLATE_PARM_DESCENDANTS (index))
- != TEMPLATE_PARM_LEVEL (index) - levels))
+ != TEMPLATE_PARM_LEVEL (index) - levels)
+ || !same_type_p (type, TREE_TYPE (TEMPLATE_PARM_DESCENDANTS (index))))
{
tree orig_decl = TEMPLATE_PARM_DECL (index);
tree decl, t;
|| (!packed_args && i < nargs - 1))
{
if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
- error ("parameter pack argument %qE must be at the end of the template argument list", arg);
+ error ("parameter pack argument %qE must be at the "
+ "end of the template argument list", arg);
else
- error ("parameter pack argument %qT must be at the end of the template argument list", arg);
-
- if (packed_args)
- TREE_VEC_ELT (packed_args, j) = error_mark_node;
+ error ("parameter pack argument %qT must be at the "
+ "end of the template argument list", arg);
}
}
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
DECL_TI_TEMPLATE (decl) = new_tmpl;
SET_DECL_TEMPLATE_SPECIALIZATION (new_tmpl);
DECL_TEMPLATE_INFO (new_tmpl)
- = tree_cons (tmpl, args, NULL_TREE);
+ = build_template_info (tmpl, args);
register_specialization (new_tmpl,
most_general_template (tmpl),
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
if (TREE_CODE (parm) == TEMPLATE_DECL)
DECL_CONTEXT (parm) = tmpl;
+
+ if (TREE_CODE (TREE_TYPE (parm)) == TEMPLATE_TYPE_PARM)
+ DECL_CONTEXT (TYPE_NAME (TREE_TYPE (parm))) = tmpl;
}
}
if (DECL_TEMPLATE_INFO (tmpl))
args = add_outermost_template_args (DECL_TI_ARGS (tmpl), args);
- info = tree_cons (tmpl, args, NULL_TREE);
+ info = build_template_info (tmpl, args);
if (DECL_IMPLICIT_TYPEDEF_P (decl))
SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
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 (arg) == TYPE_PACK_EXPANSION)
arg = PACK_EXPANSION_PATTERN (arg);
+ /* Deal with an injected-class-name used as a template template arg. */
+ if (requires_tmpl_type && CLASS_TYPE_P (arg))
+ {
+ tree t = maybe_get_template_decl_from_type_decl (TYPE_NAME (arg));
+ if (TREE_CODE (t) == TEMPLATE_DECL)
+ {
+ if (complain & tf_warning_or_error)
+ pedwarn (input_location, OPT_pedantic, "injected-class-name %qD"
+ " used as template template argument", TYPE_NAME (arg));
+ else if (flag_pedantic_errors)
+ t = arg;
+
+ arg = t;
+ }
+ }
+
is_tmpl_type =
((TREE_CODE (arg) == TEMPLATE_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
complain, in_decl,
args))
{
- val = orig_arg;
+ val = arg;
/* TEMPLATE_TEMPLATE_PARM node is preferred over
TEMPLATE_DECL. */
{
if (DECL_TEMPLATE_TEMPLATE_PARM_P (val))
val = TREE_TYPE (val);
- else if (TREE_CODE (val) == TYPE_PACK_EXPANSION
- && DECL_TEMPLATE_TEMPLATE_PARM_P (arg))
- {
- val = TREE_TYPE (arg);
- val = make_pack_expansion (val);
- }
+ if (TREE_CODE (orig_arg) == TYPE_PACK_EXPANSION)
+ val = make_pack_expansion (val);
}
}
else
error ("type/value mismatch at argument %d in "
"template parameter list for %qD",
i + 1, in_decl);
- error (" expected a template of type %qD, got %qD",
+ error (" expected a template of type %qD, got %qT",
parm, orig_arg);
}
val = error_mark_node;
else if (val == error_mark_node && (complain & tf_error))
error ("could not convert template argument %qE to %qT", orig_arg, t);
+
+ if (TREE_CODE (val) == SCOPE_REF)
+ {
+ /* Strip typedefs from the SCOPE_REF. */
+ tree type = strip_typedefs (TREE_TYPE (val));
+ tree scope = strip_typedefs (TREE_OPERAND (val, 0));
+ val = build_qualified_name (type, scope, TREE_OPERAND (val, 1),
+ QUALIFIED_NAME_IS_TEMPLATE (val));
+ }
}
return val;
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))
TEMPLATE_DECL. If DECL is a TYPE_DECL for current_class_type,
or one of its enclosing classes, and that type is a template,
return the associated TEMPLATE_DECL. Otherwise, the original
- DECL is returned. */
+ DECL is returned.
+
+ Also handle the case when DECL is a TREE_LIST of ambiguous
+ injected-class-names from different bases. */
tree
maybe_get_template_decl_from_type_decl (tree decl)
{
+ if (decl == NULL_TREE)
+ return decl;
+
+ /* DR 176: A lookup that finds an injected-class-name (10.2
+ [class.member.lookup]) can result in an ambiguity in certain cases
+ (for example, if it is found in more than one base class). If all of
+ the injected-class-names that are found refer to specializations of
+ the same class template, and if the name is followed by a
+ template-argument-list, the reference refers to the class template
+ itself and not a specialization thereof, and is not ambiguous. */
+ if (TREE_CODE (decl) == TREE_LIST)
+ {
+ tree t, tmpl = NULL_TREE;
+ for (t = decl; t; t = TREE_CHAIN (t))
+ {
+ tree elt = maybe_get_template_decl_from_type_decl (TREE_VALUE (t));
+ if (!tmpl)
+ tmpl = elt;
+ else if (tmpl != elt)
+ break;
+ }
+ if (tmpl && t == NULL_TREE)
+ return tmpl;
+ else
+ return decl;
+ }
+
return (decl != NULL_TREE
- && TREE_CODE (decl) == TYPE_DECL
- && DECL_ARTIFICIAL (decl)
- && CLASS_TYPE_P (TREE_TYPE (decl))
+ && DECL_SELF_REFERENCE_P (decl)
&& CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl)))
? CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)) : decl;
}
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));
}
found = CLASSTYPE_TI_TEMPLATE (found);
}
- SET_TYPE_TEMPLATE_INFO (t, tree_cons (found, arglist, NULL_TREE));
+ SET_TYPE_TEMPLATE_INFO (t, build_template_info (found, arglist));
elt.spec = t;
slot = (spec_entry **) htab_find_slot_with_hash (type_specializations,
case ENUMERAL_TYPE:
if (!TYPE_TEMPLATE_INFO (t))
*walk_subtrees = 0;
- else if (for_each_template_parm (TREE_VALUE (TYPE_TEMPLATE_INFO (t)),
+ else if (for_each_template_parm (TI_ARGS (TYPE_TEMPLATE_INFO (t)),
fn, data, pfd->visited,
pfd->include_nondeduced_p))
return error_mark_node;
static void
perform_typedefs_access_check (tree tmpl, tree targs)
{
- tree t;
+ location_t saved_location;
+ int i;
+ qualified_typedef_usage_t *iter;
if (!tmpl
|| (!CLASS_TYPE_P (tmpl)
&& TREE_CODE (tmpl) != FUNCTION_DECL))
return;
- for (t = get_types_needing_access_check (tmpl); t; t = TREE_CHAIN (t))
+ saved_location = input_location;
+ for (i = 0;
+ VEC_iterate (qualified_typedef_usage_t,
+ get_types_needing_access_check (tmpl),
+ i, iter);
+ ++i)
{
- tree type_decl = TREE_PURPOSE (t);
- tree type_scope = TREE_VALUE (t);
+ tree type_decl = iter->typedef_decl;
+ tree type_scope = iter->context;
if (!type_decl || !type_scope || !CLASS_TYPE_P (type_scope))
continue;
if (uses_template_parms (type_scope))
type_scope = tsubst (type_scope, targs, tf_error, NULL_TREE);
+ /* Make access check error messages point to the location
+ of the use of the typedef. */
+ input_location = iter->locus;
perform_or_defer_access_check (TYPE_BINFO (type_scope),
type_decl, type_decl);
}
+ input_location = saved_location;
}
tree
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 pattern;
tree pack, packs = NULL_TREE, unsubstituted_packs = NULL_TREE;
- tree first_arg_pack; int i, len = -1;
+ int i, len = -1;
tree result;
int incomplete = 0;
bool very_local_specializations = false;
incomplete = 1;
if (len < 0)
- {
- len = my_len;
- first_arg_pack = arg_pack;
- }
+ len = my_len;
else if (len != my_len)
{
if (incomplete)
gcc_assert (DECL_LANG_SPECIFIC (r) != 0);
TREE_CHAIN (r) = NULL_TREE;
- DECL_TEMPLATE_INFO (r) = build_tree_list (t, args);
+ DECL_TEMPLATE_INFO (r) = build_template_info (t, args);
if (TREE_CODE (decl) == TYPE_DECL)
{
if (gen_tmpl)
{
DECL_TEMPLATE_INFO (r)
- = tree_cons (gen_tmpl, argvec, NULL_TREE);
+ = build_template_info (gen_tmpl, argvec);
SET_DECL_IMPLICIT_INSTANTIATION (r);
register_specialization (r, gen_tmpl, argvec, false, hash);
= 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);
/* Create a new node for the specialization we need. */
r = copy_decl (t);
if (type == NULL_TREE)
- type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ {
+ if (is_typedef_decl (t))
+ type = DECL_ORIGINAL_TYPE (t);
+ else
+ type = TREE_TYPE (t);
+ type = tsubst (type, args, complain, in_decl);
+ }
if (TREE_CODE (r) == VAR_DECL)
{
/* Even if the original location is out of scope, the
}
determine_visibility (r);
}
- /* Preserve a typedef that names a type. */
- else if (TREE_CODE (r) == TYPE_DECL
- && DECL_ORIGINAL_TYPE (t)
- && type != error_mark_node)
- {
- DECL_ORIGINAL_TYPE (r) = tsubst (DECL_ORIGINAL_TYPE (t),
- args, complain, in_decl);
- TREE_TYPE (r) = type = build_variant_type_copy (type);
- TYPE_NAME (type) = r;
- }
if (!local_p)
{
DECL_EXTERNAL (r) = 1;
register_specialization (r, gen_tmpl, argvec, false, hash);
- DECL_TEMPLATE_INFO (r) = tree_cons (tmpl, argvec, NULL_TREE);
+ DECL_TEMPLATE_INFO (r) = build_template_info (tmpl, argvec);
SET_DECL_IMPLICIT_INSTANTIATION (r);
}
else if (cp_unevaluated_operand)
apply_late_template_attributes (&r, DECL_ATTRIBUTES (r),
(int) ATTR_FLAG_TYPE_IN_PLACE,
args, complain, in_decl);
+
+ /* Preserve a typedef that names a type. */
+ if (is_typedef_decl (r))
+ {
+ DECL_ORIGINAL_TYPE (r) = NULL_TREE;
+ set_underlying_type (r);
+ }
+
layout_decl (r, 0);
}
break;
return error_mark_node;
TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (r)
- = tree_cons (TYPE_TI_TEMPLATE (t), argvec, NULL_TREE);
+ = build_template_info (TYPE_TI_TEMPLATE (t), argvec);
}
}
break;
{
if (TREE_CODE (type) == VOID_TYPE)
error ("forming reference to void");
- else
- error ("forming %s to reference type %qT",
- (code == POINTER_TYPE) ? "pointer" : "reference",
- type);
+ else if (code == POINTER_TYPE)
+ error ("forming pointer to reference type %qT", type);
+ else
+ error ("forming reference to reference type %qT", type);
last_loc = input_location;
}
{
/* 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),
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;
r = convert_from_reference (r);
}
else
- r = build_x_indirect_ref (r, "unary *", complain);
+ r = build_x_indirect_ref (r, RO_UNARY_STAR, complain);
return r;
}
stmt_expr = finish_stmt_expr (stmt_expr, false);
cur_stmt_expr = old_stmt_expr;
+ /* If the resulting list of expression statement is empty,
+ fold it further into void_zero_node. */
+ if (empty_expr_stmt_p (stmt_expr))
+ stmt_expr = void_zero_node;
+
return stmt_expr;
}
}
/* 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);
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
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.
if (ambiguous_p)
{
- const char *str = "candidates are:";
+ const char *str;
+ char *spaces = NULL;
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))
- {
- error ("%s %+#T", str, TREE_TYPE (t));
- str = " ";
- }
+ {
+ error ("%s %+#T", spaces ? spaces : str, TREE_TYPE (t));
+ spaces = spaces ? spaces : get_spaces (str);
+ }
+ free (spaces);
return error_mark_node;
}
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);
return NULL_TREE;
}
-/* For a given template T, return the list of typedefs referenced
+/* For a given template T, return the vector of typedefs referenced
in T for which access check is needed at T instantiation time.
T is either a FUNCTION_DECL or a RECORD_TYPE.
Those typedefs were added to T by the function
append_type_to_template_for_access_check. */
-tree
+VEC(qualified_typedef_usage_t,gc)*
get_types_needing_access_check (tree t)
{
- tree ti, result = NULL_TREE;
+ tree ti;
+ VEC(qualified_typedef_usage_t,gc) *result = NULL;
if (!t || t == error_mark_node)
- return t;
+ return NULL;
if (!(ti = get_template_info (t)))
- return NULL_TREE;
+ return NULL;
if (CLASS_TYPE_P (t)
|| TREE_CODE (t) == FUNCTION_DECL)
{
if (!TI_TEMPLATE (ti))
- return NULL_TREE;
+ return NULL;
result = TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti);
}
T is either a FUNCTION_DECL or a RECORD_TYPE.
TYPE_DECL is a TYPE_DECL node representing a typedef.
SCOPE is the scope through which TYPE_DECL is accessed.
+ LOCATION is the location of the usage point of TYPE_DECL.
This function is a subroutine of
append_type_to_template_for_access_check. */
static void
append_type_to_template_for_access_check_1 (tree t,
tree type_decl,
- tree scope)
+ tree scope,
+ location_t location)
{
+ qualified_typedef_usage_t typedef_usage;
tree ti;
if (!t || t == error_mark_node)
gcc_assert (TI_TEMPLATE (ti));
- TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti) =
- tree_cons (type_decl, scope, TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti));
+ typedef_usage.typedef_decl = type_decl;
+ typedef_usage.context = scope;
+ typedef_usage.locus = location;
+
+ VEC_safe_push (qualified_typedef_usage_t, gc,
+ TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti),
+ &typedef_usage);
}
/* Append TYPE_DECL to the template TEMPL.
TEMPL is either a class type, a FUNCTION_DECL or a a TEMPLATE_DECL.
At TEMPL instanciation time, TYPE_DECL will be checked to see
if it can be accessed through SCOPE.
+ LOCATION is the location of the usage point of TYPE_DECL.
e.g. consider the following code snippet:
template<class U> struct S
{
- C::myint mi;
+ C::myint mi; // <-- usage point of the typedef C::myint
};
S<char> s;
void
append_type_to_template_for_access_check (tree templ,
tree type_decl,
- tree scope)
+ tree scope,
+ location_t location)
{
- tree node;
+ qualified_typedef_usage_t *iter;
+ int i;
gcc_assert (type_decl && (TREE_CODE (type_decl) == TYPE_DECL));
/* Make sure we don't append the type to the template twice. */
- for (node = get_types_needing_access_check (templ);
- node;
- node = TREE_CHAIN (node))
- {
- tree decl = TREE_PURPOSE (node);
- tree type_scope = TREE_VALUE (node);
-
- if (decl == type_decl && type_scope == scope)
- return;
- }
+ for (i = 0;
+ VEC_iterate (qualified_typedef_usage_t,
+ get_types_needing_access_check (templ),
+ i, iter);
+ ++i)
+ if (iter->typedef_decl == type_decl && scope == iter->context)
+ return;
- append_type_to_template_for_access_check_1 (templ, type_decl, scope);
+ append_type_to_template_for_access_check_1 (templ, type_decl,
+ scope, location);
}
/* Set up the hash tables for template instantiations. */