1 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s -analyzer-config eagerly-assume=false |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |