// RUN: %clang_cc1 -Wno-unused-value -verify %s #define NODEREF __attribute__((noderef)) struct S { int a; int b; }; struct S2 { int a[2]; int NODEREF a2[2]; int *b; int NODEREF *b2; struct S *s; struct S NODEREF *s2; }; int NODEREF *func(int NODEREF *arg) { // expected-note{{arg declared here}} int y = *arg; // expected-warning{{dereferencing arg; was declared with a 'noderef' type}} return arg; } void func2(int x) {} int test() { int NODEREF *p; // expected-note 34 {{p declared here}} int *p2; int x = *p; // expected-warning{{dereferencing p; was declared with a 'noderef' type}} x = *((int NODEREF *)p2); // expected-warning{{dereferencing expression marked as 'noderef'}} int NODEREF **q; int *NODEREF *q2; // expected-note 4 {{q2 declared here}} // Indirection x = **q; // expected-warning{{dereferencing expression marked as 'noderef'}} p2 = *q2; // expected-warning{{dereferencing q2; was declared with a 'noderef' type}} **q; // expected-warning{{dereferencing expression marked as 'noderef'}} p = *&*q; p = **&q; q = &**&q; p = &*p; p = *&p; p = &(*p); p = *(&p); x = **&p; // expected-warning{{dereferencing expression marked as 'noderef'}} *p = 2; // expected-warning{{dereferencing p; was declared with a 'noderef' type}} *q = p; // ok **q = 2; // expected-warning{{dereferencing expression marked as 'noderef'}} *q2 = p2; // expected-warning{{dereferencing q2; was declared with a 'noderef' type}} p = p + 1; p = &*(p + 1); // Struct member access struct S NODEREF *s; // expected-note 3 {{s declared here}} x = s->a; // expected-warning{{dereferencing s; was declared with a 'noderef' type}} x = (*s).b; // expected-warning{{dereferencing s; was declared with a 'noderef' type}} p = &s->a; p = &(*s).b; // Most things in sizeof() can't actually access memory x = sizeof(s->a); // ok x = sizeof(*s); // ok x = sizeof(s[0]); // ok x = sizeof(s->a + (s->b)); // ok x = sizeof(int[++s->a]); // expected-warning{{dereferencing s; was declared with a 'noderef' type}} // Struct member access should carry NoDeref type information through to an // enclosing AddrOf. p2 = &s->a; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} p2 = &(*s).a; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} x = *&s->a; // expected-warning{{dereferencing expression marked as 'noderef'}} // Nested struct access struct S2 NODEREF *s2_noderef; // expected-note 5 {{s2_noderef declared here}} p = s2_noderef->a; // ok since result is an array in a struct p = (*s2_noderef).a; // ok since result is an array in a struct p = s2_noderef->a2; // ok p = s2_noderef->b; // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}} p = s2_noderef->b2; // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}} s = s2_noderef->s; // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}} s = s2_noderef->s2; // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}} p = s2_noderef->a + 1; struct S2 *s2; p = s2->a; p = s2->a2; p = s2->b; p = s2->b2; s = s2->s; s = s2->s2; &(*(*s2).s2).b; // Subscript access x = p[1]; // expected-warning{{dereferencing p; was declared with a 'noderef' type}} x = q[0][0]; // expected-warning{{dereferencing expression marked as 'noderef'}} p2 = q2[0]; // expected-warning{{dereferencing q2; was declared with a 'noderef' type}} p = q[*p]; // expected-warning{{dereferencing p; was declared with a 'noderef' type}} x = p[*p]; // expected-warning{{dereferencing p; was declared with a 'noderef' type}} // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}} int NODEREF arr[10]; // expected-note 1 {{arr declared here}} x = arr[1]; // expected-warning{{dereferencing arr; was declared with a 'noderef' type}} int NODEREF *(arr2[10]); int NODEREF *elem = *arr2; int NODEREF(*arr3)[10]; elem = *arr3; // Combinations between indirection, subscript, and member access struct S2 NODEREF *s2_arr[10]; struct S2 NODEREF *s2_arr2[10][10]; p = s2_arr[1]->a; p = s2_arr[1]->b; // expected-warning{{dereferencing expression marked as 'noderef'}} int *NODEREF *bptr = &s2_arr[1]->b; x = s2->s2->a; // expected-warning{{dereferencing expression marked as 'noderef'}} x = s2_noderef->a[1]; // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}} p = &s2_noderef->a[1]; // Casting to dereferenceable pointer p2 = p; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} p2 = *q; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} p2 = q[0]; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} s2 = s2_arr[1]; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} s2 = s2_arr2[1][1]; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} p2 = p, p2 = *q; // expected-warning 2 {{casting to dereferenceable pointer removes 'noderef' attribute}} // typedefs typedef int NODEREF *ptr_t; ptr_t ptr; // expected-note 2 {{ptr declared here}} ptr_t *ptr2; *ptr; // expected-warning{{dereferencing ptr; was declared with a 'noderef' type}} *ptr2; **ptr2; // expected-warning{{dereferencing expression marked as 'noderef'}} typedef struct S2 NODEREF *s2_ptr_t; s2_ptr_t s2_ptr; // expected-note 4 {{s2_ptr declared here}} s2_ptr->a; // ok since result is an array in a struct s2_ptr->a2; // ok s2_ptr->b; // expected-warning{{dereferencing s2_ptr; was declared with a 'noderef' type}} s2_ptr->b2; // expected-warning{{dereferencing s2_ptr; was declared with a 'noderef' type}} s2_ptr->s; // expected-warning{{dereferencing s2_ptr; was declared with a 'noderef' type}} s2_ptr->s2; // expected-warning{{dereferencing s2_ptr; was declared with a 'noderef' type}} s2_ptr->a + 1; typedef int(int_t); typedef int_t NODEREF *(noderef_int_t); typedef noderef_int_t *noderef_int_nested_t; noderef_int_nested_t noderef_int_nested_ptr; *noderef_int_nested_ptr; **noderef_int_nested_ptr; // expected-warning{{dereferencing expression marked as 'noderef'}} typedef int_t *(NODEREF noderef_int2_t); typedef noderef_int2_t *noderef_int2_nested_t; noderef_int2_nested_t noderef_int2_nested_ptr; // expected-note{{noderef_int2_nested_ptr declared here}} *noderef_int2_nested_ptr; // expected-warning{{dereferencing noderef_int2_nested_ptr; was declared with a 'noderef' type}} typedef int_t *(noderef_int3_t); typedef noderef_int3_t(NODEREF(*(noderef_int3_nested_t))); noderef_int3_nested_t noderef_int3_nested_ptr; // expected-note{{noderef_int3_nested_ptr declared here}} *noderef_int3_nested_ptr; // expected-warning{{dereferencing noderef_int3_nested_ptr; was declared with a 'noderef' type}} // Parentheses (((*((p))))); // expected-warning{{dereferencing p; was declared with a 'noderef' type}} (*(*(&(p)))); // expected-warning{{dereferencing expression marked as 'noderef'}} (p[1]); // expected-warning{{dereferencing p; was declared with a 'noderef' type}} (q[0]); // ok (q[0][0]); // expected-warning{{dereferencing expression marked as 'noderef'}} (q2[0]); // expected-warning{{dereferencing q2; was declared with a 'noderef' type}} (q[(*(p))]); // expected-warning{{dereferencing p; was declared with a 'noderef' type}} (p[(*(p))]); // expected-warning{{dereferencing p; was declared with a 'noderef' type}} // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}} (*(ptr)); // expected-warning{{dereferencing ptr; was declared with a 'noderef' type}} (*(ptr2)); (*(*(ptr2))); // expected-warning{{dereferencing expression marked as 'noderef'}} // Functions x = *(func(p)); // expected-warning{{dereferencing expression marked as 'noderef'}} // Casting is ok q = (int NODEREF **)&p; q = (int NODEREF **)&p2; q = &p; q = &p2; x = s2->s2->a; // expected-warning{{dereferencing expression marked as 'noderef'}} // Other expressions func2(*p); // expected-warning{{dereferencing p; was declared with a 'noderef' type}} func2(*p + 1); // expected-warning{{dereferencing p; was declared with a 'noderef' type}} func2(!*p); // expected-warning{{dereferencing p; was declared with a 'noderef' type}} func2((x = *p)); // expected-warning{{dereferencing p; was declared with a 'noderef' type}} func2((char)(*p)); // expected-warning{{dereferencing p; was declared with a 'noderef' type}} // Other statements if (*p) {} // expected-warning{{dereferencing p; was declared with a 'noderef' type}} else if (*p) {} // expected-warning{{dereferencing p; was declared with a 'noderef' type}} switch (*p){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}} for (*p; *p; *p){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}} // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}} // expected-warning@-2{{dereferencing p; was declared with a 'noderef' type}} for (*p; *p;){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}} // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}} for (*p;; *p){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}} // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}} for (; *p; *p){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}} // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}} for (*p;;){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}} for (;*p;){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}} for (;;*p){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}} while (*p){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}} do {} while (*p); // expected-warning{{dereferencing p; was declared with a 'noderef' type}} return *p; // expected-warning{{dereferencing p; was declared with a 'noderef' type}} }