2018-12-06 09:05:54 +08:00
|
|
|
// 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
|
2020-11-23 21:10:35 +08:00
|
|
|
struct S NODEREF *s; // expected-note 3 {{s declared here}}
|
2018-12-06 09:05:54 +08:00
|
|
|
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;
|
|
|
|
|
2020-11-23 21:10:35 +08:00
|
|
|
// 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}}
|
|
|
|
|
2020-12-08 06:48:41 +08:00
|
|
|
// 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'}}
|
|
|
|
|
2018-12-06 09:05:54 +08:00
|
|
|
// 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
|
2020-12-08 06:39:42 +08:00
|
|
|
p = (*s2_noderef).a; // ok since result is an array in a struct
|
2018-12-06 09:05:54 +08:00
|
|
|
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'}}
|
2020-12-08 06:48:41 +08:00
|
|
|
int *NODEREF *bptr = &s2_arr[1]->b;
|
2018-12-06 09:05:54 +08:00
|
|
|
|
|
|
|
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}}
|
|
|
|
}
|