/* 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, 2012
- Free Software Foundation, Inc.
+ Copyright (C) 1992-2013 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
Rewritten by Jason Merrill (jason@cygnus.com).
#include "cp-objcp-common.h"
#include "tree-inline.h"
#include "decl.h"
-#include "output.h"
#include "toplev.h"
#include "timevar.h"
#include "tree-iterator.h"
-#include "vecprim.h"
/* The type of functions taking a tree, and some additional data, and
returning an int. */
static int template_header_count;
static GTY(()) tree saved_trees;
-static VEC(int,heap) *inline_parm_levels;
+static vec<int> inline_parm_levels;
static GTY(()) struct tinst_level *current_tinst_level;
/* A map from local variable declarations in the body of the template
presently being instantiated to the corresponding instantiated
local variables. */
-static htab_t local_specializations;
+static struct pointer_map_t *local_specializations;
+
+/* True if we've recursed into fn_type_unification too many times. */
+static bool excessive_deduction_depth;
typedef struct GTY(()) spec_entry
{
the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
TREE_LIST, whose TREE_VALUEs contain the canonical template
parameters of various types and levels. */
-static GTY(()) VEC(tree,gc) *canonical_template_parms;
+static GTY(()) vec<tree, va_gc> *canonical_template_parms;
#define UNIFY_ALLOW_NONE 0
#define UNIFY_ALLOW_MORE_CV_QUAL 1
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,
bool);
static void add_pending_template (tree);
static tree reopen_tinst_level (struct tinst_level *);
static tree tsubst_initializer_list (tree, tree);
-static tree get_class_bindings (tree, tree, tree);
+static tree get_class_bindings (tree, tree, tree, tree);
static tree coerce_template_parms (tree, tree, tree, tsubst_flags_t,
bool, bool);
+static tree coerce_innermost_template_parms (tree, tree, tree, tsubst_flags_t,
+ bool, bool);
static void tsubst_enum (tree, tree, tree);
static tree add_to_template_args (tree, tree);
static tree add_outermost_template_args (tree, tree);
static tree copy_default_args_to_explicit_spec_1 (tree, tree);
static void copy_default_args_to_explicit_spec (tree);
static int invalid_nontype_parm_type_p (tree, tsubst_flags_t);
-static int eq_local_specializations (const void *, const void *);
static bool dependent_template_arg_p (tree);
static bool any_template_arguments_need_structural_equality_p (tree);
static bool dependent_type_p_r (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 tsubst_template_parm (tree, tree, tsubst_flags_t);
+static tree instantiate_alias_template (tree, tree, tsubst_flags_t);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
- template, or VAR_DECL for static member variable (need by
- instantiate_decl). */
+ template, VAR_DECL for static member variable, or TYPE_DECL for
+ alias template (needed by instantiate_decl). */
static void
push_access_scope (tree t)
{
gcc_assert (TREE_CODE (t) == FUNCTION_DECL
+ || TREE_CODE (t) == TYPE_DECL
|| TREE_CODE (t) == VAR_DECL);
if (DECL_FRIEND_CONTEXT (t))
/* Remember how many levels of template parameters we pushed so that
we can pop them later. */
- VEC_safe_push (int, heap, inline_parm_levels, levels);
+ inline_parm_levels.safe_push (levels);
}
/* Undo the effects of maybe_begin_member_template_processing. */
int i;
int last;
- if (VEC_length (int, inline_parm_levels) == 0)
+ if (inline_parm_levels.length () == 0)
return;
- last = VEC_pop (int, inline_parm_levels);
+ last = inline_parm_levels.pop ();
for (i = 0; i < last; ++i)
{
--processing_template_decl;
processing_explicit_instantiation = false;
}
-/* An explicit specialization or partial specialization TMPL is being
+/* An explicit specialization or partial specialization of TMPL is being
declared. Check that the namespace in which the specialization is
occurring is permissible. Returns false iff it is invalid to
specialize TMPL in the current namespace. */
if (type == error_mark_node)
return error_mark_node;
+ /* A lambda that appears in specialization context is not itself a
+ specialization. */
+ if (CLASS_TYPE_P (type) && CLASSTYPE_LAMBDA_EXPR (type))
+ return type;
+
if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
error ("name of class shadows template template parameter %qD",
context = TYPE_CONTEXT (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))))
+ if (TYPE_ALIAS_P (type))
+ {
+ if (TYPE_TEMPLATE_INFO (type)
+ && DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (type)))
+ error ("specialization of alias template %qD",
+ TYPE_TI_TEMPLATE (type));
+ else
+ error ("explicit specialization of non-template %qT", type);
+ return error_mark_node;
+ }
+ else if (CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (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 (CLASS_TYPE_P (type)
- && CLASSTYPE_IMPLICIT_INSTANTIATION (type)
+ if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
&& !COMPLETE_TYPE_P (type))
{
check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type));
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
+ DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)) = input_location;
if (processing_template_decl)
{
if (push_template_decl (TYPE_MAIN_DECL (type))
return error_mark_node;
}
}
- else if (CLASS_TYPE_P (type)
- && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
+ else if (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 (errorcount && !processing_specialization
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (type)
+ && !uses_template_parms (CLASSTYPE_TI_ARGS (type)))
+ /* Trying to define a specialization either without a template<> header
+ or in an inappropriate place. We've already given an error, so just
+ bail now so we don't actually define the specialization. */
+ return error_mark_node;
}
else if (CLASS_TYPE_P (type)
&& !CLASSTYPE_USE_TEMPLATE (type)
have one level of template argument for the innermost
class template. */
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
+ DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)) = input_location;
CLASSTYPE_TI_ARGS (type)
= INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
}
/* Someday C++0x may allow for enum template specialization. */
if (cxx_dialect > cxx98 && TREE_CODE (type) == ENUMERAL_TYPE
&& CLASS_TYPE_P (context) && CLASSTYPE_USE_TEMPLATE (context))
- pedwarn (input_location, OPT_pedantic, "template specialization "
+ pedwarn (input_location, OPT_Wpedantic, "template specialization "
"of %qD not allowed by ISO C++", type);
else
{
{
tree class_template;
tree class_specialization;
- VEC(tree,gc) *methods;
+ vec<tree, va_gc> *methods;
tree fns;
int idx;
/* Iterate through the methods with the indicated name, looking
for the one that has an instance of TMPL. */
methods = CLASSTYPE_METHOD_VEC (class_specialization);
- for (fns = VEC_index (tree, methods, idx); fns; fns = OVL_NEXT (fns))
+ for (fns = (*methods)[idx]; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (DECL_TEMPLATE_INFO (fn) && DECL_TI_TEMPLATE (fn) == tmpl
static tree
retrieve_local_specialization (tree tmpl)
{
- tree spec;
+ void **slot;
if (local_specializations == NULL)
return NULL_TREE;
- spec = (tree) htab_find_with_hash (local_specializations, tmpl,
- htab_hash_pointer (tmpl));
- return spec ? TREE_PURPOSE (spec) : NULL_TREE;
+ slot = pointer_map_contains (local_specializations, tmpl);
+ return slot ? (tree) *slot : NULL_TREE;
}
/* Returns nonzero iff DECL is a specialization of TMPL. */
DECL_SOURCE_LOCATION (clone)
= DECL_SOURCE_LOCATION (fn);
}
- check_specialization_namespace (fn);
+ check_specialization_namespace (tmpl);
return fn;
}
return 0;
}
-/* Compare an entry in the local specializations hash table P1 (which
- is really a pointer to a TREE_LIST) with P2 (which is really a
- DECL). */
-
-static int
-eq_local_specializations (const void *p1, const void *p2)
-{
- return TREE_VALUE ((const_tree) p1) == (const_tree) p2;
-}
-
-/* Hash P1, an entry in the local specializations table. */
-
-static hashval_t
-hash_local_specialization (const void* p1)
-{
- return htab_hash_pointer (TREE_VALUE ((const_tree) p1));
-}
-
/* Like register_specialization, but for local declarations. We are
registering SPEC, an instantiation of TMPL. */
{
void **slot;
- slot = htab_find_slot_with_hash (local_specializations, tmpl,
- htab_hash_pointer (tmpl), INSERT);
- *slot = build_tree_list (spec, tmpl);
+ slot = pointer_map_insert (local_specializations, tmpl);
+ *slot = spec;
}
/* TYPE is a class type. Returns true if TYPE is an explicitly
}
else
{
+ tree cand = OVL_CURRENT (fn);
if (!*str)
{
/* Pick the prefix string. */
if (!more && !OVL_NEXT (fns))
{
- error ("candidate is: %+#D", OVL_CURRENT (fn));
+ inform (DECL_SOURCE_LOCATION (cand),
+ "candidate is: %#D", cand);
continue;
}
*str = _("candidates are:");
spaces = get_spaces (*str);
}
- error ("%s %+#D", *str, OVL_CURRENT (fn));
+ inform (DECL_SOURCE_LOCATION (cand), "%s %#D", *str, cand);
*str = spaces ? spaces : *str;
}
if (template_id == error_mark_node || decl == error_mark_node)
return error_mark_node;
+ /* We shouldn't be specializing a member template of an
+ unspecialized class template; we already gave an error in
+ check_specialization_scope, now avoid crashing. */
+ if (template_count && DECL_CLASS_SCOPE_P (decl)
+ && template_class_depth (DECL_CONTEXT (decl)) > 0)
+ {
+ gcc_assert (errorcount);
+ return error_mark_node;
+ }
+
fns = TREE_OPERAND (template_id, 0);
explicit_targs = TREE_OPERAND (template_id, 1);
fn_arg_types
= skip_artificial_parms_for (fn, fn_arg_types);
- /* Check that the number of function parameters matches.
- For example,
- template <class T> void f(int i = 0);
- template <> void f<int>();
- The specialization f<int> is invalid but is not caught
- by get_bindings below. */
- if (cxx_dialect < cxx11
- && list_length (fn_arg_types) != list_length (decl_arg_types))
- continue;
-
/* Function templates cannot be specializations; there are
no partial specializations of functions. Therefore, if
the type of DECL does not match FN, there is no
}
/* See whether this function might be a specialization of this
- template. */
+ template. Suppress access control because we might be trying
+ to make this specialization a friend, and we have already done
+ access control for the declaration of the specialization. */
+ push_deferring_access_checks (dk_no_check);
targs = get_bindings (fn, decl, explicit_targs, /*check_ret=*/true);
+ pop_deferring_access_checks ();
if (!targs)
/* We cannot deduce template arguments that when used to
specialize TMPL will produce DECL. */
continue;
- if (cxx_dialect >= cxx11)
- {
- /* Make sure that the deduced arguments actually work. */
- insttype = tsubst (TREE_TYPE (fn), targs, tf_none, NULL_TREE);
- if (insttype == error_mark_node)
- continue;
- fn_arg_types
- = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (insttype));
- if (!compparms (fn_arg_types, decl_arg_types))
- continue;
- }
+ /* Make sure that the deduced arguments actually work. */
+ insttype = tsubst (TREE_TYPE (fn), targs, tf_none, NULL_TREE);
+ if (insttype == error_mark_node)
+ continue;
+ fn_arg_types
+ = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (insttype));
+ if (!compparms (fn_arg_types, decl_arg_types))
+ continue;
/* Save this template, and the arguments deduced. */
templates = tree_cons (targs, fn, templates);
TREE_TYPE (decl) = new_type;
}
+/* Return the number of template headers we expect to see for a definition
+ or specialization of CTYPE or one of its non-template members. */
+
+int
+num_template_headers_for_class (tree ctype)
+{
+ int num_templates = 0;
+
+ while (ctype && CLASS_TYPE_P (ctype))
+ {
+ /* You're supposed to have one `template <...>' for every
+ template class, but you don't need one for a full
+ specialization. For example:
+
+ template <class T> struct S{};
+ template <> struct S<int> { void f(); };
+ void S<int>::f () {}
+
+ is correct; there shouldn't be a `template <>' for the
+ definition of `S<int>::f'. */
+ if (!CLASSTYPE_TEMPLATE_INFO (ctype))
+ /* If CTYPE does not have template information of any
+ kind, then it is not a template, nor is it nested
+ within a template. */
+ break;
+ if (explicit_class_specialization_p (ctype))
+ break;
+ if (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (ctype)))
+ ++num_templates;
+
+ ctype = TYPE_CONTEXT (ctype);
+ }
+
+ return num_templates;
+}
+
+/* Do a simple sanity check on the template headers that precede the
+ variable declaration DECL. */
+
+void
+check_template_variable (tree decl)
+{
+ tree ctx = CP_DECL_CONTEXT (decl);
+ int wanted = num_template_headers_for_class (ctx);
+ if (!TYPE_P (ctx) || !CLASSTYPE_TEMPLATE_INFO (ctx))
+ permerror (DECL_SOURCE_LOCATION (decl),
+ "%qD is not a static data member of a class template", decl);
+ else if (template_header_count > wanted)
+ {
+ pedwarn (DECL_SOURCE_LOCATION (decl), 0,
+ "too many template headers for %D (should be %d)",
+ decl, wanted);
+ if (CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))
+ inform (DECL_SOURCE_LOCATION (decl),
+ "members of an explicitly specialized class are defined "
+ "without a template header");
+ }
+}
+
/* Check to see if the function just declared, as indicated in
DECLARATOR, and in DECL, is a specialization of a function
template. We may also discover that the declaration is an explicit
{
idx = lookup_fnfields_1 (ctype, name);
if (idx >= 0)
- fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (ctype), idx);
+ fns = (*CLASSTYPE_METHOD_VEC (ctype))[idx];
}
else
{
- VEC(tree,gc) *methods;
+ vec<tree, va_gc> *methods;
tree ovl;
/* For a type-conversion operator, we cannot do a
methods = CLASSTYPE_METHOD_VEC (ctype);
if (methods)
for (idx = CLASSTYPE_FIRST_CONVERSION_SLOT;
- VEC_iterate (tree, methods, idx, ovl);
+ methods->iterate (idx, &ovl);
++idx)
{
if (!DECL_CONV_FN_P (OVL_CURRENT (ovl)))
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)))
+ else if (alias_template_specialization_p (t))
return true;
return false;
}
return DECL_TEMPLATE_TEMPLATE_PARM_P (parm);
}
+/* Return true iff PARM is a DECL representing a type template
+ parameter. */
+
+bool
+template_type_parameter_p (const_tree parm)
+{
+ return (parm
+ && (TREE_CODE (parm) == TYPE_DECL
+ || TREE_CODE (parm) == TEMPLATE_DECL)
+ && DECL_TEMPLATE_PARM_P (parm));
+}
+
/* Return the template parameters of T if T is a
primary template instantiation, NULL otherwise. */
tree list;
int idx = TEMPLATE_TYPE_IDX (type);
if (!canonical_template_parms)
- canonical_template_parms = VEC_alloc (tree, gc, idx+1);
+ vec_alloc (canonical_template_parms, idx+1);
- while (VEC_length (tree, canonical_template_parms) <= (unsigned)idx)
- VEC_safe_push (tree, gc, canonical_template_parms, NULL_TREE);
+ while (canonical_template_parms->length () <= (unsigned)idx)
+ vec_safe_push (canonical_template_parms, NULL_TREE);
- list = VEC_index (tree, canonical_template_parms, idx);
+ list = (*canonical_template_parms)[idx];
while (list && !comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
list = TREE_CHAIN (list);
return TREE_VALUE (list);
else
{
- VEC_replace(tree, canonical_template_parms, idx,
- tree_cons (NULL_TREE, type,
- VEC_index (tree, canonical_template_parms, idx)));
+ (*canonical_template_parms)[idx]
+ = tree_cons (NULL_TREE, type,
+ (*canonical_template_parms)[idx]);
return type;
}
}
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);
- if ((TYPE_P (pattern) && same_type_p (pattern, parm_pack))
- || (!TYPE_P (pattern) && cp_tree_equal (parm_pack, pattern)))
- /* 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. */
- 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
- arguments. */
+/* Given a set of template parameters, return them as a set of template
+ arguments. The template parameters are represented as a TREE_VEC, in
+ the form documented in cp-tree.h for template arguments. */
static tree
-current_template_args (void)
+template_parms_to_args (tree parms)
{
tree header;
tree args = NULL_TREE;
- int length = TMPL_PARMS_DEPTH (current_template_parms);
+ int length = TMPL_PARMS_DEPTH (parms);
int l = length;
/* If there is only one level of template parameters, we do not
if (length > 1)
args = make_tree_vec (length);
- for (header = current_template_parms; header; header = TREE_CHAIN (header))
+ for (header = parms; header; header = TREE_CHAIN (header))
{
tree a = copy_node (TREE_VALUE (header));
int i;
return args;
}
+/* Within the declaration of a template, return the currently active
+ template parameters as an argument TREE_VEC. */
+
+static tree
+current_template_args (void)
+{
+ return template_parms_to_args (current_template_parms);
+}
+
/* Update the declared TYPE by doing any lookups which were thought to be
dependent, but are not now that we know the SCOPE of the declarator. */
(maintmpl)))))
error ("partial specialization %qT does not specialize any template arguments", type);
+ /* A partial specialization that replaces multiple parameters of the
+ primary template with a pack expansion is less specialized for those
+ parameters. */
+ if (nargs < DECL_NTPARMS (maintmpl))
+ {
+ error ("partial specialization is not more specialized than the "
+ "primary template because it replaces multiple parameters "
+ "with a pack expansion");
+ inform (DECL_SOURCE_LOCATION (maintmpl), "primary template here");
+ return decl;
+ }
+
/* [temp.class.spec]
A partially specialized non-type argument expression shall not
/* Check that a template declaration's use of default arguments and
parameter packs is not invalid. Here, PARMS are the template
- parameters. IS_PRIMARY is nonzero if DECL is the thing declared by
- a primary template. IS_PARTIAL is nonzero if DECL is a partial
+ parameters. IS_PRIMARY is true if DECL is the thing declared by
+ a primary template. IS_PARTIAL is true if DECL is a partial
specialization.
-
IS_FRIEND_DECL is nonzero if DECL is a friend function template
declaration (but not a definition); 1 indicates a declaration, 2
Returns TRUE if there were no errors found, FALSE otherwise. */
bool
-check_default_tmpl_args (tree decl, tree parms, int is_primary,
- int is_partial, int is_friend_decl)
+check_default_tmpl_args (tree decl, tree parms, bool is_primary,
+ bool is_partial, int is_friend_decl)
{
const char *msg;
int last_level_to_check;
local scope. */
return true;
+ if (TREE_CODE (decl) == TYPE_DECL
+ && TREE_TYPE (decl)
+ && LAMBDA_TYPE_P (TREE_TYPE (decl)))
+ /* A lambda doesn't have an explicit declaration; don't complain
+ about the parms of the enclosing class. */
+ return true;
+
if (current_class_type
&& !TYPE_BEING_DEFINED (current_class_type)
&& DECL_LANG_SPECIFIC (decl)
/* Core issue 226 (C++0x only): the following only applies to class
templates. */
- if ((cxx_dialect == cxx98) || TREE_CODE (decl) != FUNCTION_DECL)
+ if (is_primary
+ && ((cxx_dialect == cxx98) || TREE_CODE (decl) != FUNCTION_DECL))
{
/* [temp.param]
TREE_PURPOSE (parm) = error_mark_node;
no_errors = false;
}
- else if (is_primary
- && !is_partial
+ else if (!is_partial
&& !is_friend_decl
/* Don't complain about an enclosing partial
specialization. */
tree args;
tree info;
tree ctx;
- int primary;
- int is_partial;
+ bool is_primary;
+ bool is_partial;
int new_template_p = 0;
/* True if the template is a member template, in the sense of
[temp.mem]. */
/* A friend template that specifies a class context, i.e.
template <typename T> friend void A<T>::f();
is not primary. */
- primary = 0;
+ is_primary = false;
else
- primary = template_parm_scope_p ();
+ is_primary = template_parm_scope_p ();
- if (primary)
+ if (is_primary)
{
if (DECL_CLASS_SCOPE_P (decl))
member_template_p = true;
/* Check to see that the rules regarding the use of default
arguments are not being violated. */
check_default_tmpl_args (decl, current_template_parms,
- primary, is_partial, /*is_friend_decl=*/0);
+ is_primary, is_partial, /*is_friend_decl=*/0);
/* Ensure that there are no parameter packs in the type of this
declaration that have not been expanded. */
if (!ctx
|| TREE_CODE (ctx) == FUNCTION_DECL
|| (CLASS_TYPE_P (ctx) && TYPE_BEING_DEFINED (ctx))
+ || (TREE_CODE (decl) == TYPE_DECL
+ && LAMBDA_TYPE_P (TREE_TYPE (decl)))
|| (is_friend && !DECL_TEMPLATE_INFO (decl)))
{
if (DECL_LANG_SPECIFIC (decl)
}
}
- if (primary)
+ if (is_primary)
{
tree parms = DECL_TEMPLATE_PARMS (tmpl);
int i;
SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
else
{
- if (primary && !DECL_LANG_SPECIFIC (decl))
+ if (is_primary && !DECL_LANG_SPECIFIC (decl))
retrofit_lang_decl (decl);
if (DECL_LANG_SPECIFIC (decl))
DECL_TEMPLATE_INFO (decl) = info;
return push_template_decl_real (decl, false);
}
+/* FN is an inheriting constructor that inherits from the constructor
+ template INHERITED; turn FN into a constructor template with a matching
+ template header. */
+
+tree
+add_inherited_template_parms (tree fn, tree inherited)
+{
+ tree inner_parms
+ = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (inherited));
+ inner_parms = copy_node (inner_parms);
+ tree parms
+ = tree_cons (size_int (processing_template_decl + 1),
+ inner_parms, current_template_parms);
+ tree tmpl = build_template_decl (fn, parms, /*member*/true);
+ tree args = template_parms_to_args (parms);
+ DECL_TEMPLATE_INFO (fn) = build_template_info (tmpl, args);
+ TREE_TYPE (tmpl) = TREE_TYPE (fn);
+ DECL_TEMPLATE_RESULT (tmpl) = fn;
+ DECL_ARTIFICIAL (tmpl) = true;
+ DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
+ return tmpl;
+}
+
/* Called when a class template TYPE is redeclared with the indicated
template PARMS, e.g.:
/* Simplify EXPR if it is a non-dependent expression. Returns the
(possibly simplified) expression. */
-static tree
+tree
fold_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain)
{
if (expr == NULL_TREE)
/* Return TRUE iff is a specialization of an alias template. */
bool
-alias_template_specialization_p (tree t)
+alias_template_specialization_p (const_tree t)
{
if (t == NULL_TREE)
return false;
- return (primary_template_instantiation_p (t)
+
+ return (TYPE_P (t)
+ && TYPE_TEMPLATE_INFO (t)
+ && PRIMARY_TEMPLATE_P (TYPE_TI_TEMPLATE (t))
&& DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (t)));
}
[...]
-- the address of an object or function with external [C++11: or
internal] linkage. */
+
+ if (TREE_CODE (fn_no_ptr) != FUNCTION_DECL)
+ {
+ error ("%qE is not a valid template argument for type %qT", expr, type);
+ if (TREE_CODE (type) == POINTER_TYPE)
+ error ("it must be the address of a function with external linkage");
+ else
+ error ("it must be the name of a function with external linkage");
+ return NULL_TREE;
+ }
+
linkage = decl_linkage (fn_no_ptr);
if (cxx_dialect >= cxx0x ? linkage == lk_none : linkage != lk_external)
{
call.c */
static int
-unify_success (bool explain_p ATTRIBUTE_UNUSED)
+unify_success (bool /*explain_p*/)
{
return 0;
}
}
static int
-unify_invalid (bool explain_p ATTRIBUTE_UNUSED)
+unify_invalid (bool /*explain_p*/)
{
return 1;
}
value_dependent_expression_p. */
if (TYPE_PTROBV_P (type)
&& TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE)
- expr = decay_conversion (expr);
+ {
+ expr = decay_conversion (expr, complain);
+ if (expr == error_mark_node)
+ return error_mark_node;
+ }
/* If we are in a template, EXPR may be non-dependent, but still
have a syntactic, rather than semantic, form. For example, 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)))
+ if (expr == nullptr_node && TYPE_PTR_OR_PTRMEM_P (type))
expr = convert (type, expr);
/* In C++11, integral or enumeration non-type template arguments can be
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))
+ else if (TYPE_PTR_OR_PTRMEM_P (type))
{
tree folded = maybe_constant_value (expr);
if (TYPE_PTR_P (type) ? integer_zerop (folded)
could actually change the type to something more cv-qualified,
and this is not folded by convert_from_reference. */
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 (probe_type),
- TREE_TYPE (TREE_TYPE (addr))));
-
- expr = TREE_OPERAND (addr, 0);
- expr_type = TREE_TYPE (expr);
+ if (TREE_CODE (probe_type) == REFERENCE_TYPE
+ && TREE_CODE (addr) == ADDR_EXPR
+ && TREE_CODE (TREE_TYPE (addr)) == POINTER_TYPE
+ && (same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (probe_type),
+ TREE_TYPE (TREE_TYPE (addr)))))
+ {
+ expr = TREE_OPERAND (addr, 0);
+ expr_type = TREE_TYPE (expr);
+ }
}
}
}
}
- expr = decay_conversion (expr);
+ expr = decay_conversion (expr, complain);
if (expr == error_mark_node)
return error_mark_node;
context information to decay the pointer. */
if (!type_unknown_p (expr_type))
{
- expr = decay_conversion (expr);
+ expr = decay_conversion (expr, complain);
if (expr == error_mark_node)
return error_mark_node;
}
expr = convert_nontype_argument_function (type, expr);
if (!expr || expr == error_mark_node)
return expr;
-
- if (TREE_CODE (expr) != ADDR_EXPR)
- {
- error ("%qE is not a valid template argument for type %qT", expr, type);
- error ("it must be the address of a function with external linkage");
- return NULL_TREE;
- }
}
/* [temp.arg.nontype]/5, bullet 5
"because it is of type %qT", expr, type,
TREE_TYPE (expr));
/* If we are just one standard conversion off, explain. */
- if (can_convert (type, TREE_TYPE (expr)))
+ if (can_convert (type, TREE_TYPE (expr), complain))
inform (input_location,
"standard conversions are not allowed in this context");
return NULL_TREE;
For a non-type template-parameter of type pointer to data member,
qualification conversions (_conv.qual_) are applied. */
- else if (TYPE_PTRMEM_P (type))
+ else if (TYPE_PTRDATAMEM_P (type))
{
/* [temp.arg.nontype] bullet 1 says the pointer to member
expression must be a pointer-to-member constant. */
if (cxx_dialect >= cxx0x)
/* OK under DR 1004. */;
else if (complain & tf_warning_or_error)
- pedwarn (input_location, OPT_pedantic, "injected-class-name %qD"
+ pedwarn (input_location, OPT_Wpedantic, "injected-class-name %qD"
" used as template template argument", TYPE_NAME (arg));
else if (flag_pedantic_errors)
t = arg;
orig_arg = make_typename_type (TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1),
typename_type,
- complain & tf_error);
+ complain);
arg = orig_arg;
is_type = 1;
}
val = error_mark_node;
}
}
- else if (!uses_template_parms (orig_arg) && !uses_template_parms (t))
+ else if (!dependent_template_arg_p (orig_arg)
+ && !uses_template_parms (t))
/* We used to call digest_init here. However, digest_init
will report errors, which we don't want when complain
is zero. More importantly, digest_init will try too
TREE_VEC_ELT (packed_types, arg_idx - parm_idx);
}
- if (arg != error_mark_node)
+ if (arg == error_mark_node)
+ {
+ if (complain & tf_error)
+ error ("template argument %d is invalid", arg_idx + 1);
+ }
+ else
arg = convert_template_argument (actual_parm,
arg, new_args, complain, parm_idx,
in_decl);
return new_inner_args;
}
+/* Like coerce_template_parms. If PARMS represents all template
+ parameters levels, this function returns a vector of vectors
+ representing all the resulting argument levels. Note that in this
+ case, only the innermost arguments are coerced because the
+ outermost ones are supposed to have been coerced already.
+
+ Otherwise, if PARMS represents only (the innermost) vector of
+ parameters, this function returns a vector containing just the
+ innermost resulting arguments. */
+
+static tree
+coerce_innermost_template_parms (tree parms,
+ tree args,
+ tree in_decl,
+ tsubst_flags_t complain,
+ bool require_all_args,
+ bool use_default_args)
+{
+ int parms_depth = TMPL_PARMS_DEPTH (parms);
+ int args_depth = TMPL_ARGS_DEPTH (args);
+ tree coerced_args;
+
+ if (parms_depth > 1)
+ {
+ coerced_args = make_tree_vec (parms_depth);
+ tree level;
+ int cur_depth;
+
+ for (level = parms, cur_depth = parms_depth;
+ parms_depth > 0 && level != NULL_TREE;
+ level = TREE_CHAIN (level), --cur_depth)
+ {
+ tree l;
+ if (cur_depth == args_depth)
+ l = coerce_template_parms (TREE_VALUE (level),
+ args, in_decl, complain,
+ require_all_args,
+ use_default_args);
+ else
+ l = TMPL_ARGS_LEVEL (args, cur_depth);
+
+ if (l == error_mark_node)
+ return error_mark_node;
+
+ SET_TMPL_ARGS_LEVEL (coerced_args, cur_depth, l);
+ }
+ }
+ else
+ coerced_args = coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parms),
+ args, in_decl, complain,
+ require_all_args,
+ use_default_args);
+ return coerced_args;
+}
+
/* Returns 1 if template args OT and NT are equivalent. */
static int
? CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)) : decl;
}
-/* Given an IDENTIFIER_NODE (type TEMPLATE_DECL) and a chain of
+/* Given an IDENTIFIER_NODE (or type TEMPLATE_DECL) and a chain of
parameters, find the desired type.
D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments.
d1 = DECL_NAME (templ);
context = DECL_CONTEXT (templ);
}
+ else if (DECL_TEMPLATE_TEMPLATE_PARM_P (d1))
+ {
+ templ = d1;
+ d1 = DECL_NAME (templ);
+ }
/* Issue an error message if we didn't find a template. */
if (! templ)
/* A local class. Make sure the decl gets registered properly. */
if (context == current_function_decl)
- pushtag (DECL_NAME (gen_tmpl), t, /*tag_scope=*/ts_global);
+ pushtag (DECL_NAME (gen_tmpl), t, /*tag_scope=*/ts_current);
if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
/* This instantiation is another name for the primary
if (CLASS_TYPE_P (template_type))
{
TREE_PRIVATE (type_decl)
- = TREE_PRIVATE (TYPE_STUB_DECL (template_type));
+ = TREE_PRIVATE (TYPE_MAIN_DECL (template_type));
TREE_PROTECTED (type_decl)
- = TREE_PROTECTED (TYPE_STUB_DECL (template_type));
+ = TREE_PROTECTED (TYPE_MAIN_DECL (template_type));
if (CLASSTYPE_VISIBILITY_SPECIFIED (template_type))
{
DECL_VISIBILITY_SPECIFIED (type_decl) = 1;
= tree_cons (arglist, t,
DECL_TEMPLATE_INSTANTIATIONS (templ));
- if (TREE_CODE (t) == ENUMERAL_TYPE && !is_dependent_type)
+ if (TREE_CODE (template_type) == ENUMERAL_TYPE && !is_dependent_type)
/* Now that the type has been registered on the instantiations
list, we set up the enumerators. Because the enumeration
constants may involve the enumeration type itself, we make
return dependent_p;
}
+/* Returns true iff current_function_decl is an incompletely instantiated
+ template. Useful instead of processing_template_decl because the latter
+ is set to 0 during fold_non_dependent_expr. */
+
+bool
+in_template_function (void)
+{
+ tree fn = current_function_decl;
+ bool ret;
+ ++processing_template_decl;
+ ret = (fn && DECL_LANG_SPECIFIC (fn)
+ && DECL_TEMPLATE_INFO (fn)
+ && any_dependent_template_arguments_p (DECL_TI_ARGS (fn)));
+ --processing_template_decl;
+ return ret;
+}
+
/* Returns true if T depends on any template parameter with level LEVEL. */
int
static int tinst_depth;
extern int max_tinst_depth;
-#ifdef GATHER_STATISTICS
int depth_reached;
-#endif
+
static GTY(()) struct tinst_level *last_error_tinst_level;
/* We're starting to instantiate D; record the template instantiation context
current_tinst_level = new_level;
++tinst_depth;
-#ifdef GATHER_STATISTICS
- if (tinst_depth > depth_reached)
+ if (GATHER_STATISTICS && (tinst_depth > depth_reached))
depth_reached = tinst_depth;
-#endif
return 1;
}
return level;
}
-/* Returns TRUE if PARM is a parameter of the template TEMPL. */
-
-bool
-parameter_of_template_p (tree parm, tree templ)
-{
- tree parms;
- int i;
-
- if (!parm || !templ)
- return false;
-
- gcc_assert (DECL_TEMPLATE_PARM_P (parm));
- gcc_assert (TREE_CODE (templ) == TEMPLATE_DECL);
-
- parms = DECL_TEMPLATE_PARMS (templ);
- parms = INNERMOST_TEMPLATE_PARMS (parms);
-
- for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
- {
- tree p = TREE_VALUE (TREE_VEC_ELT (parms, i));
- if (p == error_mark_node)
- continue;
-
- if (parm == p
- || (DECL_INITIAL (parm)
- && DECL_INITIAL (parm) == DECL_INITIAL (p)))
- return true;
- }
-
- return false;
-}
-
/* DECL is a friend FUNCTION_DECL or TEMPLATE_DECL. ARGS is the
vector of template arguments, as for tsubst.
tree tmpl;
tree context;
+ if (DECL_TEMPLATE_TEMPLATE_PARM_P (friend_tmpl))
+ {
+ tree t = tsubst (TREE_TYPE (friend_tmpl), args, tf_none, NULL_TREE);
+ return TREE_TYPE (t);
+ }
+
context = CP_DECL_CONTEXT (friend_tmpl);
if (context != global_namespace)
both F templates are the same. */
tmpl = lookup_name_real (DECL_NAME (friend_tmpl), 0, 0,
- /*block_p=*/true, 0,
- LOOKUP_COMPLAIN | LOOKUP_HIDDEN);
+ /*block_p=*/true, 0, LOOKUP_HIDDEN);
/* But, if we don't find one, it might be because we're in a
situation like this:
/* Perform (or defer) access check for typedefs that were referenced
from within the template TMPL code.
- This is a subroutine of instantiate_template and instantiate_class_template.
+ This is a subroutine of instantiate_decl and instantiate_class_template.
TMPL is the template to consider and TARGS is the list of arguments of
that template. */
perform_typedefs_access_check (tree tmpl, tree targs)
{
location_t saved_location;
- int i;
+ unsigned i;
qualified_typedef_usage_t *iter;
if (!tmpl
return;
saved_location = input_location;
- FOR_EACH_VEC_ELT (qualified_typedef_usage_t,
- get_types_needing_access_check (tmpl),
- i, iter)
+ FOR_EACH_VEC_SAFE_ELT (get_types_needing_access_check (tmpl), i, iter)
{
tree type_decl = iter->typedef_decl;
tree type_scope = iter->context;
of the use of the typedef. */
input_location = iter->locus;
perform_or_defer_access_check (TYPE_BINFO (type_scope),
- type_decl, type_decl);
+ type_decl, type_decl,
+ tf_warning_or_error);
}
input_location = saved_location;
}
/* Build new TYPE_FIELDS. */
if (TREE_CODE (t) == STATIC_ASSERT)
{
- tree condition =
- tsubst_expr (STATIC_ASSERT_CONDITION (t), args,
- tf_warning_or_error, NULL_TREE,
- /*integral_constant_expression_p=*/true);
+ tree condition;
+
+ ++c_inhibit_evaluation_warnings;
+ condition =
+ tsubst_expr (STATIC_ASSERT_CONDITION (t), args,
+ tf_warning_or_error, NULL_TREE,
+ /*integral_constant_expression_p=*/true);
+ --c_inhibit_evaluation_warnings;
+
finish_static_assert (condition,
STATIC_ASSERT_MESSAGE (t),
STATIC_ASSERT_SOURCE_LOCATION (t),
}
else
{
- if (TYPE_P (t) || DECL_CLASS_TEMPLATE_P (t))
+ if (TYPE_P (t) || DECL_CLASS_TEMPLATE_P (t)
+ || DECL_TEMPLATE_TEMPLATE_PARM_P (t))
{
/* Build new CLASSTYPE_FRIEND_CLASSES. */
}
}
- if (CLASSTYPE_LAMBDA_EXPR (type))
+ if (tree expr = CLASSTYPE_LAMBDA_EXPR (type))
{
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);
+
+ /* We need to instantiate the capture list from the template
+ after we've instantiated the closure members, but before we
+ consider adding the conversion op. Also keep any captures
+ that may have been added during instantiation of the op(). */
+ tree tmpl_expr = CLASSTYPE_LAMBDA_EXPR (pattern);
+ tree tmpl_cap
+ = tsubst_copy_and_build (LAMBDA_EXPR_CAPTURE_LIST (tmpl_expr),
+ args, tf_warning_or_error, NULL_TREE,
+ false, false);
+
+ LAMBDA_EXPR_CAPTURE_LIST (expr)
+ = chainon (tmpl_cap, nreverse (LAMBDA_EXPR_CAPTURE_LIST (expr)));
+
maybe_add_lambda_conv_op (type);
}
else
added to the template at parsing time. Let's get those and perform
the access checks then. */
perform_typedefs_access_check (pattern, args);
- perform_deferred_access_checks ();
+ perform_deferred_access_checks (tf_warning_or_error);
pop_nested_class ();
maximum_field_alignment = saved_maximum_field_alignment;
if (!fn_context)
return extract_fnparm_pack (NULL_TREE, &spec_parm);
}
+/* Return true iff the Ith element of the argument pack ARG_PACK is a
+ pack expansion. */
+
+static bool
+argument_pack_element_is_expansion_p (tree arg_pack, int i)
+{
+ tree vec = ARGUMENT_PACK_ARGS (arg_pack);
+ if (i >= TREE_VEC_LENGTH (vec))
+ return false;
+ return PACK_EXPANSION_P (TREE_VEC_ELT (vec, i));
+}
+
+
+/* Creates and return an ARGUMENT_PACK_SELECT tree node. */
+
+static tree
+make_argument_pack_select (tree arg_pack, unsigned index)
+{
+ tree aps = make_node (ARGUMENT_PACK_SELECT);
+
+ ARGUMENT_PACK_SELECT_FROM_PACK (aps) = arg_pack;
+ ARGUMENT_PACK_SELECT_INDEX (aps) = index;
+
+ return aps;
+}
+
+/* This is a subroutine of tsubst_pack_expansion.
+
+ It returns TRUE if we need to use the PACK_EXPANSION_EXTRA_ARGS
+ mechanism to store the (non complete list of) arguments of the
+ substitution and return a non substituted pack expansion, in order
+ to wait for when we have enough arguments to really perform the
+ substitution. */
+
+static bool
+use_pack_expansion_extra_args_p (tree parm_packs,
+ int arg_pack_len,
+ bool has_empty_arg)
+{
+ /* If one pack has an expansion and another pack has a normal
+ argument or if one pack has an empty argument and an another
+ one hasn't then tsubst_pack_expansion cannot perform the
+ substitution and need to fall back on the
+ PACK_EXPANSION_EXTRA mechanism. */
+ if (parm_packs == NULL_TREE)
+ return false;
+ else if (has_empty_arg)
+ return true;
+
+ bool has_expansion_arg = false;
+ for (int i = 0 ; i < arg_pack_len; ++i)
+ {
+ bool has_non_expansion_arg = false;
+ for (tree parm_pack = parm_packs;
+ parm_pack;
+ parm_pack = TREE_CHAIN (parm_pack))
+ {
+ tree arg = TREE_VALUE (parm_pack);
+
+ if (argument_pack_element_is_expansion_p (arg, i))
+ has_expansion_arg = true;
+ else
+ has_non_expansion_arg = true;
+ }
+
+ if (has_expansion_arg && has_non_expansion_arg)
+ return true;
+ }
+ return false;
+}
+
+/* [temp.variadic]/6 says that:
+
+ The instantiation of a pack expansion [...]
+ produces a list E1,E2, ..., En, where N is the number of elements
+ in the pack expansion parameters.
+
+ This subroutine of tsubst_pack_expansion produces one of these Ei.
+
+ PATTERN is the pattern of the pack expansion. PARM_PACKS is a
+ TREE_LIST in which each TREE_PURPOSE is a parameter pack of
+ PATTERN, and each TREE_VALUE is its corresponding argument pack.
+ INDEX is the index 'i' of the element Ei to produce. ARGS,
+ COMPLAIN, and IN_DECL are the same parameters as for the
+ tsubst_pack_expansion function.
+
+ The function returns the resulting Ei upon successful completion,
+ or error_mark_node.
+
+ Note that this function possibly modifies the ARGS parameter, so
+ it's the responsibility of the caller to restore it. */
+
+static tree
+gen_elem_of_pack_expansion_instantiation (tree pattern,
+ tree parm_packs,
+ unsigned index,
+ tree args /* This parm gets
+ modified. */,
+ tsubst_flags_t complain,
+ tree in_decl)
+{
+ tree t;
+ bool ith_elem_is_expansion = false;
+
+ /* For each parameter pack, change the substitution of the parameter
+ pack to the ith argument in its argument pack, then expand the
+ pattern. */
+ for (tree pack = parm_packs; pack; pack = TREE_CHAIN (pack))
+ {
+ tree parm = TREE_PURPOSE (pack);
+ tree arg_pack = TREE_VALUE (pack);
+ tree aps; /* instance of ARGUMENT_PACK_SELECT. */
+
+ ith_elem_is_expansion |=
+ argument_pack_element_is_expansion_p (arg_pack, index);
+
+ /* Select the Ith argument from the pack. */
+ if (TREE_CODE (parm) == PARM_DECL)
+ {
+ if (index == 0)
+ {
+ aps = make_argument_pack_select (arg_pack, index);
+ mark_used (parm);
+ register_local_specialization (aps, parm);
+ }
+ else
+ aps = retrieve_local_specialization (parm);
+ }
+ else
+ {
+ int idx, level;
+ template_parm_level_and_index (parm, &level, &idx);
+
+ if (index == 0)
+ {
+ aps = make_argument_pack_select (arg_pack, index);
+ /* Update the corresponding argument. */
+ TMPL_ARG (args, level, idx) = aps;
+ }
+ else
+ /* Re-use the ARGUMENT_PACK_SELECT. */
+ aps = TMPL_ARG (args, level, idx);
+ }
+ ARGUMENT_PACK_SELECT_INDEX (aps) = index;
+ }
+
+ /* Substitute into the PATTERN with the (possibly altered)
+ arguments. */
+ if (!TYPE_P (pattern))
+ t = tsubst_expr (pattern, args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+ else
+ t = tsubst (pattern, args, complain, in_decl);
+
+ /* If the Ith argument pack element is a pack expansion, then
+ the Ith element resulting from the substituting is going to
+ be a pack expansion as well. */
+ if (ith_elem_is_expansion)
+ t = make_pack_expansion (t);
+
+ return t;
+}
+
/* Substitute ARGS into T, which is an pack expansion
(i.e. TYPE_PACK_EXPANSION or EXPR_PACK_EXPANSION). Returns a
TREE_VEC with the substituted arguments, a PACK_EXPANSION_* node
tree pattern;
tree pack, packs = NULL_TREE;
bool unsubstituted_packs = false;
- bool real_packs = false;
- int missing_level = 0;
int i, len = -1;
tree result;
- htab_t saved_local_specializations = NULL;
+ struct pointer_map_t *saved_local_specializations = NULL;
bool need_local_specializations = false;
int levels;
late-specified return type). Even if it exists, it might
have the wrong value for a recursive call. Just make a
dummy decl, since it's only used for its type. */
- /* Copy before tsubsting so that we don't recurse into any
- later PARM_DECLs. */
- arg_pack = tsubst_decl (copy_node (parm_pack), args, complain);
+ arg_pack = tsubst_decl (parm_pack, args, complain);
if (arg_pack && FUNCTION_PARAMETER_PACK_P (arg_pack))
/* Partial instantiation of the parm_pack, we can't build
up an argument pack yet. */
return result;
}
- 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 =
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);
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. */
- if (unsubstituted_packs)
+ if (use_pack_expansion_extra_args_p (packs, len, unsubstituted_packs))
{
- 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;
+ /* 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. */
- t = make_pack_expansion (pattern);
+ t = make_pack_expansion (pattern);
+ PACK_EXPANSION_EXTRA_ARGS (t) = args;
+ return t;
+ }
+ else if (unsubstituted_packs)
+ {
+ /* 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;
+ }
- /* 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
- {
- /* 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;
+ gcc_assert (len >= 0);
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
+ specializations map; the current map is either NULL or (in the
case of recursive unification) might have bindings that we don't
want to use or alter. */
saved_local_specializations = local_specializations;
- local_specializations = htab_create (37,
- hash_local_specialization,
- eq_local_specializations,
- NULL);
+ local_specializations = pointer_map_create ();
}
/* For each argument in each argument pack, substitute into the
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
- the pattern. */
- 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)
- {
- 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
- {
- int idx, level;
- template_parm_level_and_index (parm, &level, &idx);
-
- if (i == 0)
- {
- 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;
- }
- 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. */
- if (!TYPE_P (pattern))
- TREE_VEC_ELT (result, i) =
- tsubst_expr (pattern, args, complain, in_decl,
- /*integral_constant_expression_p=*/false);
- else
- TREE_VEC_ELT (result, i) = tsubst (pattern, args, complain, in_decl);
-
- if (TREE_VEC_ELT (result, i) == error_mark_node)
+ t = gen_elem_of_pack_expansion_instantiation (pattern, packs,
+ i,
+ args, complain,
+ in_decl);
+ TREE_VEC_ELT (result, i) = t;
+ if (t == error_mark_node)
{
result = error_mark_node;
break;
else
{
int idx, level;
+
+ if (TREE_VALUE (pack) == NULL_TREE)
+ continue;
+
template_parm_level_and_index (parm, &level, &idx);
/* Update the corresponding argument. */
if (need_local_specializations)
{
- htab_delete (local_specializations);
+ pointer_map_destroy (local_specializations);
local_specializations = saved_local_specializations;
}
++processing_template_decl;
for (new_parms = &r;
- TMPL_PARMS_DEPTH (parms) > TMPL_ARGS_DEPTH (args);
+ parms && TMPL_PARMS_DEPTH (parms) > TMPL_ARGS_DEPTH (args);
new_parms = &(TREE_CHAIN (*new_parms)),
parms = TREE_CHAIN (parms))
{
{
tree saved_class_ptr = NULL_TREE;
tree saved_class_ref = NULL_TREE;
+ int errs = errorcount + sorrycount;
/* This can happen in invalid code. */
if (TREE_CODE (arg) == DEFAULT_ARG)
cp_function_chain->x_current_class_ref = saved_class_ref;
}
+ if (errorcount+sorrycount > errs)
+ inform (input_location,
+ " when instantiating default argument for call to %D", fn);
+
/* Make sure the default argument is reasonable. */
arg = check_default_argument (type, arg);
tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (new_type == error_mark_node)
RETURN (error_mark_node);
+ /* If we get a real template back, return it. This can happen in
+ the context of most_specialized_class. */
+ if (TREE_CODE (new_type) == TEMPLATE_DECL)
+ return new_type;
r = copy_decl (t);
DECL_CHAIN (r) = NULL_TREE;
if (type == error_mark_node)
RETURN (error_mark_node);
+ /* If we hit excessive deduction depth, the type is bogus even if
+ it isn't error_mark_node, so don't build a decl. */
+ if (excessive_deduction_depth)
+ RETURN (error_mark_node);
+
/* We do NOT check for matching decls pushed separately at this
point, as they may not represent instantiations of this
template, and in any case are considered separate under the
maybe_retrofit_in_chrg (r);
if (DECL_CONSTRUCTOR_P (r))
grok_ctor_properties (ctx, r);
+ if (DECL_INHERITED_CTOR_BASE (r))
+ deduce_inheriting_ctor (r);
/* If this is an instantiation of a member template, clone it.
If it isn't, that'll be handled by
clone_constructors_and_destructors. */
DECL_CHAIN (prev_r) = r;
}
- if (DECL_CHAIN (t))
+ /* If cp_unevaluated_operand is set, we're just looking for a
+ single dummy parameter, so don't keep going. */
+ if (DECL_CHAIN (t) && !cp_unevaluated_operand)
DECL_CHAIN (r) = tsubst (DECL_CHAIN (t), args,
complain, DECL_CHAIN (t));
if (DECL_DEPENDENT_P (t)
|| uses_template_parms (USING_DECL_SCOPE (t)))
{
- r = do_class_using_decl
- (tsubst_copy (USING_DECL_SCOPE (t), args, complain, in_decl),
- tsubst_copy (DECL_NAME (t), args, complain, in_decl));
+ tree inst_scope = tsubst_copy (USING_DECL_SCOPE (t), args,
+ complain, in_decl);
+ tree name = tsubst_copy (DECL_NAME (t), args, complain, in_decl);
+ r = do_class_using_decl (inst_scope, name);
if (!r)
r = error_mark_node;
else
}
return error_mark_node;
}
+ /* DR 657. */
+ if (abstract_virtuals_error_sfinae (NULL_TREE, type, complain))
+ return error_mark_node;
/* Do array-to-pointer, function-to-pointer conversion, and ignore
top-level qualifiers as required. */
argument in a call of this function. */
remaining_arg_types =
tree_cons (default_arg, type, remaining_arg_types);
- VEC_safe_push (tree, gc, DEFARG_INSTANTIATIONS (default_arg),
- remaining_arg_types);
+ vec_safe_push (DEFARG_INSTANTIATIONS(default_arg), remaining_arg_types);
}
else
remaining_arg_types =
return_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (return_type == error_mark_node)
return error_mark_node;
- /* The standard does not presently indicate that creation of a
- function type with an invalid return type is a deduction failure.
- However, that is clearly analogous to creating an array of "void"
- or a reference to a reference. This is core issue #486. */
+ /* DR 486 clarifies that creation of a function type with an
+ invalid return type is a deduction failure. */
if (TREE_CODE (return_type) == ARRAY_TYPE
|| TREE_CODE (return_type) == FUNCTION_TYPE)
{
}
return error_mark_node;
}
+ /* And DR 657. */
+ if (abstract_virtuals_error_sfinae (NULL_TREE, return_type, complain))
+ return error_mark_node;
/* Substitute the argument types. */
arg_types = tsubst_arg_types (TYPE_ARG_TYPES (t), args, NULL_TREE,
if (TREE_CODE (t) == FUNCTION_TYPE)
{
fntype = build_function_type (return_type, arg_types);
- fntype = apply_memfn_quals (fntype, type_memfn_quals (t));
+ fntype = apply_memfn_quals (fntype,
+ type_memfn_quals (t),
+ type_memfn_rqual (t));
}
else
{
fntype = build_method_type_directly (r, return_type,
TREE_CHAIN (arg_types));
+ fntype = build_ref_qualified_type (fntype, type_memfn_rqual (t));
}
fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
{
tree decl = TYPE_NAME (t);
- if (TYPE_DECL_ALIAS_P (decl)
- && DECL_LANG_SPECIFIC (decl)
- && DECL_TEMPLATE_INFO (decl)
- && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl)))
+ if (alias_template_specialization_p (t))
{
/* 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);
+ instantiate it. */
+ tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
+ tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
+ r = instantiate_alias_template (tmpl, gen_args, complain);
}
else if (DECL_CLASS_SCOPE_P (decl)
&& CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
arg = TMPL_ARG (args, level, idx);
if (arg && TREE_CODE (arg) == ARGUMENT_PACK_SELECT)
- /* See through ARGUMENT_PACK_SELECT arguments. */
- arg = ARGUMENT_PACK_SELECT_ARG (arg);
+ {
+ /* See through ARGUMENT_PACK_SELECT arguments. */
+ arg = ARGUMENT_PACK_SELECT_ARG (arg);
+ /* If the selected argument is an expansion E, that most
+ likely means we were called from
+ gen_elem_of_pack_expansion_instantiation during the
+ substituting of pack an argument pack (which Ith
+ element is a pack expansion, where I is
+ ARGUMENT_PACK_SELECT_INDEX) into a pack expansion.
+ In this case, the Ith element resulting from this
+ substituting is going to be a pack expansion, which
+ pattern is the pattern of E. Let's return the
+ pattern of E, and
+ gen_elem_of_pack_expansion_instantiation will
+ build the resulting pack expansion from it. */
+ if (PACK_EXPANSION_P (arg))
+ arg = PACK_EXPANSION_PATTERN (arg);
+ }
}
if (arg == error_mark_node)
about the template parameter in question. */
return t;
+ /* Early in template argument deduction substitution, we don't
+ want to reduce the level of 'auto', or it will be confused
+ with a normal template parm in subsequent deduction. */
+ if (is_auto (t) && (complain & tf_partial))
+ return t;
+
/* If we get here, we must have been looking at a parm for a
more deeply nested template. Make a new version of this
template parameter, but with a lower level. */
/* The type of the implicit object parameter gets its
cv-qualifiers from the FUNCTION_TYPE. */
tree memptr;
- tree method_type = build_memfn_type (type, r, type_memfn_quals (type));
+ tree method_type
+ = build_memfn_type (type, r, type_memfn_quals (type),
+ type_memfn_rqual (type));
memptr = build_ptrmemfunc_type (build_pointer_type (method_type));
return cp_build_qualified_type_real (memptr, cp_type_quals (t),
complain);
error ("creating array of %qT", type);
return error_mark_node;
}
- if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type))
+ if (ABSTRACT_CLASS_TYPE_P (type))
{
if (complain & tf_error)
error ("creating array of %qT, which is an abstract class type",
}
f = make_typename_type (ctx, f, typename_type,
- (complain & tf_error) | tf_keep_type_decl);
+ complain | tf_keep_type_decl);
if (f == error_mark_node)
return f;
if (TREE_CODE (f) == TYPE_DECL)
++c_inhibit_evaluation_warnings;
type = tsubst_expr (DECLTYPE_TYPE_EXPR (t), args,
- complain, in_decl,
+ complain|tf_decltype, in_decl,
/*integral_constant_expression_p=*/false);
--cp_unevaluated_operand;
else if (DECLTYPE_FOR_LAMBDA_PROXY (t))
type = lambda_proxy_type (type);
else
- type = finish_decltype_type
- (type, DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t), complain);
+ {
+ bool id = DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t);
+ if (id && TREE_CODE (DECLTYPE_TYPE_EXPR (t)) == BIT_NOT_EXPR
+ && EXPR_P (type))
+ /* In a template ~id could be either a complement expression
+ or an unqualified-id naming a destructor; if instantiating
+ it produces an expression, it's not an id-expression or
+ member access. */
+ id = false;
+ type = finish_decltype_type (type, id, complain);
+ }
return cp_build_qualified_type_real (type,
cp_type_quals (t)
| cp_type_quals (type),
tree name;
bool is_template;
tree template_args;
+ location_t loc = UNKNOWN_LOCATION;
gcc_assert (TREE_CODE (qualified_id) == SCOPE_REF);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
is_template = true;
+ loc = EXPR_LOCATION (name);
template_args = TREE_OPERAND (name, 1);
if (template_args)
template_args = tsubst_template_args (template_args, args,
if (dependent_scope_p (scope))
{
if (is_template)
- expr = build_min_nt (TEMPLATE_ID_EXPR, expr, template_args);
+ expr = build_min_nt_loc (loc, TEMPLATE_ID_EXPR, expr, template_args);
return build_qualified_name (NULL_TREE, scope, expr,
QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
}
else if (TYPE_P (scope))
{
expr = (adjust_result_of_qualified_name_lookup
- (expr, scope, current_class_type));
+ (expr, scope, current_nonlambda_class_type ()));
expr = (finish_qualified_id_expr
(scope, expr, done, address_p && PTRMEM_OK_P (qualified_id),
QUALIFIED_NAME_IS_TEMPLATE (qualified_id),
- /*template_arg_p=*/false));
+ /*template_arg_p=*/false, complain));
}
/* Expressions do not generally have reference type. */
case PARM_DECL:
r = retrieve_local_specialization (t);
- if (r == NULL)
+ if (r == NULL_TREE)
{
- tree c;
-
/* We get here for a use of 'this' in an NSDMI. */
if (DECL_NAME (t) == this_identifier
&& at_function_scope_p ()
declaration (such as in a late-specified return type). Just
make a dummy decl, since it's only used for its type. */
gcc_assert (cp_unevaluated_operand != 0);
- /* We copy T because want to tsubst the PARM_DECL only,
- not the following PARM_DECLs that are chained to T. */
- c = copy_node (t);
- r = tsubst_decl (c, args, complain);
+ r = tsubst_decl (t, args, complain);
/* Give it the template pattern as its context; its true context
hasn't been instantiated yet and this is good enough for
mangling. */
When we instantiate f<7>::S::g(), say, lookup_name is not
clever enough to find f<7>::a. */
enum_type
- = tsubst_aggr_type (TREE_TYPE (t), args, complain, in_decl,
+ = tsubst_aggr_type (DECL_CONTEXT (t), args, complain, in_decl,
/*entering_scope=*/0);
for (v = TYPE_VALUES (enum_type);
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
{
- tree expanded;
+ tree expanded, op = TREE_OPERAND (t, 0);
int len = 0;
+ if (SIZEOF_EXPR_TYPE_P (t))
+ op = TREE_TYPE (op);
+
++cp_unevaluated_operand;
++c_inhibit_evaluation_warnings;
/* We only want to compute the number of arguments. */
- expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args,
- complain, in_decl);
+ expanded = tsubst_pack_expansion (op, args, complain, in_decl);
--cp_unevaluated_operand;
--c_inhibit_evaluation_warnings;
else
return build_int_cst (size_type_node, len);
}
+ if (SIZEOF_EXPR_TYPE_P (t))
+ {
+ r = tsubst (TREE_TYPE (TREE_OPERAND (t, 0)),
+ args, complain, in_decl);
+ r = build1 (NOP_EXPR, r, error_mark_node);
+ r = build1 (SIZEOF_EXPR,
+ tsubst (TREE_TYPE (t), args, complain, in_decl), r);
+ SIZEOF_EXPR_TYPE_P (r) = 1;
+ return r;
+ }
/* Fall through */
case INDIRECT_REF:
gcc_unreachable ();
case VA_ARG_EXPR:
- return build_x_va_arg (tsubst_copy (TREE_OPERAND (t, 0), args, complain,
+ return build_x_va_arg (EXPR_LOCATION (t),
+ tsubst_copy (TREE_OPERAND (t, 0), args, complain,
in_decl),
tsubst (TREE_TYPE (t), args, complain, in_decl));
#define RECUR(NODE) \
tsubst_expr ((NODE), args, complain, in_decl, \
integral_constant_expression_p)
- tree decl, init, cond, incr, auto_node;
+ tree decl, init, cond, incr;
+ bool init_decl;
init = TREE_VEC_ELT (OMP_FOR_INIT (t), i);
gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
- decl = RECUR (TREE_OPERAND (init, 0));
+ decl = TREE_OPERAND (init, 0);
init = TREE_OPERAND (init, 1);
- auto_node = type_uses_auto (TREE_TYPE (decl));
- if (auto_node && init)
+ /* Do this before substituting into decl to handle 'auto'. */
+ init_decl = (init && TREE_CODE (init) == DECL_EXPR);
+ init = RECUR (init);
+ decl = RECUR (decl);
+ if (init_decl)
{
- tree init_expr = init;
- if (TREE_CODE (init_expr) == DECL_EXPR)
- init_expr = DECL_INITIAL (DECL_EXPR_DECL (init_expr));
- init_expr = RECUR (init_expr);
- TREE_TYPE (decl)
- = do_auto_deduction (TREE_TYPE (decl), init_expr, auto_node);
+ gcc_assert (!processing_template_decl);
+ init = DECL_INITIAL (decl);
+ DECL_INITIAL (decl) = NULL_TREE;
}
+
gcc_assert (!type_dependent_expression_p (decl));
if (!CLASS_TYPE_P (TREE_TYPE (decl)))
cond = RECUR (TREE_VEC_ELT (OMP_FOR_COND (t), i));
incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i);
if (TREE_CODE (incr) == MODIFY_EXPR)
- incr = build_x_modify_expr (RECUR (TREE_OPERAND (incr, 0)), NOP_EXPR,
+ incr = build_x_modify_expr (EXPR_LOCATION (incr),
+ RECUR (TREE_OPERAND (incr, 0)), NOP_EXPR,
RECUR (TREE_OPERAND (incr, 1)),
complain);
else
return;
}
- if (init && TREE_CODE (init) != DECL_EXPR)
+ if (init && !init_decl)
{
tree c;
for (c = *clauses; c ; c = OMP_CLAUSE_CHAIN (c))
tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
bool integral_constant_expression_p)
{
+#define RETURN(EXP) do { r = (EXP); goto out; } while(0)
#define RECUR(NODE) \
tsubst_expr ((NODE), args, complain, in_decl, \
integral_constant_expression_p)
tree stmt, tmp;
+ tree r;
+ location_t loc;
if (t == NULL_TREE || t == error_mark_node)
return t;
+ loc = input_location;
if (EXPR_HAS_LOCATION (t))
input_location = EXPR_LOCATION (t);
if (STATEMENT_CODE_P (TREE_CODE (t)))
}
insert_capture_proxy (decl);
}
+ else if (DECL_IMPLICIT_TYPEDEF_P (t))
+ /* We already did a pushtag. */;
else
{
int const_init = false;
}
}
- /* A DECL_EXPR can also be used as an expression, in the condition
- clause of an if/for/while construct. */
- return decl;
+ break;
}
case FOR_STMT:
break;
case TAG_DEFN:
- tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
+ tmp = tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
+ if (CLASS_TYPE_P (tmp))
+ {
+ /* Local classes are not independent templates; they are
+ instantiated along with their containing function. And this
+ way we don't have to deal with pushing out of one local class
+ to instantiate a member of another local class. */
+ tree fn;
+ /* Closures are handled by the LAMBDA_EXPR. */
+ gcc_assert (!LAMBDA_TYPE_P (TREE_TYPE (t)));
+ complete_type (tmp);
+ for (fn = TYPE_METHODS (tmp); fn; fn = DECL_CHAIN (fn))
+ if (!DECL_ARTIFICIAL (fn))
+ instantiate_decl (fn, /*defer_ok*/0, /*expl_inst_class*/false);
+ }
break;
case STATIC_ASSERT:
{
- tree condition =
+ tree condition;
+
+ ++c_inhibit_evaluation_warnings;
+ condition =
tsubst_expr (STATIC_ASSERT_CONDITION (t),
args,
complain, in_decl,
/*integral_constant_expression_p=*/true);
+ --c_inhibit_evaluation_warnings;
+
finish_static_assert (condition,
STATIC_ASSERT_MESSAGE (t),
STATIC_ASSERT_SOURCE_LOCATION (t),
condv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
incrv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ stmt = begin_omp_structured_block ();
+
for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++)
tsubst_omp_for_iterator (t, i, declv, initv, condv, incrv,
&clauses, args, complain, in_decl,
integral_constant_expression_p);
- stmt = begin_omp_structured_block ();
-
- for (i = 0; i < TREE_VEC_LENGTH (initv); i++)
- if (TREE_VEC_ELT (initv, i) == NULL
- || TREE_CODE (TREE_VEC_ELT (initv, i)) != DECL_EXPR)
- TREE_VEC_ELT (initv, i) = RECUR (TREE_VEC_ELT (initv, i));
- else if (CLASS_TYPE_P (TREE_TYPE (TREE_VEC_ELT (initv, i))))
- {
- tree init = RECUR (TREE_VEC_ELT (initv, i));
- gcc_assert (init == TREE_VEC_ELT (declv, i));
- TREE_VEC_ELT (initv, i) = NULL_TREE;
- }
- else
- {
- tree decl_expr = TREE_VEC_ELT (initv, i);
- tree init = DECL_INITIAL (DECL_EXPR_DECL (decl_expr));
- gcc_assert (init != NULL);
- TREE_VEC_ELT (initv, i) = RECUR (init);
- DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = NULL;
- RECUR (decl_expr);
- DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = init;
- }
-
pre_body = push_stmt_list ();
RECUR (OMP_FOR_PRE_BODY (t));
pre_body = pop_stmt_list (pre_body);
stmt = build_transaction_expr (EXPR_LOCATION (t),
RECUR (TRANSACTION_EXPR_BODY (t)),
flags, NULL_TREE);
- return stmt;
+ 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)));
+ 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;
+ RETURN (error_mark_node);
case NONTYPE_ARGUMENT_PACK:
error ("use %<...%> to expand argument pack");
- return error_mark_node;
+ RETURN (error_mark_node);
+
+ case COMPOUND_EXPR:
+ tmp = RECUR (TREE_OPERAND (t, 0));
+ if (tmp == NULL_TREE)
+ /* If the first operand was a statement, we're done with it. */
+ RETURN (RECUR (TREE_OPERAND (t, 1)));
+ RETURN (build_x_compound_expr (EXPR_LOCATION (t), tmp,
+ RECUR (TREE_OPERAND (t, 1)),
+ complain));
default:
gcc_assert (!STATEMENT_CODE_P (TREE_CODE (t)));
- return tsubst_copy_and_build (t, args, complain, in_decl,
+ RETURN (tsubst_copy_and_build (t, args, complain, in_decl,
/*function_p=*/false,
- integral_constant_expression_p);
+ integral_constant_expression_p));
}
- return NULL_TREE;
+ RETURN (NULL_TREE);
+ out:
+ input_location = loc;
+ return r;
#undef RECUR
+#undef RETURN
}
/* T is a postfix-expression that is not being used in a function
bool function_p,
bool integral_constant_expression_p)
{
+#define RETURN(EXP) do { retval = (EXP); goto out; } while(0)
#define RECUR(NODE) \
tsubst_copy_and_build (NODE, args, complain, in_decl, \
/*function_p=*/false, \
integral_constant_expression_p)
- tree op1;
+ tree retval, op1;
+ location_t loc;
if (t == NULL_TREE || t == error_mark_node)
return t;
+ loc = input_location;
+ if (EXPR_HAS_LOCATION (t))
+ input_location = EXPR_LOCATION (t);
+
+ /* N3276 decltype magic only applies to calls at the top level or on the
+ right side of a comma. */
+ tsubst_flags_t decltype_flag = (complain & tf_decltype);
+ complain &= ~tf_decltype;
+
switch (TREE_CODE (t))
{
case USING_DECL:
unqualified_name_lookup_error (decl);
decl = error_mark_node;
}
- return decl;
+ RETURN (decl);
}
case TEMPLATE_ID_EXPR:
templ = lookup_template_function (templ, targs);
if (object)
- return build3 (COMPONENT_REF, TREE_TYPE (templ),
- object, templ, NULL_TREE);
+ RETURN (build3 (COMPONENT_REF, TREE_TYPE (templ),
+ object, templ, NULL_TREE));
else
- return baselink_for_fns (templ);
+ RETURN (baselink_for_fns (templ));
}
case INDIRECT_REF:
r = convert_from_reference (r);
}
else
- r = build_x_indirect_ref (r, RO_UNARY_STAR, complain);
- return r;
+ r = build_x_indirect_ref (input_location, r, RO_UNARY_STAR,
+ complain|decltype_flag);
+ RETURN (r);
}
case NOP_EXPR:
- return build_nop
+ RETURN (build_nop
(tsubst (TREE_TYPE (t), args, complain, in_decl),
- RECUR (TREE_OPERAND (t, 0)));
+ RECUR (TREE_OPERAND (t, 0))));
case IMPLICIT_CONV_EXPR:
{
int flags = LOOKUP_IMPLICIT;
if (IMPLICIT_CONV_EXPR_DIRECT_INIT (t))
flags = LOOKUP_NORMAL;
- return perform_implicit_conversion_flags (type, expr, complain,
- flags);
+ RETURN (perform_implicit_conversion_flags (type, expr, complain,
+ flags));
}
case CONVERT_EXPR:
- return build1
+ RETURN (build1
(CONVERT_EXPR,
tsubst (TREE_TYPE (t), args, complain, in_decl),
- RECUR (TREE_OPERAND (t, 0)));
+ RECUR (TREE_OPERAND (t, 0))));
case CAST_EXPR:
case REINTERPRET_CAST_EXPR:
case STATIC_CAST_EXPR:
{
tree type;
- tree op;
+ tree op, r = NULL_TREE;
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (integral_constant_expression_p
if (complain & tf_error)
error ("a cast to a type other than an integral or "
"enumeration type cannot appear in a constant-expression");
- return error_mark_node;
+ RETURN (error_mark_node);
}
op = RECUR (TREE_OPERAND (t, 0));
+ ++c_inhibit_evaluation_warnings;
switch (TREE_CODE (t))
{
case CAST_EXPR:
- return build_functional_cast (type, op, complain);
+ r = build_functional_cast (type, op, complain);
+ break;
case REINTERPRET_CAST_EXPR:
- return build_reinterpret_cast (type, op, complain);
+ r = build_reinterpret_cast (type, op, complain);
+ break;
case CONST_CAST_EXPR:
- return build_const_cast (type, op, complain);
+ r = build_const_cast (type, op, complain);
+ break;
case DYNAMIC_CAST_EXPR:
- return build_dynamic_cast (type, op, complain);
+ r = build_dynamic_cast (type, op, complain);
+ break;
case STATIC_CAST_EXPR:
- return build_static_cast (type, op, complain);
+ r = build_static_cast (type, op, complain);
+ break;
default:
gcc_unreachable ();
}
+ --c_inhibit_evaluation_warnings;
+
+ RETURN (r);
}
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
args, complain, in_decl);
- return build_x_unary_op (TREE_CODE (t), op1, complain);
+ RETURN (build_x_unary_op (input_location, TREE_CODE (t), op1,
+ complain|decltype_flag));
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
case UNARY_PLUS_EXPR: /* Unary + */
case REALPART_EXPR:
case IMAGPART_EXPR:
- return build_x_unary_op (TREE_CODE (t), RECUR (TREE_OPERAND (t, 0)),
- complain);
+ RETURN (build_x_unary_op (input_location, TREE_CODE (t),
+ RECUR (TREE_OPERAND (t, 0)),
+ complain|decltype_flag));
case FIX_TRUNC_EXPR:
- return cp_build_unary_op (FIX_TRUNC_EXPR, RECUR (TREE_OPERAND (t, 0)),
- 0, complain);
+ 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)
- return finish_label_address_expr (DECL_NAME (op1),
- EXPR_LOCATION (op1));
+ RETURN (finish_label_address_expr (DECL_NAME (op1),
+ EXPR_LOCATION (op1)));
if (TREE_CODE (op1) == SCOPE_REF)
op1 = tsubst_qualified_id (op1, args, complain, in_decl,
/*done=*/true, /*address_p=*/true);
else
op1 = tsubst_non_call_postfix_expression (op1, args, complain,
in_decl);
- return build_x_unary_op (ADDR_EXPR, op1, complain);
+ RETURN (build_x_unary_op (input_location, ADDR_EXPR, op1,
+ complain|decltype_flag));
case PLUS_EXPR:
case MINUS_EXPR:
case MEMBER_REF:
case DOTSTAR_EXPR:
{
- tree r = build_x_binary_op
- (TREE_CODE (t),
+ tree r;
+
+ ++c_inhibit_evaluation_warnings;
+
+ r = build_x_binary_op
+ (input_location, TREE_CODE (t),
RECUR (TREE_OPERAND (t, 0)),
(TREE_NO_WARNING (TREE_OPERAND (t, 0))
? ERROR_MARK
? ERROR_MARK
: TREE_CODE (TREE_OPERAND (t, 1))),
/*overload=*/NULL,
- complain);
+ complain|decltype_flag);
if (EXPR_P (r) && TREE_NO_WARNING (t))
TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
- return r;
+
+ --c_inhibit_evaluation_warnings;
+
+ RETURN (r);
}
case SCOPE_REF:
- return tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
- /*address_p=*/false);
+ RETURN (tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
+ /*address_p=*/false));
case ARRAY_REF:
op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
args, complain, in_decl);
- return build_x_array_ref (op1, RECUR (TREE_OPERAND (t, 1)), complain);
+ RETURN (build_x_array_ref (EXPR_LOCATION (t), op1,
+ RECUR (TREE_OPERAND (t, 1)),
+ complain|decltype_flag));
case SIZEOF_EXPR:
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
- return tsubst_copy (t, args, complain, in_decl);
+ RETURN (tsubst_copy (t, args, complain, in_decl));
/* Fall through */
case ALIGNOF_EXPR:
- op1 = TREE_OPERAND (t, 0);
- if (!args)
- {
- /* When there are no ARGS, we are trying to evaluate a
- non-dependent expression from the parser. Trying to do
- the substitutions may not work. */
- if (!TYPE_P (op1))
- op1 = TREE_TYPE (op1);
- }
- else
- {
- ++cp_unevaluated_operand;
- ++c_inhibit_evaluation_warnings;
- op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
- /*function_p=*/false,
- /*integral_constant_expression_p=*/false);
- --cp_unevaluated_operand;
- --c_inhibit_evaluation_warnings;
- }
- if (TYPE_P (op1))
- return cxx_sizeof_or_alignof_type (op1, TREE_CODE (t),
- complain & tf_error);
- else
- return cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
- complain & tf_error);
+ {
+ tree r;
+
+ op1 = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
+ op1 = TREE_TYPE (op1);
+ if (!args)
+ {
+ /* When there are no ARGS, we are trying to evaluate a
+ non-dependent expression from the parser. Trying to do
+ the substitutions may not work. */
+ if (!TYPE_P (op1))
+ op1 = TREE_TYPE (op1);
+ }
+ else
+ {
+ ++cp_unevaluated_operand;
+ ++c_inhibit_evaluation_warnings;
+ if (TYPE_P (op1))
+ op1 = tsubst (op1, args, complain, in_decl);
+ else
+ op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
+ /*function_p=*/false,
+ /*integral_constant_expression_p=*/
+ false);
+ --cp_unevaluated_operand;
+ --c_inhibit_evaluation_warnings;
+ }
+ if (TYPE_P (op1))
+ r = cxx_sizeof_or_alignof_type (op1, TREE_CODE (t),
+ complain & tf_error);
+ else
+ r = cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
+ complain & tf_error);
+ if (TREE_CODE (t) == SIZEOF_EXPR && r != error_mark_node)
+ {
+ if (TREE_CODE (r) != SIZEOF_EXPR || TYPE_P (op1))
+ {
+ if (!processing_template_decl && TYPE_P (op1))
+ {
+ r = build_min (SIZEOF_EXPR, size_type_node,
+ build1 (NOP_EXPR, op1, error_mark_node));
+ SIZEOF_EXPR_TYPE_P (r) = 1;
+ }
+ else
+ r = build_min (SIZEOF_EXPR, size_type_node, op1);
+ TREE_SIDE_EFFECTS (r) = 0;
+ TREE_READONLY (r) = 1;
+ }
+ SET_EXPR_LOCATION (r, EXPR_LOCATION (t));
+ }
+ RETURN (r);
+ }
case AT_ENCODE_EXPR:
{
/*integral_constant_expression_p=*/false);
--cp_unevaluated_operand;
--c_inhibit_evaluation_warnings;
- return objc_build_encode_expr (op1);
+ RETURN (objc_build_encode_expr (op1));
}
case NOEXCEPT_EXPR:
/*integral_constant_expression_p=*/false);
--cp_unevaluated_operand;
--c_inhibit_evaluation_warnings;
- return finish_noexcept_expr (op1, complain);
+ RETURN (finish_noexcept_expr (op1, complain));
case MODOP_EXPR:
{
tree r = build_x_modify_expr
- (RECUR (TREE_OPERAND (t, 0)),
+ (EXPR_LOCATION (t),
+ RECUR (TREE_OPERAND (t, 0)),
TREE_CODE (TREE_OPERAND (t, 1)),
RECUR (TREE_OPERAND (t, 2)),
- complain);
+ complain|decltype_flag);
/* TREE_NO_WARNING must be set if either the expression was
parenthesized or it uses an operator such as >>= rather
than plain assignment. In the former case, it was already
here. */
if (TREE_NO_WARNING (t))
TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
- return r;
+ RETURN (r);
}
case ARROW_EXPR:
/* Remember that there was a reference to this entity. */
if (DECL_P (op1))
mark_used (op1);
- return build_x_arrow (op1);
+ RETURN (build_x_arrow (input_location, op1, complain));
case NEW_EXPR:
{
tree placement = RECUR (TREE_OPERAND (t, 0));
tree init = RECUR (TREE_OPERAND (t, 3));
- VEC(tree,gc) *placement_vec;
- VEC(tree,gc) *init_vec;
+ vec<tree, va_gc> *placement_vec;
+ vec<tree, va_gc> *init_vec;
tree ret;
if (placement == NULL_TREE)
{
placement_vec = make_tree_vector ();
for (; placement != NULL_TREE; placement = TREE_CHAIN (placement))
- VEC_safe_push (tree, gc, placement_vec, TREE_VALUE (placement));
+ vec_safe_push (placement_vec, TREE_VALUE (placement));
}
/* If there was an initializer in the original tree, but it
else
{
for (; init != NULL_TREE; init = TREE_CHAIN (init))
- VEC_safe_push (tree, gc, init_vec, TREE_VALUE (init));
+ vec_safe_push (init_vec, TREE_VALUE (init));
}
}
if (init_vec != NULL)
release_tree_vector (init_vec);
- return ret;
+ RETURN (ret);
}
case DELETE_EXPR:
- return delete_sanity
+ RETURN (delete_sanity
(RECUR (TREE_OPERAND (t, 0)),
RECUR (TREE_OPERAND (t, 1)),
DELETE_EXPR_USE_VEC (t),
DELETE_EXPR_USE_GLOBAL (t),
- complain);
+ complain));
case COMPOUND_EXPR:
- return build_x_compound_expr (RECUR (TREE_OPERAND (t, 0)),
- RECUR (TREE_OPERAND (t, 1)),
- complain);
+ {
+ tree op0 = tsubst_copy_and_build (TREE_OPERAND (t, 0), args,
+ complain & ~tf_decltype, in_decl,
+ /*function_p=*/false,
+ integral_constant_expression_p);
+ RETURN (build_x_compound_expr (EXPR_LOCATION (t),
+ op0,
+ RECUR (TREE_OPERAND (t, 1)),
+ complain|decltype_flag));
+ }
case CALL_EXPR:
{
tree function;
- VEC(tree,gc) *call_args;
+ vec<tree, va_gc> *call_args;
unsigned int nargs, i;
bool qualified_p;
bool koenig_p;
else
qualified_p = false;
+ if (TREE_CODE (function) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
+ /* Avoid error about taking the address of a constructor. */
+ function = TREE_OPERAND (function, 0);
+
function = tsubst_copy_and_build (function, args, complain,
in_decl,
!qualified_p,
tree arg = CALL_EXPR_ARG (t, i);
if (!PACK_EXPANSION_P (arg))
- VEC_safe_push (tree, gc, call_args,
- RECUR (CALL_EXPR_ARG (t, i)));
+ vec_safe_push (call_args, RECUR (CALL_EXPR_ARG (t, i)));
else
{
/* Expand the pack expansion and push each entry onto
tree value = TREE_VEC_ELT (arg, j);
if (value != NULL_TREE)
value = convert_from_reference (value);
- VEC_safe_push (tree, gc, call_args, value);
+ vec_safe_push (call_args, value);
}
}
else
{
/* A partial substitution. Add one entry. */
- VEC_safe_push (tree, gc, call_args, arg);
+ vec_safe_push (call_args, arg);
}
}
}
(function, args, complain, in_decl, true,
integral_constant_expression_p));
if (unq == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
if (unq != function)
{
}
if (TREE_CODE (function) == IDENTIFIER_NODE)
{
- unqualified_name_lookup_error (function);
+ if (complain & tf_error)
+ unqualified_name_lookup_error (function);
release_tree_vector (call_args);
- return error_mark_node;
+ RETURN (error_mark_node);
}
}
if (DECL_P (function))
mark_used (function);
+ /* Put back tf_decltype for the actual call. */
+ complain |= decltype_flag;
+
if (TREE_CODE (function) == OFFSET_REF)
- ret = build_offset_ref_call_from_tree (function, &call_args);
+ ret = build_offset_ref_call_from_tree (function, &call_args,
+ complain);
else if (TREE_CODE (function) == COMPONENT_REF)
{
tree instance = TREE_OPERAND (function, 0);
release_tree_vector (call_args);
- return ret;
+ RETURN (ret);
}
case COND_EXPR:
- return build_x_conditional_expr
- (RECUR (TREE_OPERAND (t, 0)),
- RECUR (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2)),
- complain);
+ {
+ tree cond = RECUR (TREE_OPERAND (t, 0));
+ tree exp1, exp2;
+
+ if (TREE_CODE (cond) == INTEGER_CST)
+ {
+ if (integer_zerop (cond))
+ {
+ ++c_inhibit_evaluation_warnings;
+ exp1 = RECUR (TREE_OPERAND (t, 1));
+ --c_inhibit_evaluation_warnings;
+ exp2 = RECUR (TREE_OPERAND (t, 2));
+ }
+ else
+ {
+ exp1 = RECUR (TREE_OPERAND (t, 1));
+ ++c_inhibit_evaluation_warnings;
+ exp2 = RECUR (TREE_OPERAND (t, 2));
+ --c_inhibit_evaluation_warnings;
+ }
+ }
+ else
+ {
+ exp1 = RECUR (TREE_OPERAND (t, 1));
+ exp2 = RECUR (TREE_OPERAND (t, 2));
+ }
+
+ RETURN (build_x_conditional_expr (EXPR_LOCATION (t),
+ cond, exp1, exp2, complain));
+ }
case PSEUDO_DTOR_EXPR:
- return finish_pseudo_destructor_expr
+ RETURN (finish_pseudo_destructor_expr
(RECUR (TREE_OPERAND (t, 0)),
RECUR (TREE_OPERAND (t, 1)),
- tsubst (TREE_OPERAND (t, 2), args, complain, in_decl));
+ tsubst (TREE_OPERAND (t, 2), args, complain, in_decl)));
case TREE_LIST:
{
tree purpose, value, chain;
if (t == void_list_node)
- return t;
+ RETURN (t);
if ((TREE_PURPOSE (t) && PACK_EXPANSION_P (TREE_PURPOSE (t)))
|| (TREE_VALUE (t) && PACK_EXPANSION_P (TREE_VALUE (t))))
else
{
/* Since we only performed a partial substitution into
- the argument pack, we only return a single list
+ the argument pack, we only RETURN (a single list
node. */
if (purposevec == TREE_PURPOSE (t)
&& valuevec == TREE_VALUE (t)
&& chain == TREE_CHAIN (t))
- return t;
+ RETURN (t);
- return tree_cons (purposevec, valuevec, chain);
+ RETURN (tree_cons (purposevec, valuevec, chain));
}
/* Convert the argument vectors into a TREE_LIST */
chain = tree_cons (purpose, value, chain);
}
- return chain;
+ RETURN (chain);
}
purpose = TREE_PURPOSE (t);
if (purpose == TREE_PURPOSE (t)
&& value == TREE_VALUE (t)
&& chain == TREE_CHAIN (t))
- return t;
- return tree_cons (purpose, value, chain);
+ RETURN (t);
+ RETURN (tree_cons (purpose, value, chain));
}
case COMPONENT_REF:
else
member = tsubst_copy (member, args, complain, in_decl);
if (member == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
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))
+ if (scalarish_type_p (object_type))
{
tree s = NULL_TREE;
tree dtor = member;
{
dtor = TREE_OPERAND (dtor, 0);
if (TYPE_P (dtor))
- return finish_pseudo_destructor_expr (object, s, dtor);
+ RETURN (finish_pseudo_destructor_expr (object, s, dtor));
}
}
}
{
qualified_name_lookup_error (scope, tmpl, member,
input_location);
- return error_mark_node;
+ RETURN (error_mark_node);
}
}
else if (TREE_CODE (member) == SCOPE_REF
error ("%qD is not a class or namespace",
TREE_OPERAND (member, 0));
}
- return error_mark_node;
+ RETURN (error_mark_node);
}
else if (TREE_CODE (member) == FIELD_DECL)
- return finish_non_static_data_member (member, object, NULL_TREE);
+ RETURN (finish_non_static_data_member (member, object, NULL_TREE));
- return finish_class_member_access_expr (object, member,
+ RETURN (finish_class_member_access_expr (object, member,
/*template_p=*/false,
- complain);
+ complain));
}
case THROW_EXPR:
- return build_throw
- (RECUR (TREE_OPERAND (t, 0)));
+ RETURN (build_throw
+ (RECUR (TREE_OPERAND (t, 0))));
case CONSTRUCTOR:
{
- VEC(constructor_elt,gc) *n;
+ vec<constructor_elt, va_gc> *n;
constructor_elt *ce;
unsigned HOST_WIDE_INT idx;
tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
tree r;
if (type == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
/* digest_init will do the wrong thing if we let it. */
if (type && TYPE_PTRMEMFUNC_P (type))
- return t;
+ RETURN (t);
/* We do not want to process the index of aggregate
initializers as they are identifier nodes which will be
looked up by digest_init. */
process_index_p = !(type && MAYBE_CLASS_TYPE_P (type));
- n = VEC_copy (constructor_elt, gc, CONSTRUCTOR_ELTS (t));
- newlen = VEC_length (constructor_elt, n);
- FOR_EACH_VEC_ELT (constructor_elt, n, idx, ce)
+ n = vec_safe_copy (CONSTRUCTOR_ELTS (t));
+ newlen = vec_safe_length (n);
+ FOR_EACH_VEC_SAFE_ELT (n, idx, ce)
{
- if (ce->index && process_index_p)
+ if (ce->index && process_index_p
+ /* An identifier index is looked up in the type
+ being initialized, not the current scope. */
+ && TREE_CODE (ce->index) != IDENTIFIER_NODE)
ce->index = RECUR (ce->index);
if (PACK_EXPANSION_P (ce->value))
if (need_copy_p)
{
- VEC(constructor_elt,gc) *old_n = n;
+ vec<constructor_elt, va_gc> *old_n = n;
- n = VEC_alloc (constructor_elt, gc, newlen);
- FOR_EACH_VEC_ELT (constructor_elt, old_n, idx, ce)
+ vec_alloc (n, newlen);
+ FOR_EACH_VEC_ELT (*old_n, idx, ce)
{
if (TREE_CODE (ce->value) == TREE_VEC)
{
CONSTRUCTOR_IS_DIRECT_INIT (r) = CONSTRUCTOR_IS_DIRECT_INIT (t);
if (TREE_HAS_CONSTRUCTOR (t))
- return finish_compound_literal (type, r, complain);
+ RETURN (finish_compound_literal (type, r, complain));
TREE_TYPE (r) = type;
- return r;
+ RETURN (r);
}
case TYPEID_EXPR:
if (TYPE_P (operand_0))
{
operand_0 = tsubst (operand_0, args, complain, in_decl);
- return get_typeid (operand_0);
+ RETURN (get_typeid (operand_0, complain));
}
else
{
operand_0 = RECUR (operand_0);
- return build_typeid (operand_0);
+ RETURN (build_typeid (operand_0, complain));
}
}
case VAR_DECL:
if (!args)
- return t;
+ RETURN (t);
/* Fall through */
case PARM_DECL:
/* If the original type was a reference, we'll be wrapped in
the appropriate INDIRECT_REF. */
r = convert_from_reference (r);
- return r;
+ RETURN (r);
}
case VA_ARG_EXPR:
- return build_x_va_arg (RECUR (TREE_OPERAND (t, 0)),
- tsubst (TREE_TYPE (t), args, complain, in_decl));
+ RETURN (build_x_va_arg (EXPR_LOCATION (t),
+ RECUR (TREE_OPERAND (t, 0)),
+ tsubst (TREE_TYPE (t), args, complain, in_decl)));
case OFFSETOF_EXPR:
- return finish_offsetof (RECUR (TREE_OPERAND (t, 0)));
+ RETURN (finish_offsetof (RECUR (TREE_OPERAND (t, 0))));
case TRAIT_EXPR:
{
if (type2)
type2 = tsubst_copy (type2, args, complain, in_decl);
- return finish_trait_expr (TRAIT_EXPR_KIND (t), type1, type2);
+ RETURN (finish_trait_expr (TRAIT_EXPR_KIND (t), type1, type2));
}
case STMT_EXPR:
if (empty_expr_stmt_p (stmt_expr))
stmt_expr = void_zero_node;
- return stmt_expr;
+ RETURN (stmt_expr);
}
- case CONST_DECL:
- 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 && !processing_template_decl)
- {
- used_types_insert (TREE_TYPE (t));
- return DECL_INITIAL (t);
- }
- return t;
-
case LAMBDA_EXPR:
{
tree r = build_lambda_expr ();
LAMBDA_EXPR_MUTABLE_P (r) = LAMBDA_EXPR_MUTABLE_P (t);
LAMBDA_EXPR_DISCRIMINATOR (r)
= (LAMBDA_EXPR_DISCRIMINATOR (t));
- LAMBDA_EXPR_EXTRA_SCOPE (r)
- = RECUR (LAMBDA_EXPR_EXTRA_SCOPE (t));
- if (LAMBDA_EXPR_RETURN_TYPE (t) == dependent_lambda_return_type_node)
+ /* For a function scope, we want to use tsubst so that we don't
+ complain about referring to an auto function before its return
+ type has been deduced. Otherwise, we want to use tsubst_copy so
+ that we look up the existing field/parameter/variable rather
+ than build a new one. */
+ tree scope = LAMBDA_EXPR_EXTRA_SCOPE (t);
+ if (scope && TREE_CODE (scope) == FUNCTION_DECL)
+ scope = tsubst (scope, args, complain, in_decl);
+ else if (scope && TREE_CODE (scope) == PARM_DECL)
{
- LAMBDA_EXPR_RETURN_TYPE (r) = dependent_lambda_return_type_node;
- LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (r) = true;
+ /* Look up the parameter we want directly, as tsubst_copy
+ doesn't do what we need. */
+ tree fn = tsubst (DECL_CONTEXT (scope), args, complain, in_decl);
+ tree parm = FUNCTION_FIRST_USER_PARM (fn);
+ while (DECL_PARM_INDEX (parm) != DECL_PARM_INDEX (scope))
+ parm = DECL_CHAIN (parm);
+ scope = parm;
+ /* FIXME Work around the parm not having DECL_CONTEXT set. */
+ if (DECL_CONTEXT (scope) == NULL_TREE)
+ DECL_CONTEXT (scope) = fn;
}
else
- LAMBDA_EXPR_RETURN_TYPE (r)
- = tsubst (LAMBDA_EXPR_RETURN_TYPE (t), args, complain, in_decl);
+ scope = RECUR (scope);
+ LAMBDA_EXPR_EXTRA_SCOPE (r) = scope;
+ 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);
- /* The capture list refers to closure members, so this needs to
- wait until after we finish instantiating the type. Also keep
- any captures that may have been added during instantiation. */
- LAMBDA_EXPR_CAPTURE_LIST (r)
- = chainon (RECUR (LAMBDA_EXPR_CAPTURE_LIST (t)),
- LAMBDA_EXPR_CAPTURE_LIST (r));
LAMBDA_EXPR_THIS_CAPTURE (r) = NULL_TREE;
- return build_lambda_object (r);
+ RETURN (build_lambda_object (r));
}
case TARGET_EXPR:
/* We can get here for a constant initializer of non-dependent type.
FIXME stop folding in cp_parser_initializer_clause. */
{
- tree r = get_target_expr (RECUR (TARGET_EXPR_INITIAL (t)));
- return r;
+ tree r = get_target_expr_sfinae (RECUR (TARGET_EXPR_INITIAL (t)),
+ complain);
+ RETURN (r);
}
case TRANSACTION_EXPR:
- return tsubst_expr(t, args, complain, in_decl,
- integral_constant_expression_p);
+ RETURN (tsubst_expr(t, args, complain, in_decl,
+ integral_constant_expression_p));
default:
/* Handle Objective-C++ constructs, if appropriate. */
= objcp_tsubst_copy_and_build (t, args, complain,
in_decl, /*function_p=*/false);
if (subst)
- return subst;
+ RETURN (subst);
}
- return tsubst_copy (t, args, complain, in_decl);
+ RETURN (tsubst_copy (t, args, complain, in_decl));
}
#undef RECUR
+#undef RETURN
+ out:
+ input_location = loc;
+ return retval;
}
/* Verify that the instantiated ARGS are valid. For type arguments,
static bool
check_instantiated_arg (tree tmpl, tree t, tsubst_flags_t complain)
{
+ if (dependent_template_arg_p (t))
+ return false;
if (ARGUMENT_PACK_P (t))
{
tree vec = ARGUMENT_PACK_ARGS (t);
return true;
}
}
+ /* Class template and alias template arguments should be OK. */
+ else if (DECL_TYPE_TEMPLATE_P (t))
+ ;
/* A non-type argument of integral or enumerated type must be a
constant. */
else if (TREE_TYPE (t)
return result;
}
-/* In C++0x, it's possible to have a function template whose type depends
- on itself recursively. This is most obvious with decltype, but can also
- occur with enumeration scope (c++/48969). So we need to catch infinite
- recursion and reject the substitution at deduction time; this function
- will return error_mark_node for any repeated substitution.
-
- This also catches excessive recursion such as when f<N> depends on
- f<N-1> across all integers, and returns error_mark_node for all the
- substitutions back up to the initial one.
+/* We're out of SFINAE context now, so generate diagnostics for the access
+ errors we saw earlier when instantiating D from TMPL and ARGS. */
- This is, of course, not reentrant. */
-
-static tree
-deduction_tsubst_fntype (tree fn, tree targs, tsubst_flags_t complain)
+static void
+recheck_decl_substitution (tree d, tree tmpl, tree args)
{
- 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;
- tree r;
-
- if (excessive_deduction_depth)
- return error_mark_node;
-
- tinst = build_tree_list (fn, targs);
- if (!push_tinst_level (tinst))
- {
- excessive_deduction_depth = true;
- ggc_free (tinst);
- return error_mark_node;
- }
-
- input_location = DECL_SOURCE_LOCATION (fn);
- ++deduction_depth;
- push_deduction_access_scope (fn);
- r = tsubst (fntype, targs, complain, NULL_TREE);
- pop_deduction_access_scope (fn);
- --deduction_depth;
-
- if (excessive_deduction_depth)
- {
- r = error_mark_node;
- if (deduction_depth == 0)
- /* Reset once we're all the way out. */
- excessive_deduction_depth = false;
- }
+ tree pattern = DECL_TEMPLATE_RESULT (tmpl);
+ tree type = TREE_TYPE (pattern);
+ location_t loc = input_location;
- pop_tinst_level ();
- /* 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;
+ push_access_scope (d);
+ push_deferring_access_checks (dk_no_deferred);
+ input_location = DECL_SOURCE_LOCATION (pattern);
+ tsubst (type, args, tf_warning_or_error, d);
+ input_location = loc;
+ pop_deferring_access_checks ();
+ pop_access_scope (d);
}
-/* Instantiate the indicated variable or function template TMPL with
+/* Instantiate the indicated variable, function, or alias template TMPL with
the template arguments in TARG_PTR. */
static tree
tree fndecl;
tree gen_tmpl;
tree spec;
+ bool access_ok = true;
if (tmpl == error_mark_node)
return error_mark_node;
|| fndecl == NULL_TREE);
if (spec != NULL_TREE)
- return spec;
+ {
+ if (FNDECL_HAS_ACCESS_ERRORS (spec))
+ {
+ if (complain & tf_error)
+ recheck_decl_substitution (spec, gen_tmpl, targ_ptr);
+ return error_mark_node;
+ }
+ return spec;
+ }
if (check_instantiated_args (gen_tmpl, INNERMOST_TEMPLATE_ARGS (targ_ptr),
complain))
/* 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 there are dependent arguments, e.g. because we're doing partial
+ ordering, make sure processing_template_decl stays set. */
+ if (uses_template_parms (targ_ptr))
+ ++processing_template_decl;
if (DECL_CLASS_SCOPE_P (gen_tmpl))
{
tree ctx = tsubst (DECL_CONTEXT (gen_tmpl), targ_ptr,
pop_from_top_level ();
if (fndecl == error_mark_node)
- return error_mark_node;
+ {
+ pop_deferring_access_checks ();
+ return error_mark_node;
+ }
+
+ /* The DECL_TI_TEMPLATE should always be the immediate parent
+ template, not the most general template. */
+ DECL_TI_TEMPLATE (fndecl) = tmpl;
/* Now we know the specialization, compute access previously
deferred. */
push_access_scope (fndecl);
-
- /* Some typedefs referenced from within the template code need to be access
- checked at template instantiation time, i.e now. These types were
- added to the template at parsing time. Let's get those and perfom
- the acces checks then. */
- perform_typedefs_access_check (DECL_TEMPLATE_RESULT (tmpl), targ_ptr);
- perform_deferred_access_checks ();
+ if (!perform_deferred_access_checks (complain))
+ access_ok = false;
pop_access_scope (fndecl);
pop_deferring_access_checks ();
- /* The DECL_TI_TEMPLATE should always be the immediate parent
- template, not the most general template. */
- DECL_TI_TEMPLATE (fndecl) = tmpl;
-
/* If we've just instantiated the main entry point for a function,
instantiate all the alternate entry points as well. We do this
by cloning the instantiation of the main entry point, not by
if (DECL_CHAIN (gen_tmpl) && DECL_CLONED_FUNCTION_P (DECL_CHAIN (gen_tmpl)))
clone_function_decl (fndecl, /*update_method_vec_p=*/0);
+ if (!access_ok)
+ {
+ if (!(complain & tf_error))
+ {
+ /* Remember to reinstantiate when we're out of SFINAE so the user
+ can see the errors. */
+ FNDECL_HAS_ACCESS_ERRORS (fndecl) = true;
+ }
+ return error_mark_node;
+ }
return fndecl;
}
return ret;
}
-/* We're going to do deduction substitution on the type of TMPL, a function
- template. In C++11 mode, push into that access scope. In C++03 mode,
- disable access checking. */
+/* Instantiate the alias template TMPL with ARGS. Also push a template
+ instantiation level, which instantiate_template doesn't do because
+ functions and variables have sufficient context established by the
+ callers. */
-static void
-push_deduction_access_scope (tree tmpl)
+static tree
+instantiate_alias_template (tree tmpl, tree args, tsubst_flags_t complain)
{
- if (cxx_dialect >= cxx0x)
+ struct pending_template *old_last_pend = last_pending_template;
+ struct tinst_level *old_error_tinst = last_error_tinst_level;
+ if (tmpl == error_mark_node || args == error_mark_node)
+ return error_mark_node;
+ tree tinst = build_tree_list (tmpl, args);
+ if (!push_tinst_level (tinst))
{
- 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;
+ ggc_free (tinst);
+ return error_mark_node;
}
- else
- push_deferring_access_checks (dk_no_check);
-}
-/* And pop back out. */
+ args =
+ coerce_innermost_template_parms (DECL_TEMPLATE_PARMS (tmpl),
+ args, tmpl, complain,
+ /*require_all_args=*/true,
+ /*use_default_args=*/true);
-static void
-pop_deduction_access_scope (tree tmpl)
-{
- if (cxx_dialect >= cxx0x)
- pop_access_scope (DECL_TEMPLATE_RESULT (tmpl));
- else
- pop_deferring_access_checks ();
+ tree r = instantiate_template (tmpl, args, complain);
+ pop_tinst_level ();
+ /* 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;
}
/* PARM is a template parameter pack for FN. Returns true iff
as in [temp.expl.spec], or when taking the address of a function
template, as in [temp.deduct.funcaddr]. */
-int
+tree
fn_type_unification (tree fn,
tree explicit_targs,
tree targs,
{
tree parms;
tree fntype;
- int result;
+ tree decl = NULL_TREE;
+ tsubst_flags_t complain = (explain_p ? tf_warning_or_error : tf_none);
+ bool ok;
+ static int deduction_depth;
+ struct pending_template *old_last_pend = last_pending_template;
+ struct tinst_level *old_error_tinst = last_error_tinst_level;
+ tree tparms = DECL_INNERMOST_TEMPLATE_PARMS (fn);
+ tree tinst;
+ tree r = error_mark_node;
+
+ /* In C++0x, it's possible to have a function template whose type depends
+ on itself recursively. This is most obvious with decltype, but can also
+ occur with enumeration scope (c++/48969). So we need to catch infinite
+ recursion and reject the substitution at deduction time; this function
+ will return error_mark_node for any repeated substitution.
+
+ This also catches excessive recursion such as when f<N> depends on
+ f<N-1> across all integers, and returns error_mark_node for all the
+ substitutions back up to the initial one.
+
+ This is, of course, not reentrant. */
+ if (excessive_deduction_depth)
+ return error_mark_node;
+ tinst = build_tree_list (fn, NULL_TREE);
+ ++deduction_depth;
+ push_deferring_access_checks (dk_deferred);
gcc_assert (TREE_CODE (fn) == TEMPLATE_DECL);
specified template argument values. If a substitution in a
template parameter or in the function type of the function
template results in an invalid type, type deduction fails. */
- tree tparms = DECL_INNERMOST_TEMPLATE_PARMS (fn);
int i, len = TREE_VEC_LENGTH (tparms);
- tree converted_args;
+ location_t loc = input_location;
bool incomplete = false;
- if (explicit_targs == error_mark_node)
- return unify_invalid (explain_p);
-
- converted_args
+ /* Adjust any explicit template arguments before entering the
+ substitution context. */
+ explicit_targs
= (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;
+ complain,
+ /*require_all_args=*/false,
+ /*use_default_args=*/false));
+ if (explicit_targs == error_mark_node)
+ goto fail;
/* Substitute the explicit args into the function type. This is
necessary so that, for instance, explicitly declared function
{
tree parm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
bool parameter_pack = false;
- tree targ = TREE_VEC_ELT (converted_args, i);
+ tree targ = TREE_VEC_ELT (explicit_targs, i);
/* Dig out the actual parm. */
if (TREE_CODE (parm) == TYPE_DECL
}
}
+ TREE_VALUE (tinst) = explicit_targs;
+ if (!push_tinst_level (tinst))
+ {
+ excessive_deduction_depth = true;
+ goto fail;
+ }
processing_template_decl += incomplete;
- fntype = deduction_tsubst_fntype (fn, converted_args,
- (explain_p
- ? tf_warning_or_error
- : tf_none));
+ input_location = DECL_SOURCE_LOCATION (fn);
+ fntype = tsubst (TREE_TYPE (fn), explicit_targs,
+ complain | tf_partial, NULL_TREE);
+ input_location = loc;
processing_template_decl -= incomplete;
+ pop_tinst_level ();
if (fntype == error_mark_node)
- return 1;
+ goto fail;
+
+ /* Throw away these access checks; we'll see them again in
+ instantiate_template and they might have the wrong
+ access path at this point. */
+ pop_deferring_access_checks ();
+ push_deferring_access_checks (dk_deferred);
/* Place the explicitly specified arguments in TARGS. */
- for (i = NUM_TMPL_ARGS (converted_args); i--;)
- TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (converted_args, i);
+ for (i = NUM_TMPL_ARGS (explicit_targs); i--;)
+ TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (explicit_targs, i);
}
/* Never do unification on the 'this' parameter. */
because the standard doesn't seem to explicitly prohibit it. Our
callers must be ready to deal with unification failures in any
event. */
- result = type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
- targs, parms, args, nargs, /*subr=*/0,
- strict, flags, explain_p);
+
+ ok = !type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
+ targs, parms, args, nargs, /*subr=*/0,
+ strict, flags, explain_p);
+ if (!ok)
+ goto fail;
/* Now that we have bindings for all of the template arguments,
ensure that the arguments deduced for the template template
parameter 'T', but 'C' is deduced to 'X' before 'T' is deduced to
'long'. Thus, we can't check that 'C' cannot bind to 'X' at the
time that we deduce 'C'. */
- if (result == 0
- && !template_template_parm_bindings_ok_p
+ if (!template_template_parm_bindings_ok_p
(DECL_INNERMOST_TEMPLATE_PARMS (fn), targs))
- return unify_inconsistent_template_template_parameters (explain_p);
+ {
+ unify_inconsistent_template_template_parameters (explain_p);
+ goto fail;
+ }
- if (result == 0)
- /* All is well so far. Now, check:
+ /* All is well so far. Now, check:
- [temp.deduct]
+ [temp.deduct]
- When all template arguments have been deduced, all uses of
- template parameters in nondeduced contexts are replaced with
- the corresponding deduced argument values. If the
- substitution results in an invalid type, as described above,
- type deduction fails. */
+ When all template arguments have been deduced, all uses of
+ template parameters in nondeduced contexts are replaced with
+ the corresponding deduced argument values. If the
+ substitution results in an invalid type, as described above,
+ type deduction fails. */
+ TREE_VALUE (tinst) = targs;
+ if (!push_tinst_level (tinst))
{
- tree substed = deduction_tsubst_fntype (fn, targs,
- (explain_p
- ? tf_warning_or_error
- : tf_none));
- if (substed == error_mark_node)
- return 1;
+ excessive_deduction_depth = true;
+ goto fail;
+ }
+ decl = instantiate_template (fn, targs, complain);
+ pop_tinst_level ();
- /* If we're looking for an exact match, check that what we got
- is indeed an exact match. It might not be if some template
- parameters are used in non-deduced contexts. */
- if (strict == DEDUCE_EXACT)
- {
- unsigned int i;
-
- tree sarg
- = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (substed));
- if (return_type)
- 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 unify_type_mismatch (explain_p, args[i],
- TREE_VALUE (sarg));
- }
+ if (decl == error_mark_node)
+ goto fail;
+
+ /* Now perform any access checks encountered during deduction, such as
+ for default template arguments. */
+ push_access_scope (decl);
+ ok = perform_deferred_access_checks (complain);
+ pop_access_scope (decl);
+ if (!ok)
+ goto fail;
+
+ /* If we're looking for an exact match, check that what we got
+ is indeed an exact match. It might not be if some template
+ parameters are used in non-deduced contexts. */
+ if (strict == DEDUCE_EXACT)
+ {
+ tree substed = TREE_TYPE (decl);
+ unsigned int i;
+
+ tree sarg
+ = skip_artificial_parms_for (decl, TYPE_ARG_TYPES (substed));
+ if (return_type)
+ 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)))
+ {
+ unify_type_mismatch (explain_p, args[i],
+ TREE_VALUE (sarg));
+ goto fail;
+ }
}
- return result;
+ r = decl;
+
+ fail:
+ pop_deferring_access_checks ();
+ --deduction_depth;
+ if (excessive_deduction_depth)
+ {
+ if (deduction_depth == 0)
+ /* Reset once we're all the way out. */
+ excessive_deduction_depth = false;
+ }
+
+ /* 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;
}
/* Adjust types before performing type deduction, as described in
if (strict == DEDUCE_CONV)
{
- if (can_convert_arg (type, parm, NULL_TREE, flags))
+ if (can_convert_arg (type, parm, NULL_TREE, flags,
+ explain_p ? tf_warning_or_error : tf_none))
return unify_success (explain_p);
}
else if (strict != DEDUCE_EXACT)
{
if (can_convert_arg (parm, type,
TYPE_P (arg) ? NULL_TREE : arg,
- flags))
+ flags, explain_p ? tf_warning_or_error : tf_none))
return unify_success (explain_p);
}
if (TREE_CODE (fn) != TEMPLATE_DECL)
continue;
- ++processing_template_decl;
- subargs = get_bindings (fn, DECL_TEMPLATE_RESULT (fn),
- expl_subargs, /*check_ret=*/false);
- if (subargs && !any_dependent_template_arguments_p (subargs))
+ subargs = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (fn),
+ expl_subargs, NULL_TREE, tf_none,
+ /*require_all_args=*/true,
+ /*use_default_args=*/true);
+ if (subargs != error_mark_node
+ && !any_dependent_template_arguments_p (subargs))
{
elem = tsubst (TREE_TYPE (fn), subargs, tf_none, NULL_TREE);
if (try_one_overload (tparms, targs, tempargs, parm,
}
else if (subargs)
++ok;
- --processing_template_decl;
}
/* If no templates (or more than one) are fully resolved by the
explicit arguments, this template-id is a non-deduced context; it
if (TREE_CODE (fn) != TEMPLATE_DECL)
continue;
- ++processing_template_decl;
- subargs = get_bindings (fn, DECL_TEMPLATE_RESULT (fn),
- expl_subargs, /*check_ret=*/false);
- if (subargs && !any_dependent_template_arguments_p (subargs))
+ subargs = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (fn),
+ expl_subargs, NULL_TREE, tf_none,
+ /*require_all_args=*/true,
+ /*use_default_args=*/true);
+ if (subargs != error_mark_node
+ && !any_dependent_template_arguments_p (subargs))
{
elem = instantiate_template (fn, subargs, tf_none);
if (elem == error_mark_node)
++good;
}
}
- --processing_template_decl;
}
if (good == 1)
{
{
tree base
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (offset, 0)));
- expr = build_offset_ref (base, expr, addr);
+ expr = build_offset_ref (base, expr, addr, tf_warning_or_error);
}
if (addr)
expr = cp_build_addr_expr (expr, tf_warning_or_error);
tree tempargs;
int i;
+ if (arg == error_mark_node)
+ return 0;
+
/* [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
to see if it matches ARG. */
{
if (TREE_CODE (arg) == TREE_CODE (parm)
- && same_type_p (parm, arg))
+ && (is_auto (parm) ? is_auto (arg)
+ : same_type_p (parm, arg)))
return unify_success (explain_p);
else
return unify_type_mismatch (explain_p, parm, arg);
&& PACK_EXPANSION_P (TREE_VEC_ELT (parmvec, len - 1)))
parm_variadic_p = 1;
+ for (i = 0; i < len - parm_variadic_p; ++i)
+ /* 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. */
+ if (PACK_EXPANSION_P (TREE_VEC_ELT (parmvec, i)))
+ return unify_success (explain_p);
+
if (TREE_VEC_LENGTH (argvec) < len - parm_variadic_p)
return unify_too_few_arguments (explain_p,
TREE_VEC_LENGTH (argvec), len);
if ((TYPE_DOMAIN (parm) == NULL_TREE)
!= (TYPE_DOMAIN (arg) == NULL_TREE))
return unify_type_mismatch (explain_p, parm, arg);
+ RECUR_AND_CHECK_FAILURE (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
+ strict & UNIFY_ALLOW_MORE_CV_QUAL, explain_p);
if (TYPE_DOMAIN (parm) != NULL_TREE)
{
tree parm_max;
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, explain_p);
+ return unify_success (explain_p);
case REAL_TYPE:
case COMPLEX_TYPE:
build_function_type (TREE_TYPE (method_type),
TREE_CHAIN (TYPE_ARG_TYPES (method_type)));
- /* Extract the cv-qualifiers of the member function from the
- implicit object parameter and place them on the function
- type to be restored later. */
- fntype = apply_memfn_quals (fntype, type_memfn_quals (method_type));
+ /* Extract the cv-qualifiers and ref-qualifier of the member
+ function from the implicit object parameter and place them
+ on the function type to be restored later. */
+ fntype = apply_memfn_quals (fntype,
+ type_memfn_quals (method_type),
+ type_memfn_rqual (method_type));
return unify (tparms, targs, TREE_TYPE (parm), fntype, strict, explain_p);
}
quals2 = cp_type_quals (arg2);
}
- if ((quals1 < 0) != (quals2 < 0))
- {
- /* Only of the args is a reference, see if we should apply
- array/function pointer decay to it. This is not part of
- DR214, but is, IMHO, consistent with the deduction rules
- for the function call itself, and with our earlier
- implementation of the underspecified partial ordering
- rules. (nathan). */
- if (quals1 >= 0)
- {
- switch (TREE_CODE (arg1))
- {
- case ARRAY_TYPE:
- arg1 = TREE_TYPE (arg1);
- /* FALLTHROUGH. */
- case FUNCTION_TYPE:
- arg1 = build_pointer_type (arg1);
- break;
-
- default:
- break;
- }
- }
- else
- {
- switch (TREE_CODE (arg2))
- {
- case ARRAY_TYPE:
- arg2 = TREE_TYPE (arg2);
- /* FALLTHROUGH. */
- case FUNCTION_TYPE:
- arg2 = build_pointer_type (arg2);
- break;
-
- default:
- break;
- }
- }
- }
-
arg1 = TYPE_MAIN_VARIANT (arg1);
arg2 = TYPE_MAIN_VARIANT (arg2);
return -1;
}
-/* Determine which of two partial specializations is more specialized.
+/* Determine which of two partial specializations of MAIN_TMPL is more
+ specialized.
PAT1 is a TREE_LIST whose TREE_TYPE is the _TYPE node corresponding
to the first partial specialization. The TREE_VALUE is the
two templates is more specialized. */
static int
-more_specialized_class (tree pat1, tree pat2)
+more_specialized_class (tree main_tmpl, tree pat1, tree pat2)
{
tree targs;
tree tmpl1, tmpl2;
types in the arguments, and we need our dependency check functions
to behave correctly. */
++processing_template_decl;
- targs = get_class_bindings (TREE_VALUE (pat1),
+ targs = get_class_bindings (main_tmpl, TREE_VALUE (pat1),
CLASSTYPE_TI_ARGS (tmpl1),
CLASSTYPE_TI_ARGS (tmpl2));
if (targs)
any_deductions = true;
}
- targs = get_class_bindings (TREE_VALUE (pat2),
+ targs = get_class_bindings (main_tmpl, TREE_VALUE (pat2),
CLASSTYPE_TI_ARGS (tmpl2),
CLASSTYPE_TI_ARGS (tmpl1));
if (targs)
{
int ntparms = DECL_NTPARMS (fn);
tree targs = make_tree_vec (ntparms);
- tree decl_type;
+ tree decl_type = TREE_TYPE (decl);
tree decl_arg_types;
tree *args;
unsigned int nargs, ix;
tree arg;
- /* Substitute the explicit template arguments into the type of DECL.
- The call to fn_type_unification will handle substitution into the
- FN. */
- decl_type = TREE_TYPE (decl);
- if (explicit_args && uses_template_parms (decl_type))
- {
- tree tmpl;
- tree converted_args;
-
- if (DECL_TEMPLATE_INFO (decl))
- tmpl = DECL_TI_TEMPLATE (decl);
- else
- /* We can get here for some invalid specializations. */
- return NULL_TREE;
-
- converted_args
- = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
- explicit_args, NULL_TREE,
- tf_none,
- /*require_all_args=*/false,
- /*use_default_args=*/false);
- if (converted_args == error_mark_node)
- return NULL_TREE;
-
- decl_type = tsubst (decl_type, converted_args, tf_none, NULL_TREE);
- if (decl_type == error_mark_node)
- return NULL_TREE;
- }
+ gcc_assert (decl != DECL_TEMPLATE_RESULT (fn));
/* Never do unification on the 'this' parameter. */
decl_arg_types = skip_artificial_parms_for (decl,
args, ix,
(check_rettype || DECL_CONV_FN_P (fn)
? TREE_TYPE (decl_type) : NULL_TREE),
- DEDUCE_EXACT, LOOKUP_NORMAL, /*explain_p=*/false))
+ DEDUCE_EXACT, LOOKUP_NORMAL, /*explain_p=*/false)
+ == error_mark_node)
return NULL_TREE;
return targs;
}
-/* Return the innermost template arguments that, when applied to a
- template specialization whose innermost template parameters are
+/* Return the innermost template arguments that, when applied to a partial
+ specialization of MAIN_TMPL whose innermost template parameters are
TPARMS, and whose specialization arguments are SPEC_ARGS, yield the
ARGS.
is bound to `double'. */
static tree
-get_class_bindings (tree tparms, tree spec_args, tree args)
+get_class_bindings (tree main_tmpl, tree tparms, tree spec_args, tree args)
{
int i, ntparms = TREE_VEC_LENGTH (tparms);
tree deduced_args;
`T' is `A' but unify () does not check whether `typename T::X'
is `int'. */
spec_args = tsubst (spec_args, deduced_args, tf_none, NULL_TREE);
+ spec_args = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (main_tmpl),
+ spec_args, main_tmpl,
+ tf_none, false, false);
if (spec_args == error_mark_node
/* We only need to check the innermost arguments; the other
arguments will always agree. */
if (partial_spec_args == error_mark_node)
return error_mark_node;
- spec_args = get_class_bindings (parms,
+ spec_args = get_class_bindings (tmpl, parms,
partial_spec_args,
args);
if (spec_args)
t = TREE_CHAIN (t);
for (; t; t = TREE_CHAIN (t))
{
- fate = more_specialized_class (champ, t);
+ fate = more_specialized_class (tmpl, champ, t);
if (fate == 1)
;
else
if (!ambiguous_p)
for (t = list; t && t != champ; t = TREE_CHAIN (t))
{
- fate = more_specialized_class (champ, t);
+ fate = more_specialized_class (tmpl, champ, t);
if (fate != 1)
{
ambiguous_p = true;
else if (storage == ridpointers[(int) RID_EXTERN])
{
if (!in_system_header && (cxx_dialect == cxx98))
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"ISO C++ 1998 forbids the use of %<extern%> on explicit "
"instantiations");
extern_p = 1;
if (storage == ridpointers[(int) RID_EXTERN])
{
if (cxx_dialect == cxx98)
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"ISO C++ 1998 forbids the use of %<extern%> on "
"explicit instantiations");
}
else
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"ISO C++ forbids the use of %qE"
" on explicit instantiations", storage);
}
that for "extern template" functions. Therefore, we check
DECL_DECLARED_INLINE_P, rather than possibly_inlined_p. */
return ((TREE_CODE (decl) == FUNCTION_DECL
- && DECL_DECLARED_INLINE_P (decl))
+ && (DECL_DECLARED_INLINE_P (decl)
+ || type_uses_auto (TREE_TYPE (TREE_TYPE (decl)))))
/* And we need to instantiate static data members so that
their initializers are available in integral constant
expressions. */
if (TREE_CODE (d) == FUNCTION_DECL)
maybe_instantiate_noexcept (d);
- /* Recheck the substitutions to obtain any warning messages
- about ignoring cv qualifiers. Don't do this for artificial decls,
- as it breaks the context-sensitive substitution for lambda op(). */
- if (!defer_ok && !DECL_ARTIFICIAL (d))
- {
- tree gen = DECL_TEMPLATE_RESULT (gen_tmpl);
- tree type = TREE_TYPE (gen);
-
- /* Make sure that we can see identifiers, and compute access
- correctly. D is already the target FUNCTION_DECL with the
- right context. */
- push_access_scope (d);
-
- if (TREE_CODE (gen) == FUNCTION_DECL)
- {
- tsubst (DECL_ARGUMENTS (gen), gen_args, tf_warning_or_error, d);
- tsubst_exception_specification (type, gen_args, tf_warning_or_error,
- d, /*defer_ok*/true);
- /* Don't simply tsubst the function type, as that will give
- duplicate warnings about poor parameter qualifications.
- The function arguments are the same as the decl_arguments
- without the top level cv qualifiers. */
- type = TREE_TYPE (type);
- }
- tsubst (type, gen_args, tf_warning_or_error, d);
-
- pop_access_scope (d);
- }
-
/* Defer all other templates, unless we have been explicitly
forbidden from doing so. */
if (/* If there is no definition, we cannot instantiate the
synthesize_method (d);
else if (TREE_CODE (d) == FUNCTION_DECL)
{
- htab_t saved_local_specializations;
+ struct pointer_map_t *saved_local_specializations;
tree subst_decl;
tree tmpl_parm;
tree spec_parm;
saved_local_specializations = local_specializations;
/* Set up the list of local specializations. */
- local_specializations = htab_create (37,
- hash_local_specialization,
- eq_local_specializations,
- NULL);
+ local_specializations = pointer_map_create ();
/* Set up context. */
start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
+ /* Some typedefs referenced from within the template code need to be
+ access checked at template instantiation time, i.e now. These
+ types were added to the template at parsing time. Let's get those
+ and perform the access checks then. */
+ perform_typedefs_access_check (DECL_TEMPLATE_RESULT (gen_tmpl),
+ gen_args);
+
/* Create substitution entries for the parameters. */
subst_decl = DECL_TEMPLATE_RESULT (template_for_substitution (d));
tmpl_parm = DECL_ARGUMENTS (subst_decl);
input_location = DECL_STRUCT_FUNCTION (code_pattern)->function_end_locus;
/* We don't need the local specializations any more. */
- htab_delete (local_specializations);
+ pointer_map_destroy (local_specializations);
local_specializations = saved_local_specializations;
/* Finish the function. */
return 0;
else if (POINTER_TYPE_P (type))
return 0;
- else if (TYPE_PTR_TO_MEMBER_P (type))
+ else if (TYPE_PTRMEM_P (type))
return 0;
else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
return 0;
dependent. */
type = TYPE_MAIN_VARIANT (type);
/* -- a compound type constructed from any dependent type. */
- if (TYPE_PTR_TO_MEMBER_P (type))
+ if (TYPE_PTRMEM_P (type))
return (dependent_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
|| dependent_type_p (TYPE_PTRMEM_POINTED_TO_TYPE
(type)));
&& !currently_open_class (scope));
}
+/* T is a SCOPE_REF; return whether we need to consider it
+ instantiation-dependent so that we can check access at instantiation
+ time even though we know which member it resolves to. */
+
+static bool
+instantiation_dependent_scope_ref_p (tree t)
+{
+ if (DECL_P (TREE_OPERAND (t, 1))
+ && CLASS_TYPE_P (TREE_OPERAND (t, 0))
+ && accessible_in_template_p (TREE_OPERAND (t, 0),
+ TREE_OPERAND (t, 1)))
+ return false;
+ else
+ return true;
+}
+
/* Returns TRUE if the EXPRESSION is value-dependent, in the sense of
[temp.dep.constexpr]. EXPRESSION is already known to be a constant
expression. */
/* Note that this predicate is not appropriate for general expressions;
only constant expressions (that satisfy potential_constant_expression)
- can be tested for value dependence.
-
- We should really also have a predicate for "instantiation-dependent".
-
- fold_non_dependent_expr: fold if constant and not type-dependent and not value-dependent.
- (what about instantiation-dependent constant-expressions?)
- is_late_template_attribute: defer if instantiation-dependent.
- compute_array_index_type: proceed if constant and not t- or v-dependent
- if instantiation-dependent, need to remember full expression
- uses_template_parms: FIXME - need to audit callers
- tsubst_decl [function_decl]: Why is this using value_dependent_expression_p?
- dependent_type_p [array_type]: dependent if index type is dependent
- (or non-constant?)
- static_assert - instantiation-dependent */
+ can be tested for value dependence. */
bool
value_dependent_expression_p (tree expression)
}
case SIZEOF_EXPR:
+ if (SIZEOF_EXPR_TYPE_P (expression))
+ return dependent_type_p (TREE_TYPE (TREE_OPERAND (expression, 0)));
+ /* FALLTHRU */
case ALIGNOF_EXPR:
case TYPEID_EXPR:
/* A `sizeof' expression is value-dependent if the operand is
return true;
else if (TYPE_P (expression))
return dependent_type_p (expression);
- return type_dependent_expression_p (expression);
+ return instantiation_dependent_expression_p (expression);
case AT_ENCODE_EXPR:
/* An 'encode' expression is value-dependent if the operand is
case NOEXCEPT_EXPR:
expression = TREE_OPERAND (expression, 0);
- return type_dependent_expression_p (expression);
+ return instantiation_dependent_expression_p (expression);
case SCOPE_REF:
- {
- tree name = TREE_OPERAND (expression, 1);
- return value_dependent_expression_p (name);
- }
+ /* All instantiation-dependent expressions should also be considered
+ value-dependent. */
+ return instantiation_dependent_scope_ref_p (expression);
case COMPONENT_REF:
return (value_dependent_expression_p (TREE_OPERAND (expression, 0))
return (dependent_type_p (TREE_TYPE (expression)));
}
+/* walk_tree callback function for instantiation_dependent_expression_p,
+ below. Returns non-zero if a dependent subexpression is found. */
+
+static tree
+instantiation_dependent_r (tree *tp, int *walk_subtrees,
+ void * /*data*/)
+{
+ if (TYPE_P (*tp))
+ {
+ /* We don't have to worry about decltype currently because decltype
+ of an instantiation-dependent expr is a dependent type. This
+ might change depending on the resolution of DR 1172. */
+ *walk_subtrees = false;
+ return NULL_TREE;
+ }
+ enum tree_code code = TREE_CODE (*tp);
+ switch (code)
+ {
+ /* Don't treat an argument list as dependent just because it has no
+ TREE_TYPE. */
+ case TREE_LIST:
+ case TREE_VEC:
+ return NULL_TREE;
+
+ case TEMPLATE_PARM_INDEX:
+ return *tp;
+
+ /* Handle expressions with type operands. */
+ case SIZEOF_EXPR:
+ case ALIGNOF_EXPR:
+ case TYPEID_EXPR:
+ case AT_ENCODE_EXPR:
+ {
+ tree op = TREE_OPERAND (*tp, 0);
+ if (code == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (*tp))
+ op = TREE_TYPE (op);
+ if (TYPE_P (op))
+ {
+ if (dependent_type_p (op))
+ return *tp;
+ else
+ {
+ *walk_subtrees = false;
+ return NULL_TREE;
+ }
+ }
+ break;
+ }
+
+ case TRAIT_EXPR:
+ if (dependent_type_p (TRAIT_EXPR_TYPE1 (*tp))
+ || (TRAIT_EXPR_TYPE2 (*tp)
+ && dependent_type_p (TRAIT_EXPR_TYPE2 (*tp))))
+ return *tp;
+ *walk_subtrees = false;
+ return NULL_TREE;
+
+ case COMPONENT_REF:
+ if (TREE_CODE (TREE_OPERAND (*tp, 1)) == IDENTIFIER_NODE)
+ /* In a template, finish_class_member_access_expr creates a
+ COMPONENT_REF with an IDENTIFIER_NODE for op1 even if it isn't
+ type-dependent, so that we can check access control at
+ instantiation time (PR 42277). See also Core issue 1273. */
+ return *tp;
+ break;
+
+ case SCOPE_REF:
+ if (instantiation_dependent_scope_ref_p (*tp))
+ return *tp;
+ else
+ break;
+
+ /* Treat statement-expressions as dependent. */
+ case BIND_EXPR:
+ return *tp;
+
+ default:
+ break;
+ }
+
+ if (type_dependent_expression_p (*tp))
+ return *tp;
+ else
+ return NULL_TREE;
+}
+
+/* Returns TRUE if the EXPRESSION is instantiation-dependent, in the
+ sense defined by the ABI:
+
+ "An expression is instantiation-dependent if it is type-dependent
+ or value-dependent, or it has a subexpression that is type-dependent
+ or value-dependent." */
+
+bool
+instantiation_dependent_expression_p (tree expression)
+{
+ tree result;
+
+ if (!processing_template_decl)
+ return false;
+
+ if (expression == error_mark_node)
+ return false;
+
+ result = cp_walk_tree_without_duplicates (&expression,
+ instantiation_dependent_r, NULL);
+ return result != NULL_TREE;
+}
+
/* Like type_dependent_expression_p, but it also works while not processing
a template definition, i.e. during substitution or mangling. */
/* Returns TRUE if ARGS contains a type-dependent expression. */
bool
-any_type_dependent_arguments_p (const VEC(tree,gc) *args)
+any_type_dependent_arguments_p (const vec<tree, va_gc> *args)
{
unsigned int i;
tree arg;
- FOR_EACH_VEC_ELT (tree, args, i, arg)
+ FOR_EACH_VEC_SAFE_ELT (args, i, arg)
{
if (type_dependent_expression_p (arg))
return true;
tree inner_expr;
#ifdef ENABLE_CHECKING
- /* Try to get a constant value for all non-type-dependent expressions in
+ /* Try to get a constant value for all non-dependent expressions in
order to expose bugs in *_dependent_expression_p and constexpr. */
- if (cxx_dialect >= cxx0x)
+ if (cxx_dialect >= cxx0x
+ && !instantiation_dependent_expression_p (expr))
maybe_constant_value (fold_non_dependent_expr_sfinae (expr, tf_none));
#endif
if (BRACE_ENCLOSED_INITIALIZER_P (expr))
return expr;
+ /* Don't wrap a dummy object, we need to be able to test for it. */
+ if (is_dummy_object (expr))
+ return expr;
+
if (TREE_CODE (expr) == COND_EXPR)
return build3 (COND_EXPR,
TREE_TYPE (expr),
This modifies ARGS in place. */
void
-make_args_non_dependent (VEC(tree,gc) *args)
+make_args_non_dependent (vec<tree, va_gc> *args)
{
unsigned int ix;
tree arg;
- FOR_EACH_VEC_ELT (tree, args, ix, arg)
+ FOR_EACH_VEC_SAFE_ELT (args, ix, arg)
{
tree newarg = build_non_dependent_expr (arg);
if (newarg != arg)
- VEC_replace (tree, args, ix, newarg);
+ (*args)[ix] = newarg;
}
}
return tsubst (type, argvec, tf_warning_or_error, NULL_TREE);
}
-/* walk_tree helper for do_auto_deduction. */
-
-static tree
-contains_auto_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
- void *type)
-{
- /* Is this a variable with the type we're looking for? */
- if (DECL_P (*tp)
- && TREE_TYPE (*tp) == type)
- return *tp;
- else
- return NULL_TREE;
-}
-
/* Replace occurrences of 'auto' in TYPE with the appropriate type deduced
from INIT. AUTO_NODE is the TEMPLATE_TYPE_PARM used for 'auto' in TYPE. */
{
tree parms, tparms, targs;
tree args[1];
- tree decl;
int val;
+ if (init == error_mark_node)
+ return error_mark_node;
+
if (type_dependent_expression_p (init))
/* Defining a subset of type-dependent expressions that we can deduce
from ahead of time isn't worth the trouble. */
return type;
- /* The name of the object being declared shall not appear in the
- initializer expression. */
- decl = cp_walk_tree_without_duplicates (&init, contains_auto_r, type);
- if (decl)
- {
- error ("variable %q#D with %<auto%> type used in its own "
- "initializer", decl);
- return error_mark_node;
- }
-
/* [dcl.spec.auto]: Obtain P from T by replacing the occurrences of auto
with either a new invented type template parameter U or, if the
initializer is a braced-init-list (8.5.4), with
/* If type is error_mark_node a diagnostic must have been
emitted by now. Also, having a mention to '<type error>'
in the diagnostic is not really useful to the user. */
- error ("unable to deduce %qT from %qE", type, init);
+ {
+ if (cfun && auto_node == current_function_auto_return_pattern
+ && LAMBDA_FUNCTION_P (current_function_decl))
+ error ("unable to deduce lambda return type from %qE", init);
+ else
+ error ("unable to deduce %qT from %qE", type, init);
+ }
return error_mark_node;
}
if (TREE_TYPE (auto_node)
&& !same_type_p (TREE_TYPE (auto_node), TREE_VEC_ELT (targs, 0)))
{
- error ("inconsistent deduction for %qT: %qT and then %qT",
- auto_node, TREE_TYPE (auto_node), TREE_VEC_ELT (targs, 0));
+ if (cfun && auto_node == current_function_auto_return_pattern
+ && LAMBDA_FUNCTION_P (current_function_decl))
+ error ("inconsistent types %qT and %qT deduced for "
+ "lambda return type", TREE_TYPE (auto_node),
+ TREE_VEC_ELT (targs, 0));
+ else
+ error ("inconsistent deduction for %qT: %qT and then %qT",
+ auto_node, TREE_TYPE (auto_node), TREE_VEC_ELT (targs, 0));
return error_mark_node;
}
TREE_TYPE (auto_node) = TREE_VEC_ELT (targs, 0);
Those typedefs were added to T by the function
append_type_to_template_for_access_check. */
-VEC(qualified_typedef_usage_t,gc)*
+vec<qualified_typedef_usage_t, va_gc> *
get_types_needing_access_check (tree t)
{
tree ti;
- VEC(qualified_typedef_usage_t,gc) *result = NULL;
+ vec<qualified_typedef_usage_t, va_gc> *result = NULL;
if (!t || t == error_mark_node)
return NULL;
typedef_usage.context = scope;
typedef_usage.locus = location;
- VEC_safe_push (qualified_typedef_usage_t, gc,
- TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti),
- &typedef_usage);
+ vec_safe_push (TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti), typedef_usage);
}
/* Append TYPE_DECL to the template TEMPL.
location_t location)
{
qualified_typedef_usage_t *iter;
- int i;
+ unsigned i;
gcc_assert (type_decl && (TREE_CODE (type_decl) == TYPE_DECL));
/* Make sure we don't append the type to the template twice. */
- FOR_EACH_VEC_ELT (qualified_typedef_usage_t,
- get_types_needing_access_check (templ),
- i, iter)
+ FOR_EACH_VEC_SAFE_ELT (get_types_needing_access_check (templ), i, iter)
if (iter->typedef_decl == type_decl && scope == iter->context)
return;