1 // RUN: %clang_cc1 -x c++ -std=c++14 -fsyntax-only -verify %s
2 
3 template <int I, int J, int K>
car()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>
foo(float * a,float b)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>
neg()40 void neg() {
41   __attribute__((address_space(I))) int *bounds; // expected-error {{address space is negative}}
42 }
43 
44 template <long int I>
tooBig()45 void tooBig() {
46   __attribute__((address_space(I))) int *bounds; // expected-error {{address space is larger than the maximum supported (8388595)}}
47 }
48 
49 template <long int I>
correct()50 void correct() {
51   __attribute__((address_space(I))) int *bounds;
52 }
53 
54 template <int I, int J>
cmp(char * x,char * y)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 
get_0fooFunction65   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 
test3fooFunction72   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>
GetAddressSpaceValue(T * p)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();
test_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]}}
test_different_template()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 
main()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<0x7FFFF3>();
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