This makes mark_used check constraints of a function _before_ calling maybe_instantiate_decl, so that we don't try instantiating a function (as part of return type deduction) with unsatisfied constraints.
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk and perhaps the 10 branch? gcc/cp/ChangeLog: PR c++/95132 * decl2.c (mark_used): Move up the constraints_satisfied_p check so that it happens before calling maybe_instantiate_decl. gcc/testsuite/ChangeLog: PR c++/95132 * g++.dg/cpp2a/concepts-fn7.C: New test. --- gcc/cp/decl2.c | 30 +++++++++++------------ gcc/testsuite/g++.dg/cpp2a/concepts-fn7.C | 11 +++++++++ 2 files changed, 26 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-fn7.C diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 2f0d6370146..de2956aa5f0 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -5604,6 +5604,21 @@ mark_used (tree decl, tsubst_flags_t complain) if (DECL_ODR_USED (decl)) return true; + if (flag_concepts && TREE_CODE (decl) == FUNCTION_DECL + && !constraints_satisfied_p (decl)) + { + if (complain & tf_error) + { + auto_diagnostic_group d; + error ("use of function %qD with unsatisfied constraints", + decl); + location_t loc = DECL_SOURCE_LOCATION (decl); + inform (loc, "declared here"); + diagnose_constraints (loc, decl, NULL_TREE); + } + return false; + } + /* Normally, we can wait until instantiation-time to synthesize DECL. However, if DECL is a static data member initialized with a constant or a constexpr function, we need it right now because a reference to @@ -5614,21 +5629,6 @@ mark_used (tree decl, tsubst_flags_t complain) directly. */ maybe_instantiate_decl (decl); - if (flag_concepts && TREE_CODE (decl) == FUNCTION_DECL - && !constraints_satisfied_p (decl)) - { - if (complain & tf_error) - { - auto_diagnostic_group d; - error ("use of function %qD with unsatisfied constraints", - decl); - location_t loc = DECL_SOURCE_LOCATION (decl); - inform (loc, "declared here"); - diagnose_constraints (loc, decl, NULL_TREE); - } - return false; - } - if (processing_template_decl || in_template_function ()) return true; diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-fn7.C b/gcc/testsuite/g++.dg/cpp2a/concepts-fn7.C new file mode 100644 index 00000000000..7fad6f374b7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-fn7.C @@ -0,0 +1,11 @@ +// PR c++/95132 +// { dg-do compile { target c++20 } } + +template<typename T> struct A { + static auto f() requires false { return T::fail; } +}; + +template<typename T> +constexpr bool v = requires { A<T>::f(); }; + +static_assert(!v<int>); -- 2.29.0.rc0