]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/Analysis/dispatch-once.m
Vendor import of clang trunk r290819:
[FreeBSD/FreeBSD.git] / test / Analysis / dispatch-once.m
1 // RUN: %clang_cc1 -w -fblocks -analyze -analyzer-checker=core,osx.API,unix.Malloc -verify %s
2 // RUN: %clang_cc1 -w -fblocks -fobjc-arc -analyze -analyzer-checker=core,osx.API,unix.Malloc -verify %s
3
4 #include "Inputs/system-header-simulator-objc.h"
5
6 typedef unsigned long size_t;
7 void *calloc(size_t nmemb, size_t size);
8
9 typedef void (^dispatch_block_t)(void);
10 typedef long dispatch_once_t;
11 void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);
12
13 void test_stack() {
14   dispatch_once_t once;
15   dispatch_once(&once, ^{}); // expected-warning{{Call to 'dispatch_once' uses the local variable 'once' for the predicate value.  Using such transient memory for the predicate is potentially dangerous.  Perhaps you intended to declare the variable as 'static'?}}
16 }
17
18 void test_static_local() {
19   static dispatch_once_t once;
20   dispatch_once(&once, ^{}); // no-warning
21 }
22
23 void test_heap_var() {
24   dispatch_once_t *once = calloc(1, sizeof(dispatch_once_t));
25   // Use regexps to check that we're NOT suggesting to make this static.
26   dispatch_once(once, ^{}); // expected-warning-re{{{{^Call to 'dispatch_once' uses heap-allocated memory for the predicate value.  Using such transient memory for the predicate is potentially dangerous$}}}}
27 }
28
29 void test_external_pointer(dispatch_once_t *once) {
30   // External pointer does not necessarily point to the heap.
31   dispatch_once(once, ^{}); // no-warning
32 }
33
34 typedef struct {
35   dispatch_once_t once;
36 } Struct;
37
38 void test_local_struct() {
39   Struct s;
40   dispatch_once(&s.once, ^{}); // expected-warning{{Call to 'dispatch_once' uses memory within the local variable 's' for the predicate value.}}
41 }
42
43 void test_heap_struct() {
44   Struct *s = calloc(1, sizeof(Struct));
45   dispatch_once(&s->once, ^{}); // expected-warning{{Call to 'dispatch_once' uses heap-allocated memory for the predicate value.}}
46 }
47
48 @interface Object : NSObject {
49 @public
50   dispatch_once_t once;
51   Struct s;
52   dispatch_once_t once_array[2];
53 }
54 - (void)test_ivar_from_inside;
55 - (void)test_ivar_struct_from_inside;
56 @end
57
58 @implementation Object
59 - (void)test_ivar_from_inside {
60   dispatch_once(&once, ^{}); // expected-warning{{Call to 'dispatch_once' uses the instance variable 'once' for the predicate value.}}
61 }
62 - (void)test_ivar_struct_from_inside {
63   dispatch_once(&s.once, ^{}); // expected-warning{{Call to 'dispatch_once' uses memory within the instance variable 's' for the predicate value.}}
64 }
65 - (void)test_ivar_array_from_inside {
66   dispatch_once(&once_array[1], ^{}); // expected-warning{{Call to 'dispatch_once' uses memory within the instance variable 'once_array' for the predicate value.}}
67 }
68 @end
69
70 void test_ivar_from_alloc_init() {
71   Object *o = [[Object alloc] init];
72   dispatch_once(&o->once, ^{}); // expected-warning{{Call to 'dispatch_once' uses the instance variable 'once' for the predicate value.}}
73 }
74 void test_ivar_struct_from_alloc_init() {
75   Object *o = [[Object alloc] init];
76   dispatch_once(&o->s.once, ^{}); // expected-warning{{Call to 'dispatch_once' uses memory within the instance variable 's' for the predicate value.}}
77 }
78 void test_ivar_array_from_alloc_init() {
79   Object *o = [[Object alloc] init];
80   dispatch_once(&o->once_array[1], ^{}); // expected-warning{{Call to 'dispatch_once' uses memory within the instance variable 'once_array' for the predicate value.}}
81 }
82
83 void test_ivar_from_external_obj(Object *o) {
84   // ObjC object pointer always points to the heap.
85   dispatch_once(&o->once, ^{}); // expected-warning{{Call to 'dispatch_once' uses the instance variable 'once' for the predicate value.}}
86 }
87 void test_ivar_struct_from_external_obj(Object *o) {
88   dispatch_once(&o->s.once, ^{}); // expected-warning{{Call to 'dispatch_once' uses memory within the instance variable 's' for the predicate value.}}
89 }
90 void test_ivar_array_from_external_obj(Object *o) {
91   dispatch_once(&o->once_array[1], ^{}); // expected-warning{{Call to 'dispatch_once' uses memory within the instance variable 'once_array' for the predicate value.}}
92 }
93
94 void test_block_var_from_block() {
95   __block dispatch_once_t once;
96   ^{
97     dispatch_once(&once, ^{}); // expected-warning{{Call to 'dispatch_once' uses the block variable 'once' for the predicate value.}}
98   };
99 }
100
101 void use_block_var(dispatch_once_t *once);
102
103 void test_block_var_from_outside_block() {
104   __block dispatch_once_t once;
105   ^{
106     use_block_var(&once);
107   };
108   dispatch_once(&once, ^{}); // expected-warning{{Call to 'dispatch_once' uses the block variable 'once' for the predicate value.}}
109 }