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
This commit is contained in:
Dan Albert 2015-08-13 16:58:50 -07:00
parent 7ee8e299ba
commit baa2a973bd
11 changed files with 151 additions and 107 deletions

View file

@ -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;
}

View file

@ -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 */

View file

@ -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*);

View file

@ -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")))

View file

@ -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

View file

@ -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))

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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