1 // RUN: %check_clang_tidy %s bugprone-spuriously-wake-up-functions %t -- --
2 #define NULL 0
3 
4 namespace std {
5 using intmax_t = int;
6 
7 template <intmax_t N, intmax_t D = 1>
8 class ratio {
9 public:
10   static constexpr intmax_t num = 0;
11   static constexpr intmax_t den = 0;
12   typedef ratio<num, den> type;
13 };
14 typedef ratio<1, 1000> milli;
15 namespace chrono {
16 
17 template <class Rep, class Period = ratio<1>>
18 class duration {
19 public:
20   using rep = Rep;
21   using period = Period;
22 
23 public:
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 
33 template <class Clock, class Duration = typename Clock::duration>
34 class time_point {
35 public:
36   using clock = Clock;
37   using duration = Duration;
38 
39 public:
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 
46 using milliseconds = duration<int, milli>;
47 
48 class system_clock {
49 public:
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 
59 class mutex;
60 template <class Mutex>
61 class unique_lock {
62 public:
63   typedef Mutex mutex_type;
64 
65   unique_lock() noexcept;
66   explicit unique_lock(mutex_type &m);
67 };
68 
69 class mutex {
70 public:
71   constexpr mutex() noexcept;
72   ~mutex();
73   mutex(const mutex &) = delete;
74   mutex &operator=(const mutex &) = delete;
75 };
76 
77 enum class cv_status {
78   no_timeout,
79   timeout
80 };
81 
82 class condition_variable {
83 public:
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>
wait_until(unique_lock<mutex> & lock,const chrono::time_point<Clock,Duration> & abs_time)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>
wait_until(unique_lock<mutex> & lock,const chrono::time_point<Clock,Duration> & abs_time,Predicate pred)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>
wait_for(unique_lock<mutex> & lock,const chrono::duration<Rep,Period> & rel_time)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>
wait_for(unique_lock<mutex> & lock,const chrono::duration<Rep,Period> & rel_time,Predicate pred)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 
109 struct Node1 {
110   void *Node1;
111   struct Node1 *next;
112 };
113 
114 static Node1 list;
115 static std::mutex m;
116 static std::condition_variable condition;
117 
consume_list_element(std::condition_variable & condition)118 void consume_list_element(std::condition_variable &condition) {
119   std::unique_lock<std::mutex> lk(m);
120 
121   if (list.next == nullptr) {
122     condition.wait(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(lk);
128   }
129 
130   do {
131     condition.wait(lk);
132   } while (list.next == nullptr);
133 
134   for (;; list.next == nullptr) {
135     condition.wait(lk);
136   }
137 
138   if (list.next == nullptr) {
139     while (list.next == nullptr) {
140       condition.wait(lk);
141     }
142   }
143 
144   if (list.next == nullptr) {
145     do {
146       condition.wait(lk);
147     } while (list.next == nullptr);
148   }
149 
150   if (list.next == nullptr) {
151     for (;; list.next == nullptr) {
152       condition.wait(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(lk, 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(lk, dur, [] { return 1; });
163   }
164   while (list.next == nullptr) {
165     condition.wait_for(lk, dur);
166   }
167   do {
168     condition.wait_for(lk, dur);
169   } while (list.next == nullptr);
170   for (;; list.next == nullptr) {
171     condition.wait_for(lk, dur);
172   }
173 
174   auto now = std::chrono::system_clock::now();
175   if (list.next == nullptr) {
176     condition.wait_until(lk, 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(lk, now, [] { return 1; });
181   }
182   while (list.next == nullptr) {
183     condition.wait_until(lk, now);
184   }
185   do {
186     condition.wait_until(lk, now);
187   } while (list.next == nullptr);
188   for (;; list.next == nullptr) {
189     condition.wait_until(lk, now);
190   }
191 }
192