/* The PENDING_TEMPLATES is a TREE_LIST of templates whose
instantiations have been deferred, either because their definitions
were not yet available, or because we were putting off doing the work. */
-struct GTY ((chain_next ("%h.next"))) pending_template {
+struct GTY ((chain_next ("%h.next"))) pending_template
+{
struct pending_template *next;
struct tinst_level *tinst;
};
static tree add_to_template_args (tree, tree);
static tree add_outermost_template_args (tree, tree);
static bool check_instantiated_args (tree, tree, tsubst_flags_t);
+static int check_non_deducible_conversion (tree, tree, int, int,
+ struct conversion **, bool);
static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*,
tree);
static int type_unification_real (tree, tree, tree, const tree *,
- unsigned int, int, unification_kind_t, int,
+ unsigned int, int, unification_kind_t,
vec<deferred_access_check, va_gc> **,
bool);
static void note_template_header (int);
return true;
else
{
- permerror (input_location,
- "specialization of %qD in different namespace", tmpl);
- inform (DECL_SOURCE_LOCATION (tmpl),
- " from definition of %q#D", tmpl);
+ auto_diagnostic_group d;
+ if (permerror (input_location,
+ "specialization of %qD in different namespace", tmpl))
+ inform (DECL_SOURCE_LOCATION (tmpl),
+ " from definition of %q#D", tmpl);
return false;
}
}
/* Make sure ARGS doesn't use any inappropriate typedefs; we should have
gone through coerce_template_parms by now. */
+static void
+verify_unstripped_args_1 (tree inner)
+{
+ 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 (ARGUMENT_PACK_P (arg))
+ verify_unstripped_args_1 (ARGUMENT_PACK_ARGS (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);
+ }
+}
+
static void
verify_unstripped_args (tree args)
{
++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);
- }
- }
+ verify_unstripped_args_1 (INNERMOST_TEMPLATE_ARGS (args));
--processing_template_decl;
}
/* We shouldn't be specializing a member template of an
unspecialized class template; we already gave an error in
check_specialization_scope, now avoid crashing. */
- if (template_count && DECL_CLASS_SCOPE_P (decl)
+ if (!VAR_P (decl)
+ && template_count && DECL_CLASS_SCOPE_P (decl)
&& template_class_depth (DECL_CONTEXT (decl)) > 0)
{
gcc_assert (errorcount);
that the const qualification is the same. Since
get_bindings does not try to merge the "this" parameter,
we must do the comparison explicitly. */
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
- && !same_type_p (TREE_VALUE (fn_arg_types),
- TREE_VALUE (decl_arg_types)))
- continue;
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+ {
+ if (!same_type_p (TREE_VALUE (fn_arg_types),
+ TREE_VALUE (decl_arg_types)))
+ continue;
+
+ /* And the ref-qualification. */
+ if (type_memfn_rqual (TREE_TYPE (decl))
+ != type_memfn_rqual (TREE_TYPE (fn)))
+ continue;
+ }
/* Skip the "this" parameter and, for constructors of
classes with virtual bases, the VTT parameter. A
decl_arg_types))
continue;
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+ && (type_memfn_rqual (TREE_TYPE (decl))
+ != type_memfn_rqual (TREE_TYPE (fn))))
+ continue;
+
// If the deduced arguments do not satisfy the constraints,
// this is not a candidate.
if (flag_concepts && !constraints_satisfied_p (fn))
new_spec_types);
new_type = cp_build_type_attribute_variant (new_type,
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;
+ new_type = cxx_copy_lang_qualifiers (new_type, old_type);
TREE_TYPE (decl) = new_type;
}
}
if (template_header_count > wanted)
{
+ auto_diagnostic_group d;
bool warned = pedwarn (DECL_SOURCE_LOCATION (decl), 0,
"too many template headers for %qD "
"(should be %d)",
if (!nattrs)
return;
+ auto_diagnostic_group d;
if (warning_at (DECL_SOURCE_LOCATION (spec), OPT_Wmissing_attributes,
"explicit specialization %q#D may be missing attributes",
spec))
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_HIDDEN_FRIEND_P (tmpl))
{
+ auto_diagnostic_group d;
if (pedwarn (DECL_SOURCE_LOCATION (decl), 0,
"friend declaration %qD is not visible to "
"explicit specialization", tmpl))
cap; cap = TREE_CHAIN (cap))
cp_walk_tree (&TREE_VALUE (cap), &find_parameter_packs_r, ppd,
ppd->visited);
- /* Since we defer implicit capture, look in the body as well. */
+ /* Since we defer implicit capture, look in the parms and body. */
tree fn = lambda_function (t);
+ cp_walk_tree (&TREE_TYPE (fn), &find_parameter_packs_r, ppd,
+ ppd->visited);
cp_walk_tree (&DECL_SAVED_TREE (fn), &find_parameter_packs_r, ppd,
ppd->visited);
*walk_subtrees = 0;
return NULL_TREE;
}
+ case IF_STMT:
+ cp_walk_tree (&IF_COND (t), &find_parameter_packs_r,
+ ppd, ppd->visited);
+ cp_walk_tree (&THEN_CLAUSE (t), &find_parameter_packs_r,
+ ppd, ppd->visited);
+ cp_walk_tree (&ELSE_CLAUSE (t), &find_parameter_packs_r,
+ ppd, ppd->visited);
+ /* Don't walk into IF_STMT_EXTRA_ARGS. */
+ *walk_subtrees = 0;
+ return NULL_TREE;
+
default:
return NULL_TREE;
}
if (complain & tf_error)
{
if (TYPE_P (arg))
- error ("expansion pattern %qT contains no argument packs", arg);
+ error ("expansion pattern %qT contains no parameter packs", arg);
else
- error ("expansion pattern %qE contains no argument packs", arg);
+ error ("expansion pattern %qE contains no parameter packs", arg);
}
return error_mark_node;
}
Returns TRUE and emits an error if there were bare parameter packs,
returns FALSE otherwise. */
bool
-check_for_bare_parameter_packs (tree t)
+check_for_bare_parameter_packs (tree t, location_t loc /* = UNKNOWN_LOCATION */)
{
tree parameter_packs = NULL_TREE;
struct find_parameter_pack_data ppd;
return false;
/* A lambda might use a parameter pack from the containing context. */
- if (current_class_type && LAMBDA_TYPE_P (current_class_type))
+ if (current_class_type && LAMBDA_TYPE_P (current_class_type)
+ && CLASSTYPE_TEMPLATE_INFO (current_class_type))
return false;
if (TREE_CODE (t) == TYPE_DECL)
if (parameter_packs)
{
- location_t loc = EXPR_LOC_OR_LOC (t, input_location);
+ if (loc == UNKNOWN_LOCATION)
+ loc = cp_expr_loc_or_loc (t, input_location);
error_at (loc, "parameter packs not expanded with %<...%>:");
while (parameter_packs)
{
template PARMS and constraints, CONSTR. If MEMBER_TEMPLATE_P is true,
the new template is a member template. */
-tree
+static tree
build_template_decl (tree decl, tree parms, bool member_template_p)
{
tree tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
+ SET_DECL_LANGUAGE (tmpl, DECL_LANGUAGE (decl));
DECL_TEMPLATE_PARMS (tmpl) = parms;
DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
{
if (!flag_concepts)
error ("partial specialization %q+D does not specialize "
- "any template arguments", decl);
+ "any template arguments; to define the primary template, "
+ "remove the template argument list", decl);
else
error ("partial specialization %q+D does not specialize any "
- "template arguments and is not more constrained than", decl);
+ "template arguments and is not more constrained than "
+ "the primary template; to define the primary template, "
+ "remove the template argument list", decl);
inform (DECL_SOURCE_LOCATION (maintmpl), "primary template here");
}
&& TMPL_ARGS_DEPTH (specargs) == 1
&& !get_partial_spec_bindings (maintmpl, maintmpl, specargs))
{
+ auto_diagnostic_group d;
if (permerror (input_location, "partial specialization %qD is not "
"more specialized than", decl))
inform (DECL_SOURCE_LOCATION (maintmpl), "primary template %qD",
fixed_parameter_pack_p_1 (tree parm, struct find_parameter_pack_data *ppd)
{
/* A type parm can't refer to another parm. */
- if (TREE_CODE (parm) == TYPE_DECL)
+ if (TREE_CODE (parm) == TYPE_DECL || parm == error_mark_node)
return;
else if (TREE_CODE (parm) == PARM_DECL)
{
}
accept:
- if (TREE_CODE (type) == REFERENCE_TYPE)
+ if (TYPE_REF_P (type))
{
if (REFERENCE_REF_P (fn))
fn = TREE_OPERAND (fn, 0);
check_valid_ptrmem_cst_expr (tree type, tree expr,
tsubst_flags_t complain)
{
- location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+ location_t loc = cp_expr_loc_or_loc (expr, input_location);
tree orig_expr = expr;
STRIP_NOPS (expr);
if (null_ptr_cst_p (expr))
tree from_type, tree arg)
{
if (explain_p)
- inform (EXPR_LOC_OR_LOC (arg, input_location),
+ inform (cp_expr_loc_or_loc (arg, input_location),
" cannot convert %qE (type %qT) to type %qT",
arg, from_type, to_type);
return unify_invalid (explain_p);
convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
{
tree expr_type;
- location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+ location_t loc = cp_expr_loc_or_loc (expr, input_location);
tree orig_expr = expr;
/* Detect immediately string literals as invalid non-type argument.
template-parameter. */
expr = build_converted_constant_expr (type, expr, complain);
if (expr == error_mark_node)
- return error_mark_node;
+ /* Make sure we return NULL_TREE only if we have really issued
+ an error, as described above. */
+ return (complain & tf_error) ? NULL_TREE : error_mark_node;
expr = maybe_constant_value (expr);
expr = convert_from_reference (expr);
}
}
}
- if (TREE_CODE (type) == REFERENCE_TYPE)
+ if (TYPE_REF_P (type))
expr = mark_lvalue_use (expr);
else
expr = mark_rvalue_use (expr);
could actually change the type to something more cv-qualified,
and this is not folded by convert_from_reference. */
tree addr = TREE_OPERAND (probe, 0);
- if (TREE_CODE (probe_type) == REFERENCE_TYPE
+ if (TYPE_REF_P (probe_type)
&& TREE_CODE (addr) == ADDR_EXPR
&& TYPE_PTR_P (TREE_TYPE (addr))
&& (same_type_ignoring_top_level_qualifiers_p
else
expr = cxx_constant_value (expr);
if (errorcount > errs || warningcount + werrorcount > warns)
- inform (loc, "in template argument for type %qT ", type);
+ inform (loc, "in template argument for type %qT", type);
if (expr == error_mark_node)
return NULL_TREE;
/* else cxx_constant_value complained but gave us
"a variable", orig_expr, expr);
return NULL_TREE;
}
- if (POINTER_TYPE_P (expr_type))
+ if (INDIRECT_TYPE_P (expr_type))
{
if (complain & tf_error)
error ("%qE is not a valid template argument for %qT "
tree val;
int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
- if (parm == error_mark_node)
+ if (parm == error_mark_node || error_operand_p (arg))
return error_mark_node;
/* Trivially convert placeholders. */
{
tree t = TREE_TYPE (parm);
- if (tree a = type_uses_auto (t))
+ if (TEMPLATE_PARM_LEVEL (get_template_parm_index (parm))
+ > TMPL_ARGS_DEPTH (args))
+ /* We don't have enough levels of args to do any substitution. This
+ can happen in the context of -fnew-ttp-matching. */;
+ else if (tree a = type_uses_auto (t))
{
t = do_auto_deduction (t, arg, a, complain, adc_unify, args);
if (t == error_mark_node)
const_tree inner = TREE_OPERAND (val, 0);
const_tree innertype = TREE_TYPE (inner);
if (innertype
- && TREE_CODE (innertype) == REFERENCE_TYPE
+ && TYPE_REF_P (innertype)
&& TREE_CODE (TREE_TYPE (innertype)) == FUNCTION_TYPE
&& TREE_OPERAND_LENGTH (inner) > 0
&& reject_gcc_builtin (TREE_OPERAND (inner, 0)))
int variadic_args_p = 0;
int post_variadic_parms = 0;
+ /* Adjustment to nparms for fixed parameter packs. */
+ int fixed_pack_adjust = 0;
+ int fixed_packs = 0;
+ int missing = 0;
+
/* Likewise for parameters with default arguments. */
int default_p = 0;
|| (TREE_VEC_ELT (parms, nargs) != error_mark_node
&& !TREE_PURPOSE (TREE_VEC_ELT (parms, nargs))))))
{
+ bad_nargs:
if (complain & tf_error)
{
if (variadic_p || default_p)
lost++;
/* We are done with all of the arguments. */
arg_idx = nargs;
+ break;
}
else
{
pack_adjust = TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg)) - 1;
arg_idx += pack_adjust;
+ if (fixed_parameter_pack_p (TREE_VALUE (parm)))
+ {
+ ++fixed_packs;
+ fixed_pack_adjust += pack_adjust;
+ }
}
continue;
error ("template argument %d is invalid", arg_idx + 1);
}
else if (!arg)
- /* This only occurs if there was an error in the template
- parameter list itself (which we would already have
- reported) that we are trying to recover from, e.g., a class
- template with a parameter list such as
- template<typename..., typename>. */
- ++lost;
+ {
+ /* This can occur if there was an error in the template
+ parameter list itself (which we would already have
+ reported) that we are trying to recover from, e.g., a class
+ template with a parameter list such as
+ template<typename..., typename> (cpp0x/variadic150.C). */
+ ++lost;
+
+ /* This can also happen with a fixed parameter pack (71834). */
+ if (arg_idx >= nargs)
+ ++missing;
+ }
else
arg = convert_template_argument (TREE_VALUE (parm),
arg, new_args, complain,
cp_unevaluated_operand = saved_unevaluated_operand;
c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
- if (variadic_p && arg_idx < nargs)
+ if (missing || arg_idx < nargs - variadic_args_p)
{
- if (complain & tf_error)
- {
- error ("wrong number of template arguments "
- "(%d, should be %d)", nargs, arg_idx);
- if (in_decl)
- error ("provided for %q+D", in_decl);
- }
- return error_mark_node;
+ /* If we had fixed parameter packs, we didn't know how many arguments we
+ actually needed earlier; now we do. */
+ nparms += fixed_pack_adjust;
+ variadic_p -= fixed_packs;
+ goto bad_nargs;
+ }
+
+ if (arg_idx < nargs)
+ {
+ /* We had some pack expansion arguments that will only work if the packs
+ are empty, but wait until instantiation time to complain.
+ See variadic-ttp3.C. */
+ int len = nparms + (nargs - arg_idx);
+ tree args = make_tree_vec (len);
+ int i = 0;
+ for (; i < nparms; ++i)
+ TREE_VEC_ELT (args, i) = TREE_VEC_ELT (new_inner_args, i);
+ for (; i < len; ++i, ++arg_idx)
+ TREE_VEC_ELT (args, i) = TREE_VEC_ELT (inner_args,
+ arg_idx - pack_adjust);
+ new_inner_args = args;
}
if (lost)
- return error_mark_node;
+ {
+ gcc_assert (!(complain & tf_error) || seen_error ());
+ return error_mark_node;
+ }
if (CHECKING_P && !NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args))
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args,
return comp_template_args (oargs, nargs, NULL, NULL, true);
}
+/* Implement a freelist interface for objects of type T.
+
+ Head is a separate object, rather than a regular member, so that we
+ can define it as a GTY deletable pointer, which is highly
+ desirable. A data member could be declared that way, but then the
+ containing object would implicitly get GTY((user)), which would
+ prevent us from instantiating freelists as global objects.
+ Although this way we can create freelist global objects, they're
+ such thin wrappers that instantiating temporaries at every use
+ loses nothing and saves permanent storage for the freelist object.
+
+ Member functions next, anew, poison and reinit have default
+ implementations that work for most of the types we're interested
+ in, but if they don't work for some type, they should be explicitly
+ specialized. See the comments before them for requirements, and
+ the example specializations for the tree_list_freelist. */
+template <typename T>
+class freelist
+{
+ /* Return the next object in a chain. We could just do type
+ punning, but if we access the object with its underlying type, we
+ avoid strict-aliasing trouble. This needs only work between
+ poison and reinit. */
+ static T *&next (T *obj) { return obj->next; }
+
+ /* Return a newly allocated, uninitialized or minimally-initialized
+ object of type T. Any initialization performed by anew should
+ either remain across the life of the object and the execution of
+ poison, or be redone by reinit. */
+ static T *anew () { return ggc_alloc<T> (); }
+
+ /* Optionally scribble all over the bits holding the object, so that
+ they become (mostly?) uninitialized memory. This is called while
+ preparing to make the object part of the free list. */
+ static void poison (T *obj) {
+ T *p ATTRIBUTE_UNUSED = obj;
+ T **q ATTRIBUTE_UNUSED = &next (obj);
+
+#ifdef ENABLE_GC_CHECKING
+ /* Poison the data, to indicate the data is garbage. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (p, sizeof (*p)));
+ memset (p, 0xa5, sizeof (*p));
+#endif
+ /* Let valgrind know the object is free. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS (p, sizeof (*p)));
+
+ /* Let valgrind know the next portion of the object is available,
+ but uninitialized. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (q, sizeof (*q)));
+ }
+
+ /* Bring an object that underwent at least one lifecycle after anew
+ and before the most recent free and poison, back to a usable
+ state, reinitializing whatever is needed for it to be
+ functionally equivalent to an object just allocated and returned
+ by anew. This may poison or clear the next field, used by
+ freelist housekeeping after poison was called. */
+ static void reinit (T *obj) {
+ T **q ATTRIBUTE_UNUSED = &next (obj);
+
+#ifdef ENABLE_GC_CHECKING
+ memset (q, 0xa5, sizeof (*q));
+#endif
+ /* Let valgrind know the entire object is available, but
+ uninitialized. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (obj, sizeof (*obj)));
+ }
+
+ /* Reference a GTY-deletable pointer that points to the first object
+ in the free list proper. */
+ T *&head;
+public:
+ /* Construct a freelist object chaining objects off of HEAD. */
+ freelist (T *&head) : head(head) {}
+
+ /* Add OBJ to the free object list. The former head becomes OBJ's
+ successor. */
+ void free (T *obj)
+ {
+ poison (obj);
+ next (obj) = head;
+ head = obj;
+ }
+
+ /* Take an object from the free list, if one is available, or
+ allocate a new one. Objects taken from the free list should be
+ regarded as filled with garbage, except for bits that are
+ configured to be preserved across free and alloc. */
+ T *alloc ()
+ {
+ if (head)
+ {
+ T *obj = head;
+ head = next (head);
+ reinit (obj);
+ return obj;
+ }
+ else
+ return anew ();
+ }
+};
+
+/* Explicitly specialize the interfaces for freelist<tree_node>: we
+ want to allocate a TREE_LIST using the usual interface, and ensure
+ TREE_CHAIN remains functional. Alas, we have to duplicate a bit of
+ build_tree_list logic in reinit, so this could go out of sync. */
+template <>
+inline tree &
+freelist<tree_node>::next (tree obj)
+{
+ return TREE_CHAIN (obj);
+}
+template <>
+inline tree
+freelist<tree_node>::anew ()
+{
+ return build_tree_list (NULL, NULL);
+}
+template <>
+inline void
+freelist<tree_node>::poison (tree obj ATTRIBUTE_UNUSED)
+{
+ int size ATTRIBUTE_UNUSED = sizeof (tree_list);
+ tree p ATTRIBUTE_UNUSED = obj;
+ tree_base *b ATTRIBUTE_UNUSED = &obj->base;
+ tree *q ATTRIBUTE_UNUSED = &next (obj);
+
+#ifdef ENABLE_GC_CHECKING
+ gcc_checking_assert (TREE_CODE (obj) == TREE_LIST);
+
+ /* Poison the data, to indicate the data is garbage. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (p, size));
+ memset (p, 0xa5, size);
+#endif
+ /* Let valgrind know the object is free. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS (p, size));
+ /* But we still want to use the TREE_CODE and TREE_CHAIN parts. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (b, sizeof (*b)));
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (q, sizeof (*q)));
+
+#ifdef ENABLE_GC_CHECKING
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (b, sizeof (*b)));
+ /* Keep TREE_CHAIN functional. */
+ TREE_SET_CODE (obj, TREE_LIST);
+#else
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (b, sizeof (*b)));
+#endif
+}
+template <>
+inline void
+freelist<tree_node>::reinit (tree obj ATTRIBUTE_UNUSED)
+{
+ tree_base *b ATTRIBUTE_UNUSED = &obj->base;
+
+#ifdef ENABLE_GC_CHECKING
+ gcc_checking_assert (TREE_CODE (obj) == TREE_LIST);
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (obj, sizeof (tree_list)));
+ memset (obj, 0, sizeof (tree_list));
+#endif
+
+ /* Let valgrind know the entire object is available, but
+ uninitialized. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (obj, sizeof (tree_list)));
+
+#ifdef ENABLE_GC_CHECKING
+ TREE_SET_CODE (obj, TREE_LIST);
+#else
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (b, sizeof (*b)));
+#endif
+}
+
+/* Point to the first object in the TREE_LIST freelist. */
+static GTY((deletable)) tree tree_list_freelist_head;
+/* Return the/an actual TREE_LIST freelist. */
+static inline freelist<tree_node>
+tree_list_freelist ()
+{
+ return tree_list_freelist_head;
+}
+
+/* Point to the first object in the tinst_level freelist. */
+static GTY((deletable)) tinst_level *tinst_level_freelist_head;
+/* Return the/an actual tinst_level freelist. */
+static inline freelist<tinst_level>
+tinst_level_freelist ()
+{
+ return tinst_level_freelist_head;
+}
+
+/* Point to the first object in the pending_template freelist. */
+static GTY((deletable)) pending_template *pending_template_freelist_head;
+/* Return the/an actual pending_template freelist. */
+static inline freelist<pending_template>
+pending_template_freelist ()
+{
+ return pending_template_freelist_head;
+}
+
+/* Build the TREE_LIST object out of a split list, store it
+ permanently, and return it. */
+tree
+tinst_level::to_list ()
+{
+ gcc_assert (split_list_p ());
+ tree ret = tree_list_freelist ().alloc ();
+ TREE_PURPOSE (ret) = tldcl;
+ TREE_VALUE (ret) = targs;
+ tldcl = ret;
+ targs = NULL;
+ gcc_assert (tree_list_p ());
+ return ret;
+}
+
+const unsigned short tinst_level::refcount_infinity;
+
+/* Increment OBJ's refcount unless it is already infinite. */
+static tinst_level *
+inc_refcount_use (tinst_level *obj)
+{
+ if (obj && obj->refcount != tinst_level::refcount_infinity)
+ ++obj->refcount;
+ return obj;
+}
+
+/* Release storage for OBJ and node, if it's a TREE_LIST. */
+void
+tinst_level::free (tinst_level *obj)
+{
+ if (obj->tree_list_p ())
+ tree_list_freelist ().free (obj->get_node ());
+ tinst_level_freelist ().free (obj);
+}
+
+/* Decrement OBJ's refcount if not infinite. If it reaches zero, release
+ OBJ's DECL and OBJ, and start over with the tinst_level object that
+ used to be referenced by OBJ's NEXT. */
+static void
+dec_refcount_use (tinst_level *obj)
+{
+ while (obj
+ && obj->refcount != tinst_level::refcount_infinity
+ && !--obj->refcount)
+ {
+ tinst_level *next = obj->next;
+ tinst_level::free (obj);
+ obj = next;
+ }
+}
+
+/* Modify PTR so that it points to OBJ, adjusting the refcounts of OBJ
+ and of the former PTR. Omitting the second argument is equivalent
+ to passing (T*)NULL; this is allowed because passing the
+ zero-valued integral constant NULL confuses type deduction and/or
+ overload resolution. */
+template <typename T>
+static void
+set_refcount_ptr (T *& ptr, T *obj = NULL)
+{
+ T *save = ptr;
+ ptr = inc_refcount_use (obj);
+ dec_refcount_use (save);
+}
+
static void
add_pending_template (tree d)
{
/* We are called both from instantiate_decl, where we've already had a
tinst_level pushed, and instantiate_template, where we haven't.
Compensate. */
- level = !current_tinst_level || current_tinst_level->decl != d;
+ gcc_assert (TREE_CODE (d) != TREE_LIST);
+ level = !current_tinst_level
+ || current_tinst_level->maybe_get_node () != d;
if (level)
push_tinst_level (d);
- pt = ggc_alloc<pending_template> ();
+ pt = pending_template_freelist ().alloc ();
pt->next = NULL;
- pt->tinst = current_tinst_level;
+ pt->tinst = NULL;
+ set_refcount_ptr (pt->tinst, current_tinst_level);
if (last_pending_template)
last_pending_template->next = pt;
else
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
error ("template constraint failure");
diagnose_constraints (input_location, gen_tmpl, arglist);
}
return found;
}
- context = tsubst (DECL_CONTEXT (gen_tmpl), arglist,
- complain, in_decl);
+ context = DECL_CONTEXT (gen_tmpl);
+ if (context && TYPE_P (context))
+ {
+ context = tsubst_aggr_type (context, arglist, complain, in_decl, true);
+ context = complete_type (context);
+ }
+ else
+ context = tsubst (context, arglist, complain, in_decl);
+
if (context == error_mark_node)
return error_mark_node;
/* A local class. Make sure the decl gets registered properly. */
if (context == current_function_decl)
- pushtag (DECL_NAME (gen_tmpl), t, /*tag_scope=*/ts_current);
+ if (pushtag (DECL_NAME (gen_tmpl), t, /*tag_scope=*/ts_current)
+ == error_mark_node)
+ return error_mark_node;
if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
/* This instantiation is another name for the primary
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
error ("use of invalid variable template %qE", var);
diagnose_constraints (location_of (var), templ, arglist);
}
break;
case TYPEOF_TYPE:
+ case DECLTYPE_TYPE:
case UNDERLYING_TYPE:
if (pfd->include_nondeduced_p
&& for_each_template_parm (TYPE_VALUES_RAW (t), fn, data,
pfd->include_nondeduced_p,
pfd->any_fn))
return error_mark_node;
+ *walk_subtrees = false;
break;
case FUNCTION_DECL:
static inline bool
neglectable_inst_p (tree d)
{
- return (DECL_P (d)
+ return (d && DECL_P (d)
&& !undeduced_auto_decl (d)
&& !(TREE_CODE (d) == FUNCTION_DECL ? DECL_DECLARED_CONSTEXPR_P (d)
: decl_maybe_constant_var_p (d)));
return false;
for (; lev; lev = lev->next)
- if (neglectable_inst_p (lev->decl))
+ if (neglectable_inst_p (lev->maybe_get_node ()))
break;
return (lev && errs > lev->errors);
static GTY(()) struct tinst_level *last_error_tinst_level;
-/* We're starting to instantiate D; record the template instantiation context
- for diagnostics and to restore it later. */
-
-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)
+static bool
+push_tinst_level_loc (tree tldcl, tree targs, location_t loc)
{
struct tinst_level *new_level;
/* 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))
+ if (!targs && limit_bad_template_recursion (tldcl))
return false;
/* When not -quiet, dump template instantiations other than functions, since
announce_function will take care of those. */
- if (!quiet_flag
- && TREE_CODE (d) != TREE_LIST
- && TREE_CODE (d) != FUNCTION_DECL)
- fprintf (stderr, " %s", decl_as_string (d, TFF_DECL_SPECIFIERS));
-
- new_level = ggc_alloc<tinst_level> ();
- new_level->decl = d;
+ if (!quiet_flag && !targs
+ && TREE_CODE (tldcl) != TREE_LIST
+ && TREE_CODE (tldcl) != FUNCTION_DECL)
+ fprintf (stderr, " %s", decl_as_string (tldcl, TFF_DECL_SPECIFIERS));
+
+ new_level = tinst_level_freelist ().alloc ();
+ new_level->tldcl = tldcl;
+ new_level->targs = targs;
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;
- current_tinst_level = new_level;
+ new_level->errors = errorcount + sorrycount;
+ new_level->next = NULL;
+ new_level->refcount = 0;
+ set_refcount_ptr (new_level->next, current_tinst_level);
+ set_refcount_ptr (current_tinst_level, new_level);
++tinst_depth;
if (GATHER_STATISTICS && (tinst_depth > depth_reached))
return true;
}
+/* We're starting substitution of TMPL<ARGS>; record the template
+ substitution context for diagnostics and to restore it later. */
+
+static bool
+push_tinst_level (tree tmpl, tree args)
+{
+ return push_tinst_level_loc (tmpl, args, input_location);
+}
+
+/* We're starting to instantiate D; record INPUT_LOCATION and the
+ template instantiation context for diagnostics and to restore it
+ later. */
+
+bool
+push_tinst_level (tree d)
+{
+ return push_tinst_level_loc (d, input_location);
+}
+
+/* Likewise, but record LOC as the program location. */
+
+bool
+push_tinst_level_loc (tree d, location_t loc)
+{
+ gcc_assert (TREE_CODE (d) != TREE_LIST);
+ return push_tinst_level_loc (d, NULL, loc);
+}
+
/* We're done instantiating this template; return to the instantiation
context. */
/* Restore the filename and line number stashed away when we started
this instantiation. */
input_location = current_tinst_level->locus;
- current_tinst_level = current_tinst_level->next;
+ set_refcount_ptr (current_tinst_level, current_tinst_level->next);
--tinst_depth;
}
for (t = level; t; t = t->next)
++tinst_depth;
- current_tinst_level = level;
+ set_refcount_ptr (current_tinst_level, level);
pop_tinst_level ();
if (current_tinst_level)
current_tinst_level->errors = errorcount+sorrycount;
- return level->decl;
+ return level->maybe_get_node ();
}
/* Returns the TINST_LEVEL which gives the original instantiation
/* Mark the type as in the process of being defined. */
TYPE_BEING_DEFINED (type) = 1;
+ /* We may be in the middle of deferred access check. Disable
+ it now. */
+ deferring_access_check_sentinel acs (dk_no_deferred);
+
/* Determine what specialization of the original template to
instantiate. */
t = most_specialized_partial_spec (type, tf_warning_or_error);
if (! push_tinst_level (type))
return type;
- /* We may be in the middle of deferred access check. Disable
- 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;
cxx_incomplete_type_error (r, rtype);
TREE_TYPE (r) = error_mark_node;
}
+ else if (TREE_CODE (rtype) == ARRAY_TYPE
+ && TYPE_DOMAIN (rtype) == NULL_TREE
+ && (TREE_CODE (type) == UNION_TYPE
+ || TREE_CODE (type) == QUAL_UNION_TYPE))
+ {
+ error ("flexible array member %qD in union", r);
+ TREE_TYPE (r) = error_mark_node;
+ }
}
/* If it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE,
maximum_field_alignment = saved_maximum_field_alignment;
if (!fn_context)
pop_from_top_level ();
- pop_deferring_access_checks ();
pop_tinst_level ();
/* The vtable for a template class can be emitted in any translation
struct el_data
{
+ hash_set<tree> internal;
tree extra;
tsubst_flags_t complain;
+
+ el_data (tsubst_flags_t c)
+ : extra (NULL_TREE), complain (c) {}
};
static tree
extract_locals_r (tree *tp, int */*walk_subtrees*/, void *data_)
el_data &data = *reinterpret_cast<el_data*>(data_);
tree *extra = &data.extra;
tsubst_flags_t complain = data.complain;
- if (tree spec = retrieve_local_specialization (*tp))
+
+ if (TYPE_P (*tp) && typedef_variant_p (*tp))
+ /* Remember local typedefs (85214). */
+ tp = &TYPE_NAME (*tp);
+
+ if (TREE_CODE (*tp) == DECL_EXPR)
+ data.internal.add (DECL_EXPR_DECL (*tp));
+ else if (tree spec = retrieve_local_specialization (*tp))
{
+ if (data.internal.contains (*tp))
+ /* Don't mess with variables declared within the pattern. */
+ return NULL_TREE;
if (TREE_CODE (spec) == NONTYPE_ARGUMENT_PACK)
{
/* Maybe pull out the PARM_DECL for a partial instantiation. */
static tree
extract_local_specs (tree pattern, tsubst_flags_t complain)
{
- el_data data = { NULL_TREE, complain };
+ el_data data (complain);
cp_walk_tree_without_duplicates (&pattern, extract_locals_r, &data);
return data.extra;
}
+/* Extract any uses of local_specializations from PATTERN and add them to ARGS
+ for use in PACK_EXPANSION_EXTRA_ARGS. */
+
+tree
+build_extra_args (tree pattern, tree args, tsubst_flags_t complain)
+{
+ tree extra = args;
+ if (local_specializations)
+ if (tree locals = extract_local_specs (pattern, complain))
+ extra = tree_cons (NULL_TREE, extra, locals);
+ return extra;
+}
+
+/* Apply any local specializations from PACK_EXPANSION_EXTRA_ARGS and add the
+ normal template args to ARGS. */
+
+tree
+add_extra_args (tree extra, tree args)
+{
+ if (extra && TREE_CODE (extra) == TREE_LIST)
+ {
+ for (tree elt = TREE_CHAIN (extra); elt; elt = TREE_CHAIN (elt))
+ {
+ /* The partial instantiation involved local declarations collected in
+ extract_local_specs; map from the general template to our local
+ context. */
+ tree gen = TREE_PURPOSE (elt);
+ tree inst = TREE_VALUE (elt);
+ if (DECL_P (inst))
+ if (tree local = retrieve_local_specialization (inst))
+ inst = local;
+ /* else inst is already a full instantiation of the pack. */
+ register_local_specialization (inst, gen);
+ }
+ gcc_assert (!TREE_PURPOSE (extra));
+ extra = TREE_VALUE (extra);
+ }
+ return add_to_template_args (extra, args);
+}
+
/* Substitute ARGS into T, which is an pack expansion
(i.e. TYPE_PACK_EXPANSION or EXPR_PACK_EXPANSION). Returns a
TREE_VEC with the substituted arguments, a PACK_EXPANSION_* node
pattern = PACK_EXPANSION_PATTERN (t);
/* Add in any args remembered from an earlier partial instantiation. */
- tree extra = PACK_EXPANSION_EXTRA_ARGS (t);
- if (extra && TREE_CODE (extra) == TREE_LIST)
- {
- for (tree elt = TREE_CHAIN (extra); elt; elt = TREE_CHAIN (elt))
- {
- /* The partial instantiation involved local declarations collected in
- extract_local_specs; map from the general template to our local
- context. */
- tree gen = TREE_PURPOSE (elt);
- tree inst = TREE_VALUE (elt);
- if (DECL_P (inst))
- if (tree local = retrieve_local_specialization (inst))
- inst = local;
- /* else inst is already a full instantiation of the pack. */
- register_local_specialization (inst, gen);
- }
- gcc_assert (!TREE_PURPOSE (extra));
- extra = TREE_VALUE (extra);
- }
- args = add_to_template_args (extra, args);
+ args = add_extra_args (PACK_EXPANSION_EXTRA_ARGS (t), args);
levels = TMPL_ARGS_DEPTH (args);
int level = 0;
if (TREE_CODE (parm_pack) == BASES)
- {
- gcc_assert (parm_pack == pattern);
- if (BASES_DIRECT (parm_pack))
- return calculate_direct_bases (tsubst_expr (BASES_TYPE (parm_pack),
- args, complain, in_decl, false));
- else
- return calculate_bases (tsubst_expr (BASES_TYPE (parm_pack),
- args, complain, in_decl, false));
- }
- else if (builtin_pack_call_p (parm_pack))
{
- /* ??? Support use in other patterns. */
gcc_assert (parm_pack == pattern);
+ if (BASES_DIRECT (parm_pack))
+ return calculate_direct_bases (tsubst_expr (BASES_TYPE (parm_pack),
+ args, complain,
+ in_decl, false),
+ complain);
+ else
+ return calculate_bases (tsubst_expr (BASES_TYPE (parm_pack),
+ args, complain, in_decl,
+ false), complain);
+ }
+ else if (builtin_pack_call_p (parm_pack))
+ {
+ if (parm_pack != pattern)
+ {
+ if (complain & tf_error)
+ sorry ("%qE is not the entire pattern of the pack expansion",
+ parm_pack);
+ return error_mark_node;
+ }
return expand_builtin_pack_call (parm_pack, args,
complain, in_decl);
}
{
/* This parameter pack was used in an unevaluated context. Just
make a dummy decl, since it's only used for its type. */
+ ++cp_unevaluated_operand;
arg_pack = tsubst_decl (parm_pack, args, complain);
+ --cp_unevaluated_operand;
if (arg_pack && DECL_PACK_P (arg_pack))
/* Partial instantiation of the parm_pack, we can't build
up an argument pack yet. */
/* We can't substitute for this parameter pack. We use a flag as
well as the missing_level counter because function parameter
packs don't have a level. */
- gcc_assert (processing_template_decl);
+ gcc_assert (processing_template_decl || is_auto (parm_pack));
unsubstituted_packs = true;
}
}
/* Also optimize expression pack expansions if we can tell that the
elements won't have reference type. */
tree type = TREE_TYPE (pattern);
- if (type && TREE_CODE (type) != REFERENCE_TYPE
+ if (type && !TYPE_REF_P (type)
&& !PACK_EXPANSION_P (type)
&& !WILDCARD_TYPE_P (type))
return args;
have values for all the packs. So remember these until then. */
t = make_pack_expansion (pattern, complain);
- tree extra = args;
- if (local_specializations)
- if (tree locals = extract_local_specs (pattern, complain))
- extra = tree_cons (NULL_TREE, extra, locals);
- PACK_EXPANSION_EXTRA_ARGS (t) = extra;
+ PACK_EXPANSION_EXTRA_ARGS (t)
+ = build_extra_args (pattern, args, complain);
return t;
}
else if (unsubstituted_packs)
tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,
tsubst_flags_t complain)
{
- tree saved_class_ptr = NULL_TREE;
- tree saved_class_ref = NULL_TREE;
int errs = errorcount + sorrycount;
/* This can happen in invalid code. */
tree parmtype = TREE_TYPE (parm);
if (DECL_BY_REFERENCE (parm))
parmtype = TREE_TYPE (parmtype);
+ if (parmtype == error_mark_node)
+ return error_mark_node;
+
gcc_assert (same_type_ignoring_top_level_qualifiers_p (type, parmtype));
tree *slot;
we must be careful to do name lookup in the scope of S<T>,
rather than in the current class. */
+ push_to_top_level ();
push_access_scope (fn);
- /* The "this" pointer is not valid in a default argument. */
- if (cfun)
- {
- saved_class_ptr = current_class_ptr;
- cp_function_chain->x_current_class_ptr = NULL_TREE;
- saved_class_ref = current_class_ref;
- cp_function_chain->x_current_class_ref = NULL_TREE;
- }
-
start_lambda_scope (parm);
- push_deferring_access_checks(dk_no_deferred);
/* The default argument expression may cause implicitly defined
member functions to be synthesized, which will result in garbage
collection. We must treat this situation as if we were within
complain, NULL_TREE,
/*integral_constant_expression_p=*/false);
--function_depth;
- pop_deferring_access_checks();
finish_lambda_scope ();
- /* Restore the "this" pointer. */
- if (cfun)
- {
- cp_function_chain->x_current_class_ptr = saved_class_ptr;
- cp_function_chain->x_current_class_ref = saved_class_ref;
- }
-
if (errorcount+sorrycount > errs
&& (complain & tf_warning_or_error))
inform (input_location,
arg = check_default_argument (type, arg, complain);
pop_access_scope (fn);
+ pop_from_top_level ();
if (arg != error_mark_node && !cp_unevaluated_operand)
{
complain);
}
+/* Hash table mapping a FUNCTION_DECL to its dependent explicit-specifier. */
+static GTY((cache)) tree_cache_map *explicit_specifier_map;
+
+/* Store a pair to EXPLICIT_SPECIFIER_MAP. */
+
+void
+store_explicit_specifier (tree v, tree t)
+{
+ if (!explicit_specifier_map)
+ explicit_specifier_map = tree_cache_map::create_ggc (37);
+ DECL_HAS_DEPENDENT_EXPLICIT_SPEC_P (v) = true;
+ explicit_specifier_map->put (v, t);
+}
+
+/* Lookup an element in EXPLICIT_SPECIFIER_MAP. */
+
+static tree
+lookup_explicit_specifier (tree v)
+{
+ return *explicit_specifier_map->get (v);
+}
+
/* Subroutine of tsubst_decl for the case when T is a FUNCTION_DECL. */
static tree
DECL_INITIAL (r) = NULL_TREE;
DECL_CONTEXT (r) = ctx;
+ /* Handle explicit(dependent-expr). */
+ if (DECL_HAS_DEPENDENT_EXPLICIT_SPEC_P (t))
+ {
+ tree spec = lookup_explicit_specifier (t);
+ spec = tsubst_copy_and_build (spec, args, complain, in_decl,
+ /*function_p=*/false,
+ /*i_c_e_p=*/true);
+ spec = build_explicit_specifier (spec, complain);
+ DECL_NONCONVERTING_P (r) = (spec == boolean_true_node);
+ }
+
/* OpenMP UDRs have the only argument a reference to the declared
type. We want to diagnose if the declared type is a reference,
which is invalid, but as references to references are usually
tree argtype
= TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (t))));
argtype = tsubst (argtype, args, complain, in_decl);
- if (TREE_CODE (argtype) == REFERENCE_TYPE)
+ if (TYPE_REF_P (argtype))
error_at (DECL_SOURCE_LOCATION (t),
"reference type %qT in "
"%<#pragma omp declare reduction%>", argtype);
for (; flambda_count < lambda_count && fn && LAMBDA_FUNCTION_P (fn);
fn = decl_function_context (fn))
++flambda_count;
- if (DECL_TEMPLATE_INFO (fn)
+ if ((fn && DECL_TEMPLATE_INFO (fn))
? most_general_template (fn) != most_general_template (tctx)
: fn != tctx)
continue;
}
/* Create a new node for the specialization we need. */
- r = copy_decl (t);
if (type == NULL_TREE)
{
if (is_typedef_decl (t))
sub_args = strip_innermost_template_args (args, extra);
}
type = tsubst (type, sub_args, complain, in_decl);
+ /* Substituting the type might have recursively instantiated this
+ same alias (c++/86171). */
+ if (gen_tmpl && DECL_ALIAS_TEMPLATE_P (gen_tmpl)
+ && (spec = retrieve_specialization (gen_tmpl, argvec, hash)))
+ {
+ r = spec;
+ break;
+ }
}
+ r = copy_decl (t);
if (VAR_P (r))
{
- /* Even if the original location is out of scope, the
- newly substituted one is not. */
- DECL_DEAD_FOR_LOCAL (r) = 0;
DECL_INITIALIZED_P (r) = 0;
DECL_TEMPLATE_INSTANTIATED (r) = 0;
if (type == error_mark_node)
/*constant_expression_p=*/false);
if (REFERENCE_REF_P (ve))
{
- gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
+ gcc_assert (TYPE_REF_P (type));
ve = TREE_OPERAND (ve, 0);
}
SET_DECL_VALUE_EXPR (r, ve);
if (TREE_CODE (t) == FUNCTION_TYPE)
{
fntype = build_function_type (return_type, arg_types);
- fntype = apply_memfn_quals (fntype,
- type_memfn_quals (t),
- type_memfn_rqual (t));
+ fntype = apply_memfn_quals (fntype, type_memfn_quals (t));
}
else
{
fntype = build_method_type_directly (r, return_type,
TREE_CHAIN (arg_types));
- fntype = build_ref_qualified_type (fntype, type_memfn_rqual (t));
}
fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
- if (late_return_type_p)
- TYPE_HAS_LATE_RETURN_TYPE (fntype) = 1;
+ /* See comment above. */
+ tree raises = NULL_TREE;
+ cp_ref_qualifier rqual = type_memfn_rqual (t);
+ fntype = build_cp_fntype_variant (fntype, rqual, raises, late_return_type_p);
return fntype;
}
&& !PLACEHOLDER_TYPE_CONSTRAINTS (r))
/* Break infinite recursion when substituting the constraints
of a constrained placeholder. */;
+ else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+ && !PLACEHOLDER_TYPE_CONSTRAINTS (t)
+ && !CLASS_PLACEHOLDER_TEMPLATE (t)
+ && (arg = TEMPLATE_TYPE_PARM_INDEX (t),
+ r = TEMPLATE_PARM_DESCENDANTS (arg))
+ && (TEMPLATE_PARM_LEVEL (r)
+ == TEMPLATE_PARM_LEVEL (arg) - levels))
+ /* Cache the simple case of lowering a type parameter. */
+ r = TREE_TYPE (r);
else
{
r = copy_type (t);
= tsubst_constraint (constr, args, complain, in_decl);
else if (tree pl = CLASS_PLACEHOLDER_TEMPLATE (t))
{
- if (DECL_TEMPLATE_TEMPLATE_PARM_P (pl))
- pl = tsubst (pl, args, complain, in_decl);
+ pl = tsubst_copy (pl, args, complain, in_decl);
CLASS_PLACEHOLDER_TEMPLATE (r) = pl;
}
}
Core issue 106 says that creating a reference to a reference
during instantiation is no longer a cause for failure. We
only enforce this check in strict C++98 mode. */
- if ((TREE_CODE (type) == REFERENCE_TYPE
+ if ((TYPE_REF_P (type)
&& (((cxx_dialect == cxx98) && flag_iso) || code != REFERENCE_TYPE))
|| (code == REFERENCE_TYPE && VOID_TYPE_P (type)))
{
if (TREE_CODE (type) == METHOD_TYPE)
r = build_ptrmemfunc_type (r);
}
- else if (TREE_CODE (type) == REFERENCE_TYPE)
+ else if (TYPE_REF_P (type))
/* In C++0x, during template argument substitution, when there is an
attempt to create a reference to a reference type, reference
collapsing is applied as described in [14.3.1/4 temp.arg.type]:
error ("creating pointer to member of non-class type %qT", r);
return error_mark_node;
}
- if (TREE_CODE (type) == REFERENCE_TYPE)
+ if (TYPE_REF_P (type))
{
if (complain & tf_error)
error ("creating pointer to member reference type %qT", type);
|| TREE_CODE (type) == FUNCTION_TYPE
|| (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == NULL_TREE)
- || TREE_CODE (type) == REFERENCE_TYPE)
+ || TYPE_REF_P (type))
{
if (complain & tf_error)
error ("creating array of %qT", type);
r = build_cplus_array_type (type, domain);
+ if (!valid_array_size_p (input_location, r, in_decl,
+ (complain & tf_error)))
+ return error_mark_node;
+
if (TYPE_USER_ALIGN (t))
{
SET_TYPE_ALIGN (r, TYPE_ALIGN (t));
/* If lookup found a single function, mark it as used at this point.
(If lookup found multiple functions the one selected later by
overload resolution will be marked as used at that point.) */
- if (!template_id_p && !really_overloaded_fn (fns)
- && !mark_used (OVL_FIRST (fns), complain) && !(complain & tf_error))
- return error_mark_node;
+ if (!template_id_p && !really_overloaded_fn (fns))
+ {
+ tree fn = OVL_FIRST (fns);
+ bool ok = mark_used (fn, complain);
+ if (!ok && !(complain & tf_error))
+ return error_mark_node;
+ if (ok && BASELINK_P (baselink))
+ /* We might have instantiated an auto function. */
+ TREE_TYPE (baselink) = TREE_TYPE (fn);
+ }
if (BASELINK_P (baselink))
{
if (is_template)
{
+ /* We may be repeating a check already done during parsing, but
+ if it was well-formed and passed then, it will pass again
+ now, and if it didn't, we wouldn't have got here. The case
+ we want to catch is when we couldn't tell then, and can now,
+ namely when templ prior to substitution was an
+ identifier. */
+ if (flag_concepts && check_auto_in_tmpl_args (expr, template_args))
+ return error_mark_node;
+
if (variable_template_p (expr))
expr = lookup_and_finish_template_variable (expr, template_args,
complain);
expanded = make_argument_pack (expanded);
if (TYPE_P (expanded))
- return cxx_sizeof_or_alignof_type (expanded, SIZEOF_EXPR,
+ return cxx_sizeof_or_alignof_type (expanded, SIZEOF_EXPR,
+ false,
complain & tf_error);
else
return cxx_sizeof_or_alignof_expr (expanded, SIZEOF_EXPR,
{
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);
+ r = build1 (code, type, op0);
+ if (code == ALIGNOF_EXPR)
+ ALIGNOF_EXPR_STD_P (r) = ALIGNOF_EXPR_STD_P (t);
+ return r;
}
case COMPONENT_REF:
case OMP_CLAUSE_INDEPENDENT:
case OMP_CLAUSE_AUTO:
case OMP_CLAUSE_SEQ:
+ case OMP_CLAUSE_IF_PRESENT:
+ case OMP_CLAUSE_FINALIZE:
break;
default:
gcc_unreachable ();
if (orig_declv && OMP_FOR_ORIG_DECLS (t))
{
tree o = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (t), i);
- TREE_VEC_ELT (orig_declv, i) = RECUR (o);
+ if (TREE_CODE (o) == TREE_LIST)
+ TREE_VEC_ELT (orig_declv, i)
+ = tree_cons (RECUR (TREE_PURPOSE (o)),
+ RECUR (TREE_VALUE (o)), NULL_TREE);
+ else
+ TREE_VEC_ELT (orig_declv, i) = RECUR (o);
}
decl = TREE_OPERAND (init, 0);
DECL_HAS_VALUE_EXPR_P (decl2) = 1;
if (VAR_P (decl3))
DECL_TEMPLATE_INSTANTIATED (decl3) = 1;
+ else
+ {
+ gcc_assert (errorcount);
+ decl = error_mark_node;
+ continue;
+ }
maybe_push_decl (decl3);
if (error_operand_p (decl3))
decl = error_mark_node;
else if (decl != error_mark_node
- && DECL_CHAIN (decl3) != prev)
+ && DECL_CHAIN (decl3) != prev
+ && decl != prev)
{
gcc_assert (errorcount);
decl = error_mark_node;
return t;
loc = input_location;
- if (EXPR_HAS_LOCATION (t))
- input_location = EXPR_LOCATION (t);
+ if (location_t eloc = cp_expr_location (t))
+ input_location = eloc;
if (STATEMENT_CODE_P (TREE_CODE (t)))
current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
register_local_specialization (inst, decl);
break;
}
+ else if (DECL_PRETTY_FUNCTION_P (decl))
+ decl = make_fname_decl (DECL_SOURCE_LOCATION (decl),
+ DECL_NAME (decl),
+ true/*DECL_PRETTY_FUNCTION_P (decl)*/);
else if (DECL_IMPLICIT_TYPEDEF_P (decl)
&& LAMBDA_TYPE_P (TREE_TYPE (decl)))
/* Don't copy the old closure; we'll create a new one in
do. */
if (VAR_P (decl))
DECL_TEMPLATE_INSTANTIATED (decl) = 1;
- if (VAR_P (decl)
+ if (VAR_P (decl) && !DECL_NAME (decl)
&& ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
/* Anonymous aggregates are a special case. */
finish_anon_union (decl);
else
{
int const_init = false;
+ unsigned int cnt = 0;
+ tree first = NULL_TREE, ndecl = error_mark_node;
maybe_push_decl (decl);
+
if (VAR_P (decl)
- && DECL_PRETTY_FUNCTION_P (decl))
- {
- /* For __PRETTY_FUNCTION__ we have to adjust the
- initializer. */
- const char *const name
- = cxx_printable_name (current_function_decl, 2);
- init = cp_fname_init (name, &TREE_TYPE (decl));
- }
- else
- init = tsubst_init (init, decl, args, complain, in_decl);
+ && DECL_DECOMPOSITION_P (decl)
+ && TREE_TYPE (pattern_decl) != error_mark_node)
+ ndecl = tsubst_decomp_names (decl, pattern_decl, args,
+ complain, in_decl, &first,
+ &cnt);
+
+ init = tsubst_init (init, decl, args, complain, in_decl);
if (VAR_P (decl))
const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P
(pattern_decl));
- if (VAR_P (decl)
- && DECL_DECOMPOSITION_P (decl)
- && TREE_TYPE (pattern_decl) != error_mark_node)
- {
- unsigned int cnt;
- tree first;
- tree ndecl
- = tsubst_decomp_names (decl, pattern_decl, args,
- complain, in_decl, &first, &cnt);
- if (ndecl != error_mark_node)
- cp_maybe_mangle_decomp (ndecl, first, cnt);
- cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
- if (ndecl != error_mark_node)
- cp_finish_decomp (ndecl, first, cnt);
- }
- else
- cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
+
+ if (ndecl != error_mark_node)
+ cp_maybe_mangle_decomp (ndecl, first, cnt);
+
+ cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
+
+ if (ndecl != error_mark_node)
+ cp_finish_decomp (ndecl, first, cnt);
}
}
}
stmt = (processing_template_decl
? begin_range_for_stmt (NULL_TREE, NULL_TREE)
: begin_for_stmt (NULL_TREE, NULL_TREE));
+ RECUR (RANGE_FOR_INIT_STMT (t));
decl = RANGE_FOR_DECL (t);
decl = tsubst (decl, args, complain, in_decl);
maybe_push_decl (decl);
RANGE_FOR_IVDEP (stmt) = RANGE_FOR_IVDEP (t);
RANGE_FOR_UNROLL (stmt) = RANGE_FOR_UNROLL (t);
finish_range_for_decl (stmt, decl, expr);
+ if (decomp_first && decl != error_mark_node)
+ cp_finish_decomp (decl, decomp_first, decomp_cnt);
}
else
{
case IF_STMT:
stmt = begin_if_stmt ();
IF_STMT_CONSTEXPR_P (stmt) = IF_STMT_CONSTEXPR_P (t);
+ if (IF_STMT_CONSTEXPR_P (t))
+ args = add_extra_args (IF_STMT_EXTRA_ARGS (t), args);
tmp = RECUR (IF_COND (t));
tmp = finish_if_stmt_cond (tmp, stmt);
+ if (IF_STMT_CONSTEXPR_P (t)
+ && instantiation_dependent_expression_p (tmp))
+ {
+ /* We're partially instantiating a generic lambda, but the condition
+ of the constexpr if is still dependent. Don't substitute into the
+ branches now, just remember the template arguments. */
+ do_poplevel (IF_SCOPE (stmt));
+ IF_COND (stmt) = IF_COND (t);
+ THEN_CLAUSE (stmt) = THEN_CLAUSE (t);
+ ELSE_CLAUSE (stmt) = ELSE_CLAUSE (t);
+ IF_STMT_EXTRA_ARGS (stmt) = build_extra_args (t, args, complain);
+ add_stmt (stmt);
+ break;
+ }
if (IF_STMT_CONSTEXPR_P (t) && integer_zerop (tmp))
/* Don't instantiate the THEN_CLAUSE. */;
else
{
- bool inhibit = integer_zerop (fold_non_dependent_expr (tmp));
+ tree folded = fold_non_dependent_expr (tmp, complain);
+ bool inhibit = integer_zerop (folded);
if (inhibit)
++c_inhibit_evaluation_warnings;
RECUR (THEN_CLAUSE (t));
/* Don't instantiate the ELSE_CLAUSE. */;
else if (ELSE_CLAUSE (t))
{
- bool inhibit = integer_nonzerop (fold_non_dependent_expr (tmp));
+ tree folded = fold_non_dependent_expr (tmp, complain);
+ bool inhibit = integer_nonzerop (folded);
begin_else_clause (stmt);
if (inhibit)
++c_inhibit_evaluation_warnings;
LAMBDA_EXPR_MUTABLE_P (r) = LAMBDA_EXPR_MUTABLE_P (t);
if (LAMBDA_EXPR_EXTRA_SCOPE (t) == NULL_TREE)
- LAMBDA_EXPR_EXTRA_SCOPE (r) = NULL_TREE;
+ /* A lambda in a default argument outside a class gets no
+ LAMBDA_EXPR_EXTRA_SCOPE, as specified by the ABI. But
+ tsubst_default_argument calls start_lambda_scope, so we need to
+ specifically ignore it here, and use the global scope. */
+ record_null_lambda_scope (r);
else
record_lambda_scope (r);
}
tree type = begin_lambda_type (r);
+ if (type == error_mark_node)
+ return error_mark_node;
/* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */
determine_visibility (TYPE_NAME (type));
register_parameter_specializations (oldfn, fn);
+ if (oldtmpl)
+ {
+ /* We might not partially instantiate some parts of the function, so
+ copy these flags from the original template. */
+ language_function *ol = DECL_STRUCT_FUNCTION (oldfn)->language;
+ current_function_returns_value = ol->returns_value;
+ current_function_returns_null = ol->returns_null;
+ current_function_returns_abnormally = ol->returns_abnormally;
+ current_function_infinite_loop = ol->infinite_loop;
+ }
+
tsubst_expr (DECL_SAVED_TREE (oldfn), args, complain, r,
/*constexpr*/false);
return t;
loc = input_location;
- if (EXPR_HAS_LOCATION (t))
- input_location = EXPR_LOCATION (t);
+ if (location_t eloc = cp_expr_location (t))
+ input_location = eloc;
/* N3276 decltype magic only applies to calls at the top level or on the
right side of a comma. */
if (targs)
targs = tsubst_template_args (targs, args, complain, in_decl);
if (targs == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
if (TREE_CODE (templ) == SCOPE_REF)
{
tree name = TREE_OPERAND (templ, 1);
tree tid = lookup_template_function (name, targs);
TREE_OPERAND (templ, 1) = tid;
- return templ;
+ RETURN (templ);
}
if (variable_template_p (templ))
{
tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
tree op0 = RECUR (TREE_OPERAND (t, 0));
+ if (op0 == error_mark_node)
+ RETURN (error_mark_node);
RETURN (build1 (CONVERT_EXPR, type, op0));
}
complain|decltype_flag));
case FIX_TRUNC_EXPR:
- RETURN (cp_build_unary_op (FIX_TRUNC_EXPR, RECUR (TREE_OPERAND (t, 0)),
- false, complain));
+ gcc_unreachable ();
case ADDR_EXPR:
op1 = TREE_OPERAND (t, 0);
{
tree op0 = RECUR (TREE_OPERAND (t, 0));
tree op1 = RECUR (TREE_OPERAND (t, 1));
- return fold_build_pointer_plus (op0, op1);
+ RETURN (fold_build_pointer_plus (op0, op1));
}
case SCOPE_REF:
op1 = TREE_OPERAND (t, 0);
if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
op1 = TREE_TYPE (op1);
+ bool std_alignof = (TREE_CODE (t) == ALIGNOF_EXPR
+ && ALIGNOF_EXPR_STD_P (t));
if (!args)
{
/* When there are no ARGS, we are trying to evaluate a
--c_inhibit_evaluation_warnings;
}
if (TYPE_P (op1))
- r = cxx_sizeof_or_alignof_type (op1, TREE_CODE (t),
+ r = cxx_sizeof_or_alignof_type (op1, TREE_CODE (t), std_alignof,
complain & tf_error);
else
r = cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
}
}
+ /* Avoid passing an enclosing decl to valid_array_size_p. */
+ in_decl = NULL_TREE;
+
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,
bool diag = true;
if (in_lambda)
- error_at (EXPR_LOC_OR_LOC (t, input_location),
+ error_at (cp_expr_loc_or_loc (t, input_location),
msg, function);
else
- diag = permerror (EXPR_LOC_OR_LOC (t, input_location),
+ diag = permerror (cp_expr_loc_or_loc (t, input_location),
msg, function);
if (diag)
{
/* Can't say anything more. */;
else if (DECL_CLASS_SCOPE_P (fn))
{
- location_t loc = EXPR_LOC_OR_LOC (t,
+ location_t loc = cp_expr_loc_or_loc (t,
input_location);
inform (loc,
"declarations in dependent base %qT are "
gcc_assert (nargs == 1);
if (vec_safe_length (call_args) != 1)
{
- error_at (EXPR_LOC_OR_LOC (t, input_location),
+ error_at (cp_expr_loc_or_loc (t, input_location),
"wrong number of arguments to "
"%<__builtin_launder%>");
ret = error_mark_node;
}
else
- ret = finish_builtin_launder (EXPR_LOC_OR_LOC (t,
+ ret = finish_builtin_launder (cp_expr_loc_or_loc (t,
input_location),
(*call_args)[0], complain);
break;
/* Unsupported internal function with arguments. */
gcc_unreachable ();
}
- else if (TREE_CODE (function) == OFFSET_REF)
+ else if (TREE_CODE (function) == OFFSET_REF
+ || TREE_CODE (function) == DOTSTAR_EXPR
+ || TREE_CODE (function) == MEMBER_REF)
ret = build_offset_ref_call_from_tree (function, &call_args,
complain);
else if (TREE_CODE (function) == COMPONENT_REF)
case COND_EXPR:
{
tree cond = RECUR (TREE_OPERAND (t, 0));
- tree folded_cond = fold_non_dependent_expr (cond);
+ cond = mark_rvalue_use (cond);
+ tree folded_cond = fold_non_dependent_expr (cond, complain);
tree exp1, exp2;
if (TREE_CODE (folded_cond) == INTEGER_CST)
else if (outer_automatic_var_p (r))
r = process_outer_var_ref (r, complain);
- if (TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE)
+ if (!TYPE_REF_P (TREE_TYPE (t)))
/* If the original type was a reference, we'll be wrapped in
the appropriate INDIRECT_REF. */
r = convert_from_reference (r);
static tree
instantiate_alias_template (tree tmpl, tree args, tsubst_flags_t complain)
{
- struct pending_template *old_last_pend = last_pending_template;
- struct tinst_level *old_error_tinst = last_error_tinst_level;
if (tmpl == error_mark_node || args == error_mark_node)
return error_mark_node;
- tree tinst = build_tree_list (tmpl, args);
- if (!push_tinst_level (tinst))
- {
- ggc_free (tinst);
- return error_mark_node;
- }
+ if (!push_tinst_level (tmpl, args))
+ return error_mark_node;
args =
coerce_innermost_template_parms (DECL_TEMPLATE_PARMS (tmpl),
tree r = instantiate_template (tmpl, args, complain);
pop_tinst_level ();
- /* We can't free this if a pending_template entry or last_error_tinst_level
- is pointing at it. */
- if (last_pending_template == old_last_pend
- && last_error_tinst_level == old_error_tinst)
- ggc_free (tinst);
return r;
}
return true;
}
+/* Subroutine of fn_type_unification: check non-dependent parms for
+ convertibility. */
+
+static int
+check_non_deducible_conversions (tree parms, const tree *args, unsigned nargs,
+ tree fn, unification_kind_t strict, int flags,
+ struct conversion **convs, bool explain_p)
+{
+ /* Non-constructor methods need to leave a conversion for 'this', which
+ isn't included in nargs here. */
+ unsigned offset = (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+ && !DECL_CONSTRUCTOR_P (fn));
+
+ for (unsigned ia = 0;
+ parms && parms != void_list_node && ia < nargs; )
+ {
+ tree 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;
+
+ if (!uses_template_parms (parm))
+ {
+ tree arg = args[ia];
+ conversion **conv_p = convs ? &convs[ia+offset] : NULL;
+ int lflags = conv_flags (ia, nargs, fn, arg, flags);
+
+ if (check_non_deducible_conversion (parm, arg, strict, lflags,
+ conv_p, explain_p))
+ return 1;
+ }
+
+ ++ia;
+ }
+
+ return 0;
+}
+
/* The FN is a TEMPLATE_DECL for a function. ARGS is an array with
NARGS elements of the arguments that are being used when calling
it. TARGS is a vector into which the deduced template arguments
tree return_type,
unification_kind_t strict,
int flags,
+ struct conversion **convs,
bool explain_p,
bool decltype_p)
{
tsubst_flags_t complain = (explain_p ? tf_warning_or_error : tf_none);
bool ok;
static int deduction_depth;
- struct pending_template *old_last_pend = last_pending_template;
- struct tinst_level *old_error_tinst = last_error_tinst_level;
tree orig_fn = fn;
if (flag_new_inheriting_ctors)
fn = strip_inheriting_ctors (fn);
tree tparms = DECL_INNERMOST_TEMPLATE_PARMS (fn);
- tree tinst;
tree r = error_mark_node;
tree full_targs = targs;
This is, of course, not reentrant. */
if (excessive_deduction_depth)
return error_mark_node;
- tinst = build_tree_list (fn, NULL_TREE);
++deduction_depth;
gcc_assert (TREE_CODE (fn) == TEMPLATE_DECL);
}
}
- TREE_VALUE (tinst) = explicit_targs;
- if (!push_tinst_level (tinst))
+ if (!push_tinst_level (fn, explicit_targs))
{
excessive_deduction_depth = true;
goto fail;
{
/* We're deducing for a call to the result of a template conversion
function. The parms we really want are in return_type. */
- if (POINTER_TYPE_P (return_type))
+ if (INDIRECT_TYPE_P (return_type))
return_type = TREE_TYPE (return_type);
parms = TYPE_ARG_TYPES (return_type);
}
callers must be ready to deal with unification failures in any
event. */
- TREE_VALUE (tinst) = targs;
/* If we aren't explaining yet, push tinst context so we can see where
any errors (e.g. from class instantiations triggered by instantiation
of default template arguments) come from. If we are explaining, this
context is redundant. */
- if (!explain_p && !push_tinst_level (tinst))
+ if (!explain_p && !push_tinst_level (fn, targs))
{
excessive_deduction_depth = true;
goto fail;
ok = !type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
full_targs, parms, args, nargs, /*subr=*/0,
- strict, flags, &checks, explain_p);
+ strict, &checks, explain_p);
if (!explain_p)
pop_tinst_level ();
if (!ok)
goto fail;
}
+ /* DR 1391: All parameters have args, now check non-dependent parms for
+ convertibility. */
+ if (check_non_deducible_conversions (parms, args, nargs, fn, strict, flags,
+ convs, explain_p))
+ goto fail;
+
/* All is well so far. Now, check:
[temp.deduct]
the corresponding deduced argument values. If the
substitution results in an invalid type, as described above,
type deduction fails. */
- TREE_VALUE (tinst) = targs;
- if (!push_tinst_level (tinst))
+ if (!push_tinst_level (fn, targs))
{
excessive_deduction_depth = true;
goto fail;
excessive_deduction_depth = false;
}
- /* We can't free this if a pending_template entry or last_error_tinst_level
- is pointing at it. */
- if (last_pending_template == old_last_pend
- && last_error_tinst_level == old_error_tinst)
- ggc_free (tinst);
-
return r;
}
/* Core issue #873: Do the DR606 thing (see below) for these cases,
too, but here handle it by stripping the reference from PARM
rather than by adding it to ARG. */
- if (TREE_CODE (*parm) == REFERENCE_TYPE
+ if (TYPE_REF_P (*parm)
&& TYPE_REF_IS_RVALUE (*parm)
&& TREE_CODE (TREE_TYPE (*parm)) == TEMPLATE_TYPE_PARM
&& cp_type_quals (TREE_TYPE (*parm)) == TYPE_UNQUALIFIED
- && TREE_CODE (*arg) == REFERENCE_TYPE
+ && TYPE_REF_P (*arg)
&& !TYPE_REF_IS_RVALUE (*arg))
*parm = TREE_TYPE (*parm);
/* Nothing else to do in this case. */
gcc_unreachable ();
}
- if (TREE_CODE (*parm) != REFERENCE_TYPE)
+ if (!TYPE_REF_P (*parm))
{
/* [temp.deduct.call]
deduction (13.3.1.8)). If P is a forwarding reference and the argument is
an lvalue, the type "lvalue reference to A" is used in place of A for type
deduction. */
- if (TREE_CODE (*parm) == REFERENCE_TYPE
+ if (TYPE_REF_P (*parm)
&& TYPE_REF_IS_RVALUE (*parm)
&& TREE_CODE (TREE_TYPE (*parm)) == TEMPLATE_TYPE_PARM
&& !TEMPLATE_TYPE_PARM_FOR_CLASS (TREE_TYPE (*parm))
reference type, the type referred to by P is used for
type deduction. */
*parm = TYPE_MAIN_VARIANT (*parm);
- if (TREE_CODE (*parm) == REFERENCE_TYPE)
+ if (TYPE_REF_P (*parm))
{
*parm = TREE_TYPE (*parm);
result |= UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
/* DR 322. For conversion deduction, remove a reference type on parm
too (which has been swapped into ARG). */
- if (strict == DEDUCE_CONV && TREE_CODE (*arg) == REFERENCE_TYPE)
+ if (strict == DEDUCE_CONV && TYPE_REF_P (*arg))
*arg = TREE_TYPE (*arg);
return result;
}
-/* Subroutine of unify_one_argument. PARM is a function parameter of a
- template which does contain any deducible template parameters; check if
+/* Subroutine of fn_type_unification. PARM is a function parameter of a
+ template which doesn't contain any deducible template parameters; check if
ARG is a suitable match for it. STRICT, FLAGS and EXPLAIN_P are as in
unify_one_argument. */
static int
check_non_deducible_conversion (tree parm, tree arg, int strict,
- int flags, bool explain_p)
+ int flags, struct conversion **conv_p,
+ bool explain_p)
{
tree type;
if (same_type_p (parm, type))
return unify_success (explain_p);
+ tsubst_flags_t complain = (explain_p ? tf_warning_or_error : tf_none);
if (strict == DEDUCE_CONV)
{
- if (can_convert_arg (type, parm, NULL_TREE, flags,
- explain_p ? tf_warning_or_error : tf_none))
+ if (can_convert_arg (type, parm, NULL_TREE, flags, complain))
return unify_success (explain_p);
}
else if (strict != DEDUCE_EXACT)
{
- if (can_convert_arg (parm, type,
- TYPE_P (arg) ? NULL_TREE : arg,
- flags, explain_p ? tf_warning_or_error : tf_none))
+ bool ok = false;
+ tree conv_arg = TYPE_P (arg) ? NULL_TREE : arg;
+ if (conv_p)
+ /* Avoid recalculating this in add_function_candidate. */
+ ok = (*conv_p
+ = good_conversion (parm, type, conv_arg, flags, complain));
+ else
+ ok = can_convert_arg (parm, type, conv_arg, flags, complain);
+ if (ok)
return unify_success (explain_p);
}
/* T*
T&
T&& */
- if (POINTER_TYPE_P (type))
+ if (INDIRECT_TYPE_P (type))
return uses_deducible_template_parms (TREE_TYPE (type));
/* T[integer-constant ]
unsigned int xnargs,
int subr,
unification_kind_t strict,
- int flags,
vec<deferred_access_check, va_gc> **checks,
bool explain_p)
{
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++)
{
if (targ || tparm == error_mark_node)
continue;
tree parm = TREE_VALUE (tparm);
-
- tsubst_flags_t fcomplain = complain;
- if (saw_undeduced == 1)
- {
- /* When saw_undeduced == 1, substitution into parm and arg might
- fail or not replace all template parameters, and that's
- fine. */
- fcomplain = tf_none;
- if (TREE_CODE (parm) == PARM_DECL
- && uses_template_parms (TREE_TYPE (parm)))
- 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, full_targs, fcomplain, NULL_TREE);
- if (arg != error_mark_node && !uses_template_parms (arg))
- arg = convert_template_argument (parm, arg, full_targs, complain,
- i, NULL_TREE);
- else if (saw_undeduced == 1)
- arg = NULL_TREE;
+
+ if (saw_undeduced == 1
+ && TREE_CODE (parm) == PARM_DECL
+ && uses_template_parms (TREE_TYPE (parm)))
+ {
+ /* The type of this non-type parameter depends on undeduced
+ parameters. Don't try to use its default argument yet,
+ since we might deduce an argument for it on the next pass,
+ but do check whether the arguments we already have cause
+ substitution failure, so that that happens before we try
+ later default arguments (78489). */
+ ++processing_template_decl;
+ tree type = tsubst (TREE_TYPE (parm), full_targs, complain,
+ NULL_TREE);
+ --processing_template_decl;
+ if (type == error_mark_node)
+ arg = error_mark_node;
+ else
+ arg = NULL_TREE;
+ }
else
- arg = error_mark_node;
+ {
+ tree substed = NULL_TREE;
+ if (saw_undeduced == 1 && processing_template_decl == 0)
+ {
+ /* First instatiate in template context, in case we still
+ depend on undeduced template parameters. */
+ ++processing_template_decl;
+ substed = tsubst_template_arg (arg, full_targs, complain,
+ NULL_TREE);
+ --processing_template_decl;
+ if (substed != error_mark_node
+ && !uses_template_parms (substed))
+ /* We replaced all the tparms, substitute again out of
+ template context. */
+ substed = NULL_TREE;
+ }
+ if (!substed)
+ substed = tsubst_template_arg (arg, full_targs, complain,
+ NULL_TREE);
+
+ if (!uses_template_parms (substed))
+ arg = convert_template_argument (parm, substed, full_targs,
+ complain, i, NULL_TREE);
+ else if (saw_undeduced == 1)
+ arg = NULL_TREE;
+ else
+ arg = error_mark_node;
+ }
+
input_location = save_loc;
*checks = get_deferred_access_checks ();
pop_deferring_access_checks ();
+
if (arg == error_mark_node)
return 1;
else if (arg)
types are not of the form "cv-list T" [14.8.2.5 temp.deduct.type].
It is ok when we're allowing additional CV qualifiers
at the outer level [14.8.2.1]/3,1st bullet. */
- if ((TREE_CODE (arg) == REFERENCE_TYPE
+ if ((TYPE_REF_P (arg)
|| TREE_CODE (arg) == FUNCTION_TYPE
|| TREE_CODE (arg) == METHOD_TYPE)
&& (parm_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)))
return 0;
- if ((!POINTER_TYPE_P (arg) && TREE_CODE (arg) != TEMPLATE_TYPE_PARM)
+ if ((!INDIRECT_TYPE_P (arg) && TREE_CODE (arg) != TEMPLATE_TYPE_PARM)
&& (parm_quals & TYPE_QUAL_RESTRICT))
return 0;
}
tree parm_pack = TREE_VALUE (pack);
int idx, level;
+ /* Only template parameter packs can be deduced, not e.g. function
+ parameter packs or __bases or __integer_pack. */
+ if (!TEMPLATE_PARM_P (parm_pack))
+ continue;
+
/* Determine the index and level of this parameter pack. */
template_parm_level_and_index (parm_pack, &level, &idx);
if (level < levels)
return unify_success (explain_p);
}
- FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
- {
- int elt_strict = strict;
+ if (strict != DEDUCE_EXACT
+ && TYPE_P (elttype)
+ && !uses_deducible_template_parms (elttype))
+ /* If ELTTYPE has no deducible template parms, skip deduction from
+ the list elements. */;
+ else
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
+ {
+ int elt_strict = strict;
- if (elt == error_mark_node)
- return unify_invalid (explain_p);
+ if (elt == error_mark_node)
+ return unify_invalid (explain_p);
- 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
- (DEDUCE_CALL, &elttype, &type, elt);
- elt = type;
- }
+ 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
+ (DEDUCE_CALL, &elttype, &type, elt);
+ elt = type;
+ }
RECUR_AND_CHECK_FAILURE (tparms, targs, elttype, elt, elt_strict,
explain_p);
template-parameter exactly, except that a template-argument
deduced from an array bound may be of any integral type.
The non-type parameter might use already deduced type parameters. */
- ++processing_template_decl;
- tparm = tsubst (TREE_TYPE (parm), targs, 0, NULL_TREE);
- --processing_template_decl;
- if (tree a = type_uses_auto (tparm))
+ tparm = TREE_TYPE (parm);
+ if (TEMPLATE_PARM_LEVEL (parm) > TMPL_ARGS_DEPTH (targs))
+ /* We don't have enough levels of args to do any substitution. This
+ can happen in the context of -fnew-ttp-matching. */;
+ else
{
- tparm = do_auto_deduction (tparm, arg, a, complain, adc_unify);
- if (tparm == error_mark_node)
- return 1;
+ ++processing_template_decl;
+ tparm = tsubst (tparm, targs, tf_none, NULL_TREE);
+ --processing_template_decl;
+
+ if (tree a = type_uses_auto (tparm))
+ {
+ tparm = do_auto_deduction (tparm, arg, a, complain, adc_unify);
+ if (tparm == error_mark_node)
+ return 1;
+ }
}
if (!TREE_TYPE (arg))
}
case REFERENCE_TYPE:
- if (TREE_CODE (arg) != REFERENCE_TYPE)
+ if (!TYPE_REF_P (arg))
return unify_type_mismatch (explain_p, parm, arg);
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
strict & UNIFY_ALLOW_MORE_CV_QUAL, explain_p);
if (type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
args, nargs, 1, DEDUCE_EXACT,
- LOOKUP_NORMAL, NULL, explain_p))
+ NULL, explain_p))
return 1;
if (flag_noexcept_type)
corresponding parameter is type-dependent. Make any necessary
adjustments based on whether arg is a reference. */
if (CONSTANT_CLASS_P (arg))
- parm = fold_non_dependent_expr (parm);
+ parm = fold_non_dependent_expr (parm, complain);
else if (REFERENCE_REF_P (arg))
{
tree sub = TREE_OPERAND (arg, 0);
linkonce sections. */
else if (TREE_PUBLIC (result))
maybe_make_one_only (result);
+ if (TREE_CODE (result) == FUNCTION_DECL
+ && DECL_TEMPLATE_INSTANTIATED (result))
+ /* If the function has already been instantiated, clear DECL_EXTERNAL,
+ since start_preparsed_function wouldn't have if we had an earlier
+ extern explicit instantiation. */
+ DECL_EXTERNAL (result) = 0;
}
/* If EXTERN_P, then this function will not be emitted -- unless
&& !uses_deducible_template_parms (arg2))
goto next;
- if (TREE_CODE (arg1) == REFERENCE_TYPE)
+ if (TYPE_REF_P (arg1))
{
ref1 = TYPE_REF_IS_RVALUE (arg1) + 1;
arg1 = TREE_TYPE (arg1);
quals1 = cp_type_quals (arg1);
}
- if (TREE_CODE (arg2) == REFERENCE_TYPE)
+ if (TYPE_REF_P (arg2))
{
ref2 = TYPE_REF_IS_RVALUE (arg2) + 1;
arg2 = TREE_TYPE (arg2);
args, ix,
(check_rettype || DECL_CONV_FN_P (fn)
? TREE_TYPE (decl_type) : NULL_TREE),
- DEDUCE_EXACT, LOOKUP_NORMAL, /*explain_p=*/false,
+ DEDUCE_EXACT, LOOKUP_NORMAL, NULL,
+ /*explain_p=*/false,
/*decltype*/false)
== error_mark_node)
return NULL_TREE;
return NULL_TREE;
}
- tree tinst = build_tree_list (spec_tmpl, deduced_args);
- if (!push_tinst_level (tinst))
+ if (!push_tinst_level (spec_tmpl, deduced_args))
{
excessive_deduction_depth = true;
return NULL_TREE;
error ("explicit instantiation of non-template %q#D", decl);
return;
}
+ else if (DECL_DECLARED_CONCEPT_P (decl))
+ {
+ if (VAR_P (decl))
+ error ("explicit instantiation of variable concept %q#D", decl);
+ else
+ error ("explicit instantiation of function concept %q#D", decl);
+ return;
+ }
bool var_templ = (DECL_TEMPLATE_INFO (decl)
&& variable_template_p (DECL_TI_TEMPLATE (decl)));
tree storage = *(tree *) data;
if (MAYBE_CLASS_TYPE_P (entry->type)
+ && CLASSTYPE_TEMPLATE_INFO (entry->type)
&& !uses_template_parms (CLASSTYPE_TI_ARGS (entry->type)))
do_type_instantiation (TYPE_MAIN_DECL (entry->type), storage, 0);
}
tree fntype, spec, noex, clone;
/* Don't instantiate a noexcept-specification from template context. */
- if (processing_template_decl)
+ if (processing_template_decl
+ && (!flag_noexcept_type || type_dependent_expression_p (fn)))
return true;
if (DECL_CLONED_FUNCTION_P (fn))
else if (!(added = !fns->add (fn)))
{
/* If hash_set::add returns true, the element was already there. */
- location_t loc = EXPR_LOC_OR_LOC (DEFERRED_NOEXCEPT_PATTERN (noex),
+ location_t loc = cp_expr_loc_or_loc (DEFERRED_NOEXCEPT_PATTERN (noex),
DECL_SOURCE_LOCATION (fn));
error_at (loc,
"exception specification of %qD depends on itself",
tf_warning_or_error, fn,
/*function_p=*/false,
/*integral_constant_expression_p=*/true);
+ spec = build_noexcept_spec (noex, tf_warning_or_error);
pop_deferring_access_checks ();
pop_access_scope (fn);
pop_tinst_level ();
- spec = build_noexcept_spec (noex, tf_warning_or_error);
if (spec == error_mark_node)
spec = noexcept_false_spec;
}
deleted_p = DECL_DELETED_FN (code_pattern);
pattern_defined = ((DECL_SAVED_TREE (code_pattern) != NULL_TREE
&& DECL_INITIAL (code_pattern) != error_mark_node)
- || DECL_DEFAULTED_OUTSIDE_CLASS_P (code_pattern)
+ || DECL_DEFAULTED_FN (code_pattern)
|| deleted_p);
}
else
bool push_to_top, nested;
tree fn_context;
fn_context = decl_function_context (d);
+ if (LAMBDA_FUNCTION_P (d))
+ /* tsubst_lambda_expr resolved any references to enclosing functions. */
+ fn_context = NULL_TREE;
nested = current_function_decl != NULL_TREE;
push_to_top = !(nested && fn_context == current_function_decl);
push_to_top_level ();
else
{
+ gcc_assert (!processing_template_decl);
push_function_context ();
cp_unevaluated_operand = 0;
c_inhibit_evaluation_warnings = 0;
to avoid infinite loop. */
if (pending_templates && retries >= max_tinst_depth)
{
- tree decl = pending_templates->tinst->decl;
+ tree decl = pending_templates->tinst->maybe_get_node ();
fatal_error (input_location,
"template instantiation depth exceeds maximum of %d"
}
if (complete)
- /* If INSTANTIATION has been instantiated, then we don't
- need to consider it again in the future. */
- *t = (*t)->next;
+ {
+ /* If INSTANTIATION has been instantiated, then we don't
+ need to consider it again in the future. */
+ struct pending_template *drop = *t;
+ *t = (*t)->next;
+ set_refcount_ptr (drop->tinst);
+ pending_template_freelist ().free (drop);
+ }
else
{
last = *t;
t = &(*t)->next;
}
tinst_depth = 0;
- current_tinst_level = NULL;
+ set_refcount_ptr (current_tinst_level);
}
last_pending_template = last;
}
void
record_last_problematic_instantiation (void)
{
- last_error_tinst_level = current_tinst_level;
+ set_refcount_ptr (last_error_tinst_level, current_tinst_level);
}
struct tinst_level *
instantiating_current_function_p (void)
{
return (current_instantiation ()
- && current_instantiation ()->decl == current_function_decl);
+ && (current_instantiation ()->maybe_get_node ()
+ == current_function_decl));
}
/* [temp.param] Check that template non-type parm TYPE is of an allowable
{
if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
return false;
- else if (POINTER_TYPE_P (type))
+ else if (TYPE_PTR_P (type))
+ return false;
+ else if (TYPE_REF_P (type)
+ && !TYPE_REF_IS_RVALUE (type))
return false;
else if (TYPE_PTRMEM_P (type))
return false;
return (dependent_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
|| dependent_type_p (TYPE_PTRMEM_POINTED_TO_TYPE
(type)));
- else if (TYPE_PTR_P (type)
- || TREE_CODE (type) == REFERENCE_TYPE)
+ else if (INDIRECT_TYPE_P (type))
return dependent_type_p (TREE_TYPE (type));
else if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
with an expression that is value-dependent. */
if (DECL_DEPENDENT_INIT_P (expression)
/* FIXME cp_finish_decl doesn't fold reference initializers. */
- || TREE_CODE (TREE_TYPE (expression)) == REFERENCE_TYPE)
+ || TYPE_REF_P (TREE_TYPE (expression)))
return true;
if (DECL_HAS_VALUE_EXPR_P (expression))
{
if (TREE_CODE (expression) == FUNCTION_DECL
&& !(DECL_CLASS_SCOPE_P (expression)
&& dependent_type_p (DECL_CONTEXT (expression)))
- && !(DECL_FRIEND_P (expression)
+ && !(DECL_LANG_SPECIFIC (expression)
+ && DECL_FRIEND_P (expression)
&& (!DECL_FRIEND_CONTEXT (expression)
|| dependent_type_p (DECL_FRIEND_CONTEXT (expression))))
&& !DECL_LOCAL_FUNCTION_P (expression))
TREE_TYPE. */
case TREE_LIST:
case TREE_VEC:
+ case NONTYPE_ARGUMENT_PACK:
return NULL_TREE;
case TEMPLATE_PARM_INDEX:
return false;
}
+/* Returns true if ARGS contains any errors. */
+
+bool
+any_erroneous_template_args_p (const_tree args)
+{
+ int i;
+ int j;
+
+ if (args == error_mark_node)
+ return true;
+
+ if (args && TREE_CODE (args) != TREE_VEC)
+ {
+ if (tree ti = get_template_info (args))
+ args = TI_ARGS (ti);
+ else
+ args = NULL_TREE;
+ }
+
+ if (!args)
+ return false;
+
+ for (i = 0; i < TMPL_ARGS_DEPTH (args); ++i)
+ {
+ const_tree level = TMPL_ARGS_LEVEL (args, i + 1);
+ for (j = 0; j < TREE_VEC_LENGTH (level); ++j)
+ if (error_operand_p (TREE_VEC_ELT (level, j)))
+ return true;
+ }
+
+ return false;
+}
+
/* Returns TRUE if the template TMPL is type-dependent. */
bool
gcc_assert (TREE_CODE (type) == TYPENAME_TYPE);
scope = TYPE_CONTEXT (type);
+ /* We shouldn't have built a TYPENAME_TYPE with a non-dependent scope. */
+ gcc_checking_assert (uses_template_parms (scope));
+
/* Usually the non-qualified identifier of a TYPENAME_TYPE is
TYPE_IDENTIFIER (type). But when 'type' is a typedef variant of
a TYPENAME_TYPE node, then TYPE_NAME (type) is set to the TYPE_DECL representing
/* scope is either the template itself or a compatible instantiation
like X<T>, so look up the name in the original template. */
scope = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope);
- /* We shouldn't have built a TYPENAME_TYPE with a non-dependent scope. */
- gcc_checking_assert (uses_template_parms (scope));
/* If scope has no fields, it can't be a current instantiation. Check this
before currently_open_class to avoid infinite recursion (71515). */
if (!TYPE_FIELDS (scope))
[temp.names]: In a qualified-id of a declarator-id, the keyword
template shall not appear at the top level. */
- pedwarn (EXPR_LOC_OR_LOC (fullname, input_location), OPT_Wpedantic,
+ pedwarn (cp_expr_loc_or_loc (fullname, input_location), OPT_Wpedantic,
"keyword %<template%> not allowed in declarator-id");
tmpl = decl;
}
/* Don't do this during concept expansion either and for
the same reason. */
&& !expanding_concept ())
- fold_non_dependent_expr (expr);
+ fold_non_dependent_expr (expr, tf_none);
STRIP_ANY_LOCATION_WRAPPER (expr);
if (is_overloaded_fn (inner_expr)
|| TREE_CODE (inner_expr) == OFFSET_REF)
return orig_expr;
- /* There is no need to return a proxy for a variable. */
- if (VAR_P (expr))
+ /* There is no need to return a proxy for a variable or enumerator. */
+ if (VAR_P (expr) || TREE_CODE (expr) == CONST_DECL)
return orig_expr;
/* Preserve string constants; conversions from string constants to
"char *" are allowed, even though normally a "const char *"
gcc_assert (TREE_TYPE (expr) != unknown_type_node);
/* Otherwise, build a NON_DEPENDENT_EXPR. */
- return build1 (NON_DEPENDENT_EXPR, TREE_TYPE (expr), expr);
+ return build1_loc (EXPR_LOCATION (orig_expr), NON_DEPENDENT_EXPR,
+ TREE_TYPE (expr), expr);
}
/* ARGS is a vector of expressions as arguments to a function call.
if (!std_init_list || !DECL_CLASS_TEMPLATE_P (std_init_list))
{
gcc_rich_location richloc (input_location);
- maybe_add_include_fixit (&richloc, "<initializer_list>");
+ maybe_add_include_fixit (&richloc, "<initializer_list>", false);
error_at (&richloc,
"deducing from brace-enclosed initializer list"
" requires %<#include <initializer_list>%>");
inline hashval_t
auto_hash::hash (tree t)
{
- if (tree c = PLACEHOLDER_TYPE_CONSTRAINTS (t))
+ if (tree c = NON_ERROR (PLACEHOLDER_TYPE_CONSTRAINTS (t)))
/* Matching constrained-type-specifiers denote the same template
parameter, so hash the constraint. */
return hash_placeholder_constraint (c);
rewrite_template_parm (tree olddecl, unsigned index, unsigned level,
tree tsubst_args, tsubst_flags_t complain)
{
+ if (olddecl == error_mark_node)
+ return error_mark_node;
+
tree oldidx = get_template_parm_index (olddecl);
tree newtype;
= TEMPLATE_TYPE_PARM_FOR_CLASS (oldtype);
}
else
- newtype = tsubst (TREE_TYPE (olddecl), tsubst_args,
- complain, NULL_TREE);
+ {
+ newtype = TREE_TYPE (olddecl);
+ if (type_uses_auto (newtype))
+ {
+ // Substitute once to fix references to other template parameters.
+ newtype = tsubst (newtype, tsubst_args,
+ complain|tf_partial, NULL_TREE);
+ // Now substitute again to reduce the level of the auto.
+ newtype = tsubst (newtype, current_template_args (),
+ complain, NULL_TREE);
+ }
+ else
+ newtype = tsubst (newtype, tsubst_args,
+ complain, NULL_TREE);
+ }
tree newdecl
= build_decl (DECL_SOURCE_LOCATION (olddecl), TREE_CODE (olddecl),
if (TYPE_P (ctor))
{
type = ctor;
- bool copy_p = TREE_CODE (type) == REFERENCE_TYPE;
+ bool copy_p = TYPE_REF_P (type);
if (copy_p)
{
type = TREE_TYPE (type);
else
{
++processing_template_decl;
+ bool ok = true;
fn_tmpl
= (TREE_CODE (ctor) == TEMPLATE_DECL ? ctor
tree olddecl = TREE_VALUE (oldelt);
tree newdecl = rewrite_template_parm (olddecl, index, level,
tsubst_args, complain);
+ if (newdecl == error_mark_node)
+ ok = false;
tree newdef = tsubst_template_arg (TREE_PURPOSE (oldelt),
tsubst_args, complain, ctor);
tree list = build_tree_list (newdef, newdecl);
current_template_parms = save_parms;
}
+
--processing_template_decl;
+ if (!ok)
+ return error_mark_node;
}
if (!memtmpl)
// FIXME cache artificial deduction guides
for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (type)); iter; ++iter)
{
+ /* Skip inherited constructors. */
+ if (iter.using_p ())
+ continue;
+
tree guide = build_deduction_guide (*iter, outer_args, complain);
+ if (guide == error_mark_node)
+ return error_mark_node;
if ((flags & LOOKUP_ONLYCONVERTING)
&& DECL_NONCONVERTING_P (STRIP_TEMPLATE (guide)))
elided = true;
if (gtype)
{
tree guide = build_deduction_guide (gtype, outer_args, complain);
+ if (guide == error_mark_node)
+ return error_mark_node;
cands = lookup_add (guide, cands);
}
}
targs = make_tree_vec (TREE_VEC_LENGTH (tparms));
int val = type_unification_real (tparms, targs, parms, &init, 1, 0,
- DEDUCE_CALL, LOOKUP_NORMAL,
+ DEDUCE_CALL,
NULL, /*explain_p=*/false);
if (val > 0)
{
else
error ("unable to deduce %qT from %qE", type, init);
type_unification_real (tparms, targs, parms, &init, 1, 0,
- DEDUCE_CALL, LOOKUP_NORMAL,
+ DEDUCE_CALL,
NULL, /*explain_p=*/true);
}
return error_mark_node;
/* Check any placeholder constraints against the deduced type. */
if (flag_concepts && !processing_template_decl)
- if (tree constr = PLACEHOLDER_TYPE_CONSTRAINTS (auto_node))
+ if (tree constr = NON_ERROR (PLACEHOLDER_TYPE_CONSTRAINTS (auto_node)))
{
/* Use the deduced type to check the associated constraints. If we
have a partial-concept-id, rebuild the argument list so that
{
if (complain & tf_warning_or_error)
{
+ auto_diagnostic_group d;
switch (context)
{
case adc_unspecified:
them. */
if (uses_template_parms (type))
return for_each_template_parm (type, is_auto_r, /*data*/NULL,
- /*visited*/NULL, /*nondeduced*/true);
+ /*visited*/NULL, /*nondeduced*/false);
else
return NULL_TREE;
}
return find_type_usage (type, is_auto);
}
+/* Report ill-formed occurrences of auto types in ARGUMENTS. If
+ concepts are enabled, auto is acceptable in template arguments, but
+ only when TEMPL identifies a template class. Return TRUE if any
+ such errors were reported. */
+
+bool
+check_auto_in_tmpl_args (tree tmpl, tree args)
+{
+ /* If there were previous errors, nevermind. */
+ if (!args || TREE_CODE (args) != TREE_VEC)
+ return false;
+
+ /* If TMPL is an identifier, we're parsing and we can't tell yet
+ whether TMPL is supposed to be a type, a function or a variable.
+ We'll only be able to tell during template substitution, so we
+ expect to be called again then. If concepts are enabled and we
+ know we have a type, we're ok. */
+ if (flag_concepts
+ && (identifier_p (tmpl)
+ || (DECL_P (tmpl)
+ && (DECL_TYPE_TEMPLATE_P (tmpl)
+ || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)))))
+ return false;
+
+ /* Quickly search for any occurrences of auto; usually there won't
+ be any, and then we'll avoid allocating the vector. */
+ if (!type_uses_auto (args))
+ return false;
+
+ bool errors = false;
+
+ tree vec = extract_autos (args);
+ for (int i = 0; i < TREE_VEC_LENGTH (vec); i++)
+ {
+ tree xauto = TREE_VALUE (TREE_VEC_ELT (vec, i));
+ error_at (DECL_SOURCE_LOCATION (xauto),
+ "invalid use of %qT in template argument", xauto);
+ errors = true;
+ }
+
+ return errors;
+}
+
/* For a given template T, return the vector of typedefs referenced
in T for which access check is needed at T instantiation time.
T is either a FUNCTION_DECL or a RECORD_TYPE.
NULL_TREE, ECF_CONST);
DECL_DECLARED_CONSTEXPR_P (ipfn) = true;
DECL_BUILT_IN_CLASS (ipfn) = BUILT_IN_FRONTEND;
+ DECL_FUNCTION_CODE (ipfn)
+ = (enum built_in_function) (int) CP_BUILT_IN_INTEGER_PACK;
}
/* Set up the hash tables for template instantiations. */