diff options
author | Eric Fiselier <eric@efcs.ca> | 2016-07-23 01:16:55 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2016-07-23 01:16:55 +0000 |
commit | 586b16e16a51c2a361de35e1a467723f6a25acc7 (patch) | |
tree | 61d1ae58de588055a8a9f6e9d6a2cf9020174dc1 /libcxx/test | |
parent | a7d9ec8751b1bb045f83934e9be202a191249db8 (diff) | |
download | bcm5719-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.cpp | 125 |
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); + } +} |