Merge "Add some <sched.h> tests."
diff --git a/libc/include/bits/fortify/fcntl.h b/libc/include/bits/fortify/fcntl.h
index 1d3d7bc..3e0a590 100644
--- a/libc/include/bits/fortify/fcntl.h
+++ b/libc/include/bits/fortify/fcntl.h
@@ -48,11 +48,6 @@
 int open(const char* pathname, int flags, mode_t modes, ...) __overloadable
         __errorattr(__open_too_many_args_error);
 
-__BIONIC_ERROR_FUNCTION_VISIBILITY
-int open(const char* pathname, int flags) __overloadable
-        __enable_if(flags & O_CREAT, __open_too_few_args_error)
-        __errorattr(__open_too_few_args_error);
-
 /*
  * pass_object_size serves two purposes here, neither of which involve __bos: it
  * disqualifies this function from having its address taken (so &open works),
@@ -60,30 +55,27 @@
  * open(const char *, int, ...).
  */
 __BIONIC_FORTIFY_INLINE
-int open(const char* const __pass_object_size pathname,
-         int flags) __overloadable {
+int open(const char* const __pass_object_size pathname, int flags)
+        __overloadable
+        __clang_error_if(flags & O_CREAT, "'open' " __open_too_few_args_error) {
     return __open_2(pathname, flags);
 }
 
 __BIONIC_FORTIFY_INLINE
-int open(const char* const __pass_object_size pathname, int flags, mode_t modes)
-        __overloadable {
+int open(const char* const __pass_object_size pathname, int flags, mode_t modes) __overloadable {
     return __open_real(pathname, flags, modes);
 }
 
 __BIONIC_ERROR_FUNCTION_VISIBILITY
-int openat(int dirfd, const char* pathname, int flags) __overloadable
-        __enable_if(flags & O_CREAT, __open_too_few_args_error)
-        __errorattr(__open_too_few_args_error);
-
-__BIONIC_ERROR_FUNCTION_VISIBILITY
 int openat(int dirfd, const char* pathname, int flags, mode_t modes, ...)
         __overloadable
         __errorattr(__open_too_many_args_error);
 
 __BIONIC_FORTIFY_INLINE
 int openat(int dirfd, const char* const __pass_object_size pathname,
-           int flags) __overloadable {
+           int flags)
+        __overloadable
+        __clang_error_if(flags & O_CREAT, "'openat' " __open_too_few_args_error) {
     return __openat_2(dirfd, pathname, flags);
 }
 
diff --git a/libc/include/bits/fortify/poll.h b/libc/include/bits/fortify/poll.h
index e9b52c8..8363e35 100644
--- a/libc/include/bits/fortify/poll.h
+++ b/libc/include/bits/fortify/poll.h
@@ -37,42 +37,31 @@
 #if defined(__BIONIC_FORTIFY)
 #if __ANDROID_API__ >= __ANDROID_API_M__
 #if defined(__clang__)
-__BIONIC_ERROR_FUNCTION_VISIBILITY
-int poll(struct pollfd* fds, nfds_t fd_count, int timeout) __overloadable
-        __enable_if(__bos(fds) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
-                    __bos(fds) < sizeof(*fds) * fd_count,
-                    "selected when there aren't fd_count fds")
-        __errorattr("too many fds specified");
-
 __BIONIC_FORTIFY_INLINE
-int poll(struct pollfd* const fds __pass_object_size, nfds_t fd_count,
-        int timeout) __overloadable {
+int poll(struct pollfd* const fds __pass_object_size, nfds_t fd_count, int timeout)
+    __overloadable
+    __clang_error_if(__bos(fds) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+                       __bos(fds) < sizeof(*fds) * fd_count,
+                     "in call to 'poll', fd_count is larger than the given buffer") {
   size_t bos_fds = __bos(fds);
 
   if (bos_fds == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
-      return __call_bypassing_fortify(poll)(fds, fd_count, timeout);
+    return __call_bypassing_fortify(poll)(fds, fd_count, timeout);
   }
-
   return __poll_chk(fds, fd_count, timeout, bos_fds);
 }
 
-__BIONIC_ERROR_FUNCTION_VISIBILITY
-int ppoll(struct pollfd* fds, nfds_t fd_count, const struct timespec* timeout,
-          const sigset_t* mask)  __overloadable
-        __enable_if(__bos(fds) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
-                    __bos(fds) < sizeof(*fds) * fd_count,
-                    "selected when there aren't fd_count fds")
-        __errorattr("too many fds specified");
-
 __BIONIC_FORTIFY_INLINE
-int ppoll(struct pollfd* const fds __pass_object_size, nfds_t fd_count,
-          const struct timespec* timeout, const sigset_t* mask) __overloadable {
+int ppoll(struct pollfd* const fds __pass_object_size, nfds_t fd_count, const struct timespec* timeout, const sigset_t* mask)
+    __overloadable
+    __clang_error_if(__bos(fds) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+                       __bos(fds) < sizeof(*fds) * fd_count,
+                     "in call to 'ppoll', fd_count is larger than the given buffer") {
   size_t bos_fds = __bos(fds);
 
   if (bos_fds == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
-      return __call_bypassing_fortify(ppoll)(fds, fd_count, timeout, mask);
+    return __call_bypassing_fortify(ppoll)(fds, fd_count, timeout, mask);
   }
-
   return __ppoll_chk(fds, fd_count, timeout, mask, bos_fds);
 }
 #else /* defined(__clang__) */
diff --git a/libc/include/bits/fortify/socket.h b/libc/include/bits/fortify/socket.h
index c9e9436..3e610d6 100644
--- a/libc/include/bits/fortify/socket.h
+++ b/libc/include/bits/fortify/socket.h
@@ -37,64 +37,55 @@
 
 #if defined(__BIONIC_FORTIFY)
 
-#define __recvfrom_bad_size "recvfrom called with size bigger than buffer"
-#define __sendto_bad_size "sendto called with size bigger than buffer"
+#define __recvfrom_bad_size "'recvfrom' called with size bigger than buffer"
+#define __sendto_bad_size "'sendto' called with size bigger than buffer"
 #if defined(__clang__)
 #if __ANDROID_API__ >= __ANDROID_API_N__
-__BIONIC_ERROR_FUNCTION_VISIBILITY
-ssize_t recvfrom(int fd, void* const buf __pass_object_size0, size_t len,
-                 int flags, struct sockaddr* src_addr, socklen_t* addr_len)
-        __overloadable
-        __enable_if(__bos(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
-                    __bos(buf) < len, "selected when the buffer is too small")
-        __errorattr(__recvfrom_bad_size);
-
 __BIONIC_FORTIFY_INLINE
-ssize_t recvfrom(int fd, void* const buf __pass_object_size0, size_t len,
-                 int flags, struct sockaddr* src_addr, socklen_t* addr_len)
-      __overloadable {
+ssize_t recvfrom(int fd, void* const buf __pass_object_size0, size_t len, int flags, struct sockaddr* src_addr, socklen_t* addr_len)
+    __overloadable
+    __clang_error_if(__bos(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE && __bos(buf) < len,
+                     __recvfrom_bad_size) {
   size_t bos = __bos0(buf);
 
   if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
-    return __call_bypassing_fortify(recvfrom)(fd, buf, len, flags, src_addr,
-              addr_len);
+    return __call_bypassing_fortify(recvfrom)(fd, buf, len, flags, src_addr, addr_len);
   }
-
   return __recvfrom_chk(fd, buf, len, bos, flags, src_addr, addr_len);
 }
 #endif /* __ANDROID_API__ >= __ANDROID_API_N__ */
 
 #if __ANDROID_API__ >= __ANDROID_API_N_MR1__
-__BIONIC_ERROR_FUNCTION_VISIBILITY
-ssize_t sendto(int fd, const void* buf, size_t len, int flags,
-               const struct sockaddr* dest_addr, socklen_t addr_len)
-        __overloadable
-        __enable_if(__bos0(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
-                    __bos0(buf) < len, "selected when the buffer is too small")
-        __errorattr(__sendto_bad_size);
-
 __BIONIC_FORTIFY_INLINE
-ssize_t sendto(int fd, const void* const buf __pass_object_size0, size_t len,
-               int flags, const struct sockaddr* dest_addr, socklen_t addr_len)
-      __overloadable {
+ssize_t sendto(int fd, const void* const buf __pass_object_size0, size_t len, int flags, const struct sockaddr* dest_addr, socklen_t addr_len)
+    __overloadable
+    __clang_error_if(__bos0(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE && __bos0(buf) < len,
+                     __sendto_bad_size) {
   size_t bos = __bos0(buf);
 
   if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
-    return __call_bypassing_fortify(sendto)(fd, buf, len, flags, dest_addr,
-              addr_len);
+    return __call_bypassing_fortify(sendto)(fd, buf, len, flags, dest_addr, addr_len);
   }
-
   return __sendto_chk(fd, buf, len, bos, flags, dest_addr, addr_len);
 }
-
-__BIONIC_ERROR_FUNCTION_VISIBILITY
-ssize_t send(int socket, const void* buf, size_t len, int flags)
-        __overloadable
-        __enable_if(__bos0(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
-                    __bos0(buf) < len, "selected when the buffer is too small")
-        __errorattr("send called with size bigger than buffer");
 #endif /* __ANDROID_API__ >= __ANDROID_API_N_MR1__ */
 
+__BIONIC_FORTIFY_INLINE
+ssize_t recv(int socket, void* const buf __pass_object_size0, size_t len, int flags)
+    __overloadable
+    __clang_error_if(__bos0(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE && __bos0(buf) < len,
+                     "'recv' called with size bigger than buffer") {
+  return recvfrom(socket, buf, len, flags, NULL, 0);
+}
+
+__BIONIC_FORTIFY_INLINE
+ssize_t send(int socket, const void* const buf __pass_object_size0, size_t len, int flags)
+    __overloadable
+    __clang_error_if(__bos0(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE && __bos0(buf) < len,
+                     "'send' called with size bigger than buffer") {
+  return sendto(socket, buf, len, flags, NULL, 0);
+}
+
 #else /* defined(__clang__) */
 ssize_t __recvfrom_real(int, void*, size_t, int, struct sockaddr*, socklen_t*) __RENAME(recvfrom);
 __errordecl(__recvfrom_error, __recvfrom_bad_size);
@@ -147,20 +138,17 @@
 }
 #endif /* __ANDROID_API__ >= __ANDROID_API_N_MR1__ */
 
-#endif /* defined(__clang__) */
-#undef __recvfrom_bad_size
-#undef __sendto_bad_size
-
 __BIONIC_FORTIFY_INLINE
-ssize_t recv(int socket, void* const buf __pass_object_size0, size_t len,
-             int flags) __overloadable {
+ssize_t recv(int socket, void* buf, size_t len, int flags) {
   return recvfrom(socket, buf, len, flags, NULL, 0);
 }
 
 __BIONIC_FORTIFY_INLINE
-ssize_t send(int socket, const void* const buf __pass_object_size0, size_t len, int flags)
-        __overloadable {
+ssize_t send(int socket, const void* buf, size_t len, int flags) {
   return sendto(socket, buf, len, flags, NULL, 0);
 }
+#endif /* defined(__clang__) */
 
+#undef __recvfrom_bad_size
+#undef __sendto_bad_size
 #endif /* __BIONIC_FORTIFY */
diff --git a/libc/include/bits/fortify/stat.h b/libc/include/bits/fortify/stat.h
index d119e2c..c168c38 100644
--- a/libc/include/bits/fortify/stat.h
+++ b/libc/include/bits/fortify/stat.h
@@ -33,23 +33,17 @@
 mode_t __umask_chk(mode_t) __INTRODUCED_IN(18);
 
 #if defined(__BIONIC_FORTIFY)
-#define __umask_invalid_mode_str "umask called with invalid mode"
+#define __umask_invalid_mode_str "'umask' called with invalid mode"
 
 #if defined(__clang__)
 
 #if __ANDROID_API__ >= __ANDROID_API_J_MR2__
-/*
- * Abuse enable_if to make these be seen as overloads of umask, rather than
- * definitions.
- */
-__BIONIC_ERROR_FUNCTION_VISIBILITY
-mode_t umask(mode_t mode) __overloadable
-        __enable_if(1, "")
-        __enable_if(mode & ~0777, __umask_invalid_mode_str)
-        __errorattr(__umask_invalid_mode_str);
-
+/* Abuse enable_if to make this an overload of umask. */
 __BIONIC_FORTIFY_INLINE
-mode_t umask(mode_t mode) __enable_if(1, "") __overloadable {
+mode_t umask(mode_t mode)
+    __overloadable
+    __enable_if(1, "")
+    __clang_error_if(mode & ~0777, __umask_invalid_mode_str) {
   return __umask_chk(mode);
 }
 #endif /* __ANDROID_API__ >= __ANDROID_API_J_MR2__ */
diff --git a/libc/include/bits/fortify/stdio.h b/libc/include/bits/fortify/stdio.h
index 4acefd7..cfc78d7 100644
--- a/libc/include/bits/fortify/stdio.h
+++ b/libc/include/bits/fortify/stdio.h
@@ -38,13 +38,13 @@
 
 #if __ANDROID_API__ >= __ANDROID_API_J_MR1__
 __BIONIC_FORTIFY_INLINE __printflike(3, 0)
-int vsnprintf(char *const __pass_object_size dest, size_t size,
-              const char * format, va_list ap) __overloadable {
+int vsnprintf(char* const __pass_object_size dest, size_t size, const char* format, va_list ap)
+        __overloadable {
     return __builtin___vsnprintf_chk(dest, size, 0, __bos(dest), format, ap);
 }
 
 __BIONIC_FORTIFY_INLINE __printflike(2, 0)
-int vsprintf(char *const __pass_object_size dest, const char* format, va_list ap) __overloadable {
+int vsprintf(char* const __pass_object_size dest, const char* format, va_list ap) __overloadable {
     return __builtin___vsprintf_chk(dest, 0, __bos(dest), format, ap);
 }
 #endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
@@ -59,14 +59,14 @@
 int snprintf(char* dest, size_t size, const char* format)
     __overloadable
     __enable_if(__bos(dest) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
-                __bos(dest) < __builtin_strlen(format),
+                    __bos(dest) < __builtin_strlen(format),
                 "format string will always overflow destination buffer")
     __errorattr("format string will always overflow destination buffer");
 
 __BIONIC_FORTIFY_INLINE
 __printflike(3, 4)
-int snprintf(char* const __pass_object_size dest,
-             size_t size, const char* format, ...) __overloadable {
+int snprintf(char* const __pass_object_size dest, size_t size, const char* format, ...)
+        __overloadable {
     va_list va;
     va_start(va, format);
     int result = __builtin___vsnprintf_chk(dest, size, 0, __bos(dest), format, va);
@@ -75,7 +75,8 @@
 }
 
 __BIONIC_ERROR_FUNCTION_VISIBILITY
-int sprintf(char* dest, const char* format) __overloadable
+int sprintf(char* dest, const char* format)
+    __overloadable
     __enable_if(__bos(dest) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
                 __bos(dest) < __builtin_strlen(format),
                 "format string will always overflow destination buffer")
@@ -94,44 +95,27 @@
 
 #if __ANDROID_API__ >= __ANDROID_API_N__
 __BIONIC_FORTIFY_INLINE
-size_t fread(void* buf, size_t size, size_t count,
-             FILE* stream) __overloadable
-        __enable_if(__unsafe_check_mul_overflow(size, count), "size * count overflows")
-        __errorattr("size * count overflows");
-
-__BIONIC_FORTIFY_INLINE
-size_t fread(void* buf, size_t size, size_t count, FILE* stream) __overloadable
-    __enable_if(!__unsafe_check_mul_overflow(size, count), "no overflow")
-    __enable_if(__bos(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
-                size * count > __bos(buf), "size * count is too large")
-    __errorattr("size * count is too large");
-
-__BIONIC_FORTIFY_INLINE
-size_t fread(void* const __pass_object_size0 buf, size_t size,
-             size_t count, FILE* stream) __overloadable {
+size_t fread(void* const __pass_object_size0 buf, size_t size, size_t count, FILE* stream)
+        __overloadable
+        __clang_error_if(__unsafe_check_mul_overflow(size, count),
+                         "in call to 'fread', size * count overflows")
+        __clang_error_if(__bos(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE && size * count > __bos(buf),
+                         "in call to 'fread', size * count is too large for the given buffer") {
     size_t bos = __bos0(buf);
 
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
         return __call_bypassing_fortify(fread)(buf, size, count, stream);
     }
-
     return __fread_chk(buf, size, count, stream, bos);
 }
 
-size_t fwrite(const void* buf, size_t size, size_t count, FILE* stream) __overloadable
-    __enable_if(__unsafe_check_mul_overflow(size, count),
-                "size * count overflows")
-    __errorattr("size * count overflows");
-
-size_t fwrite(const void* buf, size_t size, size_t count, FILE* stream) __overloadable
-    __enable_if(!__unsafe_check_mul_overflow(size, count), "no overflow")
-    __enable_if(__bos(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
-                size * count > __bos(buf), "size * count is too large")
-    __errorattr("size * count is too large");
-
 __BIONIC_FORTIFY_INLINE
 size_t fwrite(const void* const __pass_object_size0 buf, size_t size, size_t count, FILE* stream)
-        __overloadable {
+        __overloadable
+        __clang_error_if(__unsafe_check_mul_overflow(size, count),
+                         "in call to 'fwrite', size * count overflows")
+        __clang_error_if(__bos(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE && size * count > __bos(buf),
+                         "in call to 'fwrite', size * count is too large for the given buffer") {
     size_t bos = __bos0(buf);
 
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
@@ -143,19 +127,12 @@
 #endif /* __ANDROID_API__ >= __ANDROID_API_N__ */
 
 #if __ANDROID_API__ >= __ANDROID_API_J_MR1__
-__BIONIC_ERROR_FUNCTION_VISIBILITY
-char *fgets(char* dest, int size, FILE* stream) __overloadable
-    __enable_if(size < 0, "size is negative")
-    __errorattr("size is negative");
-
-__BIONIC_ERROR_FUNCTION_VISIBILITY
-char *fgets(char* dest, int size, FILE* stream) __overloadable
-    __enable_if(size >= 0 && size > __bos(dest),
-                "size is larger than the destination buffer")
-    __errorattr("size is larger than the destination buffer");
-
 __BIONIC_FORTIFY_INLINE
-char *fgets(char* const __pass_object_size dest, int size, FILE* stream) __overloadable {
+char* fgets(char* const __pass_object_size dest, int size, FILE* stream)
+        __overloadable
+        __clang_error_if(size < 0, "in call to 'fgets', size should not be negative")
+        __clang_error_if(size > __bos(dest),
+                         "in call to 'fgets', size is larger than the destination buffer") {
     size_t bos = __bos(dest);
 
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
diff --git a/libc/include/bits/fortify/stdlib.h b/libc/include/bits/fortify/stdlib.h
index bda1d45..cf4b7ea 100644
--- a/libc/include/bits/fortify/stdlib.h
+++ b/libc/include/bits/fortify/stdlib.h
@@ -32,22 +32,16 @@
 
 #if defined(__BIONIC_FORTIFY)
 #define __realpath_buf_too_small_str \
-    "realpath output parameter must be NULL or a >= PATH_MAX bytes buffer"
+    "'realpath' output parameter must be NULL or a pointer to a buffer with >= PATH_MAX bytes"
 
 /* PATH_MAX is unavailable without polluting the namespace, but it's always 4096 on Linux */
 #define __PATH_MAX 4096
 
 #if defined(__clang__)
-
-__BIONIC_ERROR_FUNCTION_VISIBILITY
-char* realpath(const char* path, char* resolved) __overloadable
-    __enable_if(__bos(resolved) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
-                __bos(resolved) < __PATH_MAX, __realpath_buf_too_small_str)
-    __errorattr(__realpath_buf_too_small_str);
-
-/* No need for a FORTIFY version; the only things we can catch are at
- * compile-time.
- */
+char* realpath(const char* path, char* resolved)
+        __clang_error_if(__bos(resolved) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+                         __bos(resolved) < __PATH_MAX, __realpath_buf_too_small_str);
+/* No need for a definition; the only issues we can catch are at compile-time. */
 
 #else /* defined(__clang__) */
 
diff --git a/libc/include/stdio_ext.h b/libc/include/stdio_ext.h
index fdf6772..3c5abc3 100644
--- a/libc/include/stdio_ext.h
+++ b/libc/include/stdio_ext.h
@@ -40,7 +40,9 @@
 
 size_t __fbufsize(FILE*) __INTRODUCED_IN(23);
 int __freadable(FILE*) __INTRODUCED_IN(23);
+int __freading(FILE*) __INTRODUCED_IN_FUTURE;
 int __fwritable(FILE*) __INTRODUCED_IN(23);
+int __fwriting(FILE*) __INTRODUCED_IN_FUTURE;
 int __flbf(FILE*) __INTRODUCED_IN(23);
 void __fpurge(FILE*) __INTRODUCED_IN(23);
 size_t __fpending(FILE*) __INTRODUCED_IN(23);
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 55e0fa2..13c9d37 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -83,8 +83,7 @@
 long atol(const char*) __attribute_pure__;
 long long atoll(const char*) __attribute_pure__;
 
-char * realpath(const char *path, char *resolved) __overloadable
-        __RENAME_CLANG(realpath);
+char* realpath(const char* path, char* resolved);
 int system(const char *string);
 
 void* bsearch(const void* key, const void* base0, size_t nmemb, size_t size,
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index d79e36b..06856c8 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1320,6 +1320,8 @@
 
 LIBC_P {
   global:
+    __freading; # future
+    __fwriting; # future
     getlogin_r; # future
 } LIBC_O;
 
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index ed1e82c..50e4390 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1240,6 +1240,8 @@
 
 LIBC_P {
   global:
+    __freading; # future
+    __fwriting; # future
     getlogin_r; # future
 } LIBC_O;
 
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index af8e550..3e4d36e 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1345,6 +1345,8 @@
 
 LIBC_P {
   global:
+    __freading; # future
+    __fwriting; # future
     getlogin_r; # future
 } LIBC_O;
 
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index 90a65e0..3fa7c9d 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1304,6 +1304,8 @@
 
 LIBC_P {
   global:
+    __freading; # future
+    __fwriting; # future
     getlogin_r; # future
 } LIBC_O;
 
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index ed1e82c..50e4390 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1240,6 +1240,8 @@
 
 LIBC_P {
   global:
+    __freading; # future
+    __fwriting; # future
     getlogin_r; # future
 } LIBC_O;
 
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index 8217562..bd74fbe 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1302,6 +1302,8 @@
 
 LIBC_P {
   global:
+    __freading; # future
+    __fwriting; # future
     getlogin_r; # future
 } LIBC_O;
 
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index ed1e82c..50e4390 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1240,6 +1240,8 @@
 
 LIBC_P {
   global:
+    __freading; # future
+    __fwriting; # future
     getlogin_r; # future
 } LIBC_O;
 
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
index 6fb2c0d..bf6a8f8 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -127,10 +127,11 @@
 // Values for `__sFILE::_flags`.
 #define __SLBF 0x0001  // Line buffered.
 #define __SNBF 0x0002  // Unbuffered.
-// RD and WR are never simultaneously asserted: use _SRW instead.
-#define __SRD  0x0004  // OK to read.
-#define __SWR  0x0008  // OK to write.
-#define __SRW  0x0010  // Open for reading & writing.
+// __SRD and __SWR are mutually exclusive because they indicate what we did last.
+// If you want to know whether we were opened read-write, check __SRW instead.
+#define __SRD  0x0004  // Last operation was read.
+#define __SWR  0x0008  // Last operation was write.
+#define __SRW  0x0010  // Was opened for reading & writing.
 #define __SEOF 0x0020  // Found EOF.
 #define __SERR 0x0040  // Found error.
 #define __SMBF 0x0080  // `_buf` is from malloc.
diff --git a/libc/stdio/stdio_ext.cpp b/libc/stdio/stdio_ext.cpp
index ebc705c..8cf4f4b 100644
--- a/libc/stdio/stdio_ext.cpp
+++ b/libc/stdio/stdio_ext.cpp
@@ -39,17 +39,13 @@
   return fp->_bf._size;
 }
 
-/* For a _SRW stream, we don't know whether we last read or wrote.
 int __freading(FILE* fp) {
-  return (fp->_flags & _SRD) != 0 || ...;
+  return (fp->_flags & __SRD) != 0;
 }
-*/
 
-/* For a _SRW stream, we don't know whether we last read or wrote.
-int __fwriting(FILE*) {
-  return (fp->_flags & _SWR) != 0 || ...;
+int __fwriting(FILE* fp) {
+  return (fp->_flags & __SWR) != 0;
 }
-*/
 
 int __freadable(FILE* fp) {
   return (fp->_flags & (__SRD|__SRW)) != 0;
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/realpath.c b/libc/upstream-freebsd/lib/libc/stdlib/realpath.c
index 914ecc9..c4bd953 100644
--- a/libc/upstream-freebsd/lib/libc/stdlib/realpath.c
+++ b/libc/upstream-freebsd/lib/libc/stdlib/realpath.c
@@ -48,7 +48,7 @@
  * in which case the path which caused trouble is left in (resolved).
  */
 char *
-realpath(const char * __restrict path, char * __restrict resolved) __overloadable
+realpath(const char * __restrict path, char * __restrict resolved)
 {
 	struct stat sb;
 	char *p, *q, *s;
diff --git a/tests/fortify_compilation_test.cpp b/tests/fortify_compilation_test.cpp
index bb2b770..bf577f6 100644
--- a/tests/fortify_compilation_test.cpp
+++ b/tests/fortify_compilation_test.cpp
@@ -169,12 +169,12 @@
 
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__fgets_too_small_error' declared with attribute error: fgets called with size less than zero
-  // CLANG: error: call to unavailable function 'fgets': size is negative
+  // CLANG: error: in call to 'fgets', size should not be negative
   fgets(buf, -1, stdin);
 
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__fgets_too_big_error' declared with attribute error: fgets called with size bigger than buffer
-  // CLANG: error: call to unavailable function 'fgets': size is larger than the destination buffer
+  // CLANG: error: in call to 'fgets', size is larger than the destination buffer
   fgets(buf, 6, stdin);
 }
 
@@ -183,15 +183,24 @@
   sockaddr_in addr;
 
   // NOLINTNEXTLINE(whitespace/line_length)
-  // GCC: error: call to '__recvfrom_error' declared with attribute error: recvfrom called with size bigger than buffer
-  // CLANG: error: call to unavailable function 'recvfrom': recvfrom called with size bigger than buffer
+  // GCC: error: call to '__recvfrom_error' declared with attribute error: 'recvfrom' called with size bigger than buffer
+  // CLANG: error: 'recvfrom' called with size bigger than buffer
   recvfrom(0, buf, 6, 0, reinterpret_cast<sockaddr*>(&addr), NULL);
 }
 
+void test_recv() {
+  char buf[4] = {0};
+
+  // NOLINTNEXTLINE(whitespace/line_length)
+  // GCC: error: call to '__recvfrom_error' declared with attribute error: 'recvfrom' called with size bigger than buffer
+  // CLANG: error: 'recv' called with size bigger than buffer
+  recv(0, buf, 6, 0);
+}
+
 void test_umask() {
   // NOLINTNEXTLINE(whitespace/line_length)
-  // GCC: error: call to '__umask_invalid_mode' declared with attribute error: umask called with invalid mode
-  // CLANG: error: call to unavailable function 'umask': umask called with invalid mode
+  // GCC: error: call to '__umask_invalid_mode' declared with attribute error: 'umask' called with invalid mode
+  // CLANG: error: 'umask' called with invalid mode
   umask(01777);
 }
 
@@ -206,7 +215,7 @@
 void test_open() {
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__creat_missing_mode' declared with attribute error: called with O_CREAT, but missing mode
-  // CLANG: error: call to unavailable function 'open': called with O_CREAT, but missing mode
+  // CLANG: error: 'open' called with O_CREAT, but missing mode
   open("/dev/null", O_CREAT);
 
   // NOLINTNEXTLINE(whitespace/line_length)
@@ -219,7 +228,7 @@
   pollfd fds[1];
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__poll_too_small_error' declared with attribute error: poll: pollfd array smaller than fd count
-  // CLANG: error: call to unavailable function 'poll': too many fds specified
+  // CLANG: error: in call to 'poll', fd_count is larger than the given buffer
   poll(fds, 2, 0);
 }
 
@@ -228,7 +237,7 @@
   timespec timeout;
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__ppoll_too_small_error' declared with attribute error: ppoll: pollfd array smaller than fd count
-  // CLANG: error: call to unavailable function 'ppoll': too many fds specified
+  // CLANG: error: in call to 'ppoll', fd_count is larger than the given buffer
   ppoll(fds, 2, &timeout, NULL);
 }
 
@@ -236,7 +245,7 @@
   char buf[4];
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__fread_overflow' declared with attribute error: fread called with overflowing size * count
-  // CLANG: error: call to unavailable function 'fread': size * count overflows
+  // CLANG: error: in call to 'fread', size * count overflows
   fread(buf, 2, (size_t)-1, stdin);
 }
 
@@ -244,7 +253,8 @@
   char buf[4];
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__fread_too_big_error' declared with attribute error: fread called with size * count bigger than buffer
-  // CLANG: error: call to unavailable function 'fread': size * count is too large
+  // NOLINTNEXTLINE(whitespace/line_length)
+  // CLANG: error: in call to 'fread', size * count is too large for the given buffer
   fread(buf, 1, 5, stdin);
 }
 
@@ -252,7 +262,7 @@
   char buf[4] = {0};
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__fwrite_overflow' declared with attribute error: fwrite called with overflowing size * count
-  // CLANG: error: call to unavailable function 'fwrite': size * count overflows
+  // CLANG: error: in call to 'fwrite', size * count overflows
   fwrite(buf, 2, (size_t)-1, stdout);
 }
 
@@ -260,7 +270,8 @@
   char buf[4] = {0};
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__fwrite_too_big_error' declared with attribute error: fwrite called with size * count bigger than buffer
-  // CLANG: error: call to unavailable function 'fwrite': size * count is too large
+  // NOLINTNEXTLINE(whitespace/line_length)
+  // CLANG: error: in call to 'fwrite', size * count is too large for the given buffer
   fwrite(buf, 1, 5, stdout);
 }
 
@@ -316,8 +327,8 @@
   sockaddr_in addr;
 
   // NOLINTNEXTLINE(whitespace/line_length)
-  // GCC: error: call to '__sendto_error' declared with attribute error: sendto called with size bigger than buffer
-  // CLANG: error: call to unavailable function 'sendto': sendto called with size bigger than buffer
+  // GCC: error: call to '__sendto_error' declared with attribute error: 'sendto' called with size bigger than buffer
+  // CLANG: error: 'sendto' called with size bigger than buffer
   sendto(0, buf, 6, 0, reinterpret_cast<sockaddr*>(&addr), sizeof(sockaddr_in));
 }
 
@@ -325,7 +336,22 @@
   char buf[4] = {0};
 
   // NOLINTNEXTLINE(whitespace/line_length)
-  // GCC: error: call to '__sendto_error' declared with attribute error: sendto called with size bigger than buffer
-  // CLANG: error: call to unavailable function 'send': send called with size bigger than buffer
+  // GCC: error: call to '__sendto_error' declared with attribute error: 'sendto' called with size bigger than buffer
+  // CLANG: error: 'send' called with size bigger than buffer
   send(0, buf, 6, 0);
 }
+
+void test_realpath() {
+  char buf[4] = {0};
+  // NOLINTNEXTLINE(whitespace/line_length)
+  // GCC: error: call to '__realpath_size_error' declared with attribute error: 'realpath' output parameter must be NULL or a pointer to a buffer with >= PATH_MAX bytes
+  // NOLINTNEXTLINE(whitespace/line_length)
+  // CLANG: error: 'realpath' output parameter must be NULL or a pointer to a buffer with >= PATH_MAX bytes
+  realpath(".", buf);
+
+  // This is fine.
+  realpath(".", NULL);
+
+  // FIXME: But we should warn on this.
+  realpath(NULL, buf);
+}
diff --git a/tests/stdio_ext_test.cpp b/tests/stdio_ext_test.cpp
index 7872567..128e255 100644
--- a/tests/stdio_ext_test.cpp
+++ b/tests/stdio_ext_test.cpp
@@ -116,20 +116,78 @@
 }
 
 TEST(stdio_ext, __freadable__fwritable) {
-  FILE* fp = fopen("/dev/null", "r");
+  FILE* fp;
+
+  // Read-only.
+  fp = fopen("/dev/null", "r");
   ASSERT_TRUE(__freadable(fp));
   ASSERT_FALSE(__fwritable(fp));
   fclose(fp);
 
+  // Write-only.
   fp = fopen("/dev/null", "w");
   ASSERT_FALSE(__freadable(fp));
   ASSERT_TRUE(__fwritable(fp));
   fclose(fp);
 
-  fp = fopen("/dev/null", "w+");
-  ASSERT_TRUE(__freadable(fp));
+  // Append (aka write-only).
+  fp = fopen("/dev/null", "a");
+  ASSERT_FALSE(__freadable(fp));
   ASSERT_TRUE(__fwritable(fp));
   fclose(fp);
+
+  // The three read-write modes.
+  for (auto read_write_mode : {"r+", "w+", "a+"}) {
+    fp = fopen("/dev/null", read_write_mode);
+    ASSERT_TRUE(__freadable(fp));
+    ASSERT_TRUE(__fwritable(fp));
+    fclose(fp);
+  }
+}
+
+TEST(stdio_ext, __freading__fwriting) {
+  FILE* fp;
+
+  // Append (aka write-only). Never reading. Always writing.
+  fp = fopen("/dev/zero", "a");
+  ASSERT_FALSE(__freading(fp)); // Not reading initially.
+  ASSERT_TRUE(__fwriting(fp)); // Writing initially.
+  ASSERT_TRUE(fputc('x', fp) != EOF);
+  ASSERT_FALSE(__freading(fp)); // Not reading after write.
+  ASSERT_TRUE(__fwriting(fp)); // Still writing after write.
+  fclose(fp);
+
+  // Write-only. Never reading. Always writing.
+  fp = fopen("/dev/zero", "w");
+  ASSERT_FALSE(__freading(fp)); // Not reading initially.
+  ASSERT_TRUE(__fwriting(fp)); // Writing initially.
+  ASSERT_TRUE(fputc('x', fp) != EOF);
+  ASSERT_FALSE(__freading(fp)); // Not reading after write.
+  ASSERT_TRUE(__fwriting(fp)); // Still writing after write.
+  fclose(fp);
+
+  // Read-only. Always reading. Never writing.
+  fp = fopen("/dev/zero", "r");
+  ASSERT_TRUE(__freading(fp)); // Reading initially.
+  ASSERT_FALSE(__fwriting(fp)); // Not writing initially.
+  ASSERT_TRUE(fgetc(fp) == 0);
+  ASSERT_TRUE(__freading(fp)); // Still reading after read.
+  ASSERT_FALSE(__fwriting(fp)); // Still not writing after read.
+  fclose(fp);
+
+  // The three read-write modes.
+  for (auto read_write_mode : {"r+", "w+", "a+"}) {
+    fp = fopen("/dev/zero", read_write_mode);
+    ASSERT_FALSE(__freading(fp)); // Not reading initially.
+    ASSERT_FALSE(__fwriting(fp)); // Not writing initially.
+    ASSERT_TRUE(fgetc(fp) == 0);
+    ASSERT_TRUE(__freading(fp)); // Reading after read.
+    ASSERT_FALSE(__fwriting(fp)); // Not writing after read.
+    ASSERT_TRUE(fputc('x', fp) != EOF);
+    ASSERT_FALSE(__freading(fp)); // Not reading after write.
+    ASSERT_TRUE(__fwriting(fp)); // Writing after write.
+    fclose(fp);
+  }
 }
 
 TEST(stdio_ext, __fsetlocking) {