| 1 | // RUN: %clang_cc1 -x c++ -std=c++14 -fsyntax-only -verify %s |
| 2 | |
| 3 | template <int I, int J, int K> |
| 4 | void car() { |
| 5 | int __attribute__((address_space(I))) __attribute__((address_space(J))) * Y; // expected-error {{multiple address spaces specified for type}} |
| 6 | int *__attribute__((address_space(I))) __attribute__((address_space(J))) * Z; // expected-error {{multiple address spaces specified for type}} |
| 7 | |
| 8 | __attribute__((address_space(I))) int local; // expected-error {{automatic variable qualified with an address space}} |
| 9 | __attribute__((address_space(J))) int array[5]; // expected-error {{automatic variable qualified with an address space}} |
| 10 | __attribute__((address_space(I))) int arrarr[5][5]; // expected-error {{automatic variable qualified with an address space}} |
| 11 | |
| 12 | __attribute__((address_space(J))) * x; // expected-error {{C++ requires a type specifier for all declarations}} |
| 13 | |
| 14 | __attribute__((address_space(I))) float *B; |
| 15 | |
| 16 | typedef __attribute__((address_space(J))) int AS2Int; |
| 17 | struct HasASFields { |
| 18 | AS2Int typedef_as_field; // expected-error {{field may not be qualified with an address space}} |
| 19 | }; |
| 20 | |
| 21 | struct _st { |
| 22 | int x, y; |
| 23 | } s __attribute((address_space(I))) = {1, 1}; |
| 24 | } |
| 25 | |
| 26 | template <int I> |
| 27 | struct HasASTemplateFields { |
| 28 | __attribute__((address_space(I))) int as_field; // expected-error {{field may not be qualified with an address space}} |
| 29 | }; |
| 30 | |
| 31 | template <int I, int J> |
| 32 | void foo(__attribute__((address_space(I))) float *a, // expected-note {{candidate template ignored: substitution failure [with I = 1, J = 2]: parameter may not be qualified with an address space}} |
| 33 | __attribute__((address_space(J))) float b) { |
| 34 | *a = 5.0f + b; |
| 35 | } |
| 36 | |
| 37 | template void foo<1, 2>(float *, float); // expected-error {{explicit instantiation of 'foo' does not refer to a function template, variable template, member function, member class, or static data member}} |
| 38 | |
| 39 | template <int I> |
| 40 | void neg() { |
| 41 | __attribute__((address_space(I))) int *bounds; // expected-error {{address space is negative}} |
| 42 | } |
| 43 | |
| 44 | template <long int I> |
| 45 | void tooBig() { |
| 46 | __attribute__((address_space(I))) int *bounds; // expected-error {{address space is larger than the maximum supported (8388598)}} |
| 47 | } |
| 48 | |
| 49 | template <long int I> |
| 50 | void correct() { |
| 51 | __attribute__((address_space(I))) int *bounds; |
| 52 | } |
| 53 | |
| 54 | template <int I, int J> |
| 55 | char *cmp(__attribute__((address_space(I))) char *x, __attribute__((address_space(J))) char *y) { |
| 56 | return x < y ? x : y; // expected-error {{comparison of distinct pointer types ('__attribute__((address_space(1))) char *' and '__attribute__((address_space(2))) char *')}} |
| 57 | } |
| 58 | |
| 59 | typedef void ft(void); |
| 60 | |
| 61 | template <int I> |
| 62 | struct fooFunction { |
| 63 | __attribute__((address_space(I))) void **const base = 0; |
| 64 | |
| 65 | void *get_0(void) { |
| 66 | return base[0]; // expected-error {{cannot initialize return object of type 'void *' with an lvalue of type '__attribute__((address_space(1))) void *}} |
| 67 | } |
| 68 | |
| 69 | __attribute__((address_space(I))) ft qf; // expected-error {{function type may not be qualified with an address space}} |
| 70 | __attribute__((address_space(I))) char *test3_val; |
| 71 | |
| 72 | void test3(void) { |
| 73 | extern void test3_helper(char *p); // expected-note {{passing argument to parameter 'p' here}} |
| 74 | test3_helper(test3_val); // expected-error {{cannot initialize a parameter of type 'char *' with an lvalue of type '__attribute__((address_space(1))) char *'}} |
| 75 | } |
| 76 | }; |
| 77 | |
| 78 | template <typename T, int N> |
| 79 | int GetAddressSpaceValue(T __attribute__((address_space(N))) * p) { |
| 80 | return N; |
| 81 | } |
| 82 | |
| 83 | template <unsigned A> int __attribute__((address_space(A))) *same_template(); |
| 84 | template <unsigned B> int __attribute__((address_space(B))) *same_template(); |
| 85 | void test_same_template() { (void) same_template<0>(); } |
| 86 | |
| 87 | template <unsigned A> int __attribute__((address_space(A))) *different_template(); // expected-note {{candidate function [with A = 0]}} |
| 88 | template <unsigned B> int __attribute__((address_space(B+1))) *different_template(); // expected-note {{candidate function [with B = 0]}} |
| 89 | void test_different_template() { (void) different_template<0>(); } // expected-error {{call to 'different_template' is ambiguous}} |
| 90 | |
| 91 | template <typename T> struct partial_spec_deduce_as; |
| 92 | template <typename T, unsigned AS> |
| 93 | struct partial_spec_deduce_as <__attribute__((address_space(AS))) T *> { |
| 94 | static const unsigned value = AS; |
| 95 | }; |
| 96 | |
| 97 | int main() { |
| 98 | int __attribute__((address_space(1))) * p1; |
| 99 | int p = GetAddressSpaceValue(p1); |
| 100 | |
| 101 | car<1, 2, 3>(); // expected-note {{in instantiation of function template specialization 'car<1, 2, 3>' requested here}} |
| 102 | HasASTemplateFields<1> HASTF; |
| 103 | neg<-1>(); // expected-note {{in instantiation of function template specialization 'neg<-1>' requested here}} |
| 104 | correct<0x7FFFF6>(); |
| 105 | tooBig<8388650>(); // expected-note {{in instantiation of function template specialization 'tooBig<8388650>' requested here}} |
| 106 | |
| 107 | __attribute__((address_space(1))) char *x; |
| 108 | __attribute__((address_space(2))) char *y; |
| 109 | cmp<1, 2>(x, y); // expected-note {{in instantiation of function template specialization 'cmp<1, 2>' requested here}} |
| 110 | |
| 111 | fooFunction<1> ff; |
| 112 | ff.get_0(); // expected-note {{in instantiation of member function 'fooFunction<1>::get_0' requested here}} |
| 113 | ff.qf(); |
| 114 | ff.test3(); // expected-note {{in instantiation of member function 'fooFunction<1>::test3' requested here}} |
| 115 | |
| 116 | static_assert(partial_spec_deduce_as<int __attribute__((address_space(3))) *>::value == 3, "address space value has been incorrectly deduced"); |
| 117 | |
| 118 | return 0; |
| 119 | } |
| 120 | |