/* Handle parameterized types (templates) for GNU -*- C++ -*-.
- Copyright (C) 1992-2014 Free Software Foundation, Inc.
+ Copyright (C) 1992-2015 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
Rewritten by Jason Merrill (jason@cygnus.com).
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "alias.h"
+#include "symtab.h"
#include "tree.h"
#include "stringpool.h"
#include "varasm.h"
tree spec;
};
-struct spec_hasher : ggc_hasher<spec_entry *>
+struct spec_hasher : ggc_ptr_hash<spec_entry>
{
static hashval_t hash (spec_entry *);
static bool equal (spec_entry *, spec_entry *);
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);
+static bool complex_alias_template_p (const_tree tmpl);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
&& !DECL_FRIEND_P (DECL_TEMPLATE_RESULT (tmpl)));
}
+/* Make sure ARGS doesn't use any inappropriate typedefs; we should have
+ gone through coerce_template_parms by now. */
+
+static void
+check_unstripped_args (tree args ATTRIBUTE_UNUSED)
+{
+#ifdef ENABLE_CHECKING
+ ++processing_template_decl;
+ if (!any_dependent_template_arguments_p (args))
+ {
+ tree inner = INNERMOST_TEMPLATE_ARGS (args);
+ for (int i = 0; i < TREE_VEC_LENGTH (inner); ++i)
+ {
+ tree arg = TREE_VEC_ELT (inner, i);
+ if (TREE_CODE (arg) == TEMPLATE_DECL)
+ /* OK */;
+ else if (TYPE_P (arg))
+ gcc_assert (strip_typedefs (arg, NULL) == arg);
+ else if (strip_typedefs (TREE_TYPE (arg), NULL) != TREE_TYPE (arg))
+ /* Allow typedefs on the type of a non-type argument, since a
+ parameter can have them. */;
+ else
+ gcc_assert (strip_typedefs_expr (arg, NULL) == arg);
+ }
+ }
+ --processing_template_decl;
+#endif
+}
+
/* Retrieve the specialization (in the sense of [temp.spec] - a
specialization is either an instantiation or an explicit
specialization) of TMPL for the given template ARGS. If there is
? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))
: template_class_depth (DECL_CONTEXT (tmpl))));
+ check_unstripped_args (args);
+
if (optimize_specialization_lookup_p (tmpl))
{
tree class_template;
switch (tclass)
{
case tcc_type:
+ if (alias_template_specialization_p (arg))
+ {
+ // We want an alias specialization that survived strip_typedefs
+ // to hash differently from its TYPE_CANONICAL, to avoid hash
+ // collisions that compare as different in template_args_equal.
+ // These could be dependent specializations that strip_typedefs
+ // left alone, or untouched specializations because
+ // coerce_template_parms returns the unconverted template
+ // arguments if it sees incomplete argument packs.
+ tree ti = TYPE_TEMPLATE_INFO (arg);
+ return hash_tmpl_and_args (TI_TEMPLATE (ti), TI_ARGS (ti));
+ }
if (TYPE_CANONICAL (arg))
return iterative_hash_object (TYPE_HASH (TYPE_CANONICAL (arg)),
val);
++header_count;
if (variable_template_p (fns))
- templates = tree_cons (explicit_targs, fns, templates);
+ {
+ tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (fns));
+ targs = coerce_template_parms (parms, explicit_targs, fns,
+ tf_warning_or_error,
+ /*req_all*/true, /*use_defarg*/true);
+ templates = tree_cons (targs, fns, templates);
+ }
else for (; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
switch (tsk)
{
case tsk_none:
- if (processing_specialization)
+ if (processing_specialization && !VAR_P (decl))
{
specialization = 1;
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
/* A specialization is not necessarily COMDAT. */
DECL_COMDAT (decl) = (TREE_PUBLIC (decl)
&& DECL_DECLARED_INLINE_P (decl));
- else if (TREE_CODE (decl) == VAR_DECL)
+ else if (VAR_P (decl))
DECL_COMDAT (decl) = false;
/* Register this specialization so that we can find it
if (!arg || arg == error_mark_node)
return arg;
- if (TREE_CODE (arg) == TREE_LIST)
+ if (TREE_CODE (arg) == TREE_LIST && TREE_PURPOSE (arg))
{
- /* The only time we will see a TREE_LIST here is for a base
+ /* A TREE_LIST with a non-null TREE_PURPOSE is for a base
class initializer. In this case, the TREE_PURPOSE will be a
_TYPE node (representing the base class expansion we're
initializing) and the TREE_VALUE will be a TREE_LIST
|| TREE_CODE (parm) == TEMPLATE_DECL)
parm = TREE_TYPE (parm);
if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM)
parm = TEMPLATE_TYPE_PARM_INDEX (parm);
gcc_assert (TREE_CODE (parm) == TEMPLATE_PARM_INDEX);
parameter pack, at the end of the template
parameter list. */
- if (TREE_CODE (TREE_VALUE (parm)) == PARM_DECL)
- error ("parameter pack %qE must be at the end of the"
- " template parameter list", TREE_VALUE (parm));
- else
- error ("parameter pack %qT must be at the end of the"
- " template parameter list",
- TREE_TYPE (TREE_VALUE (parm)));
+ error ("parameter pack %q+D must be at the end of the"
+ " template parameter list", TREE_VALUE (parm));
TREE_VALUE (TREE_VEC_ELT (inner_parms, i))
= error_mark_node;
is_partial = ((DECL_IMPLICIT_TYPEDEF_P (decl)
&& TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
&& CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
- || (TREE_CODE (decl) == VAR_DECL
+ || (VAR_P (decl)
&& DECL_LANG_SPECIFIC (decl)
&& DECL_TEMPLATE_SPECIALIZATION (decl)
&& TINFO_USED_TEMPLATE_ID (DECL_TEMPLATE_INFO (decl))));
if (DECL_CLASS_SCOPE_P (decl))
member_template_p = true;
if (TREE_CODE (decl) == TYPE_DECL
- && ANON_AGGRNAME_P (DECL_NAME (decl)))
+ && anon_aggrname_p (DECL_NAME (decl)))
{
error ("template class without a name");
return error_mark_node;
if (TREE_CODE (parm) == TEMPLATE_DECL)
DECL_CONTEXT (parm) = tmpl;
}
+
+ if (TREE_CODE (decl) == TYPE_DECL
+ && TYPE_DECL_ALIAS_P (decl)
+ && complex_alias_template_p (tmpl))
+ TEMPLATE_DECL_COMPLEX_ALIAS_P (tmpl) = true;
}
/* The DECL_TI_ARGS of DECL contains full set of arguments referring
bool
alias_template_specialization_p (const_tree t)
{
- if (t == NULL_TREE)
- return false;
-
- return (TYPE_P (t)
- && TYPE_TEMPLATE_INFO (t)
- && PRIMARY_TEMPLATE_P (TYPE_TI_TEMPLATE (t))
- && DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (t)));
+ /* It's an alias template specialization if it's an alias and its
+ TYPE_NAME is a specialization of a primary template. */
+ if (TYPE_ALIAS_P (t))
+ {
+ tree name = TYPE_NAME (t);
+ if (DECL_LANG_SPECIFIC (name))
+ if (tree ti = DECL_TEMPLATE_INFO (name))
+ {
+ tree tmpl = TI_TEMPLATE (ti);
+ return PRIMARY_TEMPLATE_P (tmpl);
+ }
+ }
+ return false;
}
-/* Return TRUE iff T is a specialization of an alias template with
+/* An alias template is complex from a SFINAE perspective if a template-id
+ using that alias can be ill-formed when the expansion is not, as with
+ the void_t template. We determine this by checking whether the
+ expansion for the alias template uses all its template parameters. */
+
+struct uses_all_template_parms_data
+{
+ int level;
+ bool *seen;
+};
+
+static int
+uses_all_template_parms_r (tree t, void *data_)
+{
+ struct uses_all_template_parms_data &data
+ = *(struct uses_all_template_parms_data*)data_;
+ tree idx = get_template_parm_index (t);
+
+ if (TEMPLATE_PARM_LEVEL (idx) == data.level)
+ data.seen[TEMPLATE_PARM_IDX (idx)] = true;
+ return 0;
+}
+
+static bool
+complex_alias_template_p (const_tree tmpl)
+{
+ struct uses_all_template_parms_data data;
+ tree pat = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
+ tree parms = DECL_TEMPLATE_PARMS (tmpl);
+ data.level = TMPL_PARMS_DEPTH (parms);
+ int len = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (parms));
+ data.seen = XALLOCAVEC (bool, len);
+ for (int i = 0; i < len; ++i)
+ data.seen[i] = false;
+
+ for_each_template_parm (pat, uses_all_template_parms_r, &data, NULL, true);
+ for (int i = 0; i < len; ++i)
+ if (!data.seen[i])
+ return true;
+ return false;
+}
+
+/* Return TRUE iff T is a specialization of a complex alias template with
dependent template-arguments. */
bool
dependent_alias_template_spec_p (const_tree t)
{
return (alias_template_specialization_p (t)
- && any_dependent_template_arguments_p (TYPE_TI_ARGS (t)));
+ && TEMPLATE_DECL_COMPLEX_ALIAS_P (DECL_TI_TEMPLATE (TYPE_NAME (t)))
+ && (any_dependent_template_arguments_p
+ (INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (t)))));
}
/* Return the number of innermost template parameters in TMPL. */
static tree
canonicalize_type_argument (tree arg, tsubst_flags_t complain)
{
- tree mv;
if (!arg || arg == error_mark_node || arg == TYPE_CANONICAL (arg))
return arg;
- mv = TYPE_MAIN_VARIANT (arg);
- arg = strip_typedefs (arg);
- if (TYPE_ALIGN (arg) != TYPE_ALIGN (mv)
- || TYPE_ATTRIBUTES (arg) != TYPE_ATTRIBUTES (mv))
- {
- if (complain & tf_warning)
- warning (0, "ignoring attributes on template argument %qT", arg);
- arg = build_aligned_type (arg, TYPE_ALIGN (mv));
- arg = cp_build_type_attribute_variant (arg, TYPE_ATTRIBUTES (mv));
- }
- return arg;
+ bool removed_attributes = false;
+ tree canon = strip_typedefs (arg, &removed_attributes);
+ if (removed_attributes
+ && (complain & tf_warning))
+ warning (0, "ignoring attributes on template argument %qT", arg);
+ return canon;
}
/* Convert the indicated template ARG as necessary to match the
tree val;
int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
+ if (parm == error_mark_node)
+ return error_mark_node;
+
if (TREE_CODE (arg) == TREE_LIST
&& TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
{
argument specification is valid. */
val = convert_nontype_argument (t, orig_arg, complain);
else
- val = strip_typedefs_expr (orig_arg);
+ {
+ bool removed_attr = false;
+ val = strip_typedefs_expr (orig_arg, &removed_attr);
+ }
if (val == NULL_TREE)
val = error_mark_node;
if (invalid_nontype_parm_type_p (t, complain))
return error_mark_node;
}
+ /* We don't know how many args we have yet, just
+ use the unconverted ones for now. */
+ return NULL_TREE;
}
packed_args = make_tree_vec (TREE_VEC_LENGTH (packed_parms));
return false;
/* Don't treat an alias template specialization with dependent
arguments as equivalent to its underlying type when used as a
- template argument; we need them to hash differently. */
- bool ndep = dependent_alias_template_spec_p (nt);
- ++processing_template_decl;
- bool odep = dependent_alias_template_spec_p (ot);
- --processing_template_decl;
- if (ndep != odep)
+ template argument; we need them to be distinct so that we
+ substitute into the specialization arguments at instantiation
+ time. And aliases can't be equivalent without being ==, so
+ we don't need to look any deeper. */
+ if (TYPE_ALIAS_P (nt) || TYPE_ALIAS_P (ot))
return false;
- else if (ndep)
- return (TYPE_TI_TEMPLATE (nt) == TYPE_TI_TEMPLATE (ot)
- && template_args_equal (TYPE_TI_ARGS (nt), TYPE_TI_ARGS (ot)));
else
return same_type_p (ot, nt);
}
else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))
return 0;
else
- return cp_tree_equal (ot, nt);
+ {
+ /* Try to treat a template non-type argument that has been converted
+ to the parameter type as equivalent to one that hasn't yet. */
+ for (enum tree_code code1 = TREE_CODE (ot);
+ CONVERT_EXPR_CODE_P (code1)
+ || code1 == NON_LVALUE_EXPR;
+ code1 = TREE_CODE (ot))
+ ot = TREE_OPERAND (ot, 0);
+ for (enum tree_code code2 = TREE_CODE (nt);
+ CONVERT_EXPR_CODE_P (code2)
+ || code2 == NON_LVALUE_EXPR;
+ code2 = TREE_CODE (nt))
+ nt = TREE_OPERAND (nt, 0);
+
+ return cp_tree_equal (ot, nt);
+ }
}
/* Returns 1 iff the OLDARGS and NEWARGS are in fact identical sets of
/* Calculate the BOUND_ARGS. These will be the args that are
actually tsubst'd into the definition to create the
instantiation. */
- if (parm_depth > 1)
- {
- /* We have multiple levels of arguments to coerce, at once. */
- int i;
- int saved_depth = TMPL_ARGS_DEPTH (arglist);
-
- tree bound_args = make_tree_vec (parm_depth);
-
- for (i = saved_depth,
- t = DECL_TEMPLATE_PARMS (gen_tmpl);
- i > 0 && t != NULL_TREE;
- --i, t = TREE_CHAIN (t))
- {
- tree a;
- if (i == saved_depth)
- a = coerce_template_parms (TREE_VALUE (t),
- arglist, gen_tmpl,
- complain,
- /*require_all_args=*/true,
- /*use_default_args=*/true);
- else
- /* Outer levels should have already been coerced. */
- a = TMPL_ARGS_LEVEL (arglist, i);
-
- /* Don't process further if one of the levels fails. */
- if (a == error_mark_node)
- {
- /* Restore the ARGLIST to its full size. */
- TREE_VEC_LENGTH (arglist) = saved_depth;
- return error_mark_node;
- }
-
- SET_TMPL_ARGS_LEVEL (bound_args, i, a);
-
- /* We temporarily reduce the length of the ARGLIST so
- that coerce_template_parms will see only the arguments
- corresponding to the template parameters it is
- examining. */
- TREE_VEC_LENGTH (arglist)--;
- }
-
- /* Restore the ARGLIST to its full size. */
- TREE_VEC_LENGTH (arglist) = saved_depth;
-
- arglist = bound_args;
- }
- else
- arglist
- = coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
- INNERMOST_TEMPLATE_ARGS (arglist),
- gen_tmpl,
- complain,
- /*require_all_args=*/true,
- /*use_default_args=*/true);
+ arglist = coerce_innermost_template_parms (parmlist, arglist, gen_tmpl,
+ complain,
+ /*require_all_args=*/true,
+ /*use_default_args=*/true);
if (arglist == error_mark_node)
/* We were unable to bind the arguments. */
if (OVERLOAD_TYPE_P (t)
&& !DECL_ALIAS_TEMPLATE_P (gen_tmpl))
{
- if (tree attributes
- = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (template_type)))
+ static const char *tags[] = {"abi_tag", "may_alias"};
+
+ for (unsigned ix = 0; ix != 2; ix++)
{
- if (!TREE_CHAIN (attributes))
+ tree attributes
+ = lookup_attribute (tags[ix], TYPE_ATTRIBUTES (template_type));
+
+ if (!attributes)
+ ;
+ else if (!TREE_CHAIN (attributes) && !TYPE_ATTRIBUTES (t))
TYPE_ATTRIBUTES (t) = attributes;
else
TYPE_ATTRIBUTES (t)
- = build_tree_list (TREE_PURPOSE (attributes),
- TREE_VALUE (attributes));
+ = tree_cons (TREE_PURPOSE (attributes),
+ TREE_VALUE (attributes),
+ TYPE_ATTRIBUTES (t));
}
}
lookup_template_variable (tree templ, tree arglist)
{
tree type = unknown_type_node;
- tsubst_flags_t complain = tf_warning_or_error;
- tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (templ));
- arglist = coerce_template_parms (parms, arglist, templ, complain,
- /*req_all*/true, /*use_default*/true);
return build2 (TEMPLATE_ID_EXPR, type, templ, arglist);
}
+/* Instantiate a variable declaration from a TEMPLATE_ID_EXPR for use. */
+
+tree
+finish_template_variable (tree var)
+{
+ tree templ = TREE_OPERAND (var, 0);
+
+ tree arglist = TREE_OPERAND (var, 1);
+ tree tmpl_args = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (templ));
+ arglist = add_outermost_template_args (tmpl_args, arglist);
+
+ tree parms = DECL_TEMPLATE_PARMS (templ);
+ tsubst_flags_t complain = tf_warning_or_error;
+ arglist = coerce_innermost_template_parms (parms, arglist, templ, complain,
+ /*req_all*/true,
+ /*use_default*/true);
+
+ return instantiate_template (templ, arglist, complain);
+}
\f
struct pair_fn_data
{
if (tinst_depth >= max_tinst_depth)
{
- fatal_error ("template instantiation depth exceeds maximum of %d"
+ fatal_error (input_location,
+ "template instantiation depth exceeds maximum of %d"
" (use -ftemplate-depth= to increase the maximum)",
max_tinst_depth);
return false;
= tree_cons (NULL_TREE, TREE_VALUE (TREE_VALUE (t)),
chain);
}
+ else if (TREE_VALUE (t) && PACK_EXPANSION_P (TREE_VALUE (t)))
+ {
+ /* An attribute pack expansion. */
+ tree purp = TREE_PURPOSE (t);
+ tree pack = (tsubst_pack_expansion
+ (TREE_VALUE (t), args, complain, in_decl));
+ int len = TREE_VEC_LENGTH (pack);
+ for (int i = 0; i < len; ++i)
+ {
+ tree elt = TREE_VEC_ELT (pack, i);
+ *q = build_tree_list (purp, elt);
+ q = &TREE_CHAIN (*q);
+ }
+ continue;
+ }
else
TREE_VALUE (t)
= tsubst_expr (TREE_VALUE (t), args, complain, in_decl,
it now. */
push_deferring_access_checks (dk_no_deferred);
+ int saved_unevaluated_operand = cp_unevaluated_operand;
+ int saved_inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
+
fn_context = decl_function_context (TYPE_MAIN_DECL (type));
/* Also avoid push_to_top_level for a lambda in an NSDMI. */
if (!fn_context && LAMBDA_TYPE_P (type) && TYPE_CLASS_SCOPE_P (type))
fn_context = error_mark_node;
if (!fn_context)
push_to_top_level ();
+ else
+ {
+ cp_unevaluated_operand = 0;
+ c_inhibit_evaluation_warnings = 0;
+ }
/* Use #pragma pack from the template context. */
saved_maximum_field_alignment = maximum_field_alignment;
maximum_field_alignment = TYPE_PRECISION (pattern);
}
}
+ if (fn_context)
+ {
+ /* Restore these before substituting into the lambda capture
+ initializers. */
+ cp_unevaluated_operand = saved_unevaluated_operand;
+ c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
+ }
+
if (tree expr = CLASSTYPE_LAMBDA_EXPR (type))
{
tree decl = lambda_function (type);
return extract_fnparm_pack (NULL_TREE, &spec_parm);
}
-/* Return true iff the Ith element of the argument pack ARG_PACK is a
- pack expansion. */
+/* Return 1 if the Ith element of the argument pack ARG_PACK is a
+ pack expansion with no extra args, 2 if it has extra args, or 0
+ if it is not a pack expansion. */
-static bool
+static int
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));
+ return 0;
+ tree elt = TREE_VEC_ELT (vec, i);
+ if (!PACK_EXPANSION_P (elt))
+ return 0;
+ if (PACK_EXPANSION_EXTRA_ARGS (elt))
+ return 2;
+ return 1;
}
{
tree arg = TREE_VALUE (parm_pack);
- if (argument_pack_element_is_expansion_p (arg, i))
+ int exp = argument_pack_element_is_expansion_p (arg, i);
+ if (exp == 2)
+ /* We can't substitute a pack expansion with extra args into
+ our pattern. */
+ return true;
+ else if (exp)
has_expansion_arg = true;
else
has_non_expansion_arg = true;
if (index == 0)
{
aps = make_argument_pack_select (arg_pack, index);
- mark_used (parm);
+ if (!mark_used (parm, complain) && !(complain & tf_error))
+ return error_mark_node;
register_local_specialization (aps, parm);
}
else
if (PRIMARY_TEMPLATE_P (t))
DECL_PRIMARY_TEMPLATE (r) = r;
- if (TREE_CODE (decl) != TYPE_DECL && TREE_CODE (decl) != VAR_DECL)
+ if (TREE_CODE (decl) != TYPE_DECL && !VAR_P (decl))
/* Record this non-type partial instantiation. */
register_specialization (r, t,
DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)),
{
/* T is a static data member or namespace-scope entity.
We have to substitute into namespace-scope variables
- (even though such entities are never templates) because
- of cases like:
+ (not just variable templates) because of cases like:
template <class T> void f() { extern T t; }
tmpl = DECL_TI_TEMPLATE (t);
gen_tmpl = most_general_template (tmpl);
argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
+ if (argvec != error_mark_node)
+ argvec = (coerce_innermost_template_parms
+ (DECL_TEMPLATE_PARMS (gen_tmpl),
+ argvec, t, complain,
+ /*all*/true, /*defarg*/true));
if (argvec == error_mark_node)
RETURN (error_mark_node);
hash = hash_tmpl_and_args (gen_tmpl, argvec);
}
SET_DECL_VALUE_EXPR (r, ve);
}
- if (TREE_STATIC (r) || DECL_EXTERNAL (r))
- set_decl_tls_model (r, decl_tls_model (t));
+ if (CP_DECL_THREAD_LOCAL_P (r)
+ && !processing_template_decl)
+ set_decl_tls_model (r, decl_default_tls_model (r));
}
else if (DECL_SELF_REFERENCE_P (t))
SET_DECL_SELF_REFERENCE_P (r);
initializer is present. We mimic the non-template
processing here. */
DECL_EXTERNAL (r) = 1;
+ if (DECL_NAMESPACE_SCOPE_P (t))
+ DECL_NOT_REALLY_EXTERN (r) = 1;
- register_specialization (r, gen_tmpl, argvec, false, hash);
DECL_TEMPLATE_INFO (r) = build_template_info (tmpl, argvec);
SET_DECL_IMPLICIT_INSTANTIATION (r);
+ register_specialization (r, gen_tmpl, argvec, false, hash);
}
else if (!cp_unevaluated_operand)
register_local_specialization (r, t);
point.) */
if (BASELINK_P (baselink))
fns = BASELINK_FUNCTIONS (baselink);
- if (!template_id_p && !really_overloaded_fn (fns))
- mark_used (OVL_CURRENT (fns));
+ if (!template_id_p && !really_overloaded_fn (fns)
+ && !mark_used (OVL_CURRENT (fns), complain) && !(complain & tf_error))
+ return error_mark_node;
/* Add back the template arguments, if present. */
if (BASELINK_P (baselink) && template_id_p)
check_accessibility_of_qualified_id (expr, /*object_type=*/NULL_TREE,
scope);
/* Remember that there was a reference to this entity. */
- mark_used (expr);
+ if (!mark_used (expr, complain) && !(complain & tf_error))
+ return error_mark_node;
}
if (expr == error_mark_node || TREE_CODE (expr) == TREE_LIST)
if (TREE_CODE (r) == ARGUMENT_PACK_SELECT)
r = ARGUMENT_PACK_SELECT_ARG (r);
- mark_used (r);
+ if (!mark_used (r, complain) && !(complain & tf_error))
+ return error_mark_node;
return r;
case CONST_DECL:
if (TREE_STATIC (r))
rest_of_decl_compilation (r, toplevel_bindings_p (),
at_eof);
- else if (decl_constant_var_p (r))
- /* A use of a local constant decays to its value.
- FIXME update for core DR 696. */
- r = scalar_constant_value (r);
+ else
+ r = process_outer_var_ref (r, complain);
}
}
/* Remember this for subsequent uses. */
}
else
r = t;
- mark_used (r);
+ if (!mark_used (r, complain) && !(complain & tf_error))
+ return error_mark_node;
return r;
case NAMESPACE_DECL:
tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
r = build2 (code, type, op0, op1);
PTRMEM_OK_P (r) = PTRMEM_OK_P (t);
- mark_used (TREE_OPERAND (r, 1));
+ if (!mark_used (TREE_OPERAND (r, 1), complain)
+ && !(complain & tf_error))
+ return error_mark_node;
return r;
}
}
}
+/* Helper function for tsubst_omp_clauses, used for instantiation of
+ OMP_CLAUSE_DECL of clauses that handles also OpenMP array sections
+ represented with TREE_LIST. */
+
+static tree
+tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain,
+ tree in_decl)
+{
+ if (TREE_CODE (decl) == TREE_LIST)
+ {
+ tree low_bound
+ = tsubst_expr (TREE_PURPOSE (decl), args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+ tree length = tsubst_expr (TREE_VALUE (decl), args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+ tree chain = tsubst_omp_clause_decl (TREE_CHAIN (decl), args, complain,
+ in_decl);
+ if (TREE_PURPOSE (decl) == low_bound
+ && TREE_VALUE (decl) == length
+ && TREE_CHAIN (decl) == chain)
+ return decl;
+ return tree_cons (low_bound, length, chain);
+ }
+ return tsubst_copy (decl, args, complain, in_decl);
+}
+
/* Like tsubst_copy, but specifically for OpenMP clauses. */
static tree
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_COPYPRIVATE:
+ case OMP_CLAUSE_UNIFORM:
+ OMP_CLAUSE_DECL (nc) = tsubst_copy (OMP_CLAUSE_DECL (oc), args,
+ complain, in_decl);
+ break;
+ case OMP_CLAUSE_DEPEND:
+ case OMP_CLAUSE_FROM:
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_MAP:
+ OMP_CLAUSE_DECL (nc)
+ = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
+ in_decl);
+ break;
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_COLLAPSE:
case OMP_CLAUSE_FINAL:
- case OMP_CLAUSE_DEPEND:
- case OMP_CLAUSE_FROM:
- case OMP_CLAUSE_TO:
- case OMP_CLAUSE_UNIFORM:
- case OMP_CLAUSE_MAP:
case OMP_CLAUSE_DEVICE:
case OMP_CLAUSE_DIST_SCHEDULE:
case OMP_CLAUSE_NUM_TEAMS:
else
gcc_assert (identifier_p (placeholder));
}
- OMP_CLAUSE_OPERAND (nc, 0)
- = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
- in_decl, /*integral_constant_expression_p=*/false);
+ OMP_CLAUSE_DECL (nc) = tsubst_copy (OMP_CLAUSE_DECL (oc), args,
+ complain, in_decl);
break;
case OMP_CLAUSE_LINEAR:
case OMP_CLAUSE_ALIGNED:
- OMP_CLAUSE_OPERAND (nc, 0)
- = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
- in_decl, /*integral_constant_expression_p=*/false);
+ OMP_CLAUSE_DECL (nc) = tsubst_copy (OMP_CLAUSE_DECL (oc), args,
+ complain, in_decl);
OMP_CLAUSE_OPERAND (nc, 1)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
break;
-
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
tmp = tsubst_omp_clauses (OMP_TARGET_UPDATE_CLAUSES (t), false,
args, complain, in_decl);
t = copy_node (t);
- OMP_CLAUSES (t) = tmp;
+ OMP_TARGET_UPDATE_CLAUSES (t) = tmp;
add_stmt (t);
break;
return t;
}
-/* Sentinel to disable certain warnings during template substitution. */
-
-struct warning_sentinel {
- int &flag;
- int val;
- warning_sentinel(int& flag, bool suppress=true)
- : flag(flag), val(flag) { if (suppress) flag = 0; }
- ~warning_sentinel() { flag = val; }
-};
-
/* Like tsubst but deals with expressions and performs semantic
analysis. FUNCTION_P is true if T is the "F" in "F (ARGS)". */
op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
args, complain, in_decl);
/* Remember that there was a reference to this entity. */
- if (DECL_P (op1))
- mark_used (op1);
+ if (DECL_P (op1)
+ && !mark_used (op1, complain) && !(complain & tf_error))
+ RETURN (error_mark_node);
RETURN (build_x_arrow (input_location, op1, complain));
case NEW_EXPR:
}
/* Remember that there was a reference to this entity. */
- if (DECL_P (function))
- mark_used (function);
+ if (DECL_P (function)
+ && !mark_used (function, complain) && !(complain & tf_error))
+ RETURN (error_mark_node);
/* Put back tf_decltype for the actual call. */
complain |= decltype_flag;
object = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
args, complain, in_decl);
/* Remember that there was a reference to this entity. */
- if (DECL_P (object))
- mark_used (object);
+ if (DECL_P (object)
+ && !mark_used (object, complain) && !(complain & tf_error))
+ RETURN (error_mark_node);
object_type = TREE_TYPE (object);
member = TREE_OPERAND (t, 1);
&& !processing_template_decl
&& !cp_unevaluated_operand
&& (TREE_STATIC (r) || DECL_EXTERNAL (r))
- && DECL_THREAD_LOCAL_P (r))
+ && CP_DECL_THREAD_LOCAL_P (r))
{
if (tree wrap = get_tls_wrapper_fn (r))
/* Replace an evaluated use of the thread_local variable with
r = build_cxx_call (wrap, 0, NULL, tf_warning_or_error);
}
else if (outer_automatic_var_p (r))
- r = process_outer_var_ref (r, complain);
+ {
+ r = process_outer_var_ref (r, complain);
+ if (is_capture_proxy (r))
+ register_local_specialization (r, t);
+ }
if (TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE)
/* If the original type was a reference, we'll be wrapped in
break;
case DEDUCE_CONV:
- {
- /* Swap PARM and ARG throughout the remainder of this
- function; the handling is precisely symmetric since PARM
- will initialize ARG rather than vice versa. */
- tree* temp = parm;
- parm = arg;
- arg = temp;
- break;
- }
+ /* Swap PARM and ARG throughout the remainder of this
+ function; the handling is precisely symmetric since PARM
+ will initialize ARG rather than vice versa. */
+ std::swap (parm, arg);
+ break;
case DEDUCE_EXACT:
/* Core issue #873: Do the DR606 thing (see below) for these cases,
static int
unify_one_argument (tree tparms, tree targs, tree parm, tree arg,
- int subr, unification_kind_t strict, int flags,
+ int subr, unification_kind_t strict,
bool explain_p)
{
tree arg_expr = NULL_TREE;
argument to convert it to the type of the corresponding function
parameter if the parameter type contains no template-parameters that
participate in template argument deduction. */
- if (TYPE_P (parm) && !uses_template_parms (parm))
- /* For function parameters that contain no template-parameters at all,
- we have historically checked for convertibility in order to shortcut
- consideration of this candidate. */
- return check_non_deducible_conversion (parm, arg, strict, flags,
- explain_p);
- else if (strict == DEDUCE_CALL
- && TYPE_P (parm) && !uses_deducible_template_parms (parm))
- /* For function parameters with only non-deducible template parameters,
- just return. */
+ if (strict != DEDUCE_EXACT
+ && TYPE_P (parm) && !uses_deducible_template_parms (parm))
+ /* For function parameters with no deducible template parameters,
+ just return. We'll check non-dependent conversions later. */
return unify_success (explain_p);
switch (strict)
++ia;
if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
- flags, explain_p))
+ explain_p))
return 1;
}
this parameter can be deduced. */
if (TREE_CODE (tparm) == PARM_DECL
&& uses_template_parms (TREE_TYPE (tparm))
- && !saw_undeduced++)
- goto again;
+ && saw_undeduced < 2)
+ {
+ saw_undeduced = 1;
+ continue;
+ }
/* Core issue #226 (C++0x) [temp.deduct]:
be NULL_TREE or ERROR_MARK_NODE, so we do not need
to explicitly check cxx_dialect here. */
if (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)))
- {
- tree parm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
- tree arg = TREE_PURPOSE (TREE_VEC_ELT (tparms, i));
- reopen_deferring_access_checks (*checks);
- location_t save_loc = input_location;
- if (DECL_P (parm))
- input_location = DECL_SOURCE_LOCATION (parm);
- arg = tsubst_template_arg (arg, targs, complain, NULL_TREE);
- arg = convert_template_argument (parm, arg, targs, complain,
- i, NULL_TREE);
- input_location = save_loc;
- *checks = get_deferred_access_checks ();
- pop_deferring_access_checks ();
- if (arg == error_mark_node)
- return 1;
- else
- {
- TREE_VEC_ELT (targs, i) = arg;
- /* The position of the first default template argument,
- is also the number of non-defaulted arguments in TARGS.
- Record that. */
- if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs))
- SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, i);
- continue;
- }
- }
+ /* OK, there is a default argument. Wait until after the
+ conversion check to do substitution. */
+ continue;
/* If the type parameter is a parameter pack, then it will
be deduced to an empty parameter pack. */
return unify_parameter_deduction_failure (explain_p, tparm);
}
+
+ /* DR 1391: All parameters have args, now check non-dependent parms for
+ convertibility. */
+ if (saw_undeduced < 2)
+ for (ia = 0, parms = xparms, args = xargs, nargs = xnargs;
+ parms && parms != void_list_node && ia < nargs; )
+ {
+ parm = TREE_VALUE (parms);
+
+ if (TREE_CODE (parm) == TYPE_PACK_EXPANSION
+ && (!TREE_CHAIN (parms)
+ || TREE_CHAIN (parms) == void_list_node))
+ /* For a function parameter pack that occurs at the end of the
+ parameter-declaration-list, the type A of each remaining
+ argument of the call is compared with the type P of the
+ declarator-id of the function parameter pack. */
+ break;
+
+ parms = TREE_CHAIN (parms);
+
+ if (TREE_CODE (parm) == TYPE_PACK_EXPANSION)
+ /* For a function parameter pack that does not occur at the
+ end of the parameter-declaration-list, the type of the
+ parameter pack is a non-deduced context. */
+ continue;
+
+ arg = args[ia];
+ ++ia;
+
+ if (uses_template_parms (parm))
+ continue;
+ if (check_non_deducible_conversion (parm, arg, strict, flags,
+ explain_p))
+ return 1;
+ }
+
+ /* Now substitute into the default template arguments. */
+ for (i = 0; i < ntparms; i++)
+ {
+ tree targ = TREE_VEC_ELT (targs, i);
+ tree tparm = TREE_VEC_ELT (tparms, i);
+
+ if (targ || tparm == error_mark_node)
+ continue;
+ tree parm = TREE_VALUE (tparm);
+
+ if (TREE_CODE (parm) == PARM_DECL
+ && uses_template_parms (TREE_TYPE (parm))
+ && saw_undeduced < 2)
+ continue;
+
+ tree arg = TREE_PURPOSE (tparm);
+ reopen_deferring_access_checks (*checks);
+ location_t save_loc = input_location;
+ if (DECL_P (parm))
+ input_location = DECL_SOURCE_LOCATION (parm);
+ arg = tsubst_template_arg (arg, targs, complain, NULL_TREE);
+ arg = convert_template_argument (parm, arg, targs, complain,
+ i, NULL_TREE);
+ input_location = save_loc;
+ *checks = get_deferred_access_checks ();
+ pop_deferring_access_checks ();
+ if (arg == error_mark_node)
+ return 1;
+ else
+ {
+ TREE_VEC_ELT (targs, i) = arg;
+ /* The position of the first default template argument,
+ is also the number of non-defaulted arguments in TARGS.
+ Record that. */
+ if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs))
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, i);
+ continue;
+ }
+ }
+
+ if (saw_undeduced++ == 1)
+ goto again;
}
#ifdef ENABLE_CHECKING
if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs))
/* Unify the pattern with the current argument. */
if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
- LOOKUP_IMPLICIT, explain_p))
+ explain_p))
return 1;
/* For each parameter pack, collect the deduced value. */
if (TREE_CODE (parm) == ARRAY_TYPE)
elttype = TREE_TYPE (parm);
else
- elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (parm), 0);
+ {
+ elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (parm), 0);
+ /* Deduction is defined in terms of a single type, so just punt
+ on the (bizarre) std::initializer_list<T...>. */
+ if (PACK_EXPANSION_P (elttype))
+ return unify_success (explain_p);
+ }
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
{
if (!BRACE_ENCLOSED_INITIALIZER_P (elt))
{
tree type = TREE_TYPE (elt);
+ if (type == error_mark_node)
+ return unify_invalid (explain_p);
/* It should only be possible to get here for a call. */
gcc_assert (elt_strict & UNIFY_ALLOW_OUTER_LEVEL);
elt_strict |= maybe_adjust_types_for_deduction
&& !TEMPLATE_PARM_PARAMETER_PACK (parm))
return unify_parameter_pack_mismatch (explain_p, parm, arg);
- arg = strip_typedefs_expr (arg);
+ {
+ bool removed_attr = false;
+ arg = strip_typedefs_expr (arg, &removed_attr);
+ }
TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
return unify_success (explain_p);
break;
if (CLASS_TYPE_P (TREE_TYPE (decl))
+ && !TYPE_DECL_ALIAS_P (TYPE_NAME (TREE_TYPE (decl)))
&& CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
break;
{
tree decl = pending_templates->tinst->decl;
- fatal_error ("template instantiation depth exceeds maximum of %d"
+ fatal_error (input_location,
+ "template instantiation depth exceeds maximum of %d"
" instantiating %q+D, possibly from virtual table generation"
" (use -ftemplate-depth= to increase the maximum)",
max_tinst_depth, decl);
/* Give this enumeration constant the correct access. */
set_current_access_from_decl (decl);
- /* Actually build the enumerator itself. */
- build_enumerator
- (DECL_NAME (decl), value, newtag, DECL_SOURCE_LOCATION (decl));
+ /* Actually build the enumerator itself. Here we're assuming that
+ enumerators can't have dependent attributes. */
+ build_enumerator (DECL_NAME (decl), value, newtag,
+ DECL_ATTRIBUTES (decl), DECL_SOURCE_LOCATION (decl));
}
if (SCOPED_ENUM_P (newtag))
tree
get_mostly_instantiated_function_type (tree decl)
{
- tree fn_type;
- tree tmpl;
- tree targs;
- tree tparms;
- int parm_depth;
-
- tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
- targs = DECL_TI_ARGS (decl);
- tparms = DECL_TEMPLATE_PARMS (tmpl);
- parm_depth = TMPL_PARMS_DEPTH (tparms);
-
- /* There should be as many levels of arguments as there are levels
- of parameters. */
- gcc_assert (parm_depth == TMPL_ARGS_DEPTH (targs));
-
- fn_type = TREE_TYPE (tmpl);
-
- if (parm_depth == 1)
- /* No substitution is necessary. */
- ;
- else
- {
- int i;
- tree partial_args;
-
- /* Replace the innermost level of the TARGS with NULL_TREEs to
- let tsubst know not to substitute for those parameters. */
- partial_args = make_tree_vec (TREE_VEC_LENGTH (targs));
- for (i = 1; i < TMPL_ARGS_DEPTH (targs); ++i)
- SET_TMPL_ARGS_LEVEL (partial_args, i,
- TMPL_ARGS_LEVEL (targs, i));
- SET_TMPL_ARGS_LEVEL (partial_args,
- TMPL_ARGS_DEPTH (targs),
- make_tree_vec (DECL_NTPARMS (tmpl)));
-
- /* Make sure that we can see identifiers, and compute access
- correctly. */
- push_access_scope (decl);
-
- ++processing_template_decl;
- /* Now, do the (partial) substitution to figure out the
- appropriate function type. */
- fn_type = tsubst (fn_type, partial_args, tf_error, NULL_TREE);
- --processing_template_decl;
-
- /* Substitute into the template parameters to obtain the real
- innermost set of parameters. This step is important if the
- innermost set of template parameters contains value
- parameters whose types depend on outer template parameters. */
- TREE_VEC_LENGTH (partial_args)--;
- tparms = tsubst_template_parms (tparms, partial_args, tf_error);
-
- pop_access_scope (decl);
- }
-
- return fn_type;
+ /* For a function, DECL_TI_TEMPLATE is partially instantiated. */
+ return TREE_TYPE (DECL_TI_TEMPLATE (decl));
}
/* Return truthvalue if we're processing a template different from
return current_tinst_level;
}
+/* Return TRUE if current_function_decl is being instantiated, false
+ otherwise. */
+
+bool
+instantiating_current_function_p (void)
+{
+ return (current_instantiation ()
+ && current_instantiation ()->decl == current_function_decl);
+}
+
/* [temp.param] Check that template non-type parm TYPE is of an allowable
type. Return zero for ok, nonzero for disallowed. Issue error and
warning messages under control of COMPLAIN. */
names a dependent type. */
if (TREE_CODE (type) == TYPENAME_TYPE)
return true;
+
+ /* An alias template specialization can be dependent even if the
+ resulting type is not. */
+ if (dependent_alias_template_spec_p (type))
+ return true;
+
/* -- a cv-qualified type where the cv-unqualified type is
dependent.
No code is necessary for this bullet; the code below handles
return true;
/* ... or any of the template arguments is a dependent type or
an expression that is type-dependent or value-dependent. */
- else if (TYPE_TEMPLATE_INFO (type)
+ else if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INFO (type)
&& (any_dependent_template_arguments_p
- (INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (type)))))
+ (INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type)))))
return true;
/* All TYPEOF_TYPEs, DECLTYPE_TYPEs, and UNDERLYING_TYPEs are
&& DECL_INITIAL (expression))
return true;
+ /* A variable template specialization is type-dependent if it has any
+ dependent template arguments. */
+ if (VAR_P (expression)
+ && DECL_LANG_SPECIFIC (expression)
+ && DECL_TEMPLATE_INFO (expression)
+ && variable_template_p (DECL_TI_TEMPLATE (expression)))
+ return any_dependent_template_arguments_p (DECL_TI_ARGS (expression));
+
+ /* Always dependent, on the number of arguments if nothing else. */
+ if (TREE_CODE (expression) == EXPR_PACK_EXPANSION)
+ return true;
+
if (TREE_TYPE (expression) == unknown_type_node)
{
if (TREE_CODE (expression) == ADDR_EXPR)
if (TREE_CODE (expression) == SCOPE_REF)
return false;
- /* Always dependent, on the number of arguments if nothing else. */
- if (TREE_CODE (expression) == EXPR_PACK_EXPANSION)
- return true;
-
if (BASELINK_P (expression))
{
if (BASELINK_OPTYPE (expression)