From 5f9fcfd314c203533a31d5fd79518810446de20d Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Fri, 24 Oct 2025 16:45:29 -0700 Subject: [PATCH] [clang][docs] assert.h is not a good candidate for a textual header The C standard behavior of `assert` cannot be accomplished with clang modules, either as a normal modular header, or a textual header. As a normal modular header: #define NDEBUG #include This pattern doesn't work, NDEBUG has to be passed on the command line to take effect, and then will effect all `assert`s in the includer. As a textual header: #define NDEBUG #include This pattern doesn't work for similar reasons, modular_header_that_has_an_assert.h captured the value of NDEBUG when its module built and won't pick it up from the includer. -DNDEBUG can be passed when building the module, but will similarly effect the entire module. This has the additional problem that every module will contain a declaration for `assert`, which can possibly conflict with each other if they use different values of NDEBUG. So really just doesn't work properly with clang modules. Avoid the issue by not mentioning it in the Modules documentation, and use "X macros" as the example for textual headers. Don't use [extern_c] in the example modules, that should very rarely be used. Don't put multiple `header` declarations in a submodule, that has the confusing effect of "fusing" the headers. e.g. does not include , but if it's in the same submodule, then an `#include ` will mysteriously also include . --- clang/docs/Modules.rst | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/clang/docs/Modules.rst b/clang/docs/Modules.rst index acbe45e0be970..e45ee9ff9eac2 100644 --- a/clang/docs/Modules.rst +++ b/clang/docs/Modules.rst @@ -421,13 +421,7 @@ As an example, the module map file for the C standard library might look a bit l .. parsed-literal:: - module std [system] [extern_c] { - module assert { - textual header "assert.h" - header "bits/assert-decls.h" - export * - } - + module std [system] { module complex { header "complex.h" export * @@ -440,7 +434,6 @@ As an example, the module map file for the C standard library might look a bit l module errno { header "errno.h" - header "sys/errno.h" export * } @@ -673,14 +666,14 @@ of checking *use-declaration*\s, and must still be a lexically-valid header file. In the future, we intend to pre-tokenize such headers and include the token sequence within the prebuilt module representation. -A header with the ``exclude`` specifier is excluded from the module. It will not be included when the module is built, nor will it be considered to be part of the module, even if an ``umbrella`` header or directory would otherwise make it part of the module. +A header with the ``exclude`` specifier is excluded from the module. It will not be included when the module is built, nor will it be considered to be part of the module, even if an ``umbrella`` directory would otherwise make it part of the module. -**Example:** The C header ``assert.h`` is an excellent candidate for a textual header, because it is meant to be included multiple times (possibly with different ``NDEBUG`` settings). However, declarations within it should typically be split into a separate modular header. +**Example:** A "X macro" header is an excellent candidate for a textual header, because it is can't be compiled standalone, and by itself does not contain any declarations. .. parsed-literal:: - module std [system] { - textual header "assert.h" + module MyLib [system] { + textual header "xmacros.h" } A given header shall not be referenced by more than one *header-declaration*.