/* Handle parameterized types (templates) for GNU C++.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
+ 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
Rewritten by Jason Merrill (jason@cygnus.com).
#define UNIFY_ALLOW_OUTER_MORE_CV_QUAL 32
#define UNIFY_ALLOW_OUTER_LESS_CV_QUAL 64
+enum template_base_result {
+ tbr_incomplete_type,
+ tbr_ambiguous_baseclass,
+ tbr_success
+};
+
static void push_access_scope (tree);
static void pop_access_scope (tree);
static void push_deduction_access_scope (tree);
static void pop_deduction_access_scope (tree);
static bool resolve_overloaded_unification (tree, tree, tree, tree,
- unification_kind_t, int);
+ unification_kind_t, int,
+ bool);
static int try_one_overload (tree, tree, tree, tree, tree,
- unification_kind_t, int, bool);
-static int unify (tree, tree, tree, tree, int);
+ unification_kind_t, int, bool, bool);
+static int unify (tree, tree, tree, tree, int, bool);
static void add_pending_template (tree);
static tree reopen_tinst_level (struct tinst_level *);
static tree tsubst_initializer_list (tree, tree);
static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*,
tree);
static int type_unification_real (tree, tree, tree, const tree *,
- unsigned int, int, unification_kind_t, int);
+ unsigned int, int, unification_kind_t, int,
+ bool);
static void note_template_header (int);
static tree convert_nontype_argument_function (tree, tree);
static tree convert_nontype_argument (tree, tree, tsubst_flags_t);
static int template_decl_level (tree);
static int check_cv_quals_for_unify (int, tree, tree);
static void template_parm_level_and_index (tree, int*, int*);
-static int unify_pack_expansion (tree, tree, tree, tree, int, bool, bool);
+static int unify_pack_expansion (tree, tree, tree,
+ tree, unification_kind_t, bool, bool);
static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
static bool check_specialization_scope (void);
static tree process_partial_specialization (tree);
static void set_current_access_from_decl (tree);
-static tree get_template_base (tree, tree, tree, tree);
-static tree try_class_unification (tree, tree, tree, tree);
+static enum template_base_result get_template_base (tree, tree, tree, tree,
+ bool , tree *);
+static tree try_class_unification (tree, tree, tree, tree, bool);
static int coerce_template_template_parms (tree, tree, tsubst_flags_t,
tree, tree);
static bool template_template_parm_bindings_ok_p (tree, tree);
static tree listify (tree);
static tree listify_autos (tree, tree);
static tree template_parm_to_arg (tree t);
+static bool arg_from_parm_pack_p (tree, tree);
static tree current_template_args (void);
static tree fixup_template_type_parm_type (tree, int);
static tree fixup_template_parm_index (tree, tree, int);
else if (DECL_CLASS_SCOPE_P (t))
push_nested_class (DECL_CONTEXT (t));
else
- pushclass (NULL_TREE);
+ push_to_top_level ();
if (TREE_CODE (t) == FUNCTION_DECL)
{
if (DECL_FRIEND_CONTEXT (t) || DECL_CLASS_SCOPE_P (t))
pop_nested_class ();
else
- popclass ();
+ pop_from_top_level ();
}
/* Do any processing required when DECL (a member template
context = TYPE_CONTEXT (type);
- if (CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type))
+ if ((CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type))
+ /* Consider non-class instantiations of alias templates as
+ well. */
+ || (TYPE_P (type)
+ && TYPE_TEMPLATE_INFO (type)
+ && DECL_LANG_SPECIFIC (TYPE_NAME (type))
+ && DECL_USE_TEMPLATE (TYPE_NAME (type))))
{
/* This is for ordinary explicit specialization and partial
specialization of a template class such as:
Make sure that `C<int>' and `C<T*>' are implicit instantiations. */
- if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
+ if (CLASS_TYPE_P (type)
+ && CLASSTYPE_IMPLICIT_INSTANTIATION (type)
&& !COMPLETE_TYPE_P (type))
{
check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type));
return error_mark_node;
}
}
- else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
+ else if (CLASS_TYPE_P (type)
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
error ("specialization of %qT after instantiation", type);
+
+ if (DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (type)))
+ {
+ error ("partial specialization of alias template %qD",
+ TYPE_TI_TEMPLATE (type));
+ return error_mark_node;
+ }
}
else if (CLASS_TYPE_P (type)
&& !CLASSTYPE_USE_TEMPLATE (type)
instantiation. Reassign it to the new member
specialization template. */
spec_entry elt;
- spec_entry **slot;
+ spec_entry *entry;
+ void **slot;
elt.tmpl = most_general_template (tmpl);
elt.args = CLASSTYPE_TI_ARGS (inst);
elt.tmpl = tmpl;
elt.args = INNERMOST_TEMPLATE_ARGS (elt.args);
- slot = (spec_entry **)
- htab_find_slot (type_specializations, &elt, INSERT);
- *slot = ggc_alloc_spec_entry ();
- **slot = elt;
+ slot = htab_find_slot (type_specializations, &elt, INSERT);
+ entry = ggc_alloc_spec_entry ();
+ *entry = elt;
+ *slot = entry;
}
else if (COMPLETE_OR_OPEN_TYPE_P (inst))
/* But if we've had an implicit instantiation, that's a
hashval_t hash)
{
tree fn;
- spec_entry **slot = NULL;
+ void **slot = NULL;
spec_entry elt;
gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL && DECL_P (spec));
if (hash == 0)
hash = hash_specialization (&elt);
- slot = (spec_entry **)
+ slot =
htab_find_slot_with_hash (decl_specializations, &elt, hash, INSERT);
if (*slot)
- fn = (*slot)->spec;
+ fn = ((spec_entry *) *slot)->spec;
else
fn = NULL_TREE;
}
&& !check_specialization_namespace (tmpl))
DECL_CONTEXT (spec) = DECL_CONTEXT (tmpl);
- if (!optimize_specialization_lookup_p (tmpl))
+ if (slot != NULL /* !optimize_specialization_lookup_p (tmpl) */)
{
+ spec_entry *entry = ggc_alloc_spec_entry ();
gcc_assert (tmpl && args && spec);
- *slot = ggc_alloc_spec_entry ();
- **slot = elt;
+ *entry = elt;
+ *slot = entry;
if (TREE_CODE (spec) == FUNCTION_DECL && DECL_NAMESPACE_SCOPE_P (spec)
&& PRIMARY_TEMPLATE_P (tmpl)
&& DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (tmpl)) == NULL_TREE)
case TYPE_PACK_EXPANSION:
case EXPR_PACK_EXPANSION:
- return iterative_hash_template_arg (PACK_EXPANSION_PATTERN (arg), val);
+ val = iterative_hash_template_arg (PACK_EXPANSION_PATTERN (arg), val);
+ return iterative_hash_template_arg (PACK_EXPANSION_EXTRA_ARGS (arg), val);
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
return val;
case CAST_EXPR:
+ case IMPLICIT_CONV_EXPR:
case STATIC_CAST_EXPR:
case REINTERPRET_CAST_EXPR:
case CONST_CAST_EXPR:
default:
gcc_assert (IS_EXPR_CODE_CLASS (tclass));
{
- unsigned n = TREE_OPERAND_LENGTH (arg);
+ unsigned n = cp_tree_operand_length (arg);
for (i = 0; i < n; ++i)
val = iterative_hash_template_arg (TREE_OPERAND (arg, i), val);
return val;
bool
reregister_specialization (tree spec, tree tinfo, tree new_spec)
{
- spec_entry **slot;
+ spec_entry *entry;
spec_entry elt;
elt.tmpl = most_general_template (TI_TEMPLATE (tinfo));
elt.args = TI_ARGS (tinfo);
elt.spec = NULL_TREE;
- slot = (spec_entry **) htab_find_slot (decl_specializations, &elt, INSERT);
- if (*slot)
+ entry = (spec_entry *) htab_find (decl_specializations, &elt);
+ if (entry != NULL)
{
- gcc_assert ((*slot)->spec == spec || (*slot)->spec == new_spec);
+ gcc_assert (entry->spec == spec || entry->spec == new_spec);
gcc_assert (new_spec != NULL_TREE);
- (*slot)->spec = new_spec;
+ entry->spec = new_spec;
return 1;
}
with the signature of DECL. */
tree templates = NULL_TREE;
int header_count;
- struct cp_binding_level *b;
+ cp_binding_level *b;
*targs_out = NULL_TREE;
if (TREE_CODE (parm) == PARM_DECL)
return (DECL_TEMPLATE_PARM_P (parm)
&& TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)));
+ if (TREE_CODE (parm) == TEMPLATE_PARM_INDEX)
+ return TEMPLATE_PARM_PARAMETER_PACK (parm);
/* If this is a list of template parameters, we could get a
TYPE_DECL or a TEMPLATE_DECL. */
if (TREE_CODE (parm) == TYPE_DECL || TREE_CODE (parm) == TEMPLATE_DECL)
parm = TREE_TYPE (parm);
+ /* Otherwise it must be a type template parameter. */
return ((TREE_CODE (parm) == TEMPLATE_TYPE_PARM
|| TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM)
&& TEMPLATE_TYPE_PARAMETER_PACK (parm));
return get_identifier (newname);
}
-/* Return true if T is a primary function
- or class template instantiation. */
+/* Return true if T is a primary function, class or alias template
+ instantiation. */
bool
primary_template_instantiation_p (const_tree t)
return DECL_LANG_SPECIFIC (t)
&& DECL_TEMPLATE_INSTANTIATION (t)
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t));
- else if (CLASS_TYPE_P (t))
+ else if (CLASS_TYPE_P (t) && !TYPE_DECL_ALIAS_P (TYPE_NAME (t)))
return CLASSTYPE_TEMPLATE_INSTANTIATION (t)
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t));
+ else if (TYPE_P (t)
+ && TYPE_TEMPLATE_INFO (t)
+ && PRIMARY_TEMPLATE_P (TYPE_TI_TEMPLATE (t))
+ && DECL_TEMPLATE_INSTANTIATION (TYPE_NAME (t)))
+ return true;
return false;
}
(struct find_parameter_pack_data*)data;
bool parameter_pack_p = false;
+ /* Handle type aliases/typedefs. */
+ if (TYPE_P (t)
+ && TYPE_NAME (t)
+ && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
+ && TYPE_DECL_ALIAS_P (TYPE_NAME (t)))
+ {
+ if (TYPE_TEMPLATE_INFO (t))
+ cp_walk_tree (&TYPE_TI_ARGS (t),
+ &find_parameter_packs_r,
+ ppd, ppd->visited);
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+
/* Identify whether this is a parameter pack or not. */
switch (TREE_CODE (t))
{
break;
case TEMPLATE_TYPE_PARM:
+ t = TYPE_MAIN_VARIANT (t);
case TEMPLATE_TEMPLATE_PARM:
if (TEMPLATE_TYPE_PARAMETER_PACK (t))
parameter_pack_p = true;
}
break;
+ case BASES:
+ parameter_pack_p = true;
+ break;
default:
/* Not a parameter pack. */
break;
*walk_subtrees = 0;
return NULL_TREE;
+ case CONSTRUCTOR:
case TEMPLATE_DECL:
cp_walk_tree (&TREE_TYPE (t),
&find_parameter_packs_r, ppd, ppd->visited);
}
PACK_EXPANSION_PARAMETER_PACKS (result) = parameter_packs;
+ PACK_EXPANSION_LOCAL_P (result) = at_function_scope_p ();
+
return result;
}
return t;
}
+/* This function returns TRUE if PARM_PACK is a template parameter
+ pack and if ARG_PACK is what template_parm_to_arg returned when
+ passed PARM_PACK. */
+
+static bool
+arg_from_parm_pack_p (tree arg_pack, tree parm_pack)
+{
+ /* For clarity in the comments below let's use the representation
+ argument_pack<elements>' to denote an argument pack and its
+ elements.
+
+ In the 'if' block below, we want to detect cases where
+ ARG_PACK is argument_pack<PARM_PACK...>. I.e, we want to
+ check if ARG_PACK is an argument pack which sole element is
+ the expansion of PARM_PACK. That argument pack is typically
+ created by template_parm_to_arg when passed a parameter
+ pack. */
+
+ if (arg_pack
+ && TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack)) == 1
+ && PACK_EXPANSION_P (TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack), 0)))
+ {
+ tree expansion = TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack), 0);
+ tree pattern = PACK_EXPANSION_PATTERN (expansion);
+ /* So we have an argument_pack<P...>. We want to test if P
+ is actually PARM_PACK. We will not use cp_tree_equal to
+ test P and PARM_PACK because during type fixup (by
+ fixup_template_parm) P can be a pre-fixup version of a
+ type and PARM_PACK be its post-fixup version.
+ cp_tree_equal would consider them as different even
+ though we would want to consider them compatible for our
+ precise purpose here.
+
+ Thus we are going to consider that P and PARM_PACK are
+ compatible if they have the same DECL. */
+ if ((/* If ARG_PACK is a type parameter pack named by the
+ same DECL as parm_pack ... */
+ (TYPE_P (pattern)
+ && TYPE_P (parm_pack)
+ && TYPE_NAME (pattern) == TYPE_NAME (parm_pack))
+ /* ... or if PARM_PACK is a non-type parameter named by the
+ same DECL as ARG_PACK. Note that PARM_PACK being a
+ non-type parameter means it's either a PARM_DECL or a
+ TEMPLATE_PARM_INDEX. */
+ || (TREE_CODE (pattern) == TEMPLATE_PARM_INDEX
+ && ((TREE_CODE (parm_pack) == PARM_DECL
+ && (TEMPLATE_PARM_DECL (pattern)
+ == TEMPLATE_PARM_DECL (DECL_INITIAL (parm_pack))))
+ || (TREE_CODE (parm_pack) == TEMPLATE_PARM_INDEX
+ && (TEMPLATE_PARM_DECL (pattern)
+ == TEMPLATE_PARM_DECL (parm_pack))))))
+ && template_parameter_pack_p (pattern))
+ return true;
+ }
+ return false;
+}
+
/* Within the declaration of a template, return all levels of template
parameters that apply. The template parameters are represented as
a TREE_VEC, in the form documented in cp-tree.h for template
tree tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
DECL_TEMPLATE_PARMS (tmpl) = parms;
DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
+ DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p;
return tmpl;
"friend declarations");
else if (TREE_CODE (decl) == FUNCTION_DECL && (cxx_dialect == cxx98))
msg = G_("default template arguments may not be used in function templates "
- "without -std=c++0x or -std=gnu++0x");
+ "without -std=c++11 or -std=gnu++11");
else if (is_partial)
msg = G_("default template arguments may not be used in "
"partial specializations");
else if (DECL_IMPLICIT_TYPEDEF_P (decl)
&& CLASS_TYPE_P (TREE_TYPE (decl)))
/* OK */;
+ else if (TREE_CODE (decl) == TYPE_DECL
+ && TYPE_DECL_ALIAS_P (decl))
+ /* alias-declaration */
+ gcc_assert (!DECL_ARTIFICIAL (decl));
else
{
error ("template declaration of %q#D", decl);
if (check_for_bare_parameter_packs (TYPE_RAISES_EXCEPTIONS (type)))
TYPE_RAISES_EXCEPTIONS (type) = NULL_TREE;
}
- else if (check_for_bare_parameter_packs (TREE_TYPE (decl)))
+ else if (check_for_bare_parameter_packs ((TREE_CODE (decl) == TYPE_DECL
+ && TYPE_DECL_ALIAS_P (decl))
+ ? DECL_ORIGINAL_TYPE (decl)
+ : TREE_TYPE (decl)))
{
TREE_TYPE (decl) = error_mark_node;
return error_mark_node;
if (DECL_IMPLICIT_TYPEDEF_P (decl))
SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
- else if (DECL_LANG_SPECIFIC (decl))
- DECL_TEMPLATE_INFO (decl) = info;
+ else
+ {
+ if (primary && !DECL_LANG_SPECIFIC (decl))
+ retrofit_lang_decl (decl);
+ if (DECL_LANG_SPECIFIC (decl))
+ DECL_TEMPLATE_INFO (decl) = info;
+ }
return DECL_TEMPLATE_RESULT (tmpl);
}
return fold_non_dependent_expr_sfinae (expr, tf_error);
}
+/* Return TRUE iff T is a type alias, a TEMPLATE_DECL for an alias
+ template declaration, or a TYPE_DECL for an alias declaration. */
+
+bool
+alias_type_or_template_p (tree t)
+{
+ if (t == NULL_TREE)
+ return false;
+ return ((TREE_CODE (t) == TYPE_DECL && TYPE_DECL_ALIAS_P (t))
+ || (TYPE_P (t)
+ && TYPE_NAME (t)
+ && TYPE_DECL_ALIAS_P (TYPE_NAME (t)))
+ || DECL_ALIAS_TEMPLATE_P (t));
+}
+
+/* Return TRUE iff is a specialization of an alias template. */
+
+bool
+alias_template_specialization_p (tree t)
+{
+ if (t == NULL_TREE)
+ return false;
+ return (primary_template_instantiation_p (t)
+ && DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (t)));
+}
+
/* Subroutine of convert_nontype_argument. Converts EXPR to TYPE, which
must be a function or a pointer-to-function type, as specified
in [temp.arg.nontype]: disambiguate EXPR if it is an overload set,
{
tree fns = expr;
tree fn, fn_no_ptr;
+ linkage_kind linkage;
fn = instantiate_type (type, fns, tf_none);
if (fn == error_mark_node)
fn_no_ptr = fn;
if (TREE_CODE (fn_no_ptr) == ADDR_EXPR)
fn_no_ptr = TREE_OPERAND (fn_no_ptr, 0);
- if (TREE_CODE (fn_no_ptr) == BASELINK)
+ if (BASELINK_P (fn_no_ptr))
fn_no_ptr = BASELINK_FUNCTIONS (fn_no_ptr);
/* [temp.arg.nontype]/1
A template-argument for a non-type, non-template template-parameter
shall be one of:
[...]
- -- the address of an object or function with external linkage. */
- if (!DECL_EXTERNAL_LINKAGE_P (fn_no_ptr))
+ -- the address of an object or function with external [C++11: or
+ internal] linkage. */
+ linkage = decl_linkage (fn_no_ptr);
+ if (cxx_dialect >= cxx0x ? linkage == lk_none : linkage != lk_external)
{
- error ("%qE is not a valid template argument for type %qT "
- "because function %qD has not external linkage",
- expr, type, fn_no_ptr);
+ if (cxx_dialect >= cxx0x)
+ error ("%qE is not a valid template argument for type %qT "
+ "because %qD has no linkage",
+ expr, type, fn_no_ptr);
+ else
+ error ("%qE is not a valid template argument for type %qT "
+ "because %qD does not have external linkage",
+ expr, type, fn_no_ptr);
return NULL_TREE;
}
STRIP_NOPS (expr);
if (expr && (null_ptr_cst_p (expr) || TREE_CODE (expr) == PTRMEM_CST))
return true;
+ if (cxx_dialect >= cxx0x && null_member_pointer_value_p (expr))
+ return true;
if (complain & tf_error)
{
error ("%qE is not a valid template argument for type %qT",
return false;
}
+/* The next set of functions are used for providing helpful explanatory
+ diagnostics for failed overload resolution. Their messages should be
+ indented by two spaces for consistency with the messages in
+ call.c */
+
+static int
+unify_success (bool explain_p ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+static int
+unify_parameter_deduction_failure (bool explain_p, tree parm)
+{
+ if (explain_p)
+ inform (input_location,
+ " couldn't deduce template parameter %qD", parm);
+ return 1;
+}
+
+static int
+unify_invalid (bool explain_p ATTRIBUTE_UNUSED)
+{
+ return 1;
+}
+
+static int
+unify_cv_qual_mismatch (bool explain_p, tree parm, tree arg)
+{
+ if (explain_p)
+ inform (input_location,
+ " types %qT and %qT have incompatible cv-qualifiers",
+ parm, arg);
+ return 1;
+}
+
+static int
+unify_type_mismatch (bool explain_p, tree parm, tree arg)
+{
+ if (explain_p)
+ inform (input_location, " mismatched types %qT and %qT", parm, arg);
+ return 1;
+}
+
+static int
+unify_parameter_pack_mismatch (bool explain_p, tree parm, tree arg)
+{
+ if (explain_p)
+ inform (input_location,
+ " template parameter %qD is not a parameter pack, but "
+ "argument %qD is",
+ parm, arg);
+ return 1;
+}
+
+static int
+unify_ptrmem_cst_mismatch (bool explain_p, tree parm, tree arg)
+{
+ if (explain_p)
+ inform (input_location,
+ " template argument %qE does not match "
+ "pointer-to-member constant %qE",
+ arg, parm);
+ return 1;
+}
+
+static int
+unify_expression_unequal (bool explain_p, tree parm, tree arg)
+{
+ if (explain_p)
+ inform (input_location, " %qE is not equivalent to %qE", parm, arg);
+ return 1;
+}
+
+static int
+unify_parameter_pack_inconsistent (bool explain_p, tree old_arg, tree new_arg)
+{
+ if (explain_p)
+ inform (input_location,
+ " inconsistent parameter pack deduction with %qT and %qT",
+ old_arg, new_arg);
+ return 1;
+}
+
+static int
+unify_inconsistency (bool explain_p, tree parm, tree first, tree second)
+{
+ if (explain_p)
+ {
+ if (TYPE_P (parm))
+ inform (input_location,
+ " deduced conflicting types for parameter %qT (%qT and %qT)",
+ parm, first, second);
+ else
+ inform (input_location,
+ " deduced conflicting values for non-type parameter "
+ "%qE (%qE and %qE)", parm, first, second);
+ }
+ return 1;
+}
+
+static int
+unify_vla_arg (bool explain_p, tree arg)
+{
+ if (explain_p)
+ inform (input_location,
+ " variable-sized array type %qT is not "
+ "a valid template argument",
+ arg);
+ return 1;
+}
+
+static int
+unify_method_type_error (bool explain_p, tree arg)
+{
+ if (explain_p)
+ inform (input_location,
+ " member function type %qT is not a valid template argument",
+ arg);
+ return 1;
+}
+
+static int
+unify_arity (bool explain_p, int have, int wanted)
+{
+ if (explain_p)
+ inform_n (input_location, wanted,
+ " candidate expects %d argument, %d provided",
+ " candidate expects %d arguments, %d provided",
+ wanted, have);
+ return 1;
+}
+
+static int
+unify_too_many_arguments (bool explain_p, int have, int wanted)
+{
+ return unify_arity (explain_p, have, wanted);
+}
+
+static int
+unify_too_few_arguments (bool explain_p, int have, int wanted)
+{
+ return unify_arity (explain_p, have, wanted);
+}
+
+static int
+unify_arg_conversion (bool explain_p, tree to_type,
+ tree from_type, tree arg)
+{
+ if (explain_p)
+ inform (input_location, " cannot convert %qE (type %qT) to type %qT",
+ arg, from_type, to_type);
+ return 1;
+}
+
+static int
+unify_no_common_base (bool explain_p, enum template_base_result r,
+ tree parm, tree arg)
+{
+ if (explain_p)
+ switch (r)
+ {
+ case tbr_ambiguous_baseclass:
+ inform (input_location, " %qT is an ambiguous base class of %qT",
+ arg, parm);
+ break;
+ default:
+ inform (input_location, " %qT is not derived from %qT", arg, parm);
+ break;
+ }
+ return 1;
+}
+
+static int
+unify_inconsistent_template_template_parameters (bool explain_p)
+{
+ if (explain_p)
+ inform (input_location,
+ " template parameters of a template template argument are "
+ "inconsistent with other deduced template arguments");
+ return 1;
+}
+
+static int
+unify_template_deduction_failure (bool explain_p, tree parm, tree arg)
+{
+ if (explain_p)
+ inform (input_location,
+ " can't deduce a template for %qT from non-template type %qT",
+ parm, arg);
+ return 1;
+}
+
+static int
+unify_template_argument_mismatch (bool explain_p, tree parm, tree arg)
+{
+ if (explain_p)
+ inform (input_location,
+ " template argument %qE does not match %qD", arg, parm);
+ return 1;
+}
+
+static int
+unify_overload_resolution_failure (bool explain_p, tree arg)
+{
+ if (explain_p)
+ inform (input_location,
+ " could not resolve address from overloaded function %qE",
+ arg);
+ return 1;
+}
+
/* 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
else
expr = mark_rvalue_use (expr);
+ /* 14.3.2/5: The null pointer{,-to-member} conversion is applied
+ to a non-type argument of "nullptr". */
+ if (expr == nullptr_node
+ && (TYPE_PTR_P (type) || TYPE_PTR_TO_MEMBER_P (type)))
+ expr = convert (type, expr);
+
+ /* In C++11, integral or enumeration non-type template arguments can be
+ arbitrary constant expressions. Pointer and pointer to
+ member arguments can be general constant expressions that evaluate
+ to a null value, but otherwise still need to be of a specific form. */
+ if (cxx_dialect >= cxx0x)
+ {
+ if (TREE_CODE (expr) == PTRMEM_CST)
+ /* A PTRMEM_CST is already constant, and a valid template
+ argument for a parameter of pointer to member type, we just want
+ to leave it in that form rather than lower it to a
+ CONSTRUCTOR. */;
+ else if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+ expr = maybe_constant_value (expr);
+ else if (TYPE_PTR_P (type)
+ || TYPE_PTR_TO_MEMBER_P (type))
+ {
+ tree folded = maybe_constant_value (expr);
+ if (TYPE_PTR_P (type) ? integer_zerop (folded)
+ : null_member_pointer_value_p (folded))
+ expr = folded;
+ }
+ }
+
/* HACK: Due to double coercion, we can get a
NOP_EXPR<REFERENCE_TYPE>(ADDR_EXPR<POINTER_TYPE> (arg)) here,
which is the tree that we built on the first call (see
function). We just strip everything and get to the arg.
See g++.old-deja/g++.oliva/template4.C and g++.dg/template/nontype9.C
for examples. */
- if (TREE_CODE (expr) == NOP_EXPR)
+ if (TYPE_REF_OBJ_P (type) || TYPE_REFFN_P (type))
{
- if (TYPE_REF_OBJ_P (type) || TYPE_REFFN_P (type))
+ tree probe_type, probe = expr;
+ if (REFERENCE_REF_P (probe))
+ probe = TREE_OPERAND (probe, 0);
+ probe_type = TREE_TYPE (probe);
+ if (TREE_CODE (probe) == NOP_EXPR)
{
/* ??? Maybe we could use convert_from_reference here, but we
would need to relax its constraints because the NOP_EXPR
could actually change the type to something more cv-qualified,
and this is not folded by convert_from_reference. */
- tree addr = TREE_OPERAND (expr, 0);
- gcc_assert (TREE_CODE (expr_type) == REFERENCE_TYPE);
+ tree addr = TREE_OPERAND (probe, 0);
+ gcc_assert (TREE_CODE (probe_type) == REFERENCE_TYPE);
gcc_assert (TREE_CODE (addr) == ADDR_EXPR);
gcc_assert (TREE_CODE (TREE_TYPE (addr)) == POINTER_TYPE);
gcc_assert (same_type_ignoring_top_level_qualifiers_p
- (TREE_TYPE (expr_type),
+ (TREE_TYPE (probe_type),
TREE_TYPE (TREE_TYPE (addr))));
expr = TREE_OPERAND (addr, 0);
expr_type = TREE_TYPE (expr);
}
+ }
- /* We could also generate a NOP_EXPR(ADDR_EXPR()) when the
- parameter is a pointer to object, through decay and
- qualification conversion. Let's strip everything. */
- else if (TYPE_PTROBV_P (type))
- {
- STRIP_NOPS (expr);
- gcc_assert (TREE_CODE (expr) == ADDR_EXPR);
- gcc_assert (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE);
- /* Skip the ADDR_EXPR only if it is part of the decay for
- an array. Otherwise, it is part of the original argument
- in the source code. */
- if (TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == ARRAY_TYPE)
- expr = TREE_OPERAND (expr, 0);
- expr_type = TREE_TYPE (expr);
- }
+ /* We could also generate a NOP_EXPR(ADDR_EXPR()) when the
+ parameter is a pointer to object, through decay and
+ qualification conversion. Let's strip everything. */
+ else if (TREE_CODE (expr) == NOP_EXPR && TYPE_PTROBV_P (type))
+ {
+ STRIP_NOPS (expr);
+ gcc_assert (TREE_CODE (expr) == ADDR_EXPR);
+ gcc_assert (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE);
+ /* Skip the ADDR_EXPR only if it is part of the decay for
+ an array. Otherwise, it is part of the original argument
+ in the source code. */
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == ARRAY_TYPE)
+ expr = TREE_OPERAND (expr, 0);
+ expr_type = TREE_TYPE (expr);
}
/* [temp.arg.nontype]/5, bullet 1
if (complain & tf_error)
{
int errs = errorcount, warns = warningcount;
+ if (processing_template_decl
+ && !require_potential_constant_expression (expr))
+ return NULL_TREE;
expr = cxx_constant_value (expr);
if (errorcount > errs || warningcount > warns)
inform (EXPR_LOC_OR_HERE (expr),
if (DECL_P (expr) && DECL_TEMPLATE_PARM_P (expr))
/* Non-type template parameters are OK. */
;
+ else if (cxx_dialect >= cxx0x && integer_zerop (expr))
+ /* Null pointer values are OK in C++11. */;
else if (TREE_CODE (expr) != ADDR_EXPR
&& TREE_CODE (expr_type) != ARRAY_TYPE)
{
expr, type, decl);
return NULL_TREE;
}
- else if (!DECL_EXTERNAL_LINKAGE_P (decl))
+ else if (cxx_dialect < cxx0x && !DECL_EXTERNAL_LINKAGE_P (decl))
{
error ("%qE is not a valid template argument of type %qT "
"because %qD does not have external linkage",
expr, type, decl);
return NULL_TREE;
}
+ else if (cxx_dialect >= cxx0x && decl_linkage (decl) == lk_none)
+ {
+ error ("%qE is not a valid template argument of type %qT "
+ "because %qD has no linkage",
+ expr, type, decl);
+ return NULL_TREE;
+ }
}
expr = decay_conversion (expr);
return error_mark_node;
}
+ if (cxx_dialect >= cxx0x && integer_zerop (expr))
+ /* Null pointer values are OK in C++11. */
+ return perform_qualification_conversions (type, expr);
+
expr = convert_nontype_argument_function (type, expr);
if (!expr || expr == error_mark_node)
return expr;
if (expr == error_mark_node)
return expr;
}
+ else if (NULLPTR_TYPE_P (type))
+ {
+ if (expr != nullptr_node)
+ {
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is of type %qT", expr, type, TREE_TYPE (expr));
+ return NULL_TREE;
+ }
+ return expr;
+ }
/* A template non-type parameter must be one of the above. */
else
gcc_unreachable ();
if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
&& TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
{
- permerror (input_location, "to refer to a type member of a template parameter, "
- "use %<typename %E%>", orig_arg);
+ if (TREE_CODE (TREE_OPERAND (arg, 1)) == BIT_NOT_EXPR)
+ {
+ if (complain & tf_error)
+ error ("invalid use of destructor %qE as a type", orig_arg);
+ return error_mark_node;
+ }
+
+ permerror (input_location,
+ "to refer to a type member of a template parameter, "
+ "use %<typename %E%>", orig_arg);
orig_arg = make_typename_type (TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1),
subtract it from nparms to get the number of non-variadic
parameters. */
int variadic_p = 0;
+ int post_variadic_parms = 0;
if (args == error_mark_node)
return error_mark_node;
for (parm_idx = 0; parm_idx < nparms; ++parm_idx)
{
tree tparm = TREE_VALUE (TREE_VEC_ELT (parms, parm_idx));
+ if (variadic_p)
+ ++post_variadic_parms;
if (template_parameter_pack_p (tparm))
++variadic_p;
}
inner_args = INNERMOST_TEMPLATE_ARGS (args);
- /* If there are 0 or 1 parameter packs, we need to expand any argument
- packs so that we can deduce a parameter pack from some non-packed args
- followed by an argument pack, as in variadic85.C. If there are more
- than that, we need to leave argument packs intact so the arguments are
- assigned to the right parameter packs. This should only happen when
- dealing with a nested class inside a partial specialization of a class
- template, as in variadic92.C. */
- if (variadic_p <= 1)
+ /* If there are no parameters that follow a parameter pack, we need to
+ expand any argument packs so that we can deduce a parameter pack from
+ some non-packed args followed by an argument pack, as in variadic85.C.
+ If there are such parameters, we need to leave argument packs intact
+ so the arguments are assigned properly. This can happen when dealing
+ with a nested class inside a partial specialization of a class
+ template, as in variadic92.C, or when deducing a template parameter pack
+ from a sub-declarator, as in variadic114.C. */
+ if (!post_variadic_parms)
inner_args = expand_template_argument_pack (inner_args);
nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
{
if (variadic_p)
{
- --nparms;
+ nparms -= variadic_p;
error ("wrong number of template arguments "
"(%d, should be %d or more)", nargs, nparms);
}
{
if (PACK_EXPANSION_P (arg))
{
- if (complain & tf_error)
- {
- /* FIXME this restriction was removed by N2555; see
- bug 35722. */
- /* If ARG is a pack expansion, but PARM is not a
- template parameter pack (if it were, we would have
- handled it above), we're trying to expand into a
- fixed-length argument list. */
- if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
- sorry ("cannot expand %<%E%> into a fixed-length "
- "argument list", arg);
- else
- sorry ("cannot expand %<%T%> into a fixed-length "
- "argument list", arg);
- }
- ++lost;
+ /* We don't know how many args we have yet, just
+ use the unconverted ones for now. */
+ new_inner_args = args;
+ break;
}
}
else if (require_all_args)
/* For member templates */
return TREE_CODE (ot) == TREE_VEC && comp_template_args (ot, nt);
else if (PACK_EXPANSION_P (ot))
- return PACK_EXPANSION_P (nt)
- && template_args_equal (PACK_EXPANSION_PATTERN (ot),
- PACK_EXPANSION_PATTERN (nt));
+ return (PACK_EXPANSION_P (nt)
+ && template_args_equal (PACK_EXPANSION_PATTERN (ot),
+ PACK_EXPANSION_PATTERN (nt))
+ && template_args_equal (PACK_EXPANSION_EXTRA_ARGS (ot),
+ PACK_EXPANSION_EXTRA_ARGS (nt)));
else if (ARGUMENT_PACK_P (ot))
{
int i, len;
return cp_tree_equal (ot, nt);
}
-/* Returns 1 iff the OLDARGS and NEWARGS are in fact identical sets
- of template arguments. Returns 0 otherwise. */
+/* Returns 1 iff the OLDARGS and NEWARGS are in fact identical sets of
+ template arguments. Returns 0 otherwise, and updates OLDARG_PTR and
+ NEWARG_PTR with the offending arguments if they are non-NULL. */
-int
-comp_template_args (tree oldargs, tree newargs)
+static int
+comp_template_args_with_info (tree oldargs, tree newargs,
+ tree *oldarg_ptr, tree *newarg_ptr)
{
int i;
+ if (oldargs == newargs)
+ return 1;
+
+ if (!oldargs || !newargs)
+ return 0;
+
if (TREE_VEC_LENGTH (oldargs) != TREE_VEC_LENGTH (newargs))
return 0;
tree ot = TREE_VEC_ELT (oldargs, i);
if (! template_args_equal (ot, nt))
- return 0;
+ {
+ if (oldarg_ptr != NULL)
+ *oldarg_ptr = ot;
+ if (newarg_ptr != NULL)
+ *newarg_ptr = nt;
+ return 0;
+ }
}
return 1;
}
+/* Returns 1 iff the OLDARGS and NEWARGS are in fact identical sets
+ of template arguments. Returns 0 otherwise. */
+
+int
+comp_template_args (tree oldargs, tree newargs)
+{
+ return comp_template_args_with_info (oldargs, newargs, NULL, NULL);
+}
+
static void
add_pending_template (tree d)
{
return error_mark_node;
gcc_assert (!arglist || TREE_CODE (arglist) == TREE_VEC);
- gcc_assert (fns && (is_overloaded_fn (fns)
- || TREE_CODE (fns) == IDENTIFIER_NODE));
+
+ if (!is_overloaded_fn (fns) && TREE_CODE (fns) != IDENTIFIER_NODE)
+ {
+ error ("%q#D is not a function template", fns);
+ return error_mark_node;
+ }
if (BASELINK_P (fns))
{
{
tree templ = NULL_TREE, parmlist;
tree t;
- spec_entry **slot;
+ void **slot;
spec_entry *entry;
spec_entry elt;
hashval_t hash;
int is_dependent_type;
int use_partial_inst_tmpl = false;
+ if (template_type == error_mark_node)
+ /* An error occured while building the template TEMPL, and a
+ diagnostic has most certainly been emitted for that
+ already. Let's propagate that error. */
+ return error_mark_node;
+
gen_tmpl = most_general_template (templ);
parmlist = DECL_TEMPLATE_PARMS (gen_tmpl);
parm_depth = TMPL_PARMS_DEPTH (parmlist);
context = tsubst (DECL_CONTEXT (gen_tmpl), arglist,
complain, in_decl);
+ if (context == error_mark_node)
+ return error_mark_node;
+
if (!context)
context = global_namespace;
ENUM_FIXED_UNDERLYING_TYPE_P (t)
= ENUM_FIXED_UNDERLYING_TYPE_P (template_type);
}
- else
+ else if (DECL_ALIAS_TEMPLATE_P (gen_tmpl))
+ {
+ /* The user referred to a specialization of an alias
+ template represented by GEN_TMPL.
+
+ [temp.alias]/2 says:
+
+ When a template-id refers to the specialization of an
+ alias template, it is equivalent to the associated
+ type obtained by substitution of its
+ template-arguments for the template-parameters in the
+ type-id of the alias template. */
+
+ t = tsubst (TREE_TYPE (gen_tmpl), arglist, complain, in_decl);
+ /* Note that the call above (by indirectly calling
+ register_specialization in tsubst_decl) registers the
+ TYPE_DECL representing the specialization of the alias
+ template. So next time someone substitutes ARGLIST for
+ the template parms into the alias template (GEN_TMPL),
+ she'll get that TYPE_DECL back. */
+
+ if (t == error_mark_node)
+ return t;
+ }
+ else if (CLASS_TYPE_P (template_type))
{
t = make_class_type (TREE_CODE (template_type));
CLASSTYPE_DECLARED_CLASS (t)
structural equality testing. */
SET_TYPE_STRUCTURAL_EQUALITY (t);
}
+ else
+ gcc_unreachable ();
/* If we called start_enum or pushtag above, this information
will already be set up. */
else
type_decl = TYPE_NAME (t);
- TREE_PRIVATE (type_decl)
- = TREE_PRIVATE (TYPE_STUB_DECL (template_type));
- TREE_PROTECTED (type_decl)
- = TREE_PROTECTED (TYPE_STUB_DECL (template_type));
- if (CLASSTYPE_VISIBILITY_SPECIFIED (template_type))
+ if (CLASS_TYPE_P (template_type))
{
- DECL_VISIBILITY_SPECIFIED (type_decl) = 1;
- DECL_VISIBILITY (type_decl) = CLASSTYPE_VISIBILITY (template_type);
+ TREE_PRIVATE (type_decl)
+ = TREE_PRIVATE (TYPE_STUB_DECL (template_type));
+ TREE_PROTECTED (type_decl)
+ = TREE_PROTECTED (TYPE_STUB_DECL (template_type));
+ if (CLASSTYPE_VISIBILITY_SPECIFIED (template_type))
+ {
+ DECL_VISIBILITY_SPECIFIED (type_decl) = 1;
+ DECL_VISIBILITY (type_decl) = CLASSTYPE_VISIBILITY (template_type);
+ }
}
/* Let's consider the explicit specialization of a member
++processing_template_decl;
partial_inst_args =
tsubst (INNERMOST_TEMPLATE_ARGS
- (CLASSTYPE_TI_ARGS (TREE_TYPE (gen_tmpl))),
+ (TYPE_TI_ARGS (TREE_TYPE (gen_tmpl))),
arglist, complain, NULL_TREE);
--processing_template_decl;
TREE_VEC_LENGTH (arglist)++;
TREE_VEC_LENGTH (arglist)--;
found = tsubst (gen_tmpl, arglist, complain, NULL_TREE);
TREE_VEC_LENGTH (arglist)++;
- found = CLASSTYPE_TI_TEMPLATE (found);
+ /* FOUND is either a proper class type, or an alias
+ template specialization. In the later case, it's a
+ TYPE_DECL, resulting from the substituting of arguments
+ for parameters in the TYPE_DECL of the alias template
+ done earlier. So be careful while getting the template
+ of FOUND. */
+ found = TREE_CODE (found) == TYPE_DECL
+ ? TYPE_TI_TEMPLATE (TREE_TYPE (found))
+ : CLASSTYPE_TI_TEMPLATE (found);
}
SET_TYPE_TEMPLATE_INFO (t, build_template_info (found, arglist));
elt.spec = t;
- slot = (spec_entry **) htab_find_slot_with_hash (type_specializations,
- &elt, hash, INSERT);
- *slot = ggc_alloc_spec_entry ();
- **slot = elt;
+ slot = htab_find_slot_with_hash (type_specializations,
+ &elt, hash, INSERT);
+ entry = ggc_alloc_spec_entry ();
+ *entry = elt;
+ *slot = entry;
/* Note this use of the partial instantiation so we can check it
later in maybe_process_partial_specialization. */
the instantiation and exit above. */
tsubst_enum (template_type, t, arglist);
- if (is_dependent_type)
+ if (CLASS_TYPE_P (template_type) && is_dependent_type)
/* If the type makes use of template parameters, the
code that generates debugging information will crash. */
DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;
case MODOP_EXPR:
case CAST_EXPR:
+ case IMPLICIT_CONV_EXPR:
case REINTERPRET_CAST_EXPR:
case CONST_CAST_EXPR:
case STATIC_CAST_EXPR:
|| EXPR_P (t)
|| TREE_CODE (t) == TEMPLATE_PARM_INDEX
|| TREE_CODE (t) == OVERLOAD
- || TREE_CODE (t) == BASELINK
+ || BASELINK_P (t)
|| TREE_CODE (t) == IDENTIFIER_NODE
|| TREE_CODE (t) == TRAIT_EXPR
|| TREE_CODE (t) == CONSTRUCTOR
/*include_nondeduced_p=*/true);
}
+/* Returns TRUE iff INST is an instantiation we don't need to do in an
+ ill-formed translation unit, i.e. a variable or function that isn't
+ usable in a constant expression. */
+
+static inline bool
+neglectable_inst_p (tree d)
+{
+ return (DECL_P (d)
+ && !(TREE_CODE (d) == FUNCTION_DECL ? DECL_DECLARED_CONSTEXPR_P (d)
+ : decl_maybe_constant_var_p (d)));
+}
+
+/* Returns TRUE iff we should refuse to instantiate DECL because it's
+ neglectable and instantiated from within an erroneous instantiation. */
+
+static bool
+limit_bad_template_recursion (tree decl)
+{
+ struct tinst_level *lev = current_tinst_level;
+ int errs = errorcount + sorrycount;
+ if (lev == NULL || errs == 0 || !neglectable_inst_p (decl))
+ return false;
+
+ for (; lev; lev = lev->next)
+ if (neglectable_inst_p (lev->decl))
+ break;
+
+ return (lev && errs > lev->errors);
+}
+
static int tinst_depth;
extern int max_tinst_depth;
#ifdef GATHER_STATISTICS
int depth_reached;
#endif
-static int tinst_level_tick;
-static int last_template_error_tick;
+static GTY(()) struct tinst_level *last_error_tinst_level;
/* We're starting to instantiate D; record the template instantiation context
for diagnostics and to restore it later. */
if (tinst_depth >= max_tinst_depth)
{
- last_template_error_tick = tinst_level_tick;
+ last_error_tinst_level = current_tinst_level;
if (TREE_CODE (d) == TREE_LIST)
error ("template instantiation depth exceeds maximum of %d (use "
"-ftemplate-depth= to increase the maximum) substituting %qS",
return 0;
}
+ /* If the current instantiation caused problems, don't let it instantiate
+ anything else. Do allow deduction substitution and decls usable in
+ constant expressions. */
+ if (limit_bad_template_recursion (d))
+ return 0;
+
new_level = ggc_alloc_tinst_level ();
new_level->decl = d;
new_level->locus = input_location;
+ new_level->errors = errorcount+sorrycount;
new_level->in_system_header_p = in_system_header;
new_level->next = current_tinst_level;
current_tinst_level = new_level;
depth_reached = tinst_depth;
#endif
- ++tinst_level_tick;
return 1;
}
input_location = current_tinst_level->locus;
current_tinst_level = current_tinst_level->next;
--tinst_depth;
- ++tinst_level_tick;
}
/* We're instantiating a deferred template; restore the template
current_tinst_level = level;
pop_tinst_level ();
+ if (current_tinst_level)
+ current_tinst_level->errors = errorcount+sorrycount;
return level->decl;
}
parms = INNERMOST_TEMPLATE_PARMS (parms);
for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
- if (parm == TREE_VALUE (TREE_VEC_ELT (parms, i)))
- return true;
+ {
+ tree p = TREE_VALUE (TREE_VEC_ELT (parms, i));
+ if (p == error_mark_node)
+ continue;
+
+ if (parm == p
+ || (DECL_INITIAL (parm)
+ && DECL_INITIAL (parm) == DECL_INITIAL (p)))
+ return true;
+ }
return false;
}
input_location = DECL_SOURCE_LOCATION (TYPE_NAME (type)) =
DECL_SOURCE_LOCATION (typedecl);
- TYPE_HAS_USER_CONSTRUCTOR (type) = TYPE_HAS_USER_CONSTRUCTOR (pattern);
- TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);
- TYPE_HAS_ARRAY_NEW_OPERATOR (type) = TYPE_HAS_ARRAY_NEW_OPERATOR (pattern);
- TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);
- TYPE_HAS_COPY_ASSIGN (type) = TYPE_HAS_COPY_ASSIGN (pattern);
- TYPE_HAS_CONST_COPY_ASSIGN (type) = TYPE_HAS_CONST_COPY_ASSIGN (pattern);
- TYPE_HAS_COPY_CTOR (type) = TYPE_HAS_COPY_CTOR (pattern);
- TYPE_HAS_CONST_COPY_CTOR (type) = TYPE_HAS_CONST_COPY_CTOR (pattern);
- TYPE_HAS_DEFAULT_CONSTRUCTOR (type) = TYPE_HAS_DEFAULT_CONSTRUCTOR (pattern);
- TYPE_HAS_CONVERSION (type) = TYPE_HAS_CONVERSION (pattern);
TYPE_PACKED (type) = TYPE_PACKED (pattern);
TYPE_ALIGN (type) = TYPE_ALIGN (pattern);
TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (pattern);
{
CLASSTYPE_VISIBILITY_SPECIFIED (type) = 1;
CLASSTYPE_VISIBILITY (type) = CLASSTYPE_VISIBILITY (pattern);
+ /* Adjust visibility for template arguments. */
+ determine_visibility (TYPE_MAIN_DECL (type));
}
CLASSTYPE_FINAL (type) = CLASSTYPE_FINAL (pattern);
--processing_template_decl;
set_current_access_from_decl (r);
finish_member_declaration (r);
+ /* Instantiate members marked with attribute used. */
+ if (r != error_mark_node && DECL_PRESERVE_P (r))
+ mark_used (r);
}
else
{
/*init_const_expr_p=*/false,
/*asmspec_tree=*/NULL_TREE,
/*flags=*/0);
+ /* Instantiate members marked with attribute used. */
+ if (r != error_mark_node && DECL_PRESERVE_P (r))
+ mark_used (r);
}
else if (TREE_CODE (r) == FIELD_DECL)
{
}
if (CLASSTYPE_LAMBDA_EXPR (type))
- maybe_add_lambda_conv_op (type);
-
- /* Set the file and line number information to whatever is given for
- the class itself. This puts error messages involving generated
+ {
+ tree decl = lambda_function (type);
+ if (decl)
+ {
+ tree lambda = CLASSTYPE_LAMBDA_EXPR (type);
+ if (LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda))
+ {
+ apply_lambda_return_type (lambda, void_type_node);
+ LAMBDA_EXPR_RETURN_TYPE (lambda) = NULL_TREE;
+ }
+ instantiate_decl (decl, false, false);
+ maybe_add_lambda_conv_op (type);
+ }
+ else
+ gcc_assert (errorcount);
+ }
+
+ /* Set the file and line number information to whatever is given for
+ the class itself. This puts error messages involving generated
implicit functions at a predictable point, and the same point
that would be used for non-template classes. */
input_location = DECL_SOURCE_LOCATION (typedecl);
/*integral_constant_expression_p=*/true);
if (!(complain & tf_warning))
--c_inhibit_evaluation_warnings;
+ /* Preserve the raw-reference nature of T. */
+ if (TREE_TYPE (t) && TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE
+ && REFERENCE_REF_P (r))
+ r = TREE_OPERAND (r, 0);
}
return r;
}
-/* Give a chain SPEC_PARM of PARM_DECLs, pack them into a
- NONTYPE_ARGUMENT_PACK. */
+/* Given a function parameter pack TMPL_PARM and some function parameters
+ instantiated from it at *SPEC_P, return a NONTYPE_ARGUMENT_PACK of them
+ and set *SPEC_P to point at the next point in the list. */
static tree
-make_fnparm_pack (tree spec_parm)
+extract_fnparm_pack (tree tmpl_parm, tree *spec_p)
{
/* Collect all of the extra "packed" parameters into an
argument pack. */
tree parmtypevec;
tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
tree argtypepack = cxx_make_type (TYPE_ARGUMENT_PACK);
- int i, len = list_length (spec_parm);
+ tree spec_parm = *spec_p;
+ int i, len;
+
+ for (len = 0; spec_parm; ++len, spec_parm = TREE_CHAIN (spec_parm))
+ if (tmpl_parm
+ && !function_parameter_expanded_from_pack_p (spec_parm, tmpl_parm))
+ break;
/* Fill in PARMVEC and PARMTYPEVEC with all of the parameters. */
parmvec = make_tree_vec (len);
parmtypevec = make_tree_vec (len);
+ spec_parm = *spec_p;
for (i = 0; i < len; i++, spec_parm = DECL_CHAIN (spec_parm))
{
TREE_VEC_ELT (parmvec, i) = spec_parm;
SET_ARGUMENT_PACK_ARGS (argpack, parmvec);
SET_ARGUMENT_PACK_ARGS (argtypepack, parmtypevec);
TREE_TYPE (argpack) = argtypepack;
+ *spec_p = spec_parm;
return argpack;
-}
+}
+
+/* Give a chain SPEC_PARM of PARM_DECLs, pack them into a
+ NONTYPE_ARGUMENT_PACK. */
+
+static tree
+make_fnparm_pack (tree spec_parm)
+{
+ return extract_fnparm_pack (NULL_TREE, &spec_parm);
+}
/* Substitute ARGS into T, which is an pack expansion
(i.e. TYPE_PACK_EXPANSION or EXPR_PACK_EXPANSION). Returns a
tree in_decl)
{
tree pattern;
- tree pack, packs = NULL_TREE, unsubstituted_packs = NULL_TREE;
+ tree pack, packs = NULL_TREE;
+ bool unsubstituted_packs = false;
+ bool real_packs = false;
+ int missing_level = 0;
int i, len = -1;
tree result;
- int incomplete = 0;
htab_t saved_local_specializations = NULL;
+ bool need_local_specializations = false;
+ int levels;
gcc_assert (PACK_EXPANSION_P (t));
pattern = PACK_EXPANSION_PATTERN (t);
+ /* Add in any args remembered from an earlier partial instantiation. */
+ args = add_to_template_args (PACK_EXPANSION_EXTRA_ARGS (t), args);
+
+ levels = TMPL_ARGS_DEPTH (args);
+
/* Determine the argument packs that will instantiate the parameter
packs used in the expansion expression. While we're at it,
compute the number of arguments to be expanded and make sure it
tree parm_pack = TREE_VALUE (pack);
tree arg_pack = NULL_TREE;
tree orig_arg = NULL_TREE;
+ int level = 0;
+ if (TREE_CODE (parm_pack) == BASES)
+ {
+ if (BASES_DIRECT (parm_pack))
+ return calculate_direct_bases (tsubst_expr (BASES_TYPE (parm_pack),
+ args, complain, in_decl, false));
+ else
+ return calculate_bases (tsubst_expr (BASES_TYPE (parm_pack),
+ args, complain, in_decl, false));
+ }
if (TREE_CODE (parm_pack) == PARM_DECL)
{
- if (!cp_unevaluated_operand)
+ if (PACK_EXPANSION_LOCAL_P (t))
arg_pack = retrieve_local_specialization (parm_pack);
else
{
arg_pack = NULL_TREE;
else
arg_pack = make_fnparm_pack (arg_pack);
+ need_local_specializations = true;
}
}
else
{
- int level, idx, levels;
+ int idx;
template_parm_level_and_index (parm_pack, &level, &idx);
- levels = TMPL_ARGS_DEPTH (args);
if (level <= levels)
arg_pack = TMPL_ARG (args, level, idx);
}
return result;
}
- /* For clarity in the comments below let's use the
- representation 'argument_pack<elements>' to denote an
- argument pack and its elements.
-
- In the 'if' block below, we want to detect cases where
- ARG_PACK is argument_pack<PARM_PACK...>. I.e, we want to
- check if ARG_PACK is an argument pack which sole element is
- the expansion of PARM_PACK. That argument pack is typically
- created by template_parm_to_arg when passed a parameter
- pack. */
- if (arg_pack
- && TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack)) == 1
- && PACK_EXPANSION_P (TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack), 0)))
- {
- tree expansion = TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack), 0);
- tree pattern = PACK_EXPANSION_PATTERN (expansion);
- /* So we have an argument_pack<P...>. We want to test if P
- is actually PARM_PACK. We will not use cp_tree_equal to
- test P and PARM_PACK because during type fixup (by
- fixup_template_parm) P can be a pre-fixup version of a
- type and PARM_PACK be its post-fixup version.
- cp_tree_equal would consider them as different even
- though we would want to consider them compatible for our
- precise purpose here.
-
- Thus we are going to consider that P and PARM_PACK are
- compatible if they have the same DECL. */
- if ((/* If ARG_PACK is a type parameter pack named by the
- same DECL as parm_pack ... */
- (TYPE_P (pattern)
- && TYPE_P (parm_pack)
- && TYPE_NAME (pattern) == TYPE_NAME (parm_pack))
- /* ... or if ARG_PACK is a non-type parameter
- named by the same DECL as parm_pack ... */
- || (TREE_CODE (pattern) == TEMPLATE_PARM_INDEX
- && TREE_CODE (parm_pack) == PARM_DECL
- && TEMPLATE_PARM_DECL (pattern)
- == TEMPLATE_PARM_DECL (DECL_INITIAL (parm_pack))))
- && template_parameter_pack_p (pattern))
- /* ... then the argument pack that the parameter maps to
- is just an expansion of the parameter itself, such as
- one would find in the implicit typedef of a class
- inside the class itself. Consider this parameter
- "unsubstituted", so that we will maintain the outer
- pack expansion. */
- arg_pack = NULL_TREE;
- }
+ if (arg_from_parm_pack_p (arg_pack, parm_pack))
+ /* The argument pack that the parameter maps to is just an
+ expansion of the parameter itself, such as one would find
+ in the implicit typedef of a class inside the class itself.
+ Consider this parameter "unsubstituted", so that we will
+ maintain the outer pack expansion. */
+ arg_pack = NULL_TREE;
if (arg_pack)
{
int my_len =
TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack));
- /* It's all-or-nothing with incomplete argument packs. */
- if (incomplete && !ARGUMENT_PACK_INCOMPLETE_P (arg_pack))
- return error_mark_node;
-
+ /* Don't bother trying to do a partial substitution with
+ incomplete packs; we'll try again after deduction. */
if (ARGUMENT_PACK_INCOMPLETE_P (arg_pack))
- incomplete = 1;
+ return t;
if (len < 0)
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)
+ if (!(complain & tf_error))
+ /* Fail quietly. */;
+ else if (TREE_CODE (t) == TYPE_PACK_EXPANSION)
error ("mismatched argument pack lengths while expanding "
"%<%T%>",
pattern);
return error_mark_node;
}
+ if (TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack)) == 1
+ && PACK_EXPANSION_P (TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack),
+ 0)))
+ /* This isn't a real argument pack yet. */;
+ else
+ real_packs = true;
+
/* Keep track of the parameter packs and their corresponding
argument packs. */
packs = tree_cons (parm_pack, arg_pack, packs);
TREE_TYPE (packs) = orig_arg;
}
else
- /* We can't substitute for this parameter pack. */
- unsubstituted_packs = tree_cons (TREE_PURPOSE (pack),
- TREE_VALUE (pack),
- unsubstituted_packs);
+ {
+ /* We can't substitute for this parameter pack. We use a flag as
+ well as the missing_level counter because function parameter
+ packs don't have a level. */
+ unsubstituted_packs = true;
+ if (!missing_level || missing_level > level)
+ missing_level = level;
+ }
}
/* We cannot expand this expansion expression, because we don't have
- all of the argument packs we need. Substitute into the pattern
- and return a PACK_EXPANSION_*. The caller will need to deal with
- that. */
+ all of the argument packs we need. */
if (unsubstituted_packs)
{
- tree new_pat;
- if (TREE_CODE (t) == EXPR_PACK_EXPANSION)
- new_pat = tsubst_expr (pattern, args, complain, in_decl,
- /*integral_constant_expression_p=*/false);
+ if (real_packs)
+ {
+ /* We got some full packs, but we can't substitute them in until we
+ have values for all the packs. So remember these until then. */
+ tree save_args;
+
+ t = make_pack_expansion (pattern);
+
+ /* The call to add_to_template_args above assumes no overlap
+ between saved args and new args, so prune away any fake
+ args, i.e. those that satisfied arg_from_parm_pack_p above. */
+ if (missing_level && levels >= missing_level)
+ {
+ gcc_assert (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)
+ && missing_level > 1);
+ TREE_VEC_LENGTH (args) = missing_level - 1;
+ save_args = copy_node (args);
+ TREE_VEC_LENGTH (args) = levels;
+ }
+ else
+ save_args = args;
+
+ PACK_EXPANSION_EXTRA_ARGS (t) = save_args;
+ }
else
- new_pat = tsubst (pattern, args, complain, in_decl);
- return make_pack_expansion (new_pat);
+ {
+ /* There were no real arguments, we're just replacing a parameter
+ pack with another version of itself. Substitute into the
+ pattern and return a PACK_EXPANSION_*. The caller will need to
+ deal with that. */
+ if (TREE_CODE (t) == EXPR_PACK_EXPANSION)
+ t = tsubst_expr (pattern, args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+ else
+ t = tsubst (pattern, args, complain, in_decl);
+ t = make_pack_expansion (t);
+ }
+ return t;
}
/* We could not find any argument packs that work. */
if (len < 0)
return error_mark_node;
- if (cp_unevaluated_operand)
+ if (need_local_specializations)
{
/* We're in a late-specified return type, so create our own local
specializations table; the current table is either NULL or (in the
/* For each argument in each argument pack, substitute into the
pattern. */
- result = make_tree_vec (len + incomplete);
- for (i = 0; i < len + incomplete; ++i)
+ result = make_tree_vec (len);
+ for (i = 0; i < len; ++i)
{
/* For parameter pack, change the substitution of the parameter
pack to the ith argument in its argument pack, then expand
for (pack = packs; pack; pack = TREE_CHAIN (pack))
{
tree parm = TREE_PURPOSE (pack);
+ tree arg;
+ /* Select the Ith argument from the pack. */
if (TREE_CODE (parm) == PARM_DECL)
{
- /* Select the Ith argument from the pack. */
- tree arg = make_node (ARGUMENT_PACK_SELECT);
- ARGUMENT_PACK_SELECT_FROM_PACK (arg) = TREE_VALUE (pack);
- ARGUMENT_PACK_SELECT_INDEX (arg) = i;
- mark_used (parm);
- register_local_specialization (arg, parm);
+ if (i == 0)
+ {
+ arg = make_node (ARGUMENT_PACK_SELECT);
+ ARGUMENT_PACK_SELECT_FROM_PACK (arg) = TREE_VALUE (pack);
+ mark_used (parm);
+ register_local_specialization (arg, parm);
+ }
+ else
+ arg = retrieve_local_specialization (parm);
}
else
{
- tree value = parm;
int idx, level;
template_parm_level_and_index (parm, &level, &idx);
-
- if (i < len)
+
+ if (i == 0)
{
- /* Select the Ith argument from the pack. */
- value = make_node (ARGUMENT_PACK_SELECT);
- ARGUMENT_PACK_SELECT_FROM_PACK (value) = TREE_VALUE (pack);
- ARGUMENT_PACK_SELECT_INDEX (value) = i;
+ arg = make_node (ARGUMENT_PACK_SELECT);
+ ARGUMENT_PACK_SELECT_FROM_PACK (arg) = TREE_VALUE (pack);
+ /* Update the corresponding argument. */
+ TMPL_ARG (args, level, idx) = arg;
}
-
- /* Update the corresponding argument. */
- TMPL_ARG (args, level, idx) = value;
+ else
+ /* Re-use the ARGUMENT_PACK_SELECT. */
+ arg = TMPL_ARG (args, level, idx);
}
+ ARGUMENT_PACK_SELECT_INDEX (arg) = i;
}
/* Substitute into the PATTERN with the altered arguments. */
else
TREE_VEC_ELT (result, i) = tsubst (pattern, args, complain, in_decl);
- if (i == len)
- /* When we have incomplete argument packs, the last "expanded"
- result is itself a pack expansion, which allows us
- to deduce more arguments. */
- TREE_VEC_ELT (result, i) =
- make_pack_expansion (TREE_VEC_ELT (result, i));
-
if (TREE_VEC_ELT (result, i) == error_mark_node)
{
result = error_mark_node;
}
}
- if (saved_local_specializations)
+ if (need_local_specializations)
{
htab_delete (local_specializations);
local_specializations = saved_local_specializations;
/* First, determine the context for the type we are looking
up. */
context = TYPE_CONTEXT (t);
- if (context)
+ if (context && TYPE_P (context))
{
context = tsubst_aggr_type (context, args, complain,
in_decl, /*entering_scope=*/1);
/* If context is a nested class inside a class template,
it may still need to be instantiated (c++/33959). */
- if (TYPE_P (context))
- context = complete_type (context);
+ context = complete_type (context);
}
/* Then, figure out what arguments are appropriate for the
DECL_TEMPLATE_INFO (r) = build_template_info (t, args);
- if (TREE_CODE (decl) == TYPE_DECL)
+ if (TREE_CODE (decl) == TYPE_DECL
+ && !TYPE_DECL_ALIAS_P (decl))
{
tree new_type;
++processing_template_decl;
TREE_TYPE (r) = type;
cp_apply_type_quals_to_decl (cp_type_quals (type), r);
- /* DECL_INITIAL gives the number of bits in a bit-field. */
- DECL_INITIAL (r)
- = tsubst_expr (DECL_INITIAL (t), args,
- complain, in_decl,
- /*integral_constant_expression_p=*/true);
+ if (DECL_C_BIT_FIELD (r))
+ /* For bit-fields, DECL_INITIAL gives the number of bits. For
+ non-bit-fields DECL_INITIAL is a non-static data member
+ initializer, which gets deferred instantiation. */
+ DECL_INITIAL (r)
+ = tsubst_expr (DECL_INITIAL (t), args,
+ complain, in_decl,
+ /*integral_constant_expression_p=*/true);
+ else if (DECL_INITIAL (t))
+ {
+ /* Set up DECL_TEMPLATE_INFO so that we can get at the
+ NSDMI in perform_member_init. Still set DECL_INITIAL
+ so that we know there is one. */
+ DECL_INITIAL (r) = void_zero_node;
+ gcc_assert (DECL_LANG_SPECIFIC (r) == NULL);
+ retrofit_lang_decl (r);
+ DECL_TEMPLATE_INFO (r) = build_template_info (t, args);
+ }
/* We don't have to set DECL_CONTEXT here; it is set by
finish_member_declaration. */
DECL_CHAIN (r) = NULL_TREE;
referencing a static data member within in its own
class. We can use pointer equality, rather than
same_type_p, because DECL_CONTEXT is always
- canonical. */
- if (ctx == DECL_CONTEXT (t))
+ canonical... */
+ if (ctx == DECL_CONTEXT (t)
+ && (TREE_CODE (t) != TYPE_DECL
+ /* ... unless T is a member template; in which
+ case our caller can be willing to create a
+ specialization of that template represented
+ by T. */
+ || !(DECL_TI_TEMPLATE (t)
+ && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (t)))))
spec = t;
}
type = DECL_ORIGINAL_TYPE (t);
else
type = TREE_TYPE (t);
- if (TREE_CODE (t) == VAR_DECL && VAR_HAD_UNKNOWN_BOUND (t))
+ if (TREE_CODE (t) == VAR_DECL
+ && VAR_HAD_UNKNOWN_BOUND (t)
+ && type != error_mark_node)
type = strip_array_domain (type);
type = tsubst (type, args, complain, in_decl);
}
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)
+ if (auto_node)
{
+ tree init
+ = tsubst_expr (DECL_INITIAL (t), args, complain, in_decl,
+ /*constant_expression_p=*/false);
init = resolve_nondeduced_context (init);
TREE_TYPE (r) = type
= do_auto_deduction (type, init, auto_node);
tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
enum tree_code code;
- tree type, r;
+ tree type, r = NULL_TREE;
if (t == NULL_TREE || t == error_mark_node
|| t == integer_type_node
&& typedef_variant_p (t))
{
tree decl = TYPE_NAME (t);
-
- if (DECL_CLASS_SCOPE_P (decl)
- && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
- && uses_template_parms (DECL_CONTEXT (decl)))
+
+ if (TYPE_DECL_ALIAS_P (decl)
+ && DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_INFO (decl)
+ && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl)))
+ {
+ /* DECL represents an alias template and we want to
+ instantiate it. Let's substitute our arguments for the
+ template parameters into the declaration and get the
+ resulting type. */
+ r = tsubst (decl, args, complain, decl);
+ }
+ else if (DECL_CLASS_SCOPE_P (decl)
+ && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
+ && uses_template_parms (DECL_CONTEXT (decl)))
{
tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
complain | tf_ignore_bad_quals);
return r;
}
- /* Else we must be instantiating the typedef, so fall through. */
+ else
+ /* We don't have an instantiation yet, so drop the typedef. */
+ t = DECL_ORIGINAL_TYPE (decl);
}
if (type
if (argvec == error_mark_node)
return error_mark_node;
+ gcc_assert (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+ || TREE_CODE (arg) == TEMPLATE_DECL
+ || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);
+
+ if (TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE)
+ /* Consider this code:
+
+ template <template <class> class Template>
+ struct Internal {
+ template <class Arg> using Bind = Template<Arg>;
+ };
+
+ template <template <class> class Template, class Arg>
+ using Instantiate = Template<Arg>; //#0
+
+ template <template <class> class Template,
+ class Argument>
+ using Bind =
+ Instantiate<Internal<Template>::template Bind,
+ Argument>; //#1
+
+ When #1 is parsed, the
+ BOUND_TEMPLATE_TEMPLATE_PARM representing the
+ parameter `Template' in #0 matches the
+ UNBOUND_CLASS_TEMPLATE representing the argument
+ `Internal<Template>::template Bind'; We then want
+ to assemble the type `Bind<Argument>' that can't
+ be fully created right now, because
+ `Internal<Template>' not being complete, the Bind
+ template cannot be looked up in that context. So
+ we need to "store" `Bind<Argument>' for later
+ when the context of Bind becomes complete. Let's
+ store that in a TYPENAME_TYPE. */
+ return make_typename_type (TYPE_CONTEXT (arg),
+ build_nt (TEMPLATE_ID_EXPR,
+ TYPE_IDENTIFIER (arg),
+ argvec),
+ typename_type,
+ complain);
+
/* We can get a TEMPLATE_TEMPLATE_PARM here when we
are resolving nested-types in the signature of a
member function templates. Otherwise ARG is a
}
else
/* TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX. */
- return unshare_expr (arg);
+ return convert_from_reference (unshare_expr (arg));
}
if (level == 1)
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 if (DECLTYPE_FOR_LAMBDA_PROXY (t))
type = lambda_proxy_type (type);
else
expr = name;
if (dependent_scope_p (scope))
- return build_qualified_name (NULL_TREE, scope, expr,
- QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
+ {
+ if (is_template)
+ expr = build_min_nt (TEMPLATE_ID_EXPR, expr, template_args);
+ return build_qualified_name (NULL_TREE, scope, expr,
+ QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
+ }
if (!BASELINK_P (name) && !DECL_P (expr))
{
expr = (adjust_result_of_qualified_name_lookup
(expr, scope, current_class_type));
expr = (finish_qualified_id_expr
- (scope, expr, done, address_p,
+ (scope, expr, done, address_p && PTRMEM_OK_P (qualified_id),
QUALIFIED_NAME_IS_TEMPLATE (qualified_id),
/*template_arg_p=*/false));
}
/* Like tsubst, but deals with expressions. This function just replaces
template parms; to finish processing the resultant expression, use
- tsubst_expr. */
+ tsubst_copy_and_build or tsubst_expr. */
static tree
tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (r == NULL)
{
tree c;
+
+ /* We get here for a use of 'this' in an NSDMI. */
+ if (DECL_NAME (t) == this_identifier
+ && at_function_scope_p ()
+ && DECL_CONSTRUCTOR_P (current_function_decl))
+ return current_class_ptr;
+
/* This can happen for a parameter name used later in a function
declaration (such as in a late-specified return type). Just
make a dummy decl, since it's only used for its type. */
mark_used (t);
return t;
+ case NAMESPACE_DECL:
+ return t;
+
case OVERLOAD:
/* An OVERLOAD will always be a non-dependent overload set; an
overload set from function scope will just be represented with an
case CONST_CAST_EXPR:
case STATIC_CAST_EXPR:
case DYNAMIC_CAST_EXPR:
+ case IMPLICIT_CONV_EXPR:
+ case CONVERT_EXPR:
case NOP_EXPR:
return build1
(code, tsubst (TREE_TYPE (t), args, complain, in_decl),
base, name,
/*template_p=*/false);
}
- else if (TREE_CODE (name) == BASELINK)
+ else if (BASELINK_P (name))
name = tsubst_baselink (name,
non_reference (TREE_TYPE (object)),
args, complain,
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_COLLAPSE:
+ case OMP_CLAUSE_FINAL:
OMP_CLAUSE_OPERAND (nc, 0)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
+ case OMP_CLAUSE_MERGEABLE:
break;
default:
gcc_unreachable ();
if (purpose)
purpose = RECUR (purpose);
value = TREE_VALUE (t);
- if (value && TREE_CODE (value) != LABEL_DECL)
- value = RECUR (value);
+ if (value)
+ {
+ if (TREE_CODE (value) != LABEL_DECL)
+ value = RECUR (value);
+ else
+ {
+ value = lookup_label (DECL_NAME (value));
+ gcc_assert (TREE_CODE (value) == LABEL_DECL);
+ TREE_USED (value) = 1;
+ }
+ }
chain = TREE_CHAIN (t);
if (chain && chain != void_type_node)
chain = RECUR (chain);
&& ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
/* Anonymous aggregates are a special case. */
finish_anon_union (decl);
+ else if (is_capture_proxy (DECL_EXPR_DECL (t)))
+ {
+ DECL_CONTEXT (decl) = current_function_decl;
+ insert_capture_proxy (decl);
+ }
else
{
int const_init = false;
case OMP_ATOMIC:
gcc_assert (OMP_ATOMIC_DEPENDENT_P (t));
+ if (TREE_CODE (TREE_OPERAND (t, 1)) != MODIFY_EXPR)
+ {
+ tree op1 = TREE_OPERAND (t, 1);
+ tree rhs1 = NULL_TREE;
+ tree lhs, rhs;
+ if (TREE_CODE (op1) == COMPOUND_EXPR)
+ {
+ rhs1 = RECUR (TREE_OPERAND (op1, 0));
+ op1 = TREE_OPERAND (op1, 1);
+ }
+ lhs = RECUR (TREE_OPERAND (op1, 0));
+ rhs = RECUR (TREE_OPERAND (op1, 1));
+ finish_omp_atomic (OMP_ATOMIC, TREE_CODE (op1), lhs, rhs,
+ NULL_TREE, NULL_TREE, rhs1);
+ }
+ else
+ {
+ tree op1 = TREE_OPERAND (t, 1);
+ tree v = NULL_TREE, lhs, rhs = NULL_TREE, lhs1 = NULL_TREE;
+ tree rhs1 = NULL_TREE;
+ enum tree_code code = TREE_CODE (TREE_OPERAND (op1, 1));
+ enum tree_code opcode = NOP_EXPR;
+ if (code == OMP_ATOMIC_READ)
+ {
+ v = RECUR (TREE_OPERAND (op1, 0));
+ lhs = RECUR (TREE_OPERAND (TREE_OPERAND (op1, 1), 0));
+ }
+ else if (code == OMP_ATOMIC_CAPTURE_OLD
+ || code == OMP_ATOMIC_CAPTURE_NEW)
+ {
+ tree op11 = TREE_OPERAND (TREE_OPERAND (op1, 1), 1);
+ v = RECUR (TREE_OPERAND (op1, 0));
+ lhs1 = RECUR (TREE_OPERAND (TREE_OPERAND (op1, 1), 0));
+ if (TREE_CODE (op11) == COMPOUND_EXPR)
+ {
+ rhs1 = RECUR (TREE_OPERAND (op11, 0));
+ op11 = TREE_OPERAND (op11, 1);
+ }
+ lhs = RECUR (TREE_OPERAND (op11, 0));
+ rhs = RECUR (TREE_OPERAND (op11, 1));
+ opcode = TREE_CODE (op11);
+ }
+ else
+ {
+ code = OMP_ATOMIC;
+ lhs = RECUR (TREE_OPERAND (op1, 0));
+ rhs = RECUR (TREE_OPERAND (op1, 1));
+ }
+ finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1);
+ }
+ break;
+
+ case TRANSACTION_EXPR:
{
- tree op1 = TREE_OPERAND (t, 1);
- tree lhs = RECUR (TREE_OPERAND (op1, 0));
- tree rhs = RECUR (TREE_OPERAND (op1, 1));
- finish_omp_atomic (TREE_CODE (op1), lhs, rhs);
+ int flags = 0;
+ flags |= (TRANSACTION_EXPR_OUTER (t) ? TM_STMT_ATTR_OUTER : 0);
+ flags |= (TRANSACTION_EXPR_RELAXED (t) ? TM_STMT_ATTR_RELAXED : 0);
+
+ if (TRANSACTION_EXPR_IS_STMT (t))
+ {
+ tree body = TRANSACTION_EXPR_BODY (t);
+ tree noex = NULL_TREE;
+ if (TREE_CODE (body) == MUST_NOT_THROW_EXPR)
+ {
+ noex = MUST_NOT_THROW_COND (body);
+ if (noex == NULL_TREE)
+ noex = boolean_true_node;
+ body = TREE_OPERAND (body, 0);
+ }
+ stmt = begin_transaction_stmt (input_location, NULL, flags);
+ RECUR (body);
+ finish_transaction_stmt (stmt, NULL, flags, RECUR (noex));
+ }
+ else
+ {
+ stmt = build_transaction_expr (EXPR_LOCATION (t),
+ RECUR (TRANSACTION_EXPR_BODY (t)),
+ flags, NULL_TREE);
+ return stmt;
+ }
}
break;
+ case MUST_NOT_THROW_EXPR:
+ return build_must_not_throw_expr (RECUR (TREE_OPERAND (t, 0)),
+ RECUR (MUST_NOT_THROW_COND (t)));
+
case EXPR_PACK_EXPANSION:
error ("invalid use of pack expansion expression");
return error_mark_node;
decl = finish_id_expression (t, decl, NULL_TREE,
&idk,
integral_constant_expression_p,
- /*allow_non_integral_constant_expression_p=*/false,
+ /*allow_non_integral_constant_expression_p=*/(cxx_dialect >= cxx0x),
&non_integral_constant_expression_p,
/*template_p=*/false,
/*done=*/true,
if (error_msg)
error (error_msg);
if (!function_p && TREE_CODE (decl) == IDENTIFIER_NODE)
- decl = unqualified_name_lookup_error (decl);
+ {
+ if (complain & tf_error)
+ unqualified_name_lookup_error (decl);
+ decl = error_mark_node;
+ }
return decl;
}
(tsubst (TREE_TYPE (t), args, complain, in_decl),
RECUR (TREE_OPERAND (t, 0)));
+ case IMPLICIT_CONV_EXPR:
+ {
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree expr = RECUR (TREE_OPERAND (t, 0));
+ int flags = LOOKUP_IMPLICIT;
+ if (IMPLICIT_CONV_EXPR_DIRECT_INIT (t))
+ flags = LOOKUP_NORMAL;
+ return perform_implicit_conversion_flags (type, expr, complain,
+ flags);
+ }
+
+ case CONVERT_EXPR:
+ return build1
+ (CONVERT_EXPR,
+ tsubst (TREE_TYPE (t), args, complain, in_decl),
+ RECUR (TREE_OPERAND (t, 0)));
+
case CAST_EXPR:
case REINTERPRET_CAST_EXPR:
case CONST_CAST_EXPR:
return build_x_unary_op (TREE_CODE (t), RECUR (TREE_OPERAND (t, 0)),
complain);
+ case FIX_TRUNC_EXPR:
+ return cp_build_unary_op (FIX_TRUNC_EXPR, RECUR (TREE_OPERAND (t, 0)),
+ 0, complain);
+
case ADDR_EXPR:
op1 = TREE_OPERAND (t, 0);
if (TREE_CODE (op1) == LABEL_DECL)
case GT_EXPR:
case MEMBER_REF:
case DOTSTAR_EXPR:
- return build_x_binary_op
- (TREE_CODE (t),
- RECUR (TREE_OPERAND (t, 0)),
- (TREE_NO_WARNING (TREE_OPERAND (t, 0))
- ? ERROR_MARK
- : TREE_CODE (TREE_OPERAND (t, 0))),
- RECUR (TREE_OPERAND (t, 1)),
- (TREE_NO_WARNING (TREE_OPERAND (t, 1))
- ? ERROR_MARK
- : TREE_CODE (TREE_OPERAND (t, 1))),
- /*overload=*/NULL,
- complain);
+ {
+ tree r = build_x_binary_op
+ (TREE_CODE (t),
+ RECUR (TREE_OPERAND (t, 0)),
+ (TREE_NO_WARNING (TREE_OPERAND (t, 0))
+ ? ERROR_MARK
+ : TREE_CODE (TREE_OPERAND (t, 0))),
+ RECUR (TREE_OPERAND (t, 1)),
+ (TREE_NO_WARNING (TREE_OPERAND (t, 1))
+ ? ERROR_MARK
+ : TREE_CODE (TREE_OPERAND (t, 1))),
+ /*overload=*/NULL,
+ complain);
+ if (EXPR_P (r) && TREE_NO_WARNING (t))
+ TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
+ return r;
+ }
case SCOPE_REF:
return tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
tree unq = (tsubst_copy_and_build
(function, args, complain, in_decl, true,
integral_constant_expression_p));
+ if (unq == error_mark_node)
+ return error_mark_node;
+
if (unq != function)
{
tree fn = unq;
+ if (TREE_CODE (fn) == INDIRECT_REF)
+ fn = TREE_OPERAND (fn, 0);
if (TREE_CODE (fn) == COMPONENT_REF)
fn = TREE_OPERAND (fn, 1);
if (is_overloaded_fn (fn))
"and no declarations were found by "
"argument-dependent lookup at the point "
"of instantiation", function);
- if (DECL_CLASS_SCOPE_P (fn))
+ if (!DECL_P (fn))
+ /* Can't say anything more. */;
+ else if (DECL_CLASS_SCOPE_P (fn))
{
inform (EXPR_LOC_OR_HERE (t),
"declarations in dependent base %qT are "
if (member == error_mark_node)
return error_mark_node;
- if (object_type && !CLASS_TYPE_P (object_type))
+ if (type_dependent_expression_p (object))
+ /* We can't do much here. */;
+ else if (!CLASS_TYPE_P (object_type))
{
if (SCALAR_TYPE_P (object_type))
{
else if (TREE_CODE (member) == SCOPE_REF
&& TREE_CODE (TREE_OPERAND (member, 1)) == TEMPLATE_ID_EXPR)
{
- tree tmpl;
- tree args;
-
/* Lookup the template functions now that we know what the
scope is. */
- tmpl = TREE_OPERAND (TREE_OPERAND (member, 1), 0);
- args = TREE_OPERAND (TREE_OPERAND (member, 1), 1);
- member = lookup_qualified_name (TREE_OPERAND (member, 0), tmpl,
+ tree scope = TREE_OPERAND (member, 0);
+ tree tmpl = TREE_OPERAND (TREE_OPERAND (member, 1), 0);
+ tree args = TREE_OPERAND (TREE_OPERAND (member, 1), 1);
+ member = lookup_qualified_name (scope, tmpl,
/*is_type_p=*/false,
/*complain=*/false);
if (BASELINK_P (member))
}
else
{
- qualified_name_lookup_error (object_type, tmpl, member,
+ qualified_name_lookup_error (scope, tmpl, member,
input_location);
return error_mark_node;
}
t = tsubst_copy (t, args, complain, in_decl);
/* As in finish_id_expression, we resolve enumeration constants
to their underlying values. */
- if (TREE_CODE (t) == CONST_DECL)
+ if (TREE_CODE (t) == CONST_DECL && !processing_template_decl)
{
used_types_insert (TREE_TYPE (t));
return DECL_INITIAL (t);
{
tree r = build_lambda_expr ();
- tree type = tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
- TREE_TYPE (r) = type;
+ tree type = tsubst (LAMBDA_EXPR_CLOSURE (t), args, complain, NULL_TREE);
+ LAMBDA_EXPR_CLOSURE (r) = type;
CLASSTYPE_LAMBDA_EXPR (type) = r;
LAMBDA_EXPR_LOCATION (r)
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_EXTRA_SCOPE (r)
= RECUR (LAMBDA_EXPR_EXTRA_SCOPE (t));
+ if (LAMBDA_EXPR_RETURN_TYPE (t) == dependent_lambda_return_type_node)
+ {
+ LAMBDA_EXPR_RETURN_TYPE (r) = dependent_lambda_return_type_node;
+ LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (r) = true;
+ }
+ else
+ LAMBDA_EXPR_RETURN_TYPE (r)
+ = tsubst (LAMBDA_EXPR_RETURN_TYPE (t), args, complain, in_decl);
+
gcc_assert (LAMBDA_EXPR_THIS_CAPTURE (t) == NULL_TREE
&& LAMBDA_EXPR_PENDING_PROXIES (t) == NULL);
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);
+ /* The capture list refers to closure members, so this needs to
+ wait until after we finish instantiating the type. */
+ LAMBDA_EXPR_CAPTURE_LIST (r)
+ = RECUR (LAMBDA_EXPR_CAPTURE_LIST (t));
return build_lambda_object (r);
}
return r;
}
+ case TRANSACTION_EXPR:
+ return tsubst_expr(t, args, complain, in_decl,
+ integral_constant_expression_p);
+
default:
/* Handle Objective-C++ constructs, if appropriate. */
{
This is, of course, not reentrant. */
static tree
-deduction_tsubst_fntype (tree fn, tree targs)
+deduction_tsubst_fntype (tree fn, tree targs, tsubst_flags_t complain)
{
static bool excessive_deduction_depth;
static int deduction_depth;
struct pending_template *old_last_pend = last_pending_template;
+ struct tinst_level *old_error_tinst = last_error_tinst_level;
tree fntype = TREE_TYPE (fn);
tree tinst;
input_location = DECL_SOURCE_LOCATION (fn);
++deduction_depth;
push_deduction_access_scope (fn);
- r = tsubst (fntype, targs, tf_none, NULL_TREE);
+ r = tsubst (fntype, targs, complain, NULL_TREE);
pop_deduction_access_scope (fn);
--deduction_depth;
}
pop_tinst_level ();
- /* We can't free this if a pending_template entry is pointing at it. */
- if (last_pending_template == old_last_pend)
+ /* We can't free this if a pending_template entry or last_error_tinst_level
+ is pointing at it. */
+ if (last_pending_template == old_last_pend
+ && last_error_tinst_level == old_error_tinst)
ggc_free (tinst);
return r;
}
tree fndecl;
tree gen_tmpl;
tree spec;
- HOST_WIDE_INT saved_processing_template_decl;
if (tmpl == error_mark_node)
return error_mark_node;
deferring all checks until we have the FUNCTION_DECL. */
push_deferring_access_checks (dk_deferred);
- /* Although PROCESSING_TEMPLATE_DECL may be true at this point
- (because, for example, we have encountered a non-dependent
- function call in the body of a template function and must now
- determine which of several overloaded functions will be called),
- within the instantiation itself we are not processing a
- template. */
- saved_processing_template_decl = processing_template_decl;
- processing_template_decl = 0;
+ /* Instantiation of the function happens in the context of the function
+ template, not the context of the overload resolution we're doing. */
+ push_to_top_level ();
+ if (DECL_CLASS_SCOPE_P (gen_tmpl))
+ {
+ tree ctx = tsubst (DECL_CONTEXT (gen_tmpl), targ_ptr,
+ complain, gen_tmpl);
+ push_nested_class (ctx);
+ }
/* Substitute template parameters to obtain the specialization. */
fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
targ_ptr, complain, gen_tmpl);
- processing_template_decl = saved_processing_template_decl;
+ if (DECL_CLASS_SCOPE_P (gen_tmpl))
+ pop_nested_class ();
+ pop_from_top_level ();
+
if (fndecl == error_mark_node)
return error_mark_node;
push_deduction_access_scope (tree tmpl)
{
if (cxx_dialect >= cxx0x)
- push_access_scope (DECL_TEMPLATE_RESULT (tmpl));
+ {
+ int ptd = processing_template_decl;
+ push_access_scope (DECL_TEMPLATE_RESULT (tmpl));
+ /* Preserve processing_template_decl across push_to_top_level. */
+ if (ptd && !processing_template_decl)
+ ++processing_template_decl;
+ }
else
push_deferring_access_checks (dk_no_check);
}
pop_deferring_access_checks ();
}
+/* PARM is a template parameter pack for FN. Returns true iff
+ PARM is used in a deducible way in the argument list of FN. */
+
+static bool
+pack_deducible_p (tree parm, tree fn)
+{
+ tree t = FUNCTION_FIRST_USER_PARMTYPE (fn);
+ for (; t; t = TREE_CHAIN (t))
+ {
+ tree type = TREE_VALUE (t);
+ tree packs;
+ if (!PACK_EXPANSION_P (type))
+ continue;
+ for (packs = PACK_EXPANSION_PARAMETER_PACKS (type);
+ packs; packs = TREE_CHAIN (packs))
+ if (TREE_VALUE (packs) == parm)
+ {
+ /* The template parameter pack is used in a function parameter
+ pack. If this is the end of the parameter list, the
+ template parameter pack is deducible. */
+ if (TREE_CHAIN (t) == void_list_node)
+ return true;
+ else
+ /* Otherwise, not. Well, it could be deduced from
+ a non-pack parameter, but doing so would end up with
+ a deduction mismatch, so don't bother. */
+ return false;
+ }
+ }
+ /* The template parameter pack isn't used in any function parameter
+ packs, but it might be used deeper, e.g. tuple<Args...>. */
+ return true;
+}
+
/* The FN is a TEMPLATE_DECL for a function. ARGS is an array with
NARGS elements of the arguments that are being used when calling
it. TARGS is a vector into which the deduced template arguments
unsigned int nargs,
tree return_type,
unification_kind_t strict,
- int flags)
+ int flags,
+ bool explain_p)
{
tree parms;
tree fntype;
int result;
- bool incomplete_argument_packs_p = false;
gcc_assert (TREE_CODE (fn) == TEMPLATE_DECL);
bool incomplete = false;
if (explicit_targs == error_mark_node)
- return 1;
+ return unify_invalid (explain_p);
converted_args
- = (coerce_template_parms (tparms, explicit_targs, NULL_TREE, tf_none,
- /*require_all_args=*/false,
- /*use_default_args=*/false));
+ = (coerce_template_parms (tparms, explicit_targs, NULL_TREE,
+ (explain_p
+ ? tf_warning_or_error
+ : tf_none),
+ /*require_all_args=*/false,
+ /*use_default_args=*/false));
if (converted_args == error_mark_node)
return 1;
{
tree parm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
bool parameter_pack = false;
+ tree targ = TREE_VEC_ELT (converted_args, i);
/* Dig out the actual parm. */
if (TREE_CODE (parm) == TYPE_DECL
parameter_pack = TEMPLATE_PARM_PARAMETER_PACK (parm);
}
- if (parameter_pack)
- {
- int level, idx;
- tree targ;
- template_parm_level_and_index (parm, &level, &idx);
+ if (!parameter_pack && targ == NULL_TREE)
+ /* No explicit argument for this template parameter. */
+ incomplete = true;
+ if (parameter_pack && pack_deducible_p (parm, fn))
+ {
/* Mark the argument pack as "incomplete". We could
still deduce more arguments during unification.
We remove this mark in type_unification_real. */
- targ = TMPL_ARG (converted_args, level, idx);
if (targ)
{
ARGUMENT_PACK_INCOMPLETE_P(targ) = 1;
}
/* We have some incomplete argument packs. */
- incomplete_argument_packs_p = true;
+ incomplete = true;
}
}
- if (incomplete_argument_packs_p)
- /* Any substitution is guaranteed to be incomplete if there
- are incomplete argument packs, because we can still deduce
- more arguments. */
- incomplete = 1;
- else
- incomplete = NUM_TMPL_ARGS (explicit_targs) != NUM_TMPL_ARGS (targs);
-
processing_template_decl += incomplete;
- fntype = deduction_tsubst_fntype (fn, converted_args);
+ fntype = deduction_tsubst_fntype (fn, converted_args,
+ (explain_p
+ ? tf_warning_or_error
+ : tf_none));
processing_template_decl -= incomplete;
if (fntype == error_mark_node)
event. */
result = type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
targs, parms, args, nargs, /*subr=*/0,
- strict, flags);
+ strict, flags, explain_p);
/* Now that we have bindings for all of the template arguments,
ensure that the arguments deduced for the template template
if (result == 0
&& !template_template_parm_bindings_ok_p
(DECL_INNERMOST_TEMPLATE_PARMS (fn), targs))
- return 1;
+ return unify_inconsistent_template_template_parameters (explain_p);
if (result == 0)
/* All is well so far. Now, check:
substitution results in an invalid type, as described above,
type deduction fails. */
{
- tree substed = deduction_tsubst_fntype (fn, targs);
+ tree substed = deduction_tsubst_fntype (fn, targs,
+ (explain_p
+ ? tf_warning_or_error
+ : tf_none));
if (substed == error_mark_node)
return 1;
sarg = tree_cons (NULL_TREE, TREE_TYPE (substed), sarg);
for (i = 0; i < nargs && sarg; ++i, sarg = TREE_CHAIN (sarg))
if (!same_type_p (args[i], TREE_VALUE (sarg)))
- return 1;
+ return unify_type_mismatch (explain_p, args[i],
+ TREE_VALUE (sarg));
}
}
return result;
}
+/* Subroutine of unify_one_argument. PARM is a function parameter of a
+ template which does contain any deducible template parameters; check if
+ ARG is a suitable match for it. STRICT, FLAGS and EXPLAIN_P are as in
+ unify_one_argument. */
+
+static int
+check_non_deducible_conversion (tree parm, tree arg, int strict,
+ int flags, bool explain_p)
+{
+ tree type;
+
+ if (!TYPE_P (arg))
+ type = TREE_TYPE (arg);
+ else
+ type = arg;
+
+ if (same_type_p (parm, type))
+ return unify_success (explain_p);
+
+ if (strict == DEDUCE_CONV)
+ {
+ if (can_convert_arg (type, parm, NULL_TREE, flags))
+ return unify_success (explain_p);
+ }
+ else if (strict != DEDUCE_EXACT)
+ {
+ if (can_convert_arg (parm, type,
+ TYPE_P (arg) ? NULL_TREE : arg,
+ flags))
+ return unify_success (explain_p);
+ }
+
+ if (strict == DEDUCE_EXACT)
+ return unify_type_mismatch (explain_p, parm, arg);
+ else
+ return unify_arg_conversion (explain_p, parm, type, arg);
+}
+
+/* Subroutine of type_unification_real and unify_pack_expansion to
+ handle unification of a single P/A pair. Parameters are as
+ for those functions. */
+
+static int
+unify_one_argument (tree tparms, tree targs, tree parm, tree arg,
+ int subr, unification_kind_t strict, int flags,
+ bool explain_p)
+{
+ tree arg_expr = NULL_TREE;
+ int arg_strict;
+
+ if (arg == error_mark_node || parm == error_mark_node)
+ return unify_invalid (explain_p);
+ if (arg == unknown_type_node)
+ /* We can't deduce anything from this, but we might get all the
+ template args from other function args. */
+ return unify_success (explain_p);
+
+ /* FIXME uses_deducible_template_parms */
+ if (TYPE_P (parm) && !uses_template_parms (parm))
+ return check_non_deducible_conversion (parm, arg, strict, flags,
+ explain_p);
+
+ switch (strict)
+ {
+ case DEDUCE_CALL:
+ arg_strict = (UNIFY_ALLOW_OUTER_LEVEL
+ | UNIFY_ALLOW_MORE_CV_QUAL
+ | UNIFY_ALLOW_DERIVED);
+ break;
+
+ case DEDUCE_CONV:
+ arg_strict = UNIFY_ALLOW_LESS_CV_QUAL;
+ break;
+
+ case DEDUCE_EXACT:
+ arg_strict = UNIFY_ALLOW_NONE;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* We only do these transformations if this is the top-level
+ parameter_type_list in a call or declaration matching; in other
+ situations (nested function declarators, template argument lists) we
+ won't be comparing a type to an expression, and we don't do any type
+ adjustments. */
+ if (!subr)
+ {
+ if (!TYPE_P (arg))
+ {
+ gcc_assert (TREE_TYPE (arg) != NULL_TREE);
+ if (type_unknown_p (arg))
+ {
+ /* [temp.deduct.type] A template-argument can be
+ deduced from a pointer to function or pointer
+ to member function argument if the set of
+ overloaded functions does not contain function
+ templates and at most one of a set of
+ overloaded functions provides a unique
+ match. */
+
+ if (resolve_overloaded_unification
+ (tparms, targs, parm, arg, strict,
+ arg_strict, explain_p))
+ return unify_success (explain_p);
+ return unify_overload_resolution_failure (explain_p, arg);
+ }
+
+ arg_expr = arg;
+ arg = unlowered_expr_type (arg);
+ if (arg == error_mark_node)
+ return unify_invalid (explain_p);
+ }
+
+ arg_strict |=
+ maybe_adjust_types_for_deduction (strict, &parm, &arg, arg_expr);
+ }
+ else
+ gcc_assert ((TYPE_P (parm) || TREE_CODE (parm) == TEMPLATE_DECL)
+ == (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL));
+
+ /* For deduction from an init-list we need the actual list. */
+ if (arg_expr && BRACE_ENCLOSED_INITIALIZER_P (arg_expr))
+ arg = arg_expr;
+ return unify (tparms, targs, parm, arg, arg_strict, explain_p);
+}
+
/* Most parms like fn_type_unification.
If SUBR is 1, we're being called recursively (to unify the
unsigned int xnargs,
int subr,
unification_kind_t strict,
- int flags)
+ int flags,
+ bool explain_p)
{
- tree parm, arg, arg_expr;
+ tree parm, arg;
int i;
int ntparms = TREE_VEC_LENGTH (tparms);
- int sub_strict;
int saw_undeduced = 0;
tree parms;
const tree *args;
in TARGS. */
NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs) = NULL_TREE;
- switch (strict)
- {
- case DEDUCE_CALL:
- sub_strict = (UNIFY_ALLOW_OUTER_LEVEL | UNIFY_ALLOW_MORE_CV_QUAL
- | UNIFY_ALLOW_DERIVED);
- break;
-
- case DEDUCE_CONV:
- sub_strict = UNIFY_ALLOW_LESS_CV_QUAL;
- break;
-
- case DEDUCE_EXACT:
- sub_strict = UNIFY_ALLOW_NONE;
- break;
-
- default:
- gcc_unreachable ();
- }
-
again:
parms = xparms;
args = xargs;
arg = args[ia];
++ia;
- arg_expr = NULL;
- if (arg == error_mark_node)
+ if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
+ flags, explain_p))
return 1;
- if (arg == unknown_type_node)
- /* We can't deduce anything from this, but we might get all the
- template args from other function args. */
- continue;
-
- /* Conversions will be performed on a function argument that
- corresponds with a function parameter that contains only
- non-deducible template parameters and explicitly specified
- template parameters. */
- if (!uses_template_parms (parm))
- {
- tree type;
-
- if (!TYPE_P (arg))
- type = TREE_TYPE (arg);
- else
- type = arg;
-
- if (same_type_p (parm, type))
- continue;
- if (strict != DEDUCE_EXACT
- && can_convert_arg (parm, type, TYPE_P (arg) ? NULL_TREE : arg,
- flags))
- continue;
-
- return 1;
- }
-
- if (!TYPE_P (arg))
- {
- gcc_assert (TREE_TYPE (arg) != NULL_TREE);
- if (type_unknown_p (arg))
- {
- /* [temp.deduct.type]
-
- A template-argument can be deduced from a pointer to
- function or pointer to member function argument if
- the set of overloaded functions does not contain
- function templates and at most one of a set of
- overloaded functions provides a unique match. */
- if (resolve_overloaded_unification
- (tparms, targs, parm, arg, strict, sub_strict))
- continue;
-
- return 1;
- }
- arg_expr = arg;
- arg = unlowered_expr_type (arg);
- if (arg == error_mark_node)
- return 1;
- }
-
- {
- int arg_strict = sub_strict;
-
- if (!subr)
- arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg,
- arg_expr);
-
- if (arg == init_list_type_node && arg_expr)
- arg = arg_expr;
- if (unify (tparms, targs, parm, arg, arg_strict))
- return 1;
- }
}
-
if (parms
&& parms != void_list_node
&& TREE_CODE (TREE_VALUE (parms)) == TYPE_PACK_EXPANSION)
/* Copy the parameter into parmvec. */
TREE_VEC_ELT (parmvec, 0) = TREE_VALUE (parms);
if (unify_pack_expansion (tparms, targs, parmvec, argvec, strict,
- /*call_args_p=*/true, /*subr=*/subr))
+ /*subr=*/subr, explain_p))
return 1;
/* Advance to the end of the list of parameters. */
/* Fail if we've reached the end of the parm list, and more args
are present, and the parm list isn't variadic. */
if (ia < nargs && parms == void_list_node)
- return 1;
+ return unify_too_many_arguments (explain_p, nargs, ia);
/* Fail if parms are left and they don't have default values. */
if (parms && parms != void_list_node
&& TREE_PURPOSE (parms) == NULL_TREE)
- return 1;
+ {
+ unsigned int count = nargs;
+ tree p = parms;
+ while (p && p != void_list_node)
+ {
+ count++;
+ p = TREE_CHAIN (p);
+ }
+ return unify_too_few_arguments (explain_p, ia, count);
+ }
if (!subr)
{
+ tsubst_flags_t complain = (explain_p
+ ? tf_warning_or_error
+ : tf_none);
+
/* Check to see if we need another pass before we start clearing
ARGUMENT_PACK_INCOMPLETE_P. */
for (i = 0; i < ntparms; i++)
{
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,
+ location_t save_loc = input_location;
+ if (DECL_P (parm))
+ input_location = DECL_SOURCE_LOCATION (parm);
+ arg = tsubst_template_arg (arg, targs, complain, NULL_TREE);
+ arg = convert_template_argument (parm, arg, targs, complain,
i, NULL_TREE);
+ input_location = save_loc;
if (arg == error_mark_node)
return 1;
else
continue;
}
- return 2;
+ return unify_parameter_deduction_failure (explain_p, tparm);
}
}
#ifdef ENABLE_CHECKING
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, TREE_VEC_LENGTH (targs));
#endif
- return 0;
+ return unify_success (explain_p);
}
/* Subroutine of type_unification_real. Args are like the variables
tree parm,
tree arg,
unification_kind_t strict,
- int sub_strict)
+ int sub_strict,
+ bool explain_p)
{
tree tempargs = copy_node (targs);
int good = 0;
{
elem = tsubst (TREE_TYPE (fn), subargs, tf_none, NULL_TREE);
if (try_one_overload (tparms, targs, tempargs, parm,
- elem, strict, sub_strict, addr_p)
- && (!goodfn || !decls_match (goodfn, elem)))
+ elem, strict, sub_strict, addr_p, explain_p)
+ && (!goodfn || !same_type_p (goodfn, elem)))
{
goodfn = elem;
++good;
for (; arg; arg = OVL_NEXT (arg))
if (try_one_overload (tparms, targs, tempargs, parm,
TREE_TYPE (OVL_CURRENT (arg)),
- strict, sub_strict, addr_p)
+ strict, sub_strict, addr_p, explain_p)
&& (!goodfn || !decls_match (goodfn, OVL_CURRENT (arg))))
{
goodfn = OVL_CURRENT (arg);
offset = expr;
expr = TREE_OPERAND (expr, 1);
}
- if (TREE_CODE (expr) == BASELINK)
+ if (BASELINK_P (expr))
{
baselink = expr;
expr = BASELINK_FUNCTIONS (expr);
}
if (good == 1)
{
+ mark_used (goodfn);
expr = goodfn;
if (baselink)
expr = build_baselink (BASELINK_BINFO (baselink),
tree arg,
unification_kind_t strict,
int sub_strict,
- bool addr_p)
+ bool addr_p,
+ bool explain_p)
{
int nargs;
tree tempargs;
nargs = TREE_VEC_LENGTH (targs);
tempargs = make_tree_vec (nargs);
- if (unify (tparms, tempargs, parm, arg, sub_strict) != 0)
+ if (unify (tparms, tempargs, parm, arg, sub_strict, explain_p))
return 0;
/* First make sure we didn't deduce anything that conflicts with
TARGS are as for unify. */
static tree
-try_class_unification (tree tparms, tree targs, tree parm, tree arg)
+try_class_unification (tree tparms, tree targs, tree parm, tree arg,
+ bool explain_p)
{
tree copy_of_targs;
/* If unification failed, we're done. */
if (unify (tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm),
- CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE))
+ CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE, explain_p))
return NULL_TREE;
return arg;
a partial specialization, as well as a plain template type. Used
by unify. */
-static tree
-get_template_base (tree tparms, tree targs, tree parm, tree arg)
+static enum template_base_result
+get_template_base (tree tparms, tree targs, tree parm, tree arg,
+ bool explain_p, tree *result)
{
tree rval = NULL_TREE;
tree binfo;
binfo = TYPE_BINFO (complete_type (arg));
if (!binfo)
- /* The type could not be completed. */
- return NULL_TREE;
+ {
+ /* The type could not be completed. */
+ *result = NULL_TREE;
+ return tbr_incomplete_type;
+ }
/* Walk in inheritance graph order. The search order is not
important, and this avoids multiple walks of virtual bases. */
for (binfo = TREE_CHAIN (binfo); binfo; binfo = TREE_CHAIN (binfo))
{
- tree r = try_class_unification (tparms, targs, parm, BINFO_TYPE (binfo));
+ tree r = try_class_unification (tparms, targs, parm,
+ BINFO_TYPE (binfo), explain_p);
if (r)
{
applies. */
if (rval && !same_type_p (r, rval))
- return NULL_TREE;
+ {
+ *result = NULL_TREE;
+ return tbr_ambiguous_baseclass;
+ }
rval = r;
}
}
- return rval;
+ *result = rval;
+ return tbr_success;
}
/* Returns the level of DECL, which declares a template parameter. */
}
}
+#define RECUR_AND_CHECK_FAILURE(TP, TA, P, A, S, EP) \
+ do { \
+ if (unify (TP, TA, P, A, S, EP)) \
+ return 1; \
+ } while (0);
+
/* Unifies the remaining arguments in PACKED_ARGS with the pack
expansion at the end of PACKED_PARMS. Returns 0 if the type
deduction succeeds, 1 otherwise. STRICT is the same as in
unify. CALL_ARGS_P is true iff PACKED_ARGS is actually a function
call argument list. We'll need to adjust the arguments to make them
types. SUBR tells us if this is from a recursive call to
- type_unification_real. */
-int
+ type_unification_real, or for comparing two template argument
+ lists. */
+
+static int
unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
- tree packed_args, int strict, bool call_args_p,
- bool subr)
+ tree packed_args, unification_kind_t strict,
+ bool subr, bool explain_p)
{
tree parm
= TREE_VEC_ELT (packed_parms, TREE_VEC_LENGTH (packed_parms) - 1);
unified and unify each with the pattern. */
for (i = start; i < len; i++)
{
- tree parm = pattern;
+ tree parm;
+ bool any_explicit = false;
+ tree arg = TREE_VEC_ELT (packed_args, i);
- /* For each parameter pack, clear out the deduced value so that
- we can deduce it again. */
+ /* For each parameter pack, set its TMPL_ARG to either NULL_TREE
+ or the element of its argument pack at the current index if
+ this argument was explicitly specified. */
for (pack = packs; pack; pack = TREE_CHAIN (pack))
{
int idx, level;
+ tree arg, pargs;
template_parm_level_and_index (TREE_PURPOSE (pack), &level, &idx);
- TMPL_ARG (targs, level, idx) = NULL_TREE;
+ arg = NULL_TREE;
+ if (TREE_VALUE (pack)
+ && (pargs = ARGUMENT_PACK_EXPLICIT_ARGS (TREE_VALUE (pack)))
+ && (i < TREE_VEC_LENGTH (pargs)))
+ {
+ any_explicit = true;
+ arg = TREE_VEC_ELT (pargs, i);
+ }
+ TMPL_ARG (targs, level, idx) = arg;
}
- /* Unify the pattern with the current argument. */
- {
- tree arg = TREE_VEC_ELT (packed_args, i);
- tree arg_expr = NULL_TREE;
- int arg_strict = strict;
- bool skip_arg_p = false;
-
- if (call_args_p)
- {
- int sub_strict;
-
- /* This mirrors what we do in type_unification_real. */
- switch (strict)
- {
- case DEDUCE_CALL:
- sub_strict = (UNIFY_ALLOW_OUTER_LEVEL
- | UNIFY_ALLOW_MORE_CV_QUAL
- | UNIFY_ALLOW_DERIVED);
- break;
-
- case DEDUCE_CONV:
- sub_strict = UNIFY_ALLOW_LESS_CV_QUAL;
- break;
-
- case DEDUCE_EXACT:
- sub_strict = UNIFY_ALLOW_NONE;
- break;
-
- default:
- gcc_unreachable ();
- }
-
- if (!TYPE_P (arg))
- {
- gcc_assert (TREE_TYPE (arg) != NULL_TREE);
- if (type_unknown_p (arg))
- {
- /* [temp.deduct.type] A template-argument can be
- deduced from a pointer to function or pointer
- to member function argument if the set of
- overloaded functions does not contain function
- templates and at most one of a set of
- overloaded functions provides a unique
- match. */
-
- if (resolve_overloaded_unification
- (tparms, targs, parm, arg,
- (unification_kind_t) strict,
- sub_strict)
- != 0)
- return 1;
- skip_arg_p = true;
- }
-
- if (!skip_arg_p)
- {
- arg_expr = arg;
- arg = unlowered_expr_type (arg);
- if (arg == error_mark_node)
- return 1;
- }
- }
-
- arg_strict = sub_strict;
-
- if (!subr)
- arg_strict |=
- maybe_adjust_types_for_deduction ((unification_kind_t) strict,
- &parm, &arg, arg_expr);
- }
+ /* If we had explicit template arguments, substitute them into the
+ pattern before deduction. */
+ if (any_explicit)
+ {
+ /* Some arguments might still be unspecified or dependent. */
+ bool dependent;
+ ++processing_template_decl;
+ dependent = any_dependent_template_arguments_p (targs);
+ if (!dependent)
+ --processing_template_decl;
+ parm = tsubst (pattern, targs,
+ explain_p ? tf_warning_or_error : tf_none,
+ NULL_TREE);
+ if (dependent)
+ --processing_template_decl;
+ if (parm == error_mark_node)
+ return 1;
+ }
+ else
+ parm = pattern;
- if (!skip_arg_p)
- {
- /* For deduction from an init-list we need the actual list. */
- if (arg_expr && BRACE_ENCLOSED_INITIALIZER_P (arg_expr))
- arg = arg_expr;
- if (unify (tparms, targs, parm, arg, arg_strict))
- return 1;
- }
- }
+ /* Unify the pattern with the current argument. */
+ if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
+ LOOKUP_IMPLICIT, explain_p))
+ return 1;
/* For each parameter pack, collect the deduced value. */
for (pack = packs; pack; pack = TREE_CHAIN (pack))
if (old_pack && ARGUMENT_PACK_INCOMPLETE_P (old_pack))
{
- /* Prepend the explicit arguments onto NEW_ARGS. */
+ /* If we had fewer function args than explicit template args,
+ just use the explicits. */
tree explicit_args = ARGUMENT_PACK_EXPLICIT_ARGS (old_pack);
- tree old_args = new_args;
- int i, explicit_len = TREE_VEC_LENGTH (explicit_args);
- int len = explicit_len + TREE_VEC_LENGTH (old_args);
-
- /* Copy the explicit arguments. */
- new_args = make_tree_vec (len);
- for (i = 0; i < explicit_len; i++)
- TREE_VEC_ELT (new_args, i) = TREE_VEC_ELT (explicit_args, i);
-
- /* Copy the deduced arguments. */
- for (; i < len; i++)
- TREE_VEC_ELT (new_args, i) =
- TREE_VEC_ELT (old_args, i - explicit_len);
+ int explicit_len = TREE_VEC_LENGTH (explicit_args);
+ if (len < explicit_len)
+ new_args = explicit_args;
}
if (!old_pack)
ARGUMENT_PACK_INCOMPLETE_P (old_pack) = 1;
ARGUMENT_PACK_EXPLICIT_ARGS (old_pack) = explicit_args;
}
- else if (!comp_template_args (ARGUMENT_PACK_ARGS (old_pack),
- new_args))
- /* Inconsistent unification of this parameter pack. */
- return 1;
+ else
+ {
+ tree bad_old_arg = NULL_TREE, bad_new_arg = NULL_TREE;
+ tree old_args = ARGUMENT_PACK_ARGS (old_pack);
+
+ if (!comp_template_args_with_info (old_args, new_args,
+ &bad_old_arg, &bad_new_arg))
+ /* Inconsistent unification of this parameter pack. */
+ return unify_parameter_pack_inconsistent (explain_p,
+ bad_old_arg,
+ bad_new_arg);
+ }
}
- return 0;
+ return unify_success (explain_p);
}
/* Deduce the value of template parameters. TPARMS is the (innermost)
qualified at this point. */
static int
-unify (tree tparms, tree targs, tree parm, tree arg, int strict)
+unify (tree tparms, tree targs, tree parm, tree arg, int strict,
+ bool explain_p)
{
int idx;
tree targ;
parm = TREE_OPERAND (parm, 0);
if (arg == error_mark_node)
- return 1;
+ return unify_invalid (explain_p);
if (arg == unknown_type_node
|| arg == init_list_type_node)
/* We can't deduce anything from this, but we might get all the
template args from other function args. */
- return 0;
+ return unify_success (explain_p);
/* If PARM uses template parameters, then we can't bail out here,
even if ARG == PARM, since we won't record unifications for the
template parameters. We might need them if we're trying to
figure out which of two things is more specialized. */
if (arg == parm && !uses_template_parms (parm))
- return 0;
+ return unify_success (explain_p);
/* Handle init lists early, so the rest of the function can assume
we're dealing with a type. */
/* We can only deduce from an initializer list argument if the
parameter is std::initializer_list; otherwise this is a
non-deduced context. */
- return 0;
+ return unify_success (explain_p);
elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (parm), 0);
int elt_strict = strict;
if (elt == error_mark_node)
- return 1;
+ return unify_invalid (explain_p);
if (!BRACE_ENCLOSED_INITIALIZER_P (elt))
{
elt = type;
}
- if (unify (tparms, targs, elttype, elt, elt_strict))
- return 1;
+ RECUR_AND_CHECK_FAILURE (tparms, targs, elttype, elt, elt_strict,
+ explain_p);
}
/* If the std::initializer_list<T> deduction worked, replace the
targ = listify (targ);
TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = targ;
}
- return 0;
+ return unify_success (explain_p);
}
/* Immediately reject some pairs that won't unify because of
is more specialized, for example. */
&& TREE_CODE (arg) != TEMPLATE_TYPE_PARM
&& !check_cv_quals_for_unify (strict_in, arg, parm))
- return 1;
+ return unify_cv_qual_mismatch (explain_p, parm, arg);
if (!(strict & UNIFY_ALLOW_OUTER_LEVEL)
&& TYPE_P (parm) && !CP_TYPE_CONST_P (parm))
/* In a type which contains a nested-name-specifier, template
argument values cannot be deduced for template parameters used
within the nested-name-specifier. */
- return 0;
+ return unify_success (explain_p);
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0));
if (tparm == error_mark_node)
- return 1;
+ return unify_invalid (explain_p);
if (TEMPLATE_TYPE_LEVEL (parm)
!= template_decl_level (tparm))
/* The PARM is not one we're trying to unify. Just check
to see if it matches ARG. */
- return (TREE_CODE (arg) == TREE_CODE (parm)
- && same_type_p (parm, arg)) ? 0 : 1;
+ {
+ if (TREE_CODE (arg) == TREE_CODE (parm)
+ && same_type_p (parm, arg))
+ return unify_success (explain_p);
+ else
+ return unify_type_mismatch (explain_p, parm, arg);
+ }
idx = TEMPLATE_TYPE_IDX (parm);
targ = TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx);
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, idx));
+ if (tparm == error_mark_node)
+ return unify_invalid (explain_p);
/* Check for mixed types and values. */
if ((TREE_CODE (parm) == TEMPLATE_TYPE_PARM
&& TREE_CODE (tparm) != TYPE_DECL)
|| (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM
&& TREE_CODE (tparm) != TEMPLATE_DECL))
- return 1;
+ gcc_unreachable ();
if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
template parameter. */
if (TREE_CODE (arg) != BOUND_TEMPLATE_TEMPLATE_PARM
&& !CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P (arg))
- return 1;
+ return unify_template_deduction_failure (explain_p, parm, arg);
{
tree parmvec = TYPE_TI_ARGS (parm);
if (coerce_template_parms (parm_parms,
full_argvec,
TYPE_TI_TEMPLATE (parm),
- tf_none,
+ (explain_p
+ ? tf_warning_or_error
+ : tf_none),
/*require_all_args=*/true,
/*use_default_args=*/false)
== error_mark_node)
parm_variadic_p = 1;
if (TREE_VEC_LENGTH (argvec) < len - parm_variadic_p)
- return 1;
+ return unify_too_few_arguments (explain_p,
+ TREE_VEC_LENGTH (argvec), len);
for (i = 0; i < len - parm_variadic_p; ++i)
{
- if (unify (tparms, targs,
- TREE_VEC_ELT (parmvec, i),
- TREE_VEC_ELT (argvec, i),
- UNIFY_ALLOW_NONE))
- return 1;
+ RECUR_AND_CHECK_FAILURE (tparms, targs,
+ TREE_VEC_ELT (parmvec, i),
+ TREE_VEC_ELT (argvec, i),
+ UNIFY_ALLOW_NONE, explain_p);
}
if (parm_variadic_p
&& unify_pack_expansion (tparms, targs,
parmvec, argvec,
- UNIFY_ALLOW_NONE,
- /*call_args_p=*/false,
- /*subr=*/false))
+ DEDUCE_EXACT,
+ /*subr=*/true, explain_p))
return 1;
}
arg = TYPE_TI_TEMPLATE (arg);
/* Simple cases: Value already set, does match or doesn't. */
if (targ != NULL_TREE && template_args_equal (targ, arg))
- return 0;
+ return unify_success (explain_p);
else if (targ)
- return 1;
+ return unify_inconsistency (explain_p, parm, targ, arg);
}
else
{
that binds `const int' to `T'. */
if (!check_cv_quals_for_unify (strict_in | UNIFY_ALLOW_LESS_CV_QUAL,
arg, parm))
- return 1;
+ return unify_cv_qual_mismatch (explain_p, parm, arg);
/* Consider the case where ARG is `const volatile int' and
PARM is `const T'. Then, T should be `volatile int'. */
arg = cp_build_qualified_type_real
(arg, cp_type_quals (arg) & ~cp_type_quals (parm), tf_none);
if (arg == error_mark_node)
- return 1;
+ return unify_invalid (explain_p);
/* Simple cases: Value already set, does match or doesn't. */
if (targ != NULL_TREE && same_type_p (targ, arg))
- return 0;
+ return unify_success (explain_p);
else if (targ)
- return 1;
+ return unify_inconsistency (explain_p, parm, targ, arg);
/* Make sure that ARG is not a variable-sized array. (Note
that were talking about variable-sized arrays (like
`int[n]'), rather than arrays of unknown size (like
`int[]').) We'll get very confused by such a type since
- the bound of the array will not be computable in an
- instantiation. Besides, such types are not allowed in
- ISO C++, so we can do as we please here. */
- if (variably_modified_type_p (arg, NULL_TREE))
- return 1;
+ the bound of the array is not constant, and therefore
+ not mangleable. Besides, such types are not allowed in
+ ISO C++, so we can do as we please here. We do allow
+ them for 'auto' deduction, since that isn't ABI-exposed. */
+ if (!is_auto (parm) && variably_modified_type_p (arg, NULL_TREE))
+ return unify_vla_arg (explain_p, arg);
/* Strip typedefs as in convert_template_argument. */
arg = canonicalize_type_argument (arg, tf_none);
against it unless PARM is also a parameter pack. */
if ((template_parameter_pack_p (arg) || PACK_EXPANSION_P (arg))
&& !template_parameter_pack_p (parm))
- return 1;
+ return unify_parameter_pack_mismatch (explain_p, parm, arg);
/* If the argument deduction results is a METHOD_TYPE,
then there is a problem.
METHOD_TYPE doesn't map to any real C++ type the result of
the deduction can not be of that type. */
if (TREE_CODE (arg) == METHOD_TYPE)
- return 1;
+ return unify_method_type_error (explain_p, arg);
TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
- return 0;
+ return unify_success (explain_p);
case TEMPLATE_PARM_INDEX:
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0));
if (tparm == error_mark_node)
- return 1;
+ return unify_invalid (explain_p);
if (TEMPLATE_PARM_LEVEL (parm)
!= template_decl_level (tparm))
- /* The PARM is not one we're trying to unify. Just check
- to see if it matches ARG. */
- return !(TREE_CODE (arg) == TREE_CODE (parm)
- && cp_tree_equal (parm, arg));
+ {
+ /* The PARM is not one we're trying to unify. Just check
+ to see if it matches ARG. */
+ int result = !(TREE_CODE (arg) == TREE_CODE (parm)
+ && cp_tree_equal (parm, arg));
+ if (result)
+ unify_expression_unequal (explain_p, parm, arg);
+ return result;
+ }
idx = TEMPLATE_PARM_IDX (parm);
targ = TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx);
if (targ)
- return !cp_tree_equal (targ, arg);
+ {
+ int x = !cp_tree_equal (targ, arg);
+ if (x)
+ unify_inconsistency (explain_p, parm, targ, arg);
+ return x;
+ }
/* [temp.deduct.type] If, in the declaration of a function template
with a non-type template-parameter, the non-type
else if (uses_template_parms (tparm))
/* We haven't deduced the type of this parameter yet. Try again
later. */
- return 0;
+ return unify_success (explain_p);
else
- return 1;
+ return unify_type_mismatch (explain_p, tparm, arg);
/* If ARG is a parameter pack or an expansion, we cannot unify
against it unless PARM is also a parameter pack. */
if ((template_parameter_pack_p (arg) || PACK_EXPANSION_P (arg))
&& !TEMPLATE_PARM_PARAMETER_PACK (parm))
- return 1;
+ return unify_parameter_pack_mismatch (explain_p, parm, arg);
TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
- return 0;
+ return unify_success (explain_p);
case PTRMEM_CST:
{
/* A pointer-to-member constant can be unified only with
another constant. */
if (TREE_CODE (arg) != PTRMEM_CST)
- return 1;
+ return unify_ptrmem_cst_mismatch (explain_p, parm, arg);
/* Just unify the class member. It would be useless (and possibly
wrong, depending on the strict flags) to unify also
Unification of &A::x and &B::x must succeed. */
return unify (tparms, targs, PTRMEM_CST_MEMBER (parm),
- PTRMEM_CST_MEMBER (arg), strict);
+ PTRMEM_CST_MEMBER (arg), strict, explain_p);
}
case POINTER_TYPE:
{
if (TREE_CODE (arg) != POINTER_TYPE)
- return 1;
+ return unify_type_mismatch (explain_p, parm, arg);
/* [temp.deduct.call]
strict |= (strict_in & UNIFY_ALLOW_DERIVED);
return unify (tparms, targs, TREE_TYPE (parm),
- TREE_TYPE (arg), strict);
+ TREE_TYPE (arg), strict, explain_p);
}
case REFERENCE_TYPE:
if (TREE_CODE (arg) != REFERENCE_TYPE)
- return 1;
+ return unify_type_mismatch (explain_p, parm, arg);
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
- strict & UNIFY_ALLOW_MORE_CV_QUAL);
+ strict & UNIFY_ALLOW_MORE_CV_QUAL, explain_p);
case ARRAY_TYPE:
if (TREE_CODE (arg) != ARRAY_TYPE)
- return 1;
+ return unify_type_mismatch (explain_p, parm, arg);
if ((TYPE_DOMAIN (parm) == NULL_TREE)
!= (TYPE_DOMAIN (arg) == NULL_TREE))
- return 1;
+ return unify_type_mismatch (explain_p, parm, arg);
if (TYPE_DOMAIN (parm) != NULL_TREE)
{
tree parm_max;
Here, the type of the ARG will be "int [g(i)]", and
may be a SAVE_EXPR, etc. */
if (TREE_CODE (arg_max) != MINUS_EXPR)
- return 1;
+ return unify_vla_arg (explain_p, arg);
arg_max = TREE_OPERAND (arg_max, 0);
}
arg_max,
integer_one_node);
- if (unify (tparms, targs, parm_max, arg_max, UNIFY_ALLOW_INTEGER))
- return 1;
+ RECUR_AND_CHECK_FAILURE (tparms, targs, parm_max, arg_max,
+ UNIFY_ALLOW_INTEGER, explain_p);
}
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
- strict & UNIFY_ALLOW_MORE_CV_QUAL);
+ strict & UNIFY_ALLOW_MORE_CV_QUAL, explain_p);
case REAL_TYPE:
case COMPLEX_TYPE:
case BOOLEAN_TYPE:
case ENUMERAL_TYPE:
case VOID_TYPE:
+ case NULLPTR_TYPE:
if (TREE_CODE (arg) != TREE_CODE (parm))
- return 1;
+ return unify_type_mismatch (explain_p, parm, arg);
/* We have already checked cv-qualification at the top of the
function. */
if (!same_type_ignoring_top_level_qualifiers_p (arg, parm))
- return 1;
+ return unify_type_mismatch (explain_p, parm, arg);
/* As far as unification is concerned, this wins. Later checks
will invalidate it if necessary. */
- return 0;
+ return unify_success (explain_p);
/* Types INTEGER_CST and MINUS_EXPR can come from array bounds. */
/* Type INTEGER_CST can come from ordinary constant template args. */
arg = TREE_OPERAND (arg, 0);
if (TREE_CODE (arg) != INTEGER_CST)
- return 1;
- return !tree_int_cst_equal (parm, arg);
+ return unify_template_argument_mismatch (explain_p, parm, arg);
+ return (tree_int_cst_equal (parm, arg)
+ ? unify_success (explain_p)
+ : unify_template_argument_mismatch (explain_p, parm, arg));
case TREE_VEC:
{
- int i;
+ int i, len, argslen;
+ int parm_variadic_p = 0;
+
if (TREE_CODE (arg) != TREE_VEC)
- return 1;
- if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg))
- return 1;
- for (i = 0; i < TREE_VEC_LENGTH (parm); ++i)
- if (unify (tparms, targs,
- TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i),
- UNIFY_ALLOW_NONE))
- return 1;
- return 0;
+ return unify_template_argument_mismatch (explain_p, parm, arg);
+
+ len = TREE_VEC_LENGTH (parm);
+ argslen = TREE_VEC_LENGTH (arg);
+
+ /* Check for pack expansions in the parameters. */
+ for (i = 0; i < len; ++i)
+ {
+ if (PACK_EXPANSION_P (TREE_VEC_ELT (parm, i)))
+ {
+ if (i == len - 1)
+ /* We can unify against something with a trailing
+ parameter pack. */
+ parm_variadic_p = 1;
+ else
+ /* [temp.deduct.type]/9: If the template argument list of
+ P contains a pack expansion that is not the last
+ template argument, the entire template argument list
+ is a non-deduced context. */
+ return unify_success (explain_p);
+ }
+ }
+
+ /* If we don't have enough arguments to satisfy the parameters
+ (not counting the pack expression at the end), or we have
+ too many arguments for a parameter list that doesn't end in
+ a pack expression, we can't unify. */
+ if (parm_variadic_p
+ ? argslen < len - parm_variadic_p
+ : argslen != len)
+ return unify_arity (explain_p, TREE_VEC_LENGTH (arg), len);
+
+ /* Unify all of the parameters that precede the (optional)
+ pack expression. */
+ for (i = 0; i < len - parm_variadic_p; ++i)
+ {
+ RECUR_AND_CHECK_FAILURE (tparms, targs,
+ TREE_VEC_ELT (parm, i),
+ TREE_VEC_ELT (arg, i),
+ UNIFY_ALLOW_NONE, explain_p);
+ }
+ if (parm_variadic_p)
+ return unify_pack_expansion (tparms, targs, parm, arg,
+ DEDUCE_EXACT,
+ /*subr=*/true, explain_p);
+ return unify_success (explain_p);
}
case RECORD_TYPE:
case UNION_TYPE:
if (TREE_CODE (arg) != TREE_CODE (parm))
- return 1;
+ return unify_type_mismatch (explain_p, parm, arg);
if (TYPE_PTRMEMFUNC_P (parm))
{
if (!TYPE_PTRMEMFUNC_P (arg))
- return 1;
+ return unify_type_mismatch (explain_p, parm, arg);
return unify (tparms, targs,
TYPE_PTRMEMFUNC_FN_TYPE (parm),
TYPE_PTRMEMFUNC_FN_TYPE (arg),
- strict);
+ strict, explain_p);
}
if (CLASSTYPE_TEMPLATE_INFO (parm))
{
/* First, we try to unify the PARM and ARG directly. */
t = try_class_unification (tparms, targs,
- parm, arg);
+ parm, arg, explain_p);
if (!t)
{
a class of the form template-id, A can be a
pointer to a derived class pointed to by the
deduced A. */
- t = get_template_base (tparms, targs, parm, arg);
+ enum template_base_result r;
+ r = get_template_base (tparms, targs, parm, arg,
+ explain_p, &t);
if (!t)
- return 1;
+ return unify_no_common_base (explain_p, r, parm, arg);
}
}
else if (CLASSTYPE_TEMPLATE_INFO (arg)
t = arg;
else
/* There's no chance of unification succeeding. */
- return 1;
+ return unify_type_mismatch (explain_p, parm, arg);
return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
- CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE);
+ CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE, explain_p);
}
else if (!same_type_ignoring_top_level_qualifiers_p (parm, arg))
- return 1;
- return 0;
+ return unify_type_mismatch (explain_p, parm, arg);
+ return unify_success (explain_p);
case METHOD_TYPE:
case FUNCTION_TYPE:
unsigned int i;
if (TREE_CODE (arg) != TREE_CODE (parm))
- return 1;
+ return unify_type_mismatch (explain_p, parm, arg);
/* CV qualifications for methods can never be deduced, they must
match exactly. We need to check them explicitly here,
(UNIFY_ALLOW_NONE,
class_of_this_parm (arg),
class_of_this_parm (parm))))
- return 1;
+ return unify_cv_qual_mismatch (explain_p, parm, arg);
- if (unify (tparms, targs, TREE_TYPE (parm),
- TREE_TYPE (arg), UNIFY_ALLOW_NONE))
- return 1;
+ RECUR_AND_CHECK_FAILURE (tparms, targs, TREE_TYPE (parm),
+ TREE_TYPE (arg), UNIFY_ALLOW_NONE, explain_p);
nargs = list_length (TYPE_ARG_TYPES (arg));
args = XALLOCAVEC (tree, nargs);
return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
args, nargs, 1, DEDUCE_EXACT,
- LOOKUP_NORMAL);
+ LOOKUP_NORMAL, explain_p);
}
case OFFSET_TYPE:
/* Check top-level cv qualifiers */
if (!check_cv_quals_for_unify (UNIFY_ALLOW_NONE, arg, parm))
- return 1;
+ return unify_cv_qual_mismatch (explain_p, parm, arg);
- if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
- TYPE_PTRMEMFUNC_OBJECT_TYPE (arg), UNIFY_ALLOW_NONE))
- return 1;
+ RECUR_AND_CHECK_FAILURE (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
+ TYPE_PTRMEMFUNC_OBJECT_TYPE (arg),
+ UNIFY_ALLOW_NONE, explain_p);
/* Determine the type of the function we are unifying against. */
method_type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (arg));
implicit object parameter and place them on the function
type to be restored later. */
fntype = apply_memfn_quals (fntype, type_memfn_quals (method_type));
- return unify (tparms, targs, TREE_TYPE (parm), fntype, strict);
+ return unify (tparms, targs, TREE_TYPE (parm), fntype, strict, explain_p);
}
if (TREE_CODE (arg) != OFFSET_TYPE)
- return 1;
- if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
- TYPE_OFFSET_BASETYPE (arg), UNIFY_ALLOW_NONE))
- return 1;
+ return unify_type_mismatch (explain_p, parm, arg);
+ RECUR_AND_CHECK_FAILURE (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
+ TYPE_OFFSET_BASETYPE (arg),
+ UNIFY_ALLOW_NONE, explain_p);
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
- strict);
+ strict, explain_p);
case CONST_DECL:
if (DECL_TEMPLATE_PARM_P (parm))
- return unify (tparms, targs, DECL_INITIAL (parm), arg, strict);
+ return unify (tparms, targs, DECL_INITIAL (parm), arg, strict, explain_p);
if (arg != integral_constant_value (parm))
- return 1;
- return 0;
+ return unify_template_argument_mismatch (explain_p, parm, arg);
+ return unify_success (explain_p);
case FIELD_DECL:
case TEMPLATE_DECL:
/* Matched cases are handled by the ARG == PARM test above. */
- return 1;
+ return unify_template_argument_mismatch (explain_p, parm, arg);
case VAR_DECL:
/* A non-type template parameter that is a variable should be a
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
- {
- tree packed_parms = ARGUMENT_PACK_ARGS (parm);
- tree packed_args = ARGUMENT_PACK_ARGS (arg);
- int i, len = TREE_VEC_LENGTH (packed_parms);
- int argslen = TREE_VEC_LENGTH (packed_args);
- int parm_variadic_p = 0;
-
- for (i = 0; i < len; ++i)
- {
- if (PACK_EXPANSION_P (TREE_VEC_ELT (packed_parms, i)))
- {
- if (i == len - 1)
- /* We can unify against something with a trailing
- parameter pack. */
- parm_variadic_p = 1;
- else
- /* Since there is something following the pack
- expansion, we cannot unify this template argument
- list. */
- return 0;
- }
- }
-
-
- /* If we don't have enough arguments to satisfy the parameters
- (not counting the pack expression at the end), or we have
- too many arguments for a parameter list that doesn't end in
- a pack expression, we can't unify. */
- if (argslen < (len - parm_variadic_p)
- || (argslen > len && !parm_variadic_p))
- return 1;
-
- /* Unify all of the parameters that precede the (optional)
- pack expression. */
- for (i = 0; i < len - parm_variadic_p; ++i)
- {
- if (unify (tparms, targs, TREE_VEC_ELT (packed_parms, i),
- TREE_VEC_ELT (packed_args, i), strict))
- return 1;
- }
-
- if (parm_variadic_p)
- return unify_pack_expansion (tparms, targs,
- packed_parms, packed_args,
- strict, /*call_args_p=*/false,
- /*subr=*/false);
- return 0;
- }
-
- break;
+ return unify (tparms, targs, ARGUMENT_PACK_ARGS (parm),
+ ARGUMENT_PACK_ARGS (arg), strict, explain_p);
case TYPEOF_TYPE:
case DECLTYPE_TYPE:
case UNDERLYING_TYPE:
/* Cannot deduce anything from TYPEOF_TYPE, DECLTYPE_TYPE,
or UNDERLYING_TYPE nodes. */
- return 0;
+ return unify_success (explain_p);
case ERROR_MARK:
/* Unification fails if we hit an error node. */
- return 1;
+ return unify_invalid (explain_p);
default:
/* An unresolved overload is a nondeduced context. */
- if (type_unknown_p (parm))
- return 0;
+ if (is_overloaded_fn (parm) || type_unknown_p (parm))
+ return unify_success (explain_p);
gcc_assert (EXPR_P (parm));
/* We must be looking at an expression. This can happen with
if (!uses_template_parms (parm)
&& !template_args_equal (parm, arg))
- return 1;
+ return unify_expression_unequal (explain_p, parm, arg);
else
- return 0;
+ return unify_success (explain_p);
}
}
+#undef RECUR_AND_CHECK_FAILURE
\f
/* Note that DECL can be defined in this translation unit, if
required. */
for (i = 0; i < len2; i++, ta = TREE_CHAIN (ta))
TREE_VEC_ELT (argvec, i) = TREE_VALUE (ta);
- deduce1 = !unify_pack_expansion (tparms1, targs1, parmvec,
- argvec, UNIFY_ALLOW_NONE,
- /*call_args_p=*/false,
- /*subr=*/0);
+ deduce1 = (unify_pack_expansion (tparms1, targs1, parmvec,
+ argvec, DEDUCE_EXACT,
+ /*subr=*/true, /*explain_p=*/false)
+ == 0);
/* We cannot deduce in the other direction, because ARG1 is
a pack expansion but ARG2 is not. */
for (i = 0; i < len1; i++, ta = TREE_CHAIN (ta))
TREE_VEC_ELT (argvec, i) = TREE_VALUE (ta);
- deduce2 = !unify_pack_expansion (tparms2, targs2, parmvec,
- argvec, UNIFY_ALLOW_NONE,
- /*call_args_p=*/false,
- /*subr=*/0);
+ deduce2 = (unify_pack_expansion (tparms2, targs2, parmvec,
+ argvec, DEDUCE_EXACT,
+ /*subr=*/true, /*explain_p=*/false)
+ == 0);
/* We cannot deduce in the other direction, because ARG2 is
a pack expansion but ARG1 is not.*/
{
/* The normal case, where neither argument is a pack
expansion. */
- deduce1 = !unify (tparms1, targs1, arg1, arg2, UNIFY_ALLOW_NONE);
- deduce2 = !unify (tparms2, targs2, arg2, arg1, UNIFY_ALLOW_NONE);
+ deduce1 = (unify (tparms1, targs1, arg1, arg2,
+ UNIFY_ALLOW_NONE, /*explain_p=*/false)
+ == 0);
+ deduce2 = (unify (tparms2, targs2, arg2, arg1,
+ UNIFY_ALLOW_NONE, /*explain_p=*/false)
+ == 0);
}
/* If we couldn't deduce arguments for tparms1 to make arg1 match
args, ix,
(check_rettype || DECL_CONV_FN_P (fn)
? TREE_TYPE (decl_type) : NULL_TREE),
- DEDUCE_EXACT, LOOKUP_NORMAL))
+ DEDUCE_EXACT, LOOKUP_NORMAL, /*explain_p=*/false))
return NULL_TREE;
return targs;
if (unify (tparms, deduced_args,
INNERMOST_TEMPLATE_ARGS (spec_args),
INNERMOST_TEMPLATE_ARGS (args),
- UNIFY_ALLOW_NONE))
+ UNIFY_ALLOW_NONE, /*explain_p=*/false))
return NULL_TREE;
for (i = 0; i < ntparms; ++i)
if (! CLASS_TYPE_P (t) || ! CLASSTYPE_TEMPLATE_INFO (t))
{
- error ("explicit instantiation of non-template type %qT", t);
+ tree tmpl =
+ (TYPE_TEMPLATE_INFO (t)) ? TYPE_TI_TEMPLATE (t) : NULL;
+ if (tmpl)
+ error ("explicit instantiation of non-class template %qD", tmpl);
+ else
+ error ("explicit instantiation of non-template type %qT", t);
return;
}
specs = tsubst_exception_specification (TREE_TYPE (code_pattern),
args, tf_error, NULL_TREE,
/*defer_ok*/false);
- if (specs)
+ if (specs && specs != error_mark_node)
TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl),
specs);
if (TREE_CODE (noex) == DEFERRED_NOEXCEPT)
{
- push_tinst_level (fn);
- push_access_scope (fn);
- input_location = DECL_SOURCE_LOCATION (fn);
- noex = tsubst_copy_and_build (DEFERRED_NOEXCEPT_PATTERN (noex),
- DEFERRED_NOEXCEPT_ARGS (noex),
- tf_warning_or_error, fn, /*function_p=*/false,
- /*integral_constant_expression_p=*/true);
- pop_access_scope (fn);
- pop_tinst_level ();
- spec = build_noexcept_spec (noex, tf_warning_or_error);
- if (spec == error_mark_node)
+ if (push_tinst_level (fn))
+ {
+ push_access_scope (fn);
+ input_location = DECL_SOURCE_LOCATION (fn);
+ noex = tsubst_copy_and_build (DEFERRED_NOEXCEPT_PATTERN (noex),
+ DEFERRED_NOEXCEPT_ARGS (noex),
+ tf_warning_or_error, fn,
+ /*function_p=*/false,
+ /*integral_constant_expression_p=*/true);
+ pop_access_scope (fn);
+ pop_tinst_level ();
+ spec = build_noexcept_spec (noex, tf_warning_or_error);
+ if (spec == error_mark_node)
+ spec = noexcept_false_spec;
+ }
+ else
spec = noexcept_false_spec;
}
else
d = DECL_CLONED_FUNCTION (d);
if (DECL_TEMPLATE_INSTANTIATED (d)
+ || (TREE_CODE (d) == FUNCTION_DECL
+ && DECL_DEFAULTED_FN (d) && DECL_INITIAL (d))
|| DECL_TEMPLATE_SPECIALIZATION (d))
/* D has already been instantiated or explicitly specialized, so
there's nothing for us to do here.
spec_parm = skip_artificial_parms_for (d, spec_parm);
tmpl_parm = skip_artificial_parms_for (subst_decl, tmpl_parm);
}
- while (tmpl_parm && !FUNCTION_PARAMETER_PACK_P (tmpl_parm))
+ for (; tmpl_parm; tmpl_parm = DECL_CHAIN (tmpl_parm))
{
- register_local_specialization (spec_parm, tmpl_parm);
- tmpl_parm = DECL_CHAIN (tmpl_parm);
- spec_parm = DECL_CHAIN (spec_parm);
+ if (!FUNCTION_PARAMETER_PACK_P (tmpl_parm))
+ {
+ register_local_specialization (spec_parm, tmpl_parm);
+ spec_parm = DECL_CHAIN (spec_parm);
+ }
+ else
+ {
+ /* Register the (value) argument pack as a specialization of
+ TMPL_PARM, then move on. */
+ tree argpack = extract_fnparm_pack (tmpl_parm, &spec_parm);
+ register_local_specialization (argpack, tmpl_parm);
+ }
}
- if (tmpl_parm && FUNCTION_PARAMETER_PACK_P (tmpl_parm))
- {
- /* Register the (value) argument pack as a specialization of
- TMPL_PARM, then move on. */
- tree argpack = make_fnparm_pack (spec_parm);
- register_local_specialization (argpack, tmpl_parm);
- tmpl_parm = DECL_CHAIN (tmpl_parm);
- spec_parm = NULL_TREE;
- }
gcc_assert (!spec_parm);
/* Substitute into the body of the function. */
/* Build a dummy EXPR_PACK_EXPANSION that will be used to
expand each argument in the TREE_VALUE of t. */
expr = make_node (EXPR_PACK_EXPANSION);
+ PACK_EXPANSION_LOCAL_P (expr) = true;
PACK_EXPANSION_PARAMETER_PACKS (expr) =
PACK_EXPANSION_PARAMETER_PACKS (TREE_PURPOSE (t));
int
problematic_instantiation_changed (void)
{
- return last_template_error_tick != tinst_level_tick;
+ return current_tinst_level != last_error_tinst_level;
}
/* Remember current template involved in diagnostics. */
void
record_last_problematic_instantiation (void)
{
- last_template_error_tick = tinst_level_tick;
+ last_error_tinst_level = current_tinst_level;
}
struct tinst_level *
return 0;
else if (TREE_CODE (type) == DECLTYPE_TYPE)
return 0;
+ else if (TREE_CODE (type) == NULLPTR_TYPE)
+ return 0;
if (complain & tf_error)
- error ("%q#T is not a valid type for a template constant parameter", type);
+ {
+ if (type == error_mark_node)
+ inform (input_location, "invalid template non-type parameter");
+ else
+ error ("%q#T is not a valid type for a template non-type parameter",
+ type);
+ }
return 1;
}
return false;
}
+ case STMT_EXPR:
+ /* Treat a GNU statement expression as dependent to avoid crashing
+ under fold_non_dependent_expr; it can't be constant. */
+ return true;
+
default:
/* A constant expression is value-dependent if any subexpression is
value-dependent. */
|| TREE_CODE (expression) == STATIC_CAST_EXPR
|| TREE_CODE (expression) == CONST_CAST_EXPR
|| TREE_CODE (expression) == REINTERPRET_CAST_EXPR
+ || TREE_CODE (expression) == IMPLICIT_CONV_EXPR
|| TREE_CODE (expression) == CAST_EXPR)
return dependent_type_p (TREE_TYPE (expression));
if (TREE_CODE (expression) == SCOPE_REF)
return false;
- if (TREE_CODE (expression) == BASELINK)
+ if (BASELINK_P (expression))
expression = BASELINK_FUNCTIONS (expression);
if (TREE_CODE (expression) == TEMPLATE_ID_EXPR)
is dependent. This is consistent with what
any_dependent_template_arguments_p [that calls this function]
does. */
- if (arg == error_mark_node)
+ if (!arg || arg == error_mark_node)
return true;
if (TREE_CODE (arg) == ARGUMENT_PACK_SELECT)
longer be considered a dependent type. */
pushed_scope = push_scope (scope);
/* Look up the declaration. */
- decl = lookup_member (scope, name, /*protect=*/0, /*want_type=*/true);
+ decl = lookup_member (scope, name, /*protect=*/0, /*want_type=*/true,
+ tf_warning_or_error);
result = NULL_TREE;
if (TREE_CODE (expr) == THROW_EXPR)
return expr;
+ /* Don't wrap an initializer list, we need to be able to look inside. */
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr))
+ return expr;
+
if (TREE_CODE (expr) == COND_EXPR)
return build3 (COND_EXPR,
TREE_TYPE (expr),
TREE_VEC_ELT (tparms, 0)
= build_tree_list (NULL_TREE, TYPE_NAME (auto_node));
val = type_unification_real (tparms, targs, parms, args, 1, 0,
- DEDUCE_CALL, LOOKUP_NORMAL);
+ DEDUCE_CALL, LOOKUP_NORMAL,
+ /*explain_p=*/false);
if (val > 0)
{
if (processing_template_decl)