|  | // RUN: %clang_analyze_cc1 -analyzer-checker=core -w -verify %s | 
|  |  | 
|  | @interface MyObject | 
|  | - (void)takePointer:(void *)ptr __attribute__((nonnull(1))); | 
|  | - (void)takePointerArg:(void *)__attribute__((nonnull)) ptr; | 
|  |  | 
|  | @end | 
|  |  | 
|  | void testNonNullMethod(int *p, MyObject *obj) { | 
|  | if (p) | 
|  | return; | 
|  | [obj takePointer:p]; // expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  |  | 
|  | @interface Subclass : MyObject | 
|  | // [[nonnull]] is an inherited attribute. | 
|  | - (void)takePointer:(void *)ptr; | 
|  | @end | 
|  |  | 
|  | void testSubclass(int *p, Subclass *obj) { | 
|  | if (p) | 
|  | return; | 
|  | [obj takePointer:p]; // expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  | void testSubclassArg(int *p, Subclass *obj) { | 
|  | if (p) | 
|  | return; | 
|  | [obj takePointerArg:p]; // expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  |  | 
|  | union rdar16153464_const_cp_t { | 
|  | const struct rdar16153464_cczp *zp; | 
|  | const struct rdar16153464_cczp_prime *prime; | 
|  | } __attribute__((transparent_union)); | 
|  |  | 
|  | struct rdar16153464_header { | 
|  | union rdar16153464_const_cp_t cp; | 
|  | unsigned char pad[16 - sizeof(union rdar16153464_const_cp_t *)]; | 
|  | } __attribute__((aligned(16))); | 
|  |  | 
|  |  | 
|  | struct rdar16153464_full_ctx { | 
|  | struct rdar16153464_header hdr; | 
|  | } __attribute__((aligned(16))); | 
|  |  | 
|  |  | 
|  | struct rdar16153464_pub_ctx { | 
|  | struct rdar16153464_header hdr; | 
|  | } __attribute__((aligned(16))); | 
|  |  | 
|  |  | 
|  | union rdar16153464_full_ctx_t { | 
|  | struct rdar16153464_full_ctx *_full; | 
|  | struct rdar16153464_header *hdr; | 
|  | struct rdar16153464_body *body; | 
|  | struct rdar16153464_public *pub; | 
|  | } __attribute__((transparent_union)); | 
|  |  | 
|  | union rdar16153464_pub_ctx_t { | 
|  | struct rdar16153464_pub_ctx *_pub; | 
|  | struct rdar16153464_full_ctx *_full; | 
|  | struct rdar16153464_header *hdr; | 
|  | struct rdar16153464_body *body; | 
|  | struct rdar16153464_public *pub; | 
|  | union rdar16153464_full_ctx_t innert; | 
|  | } __attribute__((transparent_union)); | 
|  |  | 
|  | int rdar16153464(union rdar16153464_full_ctx_t inner) | 
|  | { | 
|  | extern void rdar16153464_check(union rdar16153464_pub_ctx_t outer) __attribute((nonnull(1))); | 
|  | rdar16153464_check((union rdar16153464_pub_ctx_t){ .innert = inner }); // no-warning | 
|  | rdar16153464_check(inner); // no-warning | 
|  | rdar16153464_check(0); // expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  | // Multiple attributes, the basic case | 
|  | void multipleAttributes_1(char *p, char *q) __attribute((nonnull(1))) __attribute((nonnull(2))); | 
|  |  | 
|  | void testMultiple_1(void) { | 
|  | char c; | 
|  | multipleAttributes_1(&c, &c); // no-warning | 
|  | } | 
|  |  | 
|  | void testMultiple_2(void) { | 
|  | char c; | 
|  | multipleAttributes_1(0, &c); // expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  | void testMultiple_3(void) { | 
|  | char c; | 
|  | multipleAttributes_1(&c, 0); // expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  | void testMultiple_4(void) { | 
|  | multipleAttributes_1(0, 0);// expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  | // Multiple attributes, multiple prototypes | 
|  | void multipleAttributes_2(char *p, char *q) __attribute((nonnull(1))); | 
|  | void multipleAttributes_2(char *p, char *q) __attribute((nonnull(2))); | 
|  |  | 
|  | void testMultiple_5(void) { | 
|  | char c; | 
|  | multipleAttributes_2(0, &c);// expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  | void testMultiple_6(void) { | 
|  | char c; | 
|  | multipleAttributes_2(&c, 0);// expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  | void testMultiple_7(void) { | 
|  | multipleAttributes_2(0, 0);// expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  | // Multiple attributes, same index | 
|  | void multipleAttributes_3(char *p, char *q) __attribute((nonnull(1))) __attribute((nonnull(1))); | 
|  |  | 
|  | void testMultiple_8(void) { | 
|  | char c; | 
|  | multipleAttributes_3(0, &c); // expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  | void testMultiple_9(void) { | 
|  | char c; | 
|  | multipleAttributes_3(&c, 0); // no-warning | 
|  | } | 
|  |  | 
|  | // Multiple attributes, the middle argument is missing an attribute | 
|  | void multipleAttributes_4(char *p, char *q, char *r) __attribute((nonnull(1))) __attribute((nonnull(3))); | 
|  |  | 
|  | void testMultiple_10(void) { | 
|  | char c; | 
|  | multipleAttributes_4(0, &c, &c); // expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  | void testMultiple_11(void) { | 
|  | char c; | 
|  | multipleAttributes_4(&c, 0, &c); // no-warning | 
|  | } | 
|  |  | 
|  | void testMultiple_12(void) { | 
|  | char c; | 
|  | multipleAttributes_4(&c, &c, 0); // expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  |  | 
|  | // Multiple attributes, when the last is without index | 
|  | void multipleAttributes_all_1(char *p, char *q) __attribute((nonnull(1))) __attribute((nonnull)); | 
|  |  | 
|  | void testMultiple_13(void) { | 
|  | char c; | 
|  | multipleAttributes_all_1(0, &c); // expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  | void testMultiple_14(void) { | 
|  | char c; | 
|  | multipleAttributes_all_1(&c, 0); // expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  | // Multiple attributes, when the first is without index | 
|  | void multipleAttributes_all_2(char *p, char *q) __attribute((nonnull)) __attribute((nonnull(2))); | 
|  |  | 
|  | void testMultiple_15(void) { | 
|  | char c; | 
|  | multipleAttributes_all_2(0, &c); // expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  | void testMultiple_16(void) { | 
|  | char c; | 
|  | multipleAttributes_all_2(&c, 0); // expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  | void testVararg(int k, void *p) { | 
|  | extern void testVararg_check(int, ...) __attribute__((nonnull)); | 
|  | void *n = 0; | 
|  | testVararg_check(0); | 
|  | testVararg_check(1, p); | 
|  | if (k == 1) | 
|  | testVararg_check(1, n); // expected-warning{{nonnull}} | 
|  | testVararg_check(2, p, p); | 
|  | if (k == 2) | 
|  | testVararg_check(2, n, p); // expected-warning{{nonnull}} | 
|  | if (k == 3) | 
|  | testVararg_check(2, p, n); // expected-warning{{nonnull}} | 
|  | } | 
|  |  | 
|  | void testNotPtr() { | 
|  | struct S { int a; int b; int c; } s = {}; | 
|  | extern void testNotPtr_check(struct S, int) __attribute__((nonnull(1, 2))); | 
|  | testNotPtr_check(s, 0); | 
|  | } |