xref: /llvm-project/clang/test/Analysis/c11lock.c (revision 0dd49a5628bbe01cecf6516017da59ae44863ab3)
1 // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.C11Lock -verify %s
2 
3 typedef int mtx_t;
4 struct timespec;
5 
6 enum {
7   // FIXME: The value if this enum is implementation defined. While all the
8   // implementations I am aware of using 0, the right solution would be to
9   // look this value up in the AST (and disable the check if it is not found).
10   thrd_success = 0,
11   thrd_error = 2
12 };
13 
14 int mtx_init(mtx_t *mutex, int type);
15 int mtx_lock(mtx_t *mutex);
16 int mtx_timedlock(mtx_t *mutex,
17                   const struct timespec *time_point);
18 int mtx_trylock(mtx_t *mutex);
19 int mtx_unlock(mtx_t *mutex);
20 int mtx_destroy(mtx_t *mutex);
21 
22 mtx_t mtx1;
23 mtx_t mtx2;
24 
bad1(void)25 void bad1(void)
26 {
27   mtx_lock(&mtx1);	// no-warning
28   mtx_lock(&mtx1);	// expected-warning{{This lock has already been acquired}}
29 }
30 
bad2(void)31 void bad2(void) {
32   mtx_t mtx;
33   mtx_init(&mtx, 0);
34   mtx_lock(&mtx);
35 } // TODO: Warn for missing unlock?
36 
bad3(void)37 void bad3(void) {
38   mtx_t mtx;
39   mtx_init(&mtx, 0);
40 } // TODO: Warn for missing destroy?
41 
bad4(void)42 void bad4(void) {
43   mtx_t mtx;
44   mtx_init(&mtx, 0);
45   mtx_lock(&mtx);
46   mtx_unlock(&mtx);
47 } // TODO: warn for missing destroy?
48 
bad5(void)49 void bad5(void) {
50   mtx_lock(&mtx1);
51   mtx_unlock(&mtx1);
52   mtx_unlock(&mtx1); // expected-warning {{This lock has already been unlocked}}
53 }
54 
bad6(void)55 void bad6(void) {
56   mtx_init(&mtx1, 0);
57   if (mtx_trylock(&mtx1) != thrd_success)
58     mtx_unlock(&mtx1); // expected-warning {{This lock has already been unlocked}}
59 }
60 
bad7(void)61 void bad7(void) {
62   mtx_lock(&mtx1);
63   mtx_lock(&mtx2);
64   mtx_unlock(&mtx1); // expected-warning {{This was not the most recently acquired lock. Possible lock order reversal}}
65   mtx_unlock(&mtx2);
66 }
67 
good(void)68 void good(void) {
69   mtx_t mtx;
70   mtx_init(&mtx, 0);
71   mtx_lock(&mtx);
72   mtx_unlock(&mtx);
73   mtx_destroy(&mtx);
74 }
75 
good2(void)76 void good2(void) {
77   mtx_t mtx;
78   mtx_init(&mtx, 0);
79   if (mtx_trylock(&mtx) == thrd_success)
80     mtx_unlock(&mtx);
81   mtx_destroy(&mtx);
82 }
83 
good3(void)84 void good3(void) {
85   mtx_t mtx;
86   mtx_init(&mtx, 0);
87   if (mtx_timedlock(&mtx, 0) == thrd_success)
88     mtx_unlock(&mtx);
89   mtx_destroy(&mtx);
90 }
91