1 // RUN: %clang_cc1 -Wno-unused-value -verify %s
2 
3 #define NODEREF __attribute__((noderef))
4 
5 struct S {
6   int a;
7   int b;
8 };
9 
10 struct S2 {
11   int a[2];
12   int NODEREF a2[2];
13   int *b;
14   int NODEREF *b2;
15   struct S *s;
16   struct S NODEREF *s2;
17 };
18 
func(int NODEREF * arg)19 int NODEREF *func(int NODEREF *arg) {  // expected-note{{arg declared here}}
20   int y = *arg; // expected-warning{{dereferencing arg; was declared with a 'noderef' type}}
21   return arg;
22 }
23 
func2(int x)24 void func2(int x) {}
25 
test()26 int test() {
27   int NODEREF *p; // expected-note 34 {{p declared here}}
28   int *p2;
29 
30   int x = *p;               // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
31   x = *((int NODEREF *)p2); // expected-warning{{dereferencing expression marked as 'noderef'}}
32 
33   int NODEREF **q;
34   int *NODEREF *q2; // expected-note 4 {{q2 declared here}}
35 
36   // Indirection
37   x = **q;  // expected-warning{{dereferencing expression marked as 'noderef'}}
38   p2 = *q2; // expected-warning{{dereferencing q2; was declared with a 'noderef' type}}
39 
40   **q; // expected-warning{{dereferencing expression marked as 'noderef'}}
41 
42   p = *&*q;
43   p = **&q;
44   q = &**&q;
45   p = &*p;
46   p = *&p;
47   p = &(*p);
48   p = *(&p);
49   x = **&p; // expected-warning{{dereferencing expression marked as 'noderef'}}
50 
51   *p = 2;   // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
52   *q = p;   // ok
53   **q = 2;  // expected-warning{{dereferencing expression marked as 'noderef'}}
54   *q2 = p2; // expected-warning{{dereferencing q2; was declared with a 'noderef' type}}
55 
56   p = p + 1;
57   p = &*(p + 1);
58 
59   // Struct member access
60   struct S NODEREF *s; // expected-note 3 {{s declared here}}
61   x = s->a;   // expected-warning{{dereferencing s; was declared with a 'noderef' type}}
62   x = (*s).b; // expected-warning{{dereferencing s; was declared with a 'noderef' type}}
63   p = &s->a;
64   p = &(*s).b;
65 
66   // Most things in sizeof() can't actually access memory
67   x = sizeof(s->a);          // ok
68   x = sizeof(*s);            // ok
69   x = sizeof(s[0]);          // ok
70   x = sizeof(s->a + (s->b)); // ok
71   x = sizeof(int[++s->a]);   // expected-warning{{dereferencing s; was declared with a 'noderef' type}}
72 
73   // Struct member access should carry NoDeref type information through to an
74   // enclosing AddrOf.
75   p2 = &s->a;   // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}}
76   p2 = &(*s).a; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}}
77   x = *&s->a;   // expected-warning{{dereferencing expression marked as 'noderef'}}
78 
79   // Nested struct access
80   struct S2 NODEREF *s2_noderef;    // expected-note 5 {{s2_noderef declared here}}
81   p = s2_noderef->a;  // ok since result is an array in a struct
82   p = (*s2_noderef).a; // ok since result is an array in a struct
83   p = s2_noderef->a2; // ok
84   p = s2_noderef->b;  // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}}
85   p = s2_noderef->b2; // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}}
86   s = s2_noderef->s;  // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}}
87   s = s2_noderef->s2; // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}}
88   p = s2_noderef->a + 1;
89 
90   struct S2 *s2;
91   p = s2->a;
92   p = s2->a2;
93   p = s2->b;
94   p = s2->b2;
95   s = s2->s;
96   s = s2->s2;
97   &(*(*s2).s2).b;
98 
99   // Subscript access
100   x = p[1];    // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
101   x = q[0][0]; // expected-warning{{dereferencing expression marked as 'noderef'}}
102   p2 = q2[0];  // expected-warning{{dereferencing q2; was declared with a 'noderef' type}}
103   p = q[*p];   // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
104   x = p[*p];   // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
105                // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}}
106 
107   int NODEREF arr[10];    // expected-note 1 {{arr declared here}}
108   x = arr[1]; // expected-warning{{dereferencing arr; was declared with a 'noderef' type}}
109 
110   int NODEREF *(arr2[10]);
111   int NODEREF *elem = *arr2;
112 
113   int NODEREF(*arr3)[10];
114   elem = *arr3;
115 
116   // Combinations between indirection, subscript, and member access
117   struct S2 NODEREF *s2_arr[10];
118   struct S2 NODEREF *s2_arr2[10][10];
119 
120   p = s2_arr[1]->a;
121   p = s2_arr[1]->b; // expected-warning{{dereferencing expression marked as 'noderef'}}
122   int *NODEREF *bptr = &s2_arr[1]->b;
123 
124   x = s2->s2->a;        // expected-warning{{dereferencing expression marked as 'noderef'}}
125   x = s2_noderef->a[1]; // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}}
126   p = &s2_noderef->a[1];
127 
128   // Casting to dereferenceable pointer
129   p2 = p;             // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}}
130   p2 = *q;            // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}}
131   p2 = q[0];          // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}}
132   s2 = s2_arr[1];     // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}}
133   s2 = s2_arr2[1][1]; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}}
134   p2 = p, p2 = *q;    // expected-warning 2 {{casting to dereferenceable pointer removes 'noderef' attribute}}
135 
136   // typedefs
137   typedef int NODEREF *ptr_t;
138   ptr_t ptr; // expected-note 2 {{ptr declared here}}
139   ptr_t *ptr2;
140   *ptr; // expected-warning{{dereferencing ptr; was declared with a 'noderef' type}}
141   *ptr2;
142   **ptr2; // expected-warning{{dereferencing expression marked as 'noderef'}}
143 
144   typedef struct S2 NODEREF *s2_ptr_t;
145   s2_ptr_t s2_ptr; // expected-note 4 {{s2_ptr declared here}}
146   s2_ptr->a;       // ok since result is an array in a struct
147   s2_ptr->a2;      // ok
148   s2_ptr->b;       // expected-warning{{dereferencing s2_ptr; was declared with a 'noderef' type}}
149   s2_ptr->b2;      // expected-warning{{dereferencing s2_ptr; was declared with a 'noderef' type}}
150   s2_ptr->s;       // expected-warning{{dereferencing s2_ptr; was declared with a 'noderef' type}}
151   s2_ptr->s2;      // expected-warning{{dereferencing s2_ptr; was declared with a 'noderef' type}}
152   s2_ptr->a + 1;
153 
154   typedef int(int_t);
155   typedef int_t NODEREF *(noderef_int_t);
156   typedef noderef_int_t *noderef_int_nested_t;
157   noderef_int_nested_t noderef_int_nested_ptr;
158   *noderef_int_nested_ptr;
159   **noderef_int_nested_ptr; // expected-warning{{dereferencing expression marked as 'noderef'}}
160 
161   typedef int_t *(NODEREF noderef_int2_t);
162   typedef noderef_int2_t *noderef_int2_nested_t;
163   noderef_int2_nested_t noderef_int2_nested_ptr; // expected-note{{noderef_int2_nested_ptr declared here}}
164   *noderef_int2_nested_ptr;                      // expected-warning{{dereferencing noderef_int2_nested_ptr; was declared with a 'noderef' type}}
165 
166   typedef int_t *(noderef_int3_t);
167   typedef noderef_int3_t(NODEREF(*(noderef_int3_nested_t)));
168   noderef_int3_nested_t noderef_int3_nested_ptr; // expected-note{{noderef_int3_nested_ptr declared here}}
169   *noderef_int3_nested_ptr;                      // expected-warning{{dereferencing noderef_int3_nested_ptr; was declared with a 'noderef' type}}
170 
171   // Parentheses
172   (((*((p))))); // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
173   (*(*(&(p)))); // expected-warning{{dereferencing expression marked as 'noderef'}}
174 
175   (p[1]);      // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
176   (q[0]);      // ok
177   (q[0][0]);   // expected-warning{{dereferencing expression marked as 'noderef'}}
178   (q2[0]);     // expected-warning{{dereferencing q2; was declared with a 'noderef' type}}
179   (q[(*(p))]); // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
180   (p[(*(p))]); // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
181                // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}}
182 
183   (*(ptr)); // expected-warning{{dereferencing ptr; was declared with a 'noderef' type}}
184   (*(ptr2));
185   (*(*(ptr2))); // expected-warning{{dereferencing expression marked as 'noderef'}}
186 
187   // Functions
188   x = *(func(p)); // expected-warning{{dereferencing expression marked as 'noderef'}}
189 
190   // Casting is ok
191   q = (int NODEREF **)&p;
192   q = (int NODEREF **)&p2;
193   q = &p;
194   q = &p2;
195   x = s2->s2->a; // expected-warning{{dereferencing expression marked as 'noderef'}}
196 
197   // Other expressions
198   func2(*p);         // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
199   func2(*p + 1);     // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
200   func2(!*p);        // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
201   func2((x = *p));   // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
202   func2((char)(*p)); // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
203 
204   // Other statements
205   if (*p) {}          // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
206   else if (*p) {}     // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
207   switch (*p){}       // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
208   for (*p; *p; *p){}  // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
209                       // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}}
210                       // expected-warning@-2{{dereferencing p; was declared with a 'noderef' type}}
211   for (*p; *p;){}     // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
212                       // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}}
213   for (*p;; *p){}     // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
214                       // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}}
215   for (; *p; *p){}    // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
216                       // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}}
217   for (*p;;){}        // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
218   for (;*p;){}        // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
219   for (;;*p){}        // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
220   while (*p){}        // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
221   do {} while (*p);   // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
222   return *p;          // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
223 }
224