Skip to content

Commit fc886c3

Browse files
committed
[libc++] check that std::atomic is only instantiated for cv-unqualified types
1 parent 5afe474 commit fc886c3

File tree

3 files changed

+33
-0
lines changed

3 files changed

+33
-0
lines changed

libcxx/include/__atomic/support.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
#define _LIBCPP___ATOMIC_SUPPORT_H
1111

1212
#include <__config>
13+
#include <__type_traits/is_same.h>
1314
#include <__type_traits/is_trivially_copyable.h>
15+
#include <__type_traits/remove_cv.h>
1416

1517
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1618
# pragma GCC system_header
@@ -114,6 +116,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
114116
template <typename _Tp, typename _Base = __cxx_atomic_base_impl<_Tp> >
115117
struct __cxx_atomic_impl : public _Base {
116118
static_assert(is_trivially_copyable<_Tp>::value, "std::atomic<T> requires that 'T' be a trivially copyable type");
119+
static_assert(is_same<_Tp, typename remove_cv<_Tp>::type>::value,
120+
"std::atomic<T> requires that 'T' be a cv-unqualified type");
117121

118122
_LIBCPP_HIDE_FROM_ABI __cxx_atomic_impl() _NOEXCEPT = default;
119123
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __cxx_atomic_impl(_Tp __value) _NOEXCEPT : _Base(__value) {}

libcxx/include/__cxx03/__atomic/cxx_atomic_impl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
#include <__cxx03/__config>
1515
#include <__cxx03/__memory/addressof.h>
1616
#include <__cxx03/__type_traits/is_assignable.h>
17+
#include <__cxx03/__type_traits/is_same.h>
1718
#include <__cxx03/__type_traits/is_trivially_copyable.h>
1819
#include <__cxx03/__type_traits/remove_const.h>
20+
#include <__cxx03/__type_traits/remove_cv.h>
1921
#include <__cxx03/cstddef>
2022

2123
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -500,6 +502,8 @@ __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_o
500502
template <typename _Tp, typename _Base = __cxx_atomic_base_impl<_Tp> >
501503
struct __cxx_atomic_impl : public _Base {
502504
static_assert(is_trivially_copyable<_Tp>::value, "std::atomic<T> requires that 'T' be a trivially copyable type");
505+
static_assert(is_same<_Tp, typename remove_cv<_Tp>::type>::value,
506+
"std::atomic<T> requires that 'T' be a cv-unqualified type");
503507

504508
_LIBCPP_HIDE_FROM_ABI __cxx_atomic_impl() _NOEXCEPT = default;
505509
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __cxx_atomic_impl(_Tp __value) _NOEXCEPT : _Base(__value) {}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
// <atomic>
10+
11+
// template <class T>
12+
// struct atomic;
13+
14+
// This test checks that we static_assert inside std::atomic<T> when T
15+
// is cv-qualified, however Clang will sometimes emit additional
16+
// errors while trying to instantiate the rest of std::atomic<T>.
17+
// We silence those to make the test more robust.
18+
// ADDITIONAL_COMPILE_FLAGS: -Xclang -verify-ignore-unexpected=error
19+
20+
#include <atomic>
21+
22+
void f() {
23+
std::atomic<const int> a; // expected-error@*:* {{std::atomic<T> requires that 'T' be a cv-unqualified type}}
24+
}
25+

0 commit comments

Comments
 (0)