|  | // RUN: %clang_cc1 %s -verify -fopenacc | 
|  |  | 
|  | struct Incomplete; // #INCOMPLETE | 
|  | struct NotConvertible{} NC; | 
|  |  | 
|  | struct CorrectConvert { | 
|  | operator int(); | 
|  | } Convert; | 
|  |  | 
|  | constexpr int returns_3() { return 3; } | 
|  |  | 
|  | using FuncPtrTy = void (*)(); | 
|  | FuncPtrTy FuncPtrTyArray[2]; | 
|  |  | 
|  | void Func(int i, int j) { | 
|  | int array[5]; | 
|  | int VLA[i]; | 
|  | int *ptr; | 
|  | void *void_ptr; | 
|  |  | 
|  | // Follows int-expr rules, so only convertible to int. | 
|  | // expected-error@+1{{OpenACC sub-array bound requires expression of integer type ('struct NotConvertible' invalid}} | 
|  | #pragma acc parallel private(array[NC:]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array bound requires expression of integer type ('struct NotConvertible' invalid}} | 
|  | #pragma acc parallel private(array[:NC]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+2{{OpenACC sub-array bound requires expression of integer type ('struct NotConvertible' invalid}} | 
|  | // expected-error@+1{{OpenACC sub-array bound requires expression of integer type ('struct NotConvertible' invalid}} | 
|  | #pragma acc parallel private(array[NC:NC]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+2{{OpenACC sub-array bound requires expression of integer type ('struct NotConvertible' invalid}} | 
|  | // expected-error@+1{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is not an array}} | 
|  | #pragma acc parallel private(ptr[NC:]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array bound requires expression of integer type ('struct NotConvertible' invalid}} | 
|  | #pragma acc parallel private(ptr[:NC]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+2{{OpenACC sub-array bound requires expression of integer type ('struct NotConvertible' invalid}} | 
|  | // expected-error@+1{{OpenACC sub-array bound requires expression of integer type ('struct NotConvertible' invalid}} | 
|  | #pragma acc parallel private(ptr[NC:NC]) | 
|  | while (true); | 
|  |  | 
|  | // These are convertible, so they work. | 
|  | #pragma acc parallel private(array[Convert:Convert]) | 
|  | while (true); | 
|  |  | 
|  | #pragma acc parallel private(ptr[Convert:Convert]) | 
|  | while (true); | 
|  |  | 
|  |  | 
|  | // The length for "dynamically" allocated dimensions of an array must be | 
|  | // explicitly specified. | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is not an array}} | 
|  | #pragma acc parallel private(ptr[3:]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+2{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is an array of unknown bound}} | 
|  | // expected-warning@+1{{variable of array type 'int[i]' referenced in OpenACC 'private' clause does not have constant bounds; initialization will happen after decay to pointer}} | 
|  | #pragma acc parallel private(VLA[3:]) | 
|  | while (true); | 
|  |  | 
|  | #pragma acc parallel private(ptr[:3]) | 
|  | while (true); | 
|  |  | 
|  | // expected-warning@+1{{variable of array type 'int[i]' referenced in OpenACC 'private' clause does not have constant bounds; initialization will happen after decay to pointer}} | 
|  | #pragma acc parallel private(VLA[:3]) | 
|  | while (true); | 
|  |  | 
|  | // Error if the length of the array + the initializer is bigger the the array | 
|  | // with known bounds. | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array length evaluated to a value (6) that would be out of the range of the subscripted array size of 5}} | 
|  | #pragma acc parallel private(array[i:returns_3() + 3]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array length evaluated to a value (6) that would be out of the range of the subscripted array size of 5}} | 
|  | #pragma acc parallel private(array[:returns_3() + 3]) | 
|  | while (true); | 
|  |  | 
|  | #pragma acc parallel private(array[:returns_3()]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array specified range [3:3] would be out of the range of the subscripted array size of 5}} | 
|  | #pragma acc parallel private(array[returns_3():returns_3()]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array lower bound evaluated to a value (6) that would be out of the range of the subscripted array size of 5}} | 
|  | #pragma acc parallel private(array[returns_3() + 3:]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array lower bound evaluated to a value (6) that would be out of the range of the subscripted array size of 5}} | 
|  | #pragma acc parallel private(array[returns_3() + 3:1]) | 
|  | while (true); | 
|  |  | 
|  | // Standard doesn't specify this, but negative values are likely not | 
|  | // permitted, so disallow them here until we come up with a good reason to do | 
|  | // otherwise. | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array lower bound evaluated to negative value -1}} | 
|  | #pragma acc parallel private(array[returns_3() - 4 : ]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array length evaluated to negative value -1}} | 
|  | #pragma acc parallel private(array[: -1]) | 
|  | while (true); | 
|  |  | 
|  | Incomplete *IncompletePtr; | 
|  | // expected-error@+2{{OpenACC sub-array base is of incomplete type 'Incomplete'}} | 
|  | // expected-note@#INCOMPLETE{{forward declaration of 'Incomplete'}} | 
|  | #pragma acc parallel private(IncompletePtr[0 :1]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array base is of incomplete type 'void'}} | 
|  | #pragma acc parallel private(void_ptr[0:1]) | 
|  | while (true); | 
|  |  | 
|  | // OK: these are function pointers. | 
|  | #pragma acc parallel private(FuncPtrTyArray[0 :1]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array cannot be of function type 'void ()'}} | 
|  | #pragma acc parallel private(FuncPtrTyArray[0][0 :1]) | 
|  | while (true); | 
|  |  | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array subscripted value is not an array or pointer}} | 
|  | #pragma acc parallel private(i[0:1]) | 
|  | while (true); | 
|  | } | 
|  |  | 
|  | template<typename T, typename U, typename V, unsigned I, auto &CEArray> | 
|  | void Templ(int i){ | 
|  | T array[I]; | 
|  | T VLA[i]; | 
|  | T *ptr; | 
|  | U NC; | 
|  | V Conv; | 
|  |  | 
|  | // Convertible: | 
|  | // expected-error@+2{{OpenACC sub-array bound requires expression of integer type ('NotConvertible' invalid}} | 
|  | // expected-note@#INST{{in instantiation of function template specialization}} | 
|  | #pragma acc parallel private(array[NC:]) | 
|  | while (true); | 
|  | // expected-error@+1{{OpenACC sub-array bound requires expression of integer type ('NotConvertible' invalid}} | 
|  | #pragma acc parallel private(array[:NC]) | 
|  | while (true); | 
|  |  | 
|  | #pragma acc parallel private(array[Conv:]) | 
|  | while (true); | 
|  | #pragma acc parallel private(array[:Conv]) | 
|  | while (true); | 
|  |  | 
|  | // Need a length for unknown size. | 
|  | // expected-error@+1{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is not an array}} | 
|  | #pragma acc parallel private(ptr[Conv:]) | 
|  | while (true); | 
|  | // expected-error@+2{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is an array of unknown bound}} | 
|  | // expected-warning@+1{{variable of array type 'int[i]' referenced in OpenACC 'private' clause does not have constant bounds; initialization will happen after decay to pointer}} | 
|  | #pragma acc parallel private(VLA[Conv:]) | 
|  | while (true); | 
|  | #pragma acc parallel private(ptr[:Conv]) | 
|  | while (true); | 
|  | // expected-warning@+1{{variable of array type 'int[i]' referenced in OpenACC 'private' clause does not have constant bounds; initialization will happen after decay to pointer}} | 
|  | #pragma acc parallel private(VLA[:Conv]) | 
|  | while (true); | 
|  |  | 
|  | // Out of bounds. | 
|  | // expected-error@+1{{OpenACC sub-array lower bound evaluated to a value (2) that would be out of the range of the subscripted array size of 2}} | 
|  | #pragma acc parallel private(array[I:]) | 
|  | while (true); | 
|  |  | 
|  | // OK, don't know the value. | 
|  | #pragma acc parallel private(array[i:]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array length evaluated to a value (3) that would be out of the range of the subscripted array size of 2}} | 
|  | #pragma acc parallel private(array[:I + 1]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array lower bound evaluated to a value (5) that would be out of the range of the subscripted array size of 5}} | 
|  | #pragma acc parallel private(CEArray[5:]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array length evaluated to a value (6) that would be out of the range of the subscripted array size of 5}} | 
|  | #pragma acc parallel private(CEArray[:2 + I + I]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array length evaluated to a value (4294967295) that would be out of the range of the subscripted array size of 5}} | 
|  | #pragma acc parallel private(CEArray[:1 - I]) | 
|  | while (true); | 
|  |  | 
|  | // expected-error@+1{{OpenACC sub-array lower bound evaluated to a value (4294967295) that would be out of the range of the subscripted array size of 5}} | 
|  | #pragma acc parallel private(CEArray[1 - I:]) | 
|  | while (true); | 
|  |  | 
|  | T not_ptr; | 
|  | // expected-error@+1{{OpenACC sub-array subscripted value is not an array or pointer}} | 
|  | #pragma acc parallel private(not_ptr[0:1]) | 
|  | while (true); | 
|  | } | 
|  |  | 
|  | void inst() { | 
|  | static constexpr int CEArray[5]={1,2,3,4,5}; | 
|  | Templ<int, NotConvertible, CorrectConvert, 2, CEArray>(5); // #INST | 
|  | } |