/* 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"
#include "attribs.h"
#include "stor-layout.h"
#include "intl.h"
-#include "pointer-set.h"
#include "flags.h"
#include "cp-tree.h"
#include "c-family/c-common.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;
+};
+
+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 decl_specializations;
+static GTY (()) hash_table<spec_hasher> *decl_specializations;
-static GTY ((param_is (spec_entry)))
- htab_t type_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,
vec<deferred_access_check, va_gc> **,
bool);
static void note_template_header (int);
-static tree convert_nontype_argument_function (tree, tree);
+static tree convert_nontype_argument_function (tree, tree, tsubst_flags_t);
static tree convert_nontype_argument (tree, tree, tsubst_flags_t);
static tree convert_template_argument (tree, tree, tree,
tsubst_flags_t, int, tree);
static int for_each_template_parm (tree, tree_fn_t, void*,
- struct pointer_set_t*, bool);
+ hash_set<tree> *, bool);
static tree expand_template_argument_pack (tree);
static tree build_template_parm_index (int, int, int, tree, tree);
static bool inline_needs_template_parms (tree, bool);
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);
- entry = ggc_alloc_spec_entry ();
+ 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;
}
static tree
retrieve_local_specialization (tree tmpl)
{
- void **slot;
-
if (local_specializations == NULL)
return NULL_TREE;
- slot = pointer_map_contains (local_specializations, tmpl);
- return slot ? (tree) *slot : NULL_TREE;
+ tree *slot = local_specializations->get (tmpl);
+ return slot ? *slot : NULL_TREE;
}
/* Returns nonzero iff DECL is a specialization of TMPL. */
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
if (slot != NULL /* !optimize_specialization_lookup_p (tmpl) */)
{
- spec_entry *entry = ggc_alloc_spec_entry ();
+ spec_entry *entry = ggc_alloc<spec_entry> ();
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);
static void
register_local_specialization (tree spec, tree tmpl)
{
- void **slot;
-
- slot = pointer_map_insert (local_specializations, tmpl);
- *slot = spec;
+ local_specializations->put (tmpl, spec);
}
/* TYPE is a class type. Returns true if TYPE is an explicitly
if (BASELINK_P (fns))
fns = BASELINK_FUNCTIONS (fns);
- if (!is_overloaded_fn (fns))
+ if (TREE_CODE (decl) == FUNCTION_DECL && !is_overloaded_fn (fns))
{
error ("%qD is not a function template", fns);
return error_mark_node;
}
+ else if (VAR_P (decl) && !variable_template_p (fns))
+ {
+ error ("%qD is not a variable template", fns);
+ return error_mark_node;
+ }
/* Count the number of template headers specified for this
specialization. */
b = b->level_chain)
++header_count;
- for (; fns; fns = OVL_NEXT (fns))
+ if (variable_template_p (fns))
+ {
+ 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);
TYPE_ATTRIBUTES (old_type));
new_type = build_exception_variant (new_type,
TYPE_RAISES_EXCEPTIONS (old_type));
+
+ if (TYPE_HAS_LATE_RETURN_TYPE (old_type))
+ TYPE_HAS_LATE_RETURN_TYPE (new_type) = 1;
+
TREE_TYPE (decl) = new_type;
}
{
tree ctx = CP_DECL_CONTEXT (decl);
int wanted = num_template_headers_for_class (ctx);
- if (!TYPE_P (ctx) || !CLASSTYPE_TEMPLATE_INFO (ctx))
- permerror (DECL_SOURCE_LOCATION (decl),
- "%qD is not a static data member of a class template", decl);
- else if (template_header_count > wanted)
+ if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
+ && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl)))
+ {
+ if (cxx_dialect < cxx14)
+ pedwarn (DECL_SOURCE_LOCATION (decl), 0,
+ "variable templates only available with "
+ "-std=c++14 or -std=gnu++14");
+
+ // Namespace-scope variable templates should have a template header.
+ ++wanted;
+ }
+ if (template_header_count > wanted)
{
bool warned = pedwarn (DECL_SOURCE_LOCATION (decl), 0,
"too many template headers for %D (should be %d)",
decl, wanted);
- if (warned && CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))
+ if (warned && CLASS_TYPE_P (ctx)
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))
inform (DECL_SOURCE_LOCATION (decl),
"members of an explicitly specialized class are defined "
"without a template header");
switch (tsk)
{
case tsk_none:
- if (processing_specialization)
+ if (processing_specialization && !VAR_P (decl))
{
specialization = 1;
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
/* Fall through. */
case tsk_expl_spec:
+ if (VAR_P (decl) && TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
+ /* In cases like template<> constexpr bool v = true;
+ We'll give an error in check_template_variable. */
+ break;
+
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
if (ctype)
member_specialization = 1;
/* This case handles bogus declarations like template <>
template <class T> void f<int>(); */
- if (uses_template_parms (declarator))
- error ("function template partial specialization %qD "
- "is not allowed", declarator);
- else
+ 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 ("non-class, non-variable partial specialization %qD "
+ "is not allowed", declarator);
return decl;
+ ok:;
}
if (ctype && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype))
gcc_unreachable ();
}
- if (specialization || member_specialization)
+ if ((specialization || member_specialization)
+ /* This doesn't apply to variable templates. */
+ && (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE
+ || TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE))
{
tree t = TYPE_ARG_TYPES (TREE_TYPE (decl));
for (; t; t = TREE_CHAIN (t))
{
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))))
{
+ // We'll match variable templates in start_decl.
+ if (VAR_P (decl))
+ return decl;
+
/* Find the list of functions in ctype that have the same
name as the declared function. */
tree name = TREE_OPERAND (declarator, 0);
/* If we thought that the DECL was a member function, but it
turns out to be specializing a static member function,
make DECL a static member function as well. */
- if (DECL_STATIC_FUNCTION_P (tmpl)
+ if (DECL_FUNCTION_TEMPLATE_P (tmpl)
+ && DECL_STATIC_FUNCTION_P (tmpl)
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
revert_static_member_fn (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. */
- copy_default_args_to_explicit_spec (decl);
+ if (DECL_FUNCTION_TEMPLATE_P (tmpl))
+ copy_default_args_to_explicit_spec (decl);
/* This specialization has the same protection as the
template it specializes. */
It's just the name of an instantiation. But, it's not
a request for an instantiation, either. */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
+ else if (TREE_CODE (decl) == FUNCTION_DECL)
+ /* A specialization is not necessarily COMDAT. */
+ DECL_COMDAT (decl) = (TREE_PUBLIC (decl)
+ && DECL_DECLARED_INLINE_P (decl));
+ else if (VAR_P (decl))
+ DECL_COMDAT (decl) = false;
/* Register this specialization so that we can find it
again. */
/* A 'structor should already have clones. */
gcc_assert (decl == error_mark_node
+ || variable_template_p (tmpl)
|| !(DECL_CONSTRUCTOR_P (decl)
|| DECL_DESTRUCTOR_P (decl))
|| DECL_CLONED_FUNCTION_P (DECL_CHAIN (decl)));
tree* parameter_packs;
/* Set of AST nodes that have been visited by the traversal. */
- struct pointer_set_t *visited;
+ hash_set<tree> *visited;
};
/* Identifies all of the argument packs that occur in a template
tree parameter_packs = NULL_TREE;
struct find_parameter_pack_data ppd;
ppd.parameter_packs = ¶meter_packs;
- ppd.visited = pointer_set_create ();
+ ppd.visited = new hash_set<tree>;
cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
- pointer_set_destroy (ppd.visited);
+ delete ppd.visited;
return parameter_packs != NULL_TREE;
}
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
/* Determine which parameter packs will be used by the base
class expansion. */
- ppd.visited = pointer_set_create ();
+ ppd.visited = new hash_set<tree>;
ppd.parameter_packs = ¶meter_packs;
cp_walk_tree (&TREE_PURPOSE (arg), &find_parameter_packs_r,
&ppd, ppd.visited);
if (parameter_packs == NULL_TREE)
{
error ("base initializer expansion %<%T%> contains no parameter packs", arg);
- pointer_set_destroy (ppd.visited);
+ delete ppd.visited;
return error_mark_node;
}
}
}
- pointer_set_destroy (ppd.visited);
+ delete ppd.visited;
/* Create the pack expansion type for the base type. */
purpose = cxx_make_type (TYPE_PACK_EXPANSION);
/* Determine which parameter packs will be expanded. */
ppd.parameter_packs = ¶meter_packs;
- ppd.visited = pointer_set_create ();
+ ppd.visited = new hash_set<tree>;
cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, ppd.visited);
- pointer_set_destroy (ppd.visited);
+ delete ppd.visited;
/* Make sure we found some parameter packs. */
if (parameter_packs == NULL_TREE)
t = TREE_TYPE (t);
ppd.parameter_packs = ¶meter_packs;
- ppd.visited = pointer_set_create ();
+ ppd.visited = new hash_set<tree>;
cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
- pointer_set_destroy (ppd.visited);
+ delete ppd.visited;
if (parameter_packs)
{
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);
tree parameter_packs = NULL_TREE;
struct find_parameter_pack_data ppd;
ppd.parameter_packs = ¶meter_packs;
- ppd.visited = pointer_set_create ();
+ ppd.visited = new hash_set<tree>;
fixed_parameter_pack_p_1 (parm, &ppd);
- pointer_set_destroy (ppd.visited);
+ delete ppd.visited;
return parameter_packs;
}
in the template-parameter-list of the definition of a member of a
class template. */
- if (TREE_CODE (CP_DECL_CONTEXT (decl)) == FUNCTION_DECL)
+ if (TREE_CODE (CP_DECL_CONTEXT (decl)) == FUNCTION_DECL
+ || (TREE_CODE (decl) == FUNCTION_DECL && DECL_LOCAL_FUNCTION_P (decl)))
/* You can't have a function template declaration in a local
scope, nor you can you define a member of a class template in a
local scope. */
return true;
- if (TREE_CODE (decl) == TYPE_DECL
- && TREE_TYPE (decl)
- && LAMBDA_TYPE_P (TREE_TYPE (decl)))
+ if ((TREE_CODE (decl) == TYPE_DECL
+ && TREE_TYPE (decl)
+ && LAMBDA_TYPE_P (TREE_TYPE (decl)))
+ || (TREE_CODE (decl) == FUNCTION_DECL
+ && LAMBDA_FUNCTION_P (decl)))
/* A lambda doesn't have an explicit declaration; don't complain
about the parms of the enclosing class. */
return true;
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;
template <typename T> friend void A<T>::f();
is not primary. */
is_primary = false;
+ else if (TREE_CODE (decl) == TYPE_DECL
+ && LAMBDA_TYPE_P (TREE_TYPE (decl)))
+ is_primary = false;
else
is_primary = template_parm_scope_p ();
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;
}
else if (TREE_CODE (decl) == FUNCTION_DECL)
{
+ if (member_template_p)
+ {
+ if (DECL_OVERRIDE_P (decl) || DECL_FINAL_P (decl))
+ error ("member template %qD may not have virt-specifiers", decl);
+ }
if (DECL_DESTRUCTOR_P (decl))
{
/* [temp.mem]
&& TYPE_DECL_ALIAS_P (decl))
/* alias-declaration */
gcc_assert (!DECL_ARTIFICIAL (decl));
+ else if (VAR_P (decl))
+ /* C++14 variable template. */;
else
{
error ("template declaration of %q#D", decl);
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
DECL_TEMPLATE_INFO (decl) = info;
}
+ if (flag_implicit_templates
+ && !is_friend
+ && TREE_PUBLIC (decl)
+ && VAR_OR_FUNCTION_DECL_P (decl))
+ /* Set DECL_COMDAT on template instantiations; if we force
+ them to be emitted by explicit instantiation or -frepo,
+ mark_needed will tell cgraph to do the right thing. */
+ DECL_COMDAT (decl) = true;
+
return DECL_TEMPLATE_RESULT (tmpl);
}
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. */
and check that the resulting function has external linkage. */
static tree
-convert_nontype_argument_function (tree type, tree expr)
+convert_nontype_argument_function (tree type, tree expr,
+ tsubst_flags_t complain)
{
tree fns = expr;
tree fn, fn_no_ptr;
if (TREE_CODE (fn_no_ptr) != FUNCTION_DECL)
{
- error ("%qE is not a valid template argument for type %qT", expr, type);
- if (TYPE_PTR_P (type))
- error ("it must be the address of a function with external linkage");
- else
- error ("it must be the name of a function with external linkage");
+ if (complain & tf_error)
+ {
+ error ("%qE is not a valid template argument for type %qT",
+ expr, type);
+ if (TYPE_PTR_P (type))
+ error ("it must be the address of a function with "
+ "external linkage");
+ else
+ error ("it must be the name of a function with "
+ "external linkage");
+ }
return NULL_TREE;
}
linkage = decl_linkage (fn_no_ptr);
if (cxx_dialect >= cxx11 ? linkage == lk_none : linkage != lk_external)
{
- if (cxx_dialect >= cxx11)
- error ("%qE is not a valid template argument for type %qT "
- "because %qD has no linkage",
- expr, type, fn_no_ptr);
- else
- error ("%qE is not a valid template argument for type %qT "
- "because %qD does not have external linkage",
- expr, type, fn_no_ptr);
+ if (complain & tf_error)
+ {
+ if (cxx_dialect >= cxx11)
+ error ("%qE is not a valid template argument for type %qT "
+ "because %qD has no linkage",
+ expr, type, fn_no_ptr);
+ else
+ error ("%qE is not a valid template argument for type %qT "
+ "because %qD does not have external linkage",
+ expr, type, fn_no_ptr);
+ }
return NULL_TREE;
}
return true;
if (cxx_dialect >= cxx11 && null_member_pointer_value_p (expr))
return true;
+ if (processing_template_decl
+ && TREE_CODE (expr) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (expr, 0)) == OFFSET_REF)
+ return true;
if (complain & tf_error)
{
error ("%qE is not a valid template argument for type %qT",
}
static int
-unify_arity (bool explain_p, int have, int wanted)
+unify_arity (bool explain_p, int have, int wanted, bool least_p = false)
{
if (explain_p)
- inform_n (input_location, wanted,
- " candidate expects %d argument, %d provided",
- " candidate expects %d arguments, %d provided",
- wanted, have);
+ {
+ if (least_p)
+ inform_n (input_location, wanted,
+ " candidate expects at least %d argument, %d provided",
+ " candidate expects at least %d arguments, %d provided",
+ wanted, have);
+ else
+ inform_n (input_location, wanted,
+ " candidate expects %d argument, %d provided",
+ " candidate expects %d arguments, %d provided",
+ wanted, have);
+ }
return 1;
}
}
static int
-unify_too_few_arguments (bool explain_p, int have, int wanted)
+unify_too_few_arguments (bool explain_p, int have, int wanted,
+ bool least_p = false)
{
- return unify_arity (explain_p, have, wanted);
+ return unify_arity (explain_p, have, wanted, least_p);
}
static int
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))
{
if (VAR_P (expr))
{
- error ("%qD is not a valid template argument "
- "because %qD is a variable, not the address of "
- "a variable",
- expr, expr);
+ if (complain & tf_error)
+ error ("%qD is not a valid template argument "
+ "because %qD is a variable, not the address of "
+ "a variable", expr, expr);
return NULL_TREE;
}
if (POINTER_TYPE_P (expr_type))
{
- error ("%qE is not a valid template argument for %qT "
- "because it is not the address of a variable",
- expr, type);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument for %qT "
+ "because it is not the address of a variable",
+ expr, type);
return NULL_TREE;
}
/* Other values, like integer constants, might be valid
? TREE_OPERAND (expr, 0) : expr);
if (!VAR_P (decl))
{
- error ("%qE is not a valid template argument of type %qT "
- "because %qE is not a variable",
- expr, type, decl);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument of type %qT "
+ "because %qE is not a variable", expr, type, decl);
return NULL_TREE;
}
else if (cxx_dialect < cxx11 && !DECL_EXTERNAL_LINKAGE_P (decl))
{
- error ("%qE is not a valid template argument of type %qT "
- "because %qD does not have external linkage",
- expr, type, decl);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument of type %qT "
+ "because %qD does not have external linkage",
+ expr, type, decl);
return NULL_TREE;
}
else if (cxx_dialect >= cxx11 && decl_linkage (decl) == lk_none)
{
- error ("%qE is not a valid template argument of type %qT "
- "because %qD has no linkage",
- expr, type, decl);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument of type %qT "
+ "because %qD has no linkage", expr, type, decl);
return NULL_TREE;
}
}
if (!at_least_as_qualified_p (TREE_TYPE (type), expr_type))
{
- error ("%qE is not a valid template argument for type %qT "
- "because of conflicts in cv-qualification", expr, type);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument for type %qT "
+ "because of conflicts in cv-qualification", expr, type);
return NULL_TREE;
}
if (!real_lvalue_p (expr))
{
- error ("%qE is not a valid template argument for type %qT "
- "because it is not an lvalue", expr, type);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is not an lvalue", expr, type);
return NULL_TREE;
}
expr = TREE_OPERAND (expr, 0);
if (DECL_P (expr))
{
- error ("%q#D is not a valid template argument for type %qT "
- "because a reference variable does not have a constant "
- "address", expr, type);
+ if (complain & tf_error)
+ error ("%q#D is not a valid template argument for type %qT "
+ "because a reference variable does not have a constant "
+ "address", expr, type);
return NULL_TREE;
}
}
if (!DECL_P (expr))
{
- error ("%qE is not a valid template argument for type %qT "
- "because it is not an object with external linkage",
- expr, type);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is not an object with external linkage",
+ expr, type);
return NULL_TREE;
}
if (!DECL_EXTERNAL_LINKAGE_P (expr))
{
- error ("%qE is not a valid template argument for type %qT "
- "because object %qD has not external linkage",
- expr, type, expr);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument for type %qT "
+ "because object %qD has not external linkage",
+ expr, type, expr);
return NULL_TREE;
}
/* Null pointer values are OK in C++11. */
return perform_qualification_conversions (type, expr);
- expr = convert_nontype_argument_function (type, expr);
+ expr = convert_nontype_argument_function (type, expr, complain);
if (!expr || expr == error_mark_node)
return expr;
}
{
if (TREE_CODE (expr) == ADDR_EXPR)
{
- error ("%qE is not a valid template argument for type %qT "
- "because it is a pointer", expr, type);
- inform (input_location, "try using %qE instead", TREE_OPERAND (expr, 0));
+ if (complain & tf_error)
+ {
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is a pointer", expr, type);
+ inform (input_location, "try using %qE instead",
+ TREE_OPERAND (expr, 0));
+ }
return NULL_TREE;
}
- expr = convert_nontype_argument_function (type, expr);
+ expr = convert_nontype_argument_function (type, expr, complain);
if (!expr || expr == error_mark_node)
return expr;
provide a superior diagnostic. */
if (!same_type_p (TREE_TYPE (expr), type))
{
- error ("%qE is not a valid template argument for type %qT "
- "because it is of type %qT", expr, type,
- TREE_TYPE (expr));
- /* If we are just one standard conversion off, explain. */
- if (can_convert_standard (type, TREE_TYPE (expr), complain))
- inform (input_location,
- "standard conversions are not allowed in this context");
+ if (complain & tf_error)
+ {
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is of type %qT", expr, type,
+ TREE_TYPE (expr));
+ /* If we are just one standard conversion off, explain. */
+ if (can_convert_standard (type, TREE_TYPE (expr), complain))
+ inform (input_location,
+ "standard conversions are not allowed in this context");
+ }
return NULL_TREE;
}
}
{
if (expr != nullptr_node)
{
- error ("%qE is not a valid template argument for type %qT "
- "because it is of type %qT", expr, type, TREE_TYPE (expr));
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is of type %qT", expr, type, TREE_TYPE (expr));
return NULL_TREE;
}
return expr;
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)
{
"parameter list for %qD",
i + 1, in_decl);
if (is_type)
- error (" expected a constant of type %qT, got %qT",
- TREE_TYPE (parm),
- (DECL_P (arg) ? DECL_NAME (arg) : orig_arg));
+ inform (input_location,
+ " expected a constant of type %qT, got %qT",
+ TREE_TYPE (parm),
+ (DECL_P (arg) ? DECL_NAME (arg) : orig_arg));
else if (requires_tmpl_type)
- error (" expected a class template, got %qE", orig_arg);
+ inform (input_location,
+ " expected a class template, got %qE", orig_arg);
else
- error (" expected a type, got %qE", orig_arg);
+ inform (input_location,
+ " expected a type, got %qE", orig_arg);
}
}
return error_mark_node;
"parameter list for %qD",
i + 1, in_decl);
if (is_tmpl_type)
- error (" expected a type, got %qT", DECL_NAME (arg));
+ inform (input_location,
+ " expected a type, got %qT", DECL_NAME (arg));
else
- error (" expected a class template, got %qT", orig_arg);
+ inform (input_location,
+ " expected a class template, got %qT", orig_arg);
}
return error_mark_node;
}
error ("type/value mismatch at argument %d in "
"template parameter list for %qD",
i + 1, in_decl);
- error (" expected a template of type %qD, got %qT",
- parm, orig_arg);
+ inform (input_location,
+ " expected a template of type %qD, got %qT",
+ parm, orig_arg);
}
val = error_mark_node;
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));
if (arg_idx - parm_idx < TREE_VEC_LENGTH (packed_args)
&& TREE_VEC_LENGTH (packed_args) > 0)
{
- error ("wrong number of template arguments (%d, should be %d)",
- arg_idx - parm_idx, TREE_VEC_LENGTH (packed_args));
+ if (complain & tf_error)
+ error ("wrong number of template arguments (%d, should be %d)",
+ arg_idx - parm_idx, TREE_VEC_LENGTH (packed_args));
return error_mark_node;
}
int variadic_args_p = 0;
int post_variadic_parms = 0;
+ /* Likewise for parameters with default arguments. */
+ int default_p = 0;
+
if (args == error_mark_node)
return error_mark_node;
nparms = TREE_VEC_LENGTH (parms);
- /* Determine if there are any parameter packs. */
+ /* Determine if there are any parameter packs or default arguments. */
for (parm_idx = 0; parm_idx < nparms; ++parm_idx)
{
- tree tparm = TREE_VALUE (TREE_VEC_ELT (parms, parm_idx));
+ tree parm = TREE_VEC_ELT (parms, parm_idx);
if (variadic_p)
++post_variadic_parms;
- if (template_parameter_pack_p (tparm))
+ if (template_parameter_pack_p (TREE_VALUE (parm)))
++variadic_p;
+ if (TREE_PURPOSE (parm))
+ ++default_p;
}
inner_args = orig_inner_args = INNERMOST_TEMPLATE_ARGS (args);
{
if (complain & tf_error)
{
- if (variadic_p)
+ if (variadic_p || default_p)
{
- nparms -= variadic_p;
+ nparms -= variadic_p + default_p;
error ("wrong number of template arguments "
- "(%d, should be %d or more)", nargs, nparms);
+ "(%d, should be at least %d)", nargs, nparms);
}
else
error ("wrong number of template arguments "
"(%d, should be %d)", nargs, nparms);
if (in_decl)
- error ("provided for %q+D", in_decl);
+ inform (input_location, "provided for %q+D", in_decl);
}
return error_mark_node;
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
if (level)
push_tinst_level (d);
- pt = ggc_alloc_pending_template ();
+ pt = ggc_alloc<pending_template> ();
pt->next = NULL;
pt->tinst = current_tinst_level;
if (last_pending_template)
{
tree templ = NULL_TREE, parmlist;
tree t;
- void **slot;
+ spec_entry **slot;
spec_entry *entry;
spec_entry elt;
hashval_t hash;
templ = TYPE_TI_TEMPLATE (d1);
d1 = DECL_NAME (templ);
}
- else if (TREE_CODE (d1) == TEMPLATE_DECL
- && DECL_TEMPLATE_RESULT (d1)
- && TREE_CODE (DECL_TEMPLATE_RESULT (d1)) == TYPE_DECL)
+ else if (DECL_TYPE_TEMPLATE_P (d1))
{
templ = d1;
d1 = DECL_NAME (templ);
/* 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))
+ {
+ static const char *tags[] = {"abi_tag", "may_alias"};
+
+ for (unsigned ix = 0; ix != 2; ix++)
+ {
+ 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)
+ = tree_cons (TREE_PURPOSE (attributes),
+ TREE_VALUE (attributes),
+ TYPE_ATTRIBUTES (t));
+ }
+ }
+
/* Let's consider the explicit specialization of a member
of a class template specialization that is implicitly instantiated,
e.g.:
SET_TYPE_TEMPLATE_INFO (t, build_template_info (found, arglist));
elt.spec = t;
- slot = htab_find_slot_with_hash (type_specializations,
- &elt, hash, INSERT);
- entry = ggc_alloc_spec_entry ();
+ slot = type_specializations->find_slot_with_hash (&elt, hash, INSERT);
+ entry = ggc_alloc<spec_entry> ();
*entry = elt;
*slot = entry;
TREE_PUBLIC (type_decl) = 1;
determine_visibility (type_decl);
+ inherit_targ_abi_tags (t);
+
return t;
}
}
timevar_pop (TV_TEMPLATE_INST);
return ret;
}
+
+/* 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 = 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
{
/* True when we should also visit template parameters that occur in
non-deduced contexts. */
bool include_nondeduced_p;
- struct pointer_set_t *visited;
+ hash_set<tree> *visited;
};
/* Called from for_each_template_parm via walk_tree. */
static int
for_each_template_parm (tree t, tree_fn_t fn, void* data,
- struct pointer_set_t *visited,
+ hash_set<tree> *visited,
bool include_nondeduced_p)
{
struct pair_fn_data pfd;
if (visited)
pfd.visited = visited;
else
- pfd.visited = pointer_set_create ();
+ pfd.visited = new hash_set<tree>;
result = cp_walk_tree (&t,
for_each_template_parm_r,
&pfd,
/* Clean up. */
if (!visited)
{
- pointer_set_destroy (pfd.visited);
+ delete pfd.visited;
pfd.visited = 0;
}
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)
/* We're starting to instantiate D; record the template instantiation context
for diagnostics and to restore it later. */
-int
+bool
push_tinst_level (tree d)
+{
+ return push_tinst_level_loc (d, input_location);
+}
+
+/* We're starting to instantiate D; record the template instantiation context
+ at LOC for diagnostics and to restore it later. */
+
+bool
+push_tinst_level_loc (tree d, location_t loc)
{
struct tinst_level *new_level;
if (tinst_depth >= max_tinst_depth)
{
- last_error_tinst_level = current_tinst_level;
- if (TREE_CODE (d) == TREE_LIST)
- error ("template instantiation depth exceeds maximum of %d (use "
- "-ftemplate-depth= to increase the maximum) substituting %qS",
- max_tinst_depth, d);
- else
- error ("template instantiation depth exceeds maximum of %d (use "
- "-ftemplate-depth= to increase the maximum) instantiating %qD",
- max_tinst_depth, d);
-
- print_instantiation_context ();
-
- return 0;
+ fatal_error (input_location,
+ "template instantiation depth exceeds maximum of %d"
+ " (use -ftemplate-depth= to increase the maximum)",
+ max_tinst_depth);
+ return false;
}
/* If the current instantiation caused problems, don't let it instantiate
anything else. Do allow deduction substitution and decls usable in
constant expressions. */
if (limit_bad_template_recursion (d))
- return 0;
+ return false;
- new_level = ggc_alloc_tinst_level ();
+ new_level = ggc_alloc<tinst_level> ();
new_level->decl = d;
- new_level->locus = input_location;
+ new_level->locus = loc;
new_level->errors = errorcount+sorrycount;
new_level->in_system_header_p = in_system_header_at (input_location);
new_level->next = current_tinst_level;
if (GATHER_STATISTICS && (tinst_depth > depth_reached))
depth_reached = tinst_depth;
- return 1;
+ return true;
}
/* We're done instantiating this template; return to the instantiation
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);
&& DECL_OMP_DECLARE_REDUCTION_P (r))
cp_check_omp_declare_reduction (r);
}
+ else if (DECL_CLASS_TEMPLATE_P (t)
+ && LAMBDA_TYPE_P (TREE_TYPE (t)))
+ /* A closure type for a lambda in a default argument for a
+ member template. Ignore it; it will be instantiated with
+ the default argument. */;
else
{
/* Build new TYPE_FIELDS. */
}
}
+ 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
bool unsubstituted_packs = false;
int i, len = -1;
tree result;
- struct pointer_map_t *saved_local_specializations = NULL;
+ hash_map<tree, tree> *saved_local_specializations = NULL;
bool need_local_specializations = false;
int levels;
}
}
+ /* If the expansion is just T..., return the matching argument pack. */
+ if (!unsubstituted_packs
+ && TREE_PURPOSE (packs) == pattern)
+ {
+ tree args = ARGUMENT_PACK_ARGS (TREE_VALUE (packs));
+ if (TREE_CODE (t) == TYPE_PACK_EXPANSION
+ || pack_expansion_args_count (args))
+ return args;
+ /* Otherwise use the normal path so we get convert_from_reference. */
+ }
+
/* We cannot expand this expansion expression, because we don't have
all of the argument packs we need. */
if (use_pack_expansion_extra_args_p (packs, len, unsubstituted_packs))
case of recursive unification) might have bindings that we don't
want to use or alter. */
saved_local_specializations = local_specializations;
- local_specializations = pointer_map_create ();
+ local_specializations = new hash_map<tree, tree>;
}
/* For each argument in each argument pack, substitute into the
if (need_local_specializations)
{
- pointer_map_destroy (local_specializations);
+ delete local_specializations;
local_specializations = saved_local_specializations;
}
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)
+ 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)),
/* Set up DECL_TEMPLATE_INFO so that we can get at the
NSDMI in perform_member_init. Still set DECL_INITIAL
so that we know there is one. */
- DECL_INITIAL (r) = void_zero_node;
+ DECL_INITIAL (r) = void_node;
gcc_assert (DECL_LANG_SPECIFIC (r) == NULL);
retrofit_lang_decl (r);
DECL_TEMPLATE_INFO (r) = build_template_info (t, args);
{
/* 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; }
same_type_p, because DECL_CONTEXT is always
canonical... */
if (ctx == DECL_CONTEXT (t)
- && (TREE_CODE (t) != TYPE_DECL
- /* ... unless T is a member template; in which
- case our caller can be willing to create a
- specialization of that template represented
- by T. */
- || !(DECL_TI_TEMPLATE (t)
- && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (t)))))
+ /* ... unless T is a member template; in which
+ case our caller can be willing to create a
+ specialization of that template represented
+ by T. */
+ && !(DECL_TI_TEMPLATE (t)
+ && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (t))))
spec = t;
}
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 (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);
tree in_decl)
{
tree return_type;
- tree arg_types;
+ tree arg_types = NULL_TREE;
tree fntype;
/* The TYPE_CONTEXT is not used for function/method types. */
gcc_assert (TYPE_CONTEXT (t) == NULL_TREE);
- /* Substitute the return type. */
- return_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
- if (return_type == error_mark_node)
- return error_mark_node;
- /* DR 486 clarifies that creation of a function type with an
- invalid return type is a deduction failure. */
- if (TREE_CODE (return_type) == ARRAY_TYPE
- || TREE_CODE (return_type) == FUNCTION_TYPE)
+ /* DR 1227: Mixing immediate and non-immediate contexts in deduction
+ failure. */
+ bool late_return_type_p = TYPE_HAS_LATE_RETURN_TYPE (t);
+
+ if (late_return_type_p)
{
- if (complain & tf_error)
+ /* Substitute the argument types. */
+ arg_types = tsubst_arg_types (TYPE_ARG_TYPES (t), args, NULL_TREE,
+ complain, in_decl);
+ if (arg_types == error_mark_node)
+ return error_mark_node;
+
+ tree save_ccp = current_class_ptr;
+ tree save_ccr = current_class_ref;
+ tree this_type = (TREE_CODE (t) == METHOD_TYPE
+ ? TREE_TYPE (TREE_VALUE (arg_types)) : NULL_TREE);
+ bool do_inject = this_type && CLASS_TYPE_P (this_type);
+ if (do_inject)
{
- if (TREE_CODE (return_type) == ARRAY_TYPE)
+ /* DR 1207: 'this' is in scope in the trailing return type. */
+ inject_this_parameter (this_type, cp_type_quals (this_type));
+ }
+
+ /* Substitute the return type. */
+ return_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+
+ if (do_inject)
+ {
+ current_class_ptr = save_ccp;
+ current_class_ref = save_ccr;
+ }
+ }
+ else
+ /* Substitute the return type. */
+ return_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+
+ if (return_type == error_mark_node)
+ return error_mark_node;
+ /* DR 486 clarifies that creation of a function type with an
+ invalid return type is a deduction failure. */
+ if (TREE_CODE (return_type) == ARRAY_TYPE
+ || TREE_CODE (return_type) == FUNCTION_TYPE)
+ {
+ if (complain & tf_error)
+ {
+ if (TREE_CODE (return_type) == ARRAY_TYPE)
error ("function returning an array");
else
error ("function returning a function");
if (abstract_virtuals_error_sfinae (ACU_RETURN, return_type, complain))
return error_mark_node;
- /* Substitute the argument types. */
- arg_types = tsubst_arg_types (TYPE_ARG_TYPES (t), args, NULL_TREE,
- complain, in_decl);
- if (arg_types == error_mark_node)
- return error_mark_node;
+ if (!late_return_type_p)
+ {
+ /* Substitute the argument types. */
+ arg_types = tsubst_arg_types (TYPE_ARG_TYPES (t), args, NULL_TREE,
+ complain, in_decl);
+ if (arg_types == error_mark_node)
+ return error_mark_node;
+ }
/* Construct a new type node and return it. */
if (TREE_CODE (t) == FUNCTION_TYPE)
}
fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
+ if (late_return_type_p)
+ TYPE_HAS_LATE_RETURN_TYPE (fntype) = 1;
+
return fntype;
}
gen_elem_of_pack_expansion_instantiation will
build the resulting pack expansion from it. */
if (PACK_EXPANSION_P (arg))
- arg = PACK_EXPANSION_PATTERN (arg);
+ {
+ /* Make sure we aren't throwing away arg info. */
+ gcc_assert (!PACK_EXPANSION_EXTRA_ARGS (arg));
+ arg = PACK_EXPANSION_PATTERN (arg);
+ }
}
}
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 >= cxx1y
- && !(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);
if (type == TREE_TYPE (t) && domain == TYPE_DOMAIN (t))
return t;
- /* These checks should match the ones in grokdeclarator.
+ /* These checks should match the ones in create_array_type_for_decl.
[temp.deduct]
an abstract class type. */
if (VOID_TYPE_P (type)
|| TREE_CODE (type) == FUNCTION_TYPE
+ || (TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_DOMAIN (type) == NULL_TREE)
|| TREE_CODE (type) == REFERENCE_TYPE)
{
if (complain & tf_error)
return cp_build_qualified_type_real (type,
cp_type_quals (t)
| cp_type_quals (type),
- complain);
+ complain | tf_ignore_bad_quals);
}
case UNDERLYING_TYPE:
}
break;
+ case VOID_CST:
case INTEGER_CST:
case REAL_CST:
case STRING_CST:
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)
return expr;
}
+/* tsubst the initializer for a VAR_DECL. INIT is the unsubstituted
+ initializer, DECL is the substituted VAR_DECL. Other arguments are as
+ for tsubst. */
+
+static tree
+tsubst_init (tree init, tree decl, tree args,
+ tsubst_flags_t complain, tree in_decl)
+{
+ if (!init)
+ return NULL_TREE;
+
+ init = tsubst_expr (init, args, complain, in_decl, false);
+
+ if (!init)
+ {
+ /* If we had an initializer but it
+ instantiated to nothing,
+ value-initialize the object. This will
+ only occur when the initializer was a
+ pack expansion where the parameter packs
+ used in that expansion were of length
+ zero. */
+ init = build_value_init (TREE_TYPE (decl),
+ complain);
+ if (TREE_CODE (init) == AGGR_INIT_EXPR)
+ init = get_target_expr_sfinae (init, complain);
+ }
+
+ return init;
+}
+
/* Like tsubst, but deals with expressions. This function just replaces
template parms; to finish processing the resultant expression, use
tsubst_copy_and_build or tsubst_expr. */
{
/* We get here for a use of 'this' in an NSDMI. */
if (DECL_NAME (t) == this_identifier
- && at_function_scope_p ()
+ && current_function_decl
&& DECL_CONSTRUCTOR_P (current_function_decl))
return current_class_ptr;
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:
r = retrieve_local_specialization (t);
if (r == NULL_TREE)
{
- if (DECL_ANON_UNION_VAR_P (t))
+ /* First try name lookup to find the instantiation. */
+ r = lookup_name (DECL_NAME (t));
+ if (r)
{
- /* Just use name lookup to find a member alias for an
- anonymous union, but then add it to the hash table. */
- r = lookup_name (DECL_NAME (t));
- gcc_assert (DECL_ANON_UNION_VAR_P (r));
- register_local_specialization (r, t);
+ /* Make sure that the one we found is the one we want. */
+ tree ctx = tsubst (DECL_CONTEXT (t), args,
+ complain, in_decl);
+ if (ctx != DECL_CONTEXT (r))
+ r = NULL_TREE;
}
+
+ if (r)
+ /* OK */;
else
{
/* This can happen for a variable used in a
local static or constant. Building a new VAR_DECL
should be OK in all those cases. */
r = tsubst_decl (t, args, complain);
- if (decl_constant_var_p (r))
- /* A use of a local constant must decay to its value. */
- return integral_constant_value (r);
+ if (decl_maybe_constant_var_p (r))
+ {
+ /* We can't call cp_finish_decl, so handle the
+ initializer by hand. */
+ tree init = tsubst_init (DECL_INITIAL (t), r, args,
+ complain, in_decl);
+ if (!processing_template_decl)
+ init = maybe_constant_init (init);
+ if (processing_template_decl
+ ? potential_constant_expression (init)
+ : reduced_constant_expression_p (init))
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)
+ = TREE_CONSTANT (r) = true;
+ DECL_INITIAL (r) = init;
+ }
gcc_assert (cp_unevaluated_operand || TREE_STATIC (r)
+ || decl_constant_var_p (r)
|| errorcount || sorrycount);
- return r;
+ if (!processing_template_decl)
+ {
+ if (TREE_STATIC (r))
+ rest_of_decl_compilation (r, toplevel_bindings_p (),
+ at_eof);
+ else
+ r = process_outer_var_ref (r, complain);
+ }
}
+ /* Remember this for subsequent uses. */
+ if (local_specializations)
+ register_local_specialization (r, t);
}
}
else
r = t;
- mark_used (r);
+ if (!mark_used (r, complain) && !(complain & tf_error))
+ return error_mark_node;
return r;
case NAMESPACE_DECL:
case IMPLICIT_CONV_EXPR:
case CONVERT_EXPR:
case NOP_EXPR:
- return build1
- (code, tsubst (TREE_TYPE (t), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl));
+ {
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ return build1 (code, type, op0);
+ }
case SIZEOF_EXPR:
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
case REALPART_EXPR:
case IMAGPART_EXPR:
case PAREN_EXPR:
- return build1
- (code, tsubst (TREE_TYPE (t), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl));
+ {
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ return build1 (code, type, op0);
+ }
case COMPONENT_REF:
{
case PREINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
- return build_nt
- (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
+ {
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+ return build_nt (code, op0, op1);
+ }
case SCOPE_REF:
- return build_qualified_name (/*type=*/NULL_TREE,
- tsubst_copy (TREE_OPERAND (t, 0),
- args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1),
- args, complain, in_decl),
- QUALIFIED_NAME_IS_TEMPLATE (t));
+ {
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+ return build_qualified_name (/*type=*/NULL_TREE, op0, op1,
+ QUALIFIED_NAME_IS_TEMPLATE (t));
+ }
case ARRAY_REF:
- return build_nt
- (ARRAY_REF,
- tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
- NULL_TREE, NULL_TREE);
+ {
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+ return build_nt (ARRAY_REF, op0, op1, NULL_TREE, NULL_TREE);
+ }
case CALL_EXPR:
{
case PSEUDO_DTOR_EXPR:
case VEC_PERM_EXPR:
{
- r = build_nt
- (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl));
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+ tree op2 = tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl);
+ r = build_nt (code, op0, op1, op2);
TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
return r;
}
case NEW_EXPR:
{
- r = build_nt
- (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl));
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+ tree op2 = tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl);
+ r = build_nt (code, op0, op1, op2);
NEW_EXPR_USE_GLOBAL (r) = NEW_EXPR_USE_GLOBAL (t);
return r;
}
case DELETE_EXPR:
{
- r = build_nt
- (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+ r = build_nt (code, op0, op1);
DELETE_EXPR_USE_GLOBAL (r) = DELETE_EXPR_USE_GLOBAL (t);
DELETE_EXPR_USE_VEC (r) = DELETE_EXPR_USE_VEC (t);
return r;
gcc_unreachable ();
case VA_ARG_EXPR:
- return build_x_va_arg (EXPR_LOCATION (t),
- tsubst_copy (TREE_OPERAND (t, 0), args, complain,
- in_decl),
- tsubst (TREE_TYPE (t), args, complain, in_decl));
+ {
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ return build_x_va_arg (EXPR_LOCATION (t), op0, type);
+ }
case CLEANUP_POINT_EXPR:
/* We shouldn't have built any of these during initial template
gcc_unreachable ();
case OFFSET_REF:
- r = build2
- (code, tsubst (TREE_TYPE (t), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
- PTRMEM_OK_P (r) = PTRMEM_OK_P (t);
- mark_used (TREE_OPERAND (r, 1));
- return r;
+ {
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_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);
+ if (!mark_used (TREE_OPERAND (r, 1), complain)
+ && !(complain & tf_error))
+ return error_mark_node;
+ return r;
+ }
case EXPR_PACK_EXPANSION:
error ("invalid use of pack expansion expression");
error ("use %<...%> to expand argument pack");
return error_mark_node;
+ case VOID_CST:
+ gcc_checking_assert (t == void_node && VOID_TYPE_P (TREE_TYPE (t)));
+ return t;
+
case INTEGER_CST:
case REAL_CST:
case STRING_CST:
}
}
+/* 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:
cond = RECUR (TREE_VEC_ELT (OMP_FOR_COND (t), i));
incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i);
if (TREE_CODE (incr) == MODIFY_EXPR)
- incr = build_x_modify_expr (EXPR_LOCATION (incr),
- RECUR (TREE_OPERAND (incr, 0)), NOP_EXPR,
- RECUR (TREE_OPERAND (incr, 1)),
- complain);
+ {
+ tree lhs = RECUR (TREE_OPERAND (incr, 0));
+ tree rhs = RECUR (TREE_OPERAND (incr, 1));
+ incr = build_x_modify_expr (EXPR_LOCATION (incr), lhs,
+ NOP_EXPR, rhs, complain);
+ }
else
incr = RECUR (incr);
TREE_VEC_ELT (declv, i) = decl;
}
cond = TREE_VEC_ELT (OMP_FOR_COND (t), i);
if (COMPARISON_CLASS_P (cond))
- cond = build2 (TREE_CODE (cond), boolean_type_node,
- RECUR (TREE_OPERAND (cond, 0)),
- RECUR (TREE_OPERAND (cond, 1)));
+ {
+ tree op0 = RECUR (TREE_OPERAND (cond, 0));
+ tree op1 = RECUR (TREE_OPERAND (cond, 1));
+ cond = build2 (TREE_CODE (cond), boolean_type_node, op0, op1);
+ }
else
cond = RECUR (cond);
incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i);
|| TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR)
{
tree rhs = TREE_OPERAND (incr, 1);
- incr = build2 (MODIFY_EXPR, TREE_TYPE (decl),
- RECUR (TREE_OPERAND (incr, 0)),
+ tree lhs = RECUR (TREE_OPERAND (incr, 0));
+ tree rhs0 = RECUR (TREE_OPERAND (rhs, 0));
+ tree rhs1 = RECUR (TREE_OPERAND (rhs, 1));
+ incr = build2 (MODIFY_EXPR, TREE_TYPE (decl), lhs,
build2 (TREE_CODE (rhs), TREE_TYPE (decl),
- RECUR (TREE_OPERAND (rhs, 0)),
- RECUR (TREE_OPERAND (rhs, 1))));
+ rhs0, rhs1));
}
else
incr = RECUR (incr);
|| (TREE_CODE (TREE_OPERAND (incr, 2)) == MINUS_EXPR)))
{
tree rhs = TREE_OPERAND (incr, 2);
- incr = build2 (MODIFY_EXPR, TREE_TYPE (decl),
- RECUR (TREE_OPERAND (incr, 0)),
+ tree lhs = RECUR (TREE_OPERAND (incr, 0));
+ tree rhs0 = RECUR (TREE_OPERAND (rhs, 0));
+ tree rhs1 = RECUR (TREE_OPERAND (rhs, 1));
+ incr = build2 (MODIFY_EXPR, TREE_TYPE (decl), lhs,
build2 (TREE_CODE (rhs), TREE_TYPE (decl),
- RECUR (TREE_OPERAND (rhs, 0)),
- RECUR (TREE_OPERAND (rhs, 1))));
+ rhs0, rhs1));
}
else
incr = RECUR (incr);
init = cp_fname_init (name, &TREE_TYPE (decl));
}
else
- {
- tree t = RECUR (init);
-
- if (init && !t)
- {
- /* If we had an initializer but it
- instantiated to nothing,
- value-initialize the object. This will
- only occur when the initializer was a
- pack expansion where the parameter packs
- used in that expansion were of length
- zero. */
- init = build_value_init (TREE_TYPE (decl),
- complain);
- if (TREE_CODE (init) == AGGR_INIT_EXPR)
- init = get_target_expr_sfinae (init, complain);
- }
- else
- init = t;
- }
+ init = tsubst_init (init, decl, args, complain, in_decl);
if (VAR_P (decl))
const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P
break;
case CASE_LABEL_EXPR:
- finish_case_label (EXPR_LOCATION (t),
- RECUR (CASE_LOW (t)),
- RECUR (CASE_HIGH (t)));
+ {
+ tree low = RECUR (CASE_LOW (t));
+ tree high = RECUR (CASE_HIGH (t));
+ finish_case_label (EXPR_LOCATION (t), low, high);
+ }
break;
case LABEL_EXPR:
break;
case ASM_EXPR:
- tmp = finish_asm_stmt
- (ASM_VOLATILE_P (t),
- RECUR (ASM_STRING (t)),
- tsubst_copy_asm_operands (ASM_OUTPUTS (t), args, complain, in_decl),
- tsubst_copy_asm_operands (ASM_INPUTS (t), args, complain, in_decl),
- tsubst_copy_asm_operands (ASM_CLOBBERS (t), args, complain, in_decl),
- tsubst_copy_asm_operands (ASM_LABELS (t), args, complain, in_decl));
{
+ tree string = RECUR (ASM_STRING (t));
+ tree outputs = tsubst_copy_asm_operands (ASM_OUTPUTS (t), args,
+ complain, in_decl);
+ tree inputs = tsubst_copy_asm_operands (ASM_INPUTS (t), args,
+ complain, in_decl);
+ tree clobbers = tsubst_copy_asm_operands (ASM_CLOBBERS (t), args,
+ complain, in_decl);
+ tree labels = tsubst_copy_asm_operands (ASM_LABELS (t), args,
+ complain, in_decl);
+ tmp = finish_asm_stmt (ASM_VOLATILE_P (t), string, outputs, inputs,
+ clobbers, labels);
tree asm_expr = tmp;
if (TREE_CODE (asm_expr) == CLEANUP_POINT_EXPR)
asm_expr = TREE_OPERAND (asm_expr, 0);
case OMP_FOR:
case OMP_SIMD:
case CILK_SIMD:
+ case CILK_FOR:
case OMP_DISTRIBUTE:
{
tree clauses, body, pre_body;
case OMP_SECTIONS:
case OMP_SINGLE:
case OMP_TEAMS:
- case OMP_TARGET_DATA:
- case OMP_TARGET:
tmp = tsubst_omp_clauses (OMP_CLAUSES (t), false,
args, complain, in_decl);
stmt = push_stmt_list ();
add_stmt (t);
break;
+ case OMP_TARGET_DATA:
+ case OMP_TARGET:
+ tmp = tsubst_omp_clauses (OMP_CLAUSES (t), false,
+ args, complain, in_decl);
+ keep_next_level (true);
+ stmt = begin_omp_structured_block ();
+
+ RECUR (OMP_BODY (t));
+ stmt = finish_omp_structured_block (stmt);
+
+ t = copy_node (t);
+ OMP_BODY (t) = stmt;
+ OMP_CLAUSES (t) = tmp;
+ add_stmt (t);
+ break;
+
case OMP_TARGET_UPDATE:
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;
break;
case MUST_NOT_THROW_EXPR:
- RETURN (build_must_not_throw_expr (RECUR (TREE_OPERAND (t, 0)),
- RECUR (MUST_NOT_THROW_COND (t))));
+ {
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ tree cond = RECUR (MUST_NOT_THROW_COND (t));
+ RETURN (build_must_not_throw_expr (op0, cond));
+ }
case EXPR_PACK_EXPANSION:
error ("invalid use of pack expansion expression");
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)". */
}
case NOP_EXPR:
- RETURN (build_nop
- (tsubst (TREE_TYPE (t), args, complain, in_decl),
- RECUR (TREE_OPERAND (t, 0))));
+ {
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ RETURN (build_nop (type, op0));
+ }
case IMPLICIT_CONV_EXPR:
{
}
case CONVERT_EXPR:
- RETURN (build1
- (CONVERT_EXPR,
- tsubst (TREE_TYPE (t), args, complain, in_decl),
- RECUR (TREE_OPERAND (t, 0))));
+ {
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ RETURN (build1 (CONVERT_EXPR, type, op0));
+ }
case CAST_EXPR:
case REINTERPRET_CAST_EXPR:
case REALPART_EXPR:
case IMAGPART_EXPR:
RETURN (build_x_unary_op (input_location, TREE_CODE (t),
- RECUR (TREE_OPERAND (t, 0)),
+ RECUR (TREE_OPERAND (t, 0)),
complain|decltype_flag));
case FIX_TRUNC_EXPR:
RETURN (cp_build_unary_op (FIX_TRUNC_EXPR, RECUR (TREE_OPERAND (t, 0)),
- 0, complain));
+ 0, complain));
case ADDR_EXPR:
op1 = TREE_OPERAND (t, 0);
{
warning_sentinel s1(warn_type_limits);
warning_sentinel s2(warn_div_by_zero);
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ tree op1 = RECUR (TREE_OPERAND (t, 1));
tree r = build_x_binary_op
(input_location, TREE_CODE (t),
- RECUR (TREE_OPERAND (t, 0)),
+ op0,
(TREE_NO_WARNING (TREE_OPERAND (t, 0))
? ERROR_MARK
: TREE_CODE (TREE_OPERAND (t, 0))),
- RECUR (TREE_OPERAND (t, 1)),
+ op1,
(TREE_NO_WARNING (TREE_OPERAND (t, 1))
? ERROR_MARK
: TREE_CODE (TREE_OPERAND (t, 1))),
}
case POINTER_PLUS_EXPR:
- return fold_build_pointer_plus (RECUR (TREE_OPERAND (t, 0)),
- RECUR (TREE_OPERAND (t, 1)));
+ {
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ tree op1 = RECUR (TREE_OPERAND (t, 1));
+ return fold_build_pointer_plus (op0, op1);
+ }
case SCOPE_REF:
RETURN (tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
op1 = TREE_OPERAND (t, 0);
++cp_unevaluated_operand;
++c_inhibit_evaluation_warnings;
+ ++cp_noexcept_operand;
op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
/*function_p=*/false,
/*integral_constant_expression_p=*/false);
--cp_unevaluated_operand;
--c_inhibit_evaluation_warnings;
+ --cp_noexcept_operand;
RETURN (finish_noexcept_expr (op1, complain));
case MODOP_EXPR:
{
warning_sentinel s(warn_div_by_zero);
+ tree lhs = RECUR (TREE_OPERAND (t, 0));
+ tree rhs = RECUR (TREE_OPERAND (t, 2));
tree r = build_x_modify_expr
- (EXPR_LOCATION (t),
- RECUR (TREE_OPERAND (t, 0)),
- TREE_CODE (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2)),
+ (EXPR_LOCATION (t), lhs, TREE_CODE (TREE_OPERAND (t, 1)), rhs,
complain|decltype_flag);
/* TREE_NO_WARNING must be set if either the expression was
parenthesized or it uses an operator such as >>= rather
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:
else
{
init_vec = make_tree_vector ();
- if (init == void_zero_node)
+ if (init == void_node)
gcc_assert (init_vec != NULL);
else
{
}
}
- ret = build_new (&placement_vec,
- tsubst (TREE_OPERAND (t, 1), args, complain, in_decl),
- RECUR (TREE_OPERAND (t, 2)),
- &init_vec,
+ tree op1 = tsubst (TREE_OPERAND (t, 1), args, complain, in_decl);
+ tree op2 = RECUR (TREE_OPERAND (t, 2));
+ ret = build_new (&placement_vec, op1, op2, &init_vec,
NEW_EXPR_USE_GLOBAL (t),
complain);
}
case DELETE_EXPR:
- RETURN (delete_sanity
- (RECUR (TREE_OPERAND (t, 0)),
- RECUR (TREE_OPERAND (t, 1)),
- DELETE_EXPR_USE_VEC (t),
- DELETE_EXPR_USE_GLOBAL (t),
- complain));
+ {
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ tree op1 = RECUR (TREE_OPERAND (t, 1));
+ RETURN (delete_sanity (op0, op1,
+ DELETE_EXPR_USE_VEC (t),
+ DELETE_EXPR_USE_GLOBAL (t),
+ complain));
+ }
case COMPOUND_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
{
}
case PSEUDO_DTOR_EXPR:
- RETURN (finish_pseudo_destructor_expr
- (RECUR (TREE_OPERAND (t, 0)),
- RECUR (TREE_OPERAND (t, 1)),
- tsubst (TREE_OPERAND (t, 2), args, complain, in_decl),
- input_location));
+ {
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ tree op1 = RECUR (TREE_OPERAND (t, 1));
+ tree op2 = tsubst (TREE_OPERAND (t, 2), args, complain, in_decl);
+ RETURN (finish_pseudo_destructor_expr (op0, op1, op2,
+ input_location));
+ }
case TREE_LIST:
{
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))
+ && 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
}
case VA_ARG_EXPR:
- RETURN (build_x_va_arg (EXPR_LOCATION (t),
- RECUR (TREE_OPERAND (t, 0)),
- tsubst (TREE_TYPE (t), args, complain, in_decl)));
+ {
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ RETURN (build_x_va_arg (EXPR_LOCATION (t), op0, type));
+ }
case OFFSETOF_EXPR:
- RETURN (finish_offsetof (RECUR (TREE_OPERAND (t, 0))));
+ RETURN (finish_offsetof (RECUR (TREE_OPERAND (t, 0)),
+ EXPR_LOCATION (t)));
case TRAIT_EXPR:
{
complain, in_decl);
tree type2 = TRAIT_EXPR_TYPE2 (t);
- if (type2)
+ if (type2 && TREE_CODE (type2) == TREE_LIST)
+ type2 = RECUR (type2);
+ else if (type2)
type2 = tsubst (type2, args, complain, in_decl);
RETURN (finish_trait_expr (TRAIT_EXPR_KIND (t), type1, type2));
cur_stmt_expr = old_stmt_expr;
/* If the resulting list of expression statement is empty,
- fold it further into void_zero_node. */
+ fold it further into void_node. */
if (empty_expr_stmt_p (stmt_expr))
- stmt_expr = void_zero_node;
+ stmt_expr = void_node;
RETURN (stmt_expr);
}
RETURN (finish_parenthesized_expr (RECUR (TREE_OPERAND (t, 0))));
case VEC_PERM_EXPR:
- RETURN (build_x_vec_perm_expr (input_location,
- RECUR (TREE_OPERAND (t, 0)),
- RECUR (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2)),
- complain));
+ {
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ tree op1 = RECUR (TREE_OPERAND (t, 1));
+ tree op2 = RECUR (TREE_OPERAND (t, 2));
+ RETURN (build_x_vec_perm_expr (input_location, op0, op1, op2,
+ complain));
+ }
default:
/* Handle Objective-C++ constructs, if appropriate. */
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 ();
continue;
for (packs = PACK_EXPANSION_PARAMETER_PACKS (type);
packs; packs = TREE_CHAIN (packs))
- if (TREE_VALUE (packs) == parm)
+ if (template_args_equal (TREE_VALUE (packs), parm))
{
/* The template parameter pack is used in a function parameter
pack. If this is the end of the parameter list, the
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)
maybe_adjust_types_for_deduction (strict, &parm, &arg, arg_expr);
}
else
- gcc_assert ((TYPE_P (parm) || TREE_CODE (parm) == TEMPLATE_DECL)
- == (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL));
+ if ((TYPE_P (parm) || TREE_CODE (parm) == TEMPLATE_DECL)
+ != (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL))
+ return unify_template_argument_mismatch (explain_p, parm, arg);
/* For deduction from an init-list we need the actual list. */
if (arg_expr && BRACE_ENCLOSED_INITIALIZER_P (arg_expr))
++ia;
if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
- flags, explain_p))
+ explain_p))
return 1;
}
are present, and the parm list isn't variadic. */
if (ia < nargs && parms == void_list_node)
return unify_too_many_arguments (explain_p, nargs, ia);
- /* Fail if parms are left and they don't have default values. */
+ /* Fail if parms are left and they don't have default values and
+ they aren't all deduced as empty packs (c++/57397). This is
+ consistent with sufficient_parms_p. */
if (parms && parms != void_list_node
&& TREE_PURPOSE (parms) == NULL_TREE)
{
unsigned int count = nargs;
tree p = parms;
- while (p && p != void_list_node)
+ bool type_pack_p;
+ do
{
- count++;
+ type_pack_p = TREE_CODE (TREE_VALUE (p)) == TYPE_PACK_EXPANSION;
+ if (!type_pack_p)
+ count++;
p = TREE_CHAIN (p);
}
- return unify_too_few_arguments (explain_p, ia, count);
+ while (p && p != void_list_node);
+ if (count != nargs)
+ return unify_too_few_arguments (explain_p, ia, count,
+ type_pack_p);
}
if (!subr)
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))
int i = TREE_VEC_LENGTH (targs);
for (; i--; )
if (TREE_VEC_ELT (tempargs, i))
- TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (tempargs, i);
+ {
+ tree old = TREE_VEC_ELT (targs, i);
+ tree new_ = TREE_VEC_ELT (tempargs, i);
+ if (new_ && old && ARGUMENT_PACK_P (old)
+ && ARGUMENT_PACK_EXPLICIT_ARGS (old))
+ /* Don't forget explicit template arguments in a pack. */
+ ARGUMENT_PACK_EXPLICIT_ARGS (new_)
+ = ARGUMENT_PACK_EXPLICIT_ARGS (old);
+ TREE_VEC_ELT (targs, i) = new_;
+ }
}
if (good)
return true;
/* 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);
TYPE_PTRMEMFUNC_FN_TYPE (arg),
strict, explain_p);
}
+ else if (TYPE_PTRMEMFUNC_P (arg))
+ return unify_type_mismatch (explain_p, parm, arg);
if (CLASSTYPE_TEMPLATE_INFO (parm))
{
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);
error ("explicit instantiation of non-template %q#D", decl);
return;
}
- else if (VAR_P (decl))
+
+ bool var_templ = (DECL_TEMPLATE_INFO (decl)
+ && variable_template_p (DECL_TI_TEMPLATE (decl)));
+
+ if (VAR_P (decl) && !var_templ)
{
/* There is an asymmetry here in the way VAR_DECLs and
FUNCTION_DECLs are handled by grokdeclarator. In the case of
return;
}
}
- else if (TREE_CODE (decl) != FUNCTION_DECL)
+ else if (TREE_CODE (decl) != FUNCTION_DECL && !var_templ)
{
error ("explicit instantiation of %q#D", decl);
return;
cannot restructure the loop to just keep going until we find
a template with a definition, since that might go too far if
a specialization was declared, but not defined. */
- gcc_assert (!VAR_P (decl)
- || DECL_IN_AGGR_P (DECL_TEMPLATE_RESULT (tmpl)));
/* Fetch the more general template. */
tmpl = DECL_TI_TEMPLATE (tmpl);
tree ns;
tree init;
bool const_init = false;
+ bool enter_context = DECL_CLASS_SCOPE_P (d);
ns = decl_namespace_context (d);
push_nested_namespace (ns);
- push_nested_class (DECL_CONTEXT (d));
+ if (enter_context)
+ push_nested_class (DECL_CONTEXT (d));
init = tsubst_expr (DECL_INITIAL (code_pattern),
args,
tf_warning_or_error, NULL_TREE,
/*integral_constant_expression_p=*/false);
- /* Make sure the initializer is still constant, in case of
- circular dependency (template/instantiate6.C). */
- const_init
- = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (code_pattern);
- cp_finish_decl (d, init, /*init_const_expr_p=*/const_init,
- /*asmspec_tree=*/NULL_TREE,
- LOOKUP_ONLYCONVERTING);
- pop_nested_class ();
+ /* If instantiating the initializer involved instantiating this
+ again, don't call cp_finish_decl twice. */
+ if (!DECL_INITIAL (d))
+ {
+ /* Make sure the initializer is still constant, in case of
+ circular dependency (template/instantiate6.C). */
+ const_init
+ = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (code_pattern);
+ cp_finish_decl (d, init, /*init_const_expr_p=*/const_init,
+ /*asmspec_tree=*/NULL_TREE,
+ LOOKUP_ONLYCONVERTING);
+ }
+ if (enter_context)
+ pop_nested_class ();
pop_nested_namespace (ns);
}
DECL_EXTERNAL (d) = 0;
/* Enter the scope of D so that access-checking works correctly. */
- push_nested_class (DECL_CONTEXT (d));
+ bool enter_context = DECL_CLASS_SCOPE_P (d);
+ if (enter_context)
+ push_nested_class (DECL_CONTEXT (d));
+
const_init = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (code_pattern);
cp_finish_decl (d, init, const_init, NULL_TREE, 0);
- pop_nested_class ();
+
+ if (enter_context)
+ pop_nested_class ();
+
+ if (variable_template_p (td))
+ note_variable_template_instantiation (d);
}
else if (TREE_CODE (d) == FUNCTION_DECL && DECL_DEFAULTED_FN (code_pattern))
synthesize_method (d);
else if (TREE_CODE (d) == FUNCTION_DECL)
{
- struct pointer_map_t *saved_local_specializations;
+ hash_map<tree, tree> *saved_local_specializations;
tree subst_decl;
tree tmpl_parm;
tree spec_parm;
saved_local_specializations = local_specializations;
/* Set up the list of local specializations. */
- local_specializations = pointer_map_create ();
+ local_specializations = new hash_map<tree, tree>;
/* Set up context. */
if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern)
}
/* We don't need the local specializations any more. */
- pointer_map_destroy (local_specializations);
+ delete local_specializations;
local_specializations = saved_local_specializations;
/* Finish the function. */
{
tree decl = pending_templates->tinst->decl;
- error ("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);
+ 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);
if (TREE_CODE (decl) == FUNCTION_DECL)
/* Pretend that we defined it. */
DECL_INITIAL (decl) = error_mark_node;
/* 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
the last one involved in diagnostics. */
-int
+bool
problematic_instantiation_changed (void)
{
return current_tinst_level != last_error_tinst_level;
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))
- expression = BASELINK_FUNCTIONS (expression);
+ {
+ if (BASELINK_OPTYPE (expression)
+ && dependent_type_p (BASELINK_OPTYPE (expression)))
+ return true;
+ expression = BASELINK_FUNCTIONS (expression);
+ }
if (TREE_CODE (expression) == TEMPLATE_ID_EXPR)
{
/* 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
cannot be used to initialize a "char *". */
if (TREE_CODE (expr) == STRING_CST)
return expr;
- /* Preserve arithmetic constants, as an optimization -- there is no
+ /* Preserve void and arithmetic constants, as an optimization -- there is no
reason to create a new node. */
- if (TREE_CODE (expr) == INTEGER_CST || TREE_CODE (expr) == REAL_CST)
+ if (TREE_CODE (expr) == VOID_CST
+ || TREE_CODE (expr) == INTEGER_CST
+ || TREE_CODE (expr) == REAL_CST)
return expr;
/* Preserve THROW_EXPRs -- all throw-expressions have type "void".
There is at least one place where we want to know that a
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"