1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s
2 
3 // Tests for c11 atomics. Many of these tests currently yield unknown
4 // because we don't fully model the atomics and instead imprecisely
5 // treat their arguments as escaping.
6 
7 typedef unsigned int uint32_t;
8 typedef enum memory_order {
9   memory_order_relaxed = __ATOMIC_RELAXED,
10   memory_order_consume = __ATOMIC_CONSUME,
11   memory_order_acquire = __ATOMIC_ACQUIRE,
12   memory_order_release = __ATOMIC_RELEASE,
13   memory_order_acq_rel = __ATOMIC_ACQ_REL,
14   memory_order_seq_cst = __ATOMIC_SEQ_CST
15 } memory_order;
16 
17 void clang_analyzer_eval(int);
18 
19 struct RefCountedStruct {
20   uint32_t refCount;
21   void *ptr;
22 };
23 
test_atomic_fetch_add(struct RefCountedStruct * s)24 void test_atomic_fetch_add(struct RefCountedStruct *s) {
25   s->refCount = 1;
26 
27   uint32_t result = __c11_atomic_fetch_add((volatile _Atomic(uint32_t) *)&s->refCount,- 1, memory_order_relaxed);
28 
29   // When we model atomics fully this should (probably) be FALSE. It should never
30   // be TRUE (because the operation mutates the passed in storage).
31   clang_analyzer_eval(s->refCount == 1); // expected-warning {{UNKNOWN}}
32 
33   // When fully modeled this should be TRUE
34   clang_analyzer_eval(result == 1); // expected-warning {{UNKNOWN}}
35 }
36 
test_atomic_load(struct RefCountedStruct * s)37 void test_atomic_load(struct RefCountedStruct *s) {
38   s->refCount = 1;
39 
40   uint32_t result = __c11_atomic_load((volatile _Atomic(uint32_t) *)&s->refCount, memory_order_relaxed);
41 
42   // When we model atomics fully this should (probably) be TRUE.
43   clang_analyzer_eval(s->refCount == 1); // expected-warning {{UNKNOWN}}
44 
45   // When fully modeled this should be TRUE
46   clang_analyzer_eval(result == 1); // expected-warning {{UNKNOWN}}
47 }
48 
test_atomic_store(struct RefCountedStruct * s)49 void test_atomic_store(struct RefCountedStruct *s) {
50   s->refCount = 1;
51 
52   __c11_atomic_store((volatile _Atomic(uint32_t) *)&s->refCount, 2, memory_order_relaxed);
53 
54   // When we model atomics fully this should (probably) be FALSE. It should never
55   // be TRUE (because the operation mutates the passed in storage).
56   clang_analyzer_eval(s->refCount == 1); // expected-warning {{UNKNOWN}}
57 }
58 
test_atomic_exchange(struct RefCountedStruct * s)59 void test_atomic_exchange(struct RefCountedStruct *s) {
60   s->refCount = 1;
61 
62   uint32_t result = __c11_atomic_exchange((volatile _Atomic(uint32_t) *)&s->refCount, 2, memory_order_relaxed);
63 
64   // When we model atomics fully this should (probably) be FALSE. It should never
65   // be TRUE (because the operation mutates the passed in storage).
66   clang_analyzer_eval(s->refCount == 1); // expected-warning {{UNKNOWN}}
67 
68   // When fully modeled this should be TRUE
69   clang_analyzer_eval(result == 1); // expected-warning {{UNKNOWN}}
70 }
71 
72 
test_atomic_compare_exchange_strong(struct RefCountedStruct * s)73 void test_atomic_compare_exchange_strong(struct RefCountedStruct *s) {
74   s->refCount = 1;
75   uint32_t expected = 2;
76   uint32_t desired = 3;
77   _Bool result = __c11_atomic_compare_exchange_strong((volatile _Atomic(uint32_t) *)&s->refCount, &expected, desired, memory_order_relaxed, memory_order_relaxed);
78 
79   // For now we expect both expected and refCount to be invalidated by the
80   // call. In the future we should model more precisely.
81   clang_analyzer_eval(s->refCount == 3); // expected-warning {{UNKNOWN}}
82   clang_analyzer_eval(expected == 2); // expected-warning {{UNKNOWN}}
83 }
84 
test_atomic_compare_exchange_weak(struct RefCountedStruct * s)85 void test_atomic_compare_exchange_weak(struct RefCountedStruct *s) {
86   s->refCount = 1;
87   uint32_t expected = 2;
88   uint32_t desired = 3;
89   _Bool result = __c11_atomic_compare_exchange_weak((volatile _Atomic(uint32_t) *)&s->refCount, &expected, desired, memory_order_relaxed, memory_order_relaxed);
90 
91   // For now we expect both expected and refCount to be invalidated by the
92   // call. In the future we should model more precisely.
93   clang_analyzer_eval(s->refCount == 3); // expected-warning {{UNKNOWN}}
94   clang_analyzer_eval(expected == 2); // expected-warning {{UNKNOWN}}
95 }
96