1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// REQUIRES: verify-support, diagnose-if-support
11// UNSUPPORTED: libcpp-has-no-threads
12
13// <atomic>
14
15// Test that invalid memory order arguments are diagnosed where possible.
16
17#include <atomic>
18
19int main() {
20    std::atomic<int> x(42);
21    volatile std::atomic<int>& vx = x;
22    int val1 = 1; ((void)val1);
23    int val2 = 2; ((void)val2);
24    // load operations
25    {
26        x.load(std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}}
27        x.load(std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}}
28        vx.load(std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}}
29        vx.load(std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}}
30        // valid memory orders
31        x.load(std::memory_order_relaxed);
32        x.load(std::memory_order_consume);
33        x.load(std::memory_order_acquire);
34        x.load(std::memory_order_seq_cst);
35    }
36    {
37        std::atomic_load_explicit(&x, std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}}
38        std::atomic_load_explicit(&x, std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}}
39        std::atomic_load_explicit(&vx, std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}}
40        std::atomic_load_explicit(&vx, std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}}
41        // valid memory orders
42        std::atomic_load_explicit(&x, std::memory_order_relaxed);
43        std::atomic_load_explicit(&x, std::memory_order_consume);
44        std::atomic_load_explicit(&x, std::memory_order_acquire);
45        std::atomic_load_explicit(&x, std::memory_order_seq_cst);
46    }
47    // store operations
48    {
49        x.store(42, std::memory_order_consume); // expected-warning {{memory order argument to atomic operation is invalid}}
50        x.store(42, std::memory_order_acquire); // expected-warning {{memory order argument to atomic operation is invalid}}
51        x.store(42, std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}}
52        vx.store(42, std::memory_order_consume); // expected-warning {{memory order argument to atomic operation is invalid}}
53        vx.store(42, std::memory_order_acquire); // expected-warning {{memory order argument to atomic operation is invalid}}
54        vx.store(42, std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}}
55        // valid memory orders
56        x.store(42, std::memory_order_relaxed);
57        x.store(42, std::memory_order_release);
58        x.store(42, std::memory_order_seq_cst);
59    }
60    {
61        std::atomic_store_explicit(&x, 42, std::memory_order_consume); // expected-warning {{memory order argument to atomic operation is invalid}}
62        std::atomic_store_explicit(&x, 42, std::memory_order_acquire); // expected-warning {{memory order argument to atomic operation is invalid}}
63        std::atomic_store_explicit(&x, 42, std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}}
64        std::atomic_store_explicit(&vx, 42, std::memory_order_consume); // expected-warning {{memory order argument to atomic operation is invalid}}
65        std::atomic_store_explicit(&vx, 42, std::memory_order_acquire); // expected-warning {{memory order argument to atomic operation is invalid}}
66        std::atomic_store_explicit(&vx, 42, std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}}
67        // valid memory orders
68        std::atomic_store_explicit(&x, 42, std::memory_order_relaxed);
69        std::atomic_store_explicit(&x, 42, std::memory_order_release);
70        std::atomic_store_explicit(&x, 42, std::memory_order_seq_cst);
71    }
72    // compare exchange weak
73    {
74        x.compare_exchange_weak(val1, val2, std::memory_order_seq_cst, std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}}
75        x.compare_exchange_weak(val1, val2, std::memory_order_seq_cst, std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}}
76        vx.compare_exchange_weak(val1, val2, std::memory_order_seq_cst, std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}}
77        vx.compare_exchange_weak(val1, val2, std::memory_order_seq_cst, std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}}
78        // valid memory orders
79        x.compare_exchange_weak(val1, val2, std::memory_order_seq_cst, std::memory_order_relaxed);
80        x.compare_exchange_weak(val1, val2, std::memory_order_seq_cst, std::memory_order_consume);
81        x.compare_exchange_weak(val1, val2, std::memory_order_seq_cst, std::memory_order_acquire);
82        x.compare_exchange_weak(val1, val2, std::memory_order_seq_cst, std::memory_order_seq_cst);
83        // Test that the cmpxchg overload with only one memory order argument
84        // does not generate any diagnostics.
85        x.compare_exchange_weak(val1, val2, std::memory_order_release);
86    }
87    {
88        std::atomic_compare_exchange_weak_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}}
89        std::atomic_compare_exchange_weak_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}}
90        std::atomic_compare_exchange_weak_explicit(&vx, &val1, val2, std::memory_order_seq_cst, std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}}
91        std::atomic_compare_exchange_weak_explicit(&vx, &val1, val2, std::memory_order_seq_cst, std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}}
92        // valid memory orders
93        std::atomic_compare_exchange_weak_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_relaxed);
94        std::atomic_compare_exchange_weak_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_consume);
95        std::atomic_compare_exchange_weak_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_acquire);
96        std::atomic_compare_exchange_weak_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_seq_cst);
97    }
98    // compare exchange strong
99    {
100        x.compare_exchange_strong(val1, val2, std::memory_order_seq_cst, std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}}
101        x.compare_exchange_strong(val1, val2, std::memory_order_seq_cst, std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}}
102        vx.compare_exchange_strong(val1, val2, std::memory_order_seq_cst, std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}}
103        vx.compare_exchange_strong(val1, val2, std::memory_order_seq_cst, std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}}
104        // valid memory orders
105        x.compare_exchange_strong(val1, val2, std::memory_order_seq_cst, std::memory_order_relaxed);
106        x.compare_exchange_strong(val1, val2, std::memory_order_seq_cst, std::memory_order_consume);
107        x.compare_exchange_strong(val1, val2, std::memory_order_seq_cst, std::memory_order_acquire);
108        x.compare_exchange_strong(val1, val2, std::memory_order_seq_cst, std::memory_order_seq_cst);
109        // Test that the cmpxchg overload with only one memory order argument
110        // does not generate any diagnostics.
111        x.compare_exchange_strong(val1, val2, std::memory_order_release);
112    }
113    {
114        std::atomic_compare_exchange_strong_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}}
115        std::atomic_compare_exchange_strong_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}}
116        std::atomic_compare_exchange_strong_explicit(&vx, &val1, val2, std::memory_order_seq_cst, std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}}
117        std::atomic_compare_exchange_strong_explicit(&vx, &val1, val2, std::memory_order_seq_cst, std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}}
118        // valid memory orders
119        std::atomic_compare_exchange_strong_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_relaxed);
120        std::atomic_compare_exchange_strong_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_consume);
121        std::atomic_compare_exchange_strong_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_acquire);
122        std::atomic_compare_exchange_strong_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_seq_cst);
123    }
124}
125