1// RUN: %check_clang_tidy %s bugprone-spuriously-wake-up-functions %t -- --
2#define NULL 0
3
4namespace std {
5using intmax_t = int;
6
7template <intmax_t N, intmax_t D = 1>
8class ratio {
9public:
10 static constexpr intmax_t num = 0;
11 static constexpr intmax_t den = 0;
12 typedef ratio<num, den> type;
13};
14typedef ratio<1, 1000> milli;
15namespace chrono {
16
17template <class Rep, class Period = ratio<1>>
18class duration {
19public:
20 using rep = Rep;
21 using period = Period;
22
23public:
24 constexpr duration() = default;
25 template <class Rep2>
26 constexpr explicit duration(const Rep2 &r);
27 template <class Rep2, class Period2>
28 constexpr duration(const duration<Rep2, Period2> &d);
29 ~duration() = default;
30 duration(const duration &) = default;
31};
32
33template <class Clock, class Duration = typename Clock::duration>
34class time_point {
35public:
36 using clock = Clock;
37 using duration = Duration;
38
39public:
40 constexpr time_point();
41 constexpr explicit time_point(const duration &d);
42 template <class Duration2>
43 constexpr time_point(const time_point<clock, Duration2> &t);
44};
45
46using milliseconds = duration<int, milli>;
47
48class system_clock {
49public:
50 typedef milliseconds duration;
51 typedef duration::rep rep;
52 typedef duration::period period;
53 typedef chrono::time_point<system_clock> time_point;
54
55 static time_point now() noexcept;
56};
57} // namespace chrono
58
59class mutex;
60template <class Mutex>
61class unique_lock {
62public:
63 typedef Mutex mutex_type;
64
65 unique_lock() noexcept;
66 explicit unique_lock(mutex_type &m);
67};
68
69class mutex {
70public:
71 constexpr mutex() noexcept;
72 ~mutex();
73 mutex(const mutex &) = delete;
74 mutex &operator=(const mutex &) = delete;
75};
76
77enum class cv_status {
78 no_timeout,
79 timeout
80};
81
82class condition_variable {
83public:
84 condition_variable();
85 ~condition_variable();
86 condition_variable(const condition_variable &) = delete;
87
88 void wait(unique_lock<mutex> &lock);
89 template <class Predicate>
90 void wait(unique_lock<mutex> &lock, Predicate pred);
91 template <class Clock, class Duration>
92 cv_status wait_until(unique_lock<mutex> &lock,
93 const chrono::time_point<Clock, Duration> &abs_time){};
94 template <class Clock, class Duration, class Predicate>
95 bool wait_until(unique_lock<mutex> &lock,
96 const chrono::time_point<Clock, Duration> &abs_time,
97 Predicate pred){};
98 template <class Rep, class Period>
99 cv_status wait_for(unique_lock<mutex> &lock,
100 const chrono::duration<Rep, Period> &rel_time){};
101 template <class Rep, class Period, class Predicate>
102 bool wait_for(unique_lock<mutex> &lock,
103 const chrono::duration<Rep, Period> &rel_time,
104 Predicate pred){};
105};
106
107} // namespace std
108
109struct Node1 {
110 void *Node1;
111 struct Node1 *next;
112};
113
114static Node1 list;
115static std::mutex m;
116static std::condition_variable condition;
117
118void consume_list_element(std::condition_variable &condition) {
119 std::unique_lock<std::mutex> lk(m);
120
121 if (list.next == nullptr) {
122 condition.wait(lock&: lk);
123 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: 'wait' should be placed inside a while statement or used with a conditional parameter [bugprone-spuriously-wake-up-functions]
124 }
125
126 while (list.next == nullptr) {
127 condition.wait(lock&: lk);
128 }
129
130 do {
131 condition.wait(lock&: lk);
132 } while (list.next == nullptr);
133
134 for (;; list.next == nullptr) {
135 condition.wait(lock&: lk);
136 }
137
138 if (list.next == nullptr) {
139 while (list.next == nullptr) {
140 condition.wait(lock&: lk);
141 }
142 }
143
144 if (list.next == nullptr) {
145 do {
146 condition.wait(lock&: lk);
147 } while (list.next == nullptr);
148 }
149
150 if (list.next == nullptr) {
151 for (;; list.next == nullptr) {
152 condition.wait(lock&: lk);
153 }
154 }
155 using durtype = std::chrono::duration<int, std::milli>;
156 durtype dur = std::chrono::duration<int, std::milli>();
157 if (list.next == nullptr) {
158 condition.wait_for(lock&: lk, rel_time: dur);
159 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: 'wait_for' should be placed inside a while statement or used with a conditional parameter [bugprone-spuriously-wake-up-functions]
160 }
161 if (list.next == nullptr) {
162 condition.wait_for(lock&: lk, rel_time: dur, pred: [] { return 1; });
163 }
164 while (list.next == nullptr) {
165 condition.wait_for(lock&: lk, rel_time: dur);
166 }
167 do {
168 condition.wait_for(lock&: lk, rel_time: dur);
169 } while (list.next == nullptr);
170 for (;; list.next == nullptr) {
171 condition.wait_for(lock&: lk, rel_time: dur);
172 }
173
174 auto now = std::chrono::system_clock::now();
175 if (list.next == nullptr) {
176 condition.wait_until(lock&: lk, abs_time: now);
177 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: 'wait_until' should be placed inside a while statement or used with a conditional parameter [bugprone-spuriously-wake-up-functions]
178 }
179 if (list.next == nullptr) {
180 condition.wait_until(lock&: lk, abs_time: now, pred: [] { return 1; });
181 }
182 while (list.next == nullptr) {
183 condition.wait_until(lock&: lk, abs_time: now);
184 }
185 do {
186 condition.wait_until(lock&: lk, abs_time: now);
187 } while (list.next == nullptr);
188 for (;; list.next == nullptr) {
189 condition.wait_until(lock&: lk, abs_time: now);
190 }
191}
192

source code of clang-tools-extra/test/clang-tidy/checkers/bugprone/spuriously-wake-up-functions.cpp