summaryrefslogtreecommitdiffstats
path: root/libcxx/test
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2016-07-23 01:16:55 +0000
committerEric Fiselier <eric@efcs.ca>2016-07-23 01:16:55 +0000
commit586b16e16a51c2a361de35e1a467723f6a25acc7 (patch)
tree61d1ae58de588055a8a9f6e9d6a2cf9020174dc1 /libcxx/test
parenta7d9ec8751b1bb045f83934e9be202a191249db8 (diff)
downloadbcm5719-llvm-586b16e16a51c2a361de35e1a467723f6a25acc7.tar.gz
bcm5719-llvm-586b16e16a51c2a361de35e1a467723f6a25acc7.zip
[libcxx] Diagnose invalid memory order arguments in <atomic>. Fixes PR21179.
Summary: This patch uses the __attribute__((enable_if)) hack suggested by @rsmith to diagnose invalid arguments when possible. In order to diagnose an invalid argument `m` to `f(m)` we provide an additional overload of `f` that is only enabled when `m` is invalid. When that function is enabled it uses __attribute__((unavailable)) to produce a diagnostic message. Reviewers: mclow.lists, rsmith, jfb, EricWF Subscribers: bcraig, jfb, rsmith, cfe-commits Differential Revision: https://reviews.llvm.org/D22557 llvm-svn: 276506
Diffstat (limited to 'libcxx/test')
-rw-r--r--libcxx/test/libcxx/atomics/diagnose_invalid_memory_order.fail.cpp125
1 files changed, 125 insertions, 0 deletions
diff --git a/libcxx/test/libcxx/atomics/diagnose_invalid_memory_order.fail.cpp b/libcxx/test/libcxx/atomics/diagnose_invalid_memory_order.fail.cpp
new file mode 100644
index 00000000000..58fc684e049
--- /dev/null
+++ b/libcxx/test/libcxx/atomics/diagnose_invalid_memory_order.fail.cpp
@@ -0,0 +1,125 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// The attributes used to diagnose incorrect memory order inputs is clang
+// specific.
+// UNSUPPORTED: gcc
+
+// <atomic>
+
+// Test that invalid memory order arguments are diagnosed where possible.
+
+#include <atomic>
+
+int main() {
+ std::atomic<int> x(42);
+ volatile std::atomic<int>& vx = x;
+ int val1 = 1;
+ int val2 = 2;
+ // load operations
+ {
+ x.load(std::memory_order_release); // expected-error {{operation is invalid}}
+ x.load(std::memory_order_acq_rel); // expected-error {{operation is invalid}}
+ vx.load(std::memory_order_release); // expected-error {{operation is invalid}}
+ vx.load(std::memory_order_acq_rel); // expected-error {{operation is invalid}}
+ // valid memory orders
+ x.load(std::memory_order_relaxed);
+ x.load(std::memory_order_consume);
+ x.load(std::memory_order_acquire);
+ x.load(std::memory_order_seq_cst);
+ }
+ {
+ std::atomic_load_explicit(&x, std::memory_order_release); // expected-error {{operation is invalid}}
+ std::atomic_load_explicit(&x, std::memory_order_acq_rel); // expected-error {{operation is invalid}}
+ std::atomic_load_explicit(&vx, std::memory_order_release); // expected-error {{operation is invalid}}
+ std::atomic_load_explicit(&vx, std::memory_order_acq_rel); // expected-error {{operation is invalid}}
+ // valid memory orders
+ std::atomic_load_explicit(&x, std::memory_order_relaxed);
+ std::atomic_load_explicit(&x, std::memory_order_consume);
+ std::atomic_load_explicit(&x, std::memory_order_acquire);
+ std::atomic_load_explicit(&x, std::memory_order_seq_cst);
+ }
+ // store operations
+ {
+ x.store(42, std::memory_order_consume); // expected-error {{operation is invalid}}
+ x.store(42, std::memory_order_acquire); // expected-error {{operation is invalid}}
+ x.store(42, std::memory_order_acq_rel); // expected-error {{operation is invalid}}
+ vx.store(42, std::memory_order_consume); // expected-error {{operation is invalid}}
+ vx.store(42, std::memory_order_acquire); // expected-error {{operation is invalid}}
+ vx.store(42, std::memory_order_acq_rel); // expected-error {{operation is invalid}}
+ // valid memory orders
+ x.store(42, std::memory_order_relaxed);
+ x.store(42, std::memory_order_release);
+ x.store(42, std::memory_order_seq_cst);
+ }
+ {
+ std::atomic_store_explicit(&x, 42, std::memory_order_consume); // expected-error {{operation is invalid}}
+ std::atomic_store_explicit(&x, 42, std::memory_order_acquire); // expected-error {{operation is invalid}}
+ std::atomic_store_explicit(&x, 42, std::memory_order_acq_rel); // expected-error {{operation is invalid}}
+ std::atomic_store_explicit(&vx, 42, std::memory_order_consume); // expected-error {{operation is invalid}}
+ std::atomic_store_explicit(&vx, 42, std::memory_order_acquire); // expected-error {{operation is invalid}}
+ std::atomic_store_explicit(&vx, 42, std::memory_order_acq_rel); // expected-error {{operation is invalid}}
+ // valid memory orders
+ std::atomic_store_explicit(&x, 42, std::memory_order_relaxed);
+ std::atomic_store_explicit(&x, 42, std::memory_order_release);
+ std::atomic_store_explicit(&x, 42, std::memory_order_seq_cst);
+ }
+ // compare exchange weak
+ {
+ x.compare_exchange_weak(val1, val2, std::memory_order_seq_cst, std::memory_order_release); // expected-error {{operation is invalid}}
+ x.compare_exchange_weak(val1, val2, std::memory_order_seq_cst, std::memory_order_acq_rel); // expected-error {{operation is invalid}}
+ vx.compare_exchange_weak(val1, val2, std::memory_order_seq_cst, std::memory_order_release); // expected-error {{operation is invalid}}
+ vx.compare_exchange_weak(val1, val2, std::memory_order_seq_cst, std::memory_order_acq_rel); // expected-error {{operation is invalid}}
+ // valid memory orders
+ x.compare_exchange_weak(val1, val2, std::memory_order_seq_cst, std::memory_order_relaxed);
+ x.compare_exchange_weak(val1, val2, std::memory_order_seq_cst, std::memory_order_consume);
+ x.compare_exchange_weak(val1, val2, std::memory_order_seq_cst, std::memory_order_acquire);
+ x.compare_exchange_weak(val1, val2, std::memory_order_seq_cst, std::memory_order_seq_cst);
+ // Test that the cmpxchg overload with only one memory order argument
+ // does not generate any diagnostics.
+ x.compare_exchange_weak(val1, val2, std::memory_order_release);
+ }
+ {
+ std::atomic_compare_exchange_weak_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_release); // expected-error {{operation is invalid}}
+ std::atomic_compare_exchange_weak_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_acq_rel); // expected-error {{operation is invalid}}
+ std::atomic_compare_exchange_weak_explicit(&vx, &val1, val2, std::memory_order_seq_cst, std::memory_order_release); // expected-error {{operation is invalid}}
+ std::atomic_compare_exchange_weak_explicit(&vx, &val1, val2, std::memory_order_seq_cst, std::memory_order_acq_rel); // expected-error {{operation is invalid}}
+ // valid memory orders
+ std::atomic_compare_exchange_weak_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_relaxed);
+ std::atomic_compare_exchange_weak_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_consume);
+ std::atomic_compare_exchange_weak_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_acquire);
+ std::atomic_compare_exchange_weak_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_seq_cst);
+ }
+ // compare exchange strong
+ {
+ x.compare_exchange_strong(val1, val2, std::memory_order_seq_cst, std::memory_order_release); // expected-error {{operation is invalid}}
+ x.compare_exchange_strong(val1, val2, std::memory_order_seq_cst, std::memory_order_acq_rel); // expected-error {{operation is invalid}}
+ vx.compare_exchange_strong(val1, val2, std::memory_order_seq_cst, std::memory_order_release); // expected-error {{operation is invalid}}
+ vx.compare_exchange_strong(val1, val2, std::memory_order_seq_cst, std::memory_order_acq_rel); // expected-error {{operation is invalid}}
+ // valid memory orders
+ x.compare_exchange_strong(val1, val2, std::memory_order_seq_cst, std::memory_order_relaxed);
+ x.compare_exchange_strong(val1, val2, std::memory_order_seq_cst, std::memory_order_consume);
+ x.compare_exchange_strong(val1, val2, std::memory_order_seq_cst, std::memory_order_acquire);
+ x.compare_exchange_strong(val1, val2, std::memory_order_seq_cst, std::memory_order_seq_cst);
+ // Test that the cmpxchg overload with only one memory order argument
+ // does not generate any diagnostics.
+ x.compare_exchange_strong(val1, val2, std::memory_order_release);
+ }
+ {
+ std::atomic_compare_exchange_strong_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_release); // expected-error {{operation is invalid}}
+ std::atomic_compare_exchange_strong_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_acq_rel); // expected-error {{operation is invalid}}
+ std::atomic_compare_exchange_strong_explicit(&vx, &val1, val2, std::memory_order_seq_cst, std::memory_order_release); // expected-error {{operation is invalid}}
+ std::atomic_compare_exchange_strong_explicit(&vx, &val1, val2, std::memory_order_seq_cst, std::memory_order_acq_rel); // expected-error {{operation is invalid}}
+ // valid memory orders
+ std::atomic_compare_exchange_strong_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_relaxed);
+ std::atomic_compare_exchange_strong_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_consume);
+ std::atomic_compare_exchange_strong_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_acquire);
+ std::atomic_compare_exchange_strong_explicit(&x, &val1, val2, std::memory_order_seq_cst, std::memory_order_seq_cst);
+ }
+}
OpenPOWER on IntegriCloud