1 | //===----------------------------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | // This test fails with Clang <18 because diagnose_if doesn't emit all of the |
10 | // diagnostics when -fdelayed-template-parsing is enabled, like it is in MSVC |
11 | // mode. |
12 | // XFAIL: msvc && clang-17 |
13 | |
14 | // REQUIRES: diagnose-if-support |
15 | |
16 | // <atomic> |
17 | |
18 | // Test that invalid memory order arguments are diagnosed where possible. |
19 | |
20 | #include <atomic> |
21 | |
22 | void f() { |
23 | std::atomic<int> x(42); |
24 | volatile std::atomic<int>& vx = x; |
25 | int val1 = 1; ((void)val1); |
26 | int val2 = 2; ((void)val2); |
27 | // load operations |
28 | { |
29 | x.load(m: std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}} |
30 | x.load(m: std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}} |
31 | vx.load(m: std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}} |
32 | vx.load(m: std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}} |
33 | // valid memory orders |
34 | x.load(m: std::memory_order_relaxed); |
35 | x.load(m: std::memory_order_consume); |
36 | x.load(m: std::memory_order_acquire); |
37 | x.load(m: std::memory_order_seq_cst); |
38 | } |
39 | { |
40 | std::atomic_load_explicit(a: &x, m: std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}} |
41 | std::atomic_load_explicit(a: &x, m: std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}} |
42 | std::atomic_load_explicit(a: &vx, m: std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}} |
43 | std::atomic_load_explicit(a: &vx, m: std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}} |
44 | // valid memory orders |
45 | std::atomic_load_explicit(a: &x, m: std::memory_order_relaxed); |
46 | std::atomic_load_explicit(a: &x, m: std::memory_order_consume); |
47 | std::atomic_load_explicit(a: &x, m: std::memory_order_acquire); |
48 | std::atomic_load_explicit(a: &x, m: std::memory_order_seq_cst); |
49 | } |
50 | // store operations |
51 | { |
52 | x.store(i: 42, m: std::memory_order_consume); // expected-warning {{memory order argument to atomic operation is invalid}} |
53 | x.store(i: 42, m: std::memory_order_acquire); // expected-warning {{memory order argument to atomic operation is invalid}} |
54 | x.store(i: 42, m: std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}} |
55 | vx.store(i: 42, m: std::memory_order_consume); // expected-warning {{memory order argument to atomic operation is invalid}} |
56 | vx.store(i: 42, m: std::memory_order_acquire); // expected-warning {{memory order argument to atomic operation is invalid}} |
57 | vx.store(i: 42, m: std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}} |
58 | // valid memory orders |
59 | x.store(i: 42, m: std::memory_order_relaxed); |
60 | x.store(i: 42, m: std::memory_order_release); |
61 | x.store(i: 42, m: std::memory_order_seq_cst); |
62 | } |
63 | { |
64 | std::atomic_store_explicit(a: &x, i: 42, m: std::memory_order_consume); // expected-warning {{memory order argument to atomic operation is invalid}} |
65 | std::atomic_store_explicit(a: &x, i: 42, m: std::memory_order_acquire); // expected-warning {{memory order argument to atomic operation is invalid}} |
66 | std::atomic_store_explicit(a: &x, i: 42, m: std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}} |
67 | std::atomic_store_explicit(a: &vx, i: 42, m: std::memory_order_consume); // expected-warning {{memory order argument to atomic operation is invalid}} |
68 | std::atomic_store_explicit(a: &vx, i: 42, m: std::memory_order_acquire); // expected-warning {{memory order argument to atomic operation is invalid}} |
69 | std::atomic_store_explicit(a: &vx, i: 42, m: std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}} |
70 | // valid memory orders |
71 | std::atomic_store_explicit(a: &x, i: 42, m: std::memory_order_relaxed); |
72 | std::atomic_store_explicit(a: &x, i: 42, m: std::memory_order_release); |
73 | std::atomic_store_explicit(a: &x, i: 42, m: std::memory_order_seq_cst); |
74 | } |
75 | // compare exchange weak |
76 | { |
77 | x.compare_exchange_weak(i1&: val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}} |
78 | x.compare_exchange_weak(i1&: val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}} |
79 | vx.compare_exchange_weak(i1&: val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}} |
80 | vx.compare_exchange_weak(i1&: val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}} |
81 | // valid memory orders |
82 | x.compare_exchange_weak(i1&: val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_relaxed); |
83 | x.compare_exchange_weak(i1&: val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_consume); |
84 | x.compare_exchange_weak(i1&: val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_acquire); |
85 | x.compare_exchange_weak(i1&: val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_seq_cst); |
86 | // Test that the cmpxchg overload with only one memory order argument |
87 | // does not generate any diagnostics. |
88 | x.compare_exchange_weak(i1&: val1, i2: val2, m: std::memory_order_release); |
89 | } |
90 | { |
91 | std::atomic_compare_exchange_weak_explicit(a: &x, i1: &val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}} |
92 | std::atomic_compare_exchange_weak_explicit(a: &x, i1: &val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}} |
93 | std::atomic_compare_exchange_weak_explicit(a: &vx, i1: &val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}} |
94 | std::atomic_compare_exchange_weak_explicit(a: &vx, i1: &val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}} |
95 | // valid memory orders |
96 | std::atomic_compare_exchange_weak_explicit(a: &x, i1: &val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_relaxed); |
97 | std::atomic_compare_exchange_weak_explicit(a: &x, i1: &val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_consume); |
98 | std::atomic_compare_exchange_weak_explicit(a: &x, i1: &val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_acquire); |
99 | std::atomic_compare_exchange_weak_explicit(a: &x, i1: &val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_seq_cst); |
100 | } |
101 | // compare exchange strong |
102 | { |
103 | x.compare_exchange_strong(i1&: val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}} |
104 | x.compare_exchange_strong(i1&: val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}} |
105 | vx.compare_exchange_strong(i1&: val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}} |
106 | vx.compare_exchange_strong(i1&: val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}} |
107 | // valid memory orders |
108 | x.compare_exchange_strong(i1&: val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_relaxed); |
109 | x.compare_exchange_strong(i1&: val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_consume); |
110 | x.compare_exchange_strong(i1&: val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_acquire); |
111 | x.compare_exchange_strong(i1&: val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_seq_cst); |
112 | // Test that the cmpxchg overload with only one memory order argument |
113 | // does not generate any diagnostics. |
114 | x.compare_exchange_strong(i1&: val1, i2: val2, m: std::memory_order_release); |
115 | } |
116 | { |
117 | std::atomic_compare_exchange_strong_explicit(a: &x, i1: &val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}} |
118 | std::atomic_compare_exchange_strong_explicit(a: &x, i1: &val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}} |
119 | std::atomic_compare_exchange_strong_explicit(a: &vx, i1: &val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_release); // expected-warning {{memory order argument to atomic operation is invalid}} |
120 | std::atomic_compare_exchange_strong_explicit(a: &vx, i1: &val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_acq_rel); // expected-warning {{memory order argument to atomic operation is invalid}} |
121 | // valid memory orders |
122 | std::atomic_compare_exchange_strong_explicit(a: &x, i1: &val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_relaxed); |
123 | std::atomic_compare_exchange_strong_explicit(a: &x, i1: &val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_consume); |
124 | std::atomic_compare_exchange_strong_explicit(a: &x, i1: &val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_acquire); |
125 | std::atomic_compare_exchange_strong_explicit(a: &x, i1: &val1, i2: val2, m1: std::memory_order_seq_cst, m2: std::memory_order_seq_cst); |
126 | } |
127 | } |
128 | |