Merge "Add C23 documentation." into main
diff --git a/docs/README.md b/docs/README.md
index 2825eac..d66fa68 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -17,6 +17,7 @@
   which detects use-after-close() bugs.
 * [fdtrack](fdtrack.md) - bionic's file descriptor tracker,
   which helps debug file descriptor leaks.
+* [C23](c23.md) - dealing with C23's breaking changes.
 
 ## Maintainer documentation
 
diff --git a/docs/c23.md b/docs/c23.md
new file mode 100644
index 0000000..9ed570d
--- /dev/null
+++ b/docs/c23.md
@@ -0,0 +1,97 @@
+# C23 language changes
+
+## Breaking changes
+
+### `void foo()` now means `void foo(void)`
+In C17 and earlier, `void foo()` means "I haven't yet told you how many
+arguments this function has". In C23, it's equivalent to C++ and means "this
+function has no arguments". This may surface as a function pointer type
+mismatch, because previously `()` matched functions taking any arguments,
+whereas in C23 it only matches functions taking no arguments.
+
+Fix: in cases where your function does have arguments, declare them.
+
+### Undeclared identifiers are now errors
+In C17 and earlier, calling `foo(123)` without a declaration for `foo()`
+produced a warning. In C23 this is an error instead. One common special case of
+this is code that's explicitly ignoring such warnings to call functions that are
+GNU extensions; such code should be fixed to ensure that `_GNU_SOURCE` is
+defined before any header is included instead (often by adding `-D_GNU_SOURCE`
+to the cflags in the build file).
+
+Fix: add the missing forward declaration or `#include` (or `-D_GNU_SOURCE`).
+
+### `bool`/`true`/`false` are now keywords
+In C17 and earlier, only code that included `<stdbool.h>` would have standard
+definitions for these (typically macros for `_Bool`/`1`/`0`). In C23 these are
+keywords and should no longer be defined in your code.
+
+Fix: delete any definitions of `bool`/`true`/`false` if you only need to build
+as C23, or switch to `#include <stdbool.h>` for compatibility back to C99.
+
+### `false` is no longer `0`
+In C17 and earlier, it was common for true and false to be defined as 1 and 0
+(either by `<stdbool.h>` or by user-provided `#define`/`enum`). This meant that
+`false` (as 0) could be implicitly converted to `NULL`. In C23, a function that
+returns (or takes) a pointer can no longer return `false` (or be passed
+`false`).
+
+Fix: return/pass `NULL` (or `nullptr` for C23-only code) instead of `false`
+in pointer contexts.
+
+### `unreachable()` is now a predefined function-like macro in `<stddef.h>`
+In C17 and earlier, `unreachable()` was available for your own macros/functions.
+In C23 there's a standard definition.
+
+Fix: delete your `unreachable()` if it was just equivalent to
+`__builtin_unreachable()` or rename it if it had different behavior.
+
+### K&R prototypes are no longer valid
+In C17 and earlier, K&R function prototypes were deprecated but still allowed.
+In C23 K&R prototypes are no longer allowed.
+
+Fix: rewrite any K&R prototypes as ANSI/ISO prototypes.
+
+
+## Non-breaking changes
+
+### Unused function parameters can now be anonymous
+In C17 and earlier you'd have to use `__attribute__((unused))` on an unused
+function parameter. In C23 you can just omit the parameter name instead,
+like `void* pthread_callback_fn(void*) {` (as in C++).
+
+### New standard attributes
+C23 adds `[[deprecated("reason")]]`, `[[fallthrough]]`, `[[nodiscard]]` (the
+equivalent of the clang attribute `warn_unused_result`),
+`[[maybe_unused]]` (the equivalent of the clang attribute `unused`),
+and `[[noreturn]]` (equivalent to C11 `_Noreturn`).
+Most of these have been available before via `__attribute__` or other syntax,
+but are now standard.
+
+### `#embed`
+You can now include binary data directly into an array or string: https://en.cppreference.com/w/c/preprocessor/embed
+
+### `void foo(...)` is now allowed
+In C17 and earlier, a varargs function needed a non-varargs argument.
+In C23 this is allowed (as in C++).
+
+### `enum` base types
+You can now say `enum E : long { ... }` to explicitly choose the base type of
+your enum (as in C++, and already supported by clang as an extension).
+
+### `nullptr` constant
+There is now a `nullptr` constant (as in C++),
+and a corresponding `nullptr_t` type for that constant.
+
+### `constexpr`
+There is now a limited form of `constexpr` for defining `const` variables
+(similar to, but much more limited than C++ constexpr).
+
+
+## Library changes
+
+Library changes are not covered here because bionic does not make library
+functionality available based on target C version, since the target API level
+distinctions are confusing enough already.
+
+See [status.md](status.md) for what functionality went into which API level.