forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			157 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
| // RUN: %clang_cc1 -std=c++2a -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)
 | |
| struct A {
 | |
|   void foo();
 | |
|   struct AA;
 | |
|   enum E : int;
 | |
|   static int x;
 | |
| 
 | |
|   template <typename> requires true
 | |
|   void Mfoo();
 | |
| 
 | |
|   template <typename> requires true
 | |
|   struct M;
 | |
| 
 | |
|   template <typename> requires true
 | |
|   static int Mx;
 | |
| 
 | |
|   template <typename TT> requires true
 | |
|   using MQ = M<TT>;
 | |
| };
 | |
| 
 | |
| template <typename T> requires (!0)
 | |
| void A<T>::foo() { }
 | |
| 
 | |
| template <typename T> requires (!0)
 | |
| struct A<T>::AA { };
 | |
| 
 | |
| template <typename T> requires (!0)
 | |
| enum A<T>::E : int { E0 };
 | |
| 
 | |
| template <typename T> requires (!0)
 | |
| int A<T>::x = 0;
 | |
| 
 | |
| template <typename T> requires (!0)
 | |
| template <typename> requires true
 | |
| void A<T>::Mfoo() { }
 | |
| 
 | |
| template <typename T> requires (!0)
 | |
| template <typename> requires true
 | |
| struct A<T>::M { };
 | |
| 
 | |
| template <typename T> requires (!0)
 | |
| template <typename> requires true
 | |
| int A<T>::Mx = 0;
 | |
| 
 | |
| template <typename T> requires true
 | |
| int x = 0;
 | |
| 
 | |
| template <typename T> requires true
 | |
| using Q = A<T>;
 | |
| 
 | |
| struct C {
 | |
|   template <typename> requires true
 | |
|   void Mfoo();
 | |
| 
 | |
|   template <typename> requires true
 | |
|   struct M;
 | |
| 
 | |
|   template <typename> requires true
 | |
|   static int Mx;
 | |
| 
 | |
|   template <typename T> requires true
 | |
|   using MQ = M<T>;
 | |
| };
 | |
| 
 | |
| template <typename> requires true
 | |
| void C::Mfoo() { }
 | |
| 
 | |
| template <typename> requires true
 | |
| 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}}
 |