/* 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"
/* True if we've recursed into fn_type_unification too many times. */
static bool excessive_deduction_depth;
-typedef struct GTY(()) spec_entry
+struct GTY((for_user)) spec_entry
{
tree tmpl;
tree args;
tree spec;
-} spec_entry;
+};
-static GTY ((param_is (spec_entry)))
- htab_t decl_specializations;
+struct spec_hasher : ggc_ptr_hash<spec_entry>
+{
+ static hashval_t hash (spec_entry *);
+ static bool equal (spec_entry *, spec_entry *);
+};
-static GTY ((param_is (spec_entry)))
- htab_t type_specializations;
+static GTY (()) hash_table<spec_hasher> *decl_specializations;
+
+static GTY (()) hash_table<spec_hasher> *type_specializations;
/* Contains canonical template parameter types. The vector is indexed by
the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
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, tree);
+static tree get_partial_spec_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,
static void push_inline_template_parms_recursive (tree, int);
static tree retrieve_local_specialization (tree);
static void register_local_specialization (tree, tree);
-static hashval_t hash_specialization (const void *p);
static tree reduce_template_parm_level (tree, tree, int, tree, tsubst_flags_t);
static int mark_template_parm (tree, void *);
static int template_parm_this_level_p (tree, void *);
static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
static void regenerate_decl_from_template (tree, tree);
-static tree most_specialized_class (tree, tsubst_flags_t);
+static tree most_specialized_partial_spec (tree, tsubst_flags_t);
static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int);
static tree tsubst_arg_types (tree, tree, tree, tsubst_flags_t, tree);
static tree tsubst_function_type (tree, tree, tsubst_flags_t, 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);
+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
new member specialization template. */
spec_entry elt;
spec_entry *entry;
- void **slot;
elt.tmpl = most_general_template (tmpl);
elt.args = CLASSTYPE_TI_ARGS (inst);
elt.spec = inst;
- htab_remove_elt (type_specializations, &elt);
+ type_specializations->remove_elt (&elt);
elt.tmpl = tmpl;
elt.args = INNERMOST_TEMPLATE_ARGS (elt.args);
- slot = htab_find_slot (type_specializations, &elt, INSERT);
+ spec_entry **slot
+ = type_specializations->find_slot (&elt, INSERT);
entry = ggc_alloc<spec_entry> ();
*entry = elt;
*slot = entry;
&& !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;
{
spec_entry *found;
spec_entry elt;
- htab_t specializations;
+ hash_table<spec_hasher> *specializations;
elt.tmpl = tmpl;
elt.args = args;
specializations = decl_specializations;
if (hash == 0)
- hash = hash_specialization (&elt);
- found = (spec_entry *) htab_find_with_hash (specializations, &elt, hash);
+ hash = spec_hasher::hash (&elt);
+ found = specializations->find_with_hash (&elt, hash);
if (found)
return found->spec;
}
hashval_t hash)
{
tree fn;
- void **slot = NULL;
+ spec_entry **slot = NULL;
spec_entry elt;
gcc_assert ((TREE_CODE (tmpl) == TEMPLATE_DECL && DECL_P (spec))
elt.spec = spec;
if (hash == 0)
- hash = hash_specialization (&elt);
+ hash = spec_hasher::hash (&elt);
slot =
- htab_find_slot_with_hash (decl_specializations, &elt, hash, INSERT);
+ decl_specializations->find_slot_with_hash (&elt, hash, INSERT);
if (*slot)
fn = ((spec_entry *) *slot)->spec;
else
gcc_assert (tmpl && args && spec);
*entry = elt;
*slot = entry;
- if (TREE_CODE (spec) == FUNCTION_DECL && DECL_NAMESPACE_SCOPE_P (spec)
- && PRIMARY_TEMPLATE_P (tmpl)
- && DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (tmpl)) == NULL_TREE)
- /* TMPL is a forward declaration of a template function; keep a list
+ if ((TREE_CODE (spec) == FUNCTION_DECL && DECL_NAMESPACE_SCOPE_P (spec)
+ && PRIMARY_TEMPLATE_P (tmpl)
+ && DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (tmpl)) == NULL_TREE)
+ || variable_template_p (tmpl))
+ /* If TMPL is a forward declaration of a template function, keep a list
of all specializations in case we need to reassign them to a friend
- template later in tsubst_friend_function. */
+ template later in tsubst_friend_function.
+
+ Also keep a list of all variable template instantiations so that
+ process_partial_specialization can check whether a later partial
+ specialization would have used it. */
DECL_TEMPLATE_INSTANTIATIONS (tmpl)
= tree_cons (args, spec, DECL_TEMPLATE_INSTANTIATIONS (tmpl));
}
int comparing_specializations;
-static int
-eq_specializations (const void *p1, const void *p2)
+bool
+spec_hasher::equal (spec_entry *e1, spec_entry *e2)
{
- const spec_entry *e1 = (const spec_entry *)p1;
- const spec_entry *e2 = (const spec_entry *)p2;
int equal;
++comparing_specializations;
/* Returns a hash for a spec_entry node based on the TMPL and ARGS members,
ignoring SPEC. */
-static hashval_t
-hash_specialization (const void *p)
+hashval_t
+spec_hasher::hash (spec_entry *e)
{
- const spec_entry *e = (const spec_entry *)p;
return hash_tmpl_and_args (e->tmpl, e->args);
}
case CONSTRUCTOR:
{
tree field, value;
+ iterative_hash_template_arg (TREE_TYPE (arg), val);
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (arg), i, field, value)
{
val = iterative_hash_template_arg (field, val);
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);
elt.args = TI_ARGS (tinfo);
elt.spec = NULL_TREE;
- entry = (spec_entry *) htab_find (decl_specializations, &elt);
+ entry = decl_specializations->find (&elt);
if (entry != NULL)
{
gcc_assert (entry->spec == spec || entry->spec == new_spec);
++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);
/* This case handles bogus declarations like template <>
template <class T> void f<int>(); */
- if (uses_template_parms (declarator))
+ if (!uses_template_parms (declarator))
+ error ("template-id %qD in declaration of primary template",
+ declarator);
+ else if (variable_template_p (TREE_OPERAND (declarator, 0)))
+ {
+ /* Partial specialization of variable template. */
+ SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ specialization = 1;
+ goto ok;
+ }
+ else if (cxx_dialect < cxx14)
error ("non-type partial specialization %qD "
"is not allowed", declarator);
else
- error ("template-id %qD in declaration of primary template",
- declarator);
+ error ("non-class, non-variable partial specialization %qD "
+ "is not allowed", declarator);
return decl;
+ ok:;
}
if (ctype && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype))
{
tree tmpl = NULL_TREE;
tree targs = NULL_TREE;
+ bool was_template_id = (TREE_CODE (declarator) == TEMPLATE_ID_EXPR);
/* Make sure that the declarator is a TEMPLATE_ID_EXPR. */
- if (TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
+ if (!was_template_id)
{
tree fns;
else if (ctype != NULL_TREE
&& (identifier_p (TREE_OPERAND (declarator, 0))))
{
- // Ignore variable templates.
+ // We'll match variable templates in start_decl.
if (VAR_P (decl))
return decl;
/* If this is a specialization of a member template of a
template class, we want to return the TEMPLATE_DECL, not
the specialization of it. */
- if (tsk == tsk_template)
+ if (tsk == tsk_template && !was_template_id)
{
tree result = DECL_TEMPLATE_RESULT (tmpl);
SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
/* Set up the DECL_TEMPLATE_INFO for DECL. */
DECL_TEMPLATE_INFO (decl) = build_template_info (tmpl, targs);
+ if (was_template_id)
+ TINFO_USED_TEMPLATE_ID (DECL_TEMPLATE_INFO (decl)) = true;
+
/* Inherit default function arguments from the template
DECL is specializing. */
if (DECL_FUNCTION_TEMPLATE_P (tmpl))
/* 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
process_partial_specialization (tree decl)
{
tree type = TREE_TYPE (decl);
- tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
- tree specargs = CLASSTYPE_TI_ARGS (type);
+ tree tinfo = get_template_info (decl);
+ tree maintmpl = TI_TEMPLATE (tinfo);
+ tree specargs = TI_ARGS (tinfo);
tree inner_args = INNERMOST_TEMPLATE_ARGS (specargs);
tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl);
tree inner_parms;
The argument list of the specialization shall not be identical to
the implicit argument list of the primary template. */
- if (comp_template_args
- (inner_args,
- INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (TREE_TYPE
- (maintmpl)))))
- error ("partial specialization %qT does not specialize any template arguments", type);
+ tree main_args
+ = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (maintmpl)));
+ if (comp_template_args (inner_args, INNERMOST_TEMPLATE_ARGS (main_args)))
+ error ("partial specialization %qD does not specialize "
+ "any template arguments", decl);
/* A partial specialization that replaces multiple parameters of the
primary template with a pack expansion is less specialized for those
}
/* We should only get here once. */
- gcc_assert (!COMPLETE_TYPE_P (type));
+ if (TREE_CODE (decl) == TYPE_DECL)
+ gcc_assert (!COMPLETE_TYPE_P (type));
tree tmpl = build_template_decl (decl, current_template_parms,
DECL_MEMBER_TEMPLATE_P (maintmpl));
for (inst = DECL_TEMPLATE_INSTANTIATIONS (maintmpl); inst;
inst = TREE_CHAIN (inst))
{
- tree inst_type = TREE_VALUE (inst);
- if (COMPLETE_TYPE_P (inst_type)
- && CLASSTYPE_IMPLICIT_INSTANTIATION (inst_type))
+ tree instance = TREE_VALUE (inst);
+ if (TYPE_P (instance)
+ ? (COMPLETE_TYPE_P (instance)
+ && CLASSTYPE_IMPLICIT_INSTANTIATION (instance))
+ : DECL_TEMPLATE_INSTANTIATION (instance))
{
- tree spec = most_specialized_class (inst_type, tf_none);
- if (spec && TREE_TYPE (spec) == type)
- permerror (input_location,
- "partial specialization of %qT after instantiation "
- "of %qT", type, inst_type);
+ tree spec = most_specialized_partial_spec (instance, tf_none);
+ if (spec && TREE_VALUE (spec) == tmpl)
+ {
+ tree inst_decl = (DECL_P (instance)
+ ? instance : TYPE_NAME (instance));
+ permerror (input_location,
+ "partial specialization of %qD after instantiation "
+ "of %qD", decl, inst_decl);
+ }
}
}
|| 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;
return error_mark_node;
/* See if this is a partial specialization. */
- is_partial = (DECL_IMPLICIT_TYPEDEF_P (decl)
- && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
- && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)));
+ is_partial = ((DECL_IMPLICIT_TYPEDEF_P (decl)
+ && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
+ || (VAR_P (decl)
+ && DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_SPECIALIZATION (decl)
+ && TINFO_USED_TEMPLATE_ID (DECL_TEMPLATE_INFO (decl))));
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_FRIEND_P (decl))
is_friend = true;
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
return true;
}
+/* The actual substitution part of instantiate_non_dependent_expr_sfinae,
+ to be used when the caller has already checked
+ (processing_template_decl
+ && !instantiation_dependent_expression_p (expr)
+ && potential_constant_expression (expr))
+ and cleared processing_template_decl. */
+
+tree
+instantiate_non_dependent_expr_internal (tree expr, tsubst_flags_t complain)
+{
+ return tsubst_copy_and_build (expr,
+ /*args=*/NULL_TREE,
+ complain,
+ /*in_decl=*/NULL_TREE,
+ /*function_p=*/false,
+ /*integral_constant_expression_p=*/true);
+}
+
/* Simplify EXPR if it is a non-dependent expression. Returns the
(possibly simplified) expression. */
tree
-fold_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain)
+instantiate_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain)
{
if (expr == NULL_TREE)
return NULL_TREE;
&& !instantiation_dependent_expression_p (expr)
&& potential_constant_expression (expr))
{
- HOST_WIDE_INT saved_processing_template_decl;
-
- saved_processing_template_decl = processing_template_decl;
- processing_template_decl = 0;
- expr = tsubst_copy_and_build (expr,
- /*args=*/NULL_TREE,
- complain,
- /*in_decl=*/NULL_TREE,
- /*function_p=*/false,
- /*integral_constant_expression_p=*/true);
- processing_template_decl = saved_processing_template_decl;
+ processing_template_decl_sentinel s;
+ expr = instantiate_non_dependent_expr_internal (expr, complain);
}
return expr;
}
tree
-fold_non_dependent_expr (tree expr)
+instantiate_non_dependent_expr (tree expr)
{
- return fold_non_dependent_expr_sfinae (expr, tf_error);
+ return instantiate_non_dependent_expr_sfinae (expr, tf_error);
}
/* Return TRUE iff T is a type alias, a TEMPLATE_DECL for an alias
|| DECL_ALIAS_TEMPLATE_P (t));
}
-/* Return TRUE iff is a specialization of an alias template. */
+/* Return TRUE iff T is a specialization of an alias template. */
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;
+}
+
+/* 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)
+ && 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. */
so that access checking can be performed when the template is
instantiated -- but here we need the resolved form so that we can
convert the argument. */
+ bool non_dep = false;
if (TYPE_REF_OBJ_P (type)
&& has_value_dependent_address (expr))
/* If we want the address and it's value-dependent, don't fold. */;
- else if (!type_unknown_p (expr))
- expr = fold_non_dependent_expr_sfinae (expr, complain);
+ else if (!type_unknown_p (expr)
+ && processing_template_decl
+ && !instantiation_dependent_expression_p (expr)
+ && potential_constant_expression (expr))
+ non_dep = true;
if (error_operand_p (expr))
return error_mark_node;
expr_type = TREE_TYPE (expr);
else
expr = mark_rvalue_use (expr);
+ /* If the argument is non-dependent, perform any conversions in
+ non-dependent context as well. */
+ processing_template_decl_sentinel s (non_dep);
+ if (non_dep)
+ expr = instantiate_non_dependent_expr_internal (expr, complain);
+
/* 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_OR_PTRMEM_P (type))
right type? */
gcc_assert (same_type_ignoring_top_level_qualifiers_p
(type, TREE_TYPE (expr)));
- return expr;
+ return convert_from_reference (expr);
}
/* Subroutine of coerce_template_template_parms, which returns 1 if
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 template_args_equal (ot, nt);
}
else if (TYPE_P (nt))
- return TYPE_P (ot) && same_type_p (ot, nt);
+ {
+ if (!TYPE_P (ot))
+ 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 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
+ 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
{
tree templ = NULL_TREE, parmlist;
tree t;
- void **slot;
+ spec_entry **slot;
spec_entry *entry;
spec_entry elt;
hashval_t hash;
/* 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 we already have this specialization, return it. */
elt.tmpl = gen_tmpl;
elt.args = arglist;
- hash = hash_specialization (&elt);
- entry = (spec_entry *) htab_find_with_hash (type_specializations,
- &elt, hash);
+ hash = spec_hasher::hash (&elt);
+ entry = type_specializations->find_with_hash (&elt, hash);
if (entry)
return entry->spec;
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));
}
}
SET_TYPE_TEMPLATE_INFO (t, build_template_info (found, arglist));
elt.spec = t;
- slot = htab_find_slot_with_hash (type_specializations,
- &elt, hash, INSERT);
+ slot = type_specializations->find_slot_with_hash (&elt, hash, INSERT);
entry = ggc_alloc<spec_entry> ();
*entry = elt;
*slot = entry;
return ret;
}
-/* Return a TEMPLATE_ID_EXPR for the given variable template and ARGLIST.
- If the ARGLIST refers to any template parameters, the type of the
- expression is the unknown_type_node since the template-id could
- refer to an explicit or partial specialization. */
+/* Return a TEMPLATE_ID_EXPR for the given variable template and ARGLIST.
+ The type of the expression is the unknown_type_node since the
+ template-id could refer to an explicit or partial specialization. */
tree
lookup_template_variable (tree templ, tree arglist)
{
- tree type;
- if (uses_template_parms (arglist))
- type = unknown_type_node;
- else
- type = TREE_TYPE (templ);
+ tree type = unknown_type_node;
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
{
int
uses_template_parms (tree t)
{
+ if (t == NULL_TREE)
+ return false;
+
bool dependent_p;
int saved_processing_template_decl;
/* 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. */
+ is set to 0 during instantiate_non_dependent_expr. */
bool
in_template_function (void)
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;
elt.args = DECL_TI_ARGS (spec);
elt.spec = NULL_TREE;
- htab_remove_elt (decl_specializations, &elt);
+ decl_specializations->remove_elt (&elt);
DECL_TI_ARGS (spec)
= add_outermost_template_args (new_args,
= 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,
/* Determine what specialization of the original template to
instantiate. */
- t = most_specialized_class (type, tf_warning_or_error);
+ t = most_specialized_partial_spec (type, tf_warning_or_error);
if (t == error_mark_node)
{
TYPE_BEING_DEFINED (type) = 1;
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 (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. */
+ the context of most_specialized_partial_spec. */
if (TREE_CODE (new_type) == TEMPLATE_DECL)
return new_type;
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);
r = cp_build_reference_type (type, TYPE_REF_IS_RVALUE (t));
r = cp_build_qualified_type_real (r, cp_type_quals (t), complain);
- if (cxx_dialect >= cxx14
- && !(TREE_CODE (t) == REFERENCE_TYPE && REFERENCE_VLA_OK (t))
- && array_of_runtime_bound_p (type)
- && (flag_iso || warn_vla > 0))
- {
- if (complain & tf_warning_or_error)
- pedwarn
- (input_location, OPT_Wvla,
- code == REFERENCE_TYPE
- ? G_("cannot declare reference to array of runtime bound")
- : G_("cannot declare pointer to array of runtime bound"));
- else
- r = error_mark_node;
- }
-
if (r != error_mark_node)
/* Will this ever be needed for TYPE_..._TO values? */
layout_type (r);
return cp_build_qualified_type_real (type,
cp_type_quals (t)
| cp_type_quals (type),
- complain);
+ complain | tf_ignore_bad_quals);
}
case UNDERLYING_TYPE:
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:
return t;
/* If ARGS is NULL, then T is known to be non-dependent. */
if (args == NULL_TREE)
- return integral_constant_value (t);
+ return scalar_constant_value (t);
/* Unfortunately, we cannot just call lookup_name here.
Consider:
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 = integral_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;
case COND_EXPR:
{
tree cond = RECUR (TREE_OPERAND (t, 0));
+ tree folded_cond = fold_non_dependent_expr (cond);
tree exp1, exp2;
- if (TREE_CODE (cond) == INTEGER_CST)
+ if (TREE_CODE (folded_cond) == INTEGER_CST)
{
- if (integer_zerop (cond))
+ if (integer_zerop (folded_cond))
{
++c_inhibit_evaluation_warnings;
exp1 = RECUR (TREE_OPERAND (t, 1));
exp2 = RECUR (TREE_OPERAND (t, 2));
--c_inhibit_evaluation_warnings;
}
+ cond = folded_cond;
}
else
{
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);
case PARM_DECL:
{
tree r = tsubst_copy (t, args, complain, in_decl);
+ /* ??? We're doing a subset of finish_id_expression here. */
if (VAR_P (r)
&& !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
a call to its wrapper. */
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);
+ 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
constant. */
else if (TREE_TYPE (t)
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t))
+ && !REFERENCE_REF_P (t)
&& !TREE_CONSTANT (t))
{
if (complain & tf_error)
++processing_template_decl;
if (DECL_CLASS_SCOPE_P (gen_tmpl))
{
- tree ctx = tsubst (DECL_CONTEXT (gen_tmpl), targ_ptr,
- complain, gen_tmpl);
+ tree ctx = tsubst_aggr_type (DECL_CONTEXT (gen_tmpl), targ_ptr,
+ complain, gen_tmpl, true);
push_nested_class (ctx);
}
+
+ tree pattern = DECL_TEMPLATE_RESULT (gen_tmpl);
+
+ if (VAR_P (pattern))
+ {
+ /* We need to determine if we're using a partial or explicit
+ specialization now, because the type of the variable could be
+ different. */
+ tree tid = lookup_template_variable (gen_tmpl, targ_ptr);
+ tree elt = most_specialized_partial_spec (tid, complain);
+ if (elt == error_mark_node)
+ pattern = error_mark_node;
+ else if (elt)
+ {
+ tmpl = TREE_VALUE (elt);
+ pattern = DECL_TEMPLATE_RESULT (tmpl);
+ targ_ptr = TREE_PURPOSE (elt);
+ }
+ }
+
/* Substitute template parameters to obtain the specialization. */
- fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
- targ_ptr, complain, gen_tmpl);
+ fndecl = tsubst (pattern, targ_ptr, complain, gen_tmpl);
if (DECL_CLASS_SCOPE_P (gen_tmpl))
pop_nested_class ();
pop_from_top_level ();
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);
case CONST_DECL:
if (DECL_TEMPLATE_PARM_P (parm))
return unify (tparms, targs, DECL_INITIAL (parm), arg, strict, explain_p);
- if (arg != integral_constant_value (parm))
+ if (arg != scalar_constant_value (parm))
return unify_template_argument_mismatch (explain_p, parm, arg);
return unify_success (explain_p);
case INDIRECT_REF:
if (REFERENCE_REF_P (parm))
- return unify (tparms, targs, TREE_OPERAND (parm, 0), arg,
- strict, explain_p);
+ {
+ if (REFERENCE_REF_P (arg))
+ arg = TREE_OPERAND (arg, 0);
+ return unify (tparms, targs, TREE_OPERAND (parm, 0), arg,
+ strict, explain_p);
+ }
/* FALLTHRU */
default:
/* Determine which of two partial specializations of 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
+ PAT1 is a TREE_LIST whose TREE_VALUE is the TEMPLATE_DECL corresponding
+ to the first partial specialization. The TREE_PURPOSE is the
innermost set of template parameters for the partial
specialization. PAT2 is similar, but for the second template.
two templates is more specialized. */
static int
-more_specialized_class (tree tmpl, tree pat1, tree pat2)
+more_specialized_partial_spec (tree tmpl, tree pat1, tree pat2)
{
tree targs;
- tree tmpl1, tmpl2;
int winner = 0;
bool any_deductions = false;
- tmpl1 = TREE_TYPE (pat1);
- tmpl2 = TREE_TYPE (pat2);
+ tree tmpl1 = TREE_VALUE (pat1);
+ tree tmpl2 = TREE_VALUE (pat2);
+ tree parms1 = DECL_INNERMOST_TEMPLATE_PARMS (tmpl1);
+ tree parms2 = DECL_INNERMOST_TEMPLATE_PARMS (tmpl2);
+ tree specargs1 = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (tmpl1)));
+ tree specargs2 = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (tmpl2)));
/* Just like what happens for functions, if we are ordering between
- different class template specializations, we may encounter dependent
+ different template specializations, we may encounter dependent
types in the arguments, and we need our dependency check functions
to behave correctly. */
++processing_template_decl;
- targs = get_class_bindings (tmpl, TREE_VALUE (pat1),
- CLASSTYPE_TI_ARGS (tmpl1),
- CLASSTYPE_TI_ARGS (tmpl2));
+ targs = get_partial_spec_bindings (tmpl, parms1, specargs1, specargs2);
if (targs)
{
--winner;
any_deductions = true;
}
- targs = get_class_bindings (tmpl, TREE_VALUE (pat2),
- CLASSTYPE_TI_ARGS (tmpl2),
- CLASSTYPE_TI_ARGS (tmpl1));
+ targs = get_partial_spec_bindings (tmpl, parms2, specargs2, specargs1);
if (targs)
{
++winner;
}
--processing_template_decl;
- /* In the case of a tie where at least one of the class templates
+ /* In the case of a tie where at least one of the templates
has a parameter pack at the end, the template with the most
non-packed parameters wins. */
if (winner == 0
is bound to `double'. */
static tree
-get_class_bindings (tree tmpl, tree tparms, tree spec_args, tree args)
+get_partial_spec_bindings (tree tmpl, tree tparms, tree spec_args, tree args)
{
int i, ntparms = TREE_VEC_LENGTH (tparms);
tree deduced_args;
break;
if (CLASS_TYPE_P (TREE_TYPE (decl))
+ && !TYPE_DECL_ALIAS_P (TYPE_NAME (TREE_TYPE (decl)))
&& CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
break;
return decl;
}
-/* Return the most specialized of the class template partial
- specializations which can produce TYPE, a specialization of some class
- template. The value returned is actually a TREE_LIST; the TREE_TYPE is
- a _TYPE node corresponding to the partial specialization, while the
- TREE_PURPOSE is the set of template arguments that must be
- substituted into the TREE_TYPE in order to generate TYPE.
+/* Return the most specialized of the template partial specializations
+ which can produce TARGET, a specialization of some class or variable
+ template. The value returned is actually a TREE_LIST; the TREE_VALUE is
+ a TEMPLATE_DECL node corresponding to the partial specialization, while
+ the TREE_PURPOSE is the set of template arguments that must be
+ substituted into the template pattern in order to generate TARGET.
If the choice of partial specialization is ambiguous, a diagnostic
is issued, and the error_mark_node is returned. If there are no
- partial specializations matching TYPE, then NULL_TREE is
+ partial specializations matching TARGET, then NULL_TREE is
returned, indicating that the primary template should be used. */
static tree
-most_specialized_class (tree type, tsubst_flags_t complain)
+most_specialized_partial_spec (tree target, tsubst_flags_t complain)
{
tree list = NULL_TREE;
tree t;
int fate;
bool ambiguous_p;
tree outer_args = NULL_TREE;
+ tree tmpl, args;
+
+ if (TYPE_P (target))
+ {
+ tree tinfo = CLASSTYPE_TEMPLATE_INFO (target);
+ tmpl = TI_TEMPLATE (tinfo);
+ args = TI_ARGS (tinfo);
+ }
+ else if (TREE_CODE (target) == TEMPLATE_ID_EXPR)
+ {
+ tmpl = TREE_OPERAND (target, 0);
+ args = TREE_OPERAND (target, 1);
+ }
+ else if (VAR_P (target))
+ {
+ tree tinfo = DECL_TEMPLATE_INFO (target);
+ tmpl = TI_TEMPLATE (tinfo);
+ args = TI_ARGS (tinfo);
+ }
+ else
+ gcc_unreachable ();
- tree tmpl = CLASSTYPE_TI_TEMPLATE (type);
tree main_tmpl = most_general_template (tmpl);
- tree args = CLASSTYPE_TI_ARGS (type);
/* For determining which partial specialization to use, only the
innermost args are interesting. */
tree partial_spec_args;
tree spec_args;
tree spec_tmpl = TREE_VALUE (t);
- tree orig_parms = DECL_INNERMOST_TEMPLATE_PARMS (spec_tmpl);
- partial_spec_args = CLASSTYPE_TI_ARGS (TREE_TYPE (t));
+ partial_spec_args = TREE_PURPOSE (t);
++processing_template_decl;
return error_mark_node;
tree parms = DECL_INNERMOST_TEMPLATE_PARMS (spec_tmpl);
- spec_args = get_class_bindings (tmpl, parms,
+ spec_args = get_partial_spec_bindings (tmpl, parms,
partial_spec_args,
args);
if (spec_args)
{
if (outer_args)
spec_args = add_to_template_args (outer_args, spec_args);
- list = tree_cons (spec_args, orig_parms, list);
+ list = tree_cons (spec_args, TREE_VALUE (t), list);
TREE_TYPE (list) = TREE_TYPE (t);
}
}
t = TREE_CHAIN (t);
for (; t; t = TREE_CHAIN (t))
{
- fate = more_specialized_class (tmpl, champ, t);
+ fate = more_specialized_partial_spec (tmpl, champ, t);
if (fate == 1)
;
else
if (!ambiguous_p)
for (t = list; t && t != champ; t = TREE_CHAIN (t))
{
- fate = more_specialized_class (tmpl, champ, t);
+ fate = more_specialized_partial_spec (tmpl, champ, t);
if (fate != 1)
{
ambiguous_p = true;
char *spaces = NULL;
if (!(complain & tf_error))
return error_mark_node;
- error ("ambiguous class template instantiation for %q#T", type);
+ if (TYPE_P (target))
+ error ("ambiguous template instantiation for %q#T", target);
+ else
+ error ("ambiguous template instantiation for %q#D", target);
str = ngettext ("candidate is:", "candidates are:", list_length (list));
for (t = list; t; t = TREE_CHAIN (t))
{
- error ("%s %+#T", spaces ? spaces : str, TREE_TYPE (t));
+ tree subst = build_tree_list (TREE_VALUE (t), TREE_PURPOSE (t));
+ inform (DECL_SOURCE_LOCATION (TREE_VALUE (t)),
+ "%s %#S", spaces ? spaces : str, subst);
spaces = spaces ? spaces : get_spaces (str);
}
free (spaces);
{
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. */
- type = TYPE_MAIN_VARIANT (type);
+ dependent.
+ No code is necessary for this bullet; the code below handles
+ cv-qualified types, and we don't want to strip aliases with
+ TYPE_MAIN_VARIANT because of DR 1558. */
/* -- a compound type constructed from any dependent type. */
if (TYPE_PTRMEM_P (type))
return (dependent_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
if (DECL_INITIAL (expression)
&& decl_constant_var_p (expression)
&& (TREE_CODE (DECL_INITIAL (expression)) == TREE_LIST
+ /* cp_finish_decl doesn't fold reference initializers. */
+ || TREE_CODE (TREE_TYPE (expression)) == REFERENCE_TYPE
|| value_dependent_expression_p (DECL_INITIAL (expression))))
return true;
return false;
{
unsigned ix;
tree val;
+ if (dependent_type_p (TREE_TYPE (expression)))
+ return true;
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expression), ix, val)
if (value_dependent_expression_p (val))
return true;
case STMT_EXPR:
/* Treat a GNU statement expression as dependent to avoid crashing
- under fold_non_dependent_expr; it can't be constant. */
+ under instantiate_non_dependent_expr; it can't be constant. */
return true;
default:
&& 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)
/* 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 >= cxx11)
- maybe_constant_value (fold_non_dependent_expr_sfinae (expr, tf_none));
+ fold_non_dependent_expr (expr);
#endif
/* Preserve OVERLOADs; the functions must be available to resolve
initializer is a braced-init-list (8.5.4), with
std::initializer_list<U>. */
if (BRACE_ENCLOSED_INITIALIZER_P (init))
- type = listify_autos (type, auto_node);
+ {
+ if (!DIRECT_LIST_INIT_P (init))
+ type = listify_autos (type, auto_node);
+ else if (CONSTRUCTOR_NELTS (init) == 1)
+ init = CONSTRUCTOR_ELT (init, 0)->value;
+ else
+ {
+ if (permerror (input_location, "direct-list-initialization of "
+ "%<auto%> requires exactly one element"))
+ inform (input_location,
+ "for deduction to %<std::initializer_list%>, use copy-"
+ "list-initialization (i.e. add %<=%> before the %<{%>)");
+ type = listify_autos (type, auto_node);
+ }
+ }
init = resolve_nondeduced_context (init);
void
init_template_processing (void)
{
- decl_specializations = htab_create_ggc (37,
- hash_specialization,
- eq_specializations,
- ggc_free);
- type_specializations = htab_create_ggc (37,
- hash_specialization,
- eq_specializations,
- ggc_free);
+ decl_specializations = hash_table<spec_hasher>::create_ggc (37);
+ type_specializations = hash_table<spec_hasher>::create_ggc (37);
}
/* Print stats about the template hash tables for -fstats. */
print_template_statistics (void)
{
fprintf (stderr, "decl_specializations: size %ld, %ld elements, "
- "%f collisions\n", (long) htab_size (decl_specializations),
- (long) htab_elements (decl_specializations),
- htab_collisions (decl_specializations));
+ "%f collisions\n", (long) decl_specializations->size (),
+ (long) decl_specializations->elements (),
+ decl_specializations->collisions ());
fprintf (stderr, "type_specializations: size %ld, %ld elements, "
- "%f collisions\n", (long) htab_size (type_specializations),
- (long) htab_elements (type_specializations),
- htab_collisions (type_specializations));
+ "%f collisions\n", (long) type_specializations->size (),
+ (long) type_specializations->elements (),
+ type_specializations->collisions ());
}
#include "gt-cp-pt.h"