+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
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,
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;
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);
/* 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)
{
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 {
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>
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>
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>
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>
--- /dev/null
+// 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>();
+}