summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp31
-rw-r--r--clang/test/CXX/temp/temp.constr/temp.constr.constr/function-templates.cpp43
-rw-r--r--clang/test/CXX/temp/temp.constr/temp.constr.constr/non-function-templates.cpp92
-rw-r--r--clang/test/CXX/temp/temp.constr/temp.constr.constr/partial-specializations.cpp67
4 files changed, 233 insertions, 0 deletions
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp
index dd3f0c0e3d6..1e10d4550ce 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp
@@ -72,6 +72,15 @@ template<typename T> struct T2 { static constexpr bool value = sizeof(T) == 2; }
static_assert(IsTypePredicate<T2>);
static_assert(!IsTypePredicate<T1>);
+template<typename T, typename U, typename... Ts>
+concept OneOf = (Same<T, Ts> || ...);
+
+template<typename... X>
+constexpr bool S = OneOf<X..., int, int>;
+
+static_assert(S<int, long, int>);
+static_assert(!S<long, int, char, char>);
+
namespace piecewise_substitution {
template <typename T>
concept True = true;
@@ -147,3 +156,25 @@ template<typename T>
struct X { static constexpr bool a = SameSize<T>; };
static_assert(X<unsigned>::a);
+
+// static_assert concept diagnostics
+template<typename T>
+concept Large = sizeof(T) > 100;
+// expected-note@-1 2{{because 'sizeof(small) > 100' (1 > 100) evaluated to false}}
+
+struct small { };
+static_assert(Large<small>);
+// expected-error@-1 {{static_assert failed}}
+// expected-note@-2 {{because 'small' does not satisfy 'Large'}}
+static_assert(Large<small>, "small isn't large");
+// expected-error@-1 {{static_assert failed "small isn't large"}}
+// expected-note@-2 {{because 'small' does not satisfy 'Large'}}
+
+// Make sure access-checking can fail a concept specialization
+
+class T4 { static constexpr bool f = true; };
+template<typename T> concept AccessPrivate = T{}.f;
+// expected-note@-1{{because substituted constraint expression is ill-formed: 'f' is a private member of 'T4'}}
+static_assert(AccessPrivate<T4>);
+// expected-error@-1{{static_assert failed}}
+// expected-note@-2{{because 'T4' does not satisfy 'AccessPrivate'}}
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
new file mode 100644
index 00000000000..c1a3a27fbea
--- /dev/null
+++ b/clang/test/CXX/temp/temp.constr/temp.constr.constr/function-templates.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ -verify %s
+
+template<typename T>
+constexpr bool is_ptr_v = false;
+
+template<typename T>
+constexpr bool is_ptr_v<T*> = true;
+
+template<typename T, typename U>
+constexpr bool is_same_v = false;
+
+template<typename T>
+constexpr bool is_same_v<T, T> = true;
+
+template<typename T> requires is_ptr_v<T> // expected-note {{because 'is_ptr_v<int>' evaluated to false}}
+ // expected-note@-1{{because 'is_ptr_v<char>' evaluated to false}}
+auto dereference(T t) { // expected-note {{candidate template ignored: constraints not satisfied [with T = int]}}
+ // expected-note@-1{{candidate template ignored: constraints not satisfied [with T = char]}}
+ return *t;
+}
+
+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')}}
+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
+// 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]}}
+ return t + t;
+}
+
+struct A { };
+
+static_assert(foo(A{})); // expected-error {{no matching function for call to 'foo'}}
+static_assert(bar(A{})); // expected-error {{no matching function for call to 'bar'}} \ No newline at end of file
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
new file mode 100644
index 00000000000..24caa5063a1
--- /dev/null
+++ b/clang/test/CXX/temp/temp.constr/temp.constr.constr/non-function-templates.cpp
@@ -0,0 +1,92 @@
+// 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}}
+struct A {
+ static constexpr int value = sizeof(T);
+};
+
+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}}
+constexpr int SizeDiff = sizeof(T) > sizeof(U) ? sizeof(T) - sizeof(U) : sizeof(U) - sizeof(T);
+
+static_assert(SizeDiff<int, char> == 3);
+static_assert(SizeDiff<int, char[4]> == 0); // expected-error{{constraints not satisfied for variable template 'SizeDiff' [with T = int, U = char [4]]}}
+static_assert(SizeDiff<char, int> == 3); // expected-error{{constraints not satisfied for variable template 'SizeDiff' [with T = char, U = int]}}
+
+template<typename... Ts>
+ requires ((sizeof(Ts) == 4) || ...) // expected-note{{because 'sizeof(char) == 4' (1 == 4) evaluated to false}} expected-note{{'sizeof(long long) == 4' (8 == 4) evaluated to false}} expected-note{{'sizeof(int [20]) == 4' (80 == 4) evaluated to false}}
+constexpr auto SumSizes = (sizeof(Ts) + ...);
+
+static_assert(SumSizes<char, long long, int> == 13);
+static_assert(SumSizes<char, long long, int[20]> == 89); // expected-error{{constraints not satisfied for variable template 'SumSizes' [with Ts = <char, long long, int [20]>]}}
+
+template<typename T>
+concept IsBig = sizeof(T) > 100; // expected-note{{because 'sizeof(int) > 100' (4 > 100) evaluated to false}}
+
+template<typename T>
+ requires IsBig<T> // expected-note{{'int' does not satisfy 'IsBig'}}
+using BigPtr = T*;
+
+static_assert(sizeof(BigPtr<int>)); // expected-error{{constraints not satisfied for alias template 'BigPtr' [with T = int]}}}}
+
+template<typename T> requires T::value // expected-note{{because substituted constraint expression is ill-formed: type 'int' cannot be used prior to '::' because it has no members}}
+struct S { static constexpr bool value = true; };
+
+struct S2 { static constexpr bool value = true; };
+
+static_assert(S<int>::value); // expected-error{{constraints not satisfied for class template 'S' [with T = int]}}
+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}}
+ 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}}
+ 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}}
+ static constexpr int getB() { // expected-note{{candidate template ignored: constraints not satisfied [with U = int [2]]}}
+ return 2;
+ }
+
+ static auto foo()
+ {
+ return B<T[2]>::a; // expected-error{{constraints not satisfied for class template 'B' [with U = int [2]]}}
+ }
+
+ static auto foo1()
+ {
+ return b<T[2]>; // expected-error{{constraints not satisfied for variable template 'b' [with U = int [2]]}}
+ }
+
+ static auto foo2()
+ {
+ return AA<T>::getB<T[2]>(); // expected-error{{no matching function for call to 'getB'}}
+ }
+};
+
+constexpr auto x = AA<int>::foo(); // expected-note{{in instantiation of member function 'AA<int>::foo' requested here}}
+constexpr auto x1 = AA<int>::foo1(); // expected-note{{in instantiation of member function 'AA<int>::foo1' requested here}}
+constexpr auto x2 = AA<int>::foo2(); // expected-note{{in instantiation of member function 'AA<int>::foo2' requested here}}
+
+template<typename T>
+struct B { using type = typename T::type; }; // expected-error{{type 'int' cannot be used prior to '::' because it has no members}}
+
+template<typename T> requires B<T>::type // expected-note{{in instantiation of template class 'B<int>' requested here}}
+ // 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')}}
+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
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
new file mode 100644
index 00000000000..47bd2a55076
--- /dev/null
+++ b/clang/test/CXX/temp/temp.constr/temp.constr.constr/partial-specializations.cpp
@@ -0,0 +1,67 @@
+// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ -verify %s
+
+namespace class_templates
+{
+ 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
+ struct is_same<T*, T*> { static constexpr bool value = true; };
+
+ static_assert(!is_same<char*, char*>::value);
+ static_assert(!is_same<short*, short*>::value);
+ static_assert(is_same<int*, int*>::value);
+ static_assert(is_same<char, char>::value); // expected-error {{constraints not satisfied for class template 'is_same' [with T = char, U = char]}}
+
+ template<typename T>
+ struct A { using type = typename T::type; }; // expected-error{{type 'int *' cannot be used prior to '::' because it has no members}}
+
+ template<typename T>
+ struct B {};
+
+ template<typename T> requires A<T>::type // expected-note{{in instantiation of template class 'class_templates::A<int *>' requested here}}
+ // 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')}}
+ struct B<T**> {};
+
+ static_assert((B<int**>{}, true)); // expected-note{{while checking constraint satisfaction for class template partial specialization 'B<int *>' required here}}
+ // expected-note@-1{{while checking constraint satisfaction for class template partial specialization 'B<int>' required here}}
+ // expected-note@-2{{during template argument deduction for class template partial specialization 'B<T *>' [with T = int *]}}
+ // expected-note@-3{{during template argument deduction for class template partial specialization 'B<T **>' [with T = int]}}
+ // expected-note@-4 2{{in instantiation of template class 'class_templates::B<int **>' requested here}}
+}
+
+namespace variable_templates
+{
+ 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
+ constexpr bool is_same_v<T*, T*> = true;
+
+ static_assert(!is_same_v<char*, char*>);
+ static_assert(!is_same_v<short*, short*>);
+ static_assert(is_same_v<int*, int*>);
+
+ template<typename T>
+ struct A { using type = typename T::type; }; // expected-error{{type 'int *' cannot be used prior to '::' because it has no members}}
+
+ template<typename T>
+ constexpr bool v1 = false;
+
+ template<typename T> requires A<T>::type // expected-note{{in instantiation of template class 'variable_templates::A<int *>' requested here}}
+ // 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')}}
+ constexpr bool v1<T**> = true;
+
+ static_assert(v1<int**>); // expected-note{{while checking constraint satisfaction for variable template partial specialization 'v1<int *>' required here}}
+ // expected-note@-1{{while checking constraint satisfaction for variable template partial specialization 'v1<int>' required here}}
+ // expected-note@-2{{during template argument deduction for variable template partial specialization 'v1<T *>' [with T = int *]}}
+ // expected-note@-3{{during template argument deduction for variable template partial specialization 'v1<T **>' [with T = int]}}
+ // expected-error@-4{{static_assert failed due to requirement 'v1<int **>'}}
+
+} \ No newline at end of file
OpenPOWER on IntegriCloud