diff options
Diffstat (limited to 'clang/test')
21 files changed, 592 insertions, 76 deletions
diff --git a/clang/test/CXX/class.derived/class.virtual/p6.cpp b/clang/test/CXX/class.derived/class.virtual/p6.cpp new file mode 100644 index 00000000000..63a4313de55 --- /dev/null +++ b/clang/test/CXX/class.derived/class.virtual/p6.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -verify %s + +template<typename T> +class A { + virtual void f1() requires (sizeof(T) == 0); + // expected-error@-1{{virtual function cannot have a requires clause}} + virtual void f2() requires (sizeof(T) == 1); + // expected-error@-1{{virtual function cannot have a requires clause}} +}; + +template<typename T> +class B : A<T> { + virtual void f1() requires (sizeof(T) == 0) override {} + // expected-error@-1{{virtual function cannot have a requires clause}} +}; + +template<typename T> struct C : T {void f() requires true; }; +// expected-error@-1{{virtual function cannot have a requires clause}} +struct D { virtual void f(); }; +template struct C<D>; +// expected-note@-1{{in instantiation of template class 'C<D>' requested here}}
\ No newline at end of file diff --git a/clang/test/CXX/dcl/dcl.decl/p3.cpp b/clang/test/CXX/dcl/dcl.decl/p3.cpp new file mode 100644 index 00000000000..eec0aa2043a --- /dev/null +++ b/clang/test/CXX/dcl/dcl.decl/p3.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -verify %s + +template<typename T, typename U> +constexpr bool is_same_v = false; + +template<typename T> +constexpr bool is_same_v<T, T> = true; + +void f1(int a) requires true; // OK +auto f2(int a) -> bool requires true; // OK +auto f3(int a) -> bool (*)(int b) requires true; // OK +auto f4(int a) requires true -> bool; // expected-error{{trailing return type must appear before trailing requires clause}} +int f5(int a) requires; // expected-error{{expected expression}} +int f6(int a) requires {} // expected-error{{expected expression}} +void (f7()) requires true; +void (f8() requires true); // expected-error{{trailing requires clause should be placed outside parentheses}} +void (*(f9 requires (true)))(); // expected-error{{trailing requires clause should be placed outside parentheses}} +static_assert(is_same_v<decltype(f9), void (*)()>); +void (*pf)() requires true; // expected-error{{trailing requires clause can only be used when declaring a function}} +void g1(int (*dsdads)() requires false); // expected-error{{trailing requires clause can only be used when declaring a function}} +void g2(int (*(*dsdads)())() requires true); // expected-error{{trailing requires clause can only be used when declaring a function}} +void g3(int (*(*dsdads)(int) requires true)() ); // expected-error{{trailing requires clause should be placed outside parentheses}} +using T = void (); +T x requires true; +struct S { + T m1 requires true, m2 requires true; +}; + +template<typename T> +struct R { + R(T t); +}; + +template<typename T> +R(T) -> R<T> requires true; // expected-error{{deduction guide cannot have a requires clause}} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.id/mixed-constraints.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.id/mixed-constraints.cpp new file mode 100644 index 00000000000..fafb3f7b35d --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.id/mixed-constraints.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -verify %s + +template<typename T> requires (sizeof(T) >= 4 && sizeof(T) <= 10) +// expected-note@-1{{because 'sizeof(char [20]) <= 10' (20 <= 10) evaluated to false}} +// expected-note@-2{{because 'sizeof(char) >= 4' (1 >= 4) evaluated to false}} +void foo() requires (sizeof(T) <= 8) {} +// expected-note@-1{{candidate template ignored: constraints not satisfied [with T = char]}} +// expected-note@-2{{candidate template ignored: constraints not satisfied [with T = char [9]]}} +// expected-note@-3{{candidate template ignored: constraints not satisfied [with T = char [20]]}} +// expected-note@-4{{because 'sizeof(char [9]) <= 8' (9 <= 8) evaluated to false}} + +void bar() { + foo<char>(); // expected-error{{no matching function for call to 'foo'}} + foo<int>(); + foo<unsigned long long int>(); + foo<char[9]>(); // expected-error{{no matching function for call to 'foo'}} + foo<char[20]>(); // expected-error{{no matching function for call to 'foo'}} +}
\ No newline at end of file diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.id/p4.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.id/p4.cpp new file mode 100644 index 00000000000..f13ab279da3 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.id/p4.cpp @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -verify %s + +namespace functions +{ + void foo(int) requires false {} + // expected-note@-1 3{{because 'false' evaluated to false}} + // expected-note@-2 {{candidate function not viable: constraints not satisfied}} + void bar(int) requires true {} + + void a(int); + void a(double); + + void baz() { + foo(1); // expected-error{{no matching function for call to 'foo'}} + bar(1); + void (*p1)(int) = foo; // expected-error{{invalid reference to function 'foo': constraints not satisfied}} + void (*p3)(int) = bar; + decltype(foo)* a1 = nullptr; // expected-error{{invalid reference to function 'foo': constraints not satisfied}} + decltype(bar)* a2 = nullptr; + } +} + +namespace methods +{ + template<typename T> + struct A { + static void foo(int) requires (sizeof(T) == 1) {} // expected-note 3{{because 'sizeof(char [2]) == 1' (2 == 1) evaluated to false}} + static void bar(int) requires (sizeof(T) == 2) {} // expected-note 3{{because 'sizeof(char) == 2' (1 == 2) evaluated to false}} + }; + + void baz() { + A<char>::foo(1); + A<char>::bar(1); // expected-error{{invalid reference to function 'bar': constraints not satisfied}} + A<char[2]>::foo(1); // expected-error{{invalid reference to function 'foo': constraints not satisfied}} + A<char[2]>::bar(1); + void (*p1)(int) = A<char>::foo; + void (*p2)(int) = A<char>::bar; // expected-error{{invalid reference to function 'bar': constraints not satisfied}} + void (*p3)(int) = A<char[2]>::foo; // expected-error{{invalid reference to function 'foo': constraints not satisfied}} + void (*p4)(int) = A<char[2]>::bar; + decltype(A<char>::foo)* a1 = nullptr; + decltype(A<char>::bar)* a2 = nullptr; // expected-error{{invalid reference to function 'bar': constraints not satisfied}} + decltype(A<char[2]>::foo)* a3 = nullptr; // expected-error{{invalid reference to function 'foo': constraints not satisfied}} + decltype(A<char[2]>::bar)* a4 = nullptr; + } +} + +namespace operators +{ + template<typename T> + struct A { + A<T> operator-(A<T> b) requires (sizeof(T) == 1) { return b; } // expected-note{{because 'sizeof(int) == 1' (4 == 1) evaluated to false}} + }; + + void baz() { + auto* x = &A<int>::operator-; // expected-error{{invalid reference to function 'operator-': constraints not satisfied}} + auto y = &A<char>::operator-; + } +}
\ No newline at end of file diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/expr.prim.lambda.closure/p3.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/expr.prim.lambda.closure/p3.cpp new file mode 100644 index 00000000000..942280e1059 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/expr.prim.lambda.closure/p3.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -verify %s + +auto l1 = [] (auto x) requires (sizeof(decltype(x)) == 1) { return x; }; +// expected-note@-1{{candidate template ignored: constraints not satisfied [with $0 = int]}} +// expected-note@-2{{because 'sizeof(decltype(x)) == 1' (4 == 1) evaluated to false}} + +auto l1t1 = l1('a'); +auto l1t2 = l1(1); +// expected-error@-1{{no matching function for call to object of type '(lambda at}} + +auto l2 = [] (auto... x) requires ((sizeof(decltype(x)) >= 2) && ...) { return (x + ...); }; +// expected-note@-1{{candidate template ignored: constraints not satisfied [with $0 = <char>]}} +// expected-note@-2{{candidate template ignored: constraints not satisfied [with $0 = <int, char>]}} +// expected-note@-3 2{{because 'sizeof(decltype(x)) >= 2' (1 >= 2) evaluated to false}} + +auto l2t1 = l2('a'); +// expected-error@-1{{no matching function for call to object of type '(lambda at}} +auto l2t2 = l2(1, 'a'); +// expected-error@-1{{no matching function for call to object of type '(lambda at}} +auto l2t3 = l2((short)1, (short)1);
\ No newline at end of file diff --git a/clang/test/CXX/over/over.match/over.match.best/p1-2a.cpp b/clang/test/CXX/over/over.match/over.match.best/p1-2a.cpp new file mode 100644 index 00000000000..dba2ef204e1 --- /dev/null +++ b/clang/test/CXX/over/over.match/over.match.best/p1-2a.cpp @@ -0,0 +1,114 @@ +// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -verify %s + +template<typename T, typename U> +constexpr static bool is_same_v = false; + +template<typename T> +constexpr static bool is_same_v<T, T> = true; + +namespace templates +{ + template<typename T> + concept AtLeast1 = sizeof(T) >= 1; + + template<typename T> + int foo(T t) requires (sizeof(T) == 4) { // expected-note {{candidate function}} + return 0; + } + + template<typename T> + char foo(T t) requires AtLeast1<T> { // expected-note {{candidate function}} + return 'a'; + } + + template<typename T> + double foo(T t) requires (AtLeast1<T> && sizeof(T) <= 2) { + return 'a'; + } + + static_assert(is_same_v<decltype(foo(10)), int>); // expected-error {{call to 'foo' is ambiguous}} + static_assert(is_same_v<decltype(foo(short(10))), double>); + + template<typename T> + void bar() requires (sizeof(T) == 1) { } + // expected-note@-1{{similar constraint expressions not considered equivalent}} + // expected-note@-2{{candidate function [with T = char]}} + + template<typename T> + void bar() requires (sizeof(T) == 1 && sizeof(T) >= 0) { } + // expected-note@-1{{candidate function [with T = char]}} + // expected-note@-2{{similar constraint expression here}} + + static_assert(is_same_v<decltype(bar<char>()), void>); + // expected-error@-1{{call to 'bar' is ambiguous}} + + template<typename T> + constexpr int baz() requires AtLeast1<T> { // expected-note {{candidate function}} + return 1; + } + + template<typename T> requires AtLeast1<T> + constexpr int baz() { // expected-note {{candidate function [with T = int]}} + return 2; + } + + static_assert(baz<int>() == 1); // expected-error {{call to 'baz' is ambiguous}} +} + +namespace non_template +{ + template<typename T> + concept AtLeast2 = sizeof(T) >= 2; + + template<typename T> + concept AtMost8 = sizeof(T) <= 8; + + int foo() requires AtLeast2<long> && AtMost8<long> { + return 0; + } + + double foo() requires AtLeast2<long> { + return 0.0; + } + + double baz() requires AtLeast2<long> && AtMost8<long> { // expected-note {{candidate function}} + return 0.0; + } + + int baz() requires AtMost8<long> && AtLeast2<long> { // expected-note {{candidate function}} + return 0.0; + } + + void bar() requires (sizeof(long) >= 8) { } + // expected-note@-1 {{candidate function}} + // expected-note@-2 {{similar constraint expressions not considered equivalent}} + + void bar() requires (sizeof(long) >= 8 && sizeof(int) <= 30) { } + // expected-note@-1 {{candidate function}} + // expected-note@-2 {{similar constraint expression here}} + + static_assert(is_same_v<decltype(foo()), int>); + static_assert(is_same_v<decltype(baz()), int>); // expected-error {{call to 'baz' is ambiguous}} + static_assert(is_same_v<decltype(bar()), void>); // expected-error {{call to 'bar' is ambiguous}} + + constexpr int goo(int a) requires AtLeast2<int> && true { + return 1; + } + + constexpr int goo(const int b) requires AtLeast2<int> { + return 2; + } + + // Only trailing requires clauses of redeclarations are compared for overload resolution. + constexpr int doo(int a, ...) requires AtLeast2<int> && true { // expected-note {{candidate function}} + return 1; + } + + constexpr int doo(int b) requires AtLeast2<int> { // expected-note {{candidate function}} + return 2; + } + + static_assert(goo(1) == 1); + static_assert(doo(2) == 1); // expected-error {{call to 'doo' is ambiguous}} +} + diff --git a/clang/test/CXX/over/over.match/over.match.viable/p3.cpp b/clang/test/CXX/over/over.match/over.match.viable/p3.cpp new file mode 100644 index 00000000000..ef752d76ec2 --- /dev/null +++ b/clang/test/CXX/over/over.match/over.match.viable/p3.cpp @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -verify %s + +struct S2 {}; +// expected-note@-1 {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'S1' to 'const S2' for 1st argument}} +// expected-note@-2 {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'S1' to 'S2' for 1st argument}} +// expected-note@-3 {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} + +struct S1 { + void foo() const requires true {} + void foo() const requires false {} + void bar() const requires false {} + // expected-note@-1 {{because 'false' evaluated to false}} + operator bool() const requires true { return true; } + explicit operator bool() const requires false; + explicit operator S2() const requires false; + // expected-note@-1 {{candidate function not viable: constraints not satisfied}} + // expected-note@-2 {{because 'false' evaluated to false}} +}; + +void foo() { + S1().foo(); + S1().bar(); + // expected-error@-1 {{invalid reference to function 'bar': constraints not satisfied}} + (void) static_cast<bool>(S1()); + (void) static_cast<S2>(S1()); + // expected-error@-1 {{no matching conversion for static_cast from 'S1' to 'S2'}} +} + +// Test that constraints are checked before implicit conversions are formed. + +template<typename T> +struct invalid_template { using X = typename T::non_existant; }; +struct A { + template<typename T, bool=invalid_template<T>::aadasas> + operator T() {} +}; + +void foo(int) requires false; +void foo(A) requires true; + +struct S { + void foo(int) requires false; + void foo(A) requires true; + S(A) requires false; + S(double) requires true; + ~S() requires false; + // expected-note@-1 2{{because 'false' evaluated to false}} + ~S() requires true; + operator int() requires true; + operator int() requires false; +}; + +void bar() { + foo(A{}); + S{1.}.foo(A{}); + // expected-error@-1{{invalid reference to function '~S': constraints not satisfied}} + // Note - this behavior w.r.t. constrained dtors is a consequence of current + // wording, which does not invoke overload resolution when a dtor is called. + // P0848 is set to address this issue. + S s = 1; + // expected-error@-1{{invalid reference to function '~S': constraints not satisfied}} + int a = s; +}
\ No newline at end of file diff --git a/clang/test/CXX/over/over.over/p4-2a.cpp b/clang/test/CXX/over/over.over/p4-2a.cpp new file mode 100644 index 00000000000..a5d7a110992 --- /dev/null +++ b/clang/test/CXX/over/over.over/p4-2a.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -verify %s + +template<typename T, typename U> +constexpr static bool is_same_v = false; + +template<typename T> +constexpr static bool is_same_v<T, T> = true; + +template<typename T> +concept AtLeast2 = sizeof(T) >= 2; + +template<typename T> +concept AtMost8 = sizeof(T) <= 8; + +int foo() requires AtLeast2<long> && AtMost8<long> { + return 0; +} + +double foo() requires AtLeast2<char> { + return 0.0; +} + +char bar() requires AtLeast2<char> { // expected-note {{possible target for call}} + return 1.0; +} + +short bar() requires AtLeast2<long> && AtMost8<long> { +// expected-note@-1{{possible target for call}} +// expected-note@-2{{candidate function}} + return 0.0; +} + +int bar() requires AtMost8<long> && AtLeast2<long> { +// expected-note@-1{{possible target for call}} +// expected-note@-2{{candidate function}} + return 0.0; +} + +char baz() requires AtLeast2<char> { + return 1.0; +} + +short baz() requires AtLeast2<long> && AtMost8<long> { + return 0.0; +} + +int baz() requires AtMost8<long> && AtLeast2<long> { + return 0.0; +} + +long baz() requires AtMost8<long> && AtLeast2<long> && AtLeast2<short> { + return 3.0; +} + +void a() { + static_assert(is_same_v<decltype(&foo), int(*)()>); + static_assert(is_same_v<decltype(&bar), long(*)()>); + // expected-error@-1{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} + // expected-error@-2{{call to 'bar' is ambiguous}} + static_assert(is_same_v<decltype(&baz), long(*)()>); +}
\ No newline at end of file diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.constr/function-templates.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.constr/function-templates.cpp index c1a3a27fbea..99de7261a81 100644 --- a/clang/test/CXX/temp/temp.constr/temp.constr.constr/function-templates.cpp +++ b/clang/test/CXX/temp/temp.constr/temp.constr.constr/function-templates.cpp @@ -23,14 +23,13 @@ static_assert(is_same_v<decltype(dereference<int*>(nullptr)), int>); static_assert(is_same_v<decltype(dereference(2)), int>); // expected-error {{no matching function for call to 'dereference'}} static_assert(is_same_v<decltype(dereference<char>('a')), char>); // expected-error {{no matching function for call to 'dereference'}} - -template<typename T> requires T{} + T{} // expected-note {{because substituted constraint expression is ill-formed: invalid operands to binary expression ('A' and 'A')}} +template<typename T> requires (T{} + T{}) // expected-note {{because substituted constraint expression is ill-formed: invalid operands to binary expression ('A' and 'A')}} auto foo(T t) { // expected-note {{candidate template ignored: constraints not satisfied [with T = A]}} return t + t; } -template<typename T> requires !((T{} - T{}) && (T{} + T{})) || false +template<typename T> requires (!((T{} - T{}) && (T{} + T{})) || false) // expected-note@-1{{because substituted constraint expression is ill-formed: invalid operands to binary expression ('A' and 'A')}} // expected-note@-2{{and 'false' evaluated to false}} auto bar(T t) { // expected-note {{candidate template ignored: constraints not satisfied [with T = A]}} diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.constr/non-function-templates.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.constr/non-function-templates.cpp index 24caa5063a1..a25b22a9a15 100644 --- a/clang/test/CXX/temp/temp.constr/temp.constr.constr/non-function-templates.cpp +++ b/clang/test/CXX/temp/temp.constr/temp.constr.constr/non-function-templates.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ -verify %s -template<typename T> requires sizeof(T) >= 2 // expected-note{{because 'sizeof(char) >= 2' (1 >= 2) evaluated to false}} +template<typename T> requires (sizeof(T) >= 2) // expected-note{{because 'sizeof(char) >= 2' (1 >= 2) evaluated to false}} struct A { static constexpr int value = sizeof(T); }; @@ -9,8 +9,8 @@ static_assert(A<int>::value == 4); static_assert(A<char>::value == 1); // expected-error{{constraints not satisfied for class template 'A' [with T = char]}} template<typename T, typename U> - requires sizeof(T) != sizeof(U) // expected-note{{because 'sizeof(int) != sizeof(char [4])' (4 != 4) evaluated to false}} - && sizeof(T) >= 4 // expected-note{{because 'sizeof(char) >= 4' (1 >= 4) evaluated to false}} + requires (sizeof(T) != sizeof(U) // expected-note{{because 'sizeof(int) != sizeof(char [4])' (4 != 4) evaluated to false}} + && sizeof(T) >= 4) // expected-note{{because 'sizeof(char) >= 4' (1 >= 4) evaluated to false}} constexpr int SizeDiff = sizeof(T) > sizeof(U) ? sizeof(T) - sizeof(U) : sizeof(U) - sizeof(T); static_assert(SizeDiff<int, char> == 3); @@ -44,16 +44,16 @@ static_assert(S<S2>::value); template<typename T> struct AA { - template<typename U> requires sizeof(U) == sizeof(T) // expected-note{{because 'sizeof(int [2]) == sizeof(int)' (8 == 4) evaluated to false}} + template<typename U> requires (sizeof(U) == sizeof(T)) // expected-note{{because 'sizeof(int [2]) == sizeof(int)' (8 == 4) evaluated to false}} struct B { static constexpr int a = 0; }; - template<typename U> requires sizeof(U) == sizeof(T) // expected-note{{because 'sizeof(int [2]) == sizeof(int)' (8 == 4) evaluated to false}} + template<typename U> requires (sizeof(U) == sizeof(T)) // expected-note{{because 'sizeof(int [2]) == sizeof(int)' (8 == 4) evaluated to false}} static constexpr int b = 1; - template<typename U> requires sizeof(U) == sizeof(T) // expected-note{{because 'sizeof(int [2]) == sizeof(int)' (8 == 4) evaluated to false}} + template<typename U> requires (sizeof(U) == sizeof(T)) // expected-note{{because 'sizeof(int [2]) == sizeof(int)' (8 == 4) evaluated to false}} static constexpr int getB() { // expected-note{{candidate template ignored: constraints not satisfied [with U = int [2]]}} return 2; } @@ -85,8 +85,8 @@ template<typename T> requires B<T>::type // expected-note{{in instantiation of t // expected-note@-1{{while substituting template arguments into constraint expression here}} struct C { }; -template<typename T> requires T{} // expected-error{{atomic constraint must be of type 'bool' (found 'int')}} +template<typename T> requires (T{}) // expected-error{{atomic constraint must be of type 'bool' (found 'int')}} struct D { }; static_assert(C<int>{}); // expected-note{{while checking constraint satisfaction for template 'C<int>' required here}} -static_assert(D<int>{}); // expected-note{{while checking constraint satisfaction for template 'D<int>' required here}}
\ No newline at end of file +static_assert(D<int>{}); // expected-note{{while checking constraint satisfaction for template 'D<int>' required here}} diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.constr/partial-specializations.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.constr/partial-specializations.cpp index 47bd2a55076..1ea4da29ee9 100644 --- a/clang/test/CXX/temp/temp.constr/temp.constr.constr/partial-specializations.cpp +++ b/clang/test/CXX/temp/temp.constr/temp.constr.constr/partial-specializations.cpp @@ -2,10 +2,10 @@ namespace class_templates { - template<typename T, typename U> requires sizeof(T) >= 4 // expected-note {{because 'sizeof(char) >= 4' (1 >= 4) evaluated to false}} + template<typename T, typename U> requires (sizeof(T) >= 4) // expected-note {{because 'sizeof(char) >= 4' (1 >= 4) evaluated to false}} struct is_same { static constexpr bool value = false; }; - template<typename T> requires sizeof(T*) >= 4 && sizeof(T) >= 4 + template<typename T> requires (sizeof(T*) >= 4 && sizeof(T) >= 4) struct is_same<T*, T*> { static constexpr bool value = true; }; static_assert(!is_same<char*, char*>::value); @@ -23,7 +23,7 @@ namespace class_templates // expected-note@-1{{while substituting template arguments into constraint expression here}} struct B<T*> {}; - template<typename T> requires T{} // expected-error{{atomic constraint must be of type 'bool' (found 'int')}} + template<typename T> requires (T{}) // expected-error{{atomic constraint must be of type 'bool' (found 'int')}} struct B<T**> {}; static_assert((B<int**>{}, true)); // expected-note{{while checking constraint satisfaction for class template partial specialization 'B<int *>' required here}} @@ -35,10 +35,10 @@ namespace class_templates namespace variable_templates { - template<typename T, typename U> requires sizeof(T) >= 4 + template<typename T, typename U> requires (sizeof(T) >= 4) constexpr bool is_same_v = false; - template<typename T> requires sizeof(T*) >= 4 && sizeof(T) >= 4 + template<typename T> requires (sizeof(T*) >= 4 && sizeof(T) >= 4) constexpr bool is_same_v<T*, T*> = true; static_assert(!is_same_v<char*, char*>); @@ -55,7 +55,7 @@ namespace variable_templates // expected-note@-1{{while substituting template arguments into constraint expression here}} constexpr bool v1<T*> = true; - template<typename T> requires T{} // expected-error{{atomic constraint must be of type 'bool' (found 'int')}} + template<typename T> requires (T{}) // expected-error{{atomic constraint must be of type 'bool' (found 'int')}} constexpr bool v1<T**> = true; static_assert(v1<int**>); // expected-note{{while checking constraint satisfaction for variable template partial specialization 'v1<int *>' required here}} diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp index 5d5361f9c20..6f7b80e26a6 100644 --- a/clang/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp +++ b/clang/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp @@ -2,9 +2,9 @@ namespace nodiag { -template <typename T> requires bool(T()) +template <typename T> requires (bool(T())) struct A; -template <typename U> requires bool(U()) +template <typename U> requires (bool(U())) struct A; } // end namespace nodiag @@ -21,7 +21,7 @@ struct B; template <typename T> requires true // expected-note{{previous template declaration is here}} struct C; -template <typename T> requires !0 // expected-error{{requires clause differs in template redeclaration}} +template <typename T> requires (!0) // expected-error{{requires clause differs in template redeclaration}} struct C; } // end namespace diag @@ -29,15 +29,15 @@ struct C; namespace nodiag { struct AA { - template <typename T> requires someFunc(T()) + template <typename T> requires (someFunc(T())) struct A; }; -template <typename U> requires someFunc(U()) +template <typename U> requires (someFunc(U())) struct AA::A { }; struct AAF { - template <typename T> requires someFunc(T()) + template <typename T> requires (someFunc(T())) friend struct AA::A; }; diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.decl/func-template-decl.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.decl/func-template-decl.cpp index c83ab26059d..30fbec64eea 100644 --- a/clang/test/CXX/temp/temp.constr/temp.constr.decl/func-template-decl.cpp +++ b/clang/test/CXX/temp/temp.constr/temp.constr.decl/func-template-decl.cpp @@ -2,9 +2,9 @@ namespace nodiag { -template <typename T> requires bool(T()) +template <typename T> requires (bool(T())) int A(); -template <typename U> requires bool(U()) +template <typename U> requires (bool(U())) int A(); } // end namespace nodiag @@ -26,7 +26,7 @@ int orig::A(); template <typename T> requires true int orig::B(); // expected-error@-1{{out-of-line declaration of 'B' does not match any declaration in namespace 'diag::orig'}} -template <typename T> requires !0 +template <typename T> requires (!0) int orig::C(); // expected-error@-1{{out-of-line declaration of 'C' does not match any declaration in namespace 'diag::orig'}} @@ -35,11 +35,11 @@ int orig::C(); namespace nodiag { struct AA { - template <typename T> requires someFunc(T()) + template <typename T> requires (someFunc(T())) int A(); }; -template <typename T> requires someFunc(T()) +template <typename T> requires (someFunc(T())) int AA::A() { return sizeof(T); } } // end namespace nodiag diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.decl/var-template-decl.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.decl/var-template-decl.cpp index cf6874f12d3..eabb636b0bb 100644 --- a/clang/test/CXX/temp/temp.constr/temp.constr.decl/var-template-decl.cpp +++ b/clang/test/CXX/temp/temp.constr/temp.constr.decl/var-template-decl.cpp @@ -3,11 +3,11 @@ namespace nodiag { struct B { - template <typename T> requires bool(T()) + template <typename T> requires (bool(T())) static int A; }; -template <typename U> requires bool(U()) +template <typename U> requires (bool(U())) int B::A = int(U()); } // end namespace nodiag @@ -15,11 +15,11 @@ int B::A = int(U()); namespace diag { struct B { - template <typename T> requires bool(T()) // expected-note{{previous template declaration is here}} + template <typename T> requires (bool(T())) // expected-note{{previous template declaration is here}} static int A; }; -template <typename U> requires !bool(U()) // expected-error{{requires clause differs in template redeclaration}} +template <typename U> requires (!bool(U())) // expected-error{{requires clause differs in template redeclaration}} int B::A = int(U()); } // end namespace diag
\ No newline at end of file diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.order/class-template-partial-specializations.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.order/class-template-partial-specializations.cpp index 8c2f5526941..5d41035aa88 100644 --- a/clang/test/CXX/temp/temp.constr/temp.constr.order/class-template-partial-specializations.cpp +++ b/clang/test/CXX/temp/temp.constr/temp.constr.order/class-template-partial-specializations.cpp @@ -1,9 +1,12 @@ // RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ -verify %s -template<typename T> requires sizeof(T) >= 4 +template<typename T> requires (sizeof(T) >= 4) +// expected-note@-1{{similar constraint expressions not considered equivalen}} class A{}; // expected-note{{template is declared here}} -template<typename T> requires sizeof(T) >= 4 && sizeof(T) <= 10 +template<typename T> requires (sizeof(T) >= 4 && sizeof(T) <= 10) +// expected-note@-1{{similar constraint expression here}} + class A<T>{}; // expected-error{{class template partial specialization is not more specialized than the primary template}} template<typename T> @@ -12,7 +15,7 @@ concept C1 = sizeof(T) >= 4; template<typename T> requires C1<T> class B{}; -template<typename T> requires C1<T> && sizeof(T) <= 10 +template<typename T> requires (C1<T> && sizeof(T) <= 10) class B<T>{}; template<typename T> @@ -48,3 +51,15 @@ struct F<T>{ enum{ value = 3 }; }; static_assert(F<unsigned>::value == 2); static_assert(F<char[10]>::value == 3); static_assert(F<char>::value == 1); + +// Make sure atomic constraints subsume each other only if their parameter +// mappings are identical. + +template<typename T, typename U> requires C2<T> +struct I { }; // expected-note {{template is declared here}} + +template<typename T, typename U> requires C2<U> +struct I<T, U> { }; // expected-error {{class template partial specialization is not more specialized than the primary template}} + +template<typename T, typename U> requires C2<T> && C2<U> +struct I<T, U> { }; diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.order/function-templates.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.order/function-templates.cpp index cc578fe0ad6..7f68369d528 100644 --- a/clang/test/CXX/temp/temp.constr/temp.constr.order/function-templates.cpp +++ b/clang/test/CXX/temp/temp.constr/temp.constr.order/function-templates.cpp @@ -1,9 +1,11 @@ // RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ -verify %s -template<typename T> requires sizeof(T) >= 4 +template<typename T> requires (sizeof(T) >= 4) +// expected-note@-1{{similar constraint expressions not considered equivalent}} bool a() { return false; } // expected-note {{candidate function [with T = unsigned int]}} -template<typename T> requires sizeof(T) >= 4 && sizeof(T) <= 10 +template<typename T> requires (sizeof(T) >= 4 && sizeof(T) <= 10) +// expected-note@-1{{similar constraint expression here}} bool a() { return true; } // expected-note {{candidate function [with T = unsigned int]}} bool av = a<unsigned>(); // expected-error {{call to 'a' is ambiguous}} @@ -14,7 +16,7 @@ concept C1 = sizeof(T) >= 4; template<typename T> requires C1<T> constexpr bool b() { return false; } -template<typename T> requires C1<T> && sizeof(T) <= 10 +template<typename T> requires (C1<T> && sizeof(T) <= 10) constexpr bool b() { return true; } static_assert(b<int>()); @@ -86,4 +88,4 @@ static_assert(sizeof(g<int>())); template <unsigned> struct X {}; template <class...> int h(X<0>); template <unsigned b, class...> int h(X<b>); -static_assert(sizeof(h(X<0>{})));
\ No newline at end of file +static_assert(sizeof(h(X<0>{}))); diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.order/var-template-partial-specializations.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.order/var-template-partial-specializations.cpp index b40c77e70a1..cf88e34036d 100644 --- a/clang/test/CXX/temp/temp.constr/temp.constr.order/var-template-partial-specializations.cpp +++ b/clang/test/CXX/temp/temp.constr/temp.constr.order/var-template-partial-specializations.cpp @@ -1,9 +1,11 @@ // RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ -verify %s -template<typename T> requires sizeof(T) >= 4 +template<typename T> requires (sizeof(T) >= 4) +// expected-note@-1{{similar constraint expressions not considered equivalent}} bool a = false; // expected-note{{template is declared here}} -template<typename T> requires sizeof(T) >= 4 && sizeof(T) <= 10 +template<typename T> requires (sizeof(T) >= 4 && sizeof(T) <= 10) +// expected-note@-1{{similar constraint expression here}} bool a<T> = true; // expected-error{{variable template partial specialization is not more specialized than the primary template}} template<typename T> @@ -12,7 +14,7 @@ concept C1 = sizeof(T) >= 4; template<typename T> requires C1<T> bool b = false; -template<typename T> requires C1<T> && sizeof(T) <= 10 +template<typename T> requires (C1<T> && sizeof(T) <= 10) bool b<T> = true; template<typename T> diff --git a/clang/test/CXX/temp/temp.explicit/p8.cpp b/clang/test/CXX/temp/temp.explicit/p8.cpp new file mode 100644 index 00000000000..72d22557899 --- /dev/null +++ b/clang/test/CXX/temp/temp.explicit/p8.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ -verify %s + +template<typename T, typename S = char> requires (sizeof(T) + sizeof(S) < 10) +// expected-note@-1{{because 'sizeof(char [100]) + sizeof(char) < 10' (101 < 10) evaluated to false}} +void f(T t, S s) requires (sizeof(t) == 1 && sizeof(s) == 1) { }; +// expected-note@-1{{candidate template ignored: constraints not satisfied [with T = int, S = char]}} +// expected-note@-2{{because 'sizeof (t) == 1' (4 == 1) evaluated to false}} +// expected-note@-3{{candidate template ignored: constraints not satisfied [with T = char, S = short]}} +// expected-note@-4{{because 'sizeof (s) == 1' (2 == 1) evaluated to false}} +// expected-note@-5{{candidate template ignored: constraints not satisfied [with T = char [100], S = char]}} + +template<> +void f<int>(int t, char s) { }; +// expected-error@-1{{no function template matches function template specialization 'f'}} + +template<> +void f<char, short>(char t, short s) { }; +// expected-error@-1{{no function template matches function template specialization 'f'}} + +template<> +void f<char[100]>(char t[100], char s) { }; +// expected-error@-1{{no function template matches function template specialization 'f'}}
\ No newline at end of file diff --git a/clang/test/Parser/cxx-concepts-ambig-constraint-expr.cpp b/clang/test/Parser/cxx-concepts-ambig-constraint-expr.cpp index 12ab338a6b0..1cd2605ce05 100644 --- a/clang/test/Parser/cxx-concepts-ambig-constraint-expr.cpp +++ b/clang/test/Parser/cxx-concepts-ambig-constraint-expr.cpp @@ -5,25 +5,5 @@ // the syntax is consumed without backtracking. // type-specifier-seq in conversion-type-id -template <typename T> requires (bool)&T::operator short -unsigned int foo(); // expected-error {{C++ requires a type specifier for all declarations}} - -// type-specifier-seq in new-type-id -template <typename T> requires (bool)sizeof new (T::f()) short -unsigned int bar(); // expected-error {{C++ requires a type specifier for all declarations}} - -template<typename T> requires (bool)sizeof new (T::f()) unsigned // expected-error {{'struct' cannot be signed or unsigned}} -struct X { }; // expected-error {{'X' cannot be defined in a type specifier}} - -// C-style cast -// of function call on function-style cast -template <typename T> requires (bool(T())) -T (*fp)(); // expected-error {{use of undeclared identifier 'fp'}} - -// function-style cast -// as the callee in a function call -struct A { - static int t; - template <typename T> requires bool(T()) - (A(T (&t))) { } // expected-error {{called object type 'bool' is not a function or function pointer}} -}; +template <typename T> requires T::operator short +unsigned int foo(); // expected-error {{C++ requires a type specifier for all declarations}}
\ No newline at end of file diff --git a/clang/test/Parser/cxx-concepts-requires-clause.cpp b/clang/test/Parser/cxx-concepts-requires-clause.cpp index 01893a94cbc..60e7004e081 100644 --- a/clang/test/Parser/cxx-concepts-requires-clause.cpp +++ b/clang/test/Parser/cxx-concepts-requires-clause.cpp @@ -1,13 +1,11 @@ -// RUN: %clang_cc1 -std=c++14 -fconcepts-ts -x c++ %s -verify -// expected-no-diagnostics +// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify // Test parsing of the optional requires-clause in a template-declaration. template <typename T> requires true void foo() { } - -template <typename T> requires !0 +template <typename T> requires (!0) struct A { void foo(); struct AA; @@ -27,31 +25,30 @@ struct A { using MQ = M<TT>; }; -template <typename T> requires !0 +template <typename T> requires (!0) void A<T>::foo() { } -template <typename T> requires !0 +template <typename T> requires (!0) struct A<T>::AA { }; -template <typename T> requires !0 +template <typename T> requires (!0) enum A<T>::E : int { E0 }; -template <typename T> requires !0 +template <typename T> requires (!0) int A<T>::x = 0; -template <typename T> requires !0 +template <typename T> requires (!0) template <typename> requires true void A<T>::Mfoo() { } -template <typename T> requires !0 +template <typename T> requires (!0) template <typename> requires true struct A<T>::M { }; -template <typename T> requires !0 +template <typename T> requires (!0) template <typename> requires true int A<T>::Mx = 0; - template <typename T> requires true int x = 0; @@ -80,3 +77,81 @@ struct C::M { }; template <typename> requires true int C::Mx = 0; + +// Test behavior with non-primary-expression requires clauses + +template<typename T> requires foo<T>() +// expected-error@-1{{parentheses are required around this expression in a requires clause}} +struct B1 { }; + +int func() { } + +template<typename T> requires func() +// expected-error@-1{{atomic constraint must be of type 'bool' (found '<overloaded function type>')}} +// expected-note@-2{{parentheses are required around this expression in a requires clause}} +struct B2 { }; + +template<typename T> requires (foo<T>()) +struct B3 { }; + +template<typename T> requires T{} +// expected-error@-1{{parentheses are required around this expression in a requires clause}} +struct B4 { }; + +template<typename T> requires sizeof(T) == 0 +// expected-error@-1{{parentheses are required around this expression in a requires clause}} +struct B5 { }; + +template<typename T> requires (sizeof(T)) == 0 +// expected-error@-1{{parentheses are required around this expression in a requires clause}} +struct B6 { }; + +template<typename T> requires 0 +// expected-error@-1{{atomic constraint must be of type 'bool' (found 'int')}} +(int) bar() { }; + +template<typename T> requires foo<T> +(int) bar() { }; +// expected-error@-1{{expected '(' for function-style cast or type construction}} + +template<typename T> +void bar() requires foo<T>(); +// expected-error@-1{{parentheses are required around this expression in a requires clause}} + +template<typename T> +void bar() requires (foo<T>()); + +template<typename T> +void bar() requires func(); +// expected-error@-1{{atomic constraint must be of type 'bool' (found '<overloaded function type>')}} +// expected-note@-2{{parentheses are required around this expression in a requires clause}} + +template<typename T> +void bar() requires T{}; +// expected-error@-1{{parentheses are required around this expression in a requires clause}} + +template<typename T> +void bar() requires sizeof(T) == 0; +// expected-error@-1{{parentheses are required around this expression in a requires clause}} + +template<typename T> +void bar() requires (sizeof(T)) == 0; +// expected-error@-1{{parentheses are required around this expression in a requires clause}} + +void bar(int x, int y) requires (x, y, true); + +struct B { + int x; + void foo(int y) requires (x, this, this->x, y, true); + static void bar(int y) requires (x, true); + // expected-error@-1{{'this' cannot be implicitly used in a static member function declaration}} + static void baz(int y) requires (this, true); + // expected-error@-1{{'this' cannot be used in a static member function declaration}} +}; + +auto lambda1 = [] (auto x) requires (sizeof(decltype(x)) == 1) { }; + +auto lambda2 = [] (auto x) constexpr -> int requires (sizeof(decltype(x)) == 1) { return 0; }; + +auto lambda3 = [] requires (sizeof(char) == 1) { }; +// expected-error@-1{{lambda requires '()' before 'requires' clause}}
\ No newline at end of file diff --git a/clang/test/SemaTemplate/instantiate-requires-clause.cpp b/clang/test/SemaTemplate/instantiate-requires-clause.cpp new file mode 100644 index 00000000000..f36396b98db --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-requires-clause.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify + +template <typename... Args> requires ((sizeof(Args) == 1), ...) +// expected-note@-1 {{because '(sizeof(int) == 1) , (sizeof(char) == 1) , (sizeof(int) == 1)' evaluated to false}} +void f1(Args&&... args) { } +// expected-note@-1 {{candidate template ignored: constraints not satisfied [with Args = <int, char, int>]}} + +using f11 = decltype(f1('a')); +using f12 = decltype(f1(1, 'b')); +using f13 = decltype(f1(1, 'b', 2)); +// expected-error@-1 {{no matching function for call to 'f1'}} + +template <typename... Args> +void f2(Args&&... args) requires ((sizeof(args) == 1), ...) { } +// expected-note@-1 {{candidate template ignored: constraints not satisfied [with Args = <int, char, int>]}} +// expected-note@-2 {{because '(sizeof (args) == 1) , (sizeof (args) == 1) , (sizeof (args) == 1)' evaluated to false}} + +using f21 = decltype(f2('a')); +using f22 = decltype(f2(1, 'b')); +using f23 = decltype(f2(1, 'b', 2)); +// expected-error@-1 {{no matching function for call to 'f2'}} + +template <typename... Args> requires ((sizeof(Args) == 1), ...) +// expected-note@-1 {{because '(sizeof(int) == 1) , (sizeof(char) == 1) , (sizeof(int) == 1)' evaluated to false}} +void f3(Args&&... args) requires ((sizeof(args) == 1), ...) { } +// expected-note@-1 {{candidate template ignored: constraints not satisfied [with Args = <int, char, int>]}} + +using f31 = decltype(f3('a')); +using f32 = decltype(f3(1, 'b')); +using f33 = decltype(f3(1, 'b', 2)); +// expected-error@-1 {{no matching function for call to 'f3'}} |