[libcxx] r333325 - Add nonnull; use it for atomics

JF Bastien via cfe-commits cfe-commits at lists.llvm.org
Fri May 25 16:43:53 PDT 2018


Author: jfb
Date: Fri May 25 16:43:53 2018
New Revision: 333325

URL: http://llvm.org/viewvc/llvm-project?rev=333325&view=rev
Log:
Add nonnull; use it for atomics

Summary:
The atomic non-member functions accept pointers to std::atomic / std::atomic_flag as well as to the non-atomic value. These are all dereferenced unconditionally when lowered, and therefore will fault if null. It's a tiny gotcha for new users, especially when they pass in NULL as expected value (instead of passing a pointer to a NULL value). We can therefore use the nonnull attribute to denote that:

  - A warning should be generated if the argument is null
  - It is undefined behavior if the argument is null (because a dereference will segfault)

This patch adds support for this attribute for clang and GCC, and sticks to the subset of the syntax both supports. In particular, work around this GCC oddity:
  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60625

The attributes are documented:

  - https://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Function-Attributes.html
  - https://clang.llvm.org/docs/AttributeReference.html#nullability-attributes

I'm authoring a companion clang patch for the __c11_* and __atomic_* builtins, which currently only warn on a subset of the pointer parameters.

In all cases the check needs to be explicit and not use the empty nonnull list, because some of the overloads are for atomic<T*> and the values themselves are allowed to be null.

<rdar://problem/18473124>

Reviewers: arphaman, EricWF

Subscribers: aheejin, christof, cfe-commits

Differential Revision: https://reviews.llvm.org/D47225

Added:
    libcxx/trunk/test/libcxx/atomics/diagnose_nonnull.fail.cpp
Modified:
    libcxx/trunk/include/__config
    libcxx/trunk/include/atomic

Modified: libcxx/trunk/include/__config
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__config?rev=333325&r1=333324&r2=333325&view=diff
==============================================================================
--- libcxx/trunk/include/__config (original)
+++ libcxx/trunk/include/__config Fri May 25 16:43:53 2018
@@ -1218,6 +1218,17 @@ _LIBCPP_FUNC_VIS extern "C" void __sanit
 #  endif
 #endif
 
+#if __has_attribute(nonnull) || _GNUC_VER >= 400
+// Function pointer parameter must be non-null: warns on null parameter,
+// undefined behavior if the parameter is null. Omitting parameter indices
+// indicates that all parameters of pointer type cannot be null.
+//
+// Note: parameter indexing starts at 1.
+#  define _LIBCPP_NONNULL(...) __attribute__((nonnull(__VA_ARGS__)))
+#else
+#  define _LIBCPP_NONNULL(...)
+#endif
+
 // Define availability macros.
 #if defined(_LIBCPP_USE_AVAILABILITY_APPLE)
 #  define _LIBCPP_AVAILABILITY_SHARED_MUTEX                                    \

Modified: libcxx/trunk/include/atomic
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/atomic?rev=333325&r1=333324&r2=333325&view=diff
==============================================================================
--- libcxx/trunk/include/atomic (original)
+++ libcxx/trunk/include/atomic Fri May 25 16:43:53 2018
@@ -646,19 +646,23 @@ static inline _LIBCPP_CONSTEXPR int __to
 } // namespace __gcc_atomic
 
 template <typename _Tp>
+_LIBCPP_NONNULL(1)
 static inline
 typename enable_if<
     __gcc_atomic::__can_assign<volatile _Atomic(_Tp)*, _Tp>::value>::type
-__c11_atomic_init(volatile _Atomic(_Tp)* __a,  _Tp __val) {
+__c11_atomic_init(volatile _Atomic(_Tp)* __a,  _Tp __val)
+{
   __a->__a_value = __val;
 }
 
 template <typename _Tp>
+_LIBCPP_NONNULL(1)
 static inline
 typename enable_if<
     !__gcc_atomic::__can_assign<volatile _Atomic(_Tp)*, _Tp>::value &&
      __gcc_atomic::__can_assign<         _Atomic(_Tp)*, _Tp>::value>::type
-__c11_atomic_init(volatile _Atomic(_Tp)* __a,  _Tp __val) {
+__c11_atomic_init(volatile _Atomic(_Tp)* __a,  _Tp __val)
+{
   // [atomics.types.generic]p1 guarantees _Tp is trivially copyable. Because
   // the default operator= in an object is not volatile, a byte-by-byte copy
   // is required.
@@ -671,7 +675,9 @@ __c11_atomic_init(volatile _Atomic(_Tp)*
 }
 
 template <typename _Tp>
-static inline void __c11_atomic_init(_Atomic(_Tp)* __a,  _Tp __val) {
+_LIBCPP_NONNULL(1)
+static inline void __c11_atomic_init(_Atomic(_Tp)* __a,  _Tp __val)
+{
   __a->__a_value = __val;
 }
 
@@ -684,22 +690,28 @@ static inline void __c11_atomic_signal_f
 }
 
 template <typename _Tp>
+_LIBCPP_NONNULL(1)
 static inline void __c11_atomic_store(volatile _Atomic(_Tp)* __a,  _Tp __val,
-                                      memory_order __order) {
+                                      memory_order __order)
+{
   return __atomic_store(&__a->__a_value, &__val,
                         __gcc_atomic::__to_gcc_order(__order));
 }
 
 template <typename _Tp>
+_LIBCPP_NONNULL(1)
 static inline void __c11_atomic_store(_Atomic(_Tp)* __a,  _Tp __val,
-                                      memory_order __order) {
+                                      memory_order __order)
+{
   __atomic_store(&__a->__a_value, &__val,
                  __gcc_atomic::__to_gcc_order(__order));
 }
 
 template <typename _Tp>
+_LIBCPP_NONNULL(1)
 static inline _Tp __c11_atomic_load(volatile _Atomic(_Tp)* __a,
-                                    memory_order __order) {
+                                    memory_order __order)
+{
   _Tp __ret;
   __atomic_load(&__a->__a_value, &__ret,
                 __gcc_atomic::__to_gcc_order(__order));
@@ -707,7 +719,9 @@ static inline _Tp __c11_atomic_load(vola
 }
 
 template <typename _Tp>
-static inline _Tp __c11_atomic_load(_Atomic(_Tp)* __a, memory_order __order) {
+_LIBCPP_NONNULL(1)
+static inline _Tp __c11_atomic_load(_Atomic(_Tp)* __a, memory_order __order)
+{
   _Tp __ret;
   __atomic_load(&__a->__a_value, &__ret,
                 __gcc_atomic::__to_gcc_order(__order));
@@ -715,8 +729,10 @@ static inline _Tp __c11_atomic_load(_Ato
 }
 
 template <typename _Tp>
+_LIBCPP_NONNULL(1)
 static inline _Tp __c11_atomic_exchange(volatile _Atomic(_Tp)* __a,
-                                        _Tp __value, memory_order __order) {
+                                        _Tp __value, memory_order __order)
+{
   _Tp __ret;
   __atomic_exchange(&__a->__a_value, &__value, &__ret,
                     __gcc_atomic::__to_gcc_order(__order));
@@ -724,8 +740,10 @@ static inline _Tp __c11_atomic_exchange(
 }
 
 template <typename _Tp>
+_LIBCPP_NONNULL(1)
 static inline _Tp __c11_atomic_exchange(_Atomic(_Tp)* __a, _Tp __value,
-                                        memory_order __order) {
+                                        memory_order __order)
+{
   _Tp __ret;
   __atomic_exchange(&__a->__a_value, &__value, &__ret,
                     __gcc_atomic::__to_gcc_order(__order));
@@ -733,9 +751,11 @@ static inline _Tp __c11_atomic_exchange(
 }
 
 template <typename _Tp>
+_LIBCPP_NONNULL(1, 2)
 static inline bool __c11_atomic_compare_exchange_strong(
     volatile _Atomic(_Tp)* __a, _Tp* __expected, _Tp __value,
-    memory_order __success, memory_order __failure) {
+    memory_order __success, memory_order __failure)
+{
   return __atomic_compare_exchange(&__a->__a_value, __expected, &__value,
                                    false,
                                    __gcc_atomic::__to_gcc_order(__success),
@@ -743,9 +763,11 @@ static inline bool __c11_atomic_compare_
 }
 
 template <typename _Tp>
+_LIBCPP_NONNULL(1, 2)
 static inline bool __c11_atomic_compare_exchange_strong(
     _Atomic(_Tp)* __a, _Tp* __expected, _Tp __value, memory_order __success,
-    memory_order __failure) {
+    memory_order __failure)
+{
   return __atomic_compare_exchange(&__a->__a_value, __expected, &__value,
                                    false,
                                    __gcc_atomic::__to_gcc_order(__success),
@@ -753,9 +775,11 @@ static inline bool __c11_atomic_compare_
 }
 
 template <typename _Tp>
+_LIBCPP_NONNULL(1, 2)
 static inline bool __c11_atomic_compare_exchange_weak(
     volatile _Atomic(_Tp)* __a, _Tp* __expected, _Tp __value,
-    memory_order __success, memory_order __failure) {
+    memory_order __success, memory_order __failure)
+{
   return __atomic_compare_exchange(&__a->__a_value, __expected, &__value,
                                    true,
                                    __gcc_atomic::__to_gcc_order(__success),
@@ -763,9 +787,11 @@ static inline bool __c11_atomic_compare_
 }
 
 template <typename _Tp>
+_LIBCPP_NONNULL(1, 2)
 static inline bool __c11_atomic_compare_exchange_weak(
     _Atomic(_Tp)* __a, _Tp* __expected, _Tp __value, memory_order __success,
-    memory_order __failure) {
+    memory_order __failure)
+{
   return __atomic_compare_exchange(&__a->__a_value, __expected, &__value,
                                    true,
                                    __gcc_atomic::__to_gcc_order(__success),
@@ -786,71 +812,91 @@ template <typename _Tp, int n>
 struct __skip_amt<_Tp[n]> { };
 
 template <typename _Tp, typename _Td>
+_LIBCPP_NONNULL(1)
 static inline _Tp __c11_atomic_fetch_add(volatile _Atomic(_Tp)* __a,
-                                         _Td __delta, memory_order __order) {
+                                         _Td __delta, memory_order __order)
+{
   return __atomic_fetch_add(&__a->__a_value, __delta * __skip_amt<_Tp>::value,
                             __gcc_atomic::__to_gcc_order(__order));
 }
 
 template <typename _Tp, typename _Td>
+_LIBCPP_NONNULL(1)
 static inline _Tp __c11_atomic_fetch_add(_Atomic(_Tp)* __a, _Td __delta,
-                                         memory_order __order) {
+                                         memory_order __order)
+{
   return __atomic_fetch_add(&__a->__a_value, __delta * __skip_amt<_Tp>::value,
                             __gcc_atomic::__to_gcc_order(__order));
 }
 
 template <typename _Tp, typename _Td>
+_LIBCPP_NONNULL(1)
 static inline _Tp __c11_atomic_fetch_sub(volatile _Atomic(_Tp)* __a,
-                                         _Td __delta, memory_order __order) {
+                                         _Td __delta, memory_order __order)
+{
   return __atomic_fetch_sub(&__a->__a_value, __delta * __skip_amt<_Tp>::value,
                             __gcc_atomic::__to_gcc_order(__order));
 }
 
 template <typename _Tp, typename _Td>
+_LIBCPP_NONNULL(1)
 static inline _Tp __c11_atomic_fetch_sub(_Atomic(_Tp)* __a, _Td __delta,
-                                         memory_order __order) {
+                                         memory_order __order)
+{
   return __atomic_fetch_sub(&__a->__a_value, __delta * __skip_amt<_Tp>::value,
                             __gcc_atomic::__to_gcc_order(__order));
 }
 
 template <typename _Tp>
+_LIBCPP_NONNULL(1)
 static inline _Tp __c11_atomic_fetch_and(volatile _Atomic(_Tp)* __a,
-                                         _Tp __pattern, memory_order __order) {
+                                         _Tp __pattern, memory_order __order)
+{
   return __atomic_fetch_and(&__a->__a_value, __pattern,
                             __gcc_atomic::__to_gcc_order(__order));
 }
 
 template <typename _Tp>
+_LIBCPP_NONNULL(1)
 static inline _Tp __c11_atomic_fetch_and(_Atomic(_Tp)* __a,
-                                         _Tp __pattern, memory_order __order) {
+                                         _Tp __pattern, memory_order __order)
+{
   return __atomic_fetch_and(&__a->__a_value, __pattern,
                             __gcc_atomic::__to_gcc_order(__order));
 }
 
 template <typename _Tp>
+_LIBCPP_NONNULL(1)
 static inline _Tp __c11_atomic_fetch_or(volatile _Atomic(_Tp)* __a,
-                                        _Tp __pattern, memory_order __order) {
+                                        _Tp __pattern, memory_order __order)
+{
   return __atomic_fetch_or(&__a->__a_value, __pattern,
                            __gcc_atomic::__to_gcc_order(__order));
 }
 
 template <typename _Tp>
+_LIBCPP_NONNULL(1)
 static inline _Tp __c11_atomic_fetch_or(_Atomic(_Tp)* __a, _Tp __pattern,
-                                        memory_order __order) {
+                                        memory_order __order)
+{
   return __atomic_fetch_or(&__a->__a_value, __pattern,
                            __gcc_atomic::__to_gcc_order(__order));
 }
 
 template <typename _Tp>
+_LIBCPP_NONNULL(1)
 static inline _Tp __c11_atomic_fetch_xor(volatile _Atomic(_Tp)* __a,
-                                         _Tp __pattern, memory_order __order) {
+                                         _Tp __pattern, memory_order __order)
+{
   return __atomic_fetch_xor(&__a->__a_value, __pattern,
                             __gcc_atomic::__to_gcc_order(__order));
 }
 
 template <typename _Tp>
+_LIBCPP_NONNULL(1)
 static inline _Tp __c11_atomic_fetch_xor(_Atomic(_Tp)* __a, _Tp __pattern,
-                                         memory_order __order) {
+                                         memory_order __order)
+{
   return __atomic_fetch_xor(&__a->__a_value, __pattern,
                             __gcc_atomic::__to_gcc_order(__order));
 }
@@ -1164,6 +1210,7 @@ struct atomic<_Tp*>
 // atomic_is_lock_free
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 bool
 atomic_is_lock_free(const volatile atomic<_Tp>* __o) _NOEXCEPT
@@ -1172,6 +1219,7 @@ atomic_is_lock_free(const volatile atomi
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 bool
 atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT
@@ -1182,6 +1230,7 @@ atomic_is_lock_free(const atomic<_Tp>* _
 // atomic_init
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 void
 atomic_init(volatile atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
@@ -1190,6 +1239,7 @@ atomic_init(volatile atomic<_Tp>* __o, _
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 void
 atomic_init(atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
@@ -1200,6 +1250,7 @@ atomic_init(atomic<_Tp>* __o, _Tp __d) _
 // atomic_store
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 void
 atomic_store(volatile atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
@@ -1208,6 +1259,7 @@ atomic_store(volatile atomic<_Tp>* __o,
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 void
 atomic_store(atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
@@ -1218,6 +1270,7 @@ atomic_store(atomic<_Tp>* __o, _Tp __d)
 // atomic_store_explicit
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 void
 atomic_store_explicit(volatile atomic<_Tp>* __o, _Tp __d, memory_order __m) _NOEXCEPT
@@ -1227,6 +1280,7 @@ atomic_store_explicit(volatile atomic<_T
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 void
 atomic_store_explicit(atomic<_Tp>* __o, _Tp __d, memory_order __m) _NOEXCEPT
@@ -1238,6 +1292,7 @@ atomic_store_explicit(atomic<_Tp>* __o,
 // atomic_load
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp
 atomic_load(const volatile atomic<_Tp>* __o) _NOEXCEPT
@@ -1246,6 +1301,7 @@ atomic_load(const volatile atomic<_Tp>*
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp
 atomic_load(const atomic<_Tp>* __o) _NOEXCEPT
@@ -1256,6 +1312,7 @@ atomic_load(const atomic<_Tp>* __o) _NOE
 // atomic_load_explicit
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp
 atomic_load_explicit(const volatile atomic<_Tp>* __o, memory_order __m) _NOEXCEPT
@@ -1265,6 +1322,7 @@ atomic_load_explicit(const volatile atom
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp
 atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT
@@ -1276,6 +1334,7 @@ atomic_load_explicit(const atomic<_Tp>*
 // atomic_exchange
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp
 atomic_exchange(volatile atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
@@ -1284,6 +1343,7 @@ atomic_exchange(volatile atomic<_Tp>* __
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp
 atomic_exchange(atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
@@ -1294,6 +1354,7 @@ atomic_exchange(atomic<_Tp>* __o, _Tp __
 // atomic_exchange_explicit
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp
 atomic_exchange_explicit(volatile atomic<_Tp>* __o, _Tp __d, memory_order __m) _NOEXCEPT
@@ -1302,6 +1363,7 @@ atomic_exchange_explicit(volatile atomic
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp
 atomic_exchange_explicit(atomic<_Tp>* __o, _Tp __d, memory_order __m) _NOEXCEPT
@@ -1312,6 +1374,7 @@ atomic_exchange_explicit(atomic<_Tp>* __
 // atomic_compare_exchange_weak
 
 template <class _Tp>
+_LIBCPP_NONNULL(1, 2)
 inline _LIBCPP_INLINE_VISIBILITY
 bool
 atomic_compare_exchange_weak(volatile atomic<_Tp>* __o, _Tp* __e, _Tp __d) _NOEXCEPT
@@ -1320,6 +1383,7 @@ atomic_compare_exchange_weak(volatile at
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1, 2)
 inline _LIBCPP_INLINE_VISIBILITY
 bool
 atomic_compare_exchange_weak(atomic<_Tp>* __o, _Tp* __e, _Tp __d) _NOEXCEPT
@@ -1330,6 +1394,7 @@ atomic_compare_exchange_weak(atomic<_Tp>
 // atomic_compare_exchange_strong
 
 template <class _Tp>
+_LIBCPP_NONNULL(1, 2)
 inline _LIBCPP_INLINE_VISIBILITY
 bool
 atomic_compare_exchange_strong(volatile atomic<_Tp>* __o, _Tp* __e, _Tp __d) _NOEXCEPT
@@ -1338,6 +1403,7 @@ atomic_compare_exchange_strong(volatile
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1, 2)
 inline _LIBCPP_INLINE_VISIBILITY
 bool
 atomic_compare_exchange_strong(atomic<_Tp>* __o, _Tp* __e, _Tp __d) _NOEXCEPT
@@ -1348,6 +1414,7 @@ atomic_compare_exchange_strong(atomic<_T
 // atomic_compare_exchange_weak_explicit
 
 template <class _Tp>
+_LIBCPP_NONNULL(1, 2)
 inline _LIBCPP_INLINE_VISIBILITY
 bool
 atomic_compare_exchange_weak_explicit(volatile atomic<_Tp>* __o, _Tp* __e,
@@ -1359,6 +1426,7 @@ atomic_compare_exchange_weak_explicit(vo
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1, 2)
 inline _LIBCPP_INLINE_VISIBILITY
 bool
 atomic_compare_exchange_weak_explicit(atomic<_Tp>* __o, _Tp* __e, _Tp __d,
@@ -1371,6 +1439,7 @@ atomic_compare_exchange_weak_explicit(at
 // atomic_compare_exchange_strong_explicit
 
 template <class _Tp>
+_LIBCPP_NONNULL(1, 2)
 inline _LIBCPP_INLINE_VISIBILITY
 bool
 atomic_compare_exchange_strong_explicit(volatile atomic<_Tp>* __o,
@@ -1382,6 +1451,7 @@ atomic_compare_exchange_strong_explicit(
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1, 2)
 inline _LIBCPP_INLINE_VISIBILITY
 bool
 atomic_compare_exchange_strong_explicit(atomic<_Tp>* __o, _Tp* __e,
@@ -1395,6 +1465,7 @@ atomic_compare_exchange_strong_explicit(
 // atomic_fetch_add
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1407,6 +1478,7 @@ atomic_fetch_add(volatile atomic<_Tp>* _
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1419,6 +1491,7 @@ atomic_fetch_add(atomic<_Tp>* __o, _Tp _
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp*
 atomic_fetch_add(volatile atomic<_Tp*>* __o, ptrdiff_t __op) _NOEXCEPT
@@ -1427,6 +1500,7 @@ atomic_fetch_add(volatile atomic<_Tp*>*
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp*
 atomic_fetch_add(atomic<_Tp*>* __o, ptrdiff_t __op) _NOEXCEPT
@@ -1437,6 +1511,7 @@ atomic_fetch_add(atomic<_Tp*>* __o, ptrd
 // atomic_fetch_add_explicit
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1449,6 +1524,7 @@ atomic_fetch_add_explicit(volatile atomi
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1461,6 +1537,7 @@ atomic_fetch_add_explicit(atomic<_Tp>* _
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp*
 atomic_fetch_add_explicit(volatile atomic<_Tp*>* __o, ptrdiff_t __op,
@@ -1470,6 +1547,7 @@ atomic_fetch_add_explicit(volatile atomi
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp*
 atomic_fetch_add_explicit(atomic<_Tp*>* __o, ptrdiff_t __op, memory_order __m) _NOEXCEPT
@@ -1480,6 +1558,7 @@ atomic_fetch_add_explicit(atomic<_Tp*>*
 // atomic_fetch_sub
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1492,6 +1571,7 @@ atomic_fetch_sub(volatile atomic<_Tp>* _
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1504,6 +1584,7 @@ atomic_fetch_sub(atomic<_Tp>* __o, _Tp _
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp*
 atomic_fetch_sub(volatile atomic<_Tp*>* __o, ptrdiff_t __op) _NOEXCEPT
@@ -1512,6 +1593,7 @@ atomic_fetch_sub(volatile atomic<_Tp*>*
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp*
 atomic_fetch_sub(atomic<_Tp*>* __o, ptrdiff_t __op) _NOEXCEPT
@@ -1522,6 +1604,7 @@ atomic_fetch_sub(atomic<_Tp*>* __o, ptrd
 // atomic_fetch_sub_explicit
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1534,6 +1617,7 @@ atomic_fetch_sub_explicit(volatile atomi
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1546,6 +1630,7 @@ atomic_fetch_sub_explicit(atomic<_Tp>* _
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp*
 atomic_fetch_sub_explicit(volatile atomic<_Tp*>* __o, ptrdiff_t __op,
@@ -1555,6 +1640,7 @@ atomic_fetch_sub_explicit(volatile atomi
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp*
 atomic_fetch_sub_explicit(atomic<_Tp*>* __o, ptrdiff_t __op, memory_order __m) _NOEXCEPT
@@ -1565,6 +1651,7 @@ atomic_fetch_sub_explicit(atomic<_Tp*>*
 // atomic_fetch_and
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1577,6 +1664,7 @@ atomic_fetch_and(volatile atomic<_Tp>* _
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1591,6 +1679,7 @@ atomic_fetch_and(atomic<_Tp>* __o, _Tp _
 // atomic_fetch_and_explicit
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1603,6 +1692,7 @@ atomic_fetch_and_explicit(volatile atomi
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1617,6 +1707,7 @@ atomic_fetch_and_explicit(atomic<_Tp>* _
 // atomic_fetch_or
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1629,6 +1720,7 @@ atomic_fetch_or(volatile atomic<_Tp>* __
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1643,6 +1735,7 @@ atomic_fetch_or(atomic<_Tp>* __o, _Tp __
 // atomic_fetch_or_explicit
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1655,6 +1748,7 @@ atomic_fetch_or_explicit(volatile atomic
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1669,6 +1763,7 @@ atomic_fetch_or_explicit(atomic<_Tp>* __
 // atomic_fetch_xor
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1681,6 +1776,7 @@ atomic_fetch_xor(volatile atomic<_Tp>* _
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1695,6 +1791,7 @@ atomic_fetch_xor(atomic<_Tp>* __o, _Tp _
 // atomic_fetch_xor_explicit
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1707,6 +1804,7 @@ atomic_fetch_xor_explicit(volatile atomi
 }
 
 template <class _Tp>
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
@@ -1759,6 +1857,7 @@ private:
 #endif
 } atomic_flag;
 
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 bool
 atomic_flag_test_and_set(volatile atomic_flag* __o) _NOEXCEPT
@@ -1766,6 +1865,7 @@ atomic_flag_test_and_set(volatile atomic
     return __o->test_and_set();
 }
 
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 bool
 atomic_flag_test_and_set(atomic_flag* __o) _NOEXCEPT
@@ -1773,6 +1873,7 @@ atomic_flag_test_and_set(atomic_flag* __
     return __o->test_and_set();
 }
 
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 bool
 atomic_flag_test_and_set_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT
@@ -1780,6 +1881,7 @@ atomic_flag_test_and_set_explicit(volati
     return __o->test_and_set(__m);
 }
 
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 bool
 atomic_flag_test_and_set_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT
@@ -1787,6 +1889,7 @@ atomic_flag_test_and_set_explicit(atomic
     return __o->test_and_set(__m);
 }
 
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 void
 atomic_flag_clear(volatile atomic_flag* __o) _NOEXCEPT
@@ -1794,6 +1897,7 @@ atomic_flag_clear(volatile atomic_flag*
     __o->clear();
 }
 
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 void
 atomic_flag_clear(atomic_flag* __o) _NOEXCEPT
@@ -1801,6 +1905,7 @@ atomic_flag_clear(atomic_flag* __o) _NOE
     __o->clear();
 }
 
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 void
 atomic_flag_clear_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT
@@ -1808,6 +1913,7 @@ atomic_flag_clear_explicit(volatile atom
     __o->clear(__m);
 }
 
+_LIBCPP_NONNULL(1)
 inline _LIBCPP_INLINE_VISIBILITY
 void
 atomic_flag_clear_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT

Added: libcxx/trunk/test/libcxx/atomics/diagnose_nonnull.fail.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/atomics/diagnose_nonnull.fail.cpp?rev=333325&view=auto
==============================================================================
--- libcxx/trunk/test/libcxx/atomics/diagnose_nonnull.fail.cpp (added)
+++ libcxx/trunk/test/libcxx/atomics/diagnose_nonnull.fail.cpp Fri May 25 16:43:53 2018
@@ -0,0 +1,92 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: verify-support
+// UNSUPPORTED: libcpp-has-no-threads
+
+// <atomic>
+
+// Test that null pointer parameters are diagnosed.
+
+#include <atomic>
+
+int main() {
+  std::atomic<int> ai = ATOMIC_VAR_INIT(0);
+  volatile std::atomic<int> vai = ATOMIC_VAR_INIT(0);
+  int i = 42;
+
+  atomic_is_lock_free((const volatile std::atomic<int>*)0); // expected-error {{null passed to a callee that requires a non-null argument}}
+  atomic_is_lock_free((const std::atomic<int>*)0); // expected-error {{null passed to a callee that requires a non-null argument}}
+  atomic_init((volatile std::atomic<int>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  atomic_init((std::atomic<int>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  atomic_store((volatile std::atomic<int>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  atomic_store((std::atomic<int>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  atomic_store_explicit((volatile std::atomic<int>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  atomic_store_explicit((std::atomic<int>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_load((const volatile std::atomic<int>*)0); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_load((const std::atomic<int>*)0); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_load_explicit((const volatile std::atomic<int>*)0, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_load_explicit((const std::atomic<int>*)0, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_exchange((volatile std::atomic<int>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_exchange((std::atomic<int>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_exchange_explicit((volatile std::atomic<int>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_exchange_explicit((std::atomic<int>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_compare_exchange_weak((volatile std::atomic<int>*)0, &i, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_compare_exchange_weak((std::atomic<int>*)0, &i, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_compare_exchange_strong((volatile std::atomic<int>*)0, &i, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_compare_exchange_strong((std::atomic<int>*)0, &i, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_compare_exchange_weak(&vai, (int*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_compare_exchange_weak(&ai, (int*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_compare_exchange_strong(&vai, (int*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_compare_exchange_strong(&ai, (int*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_compare_exchange_weak_explicit((volatile std::atomic<int>*)0, &i, 42, std::memory_order_relaxed, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_compare_exchange_weak_explicit((std::atomic<int>*)0, &i, 42, std::memory_order_relaxed, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_compare_exchange_strong_explicit((volatile std::atomic<int>*)0, &i, 42, std::memory_order_relaxed, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_compare_exchange_strong_explicit((std::atomic<int>*)0, &i, 42, std::memory_order_relaxed, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_compare_exchange_weak_explicit(&vai, (int*)0, 42, std::memory_order_relaxed, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_compare_exchange_weak_explicit(&ai, (int*)0, 42, std::memory_order_relaxed, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_compare_exchange_strong_explicit(&vai, (int*)0, 42, std::memory_order_relaxed, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_compare_exchange_strong_explicit(&ai, (int*)0, 42, std::memory_order_relaxed, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_add((volatile std::atomic<int>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_add((std::atomic<int>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_add((volatile std::atomic<int*>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_add((std::atomic<int*>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_add_explicit((volatile std::atomic<int>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_add_explicit((std::atomic<int>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_add_explicit((volatile std::atomic<int*>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_add_explicit((std::atomic<int*>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_sub((volatile std::atomic<int>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_sub((std::atomic<int>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_sub((volatile std::atomic<int*>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_sub((std::atomic<int*>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_sub_explicit((volatile std::atomic<int>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_sub_explicit((std::atomic<int>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_sub_explicit((volatile std::atomic<int*>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_sub_explicit((std::atomic<int*>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_and((volatile std::atomic<int>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_and((std::atomic<int>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_and_explicit((volatile std::atomic<int>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_and_explicit((std::atomic<int>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_or((volatile std::atomic<int>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_or((std::atomic<int>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_or_explicit((volatile std::atomic<int>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_or_explicit((std::atomic<int>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_xor((volatile std::atomic<int>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_xor((std::atomic<int>*)0, 42); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_xor_explicit((volatile std::atomic<int>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_fetch_xor_explicit((std::atomic<int>*)0, 42, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_flag_test_and_set((volatile std::atomic_flag*)0); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_flag_test_and_set((std::atomic_flag*)0); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_flag_test_and_set_explicit((volatile std::atomic_flag*)0, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_flag_test_and_set_explicit((std::atomic_flag*)0, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_flag_clear((volatile std::atomic_flag*)0); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_flag_clear((std::atomic_flag*)0); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_flag_clear_explicit((volatile std::atomic_flag*)0, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+  (void)atomic_flag_clear_explicit((std::atomic_flag*)0, std::memory_order_relaxed); // expected-error {{null passed to a callee that requires a non-null argument}}
+}




More information about the cfe-commits mailing list