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
22void 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

source code of libcxx/test/libcxx/atomics/diagnose_invalid_memory_order.verify.cpp