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;
}
}
}
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))
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;
}
&& 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",
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);
}
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. */
{
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;
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
error ("use of invalid variable template %qE", var);
diagnose_constraints (location_of (var), templ, arglist);
}
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
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);
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
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
{
/* 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;
{
tree cond = RECUR (TREE_OPERAND (t, 0));
cond = mark_rvalue_use (cond);
- tree folded_cond = fold_non_dependent_expr (cond);
+ tree folded_cond = fold_non_dependent_expr (cond, complain);
tree exp1, exp2;
if (TREE_CODE (folded_cond) == INTEGER_CST)
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)
{
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]
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);
}
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;
-
- if (BRACE_ENCLOSED_INITIALIZER_P (arg)
- && (TREE_CODE (parm) == ARRAY_TYPE || is_std_init_list (parm)))
- {
- tree elt, elttype;
- unsigned int i;
-
- if (TREE_CODE (parm) == ARRAY_TYPE)
- elttype = TREE_TYPE (parm);
- else
- elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (parm), 0);
- FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
- if (check_non_deducible_conversion (elttype, elt, strict,
- flags, explain_p))
- return 1;
- }
- }
-
/* Now substitute into the default template arguments. */
for (i = 0; i < ntparms; i++)
{
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);
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;
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)));
/* 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 (!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);
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:
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. */