#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 tree listify (tree);
+static tree listify_autos (tree, tree);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
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
-get_template_info (tree t)
+get_template_info (const_tree t)
{
tree tinfo = NULL_TREE;
+ if (!t || t == error_mark_node)
+ return NULL;
+
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))
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 (DECL_TEMPLATE_INSTANTIATION (fn))
{
- if (TREE_USED (fn)
+ if (DECL_ODR_USED (fn)
|| DECL_EXPLICIT_INSTANTIATION (fn))
{
error ("specialization of %qD after instantiation",
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;
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. */
}
/* Determine whether PARM is a parameter pack. */
+
bool
template_parameter_pack_p (const_tree parm)
{
&& TEMPLATE_TYPE_PARAMETER_PACK (parm));
}
+/* Determine if T is a function parameter pack. */
+
+bool
+function_parameter_pack_p (const_tree t)
+{
+ if (t && TREE_CODE (t) == PARM_DECL)
+ return FUNCTION_PARAMETER_PACK_P (t);
+ return false;
+}
+
+/* Return the function template declaration of PRIMARY_FUNC_TMPL_INST.
+ PRIMARY_FUNC_TMPL_INST is a primary function template instantiation. */
+
+tree
+get_function_template_decl (const_tree primary_func_tmpl_inst)
+{
+ if (! primary_func_tmpl_inst
+ || TREE_CODE (primary_func_tmpl_inst) != FUNCTION_DECL
+ || ! primary_template_instantiation_p (primary_func_tmpl_inst))
+ return NULL;
+
+ return DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (primary_func_tmpl_inst));
+}
+
+/* Return true iff the function parameter PARAM_DECL was expanded
+ from the function parameter pack PACK. */
+
+bool
+function_parameter_expanded_from_pack_p (tree param_decl, tree 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);
+}
+
/* Determine whether ARGS describes a variadic template args list,
i.e., one that is terminated by a template argument pack. */
+
static bool
template_args_variadic_p (tree args)
{
/* Generate a new name for the parameter pack name NAME (an
IDENTIFIER_NODE) that incorporates its */
+
static tree
make_ith_pack_parameter_name (tree name, int i)
{
/* Munge the name to include the parameter index. */
- char numbuf[128];
+#define NUMBUF_LEN 128
+ char numbuf[NUMBUF_LEN];
char* newname;
-
- sprintf(numbuf, "%i", i);
- newname = (char*)alloca (IDENTIFIER_LENGTH (name) + strlen(numbuf) + 2);
- sprintf(newname, "%s#%i", IDENTIFIER_POINTER (name), i);
+ int newname_len;
+
+ snprintf (numbuf, NUMBUF_LEN, "%i", i);
+ newname_len = IDENTIFIER_LENGTH (name)
+ + strlen (numbuf) + 2;
+ newname = (char*)alloca (newname_len);
+ snprintf (newname, newname_len,
+ "%s#%i", IDENTIFIER_POINTER (name), i);
return get_identifier (newname);
}
+/* Return true if T is a primary function
+ or class template instantiation. */
+
+bool
+primary_template_instantiation_p (const_tree t)
+{
+ if (!t)
+ return false;
+
+ if (TREE_CODE (t) == FUNCTION_DECL)
+ return DECL_LANG_SPECIFIC (t)
+ && DECL_TEMPLATE_INSTANTIATION (t)
+ && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t));
+ else if (CLASS_TYPE_P (t))
+ return CLASSTYPE_TEMPLATE_INSTANTIATION (t)
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t));
+ return false;
+}
+
+/* Return true if PARM is a template template parameter. */
+
+bool
+template_template_parameter_p (const_tree parm)
+{
+ return DECL_TEMPLATE_TEMPLATE_PARM_P (parm);
+}
+
+/* Return the template parameters of T if T is a
+ primary template instantiation, NULL otherwise. */
+
+tree
+get_primary_template_innermost_parameters (const_tree t)
+{
+ tree parms = NULL, template_info = NULL;
+
+ if ((template_info = get_template_info (t))
+ && primary_template_instantiation_p (t))
+ parms = INNERMOST_TEMPLATE_PARMS
+ (DECL_TEMPLATE_PARMS (TI_TEMPLATE (template_info)));
+
+ return parms;
+}
+
+/* Returns the template arguments of T if T is a template instantiation,
+ NULL otherwise. */
+
+tree
+get_template_innermost_arguments (const_tree t)
+{
+ tree args = NULL, template_info = NULL;
+
+ if ((template_info = get_template_info (t))
+ && TI_ARGS (template_info))
+ args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (template_info));
+
+ return args;
+}
+
+/* Return the argument pack elements of T if T is a template argument pack,
+ NULL otherwise. */
+
+tree
+get_template_argument_pack_elems (const_tree t)
+{
+ if (TREE_CODE (t) != TYPE_ARGUMENT_PACK
+ && TREE_CODE (t) != NONTYPE_ARGUMENT_PACK)
+ return NULL;
+
+ return ARGUMENT_PACK_ARGS (t);
+}
+
/* Structure used to track the progress of find_parameter_packs_r. */
struct find_parameter_pack_data
{
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;
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)
{
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;
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);
}
}
|| (!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;
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))
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;
}
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));
}
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
- || (!RECORD_OR_UNION_CODE_P (TREE_CODE (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 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. */
{
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)
+ /* 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%>",
return result;
}
+/* Given PARM_DECL PARM, find the corresponding PARM_DECL in the template
+ TMPL. We do this using DECL_PARM_INDEX, which should work even with
+ parameter packs; all parms generated from a function parameter pack will
+ have the same DECL_PARM_INDEX. */
+
+tree
+get_pattern_parm (tree parm, tree tmpl)
+{
+ tree pattern = DECL_TEMPLATE_RESULT (tmpl);
+ tree patparm;
+
+ if (DECL_ARTIFICIAL (parm))
+ {
+ for (patparm = DECL_ARGUMENTS (pattern);
+ patparm; patparm = TREE_CHAIN (patparm))
+ if (DECL_ARTIFICIAL (patparm)
+ && DECL_NAME (parm) == DECL_NAME (patparm))
+ break;
+ }
+ else
+ {
+ patparm = FUNCTION_FIRST_USER_PARM (DECL_TEMPLATE_RESULT (tmpl));
+ patparm = chain_index (DECL_PARM_INDEX (parm)-1, patparm);
+ gcc_assert (DECL_PARM_INDEX (patparm)
+ == DECL_PARM_INDEX (parm));
+ }
+
+ return patparm;
+}
+
/* Substitute ARGS into the vector or list of template arguments T. */
static tree
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,
cp_function_chain->x_current_class_ref = saved_class_ref;
}
- pop_access_scope (fn);
-
/* Make sure the default argument is reasonable. */
arg = check_default_argument (type, arg);
+ pop_access_scope (fn);
+
return 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);
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)
{
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 (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);
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
{
if (DECL_TEMPLATE_PARM_P (t))
SET_DECL_TEMPLATE_PARM_P (r);
+ /* An argument of a function parameter pack is not a parameter
+ pack. */
+ FUNCTION_PARAMETER_PACK_P (r) = false;
+
if (expanded_types)
/* We're on the Ith parameter of the function parameter
pack. */
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;
}
/* 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
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)
}
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)
+ {
+ /* 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);
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;
default:
gcc_unreachable ();
}
+#undef RETURN
+ out:
/* Restore the file and line information. */
input_location = saved_loc;
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);
if (e1 == error_mark_node || e2 == error_mark_node)
return error_mark_node;
- return fold_build2 (TREE_CODE (t), TREE_TYPE (t), e1, e2);
+ return fold_build2_loc (input_location,
+ TREE_CODE (t), TREE_TYPE (t), e1, e2);
}
case NEGATE_EXPR:
if (e == error_mark_node)
return error_mark_node;
- return fold_build1 (TREE_CODE (t), TREE_TYPE (t), e);
+ return fold_build1_loc (input_location, TREE_CODE (t), TREE_TYPE (t), e);
}
case TYPENAME_TYPE:
But, such constructs have already been resolved by this
point, so here CTX really should have complete type, unless
it's a partial instantiation. */
- ctx = complete_type (ctx);
+ if (!(complain & tf_no_class_instantiations))
+ ctx = complete_type (ctx);
if (!COMPLETE_TYPE_P (ctx))
{
if (complain & tf_error)
{
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;
if (purpose)
purpose = RECUR (purpose);
value = TREE_VALUE (t);
- if (value)
+ if (value && TREE_CODE (value) != LABEL_DECL)
value = RECUR (value);
chain = TREE_CHAIN (t);
if (chain && chain != void_type_node)
RECUR (ASM_STRING (t)),
tsubst_copy_asm_operands (ASM_OUTPUTS (t), args, complain, in_decl),
tsubst_copy_asm_operands (ASM_INPUTS (t), args, complain, in_decl),
- tsubst_copy_asm_operands (ASM_CLOBBERS (t), args, complain, in_decl));
+ tsubst_copy_asm_operands (ASM_CLOBBERS (t), args, complain, in_decl),
+ tsubst_copy_asm_operands (ASM_LABELS (t), args, complain, in_decl));
{
tree asm_expr = tmp;
if (TREE_CODE (asm_expr) == CLEANUP_POINT_EXPR)
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;
}
}
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. */
{
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. */
- tree nt = no_linkage_check (t, /*relaxed_p=*/false);
+ 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)
{
}
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 (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);
{
tree elt, elttype;
unsigned i;
+ tree orig_parm = parm;
+
+ /* Replace T with std::initializer_list<T> for deduction. */
+ if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM
+ && flag_deduce_init_list)
+ parm = listify (parm);
if (!is_std_init_list (parm))
/* We can only deduce from an initializer list argument if the
if (unify (tparms, targs, elttype, elt, elt_strict))
return 1;
}
+
+ /* If the std::initializer_list<T> deduction worked, replace the
+ deduced A with std::initializer_list<A>. */
+ if (orig_parm != parm)
+ {
+ idx = TEMPLATE_TYPE_IDX (orig_parm);
+ targ = TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx);
+ targ = listify (targ);
+ TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = targ;
+ }
return 0;
}
/* If only one of the bounds used a MINUS_EXPR, compensate
by adding one to the other bound. */
if (parm_cst && !arg_cst)
- parm_max = fold_build2 (PLUS_EXPR,
+ parm_max = fold_build2_loc (input_location, PLUS_EXPR,
integer_type_node,
parm_max,
integer_one_node);
else if (arg_cst && !parm_cst)
- arg_max = fold_build2 (PLUS_EXPR,
+ arg_max = fold_build2_loc (input_location, PLUS_EXPR,
integer_type_node,
arg_max,
integer_one_node);
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;
}
return tmpl;
}
+/* Returns true if we need to instantiate this template instance even if we
+ know we aren't going to emit it.. */
+
+bool
+always_instantiate_p (tree decl)
+{
+ /* We always instantiate inline functions so that we can inline them. An
+ explicit instantiation declaration prohibits implicit instantiation of
+ non-inline functions. With high levels of optimization, we would
+ normally inline non-inline functions -- but we're not allowed to do
+ that for "extern template" functions. Therefore, we check
+ DECL_DECLARED_INLINE_P, rather than possibly_inlined_p. */
+ return ((TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_DECLARED_INLINE_P (decl))
+ /* And we need to instantiate static data members so that
+ their initializers are available in integral constant
+ expressions. */
+ || (TREE_CODE (decl) == VAR_DECL
+ && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)));
+}
+
/* Produce the definition of D, a _DECL generated from a template. If
DEFER_OK is nonzero, then we don't have to actually do the
instantiation now; we just have to do it sometime. Normally it is
the instantiation. */
return d;
+ /* Check to see whether we know that this template will be
+ instantiated in some other file, as with "extern template"
+ extension. */
+ external_p = (DECL_INTERFACE_KNOWN (d) && DECL_REALLY_EXTERN (d));
+
+ /* In general, we do not instantiate such templates. */
+ if (external_p && !always_instantiate_p (d))
+ return d;
+
gen_tmpl = most_general_template (tmpl);
gen_args = DECL_TI_ARGS (d);
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);
pop_access_scope (d);
}
- /* Check to see whether we know that this template will be
- instantiated in some other file, as with "extern template"
- extension. */
- external_p = (DECL_INTERFACE_KNOWN (d) && DECL_REALLY_EXTERN (d));
- /* In general, we do not instantiate such templates... */
- if (external_p
- /* ... but we instantiate inline functions so that we can inline
- them. An explicit instantiation declaration prohibits implicit
- instantiation of non-inline functions. With high levels of
- optimization, we would normally inline non-inline functions
- -- but we're not allowed to do that for "extern template" functions.
- Therefore, we check DECL_DECLARED_INLINE_P, rather than
- possibly_inlined_p. And ... */
- && ! (TREE_CODE (d) == FUNCTION_DECL
- && DECL_DECLARED_INLINE_P (d))
- /* ... we instantiate static data members whose values are
- needed in integral constant expressions. */
- && ! (TREE_CODE (d) == VAR_DECL
- && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (d)))
- goto out;
/* Defer all other templates, unless we have been explicitly
forbidden from doing so. */
if (/* If there is no definition, we cannot instantiate the
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 au;
}
-/* Replace auto in TYPE with std::initializer_list<auto>. */
+/* Given type ARG, return std::initializer_list<ARG>. */
static tree
-listify_autos (tree type, tree auto_node)
+listify (tree arg)
{
tree std_init_list = namespace_binding
(get_identifier ("initializer_list"), std_node);
tree argvec;
- tree init_auto;
if (!std_init_list || !DECL_CLASS_TEMPLATE_P (std_init_list))
{
- error ("deducing auto from brace-enclosed initializer list requires "
+ error ("deducing from brace-enclosed initializer list requires "
"#include <initializer_list>");
return error_mark_node;
}
argvec = make_tree_vec (1);
- TREE_VEC_ELT (argvec, 0) = auto_node;
- init_auto = lookup_template_class (std_init_list, argvec, NULL_TREE,
- NULL_TREE, 0, tf_warning_or_error);
+ TREE_VEC_ELT (argvec, 0) = arg;
+ return lookup_template_class (std_init_list, argvec, NULL_TREE,
+ NULL_TREE, 0, tf_warning_or_error);
+}
+/* Replace auto in TYPE with std::initializer_list<auto>. */
+
+static tree
+listify_autos (tree type, tree auto_node)
+{
+ tree init_auto = listify (auto_node);
+ tree argvec = make_tree_vec (1);
TREE_VEC_ELT (argvec, 0) = init_auto;
if (processing_template_decl)
argvec = add_to_template_args (current_template_args (), argvec);
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 (RECORD_OR_UNION_CODE_P (TREE_CODE (t))
+ 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)
return;
gcc_assert ((TREE_CODE (t) == FUNCTION_DECL
- || RECORD_OR_UNION_CODE_P (TREE_CODE (t)))
+ || CLASS_TYPE_P (t))
&& type_decl
&& TREE_CODE (type_decl) == TYPE_DECL
&& scope);
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. */