From baa2a973bd776a51bb05a8590ab05d86eea7b321 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Thu, 13 Aug 2015 16:58:50 -0700 Subject: [PATCH] Use clang's nullability instead of nonnull. http://clang.llvm.org/docs/AttributeReference.html#nonnull _Nonnull is similar to the nonnull attribute in that it will instruct compilers to warn the user if it can prove that a null argument is being passed. Unlike the nonnull attribute, this annotation indicated that a value *should not* be null, not that it *cannot* be null, or even that the behavior is undefined. The important distinction is that the optimizer will perform surprising optimizations like the following: void foo(void*) __attribute__(nonnull, 1); int bar(int* p) { foo(p); // The following null check will be elided because nonnull // attribute means that, since we call foo with p, p can be // assumed to not be null. Thus this will crash if we are called // with a null pointer. if (src != NULL) { return *p; } return 0; } int main() { return bar(NULL); } Note that by doing this we are no longer attaching any sort of attribute for GCC (GCC doesn't support attaching nonnull directly to a parameter, only to the function and naming the arguments positionally). This means we won't be getting a warning for this case from GCC any more. People that listen to warnings tend to use clang anyway, and we're quickly moving toward that as the default, so this seems to be an acceptable tradeoff. Change-Id: Ie05fe7cec2f19a082c1defb303f82bcf9241b88d --- libc/bionic/pthread_mutex.cpp | 6 ++ libc/include/dlfcn.h | 6 +- libc/include/pthread.h | 162 ++++++++++++++++------------------ libc/include/signal.h | 6 +- libc/include/string.h | 6 +- libc/include/sys/cdefs.h | 32 +++++++ libc/include/sys/signalfd.h | 2 +- libc/include/sys/statvfs.h | 8 +- libc/include/sys/swap.h | 4 +- libc/include/sys/vfs.h | 8 +- tests/pthread_test.cpp | 18 +++- 11 files changed, 151 insertions(+), 107 deletions(-) diff --git a/libc/bionic/pthread_mutex.cpp b/libc/bionic/pthread_mutex.cpp index 7d8e8a820..14e0ab0c5 100644 --- a/libc/bionic/pthread_mutex.cpp +++ b/libc/bionic/pthread_mutex.cpp @@ -502,6 +502,9 @@ static int __pthread_mutex_lock_with_timeout(pthread_mutex_internal_t* mutex, int pthread_mutex_lock(pthread_mutex_t* mutex_interface) { #if !defined(__LP64__) + // Some apps depend on being able to pass NULL as a mutex and get EINVAL + // back. Don't need to worry about it for LP64 since the ABI is brand new, + // but keep compatibility for LP32. http://b/19995172. if (mutex_interface == NULL) { return EINVAL; } @@ -523,6 +526,9 @@ int pthread_mutex_lock(pthread_mutex_t* mutex_interface) { int pthread_mutex_unlock(pthread_mutex_t* mutex_interface) { #if !defined(__LP64__) + // Some apps depend on being able to pass NULL as a mutex and get EINVAL + // back. Don't need to worry about it for LP64 since the ABI is brand new, + // but keep compatibility for LP32. http://b/19995172. if (mutex_interface == NULL) { return EINVAL; } diff --git a/libc/include/dlfcn.h b/libc/include/dlfcn.h index 25a302ff8..5dc83501f 100644 --- a/libc/include/dlfcn.h +++ b/libc/include/dlfcn.h @@ -46,8 +46,8 @@ typedef struct { extern void* dlopen(const char* filename, int flag); extern int dlclose(void* handle); extern const char* dlerror(void); -extern void* dlsym(void* handle, const char* symbol) __nonnull((2)); -extern void* dlvsym(void* handle, const char* symbol, const char* version) __nonnull((2, 3)) +extern void* dlsym(void* handle, const char* _Nonnull symbol); +extern void* dlvsym(void* handle, const char* _Nonnull symbol, const char* _Nonnull version) __INTRODUCED_IN(24); extern int dladdr(const void* addr, Dl_info *info); @@ -80,5 +80,3 @@ enum { __END_DECLS #endif /* __DLFCN_H */ - - diff --git a/libc/include/pthread.h b/libc/include/pthread.h index 2df9b74e3..fd8aa0024 100644 --- a/libc/include/pthread.h +++ b/libc/include/pthread.h @@ -135,49 +135,51 @@ __BEGIN_DECLS int pthread_atfork(void (*)(void), void (*)(void), void (*)(void)) __INTRODUCED_IN(21); -int pthread_attr_destroy(pthread_attr_t*) __nonnull((1)); -int pthread_attr_getdetachstate(const pthread_attr_t*, int*) __nonnull((1, 2)); -int pthread_attr_getguardsize(const pthread_attr_t*, size_t*) __nonnull((1, 2)); -int pthread_attr_getschedparam(const pthread_attr_t*, struct sched_param*) __nonnull((1, 2)); -int pthread_attr_getschedpolicy(const pthread_attr_t*, int*) __nonnull((1, 2)); -int pthread_attr_getscope(const pthread_attr_t*, int*) __nonnull((1, 2)); -int pthread_attr_getstack(const pthread_attr_t*, void**, size_t*) __nonnull((1, 2, 3)); -int pthread_attr_getstacksize(const pthread_attr_t*, size_t*) __nonnull((1, 2)); -int pthread_attr_init(pthread_attr_t*) __nonnull((1)); -int pthread_attr_setdetachstate(pthread_attr_t*, int) __nonnull((1)); -int pthread_attr_setguardsize(pthread_attr_t*, size_t) __nonnull((1)); -int pthread_attr_setschedparam(pthread_attr_t*, const struct sched_param*) __nonnull((1, 2)); -int pthread_attr_setschedpolicy(pthread_attr_t*, int) __nonnull((1)); -int pthread_attr_setscope(pthread_attr_t*, int) __nonnull((1)); -int pthread_attr_setstack(pthread_attr_t*, void*, size_t) __nonnull((1)); -int pthread_attr_setstacksize(pthread_attr_t*, size_t) __nonnull((1)); +int pthread_attr_destroy(pthread_attr_t* _Nonnull); +int pthread_attr_getdetachstate(const pthread_attr_t* _Nonnull, int* _Nonnull); +int pthread_attr_getguardsize(const pthread_attr_t* _Nonnull, size_t* _Nonnull); +int pthread_attr_getschedparam(const pthread_attr_t* _Nonnull, struct sched_param* _Nonnull); +int pthread_attr_getschedpolicy(const pthread_attr_t* _Nonnull, int* _Nonnull); +int pthread_attr_getscope(const pthread_attr_t* _Nonnull, int* _Nonnull); +int pthread_attr_getstack(const pthread_attr_t* _Nonnull, void** _Nonnull, size_t* _Nonnull); +int pthread_attr_getstacksize(const pthread_attr_t* _Nonnull, size_t* _Nonnull); +int pthread_attr_init(pthread_attr_t* _Nonnull); +int pthread_attr_setdetachstate(pthread_attr_t* _Nonnull, int); +int pthread_attr_setguardsize(pthread_attr_t* _Nonnull, size_t); +int pthread_attr_setschedparam(pthread_attr_t* _Nonnull, const struct sched_param* _Nonnull); +int pthread_attr_setschedpolicy(pthread_attr_t* _Nonnull, int); +int pthread_attr_setscope(pthread_attr_t* _Nonnull, int); +int pthread_attr_setstack(pthread_attr_t* _Nonnull, void*, size_t); +int pthread_attr_setstacksize(pthread_attr_t* _Nonnull, size_t); -int pthread_condattr_destroy(pthread_condattr_t*) __nonnull((1)); -int pthread_condattr_getclock(const pthread_condattr_t*, clockid_t*) __nonnull((1, 2)) +int pthread_condattr_destroy(pthread_condattr_t* _Nonnull); +int pthread_condattr_getclock(const pthread_condattr_t* _Nonnull, clockid_t* _Nonnull) __INTRODUCED_IN(21); -int pthread_condattr_getpshared(const pthread_condattr_t*, int*) __nonnull((1, 2)); -int pthread_condattr_init(pthread_condattr_t*) __nonnull((1)); -int pthread_condattr_setclock(pthread_condattr_t*, clockid_t) __nonnull((1)) __INTRODUCED_IN(21); -int pthread_condattr_setpshared(pthread_condattr_t*, int) __nonnull((1)); +int pthread_condattr_getpshared(const pthread_condattr_t* _Nonnull, int* _Nonnull); +int pthread_condattr_init(pthread_condattr_t* _Nonnull); +int pthread_condattr_setclock(pthread_condattr_t* _Nonnull, clockid_t) __INTRODUCED_IN(21); +int pthread_condattr_setpshared(pthread_condattr_t* _Nonnull, int); -int pthread_cond_broadcast(pthread_cond_t*) __nonnull((1)); -int pthread_cond_destroy(pthread_cond_t*) __nonnull((1)); -int pthread_cond_init(pthread_cond_t*, const pthread_condattr_t*) __nonnull((1)); -int pthread_cond_signal(pthread_cond_t*) __nonnull((1)); -int pthread_cond_timedwait(pthread_cond_t*, pthread_mutex_t*, const struct timespec*) __nonnull((1, 2, 3)); -int pthread_cond_wait(pthread_cond_t*, pthread_mutex_t*) __nonnull((1, 2)); +int pthread_cond_broadcast(pthread_cond_t* _Nonnull); +int pthread_cond_destroy(pthread_cond_t* _Nonnull); +int pthread_cond_init(pthread_cond_t* _Nonnull, const pthread_condattr_t*); +int pthread_cond_signal(pthread_cond_t* _Nonnull); +int pthread_cond_timedwait(pthread_cond_t* _Nonnull, pthread_mutex_t* _Nonnull, + const struct timespec* _Nonnull); +int pthread_cond_wait(pthread_cond_t* _Nonnull, pthread_mutex_t* _Nonnull); -int pthread_create(pthread_t*, pthread_attr_t const*, void *(*)(void*), void*) __nonnull((1, 3)); +int pthread_create(pthread_t* _Nonnull, pthread_attr_t const*, + void* (* _Nonnull start_routine)(void*), void*); int pthread_detach(pthread_t); void pthread_exit(void*) __noreturn; int pthread_equal(pthread_t, pthread_t); -int pthread_getattr_np(pthread_t, pthread_attr_t*) __nonnull((2)); +int pthread_getattr_np(pthread_t, pthread_attr_t* _Nonnull); -int pthread_getcpuclockid(pthread_t, clockid_t*) __nonnull((2)); +int pthread_getcpuclockid(pthread_t, clockid_t* _Nonnull); -int pthread_getschedparam(pthread_t, int*, struct sched_param*) __nonnull((2, 3)); +int pthread_getschedparam(pthread_t, int* _Nonnull, struct sched_param* _Nonnull); void* pthread_getspecific(pthread_key_t); @@ -185,79 +187,71 @@ pid_t pthread_gettid_np(pthread_t) __INTRODUCED_IN(21); int pthread_join(pthread_t, void**); -int pthread_key_create(pthread_key_t*, void (*)(void*)) __nonnull((1)); +int pthread_key_create(pthread_key_t* _Nonnull, void (*)(void*)); int pthread_key_delete(pthread_key_t); -int pthread_mutexattr_destroy(pthread_mutexattr_t*) __nonnull((1)); -int pthread_mutexattr_getpshared(const pthread_mutexattr_t*, int*) __nonnull((1, 2)); -int pthread_mutexattr_gettype(const pthread_mutexattr_t*, int*) __nonnull((1, 2)); -int pthread_mutexattr_init(pthread_mutexattr_t*) __nonnull((1)); -int pthread_mutexattr_setpshared(pthread_mutexattr_t*, int) __nonnull((1)); -int pthread_mutexattr_settype(pthread_mutexattr_t*, int) __nonnull((1)); +int pthread_mutexattr_destroy(pthread_mutexattr_t* _Nonnull); +int pthread_mutexattr_getpshared(const pthread_mutexattr_t* _Nonnull, int* _Nonnull); +int pthread_mutexattr_gettype(const pthread_mutexattr_t* _Nonnull, int* _Nonnull); +int pthread_mutexattr_init(pthread_mutexattr_t* _Nonnull); +int pthread_mutexattr_setpshared(pthread_mutexattr_t* _Nonnull, int); +int pthread_mutexattr_settype(pthread_mutexattr_t* _Nonnull, int); -int pthread_mutex_destroy(pthread_mutex_t*) __nonnull((1)); -int pthread_mutex_init(pthread_mutex_t*, const pthread_mutexattr_t*) __nonnull((1)); -#if !defined(__LP64__) -int pthread_mutex_lock(pthread_mutex_t*) /* __nonnull((1)) */; -#else -int pthread_mutex_lock(pthread_mutex_t*) __nonnull((1)); -#endif -int pthread_mutex_timedlock(pthread_mutex_t*, const struct timespec*) __nonnull((1, 2)) +int pthread_mutex_destroy(pthread_mutex_t* _Nonnull); +int pthread_mutex_init(pthread_mutex_t* _Nonnull, const pthread_mutexattr_t*); +int pthread_mutex_lock(pthread_mutex_t* _Nonnull); +int pthread_mutex_timedlock(pthread_mutex_t* _Nonnull, const struct timespec* _Nonnull) __INTRODUCED_IN(21); -int pthread_mutex_trylock(pthread_mutex_t*) __nonnull((1)); -#if !defined(__LP4__) -int pthread_mutex_unlock(pthread_mutex_t*) /* __nonnull((1)) */; -#else -int pthread_mutex_unlock(pthread_mutex_t*) __nonnull((1)); -#endif +int pthread_mutex_trylock(pthread_mutex_t* _Nonnull); +int pthread_mutex_unlock(pthread_mutex_t* _Nonnull); -int pthread_once(pthread_once_t*, void (*)(void)) __nonnull((1, 2)); +int pthread_once(pthread_once_t* _Nonnull, void (* _Nonnull init_routine)(void)); -int pthread_rwlockattr_init(pthread_rwlockattr_t*) __nonnull((1)); -int pthread_rwlockattr_destroy(pthread_rwlockattr_t*) __nonnull((1)); -int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t*, int*) __nonnull((1, 2)); -int pthread_rwlockattr_setpshared(pthread_rwlockattr_t*, int) __nonnull((1)); -int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t*, int*) __nonnull((1, 2)) +int pthread_rwlockattr_init(pthread_rwlockattr_t* _Nonnull); +int pthread_rwlockattr_destroy(pthread_rwlockattr_t* _Nonnull); +int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t* _Nonnull, int* _Nonnull); +int pthread_rwlockattr_setpshared(pthread_rwlockattr_t* _Nonnull, int); +int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t* _Nonnull, int* _Nonnull) __INTRODUCED_IN(23); -int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t*, int) __nonnull((1)) __INTRODUCED_IN(23); +int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t* _Nonnull, int) __INTRODUCED_IN(23); -int pthread_rwlock_destroy(pthread_rwlock_t*) __nonnull((1)); -int pthread_rwlock_init(pthread_rwlock_t*, const pthread_rwlockattr_t*) __nonnull((1)); -int pthread_rwlock_rdlock(pthread_rwlock_t*) __nonnull((1)); -int pthread_rwlock_timedrdlock(pthread_rwlock_t*, const struct timespec*) __nonnull((1, 2)); -int pthread_rwlock_timedwrlock(pthread_rwlock_t*, const struct timespec*) __nonnull((1, 2)); -int pthread_rwlock_tryrdlock(pthread_rwlock_t*) __nonnull((1)); -int pthread_rwlock_trywrlock(pthread_rwlock_t*) __nonnull((1)); -int pthread_rwlock_unlock(pthread_rwlock_t *) __nonnull((1)); -int pthread_rwlock_wrlock(pthread_rwlock_t*) __nonnull((1)); +int pthread_rwlock_destroy(pthread_rwlock_t* _Nonnull); +int pthread_rwlock_init(pthread_rwlock_t* _Nonnull, const pthread_rwlockattr_t*); +int pthread_rwlock_rdlock(pthread_rwlock_t* _Nonnull); +int pthread_rwlock_timedrdlock(pthread_rwlock_t* _Nonnull, const struct timespec* _Nonnull); +int pthread_rwlock_timedwrlock(pthread_rwlock_t* _Nonnull, const struct timespec* _Nonnull); +int pthread_rwlock_tryrdlock(pthread_rwlock_t* _Nonnull); +int pthread_rwlock_trywrlock(pthread_rwlock_t* _Nonnull); +int pthread_rwlock_unlock(pthread_rwlock_t* _Nonnull); +int pthread_rwlock_wrlock(pthread_rwlock_t* _Nonnull); -int pthread_barrierattr_init(pthread_barrierattr_t* attr) __nonnull((1)) __INTRODUCED_IN(24); -int pthread_barrierattr_destroy(pthread_barrierattr_t* attr) __nonnull((1)) __INTRODUCED_IN(24); -int pthread_barrierattr_getpshared(pthread_barrierattr_t* attr, int* pshared) __nonnull((1, 2)) +int pthread_barrierattr_init(pthread_barrierattr_t* _Nonnull attr) __INTRODUCED_IN(24); +int pthread_barrierattr_destroy(pthread_barrierattr_t* _Nonnull attr) __INTRODUCED_IN(24); +int pthread_barrierattr_getpshared(pthread_barrierattr_t* _Nonnull attr, int* _Nonnull pshared) __INTRODUCED_IN(24); -int pthread_barrierattr_setpshared(pthread_barrierattr_t* attr, int pshared) __nonnull((1)) +int pthread_barrierattr_setpshared(pthread_barrierattr_t* _Nonnull attr, int pshared) __INTRODUCED_IN(24); -int pthread_barrier_init(pthread_barrier_t*, const pthread_barrierattr_t*, unsigned) __nonnull((1)) +int pthread_barrier_init(pthread_barrier_t* _Nonnull, const pthread_barrierattr_t*, unsigned) __INTRODUCED_IN(24); -int pthread_barrier_destroy(pthread_barrier_t*) __nonnull((1)) __INTRODUCED_IN(24); -int pthread_barrier_wait(pthread_barrier_t*) __nonnull((1)) __INTRODUCED_IN(24); +int pthread_barrier_destroy(pthread_barrier_t* _Nonnull) __INTRODUCED_IN(24); +int pthread_barrier_wait(pthread_barrier_t* _Nonnull) __INTRODUCED_IN(24); -int pthread_spin_destroy(pthread_spinlock_t*) __nonnull((1)) __INTRODUCED_IN(24); -int pthread_spin_init(pthread_spinlock_t*, int) __nonnull((1)) __INTRODUCED_IN(24); -int pthread_spin_lock(pthread_spinlock_t*) __nonnull((1)) __INTRODUCED_IN(24); -int pthread_spin_trylock(pthread_spinlock_t*) __nonnull((1)) __INTRODUCED_IN(24); -int pthread_spin_unlock(pthread_spinlock_t*) __nonnull((1)) __INTRODUCED_IN(24); +int pthread_spin_destroy(pthread_spinlock_t* _Nonnull) __INTRODUCED_IN(24); +int pthread_spin_init(pthread_spinlock_t* _Nonnull, int) __INTRODUCED_IN(24); +int pthread_spin_lock(pthread_spinlock_t* _Nonnull) __INTRODUCED_IN(24); +int pthread_spin_trylock(pthread_spinlock_t* _Nonnull) __INTRODUCED_IN(24); +int pthread_spin_unlock(pthread_spinlock_t* _Nonnull) __INTRODUCED_IN(24); pthread_t pthread_self(void) __pure2; #if defined(__USE_GNU) -int pthread_getname_np(pthread_t, char*, size_t) __nonnull((2)) __INTRODUCED_IN_FUTURE; +int pthread_getname_np(pthread_t, char* _Nonnull, size_t) __INTRODUCED_IN_FUTURE; #endif /* TODO: this should be __USE_GNU too. */ -int pthread_setname_np(pthread_t, const char*) __nonnull((2)); +int pthread_setname_np(pthread_t, const char* _Nonnull); -int pthread_setschedparam(pthread_t, int, const struct sched_param*) __nonnull((3)); +int pthread_setschedparam(pthread_t, int, const struct sched_param* _Nonnull); int pthread_setspecific(pthread_key_t, const void*); diff --git a/libc/include/signal.h b/libc/include/signal.h index 4b5e4ac61..d9f43deb6 100644 --- a/libc/include/signal.h +++ b/libc/include/signal.h @@ -120,10 +120,10 @@ __BIONIC_LEGACY_INLINE int sigemptyset(sigset_t*); __BIONIC_LEGACY_INLINE int sigfillset(sigset_t*); __BIONIC_LEGACY_INLINE int sigismember(const sigset_t*, int); -extern int sigpending(sigset_t*) __nonnull((1)); +extern int sigpending(sigset_t* _Nonnull); extern int sigprocmask(int, const sigset_t*, sigset_t*); -extern int sigsuspend(const sigset_t*) __nonnull((1)); -extern int sigwait(const sigset_t*, int*) __nonnull((1, 2)); +extern int sigsuspend(const sigset_t* _Nonnull); +extern int sigwait(const sigset_t* _Nonnull, int* _Nonnull); extern int sighold(int) __attribute__((deprecated("use sigprocmask() or pthread_sigmask() instead"))) diff --git a/libc/include/string.h b/libc/include/string.h index 3f98af1ea..f39a86b4d 100644 --- a/libc/include/string.h +++ b/libc/include/string.h @@ -120,10 +120,10 @@ extern size_t strxfrm_l(char* __restrict, const char* __restrict, size_t, locale */ #if defined(__cplusplus) -extern "C++" char* basename(char*) __RENAME(__gnu_basename) __nonnull((1)); -extern "C++" const char* basename(const char*) __RENAME(__gnu_basename) __nonnull((1)); +extern "C++" char* basename(char* _Nonnull) __RENAME(__gnu_basename); +extern "C++" const char* basename(const char* _Nonnull) __RENAME(__gnu_basename); #else -extern char* basename(const char*) __RENAME(__gnu_basename) __nonnull((1)) __INTRODUCED_IN(23); +extern char* basename(const char* _Nonnull) __RENAME(__gnu_basename) __INTRODUCED_IN(23); #endif #endif diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h index 3fcf163bd..7b06967de 100644 --- a/libc/include/sys/cdefs.h +++ b/libc/include/sys/cdefs.h @@ -159,6 +159,38 @@ #define __nonnull(args) __attribute__((__nonnull__ args)) +/* + * _Nonnull is similar to the nonnull attribute in that it will instruct + * compilers to warn the user if it can prove that a null argument is being + * passed. Unlike the nonnull attribute, this annotation indicated that a value + * *should not* be null, not that it *cannot* be null, or even that the behavior + * is undefined. The important distinction is that the optimizer will perform + * surprising optimizations like the following: + * + * void foo(void*) __attribute__(nonnull, 1); + * + * int bar(int* p) { + * foo(p); + * + * // The following null check will be elided because nonnull attribute + * // means that, since we call foo with p, p can be assumed to not be + * // null. Thus this will crash if we are called with a null pointer. + * if (src != NULL) { + * return *p; + * } + * return 0; + * } + * + * int main() { + * return bar(NULL); + * } + * + * http://clang.llvm.org/docs/AttributeReference.html#nonnull + */ +#if !(defined(__clang__) && __has_feature(nullability)) +#define _Nonnull +#endif + #define __printflike(x, y) __attribute__((__format__(printf, x, y))) __nonnull((x)) #define __scanflike(x, y) __attribute__((__format__(scanf, x, y))) __nonnull((x)) diff --git a/libc/include/sys/signalfd.h b/libc/include/sys/signalfd.h index 5b678226f..084a5284c 100644 --- a/libc/include/sys/signalfd.h +++ b/libc/include/sys/signalfd.h @@ -35,7 +35,7 @@ __BEGIN_DECLS -extern int signalfd(int fd, const sigset_t* mask, int flags) __nonnull((2)) __INTRODUCED_IN(21); +extern int signalfd(int fd, const sigset_t* _Nonnull mask, int flags) __INTRODUCED_IN(21); __END_DECLS diff --git a/libc/include/sys/statvfs.h b/libc/include/sys/statvfs.h index e12f0698c..1f00b9d57 100644 --- a/libc/include/sys/statvfs.h +++ b/libc/include/sys/statvfs.h @@ -59,12 +59,12 @@ struct statvfs64 { __STATVFS64_BODY }; #define ST_NODIRATIME 0x0800 #define ST_RELATIME 0x1000 -extern int statvfs(const char* __restrict, struct statvfs* __restrict) __nonnull((1, 2)) +extern int statvfs(const char* __restrict _Nonnull, struct statvfs* __restrict _Nonnull) __INTRODUCED_IN(21); -extern int statvfs64(const char* __restrict, struct statvfs64* __restrict) __nonnull((1, 2)) +extern int statvfs64(const char* __restrict _Nonnull, struct statvfs64* __restrict _Nonnull) __INTRODUCED_IN(21); -extern int fstatvfs(int, struct statvfs*) __nonnull((2)) __INTRODUCED_IN(21); -extern int fstatvfs64(int, struct statvfs64*) __nonnull((2)) __INTRODUCED_IN(21); +extern int fstatvfs(int, struct statvfs* _Nonnull) __INTRODUCED_IN(21); +extern int fstatvfs64(int, struct statvfs64* _Nonnull) __INTRODUCED_IN(21); __END_DECLS diff --git a/libc/include/sys/swap.h b/libc/include/sys/swap.h index b1f929583..fe14a30fe 100644 --- a/libc/include/sys/swap.h +++ b/libc/include/sys/swap.h @@ -38,8 +38,8 @@ __BEGIN_DECLS #define SWAP_FLAG_PRIO_MASK 0x7fff #define SWAP_FLAG_PRIO_SHIFT 0 -extern int swapon(const char*, int) __nonnull((1)) __INTRODUCED_IN(21); -extern int swapoff(const char*) __nonnull((1)) __INTRODUCED_IN(21); +extern int swapon(const char* _Nonnull, int) __INTRODUCED_IN(21); +extern int swapoff(const char* _Nonnull) __INTRODUCED_IN(21); __END_DECLS diff --git a/libc/include/sys/vfs.h b/libc/include/sys/vfs.h index 9f04b2892..bf094dc7b 100644 --- a/libc/include/sys/vfs.h +++ b/libc/include/sys/vfs.h @@ -137,10 +137,10 @@ struct statfs64 { __STATFS64_BODY }; #define XENIX_SUPER_MAGIC 0x012FF7B4 #define XFS_SUPER_MAGIC 0x58465342 -extern int statfs(const char*, struct statfs*) __nonnull((1, 2)); -extern int statfs64(const char*, struct statfs64*) __nonnull((1, 2)) __INTRODUCED_IN(21); -extern int fstatfs(int, struct statfs*) __nonnull((2)); -extern int fstatfs64(int, struct statfs64*) __nonnull((2)) __INTRODUCED_IN(21); +extern int statfs(const char* _Nonnull, struct statfs* _Nonnull); +extern int statfs64(const char* _Nonnull, struct statfs64* _Nonnull) __INTRODUCED_IN(21); +extern int fstatfs(int, struct statfs* _Nonnull); +extern int fstatfs64(int, struct statfs64* _Nonnull) __INTRODUCED_IN(21); __END_DECLS diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp index d9b252375..52a3252f0 100755 --- a/tests/pthread_test.cpp +++ b/tests/pthread_test.cpp @@ -1780,7 +1780,14 @@ TEST(pthread, pthread_types_allow_four_bytes_alignment) { TEST(pthread, pthread_mutex_lock_null_32) { #if defined(__BIONIC__) && !defined(__LP64__) - ASSERT_EQ(EINVAL, pthread_mutex_lock(NULL)); + // For LP32, the pthread lock/unlock functions allow a NULL mutex and return + // EINVAL in that case: http://b/19995172. + // + // We decorate the public defintion with _Nonnull so that people recompiling + // their code with get a warning and might fix their bug, but need to pass + // NULL here to test that we remain compatible. + pthread_mutex_t* null_value = nullptr; + ASSERT_EQ(EINVAL, pthread_mutex_lock(null_value)); #else GTEST_LOG_(INFO) << "This test tests bionic implementation details on 32 bit devices."; #endif @@ -1788,7 +1795,14 @@ TEST(pthread, pthread_mutex_lock_null_32) { TEST(pthread, pthread_mutex_unlock_null_32) { #if defined(__BIONIC__) && !defined(__LP64__) - ASSERT_EQ(EINVAL, pthread_mutex_unlock(NULL)); + // For LP32, the pthread lock/unlock functions allow a NULL mutex and return + // EINVAL in that case: http://b/19995172. + // + // We decorate the public defintion with _Nonnull so that people recompiling + // their code with get a warning and might fix their bug, but need to pass + // NULL here to test that we remain compatible. + pthread_mutex_t* null_value = nullptr; + ASSERT_EQ(EINVAL, pthread_mutex_unlock(null_value)); #else GTEST_LOG_(INFO) << "This test tests bionic implementation details on 32 bit devices."; #endif