Corentin Jabot f9caa12328 [Clang] Fix constraint checking of non-generic lambdas.
A lambda call operator can be a templated entity -
and therefore have constraints while not being a function template

   template<class T> void f() {
     []() requires false { }();
   }

In that case, we would check the constraints of the call operator
which is non-viable. However, we would find a viable candidate:
the conversion operator to function pointer, and use it to
perform a surrogate call.
These constraints were not checked because:
 * We never check the constraints of surrogate functions
 * The lambda conversion operator has non constraints.

From the wording, it is not clear what the intent is but
it seems reasonable to expect the constraints of the lambda conversion
operator to be checked and it is consistent with GCC and MSVC.

This patch also improve the diagnostics for constraint failure
on surrogate calls.

Fixes #63181

Reviewed By: #clang-language-wg, aaron.ballman

Differential Revision: https://reviews.llvm.org/D154368
2023-07-21 10:59:36 +02:00

997 lines
34 KiB
C++

// RUN: %clang_cc1 -std=c++20 -verify %s
namespace PR47043 {
template<typename T> concept True = true;
template<typename ...T> concept AllTrue1 = True<T>; // expected-error {{expression contains unexpanded parameter pack 'T'}}
template<typename ...T> concept AllTrue2 = (True<T> && ...);
template<typename ...T> concept AllTrue3 = (bool)(True<T> & ...);
static_assert(AllTrue2<int, float, char>);
static_assert(AllTrue3<int, float, char>);
}
namespace PR47025 {
template<typename ...T> concept AllAddable1 = requires(T ...t) { (void(t + 1), ...); };
template<typename ...T> concept AllAddable2 = (requires(T ...t) { (t + 1); } && ...); // expected-error {{requirement contains unexpanded parameter pack 't'}}
template<typename ...T> concept AllAddable3 = (requires(T t) { (t + 1); } && ...);
template<typename ...T> concept AllAddable4 = requires(T t) { (t + 1); }; // expected-error {{expression contains unexpanded parameter pack 'T'}}
template<typename ...T> concept AllAddable5 = requires(T t) { (void(t + 1), ...); }; // expected-error {{does not contain any unexpanded}}
template<typename ...T> concept AllAddable6 = (requires { (T() + 1); } && ...);
template<typename ...T> concept AllAddable7 = requires { (T() + 1); }; // expected-error {{expression contains unexpanded parameter pack 'T'}}
static_assert(AllAddable1<int, float>);
static_assert(AllAddable3<int, float>);
static_assert(AllAddable6<int, float>);
static_assert(!AllAddable1<int, void>);
static_assert(!AllAddable3<int, void>);
static_assert(!AllAddable6<int, void>);
}
namespace PR45699 {
template<class> concept C = true; // expected-note 2{{here}}
template<class ...Ts> void f1a() requires C<Ts>; // expected-error {{requires clause contains unexpanded parameter pack 'Ts'}}
template<class ...Ts> requires C<Ts> void f1b(); // expected-error {{requires clause contains unexpanded parameter pack 'Ts'}}
template<class ...Ts> void f2a() requires (C<Ts> && ...);
template<class ...Ts> requires (C<Ts> && ...) void f2b();
template<class ...Ts> void f3a() requires C<Ts...>; // expected-error {{pack expansion used as argument for non-pack parameter of concept}}
template<class ...Ts> requires C<Ts...> void f3b(); // expected-error {{pack expansion used as argument for non-pack parameter of concept}}
template<class ...Ts> void f4() {
([] () requires C<Ts> {} ()); // expected-error {{expression contains unexpanded parameter pack 'Ts'}}
([]<int = 0> requires C<Ts> () {} ()); // expected-error {{expression contains unexpanded parameter pack 'Ts'}}
}
template<class ...Ts> void f5() {
([] () requires C<Ts> {} (), ...);
([]<int = 0> requires C<Ts> () {} (), ...);
}
void g() {
f1a();
f1b(); // FIXME: Bad error recovery. expected-error {{undeclared identifier}}
f2a();
f2b();
f3a();
f3b(); // FIXME: Bad error recovery. expected-error {{undeclared identifier}}
f4();
f5();
}
}
namespace P0857R0 {
template <typename T> static constexpr bool V = true;
void f() {
auto x = []<bool B> requires B {}; // expected-note {{constraints not satisfied}} expected-note {{false}}
x.operator()<true>();
x.operator()<false>(); // expected-error {{no matching member function}}
auto y = []<typename T> requires V<T> () {};
y.operator()<int>(); // OK
}
template<typename T> concept C = true;
template<template<typename T> requires C<T> typename U> struct X {};
template<typename T> requires C<T> struct Y {};
X<Y> xy;
}
namespace PR50306 {
template<typename T> concept NotInt = sizeof(T) != sizeof(int); // expected-note {{because}}
template<typename T> void f() {
[](NotInt auto) {}(T()); // expected-error {{no matching function}} expected-note {{constraints not satisfied}} expected-note {{because}}
}
template void f<char>(); // OK
template void f<int>(); // expected-note {{in instantiation of}}
}
namespace PackInTypeConstraint {
template<typename T, typename U> concept C = sizeof(T) == sizeof(int); // expected-note 3{{}}
template<typename ...T, C<T> U> void h1(); // expected-error {{type constraint contains unexpanded parameter pack 'T'}}
template<typename ...T, C<T> ...U> void h2();
template<typename ...T> void h3(C<T> auto); // expected-error {{type constraint contains unexpanded parameter pack 'T'}}
template<typename ...T> void h4(C<T> auto...);
template<typename ...T> void f1() {
[]<C<T> U>(U u){}(T()); // expected-error {{unexpanded parameter pack 'T'}}
}
template<typename ...T> void f2() {
([]<C<T> U>(U u){}(T()), ...); // expected-error {{no match}} expected-note 2{{}}
}
template void f2<int, int, int>(); // OK
template void f2<int, char, double>(); // expected-note {{in instantiation of}}
void f3() {
([]<typename ...T, C<T> U>(U u){}(0), // expected-error {{type constraint contains unexpanded parameter pack 'T'}}
...); // expected-error {{does not contain any unexpanded}}
}
template<typename ...T> void g1() {
[](C<T> auto){}(T()); // expected-error {{expression contains unexpanded parameter pack 'T'}}
}
template<typename ...T> void g2() {
([](C<T> auto){}(T()), ...); // expected-error {{no matching function}} expected-note {{constraints not satisfied}} expected-note {{because}}
}
template void g2<int, int, int>(); // OK
template void g2<int, char, double>(); // expected-note {{in instantiation of}}
void g3() {
([]<typename ...T>(C<T> auto){}(1), // expected-error {{type constraint contains unexpanded parameter pack 'T'}}
...); // expected-error {{does not contain any unexpanded}}
}
template<typename ...T> void g4() {
[]() -> C<T> auto{ return T(); }(); // expected-error {{expression contains unexpanded parameter pack 'T'}}
}
template<typename ...T> void g5() {
([]() -> C<T> auto{ // expected-error-re {{deduced type {{.*}} does not satisfy}} expected-note {{while substituting into a lambda}}
return T();
}(), ...);
}
template void g5<int, int, int>(); // OK
template void g5<int, char, double>(); // expected-note {{in instantiation of}}
void g6() {
([]<typename ...T>() -> C<T> auto{ // expected-error {{declaration type contains unexpanded parameter pack 'T'}}
return T(); // expected-error {{expression contains unexpanded parameter pack 'T'}}
}(),
...); // expected-error {{does not contain any unexpanded}}
}
}
namespace BuiltinIsConstantEvaluated {
// Check that we do all satisfaction and diagnostic checks in a constant context.
template<typename T> concept C = __builtin_is_constant_evaluated(); // expected-warning {{always}}
static_assert(C<int>);
template<typename T> concept D = __builtin_is_constant_evaluated() == true; // expected-warning {{always}}
static_assert(D<int>);
template<typename T> concept E = __builtin_is_constant_evaluated() == true && // expected-warning {{always}}
false; // expected-note {{'false' evaluated to false}}
static_assert(E<int>); // expected-error {{failed}} expected-note {{because 'int' does not satisfy 'E'}}
template<typename T> concept F = __builtin_is_constant_evaluated() == false; // expected-warning {{always}}
// expected-note@-1 {{'__builtin_is_constant_evaluated() == false' (1 == 0)}}
static_assert(F<int>); // expected-error {{failed}} expected-note {{because 'int' does not satisfy 'F'}}
template<typename T> concept G = __builtin_is_constant_evaluated() && // expected-warning {{always}}
false; // expected-note {{'false' evaluated to false}}
static_assert(G<int>); // expected-error {{failed}} expected-note {{because 'int' does not satisfy 'G'}}
}
namespace NoConstantFolding {
// Ensure we use strict constant evaluation rules when checking satisfaction.
int n;
template <class T> concept C = &n + 3 - 3 == &n; // expected-error {{non-constant expression}} expected-note {{cannot refer to element 3 of non-array object}}
static_assert(C<void>); // expected-note {{while checking}}
}
namespace PR50337 {
template <typename T> concept foo = true;
template <typename T> concept foo2 = foo<T> && true;
void f(foo auto, auto);
void f(foo2 auto, auto);
void g() { f(1, 2); }
}
namespace PR50561 {
template<typename> concept C = false;
template<typename T, typename U> void f(T, U);
template<C T, typename U> void f(T, U) = delete;
void g() { f(0, 0); }
}
namespace PR49188 {
template<class T> concept C = false; // expected-note 7 {{because 'false' evaluated to false}}
C auto f1() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
return void();
}
C auto f2() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
return;
}
C auto f3() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
}
C decltype(auto) f4() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
return void();
}
C decltype(auto) f5() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
return;
}
C decltype(auto) f6() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
}
C auto& f7() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
return void();
}
C auto& f8() {
return; // expected-error {{cannot deduce return type 'C auto &' from omitted return expression}}
}
C auto& f9() { // expected-error {{cannot deduce return type 'C auto &' for function with no return statements}}
}
}
namespace PR53911 {
template<class T> concept C = false; // expected-note 3 {{because 'false' evaluated to false}}
C auto *f1() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
return (void*)nullptr;
}
C auto *f2() { // expected-error {{deduced type 'int' does not satisfy 'C'}}
return (int*)nullptr;
}
C auto *****f3() { // expected-error {{deduced type 'int' does not satisfy 'C'}}
return (int*****)nullptr;
}
}
namespace PR54379 {
template <int N>
struct A {
static void f() requires (N == 0) { return; } // expected-note {{candidate template ignored: constraints not satisfied}} expected-note {{evaluated to false}}
static void f() requires (N == 1) { return; } // expected-note {{candidate template ignored: constraints not satisfied}} expected-note {{evaluated to false}}
};
void (*f1)() = A<2>::f; // expected-error {{address of overloaded function 'f' does not match required type}}
struct B {
template <int N2 = 1> static void f() requires (N2 == 0) { return; } // expected-note {{candidate template ignored: constraints not satisfied [with N2 = 1]}} expected-note {{evaluated to false}}
};
void (*f2)() = B::f; // expected-error {{address of overloaded function 'f' does not match required type}}
}
namespace PR54443 {
template <class T, class U>
struct is_same { static constexpr bool value = false; };
template <class T>
struct is_same<T, T> { static constexpr bool value = true; };
template <class T, class U>
concept same_as = is_same<T, U>::value; // expected-note-re 4 {{because {{.*}} evaluated to false}}
int const &f();
same_as<int const> auto i1 = f(); // expected-error {{deduced type 'int' does not satisfy 'same_as<const int>'}}
same_as<int const> auto &i2 = f();
same_as<int const> auto &&i3 = f(); // expected-error {{deduced type 'const int &' does not satisfy 'same_as<const int>'}}
same_as<int const &> auto i4 = f(); // expected-error {{deduced type 'int' does not satisfy 'same_as<const int &>'}}
same_as<int const &> auto &i5 = f(); // expected-error {{deduced type 'const int' does not satisfy 'same_as<const int &>'}}
same_as<int const &> auto &&i6 = f();
template <class T>
concept C = false; // expected-note 3 {{because 'false' evaluated to false}}
int **const &g();
C auto **j1 = g(); // expected-error {{deduced type 'int' does not satisfy 'C'}}
C auto **&j2 = g(); // expected-error {{deduced type 'int' does not satisfy 'C'}}
C auto **&&j3 = g(); // expected-error {{deduced type 'int' does not satisfy 'C'}}
}
namespace GH55567 {
template<class, template <class> class> concept C = true;
template <class> struct S {};
void f(C<GH55567::S> auto);
} // namespace GH55567
namespace SubConstraintChecks {
template <typename T>
concept TrueConstraint = true;
template <typename T>
concept FalseConstraint = false;
template <typename T, typename... Us>
class ContainsConstrainedFuncTrue {
public:
template <typename V, TrueConstraint Constrained>
static void func(V &&, Constrained &&C);
};
template <typename T, typename... Us>
class ContainsConstrainedFuncFalse {
public:
template <typename V, FalseConstraint Constrained>
static void func(V &&, Constrained &&C);
};
template <typename... Us>
concept TrueConstraint2 =
requires(float &&t) {
ContainsConstrainedFuncTrue<float, Us...>::func(5, 0.0);
};
template <typename... Us>
concept FalseConstraint2 =
requires(float &&t) {
ContainsConstrainedFuncFalse<float, Us...>::func(5, 0.0); // #FC2_CONSTR
};
template <typename T>
void useTrue(int F)
requires TrueConstraint2<int>
{}
template <typename T>
void useFalse(int F) // #USE_FALSE
requires FalseConstraint2<int> // #USE_FALSE_CONSTR
{}
// Should only diagnose 'false' once instantiated.
void UseUse() {
useTrue<int>(5);
useFalse<int>(5);
// expected-error@-1{{no matching function for call to 'useFalse'}}
// expected-note@#USE_FALSE{{constraints not satisfied}}
// expected-note@#USE_FALSE_CONSTR{{because 'int' does not satisfy 'FalseConstraint2'}}
// expected-note@#FC2_CONSTR {{would be invalid: no matching function for call to 'func'}}
}
} // namespace SubConstraintChecks
namespace DeducedTemplateArgs {
template <typename Itr> struct ItrTraits {
template <typename PtrItr> struct Ptr {
};
template <typename PtrItr>
requires requires { typename PtrItr::pointer; }
struct Ptr<PtrItr> {
using type = typename Itr::pointer;
};
using pointer = typename Ptr<Itr>::type; // #TRAITS_PTR
};
struct complete_itr {
using pointer = int;
};
template <typename T> class Complete {
using ItrType = ItrTraits<complete_itr>;
ItrType begin() noexcept { return ItrType(); }
};
// This version doesn't have 'pointer', so error confirms we are in the first
// verison of 'Ptr'.
struct not_complete_itr {
};
template <typename T> class NotComplete {
using ItrType = ItrTraits<not_complete_itr>;
ItrType begin() noexcept { return ItrType(); }
// expected-error@#TRAITS_PTR{{no type named 'type' in }}
// expected-note@-2{{in instantiation of template class }}
};
} // namespace DeducedTemplateArgs
namespace DeferredInstantiationInstScope {
template <typename T>
struct remove_ref {
using type = T;
};
template <typename T>
struct remove_ref<T &> {
using type = T;
};
template <typename T>
struct remove_ref<T &&> {
using type = T;
};
template <typename T>
constexpr bool IsInt = PR54443::is_same<typename remove_ref<T>::type,
int>::value;
template <typename U>
void SingleDepthReferencesTop(U &&u) {
struct lc {
void operator()() // #SDRT_OP
requires IsInt<decltype(u)> // #SDRT_REQ
{}
};
lc lv;
lv(); // #SDRT_CALL
}
template <typename U>
void SingleDepthReferencesTopNotCalled(U &&u) {
struct lc {
void operator()()
requires IsInt<typename decltype(u)::FOO>
{}
};
lc lv;
}
template <typename U>
void SingleDepthReferencesTopCalled(U &&u) {
struct lc {
void operator()() // #CALLOP
requires IsInt<typename decltype(u)::FOO> // #CONSTR
{}
};
lc lv;
lv();
// expected-error@-1{{no matching function for call to object of type 'lc'}}
// expected-note@#SDRTC{{in instantiation of function template}}
// expected-note@#CALLOP{{constraints not satisfied}}
// expected-note@#CONSTR{{substituted constraint expression is ill-formed}}
}
template <typename U>
void SingleDepthReferencesTopLambda(U &&u) {
[]() // #SDRTL_OP
requires IsInt<decltype(u)> // #SDRTL_REQ
{}();
}
template <typename U>
void DoubleDepthReferencesTop(U &&u) {
struct lc { // #DDRT_STRCT
void operator()() {
struct lc2 {
void operator()() // #DDRT_OP
requires IsInt<decltype(u)> // #DDRT_REQ
{}
};
lc2 lv2;
lv2(); // #DDRT_CALL
}
};
lc lv;
lv();
}
template <typename U>
void DoubleDepthReferencesTopLambda(U &&u) {
[]() { []() // #DDRTL_OP
requires IsInt<decltype(u)> // #DDRTL_REQ
{}(); }();
}
template <typename U>
void DoubleDepthReferencesAll(U &&u) {
struct lc { // #DDRA_STRCT
void operator()(U &&u2) {
struct lc2 {
void operator()(U &&u3) // #DDRA_OP
requires IsInt<decltype(u)> && // #DDRA_REQ
IsInt<decltype(u2)> && IsInt<decltype(u3)>
{}
};
lc2 lv2;
lv2(u2); // #DDRA_CALL
}
};
lc lv;
lv(u);
}
template <typename U>
void DoubleDepthReferencesAllLambda(U &&u) {
[](U &&u2) { // #DDRAL_OP1
[](U && u3) // #DDRAL_OP2
requires IsInt<decltype(u)> // #DDRAL_REQ
&& IsInt<decltype(u2)>
&& IsInt<decltype(u3)>
{}(u2);
}(u);
}
template <typename U>
struct CausesFriendConstraint {
template <typename V>
friend void FriendFunc(CausesFriendConstraint, V) // #FF_DECL
requires IsInt<U> &&
IsInt<V> // #FF_REQ
{}
};
// FIXME: Re-enable this test when constraints are allowed to refer to captures.
// template<typename T>
// void ChecksCapture(T x) {
// [y = x]() requires(IsInt<decltype(y)>){}();
// }
template <typename T>
void ChecksLocalVar(T x) {
T Local;
[]() // #CLV_OP
requires(IsInt<decltype(Local)>) // #CLV_REQ
{}();
}
template <typename T>
void LocalStructMemberVar(T x) {
struct S {
T local;
void foo()
requires(IsInt<decltype(local)>) // #LSMV_REQ
{}
} s;
s.foo(); // #LSMV_CALL
};
template <typename T>
struct ChecksMemberVar {
T t;
void foo()
requires(IsInt<decltype(t)>) // #CMV_FOO
{}
template <typename U>
void foo2() // #CMV_FOO2
requires(IsInt<decltype(t)>) // #CMV_FOO2_REQ
{}
};
void test_dependent() {
int v = 0;
float will_fail;
SingleDepthReferencesTop(v);
SingleDepthReferencesTop(will_fail);
// expected-error@#SDRT_CALL{{no matching function for call to object of type 'lc'}}
// expected-note@-2{{in instantiation of function template specialization}}
// expected-note@#SDRT_OP{{candidate function not viable}}
// expected-note@#SDRT_REQ{{'IsInt<decltype(u)>' evaluated to false}}
SingleDepthReferencesTopNotCalled(v);
// Won't error unless we try to call it.
SingleDepthReferencesTopNotCalled(will_fail);
SingleDepthReferencesTopCalled(v); // #SDRTC
SingleDepthReferencesTopLambda(v);
SingleDepthReferencesTopLambda(will_fail);
// expected-note@-1{{in instantiation of function template specialization}}
// expected-error@#SDRTL_OP{{no matching function for call to object of type}}
// expected-note@#SDRTL_OP{{candidate function not viable: constraints not satisfied}}
// expected-note@#SDRTL_REQ{{because 'IsInt<decltype(u)>' evaluated to false}}
DoubleDepthReferencesTop(v);
DoubleDepthReferencesTop(will_fail);
// expected-error@#DDRT_CALL{{no matching function for call to object of type 'lc2'}}
// expected-note@-2{{in instantiation of function template specialization}}
// expected-note@#DDRT_STRCT{{in instantiation of member function}}
// expected-note@#DDRT_OP{{candidate function not viable}}
// expected-note@#DDRT_REQ{{'IsInt<decltype(u)>' evaluated to false}}
DoubleDepthReferencesTopLambda(v);
DoubleDepthReferencesTopLambda(will_fail);
// expected-note@-1{{in instantiation of function template specialization}}
// expected-error@#DDRTL_OP{{no matching function for call to object of type}}
// expected-note@#DDRTL_OP{{candidate function not viable: constraints not satisfied}}
// expected-note@#DDRTL_OP{{while substituting into a lambda expression here}}
// expected-note@#DDRTL_REQ{{because 'IsInt<decltype(u)>' evaluated to false}}
DoubleDepthReferencesAll(v);
DoubleDepthReferencesAll(will_fail);
// expected-error@#DDRA_CALL{{no matching function for call to object of type 'lc2'}}
// expected-note@-2{{in instantiation of function template specialization}}
// expected-note@#DDRA_STRCT{{in instantiation of member function}}
// expected-note@#DDRA_OP{{candidate function not viable}}
// expected-note@#DDRA_REQ{{'IsInt<decltype(u)>' evaluated to false}}
DoubleDepthReferencesAllLambda(v);
DoubleDepthReferencesAllLambda(will_fail);
// expected-note@-1{{in instantiation of function template specialization}}
// expected-note@#DDRAL_OP1{{while substituting into a lambda expression here}}
// expected-error@#DDRAL_OP2{{no matching function for call to object of type}}
// expected-note@#DDRAL_OP2{{candidate function not viable: constraints not satisfied}}
// expected-note@#DDRAL_REQ{{because 'IsInt<decltype(u)>' evaluated to false}}
CausesFriendConstraint<int> CFC;
FriendFunc(CFC, 1);
FriendFunc(CFC, 1.0);
// expected-error@-1{{no matching function for call to 'FriendFunc'}}
// expected-note@#FF_DECL{{constraints not satisfied}}
// expected-note@#FF_REQ{{because 'IsInt<double>' evaluated to false}}
// FIXME: Re-enable this test when constraints are allowed to refer to captures.
// ChecksCapture(v);
ChecksLocalVar(v);
ChecksLocalVar(will_fail);
// expected-note@-1{{in instantiation of function template specialization}}
// expected-error@#CLV_OP{{no matching function for call to object of type}}
// expected-note@#CLV_OP{{candidate function not viable: constraints not satisfied}}
// expected-note@#CLV_REQ{{because 'IsInt<decltype(Local)>' evaluated to false}}
LocalStructMemberVar(v);
LocalStructMemberVar(will_fail);
// expected-error@#LSMV_CALL{{invalid reference to function 'foo'}}
// expected-note@-2{{in instantiation of function template specialization}}
// expected-note@#LSMV_REQ{{because 'IsInt<decltype(this->local)>' evaluated to false}}
ChecksMemberVar<int> CMV;
CMV.foo();
CMV.foo2<int>();
ChecksMemberVar<float> CMV2;
CMV2.foo();
// expected-error@-1{{invalid reference to function 'foo'}}
// expected-note@#CMV_FOO{{because 'IsInt<decltype(this->t)>' evaluated to false}}
CMV2.foo2<float>();
// expected-error@-1{{no matching member function for call to 'foo2'}}
// expected-note@#CMV_FOO2{{constraints not satisfied}}
// expected-note@#CMV_FOO2_REQ{{because 'IsInt<decltype(this->t)>' evaluated to false}}
}
} // namespace DeferredInstantiationInstScope
// Ane example of evaluating a concept at two different depths in the same
// evaluation. No diagnostic is expected.
namespace SameConceptDifferentDepth {
template <class _Ip>
concept sentinel_for =
requires(_Ip __i) {
__i++;
};
template <class _Ip>
concept bidirectional_iterator =
sentinel_for<_Ip>;
template <class _Iter>
class move_iterator {
public:
auto operator++(int)
requires sentinel_for<_Iter>{}
};
static_assert(bidirectional_iterator<move_iterator<int>>);
} // namespace SameConceptDifferentDepth
namespace VarInit {
template <class _Tp>
concept __can_reference = true;
template <class _Iter>
class common_iterator {
public:
common_iterator() {
constexpr auto x = requires(_Iter & __i) { { __i } -> __can_reference; };
}
};
void test() {
auto commonIter1 = common_iterator<int>();
}
} // namespace VarInit
namespace InlineFriendOperator {
template <typename T>
concept C = true;
template <class _Iter>
class counted_iterator {
_Iter I;
public:
constexpr counted_iterator() = default;
friend constexpr auto operator+( // expected-note {{candidate function not viable}}
int __n, const counted_iterator &__x)
requires C<decltype(I)>
{
return __x + __n; // expected-error{{invalid operands to binary expression}}
}
};
constexpr bool test() {
counted_iterator<int> iter;
auto x = 2 + iter; // expected-note{{in instantiation of member function 'InlineFriendOperator::operator+'}}
return true;
}
} // namespace InlineFriendOperator
namespace ClassTemplateInstantiation {
struct Type;
template < typename A, typename B, typename C>
concept ConstraintF = false; // #ConstraintF
template < typename A, typename B, typename C>
concept ConstraintT = true;
template < typename T > struct Parent {
template < typename U, ConstraintT<T, U> > struct ChildT{};
ChildT<Type, Type> CauseInstT;
template < typename U, ConstraintF<T, U> > struct ChildF{};// #ChildF
ChildF<Type, Type> CauseInstF; //#CauseInstF
};
// expected-error@#CauseInstF{{constraints not satisfied for class template}}
// expected-note@+3{{in instantiation of template class}}
// expected-note@#ChildF{{evaluated to false}}
// expected-note@#ConstraintF{{because 'false' evaluated to false}}
Parent<int> Inst;
} // namespace ClassTemplateInstantiation
namespace SelfFriend {
template<class T>
concept Constraint = requires (T i) { (*i); };
template<class T>
concept Constraint2 = requires (T i) { (*i); };
template<Constraint T>
struct Iterator {
template <Constraint>
friend class Iterator;
void operator*();
};
template<Constraint T> // #ITER_BAD
struct IteratorBad {
template <Constraint2>//#ITER_BAD_FRIEND
friend class IteratorBad;
void operator*();
};
Iterator<int*> I;
Iterator<char*> I2;
IteratorBad<int*> I3; // expected-error@#ITER_BAD_FRIEND{{constraint differs}}
// expected-note@-1{{in instantiation of template class}}
// expected-note@#ITER_BAD{{previous template declaration}}
} // namespace SelfFriend
namespace Surrogates {
int f1(int);
template <auto N>
struct A {
using F = int(int);
operator F*() requires N { return f1; } // expected-note{{conversion candidate 'operator int (*)(int)' not viable: constraints not satisfied}}
};
int i = A<true>{}(0);
int j = A<false>{}(0); // expected-error{{no matching function for call to object of type 'A<false>'}}
}
namespace ConstrainedMemberVarTemplate {
template <long Size> struct Container {
static constexpr long arity = Size;
template <typename U>
requires(sizeof(U) == arity) // #CMVT_REQ
using var_templ = int;
};
Container<4>::var_templ<int> inst;
Container<5>::var_templ<int> inst_fail;
// expected-error@-1{{constraints not satisfied for alias template 'var_templ'}}
// expected-note@#CMVT_REQ{{because 'sizeof(int) == arity' (4 == 5) evaluated to false}}
} // namespace ConstrainedMemberVarTemplate
// These should not diagnose, where we were unintentionally doing so before by
// checking trailing requires clause twice, yet not having the ability to the
// 2nd time, since it was no longer a dependent variant.
namespace InheritedFromPartialSpec {
template<class C>
constexpr bool Check = true;
template<typename T>
struct Foo {
template<typename U>
Foo(U&&) requires (Check<U>){}
template<typename U>
void MemFunc(U&&) requires (Check<U>){}
template<typename U>
static void StaticMemFunc(U&&) requires (Check<U>){}
~Foo() requires (Check<T>){}
};
template<>
struct Foo<void> : Foo<int> {
using Foo<int>::Foo;
using Foo<int>::MemFunc;
using Foo<int>::StaticMemFunc;
};
void use() {
Foo<void> F {1.1};
F.MemFunc(1.1);
Foo<void>::StaticMemFunc(1.1);
}
template<typename T>
struct counted_iterator {
constexpr auto operator->() const noexcept requires false {
return T::Invalid;
};
};
template<class _Ip>
concept __has_member_pointer = requires { typename _Ip::pointer; };
template<class>
struct __iterator_traits_member_pointer_or_arrow_or_void { using type = void; };
template<__has_member_pointer _Ip>
struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> { using type = typename _Ip::pointer; };
template<class _Ip>
requires requires(_Ip& __i) { __i.operator->(); } && (!__has_member_pointer<_Ip>)
struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> {
using type = decltype(declval<_Ip&>().operator->());
};
void use2() {
__iterator_traits_member_pointer_or_arrow_or_void<counted_iterator<int>> f;
}
}// namespace InheritedFromPartialSpec
namespace GH48182 {
template<typename, typename..., typename = int> // expected-error{{template parameter pack must be the last template parameter}}
concept invalid = true;
template<typename> requires invalid<int> // expected-error{{use of undeclared identifier 'invalid'}}
no errors are printed
;
static_assert(invalid<int> also here ; // expected-error{{use of undeclared identifier 'invalid'}}
int foo() {
bool b;
b = invalid<int> not just in declarations; // expected-error{{expected ';' after expression}}
// expected-error@-1{{use of undeclared identifier 'invalid'}}
// expected-error@-2{{expected ';' after expression}}
// expected-error@-3{{use of undeclared identifier 'just'}}
// expected-error@-4{{unknown type name 'in'}}
return b;
}
} // namespace GH48182
namespace GH61777 {
template<class T> concept C = sizeof(T) == 4; // #61777_C
template<class T, class U> concept C2 = sizeof(T) == sizeof(U); //#61777_C2
template<class T>
struct Parent {
template<class, C auto> struct TakesUnary { static const int i = 0 ; }; // #UNARY
template<class, C2<T> auto> struct TakesBinary { static const int i = 0 ; }; //#BINARY
};
static_assert(Parent<void>::TakesUnary<int, 0>::i == 0);
// expected-error@+3{{constraints not satisfied for class template 'TakesUnary'}}
// expected-note@#UNARY{{because 'decltype(0ULL)' (aka 'unsigned long long') does not satisfy 'C'}}
// expected-note@#61777_C{{because 'sizeof(unsigned long long) == 4' (8 == 4) evaluated to false}}
static_assert(Parent<void>::TakesUnary<int, 0uLL>::i == 0);
static_assert(Parent<int>::TakesBinary<int, 0>::i == 0);
// expected-error@+3{{constraints not satisfied for class template 'TakesBinary'}}
// expected-note@#BINARY{{because 'C2<decltype(0ULL), int>' evaluated to false}}
// expected-note@#61777_C2{{because 'sizeof(unsigned long long) == sizeof(int)' (8 == 4) evaluated to false}}
static_assert(Parent<int>::TakesBinary<int, 0ULL>::i == 0);
}
namespace TemplateInsideNonTemplateClass {
template<typename T, typename U> concept C = true;
template<typename T> auto L = []<C<T> U>() {};
struct Q {
template<C<int> U> friend constexpr auto decltype(L<int>)::operator()() const;
};
template <class T>
concept C1 = false;
struct Foo {
template <typename>
struct Bar {};
template <typename T>
requires(C1<T>)
struct Bar<T>;
};
Foo::Bar<int> BarInstance;
} // namespace TemplateInsideNonTemplateClass
namespace GH61959 {
template <typename T0>
concept C = (sizeof(T0) >= 4);
template<typename...>
struct Orig { };
template<typename T>
struct Orig<T> {
template<typename> requires C<T>
void f() { }
template<typename> requires true
void f() { }
};
template <typename...> struct Mod {};
template <typename T1, typename T2>
struct Mod<T1, T2> {
template <typename> requires C<T1>
constexpr static int f() { return 1; }
template <typename> requires C<T2>
constexpr static int f() { return 2; }
};
static_assert(Mod<int, char>::f<double>() == 1);
static_assert(Mod<char, int>::f<double>() == 2);
template<typename T>
struct Outer {
template<typename ...>
struct Inner {};
template<typename U>
struct Inner<U> {
template<typename V>
void foo() requires C<U> && C<T> && C<V>{}
template<typename V>
void foo() requires true{}
};
};
void bar() {
Outer<int>::Inner<float> I;
I.foo<char>();
}
} // namespace GH61959
namespace TemplateInsideTemplateInsideTemplate {
template<typename T>
concept C1 = false;
template <unsigned I0>
struct W0 {
template <unsigned I1>
struct W1 {
template <typename T>
struct F {
enum { value = 1 };
};
template <typename T>
requires C1<T>
struct F<T> {
enum { value = 2 };
};
};
};
static_assert(W0<0>::W1<1>::F<int>::value == 1);
} // TemplateInsideTemplateInsideTemplate
namespace GH63181 {
template<auto N, class T> void f() {
auto l = []() requires N { }; // expected-note 2{{candidate function not viable: constraints not satisfied}} \
// expected-note 2{{because 'false' evaluated to false}}
l();
// expected-error@-1 {{no matching function for call to object of type}}
void(*ptr)() = l;
// expected-error-re@-1 {{no viable conversion from '(lambda {{.*}})' to 'void (*)()'}}
}
template void f<false, int>(); // expected-note {{in instantiation of function template specialization 'GH63181::f<false, int>' requested here}}
template void f<true, int>();
template<class T> concept C = __is_same(T, int); // expected-note{{because '__is_same(char, int)' evaluated to false}}
template<class... Ts> void f() {
([]() requires C<Ts> { return Ts(); }(), ...);
// expected-error@-1 {{no matching function for call to object of type}} \
// expected-note@-1 {{candidate function not viable: constraints not satisfied}} \
// expected-note@-1 {{because 'char' does not satisfy 'C'}}
}
template void f<int, int, int>();
template void f<int, int, char>();
//expected-note@-1{{in instantiation of function template specialization 'GH63181::f<int, int, char>' requested here}}
template <typename T, bool IsTrue>
concept Test = IsTrue; // expected-note 2{{because 'false' evaluated to false}}
template <typename T, bool IsTrue>
void params() {
auto l = [](T t) // expected-note 2{{candidate function not viable: constraints not satisfied}}
requires Test<decltype(t), IsTrue> // expected-note 2{{because 'Test<decltype(t), false>' evaluated to false}}
{};
using F = void(T);
F* f = l; // expected-error {{no viable conversion from}}
l(0); // expected-error {{no matching function for call to object}}
}
void test_params() {
params<int, true>();
params<int, false>(); // expected-note {{in instantiation of function template specialization 'GH63181::params<int, false>' requested here}}
}
}