Commit 56e0346d by Jason Merrill Committed by Jason Merrill

PR c++/92268 - hard error satisfying return-type-requirement

Previously we would put the template arguments for the concept-check in a
TEMPLATE_ID and then also pass them to constraints_satisfied_p, which meant
that we would try to normalize the concept-check with the fully instantiated
arguments, leading to sadness.  Simply not passing the args to
constraints_satisfied_p fixes the problem.

I also noticed that we weren't detecting substitution failure in the
constraints, but were silently treating it as success.

	* constraint.cc (type_deducible_p): Check for substitution failure.
	(diagnose_compound_requirement): Adjust diagnostic.
	* pt.c (do_auto_deduction): Don't pass cargs to
	constraints_satisfied_p.

From-SVN: r277654
parent d11368e6
2019-10-30 Jason Merrill <jason@redhat.com>
PR c++/92268 - hard error satisfying return-type-requirement
* constraint.cc (type_deducible_p): Check for substitution failure.
(diagnose_compound_requirement): Adjust diagnostic.
* pt.c (do_auto_deduction): Don't pass cargs to
constraints_satisfied_p.
2019-10-30 Jakub Jelinek <jakub@redhat.com>
PR c++/91369 - Implement P0784R7: constexpr new
......
......@@ -1822,10 +1822,7 @@ tsubst_type_requirement (tree t, tree args, subst_info info)
return finish_type_requirement (EXPR_LOCATION (t), type);
}
/* True if TYPE can be deduced from EXPR.
FIXME: C++20 compound requirement constraints should be normalized and then
satisfied rather than substituted. */
/* True if TYPE can be deduced from EXPR. */
static bool
type_deducible_p (tree expr, tree type, tree placeholder, tree args,
......@@ -1839,12 +1836,17 @@ type_deducible_p (tree expr, tree type, tree placeholder, tree args,
substitutes args into any template parameters in the trailing
result type. */
tree saved_constr = PLACEHOLDER_TYPE_CONSTRAINTS (placeholder);
PLACEHOLDER_TYPE_CONSTRAINTS (placeholder)
tree subst_constr
= tsubst_constraint (saved_constr,
args,
info.complain | tf_partial,
info.in_decl);
if (subst_constr == error_mark_node)
return false;
PLACEHOLDER_TYPE_CONSTRAINTS (placeholder) = subst_constr;
/* Temporarily unlink the canonical type. */
tree saved_type = TYPE_CANONICAL (placeholder);
TYPE_CANONICAL (placeholder) = NULL_TREE;
......@@ -3139,7 +3141,8 @@ diagnose_compound_requirement (tree req, tree args, tree in_decl)
if (!type_deducible_p (expr, type, placeholder, args, quiet))
{
tree orig_expr = TREE_OPERAND (req, 0);
inform (loc, "type deduction from %qE failed", orig_expr);
inform (loc, "%qE does not satisfy return-type-requirement",
orig_expr);
/* Further explain the reason for the error. */
type_deducible_p (expr, type, placeholder, args, noisy);
......
......@@ -28138,7 +28138,7 @@ do_auto_deduction (tree type, tree init, tree auto_node,
/* Rebuild the check using the deduced arguments. */
check = build_concept_check (cdecl, cargs, tf_none);
if (!constraints_satisfied_p (check, cargs))
if (!constraints_satisfied_p (check))
{
if (complain & tf_warning_or_error)
{
......
......@@ -8,12 +8,12 @@ concept bool SameAs = __is_same_as(T, U);
template <class T>
concept bool R1 = requires (T& t) { // { dg-message "in requirements" }
{ t.begin() } -> T; // { dg-error "no match" }
{ t.end() } -> SameAs<T*>; // { dg-error "does not satisfy" }
{ t.end() } -> SameAs<T*>; // { dg-message "does not satisfy" }
};
template <class T>
concept bool R2 = requires (T& t) { // { dg-message "in requirements" }
{ t.end() } -> SameAs<T*>; // { dg-error "does not satisfy" }
{ t.end() } -> SameAs<T*>; // { dg-message "does not satisfy" }
};
struct foo {
......
......@@ -8,7 +8,7 @@ concept bool Same = __is_same_as(T, U);
template <class T>
concept bool C =
requires { // { dg-message "in requirements" }
{ 0 } -> Same<T>; // { dg-error "does not satisfy" }
{ 0 } -> Same<T>; // { dg-message "does not satisfy" }
};
template <C c>
......
......@@ -8,7 +8,7 @@ concept bool Same = __is_same_as(T, U);
template <class T>
concept bool C =
requires { // { dg-message "in requirements" }
{ 0 } -> Same<T>; // { dg-error "does not satisfy" }
{ 0 } -> Same<T>; // { dg-message "does not satisfy" }
};
template <class T>
......
......@@ -12,7 +12,7 @@ concept C0 = requires (auto x) { // { dg-error "placeholder type" }
template<typename T>
concept C1 = requires (C1 auto x) { // { dg-error "not been declared|placeholder|two or more|in requirements" }
x; // { dg-error "not declared" }
{ x } -> c; // { dg-error "not declared|does not satisfy" }
{ x } -> c; // { dg-message "not declared|does not satisfy" }
};
template<typename T>
......
......@@ -10,7 +10,7 @@ concept SameAs = __is_same_as(T, U);
template <typename T>
concept C1 = requires(T t) { // { dg-message "in requirements" }
{ t } -> SameAs<T>; // NOTE: t deduced as decltype((t))
// { dg-error "does not satisfy placeholder constraints" "" { target *-*-* } .-1 }
// { dg-message "does not satisfy" "" { target *-*-* } .-1 }
};
template <typename T>
......
// PR c++/92268
// { dg-do compile { target c++2a } }
template <class T> concept Two = true;
template <class T> concept One = Two<typename T::type>;
template <class T> concept Zero = requires
{
{ T() } -> One;
};
template <class T>
void f() requires Zero<T>;
template <class T>
int f(...);
int main()
{
f<int>();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment