| 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> |
| 92 | cv_status wait_until(unique_lock<mutex> &lock, |
| 93 | const chrono::time_point<Clock, Duration> &abs_time){ return cv_status::no_timeout; }; |
| 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){ return false; }; |
| 98 | template <class Rep, class Period> |
| 99 | cv_status wait_for(unique_lock<mutex> &lock, |
| 100 | const chrono::duration<Rep, Period> &rel_time){ return cv_status::no_timeout; }; |
| 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){ return false; }; |
| 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 | |
| 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(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 | |