[llvm-branch-commits] [clang] [docs] Finish MyST migration for selected clang docs (PR #206182)
Reid Kleckner via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Jun 26 13:59:48 PDT 2026
https://github.com/rnk created https://github.com/llvm/llvm-project/pull/206182
This stacked PR contains the rst2myst conversion and follow-up MyST cleanup for the 20 clang docs renamed in #206181.
The `after` links are intended to be served from the combined staging branch `users/rnk/markdown-docs` after the llvmdocs staging container is refreshed.
<!-- clang-md-html-links:start -->
| Source file | Before HTML | After HTML |
| --- | --- | --- |
| `clang/docs/AddressSanitizer.md` | [before](https://clang.llvm.org/docs/AddressSanitizer.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/AddressSanitizer.html) |
| `clang/docs/ClangStaticAnalyzer.md` | [before](https://clang.llvm.org/docs/ClangStaticAnalyzer.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/ClangStaticAnalyzer.html) |
| `clang/docs/CrossCompilation.md` | [before](https://clang.llvm.org/docs/CrossCompilation.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/CrossCompilation.html) |
| `clang/docs/DataFlowSanitizer.md` | [before](https://clang.llvm.org/docs/DataFlowSanitizer.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/DataFlowSanitizer.html) |
| `clang/docs/FunctionEffectAnalysis.md` | [before](https://clang.llvm.org/docs/FunctionEffectAnalysis.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/FunctionEffectAnalysis.html) |
| `clang/docs/LanguageExtensions.md` | [before](https://clang.llvm.org/docs/LanguageExtensions.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/LanguageExtensions.html) |
| `clang/docs/LeakSanitizer.md` | [before](https://clang.llvm.org/docs/LeakSanitizer.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/LeakSanitizer.html) |
| `clang/docs/LifetimeSafety.md` | [before](https://clang.llvm.org/docs/LifetimeSafety.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/LifetimeSafety.html) |
| `clang/docs/MemorySanitizer.md` | [before](https://clang.llvm.org/docs/MemorySanitizer.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/MemorySanitizer.html) |
| `clang/docs/RealtimeSanitizer.md` | [before](https://clang.llvm.org/docs/RealtimeSanitizer.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/RealtimeSanitizer.html) |
| `clang/docs/ReleaseNotes.md` | [before](https://clang.llvm.org/docs/ReleaseNotes.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/ReleaseNotes.html) |
| `clang/docs/SafeBuffers.md` | [before](https://clang.llvm.org/docs/SafeBuffers.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/SafeBuffers.html) |
| `clang/docs/SanitizerCoverage.md` | [before](https://clang.llvm.org/docs/SanitizerCoverage.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/SanitizerCoverage.html) |
| `clang/docs/ScalableStaticAnalysis/index.md` | [before](https://clang.llvm.org/docs/ScalableStaticAnalysis/index.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/ScalableStaticAnalysis/index.html) |
| `clang/docs/ThreadSafetyAnalysis.md` | [before](https://clang.llvm.org/docs/ThreadSafetyAnalysis.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/ThreadSafetyAnalysis.html) |
| `clang/docs/ThreadSanitizer.md` | [before](https://clang.llvm.org/docs/ThreadSanitizer.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/ThreadSanitizer.html) |
| `clang/docs/Toolchain.md` | [before](https://clang.llvm.org/docs/Toolchain.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/Toolchain.html) |
| `clang/docs/TypeSanitizer.md` | [before](https://clang.llvm.org/docs/TypeSanitizer.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/TypeSanitizer.html) |
| `clang/docs/UndefinedBehaviorSanitizer.md` | [before](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/UndefinedBehaviorSanitizer.html) |
| `clang/docs/WarningSuppressionMappings.md` | [before](https://clang.llvm.org/docs/WarningSuppressionMappings.html) | [after](https://llvmdocs.staging.reidkleckner.dev/clang/docs/WarningSuppressionMappings.html) |
<!-- clang-md-html-links:end -->
>From 37ddcda408b552c860832e2b4647ad1e7dffc5a3 Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Thu, 25 Jun 2026 21:39:53 +0000
Subject: [PATCH 1/2] [docs] Convert selected rst docs with rst2myst
---
clang/docs/AddressSanitizer.md | 501 +-
clang/docs/ClangStaticAnalyzer.md | 23 +-
clang/docs/CrossCompilation.md | 108 +-
clang/docs/DataFlowSanitizer.md | 426 +-
clang/docs/FunctionEffectAnalysis.md | 628 +-
clang/docs/LanguageExtensions.md | 8411 ++++++++++----------
clang/docs/LeakSanitizer.md | 77 +-
clang/docs/LifetimeSafety.md | 613 +-
clang/docs/MemorySanitizer.md | 330 +-
clang/docs/RealtimeSanitizer.md | 379 +-
clang/docs/ReleaseNotes.md | 1204 ++-
clang/docs/SafeBuffers.md | 534 +-
clang/docs/SanitizerCoverage.md | 837 +-
clang/docs/ScalableStaticAnalysis/index.md | 25 +-
clang/docs/ThreadSafetyAnalysis.md | 1616 ++--
clang/docs/ThreadSanitizer.md | 326 +-
clang/docs/Toolchain.md | 280 +-
clang/docs/TypeSanitizer.md | 265 +-
clang/docs/UndefinedBehaviorSanitizer.md | 692 +-
clang/docs/WarningSuppressionMappings.md | 101 +-
20 files changed, 8290 insertions(+), 9086 deletions(-)
diff --git a/clang/docs/AddressSanitizer.md b/clang/docs/AddressSanitizer.md
index 80b1cdd95d77a..837c4a1f4ec38 100644
--- a/clang/docs/AddressSanitizer.md
+++ b/clang/docs/AddressSanitizer.md
@@ -1,200 +1,189 @@
-================
-AddressSanitizer
-================
+# AddressSanitizer
-.. contents::
- :local:
+```{contents}
+:local: true
+```
-Introduction
-============
+## Introduction
AddressSanitizer is a fast memory error detector. It consists of a compiler
instrumentation module and a run-time library. The tool can detect the
following types of bugs:
-* Out-of-bounds accesses to heap, stack and globals
-* Use-after-free
-* Use-after-return (clang flag ``-fsanitize-address-use-after-return=(never|runtime|always)`` default: ``runtime``)
- * Enable with: ``ASAN_OPTIONS=detect_stack_use_after_return=1`` (already enabled on Linux).
- * Disable with: ``ASAN_OPTIONS=detect_stack_use_after_return=0``.
-* Use-after-scope (clang flag ``-fsanitize-address-use-after-scope``)
-* Double-free, invalid free
-* Memory leaks (experimental)
+- Out-of-bounds accesses to heap, stack and globals
+- Use-after-free
+- Use-after-return (clang flag `-fsanitize-address-use-after-return=(never|runtime|always)` default: `runtime`)
+ : - Enable with: `ASAN_OPTIONS=detect_stack_use_after_return=1` (already enabled on Linux).
+ - Disable with: `ASAN_OPTIONS=detect_stack_use_after_return=0`.
+- Use-after-scope (clang flag `-fsanitize-address-use-after-scope`)
+- Double-free, invalid free
+- Memory leaks (experimental)
Typical slowdown introduced by AddressSanitizer is **2x**.
-How to build
-============
+## How to build
-Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>`_ and enable
-the ``compiler-rt`` runtime. An example CMake configuration that will allow
+Build LLVM/Clang with [CMake](https://llvm.org/docs/CMake.html) and enable
+the `compiler-rt` runtime. An example CMake configuration that will allow
for the use/testing of AddressSanitizer:
-.. code-block:: console
+```console
+$ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_ENABLE_RUNTIMES="compiler-rt" <path to source>/llvm
+```
- $ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_ENABLE_RUNTIMES="compiler-rt" <path to source>/llvm
+## Usage
-Usage
-=====
-
-Simply compile and link your program with ``-fsanitize=address`` flag. The
+Simply compile and link your program with `-fsanitize=address` flag. The
AddressSanitizer run-time library should be linked to the final executable, so
-make sure to use ``clang`` (not ``ld``) for the final link step. When linking
+make sure to use `clang` (not `ld`) for the final link step. When linking
shared libraries, the AddressSanitizer run-time is not linked, so
-``-Wl,-z,defs`` may cause link errors (don't use it with AddressSanitizer). To
-get a reasonable performance add ``-O1`` or higher. To get nicer stack traces
-in error messages add ``-fno-omit-frame-pointer``. To get perfect stack traces
-you may need to disable inlining (just use ``-O1``) and tail call elimination
-(``-fno-optimize-sibling-calls``).
-
-.. code-block:: console
-
- % cat example_UseAfterFree.cc
- int main(int argc, char **argv) {
- int *array = new int[100];
- delete [] array;
- return array[argc]; // BOOM
- }
-
- # Compile and link
- % clang++ -O1 -g -fsanitize=address -fno-omit-frame-pointer example_UseAfterFree.cc
+`-Wl,-z,defs` may cause link errors (don't use it with AddressSanitizer). To
+get a reasonable performance add `-O1` or higher. To get nicer stack traces
+in error messages add `-fno-omit-frame-pointer`. To get perfect stack traces
+you may need to disable inlining (just use `-O1`) and tail call elimination
+(`-fno-optimize-sibling-calls`).
+
+```console
+% cat example_UseAfterFree.cc
+int main(int argc, char **argv) {
+ int *array = new int[100];
+ delete [] array;
+ return array[argc]; // BOOM
+}
+
+# Compile and link
+% clang++ -O1 -g -fsanitize=address -fno-omit-frame-pointer example_UseAfterFree.cc
+```
or:
-.. code-block:: console
-
- # Compile
- % clang++ -O1 -g -fsanitize=address -fno-omit-frame-pointer -c example_UseAfterFree.cc
- # Link
- % clang++ -g -fsanitize=address example_UseAfterFree.o
+```console
+# Compile
+% clang++ -O1 -g -fsanitize=address -fno-omit-frame-pointer -c example_UseAfterFree.cc
+# Link
+% clang++ -g -fsanitize=address example_UseAfterFree.o
+```
If a bug is detected, the program will print an error message to stderr and
exit with a non-zero exit code. AddressSanitizer exits on the first detected error.
This is by design:
-* This approach allows AddressSanitizer to produce faster and smaller generated code
+- This approach allows AddressSanitizer to produce faster and smaller generated code
(both by ~5%).
-* Fixing bugs becomes unavoidable. AddressSanitizer does not produce
+- Fixing bugs becomes unavoidable. AddressSanitizer does not produce
false alarms. Once a memory corruption occurs, the program is in an inconsistent
state, which could lead to confusing results and potentially misleading
subsequent reports.
If your process is sandboxed and you are running on OS X 10.10 or earlier, you
-will need to set ``DYLD_INSERT_LIBRARIES`` environment variable and point it to
+will need to set `DYLD_INSERT_LIBRARIES` environment variable and point it to
the ASan library that is packaged with the compiler used to build the
executable. (You can find the library by searching for dynamic libraries with
-``asan`` in their name.) If the environment variable is not set, the process will
+`asan` in their name.) If the environment variable is not set, the process will
try to re-exec. Also keep in mind that when moving the executable to another machine,
the ASan library will also need to be copied over.
-Symbolizing the Reports
-=========================
+## Symbolizing the Reports
To make AddressSanitizer symbolize its output
-you need to set the ``ASAN_SYMBOLIZER_PATH`` environment variable to point to
-the ``llvm-symbolizer`` binary (or make sure ``llvm-symbolizer`` is in your
-``$PATH``):
-
-.. code-block:: console
-
- % ASAN_SYMBOLIZER_PATH=/usr/local/bin/llvm-symbolizer ./a.out
- ==9442== ERROR: AddressSanitizer heap-use-after-free on address 0x7f7ddab8c084 at pc 0x403c8c bp 0x7fff87fb82d0 sp 0x7fff87fb82c8
- READ of size 4 at 0x7f7ddab8c084 thread T0
- #0 0x403c8c in main example_UseAfterFree.cc:4
- #1 0x7f7ddabcac4d in __libc_start_main ??:0
- 0x7f7ddab8c084 is located 4 bytes inside of 400-byte region [0x7f7ddab8c080,0x7f7ddab8c210)
- freed by thread T0 here:
- #0 0x404704 in operator delete[](void*) ??:0
- #1 0x403c53 in main example_UseAfterFree.cc:4
- #2 0x7f7ddabcac4d in __libc_start_main ??:0
- previously allocated by thread T0 here:
- #0 0x404544 in operator new[](unsigned long) ??:0
- #1 0x403c43 in main example_UseAfterFree.cc:2
- #2 0x7f7ddabcac4d in __libc_start_main ??:0
- ==9442== ABORTING
+you need to set the `ASAN_SYMBOLIZER_PATH` environment variable to point to
+the `llvm-symbolizer` binary (or make sure `llvm-symbolizer` is in your
+`$PATH`):
+
+```console
+% ASAN_SYMBOLIZER_PATH=/usr/local/bin/llvm-symbolizer ./a.out
+==9442== ERROR: AddressSanitizer heap-use-after-free on address 0x7f7ddab8c084 at pc 0x403c8c bp 0x7fff87fb82d0 sp 0x7fff87fb82c8
+READ of size 4 at 0x7f7ddab8c084 thread T0
+ #0 0x403c8c in main example_UseAfterFree.cc:4
+ #1 0x7f7ddabcac4d in __libc_start_main ??:0
+0x7f7ddab8c084 is located 4 bytes inside of 400-byte region [0x7f7ddab8c080,0x7f7ddab8c210)
+freed by thread T0 here:
+ #0 0x404704 in operator delete[](void*) ??:0
+ #1 0x403c53 in main example_UseAfterFree.cc:4
+ #2 0x7f7ddabcac4d in __libc_start_main ??:0
+previously allocated by thread T0 here:
+ #0 0x404544 in operator new[](unsigned long) ??:0
+ #1 0x403c43 in main example_UseAfterFree.cc:2
+ #2 0x7f7ddabcac4d in __libc_start_main ??:0
+==9442== ABORTING
+```
If that does not work for you (e.g. your process is sandboxed), you can use a
separate script to symbolize the result offline (online symbolization can be
-force disabled by setting ``ASAN_OPTIONS=symbolize=0``):
-
-.. code-block:: console
+force disabled by setting `ASAN_OPTIONS=symbolize=0`):
- % ASAN_OPTIONS=symbolize=0 ./a.out 2> log
- % projects/compiler-rt/lib/asan/scripts/asan_symbolize.py / < log | c++filt
- ==9442== ERROR: AddressSanitizer heap-use-after-free on address 0x7f7ddab8c084 at pc 0x403c8c bp 0x7fff87fb82d0 sp 0x7fff87fb82c8
- READ of size 4 at 0x7f7ddab8c084 thread T0
- #0 0x403c8c in main example_UseAfterFree.cc:4
- #1 0x7f7ddabcac4d in __libc_start_main ??:0
- ...
+```console
+% ASAN_OPTIONS=symbolize=0 ./a.out 2> log
+% projects/compiler-rt/lib/asan/scripts/asan_symbolize.py / < log | c++filt
+==9442== ERROR: AddressSanitizer heap-use-after-free on address 0x7f7ddab8c084 at pc 0x403c8c bp 0x7fff87fb82d0 sp 0x7fff87fb82c8
+READ of size 4 at 0x7f7ddab8c084 thread T0
+ #0 0x403c8c in main example_UseAfterFree.cc:4
+ #1 0x7f7ddabcac4d in __libc_start_main ??:0
+...
+```
-Note that on macOS you may need to run ``dsymutil`` on your binary to have the
-file\:line info in the AddressSanitizer reports.
+Note that on macOS you may need to run `dsymutil` on your binary to have the
+file:line info in the AddressSanitizer reports.
-Additional Checks
-=================
+## Additional Checks
-Initialization order checking
------------------------------
+### Initialization order checking
AddressSanitizer can optionally detect dynamic initialization order problems,
when initialization of globals defined in one translation unit uses
globals defined in another translation unit. To enable this check at runtime,
you should set environment variable
-``ASAN_OPTIONS=check_initialization_order=1``.
+`ASAN_OPTIONS=check_initialization_order=1`.
Note that this option is not supported on macOS.
-Stack Use After Return (UAR)
-----------------------------
+### Stack Use After Return (UAR)
AddressSanitizer can optionally detect stack use after return problems.
This is available by default, or explicitly
-(``-fsanitize-address-use-after-return=runtime``).
+(`-fsanitize-address-use-after-return=runtime`).
To disable this check at runtime, set the environment variable
-``ASAN_OPTIONS=detect_stack_use_after_return=0``.
+`ASAN_OPTIONS=detect_stack_use_after_return=0`.
-Enabling this check (``-fsanitize-address-use-after-return=always``) will
-reduce code size. The code size may be reduced further by completely
-eliminating this check (``-fsanitize-address-use-after-return=never``).
+Enabling this check (`-fsanitize-address-use-after-return=always`) will
+reduce code size. The code size may be reduced further by completely
+eliminating this check (`-fsanitize-address-use-after-return=never`).
-To summarize: ``-fsanitize-address-use-after-return=<mode>``
- * ``never``: Completely disables detection of UAR errors (reduces code size).
- * ``runtime``: Adds the code for detection, but it can be disabled via the
- runtime environment (``ASAN_OPTIONS=detect_stack_use_after_return=0``).
- * ``always``: Enables detection of UAR errors in all cases. (reduces code
- size, but not as much as ``never``).
+To summarize: `-fsanitize-address-use-after-return=<mode>`
+: - `never`: Completely disables detection of UAR errors (reduces code size).
+ - `runtime`: Adds the code for detection, but it can be disabled via the
+ runtime environment (`ASAN_OPTIONS=detect_stack_use_after_return=0`).
+ - `always`: Enables detection of UAR errors in all cases. (reduces code
+ size, but not as much as `never`).
-Container Overflow Detection
-----------------------------
+### Container Overflow Detection
AddressSanitizer can detect overflows in containers with custom allocators
(such as std::vector) where the library developers have added calls into the
AddressSanitizer runtime to indicate which memory is poisoned etc.
Note that this feature is prone to false positives:
- * Partially poisoning objects on stack, e.g. for small string optimization, can
+: - Partially poisoning objects on stack, e.g. for small string optimization, can
cause both false positives and negatives.
- * If the binary is partially AddressSanitizer instrumented, these
+ - If the binary is partially AddressSanitizer instrumented, these
checks can cause false positives.
-See `Disabling container overflow checks`_ for details on suppressing checks.
+See [Disabling container overflow checks] for details on suppressing checks.
-Memory leak detection
----------------------
+### Memory leak detection
For more information on leak detector in AddressSanitizer, see
-:doc:`LeakSanitizer`. The leak detection is turned on by default on Linux,
-and can be enabled using ``ASAN_OPTIONS=detect_leaks=1`` on macOS;
+{doc}`LeakSanitizer`. The leak detection is turned on by default on Linux,
+and can be enabled using `ASAN_OPTIONS=detect_leaks=1` on macOS;
however, it is not yet supported on other platforms.
-Issue Suppression
-=================
+## Issue Suppression
AddressSanitizer is not expected to produce false positives. If you see one,
look again; most likely it is a true positive!
-Suppressing Reports in External Libraries
------------------------------------------
+### Suppressing Reports in External Libraries
+
Runtime interposition allows AddressSanitizer to find bugs in code that is
not being recompiled. If you run into an issue in external libraries, we
recommend immediately reporting it to the library maintainer so that it
@@ -202,80 +191,76 @@ gets addressed. However, you can use the following suppression mechanism
to unblock yourself and continue on with the testing. This suppression
mechanism should only be used for suppressing issues in external code; it
does not work on code recompiled with AddressSanitizer. To suppress errors
-in external libraries, set the ``ASAN_OPTIONS`` environment variable to point
+in external libraries, set the `ASAN_OPTIONS` environment variable to point
to a suppression file. You can either specify the full path to the file or the
path of the file relative to the location of your executable.
-.. code-block:: bash
-
- ASAN_OPTIONS=suppressions=MyASan.supp
+```bash
+ASAN_OPTIONS=suppressions=MyASan.supp
+```
Use the following format to specify the names of the functions or libraries
you want to suppress. You can see these in the error report. Remember that
the narrower the scope of the suppression, the more bugs you will be able to
catch.
-.. code-block:: bash
+```bash
+interceptor_via_fun:NameOfCFunctionToSuppress
+interceptor_via_fun:-[ClassName objCMethodToSuppress:]
+interceptor_via_lib:NameOfTheLibraryToSuppress
+```
- interceptor_via_fun:NameOfCFunctionToSuppress
- interceptor_via_fun:-[ClassName objCMethodToSuppress:]
- interceptor_via_lib:NameOfTheLibraryToSuppress
-
-Conditional Compilation with ``__has_feature(address_sanitizer)``
------------------------------------------------------------------
+### Conditional Compilation with `__has_feature(address_sanitizer)`
In some cases one may need to execute different code depending on whether
AddressSanitizer is enabled.
-:ref:`\_\_has\_feature <langext-__has_feature-__has_extension>` can be used for
+{ref}`\_\_has\_feature <langext-__has_feature-__has_extension>` can be used for
this purpose.
-.. code-block:: c
-
- #if defined(__has_feature)
- # if __has_feature(address_sanitizer)
- // code that builds only under AddressSanitizer
- # endif
- #endif
+```c
+#if defined(__has_feature)
+# if __has_feature(address_sanitizer)
+// code that builds only under AddressSanitizer
+# endif
+#endif
+```
-Disabling Instrumentation with ``__attribute__((no_sanitize("address")))``
---------------------------------------------------------------------------
+### Disabling Instrumentation with `__attribute__((no_sanitize("address")))`
Some code should not be instrumented by AddressSanitizer. One may use
-the attribute ``__attribute__((no_sanitize("address")))`` (which has
+the attribute `__attribute__((no_sanitize("address")))` (which has
deprecated synonyms `no_sanitize_address` and
`no_address_safety_analysis`) to disable instrumentation of a
particular function. This attribute may not be supported by other
compilers, so we suggest to use it together with
-``__has_feature(address_sanitizer)``.
+`__has_feature(address_sanitizer)`.
The same attribute used on a global variable prevents AddressSanitizer
from adding redzones around it and detecting out of bounds accesses.
AddressSanitizer also supports
-``__attribute__((disable_sanitizer_instrumentation))``. This attribute
-works similarly to ``__attribute__((no_sanitize("address")))``, but it also
+`__attribute__((disable_sanitizer_instrumentation))`. This attribute
+works similarly to `__attribute__((no_sanitize("address")))`, but it also
prevents instrumentation performed by other sanitizers.
-Interaction of Inlining with Disabling Sanitizer Instrumentation
------------------------------------------------------------------
+### Interaction of Inlining with Disabling Sanitizer Instrumentation
-* A `no_sanitize` function will not be inlined heuristically by the compiler into a sanitized function.
-* An `always_inline` function will adopt the instrumentation status of the function it is inlined into.
-* Forcibly combining `no_sanitize` and ``__attribute__((always_inline))`` is not supported, and will often lead to unexpected results. To avoid mixing these attributes, use:
+- A `no_sanitize` function will not be inlined heuristically by the compiler into a sanitized function.
+- An `always_inline` function will adopt the instrumentation status of the function it is inlined into.
+- Forcibly combining `no_sanitize` and `__attribute__((always_inline))` is not supported, and will often lead to unexpected results. To avoid mixing these attributes, use:
-.. code-block:: c
+```c
+// Note, __has_feature test for sanitizers is deprecated, and Clang will support __SANITIZE_<sanitizer>__ similar to GCC.
+#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) || ... <other sanitizers>
+#define ALWAYS_INLINE_IF_UNINSTRUMENTED
+#else
+#define ALWAYS_INLINE_IF_UNINSTRUMENTED __attribute__((always_inline))
+#endif
+```
- // Note, __has_feature test for sanitizers is deprecated, and Clang will support __SANITIZE_<sanitizer>__ similar to GCC.
- #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) || ... <other sanitizers>
- #define ALWAYS_INLINE_IF_UNINSTRUMENTED
- #else
- #define ALWAYS_INLINE_IF_UNINSTRUMENTED __attribute__((always_inline))
- #endif
+### Explicit Sanitizer Checks with `__builtin_allow_sanitize_check`
-Explicit Sanitizer Checks with ``__builtin_allow_sanitize_check``
------------------------------------------------------------------
-
-The ``__builtin_allow_sanitize_check("address")`` builtin can be used to
+The `__builtin_allow_sanitize_check("address")` builtin can be used to
conditionally execute code depending on whether AddressSanitizer checks are
enabled and permitted by the current policy (after inlining). This is
particularly useful for inserting explicit, sanitizer-specific checks around
@@ -284,174 +269,162 @@ by the sanitizer.
Example:
-.. code-block:: c
-
- void __asan_load8(void *);
+```c
+void __asan_load8(void *);
- inline __attribute__((always_inline))
- void my_helper(void *addr) {
- if (__builtin_allow_sanitize_check("address"))
- __asan_load8(addr);
- // ... actual logic, e.g. inline assembly ...
- asm volatile ("..." : : "r" (addr) : "memory");
- }
+inline __attribute__((always_inline))
+void my_helper(void *addr) {
+ if (__builtin_allow_sanitize_check("address"))
+ __asan_load8(addr);
+ // ... actual logic, e.g. inline assembly ...
+ asm volatile ("..." : : "r" (addr) : "memory");
+}
- void instrumented_function() {
- ...
- my_helper(buf); // checks are active
- ...
- }
+void instrumented_function() {
+ ...
+ my_helper(buf); // checks are active
+ ...
+}
- __attribute__((no_sanitize("address")))
- void uninstrumented_function() {
- ...
- my_helper(buf); // checks are skipped
- ...
- }
+__attribute__((no_sanitize("address")))
+void uninstrumented_function() {
+ ...
+ my_helper(buf); // checks are skipped
+ ...
+}
+```
-Disabling container overflow checks
------------------------------------
+### Disabling container overflow checks
-Runtime suppression
-^^^^^^^^^^^^^^^^^^^
+#### Runtime suppression
Container overflow checks can be disabled at runtime using the
-``ASAN_OPTIONS=detect_container_overflow=0`` environment variable.
+`ASAN_OPTIONS=detect_container_overflow=0` environment variable.
-Compile time suppression
-^^^^^^^^^^^^^^^^^^^^^^^^
+#### Compile time suppression
-``-D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__`` can be used at compile time to
+`-D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__` can be used at compile time to
disable container overflow checks if the container library has added support
for this define.
To support a standard way to disable container overflow checks at compile time,
-library developers should use this definition in conjunction with the
-AddressSanitizer feature test to conditionally include container overflow
+library developers should use this definition in conjunction with the
+AddressSanitizer feature test to conditionally include container overflow
related code compiled into user code:
The recommended form is
-.. code-block:: c
+```c
+// include the sanitizer common interfaces
+#include <sanitizer/common_interface_defs.h>
- // include the sanitizer common interfaces
- #include <sanitizer/common_interface_defs.h>
-
- #if __has_feature(address_sanitizer)
- // Container overflow detection enabled - include annotations
- __sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid);
- #endif
+#if __has_feature(address_sanitizer)
+// Container overflow detection enabled - include annotations
+__sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid);
+#endif
+```
This pattern ensures that:
-* Container overflow annotations are only included when AddressSanitizer is
+- Container overflow annotations are only included when AddressSanitizer is
enabled
-* Container overflow detection can be disabled by passing
- ``-D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__`` to the compiler
+- Container overflow detection can be disabled by passing
+ `-D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__` to the compiler
-Suppressing Errors in Recompiled Code (Ignorelist)
---------------------------------------------------
+### Suppressing Errors in Recompiled Code (Ignorelist)
-AddressSanitizer supports ``src`` and ``fun`` entity types in
-:doc:`SanitizerSpecialCaseList`, that can be used to suppress error reports
+AddressSanitizer supports `src` and `fun` entity types in
+{doc}`SanitizerSpecialCaseList`, that can be used to suppress error reports
in the specified source files or functions. Additionally, AddressSanitizer
-introduces ``global`` and ``type`` entity types that can be used to
+introduces `global` and `type` entity types that can be used to
suppress error reports for out-of-bound access to globals with certain
names and types (you may only specify class or struct types).
-You may use an ``init`` category to suppress reports about initialization-order
+You may use an `init` category to suppress reports about initialization-order
problems happening in certain source files or with certain global variables.
-.. code-block:: bash
-
- # Suppress error reports for code in a file or in a function:
- src:bad_file.cpp
- # Ignore all functions with names containing MyFooBar:
- fun:*MyFooBar*
- # Disable out-of-bound checks for global:
- global:bad_array
- # Disable out-of-bound checks for global instances of a given class ...
- type:Namespace::BadClassName
- # ... or a given struct. Use wildcard to deal with anonymous namespace.
- type:Namespace2::*::BadStructName
- # Disable initialization-order checks for globals:
- global:bad_init_global=init
- type:*BadInitClassSubstring*=init
- src:bad/init/files/*=init
-
-Suppressing memory leaks
-------------------------
-
-Memory leak reports produced by :doc:`LeakSanitizer` (if it is run as a part
+```bash
+# Suppress error reports for code in a file or in a function:
+src:bad_file.cpp
+# Ignore all functions with names containing MyFooBar:
+fun:*MyFooBar*
+# Disable out-of-bound checks for global:
+global:bad_array
+# Disable out-of-bound checks for global instances of a given class ...
+type:Namespace::BadClassName
+# ... or a given struct. Use wildcard to deal with anonymous namespace.
+type:Namespace2::*::BadStructName
+# Disable initialization-order checks for globals:
+global:bad_init_global=init
+type:*BadInitClassSubstring*=init
+src:bad/init/files/*=init
+```
+
+### Suppressing memory leaks
+
+Memory leak reports produced by {doc}`LeakSanitizer` (if it is run as a part
of AddressSanitizer) can be suppressed by a separate file passed as
-.. code-block:: bash
-
- LSAN_OPTIONS=suppressions=MyLSan.supp
+```bash
+LSAN_OPTIONS=suppressions=MyLSan.supp
+```
which contains lines of the form `leak:<pattern>`. Memory leak will be
suppressed if pattern matches any function name, source file name, or
library name in the symbolized stack trace of the leak report. See
-`full documentation
-<https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer#suppressions>`_
+[full documentation](https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer#suppressions)
for more details.
-Code generation control
-=======================
+## Code generation control
-Instrumentation code outlining
-------------------------------
+### Instrumentation code outlining
By default AddressSanitizer inlines the instrumentation code to improve the
run-time performance, which leads to increased binary size. Using the
-(clang flag ``-fsanitize-address-outline-instrumentation`` default: ``false``)
+(clang flag `-fsanitize-address-outline-instrumentation` default: `false`)
flag forces all code instrumentation to be outlined, which reduces the size
of the generated code, but also reduces the run-time performance.
-Limitations
-===========
+## Limitations
-* AddressSanitizer uses more real memory than a native run. Exact overhead
+- AddressSanitizer uses more real memory than a native run. Exact overhead
depends on the allocation sizes. The smaller the allocations you make the
bigger the overhead is.
-* AddressSanitizer uses more stack memory. We have seen up to 3x increase.
-* On 64-bit platforms AddressSanitizer maps (but not reserves) 16+ Terabytes of
- virtual address space. This means that tools like ``ulimit`` may not work as
+- AddressSanitizer uses more stack memory. We have seen up to 3x increase.
+- On 64-bit platforms AddressSanitizer maps (but not reserves) 16+ Terabytes of
+ virtual address space. This means that tools like `ulimit` may not work as
usually expected.
-* Static linking of executables is not supported.
+- Static linking of executables is not supported.
-Security Considerations
-=======================
+## Security Considerations
AddressSanitizer is a bug detection tool and its runtime is not meant to be
linked against production executables. While it may be useful for testing,
AddressSanitizer's runtime was not developed with security-sensitive
constraints in mind and may compromise the security of the resulting executable.
-Supported Platforms
-===================
+## Supported Platforms
AddressSanitizer is supported on:
-* Linux
-* macOS
-* iOS Simulator
-* Android
-* NetBSD
-* FreeBSD
-* Windows 8.1+
+- Linux
+- macOS
+- iOS Simulator
+- Android
+- NetBSD
+- FreeBSD
+- Windows 8.1+
-Current Status
-==============
+## Current Status
AddressSanitizer is fully functional on supported platforms starting from LLVM
-3.1. The test suite is integrated into CMake build and can be run with ``make
-check-asan`` command.
+3.1. The test suite is integrated into CMake build and can be run with `make
+check-asan` command.
The Windows port is functional and is used by Chrome and Firefox, but it is not
as well supported as the other ports.
-More Information
-================
+## More Information
+
+[https://github.com/google/sanitizers/wiki/AddressSanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer)
-`<https://github.com/google/sanitizers/wiki/AddressSanitizer>`_
diff --git a/clang/docs/ClangStaticAnalyzer.md b/clang/docs/ClangStaticAnalyzer.md
index 9ab485f6800f8..0172c6f4a5e9d 100644
--- a/clang/docs/ClangStaticAnalyzer.md
+++ b/clang/docs/ClangStaticAnalyzer.md
@@ -1,20 +1,19 @@
-=====================
-Clang Static Analyzer
-=====================
+# Clang Static Analyzer
The Clang Static Analyzer is a source code analysis tool that finds bugs in C, C++, and Objective-C programs.
It implements *path-sensitive*, *inter-procedural analysis* based on *symbolic execution* technique.
-The Static Analyzer is a part of Clang; for downloading and installing Clang visit the `LLVM releases page <https://releases.llvm.org/>`_.
+The Static Analyzer is a part of Clang; for downloading and installing Clang visit the [LLVM releases page](https://releases.llvm.org/).
-This is the documentation page of the Static Analyzer; there is also an old `Official Tool Page <https://clang-analyzer.llvm.org/>`_ which provides a short overview of features and limitations.
+This is the documentation page of the Static Analyzer; there is also an old [Official Tool Page](https://clang-analyzer.llvm.org/) which provides a short overview of features and limitations.
-.. toctree::
- :caption: Table of Contents
- :numbered:
- :maxdepth: 2
+```{toctree}
+:caption: Table of Contents
+:maxdepth: 2
+:numbered: true
- analyzer/checkers
- analyzer/user-docs
- analyzer/developer-docs
+analyzer/checkers
+analyzer/user-docs
+analyzer/developer-docs
+```
diff --git a/clang/docs/CrossCompilation.md b/clang/docs/CrossCompilation.md
index 48f0f72477544..d6a0134a8fb2b 100644
--- a/clang/docs/CrossCompilation.md
+++ b/clang/docs/CrossCompilation.md
@@ -1,9 +1,6 @@
-===================================================================
-Cross-compilation using Clang
-===================================================================
+# Cross-compilation using Clang
-Introduction
-============
+## Introduction
This document will guide you in choosing the right Clang options
for cross-compiling your code to a different architecture. It assumes you
@@ -14,15 +11,13 @@ However, this document is *not* a "how to" and won't help you setting your
build system or Makefiles, nor choosing the right CMake options, etc.
Also, it does not cover all the possible options, nor does it contain
specific examples for specific architectures. For a concrete example, the
-`instructions for cross-compiling LLVM itself
-<https://llvm.org/docs/HowToCrossCompileLLVM.html>`_ may be of interest.
+[instructions for cross-compiling LLVM itself](https://llvm.org/docs/HowToCrossCompileLLVM.html) may be of interest.
After reading this document, you should be familiar with the main issues
related to cross-compilation, and what main compiler options Clang provides
for performing cross-compilation.
-Cross compilation issues
-========================
+## Cross compilation issues
In GCC world, every host/target combination has its own set of binaries,
headers, libraries, etc. So, it's usually simple to download a package
@@ -31,7 +26,7 @@ that compiler, that will know about its location and find all it needs to
when compiling your code.
On the other hand, Clang/LLVM is natively a cross-compiler, meaning that
-one set of programs can compile to all targets by setting the ``-target``
+one set of programs can compile to all targets by setting the `-target`
option. That makes it a lot easier for programmers wishing to compile to
different platforms and architectures, and for compiler developers that
only have to maintain one build system, and for OS distributions, that
@@ -44,45 +39,43 @@ So you'll need special options to help Clang understand what target
you're compiling to, where your tools are, etc.
Another problem is that compilers come with standard libraries only (like
-``compiler-rt``, ``libcxx``, ``libgcc``, ``libm``, etc), so you'll have to
+`compiler-rt`, `libcxx`, `libgcc`, `libm`, etc), so you'll have to
find and make available to the build system, every other library required
to build your software, that is specific to your target. It's not enough to
have your host's libraries installed.
Finally, not all toolchains are the same, and consequently, not every Clang
-option will work magically. Some options, like ``--sysroot`` (which
+option will work magically. Some options, like `--sysroot` (which
effectively changes the logical root for headers and libraries), assume
all your binaries and libraries are in the same directory, which may not
true when your cross-compiler was installed by the distribution's package
management. So, for each specific case, you may use more than one
-option, and in most cases, you'll end up setting include paths (``-I``) and
-library paths (``-L``) manually.
+option, and in most cases, you'll end up setting include paths (`-I`) and
+library paths (`-L`) manually.
To sum up, different toolchains can:
- * be host/target specific or more flexible
- * be in a single directory, or spread out across your system
- * have different sets of libraries and headers by default
- * need special options, which your build system won't be able to figure
- out by itself
+: - be host/target specific or more flexible
+ - be in a single directory, or spread out across your system
+ - have different sets of libraries and headers by default
+ - need special options, which your build system won't be able to figure
+ out by itself
-General Cross-Compilation Options in Clang
-==========================================
+## General Cross-Compilation Options in Clang
-Target Triple
--------------
+### Target Triple
The basic option is to define the target architecture. For that, use
-``-target <triple>``. If you don't specify the target, CPU names won't
+`-target <triple>`. If you don't specify the target, CPU names won't
match (since Clang assumes the host triple), and the compilation will
go ahead, creating code for the host platform, which will break later
on when assembling or linking.
-The triple has the general format ``<arch><sub>-<vendor>-<sys>-<env>``, where:
- * ``arch`` = ``x86_64``, ``i386``, ``arm``, ``thumb``, ``mips``, etc.
- * ``sub`` = for ex. on ARM: ``v5``, ``v6m``, ``v7a``, ``v7m``, etc.
- * ``vendor`` = ``pc``, ``apple``, ``nvidia``, ``ibm``, etc.
- * ``sys`` = ``none``, ``linux``, ``win32``, ``darwin``, ``cuda``, etc.
- * ``env`` = ``eabi``, ``gnu``, ``android``, ``macho``, ``elf``, etc.
+The triple has the general format `<arch><sub>-<vendor>-<sys>-<env>`, where:
+: - `arch` = `x86_64`, `i386`, `arm`, `thumb`, `mips`, etc.
+ - `sub` = for ex. on ARM: `v5`, `v6m`, `v7a`, `v7m`, etc.
+ - `vendor` = `pc`, `apple`, `nvidia`, `ibm`, etc.
+ - `sys` = `none`, `linux`, `win32`, `darwin`, `cuda`, etc.
+ - `env` = `eabi`, `gnu`, `android`, `macho`, `elf`, etc.
The sub-architecture options are available for their own architectures,
of course, so "x86v7a" doesn't make sense. The vendor needs to be
@@ -93,58 +86,56 @@ The system name is generally the OS (linux, darwin), but could be special
like the bare-metal "none".
When a parameter is not important, it can be omitted, or you can
-choose ``unknown`` and the defaults will be used. If you choose a parameter
-that Clang doesn't know, like ``blerg``, it'll ignore and assume
-``unknown``, which is not always desired, so be careful.
+choose `unknown` and the defaults will be used. If you choose a parameter
+that Clang doesn't know, like `blerg`, it'll ignore and assume
+`unknown`, which is not always desired, so be careful.
Finally, the env (environment) option is something that will pick default
CPU/FPU, define the specific behaviour of your code (PCS, extensions),
and also choose the correct library calls, etc.
-CPU, FPU, ABI
--------------
+### CPU, FPU, ABI
Once your target is specified, it's time to pick the hardware you'll
be compiling to. For every architecture, a default set of CPU/FPU/ABI
will be chosen, so you'll almost always have to change it via flags.
Typical flags include:
- * ``-mcpu=<cpu-name>``, like x86-64, swift, cortex-a15
- * ``-mfpu=<fpu-name>``, like SSE3, NEON, controlling the FP unit available
- * ``-mfloat-abi=<fabi>``, like soft, hard, controlling which registers
- to use for floating-point
+: - `-mcpu=<cpu-name>`, like x86-64, swift, cortex-a15
+ - `-mfpu=<fpu-name>`, like SSE3, NEON, controlling the FP unit available
+ - `-mfloat-abi=<fabi>`, like soft, hard, controlling which registers
+ to use for floating-point
The default is normally the common denominator, so that Clang doesn't
generate code that breaks. But that also means you won't get the best
code for your specific hardware, which may mean orders of magnitude
slower than you expect.
-For example, if your target is ``arm-none-eabi``, the default CPU will
-be ``arm7tdmi`` using soft float, which is extremely slow on modern cores,
-whereas if your triple is ``armv7a-none-eabi``, it'll be Cortex-A8 with
+For example, if your target is `arm-none-eabi`, the default CPU will
+be `arm7tdmi` using soft float, which is extremely slow on modern cores,
+whereas if your triple is `armv7a-none-eabi`, it'll be Cortex-A8 with
NEON, but still using soft-float, which is much better, but still not
great.
-Toolchain Options
------------------
+### Toolchain Options
There are three main options to control access to your cross-compiler:
-``--sysroot``, ``-I``, and ``-L``. The two last ones are well known,
+`--sysroot`, `-I`, and `-L`. The two last ones are well known,
but they're particularly important for additional libraries
and headers that are specific to your target.
There are two main ways to have a cross-compiler:
-#. When you have extracted your cross-compiler from a zip file into
- a directory, you have to use ``--sysroot=<path>``. The path is the
+1. When you have extracted your cross-compiler from a zip file into
+ a directory, you have to use `--sysroot=<path>`. The path is the
root directory where you have unpacked your file, and Clang will
- look for the directories ``bin``, ``lib``, ``include`` in there.
+ look for the directories `bin`, `lib`, `include` in there.
In this case, your setup should be pretty much done (if no
additional headers or libraries are needed), as Clang will find
all binaries it needs (assembler, linker, etc) in there.
-#. When you have installed via a package manager (modern Linux
+2. When you have installed via a package manager (modern Linux
distributions have cross-compiler packages available), make
sure the target triple you set is *also* the prefix of your
cross-compiler toolchain.
@@ -156,15 +147,14 @@ There are two main ways to have a cross-compiler:
other way around.
So, here, you'll be a lot safer if you specify the include/library
- directories manually (via ``-I`` and ``-L``).
+ directories manually (via `-I` and `-L`).
-Target-Specific Libraries
-=========================
+## Target-Specific Libraries
All libraries that you compile as part of your build will be
cross-compiled to your target, and your build system will probably
find them in the right place. But all dependencies that are
-normally checked against (like ``libxml`` or ``libz`` etc) will match
+normally checked against (like `libxml` or `libz` etc) will match
against the host platform, not the target.
So, if the build system is not aware that you want to cross-compile
@@ -176,7 +166,7 @@ as for your host machine. There aren't many cross-libraries available
as packages to most OS's, so you'll have to either cross-compile them
from source, or download the package for your target platform,
extract the libraries and headers, put them in specific directories
-and add ``-I`` and ``-L`` pointing to them.
+and add `-I` and `-L` pointing to them.
Also, some libraries have different dependencies on different targets,
so configuration tools to find dependencies in the host can get the
@@ -185,8 +175,7 @@ of your build can get things wrong when setting their own library
paths, and you'll have to augment it via additional flags (configure,
Make, CMake, etc).
-Multilibs
----------
+### Multilibs
When you want to cross-compile to more than one configuration, for
example hard-float-ARM and soft-float-ARM, you'll have to have multiple
@@ -194,10 +183,11 @@ copies of your libraries and (possibly) headers.
Some Linux distributions have support for Multilib, which handle that
for you in an easier way, but if you're not careful and, for instance,
-forget to specify ``-ccc-gcc-name armv7l-linux-gnueabihf-gcc`` (which
-uses hard-float), Clang will pick the ``armv7l-linux-gnueabi-ld``
+forget to specify `-ccc-gcc-name armv7l-linux-gnueabihf-gcc` (which
+uses hard-float), Clang will pick the `armv7l-linux-gnueabi-ld`
(which uses soft-float) and linker errors will happen.
The same is true if you're compiling for different environments, like
-``gnueabi`` and ``androideabi``, and might even link and run, but produce
+`gnueabi` and `androideabi`, and might even link and run, but produce
run-time errors, which are much harder to track down and fix.
+
diff --git a/clang/docs/DataFlowSanitizer.md b/clang/docs/DataFlowSanitizer.md
index 154229f9780b1..565c05b3c4b92 100644
--- a/clang/docs/DataFlowSanitizer.md
+++ b/clang/docs/DataFlowSanitizer.md
@@ -1,74 +1,70 @@
-=================
-DataFlowSanitizer
-=================
+# DataFlowSanitizer
-.. toctree::
- :hidden:
+```{toctree}
+:hidden: true
- DataFlowSanitizerDesign
+DataFlowSanitizerDesign
+```
-.. contents::
- :local:
+```{contents}
+:local: true
+```
-Introduction
-============
+## Introduction
DataFlowSanitizer is a generalised dynamic data flow analysis.
Unlike other Sanitizer tools, this tool is not designed to detect a
-specific class of bugs on its own. Instead, it provides a generic
+specific class of bugs on its own. Instead, it provides a generic
dynamic data flow analysis framework to be used by clients to help
detect application-specific issues within their own code.
-How to build libc++ with DFSan
-==============================
+## How to build libc++ with DFSan
DFSan requires either all of your code to be instrumented or for uninstrumented
-functions to be listed as ``uninstrumented`` in the `ABI list`_.
+functions to be listed as `uninstrumented` in the [ABI list].
If you'd like to have instrumented libc++ functions, then you need to build it
with DFSan instrumentation from source. Here is an example of how to build
libc++ and the libc++ ABI with data flow sanitizer instrumentation.
-.. code-block:: console
+```console
+mkdir libcxx-build
+cd libcxx-build
- mkdir libcxx-build
- cd libcxx-build
+# An example using ninja
+cmake -GNinja -S <monorepo-root>/runtimes \
+ -DCMAKE_C_COMPILER=clang \
+ -DCMAKE_CXX_COMPILER=clang++ \
+ -DLLVM_USE_SANITIZER="DataFlow" \
+ -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi"
- # An example using ninja
- cmake -GNinja -S <monorepo-root>/runtimes \
- -DCMAKE_C_COMPILER=clang \
- -DCMAKE_CXX_COMPILER=clang++ \
- -DLLVM_USE_SANITIZER="DataFlow" \
- -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi"
-
- ninja cxx cxxabi
+ninja cxx cxxabi
+```
Note: Ensure you are building with a sufficiently new version of Clang.
-Usage
-=====
+## Usage
With no program changes, applying DataFlowSanitizer to a program
-will not alter its behavior. To use DataFlowSanitizer, the program
+will not alter its behavior. To use DataFlowSanitizer, the program
uses API functions to apply tags to data to cause it to be tracked, and to
-check the tag of a specific data item. DataFlowSanitizer manages
+check the tag of a specific data item. DataFlowSanitizer manages
the propagation of tags through the program according to its data flow.
-The APIs are defined in the header file ``sanitizer/dfsan_interface.h``.
+The APIs are defined in the header file `sanitizer/dfsan_interface.h`.
For further information about each function, please refer to the header
file.
-.. _ABI list:
+(abi-list)=
-ABI List
---------
+### ABI List
DataFlowSanitizer uses a list of functions known as an ABI list to decide
whether a call to a specific function should use the operating system's native
ABI or whether it should use a variant of this ABI that also propagates labels
-through function parameters and return values. The ABI list file also controls
-how labels are propagated in the former case. DataFlowSanitizer comes with a
+through function parameters and return values. The ABI list file also controls
+how labels are propagated in the former case. DataFlowSanitizer comes with a
default ABI list which is intended to eventually cover the glibc library on
Linux but it may become necessary for users to extend the ABI list in cases
where a particular library or function cannot be instrumented (e.g. because
@@ -76,152 +72,150 @@ it is implemented in assembly or another language which DataFlowSanitizer does
not support) or a function is called from a library or function which cannot
be instrumented.
-DataFlowSanitizer's ABI list file is a :doc:`SanitizerSpecialCaseList`.
-The pass treats every function in the ``uninstrumented`` category in the
-ABI list file as conforming to the native ABI. Unless the ABI list contains
+DataFlowSanitizer's ABI list file is a {doc}`SanitizerSpecialCaseList`.
+The pass treats every function in the `uninstrumented` category in the
+ABI list file as conforming to the native ABI. Unless the ABI list contains
additional categories for those functions, a call to one of those functions
will produce a warning message, as the labelling behavior of the function
-is unknown. The other supported categories are ``discard``, ``functional``
-and ``custom``.
+is unknown. The other supported categories are `discard`, `functional`
+and `custom`.
-* ``discard`` -- To the extent that this function writes to (user-accessible)
+- `discard` -- To the extent that this function writes to (user-accessible)
memory, it also updates labels in shadow memory (this condition is trivially
- satisfied for functions which do not write to user-accessible memory). Its
+ satisfied for functions which do not write to user-accessible memory). Its
return value is unlabelled.
-* ``functional`` -- Like ``discard``, except that the label of its return value
+- `functional` -- Like `discard`, except that the label of its return value
is the union of the label of its arguments.
-* ``custom`` -- Instead of calling the function, a custom wrapper ``__dfsw_F``
- is called, where ``F`` is the name of the function. This function may wrap
- the original function or provide its own implementation. This category is
+- `custom` -- Instead of calling the function, a custom wrapper `__dfsw_F`
+ is called, where `F` is the name of the function. This function may wrap
+ the original function or provide its own implementation. This category is
generally used for uninstrumentable functions which write to user-accessible
- memory or which have more complex label propagation behavior. The signature
- of ``__dfsw_F`` is based on that of ``F`` with each argument having a
- label of type ``dfsan_label`` appended to the argument list. If ``F``
- is of non-void return type a final argument of type ``dfsan_label *``
+ memory or which have more complex label propagation behavior. The signature
+ of `__dfsw_F` is based on that of `F` with each argument having a
+ label of type `dfsan_label` appended to the argument list. If `F`
+ is of non-void return type a final argument of type `dfsan_label *`
is appended to which the custom function can store the label for the
- return value. For example:
-
-.. code-block:: c++
+ return value. For example:
- void f(int x);
- void __dfsw_f(int x, dfsan_label x_label);
+```c++
+void f(int x);
+void __dfsw_f(int x, dfsan_label x_label);
- void *memcpy(void *dest, const void *src, size_t n);
- void *__dfsw_memcpy(void *dest, const void *src, size_t n,
- dfsan_label dest_label, dfsan_label src_label,
- dfsan_label n_label, dfsan_label *ret_label);
+void *memcpy(void *dest, const void *src, size_t n);
+void *__dfsw_memcpy(void *dest, const void *src, size_t n,
+ dfsan_label dest_label, dfsan_label src_label,
+ dfsan_label n_label, dfsan_label *ret_label);
+```
If a function defined in the translation unit being compiled belongs to the
-``uninstrumented`` category, it will be compiled so as to conform to the
-native ABI. Its arguments will be assumed to be unlabelled, but it will
+`uninstrumented` category, it will be compiled so as to conform to the
+native ABI. Its arguments will be assumed to be unlabelled, but it will
propagate labels in shadow memory.
For example:
-.. code-block:: none
-
- # main is called by the C runtime using the native ABI.
- fun:main=uninstrumented
- fun:main=discard
+```none
+# main is called by the C runtime using the native ABI.
+fun:main=uninstrumented
+fun:main=discard
- # malloc only writes to its internal data structures, not user-accessible memory.
- fun:malloc=uninstrumented
- fun:malloc=discard
+# malloc only writes to its internal data structures, not user-accessible memory.
+fun:malloc=uninstrumented
+fun:malloc=discard
- # tolower is a pure function.
- fun:tolower=uninstrumented
- fun:tolower=functional
+# tolower is a pure function.
+fun:tolower=uninstrumented
+fun:tolower=functional
- # memcpy needs to copy the shadow from the source to the destination region.
- # This is done in a custom function.
- fun:memcpy=uninstrumented
- fun:memcpy=custom
+# memcpy needs to copy the shadow from the source to the destination region.
+# This is done in a custom function.
+fun:memcpy=uninstrumented
+fun:memcpy=custom
+```
-For instrumented functions, the ABI list supports a ``force_zero_labels``
+For instrumented functions, the ABI list supports a `force_zero_labels`
category, which will make all stores and return values set zero labels.
-Functions should never be labelled with both ``force_zero_labels``
-and ``uninstrumented`` or any of the uninstrumented wrapper kinds.
+Functions should never be labelled with both `force_zero_labels`
+and `uninstrumented` or any of the uninstrumented wrapper kinds.
For example:
-.. code-block:: none
+```none
+# e.g. void writes_data(char* out_buf, int out_buf_len) {...}
+# Applying force_zero_labels will force out_buf shadow to zero.
+fun:writes_data=force_zero_labels
+```
- # e.g. void writes_data(char* out_buf, int out_buf_len) {...}
- # Applying force_zero_labels will force out_buf shadow to zero.
- fun:writes_data=force_zero_labels
+### Compilation Flags
-
-Compilation Flags
------------------
-
-* ``-dfsan-abilist`` -- The additional ABI list files that control how shadow
+- `-dfsan-abilist` -- The additional ABI list files that control how shadow
parameters are passed. File names are separated by comma.
-* ``-dfsan-combine-pointer-labels-on-load`` -- Controls whether to include or
+- `-dfsan-combine-pointer-labels-on-load` -- Controls whether to include or
ignore the labels of pointers in load instructions. Its default value is true.
For example:
-.. code-block:: c++
-
- v = *p;
+```c++
+v = *p;
+```
-If the flag is true, the label of ``v`` is the union of the label of ``p`` and
-the label of ``*p``. If the flag is false, the label of ``v`` is the label of
-just ``*p``.
+If the flag is true, the label of `v` is the union of the label of `p` and
+the label of `*p`. If the flag is false, the label of `v` is the label of
+just `*p`.
-* ``-dfsan-combine-pointer-labels-on-store`` -- Controls whether to include or
+- `-dfsan-combine-pointer-labels-on-store` -- Controls whether to include or
ignore the labels of pointers in store instructions. Its default value is
false. For example:
-.. code-block:: c++
+```c++
+*p = v;
+```
- *p = v;
+If the flag is true, the label of `*p` is the union of the label of `p` and
+the label of `v`. If the flag is false, the label of `*p` is the label of
+just `v`.
-If the flag is true, the label of ``*p`` is the union of the label of ``p`` and
-the label of ``v``. If the flag is false, the label of ``*p`` is the label of
-just ``v``.
-
-* ``-dfsan-combine-offset-labels-on-gep`` -- Controls whether to propagate
+- `-dfsan-combine-offset-labels-on-gep` -- Controls whether to propagate
labels of offsets in GEP instructions. Its default value is true. For example:
-.. code-block:: c++
-
- p += i;
+```c++
+p += i;
+```
-If the flag is true, the label of ``p`` is the union of the label of ``p`` and
-the label of ``i``. If the flag is false, the label of ``p`` is unchanged.
+If the flag is true, the label of `p` is the union of the label of `p` and
+the label of `i`. If the flag is false, the label of `p` is unchanged.
-* ``-dfsan-track-select-control-flow`` -- Controls whether to track the control
+- `-dfsan-track-select-control-flow` -- Controls whether to track the control
flow of select instructions. Its default value is true. For example:
-.. code-block:: c++
-
- v = b? v1: v2;
+```c++
+v = b? v1: v2;
+```
-If the flag is true, the label of ``v`` is the union of the labels of ``b``,
-``v1`` and ``v2``. If the flag is false, the label of ``v`` is the union of the
-labels of just ``v1`` and ``v2``.
+If the flag is true, the label of `v` is the union of the labels of `b`,
+`v1` and `v2`. If the flag is false, the label of `v` is the union of the
+labels of just `v1` and `v2`.
-* ``-dfsan-event-callbacks`` -- An experimental feature that inserts callbacks for
+- `-dfsan-event-callbacks` -- An experimental feature that inserts callbacks for
certain data events. Currently callbacks are only inserted for loads, stores,
memory transfers (i.e. memcpy and memmove), and comparisons. Its default value
is false. If this flag is set to true, a user must provide definitions for the
following callback functions:
-.. code-block:: c++
+```c++
+void __dfsan_load_callback(dfsan_label Label, void* Addr);
+void __dfsan_store_callback(dfsan_label Label, void* Addr);
+void __dfsan_mem_transfer_callback(dfsan_label *Start, size_t Len);
+void __dfsan_cmp_callback(dfsan_label CombinedLabel);
+```
- void __dfsan_load_callback(dfsan_label Label, void* Addr);
- void __dfsan_store_callback(dfsan_label Label, void* Addr);
- void __dfsan_mem_transfer_callback(dfsan_label *Start, size_t Len);
- void __dfsan_cmp_callback(dfsan_label CombinedLabel);
-
-* ``-dfsan-conditional-callbacks`` -- An experimental feature that inserts
+- `-dfsan-conditional-callbacks` -- An experimental feature that inserts
callbacks for control flow conditional expressions.
This can be used to find where tainted values can control execution.
In addition to this compilation flag, a callback handler must be registered
- using ``dfsan_set_conditional_callback(my_callback);``, where my_callback is
+ using `dfsan_set_conditional_callback(my_callback);`, where my_callback is
a function with a signature matching
- ``void my_callback(dfsan_label l, dfsan_origin o);``.
+ `void my_callback(dfsan_label l, dfsan_origin o);`.
This signature is the same when origin tracking is disabled - in this case
the dfsan_origin passed in it will always be 0.
@@ -231,62 +225,60 @@ labels of just ``v1`` and ``v2``.
handlers, as this is prone to deadlock. Tainted values used in conditional
expressions inside signal handlers will instead be aggregated via bitwise
or, and can be accessed using
- ``dfsan_label dfsan_get_labels_in_signal_conditional();``.
+ `dfsan_label dfsan_get_labels_in_signal_conditional();`.
-* ``-dfsan-reaches-function-callbacks`` -- An experimental feature that inserts
+- `-dfsan-reaches-function-callbacks` -- An experimental feature that inserts
callbacks for data entering a function.
In addition to this compilation flag, a callback handler must be registered
- using ``dfsan_set_reaches_function_callback(my_callback);``, where my_callback is
+ using `dfsan_set_reaches_function_callback(my_callback);`, where my_callback is
a function with a signature matching
- ``void my_callback(dfsan_label label, dfsan_origin origin, const char *file, unsigned int line, const char *function);``
+ `void my_callback(dfsan_label label, dfsan_origin origin, const char *file, unsigned int line, const char *function);`
This signature is the same when origin tracking is disabled - in this case
the dfsan_origin passed in it will always be 0.
The callback will be called when a tainted value reaches stack/registers
in the context of a function. Tainted values can reach a function:
- * via the arguments of the function
- * via the return value of a call that occurs in the function
- * via the loaded value of a load that occurs in the function
+ \* via the arguments of the function
+ \* via the return value of a call that occurs in the function
+ \* via the loaded value of a load that occurs in the function
The callback will be skipped for conditional expressions inside signal
handlers, as this is prone to deadlock. Tainted values reaching functions
inside signal handlers will instead be aggregated via bitwise or, and can
be accessed using
- ``dfsan_label dfsan_get_labels_in_signal_reaches_function()``.
+ `dfsan_label dfsan_get_labels_in_signal_reaches_function()`.
-* ``-dfsan-track-origins`` -- Controls how to track origins. When its value is
+- `-dfsan-track-origins` -- Controls how to track origins. When its value is
0, the runtime does not track origins. When its value is 1, the runtime tracks
origins at memory store operations. When its value is 2, the runtime tracks
origins at memory load and store operations. Its default value is 0.
-* ``-dfsan-instrument-with-call-threshold`` -- If a function being instrumented
+- `-dfsan-instrument-with-call-threshold` -- If a function being instrumented
requires more than this number of origin stores, use callbacks instead of
inline checks (-1 means never use callbacks). Its default value is 3500.
-Environment Variables
----------------------
+### Environment Variables
-* ``warn_unimplemented`` -- Whether to warn on unimplemented functions. Its
+- `warn_unimplemented` -- Whether to warn on unimplemented functions. Its
default value is false.
-* ``strict_data_dependencies`` -- Whether to propagate labels only when there is
+- `strict_data_dependencies` -- Whether to propagate labels only when there is
explicit obvious data dependency (e.g., when comparing strings, ignore the fact
that the output of the comparison might be implicit data-dependent on the
- content of the strings). This applies only to functions with ``custom`` category
+ content of the strings). This applies only to functions with `custom` category
in ABI list. Its default value is true.
-* ``origin_history_size`` -- The limit of origin chain length. Non-positive values
+- `origin_history_size` -- The limit of origin chain length. Non-positive values
mean unlimited. Its default value is 16.
-* ``origin_history_per_stack_limit`` -- The limit of origin node's references count.
+- `origin_history_per_stack_limit` -- The limit of origin node's references count.
Non-positive values mean unlimited. Its default value is 20000.
-* ``store_context_size`` -- The depth limit of origin tracking stack traces. Its
+- `store_context_size` -- The depth limit of origin tracking stack traces. Its
default value is 20.
-* ``zero_in_malloc`` -- Whether to zero shadow space of new allocated memory. Its
+- `zero_in_malloc` -- Whether to zero shadow space of new allocated memory. Its
default value is true.
-* ``zero_in_free`` --- Whether to zero shadow space of deallocated memory. Its
+- `zero_in_free` --- Whether to zero shadow space of deallocated memory. Its
default value is true.
-Example
-=======
+## Example
DataFlowSanitizer supports up to 8 labels, to achieve low CPU and code
size overhead. Base labels are simply 8-bit unsigned integers that are
@@ -296,94 +288,92 @@ by ORing base labels.
The following program demonstrates label propagation by checking that
the correct labels are propagated.
-.. code-block:: c++
-
- #include <sanitizer/dfsan_interface.h>
- #include <assert.h>
+```c++
+#include <sanitizer/dfsan_interface.h>
+#include <assert.h>
- int main(void) {
- int i = 100;
- int j = 200;
- int k = 300;
- dfsan_label i_label = 1;
- dfsan_label j_label = 2;
- dfsan_label k_label = 4;
- dfsan_set_label(i_label, &i, sizeof(i));
- dfsan_set_label(j_label, &j, sizeof(j));
- dfsan_set_label(k_label, &k, sizeof(k));
+int main(void) {
+ int i = 100;
+ int j = 200;
+ int k = 300;
+ dfsan_label i_label = 1;
+ dfsan_label j_label = 2;
+ dfsan_label k_label = 4;
+ dfsan_set_label(i_label, &i, sizeof(i));
+ dfsan_set_label(j_label, &j, sizeof(j));
+ dfsan_set_label(k_label, &k, sizeof(k));
- dfsan_label ij_label = dfsan_get_label(i + j);
+ dfsan_label ij_label = dfsan_get_label(i + j);
- assert(ij_label & i_label); // ij_label has i_label
- assert(ij_label & j_label); // ij_label has j_label
- assert(!(ij_label & k_label)); // ij_label doesn't have k_label
- assert(ij_label == 3); // Verifies all of the above
+ assert(ij_label & i_label); // ij_label has i_label
+ assert(ij_label & j_label); // ij_label has j_label
+ assert(!(ij_label & k_label)); // ij_label doesn't have k_label
+ assert(ij_label == 3); // Verifies all of the above
- // Or, equivalently:
- assert(dfsan_has_label(ij_label, i_label));
- assert(dfsan_has_label(ij_label, j_label));
- assert(!dfsan_has_label(ij_label, k_label));
+ // Or, equivalently:
+ assert(dfsan_has_label(ij_label, i_label));
+ assert(dfsan_has_label(ij_label, j_label));
+ assert(!dfsan_has_label(ij_label, k_label));
- dfsan_label ijk_label = dfsan_get_label(i + j + k);
+ dfsan_label ijk_label = dfsan_get_label(i + j + k);
- assert(ijk_label & i_label); // ijk_label has i_label
- assert(ijk_label & j_label); // ijk_label has j_label
- assert(ijk_label & k_label); // ijk_label has k_label
- assert(ijk_label == 7); // Verifies all of the above
+ assert(ijk_label & i_label); // ijk_label has i_label
+ assert(ijk_label & j_label); // ijk_label has j_label
+ assert(ijk_label & k_label); // ijk_label has k_label
+ assert(ijk_label == 7); // Verifies all of the above
- // Or, equivalently:
- assert(dfsan_has_label(ijk_label, i_label));
- assert(dfsan_has_label(ijk_label, j_label));
- assert(dfsan_has_label(ijk_label, k_label));
+ // Or, equivalently:
+ assert(dfsan_has_label(ijk_label, i_label));
+ assert(dfsan_has_label(ijk_label, j_label));
+ assert(dfsan_has_label(ijk_label, k_label));
- return 0;
- }
+ return 0;
+}
+```
-Origin Tracking
-===============
+## Origin Tracking
DataFlowSanitizer can track origins of labeled values. This feature is enabled by
-``-mllvm -dfsan-track-origins=1``. For example,
-
-.. code-block:: console
-
- % cat test.cc
- #include <sanitizer/dfsan_interface.h>
- #include <stdio.h>
-
- int main(int argc, char** argv) {
- int i = 0;
- dfsan_set_label(i_label, &i, sizeof(i));
- int j = i + 1;
- dfsan_print_origin_trace(&j, "A flow from i to j");
- return 0;
- }
-
- % clang++ -fsanitize=dataflow -mllvm -dfsan-track-origins=1 -fno-omit-frame-pointer -g -O2 test.cc
- % ./a.out
- Taint value 0x1 (at 0x7ffd42bf415c) origin tracking (A flow from i to j)
- Origin value: 0x13900001, Taint value was stored to memory at
- #0 0x55676db85a62 in main test.cc:7:7
- #1 0x7f0083611bbc in __libc_start_main libc-start.c:285
-
- Origin value: 0x9e00001, Taint value was created at
- #0 0x55676db85a08 in main test.cc:6:3
- #1 0x7f0083611bbc in __libc_start_main libc-start.c:285
-
-By ``-mllvm -dfsan-track-origins=1`` DataFlowSanitizer collects only
+`-mllvm -dfsan-track-origins=1`. For example,
+
+```console
+% cat test.cc
+#include <sanitizer/dfsan_interface.h>
+#include <stdio.h>
+
+int main(int argc, char** argv) {
+ int i = 0;
+ dfsan_set_label(i_label, &i, sizeof(i));
+ int j = i + 1;
+ dfsan_print_origin_trace(&j, "A flow from i to j");
+ return 0;
+}
+
+% clang++ -fsanitize=dataflow -mllvm -dfsan-track-origins=1 -fno-omit-frame-pointer -g -O2 test.cc
+% ./a.out
+Taint value 0x1 (at 0x7ffd42bf415c) origin tracking (A flow from i to j)
+Origin value: 0x13900001, Taint value was stored to memory at
+ #0 0x55676db85a62 in main test.cc:7:7
+ #1 0x7f0083611bbc in __libc_start_main libc-start.c:285
+
+Origin value: 0x9e00001, Taint value was created at
+ #0 0x55676db85a08 in main test.cc:6:3
+ #1 0x7f0083611bbc in __libc_start_main libc-start.c:285
+```
+
+By `-mllvm -dfsan-track-origins=1` DataFlowSanitizer collects only
intermediate stores a labeled value went through. Origin tracking slows down
program execution by a factor of 2x on top of the usual DataFlowSanitizer
-slowdown and increases memory overhead by 1x. By ``-mllvm -dfsan-track-origins=2``
+slowdown and increases memory overhead by 1x. By `-mllvm -dfsan-track-origins=2`
DataFlowSanitizer also collects intermediate loads a labeled value went through.
This mode slows down program execution by a factor of 4x.
-Current status
-==============
+## Current status
DataFlowSanitizer is a work in progress, currently under development for
-x86\_64 Linux.
+x86_64 Linux.
+
+## Design
-Design
-======
+Please refer to the {doc}`design document<DataFlowSanitizerDesign>`.
-Please refer to the :doc:`design document<DataFlowSanitizerDesign>`.
diff --git a/clang/docs/FunctionEffectAnalysis.md b/clang/docs/FunctionEffectAnalysis.md
index 3f2c4db7bad0c..9d49df44866f8 100644
--- a/clang/docs/FunctionEffectAnalysis.md
+++ b/clang/docs/FunctionEffectAnalysis.md
@@ -1,102 +1,94 @@
-========================
-Function Effect Analysis
-========================
+# Function Effect Analysis
-.. contents::
- :depth: 3
- :local:
+```{contents}
+:depth: 3
+:local: true
+```
-
-Introduction
-============
+## Introduction
Clang Function Effect Analysis is a language extension which can warn about "unsafe"
constructs. The feature is currently tailored for the Performance Constraint attributes
-``nonblocking`` and ``nonallocating``; functions with these attributes are verified as not
+`nonblocking` and `nonallocating`; functions with these attributes are verified as not
containing any language constructs or calls to other functions which violate the constraint.
-(See :doc:`AttributeReference`.)
-
+(See {doc}`AttributeReference`.)
-The ``nonblocking`` and ``nonallocating`` attributes
-====================================================
+## The `nonblocking` and `nonallocating` attributes
-Attribute syntax
-----------------
+### Attribute syntax
-The ``nonblocking`` and ``nonallocating`` attributes apply to function types, allowing them to be
+The `nonblocking` and `nonallocating` attributes apply to function types, allowing them to be
attached to functions, blocks, function pointers, lambdas, and member functions.
-.. code-block:: c++
-
- // Functions
- void nonblockingFunction() [[clang::nonblocking]];
- void nonallocatingFunction() [[clang::nonallocating]];
+```c++
+// Functions
+void nonblockingFunction() [[clang::nonblocking]];
+void nonallocatingFunction() [[clang::nonallocating]];
- // Function pointers
- void (*nonblockingFunctionPtr)() [[clang::nonblocking]];
+// Function pointers
+void (*nonblockingFunctionPtr)() [[clang::nonblocking]];
- // Typedefs, type aliases.
- typedef void (*NBFunctionPtrTypedef)() [[clang::nonblocking]];
- using NBFunctionPtrTypeAlias_gnu = __attribute__((nonblocking)) void (*)();
- using NBFunctionPtrTypeAlias_std = void (*)() [[clang::nonblocking]];
+// Typedefs, type aliases.
+typedef void (*NBFunctionPtrTypedef)() [[clang::nonblocking]];
+using NBFunctionPtrTypeAlias_gnu = __attribute__((nonblocking)) void (*)();
+using NBFunctionPtrTypeAlias_std = void (*)() [[clang::nonblocking]];
- // C++ methods
- struct Struct {
- void NBMethod() [[clang::nonblocking]];
- };
+// C++ methods
+struct Struct {
+ void NBMethod() [[clang::nonblocking]];
+};
- // C++ lambdas
- auto nbLambda = []() [[clang::nonblocking]] {};
+// C++ lambdas
+auto nbLambda = []() [[clang::nonblocking]] {};
- // Blocks
- void (^nbBlock)() = ^() [[clang::nonblocking]] {};
+// Blocks
+void (^nbBlock)() = ^() [[clang::nonblocking]] {};
+```
The attribute applies only to the function itself. In particular, it does not apply to any nested
functions or declarations, such as blocks, lambdas, and local classes.
-This document uses the C++/C23 syntax ``[[clang::nonblocking]]``, since it parallels the placement
-of the ``noexcept`` specifier, and the attributes have other similarities to ``noexcept``. The GNU
-``__attribute__((nonblocking))`` syntax is also supported. Note that it requires a different
+This document uses the C++/C23 syntax `[[clang::nonblocking]]`, since it parallels the placement
+of the `noexcept` specifier, and the attributes have other similarities to `noexcept`. The GNU
+`__attribute__((nonblocking))` syntax is also supported. Note that it requires a different
placement on a C++ type alias.
-Like ``noexcept``, ``nonblocking`` and ``nonallocating`` have an optional argument, a compile-time
-constant boolean expression. By default, the argument is ``true``, so ``[[clang::nonblocking]]``
-is equivalent to ``[[clang::nonblocking(true)]]``, and declares the function type as never blocking.
+Like `noexcept`, `nonblocking` and `nonallocating` have an optional argument, a compile-time
+constant boolean expression. By default, the argument is `true`, so `[[clang::nonblocking]]`
+is equivalent to `[[clang::nonblocking(true)]]`, and declares the function type as never blocking.
+### Attribute semantics
-Attribute semantics
--------------------
-
-Together with ``noexcept``, the ``nonallocating`` and ``nonblocking`` attributes define an ordered
+Together with `noexcept`, the `nonallocating` and `nonblocking` attributes define an ordered
series of performance constraints. From weakest to strongest:
-- ``noexcept`` (as per the C++ standard): The function type will never throw an exception.
-- ``nonallocating``: The function type will never allocate memory on the heap or throw an
+- `noexcept` (as per the C++ standard): The function type will never throw an exception.
+- `nonallocating`: The function type will never allocate memory on the heap or throw an
exception.
-- ``nonblocking``: The function type will never block on a lock, allocate memory on the heap,
+- `nonblocking`: The function type will never block on a lock, allocate memory on the heap,
or throw an exception.
-``nonblocking`` includes the ``nonallocating`` guarantee.
+`nonblocking` includes the `nonallocating` guarantee.
-While ``nonblocking`` and ``nonallocating`` are conceptually a superset of ``noexcept``, neither
-attribute implicitly specifies ``noexcept``. Further, ``noexcept`` has a specified runtime behavior of
-aborting if an exception is thrown, while the ``nonallocating`` and ``nonblocking`` attributes are
+While `nonblocking` and `nonallocating` are conceptually a superset of `noexcept`, neither
+attribute implicitly specifies `noexcept`. Further, `noexcept` has a specified runtime behavior of
+aborting if an exception is thrown, while the `nonallocating` and `nonblocking` attributes are
mainly for compile-time analysis and have no runtime behavior, except in code built
-with Clang's :doc:`RealtimeSanitizer`. Nonetheless, Clang emits a
-warning if, in C++, a function is declared ``nonblocking`` or ``nonallocating`` without
-``noexcept``. This diagnostic is controlled by ``-Wperf-constraint-implies-noexcept``.
+with Clang's {doc}`RealtimeSanitizer`. Nonetheless, Clang emits a
+warning if, in C++, a function is declared `nonblocking` or `nonallocating` without
+`noexcept`. This diagnostic is controlled by `-Wperf-constraint-implies-noexcept`.
-``nonblocking(true)`` and ``nonallocating(true)`` apply to function *types*, and by extension, to
+`nonblocking(true)` and `nonallocating(true)` apply to function *types*, and by extension, to
function-like declarations. When applied to a declaration with a body, the compiler verifies the
function, as described in the section "Analysis and warnings", below.
-``blocking`` and ``allocating`` are synonyms for ``nonblocking(false)`` and
-``nonallocating(false)``, respectively. They can be used on a function-like declaration to
-explicitly disable any potential inference of ``nonblocking`` or ``nonallocating`` during
-verification. (Inference is described later in this document). ``nonblocking(false)`` and
-``nonallocating(false)`` are legal, but superfluous when applied to a function *type*
-that is not part of a declarator: ``float (int) [[nonblocking(false)]]`` and
-``float (int)`` are identical types.
+`blocking` and `allocating` are synonyms for `nonblocking(false)` and
+`nonallocating(false)`, respectively. They can be used on a function-like declaration to
+explicitly disable any potential inference of `nonblocking` or `nonallocating` during
+verification. (Inference is described later in this document). `nonblocking(false)` and
+`nonallocating(false)` are legal, but superfluous when applied to a function *type*
+that is not part of a declarator: `float (int) [[nonblocking(false)]]` and
+`float (int)` are identical types.
For functions with no explicit performance constraint, the worst is assumed: the function
allocates memory and potentially blocks, unless it can be inferred otherwise. This is detailed in the
@@ -104,278 +96,263 @@ discussion of verification.
The following example describes the meanings of all permutations of the two attributes and arguments:
-.. code-block:: c++
-
- void nb1_na1() [[clang::nonblocking(true)]] [[clang::nonallocating(true)]];
- // Valid; nonallocating(true) is superfluous but doesn't contradict the guarantee.
-
- void nb1_na0() [[clang::nonblocking(true)]] [[clang::nonallocating(false)]];
- // error: 'allocating' and 'nonblocking' attributes are not compatible
+```c++
+void nb1_na1() [[clang::nonblocking(true)]] [[clang::nonallocating(true)]];
+// Valid; nonallocating(true) is superfluous but doesn't contradict the guarantee.
- void nb0_na1() [[clang::nonblocking(false)]] [[clang::nonallocating(true)]];
- // Valid; the function does not allocate memory, but may lock for other reasons.
+void nb1_na0() [[clang::nonblocking(true)]] [[clang::nonallocating(false)]];
+// error: 'allocating' and 'nonblocking' attributes are not compatible
- void nb0_na0() [[clang::nonblocking(false)]] [[clang::nonallocating(false)]];
- // Valid.
+void nb0_na1() [[clang::nonblocking(false)]] [[clang::nonallocating(true)]];
+// Valid; the function does not allocate memory, but may lock for other reasons.
+void nb0_na0() [[clang::nonblocking(false)]] [[clang::nonallocating(false)]];
+// Valid.
+```
-Type conversions
-----------------
+### Type conversions
A performance constraint can be removed or weakened via an implicit conversion. An attempt to add
or strengthen a performance constraint is unsafe and results in a warning. The rules for this
-are comparable to that for ``noexcept`` in C++17 and later.
-
-.. code-block:: c++
-
- void unannotated();
- void nonblocking() [[clang::nonblocking]];
- void nonallocating() [[clang::nonallocating]];
-
- void example()
- {
- // It's fine to remove a performance constraint.
- void (*fp_plain)();
- fp_plain = unannotated;
- fp_plain = nonblocking;
- fp_plain = nonallocating;
-
- // Adding/spoofing nonblocking is unsafe.
- void (*fp_nonblocking)() [[clang::nonblocking]];
- fp_nonblocking = nullptr;
- fp_nonblocking = nonblocking;
- fp_nonblocking = unannotated;
- // ^ warning: attribute 'nonblocking' should not be added via type conversion
- fp_nonblocking = nonallocating;
- // ^ warning: attribute 'nonblocking' should not be added via type conversion
-
- // Adding/spoofing nonallocating is unsafe.
- void (*fp_nonallocating)() [[clang::nonallocating]];
- fp_nonallocating = nullptr;
- fp_nonallocating = nonallocating;
- fp_nonallocating = nonblocking; // no warning because nonblocking includes nonallocating
- fp_nonallocating = unannotated;
- // ^ warning: attribute 'nonallocating' should not be added via type conversion
- }
-
-Virtual methods
----------------
+are comparable to that for `noexcept` in C++17 and later.
+
+```c++
+void unannotated();
+void nonblocking() [[clang::nonblocking]];
+void nonallocating() [[clang::nonallocating]];
+
+void example()
+{
+ // It's fine to remove a performance constraint.
+ void (*fp_plain)();
+ fp_plain = unannotated;
+ fp_plain = nonblocking;
+ fp_plain = nonallocating;
+
+ // Adding/spoofing nonblocking is unsafe.
+ void (*fp_nonblocking)() [[clang::nonblocking]];
+ fp_nonblocking = nullptr;
+ fp_nonblocking = nonblocking;
+ fp_nonblocking = unannotated;
+ // ^ warning: attribute 'nonblocking' should not be added via type conversion
+ fp_nonblocking = nonallocating;
+ // ^ warning: attribute 'nonblocking' should not be added via type conversion
+
+ // Adding/spoofing nonallocating is unsafe.
+ void (*fp_nonallocating)() [[clang::nonallocating]];
+ fp_nonallocating = nullptr;
+ fp_nonallocating = nonallocating;
+ fp_nonallocating = nonblocking; // no warning because nonblocking includes nonallocating
+ fp_nonallocating = unannotated;
+ // ^ warning: attribute 'nonallocating' should not be added via type conversion
+}
+```
+
+### Virtual methods
In C++, when a virtual method has a performance constraint, overriding methods in
subclasses inherit the constraint.
-.. code-block:: c++
-
- struct Base {
- virtual void unsafe();
- virtual void safe() noexcept [[clang::nonblocking]];
- };
+```c++
+struct Base {
+ virtual void unsafe();
+ virtual void safe() noexcept [[clang::nonblocking]];
+};
- struct Derived : public Base {
- void unsafe() [[clang::nonblocking]] override;
- // It's okay for an overridden method to be more constrained
+struct Derived : public Base {
+ void unsafe() [[clang::nonblocking]] override;
+ // It's okay for an overridden method to be more constrained
- void safe() noexcept override;
- // This method is implicitly declared `nonblocking`, inherited from Base.
- };
+ void safe() noexcept override;
+ // This method is implicitly declared `nonblocking`, inherited from Base.
+};
+```
-Redeclarations, overloads, and name mangling
---------------------------------------------
+### Redeclarations, overloads, and name mangling
-The ``nonblocking`` and ``nonallocating`` attributes, like ``noexcept``, do not factor into
+The `nonblocking` and `nonallocating` attributes, like `noexcept`, do not factor into
argument-dependent lookup and overloaded functions/methods.
-First, consider that ``noexcept`` is integral to a function's type:
-
-.. code-block:: c++
+First, consider that `noexcept` is integral to a function's type:
- void f1(int);
- void f1(int) noexcept;
- // error: exception specification in declaration does not match previous
- // declaration
+```c++
+void f1(int);
+void f1(int) noexcept;
+// error: exception specification in declaration does not match previous
+// declaration
+```
-Unlike ``noexcept``, a redeclaration of ``f2`` with an added or stronger performance constraint is
+Unlike `noexcept`, a redeclaration of `f2` with an added or stronger performance constraint is
legal and propagates the attribute to the previous declaration:
-.. code-block:: c++
-
- int f2();
- int f2() [[clang::nonblocking]]; // redeclaration with stronger constraint is OK.
+```c++
+int f2();
+int f2() [[clang::nonblocking]]; // redeclaration with stronger constraint is OK.
+```
This greatly eases adoption by making it possible to annotate functions in external libraries
without modifying library headers.
A redeclaration with a removed or weaker performance constraint produces a warning, paralleling
-the behavior of ``noexcept``:
-
-.. code-block:: c++
+the behavior of `noexcept`:
- int f2() { return 42; }
- // warning: attribute 'nonblocking' on function does not match previous declaration
+```c++
+int f2() { return 42; }
+// warning: attribute 'nonblocking' on function does not match previous declaration
+```
In C++14, the following two declarations of `f3` are identical (a single function). In C++17 they
are separate overloads:
-.. code-block:: c++
-
- void f3(void (*)());
- void f3(void (*)() noexcept);
+```c++
+void f3(void (*)());
+void f3(void (*)() noexcept);
+```
Similarly, the following two declarations of `f4` are separate overloads. This pattern may pose
difficulties due to ambiguity:
-.. code-block:: c++
-
- void f4(void (*)());
- void f4(void (*)() [[clang::nonblocking]]);
+```c++
+void f4(void (*)());
+void f4(void (*)() [[clang::nonblocking]]);
+```
The attributes have no effect on the mangling of function and method names.
-Objective-C
------------
+### Objective-C
The attributes are currently unsupported on Objective-C methods.
-Analysis and warnings
-=====================
+## Analysis and warnings
-Constraints
------------
+### Constraints
-Functions declared ``nonallocating`` or ``nonblocking``, when defined, are verified according to the
+Functions declared `nonallocating` or `nonblocking`, when defined, are verified according to the
following rules. Such functions:
1. May not allocate or deallocate memory on the heap. The analysis follows the calls to
- ``operator new`` and ``operator delete`` generated by the ``new`` and ``delete`` keywords, and
- treats them like any other function call. The global ``operator new`` and ``operator delete``
- aren't declared ``nonblocking`` or ``nonallocating`` and so they are considered unsafe. (This
+ `operator new` and `operator delete` generated by the `new` and `delete` keywords, and
+ treats them like any other function call. The global `operator new` and `operator delete`
+ aren't declared `nonblocking` or `nonallocating` and so they are considered unsafe. (This
is correct because most memory allocators are not lock-free. Note that the placement form of
- ``operator new`` is implemented inline in libc++'s ``<new>`` header, and is verifiably
- ``nonblocking``, since it merely casts the supplied pointer to the result type.)
-
+ `operator new` is implemented inline in libc++'s `<new>` header, and is verifiably
+ `nonblocking`, since it merely casts the supplied pointer to the result type.)
2. May not throw or catch exceptions. To throw, the compiler must allocate the exception on the
- heap. (Also, many subclasses of ``std::exception`` allocate a string). Exceptions are
+ heap. (Also, many subclasses of `std::exception` allocate a string). Exceptions are
deallocated when caught.
-
3. May not make any indirect function call, via a virtual method, function pointer, or
pointer-to-member function, unless the target is explicitly declared with the same
- ``nonblocking`` or ``nonallocating`` attribute (or stronger).
-
+ `nonblocking` or `nonallocating` attribute (or stronger).
4. May not make direct calls to any other function, with the following exceptions:
- a. The callee is also explicitly declared with the same ``nonblocking`` or ``nonallocating``
- attribute (or stronger).
- b. The callee is defined in the same translation unit as the caller, does not have the ``false``
- form of the required attribute, and can be verified to have the same attribute or stronger,
- according to these same rules.
- c. The callee is a built-in function that is known not to block or allocate.
- d. The callee is declared ``noreturn`` and, if compiling C++, the callee is also declared
- ``noexcept``. This special case excludes functions such as ``abort()`` and ``std::terminate()``
- from the analysis. (The reason for requiring ``noexcept`` in C++ is that a function declared
- ``noreturn`` could be a wrapper for ``throw``.)
-
-5. May not invoke or access an Objective-C method or property, since ``objc_msgSend()`` calls into
+> 1. The callee is also explicitly declared with the same `nonblocking` or `nonallocating`
+> attribute (or stronger).
+> 2. The callee is defined in the same translation unit as the caller, does not have the `false`
+> form of the required attribute, and can be verified to have the same attribute or stronger,
+> according to these same rules.
+> 3. The callee is a built-in function that is known not to block or allocate.
+> 4. The callee is declared `noreturn` and, if compiling C++, the callee is also declared
+> `noexcept`. This special case excludes functions such as `abort()` and `std::terminate()`
+> from the analysis. (The reason for requiring `noexcept` in C++ is that a function declared
+> `noreturn` could be a wrapper for `throw`.)
+
+5. May not invoke or access an Objective-C method or property, since `objc_msgSend()` calls into
the Objective-C runtime, which may allocate memory or otherwise block.
-
6. May not access thread-local variables. Typically, thread-local variables are allocated on the
heap when first accessed.
-Functions declared ``nonblocking`` have an additional constraint:
+Functions declared `nonblocking` have an additional constraint:
7. May not declare static local variables (e.g. Meyers singletons). The compiler generates a lock
protecting the initialization of the variable.
-Violations of any of these rules result in warnings, in the ``-Wfunction-effects`` category:
+Violations of any of these rules result in warnings, in the `-Wfunction-effects` category:
-.. code-block:: c++
+```c++
+void notInline();
- void notInline();
+void example() [[clang::nonblocking]]
+{
+ auto* x = new int;
+ // warning: function with 'nonblocking' attribute must not allocate or deallocate
+ // memory
- void example() [[clang::nonblocking]]
- {
- auto* x = new int;
- // warning: function with 'nonblocking' attribute must not allocate or deallocate
- // memory
-
- if (x == nullptr) {
- static Logger* logger = createLogger();
- // warning: function with 'nonblocking' attribute must not have static local variables
-
- throw std::runtime_warning{ "null" };
- // warning: 'nonblocking" function 'example' must not throw exceptions
- }
- notInline();
- // warning: 'function with 'nonblocking' attribute must not call non-'nonblocking' function
- // 'notInline'
- // note (on notInline()): declaration cannot be inferred 'nonblocking' because it has no
- // definition in this translation unit
+ if (x == nullptr) {
+ static Logger* logger = createLogger();
+ // warning: function with 'nonblocking' attribute must not have static local variables
+
+ throw std::runtime_warning{ "null" };
+ // warning: 'nonblocking" function 'example' must not throw exceptions
}
+ notInline();
+ // warning: 'function with 'nonblocking' attribute must not call non-'nonblocking' function
+ // 'notInline'
+ // note (on notInline()): declaration cannot be inferred 'nonblocking' because it has no
+ // definition in this translation unit
+}
+```
-Inferring ``nonblocking`` or ``nonallocating``
-----------------------------------------------
+### Inferring `nonblocking` or `nonallocating`
-In the absence of a ``nonblocking`` or ``nonallocating`` attribute (whether ``true`` or ``false``),
+In the absence of a `nonblocking` or `nonallocating` attribute (whether `true` or `false`),
a function that is called from a performance-constrained function may be analyzed to
infer whether it has a desired attribute. This analysis happens when the function is not a virtual
method, and it has a visible definition within the current translation unit (i.e. its body can be
traversed).
-.. code-block:: c++
-
- void notInline();
- int implicitlySafe() { return 42; }
- void implicitlyUnsafe() { notInline(); }
-
- void example() [[clang::nonblocking]]
- {
- int x = implicitlySafe(); // OK
- implicitlyUnsafe();
- // warning: function with 'nonblocking' attribute must not call non-'nonblocking' function
- // 'implicitlyUnsafe'
- // note (on implicitlyUnsafe): function cannot be inferred 'nonblocking' because it calls
- // non-'nonblocking' function 'notInline'
- // note (on notInline()): declaration cannot be inferred 'nonblocking' because it has no
- // definition in this translation unit
- }
-
-Lambdas and blocks
-------------------
+```c++
+void notInline();
+int implicitlySafe() { return 42; }
+void implicitlyUnsafe() { notInline(); }
+
+void example() [[clang::nonblocking]]
+{
+ int x = implicitlySafe(); // OK
+ implicitlyUnsafe();
+ // warning: function with 'nonblocking' attribute must not call non-'nonblocking' function
+ // 'implicitlyUnsafe'
+ // note (on implicitlyUnsafe): function cannot be inferred 'nonblocking' because it calls
+ // non-'nonblocking' function 'notInline'
+ // note (on notInline()): declaration cannot be inferred 'nonblocking' because it has no
+ // definition in this translation unit
+}
+```
+
+### Lambdas and blocks
As mentioned earlier, the performance constraint attributes apply only to a single function and not
to any code nested inside it, including blocks, lambdas, and local classes. It is possible for a
nonblocking function to schedule the execution of a blocking lambda on another thread. Similarly, a
-blocking function may create a ``nonblocking`` lambda for use in a realtime context.
+blocking function may create a `nonblocking` lambda for use in a realtime context.
Operations which create, destroy, copy, and move lambdas and blocks are analyzed in terms of the
underlying function calls. For example, the creation of a lambda with captures generates a function
call to an anonymous struct's constructor, passing the captures as parameters.
-Implicit function calls in the AST
-----------------------------------
+### Implicit function calls in the AST
-The ``nonblocking`` / ``nonallocating`` analysis occurs at the Sema phase of analysis in Clang.
+The `nonblocking` / `nonallocating` analysis occurs at the Sema phase of analysis in Clang.
During Sema, there are some constructs which will eventually become function calls, but do not
-appear as function calls in the AST. For example, ``auto* foo = new Foo;`` becomes a declaration
-containing a ``CXXNewExpr`` which is understood as a function call to the global ``operator new``
-(in this example), and a ``CXXConstructExpr``, which, for analysis purposes, is a function call to
-``Foo``'s constructor. Most gaps in the analysis would be due to incomplete knowledge of AST
+appear as function calls in the AST. For example, `auto* foo = new Foo;` becomes a declaration
+containing a `CXXNewExpr` which is understood as a function call to the global `operator new`
+(in this example), and a `CXXConstructExpr`, which, for analysis purposes, is a function call to
+`Foo`'s constructor. Most gaps in the analysis would be due to incomplete knowledge of AST
constructs which become function calls.
-Disabling diagnostics
----------------------
+### Disabling diagnostics
-Function effect diagnostics are controlled by ``-Wfunction-effects``.
+Function effect diagnostics are controlled by `-Wfunction-effects`.
A construct like this can be used to exempt code from the checks described here:
-.. code-block:: c++
-
- #define NONBLOCKING_UNSAFE(...) \
- _Pragma("clang diagnostic push") \
- _Pragma("clang diagnostic ignored \"-Wunknown-warning-option\"") \
- _Pragma("clang diagnostic ignored \"-Wfunction-effects\"") \
- __VA_ARGS__ \
- _Pragma("clang diagnostic pop")
+```c++
+#define NONBLOCKING_UNSAFE(...) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Wunknown-warning-option\"") \
+ _Pragma("clang diagnostic ignored \"-Wfunction-effects\"") \
+ __VA_ARGS__ \
+ _Pragma("clang diagnostic pop")
+```
Disabling the diagnostic allows for:
@@ -384,152 +361,137 @@ Disabling the diagnostic allows for:
- using libraries which are safe but not yet annotated;
- incremental adoption in a large codebase.
-Adoption
-========
+## Adoption
-There are a few common issues that arise when adopting the ``nonblocking`` and ``nonallocating``
+There are a few common issues that arise when adopting the `nonblocking` and `nonallocating`
attributes.
-C++ exceptions
---------------
+### C++ exceptions
Exceptions pose a challenge to the adoption of the performance constraints. Common library functions
which throw exceptions include:
-+----------------------------------+-----------------------------------------------------------------------+
-| Method | Alternative |
-+==================================+=======================================================================+
-| ``std::vector<T>::at()`` | ``operator[](size_t)``, after verifying that the index is in range. |
-+----------------------------------+-----------------------------------------------------------------------+
-| ``std::optional<T>::value()`` | ``operator*``, after checking ``has_value()`` or ``operator bool()``. |
-+----------------------------------+-----------------------------------------------------------------------+
-| ``std::expected<T, E>::value()`` | Same as for ``std::optional<T>::value()``. |
-+----------------------------------+-----------------------------------------------------------------------+
+| Method | Alternative |
+| ------------------------------ | ----------------------------------------------------------------- |
+| `std::vector<T>::at()` | `operator[](size_t)`, after verifying that the index is in range. |
+| `std::optional<T>::value()` | `operator*`, after checking `has_value()` or `operator bool()`. |
+| `std::expected<T, E>::value()` | Same as for `std::optional<T>::value()`. |
+### `std::function<R(Args...)>`
-``std::function<R(Args...)>``
------------------------------
-
-``std::function<R(Args...)>`` is generally incompatible with ``nonblocking`` and ``nonallocating``
+`std::function<R(Args...)>` is generally incompatible with `nonblocking` and `nonallocating`
code, because a typical implementation may allocate heap memory in the constructor.
Alternatives:
-- ``std::function_ref`` (available in C++26 or as ``llvm::function_ref``). This is appropriate and
+- `std::function_ref` (available in C++26 or as `llvm::function_ref`). This is appropriate and
optimal when a functor's lifetime does not need to extend past the function that created it.
-
-- ``inplace_function`` from WG14. This solves the allocation problem by giving the functor wrapper
+- `inplace_function` from WG14. This solves the allocation problem by giving the functor wrapper
a fixed size known at compile time and using an inline buffer.
-While these alternatives both address the heap allocation of ``std::function``, they are still
-obstacles to ``nonblocking/nonallocating`` verification, for reasons detailed in the next section.
+While these alternatives both address the heap allocation of `std::function`, they are still
+obstacles to `nonblocking/nonallocating` verification, for reasons detailed in the next section.
+### Interactions with type-erasure techniques
-Interactions with type-erasure techniques
------------------------------------------
-
-``std::function<R(Args...)>`` illustrates a common C++ type-erasure technique. Using template
+`std::function<R(Args...)>` illustrates a common C++ type-erasure technique. Using template
argument deduction, it decomposes a function type into its return and parameter types. Additional
-components of the function type, including ``noexcept``, ``nonblocking``, ``nonallocating``, and any
+components of the function type, including `noexcept`, `nonblocking`, `nonallocating`, and any
other attributes, are discarded.
Standard library support for these components of a function type is not immediately forthcoming.
Code can work around this limitation in either of two ways:
-1. Avoid abstractions like ``std::function`` and instead work directly with the original lambda type.
-
-2. Create a specialized alternative, e.g. ``nonblocking_function_ref<R(Args...)>`` where all function
- pointers used in the implementation and its interface are ``nonblocking``.
+1. Avoid abstractions like `std::function` and instead work directly with the original lambda type.
+2. Create a specialized alternative, e.g. `nonblocking_function_ref<R(Args...)>` where all function
+ pointers used in the implementation and its interface are `nonblocking`.
As an example of the first approach, when using a lambda as a *Callable* template parameter, the
attribute is preserved:
-.. code-block:: c++
-
- std::sort(vec.begin(), vec.end(),
- [](const Elem& a, const Elem& b) [[clang::nonblocking]] { return a.mem < b.mem; });
+```c++
+std::sort(vec.begin(), vec.end(),
+ [](const Elem& a, const Elem& b) [[clang::nonblocking]] { return a.mem < b.mem; });
+```
-Here, the type of the ``Compare`` template parameter is an anonymous class generated from the
-lambda, with an ``operator()`` method holding the ``nonblocking`` attribute.
+Here, the type of the `Compare` template parameter is an anonymous class generated from the
+lambda, with an `operator()` method holding the `nonblocking` attribute.
A complication arises when a *Callable* template parameter, instead of being a lambda or class
-implementing ``operator()``, is a function pointer:
+implementing `operator()`, is a function pointer:
-.. code-block:: c++
+```c++
+static bool compare_elems(const Elem& a, const Elem& b) [[clang::nonblocking]] {
+ return a.mem < b.mem; };
- static bool compare_elems(const Elem& a, const Elem& b) [[clang::nonblocking]] {
- return a.mem < b.mem; };
+std::sort(vec.begin(), vec.end(), compare_elems);
+```
- std::sort(vec.begin(), vec.end(), compare_elems);
-
-Here, the type of ``compare_elems`` is decomposed to ``bool(const Elem&, const Elem&)``, without
-``nonblocking``, when forming the template parameter. This can be solved using the second approach,
+Here, the type of `compare_elems` is decomposed to `bool(const Elem&, const Elem&)`, without
+`nonblocking`, when forming the template parameter. This can be solved using the second approach,
creating a specialized alternative which explicitly requires the attribute. In this case, it's
possible to use a small wrapper to transform the function pointer into a functor:
-.. code-block:: c++
-
- template <typename>
- class nonblocking_fp;
+```c++
+template <typename>
+class nonblocking_fp;
- template <typename R, typename... Args>
- class nonblocking_fp<R(Args...)> {
- public:
- using impl_t = R (*)(Args...) [[clang::nonblocking]];
+template <typename R, typename... Args>
+class nonblocking_fp<R(Args...)> {
+public:
+ using impl_t = R (*)(Args...) [[clang::nonblocking]];
- private:
- impl_t mImpl{ nullptr_t };
- public:
- nonblocking_fp() = default;
- nonblocking_fp(impl_t f) : mImpl{ f } {}
+private:
+ impl_t mImpl{ nullptr_t };
+public:
+ nonblocking_fp() = default;
+ nonblocking_fp(impl_t f) : mImpl{ f } {}
- R operator()(Args... args) const
- {
- return mImpl(std::forward<Args>(args)...);
- }
- };
-
- // deduction guide (like std::function's)
- template< class R, class... ArgTypes >
- nonblocking_fp( R(*)(ArgTypes...) ) -> nonblocking_fp<R(ArgTypes...)>;
+ R operator()(Args... args) const
+ {
+ return mImpl(std::forward<Args>(args)...);
+ }
+};
- // --
+// deduction guide (like std::function's)
+template< class R, class... ArgTypes >
+nonblocking_fp( R(*)(ArgTypes...) ) -> nonblocking_fp<R(ArgTypes...)>;
- // Wrap the function pointer in a functor which preserves ``nonblocking``.
- std::sort(vec.begin(), vec.end(), nonblocking_fp{ compare_elems });
+// --
-Now, the ``nonblocking`` attribute of ``compare_elems`` is verified when it is converted to a
-``nonblocking`` function pointer, as the argument to ``nonblocking_fp``'s constructor. The template
-parameter is the functor class ``nonblocking_fp``.
+// Wrap the function pointer in a functor which preserves ``nonblocking``.
+std::sort(vec.begin(), vec.end(), nonblocking_fp{ compare_elems });
+```
+Now, the `nonblocking` attribute of `compare_elems` is verified when it is converted to a
+`nonblocking` function pointer, as the argument to `nonblocking_fp`'s constructor. The template
+parameter is the functor class `nonblocking_fp`.
-Static local variables
-----------------------
+### Static local variables
Static local variables are often used for lazily-constructed globals (Meyers singletons). Beyond the
compiler's use of a lock to ensure thread-safe initialization, it is dangerously easy to
-inadvertently trigger initialization, involving heap allocation, from a ``nonblocking`` or
-``nonallocating`` context.
+inadvertently trigger initialization, involving heap allocation, from a `nonblocking` or
+`nonallocating` context.
Generally, such singletons need to be replaced by globals, and care must be taken to ensure their
-initialization before they are used from ``nonblocking`` or ``nonallocating`` contexts.
+initialization before they are used from `nonblocking` or `nonallocating` contexts.
-
-Annotating libraries
---------------------
+### Annotating libraries
It can be surprising that the analysis does not depend on knowledge of any primitives; it simply
assumes the worst, that all function calls are unsafe unless explicitly marked as safe or able to be
-inferred as safe. With ``nonblocking``, this appears to suffice for all but the most primitive of
+inferred as safe. With `nonblocking`, this appears to suffice for all but the most primitive of
spinlocks.
At least for an operating system's C functions, it is possible to define an override header which
-redeclares safe common functions (e.g. ``pthread_self()``) with the addition of ``nonblocking``.
+redeclares safe common functions (e.g. `pthread_self()`) with the addition of `nonblocking`.
This may help in adopting the feature incrementally.
-It also helps that many of the functions in the standard C libraries (notably ``<math.h>``)
+It also helps that many of the functions in the standard C libraries (notably `<math.h>`)
are treated as built-in functions by Clang, which the diagnosis understands to be safe.
Much of the C++ standard library consists of inline templated functions which work well with
-inference. A small number of primitives may need explicit ``nonblocking/nonallocating`` attributes.
+inference. A small number of primitives may need explicit `nonblocking/nonallocating` attributes.
+
diff --git a/clang/docs/LanguageExtensions.md b/clang/docs/LanguageExtensions.md
index 11cfd34d051d0..71ee369347e93 100644
--- a/clang/docs/LanguageExtensions.md
+++ b/clang/docs/LanguageExtensions.md
@@ -1,44 +1,40 @@
-=========================
-Clang Language Extensions
-=========================
+# Clang Language Extensions
-.. contents::
- :local:
- :depth: 1
+```{contents}
+:depth: 1
+:local: true
+```
-.. toctree::
- :hidden:
+```{toctree}
+:hidden: true
- ObjectiveCLiterals
- BlockLanguageSpec
- Block-ABI-Apple
- AutomaticReferenceCounting
- PointerAuthentication
- MatrixTypes
- CXXTypeAwareAllocators
+ObjectiveCLiterals
+BlockLanguageSpec
+Block-ABI-Apple
+AutomaticReferenceCounting
+PointerAuthentication
+MatrixTypes
+CXXTypeAwareAllocators
+```
-Introduction
-============
+## Introduction
-This document describes the language extensions provided by Clang. In addition
+This document describes the language extensions provided by Clang. In addition
to the language extensions listed here, Clang aims to support a broad range of
-GCC extensions. Please see the `GCC manual
-<https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html>`_ for more information on
+GCC extensions. Please see the [GCC manual](https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html) for more information on
these extensions.
-.. _langext-feature_check:
+(langext-feature-check)=
-Feature Checking Macros
-=======================
+## Feature Checking Macros
Language extensions can be very useful, but only if you know you can depend on
-them. In order to allow fine-grained feature checks, we support three builtin
-function-like macros. This allows you to directly test for a feature in your
+them. In order to allow fine-grained feature checks, we support three builtin
+function-like macros. This allows you to directly test for a feature in your
code without having to resort to something like autoconf or fragile "compiler
version checks".
-``__has_builtin``
------------------
+### `__has_builtin`
This function-like macro takes a single identifier argument that is the name of
a builtin function, a builtin pseudo-function (taking one or more type
@@ -46,33 +42,32 @@ arguments), or a builtin template.
It evaluates to 1 if the builtin is supported or 0 if not.
It can be used like this:
-.. code-block:: c++
-
- #ifndef __has_builtin // Optional of course.
- #define __has_builtin(x) 0 // Compatibility with non-clang compilers.
- #endif
-
- ...
- #if __has_builtin(__builtin_trap)
- __builtin_trap();
- #else
- abort();
- #endif
- ...
+```c++
+#ifndef __has_builtin // Optional of course.
+ #define __has_builtin(x) 0 // Compatibility with non-clang compilers.
+#endif
-.. note::
+...
+#if __has_builtin(__builtin_trap)
+ __builtin_trap();
+#else
+ abort();
+#endif
+...
+```
- Prior to Clang 10, ``__has_builtin`` could not be used to detect most builtin
- pseudo-functions.
+:::{note}
+Prior to Clang 10, `__has_builtin` could not be used to detect most builtin
+pseudo-functions.
- ``__has_builtin`` should not be used to detect support for a builtin macro;
- use ``#ifdef`` instead.
+`__has_builtin` should not be used to detect support for a builtin macro;
+use `#ifdef` instead.
- When compiling with target offloading, ``__has_builtin`` only considers the
- currently active target.
+When compiling with target offloading, `__has_builtin` only considers the
+currently active target.
+:::
-``__has_constexpr_builtin``
----------------------------
+### `__has_constexpr_builtin`
This function-like macro takes a single identifier argument that is the name of
a builtin function, a builtin pseudo-function (taking one or more type
@@ -80,82 +75,80 @@ arguments), or a builtin template.
It evaluates to 1 if the builtin is supported and can be constant evaluated or
0 if not. It can be used for writing conditionally constexpr code like this:
-.. code-block:: c++
-
- #ifndef __has_constexpr_builtin // Optional of course.
- #define __has_constexpr_builtin(x) 0 // Compatibility with non-clang compilers.
- #endif
-
- ...
- #if __has_constexpr_builtin(__builtin_fmax)
- constexpr
- #endif
- double money_fee(double amount) {
- return __builtin_fmax(amount * 0.03, 10.0);
- }
- ...
+```c++
+#ifndef __has_constexpr_builtin // Optional of course.
+ #define __has_constexpr_builtin(x) 0 // Compatibility with non-clang compilers.
+#endif
+
+...
+#if __has_constexpr_builtin(__builtin_fmax)
+ constexpr
+#endif
+ double money_fee(double amount) {
+ return __builtin_fmax(amount * 0.03, 10.0);
+ }
+...
+```
-For example, ``__has_constexpr_builtin`` is used in libcxx's implementation of
-the ``<cmath>`` header file to conditionally make a function constexpr whenever
+For example, `__has_constexpr_builtin` is used in libcxx's implementation of
+the `<cmath>` header file to conditionally make a function constexpr whenever
the constant evaluation of the corresponding builtin (for example,
-``std::fmax`` calls ``__builtin_fmax``) is supported in Clang.
+`std::fmax` calls `__builtin_fmax`) is supported in Clang.
-.. _langext-__has_feature-__has_extension:
+(langext-has-feature-has-extension)=
-``__has_feature`` and ``__has_extension``
------------------------------------------
+### `__has_feature` and `__has_extension`
These function-like macros take a single identifier argument that is the name
-of a feature. ``__has_feature`` evaluates to 1 if the feature is both
+of a feature. `__has_feature` evaluates to 1 if the feature is both
supported by Clang and standardized in the current language standard or 0 if
-not (but see :ref:`below <langext-has-feature-back-compat>`), while
-``__has_extension`` evaluates to 1 if the feature is supported by Clang in the
+not (but see {ref}`below <langext-has-feature-back-compat>`), while
+`__has_extension` evaluates to 1 if the feature is supported by Clang in the
current language (either as a language extension or a standard language
-feature) or 0 if not. They can be used like this:
-
-.. code-block:: c++
-
- #ifndef __has_feature // Optional of course.
- #define __has_feature(x) 0 // Compatibility with non-clang compilers.
- #endif
- #ifndef __has_extension
- #define __has_extension __has_feature // Compatibility with pre-3.0 compilers.
- #endif
-
- ...
- #if __has_feature(cxx_rvalue_references)
- // This code will only be compiled with the -std=c++11 and -std=gnu++11
- // options, because rvalue references are only standardized in C++11.
- #endif
-
- #if __has_extension(cxx_rvalue_references)
- // This code will be compiled with the -std=c++11, -std=gnu++11, -std=c++98
- // and -std=gnu++98 options, because rvalue references are supported as a
- // language extension in C++98.
- #endif
-
-.. _langext-has-feature-back-compat:
-
-For backward compatibility, ``__has_feature`` can also be used to test
-for support for non-standardized features, i.e., features not prefixed ``c_``,
-``cxx_`` or ``objc_``.
-
-Another use of ``__has_feature`` is to check for compiler features not related
-to the language standard, such as :doc:`AddressSanitizer
+feature) or 0 if not. They can be used like this:
+
+```c++
+#ifndef __has_feature // Optional of course.
+ #define __has_feature(x) 0 // Compatibility with non-clang compilers.
+#endif
+#ifndef __has_extension
+ #define __has_extension __has_feature // Compatibility with pre-3.0 compilers.
+#endif
+
+...
+#if __has_feature(cxx_rvalue_references)
+// This code will only be compiled with the -std=c++11 and -std=gnu++11
+// options, because rvalue references are only standardized in C++11.
+#endif
+
+#if __has_extension(cxx_rvalue_references)
+// This code will be compiled with the -std=c++11, -std=gnu++11, -std=c++98
+// and -std=gnu++98 options, because rvalue references are supported as a
+// language extension in C++98.
+#endif
+```
+
+(langext-has-feature-back-compat)=
+
+For backward compatibility, `__has_feature` can also be used to test
+for support for non-standardized features, i.e., features not prefixed `c_`,
+`cxx_` or `objc_`.
+
+Another use of `__has_feature` is to check for compiler features not related
+to the language standard, such as {doc}`AddressSanitizer
<AddressSanitizer>`.
-If the ``-pedantic-errors`` option is given, ``__has_extension`` is equivalent
-to ``__has_feature``.
+If the `-pedantic-errors` option is given, `__has_extension` is equivalent
+to `__has_feature`.
The feature tag is described along with the language feature below.
The feature name or extension name can also be specified with a preceding and
-following ``__`` (double underscore) to avoid interference from a macro with
-the same name. For instance, ``__cxx_rvalue_references__`` can be used instead
-of ``cxx_rvalue_references``.
+following `__` (double underscore) to avoid interference from a macro with
+the same name. For instance, `__cxx_rvalue_references__` can be used instead
+of `cxx_rvalue_references`.
-``__has_cpp_attribute``
------------------------
+### `__has_cpp_attribute`
This function-like macro is available in C++20 by default, and is provided as an
extension in earlier language standards. It takes a single argument that is the
@@ -163,34 +156,32 @@ name of a double-square-bracket-style attribute. The argument can be either a
single identifier or a scoped identifier. If the attribute is supported, a
nonzero value is returned. If the attribute is a standards-based attribute, this
macro returns a nonzero value based on the year and month in which the attribute
-was voted into the working draft. See `WG21 SD-6
-<https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations>`_
+was voted into the working draft. See [WG21 SD-6](https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations)
for the list of values returned for standards-based attributes. If the attribute
is not supported by the current compilation target, this macro evaluates to 0.
It can be used like this:
-.. code-block:: c++
-
- #ifndef __has_cpp_attribute // For backwards compatibility
- #define __has_cpp_attribute(x) 0
- #endif
-
- ...
- #if __has_cpp_attribute(clang::fallthrough)
- #define FALLTHROUGH [[clang::fallthrough]]
- #else
- #define FALLTHROUGH
- #endif
- ...
-
-The attribute scope tokens ``clang`` and ``_Clang`` are interchangeable, as are
-the attribute scope tokens ``gnu`` and ``__gnu__``. Attribute tokens in either
-of these namespaces can be specified with a preceding and following ``__``
+```c++
+#ifndef __has_cpp_attribute // For backwards compatibility
+ #define __has_cpp_attribute(x) 0
+#endif
+
+...
+#if __has_cpp_attribute(clang::fallthrough)
+#define FALLTHROUGH [[clang::fallthrough]]
+#else
+#define FALLTHROUGH
+#endif
+...
+```
+
+The attribute scope tokens `clang` and `_Clang` are interchangeable, as are
+the attribute scope tokens `gnu` and `__gnu__`. Attribute tokens in either
+of these namespaces can be specified with a preceding and following `__`
(double underscore) to avoid interference from a macro with the same name. For
-instance, ``gnu::__const__`` can be used instead of ``gnu::const``.
+instance, `gnu::__const__` can be used instead of `gnu::const`.
-``__has_c_attribute``
----------------------
+### `__has_c_attribute`
This function-like macro takes a single argument that is the name of an
attribute exposed with the double square-bracket syntax in C mode. The argument
@@ -198,460 +189,440 @@ can either be a single identifier or a scoped identifier. If the attribute is
supported, a nonzero value is returned. If the attribute is not supported by the
current compilation target, this macro evaluates to 0. It can be used like this:
-.. code-block:: c
-
- #ifndef __has_c_attribute // Optional of course.
- #define __has_c_attribute(x) 0 // Compatibility with non-clang compilers.
- #endif
+```c
+#ifndef __has_c_attribute // Optional of course.
+ #define __has_c_attribute(x) 0 // Compatibility with non-clang compilers.
+#endif
- ...
- #if __has_c_attribute(fallthrough)
- #define FALLTHROUGH [[fallthrough]]
- #else
- #define FALLTHROUGH
- #endif
- ...
+...
+#if __has_c_attribute(fallthrough)
+ #define FALLTHROUGH [[fallthrough]]
+#else
+ #define FALLTHROUGH
+#endif
+...
+```
-The attribute scope tokens ``clang`` and ``_Clang`` are interchangeable, as are
-the attribute scope tokens ``gnu`` and ``__gnu__``. Attribute tokens in either
-of these namespaces can be specified with a preceding and following ``__``
+The attribute scope tokens `clang` and `_Clang` are interchangeable, as are
+the attribute scope tokens `gnu` and `__gnu__`. Attribute tokens in either
+of these namespaces can be specified with a preceding and following `__`
(double underscore) to avoid interference from a macro with the same name. For
-instance, ``gnu::__const__`` can be used instead of ``gnu::const``.
+instance, `gnu::__const__` can be used instead of `gnu::const`.
-``__has_attribute``
--------------------
+### `__has_attribute`
This function-like macro takes a single identifier argument that is the name of
-a GNU-style attribute. It evaluates to 1 if the attribute is supported by the
-current compilation target, or 0 if not. It can be used like this:
-
-.. code-block:: c++
-
- #ifndef __has_attribute // Optional of course.
- #define __has_attribute(x) 0 // Compatibility with non-clang compilers.
- #endif
-
- ...
- #if __has_attribute(always_inline)
- #define ALWAYS_INLINE __attribute__((always_inline))
- #else
- #define ALWAYS_INLINE
- #endif
- ...
-
-The attribute name can also be specified with a preceding and following ``__``
-(double underscore) to avoid interference from a macro with the same name. For
-instance, ``__always_inline__`` can be used instead of ``always_inline``.
-
+a GNU-style attribute. It evaluates to 1 if the attribute is supported by the
+current compilation target, or 0 if not. It can be used like this:
+
+```c++
+#ifndef __has_attribute // Optional of course.
+ #define __has_attribute(x) 0 // Compatibility with non-clang compilers.
+#endif
+
+...
+#if __has_attribute(always_inline)
+#define ALWAYS_INLINE __attribute__((always_inline))
+#else
+#define ALWAYS_INLINE
+#endif
+...
+```
+
+The attribute name can also be specified with a preceding and following `__`
+(double underscore) to avoid interference from a macro with the same name. For
+instance, `__always_inline__` can be used instead of `always_inline`.
-``__has_declspec_attribute``
-----------------------------
+### `__has_declspec_attribute`
This function-like macro takes a single identifier argument that is the name of
-an attribute implemented as a Microsoft-style ``__declspec`` attribute. It
+an attribute implemented as a Microsoft-style `__declspec` attribute. It
evaluates to 1 if the attribute is supported by the current compilation target,
-or 0 if not. It can be used like this:
-
-.. code-block:: c++
-
- #ifndef __has_declspec_attribute // Optional of course.
- #define __has_declspec_attribute(x) 0 // Compatibility with non-clang compilers.
- #endif
-
- ...
- #if __has_declspec_attribute(dllexport)
- #define DLLEXPORT __declspec(dllexport)
- #else
- #define DLLEXPORT
- #endif
- ...
-
-The attribute name can also be specified with a preceding and following ``__``
-(double underscore) to avoid interference from a macro with the same name. For
-instance, ``__dllexport__`` can be used instead of ``dllexport``.
+or 0 if not. It can be used like this:
+
+```c++
+#ifndef __has_declspec_attribute // Optional of course.
+ #define __has_declspec_attribute(x) 0 // Compatibility with non-clang compilers.
+#endif
+
+...
+#if __has_declspec_attribute(dllexport)
+#define DLLEXPORT __declspec(dllexport)
+#else
+#define DLLEXPORT
+#endif
+...
+```
+
+The attribute name can also be specified with a preceding and following `__`
+(double underscore) to avoid interference from a macro with the same name. For
+instance, `__dllexport__` can be used instead of `dllexport`.
-``__is_identifier``
--------------------
+### `__is_identifier`
This function-like macro takes a single identifier argument that might be either
a reserved word or a regular identifier. It evaluates to 1 if the argument is just
a regular identifier and not a reserved word, in the sense that it can then be
used as the name of a user-defined function or variable. Otherwise it evaluates
-to 0. It can be used like this:
-
-.. code-block:: c++
+to 0. It can be used like this:
- ...
- #ifdef __is_identifier // Compatibility with non-clang compilers.
- #if __is_identifier(__wchar_t)
- typedef wchar_t __wchar_t;
- #endif
+```c++
+...
+#ifdef __is_identifier // Compatibility with non-clang compilers.
+ #if __is_identifier(__wchar_t)
+ typedef wchar_t __wchar_t;
#endif
+#endif
- __wchar_t WideCharacter;
- ...
+__wchar_t WideCharacter;
+...
+```
-Include File Checking Macros
-============================
+## Include File Checking Macros
-Not all developments systems have the same include files. The
-:ref:`langext-__has_include` and :ref:`langext-__has_include_next` macros allow
+Not all developments systems have the same include files. The
+{ref}`langext-__has_include` and {ref}`langext-__has_include_next` macros allow
you to check for the existence of an include file before doing a possibly
-failing ``#include`` directive. Include file checking macros must be used
-as expressions in ``#if`` or ``#elif`` preprocessing directives.
+failing `#include` directive. Include file checking macros must be used
+as expressions in `#if` or `#elif` preprocessing directives.
-.. _langext-__has_include:
+(langext-has-include)=
-``__has_include``
------------------
+### `__has_include`
This function-like macro takes a single file name string argument that is the
-name of an include file. It evaluates to 1 if the file can be found using the
+name of an include file. It evaluates to 1 if the file can be found using the
include paths, or 0 otherwise:
-.. code-block:: c++
-
- // Note the two possible file name string formats.
- #if __has_include("myinclude.h") && __has_include(<stdint.h>)
- # include "myinclude.h"
- #endif
-
-To test for this feature, use ``#if defined(__has_include)``:
+```c++
+// Note the two possible file name string formats.
+#if __has_include("myinclude.h") && __has_include(<stdint.h>)
+# include "myinclude.h"
+#endif
+```
-.. code-block:: c++
+To test for this feature, use `#if defined(__has_include)`:
- // To avoid problems with non-clang compilers not having this macro.
- #if defined(__has_include)
- #if __has_include("myinclude.h")
- # include "myinclude.h"
- #endif
- #endif
+```c++
+// To avoid problems with non-clang compilers not having this macro.
+#if defined(__has_include)
+#if __has_include("myinclude.h")
+# include "myinclude.h"
+#endif
+#endif
+```
-.. _langext-__has_include_next:
+(langext-has-include-next)=
-``__has_include_next``
-----------------------
+### `__has_include_next`
This function-like macro takes a single file name string argument that is the
-name of an include file. It is like ``__has_include`` except that it looks for
-the second instance of the given file found in the include paths. It evaluates
+name of an include file. It is like `__has_include` except that it looks for
+the second instance of the given file found in the include paths. It evaluates
to 1 if the second instance of the file can be found using the include paths,
or 0 otherwise:
-.. code-block:: c++
-
- // Note the two possible file name string formats.
- #if __has_include_next("myinclude.h") && __has_include_next(<stdint.h>)
- # include_next "myinclude.h"
- #endif
-
- // To avoid problems with non-clang compilers not having this macro.
- #if defined(__has_include_next)
- #if __has_include_next("myinclude.h")
- # include_next "myinclude.h"
- #endif
- #endif
-
-Note that ``__has_include_next``, like the GNU extension ``#include_next``
+```c++
+// Note the two possible file name string formats.
+#if __has_include_next("myinclude.h") && __has_include_next(<stdint.h>)
+# include_next "myinclude.h"
+#endif
+
+// To avoid problems with non-clang compilers not having this macro.
+#if defined(__has_include_next)
+#if __has_include_next("myinclude.h")
+# include_next "myinclude.h"
+#endif
+#endif
+```
+
+Note that `__has_include_next`, like the GNU extension `#include_next`
directive, is intended for use in headers only, and will issue a warning if
-used in the top-level compilation file. A warning will also be issued if an
+used in the top-level compilation file. A warning will also be issued if an
absolute path is used in the file argument.
-``__has_warning``
------------------
+### `__has_warning`
This function-like macro takes a string literal that represents a command line
-option for a warning and returns ``true`` if that is a valid warning option.
+option for a warning and returns `true` if that is a valid warning option.
-.. code-block:: c++
+```c++
+#if __has_warning("-Wformat")
+...
+#endif
+```
- #if __has_warning("-Wformat")
- ...
- #endif
+(languageextensions-builtin-macros)=
-.. _languageextensions-builtin-macros:
+## Builtin Macros
-Builtin Macros
-==============
+`__BASE_FILE__`
-``__BASE_FILE__``
- Defined to a string that contains the name of the main input file passed to
+: Defined to a string that contains the name of the main input file passed to
Clang.
-``__FILE_NAME__``
- Clang-specific extension that functions similar to ``__FILE__`` but only
+`__FILE_NAME__`
+
+: Clang-specific extension that functions similar to `__FILE__` but only
renders the last path component (the filename) instead of an
invocation-dependent full path to that file.
-``__COUNTER__``
- Defined to an integer value that starts at zero and is incremented each time
- the ``__COUNTER__`` macro is expanded. This is a standard feature in C2y but
+`__COUNTER__`
+
+: Defined to an integer value that starts at zero and is incremented each time
+ the `__COUNTER__` macro is expanded. This is a standard feature in C2y but
is an extension in earlier language modes and in C++. This macro can only be
expanded 2147483647 times at most.
-``__INCLUDE_LEVEL__``
- Defined to an integral value that is the include depth of the file currently
- being translated. For the main file, this value is zero.
+`__INCLUDE_LEVEL__`
-``__TIMESTAMP__``
- Defined to the date and time of the last modification of the current source
+: Defined to an integral value that is the include depth of the file currently
+ being translated. For the main file, this value is zero.
+
+`__TIMESTAMP__`
+
+: Defined to the date and time of the last modification of the current source
file.
-``__clang__``
- Defined when compiling with Clang.
+`__clang__`
+
+: Defined when compiling with Clang.
+
+`__clang_major__`
-``__clang_major__``
- Defined to the major marketing version number of Clang (e.g., the 2 in
- 2.0.1). Note that marketing version numbers should not be used to check for
+: Defined to the major marketing version number of Clang (e.g., the 2 in
+ 2.0.1). Note that marketing version numbers should not be used to check for
language features, as different vendors use different numbering schemes.
- Instead, use the :ref:`langext-feature_check`.
+ Instead, use the {ref}`langext-feature_check`.
-``__clang_minor__``
- Defined to the minor version number of Clang (e.g., the 0 in 2.0.1). Note
+`__clang_minor__`
+
+: Defined to the minor version number of Clang (e.g., the 0 in 2.0.1). Note
that marketing version numbers should not be used to check for language
- features, as different vendors use different numbering schemes. Instead, use
- the :ref:`langext-feature_check`.
+ features, as different vendors use different numbering schemes. Instead, use
+ the {ref}`langext-feature_check`.
+
+`__clang_patchlevel__`
+
+: Defined to the marketing patch level of Clang (e.g., the 1 in 2.0.1).
+
+`__clang_version__`
-``__clang_patchlevel__``
- Defined to the marketing patch level of Clang (e.g., the 1 in 2.0.1).
+: Defined to a string that captures the Clang marketing version, including the
+ Subversion tag or revision number, e.g., "`1.5 (trunk 102332)`".
-``__clang_version__``
- Defined to a string that captures the Clang marketing version, including the
- Subversion tag or revision number, e.g., "``1.5 (trunk 102332)``".
+`__clang_literal_encoding__`
-``__clang_literal_encoding__``
- Defined to a narrow string literal that represents the current encoding of
- narrow string literals, e.g., ``"hello"``. This macro typically expands to
+: Defined to a narrow string literal that represents the current encoding of
+ narrow string literals, e.g., `"hello"`. This macro typically expands to
"UTF-8" (but may change in the future if the
- ``-fexec-charset="Encoding-Name"`` option is implemented.)
+ `-fexec-charset="Encoding-Name"` option is implemented.)
-``__clang_wide_literal_encoding__``
- Defined to a narrow string literal that represents the current encoding of
- wide string literals, e.g., ``L"hello"``. This macro typically expands to
+`__clang_wide_literal_encoding__`
+
+: Defined to a narrow string literal that represents the current encoding of
+ wide string literals, e.g., `L"hello"`. This macro typically expands to
"UTF-16" or "UTF-32" (but may change in the future if the
- ``-fwide-exec-charset="Encoding-Name"`` option is implemented.)
+ `-fwide-exec-charset="Encoding-Name"` option is implemented.)
-Implementation-defined keywords
-===============================
+## Implementation-defined keywords
-__datasizeof
-------------
+### \_\_datasizeof
-``__datasizeof`` behaves like ``sizeof``, except that it returns the size of the
+`__datasizeof` behaves like `sizeof`, except that it returns the size of the
type ignoring tail padding.
-_BitInt, _ExtInt
-----------------
+### \_BitInt, \_ExtInt
-Clang supports the C23 ``_BitInt(N)`` feature as an extension in older C modes
+Clang supports the C23 `_BitInt(N)` feature as an extension in older C modes
and in C++. This type was previously implemented in Clang with the same
-semantics, but spelled ``_ExtInt(N)``. This spelling has been deprecated in
+semantics, but spelled `_ExtInt(N)`. This spelling has been deprecated in
favor of the standard type.
-Note: the ABI for ``_BitInt(N)`` is still in the process of being stabilized,
+Note: the ABI for `_BitInt(N)` is still in the process of being stabilized,
so this type should not yet be used in interfaces that require ABI stability.
-C keywords supported in all language modes
-------------------------------------------
+### C keywords supported in all language modes
-Clang supports ``_Alignas``, ``_Alignof``, ``_Atomic``, ``_Complex``,
-``_Generic``, ``_Imaginary``, ``_Noreturn``, ``_Static_assert``,
-``_Thread_local``, and ``_Float16`` in all language modes with the C semantics.
+Clang supports `_Alignas`, `_Alignof`, `_Atomic`, `_Complex`,
+`_Generic`, `_Imaginary`, `_Noreturn`, `_Static_assert`,
+`_Thread_local`, and `_Float16` in all language modes with the C semantics.
-__alignof, __alignof__
-----------------------
+### \_\_alignof, \_\_alignof\_\_
-``__alignof`` and ``__alignof__`` return, in contrast to ``_Alignof`` and
-``alignof``, the preferred alignment of a type. This may be larger than the
+`__alignof` and `__alignof__` return, in contrast to `_Alignof` and
+`alignof`, the preferred alignment of a type. This may be larger than the
required alignment for improved performance.
-__extension__
--------------
+### \_\_extension\_\_
-``__extension__`` suppresses extension diagnostics in the statement it is
+`__extension__` suppresses extension diagnostics in the statement it is
prepended to.
-__auto_type
------------
+### \_\_auto_type
-``__auto_type`` behaves the same as ``auto`` in C++11 but is available in all
+`__auto_type` behaves the same as `auto` in C++11 but is available in all
language modes.
-__imag, __imag__
-----------------
+### \_\_imag, \_\_imag\_\_
-``__imag`` and ``__imag__`` can be used to get the imaginary part of a complex
+`__imag` and `__imag__` can be used to get the imaginary part of a complex
value.
-__real, __real__
-----------------
+### \_\_real, \_\_real\_\_
-``__real`` and ``__real__`` can be used to get the real part of a complex value.
+`__real` and `__real__` can be used to get the real part of a complex value.
-__asm, __asm__
---------------
+### \_\_asm, \_\_asm\_\_
-``__asm`` and ``__asm__`` are alternate spellings for ``asm``, but available in
+`__asm` and `__asm__` are alternate spellings for `asm`, but available in
all language modes.
-__complex, __complex__
-----------------------
+### \_\_complex, \_\_complex\_\_
-``__complex`` and ``__complex__`` are alternate spellings for ``_Complex``.
+`__complex` and `__complex__` are alternate spellings for `_Complex`.
-__const, __const__, __volatile, __volatile__, __restrict, __restrict__
-----------------------------------------------------------------------
+### \_\_const, \_\_const\_\_, \_\_volatile, \_\_volatile\_\_, \_\_restrict, \_\_restrict\_\_
These are alternate spellings for their non-underscore counterparts, but are
available in all language modes.
-__decltype
-----------
+### \_\_decltype
-``__decltype`` is an alternate spelling for ``decltype``, but is also available
+`__decltype` is an alternate spelling for `decltype`, but is also available
in C++ modes before C++11.
-__inline, __inline__
---------------------
+### \_\_inline, \_\_inline\_\_
-``__inline`` and ``__inline__`` are alternate spellings for ``inline``, but are
+`__inline` and `__inline__` are alternate spellings for `inline`, but are
available in all language modes.
-__nullptr
----------
+### \_\_nullptr
-``__nullptr`` is an alternate spelling for ``nullptr``. It is available in all C and C++ language modes.
+`__nullptr` is an alternate spelling for `nullptr`. It is available in all C and C++ language modes.
-__signed, __signed__
---------------------
+### \_\_signed, \_\_signed\_\_
-``__signed`` and ``__signed__`` are alternate spellings for ``signed``.
-``__unsigned`` and ``__unsigned__`` are **not** supported.
+`__signed` and `__signed__` are alternate spellings for `signed`.
+`__unsigned` and `__unsigned__` are **not** supported.
-__typeof, __typeof__, __typeof_unqual, __typeof_unqual__
---------------------------------------------------------
+### \_\_typeof, \_\_typeof\_\_, \_\_typeof_unqual, \_\_typeof_unqual\_\_
-``__typeof`` and ``__typeof__`` are alternate spellings for ``typeof``, but are
+`__typeof` and `__typeof__` are alternate spellings for `typeof`, but are
available in all language modes. These spellings result in the operand,
retaining all qualifiers.
-``__typeof_unqual`` and ``__typeof_unqual__`` are alternate spellings for the
-C23 ``typeof_unqual`` type specifier, but are available in all language modes.
+`__typeof_unqual` and `__typeof_unqual__` are alternate spellings for the
+C23 `typeof_unqual` type specifier, but are available in all language modes.
These spellings result in the type of the operand, stripping all qualifiers.
-__char16_t, __char32_t
-----------------------
+### \_\_char16_t, \_\_char32_t
-``__char16_t`` and ``__char32_t`` are alternate spellings for ``char16_t`` and
-``char32_t`` respectively, but are also available in C++ modes before C++11.
-They are only supported in C++. ``__char8_t`` is not available.
+`__char16_t` and `__char32_t` are alternate spellings for `char16_t` and
+`char32_t` respectively, but are also available in C++ modes before C++11.
+They are only supported in C++. `__char8_t` is not available.
-..
- FIXME: This should list all the keyword extensions
+% FIXME: This should list all the keyword extensions
-.. _langext-vectors:
+(langext-vectors)=
-Vectors and Extended Vectors
-============================
+## Vectors and Extended Vectors
Supports the GCC, OpenCL, AltiVec, NEON, SVE and RVV vector extensions.
-OpenCL vector types are created using the ``ext_vector_type`` attribute. It
-supports the ``V.xyzw`` syntax and other tidbits as seen in OpenCL. An example
+OpenCL vector types are created using the `ext_vector_type` attribute. It
+supports the `V.xyzw` syntax and other tidbits as seen in OpenCL. An example
is:
-.. code-block:: c++
-
- typedef float float4 __attribute__((ext_vector_type(4)));
- typedef float float2 __attribute__((ext_vector_type(2)));
-
- float4 foo(float2 a, float2 b) {
- float4 c;
- c.xz = a;
- c.yw = b;
- return c;
- }
-
-Query for this feature with ``__has_attribute(ext_vector_type)``.
-
-Giving ``-maltivec`` option to clang enables support for AltiVec vector syntax
-and functions. For example:
-
-.. code-block:: c++
-
- vector float foo(vector int a) {
- vector int b;
- b = vec_add(a, a) + a;
- return (vector float)b;
- }
-
-NEON vector types are created using ``neon_vector_type`` and
-``neon_polyvector_type`` attributes. For example:
-
-.. code-block:: c++
-
- typedef __attribute__((neon_vector_type(8))) int8_t int8x8_t;
- typedef __attribute__((neon_polyvector_type(16))) poly8_t poly8x16_t;
-
- int8x8_t foo(int8x8_t a) {
- int8x8_t v;
- v = a;
- return v;
- }
-
-GCC vector types are created using the ``vector_size(N)`` attribute. The
-argument ``N`` specifies the number of bytes that will be allocated for an
-object of this type. The size has to be a multiple of the size of the vector
+```c++
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef float float2 __attribute__((ext_vector_type(2)));
+
+float4 foo(float2 a, float2 b) {
+ float4 c;
+ c.xz = a;
+ c.yw = b;
+ return c;
+}
+```
+
+Query for this feature with `__has_attribute(ext_vector_type)`.
+
+Giving `-maltivec` option to clang enables support for AltiVec vector syntax
+and functions. For example:
+
+```c++
+vector float foo(vector int a) {
+ vector int b;
+ b = vec_add(a, a) + a;
+ return (vector float)b;
+}
+```
+
+NEON vector types are created using `neon_vector_type` and
+`neon_polyvector_type` attributes. For example:
+
+```c++
+typedef __attribute__((neon_vector_type(8))) int8_t int8x8_t;
+typedef __attribute__((neon_polyvector_type(16))) poly8_t poly8x16_t;
+
+int8x8_t foo(int8x8_t a) {
+ int8x8_t v;
+ v = a;
+ return v;
+}
+```
+
+GCC vector types are created using the `vector_size(N)` attribute. The
+argument `N` specifies the number of bytes that will be allocated for an
+object of this type. The size has to be a multiple of the size of the vector
element type. For example:
-.. code-block:: c++
-
- // OK: This declares a vector type with four 'int' elements
- typedef int int4 __attribute__((vector_size(4 * sizeof(int))));
-
- // ERROR: '11' is not a multiple of sizeof(int)
- typedef int int_impossible __attribute__((vector_size(11)));
-
- int4 foo(int4 a) {
- int4 v;
- v = a;
- return v;
- }
-
+```c++
+// OK: This declares a vector type with four 'int' elements
+typedef int int4 __attribute__((vector_size(4 * sizeof(int))));
-Boolean Vectors
----------------
+// ERROR: '11' is not a multiple of sizeof(int)
+typedef int int_impossible __attribute__((vector_size(11)));
-Clang also supports the ``ext_vector_type`` attribute with boolean element types in
-C and C++. For example:
+int4 foo(int4 a) {
+ int4 v;
+ v = a;
+ return v;
+}
+```
-.. code-block:: c++
+### Boolean Vectors
- // legal for Clang, error for GCC:
- typedef bool bool4 __attribute__((ext_vector_type(4)));
- // Objects of bool4 type hold 8 bits, sizeof(bool4) == 1
+Clang also supports the `ext_vector_type` attribute with boolean element types in
+C and C++. For example:
- bool4 foo(bool4 a) {
- bool4 v;
- v = a;
- return v;
- }
+```c++
+// legal for Clang, error for GCC:
+typedef bool bool4 __attribute__((ext_vector_type(4)));
+// Objects of bool4 type hold 8 bits, sizeof(bool4) == 1
+bool4 foo(bool4 a) {
+ bool4 v;
+ v = a;
+ return v;
+}
+```
-Boolean vectors are a Clang extension of the ext vector type. Boolean vectors
-are intended, though not guaranteed, to map to vector mask registers. The size
-parameter of a boolean vector type is the number of bits in the vector. The
+Boolean vectors are a Clang extension of the ext vector type. Boolean vectors
+are intended, though not guaranteed, to map to vector mask registers. The size
+parameter of a boolean vector type is the number of bits in the vector. The
boolean vector is dense and each bit in the boolean vector is one vector
-element. Query for this feature with ``__has_feature(ext_vector_type_boolean)``.
+element. Query for this feature with `__has_feature(ext_vector_type_boolean)`.
The semantics of boolean vectors borrows from C bit-fields with the following
differences:
-* Distinct boolean vectors are always distinct memory objects (there is no
+- Distinct boolean vectors are always distinct memory objects (there is no
packing).
-* Only the operators `?:`, `!`, `~`, `|`, `&`, `^` and comparison are allowed on
+- Only the operators `?:`, `!`, `~`, `|`, `&`, `^` and comparison are allowed on
boolean vectors.
-* Casting a scalar bool value to a boolean vector type means broadcasting the
+- Casting a scalar bool value to a boolean vector type means broadcasting the
scalar value onto all lanes (same as general ext_vector_type).
The size and alignment are both the number of bits rounded up to the next power
@@ -661,111 +632,107 @@ target.
A boolean vector can be used in a ternary `?:` operator to select vector
elements of a different type.
-.. code-block:: c++
-
- typedef int int4 __attribute__((ext_vector_type(4)));
- typedef bool bool4 __attribute__((ext_vector_type(4)));
+```c++
+typedef int int4 __attribute__((ext_vector_type(4)));
+typedef bool bool4 __attribute__((ext_vector_type(4)));
- int4 blend(bool4 cond, int4 a, int4 b) { return cond ? a : b; }
+int4 blend(bool4 cond, int4 a, int4 b) { return cond ? a : b; }
+```
-
-Vector Literals
----------------
+### Vector Literals
Vector literals can be used to create vectors from a set of scalars, or
-vectors. Either parentheses or braces form can be used. In the parentheses
+vectors. Either parentheses or braces form can be used. In the parentheses
form the number of literal values specified must be one, i.e., referring to a
-scalar value, or must match the size of the vector type being created. If a
+scalar value, or must match the size of the vector type being created. If a
single scalar literal value is specified, the scalar literal value will be
-replicated to all the components of the vector type. In the brackets form any
-number of literals can be specified. For example:
-
-.. code-block:: c++
-
- typedef int v4si __attribute__((__vector_size__(16)));
- typedef float float4 __attribute__((ext_vector_type(4)));
- typedef float float2 __attribute__((ext_vector_type(2)));
-
- v4si vsi = (v4si){1, 2, 3, 4};
- float4 vf = (float4)(1.0f, 2.0f, 3.0f, 4.0f);
- vector int vi1 = (vector int)(1); // vi1 will be (1, 1, 1, 1).
- vector int vi2 = (vector int){1}; // vi2 will be (1, 0, 0, 0).
- vector int vi3 = (vector int)(1, 2); // error
- vector int vi4 = (vector int){1, 2}; // vi4 will be (1, 2, 0, 0).
- vector int vi5 = (vector int)(1, 2, 3, 4);
- float4 vf = (float4)((float2)(1.0f, 2.0f), (float2)(3.0f, 4.0f));
-
-Vector Operations
------------------
-
-The table below shows the support for each operation by vector extension. A
+replicated to all the components of the vector type. In the brackets form any
+number of literals can be specified. For example:
+
+```c++
+typedef int v4si __attribute__((__vector_size__(16)));
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef float float2 __attribute__((ext_vector_type(2)));
+
+v4si vsi = (v4si){1, 2, 3, 4};
+float4 vf = (float4)(1.0f, 2.0f, 3.0f, 4.0f);
+vector int vi1 = (vector int)(1); // vi1 will be (1, 1, 1, 1).
+vector int vi2 = (vector int){1}; // vi2 will be (1, 0, 0, 0).
+vector int vi3 = (vector int)(1, 2); // error
+vector int vi4 = (vector int){1, 2}; // vi4 will be (1, 2, 0, 0).
+vector int vi5 = (vector int)(1, 2, 3, 4);
+float4 vf = (float4)((float2)(1.0f, 2.0f), (float2)(3.0f, 4.0f));
+```
+
+### Vector Operations
+
+The table below shows the support for each operation by vector extension. A
dash indicates that an operation is not accepted according to a corresponding
specification.
-============================== ======= ======= ============= ======= ============ ===========
- Operator OpenCL AltiVec GCC NEON SVE RVV
-============================== ======= ======= ============= ======= ============ ===========
-[] yes yes yes yes yes yes
-unary operators +, -- yes yes yes yes yes yes
-++, -- -- yes yes yes no no no
-+,--,*,/,% yes yes yes yes yes yes
-bitwise operators &,|,^,~ yes yes yes yes yes yes
->>,<< yes yes yes yes yes yes
-!, &&, || yes -- yes yes yes yes
-==, !=, >, <, >=, <= yes yes yes yes yes yes
-= yes yes yes yes yes yes
-?: [#]_ yes -- yes yes yes yes
-sizeof yes yes yes yes yes [#vls]_ yes [#vls]_
-C-style cast yes yes yes no no yes
-reinterpret_cast yes no yes no no yes
-static_cast yes no yes no no yes
-const_cast no no no no no no
-address &v[i] no no no [#]_ no no no
-============================== ======= ======= ============= ======= ============ ===========
+| Operator | OpenCL | AltiVec | GCC | NEON | SVE | RVV |
+| -------------------------- | ------ | ------- | ---------------- | ---- | ---------- | ---------- |
+| [] | yes | yes | yes | yes | yes | yes |
+| unary operators +, -- | yes | yes | yes | yes | yes | yes |
+| ++, -- -- | yes | yes | yes | no | no | no |
+| +,--,\*,/,% | yes | yes | yes | yes | yes | yes |
+| bitwise operators &,\|,^,~ | yes | yes | yes | yes | yes | yes |
+| >>,\<< | yes | yes | yes | yes | yes | yes |
+| !, &&, \|\| | yes | -- | yes | yes | yes | yes |
+| ==, !=, >, \<, >=, \<= | yes | yes | yes | yes | yes | yes |
+| = | yes | yes | yes | yes | yes | yes |
+| ?: [^footnote-1] | yes | -- | yes | yes | yes | yes |
+| sizeof | yes | yes | yes | yes | yes [^vls] | yes [^vls] |
+| C-style cast | yes | yes | yes | no | no | yes |
+| reinterpret_cast | yes | no | yes | no | no | yes |
+| static_cast | yes | no | yes | no | no | yes |
+| const_cast | no | no | no | no | no | no |
+| address &v[i] | no | no | no [^footnote-2] | no | no | no |
Both SVE and RVV define sizeless vector types which cannot be used in globals,
-structs, unions, or arrays. Both provide an attribute (``arm_sve_vector_bits``
-and ``riscv_rvv_vector_bits`` respectively) to create fixed-length
-vector-length-specific (VLS) variants that remove these restrictions. Using
-these attributes requires the command line option ``-msve-vector-bits=<N>`` or
-``-mrvv-vector-bits=<N>`` respectively. For SVE, the operators above are
-supported on both sizeless and VLS types. For RVV, the operators are only
+structs, unions, or arrays. Both provide an attribute (`arm_sve_vector_bits`
+and `riscv_rvv_vector_bits` respectively) to create fixed-length
+vector-length-specific (VLS) variants that remove these restrictions. Using
+these attributes requires the command line option `-msve-vector-bits=<N>` or
+`-mrvv-vector-bits=<N>` respectively. For SVE, the operators above are
+supported on both sizeless and VLS types. For RVV, the operators are only
supported on VLS types.
-See also :ref:`langext-__builtin_shufflevector`, :ref:`langext-__builtin_convertvector`.
+See also {ref}`langext-__builtin_shufflevector`, {ref}`langext-__builtin_convertvector`.
+
+[^footnote-1]: ternary operator(?:) has different behaviors depending on the condition
+ operand's vector type. If the condition is a GNU vector (i.e., `__vector_size__`),
+ a NEON vector, an SVE vector or an RVV vector, it's only available in C++
+ and uses normal bool conversions (that is, != 0).
+ If it's an extension (OpenCL) vector, it's only available in C and OpenCL C.
+ And it selects based on the signedness of the condition operands (OpenCL v1.1 s6.3.9).
-.. [#] ternary operator(?:) has different behaviors depending on the condition
- operand's vector type. If the condition is a GNU vector (i.e., ``__vector_size__``),
- a NEON vector, an SVE vector or an RVV vector, it's only available in C++
- and uses normal bool conversions (that is, != 0).
- If it's an extension (OpenCL) vector, it's only available in C and OpenCL C.
- And it selects based on the signedness of the condition operands (OpenCL v1.1 s6.3.9).
-.. [#vls] sizeof can only be used on vector length specific SVE and RVV types.
-.. [#] Clang does not allow the address of an element to be taken while GCC
- allows this. This is intentional for vectors with a boolean element type and
- not implemented otherwise.
+[^vls]: sizeof can only be used on vector length specific SVE and RVV types.
-Vector Builtins
----------------
+[^footnote-2]: Clang does not allow the address of an element to be taken while GCC
+ allows this. This is intentional for vectors with a boolean element type and
+ not implemented otherwise.
+
+### Vector Builtins
**Note: The implementation of vector builtins is work-in-progress and incomplete.**
In addition to the operators mentioned above, Clang provides a set of builtins
to perform additional operations on certain scalar and vector types.
-Let ``T`` be one of the following types:
+Let `T` be one of the following types:
-* an integer type (as in C23 6.2.5p22), but excluding enumerated types and ``bool``
-* the standard floating types ``float`` or ``double``
-* a half-precision floating point type, if one is supported on the target
-* a vector type.
+- an integer type (as in C23 6.2.5p22), but excluding enumerated types and `bool`
+- the standard floating types `float` or `double`
+- a half-precision floating point type, if one is supported on the target
+- a vector type.
For scalar types, consider the operation applied to a vector with a single element.
*Vector Size*
-To determine the number of elements in a vector, use ``__builtin_vectorelements()``.
-For fixed-sized vectors, e.g., defined via ``__attribute__((vector_size(N)))`` or ARM
-NEON's vector types (e.g., ``uint16x8_t``), this returns the constant number of
+To determine the number of elements in a vector, use `__builtin_vectorelements()`.
+For fixed-sized vectors, e.g., defined via `__attribute__((vector_size(N)))` or ARM
+NEON's vector types (e.g., `uint16x8_t`), this returns the constant number of
elements at compile-time. For scalable vectors, e.g., SVE or RISC-V V, the number of
elements is not known at compile-time and is determined at runtime. This builtin can
be used, e.g., to increment the loop-counter in vector-type agnostic loops.
@@ -777,318 +744,231 @@ elementwise to the input.
Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±infinity
-The elementwise intrinsics ``__builtin_elementwise_popcount``,
-``__builtin_elementwise_bitreverse``, ``__builtin_elementwise_add_sat``,
-``__builtin_elementwise_sub_sat``, ``__builtin_elementwise_max``,
-``__builtin_elementwise_min``, ``__builtin_elementwise_abs``,
-``__builtin_elementwise_clzg``, ``__builtin_elementwise_ctzg``, and
-``__builtin_elementwise_fma`` can be called in a ``constexpr`` context.
+The elementwise intrinsics `__builtin_elementwise_popcount`,
+`__builtin_elementwise_bitreverse`, `__builtin_elementwise_add_sat`,
+`__builtin_elementwise_sub_sat`, `__builtin_elementwise_max`,
+`__builtin_elementwise_min`, `__builtin_elementwise_abs`,
+`__builtin_elementwise_clzg`, `__builtin_elementwise_ctzg`, and
+`__builtin_elementwise_fma` can be called in a `constexpr` context.
No implicit promotion of integer types takes place. The mixing of integer types
of different sizes and signs is forbidden in binary and ternary builtins.
-============================================== ====================================================================== =========================================
- Name Operation Supported element types
-============================================== ====================================================================== =========================================
- T __builtin_elementwise_abs(T x) return the absolute value of a number x; the absolute value of signed integer and floating point types
- the most negative integer remains the most negative integer
- T __builtin_elementwise_fma(T x, T y, T z) fused multiply add, (x * y) + z. floating point types
- T __builtin_elementwise_ceil(T x) return the smallest integral value greater than or equal to x floating point types
- T __builtin_elementwise_sin(T x) return the sine of x interpreted as an angle in radians floating point types
- T __builtin_elementwise_cos(T x) return the cosine of x interpreted as an angle in radians floating point types
- T __builtin_elementwise_tan(T x) return the tangent of x interpreted as an angle in radians floating point types
- T __builtin_elementwise_asin(T x) return the arcsine of x interpreted as an angle in radians floating point types
- T __builtin_elementwise_acos(T x) return the arccosine of x interpreted as an angle in radians floating point types
- T __builtin_elementwise_atan(T x) return the arctangent of x interpreted as an angle in radians floating point types
- T __builtin_elementwise_atan2(T y, T x) return the arctangent of y/x floating point types
- T __builtin_elementwise_sinh(T x) return the hyperbolic sine of angle x in radians floating point types
- T __builtin_elementwise_cosh(T x) return the hyperbolic cosine of angle x in radians floating point types
- T __builtin_elementwise_tanh(T x) return the hyperbolic tangent of angle x in radians floating point types
- T __builtin_elementwise_floor(T x) return the largest integral value less than or equal to x floating point types
- T __builtin_elementwise_log(T x) return the natural logarithm of x floating point types
- T __builtin_elementwise_log2(T x) return the base 2 logarithm of x floating point types
- T __builtin_elementwise_log10(T x) return the base 10 logarithm of x floating point types
- T __builtin_elementwise_popcount(T x) return the number of 1 bits in x integer types
- T __builtin_elementwise_pow(T x, T y) return x raised to the power of y floating point types
- T __builtin_elementwise_bitreverse(T x) return the integer represented after reversing the bits of x integer types
- T __builtin_elementwise_exp(T x) returns the base-e exponential, e^x, of the specified value floating point types
- T __builtin_elementwise_exp2(T x) returns the base-2 exponential, 2^x, of the specified value floating point types
- T __builtin_elementwise_exp10(T x) returns the base-10 exponential, 10^x, of the specified value floating point types
- T __builtin_elementwise_ldexp(T x, IntT y) returns the product of x and 2 raised to the power y. T: floating point types,
- y must be an integer type matching the shape of x. IntT: integer types
-
- T __builtin_elementwise_sqrt(T x) return the square root of a floating-point number floating point types
- T __builtin_elementwise_roundeven(T x) round x to the nearest integer value in floating point format, floating point types
- rounding halfway cases to even (that is, to the nearest value
- that is an even integer), regardless of the current rounding
- direction.
- T __builtin_elementwise_round(T x) round x to the nearest integer value in floating point format, floating point types
- rounding halfway cases away from zero, regardless of the
- current rounding direction. May raise floating-point
- exceptions.
- T __builtin_elementwise_trunc(T x) return the integral value nearest to but no larger in floating point types
- magnitude than x
-
- T __builtin_elementwise_nearbyint(T x) round x to the nearest integer value in floating point format, floating point types
- rounding according to the current rounding direction.
- May not raise the inexact floating-point exception. This is
- treated the same as ``__builtin_elementwise_rint`` unless
- :ref:`FENV_ACCESS is enabled <floating-point-environment>`.
-
- T __builtin_elementwise_rint(T x) round x to the nearest integer value in floating point format, floating point types
- rounding according to the current rounding
- direction. May raise floating-point exceptions. This is treated
- the same as ``__builtin_elementwise_nearbyint`` unless
- :ref:`FENV_ACCESS is enabled <floating-point-environment>`.
-
- T __builtin_elementwise_canonicalize(T x) return the platform specific canonical encoding floating point types
- of a floating-point number
- T __builtin_elementwise_copysign(T x, T y) return the magnitude of x with the sign of y. floating point types
- T __builtin_elementwise_fmod(T x, T y) return the floating-point remainder of (x/y) whose sign floating point types
- matches the sign of x.
- T __builtin_elementwise_max(T x, T y) return x or y, whichever is larger integer
- For floating point types, follows semantics of maxNum floating point types (deprecated)
- in IEEE 754-2008. See `LangRef
- <http://llvm.org/docs/LangRef.html#i-fminmax-family>`_
- for the comparison.
- T __builtin_elementwise_min(T x, T y) return x or y, whichever is smaller integer
- For floating point types, follows semantics of minNum floating point types (deprecated)
- in IEEE 754-2008. See `LangRef
- <http://llvm.org/docs/LangRef.html#i-fminmax-family>`_
- for the comparison.
- T __builtin_elementwise_maxnum(T x, T y) return x or y, whichever is larger. Follows IEEE 754-2008 floating point types
- semantics (maxNum) with +0.0>-0.0. See `LangRef
- <http://llvm.org/docs/LangRef.html#i-fminmax-family>`_
- for the comparison.
- T __builtin_elementwise_minnum(T x, T y) return x or y, whichever is smaller. Follows IEEE 754-2008 floating point types
- semantics (minNum) with +0.0>-0.0. See `LangRef
- <http://llvm.org/docs/LangRef.html#i-fminmax-family>`_
- for the comparison.
- T __builtin_elementwise_add_sat(T x, T y) return the sum of x and y, clamped to the range of integer types
- representable values for the signed/unsigned integer type.
- T __builtin_elementwise_sub_sat(T x, T y) return the difference of x and y, clamped to the range of integer types
- representable values for the signed/unsigned integer type.
- T __builtin_elementwise_maximum(T x, T y) return x or y, whichever is larger. Follows IEEE 754-2019 floating point types
- semantics, see `LangRef
- <http://llvm.org/docs/LangRef.html#i-fminmax-family>`_
- for the comparison.
- T __builtin_elementwise_minimum(T x, T y) return x or y, whichever is smaller. Follows IEEE 754-2019 floating point types
- semantics, see `LangRef
- <http://llvm.org/docs/LangRef.html#i-fminmax-family>`_
- for the comparison.
- T __builtin_elementwise_maximumnum(T x, T y) return x or y, whichever is larger. Follows IEEE 754-2019 floating point types
- semantics, see `LangRef
- <http://llvm.org/docs/LangRef.html#i-fminmax-family>`_
- for the comparison.
- T __builtin_elementwise_minimumnum(T x, T y) return x or y, whichever is smaller. Follows IEEE 754-2019 floating point types
- semantics, see `LangRef
- <http://llvm.org/docs/LangRef.html#i-fminmax-family>`_
- for the comparison.
-T __builtin_elementwise_fshl(T x, T y, T z) perform a funnel shift left. Concatenate x and y (x is the most integer types
- significant bits of the wide value), the combined value is shifted
- left by z (modulo the bit width of the original arguments),
- and the most significant bits are extracted to produce
- a result that is the same size as the original arguments.
-
-T __builtin_elementwise_fshr(T x, T y, T z) perform a funnel shift right. Concatenate x and y (x is the most integer types
- significant bits of the wide value), the combined value is shifted
- right by z (modulo the bit width of the original arguments),
- and the least significant bits are extracted to produce
- a result that is the same size as the original arguments.
- T __builtin_elementwise_clzg(T x[, T y]) return the number of leading 0 bits in the first argument. If integer types
- the first argument is 0 and an optional second argument is provided,
- the second argument is returned. It is undefined behaviour if the
- first argument is 0 and no second argument is provided.
- T __builtin_elementwise_ctzg(T x[, T y]) return the number of trailing 0 bits in the first argument. If integer types
- the first argument is 0 and an optional second argument is provided,
- the second argument is returned. It is undefined behaviour if the
- first argument is 0 and no second argument is provided.
-T __builtin_elementwise_clmul(T x, T y) perform a carry-less multiplication of x and y, returning the least integer types
- significant bits of the wide result.
-T __builtin_elementwise_pext(T x, T m) extract bits from x selected by the mask m, pack them contiguously integer types
- into the least significant bits of the result, and zero the rest.
-T __builtin_elementwise_pdep(T x, T m) deposit the least significant bits of x at the positions integer types
- where m has a 1-bit, and zero the rest.
-============================================== ====================================================================== =========================================
-
+| Name | Operation | Supported element types |
+| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------- |
+| T \_\_builtin_elementwise_abs(T x) | return the absolute value of a number x; the absolute value of the most negative integer remains the most negative integer | signed integer and floating point types |
+| T \_\_builtin_elementwise_fma(T x, T y, T z) | fused multiply add, (x * y) + z. | floating point types |
+| T \_\_builtin_elementwise_ceil(T x) | return the smallest integral value greater than or equal to x | floating point types |
+| T \_\_builtin_elementwise_sin(T x) | return the sine of x interpreted as an angle in radians | floating point types |
+| T \_\_builtin_elementwise_cos(T x) | return the cosine of x interpreted as an angle in radians | floating point types |
+| T \_\_builtin_elementwise_tan(T x) | return the tangent of x interpreted as an angle in radians | floating point types |
+| T \_\_builtin_elementwise_asin(T x) | return the arcsine of x interpreted as an angle in radians | floating point types |
+| T \_\_builtin_elementwise_acos(T x) | return the arccosine of x interpreted as an angle in radians | floating point types |
+| T \_\_builtin_elementwise_atan(T x) | return the arctangent of x interpreted as an angle in radians | floating point types |
+| T \_\_builtin_elementwise_atan2(T y, T x) | return the arctangent of y/x | floating point types |
+| T \_\_builtin_elementwise_sinh(T x) | return the hyperbolic sine of angle x in radians | floating point types |
+| T \_\_builtin_elementwise_cosh(T x) | return the hyperbolic cosine of angle x in radians | floating point types |
+| T \_\_builtin_elementwise_tanh(T x) | return the hyperbolic tangent of angle x in radians | floating point types |
+| T \_\_builtin_elementwise_floor(T x) | return the largest integral value less than or equal to x | floating point types |
+| T \_\_builtin_elementwise_log(T x) | return the natural logarithm of x | floating point types |
+| T \_\_builtin_elementwise_log2(T x) | return the base 2 logarithm of x | floating point types |
+| T \_\_builtin_elementwise_log10(T x) | return the base 10 logarithm of x | floating point types |
+| T \_\_builtin_elementwise_popcount(T x) | return the number of 1 bits in x | integer types |
+| T \_\_builtin_elementwise_pow(T x, T y) | return x raised to the power of y | floating point types |
+| T \_\_builtin_elementwise_bitreverse(T x) | return the integer represented after reversing the bits of x | integer types |
+| T \_\_builtin_elementwise_exp(T x) | returns the base-e exponential, e^x, of the specified value | floating point types |
+| T \_\_builtin_elementwise_exp2(T x) | returns the base-2 exponential, 2^x, of the specified value | floating point types |
+| T \_\_builtin_elementwise_exp10(T x) | returns the base-10 exponential, 10^x, of the specified value | floating point types |
+| T \_\_builtin_elementwise_ldexp(T x, IntT y) | returns the product of x and 2 raised to the power y. y must be an integer type matching the shape of x. | T: floating point types, IntT: integer types |
+| T \_\_builtin_elementwise_sqrt(T x) | return the square root of a floating-point number | floating point types |
+| T \_\_builtin_elementwise_roundeven(T x) | round x to the nearest integer value in floating point format, rounding halfway cases to even (that is, to the nearest value that is an even integer), regardless of the current rounding direction. | floating point types |
+| T \_\_builtin_elementwise_round(T x) | round x to the nearest integer value in floating point format, rounding halfway cases away from zero, regardless of the current rounding direction. May raise floating-point exceptions. | floating point types |
+| T \_\_builtin_elementwise_trunc(T x) | return the integral value nearest to but no larger in magnitude than x | floating point types |
+| T \_\_builtin_elementwise_nearbyint(T x) | round x to the nearest integer value in floating point format, rounding according to the current rounding direction. May not raise the inexact floating-point exception. This is treated the same as `__builtin_elementwise_rint` unless {ref}`FENV_ACCESS is enabled <floating-point-environment>`. | floating point types |
+| T \_\_builtin_elementwise_rint(T x) | round x to the nearest integer value in floating point format, rounding according to the current rounding direction. May raise floating-point exceptions. This is treated the same as `__builtin_elementwise_nearbyint` unless {ref}`FENV_ACCESS is enabled <floating-point-environment>`. | floating point types |
+| T \_\_builtin_elementwise_canonicalize(T x) | return the platform specific canonical encoding of a floating-point number | floating point types |
+| T \_\_builtin_elementwise_copysign(T x, T y) | return the magnitude of x with the sign of y. | floating point types |
+| T \_\_builtin_elementwise_fmod(T x, T y) | return the floating-point remainder of (x/y) whose sign matches the sign of x. | floating point types |
+| T \_\_builtin_elementwise_max(T x, T y) | return x or y, whichever is larger For floating point types, follows semantics of maxNum in IEEE 754-2008. See [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison. | integer floating point types (deprecated) |
+| T \_\_builtin_elementwise_min(T x, T y) | return x or y, whichever is smaller For floating point types, follows semantics of minNum in IEEE 754-2008. See [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison. | integer floating point types (deprecated) |
+| T \_\_builtin_elementwise_maxnum(T x, T y) | return x or y, whichever is larger. Follows IEEE 754-2008 semantics (maxNum) with +0.0>-0.0. See [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison. | floating point types |
+| T \_\_builtin_elementwise_minnum(T x, T y) | return x or y, whichever is smaller. Follows IEEE 754-2008 semantics (minNum) with +0.0>-0.0. See [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison. | floating point types |
+| T \_\_builtin_elementwise_add_sat(T x, T y) | return the sum of x and y, clamped to the range of representable values for the signed/unsigned integer type. | integer types |
+| T \_\_builtin_elementwise_sub_sat(T x, T y) | return the difference of x and y, clamped to the range of representable values for the signed/unsigned integer type. | integer types |
+| T \_\_builtin_elementwise_maximum(T x, T y) | return x or y, whichever is larger. Follows IEEE 754-2019 semantics, see [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison. | floating point types |
+| T \_\_builtin_elementwise_minimum(T x, T y) | return x or y, whichever is smaller. Follows IEEE 754-2019 semantics, see [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison. | floating point types |
+| T \_\_builtin_elementwise_maximumnum(T x, T y) | return x or y, whichever is larger. Follows IEEE 754-2019 semantics, see [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison. | floating point types |
+| T \_\_builtin_elementwise_minimumnum(T x, T y) | return x or y, whichever is smaller. Follows IEEE 754-2019 semantics, see [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison. | floating point types |
+| T \_\_builtin_elementwise_fshl(T x, T y, T z) | perform a funnel shift left. Concatenate x and y (x is the most significant bits of the wide value), the combined value is shifted left by z (modulo the bit width of the original arguments), and the most significant bits are extracted to produce a result that is the same size as the original arguments. | integer types |
+| T \_\_builtin_elementwise_fshr(T x, T y, T z) | perform a funnel shift right. Concatenate x and y (x is the most significant bits of the wide value), the combined value is shifted right by z (modulo the bit width of the original arguments), and the least significant bits are extracted to produce a result that is the same size as the original arguments. | integer types |
+| T \_\_builtin_elementwise_clzg(T x[, T y]) | return the number of leading 0 bits in the first argument. If the first argument is 0 and an optional second argument is provided, the second argument is returned. It is undefined behaviour if the first argument is 0 and no second argument is provided. | integer types |
+| T \_\_builtin_elementwise_ctzg(T x[, T y]) | return the number of trailing 0 bits in the first argument. If the first argument is 0 and an optional second argument is provided, the second argument is returned. It is undefined behaviour if the first argument is 0 and no second argument is provided. | integer types |
+| T \_\_builtin_elementwise_clmul(T x, T y) | perform a carry-less multiplication of x and y, returning the least significant bits of the wide result. | integer types |
+| T \_\_builtin_elementwise_pext(T x, T m) | extract bits from x selected by the mask m, pack them contiguously into the least significant bits of the result, and zero the rest. | integer types |
+| T \_\_builtin_elementwise_pdep(T x, T m) | deposit the least significant bits of x at the positions where m has a 1-bit, and zero the rest. | integer types |
*Reduction Builtins*
Each builtin returns a scalar equivalent to applying the specified
operation(x, y) as recursive even-odd pairwise reduction to all vector
-elements. ``operation(x, y)`` is repeatedly applied to each non-overlapping
-even-odd element pair with indices ``i * 2`` and ``i * 2 + 1`` with
-``i in [0, Number of elements / 2)``. If the number of elements is not a
+elements. `operation(x, y)` is repeatedly applied to each non-overlapping
+even-odd element pair with indices `i * 2` and `i * 2 + 1` with
+`i in [0, Number of elements / 2)`. If the number of elements is not a
power of 2, the vector is widened with neutral elements for the reduction
at the end to the next power of 2.
These reductions support both fixed-sized and scalable vector types.
-The integer reduction intrinsics, including ``__builtin_reduce_max``,
-``__builtin_reduce_min``, ``__builtin_reduce_add``, ``__builtin_reduce_mul``,
-``__builtin_reduce_and``, ``__builtin_reduce_or``, and ``__builtin_reduce_xor``,
-can be called in a ``constexpr`` context.
+The integer reduction intrinsics, including `__builtin_reduce_max`,
+`__builtin_reduce_min`, `__builtin_reduce_add`, `__builtin_reduce_mul`,
+`__builtin_reduce_and`, `__builtin_reduce_or`, and `__builtin_reduce_xor`,
+can be called in a `constexpr` context.
Example:
-.. code-block:: c++
-
- __builtin_reduce_add([e3, e2, e1, e0]) = __builtin_reduced_add([e3 + e2, e1 + e0])
- = (e3 + e2) + (e1 + e0)
-
-
-Let ``VT`` be a vector type and ``ET`` the element type of ``VT``.
-
-============================================== ====================================================================== ==================================
- Name Operation Supported element types
-============================================== ====================================================================== ==================================
- ET __builtin_reduce_max(VT a) return the largest element of the vector. The floating point result integer and floating point types
- will always be a number unless all elements of the vector are NaN.
- ET __builtin_reduce_min(VT a) return the smallest element of the vector. The floating point result integer and floating point types
- will always be a number unless all elements of the vector are NaN.
- ET __builtin_reduce_add(VT a) \+ integer types
- ET __builtin_reduce_mul(VT a) \* integer types
- ET __builtin_reduce_and(VT a) & integer types
- ET __builtin_reduce_or(VT a) \| integer types
- ET __builtin_reduce_xor(VT a) ^ integer types
- ET __builtin_reduce_maximum(VT a) return the largest element of the vector. Follows IEEE 754-2019 floating point types
- semantics, see `LangRef
- <http://llvm.org/docs/LangRef.html#i-fminmax-family>`_
- for the comparison.
- ET __builtin_reduce_minimum(VT a) return the smallest element of the vector. Follows IEEE 754-2019 floating point types
- semantics, see `LangRef
- <http://llvm.org/docs/LangRef.html#i-fminmax-family>`_
- for the comparison.
- ET __builtin_reduce_assoc_fadd(VT a[, ET s]) associative floating-point add reduction. floating point types
- ET __builtin_reduce_in_order_fadd(VT a, ET s) in order floating-point add reduction, initializing the accumulator floating point types
- with `(ET)s`, then adding each lane of the `a` in-order, starting
- from lane 0. The additions cannot be reassociated.
-============================================== ====================================================================== ==================================
+```c++
+__builtin_reduce_add([e3, e2, e1, e0]) = __builtin_reduced_add([e3 + e2, e1 + e0])
+ = (e3 + e2) + (e1 + e0)
+```
+
+Let `VT` be a vector type and `ET` the element type of `VT`.
+
+| Name | Operation | Supported element types |
+| ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
+| ET \_\_builtin_reduce_max(VT a) | return the largest element of the vector. The floating point result will always be a number unless all elements of the vector are NaN. | integer and floating point types |
+| ET \_\_builtin_reduce_min(VT a) | return the smallest element of the vector. The floating point result will always be a number unless all elements of the vector are NaN. | integer and floating point types |
+| ET \_\_builtin_reduce_add(VT a) | + | integer types |
+| ET \_\_builtin_reduce_mul(VT a) | \* | integer types |
+| ET \_\_builtin_reduce_and(VT a) | & | integer types |
+| ET \_\_builtin_reduce_or(VT a) | \| | integer types |
+| ET \_\_builtin_reduce_xor(VT a) | ^ | integer types |
+| ET \_\_builtin_reduce_maximum(VT a) | return the largest element of the vector. Follows IEEE 754-2019 semantics, see [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison. | floating point types |
+| ET \_\_builtin_reduce_minimum(VT a) | return the smallest element of the vector. Follows IEEE 754-2019 semantics, see [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison. | floating point types |
+| ET \_\_builtin_reduce_assoc_fadd(VT a[, ET s]) | associative floating-point add reduction. | floating point types |
+| ET \_\_builtin_reduce_in_order_fadd(VT a, ET s) | in order floating-point add reduction, initializing the accumulator with `(ET)s`, then adding each lane of the `a` in-order, starting from lane 0. The additions cannot be reassociated. | floating point types |
*Masked Builtins*
Each builtin accesses memory according to a provided boolean mask. These are
-provided as ``__builtin_masked_load`` and ``__builtin_masked_store``. The first
-argument is always a boolean mask vector. The ``__builtin_masked_load`` builtin
+provided as `__builtin_masked_load` and `__builtin_masked_store`. The first
+argument is always a boolean mask vector. The `__builtin_masked_load` builtin
takes an optional third vector argument that will be used for the result of the
masked-off lanes. These builtins assume the memory is unaligned, use
-``__builtin_assume_aligned`` if alignment is desired.
+`__builtin_assume_aligned` if alignment is desired.
-The ``__builtin_masked_expand_load`` and ``__builtin_masked_compress_store``
+The `__builtin_masked_expand_load` and `__builtin_masked_compress_store`
builtins have the same interface but store the result in consecutive indices.
-Effectively this performs the ``if (mask[i]) val[i] = ptr[j++]`` and ``if
-(mask[i]) ptr[j++] = val[i]`` pattern respectively.
+Effectively this performs the `if (mask[i]) val[i] = ptr[j++]` and `if
+(mask[i]) ptr[j++] = val[i]` pattern respectively.
-The ``__builtin_masked_gather`` and ``__builtin_masked_scatter`` builtins handle
+The `__builtin_masked_gather` and `__builtin_masked_scatter` builtins handle
non-sequential memory access for vector types. These use a base pointer and a
vector of integer indices to gather memory into a vector type or scatter it to
separate indices.
Example:
-.. code-block:: c++
-
- using v8b = bool [[clang::ext_vector_type(8)]];
- using v8i = int [[clang::ext_vector_type(8)]];
+```c++
+using v8b = bool [[clang::ext_vector_type(8)]];
+using v8i = int [[clang::ext_vector_type(8)]];
- v8i load(v8b mask, int *ptr) { return __builtin_masked_load(mask, ptr); }
-
- v8i load_expand(v8b mask, int *ptr) {
- return __builtin_masked_expand_load(mask, ptr);
- }
+v8i load(v8b mask, int *ptr) { return __builtin_masked_load(mask, ptr); }
- void store(v8b mask, v8i val, int *ptr) {
- __builtin_masked_store(mask, val, ptr);
- }
+v8i load_expand(v8b mask, int *ptr) {
+ return __builtin_masked_expand_load(mask, ptr);
+}
- void store_compress(v8b mask, v8i val, int *ptr) {
- __builtin_masked_compress_store(mask, val, ptr);
- }
+void store(v8b mask, v8i val, int *ptr) {
+ __builtin_masked_store(mask, val, ptr);
+}
- v8i gather(v8b mask, v8i idx, int *ptr) {
- return __builtin_masked_gather(mask, idx, ptr);
- }
+void store_compress(v8b mask, v8i val, int *ptr) {
+ __builtin_masked_compress_store(mask, val, ptr);
+}
- void scatter(v8b mask, v8i val, v8i idx, int *ptr) {
- __builtin_masked_scatter(mask, idx, val, ptr);
- }
+v8i gather(v8b mask, v8i idx, int *ptr) {
+ return __builtin_masked_gather(mask, idx, ptr);
+}
+void scatter(v8b mask, v8i val, v8i idx, int *ptr) {
+ __builtin_masked_scatter(mask, idx, val, ptr);
+}
+```
-Matrix Types
-============
+## Matrix Types
Clang provides an extension for matrix types, which is currently being
-implemented. See :ref:`the draft specification <matrixtypes>` for more details.
+implemented. See {ref}`the draft specification <matrixtypes>` for more details.
For example, the code below uses the matrix types extension to multiply two 4x4
float matrices and add the result to a third 4x4 matrix.
-.. code-block:: c++
-
- typedef float m4x4_t __attribute__((matrix_type(4, 4)));
+```c++
+typedef float m4x4_t __attribute__((matrix_type(4, 4)));
- m4x4_t f(m4x4_t a, m4x4_t b, m4x4_t c) {
- return a + b * c;
- }
+m4x4_t f(m4x4_t a, m4x4_t b, m4x4_t c) {
+ return a + b * c;
+}
+```
The matrix type extension also supports operations on a matrix and a scalar.
-.. code-block:: c++
-
- typedef float m4x4_t __attribute__((matrix_type(4, 4)));
+```c++
+typedef float m4x4_t __attribute__((matrix_type(4, 4)));
- m4x4_t f(m4x4_t a) {
- return (a + 23) * 12;
- }
+m4x4_t f(m4x4_t a) {
+ return (a + 23) * 12;
+}
+```
The matrix type extension supports division on a matrix and a scalar but not on a matrix and a matrix.
-.. code-block:: c++
-
- typedef float m4x4_t __attribute__((matrix_type(4, 4)));
+```c++
+typedef float m4x4_t __attribute__((matrix_type(4, 4)));
- m4x4_t f(m4x4_t a) {
- a = a / 3.0;
- return a;
- }
+m4x4_t f(m4x4_t a) {
+ a = a / 3.0;
+ return a;
+}
+```
The matrix type extension supports compound assignments for addition, subtraction, and multiplication on matrices
and on a matrix and a scalar, provided their types are consistent.
-.. code-block:: c++
-
- typedef float m4x4_t __attribute__((matrix_type(4, 4)));
+```c++
+typedef float m4x4_t __attribute__((matrix_type(4, 4)));
- m4x4_t f(m4x4_t a, m4x4_t b) {
- a += b;
- a -= b;
- a *= b;
- a += 23;
- a -= 12;
- return a;
- }
+m4x4_t f(m4x4_t a, m4x4_t b) {
+ a += b;
+ a -= b;
+ a *= b;
+ a += 23;
+ a -= 12;
+ return a;
+}
+```
The matrix type extension supports explicit casts. Implicit type conversion between matrix types is not allowed.
-.. code-block:: c++
-
- typedef int ix5x5 __attribute__((matrix_type(5, 5)));
- typedef float fx5x5 __attribute__((matrix_type(5, 5)));
+```c++
+typedef int ix5x5 __attribute__((matrix_type(5, 5)));
+typedef float fx5x5 __attribute__((matrix_type(5, 5)));
- fx5x5 f1(ix5x5 i, fx5x5 f) {
- return (fx5x5) i;
- }
+fx5x5 f1(ix5x5 i, fx5x5 f) {
+ return (fx5x5) i;
+}
- template <typename X>
- using matrix_4_4 = X __attribute__((matrix_type(4, 4)));
+template <typename X>
+using matrix_4_4 = X __attribute__((matrix_type(4, 4)));
- void f2() {
- matrix_5_5<double> d;
- matrix_5_5<int> i;
- i = (matrix_5_5<int>)d;
- i = static_cast<matrix_5_5<int>>(d);
- }
+void f2() {
+ matrix_5_5<double> d;
+ matrix_5_5<int> i;
+ i = (matrix_5_5<int>)d;
+ i = static_cast<matrix_5_5<int>>(d);
+}
+```
The matrix type extension supports column and row major memory layouts, but not
all builtins are supported with row-major layout. The layout defaults to column
@@ -1096,66 +976,64 @@ major and can be specified using `-fmatrix-memory-layout`. To enable column
major layout, use `-fmatrix-memory-layout=column-major`, and for row major
layout use `-fmatrix-memory-layout=row-major`
-Half-Precision Floating Point
-=============================
+## Half-Precision Floating Point
Clang supports three half-precision (16-bit) floating point types:
-``__fp16``, ``_Float16`` and ``__bf16``. These types are supported
+`__fp16`, `_Float16` and `__bf16`. These types are supported
in all language modes, but their support differs between targets.
A target is said to have "native support" for a type if the target
processor offers instructions for directly performing basic arithmetic
-on that type. In the absence of native support, a type can still be
+on that type. In the absence of native support, a type can still be
supported if the compiler can emulate arithmetic on the type by promoting
-to ``float``; see below for more information on this emulation.
+to `float`; see below for more information on this emulation.
-* ``__fp16`` is supported on all targets. The special semantics of this
- type mean that no arithmetic is ever performed directly on ``__fp16`` values;
+- `__fp16` is supported on all targets. The special semantics of this
+ type mean that no arithmetic is ever performed directly on `__fp16` values;
see below.
-* ``_Float16`` is supported on the following targets:
+- `_Float16` is supported on the following targets:
- * 32-bit ARM (natively on some architecture versions)
- * 64-bit ARM (AArch64) (natively on ARMv8.2a and above)
- * AMDGPU (natively)
- * NVPTX (natively)
- * SPIR (natively)
- * X86 (if SSE2 is available; natively if AVX512-FP16 is also available)
- * RISC-V (natively if Zfh or Zhinx is available)
- * SystemZ (emulated)
- * LoongArch (emulated)
+ - 32-bit ARM (natively on some architecture versions)
+ - 64-bit ARM (AArch64) (natively on ARMv8.2a and above)
+ - AMDGPU (natively)
+ - NVPTX (natively)
+ - SPIR (natively)
+ - X86 (if SSE2 is available; natively if AVX512-FP16 is also available)
+ - RISC-V (natively if Zfh or Zhinx is available)
+ - SystemZ (emulated)
+ - LoongArch (emulated)
-* ``__bf16`` is supported on the following targets (currently never natively):
+- `__bf16` is supported on the following targets (currently never natively):
- * 32-bit ARM
- * 64-bit ARM (AArch64)
- * RISC-V
- * X86 (when SSE2 is available)
- * LoongArch
+ - 32-bit ARM
+ - 64-bit ARM (AArch64)
+ - RISC-V
+ - X86 (when SSE2 is available)
+ - LoongArch
(For X86, SSE2 is available on 64-bit and all recent 32-bit processors.)
-``__fp16`` and ``_Float16`` both use the binary16 format from IEEE
+`__fp16` and `_Float16` both use the binary16 format from IEEE
754-2008, which provides a 5-bit exponent and an 11-bit significand
-(including the implicit leading 1). ``__bf16`` uses the `bfloat16
-<https://en.wikipedia.org/wiki/Bfloat16_floating-point_format>`_ format,
+(including the implicit leading 1). `__bf16` uses the [bfloat16](https://en.wikipedia.org/wiki/Bfloat16_floating-point_format) format,
which provides an 8-bit exponent and an 8-bit significand; this is the same
exponent range as `float`, just with greatly reduced precision.
-``_Float16`` and ``__bf16`` follow the usual rules for arithmetic
+`_Float16` and `__bf16` follow the usual rules for arithmetic
floating-point types. Most importantly, this means that arithmetic operations
on operands of these types are formally performed in the type and produce
-values of the type. ``__fp16`` does not follow those rules: most operations
-immediately promote operands of type ``__fp16`` to ``float``, and so
-arithmetic operations are defined to be performed in ``float`` and so result in
-a value of type ``float`` (unless further promoted because of other operands).
+values of the type. `__fp16` does not follow those rules: most operations
+immediately promote operands of type `__fp16` to `float`, and so
+arithmetic operations are defined to be performed in `float` and so result in
+a value of type `float` (unless further promoted because of other operands).
See below for more information on the exact specifications of these types.
-When compiling arithmetic on ``_Float16`` and ``__bf16`` for a target without
-native support, Clang will perform the arithmetic in ``float``, inserting
+When compiling arithmetic on `_Float16` and `__bf16` for a target without
+native support, Clang will perform the arithmetic in `float`, inserting
extensions and truncations as necessary. This can be done in a way that
exactly matches the operation-by-operation behavior of native support,
but that can require many extra truncations and extensions. By default,
-when emulating ``_Float16`` and ``__bf16`` arithmetic using ``float``, Clang
+when emulating `_Float16` and `__bf16` arithmetic using `float`, Clang
does not truncate intermediate operands back to their true type unless the
operand is the result of an explicit cast or assignment. This is generally
much faster but can generate different results from strict operation-by-operation
@@ -1165,153 +1043,147 @@ see the discussion of evaluation formats in the C standard and [expr.pre] in
the C++ standard.
The use of excess precision can be independently controlled for these two
-types with the ``-ffloat16-excess-precision=`` and
-``-fbfloat16-excess-precision=`` options. Valid values include:
+types with the `-ffloat16-excess-precision=` and
+`-fbfloat16-excess-precision=` options. Valid values include:
-* ``none``: meaning to perform strict operation-by-operation emulation
-* ``standard``: meaning that excess precision is permitted under the rules
+- `none`: meaning to perform strict operation-by-operation emulation
+- `standard`: meaning that excess precision is permitted under the rules
described in the standard, i.e., never across explicit casts or statements
-* ``fast``: meaning that excess precision is permitted whenever the
+- `fast`: meaning that excess precision is permitted whenever the
optimizer sees an opportunity to avoid truncations; currently this has no
- effect beyond ``standard``
+ effect beyond `standard`
-The ``_Float16`` type is an interchange floating type specified in
+The `_Float16` type is an interchange floating type specified in
ISO/IEC TS 18661-3:2015 ("Floating-point extensions for C"). It will
be supported on more targets as they define ABIs for it.
-The ``__bf16`` type is a non-standard extension, but it generally follows
+The `__bf16` type is a non-standard extension, but it generally follows
the rules for arithmetic interchange floating types from ISO/IEC TS
18661-3:2015. In previous versions of Clang, it was a storage-only type
that forbade arithmetic operations. It will be supported on more targets
as they define ABIs for it.
-The ``__fp16`` type was originally an ARM extension and is specified
-by the `ARM C Language Extensions <https://github.com/ARM-software/acle/releases>`_.
-Clang uses the ``binary16`` format from IEEE 754-2008 for ``__fp16``,
+The `__fp16` type was originally an ARM extension and is specified
+by the [ARM C Language Extensions](https://github.com/ARM-software/acle/releases).
+Clang uses the `binary16` format from IEEE 754-2008 for `__fp16`,
not the ARM alternative format. Operators that expect arithmetic operands
-immediately promote ``__fp16`` operands to ``float``.
+immediately promote `__fp16` operands to `float`.
-It is recommended that portable code use ``_Float16`` instead of ``__fp16``,
+It is recommended that portable code use `_Float16` instead of `__fp16`,
as it has been defined by the C standards committee and has behavior that is
more familiar to most programmers.
-Because ``__fp16`` operands are always immediately promoted to ``float``, the
-common real type of ``__fp16`` and ``_Float16`` for the purposes of the usual
-arithmetic conversions is ``float``.
+Because `__fp16` operands are always immediately promoted to `float`, the
+common real type of `__fp16` and `_Float16` for the purposes of the usual
+arithmetic conversions is `float`.
-A literal can be given ``_Float16`` type using the suffix ``f16``. For example,
-``3.14f16``.
+A literal can be given `_Float16` type using the suffix `f16`. For example,
+`3.14f16`.
Because default argument promotion only applies to the standard floating-point
-types, ``_Float16`` values are not promoted to ``double`` when passed as variadic
+types, `_Float16` values are not promoted to `double` when passed as variadic
or untyped arguments. As a consequence, some caution must be taken when using
-certain library facilities with ``_Float16``; for example, there is no ``printf`` format
-specifier for ``_Float16``, and (unlike ``float``) it will not be implicitly promoted to
-``double`` when passed to ``printf``, so the programmer must explicitly cast it to
-``double`` before using it with an ``%f`` or similar specifier.
+certain library facilities with `_Float16`; for example, there is no `printf` format
+specifier for `_Float16`, and (unlike `float`) it will not be implicitly promoted to
+`double` when passed to `printf`, so the programmer must explicitly cast it to
+`double` before using it with an `%f` or similar specifier.
-Pragmas
-=======
+## Pragmas
-#pragma export
---------------
+### #pragma export
Clang supports the export pragma used to indicate an
-external symbol is to be exported from the shared library being built. The
+external symbol is to be exported from the shared library being built. The
syntax for the pragma is:
-.. code-block:: c++
-
- #pragma export (name)
-
-where ``name`` is the name of the external function or variable to be
-exported. The symbol needs to have external linkage. The pragma may appear
-before or after the declaration of ``name``, but must precede the
-definition. The pragma must also appear at file scope. If ``name`` is not
-defined, the pragma will have no effect. The pragma needs to be specified
-in the same translation unit as ``name`` is defined.
-
-The pragma has the same effect as adding ``__attribute__((visibility("default")))``
-to the declaration of ``name``.
+```c++
+#pragma export (name)
+```
-In C++, the function being exported must be declared as ``extern "C"``. If the
-function has overloads, the pragma only applies to the overload with ``extern "C"``
-linkage. For example:
+where `name` is the name of the external function or variable to be
+exported. The symbol needs to have external linkage. The pragma may appear
+before or after the declaration of `name`, but must precede the
+definition. The pragma must also appear at file scope. If `name` is not
+defined, the pragma will have no effect. The pragma needs to be specified
+in the same translation unit as `name` is defined.
-.. code-block:: c++
+The pragma has the same effect as adding `__attribute__((visibility("default")))`
+to the declaration of `name`.
- #pragma export(func)
- int func(double) { return 0; }
- extern "C" int func(int) { return 4;}
+In C++, the function being exported must be declared as `extern "C"`. If the
+function has overloads, the pragma only applies to the overload with `extern "C"`
+linkage. For example:
-In the code above the pragma will export ``func(int)`` but not ``func(double)``.
+```c++
+#pragma export(func)
+int func(double) { return 0; }
+extern "C" int func(int) { return 4;}
+```
-If none of the overloads are declared with ``extern "C"`` a warning will be
-generated saying the pragma didn't resolve to a declaration. For example:
+In the code above the pragma will export `func(int)` but not `func(double)`.
-.. code-block:: c++
+If none of the overloads are declared with `extern "C"` a warning will be
+generated saying the pragma didn't resolve to a declaration. For example:
- #pragma export(func)
- int func(double) { return 0; } // warning: failed to resolve '#pragma export' to a declaration
+```c++
+#pragma export(func)
+int func(double) { return 0; } // warning: failed to resolve '#pragma export' to a declaration
+```
-Overflow behavior types
-=======================
+## Overflow behavior types
Clang provides an extension that allows developers to annotate integer types
with explicit overflow behavior. This enables fine-grained control over whether
arithmetic operations should wrap on overflow (with two's complement semantics)
or be checked for overflow (trapping or reporting via sanitizers).
-This feature is experimental and must be enabled with the ``-cc1`` option
-``-fexperimental-overflow-behavior-types``.
+This feature is experimental and must be enabled with the `-cc1` option
+`-fexperimental-overflow-behavior-types`.
-Query for this feature with ``__has_extension(overflow_behavior_types)``.
+Query for this feature with `__has_extension(overflow_behavior_types)`.
-Syntax
-------
+### Syntax
Overflow behavior can be specified using either attribute syntax or keyword
syntax:
**Attribute syntax:**
-.. code-block:: c
-
- typedef int __attribute__((overflow_behavior(wrap))) wrapping_int;
- typedef int __attribute__((overflow_behavior(trap))) checked_int;
+```c
+typedef int __attribute__((overflow_behavior(wrap))) wrapping_int;
+typedef int __attribute__((overflow_behavior(trap))) checked_int;
+```
**Keyword syntax:**
-.. code-block:: c
-
- typedef int __ob_wrap wrapping_int;
- typedef int __ob_trap checked_int;
+```c
+typedef int __ob_wrap wrapping_int;
+typedef int __ob_trap checked_int;
+```
The annotation can also be applied directly to variable declarations:
-.. code-block:: c
+```c
+int __ob_wrap counter = 0;
+unsigned __ob_trap safe_index = 0;
+```
- int __ob_wrap counter = 0;
- unsigned __ob_trap safe_index = 0;
-
-Semantics
----------
+### Semantics
**wrap behavior:**
-When an integer type is annotated with ``wrap`` (or ``__ob_wrap``), arithmetic
+When an integer type is annotated with `wrap` (or `__ob_wrap`), arithmetic
operations on values of that type use two's complement wrapping semantics on
overflow. This behavior is well-defined regardless of signedness. Compilers
must not optimize based on the assumption that overflow does not occur.
**trap behavior:**
-When an integer type is annotated with ``trap`` (or ``__ob_trap``), arithmetic
+When an integer type is annotated with `trap` (or `__ob_trap`), arithmetic
operations on values of that type are checked for overflow. If overflow occurs,
the program traps or reports via sanitizers (depending on compiler settings).
-Integer Promotions and Conversions
-----------------------------------
+### Integer Promotions and Conversions
Overflow behavior types follow standard C integer promotion and conversion
rules. The overflow behavior annotation is preserved through implicit
@@ -1319,29 +1191,29 @@ promotions and conversions.
**Standard promotion rules apply:**
-Integer literals without a suffix have type ``int`` (or a larger type if the
+Integer literals without a suffix have type `int` (or a larger type if the
value requires it), following normal C rules. When such a literal is used in
an operation with an overflow behavior type, standard promotion rules determine
the result type, and the overflow behavior is propagated:
-.. code-block:: c
-
- typedef int __ob_wrap wrap_int;
- wrap_int x = 100;
- wrap_int y = x + 1; // 1 is promoted; result is __ob_wrap int
+```c
+typedef int __ob_wrap wrap_int;
+wrap_int x = 100;
+wrap_int y = x + 1; // 1 is promoted; result is __ob_wrap int
+```
**Combining different overflow behaviors:**
-When operands have different overflow behaviors, ``trap`` takes precedence
-over ``wrap``:
+When operands have different overflow behaviors, `trap` takes precedence
+over `wrap`:
-.. code-block:: c
-
- typedef int __ob_wrap wrap_int;
- typedef int __ob_trap trap_int;
- wrap_int a = 1;
- trap_int b = 2;
- auto c = a + b; // Result is __ob_trap int (trap dominates)
+```c
+typedef int __ob_wrap wrap_int;
+typedef int __ob_trap trap_int;
+wrap_int a = 1;
+trap_int b = 2;
+auto c = a + b; // Result is __ob_trap int (trap dominates)
+```
**Conversion to standard types:**
@@ -1349,546 +1221,483 @@ When an overflow behavior type is converted to a standard integer type (without
an overflow behavior annotation), the overflow behavior is discarded. Compilers
may warn about this:
-.. code-block:: c
-
- typedef int __ob_wrap wrap_int;
- wrap_int w = 42;
- int i = w; // Warning: discards overflow behavior
+```c
+typedef int __ob_wrap wrap_int;
+wrap_int w = 42;
+int i = w; // Warning: discards overflow behavior
+```
-Interaction with Compiler Flags
--------------------------------
+### Interaction with Compiler Flags
Overflow behavior annotations take precedence over global compiler flags:
-- A ``wrap`` type wraps on overflow even when ``-ftrapv`` is enabled.
-- A ``trap`` type is checked for overflow even when ``-fwrapv`` is enabled.
+- A `wrap` type wraps on overflow even when `-ftrapv` is enabled.
+- A `trap` type is checked for overflow even when `-fwrapv` is enabled.
This allows mixing different overflow behaviors within the same program,
enabling developers to selectively apply wrapping or checking to specific
types while using different defaults elsewhere.
-Incompatible Assignments
-------------------------
+### Incompatible Assignments
-Direct assignment between types with different overflow behaviors (``wrap``
-vs ``trap``) is an error:
+Direct assignment between types with different overflow behaviors (`wrap`
+vs `trap`) is an error:
-.. code-block:: c
+```c
+int __ob_wrap w;
+int __ob_trap t;
+w = t; // Error: incompatible overflow behaviors
+```
- int __ob_wrap w;
- int __ob_trap t;
- w = t; // Error: incompatible overflow behaviors
+For more detailed documentation, see {doc}`OverflowBehaviorTypes`.
-For more detailed documentation, see :doc:`OverflowBehaviorTypes`.
+## Messages on `deprecated` and `unavailable` Attributes
-Messages on ``deprecated`` and ``unavailable`` Attributes
-=========================================================
+An optional string message can be added to the `deprecated` and
+`unavailable` attributes. For example:
-An optional string message can be added to the ``deprecated`` and
-``unavailable`` attributes. For example:
-
-.. code-block:: c++
-
- void explode(void) __attribute__((deprecated("extremely unsafe, use 'combust' instead!!!")));
+```c++
+void explode(void) __attribute__((deprecated("extremely unsafe, use 'combust' instead!!!")));
+```
If the deprecated or unavailable declaration is used, the message will be
incorporated into the appropriate diagnostic:
-.. code-block:: none
-
- harmless.c:4:3: warning: 'explode' is deprecated: extremely unsafe, use 'combust' instead!!!
- [-Wdeprecated-declarations]
- explode();
- ^
+```none
+harmless.c:4:3: warning: 'explode' is deprecated: extremely unsafe, use 'combust' instead!!!
+ [-Wdeprecated-declarations]
+ explode();
+ ^
+```
Query for this feature with
-``__has_extension(attribute_deprecated_with_message)`` and
-``__has_extension(attribute_unavailable_with_message)``.
+`__has_extension(attribute_deprecated_with_message)` and
+`__has_extension(attribute_unavailable_with_message)`.
-Attributes on Enumerators
-=========================
+## Attributes on Enumerators
-Clang allows attributes to be written on individual enumerators. This allows
-enumerators to be deprecated, made unavailable, etc. The attribute must appear
+Clang allows attributes to be written on individual enumerators. This allows
+enumerators to be deprecated, made unavailable, etc. The attribute must appear
after the enumerator name and before any initializer, like so:
-.. code-block:: c++
-
- enum OperationMode {
- OM_Invalid,
- OM_Normal,
- OM_Terrified __attribute__((deprecated)),
- OM_AbortOnError __attribute__((deprecated)) = 4
- };
+```c++
+enum OperationMode {
+ OM_Invalid,
+ OM_Normal,
+ OM_Terrified __attribute__((deprecated)),
+ OM_AbortOnError __attribute__((deprecated)) = 4
+};
+```
-Attributes on the ``enum`` declaration do not apply to individual enumerators.
+Attributes on the `enum` declaration do not apply to individual enumerators.
-Query for this feature with ``__has_extension(enumerator_attributes)``.
+Query for this feature with `__has_extension(enumerator_attributes)`.
-C++11 Attributes on using-declarations
-======================================
+## C++11 Attributes on using-declarations
-Clang allows C++-style ``[[]]`` attributes to be written on using-declarations.
+Clang allows C++-style `[[]]` attributes to be written on using-declarations.
For instance:
-.. code-block:: c++
-
- [[clang::using_if_exists]] using foo::bar;
- using foo::baz [[clang::using_if_exists]];
+```c++
+[[clang::using_if_exists]] using foo::bar;
+using foo::baz [[clang::using_if_exists]];
+```
You can test for support for this extension with
-``__has_extension(cxx_attributes_on_using_declarations)``.
+`__has_extension(cxx_attributes_on_using_declarations)`.
-'User-Specified' System Frameworks
-==================================
+## 'User-Specified' System Frameworks
Clang provides a mechanism by which frameworks can be built in such a way that
they will always be treated as being "system frameworks", even if they are not
-present in a system framework directory. This can be useful to system
+present in a system framework directory. This can be useful to system
framework developers who want to be able to test building other applications
with development builds of their framework, including the manner in which the
compiler changes warning behavior for system headers.
Framework developers can opt-in to this mechanism by creating a
-"``.system_framework``" file at the top-level of their framework. That is, the
+"`.system_framework`" file at the top-level of their framework. That is, the
framework should have contents like:
-.. code-block:: none
-
- .../TestFramework.framework
- .../TestFramework.framework/.system_framework
- .../TestFramework.framework/Headers
- .../TestFramework.framework/Headers/TestFramework.h
- ...
+```none
+.../TestFramework.framework
+.../TestFramework.framework/.system_framework
+.../TestFramework.framework/Headers
+.../TestFramework.framework/Headers/TestFramework.h
+...
+```
Clang will treat the presence of this file as an indicator that the framework
should be treated as a system framework, regardless of how it was found in the
-framework search path. For consistency, we recommend that such files never be
+framework search path. For consistency, we recommend that such files never be
included in installed versions of the framework.
-Checks for Standard Language Features
-=====================================
+## Checks for Standard Language Features
-The ``__has_feature`` macro can be used to query if certain standard language
-features are enabled. The ``__has_extension`` macro can be used to query if
+The `__has_feature` macro can be used to query if certain standard language
+features are enabled. The `__has_extension` macro can be used to query if
language features are available as an extension when compiling for a standard
-which does not provide them. The features which can be tested are listed here.
+which does not provide them. The features which can be tested are listed here.
Since Clang 3.4, the C++ SD-6 feature test macros are also supported.
-These are macros with names of the form ``__cpp_<feature_name>``, and are
+These are macros with names of the form `__cpp_<feature_name>`, and are
intended to be a portable way to query the supported features of the compiler.
-See `the C++ status page <https://clang.llvm.org/cxx_status.html#ts>`_ for
+See [the C++ status page](https://clang.llvm.org/cxx_status.html#ts) for
information on the version of SD-6 supported by each Clang release, and the
macros provided by that revision of the recommendations.
-C++98
------
+### C++98
-The features listed below are part of the C++98 standard. These features are
+The features listed below are part of the C++98 standard. These features are
enabled by default when compiling C++ code.
-C++ exceptions
-^^^^^^^^^^^^^^
+#### C++ exceptions
-Use ``__has_feature(cxx_exceptions)`` to determine if C++ exceptions have been
-enabled. For example, compiling code with ``-fno-exceptions`` disables C++
+Use `__has_feature(cxx_exceptions)` to determine if C++ exceptions have been
+enabled. For example, compiling code with `-fno-exceptions` disables C++
exceptions.
-C++ RTTI
-^^^^^^^^
+#### C++ RTTI
-Use ``__has_feature(cxx_rtti)`` to determine if C++ RTTI has been enabled. For
-example, compiling code with ``-fno-rtti`` disables the use of RTTI.
+Use `__has_feature(cxx_rtti)` to determine if C++ RTTI has been enabled. For
+example, compiling code with `-fno-rtti` disables the use of RTTI.
-C++11
------
+### C++11
-The features listed below are part of the C++11 standard. As a result, all
-these features are enabled with the ``-std=c++11`` or ``-std=gnu++11`` option
+The features listed below are part of the C++11 standard. As a result, all
+these features are enabled with the `-std=c++11` or `-std=gnu++11` option
when compiling C++ code.
-C++11 SFINAE includes access control
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 SFINAE includes access control
-Use ``__has_feature(cxx_access_control_sfinae)`` or
-``__has_extension(cxx_access_control_sfinae)`` to determine whether
+Use `__has_feature(cxx_access_control_sfinae)` or
+`__has_extension(cxx_access_control_sfinae)` to determine whether
access-control errors (e.g., calling a private constructor) are considered to
-be template argument deduction errors (aka SFINAE errors), per `C++ DR1170
-<http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1170>`_.
+be template argument deduction errors (aka SFINAE errors), per [C++ DR1170](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1170).
-C++11 alias templates
-^^^^^^^^^^^^^^^^^^^^^
+#### C++11 alias templates
-Use ``__has_feature(cxx_alias_templates)`` or
-``__has_extension(cxx_alias_templates)`` to determine if support for C++11's
+Use `__has_feature(cxx_alias_templates)` or
+`__has_extension(cxx_alias_templates)` to determine if support for C++11's
alias declarations and alias templates is enabled.
-C++11 alignment specifiers
-^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 alignment specifiers
-Use ``__has_feature(cxx_alignas)`` or ``__has_extension(cxx_alignas)`` to
-determine if support for alignment specifiers using ``alignas`` is enabled.
+Use `__has_feature(cxx_alignas)` or `__has_extension(cxx_alignas)` to
+determine if support for alignment specifiers using `alignas` is enabled.
-Use ``__has_feature(cxx_alignof)`` or ``__has_extension(cxx_alignof)`` to
-determine if support for the ``alignof`` keyword is enabled.
+Use `__has_feature(cxx_alignof)` or `__has_extension(cxx_alignof)` to
+determine if support for the `alignof` keyword is enabled.
-C++11 attributes
-^^^^^^^^^^^^^^^^
+#### C++11 attributes
-Use ``__has_feature(cxx_attributes)`` or ``__has_extension(cxx_attributes)`` to
+Use `__has_feature(cxx_attributes)` or `__has_extension(cxx_attributes)` to
determine if support for attribute parsing with C++11's square bracket notation
is enabled.
-C++11 generalized constant expressions
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 generalized constant expressions
-Use ``__has_feature(cxx_constexpr)`` to determine if support for generalized
-constant expressions (e.g., ``constexpr``) is enabled.
+Use `__has_feature(cxx_constexpr)` to determine if support for generalized
+constant expressions (e.g., `constexpr`) is enabled.
-C++11 ``decltype()``
-^^^^^^^^^^^^^^^^^^^^
+#### C++11 `decltype()`
-Use ``__has_feature(cxx_decltype)`` or ``__has_extension(cxx_decltype)`` to
-determine if support for the ``decltype()`` specifier is enabled. C++11's
-``decltype`` does not require type-completeness of a function call expression.
-Use ``__has_feature(cxx_decltype_incomplete_return_types)`` or
-``__has_extension(cxx_decltype_incomplete_return_types)`` to determine if
+Use `__has_feature(cxx_decltype)` or `__has_extension(cxx_decltype)` to
+determine if support for the `decltype()` specifier is enabled. C++11's
+`decltype` does not require type-completeness of a function call expression.
+Use `__has_feature(cxx_decltype_incomplete_return_types)` or
+`__has_extension(cxx_decltype_incomplete_return_types)` to determine if
support for this feature is enabled.
-C++11 default template arguments in function templates
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 default template arguments in function templates
-Use ``__has_feature(cxx_default_function_template_args)`` or
-``__has_extension(cxx_default_function_template_args)`` to determine if support
+Use `__has_feature(cxx_default_function_template_args)` or
+`__has_extension(cxx_default_function_template_args)` to determine if support
for default template arguments in function templates is enabled.
-C++11 ``default``\ ed functions
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 `default`ed functions
-Use ``__has_feature(cxx_defaulted_functions)`` or
-``__has_extension(cxx_defaulted_functions)`` to determine if support for
-defaulted function definitions (with ``= default``) is enabled.
+Use `__has_feature(cxx_defaulted_functions)` or
+`__has_extension(cxx_defaulted_functions)` to determine if support for
+defaulted function definitions (with `= default`) is enabled.
-C++11 delegating constructors
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 delegating constructors
-Use ``__has_feature(cxx_delegating_constructors)`` to determine if support for
+Use `__has_feature(cxx_delegating_constructors)` to determine if support for
delegating constructors is enabled.
-C++11 ``deleted`` functions
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 `deleted` functions
-Use ``__has_feature(cxx_deleted_functions)`` or
-``__has_extension(cxx_deleted_functions)`` to determine if support for deleted
-function definitions (with ``= delete``) is enabled.
+Use `__has_feature(cxx_deleted_functions)` or
+`__has_extension(cxx_deleted_functions)` to determine if support for deleted
+function definitions (with `= delete`) is enabled.
-C++11 explicit conversion functions
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 explicit conversion functions
-Use ``__has_feature(cxx_explicit_conversions)`` to determine if support for
-``explicit`` conversion functions is enabled.
+Use `__has_feature(cxx_explicit_conversions)` to determine if support for
+`explicit` conversion functions is enabled.
-C++11 generalized initializers
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 generalized initializers
-Use ``__has_feature(cxx_generalized_initializers)`` to determine if support for
-generalized initializers (using braced lists and ``std::initializer_list``) is
+Use `__has_feature(cxx_generalized_initializers)` to determine if support for
+generalized initializers (using braced lists and `std::initializer_list`) is
enabled.
-C++11 implicit move constructors/assignment operators
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 implicit move constructors/assignment operators
-Use ``__has_feature(cxx_implicit_moves)`` to determine if Clang will implicitly
+Use `__has_feature(cxx_implicit_moves)` to determine if Clang will implicitly
generate move constructors and move assignment operators where needed.
-C++11 inheriting constructors
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 inheriting constructors
-Use ``__has_feature(cxx_inheriting_constructors)`` to determine if support for
+Use `__has_feature(cxx_inheriting_constructors)` to determine if support for
inheriting constructors is enabled.
-C++11 inline namespaces
-^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 inline namespaces
-Use ``__has_feature(cxx_inline_namespaces)`` or
-``__has_extension(cxx_inline_namespaces)`` to determine if support for inline
+Use `__has_feature(cxx_inline_namespaces)` or
+`__has_extension(cxx_inline_namespaces)` to determine if support for inline
namespaces is enabled.
-C++11 lambdas
-^^^^^^^^^^^^^
+#### C++11 lambdas
-Use ``__has_feature(cxx_lambdas)`` or ``__has_extension(cxx_lambdas)`` to
+Use `__has_feature(cxx_lambdas)` or `__has_extension(cxx_lambdas)` to
determine if support for lambdas is enabled.
-C++11 local and unnamed types as template arguments
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 local and unnamed types as template arguments
-Use ``__has_feature(cxx_local_type_template_args)`` or
-``__has_extension(cxx_local_type_template_args)`` to determine if support for
+Use `__has_feature(cxx_local_type_template_args)` or
+`__has_extension(cxx_local_type_template_args)` to determine if support for
local and unnamed types as template arguments is enabled.
-C++11 noexcept
-^^^^^^^^^^^^^^
+#### C++11 noexcept
-Use ``__has_feature(cxx_noexcept)`` or ``__has_extension(cxx_noexcept)`` to
+Use `__has_feature(cxx_noexcept)` or `__has_extension(cxx_noexcept)` to
determine if support for noexcept exception specifications is enabled.
-C++11 in-class non-static data member initialization
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 in-class non-static data member initialization
-Use ``__has_feature(cxx_nonstatic_member_init)`` to determine whether in-class
+Use `__has_feature(cxx_nonstatic_member_init)` to determine whether in-class
initialization of non-static data members is enabled.
-C++11 ``nullptr``
-^^^^^^^^^^^^^^^^^
+#### C++11 `nullptr`
-Use ``__has_feature(cxx_nullptr)`` or ``__has_extension(cxx_nullptr)`` to
-determine if support for ``nullptr`` is enabled.
+Use `__has_feature(cxx_nullptr)` or `__has_extension(cxx_nullptr)` to
+determine if support for `nullptr` is enabled.
-C++11 ``override control``
-^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 `override control`
-Use ``__has_feature(cxx_override_control)`` or
-``__has_extension(cxx_override_control)`` to determine if support for the
+Use `__has_feature(cxx_override_control)` or
+`__has_extension(cxx_override_control)` to determine if support for the
override control keywords is enabled.
-C++11 reference-qualified functions
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 reference-qualified functions
-Use ``__has_feature(cxx_reference_qualified_functions)`` or
-``__has_extension(cxx_reference_qualified_functions)`` to determine if support
-for reference-qualified functions (e.g., member functions with ``&`` or ``&&``
-applied to ``*this``) is enabled.
+Use `__has_feature(cxx_reference_qualified_functions)` or
+`__has_extension(cxx_reference_qualified_functions)` to determine if support
+for reference-qualified functions (e.g., member functions with `&` or `&&`
+applied to `*this`) is enabled.
-C++11 range-based ``for`` loop
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 range-based `for` loop
-Use ``__has_feature(cxx_range_for)`` or ``__has_extension(cxx_range_for)`` to
+Use `__has_feature(cxx_range_for)` or `__has_extension(cxx_range_for)` to
determine if support for the range-based for loop is enabled.
-C++11 raw string literals
-^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 raw string literals
-Use ``__has_feature(cxx_raw_string_literals)`` to determine if support for raw
-string literals (e.g., ``R"x(foo\bar)x"``) is enabled.
+Use `__has_feature(cxx_raw_string_literals)` to determine if support for raw
+string literals (e.g., `R"x(foo\bar)x"`) is enabled.
-C++11 rvalue references
-^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 rvalue references
-Use ``__has_feature(cxx_rvalue_references)`` or
-``__has_extension(cxx_rvalue_references)`` to determine if support for rvalue
+Use `__has_feature(cxx_rvalue_references)` or
+`__has_extension(cxx_rvalue_references)` to determine if support for rvalue
references is enabled.
-C++11 ``static_assert()``
-^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 `static_assert()`
-Use ``__has_feature(cxx_static_assert)`` or
-``__has_extension(cxx_static_assert)`` to determine if support for compile-time
-assertions using ``static_assert`` is enabled.
+Use `__has_feature(cxx_static_assert)` or
+`__has_extension(cxx_static_assert)` to determine if support for compile-time
+assertions using `static_assert` is enabled.
-C++11 ``thread_local``
-^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 `thread_local`
-Use ``__has_feature(cxx_thread_local)`` to determine if support for
-``thread_local`` variables is enabled.
+Use `__has_feature(cxx_thread_local)` to determine if support for
+`thread_local` variables is enabled.
-C++11 type inference
-^^^^^^^^^^^^^^^^^^^^
+#### C++11 type inference
-Use ``__has_feature(cxx_auto_type)`` or ``__has_extension(cxx_auto_type)`` to
-determine C++11 type inference is supported using the ``auto`` specifier. If
-this is disabled, ``auto`` will instead be a storage class specifier, as in C
+Use `__has_feature(cxx_auto_type)` or `__has_extension(cxx_auto_type)` to
+determine C++11 type inference is supported using the `auto` specifier. If
+this is disabled, `auto` will instead be a storage class specifier, as in C
or C++98.
-C++11 strongly typed enumerations
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 strongly typed enumerations
-Use ``__has_feature(cxx_strong_enums)`` or
-``__has_extension(cxx_strong_enums)`` to determine if support for strongly
+Use `__has_feature(cxx_strong_enums)` or
+`__has_extension(cxx_strong_enums)` to determine if support for strongly
typed, scoped enumerations is enabled.
-C++11 trailing return type
-^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 trailing return type
-Use ``__has_feature(cxx_trailing_return)`` or
-``__has_extension(cxx_trailing_return)`` to determine if support for the
+Use `__has_feature(cxx_trailing_return)` or
+`__has_extension(cxx_trailing_return)` to determine if support for the
alternate function declaration syntax with trailing return type is enabled.
-C++11 Unicode string literals
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 Unicode string literals
-Use ``__has_feature(cxx_unicode_literals)`` to determine if support for Unicode
+Use `__has_feature(cxx_unicode_literals)` to determine if support for Unicode
string literals is enabled.
-C++11 unrestricted unions
-^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 unrestricted unions
-Use ``__has_feature(cxx_unrestricted_unions)`` to determine if support for
+Use `__has_feature(cxx_unrestricted_unions)` to determine if support for
unrestricted unions is enabled.
-C++11 user-defined literals
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 user-defined literals
-Use ``__has_feature(cxx_user_literals)`` to determine if support for
+Use `__has_feature(cxx_user_literals)` to determine if support for
user-defined literals is enabled.
-C++11 variadic templates
-^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++11 variadic templates
-Use ``__has_feature(cxx_variadic_templates)`` or
-``__has_extension(cxx_variadic_templates)`` to determine if support for
+Use `__has_feature(cxx_variadic_templates)` or
+`__has_extension(cxx_variadic_templates)` to determine if support for
variadic templates is enabled.
-C++14
------
+### C++14
-The features listed below are part of the C++14 standard. As a result, all
-these features are enabled with the ``-std=C++14`` or ``-std=gnu++14`` option
+The features listed below are part of the C++14 standard. As a result, all
+these features are enabled with the `-std=C++14` or `-std=gnu++14` option
when compiling C++ code.
-C++14 binary literals
-^^^^^^^^^^^^^^^^^^^^^
+#### C++14 binary literals
-Use ``__has_feature(cxx_binary_literals)`` or
-``__has_extension(cxx_binary_literals)`` to determine whether
-binary literals (for instance, ``0b10010``) are recognized. Clang supports this
+Use `__has_feature(cxx_binary_literals)` or
+`__has_extension(cxx_binary_literals)` to determine whether
+binary literals (for instance, `0b10010`) are recognized. Clang supports this
feature as an extension in all language modes.
-C++14 contextual conversions
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++14 contextual conversions
-Use ``__has_feature(cxx_contextual_conversions)`` or
-``__has_extension(cxx_contextual_conversions)`` to determine if the C++14 rules
+Use `__has_feature(cxx_contextual_conversions)` or
+`__has_extension(cxx_contextual_conversions)` to determine if the C++14 rules
are used when performing an implicit conversion for an array bound in a
*new-expression*, the operand of a *delete-expression*, an integral constant
-expression, or a condition in a ``switch`` statement.
+expression, or a condition in a `switch` statement.
-C++14 decltype(auto)
-^^^^^^^^^^^^^^^^^^^^
+#### C++14 decltype(auto)
-Use ``__has_feature(cxx_decltype_auto)`` or
-``__has_extension(cxx_decltype_auto)`` to determine if support
-for the ``decltype(auto)`` placeholder type is enabled.
+Use `__has_feature(cxx_decltype_auto)` or
+`__has_extension(cxx_decltype_auto)` to determine if support
+for the `decltype(auto)` placeholder type is enabled.
-C++14 default initializers for aggregates
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++14 default initializers for aggregates
-Use ``__has_feature(cxx_aggregate_nsdmi)`` or
-``__has_extension(cxx_aggregate_nsdmi)`` to determine if support
+Use `__has_feature(cxx_aggregate_nsdmi)` or
+`__has_extension(cxx_aggregate_nsdmi)` to determine if support
for default initializers in aggregate members is enabled.
-C++14 digit separators
-^^^^^^^^^^^^^^^^^^^^^^
+#### C++14 digit separators
-Use ``__cpp_digit_separators`` to determine if support for digit separators
-using single quotes (for instance, ``10'000``) is enabled. At this time, there
-is no corresponding ``__has_feature`` name.
+Use `__cpp_digit_separators` to determine if support for digit separators
+using single quotes (for instance, `10'000`) is enabled. At this time, there
+is no corresponding `__has_feature` name.
-C++14 generalized lambda capture
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++14 generalized lambda capture
-Use ``__has_feature(cxx_init_captures)`` or
-``__has_extension(cxx_init_captures)`` to determine if support for
+Use `__has_feature(cxx_init_captures)` or
+`__has_extension(cxx_init_captures)` to determine if support for
lambda captures with explicit initializers is enabled
-(for instance, ``[n(0)] { return ++n; }``).
+(for instance, `[n(0)] { return ++n; }`).
-C++14 generic lambdas
-^^^^^^^^^^^^^^^^^^^^^
+#### C++14 generic lambdas
-Use ``__has_feature(cxx_generic_lambdas)`` or
-``__has_extension(cxx_generic_lambdas)`` to determine if support for generic
+Use `__has_feature(cxx_generic_lambdas)` or
+`__has_extension(cxx_generic_lambdas)` to determine if support for generic
(polymorphic) lambdas is enabled
-(for instance, ``[] (auto x) { return x + 1; }``).
+(for instance, `[] (auto x) { return x + 1; }`).
-C++14 relaxed constexpr
-^^^^^^^^^^^^^^^^^^^^^^^
+#### C++14 relaxed constexpr
-Use ``__has_feature(cxx_relaxed_constexpr)`` or
-``__has_extension(cxx_relaxed_constexpr)`` to determine if variable
+Use `__has_feature(cxx_relaxed_constexpr)` or
+`__has_extension(cxx_relaxed_constexpr)` to determine if variable
declarations, local variable modification, and control flow constructs
-are permitted in ``constexpr`` functions.
+are permitted in `constexpr` functions.
-C++14 return type deduction
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++14 return type deduction
-Use ``__has_feature(cxx_return_type_deduction)`` or
-``__has_extension(cxx_return_type_deduction)`` to determine if support
-for return type deduction for functions (using ``auto`` as a return type)
+Use `__has_feature(cxx_return_type_deduction)` or
+`__has_extension(cxx_return_type_deduction)` to determine if support
+for return type deduction for functions (using `auto` as a return type)
is enabled.
-C++14 runtime-sized arrays
-^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++14 runtime-sized arrays
-Use ``__has_feature(cxx_runtime_array)`` or
-``__has_extension(cxx_runtime_array)`` to determine if support
+Use `__has_feature(cxx_runtime_array)` or
+`__has_extension(cxx_runtime_array)` to determine if support
for arrays of runtime bound (a restricted form of variable-length arrays)
is enabled.
Clang's implementation of this feature is incomplete.
-C++14 variable templates
-^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++14 variable templates
-Use ``__has_feature(cxx_variable_templates)`` or
-``__has_extension(cxx_variable_templates)`` to determine if support for
+Use `__has_feature(cxx_variable_templates)` or
+`__has_extension(cxx_variable_templates)` to determine if support for
templated variable declarations is enabled.
-C++ type aware allocators
-^^^^^^^^^^^^^^^^^^^^^^^^^
+#### C++ type aware allocators
-Use ``__has_extension(cxx_type_aware_allocators)`` to determine the existence of
+Use `__has_extension(cxx_type_aware_allocators)` to determine the existence of
support for the future C++2d type aware allocator feature. For full details, see
-:doc:`C++ Type Aware Allocators <CXXTypeAwareAllocators>` for additional details.
+{doc}`C++ Type Aware Allocators <CXXTypeAwareAllocators>` for additional details.
-C11
----
+### C11
-The features listed below are part of the C11 standard. As a result, all these
-features are enabled with the ``-std=c11`` or ``-std=gnu11`` option when
-compiling C code. Additionally, because these features are all
+The features listed below are part of the C11 standard. As a result, all these
+features are enabled with the `-std=c11` or `-std=gnu11` option when
+compiling C code. Additionally, because these features are all
backward-compatible, they are available as extensions in all language modes.
-C11 alignment specifiers
-^^^^^^^^^^^^^^^^^^^^^^^^
+#### C11 alignment specifiers
-Use ``__has_feature(c_alignas)`` or ``__has_extension(c_alignas)`` to determine
-if support for alignment specifiers using ``_Alignas`` is enabled.
+Use `__has_feature(c_alignas)` or `__has_extension(c_alignas)` to determine
+if support for alignment specifiers using `_Alignas` is enabled.
-Use ``__has_feature(c_alignof)`` or ``__has_extension(c_alignof)`` to determine
-if support for the ``_Alignof`` keyword is enabled.
+Use `__has_feature(c_alignof)` or `__has_extension(c_alignof)` to determine
+if support for the `_Alignof` keyword is enabled.
-C11 atomic operations
-^^^^^^^^^^^^^^^^^^^^^
+#### C11 atomic operations
-Use ``__has_feature(c_atomic)`` or ``__has_extension(c_atomic)`` to determine
-if support for atomic types using ``_Atomic`` is enabled. Clang also provides
-:ref:`a set of builtins <langext-__c11_atomic>` which can be used to implement
-the ``<stdatomic.h>`` operations on ``_Atomic`` types. Use
-``__has_include(<stdatomic.h>)`` to determine if C11's ``<stdatomic.h>`` header
+Use `__has_feature(c_atomic)` or `__has_extension(c_atomic)` to determine
+if support for atomic types using `_Atomic` is enabled. Clang also provides
+{ref}`a set of builtins <langext-__c11_atomic>` which can be used to implement
+the `<stdatomic.h>` operations on `_Atomic` types. Use
+`__has_include(<stdatomic.h>)` to determine if C11's `<stdatomic.h>` header
is available.
-Clang will use the system's ``<stdatomic.h>`` header when one is available, and
+Clang will use the system's `<stdatomic.h>` header when one is available, and
will otherwise use its own. When using its own, implementations of the atomic
operations are provided as macros. In the cases where C11 also requires a real
function, this header provides only the declaration of that function (along
with a shadowing macro implementation), and you must link to a library which
provides a definition of the function if you use it instead of the macro.
-C11 generic selections
-^^^^^^^^^^^^^^^^^^^^^^
+#### C11 generic selections
-Use ``__has_feature(c_generic_selections)`` or
-``__has_extension(c_generic_selections)`` to determine if support for generic
+Use `__has_feature(c_generic_selections)` or
+`__has_extension(c_generic_selections)` to determine if support for generic
selections is enabled.
As an extension, the C11 generic selection expression is available in all
-languages supported by Clang. The syntax is the same as that given in the C11
+languages supported by Clang. The syntax is the same as that given in the C11
standard.
In C, type compatibility is decided according to the rules given in the
appropriate standard, but in C++, which lacks the type compatibility rules used
in C, types are considered compatible only if they are equivalent.
-Clang also supports an extended form of ``_Generic`` with a controlling type
+Clang also supports an extended form of `_Generic` with a controlling type
rather than a controlling expression. Unlike with a controlling expression, a
controlling type argument does not undergo any conversions and thus is suitable
for use when trying to match qualified types, incomplete types, or function
@@ -1896,725 +1705,691 @@ types. Variable-length array types lack the necessary compile-time information
to resolve which association they match with and thus are not allowed as a
controlling type argument.
-Use ``__has_extension(c_generic_selection_with_controlling_type)`` to determine
+Use `__has_extension(c_generic_selection_with_controlling_type)` to determine
if support for this extension is enabled.
-C11 ``_Static_assert()``
-^^^^^^^^^^^^^^^^^^^^^^^^
+#### C11 `_Static_assert()`
-Use ``__has_feature(c_static_assert)`` or ``__has_extension(c_static_assert)``
-to determine if support for compile-time assertions using ``_Static_assert`` is
+Use `__has_feature(c_static_assert)` or `__has_extension(c_static_assert)`
+to determine if support for compile-time assertions using `_Static_assert` is
enabled.
-C11 ``_Thread_local``
-^^^^^^^^^^^^^^^^^^^^^
+#### C11 `_Thread_local`
-Use ``__has_feature(c_thread_local)`` or ``__has_extension(c_thread_local)``
-to determine if support for ``_Thread_local`` variables is enabled.
+Use `__has_feature(c_thread_local)` or `__has_extension(c_thread_local)`
+to determine if support for `_Thread_local` variables is enabled.
-C2y
----
+### C2y
-The features listed below are part of the C2y standard. As a result, all these
-features are enabled with the ``-std=c2y`` or ``-std=gnu2y`` option when
+The features listed below are part of the C2y standard. As a result, all these
+features are enabled with the `-std=c2y` or `-std=gnu2y` option when
compiling C code.
-C2y ``_Countof``
-^^^^^^^^^^^^^^^^
+#### C2y `_Countof`
-Use ``__has_feature(c_countof)`` (in C2y or later mode) or
-``__has_extension(c_countof)`` (in C23 or earlier mode) to determine if support
-for the ``_Countof`` operator is enabled. This feature is not available in C++
+Use `__has_feature(c_countof)` (in C2y or later mode) or
+`__has_extension(c_countof)` (in C23 or earlier mode) to determine if support
+for the `_Countof` operator is enabled. This feature is not available in C++
mode.
-
-Modules
--------
-
-Use ``__has_feature(modules)`` to determine if Modules have been enabled.
-For example, compiling code with ``-fmodules`` enables the use of Modules.
-
-More information can be found `here <https://clang.llvm.org/docs/Modules.html>`_.
-
-Language Extensions Back-ported to Previous Standards
-=====================================================
-
-============================================= ================================ ============= =============
-Feature Feature Test Macro Introduced In Backported To
-============================================= ================================ ============= =============
-variadic templates __cpp_variadic_templates C++11 C++03
-Alias templates __cpp_alias_templates C++11 C++03
-Non-static data member initializers __cpp_nsdmi C++11 C++03
-Range-based ``for`` loop __cpp_range_based_for C++11 C++03
-RValue references __cpp_rvalue_references C++11 C++03
-Attributes __cpp_attributes C++11 C++03
-Lambdas __cpp_lambdas C++11 C++03
-Generalized lambda captures __cpp_init_captures C++14 C++03
-Generic lambda expressions __cpp_generic_lambdas C++14 C++03
-variable templates __cpp_variable_templates C++14 C++03
-Binary literals __cpp_binary_literals C++14 C++03
-Relaxed constexpr __cpp_constexpr C++14 C++11
-Static assert with no message __cpp_static_assert >= 201411L C++17 C++11
-Pack expansion in generalized lambda-capture __cpp_init_captures C++17 C++03
-``if constexpr`` __cpp_if_constexpr C++17 C++11
-fold expressions __cpp_fold_expressions C++17 C++03
-Lambda capture of \*this by value __cpp_capture_star_this C++17 C++03
-Attributes on enums __cpp_enumerator_attributes C++17 C++03
-Guaranteed copy elision __cpp_guaranteed_copy_elision C++17 C++03
-Hexadecimal floating literals __cpp_hex_float C++17 C++03
-``inline`` variables __cpp_inline_variables C++17 C++03
-Attributes on namespaces __cpp_namespace_attributes C++17 C++11
-Structured bindings __cpp_structured_bindings C++17 C++03
-template template arguments __cpp_template_template_args C++17 C++03
-Familiar template syntax for generic lambdas __cpp_generic_lambdas C++20 C++03
-``static operator[]`` __cpp_multidimensional_subscript C++20 C++03
-Designated initializers __cpp_designated_initializers C++20 C++03
-Conditional ``explicit`` __cpp_conditional_explicit C++20 C++03
-``using enum`` __cpp_using_enum C++20 C++03
-``auto`` parameters C++20 C++03
-``if consteval`` __cpp_if_consteval C++23 C++20
-``static operator()`` __cpp_static_call_operator C++23 C++03
-Attributes on Lambda-Expressions C++23 C++11
-Attributes on Structured Bindings __cpp_structured_bindings C++26 C++03
-Packs in Structured Bindings __cpp_structured_bindings C++26 C++03
-Structured binding declaration as a condition __cpp_structured_bindings C++26 C++98
-Static assert with user-generated message __cpp_static_assert >= 202306L C++26 C++11
-Pack Indexing __cpp_pack_indexing C++26 C++03
-``= delete ("should have a reason");`` __cpp_deleted_function C++26 C++03
-Variadic Friends __cpp_variadic_friend C++26 C++03
-Trivial Relocatability __cpp_trivial_relocatability C++26 C++03
---------------------------------------------- -------------------------------- ------------- -------------
-Designated initializers (N494) C99 C89
-``_Complex`` (N693) C99 C89, C++
-``_Bool`` (N815) C99 C89
-Variable-length arrays (N683) C99 C89, C++
-Flexible array members C99 C89, C++
-static and type quals in arrays C99 C89
-``long long`` (N601) C99 C89
-Hexadecimal floating constants (N308) C99 C89
-Compound literals (N716) C99 C89, C++
-``//`` comments (N644) C99 C89
-Mixed declarations and code (N740) C99 C89
-init-statement in for (N740) C99 C89
-Variadic macros (N707) C99 C89
-Empty macro arguments (N570) C99 C89
-Trailing comma in enum declaration C99 C89
-Implicit ``return 0`` in ``main`` C99 C89
-``__func__`` (N611) C99 C89
-``_Generic`` (N1441) C11 C89, C++
-``_Static_assert`` (N1330) C11 C89, C++
-``_Atomic`` (N1485) C11 C89, C++
-``_Thread_local`` (N1364) C11 C89, C++
-Array & element qualification (N2607) C23 C89
-Attributes (N2335) C23 C89
-``#embed`` (N3017) C23 C89, C++
-Enum with fixed underlying type (N3030) C23 C89
-``#warning`` (N2686) C23 C89
-``_BitInt`` (N3035) C23 C89, C++
-Binary literals (N2549) C23 C89
-Unnamed parameters in a function definition C23 C89
-Free positioning of labels (N2508) C23 C89
-``#elifdef`` (N2645) C23 C89
-``__has_include`` (N2799) C23 C89
-Octal literals prefixed with ``0o`` or ``0O`` C2y C89, C++
-``_Countof`` (N3369, N3469) C2y C89
-``_Generic`` with a type operand (N3260) C2y C89, C++
-``++``/``--`` on ``_Complex`` value (N3259) C2y C89, C++
-``__COUNTER__`` (N3457) C2y C89, C++
-============================================= ================================ ============= =============
-
-Builtin type aliases
-====================
+### Modules
+
+Use `__has_feature(modules)` to determine if Modules have been enabled.
+For example, compiling code with `-fmodules` enables the use of Modules.
+
+More information can be found [here](https://clang.llvm.org/docs/Modules.html).
+
+## Language Extensions Back-ported to Previous Standards
+
+| Feature | Feature Test Macro | Introduced In | Backported To |
+| --------------------------------------------- | ---------------------------------- | ------------- | ------------- |
+| variadic templates | \_\_cpp_variadic_templates | C++11 | C++03 |
+| Alias templates | \_\_cpp_alias_templates | C++11 | C++03 |
+| Non-static data member initializers | \_\_cpp_nsdmi | C++11 | C++03 |
+| Range-based `for` loop | \_\_cpp_range_based_for | C++11 | C++03 |
+| RValue references | \_\_cpp_rvalue_references | C++11 | C++03 |
+| Attributes | \_\_cpp_attributes | C++11 | C++03 |
+| Lambdas | \_\_cpp_lambdas | C++11 | C++03 |
+| Generalized lambda captures | \_\_cpp_init_captures | C++14 | C++03 |
+| Generic lambda expressions | \_\_cpp_generic_lambdas | C++14 | C++03 |
+| variable templates | \_\_cpp_variable_templates | C++14 | C++03 |
+| Binary literals | \_\_cpp_binary_literals | C++14 | C++03 |
+| Relaxed constexpr | \_\_cpp_constexpr | C++14 | C++11 |
+| Static assert with no message | \_\_cpp_static_assert >= 201411L | C++17 | C++11 |
+| Pack expansion in generalized lambda-capture | \_\_cpp_init_captures | C++17 | C++03 |
+| `if constexpr` | \_\_cpp_if_constexpr | C++17 | C++11 |
+| fold expressions | \_\_cpp_fold_expressions | C++17 | C++03 |
+| Lambda capture of \*this by value | \_\_cpp_capture_star_this | C++17 | C++03 |
+| Attributes on enums | \_\_cpp_enumerator_attributes | C++17 | C++03 |
+| Guaranteed copy elision | \_\_cpp_guaranteed_copy_elision | C++17 | C++03 |
+| Hexadecimal floating literals | \_\_cpp_hex_float | C++17 | C++03 |
+| `inline` variables | \_\_cpp_inline_variables | C++17 | C++03 |
+| Attributes on namespaces | \_\_cpp_namespace_attributes | C++17 | C++11 |
+| Structured bindings | \_\_cpp_structured_bindings | C++17 | C++03 |
+| template template arguments | \_\_cpp_template_template_args | C++17 | C++03 |
+| Familiar template syntax for generic lambdas | \_\_cpp_generic_lambdas | C++20 | C++03 |
+| `static operator[]` | \_\_cpp_multidimensional_subscript | C++20 | C++03 |
+| Designated initializers | \_\_cpp_designated_initializers | C++20 | C++03 |
+| Conditional `explicit` | \_\_cpp_conditional_explicit | C++20 | C++03 |
+| `using enum` | \_\_cpp_using_enum | C++20 | C++03 |
+| `auto` parameters | | C++20 | C++03 |
+| `if consteval` | \_\_cpp_if_consteval | C++23 | C++20 |
+| `static operator()` | \_\_cpp_static_call_operator | C++23 | C++03 |
+| Attributes on Lambda-Expressions | | C++23 | C++11 |
+| Attributes on Structured Bindings | \_\_cpp_structured_bindings | C++26 | C++03 |
+| Packs in Structured Bindings | \_\_cpp_structured_bindings | C++26 | C++03 |
+| Structured binding declaration as a condition | \_\_cpp_structured_bindings | C++26 | C++98 |
+| Static assert with user-generated message | \_\_cpp_static_assert >= 202306L | C++26 | C++11 |
+| Pack Indexing | \_\_cpp_pack_indexing | C++26 | C++03 |
+| `= delete ("should have a reason");` | \_\_cpp_deleted_function | C++26 | C++03 |
+| Variadic Friends | \_\_cpp_variadic_friend | C++26 | C++03 |
+| Trivial Relocatability | \_\_cpp_trivial_relocatability | C++26 | C++03 |
+| Designated initializers (N494) | | C99 | C89 |
+| `_Complex` (N693) | | C99 | C89, C++ |
+| `_Bool` (N815) | | C99 | C89 |
+| Variable-length arrays (N683) | | C99 | C89, C++ |
+| Flexible array members | | C99 | C89, C++ |
+| static and type quals in arrays | | C99 | C89 |
+| `long long` (N601) | | C99 | C89 |
+| Hexadecimal floating constants (N308) | | C99 | C89 |
+| Compound literals (N716) | | C99 | C89, C++ |
+| `//` comments (N644) | | C99 | C89 |
+| Mixed declarations and code (N740) | | C99 | C89 |
+| init-statement in for (N740) | | C99 | C89 |
+| Variadic macros (N707) | | C99 | C89 |
+| Empty macro arguments (N570) | | C99 | C89 |
+| Trailing comma in enum declaration | | C99 | C89 |
+| Implicit `return 0` in `main` | | C99 | C89 |
+| `__func__` (N611) | | C99 | C89 |
+| `_Generic` (N1441) | | C11 | C89, C++ |
+| `_Static_assert` (N1330) | | C11 | C89, C++ |
+| `_Atomic` (N1485) | | C11 | C89, C++ |
+| `_Thread_local` (N1364) | | C11 | C89, C++ |
+| Array & element qualification (N2607) | | C23 | C89 |
+| Attributes (N2335) | | C23 | C89 |
+| `#embed` (N3017) | | C23 | C89, C++ |
+| Enum with fixed underlying type (N3030) | | C23 | C89 |
+| `#warning` (N2686) | | C23 | C89 |
+| `_BitInt` (N3035) | | C23 | C89, C++ |
+| Binary literals (N2549) | | C23 | C89 |
+| Unnamed parameters in a function definition | | C23 | C89 |
+| Free positioning of labels (N2508) | | C23 | C89 |
+| `#elifdef` (N2645) | | C23 | C89 |
+| `__has_include` (N2799) | | C23 | C89 |
+| Octal literals prefixed with `0o` or `0O` | | C2y | C89, C++ |
+| `_Countof` (N3369, N3469) | | C2y | C89 |
+| `_Generic` with a type operand (N3260) | | C2y | C89, C++ |
+| `++`/`--` on `_Complex` value (N3259) | | C2y | C89, C++ |
+| `__COUNTER__` (N3457) | | C2y | C89, C++ |
+
+## Builtin type aliases
Clang provides a few builtin aliases to improve the throughput of certain metaprogramming facilities.
-__builtin_common_type
----------------------
-
-.. code-block:: c++
-
- template <template <class... Args> class BaseTemplate,
- template <class TypeMember> class HasTypeMember,
- class HasNoTypeMember,
- class... Ts>
- using __builtin_common_type = ...;
-
-This alias is used for implementing ``std::common_type``. If ``std::common_type`` should contain a ``type`` member,
-it is an alias to ``HasTypeMember<TheCommonType>``. Otherwise it is an alias to ``HasNoTypeMember``. The
-``BaseTemplate`` is usually ``std::common_type``. ``Ts`` are the arguments to ``std::common_type``.
-
-__type_pack_element
--------------------
+### \_\_builtin_common_type
-.. code-block:: c++
+```c++
+template <template <class... Args> class BaseTemplate,
+ template <class TypeMember> class HasTypeMember,
+ class HasNoTypeMember,
+ class... Ts>
+using __builtin_common_type = ...;
+```
- template <std::size_t Index, class... Ts>
- using __type_pack_element = ...;
+This alias is used for implementing `std::common_type`. If `std::common_type` should contain a `type` member,
+it is an alias to `HasTypeMember<TheCommonType>`. Otherwise it is an alias to `HasNoTypeMember`. The
+`BaseTemplate` is usually `std::common_type`. `Ts` are the arguments to `std::common_type`.
-This alias returns the type at ``Index`` in the parameter pack ``Ts``.
+### \_\_type_pack_element
-__make_integer_seq
-------------------
+```c++
+template <std::size_t Index, class... Ts>
+using __type_pack_element = ...;
+```
-.. code-block:: c++
+This alias returns the type at `Index` in the parameter pack `Ts`.
- template <template <class IntSeqT, IntSeqT... Ints> class IntSeq, class T, T N>
- using __make_integer_seq = ...;
+### \_\_make_integer_seq
-This alias returns ``IntSeq`` instantiated with ``IntSeqT = T``and ``Ints`` being the pack ``0, ..., N - 1``.
+```c++
+template <template <class IntSeqT, IntSeqT... Ints> class IntSeq, class T, T N>
+using __make_integer_seq = ...;
+```
-__builtin_dedup_pack
---------------------
+This alias returns `IntSeq` instantiated with ``` IntSeqT = T``and ``Ints ``` being the pack `0, ..., N - 1`.
-.. code-block:: c++
+### \_\_builtin_dedup_pack
- template <class... Ts>
- using __builtin_dedup_pack = ...;
+```c++
+template <class... Ts>
+using __builtin_dedup_pack = ...;
+```
-This alias takes a template parameter pack ``Ts`` and produces a new unexpanded pack containing the unique types
-from ``Ts``, with the order of the first occurrence of each type preserved.
+This alias takes a template parameter pack `Ts` and produces a new unexpanded pack containing the unique types
+from `Ts`, with the order of the first occurrence of each type preserved.
It is useful in template metaprogramming to normalize type lists.
The resulting pack can be expanded in contexts like template argument lists or base specifiers.
**Example of Use**:
-.. code-block:: c++
-
- template <typename...> struct TypeList;
+```c++
+template <typename...> struct TypeList;
- // The resulting type is TypeList<int, double, char>
- template <typename ...ExtraTypes>
- using MyTypeList = TypeList<__builtin_dedup_pack<int, double, int, char, double, ExtraTypes...>...>;
+// The resulting type is TypeList<int, double, char>
+template <typename ...ExtraTypes>
+using MyTypeList = TypeList<__builtin_dedup_pack<int, double, int, char, double, ExtraTypes...>...>;
+```
**Limitations**:
-* This builtin can only be used inside a template.
-* The resulting pack is currently only supported for expansion in template argument lists and base specifiers.
-* This builtin cannot be assigned to a template template parameter.
-
+- This builtin can only be used inside a template.
+- The resulting pack is currently only supported for expansion in template argument lists and base specifiers.
+- This builtin cannot be assigned to a template template parameter.
-Type Trait Primitives
-=====================
+## Type Trait Primitives
Type trait primitives are special builtin constant expressions that can be used
by the standard C++ library to facilitate or simplify the implementation of
-user-facing type traits in the ``<type_traits>`` header.
+user-facing type traits in the `<type_traits>` header.
They are not intended to be used directly by user code because they are
implementation-defined and subject to change -- as such they're tied closely to
the supported set of system headers, currently:
-* LLVM's own libc++
-* GNU libstdc++
-* The Microsoft standard C++ library
+- LLVM's own libc++
+- GNU libstdc++
+- The Microsoft standard C++ library
-Clang supports the `GNU C++ type traits
-<https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html>`_ and a subset of the
-`Microsoft Visual C++ type traits
-<https://msdn.microsoft.com/en-us/library/ms177194(v=VS.100).aspx>`_,
+Clang supports the [GNU C++ type traits](https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html) and a subset of the
+[Microsoft Visual C++ type traits](<https://msdn.microsoft.com/en-us/library/ms177194(v=VS.100).aspx>),
as well as nearly all of the
-`Embarcadero C++ type traits
-<http://docwiki.embarcadero.com/RADStudio/Rio/en/Type_Trait_Functions_(C%2B%2B11)_Index>`_.
+[Embarcadero C++ type traits](<http://docwiki.embarcadero.com/RADStudio/Rio/en/Type_Trait_Functions_(C%2B%2B11)_Index>).
The following type trait primitives are supported by Clang. Those traits marked
(C++) provide implementations for type traits specified by the C++ standard;
-``__X(...)`` has the same semantics and constraints as the corresponding
-``std::X_t<...>`` or ``std::X_v<...>`` type trait.
-
-* ``__array_rank(type)`` (Embarcadero):
- Returns the number of levels of array in the type ``type``:
- ``0`` if ``type`` is not an array type, and
- ``__array_rank(element) + 1`` if ``type`` is an array of ``element``.
-* ``__array_extent(type, dim)`` (Embarcadero):
- The ``dim``'th array bound in the type ``type``, or ``0`` if
- ``dim >= __array_rank(type)``.
-* ``__builtin_is_implicit_lifetime`` (C++, GNU, Microsoft)
-* ``__builtin_is_virtual_base_of`` (C++, GNU, Microsoft)
-* ``__can_pass_in_regs`` (C++)
+`__X(...)` has the same semantics and constraints as the corresponding
+`std::X_t<...>` or `std::X_v<...>` type trait.
+
+- `__array_rank(type)` (Embarcadero):
+ Returns the number of levels of array in the type `type`:
+ `0` if `type` is not an array type, and
+ `__array_rank(element) + 1` if `type` is an array of `element`.
+- `__array_extent(type, dim)` (Embarcadero):
+ The `dim`'th array bound in the type `type`, or `0` if
+ `dim >= __array_rank(type)`.
+- `__builtin_is_implicit_lifetime` (C++, GNU, Microsoft)
+- `__builtin_is_virtual_base_of` (C++, GNU, Microsoft)
+- `__can_pass_in_regs` (C++)
Returns whether a class can be passed in registers under the current
ABI. This type can only be applied to unqualified class types.
This is not a portable type trait.
-* ``__has_nothrow_assign`` (GNU, Microsoft, Embarcadero):
- Deprecated, use ``__is_nothrow_assignable`` instead.
-* ``__has_nothrow_move_assign`` (GNU, Microsoft):
- Deprecated, use ``__is_nothrow_assignable`` instead.
-* ``__has_nothrow_copy`` (GNU, Microsoft):
- Deprecated, use ``__is_nothrow_constructible`` instead.
-* ``__has_nothrow_constructor`` (GNU, Microsoft):
- Deprecated, use ``__is_nothrow_constructible`` instead.
-* ``__has_trivial_assign`` (GNU, Microsoft, Embarcadero):
- Deprecated, use ``__is_trivially_assignable`` instead.
-* ``__has_trivial_move_assign`` (GNU, Microsoft):
- Deprecated, use ``__is_trivially_assignable`` instead.
-* ``__has_trivial_copy`` (GNU, Microsoft):
- Deprecated, use ``__is_trivially_copyable`` instead.
-* ``__has_trivial_constructor`` (GNU, Microsoft):
- Deprecated, use ``__is_trivially_constructible`` instead.
-* ``__has_trivial_move_constructor`` (GNU, Microsoft):
- Deprecated, use ``__is_trivially_constructible`` instead.
-* ``__has_trivial_destructor`` (GNU, Microsoft, Embarcadero):
- Deprecated, use ``__is_trivially_destructible`` instead.
-* ``__has_unique_object_representations`` (C++, GNU)
-* ``__has_virtual_destructor`` (C++, GNU, Microsoft, Embarcadero)
-* ``__is_abstract`` (C++, GNU, Microsoft, Embarcadero)
-* ``__is_aggregate`` (C++, GNU, Microsoft)
-* ``__is_arithmetic`` (C++, Embarcadero)
-* ``__is_array`` (C++, Embarcadero)
-* ``__is_assignable`` (C++, MSVC 2015)
-* ``__is_base_of`` (C++, GNU, Microsoft, Embarcadero)
-* ``__is_bounded_array`` (C++, GNU, Microsoft, Embarcadero)
-* ``__is_class`` (C++, GNU, Microsoft, Embarcadero)
-* ``__is_complete_type(type)`` (Embarcadero):
- Return ``true`` if ``type`` is a complete type.
+- `__has_nothrow_assign` (GNU, Microsoft, Embarcadero):
+ Deprecated, use `__is_nothrow_assignable` instead.
+- `__has_nothrow_move_assign` (GNU, Microsoft):
+ Deprecated, use `__is_nothrow_assignable` instead.
+- `__has_nothrow_copy` (GNU, Microsoft):
+ Deprecated, use `__is_nothrow_constructible` instead.
+- `__has_nothrow_constructor` (GNU, Microsoft):
+ Deprecated, use `__is_nothrow_constructible` instead.
+- `__has_trivial_assign` (GNU, Microsoft, Embarcadero):
+ Deprecated, use `__is_trivially_assignable` instead.
+- `__has_trivial_move_assign` (GNU, Microsoft):
+ Deprecated, use `__is_trivially_assignable` instead.
+- `__has_trivial_copy` (GNU, Microsoft):
+ Deprecated, use `__is_trivially_copyable` instead.
+- `__has_trivial_constructor` (GNU, Microsoft):
+ Deprecated, use `__is_trivially_constructible` instead.
+- `__has_trivial_move_constructor` (GNU, Microsoft):
+ Deprecated, use `__is_trivially_constructible` instead.
+- `__has_trivial_destructor` (GNU, Microsoft, Embarcadero):
+ Deprecated, use `__is_trivially_destructible` instead.
+- `__has_unique_object_representations` (C++, GNU)
+- `__has_virtual_destructor` (C++, GNU, Microsoft, Embarcadero)
+- `__is_abstract` (C++, GNU, Microsoft, Embarcadero)
+- `__is_aggregate` (C++, GNU, Microsoft)
+- `__is_arithmetic` (C++, Embarcadero)
+- `__is_array` (C++, Embarcadero)
+- `__is_assignable` (C++, MSVC 2015)
+- `__is_base_of` (C++, GNU, Microsoft, Embarcadero)
+- `__is_bounded_array` (C++, GNU, Microsoft, Embarcadero)
+- `__is_class` (C++, GNU, Microsoft, Embarcadero)
+- `__is_complete_type(type)` (Embarcadero):
+ Return `true` if `type` is a complete type.
Warning: this trait is dangerous because it can return different values at
different points in the same program.
-* ``__is_compound`` (C++, Embarcadero)
-* ``__is_const`` (C++, Embarcadero)
-* ``__is_constructible`` (C++, MSVC 2013)
-* ``__is_convertible`` (C++, Embarcadero)
-* ``__is_nothrow_convertible`` (C++, GNU)
-* ``__is_convertible_to`` (Microsoft):
- Synonym for ``__is_convertible``.
-* ``__is_destructible`` (C++, MSVC 2013)
-* ``__is_empty`` (C++, GNU, Microsoft, Embarcadero)
-* ``__is_enum`` (C++, GNU, Microsoft, Embarcadero)
-* ``__is_final`` (C++, GNU, Microsoft)
-* ``__is_floating_point`` (C++, Embarcadero)
-* ``__is_function`` (C++, Embarcadero)
-* ``__is_fundamental`` (C++, Embarcadero)
-* ``__is_integral`` (C++, Embarcadero)
-* ``__is_interface_class`` (Microsoft):
- Returns ``false``, even for types defined with ``__interface``.
-* ``__is_layout_compatible`` (C++, GNU, Microsoft)
-* ``__is_literal`` (Clang):
- Synonym for ``__is_literal_type``.
-* ``__is_literal_type`` (C++, GNU, Microsoft):
+- `__is_compound` (C++, Embarcadero)
+- `__is_const` (C++, Embarcadero)
+- `__is_constructible` (C++, MSVC 2013)
+- `__is_convertible` (C++, Embarcadero)
+- `__is_nothrow_convertible` (C++, GNU)
+- `__is_convertible_to` (Microsoft):
+ Synonym for `__is_convertible`.
+- `__is_destructible` (C++, MSVC 2013)
+- `__is_empty` (C++, GNU, Microsoft, Embarcadero)
+- `__is_enum` (C++, GNU, Microsoft, Embarcadero)
+- `__is_final` (C++, GNU, Microsoft)
+- `__is_floating_point` (C++, Embarcadero)
+- `__is_function` (C++, Embarcadero)
+- `__is_fundamental` (C++, Embarcadero)
+- `__is_integral` (C++, Embarcadero)
+- `__is_interface_class` (Microsoft):
+ Returns `false`, even for types defined with `__interface`.
+- `__is_layout_compatible` (C++, GNU, Microsoft)
+- `__is_literal` (Clang):
+ Synonym for `__is_literal_type`.
+- `__is_literal_type` (C++, GNU, Microsoft):
Note, the corresponding standard trait was deprecated in C++17
and removed in C++20.
-* ``__is_lvalue_reference`` (C++, Embarcadero)
-* ``__is_member_object_pointer`` (C++, Embarcadero)
-* ``__is_member_function_pointer`` (C++, Embarcadero)
-* ``__is_member_pointer`` (C++, Embarcadero)
-* ``__is_nothrow_assignable`` (C++, MSVC 2013)
-* ``__is_nothrow_constructible`` (C++, MSVC 2013)
-* ``__is_nothrow_destructible`` (C++, MSVC 2013)
-* ``__is_object`` (C++, Embarcadero)
-* ``__is_pod`` (C++, GNU, Microsoft, Embarcadero):
+- `__is_lvalue_reference` (C++, Embarcadero)
+- `__is_member_object_pointer` (C++, Embarcadero)
+- `__is_member_function_pointer` (C++, Embarcadero)
+- `__is_member_pointer` (C++, Embarcadero)
+- `__is_nothrow_assignable` (C++, MSVC 2013)
+- `__is_nothrow_constructible` (C++, MSVC 2013)
+- `__is_nothrow_destructible` (C++, MSVC 2013)
+- `__is_object` (C++, Embarcadero)
+- `__is_pod` (C++, GNU, Microsoft, Embarcadero):
Note, the corresponding standard trait was deprecated in C++20.
-* ``__is_pointer`` (C++, Embarcadero)
-* ``__is_pointer_interconvertible_base_of`` (C++, GNU, Microsoft)
-* ``__is_polymorphic`` (C++, GNU, Microsoft, Embarcadero)
-* ``__is_reference`` (C++, Embarcadero)
-* ``__is_rvalue_reference`` (C++, Embarcadero)
-* ``__is_same`` (C++, Embarcadero)
-* ``__is_same_as`` (GCC): Synonym for ``__is_same``.
-* ``__is_scalar`` (C++, Embarcadero)
-* ``__is_scoped_enum`` (C++, GNU, Microsoft, Embarcadero)
-* ``__is_sealed`` (Microsoft):
- Synonym for ``__is_final``.
-* ``__is_signed`` (C++, Embarcadero):
+- `__is_pointer` (C++, Embarcadero)
+- `__is_pointer_interconvertible_base_of` (C++, GNU, Microsoft)
+- `__is_polymorphic` (C++, GNU, Microsoft, Embarcadero)
+- `__is_reference` (C++, Embarcadero)
+- `__is_rvalue_reference` (C++, Embarcadero)
+- `__is_same` (C++, Embarcadero)
+- `__is_same_as` (GCC): Synonym for `__is_same`.
+- `__is_scalar` (C++, Embarcadero)
+- `__is_scoped_enum` (C++, GNU, Microsoft, Embarcadero)
+- `__is_sealed` (Microsoft):
+ Synonym for `__is_final`.
+- `__is_signed` (C++, Embarcadero):
Returns false for enumeration types, and returns true for floating-point
types. Note, before Clang 10, returned true for enumeration types if the
underlying type was signed, and returned false for floating-point types.
-* ``__is_standard_layout`` (C++, GNU, Microsoft, Embarcadero)
-* ``__is_trivial`` (C++, GNU, Microsoft, Embarcadero)
-* ``__is_trivially_assignable`` (C++, GNU, Microsoft)
-* ``__is_trivially_constructible`` (C++, GNU, Microsoft)
-* ``__is_trivially_copyable`` (C++, GNU, Microsoft)
-* ``__is_trivially_destructible`` (C++, MSVC 2013)
-* ``__is_trivially_relocatable`` (Clang) (Deprecated,
- use ``__builtin_is_cpp_trivially_relocatable`` instead).
+- `__is_standard_layout` (C++, GNU, Microsoft, Embarcadero)
+- `__is_trivial` (C++, GNU, Microsoft, Embarcadero)
+- `__is_trivially_assignable` (C++, GNU, Microsoft)
+- `__is_trivially_constructible` (C++, GNU, Microsoft)
+- `__is_trivially_copyable` (C++, GNU, Microsoft)
+- `__is_trivially_destructible` (C++, MSVC 2013)
+- `__is_trivially_relocatable` (Clang) (Deprecated,
+ use `__builtin_is_cpp_trivially_relocatable` instead).
Returns true if moving an object
of the given type, and then destroying the source object, is known to be
functionally equivalent to copying the underlying bytes and then dropping the
source object on the floor. This is true of trivial types,
C++26 relocatable types, and types which
- were made trivially relocatable via the ``clang::trivial_abi`` attribute.
+ were made trivially relocatable via the `clang::trivial_abi` attribute.
This trait is deprecated and should be replaced by
- ``__builtin_is_cpp_trivially_relocatable``. Note, however, that it is generally
- unsafe to relocate a C++-relocatable type with ``memcpy`` or ``memmove``;
- use ``__builtin_trivially_relocate``.
-* ``__builtin_is_cpp_trivially_relocatable`` (C++): Returns true if an object
+ `__builtin_is_cpp_trivially_relocatable`. Note, however, that it is generally
+ unsafe to relocate a C++-relocatable type with `memcpy` or `memmove`;
+ use `__builtin_trivially_relocate`.
+- `__builtin_is_cpp_trivially_relocatable` (C++): Returns true if an object
is trivially relocatable, as defined by the C++26 standard [meta.unary.prop].
Note that when relocating the caller code should ensure that if the object is polymorphic,
the dynamic type is of the most derived type. Padding bytes should not be copied.
-* ``__is_trivially_equality_comparable`` (Clang): Returns true if comparing two
+- `__is_trivially_equality_comparable` (Clang): Returns true if comparing two
objects of the provided type is known to be equivalent to comparing their
object representations. Note that types containing padding bytes are never
trivially equality comparable.
-* ``__is_unbounded_array`` (C++, GNU, Microsoft, Embarcadero)
-* ``__is_union`` (C++, GNU, Microsoft, Embarcadero)
-* ``__is_unsigned`` (C++, Embarcadero):
+- `__is_unbounded_array` (C++, GNU, Microsoft, Embarcadero)
+- `__is_union` (C++, GNU, Microsoft, Embarcadero)
+- `__is_unsigned` (C++, Embarcadero):
Returns false for enumeration types. Note, before Clang 13, returned true for
enumeration types if the underlying type was unsigned.
-* ``__is_void`` (C++, Embarcadero)
-* ``__is_volatile`` (C++, Embarcadero)
-* ``__reference_binds_to_temporary(T, U)`` (Clang): Determines whether a
- reference of type ``T`` bound to an expression of type ``U`` would bind to a
- materialized temporary object. If ``T`` is not a reference type, the result
+- `__is_void` (C++, Embarcadero)
+- `__is_volatile` (C++, Embarcadero)
+- `__reference_binds_to_temporary(T, U)` (Clang): Determines whether a
+ reference of type `T` bound to an expression of type `U` would bind to a
+ materialized temporary object. If `T` is not a reference type, the result
is false. Note this trait will also return false when the initialization of
- ``T`` from ``U`` is ill-formed.
- Deprecated, use ``__reference_constructs_from_temporary``.
-* ``__reference_constructs_from_temporary(T, U)`` (C++)
- Returns true if a reference ``T`` can be direct-initialized from a temporary of type
- a non-cv-qualified ``U``.
-* ``__reference_converts_from_temporary(T, U)`` (C++)
- Returns true if a reference ``T`` can be copy-initialized from a temporary of type
- a non-cv-qualified ``U``.
-* ``__underlying_type`` (C++, GNU, Microsoft)
-* ``__builtin_lt_synthesizes_from_spaceship``, ``__builtin_gt_synthesizes_from_spaceship``,
- ``__builtin_le_synthesizes_from_spaceship``, ``__builtin_ge_synthesizes_from_spaceship`` (Clang):
+ `T` from `U` is ill-formed.
+ Deprecated, use `__reference_constructs_from_temporary`.
+- `__reference_constructs_from_temporary(T, U)` (C++)
+ Returns true if a reference `T` can be direct-initialized from a temporary of type
+ a non-cv-qualified `U`.
+- `__reference_converts_from_temporary(T, U)` (C++)
+ : Returns true if a reference `T` can be copy-initialized from a temporary of type
+ a non-cv-qualified `U`.
+- `__underlying_type` (C++, GNU, Microsoft)
+- `__builtin_lt_synthesizes_from_spaceship`, `__builtin_gt_synthesizes_from_spaceship`,
+ `__builtin_le_synthesizes_from_spaceship`, `__builtin_ge_synthesizes_from_spaceship` (Clang):
These builtins can be used to determine whether the corresponding operator is synthesized from a spaceship operator.
In addition, the following expression traits are supported:
-* ``__is_lvalue_expr(e)`` (Embarcadero):
- Returns true if ``e`` is an lvalue expression.
- Deprecated, use ``__is_lvalue_reference(decltype((e)))`` instead.
-* ``__is_rvalue_expr(e)`` (Embarcadero):
- Returns true if ``e`` is a prvalue expression.
- Deprecated, use ``!__is_reference(decltype((e)))`` instead.
+- `__is_lvalue_expr(e)` (Embarcadero):
+ Returns true if `e` is an lvalue expression.
+ Deprecated, use `__is_lvalue_reference(decltype((e)))` instead.
+- `__is_rvalue_expr(e)` (Embarcadero):
+ Returns true if `e` is a prvalue expression.
+ Deprecated, use `!__is_reference(decltype((e)))` instead.
-There are multiple ways to detect support for a type trait ``__X`` in the
+There are multiple ways to detect support for a type trait `__X` in the
compiler, depending on the oldest version of Clang you wish to support.
-* From Clang 10 onwards, ``__has_builtin(__X)`` can be used.
-* From Clang 6 onwards, ``!__is_identifier(__X)`` can be used.
-* From Clang 3 onwards, ``__has_feature(X)`` can be used, but only supports
- the following traits:
+- From Clang 10 onwards, `__has_builtin(__X)` can be used.
- * ``__has_nothrow_assign``
- * ``__has_nothrow_copy``
- * ``__has_nothrow_constructor``
- * ``__has_trivial_assign``
- * ``__has_trivial_copy``
- * ``__has_trivial_constructor``
- * ``__has_trivial_destructor``
- * ``__has_virtual_destructor``
- * ``__is_abstract``
- * ``__is_base_of``
- * ``__is_class``
- * ``__is_constructible``
- * ``__is_convertible_to``
- * ``__is_empty``
- * ``__is_enum``
- * ``__is_final``
- * ``__is_literal``
- * ``__is_standard_layout``
- * ``__is_pod``
- * ``__is_polymorphic``
- * ``__is_sealed``
- * ``__is_trivial``
- * ``__is_trivially_assignable``
- * ``__is_trivially_constructible``
- * ``__is_trivially_copyable``
- * ``__is_union``
- * ``__underlying_type``
+- From Clang 6 onwards, `!__is_identifier(__X)` can be used.
-A simplistic usage example as might be seen in standard C++ headers follows:
+- From Clang 3 onwards, `__has_feature(X)` can be used, but only supports
+ the following traits:
-.. code-block:: c++
+ - `__has_nothrow_assign`
+ - `__has_nothrow_copy`
+ - `__has_nothrow_constructor`
+ - `__has_trivial_assign`
+ - `__has_trivial_copy`
+ - `__has_trivial_constructor`
+ - `__has_trivial_destructor`
+ - `__has_virtual_destructor`
+ - `__is_abstract`
+ - `__is_base_of`
+ - `__is_class`
+ - `__is_constructible`
+ - `__is_convertible_to`
+ - `__is_empty`
+ - `__is_enum`
+ - `__is_final`
+ - `__is_literal`
+ - `__is_standard_layout`
+ - `__is_pod`
+ - `__is_polymorphic`
+ - `__is_sealed`
+ - `__is_trivial`
+ - `__is_trivially_assignable`
+ - `__is_trivially_constructible`
+ - `__is_trivially_copyable`
+ - `__is_union`
+ - `__underlying_type`
- #if __has_builtin(__is_convertible_to)
- template<typename From, typename To>
- struct is_convertible_to {
- static const bool value = __is_convertible_to(From, To);
- };
- #else
- // Emulate type trait for compatibility with other compilers.
- #endif
+A simplistic usage example as might be seen in standard C++ headers follows:
+```c++
+#if __has_builtin(__is_convertible_to)
+template<typename From, typename To>
+struct is_convertible_to {
+ static const bool value = __is_convertible_to(From, To);
+};
+#else
+// Emulate type trait for compatibility with other compilers.
+#endif
+```
-.. _builtin_structured_binding_size-doc:
+(builtin-structured-binding-size-doc)=
-__builtin_structured_binding_size (C++)
----------------------------------------
+### \_\_builtin_structured_binding_size (C++)
-The ``__builtin_structured_binding_size(T)`` type trait returns
-the *structured binding size* ([dcl.struct.bind]) of type ``T``
+The `__builtin_structured_binding_size(T)` type trait returns
+the *structured binding size* ([dcl.struct.bind]) of type `T`
-This is equivalent to the size of the pack ``p`` in ``auto&& [...p] = declval<T&>();``.
-If the argument cannot be decomposed, ``__builtin_structured_binding_size(T)``
-is not a valid expression (``__builtin_structured_binding_size`` is SFINAE-friendly).
+This is equivalent to the size of the pack `p` in `auto&& [...p] = declval<T&>();`.
+If the argument cannot be decomposed, `__builtin_structured_binding_size(T)`
+is not a valid expression (`__builtin_structured_binding_size` is SFINAE-friendly).
builtin arrays, builtin SIMD vectors,
builtin complex types, *tuple-like* types, and decomposable class types
are decomposable types.
-A type is considered a valid *tuple-like* if ``std::tuple_size_v<T>`` is a valid expression,
-even if there is no valid ``std::tuple_element`` specialization or suitable
-``get`` function for that type.
-
-.. code-block:: c++
-
- template<std::size_t Idx, typename T>
- requires (Idx < __builtin_structured_binding_size(T))
- decltype(auto) constexpr get_binding(T&& obj) {
- auto && [...p] = std::forward<T>(obj);
- return p...[Idx];
- }
- struct S { int a = 0, b = 42; };
- static_assert(__builtin_structured_binding_size(S) == 2);
- static_assert(get_binding<1>(S{}) == 42);
+A type is considered a valid *tuple-like* if `std::tuple_size_v<T>` is a valid expression,
+even if there is no valid `std::tuple_element` specialization or suitable
+`get` function for that type.
+```c++
+template<std::size_t Idx, typename T>
+requires (Idx < __builtin_structured_binding_size(T))
+decltype(auto) constexpr get_binding(T&& obj) {
+ auto && [...p] = std::forward<T>(obj);
+ return p...[Idx];
+}
+struct S { int a = 0, b = 42; };
+static_assert(__builtin_structured_binding_size(S) == 2);
+static_assert(get_binding<1>(S{}) == 42);
+```
-Blocks
-======
+## Blocks
The syntax and high-level language feature description is in
-:doc:`BlockLanguageSpec<BlockLanguageSpec>`. Implementation and ABI details for
-the clang implementation are in :doc:`Block-ABI-Apple<Block-ABI-Apple>`.
+{doc}`BlockLanguageSpec<BlockLanguageSpec>`. Implementation and ABI details for
+the clang implementation are in {doc}`Block-ABI-Apple<Block-ABI-Apple>`.
-Query for this feature with ``__has_extension(blocks)``.
+Query for this feature with `__has_extension(blocks)`.
-ASM Goto with Output Constraints
-================================
+## ASM Goto with Output Constraints
-Outputs may be used along any branches from the ``asm goto`` whether the
+Outputs may be used along any branches from the `asm goto` whether the
branches are taken or not.
-Query for this feature with ``__has_extension(gnu_asm_goto_with_outputs)``.
+Query for this feature with `__has_extension(gnu_asm_goto_with_outputs)`.
Prior to clang-16, the output may only be used safely when the indirect
-branches are not taken. Query for this difference with
-``__has_extension(gnu_asm_goto_with_outputs_full)``.
+branches are not taken. Query for this difference with
+`__has_extension(gnu_asm_goto_with_outputs_full)`.
When using tied-outputs (i.e., outputs that are inputs and outputs, not just
outputs) with the `+r` constraint, there is a hidden input that's created
before the label, so numeric references to operands must account for that.
-.. code-block:: c++
-
- int foo(int x) {
- // %0 and %1 both refer to x
- // %l2 refers to err
- asm goto("# %0 %1 %l2" : "+r"(x) : : : err);
- return x;
- err:
- return -1;
- }
+```c++
+int foo(int x) {
+ // %0 and %1 both refer to x
+ // %l2 refers to err
+ asm goto("# %0 %1 %l2" : "+r"(x) : : : err);
+ return x;
+ err:
+ return -1;
+}
+```
This was changed to match GCC in clang-13; for better portability, symbolic
references can be used instead of numeric references.
-.. code-block:: c++
-
- int foo(int x) {
- asm goto("# %[x] %l[err]" : [x]"+r"(x) : : : err);
- return x;
- err:
- return -1;
- }
+```c++
+int foo(int x) {
+ asm goto("# %[x] %l[err]" : [x]"+r"(x) : : : err);
+ return x;
+ err:
+ return -1;
+}
+```
-ASM Goto versus Branch Target Enforcement
-=========================================
+## ASM Goto versus Branch Target Enforcement
Some target architectures implement branch target enforcement, by requiring
indirect (register-controlled) branch instructions to jump only to locations
-marked by a special instruction (such as AArch64 ``bti``).
+marked by a special instruction (such as AArch64 `bti`).
-The assembler code inside an ``asm goto`` statement is expected not to use a
+The assembler code inside an `asm goto` statement is expected not to use a
branch instruction of that kind to transfer control to any of its destination
-labels. Therefore, using a label in an ``asm goto`` statement does not cause
-clang to put a ``bti`` or equivalent instruction at the label.
+labels. Therefore, using a label in an `asm goto` statement does not cause
+clang to put a `bti` or equivalent instruction at the label.
-Constexpr strings in GNU ASM statements
-=======================================
+## Constexpr strings in GNU ASM statements
In C++11 mode (and greater), Clang supports specifying the template,
constraints, and clobber strings with a parenthesized constant expression
producing an object with the following member functions
-.. code-block:: c++
-
- constexpr const char* data() const;
- constexpr size_t size() const;
+```c++
+constexpr const char* data() const;
+constexpr size_t size() const;
+```
-such as ``std::string``, ``std::string_view``, ``std::vector<char>``.
-This mechanism follows the same rules as ``static_assert`` messages in
-C++26, see ``[dcl.pre]/p12``.
+such as `std::string`, `std::string_view`, `std::vector<char>`.
+This mechanism follows the same rules as `static_assert` messages in
+C++26, see `[dcl.pre]/p12`.
-Query for this feature with ``__has_extension(gnu_asm_constexpr_strings)``.
-
-.. code-block:: c++
-
- int foo() {
- asm((std::string_view("nop")) ::: (std::string_view("memory")));
- }
+Query for this feature with `__has_extension(gnu_asm_constexpr_strings)`.
+```c++
+int foo() {
+ asm((std::string_view("nop")) ::: (std::string_view("memory")));
+}
+```
-Objective-C Features
-====================
+## Objective-C Features
-Related result types
---------------------
+### Related result types
According to Cocoa conventions, Objective-C methods with certain names
-("``init``", "``alloc``", etc.) always return objects that are an instance of
-the receiving class's type. Such methods are said to have a "related result
+("`init`", "`alloc`", etc.) always return objects that are an instance of
+the receiving class's type. Such methods are said to have a "related result
type", meaning that a message send to one of these methods will have the same
-static type as an instance of the receiver class. For example, given the
+static type as an instance of the receiver class. For example, given the
following classes:
-.. code-block:: objc
+```objc
+ at interface NSObject
++ (id)alloc;
+- (id)init;
+ at end
- @interface NSObject
- + (id)alloc;
- - (id)init;
- @end
-
- @interface NSArray : NSObject
- @end
+ at interface NSArray : NSObject
+ at end
+```
and this common initialization pattern
-.. code-block:: objc
-
- NSArray *array = [[NSArray alloc] init];
+```objc
+NSArray *array = [[NSArray alloc] init];
+```
-the type of the expression ``[NSArray alloc]`` is ``NSArray*`` because
-``alloc`` implicitly has a related result type. Similarly, the type of the
-expression ``[[NSArray alloc] init]`` is ``NSArray*``, since ``init`` has a
-related result type and its receiver is known to have the type ``NSArray *``.
-If neither ``alloc`` nor ``init`` had a related result type, the expressions
-would have had type ``id``, as declared in the method signature.
+the type of the expression `[NSArray alloc]` is `NSArray*` because
+`alloc` implicitly has a related result type. Similarly, the type of the
+expression `[[NSArray alloc] init]` is `NSArray*`, since `init` has a
+related result type and its receiver is known to have the type `NSArray *`.
+If neither `alloc` nor `init` had a related result type, the expressions
+would have had type `id`, as declared in the method signature.
A method with a related result type can be declared by using the type
-``instancetype`` as its result type. ``instancetype`` is a contextual keyword
+`instancetype` as its result type. `instancetype` is a contextual keyword
that is only permitted in the result type of an Objective-C method, e.g.
-.. code-block:: objc
+```objc
+ at interface A
++ (instancetype)constructAnA;
+ at end
+```
- @interface A
- + (instancetype)constructAnA;
- @end
-
-The related result type can also be inferred for some methods. To determine
+The related result type can also be inferred for some methods. To determine
whether a method has an inferred related result type, the first word in the
-camel-case selector (e.g., "``init``" in "``initWithObjects``") is considered,
+camel-case selector (e.g., "`init`" in "`initWithObjects`") is considered,
and the method will have a related result type if its return type is compatible
with the type of its class and if:
-* the first word is "``alloc``" or "``new``", and the method is a class method,
+- the first word is "`alloc`" or "`new`", and the method is a class method,
or
-
-* the first word is "``autorelease``", "``init``", "``retain``", or "``self``",
+- the first word is "`autorelease`", "`init`", "`retain`", or "`self`",
and the method is an instance method.
If a method with a related result type is overridden by a subclass method, the
subclass method must also return a type that is compatible with the subclass
-type. For example:
+type. For example:
-.. code-block:: objc
-
- @interface NSString : NSObject
- - (NSUnrelated *)init; // incorrect usage: NSUnrelated is not NSString or a superclass of NSString
- @end
+```objc
+ at interface NSString : NSObject
+- (NSUnrelated *)init; // incorrect usage: NSUnrelated is not NSString or a superclass of NSString
+ at end
+```
Related result types only affect the type of a message send or property access
-via the given method. In all other respects, a method with a related result
-type is treated the same way as method that returns ``id``.
+via the given method. In all other respects, a method with a related result
+type is treated the same way as method that returns `id`.
-Use ``__has_feature(objc_instancetype)`` to determine whether the
-``instancetype`` contextual keyword is available.
+Use `__has_feature(objc_instancetype)` to determine whether the
+`instancetype` contextual keyword is available.
-Automatic reference counting
-----------------------------
+### Automatic reference counting
-Clang provides support for :doc:`automated reference counting
+Clang provides support for {doc}`automated reference counting
<AutomaticReferenceCounting>` in Objective-C, which eliminates the need
-for manual ``retain``/``release``/``autorelease`` message sends. There are three
+for manual `retain`/`release`/`autorelease` message sends. There are three
feature macros associated with automatic reference counting:
-``__has_feature(objc_arc)`` indicates the availability of automated reference
-counting in general, while ``__has_feature(objc_arc_weak)`` indicates that
-automated reference counting also includes support for ``__weak`` pointers to
-Objective-C objects. ``__has_feature(objc_arc_fields)`` indicates that C structs
+`__has_feature(objc_arc)` indicates the availability of automated reference
+counting in general, while `__has_feature(objc_arc_weak)` indicates that
+automated reference counting also includes support for `__weak` pointers to
+Objective-C objects. `__has_feature(objc_arc_fields)` indicates that C structs
are allowed to have fields that are pointers to Objective-C objects managed by
automatic reference counting.
-.. _objc-weak:
+(objc-weak)=
-Weak references
----------------
+### Weak references
Clang supports ARC-style weak and unsafe references in Objective-C even
-outside of ARC mode. Weak references must be explicitly enabled with
-the ``-fobjc-weak`` option; use ``__has_feature((objc_arc_weak))``
-to test whether they are enabled. Unsafe references are enabled
-unconditionally. ARC-style weak and unsafe references cannot be used
+outside of ARC mode. Weak references must be explicitly enabled with
+the `-fobjc-weak` option; use `__has_feature((objc_arc_weak))`
+to test whether they are enabled. Unsafe references are enabled
+unconditionally. ARC-style weak and unsafe references cannot be used
when Objective-C garbage collection is enabled.
-Except as noted below, the language rules for the ``__weak`` and
-``__unsafe_unretained`` qualifiers (and the ``weak`` and
-``unsafe_unretained`` property attributes) are just as laid out
-in the :doc:`ARC specification <AutomaticReferenceCounting>`.
+Except as noted below, the language rules for the `__weak` and
+`__unsafe_unretained` qualifiers (and the `weak` and
+`unsafe_unretained` property attributes) are just as laid out
+in the {doc}`ARC specification <AutomaticReferenceCounting>`.
In particular, note that some classes do not support forming weak
references to their instances, and note that special care must be
taken when storing weak references in memory where initialization
and deinitialization are outside the responsibility of the compiler
-(such as in ``malloc``-ed memory).
+(such as in `malloc`-ed memory).
-Loading from a ``__weak`` variable always implicitly retains the
-loaded value. In non-ARC modes, this retain is normally balanced
-by an implicit autorelease. This autorelease can be suppressed
-by performing the load in the receiver position of a ``-retain``
-message send (e.g., ``[weakReference retain]``); note that this performs
+Loading from a `__weak` variable always implicitly retains the
+loaded value. In non-ARC modes, this retain is normally balanced
+by an implicit autorelease. This autorelease can be suppressed
+by performing the load in the receiver position of a `-retain`
+message send (e.g., `[weakReference retain]`); note that this performs
only a single retain (the retain done when primitively loading from
the weak reference).
-For the most part, ``__unsafe_unretained`` in non-ARC modes is just the
-default behavior of variables and therefore is not needed. However,
+For the most part, `__unsafe_unretained` in non-ARC modes is just the
+default behavior of variables and therefore is not needed. However,
it does have an effect on the semantics of block captures: normally,
copying a block which captures an Objective-C object or block pointer
causes the captured pointer to be retained or copied, respectively,
but that behavior is suppressed when the captured variable is qualified
-with ``__unsafe_unretained``.
+with `__unsafe_unretained`.
-Note that the ``__weak`` qualifier formerly meant the GC qualifier in
-all non-ARC modes and was silently ignored outside of GC modes. It now
+Note that the `__weak` qualifier formerly meant the GC qualifier in
+all non-ARC modes and was silently ignored outside of GC modes. It now
means the ARC-style qualifier in all non-GC modes and is no longer
-allowed if not enabled by either ``-fobjc-arc`` or ``-fobjc-weak``.
-It is expected that ``-fobjc-weak`` will eventually be enabled by default
+allowed if not enabled by either `-fobjc-arc` or `-fobjc-weak`.
+It is expected that `-fobjc-weak` will eventually be enabled by default
in all non-GC Objective-C modes.
-.. _objc-fixed-enum:
+(objc-fixed-enum)=
-Enumerations with a fixed underlying type
------------------------------------------
+### Enumerations with a fixed underlying type
Clang provides support for C++11 enumerations with a fixed underlying type
-within Objective-C and C `prior to C23 <https://open-std.org/JTC1/SC22/WG14/www/docs/n3030.htm>`_. For example, one can write an enumeration type as:
-
-.. code-block:: c++
+within Objective-C and C [prior to C23](https://open-std.org/JTC1/SC22/WG14/www/docs/n3030.htm). For example, one can write an enumeration type as:
- typedef enum : unsigned char { Red, Green, Blue } Color;
+```c++
+typedef enum : unsigned char { Red, Green, Blue } Color;
+```
This specifies that the underlying type, which is used to store the enumeration
-value, is ``unsigned char``.
+value, is `unsigned char`.
-Use ``__has_feature(objc_fixed_enum)`` to determine whether support for fixed
+Use `__has_feature(objc_fixed_enum)` to determine whether support for fixed
underlying types is available in Objective-C.
-Use ``__has_extension(c_fixed_enum)`` to determine whether support for fixed
-underlying types is available in C prior to C23. This will also report ``true`` in C23
+Use `__has_extension(c_fixed_enum)` to determine whether support for fixed
+underlying types is available in C prior to C23. This will also report `true` in C23
and later modes as the functionality is available even if it's not an extension in
those modes.
-Use ``__has_feature(c_fixed_enum)`` to determine whether support for fixed
+Use `__has_feature(c_fixed_enum)` to determine whether support for fixed
underlying types is available in C23 and later.
-Enumerations with no enumerators
---------------------------------
+### Enumerations with no enumerators
Clang provides support for Microsoft extensions to support enumerations with no enumerators.
-.. code-block:: c++
-
- typedef enum empty { } A;
+```c++
+typedef enum empty { } A;
+```
-Microsoft Anonymous Structs and Unions
---------------------------------------
+### Microsoft Anonymous Structs and Unions
Clang provides support for a Microsoft extension that allows use of named struct or union types to
declare anonymous members inside another struct or union, making their fields directly accessible
@@ -2622,21 +2397,21 @@ from the enclosing type.
For example, consider the following code:
-.. code-block:: c
-
- struct Inner {
- int x;
- int y;
- };
+```c
+struct Inner {
+ int x;
+ int y;
+};
- struct Outer {
- struct Inner; /* Microsoft extension: named anonymous struct member */
- };
+struct Outer {
+ struct Inner; /* Microsoft extension: named anonymous struct member */
+};
- void f(struct Outer *o) {
- o->x = 1; /* accesses x member of anonymous member of type Inner directly */
- o->y = 1; /* accesses x member of anonymous member of type Inner directly */
- }
+void f(struct Outer *o) {
+ o->x = 1; /* accesses x member of anonymous member of type Inner directly */
+ o->y = 1; /* accesses x member of anonymous member of type Inner directly */
+}
+```
Without this extension, such declarations generate a warning that the declaration does not
declare anything, the associated member names are not available for access, and the layout
@@ -2644,68 +2419,66 @@ of types containing such declarations are affected accordingly.
This extension can be controlled independently of other Microsoft extensions:
-* ``-fms-anonymous-structs``
- Enable named anonymous struct/union support
-
-* ``-fno-ms-anonymous-structs``
- Disable anonymous struct/union support
+- `-fms-anonymous-structs`
+ : Enable named anonymous struct/union support
+- `-fno-ms-anonymous-structs`
+ : Disable anonymous struct/union support
This extension is also **implicitly enabled** when either of the following options is used:
-* ``-fms-extensions``
-* ``-fms-compatibility``
+- `-fms-extensions`
+- `-fms-compatibility`
When multiple controlling options are specified, the last option on the command line takes
precedence.
-Interoperability with C++11 lambdas
------------------------------------
+### Interoperability with C++11 lambdas
Clang provides interoperability between C++11 lambdas and blocks-based APIs, by
permitting a lambda to be implicitly converted to a block pointer with the
-corresponding signature. For example, consider an API such as ``NSArray``'s
+corresponding signature. For example, consider an API such as `NSArray`'s
array-sorting method:
-.. code-block:: objc
-
- - (NSArray *)sortedArrayUsingComparator:(NSComparator)cmptr;
+```objc
+- (NSArray *)sortedArrayUsingComparator:(NSComparator)cmptr;
+```
-``NSComparator`` is simply a typedef for the block pointer ``NSComparisonResult
-(^)(id, id)``, and parameters of this type are generally provided with block
-literals as arguments. However, one can also use a C++11 lambda so long as it
+`NSComparator` is simply a typedef for the block pointer `NSComparisonResult
+(^)(id, id)`, and parameters of this type are generally provided with block
+literals as arguments. However, one can also use a C++11 lambda so long as it
provides the same signature (in this case, accepting two parameters of type
-``id`` and returning an ``NSComparisonResult``):
-
-.. code-block:: objc
-
- NSArray *array = @[@"string 1", @"string 21", @"string 12", @"String 11",
- @"String 02"];
- const NSStringCompareOptions comparisonOptions
- = NSCaseInsensitiveSearch | NSNumericSearch |
- NSWidthInsensitiveSearch | NSForcedOrderingSearch;
- NSLocale *currentLocale = [NSLocale currentLocale];
- NSArray *sorted
- = [array sortedArrayUsingComparator:[=](id s1, id s2) -> NSComparisonResult {
- NSRange string1Range = NSMakeRange(0, [s1 length]);
- return [s1 compare:s2 options:comparisonOptions
- range:string1Range locale:currentLocale];
- }];
- NSLog(@"sorted: %@", sorted);
+`id` and returning an `NSComparisonResult`):
+
+```objc
+NSArray *array = @[@"string 1", @"string 21", @"string 12", @"String 11",
+ @"String 02"];
+const NSStringCompareOptions comparisonOptions
+ = NSCaseInsensitiveSearch | NSNumericSearch |
+ NSWidthInsensitiveSearch | NSForcedOrderingSearch;
+NSLocale *currentLocale = [NSLocale currentLocale];
+NSArray *sorted
+ = [array sortedArrayUsingComparator:[=](id s1, id s2) -> NSComparisonResult {
+ NSRange string1Range = NSMakeRange(0, [s1 length]);
+ return [s1 compare:s2 options:comparisonOptions
+ range:string1Range locale:currentLocale];
+ }];
+NSLog(@"sorted: %@", sorted);
+```
This code relies on an implicit conversion from the type of the lambda
expression (an unnamed, local class type called the *closure type*) to the
-corresponding block pointer type. The conversion itself is expressed by a
+corresponding block pointer type. The conversion itself is expressed by a
conversion operator in that closure type that produces a block pointer with the
same signature as the lambda itself, e.g.,
-.. code-block:: objc
-
- operator NSComparisonResult (^)(id, id)() const;
+```objc
+operator NSComparisonResult (^)(id, id)() const;
+```
This conversion function returns a new block that simply forwards the two
parameters to the lambda object (which it captures by copy), then returns the
-result. The returned block is first copied (with ``Block_copy``) and then
-autoreleased. As an optimization, if a lambda expression is immediately
+result. The returned block is first copied (with `Block_copy`) and then
+autoreleased. As an optimization, if a lambda expression is immediately
converted to a block pointer (as in the first example, above), then the block
is not copied and autoreleased: rather, it is given the same lifetime as a
block literal written at that point in the program, which avoids the overhead
@@ -2715,223 +2488,211 @@ The conversion from a lambda to a block pointer is only available in
Objective-C++, and not in C++ with blocks, due to its use of Objective-C memory
management (autorelease).
-Object Literals and Subscripting
---------------------------------
+### Object Literals and Subscripting
-Clang provides support for :doc:`Object Literals and Subscripting
+Clang provides support for {doc}`Object Literals and Subscripting
<ObjectiveCLiterals>` in Objective-C, which simplifies common Objective-C
programming patterns, makes programs more concise, and improves the safety of
-container creation. There are several feature macros associated with object
-literals and subscripting: ``__has_feature(objc_array_literals)`` tests the
-availability of array literals; ``__has_feature(objc_dictionary_literals)``
-tests the availability of dictionary literals; ``objc_constant_literals``
+container creation. There are several feature macros associated with object
+literals and subscripting: `__has_feature(objc_array_literals)` tests the
+availability of array literals; `__has_feature(objc_dictionary_literals)`
+tests the availability of dictionary literals; `objc_constant_literals`
tests the availability of having number, array, and dictionary literals
-emitted at compile time; ``__has_feature(objc_subscripting)`` tests the availability of object
+emitted at compile time; `__has_feature(objc_subscripting)` tests the availability of object
subscripting.
-Objective-C Autosynthesis of Properties
----------------------------------------
+### Objective-C Autosynthesis of Properties
-Clang provides support for autosynthesis of declared properties. Using this
+Clang provides support for autosynthesis of declared properties. Using this
feature, clang provides default synthesis of those properties not declared
@dynamic and not having user-provided backing getter and setter methods.
-``__has_feature(objc_default_synthesize_properties)`` checks for availability
+`__has_feature(objc_default_synthesize_properties)` checks for availability
of this feature in version of clang being used.
-.. _langext-objc-retain-release:
+(langext-objc-retain-release)=
-Objective-C retaining behavior attributes
------------------------------------------
+### Objective-C retaining behavior attributes
In Objective-C, functions and methods are generally assumed to follow the
-`Cocoa Memory Management
-<https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html>`_
+[Cocoa Memory Management](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html)
conventions for ownership of object arguments and
return values. However, there are exceptions, and so Clang provides attributes
to allow these exceptions to be documented. These are used by ARC and the
-`static analyzer <https://clang-analyzer.llvm.org>`_ Some exceptions may be
-better described using the ``objc_method_family`` attribute instead.
+[static analyzer](https://clang-analyzer.llvm.org) Some exceptions may be
+better described using the `objc_method_family` attribute instead.
-**Usage**: The ``ns_returns_retained``, ``ns_returns_not_retained``,
-``ns_returns_autoreleased``, ``cf_returns_retained``, and
-``cf_returns_not_retained`` attributes can be placed on methods and functions
+**Usage**: The `ns_returns_retained`, `ns_returns_not_retained`,
+`ns_returns_autoreleased`, `cf_returns_retained`, and
+`cf_returns_not_retained` attributes can be placed on methods and functions
that return Objective-C or CoreFoundation objects. They are commonly placed at
the end of a function prototype or method declaration:
-.. code-block:: objc
-
- id foo() __attribute__((ns_returns_retained));
+```objc
+id foo() __attribute__((ns_returns_retained));
- - (NSString *)bar:(int)x __attribute__((ns_returns_retained));
+- (NSString *)bar:(int)x __attribute__((ns_returns_retained));
+```
-The ``*_returns_retained`` attributes specify that the returned object has a +1
-retain count. The ``*_returns_not_retained`` attributes specify that the return
+The `*_returns_retained` attributes specify that the returned object has a +1
+retain count. The `*_returns_not_retained` attributes specify that the return
object has a +0 retain count, even if the normal convention for its selector
-would be +1. ``ns_returns_autoreleased`` specifies that the returned object is
+would be +1. `ns_returns_autoreleased` specifies that the returned object is
+0, but is guaranteed to live at least as long as the next flush of an
autorelease pool.
-**Usage**: The ``ns_consumed`` and ``cf_consumed`` attributes can be placed on
+**Usage**: The `ns_consumed` and `cf_consumed` attributes can be placed on
a parameter declaration; they specify that the argument is expected to have a
+1 retain count, which will be balanced in some way by the function or method.
-The ``ns_consumes_self`` attribute can only be placed on an Objective-C
-method; it specifies that the method expects its ``self`` parameter to have a
+The `ns_consumes_self` attribute can only be placed on an Objective-C
+method; it specifies that the method expects its `self` parameter to have a
+1 retain count, which it will balance in some way.
-.. code-block:: objc
+```objc
+void foo(__attribute__((ns_consumed)) NSString *string);
- void foo(__attribute__((ns_consumed)) NSString *string);
-
- - (void) bar __attribute__((ns_consumes_self));
- - (void) baz:(id) __attribute__((ns_consumed)) x;
+- (void) bar __attribute__((ns_consumes_self));
+- (void) baz:(id) __attribute__((ns_consumed)) x;
+```
Further examples of these attributes are available in the static analyzer's
-`list of annotations for analysis <analyzer/user-docs/Annotations.html#cocoa-mem>`__.
+[list of annotations for analysis](analyzer/user-docs/Annotations.html#cocoa-mem).
-Query for these features with ``__has_attribute(ns_consumed)``,
-``__has_attribute(ns_returns_retained)``, etc.
+Query for these features with `__has_attribute(ns_consumed)`,
+`__has_attribute(ns_returns_retained)`, etc.
-Objective-C @available
-----------------------
+### Objective-C @available
It is possible to use the newest SDK but still build a program that can run on
-older versions of macOS and iOS by passing ``-mmacos-version-min=`` /
-``-miphoneos-version-min=``.
+older versions of macOS and iOS by passing `-mmacos-version-min=` /
+`-miphoneos-version-min=`.
Before LLVM 5.0, when calling a function that exists only in the OS that's
newer than the target OS (as determined by the minimum deployment version),
programmers had to carefully check if the function exists at runtime, using
-null checks for weakly-linked C functions, ``+class`` for Objective-C classes,
-and ``-respondsToSelector:`` or ``+instancesRespondToSelector:`` for
-Objective-C methods. If such a check was missed, the program would compile
+null checks for weakly-linked C functions, `+class` for Objective-C classes,
+and `-respondsToSelector:` or `+instancesRespondToSelector:` for
+Objective-C methods. If such a check was missed, the program would compile
fine, run fine on newer systems, but crash on older systems.
-As of LLVM 5.0, ``-Wunguarded-availability`` uses the `availability attributes
-<https://clang.llvm.org/docs/AttributeReference.html#availability>`_ together
-with the new ``@available()`` keyword to assist with this issue.
+As of LLVM 5.0, `-Wunguarded-availability` uses the [availability attributes](https://clang.llvm.org/docs/AttributeReference.html#availability) together
+with the new `@available()` keyword to assist with this issue.
When a method that's introduced in the OS newer than the target OS is called, a
-Wunguarded-availability warning is emitted if that call is not guarded:
-.. code-block:: objc
-
- void my_fun(NSSomeClass* var) {
- // If fancyNewMethod was added in e.g., macOS 10.12, but the code is
- // built with -mmacos-version-min=10.11, then this unconditional call
- // will emit a -Wunguarded-availability warning:
- [var fancyNewMethod];
- }
+```objc
+void my_fun(NSSomeClass* var) {
+ // If fancyNewMethod was added in e.g., macOS 10.12, but the code is
+ // built with -mmacos-version-min=10.11, then this unconditional call
+ // will emit a -Wunguarded-availability warning:
+ [var fancyNewMethod];
+}
+```
To fix the warning and to avoid the crash on macOS 10.11, wrap it in
-``if(@available())``:
+`if(@available())`:
-.. code-block:: objc
-
- void my_fun(NSSomeClass* var) {
- if (@available(macOS 10.12, *)) {
- [var fancyNewMethod];
- } else {
- // Put fallback behavior for old macOS versions (and for non-mac
- // platforms) here.
- }
+```objc
+void my_fun(NSSomeClass* var) {
+ if (@available(macOS 10.12, *)) {
+ [var fancyNewMethod];
+ } else {
+ // Put fallback behavior for old macOS versions (and for non-mac
+ // platforms) here.
}
+}
+```
-The ``*`` is required and means that platforms not explicitly listed will take
-the true branch, and the compiler will emit ``-Wunguarded-availability``
+The `*` is required and means that platforms not explicitly listed will take
+the true branch, and the compiler will emit `-Wunguarded-availability`
warnings for unlisted platforms based on those platform's deployment target.
-More than one platform can be listed in ``@available()``:
-
-.. code-block:: objc
+More than one platform can be listed in `@available()`:
- void my_fun(NSSomeClass* var) {
- if (@available(macOS 10.12, iOS 10, *)) {
- [var fancyNewMethod];
- }
+```objc
+void my_fun(NSSomeClass* var) {
+ if (@available(macOS 10.12, iOS 10, *)) {
+ [var fancyNewMethod];
}
+}
+```
-If the caller of ``my_fun()`` already checks that ``my_fun()`` is only called
-on 10.12, then add an `availability attribute
-<https://clang.llvm.org/docs/AttributeReference.html#availability>`_ to it,
+If the caller of `my_fun()` already checks that `my_fun()` is only called
+on 10.12, then add an [availability attribute](https://clang.llvm.org/docs/AttributeReference.html#availability) to it,
which will also suppress the warning and require that calls to my_fun() are
checked:
-.. code-block:: objc
-
- API_AVAILABLE(macos(10.12)) void my_fun(NSSomeClass* var) {
- [var fancyNewMethod]; // Now ok.
- }
+```objc
+API_AVAILABLE(macos(10.12)) void my_fun(NSSomeClass* var) {
+ [var fancyNewMethod]; // Now ok.
+}
+```
-``@available()`` is only available in Objective-C code. To use the feature
-in C and C++ code, use the ``__builtin_available()`` spelling instead.
+`@available()` is only available in Objective-C code. To use the feature
+in C and C++ code, use the `__builtin_available()` spelling instead.
-If existing code uses null checks or ``-respondsToSelector:``, it should
-be changed to use ``@available()`` (or ``__builtin_available``) instead.
+If existing code uses null checks or `-respondsToSelector:`, it should
+be changed to use `@available()` (or `__builtin_available`) instead.
-``-Wunguarded-availability`` is disabled by default, but
-``-Wunguarded-availability-new``, which only emits this warning for APIs
+`-Wunguarded-availability` is disabled by default, but
+`-Wunguarded-availability-new`, which only emits this warning for APIs
that have been introduced in macOS >= 10.13, iOS >= 11, watchOS >= 4 and
tvOS >= 11, is enabled by default.
-.. _langext-overloading:
+(langext-overloading)=
-Objective-C++ ABI: protocol-qualifier mangling of parameters
-------------------------------------------------------------
+### Objective-C++ ABI: protocol-qualifier mangling of parameters
Starting with LLVM 3.4, Clang produces a new mangling for parameters whose
-type is a qualified-``id`` (e.g., ``id<Foo>``). This mangling allows such
-parameters to be differentiated from those with the regular unqualified ``id``
+type is a qualified-`id` (e.g., `id<Foo>`). This mangling allows such
+parameters to be differentiated from those with the regular unqualified `id`
type.
-This was a non-backward compatible mangling change to the ABI. This change
+This was a non-backward compatible mangling change to the ABI. This change
allows proper overloading, and also prevents mangling conflicts with template
parameters of protocol-qualified type.
Query the presence of this new mangling with
-``__has_feature(objc_protocol_qualifier_mangling)``.
+`__has_feature(objc_protocol_qualifier_mangling)`.
-Initializer lists for complex numbers in C
-==========================================
+## Initializer lists for complex numbers in C
clang supports an extension which allows the following in C:
-.. code-block:: c++
-
- #include <math.h>
- #include <complex.h>
- complex float x = { 1.0f, INFINITY }; // Init to (1, Inf)
+```c++
+#include <math.h>
+#include <complex.h>
+complex float x = { 1.0f, INFINITY }; // Init to (1, Inf)
+```
This construct is useful because there is no way to separately initialize the
real and imaginary parts of a complex variable in standard C, given that clang
-does not support ``_Imaginary``. (Clang also supports the ``__real__`` and
-``__imag__`` extensions from gcc, which help in some cases, but are not usable
+does not support `_Imaginary`. (Clang also supports the `__real__` and
+`__imag__` extensions from gcc, which help in some cases, but are not usable
in static initializers.)
Note that this extension does not allow eliding the braces; the meaning of the
following two lines is different:
-.. code-block:: c++
-
- complex float x[] = { { 1.0f, 1.0f } }; // [0] = (1, 1)
- complex float x[] = { 1.0f, 1.0f }; // [0] = (1, 0), [1] = (1, 0)
+```c++
+complex float x[] = { { 1.0f, 1.0f } }; // [0] = (1, 1)
+complex float x[] = { 1.0f, 1.0f }; // [0] = (1, 0), [1] = (1, 0)
+```
This extension also works in C++ mode, as far as that goes, but does not apply
-to the C++ ``std::complex``. (In C++11, list initialization allows the same
-syntax to be used with ``std::complex`` with the same meaning.)
+to the C++ `std::complex`. (In C++11, list initialization allows the same
+syntax to be used with `std::complex` with the same meaning.)
-For GCC compatibility, ``__builtin_complex(re, im)`` can also be used to
+For GCC compatibility, `__builtin_complex(re, im)` can also be used to
construct a complex number from the given real and imaginary components.
-OpenCL Features
-===============
+## OpenCL Features
Clang supports internal OpenCL extensions documented below.
-``__cl_clang_bitfields``
---------------------------------
+### `__cl_clang_bitfields`
With this extension it is possible to enable bitfields in structs
or unions using the OpenCL extension pragma mechanism detailed in
-`the OpenCL Extension Specification, section 1.2
-<https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview>`_.
+[the OpenCL Extension Specification, section 1.2](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview).
Use of bitfields in OpenCL kernels can result in reduced portability as struct
layout is not guaranteed to be consistent when compiled by different compilers.
@@ -2941,33 +2702,29 @@ device code.
**Example of Use**:
-.. code-block:: c++
-
- #pragma OPENCL EXTENSION __cl_clang_bitfields : enable
- struct with_bitfield {
- unsigned int i : 5; // compiled - no diagnostic generated
- };
+```c++
+#pragma OPENCL EXTENSION __cl_clang_bitfields : enable
+struct with_bitfield {
+ unsigned int i : 5; // compiled - no diagnostic generated
+};
- #pragma OPENCL EXTENSION __cl_clang_bitfields : disable
- struct without_bitfield {
- unsigned int i : 5; // error - bitfields are not supported
- };
+#pragma OPENCL EXTENSION __cl_clang_bitfields : disable
+struct without_bitfield {
+ unsigned int i : 5; // error - bitfields are not supported
+};
+```
-``__cl_clang_function_pointers``
---------------------------------
+### `__cl_clang_function_pointers`
With this extension it is possible to enable various language features that
are relying on function pointers using regular OpenCL extension pragma
-mechanism detailed in `the OpenCL Extension Specification,
-section 1.2
-<https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview>`_.
+mechanism detailed in [the OpenCL Extension Specification,
+section 1.2](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview).
In C++ for OpenCL this also enables:
- Use of member function pointers;
-
- Unrestricted use of references to functions;
-
- Virtual member functions.
Such functionality is not conformant and does not guarantee to compile
@@ -2976,36 +2733,32 @@ correctly in any circumstances. It can be used if:
- the kernel source does not contain call expressions to (member-) function
pointers, or virtual functions. For example, this extension can be used in
metaprogramming algorithms to be able to specify/detect types generically.
-
- the generated kernel binary does not contain indirect calls because they
are eliminated using compiler optimizations e.g., devirtualization.
-
- the selected target supports the function pointer like functionality e.g.
most CPU targets.
**Example of Use**:
-.. code-block:: c++
+```c++
+#pragma OPENCL EXTENSION __cl_clang_function_pointers : enable
+void foo()
+{
+ void (*fp)(); // compiled - no diagnostic generated
+}
- #pragma OPENCL EXTENSION __cl_clang_function_pointers : enable
- void foo()
- {
- void (*fp)(); // compiled - no diagnostic generated
- }
-
- #pragma OPENCL EXTENSION __cl_clang_function_pointers : disable
- void bar()
- {
- void (*fp)(); // error - pointers to function are not allowed
- }
+#pragma OPENCL EXTENSION __cl_clang_function_pointers : disable
+void bar()
+{
+ void (*fp)(); // error - pointers to function are not allowed
+}
+```
-``__cl_clang_variadic_functions``
----------------------------------
+### `__cl_clang_variadic_functions`
With this extension it is possible to enable variadic arguments in functions
-using regular OpenCL extension pragma mechanism detailed in `the OpenCL
-Extension Specification, section 1.2
-<https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview>`_.
+using regular OpenCL extension pragma mechanism detailed in [the OpenCL
+Extension Specification, section 1.2](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview).
This is not conformant behavior and it can only be used portably when the
functions with variadic prototypes do not get generated in binary e.g., the
@@ -3017,23 +2770,20 @@ supporting the variadic arguments e.g., majority of CPU targets.
**Example of Use**:
-.. code-block:: c++
-
- #pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
- void foo(int a, ...); // compiled - no diagnostic generated
+```c++
+#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
+void foo(int a, ...); // compiled - no diagnostic generated
- #pragma OPENCL EXTENSION __cl_clang_variadic_functions : disable
- void bar(int a, ...); // error - variadic prototype is not allowed
+#pragma OPENCL EXTENSION __cl_clang_variadic_functions : disable
+void bar(int a, ...); // error - variadic prototype is not allowed
+```
-``__cl_clang_non_portable_kernel_param_types``
-----------------------------------------------
+### `__cl_clang_non_portable_kernel_param_types`
With this extension it is possible to enable the use of some restricted types
-in kernel parameters specified in `C++ for OpenCL v1.0 s2.4
-<https://www.khronos.org/opencl/assets/CXX_for_OpenCL.html#kernel_function>`_.
+in kernel parameters specified in [C++ for OpenCL v1.0 s2.4](https://www.khronos.org/opencl/assets/CXX_for_OpenCL.html#kernel_function).
The restrictions can be relaxed using regular OpenCL extension pragma mechanism
-detailed in `the OpenCL Extension Specification, section 1.2
-<https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview>`_.
+detailed in [the OpenCL Extension Specification, section 1.2](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview).
This is not a conformant behavior and it can only be used when the
kernel arguments are not accessed on the host side or the data layout/size
@@ -3041,50 +2791,47 @@ between the host and device is known to be compatible.
**Example of Use**:
-.. code-block:: c++
-
- // Plain Old Data type.
- struct Pod {
- int a;
- int b;
- };
-
- // Not POD type because of the constructor.
- // Standard layout type because there is only one access control.
- struct OnlySL {
- int a;
- int b;
- OnlySL() : a(0), b(0) {}
- };
-
- // Not standard layout type because of two different access controls.
- struct NotSL {
- int a;
- private:
- int b;
- };
-
- #pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : enable
- kernel void kernel_main(
- Pod a,
-
- OnlySL b,
- global NotSL *c,
- global OnlySL *d
- );
- #pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : disable
-
-``__cl_clang_function_scope_local_variables``
-----------------------------------------------
+```c++
+// Plain Old Data type.
+struct Pod {
+ int a;
+ int b;
+};
+
+// Not POD type because of the constructor.
+// Standard layout type because there is only one access control.
+struct OnlySL {
+ int a;
+ int b;
+ OnlySL() : a(0), b(0) {}
+};
+
+// Not standard layout type because of two different access controls.
+struct NotSL {
+ int a;
+private:
+ int b;
+};
+
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : enable
+kernel void kernel_main(
+ Pod a,
+
+ OnlySL b,
+ global NotSL *c,
+ global OnlySL *d
+);
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : disable
+```
+
+### `__cl_clang_function_scope_local_variables`
This extension allows declaring variables in the local address space within
function scope, including non-kernel functions or nested scopes within a kernel,
-using regular OpenCL extension pragma mechanism detailed in `the OpenCL
-Extension Specification, section 1.2
-<https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview>`_.
+using regular OpenCL extension pragma mechanism detailed in [the OpenCL
+Extension Specification, section 1.2](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview).
-This relaxes the `Declaration Scopes and Variable Types
-<https://registry.khronos.org/OpenCL/specs/3.0-unified/html/OpenCL_C.html#_usage_for_declaration_scopes_and_variable_types>`_
+This relaxes the [Declaration Scopes and Variable Types](https://registry.khronos.org/OpenCL/specs/3.0-unified/html/OpenCL_C.html#_usage_for_declaration_scopes_and_variable_types)
rule that limits local-address-space variable declarations to the outermost
compound statement inside the body of the kernel function.
@@ -3092,58 +2839,56 @@ To expose static local allocations at kernel scope, targets can either force-
inline non-kernel functions that declare local memory or pass a kernel-allocated
local buffer to those functions via an implicit argument.
-.. code-block:: c++
-
- #pragma OPENCL EXTENSION __cl_clang_function_scope_local_variables : enable
- kernel void kernel1(...)
- {
- {
- local float a; // compiled - no diagnostic generated
- }
- }
- void foo()
- {
- local float c; // compiled - no diagnostic generated
- }
-
- #pragma OPENCL EXTENSION __cl_clang_function_scope_local_variables : disable
- kernel void kernel2(...)
+```c++
+#pragma OPENCL EXTENSION __cl_clang_function_scope_local_variables : enable
+kernel void kernel1(...)
+{
{
- {
- local float a; // error - variables in the local address space can only be declared in the outermost scope of a kernel function
- }
+ local float a; // compiled - no diagnostic generated
}
- void bar()
+}
+void foo()
+{
+ local float c; // compiled - no diagnostic generated
+}
+
+#pragma OPENCL EXTENSION __cl_clang_function_scope_local_variables : disable
+kernel void kernel2(...)
+{
{
- local float c; // error - non-kernel function variable cannot be declared in local address space
+ local float a; // error - variables in the local address space can only be declared in the outermost scope of a kernel function
}
+}
+void bar()
+{
+ local float c; // error - non-kernel function variable cannot be declared in local address space
+}
+```
-Remove address space builtin function
--------------------------------------
+### Remove address space builtin function
-``__remove_address_space`` allows to derive types in C++ for OpenCL
+`__remove_address_space` allows to derive types in C++ for OpenCL
that have address space qualifiers removed. This utility only affects
address space qualifiers, therefore, other type qualifiers such as
-``const`` or ``volatile`` remain unchanged.
+`const` or `volatile` remain unchanged.
**Example of Use**:
-.. code-block:: c++
-
- template<typename T>
- void foo(T *par){
- T var1; // error - local function variable with global address space
- __private T var2; // error - conflicting address space qualifiers
- __private __remove_address_space<T>::type var3; // var3 is __private int
- }
+```c++
+template<typename T>
+void foo(T *par){
+ T var1; // error - local function variable with global address space
+ __private T var2; // error - conflicting address space qualifiers
+ __private __remove_address_space<T>::type var3; // var3 is __private int
+}
- void bar(){
- __global int* ptr;
- foo(ptr);
- }
+void bar(){
+ __global int* ptr;
+ foo(ptr);
+}
+```
-Legacy 1.x atomics with generic address space
----------------------------------------------
+### Legacy 1.x atomics with generic address space
Clang allows the use of atomic functions from the OpenCL 1.x standards
with the generic address space pointer in C++ for OpenCL mode.
@@ -3153,23 +2898,21 @@ targets.
**Example of Use**:
-.. code-block:: c++
-
- void foo(__generic volatile unsigned int* a) {
- atomic_add(a, 1);
- }
+```c++
+void foo(__generic volatile unsigned int* a) {
+ atomic_add(a, 1);
+}
+```
-WebAssembly Features
-====================
+## WebAssembly Features
Clang supports the WebAssembly features documented below. For further
-information related to the semantics of the builtins, please refer to the `WebAssembly Specification <https://webassembly.github.io/spec/core/>`_.
+information related to the semantics of the builtins, please refer to the [WebAssembly Specification](https://webassembly.github.io/spec/core/).
In this section, when we refer to reference types, we are referring to
WebAssembly reference types, not C++ reference types unless stated
otherwise.
-``__builtin_wasm_table_set``
-----------------------------
+### `__builtin_wasm_table_set`
This builtin function stores a value in a WebAssembly table.
It takes three arguments.
@@ -3178,52 +2921,49 @@ argument is the index to which to store the value into, and the
third argument is a value of reference type to store in the table.
It returns nothing.
-.. code-block:: c++
-
- static __externref_t table[0];
- extern __externref_t JSObj;
+```c++
+static __externref_t table[0];
+extern __externref_t JSObj;
- void store(int index) {
- __builtin_wasm_table_set(table, index, JSObj);
- }
+void store(int index) {
+ __builtin_wasm_table_set(table, index, JSObj);
+}
+```
-``__builtin_wasm_table_get``
-----------------------------
+### `__builtin_wasm_table_get`
-This builtin function is the counterpart to ``__builtin_wasm_table_set``
+This builtin function is the counterpart to `__builtin_wasm_table_set`
and loads a value from a WebAssembly table of reference typed values.
It takes 2 arguments.
The first argument is a table of reference typed values and the
second argument is an index from which to load the value. It returns
the loaded reference typed value.
-.. code-block:: c++
-
- static __externref_t table[0];
+```c++
+static __externref_t table[0];
- __externref_t load(int index) {
- __externref_t Obj = __builtin_wasm_table_get(table, index);
- return Obj;
- }
+__externref_t load(int index) {
+ __externref_t Obj = __builtin_wasm_table_get(table, index);
+ return Obj;
+}
+```
-``__builtin_wasm_table_size``
------------------------------
+### `__builtin_wasm_table_size`
This builtin function returns the size of the WebAssembly table.
-Takes the table as an argument and returns an unsigned integer (``size_t``)
+Takes the table as an argument and returns an unsigned integer (`size_t`)
with the current table size.
-.. code-block:: c++
-
- typedef void (*__funcref funcref_t)();
- static funcref_t table[0];
+```c++
+typedef void (*__funcref funcref_t)();
+static funcref_t table[0];
- size_t getSize() {
- return __builtin_wasm_table_size(table);
- }
+size_t getSize() {
+ return __builtin_wasm_table_size(table);
+}
+```
-``__builtin_wasm_table_grow``
------------------------------
+### `__builtin_wasm_table_grow`
This builtin function grows the WebAssembly table by a certain amount.
Currently, as all WebAssembly tables created in C/C++ are zero-sized,
@@ -3235,21 +2975,20 @@ the new table entries (the initialization value), and the third argument
is the amount to grow the table by. It returns the previous table size
or -1. It will return -1 if not enough space could be allocated.
-.. code-block:: c++
-
- typedef void (*__funcref funcref_t)();
- static funcref_t table[0];
+```c++
+typedef void (*__funcref funcref_t)();
+static funcref_t table[0];
- // grow returns the new table size or -1 on error.
- int grow(funcref_t fn, int delta) {
- int prevSize = __builtin_wasm_table_grow(table, fn, delta);
- if (prevSize == -1)
- return -1;
- return prevSize + delta;
- }
+// grow returns the new table size or -1 on error.
+int grow(funcref_t fn, int delta) {
+ int prevSize = __builtin_wasm_table_grow(table, fn, delta);
+ if (prevSize == -1)
+ return -1;
+ return prevSize + delta;
+}
+```
-``__builtin_wasm_table_fill``
------------------------------
+### `__builtin_wasm_table_fill`
This builtin function sets all the entries of a WebAssembly table to a given
reference typed value. It takes four arguments. The first argument is
@@ -3258,18 +2997,17 @@ range, the third argument is the value to set in the new entries, and
the fourth and the last argument is the size of the range. It returns
nothing.
-.. code-block:: c++
-
- static __externref_t table[0];
+```c++
+static __externref_t table[0];
- // resets a table by setting all of its entries to a given value.
- void reset(__externref_t Obj) {
- int Size = __builtin_wasm_table_size(table);
- __builtin_wasm_table_fill(table, 0, Obj, Size);
- }
+// resets a table by setting all of its entries to a given value.
+void reset(__externref_t Obj) {
+ int Size = __builtin_wasm_table_size(table);
+ __builtin_wasm_table_fill(table, 0, Obj, Size);
+}
+```
-``__builtin_wasm_table_copy``
------------------------------
+### `__builtin_wasm_table_copy`
This builtin function copies elements from a source WebAssembly table
to a possibly overlapping destination region. It takes five arguments.
@@ -3279,130 +3017,124 @@ destination index from where the copy starts, the fourth argument is the
source index from where the copy starts, and the fifth and last argument
is the number of elements to copy. It returns nothing.
-.. code-block:: c++
-
- static __externref_t tableSrc[0];
- static __externref_t tableDst[0];
-
- // Copy nelem elements from [src, src + nelem - 1] in tableSrc to
- // [dst, dst + nelem - 1] in tableDst
- void copy(int dst, int src, int nelem) {
- __builtin_wasm_table_copy(tableDst, tableSrc, dst, src, nelem);
- }
+```c++
+static __externref_t tableSrc[0];
+static __externref_t tableDst[0];
+// Copy nelem elements from [src, src + nelem - 1] in tableSrc to
+// [dst, dst + nelem - 1] in tableDst
+void copy(int dst, int src, int nelem) {
+ __builtin_wasm_table_copy(tableDst, tableSrc, dst, src, nelem);
+}
+```
-Builtin Functions
-=================
+## Builtin Functions
Clang supports a number of builtin library functions with the same syntax as
-GCC, including things like ``__builtin_nan``, ``__builtin_constant_p``,
-``__builtin_choose_expr``, ``__builtin_types_compatible_p``,
-``__builtin_assume_aligned``, ``__sync_fetch_and_add``, etc. In addition to
+GCC, including things like `__builtin_nan`, `__builtin_constant_p`,
+`__builtin_choose_expr`, `__builtin_types_compatible_p`,
+`__builtin_assume_aligned`, `__sync_fetch_and_add`, etc. In addition to
the GCC builtins, Clang supports a number of builtins that GCC does not, which
are listed here.
Please note that Clang does not and will not support all of the GCC builtins
-for vector operations. Instead of using builtins, you should use the functions
-defined in target-specific header files like ``<xmmintrin.h>``, which define
-portable wrappers for these. Many of the Clang versions of these functions are
-implemented directly in terms of :ref:`extended vector support
+for vector operations. Instead of using builtins, you should use the functions
+defined in target-specific header files like `<xmmintrin.h>`, which define
+portable wrappers for these. Many of the Clang versions of these functions are
+implemented directly in terms of {ref}`extended vector support
<langext-vectors>` instead of builtins, in order to reduce the number of
builtins that we need to implement.
-``__builtin_alloca``
---------------------
+### `__builtin_alloca`
-``__builtin_alloca`` is used to dynamically allocate memory on the stack. Memory
+`__builtin_alloca` is used to dynamically allocate memory on the stack. Memory
is automatically freed upon function termination.
**Syntax**:
-.. code-block:: c++
-
- __builtin_alloca(size_t n)
+```c++
+__builtin_alloca(size_t n)
+```
**Example of Use**:
-.. code-block:: c++
-
- void init(float* data, size_t nbelems);
- void process(float* data, size_t nbelems);
- int foo(size_t n) {
- auto mem = (float*)__builtin_alloca(n * sizeof(float));
- init(mem, n);
- process(mem, n);
- /* mem is automatically freed at this point */
- }
+```c++
+void init(float* data, size_t nbelems);
+void process(float* data, size_t nbelems);
+int foo(size_t n) {
+ auto mem = (float*)__builtin_alloca(n * sizeof(float));
+ init(mem, n);
+ process(mem, n);
+ /* mem is automatically freed at this point */
+}
+```
**Description**:
-``__builtin_alloca`` is meant to be used to allocate a dynamic amount of memory
+`__builtin_alloca` is meant to be used to allocate a dynamic amount of memory
on the stack. This amount is subject to stack allocation limits.
-Query for this feature with ``__has_builtin(__builtin_alloca)``.
+Query for this feature with `__has_builtin(__builtin_alloca)`.
-``__builtin_alloca_with_align``
--------------------------------
+### `__builtin_alloca_with_align`
-``__builtin_alloca_with_align`` is used to dynamically allocate memory on the
+`__builtin_alloca_with_align` is used to dynamically allocate memory on the
stack while controlling its alignment. Memory is automatically freed upon
function termination.
-
**Syntax**:
-.. code-block:: c++
-
- __builtin_alloca_with_align(size_t n, size_t align)
+```c++
+__builtin_alloca_with_align(size_t n, size_t align)
+```
**Example of Use**:
-.. code-block:: c++
-
- void init(float* data, size_t nbelems);
- void process(float* data, size_t nbelems);
- int foo(size_t n) {
- auto mem = (float*)__builtin_alloca_with_align(
- n * sizeof(float),
- CHAR_BIT * alignof(float));
- init(mem, n);
- process(mem, n);
- /* mem is automatically freed at this point */
- }
+```c++
+void init(float* data, size_t nbelems);
+void process(float* data, size_t nbelems);
+int foo(size_t n) {
+ auto mem = (float*)__builtin_alloca_with_align(
+ n * sizeof(float),
+ CHAR_BIT * alignof(float));
+ init(mem, n);
+ process(mem, n);
+ /* mem is automatically freed at this point */
+}
+```
**Description**:
-``__builtin_alloca_with_align`` is meant to be used to allocate a dynamic amount of memory
-on the stack. It is similar to ``__builtin_alloca`` but accepts a second
+`__builtin_alloca_with_align` is meant to be used to allocate a dynamic amount of memory
+on the stack. It is similar to `__builtin_alloca` but accepts a second
argument whose value is the alignment constraint, as a power of 2 in *bits*.
-Query for this feature with ``__has_builtin(__builtin_alloca_with_align)``.
+Query for this feature with `__has_builtin(__builtin_alloca_with_align)`.
-.. _langext-__builtin_assume:
+(langext-builtin-assume)=
-``__builtin_assume``
---------------------
+### `__builtin_assume`
-``__builtin_assume`` is used to provide the optimizer with a boolean
+`__builtin_assume` is used to provide the optimizer with a boolean
invariant that is defined to be true.
**Syntax**:
-.. code-block:: c++
-
- __builtin_assume(bool)
+```c++
+__builtin_assume(bool)
+```
**Example of Use**:
-.. code-block:: c++
-
- int foo(int x) {
- __builtin_assume(x != 0);
- // The optimizer may short-circuit this check using the invariant.
- if (x == 0)
- return do_something();
- return do_something_else();
- }
+```c++
+int foo(int x) {
+ __builtin_assume(x != 0);
+ // The optimizer may short-circuit this check using the invariant.
+ if (x == 0)
+ return do_something();
+ return do_something_else();
+}
+```
**Description**:
@@ -3412,33 +3144,32 @@ that information used to optimize the program. If the condition is violated
during execution, the behavior is undefined. The argument itself is never
evaluated, so any side effects of the expression will be discarded.
-Query for this feature with ``__has_builtin(__builtin_assume)``.
+Query for this feature with `__has_builtin(__builtin_assume)`.
-.. _langext-__builtin_assume_separate_storage:
+(langext-builtin-assume-separate-storage)=
-``__builtin_assume_separate_storage``
--------------------------------------
+### `__builtin_assume_separate_storage`
-``__builtin_assume_separate_storage`` is used to provide the optimizer with the
+`__builtin_assume_separate_storage` is used to provide the optimizer with the
knowledge that its two arguments point to separately allocated objects.
**Syntax**:
-.. code-block:: c++
-
- __builtin_assume_separate_storage(const volatile void *, const volatile void *)
+```c++
+__builtin_assume_separate_storage(const volatile void *, const volatile void *)
+```
**Example of Use**:
-.. code-block:: c++
-
- int foo(int *x, int *y) {
- __builtin_assume_separate_storage(x, y);
- *x = 0;
- *y = 1;
- // The optimizer may optimize this to return 0 without reloading from *x.
- return *x;
- }
+```c++
+int foo(int *x, int *y) {
+ __builtin_assume_separate_storage(x, y);
+ *x = 0;
+ *y = 1;
+ // The optimizer may optimize this to return 0 without reloading from *x.
+ return *x;
+}
+```
**Description**:
@@ -3451,1132 +3182,1089 @@ particular object (so for example, it's never correct to call this function
passing the addresses of fields in the same struct, elements of the same array,
etc.).
-Query for this feature with ``__has_builtin(__builtin_assume_separate_storage)``.
+Query for this feature with `__has_builtin(__builtin_assume_separate_storage)`.
-``__builtin_assume_dereferenceable``
--------------------------------------
+### `__builtin_assume_dereferenceable`
-``__builtin_assume_dereferenceable`` is used to provide the optimizer with the
+`__builtin_assume_dereferenceable` is used to provide the optimizer with the
knowledge that the pointer argument P is dereferenceable up to at least the
specified number of bytes.
**Syntax**:
-.. code-block:: c++
-
- __builtin_assume_dereferenceable(const void *, size_t)
+```c++
+__builtin_assume_dereferenceable(const void *, size_t)
+```
**Example of Use**:
-.. code-block:: c++
-
- int foo(int *x, int y) {
- __builtin_assume_dereferenceable(x, sizeof(int));
- int z = 0;
- if (y == 1) {
- // The optimizer may execute the load of x unconditionally due to
- // __builtin_assume_dereferenceable guaranteeing sizeof(int) bytes can
- // be loaded speculatively without trapping.
- z = *x;
- }
- return z;
- }
+```c++
+int foo(int *x, int y) {
+ __builtin_assume_dereferenceable(x, sizeof(int));
+ int z = 0;
+ if (y == 1) {
+ // The optimizer may execute the load of x unconditionally due to
+ // __builtin_assume_dereferenceable guaranteeing sizeof(int) bytes can
+ // be loaded speculatively without trapping.
+ z = *x;
+ }
+ return z;
+}
+```
**Description**:
-The arguments to this function provide a start pointer ``P`` and a size ``S``.
-``S`` must be at least 1 and a constant. The optimizer may assume that ``S``
-bytes are dereferenceable starting at ``P``. Note that this does not necessarily
-imply that ``P`` is non-null as ``nullptr`` can be dereferenced in some cases.
-The assumption also does not imply that ``P`` is not dereferenceable past ``S``
+The arguments to this function provide a start pointer `P` and a size `S`.
+`S` must be at least 1 and a constant. The optimizer may assume that `S`
+bytes are dereferenceable starting at `P`. Note that this does not necessarily
+imply that `P` is non-null as `nullptr` can be dereferenced in some cases.
+The assumption also does not imply that `P` is not dereferenceable past `S`
bytes.
+Query for this feature with `__has_builtin(__builtin_assume_dereferenceable)`.
-Query for this feature with ``__has_builtin(__builtin_assume_dereferenceable)``.
-
+### `__builtin_offsetof`
-``__builtin_offsetof``
-----------------------
-
-``__builtin_offsetof`` is used to implement the ``offsetof`` macro, which
+`__builtin_offsetof` is used to implement the `offsetof` macro, which
calculates the offset (in bytes) to a given member of the given type.
**Syntax**:
-.. code-block:: c++
-
- __builtin_offsetof(type-name, member-designator)
+```c++
+__builtin_offsetof(type-name, member-designator)
+```
**Example of Use**:
-.. code-block:: c++
-
- struct S {
- char c;
- int i;
- struct T {
- float f[2];
- } t;
- };
+```c++
+struct S {
+ char c;
+ int i;
+ struct T {
+ float f[2];
+ } t;
+};
- const int offset_to_i = __builtin_offsetof(struct S, i);
- const int ext1 = __builtin_offsetof(struct U { int i; }, i); // C extension
- const int offset_to_subobject = __builtin_offsetof(struct S, t.f[1]);
+const int offset_to_i = __builtin_offsetof(struct S, i);
+const int ext1 = __builtin_offsetof(struct U { int i; }, i); // C extension
+const int offset_to_subobject = __builtin_offsetof(struct S, t.f[1]);
+```
**Description**:
This builtin is usable in an integer constant expression which returns a value
-of type ``size_t``. The value returned is the offset in bytes to the subobject
+of type `size_t`. The value returned is the offset in bytes to the subobject
designated by the member-designator from the beginning of an object of type
-``type-name``. Clang extends the required standard functionality in the
+`type-name`. Clang extends the required standard functionality in the
following way:
-* In C language modes, the first argument may be the definition of a new type.
+- In C language modes, the first argument may be the definition of a new type.
Any type declared this way is scoped to the nearest scope containing the call
to the builtin.
-Query for this feature with ``__has_builtin(__builtin_offsetof)``.
+Query for this feature with `__has_builtin(__builtin_offsetof)`.
-``__builtin_get_vtable_pointer``
---------------------------------
+### `__builtin_get_vtable_pointer`
-``__builtin_get_vtable_pointer`` loads and authenticates the primary vtable
+`__builtin_get_vtable_pointer` loads and authenticates the primary vtable
pointer from an instance of a polymorphic C++ class. This builtin is needed
for directly loading the vtable pointer when on platforms using
-:doc:`PointerAuthentication`.
+{doc}`PointerAuthentication`.
**Syntax**:
-.. code-block:: c++
-
- __builtin_get_vtable_pointer(PolymorphicClass*)
+```c++
+__builtin_get_vtable_pointer(PolymorphicClass*)
+```
**Example of Use**:
-.. code-block:: c++
-
- struct PolymorphicClass {
- virtual ~PolymorphicClass();
- };
+```c++
+struct PolymorphicClass {
+ virtual ~PolymorphicClass();
+};
- PolymorphicClass anInstance;
- const void* vtablePointer = __builtin_get_vtable_pointer(&anInstance);
+PolymorphicClass anInstance;
+const void* vtablePointer = __builtin_get_vtable_pointer(&anInstance);
+```
**Description**:
-The ``__builtin_get_vtable_pointer`` builtin loads the primary vtable
+The `__builtin_get_vtable_pointer` builtin loads the primary vtable
pointer from a polymorphic C++ type. If the target platform authenticates
vtable pointers, this builtin will perform the authentication and produce
the underlying raw pointer. The object being queried must be polymorphic,
and so must also be a complete type.
-Query for this feature with ``__has_builtin(__builtin_get_vtable_pointer)``.
+Query for this feature with `__has_builtin(__builtin_get_vtable_pointer)`.
-``__builtin_call_with_static_chain``
-------------------------------------
+### `__builtin_call_with_static_chain`
-``__builtin_call_with_static_chain`` is used to perform a static call while
+`__builtin_call_with_static_chain` is used to perform a static call while
updating the static chain register.
**Syntax**:
-.. code-block:: c++
-
- T __builtin_call_with_static_chain(T expr, void* ptr)
+```c++
+T __builtin_call_with_static_chain(T expr, void* ptr)
+```
**Example of Use**:
-.. code-block:: c++
-
- auto v = __builtin_call_with_static_chain(foo(3), foo);
+```c++
+auto v = __builtin_call_with_static_chain(foo(3), foo);
+```
**Description**:
-This builtin returns ``expr`` after checking that ``expr`` is a non-member
-static call expression. The call to that expression is made while using ``ptr``
+This builtin returns `expr` after checking that `expr` is a non-member
+static call expression. The call to that expression is made while using `ptr`
as a function pointer stored in a dedicated register to implement *static chain*
calling convention, as used by some language to implement closures or nested
functions.
-Query for this feature with ``__has_builtin(__builtin_call_with_static_chain)``.
+Query for this feature with `__has_builtin(__builtin_call_with_static_chain)`.
-``__builtin_readcyclecounter``
-------------------------------
+### `__builtin_readcyclecounter`
-``__builtin_readcyclecounter`` is used to access the cycle counter register (or
+`__builtin_readcyclecounter` is used to access the cycle counter register (or
a similar low-latency, high-accuracy clock) on those targets that support it.
**Syntax**:
-.. code-block:: c++
-
- __builtin_readcyclecounter()
+```c++
+__builtin_readcyclecounter()
+```
**Example of Use**:
-.. code-block:: c++
-
- unsigned long long t0 = __builtin_readcyclecounter();
- do_something();
- unsigned long long t1 = __builtin_readcyclecounter();
- unsigned long long cycles_to_do_something = t1 - t0; // assuming no overflow
+```c++
+unsigned long long t0 = __builtin_readcyclecounter();
+do_something();
+unsigned long long t1 = __builtin_readcyclecounter();
+unsigned long long cycles_to_do_something = t1 - t0; // assuming no overflow
+```
**Description**:
-The ``__builtin_readcyclecounter()`` builtin returns the cycle counter value,
+The `__builtin_readcyclecounter()` builtin returns the cycle counter value,
which may be either global or process/thread-specific depending on the target.
As the backing counters often overflow quickly (on the order of seconds) this
-should only be used for timing small intervals. When not supported by the
-target, the return value is always zero. This builtin takes no arguments and
+should only be used for timing small intervals. When not supported by the
+target, the return value is always zero. This builtin takes no arguments and
produces an unsigned long long result.
-Query for this feature with ``__has_builtin(__builtin_readcyclecounter)``. Note
+Query for this feature with `__has_builtin(__builtin_readcyclecounter)`. Note
that even if present, its use may depend on run-time privilege or other OS
controlled state.
-``__builtin_readsteadycounter``
--------------------------------
+### `__builtin_readsteadycounter`
-``__builtin_readsteadycounter`` is used to access the fixed frequency counter
+`__builtin_readsteadycounter` is used to access the fixed frequency counter
register (or a similar steady-rate clock) on those targets that support it.
-The function is similar to ``__builtin_readcyclecounter`` above except that the
+The function is similar to `__builtin_readcyclecounter` above except that the
frequency is fixed, making it suitable for measuring elapsed time.
**Syntax**:
-.. code-block:: c++
-
- __builtin_readsteadycounter()
+```c++
+__builtin_readsteadycounter()
+```
**Example of Use**:
-.. code-block:: c++
-
- unsigned long long t0 = __builtin_readsteadycounter();
- do_something();
- unsigned long long t1 = __builtin_readsteadycounter();
- unsigned long long secs_to_do_something = (t1 - t0) / tick_rate;
+```c++
+unsigned long long t0 = __builtin_readsteadycounter();
+do_something();
+unsigned long long t1 = __builtin_readsteadycounter();
+unsigned long long secs_to_do_something = (t1 - t0) / tick_rate;
+```
**Description**:
-The ``__builtin_readsteadycounter()`` builtin returns the frequency counter value.
+The `__builtin_readsteadycounter()` builtin returns the frequency counter value.
When not supported by the target, the return value is always zero. This builtin
takes no arguments and produces an unsigned long long result. The builtin does
not guarantee any particular frequency, only that it is stable. Knowledge of the
counter's true frequency will need to be provided by the user.
-Query for this feature with ``__has_builtin(__builtin_readsteadycounter)``.
+Query for this feature with `__has_builtin(__builtin_readsteadycounter)`.
-``__builtin_cpu_supports``
---------------------------
+### `__builtin_cpu_supports`
**Syntax**:
-.. code-block:: c++
-
- int __builtin_cpu_supports(const char *features);
+```c++
+int __builtin_cpu_supports(const char *features);
+```
**Example of Use:**:
-.. code-block:: c++
-
- if (__builtin_cpu_supports("sve"))
- sve_code();
+```c++
+if (__builtin_cpu_supports("sve"))
+ sve_code();
+```
**Description**:
-The ``__builtin_cpu_supports`` function detects if the run-time CPU supports
+The `__builtin_cpu_supports` function detects if the run-time CPU supports
features specified in string argument. It returns a positive integer if all
features are supported and 0 otherwise. Feature names are target specific. On
-AArch64, features are combined using ``+`` like this
-``__builtin_cpu_supports("flagm+sha3+lse+rcpc2+fcma+memtag+bti+sme2")``.
+AArch64, features are combined using `+` like this
+`__builtin_cpu_supports("flagm+sha3+lse+rcpc2+fcma+memtag+bti+sme2")`.
If a feature name is not supported, Clang will issue a warning and replace
builtin by the constant 0.
-Query for this feature with ``__has_builtin(__builtin_cpu_supports)``.
+Query for this feature with `__has_builtin(__builtin_cpu_supports)`.
-``__builtin_dump_struct``
--------------------------
+### `__builtin_dump_struct`
**Syntax**:
-.. code-block:: c++
-
- __builtin_dump_struct(&some_struct, some_printf_func, args...);
+```c++
+__builtin_dump_struct(&some_struct, some_printf_func, args...);
+```
**Examples**:
-.. code-block:: c++
-
- struct S {
- int x, y;
- float f;
- struct T {
- int i;
- } t;
- };
+```c++
+struct S {
+ int x, y;
+ float f;
+ struct T {
+ int i;
+ } t;
+};
- void func(struct S *s) {
- __builtin_dump_struct(s, printf);
- }
+void func(struct S *s) {
+ __builtin_dump_struct(s, printf);
+}
+```
Example output:
-.. code-block:: none
-
- struct S {
- int x = 100
- int y = 42
- float f = 3.141593
- struct T t = {
- int i = 1997
- }
- }
-
-.. code-block:: c++
-
- #include <string>
- struct T { int a, b; };
- constexpr void constexpr_sprintf(std::string &out, const char *format,
- auto ...args) {
- // ...
- }
- constexpr std::string dump_struct(auto &x) {
- std::string s;
- __builtin_dump_struct(&x, constexpr_sprintf, s);
- return s;
- }
- static_assert(dump_struct(T{1, 2}) == R"(struct T {
- int a = 1
- int b = 2
- }
- )");
+```none
+struct S {
+ int x = 100
+ int y = 42
+ float f = 3.141593
+ struct T t = {
+ int i = 1997
+ }
+}
+```
+
+```c++
+#include <string>
+struct T { int a, b; };
+constexpr void constexpr_sprintf(std::string &out, const char *format,
+ auto ...args) {
+ // ...
+}
+constexpr std::string dump_struct(auto &x) {
+ std::string s;
+ __builtin_dump_struct(&x, constexpr_sprintf, s);
+ return s;
+}
+static_assert(dump_struct(T{1, 2}) == R"(struct T {
+ int a = 1
+ int b = 2
+}
+)");
+```
**Description**:
-The ``__builtin_dump_struct`` function is used to print the fields of a simple
+The `__builtin_dump_struct` function is used to print the fields of a simple
structure and their values for debugging purposes. The first argument of the
-builtin should be a pointer to a complete record type to dump. The second argument ``f``
+builtin should be a pointer to a complete record type to dump. The second argument `f`
should be some callable expression, and can be a function object or an overload
-set. The builtin calls ``f``, passing any further arguments ``args...``
-followed by a ``printf``-compatible format string and the corresponding
-arguments. ``f`` may be called more than once, and ``f`` and ``args`` will be
-evaluated once per call. In C++, ``f`` may be a template or overload set and
+set. The builtin calls `f`, passing any further arguments `args...`
+followed by a `printf`-compatible format string and the corresponding
+arguments. `f` may be called more than once, and `f` and `args` will be
+evaluated once per call. In C++, `f` may be a template or overload set and
resolve to different functions for each call.
In the format string, a suitable format specifier will be used for builtin
types that Clang knows how to format. This includes standard builtin types, as
-well as aggregate structures, ``void*`` (printed with ``%p``), and ``const
-char*`` (printed with ``%s``). A ``*%p`` specifier will be used for a field
+well as aggregate structures, `void*` (printed with `%p`), and `const
+char*` (printed with `%s`). A `*%p` specifier will be used for a field
that Clang doesn't know how to format, and the corresponding argument will be a
pointer to the field. This allows a C++ templated formatting function to detect
-this case and implement custom formatting. A ``*`` will otherwise not precede a
+this case and implement custom formatting. A `*` will otherwise not precede a
format specifier.
This builtin does not return a value.
This builtin can be used in constant expressions.
-Query for this feature with ``__has_builtin(__builtin_dump_struct)``
+Query for this feature with `__has_builtin(__builtin_dump_struct)`
-.. _langext-__builtin_shufflevector:
+(langext-builtin-shufflevector)=
-``__builtin_shufflevector``
----------------------------
+### `__builtin_shufflevector`
-``__builtin_shufflevector`` is used to express generic vector
-permutation/shuffle/swizzle operations. This builtin is also very important
+`__builtin_shufflevector` is used to express generic vector
+permutation/shuffle/swizzle operations. This builtin is also very important
for the implementation of various target-specific header files like
-``<xmmintrin.h>``. This builtin can be used within constant expressions.
+`<xmmintrin.h>`. This builtin can be used within constant expressions.
**Syntax**:
-.. code-block:: c++
-
- __builtin_shufflevector(vec1, vec2, index1, index2, ...)
+```c++
+__builtin_shufflevector(vec1, vec2, index1, index2, ...)
+```
**Examples**:
-.. code-block:: c++
-
- // identity operation - return 4-element vector v1.
- __builtin_shufflevector(v1, v1, 0, 1, 2, 3)
+```c++
+// identity operation - return 4-element vector v1.
+__builtin_shufflevector(v1, v1, 0, 1, 2, 3)
- // "Splat" element 0 of V1 into a 4-element result.
- __builtin_shufflevector(V1, V1, 0, 0, 0, 0)
+// "Splat" element 0 of V1 into a 4-element result.
+__builtin_shufflevector(V1, V1, 0, 0, 0, 0)
- // Reverse 4-element vector V1.
- __builtin_shufflevector(V1, V1, 3, 2, 1, 0)
+// Reverse 4-element vector V1.
+__builtin_shufflevector(V1, V1, 3, 2, 1, 0)
- // Concatenate every other element of 4-element vectors V1 and V2.
- __builtin_shufflevector(V1, V2, 0, 2, 4, 6)
+// Concatenate every other element of 4-element vectors V1 and V2.
+__builtin_shufflevector(V1, V2, 0, 2, 4, 6)
- // Concatenate every other element of 8-element vectors V1 and V2.
- __builtin_shufflevector(V1, V2, 0, 2, 4, 6, 8, 10, 12, 14)
+// Concatenate every other element of 8-element vectors V1 and V2.
+__builtin_shufflevector(V1, V2, 0, 2, 4, 6, 8, 10, 12, 14)
- // Shuffle v1 with some elements being undefined. Not allowed in constexpr.
- __builtin_shufflevector(v1, v1, 3, -1, 1, -1)
+// Shuffle v1 with some elements being undefined. Not allowed in constexpr.
+__builtin_shufflevector(v1, v1, 3, -1, 1, -1)
+```
**Description**:
-The first two arguments to ``__builtin_shufflevector`` are vectors that have
-the same element type. The remaining arguments are a list of integers that
+The first two arguments to `__builtin_shufflevector` are vectors that have
+the same element type. The remaining arguments are a list of integers that
specify the elements indices of the first two vectors that should be extracted
-and returned in a new vector. These element indices are numbered sequentially
-starting with the first vector, continuing into the second vector. Thus, if
-``vec1`` is a 4-element vector, index 5 would refer to the second element of
-``vec2``. An index of -1 can be used to indicate that the corresponding element
+and returned in a new vector. These element indices are numbered sequentially
+starting with the first vector, continuing into the second vector. Thus, if
+`vec1` is a 4-element vector, index 5 would refer to the second element of
+`vec2`. An index of -1 can be used to indicate that the corresponding element
in the returned vector is a don't care and can be optimized by the backend.
Values of -1 are not supported in constant expressions.
-The result of ``__builtin_shufflevector`` is a vector with the same element
-type as ``vec1``/``vec2`` but that has an element count equal to the number of
+The result of `__builtin_shufflevector` is a vector with the same element
+type as `vec1`/`vec2` but that has an element count equal to the number of
indices specified.
-Query for this feature with ``__has_builtin(__builtin_shufflevector)``.
+Query for this feature with `__has_builtin(__builtin_shufflevector)`.
-.. _langext-__builtin_convertvector:
+(langext-builtin-convertvector)=
-``__builtin_convertvector``
----------------------------
+### `__builtin_convertvector`
-``__builtin_convertvector`` is used to express generic vector
+`__builtin_convertvector` is used to express generic vector
type-conversion operations. The input vector and the output vector
type must have the same number of elements. This builtin can be used within
constant expressions.
**Syntax**:
-.. code-block:: c++
-
- __builtin_convertvector(src_vec, dst_vec_type)
+```c++
+__builtin_convertvector(src_vec, dst_vec_type)
+```
**Examples**:
-.. code-block:: c++
-
- typedef double vector4double __attribute__((__vector_size__(32)));
- typedef float vector4float __attribute__((__vector_size__(16)));
- typedef short vector4short __attribute__((__vector_size__(8)));
- vector4float vf; vector4short vs;
+```c++
+typedef double vector4double __attribute__((__vector_size__(32)));
+typedef float vector4float __attribute__((__vector_size__(16)));
+typedef short vector4short __attribute__((__vector_size__(8)));
+vector4float vf; vector4short vs;
- // convert from a vector of 4 floats to a vector of 4 doubles.
- __builtin_convertvector(vf, vector4double)
- // equivalent to:
- (vector4double) { (double) vf[0], (double) vf[1], (double) vf[2], (double) vf[3] }
+// convert from a vector of 4 floats to a vector of 4 doubles.
+__builtin_convertvector(vf, vector4double)
+// equivalent to:
+(vector4double) { (double) vf[0], (double) vf[1], (double) vf[2], (double) vf[3] }
- // convert from a vector of 4 shorts to a vector of 4 floats.
- __builtin_convertvector(vs, vector4float)
- // equivalent to:
- (vector4float) { (float) vs[0], (float) vs[1], (float) vs[2], (float) vs[3] }
+// convert from a vector of 4 shorts to a vector of 4 floats.
+__builtin_convertvector(vs, vector4float)
+// equivalent to:
+(vector4float) { (float) vs[0], (float) vs[1], (float) vs[2], (float) vs[3] }
+```
**Description**:
-The first argument to ``__builtin_convertvector`` is a vector, and the second
+The first argument to `__builtin_convertvector` is a vector, and the second
argument is a vector type with the same number of elements as the first
argument.
-The result of ``__builtin_convertvector`` is a vector with the same element
+The result of `__builtin_convertvector` is a vector with the same element
type as the second argument, with a value defined in terms of the action of a
C-style cast applied to each element of the first argument.
-Query for this feature with ``__has_builtin(__builtin_convertvector)``.
+Query for this feature with `__has_builtin(__builtin_convertvector)`.
-``__builtin_bitreverse``
-------------------------
+### `__builtin_bitreverse`
-* ``__builtin_bitreverse8``
-* ``__builtin_bitreverse16``
-* ``__builtin_bitreverse32``
-* ``__builtin_bitreverse64``
+- `__builtin_bitreverse8`
+- `__builtin_bitreverse16`
+- `__builtin_bitreverse32`
+- `__builtin_bitreverse64`
**Syntax**:
-.. code-block:: c++
-
- __builtin_bitreverse32(x)
+```c++
+__builtin_bitreverse32(x)
+```
**Examples**:
-.. code-block:: c++
-
- uint8_t rev_x = __builtin_bitreverse8(x);
- uint16_t rev_x = __builtin_bitreverse16(x);
- uint32_t rev_y = __builtin_bitreverse32(y);
- uint64_t rev_z = __builtin_bitreverse64(z);
+```c++
+uint8_t rev_x = __builtin_bitreverse8(x);
+uint16_t rev_x = __builtin_bitreverse16(x);
+uint32_t rev_y = __builtin_bitreverse32(y);
+uint64_t rev_z = __builtin_bitreverse64(z);
+```
**Description**:
-The '``__builtin_bitreverse``' family of builtins is used to reverse
-the bitpattern of an integer value; for example, ``0b10110110`` becomes
-``0b01101101``. These builtins can be used within constant expressions.
+The '`__builtin_bitreverse`' family of builtins is used to reverse
+the bitpattern of an integer value; for example, `0b10110110` becomes
+`0b01101101`. These builtins can be used within constant expressions.
-``__builtin_rotateleft``
-------------------------
+### `__builtin_rotateleft`
-* ``__builtin_rotateleft8``
-* ``__builtin_rotateleft16``
-* ``__builtin_rotateleft32``
-* ``__builtin_rotateleft64``
+- `__builtin_rotateleft8`
+- `__builtin_rotateleft16`
+- `__builtin_rotateleft32`
+- `__builtin_rotateleft64`
**Syntax**:
-.. code-block:: c++
-
- __builtin_rotateleft32(x, y)
+```c++
+__builtin_rotateleft32(x, y)
+```
**Examples**:
-.. code-block:: c++
-
- uint8_t rot_x = __builtin_rotateleft8(x, y);
- uint16_t rot_x = __builtin_rotateleft16(x, y);
- uint32_t rot_x = __builtin_rotateleft32(x, y);
- uint64_t rot_x = __builtin_rotateleft64(x, y);
+```c++
+uint8_t rot_x = __builtin_rotateleft8(x, y);
+uint16_t rot_x = __builtin_rotateleft16(x, y);
+uint32_t rot_x = __builtin_rotateleft32(x, y);
+uint64_t rot_x = __builtin_rotateleft64(x, y);
+```
**Description**:
-The '``__builtin_rotateleft``' family of builtins is used to rotate
+The '`__builtin_rotateleft`' family of builtins is used to rotate
the bits in the first argument by the amount in the second argument.
-For example, ``0b10000110`` rotated left by 11 becomes ``0b00110100``.
+For example, `0b10000110` rotated left by 11 becomes `0b00110100`.
The shift value is treated as an unsigned amount modulo the size of
the arguments. Both arguments and the result have the bitwidth specified
by the name of the builtin. These builtins can be used within constant
expressions.
-``__builtin_rotateright``
--------------------------
+### `__builtin_rotateright`
-* ``__builtin_rotateright8``
-* ``__builtin_rotateright16``
-* ``__builtin_rotateright32``
-* ``__builtin_rotateright64``
+- `__builtin_rotateright8`
+- `__builtin_rotateright16`
+- `__builtin_rotateright32`
+- `__builtin_rotateright64`
**Syntax**:
-.. code-block:: c++
-
- __builtin_rotateright32(x, y)
+```c++
+__builtin_rotateright32(x, y)
+```
**Examples**:
-.. code-block:: c++
-
- uint8_t rot_x = __builtin_rotateright8(x, y);
- uint16_t rot_x = __builtin_rotateright16(x, y);
- uint32_t rot_x = __builtin_rotateright32(x, y);
- uint64_t rot_x = __builtin_rotateright64(x, y);
+```c++
+uint8_t rot_x = __builtin_rotateright8(x, y);
+uint16_t rot_x = __builtin_rotateright16(x, y);
+uint32_t rot_x = __builtin_rotateright32(x, y);
+uint64_t rot_x = __builtin_rotateright64(x, y);
+```
**Description**:
-The '``__builtin_rotateright``' family of builtins is used to rotate
+The '`__builtin_rotateright`' family of builtins is used to rotate
the bits in the first argument by the amount in the second argument.
-For example, ``0b10000110`` rotated right by 3 becomes ``0b11010000``.
+For example, `0b10000110` rotated right by 3 becomes `0b11010000`.
The shift value is treated as an unsigned amount modulo the size of
the arguments. Both arguments and the result have the bitwidth specified
by the name of the builtin. These builtins can be used within constant
expressions.
-``__builtin_stdc_rotate_left`` and ``__builtin_stdc_rotate_right``
-------------------------------------------------------------------
+### `__builtin_stdc_rotate_left` and `__builtin_stdc_rotate_right`
**Syntax**:
-.. code-block:: c
-
- T __builtin_stdc_rotate_left(T value, count)
- T __builtin_stdc_rotate_right(T value, count)
+```c
+T __builtin_stdc_rotate_left(T value, count)
+T __builtin_stdc_rotate_right(T value, count)
+```
-where ``T`` is any unsigned integer type and ``count`` is any integer type.
+where `T` is any unsigned integer type and `count` is any integer type.
**Description**:
-These builtins rotate the bits in ``value`` by ``count`` positions. The
-``__builtin_stdc_rotate_left`` builtin rotates bits to the left, while
-``__builtin_stdc_rotate_right`` rotates bits to the right. The first
-argument (``value``) must be an unsigned integer type, including ``_BitInt`` types.
-The second argument (``count``) can be any integer type. The rotation count is
+These builtins rotate the bits in `value` by `count` positions. The
+`__builtin_stdc_rotate_left` builtin rotates bits to the left, while
+`__builtin_stdc_rotate_right` rotates bits to the right. The first
+argument (`value`) must be an unsigned integer type, including `_BitInt` types.
+The second argument (`count`) can be any integer type. The rotation count is
normalized modulo the bit-width of the value being rotated, with negative
counts converted to equivalent positive rotations (e.g., rotating left
-by ``-1`` is equivalent to rotating left by ``BitWidth-1``). These builtins can
+by `-1` is equivalent to rotating left by `BitWidth-1`). These builtins can
be used within constant expressions.
**Example of use**:
-.. code-block:: c
+```c
+unsigned char rotated_left = __builtin_stdc_rotate_left((unsigned char)0xB1, 3);
+unsigned int rotated_right = __builtin_stdc_rotate_right(0x12345678U, 8);
- unsigned char rotated_left = __builtin_stdc_rotate_left((unsigned char)0xB1, 3);
- unsigned int rotated_right = __builtin_stdc_rotate_right(0x12345678U, 8);
+unsigned char neg_rotate = __builtin_stdc_rotate_left((unsigned char)0xB1, -1);
- unsigned char neg_rotate = __builtin_stdc_rotate_left((unsigned char)0xB1, -1);
+unsigned _BitInt(20) value = 0xABCDE;
+unsigned _BitInt(20) rotated = __builtin_stdc_rotate_left(value, 5);
+```
- unsigned _BitInt(20) value = 0xABCDE;
- unsigned _BitInt(20) rotated = __builtin_stdc_rotate_left(value, 5);
-
-``__builtin_stdc_*`` bit utilities
-----------------------------------
+### `__builtin_stdc_*` bit utilities
**Syntax**:
-.. code-block:: c
-
- unsigned int __builtin_stdc_leading_zeros(T value);
- unsigned int __builtin_stdc_leading_ones(T value);
- unsigned int __builtin_stdc_trailing_zeros(T value);
- unsigned int __builtin_stdc_trailing_ones(T value);
- unsigned int __builtin_stdc_first_leading_zero(T value);
- unsigned int __builtin_stdc_first_leading_one(T value);
- unsigned int __builtin_stdc_first_trailing_zero(T value);
- unsigned int __builtin_stdc_first_trailing_one(T value);
- unsigned int __builtin_stdc_count_zeros(T value);
- unsigned int __builtin_stdc_count_ones(T value);
- bool __builtin_stdc_has_single_bit(T value);
- unsigned int __builtin_stdc_bit_width(T value);
- T __builtin_stdc_bit_floor(T value);
- T __builtin_stdc_bit_ceil(T value);
-
-where ``T`` is any unsigned integer type except ``bool`` and enumeration types,
-including ``_BitInt`` types.
+```c
+unsigned int __builtin_stdc_leading_zeros(T value);
+unsigned int __builtin_stdc_leading_ones(T value);
+unsigned int __builtin_stdc_trailing_zeros(T value);
+unsigned int __builtin_stdc_trailing_ones(T value);
+unsigned int __builtin_stdc_first_leading_zero(T value);
+unsigned int __builtin_stdc_first_leading_one(T value);
+unsigned int __builtin_stdc_first_trailing_zero(T value);
+unsigned int __builtin_stdc_first_trailing_one(T value);
+unsigned int __builtin_stdc_count_zeros(T value);
+unsigned int __builtin_stdc_count_ones(T value);
+bool __builtin_stdc_has_single_bit(T value);
+unsigned int __builtin_stdc_bit_width(T value);
+T __builtin_stdc_bit_floor(T value);
+T __builtin_stdc_bit_ceil(T value);
+```
+
+where `T` is any unsigned integer type except `bool` and enumeration types,
+including `_BitInt` types.
**Description**:
-These builtins implement the C23 ``<stdbit.h>`` operations. Following the C23
-standard, ``unsigned int`` is used as the ``generic_return_type`` for count and
-position queries (``leading_zeros``, ``leading_ones``, ``trailing_zeros``,
-``trailing_ones``, ``first_leading_zero``, ``first_leading_one``,
-``first_trailing_zero``, ``first_trailing_one``, ``count_zeros``,
-``count_ones``, ``bit_width``); ``has_single_bit`` returns ``bool``; and
-``bit_floor``/``bit_ceil`` return the same type as the operand. Zero and
+These builtins implement the C23 `<stdbit.h>` operations. Following the C23
+standard, `unsigned int` is used as the `generic_return_type` for count and
+position queries (`leading_zeros`, `leading_ones`, `trailing_zeros`,
+`trailing_ones`, `first_leading_zero`, `first_leading_one`,
+`first_trailing_zero`, `first_trailing_one`, `count_zeros`,
+`count_ones`, `bit_width`); `has_single_bit` returns `bool`; and
+`bit_floor`/`bit_ceil` return the same type as the operand. Zero and
all-ones cases follow the C23 definitions. All are usable in constant
expressions.
-``bool`` and enumeration types are rejected as arguments because C23 does not
+`bool` and enumeration types are rejected as arguments because C23 does not
permit them for these functions.
-As a Clang extension, ``_BitInt`` types of arbitrary widths are supported. C23
+As a Clang extension, `_BitInt` types of arbitrary widths are supported. C23
only requires support for bit-precise integers whose width matches a standard
or extended integer type.
**Examples**:
-.. code-block:: c
-
- unsigned _BitInt(9) x = 0x11;
- unsigned int lz = __builtin_stdc_leading_zeros(x);
- unsigned int tz = __builtin_stdc_trailing_zeros(x);
- unsigned int fto = __builtin_stdc_first_trailing_one(x);
- unsigned int cz = __builtin_stdc_count_zeros(x);
- bool has_one = __builtin_stdc_has_single_bit(x);
- unsigned _BitInt(9) ceilv = __builtin_stdc_bit_ceil((unsigned _BitInt(9))5);
- unsigned _BitInt(9) floorv = __builtin_stdc_bit_floor((unsigned _BitInt(9))5);
+```c
+unsigned _BitInt(9) x = 0x11;
+unsigned int lz = __builtin_stdc_leading_zeros(x);
+unsigned int tz = __builtin_stdc_trailing_zeros(x);
+unsigned int fto = __builtin_stdc_first_trailing_one(x);
+unsigned int cz = __builtin_stdc_count_zeros(x);
+bool has_one = __builtin_stdc_has_single_bit(x);
+unsigned _BitInt(9) ceilv = __builtin_stdc_bit_ceil((unsigned _BitInt(9))5);
+unsigned _BitInt(9) floorv = __builtin_stdc_bit_floor((unsigned _BitInt(9))5);
+```
-``__builtin_unreachable``
--------------------------
+### `__builtin_unreachable`
-``__builtin_unreachable`` is used to indicate that a specific point in the
+`__builtin_unreachable` is used to indicate that a specific point in the
program cannot be reached, even if the compiler might otherwise think it can.
-This is useful to improve optimization and eliminates certain warnings. For
-example, without the ``__builtin_unreachable`` in the example below, the
+This is useful to improve optimization and eliminates certain warnings. For
+example, without the `__builtin_unreachable` in the example below, the
compiler assumes that the inline asm can fall through and prints a "function
-declared '``noreturn``' should not return" warning.
+declared '`noreturn`' should not return" warning.
**Syntax**:
-.. code-block:: c++
-
- __builtin_unreachable()
+```c++
+__builtin_unreachable()
+```
**Example of use**:
-.. code-block:: c++
-
- void myabort(void) __attribute__((noreturn));
- void myabort(void) {
- asm("int3");
- __builtin_unreachable();
- }
+```c++
+void myabort(void) __attribute__((noreturn));
+void myabort(void) {
+ asm("int3");
+ __builtin_unreachable();
+}
+```
**Description**:
-The ``__builtin_unreachable()`` builtin has completely undefined behavior.
+The `__builtin_unreachable()` builtin has completely undefined behavior.
Since it has undefined behavior, it is a statement that it is never reached and
-the optimizer can take advantage of this to produce better code. This builtin
+the optimizer can take advantage of this to produce better code. This builtin
takes no arguments and produces a void result.
-Query for this feature with ``__has_builtin(__builtin_unreachable)``.
+Query for this feature with `__has_builtin(__builtin_unreachable)`.
-``__builtin_unpredictable``
----------------------------
+### `__builtin_unpredictable`
-``__builtin_unpredictable`` is used to indicate that a branch condition is
+`__builtin_unpredictable` is used to indicate that a branch condition is
unpredictable by hardware mechanisms such as branch prediction logic.
**Syntax**:
-.. code-block:: c++
-
- __builtin_unpredictable(long long)
+```c++
+__builtin_unpredictable(long long)
+```
**Example of use**:
-.. code-block:: c++
-
- if (__builtin_unpredictable(x > 0)) {
- foo();
- }
+```c++
+if (__builtin_unpredictable(x > 0)) {
+ foo();
+}
+```
**Description**:
-The ``__builtin_unpredictable()`` builtin is expected to be used with control
-flow conditions such as in ``if`` and ``switch`` statements.
+The `__builtin_unpredictable()` builtin is expected to be used with control
+flow conditions such as in `if` and `switch` statements.
-Query for this feature with ``__has_builtin(__builtin_unpredictable)``.
+Query for this feature with `__has_builtin(__builtin_unpredictable)`.
+### `__builtin_expect`
-``__builtin_expect``
---------------------
-
-``__builtin_expect`` is used to indicate that the value of an expression is
+`__builtin_expect` is used to indicate that the value of an expression is
anticipated to be the same as a statically known result.
**Syntax**:
-.. code-block:: c++
-
- long __builtin_expect(long expr, long val)
+```c++
+long __builtin_expect(long expr, long val)
+```
**Example of use**:
-.. code-block:: c++
-
- if (__builtin_expect(x, 0)) {
- bar();
- }
+```c++
+if (__builtin_expect(x, 0)) {
+ bar();
+}
+```
**Description**:
-The ``__builtin_expect()`` builtin is typically used with control flow
-conditions such as in ``if`` and ``switch`` statements to help branch
-prediction. It means that its first argument ``expr`` is expected to take the
-value of its second argument ``val``. It always returns ``expr``.
+The `__builtin_expect()` builtin is typically used with control flow
+conditions such as in `if` and `switch` statements to help branch
+prediction. It means that its first argument `expr` is expected to take the
+value of its second argument `val`. It always returns `expr`.
-Query for this feature with ``__has_builtin(__builtin_expect)``.
+Query for this feature with `__has_builtin(__builtin_expect)`.
-``__builtin_expect_with_probability``
--------------------------------------
+### `__builtin_expect_with_probability`
-``__builtin_expect_with_probability`` is similar to ``__builtin_expect`` but it
+`__builtin_expect_with_probability` is similar to `__builtin_expect` but it
takes a probability as third argument.
**Syntax**:
-.. code-block:: c++
-
- long __builtin_expect_with_probability(long expr, long val, double p)
+```c++
+long __builtin_expect_with_probability(long expr, long val, double p)
+```
**Example of use**:
-.. code-block:: c++
-
- if (__builtin_expect_with_probability(x, 0, .3)) {
- bar();
- }
+```c++
+if (__builtin_expect_with_probability(x, 0, .3)) {
+ bar();
+}
+```
**Description**:
-The ``__builtin_expect_with_probability()`` builtin is typically used with
-control flow conditions such as in ``if`` and ``switch`` statements to help
-branch prediction. It means that its first argument ``expr`` is expected to take
-the value of its second argument ``val`` with probability ``p``. ``p`` must be
-within ``[0.0 ; 1.0]`` bounds. This builtin always returns the value of ``expr``.
+The `__builtin_expect_with_probability()` builtin is typically used with
+control flow conditions such as in `if` and `switch` statements to help
+branch prediction. It means that its first argument `expr` is expected to take
+the value of its second argument `val` with probability `p`. `p` must be
+within `[0.0 ; 1.0]` bounds. This builtin always returns the value of `expr`.
-Query for this feature with ``__has_builtin(__builtin_expect_with_probability)``.
+Query for this feature with `__has_builtin(__builtin_expect_with_probability)`.
-``__builtin_prefetch``
-----------------------
+### `__builtin_prefetch`
-``__builtin_prefetch`` is used to communicate with the cache handler to bring
+`__builtin_prefetch` is used to communicate with the cache handler to bring
data into the cache before it gets used.
**Syntax**:
-.. code-block:: c++
-
- void __builtin_prefetch(const void *addr, int rw=0, int locality=3)
+```c++
+void __builtin_prefetch(const void *addr, int rw=0, int locality=3)
+```
**Example of use**:
-.. code-block:: c++
-
- __builtin_prefetch(a + i);
+```c++
+__builtin_prefetch(a + i);
+```
**Description**:
-The ``__builtin_prefetch(addr, rw, locality)`` builtin is expected to be used to
+The `__builtin_prefetch(addr, rw, locality)` builtin is expected to be used to
avoid cache misses when the developer has a good understanding of which data
-are going to be used next. ``addr`` is the address that needs to be brought into
-the cache. ``rw`` indicates the expected access mode: ``0`` for *read* and ``1``
-for *write*. In case of *read write* access, ``1`` is to be used. ``locality``
-indicates the expected persistence of data in cache, from ``0`` which means that
-data can be discarded from cache after its next use to ``3`` which means that
-data is going to be reused a lot once in cache. ``1`` and ``2`` provide
+are going to be used next. `addr` is the address that needs to be brought into
+the cache. `rw` indicates the expected access mode: `0` for *read* and `1`
+for *write*. In case of *read write* access, `1` is to be used. `locality`
+indicates the expected persistence of data in cache, from `0` which means that
+data can be discarded from cache after its next use to `3` which means that
+data is going to be reused a lot once in cache. `1` and `2` provide
intermediate behavior between these two extremes.
-Query for this feature with ``__has_builtin(__builtin_prefetch)``.
+Query for this feature with `__has_builtin(__builtin_prefetch)`.
-``__sync_swap``
----------------
+### `__sync_swap`
-``__sync_swap`` is used to atomically swap integers or pointers in memory.
+`__sync_swap` is used to atomically swap integers or pointers in memory.
**Syntax**:
-.. code-block:: c++
-
- type __sync_swap(type *ptr, type value, ...)
+```c++
+type __sync_swap(type *ptr, type value, ...)
+```
**Example of Use**:
-.. code-block:: c++
-
- int old_value = __sync_swap(&value, new_value);
+```c++
+int old_value = __sync_swap(&value, new_value);
+```
**Description**:
-The ``__sync_swap()`` builtin extends the existing ``__sync_*()`` family of
+The `__sync_swap()` builtin extends the existing `__sync_*()` family of
atomic intrinsics to allow code to atomically swap the current value with the
-new value. More importantly, it helps developers write more efficient and
+new value. More importantly, it helps developers write more efficient and
correct code by avoiding expensive loops around
-``__sync_bool_compare_and_swap()`` or relying on the platform specific
-implementation details of ``__sync_lock_test_and_set()``. The
-``__sync_swap()`` builtin is a full barrier.
+`__sync_bool_compare_and_swap()` or relying on the platform specific
+implementation details of `__sync_lock_test_and_set()`. The
+`__sync_swap()` builtin is a full barrier.
-``__builtin_addressof``
------------------------
+### `__builtin_addressof`
-``__builtin_addressof`` performs the functionality of the built-in ``&``
-operator, ignoring any ``operator&`` overload. This is useful in constant
+`__builtin_addressof` performs the functionality of the built-in `&`
+operator, ignoring any `operator&` overload. This is useful in constant
expressions in C++11, where there is no other way to take the address of an
-object that overloads ``operator&``. Clang automatically adds
-``[[clang::lifetimebound]]`` to the parameter of ``__builtin_addressof``.
+object that overloads `operator&`. Clang automatically adds
+`[[clang::lifetimebound]]` to the parameter of `__builtin_addressof`.
**Example of use**:
-.. code-block:: c++
-
- template<typename T> constexpr T *addressof(T &value) {
- return __builtin_addressof(value);
- }
+```c++
+template<typename T> constexpr T *addressof(T &value) {
+ return __builtin_addressof(value);
+}
+```
-``__builtin_function_start``
------------------------------
+### `__builtin_function_start`
-``__builtin_function_start`` returns the address of a function body.
+`__builtin_function_start` returns the address of a function body.
**Syntax**:
-.. code-block:: c++
-
- void *__builtin_function_start(function)
+```c++
+void *__builtin_function_start(function)
+```
**Example of use**:
-.. code-block:: c++
-
- void a() {}
- void *p = __builtin_function_start(a);
+```c++
+void a() {}
+void *p = __builtin_function_start(a);
- class A {
- public:
- void a(int n);
- void a();
- };
+class A {
+public:
+ void a(int n);
+ void a();
+};
- void A::a(int n) {}
- void A::a() {}
+void A::a(int n) {}
+void A::a() {}
- void *pa1 = __builtin_function_start((void(A::*)(int)) &A::a);
- void *pa2 = __builtin_function_start((void(A::*)()) &A::a);
+void *pa1 = __builtin_function_start((void(A::*)(int)) &A::a);
+void *pa2 = __builtin_function_start((void(A::*)()) &A::a);
+```
**Description**:
-The ``__builtin_function_start`` builtin accepts an argument that can be
+The `__builtin_function_start` builtin accepts an argument that can be
constant-evaluated to a function, and returns the address of the function
-body. This builtin is not supported on all targets.
+body. This builtin is not supported on all targets.
The returned pointer may differ from the normally taken function address
-and is not safe to call. For example, with ``-fsanitize=cfi``, taking a
+and is not safe to call. For example, with `-fsanitize=cfi`, taking a
function address produces a callable pointer to a CFI jump table, while
-``__builtin_function_start`` returns an address that fails
-:doc:`cfi-icall<ControlFlowIntegrity>` checks.
+`__builtin_function_start` returns an address that fails
+{doc}`cfi-icall<ControlFlowIntegrity>` checks.
-``__builtin_operator_new`` and ``__builtin_operator_delete``
-------------------------------------------------------------
+### `__builtin_operator_new` and `__builtin_operator_delete`
-A call to ``__builtin_operator_new(args)`` is exactly the same as a call to
-``::operator new(args)``, except that it allows certain optimizations
+A call to `__builtin_operator_new(args)` is exactly the same as a call to
+`::operator new(args)`, except that it allows certain optimizations
that the C++ standard does not permit for a direct function call to
-``::operator new`` (in particular, removing ``new`` / ``delete`` pairs and
+`::operator new` (in particular, removing `new` / `delete` pairs and
merging allocations), and that the call is required to resolve to a
-`replaceable global allocation function
-<https://en.cppreference.com/w/cpp/memory/new/operator_new>`_.
+[replaceable global allocation function](https://en.cppreference.com/w/cpp/memory/new/operator_new).
-Likewise, ``__builtin_operator_delete`` is exactly the same as a call to
-``::operator delete(args)``, except that it permits optimizations
+Likewise, `__builtin_operator_delete` is exactly the same as a call to
+`::operator delete(args)`, except that it permits optimizations
and that the call is required to resolve to a
-`replaceable global deallocation function
-<https://en.cppreference.com/w/cpp/memory/new/operator_delete>`_.
+[replaceable global deallocation function](https://en.cppreference.com/w/cpp/memory/new/operator_delete).
-These builtins are intended for use in the implementation of ``std::allocator``
+These builtins are intended for use in the implementation of `std::allocator`
and other similar allocation libraries, and are only available in C++.
-Query for this feature with ``__has_builtin(__builtin_operator_new)`` or
-``__has_builtin(__builtin_operator_delete)``:
+Query for this feature with `__has_builtin(__builtin_operator_new)` or
+`__has_builtin(__builtin_operator_delete)`:
- * If the value is at least ``201802L``, the builtins behave as described above.
+> - If the value is at least `201802L`, the builtins behave as described above.
+> - If the value is non-zero, the builtins may not support calling arbitrary
+> replaceable global (de)allocation functions, but do support calling at least
+> `::operator new(size_t)` and `::operator delete(void*)`.
- * If the value is non-zero, the builtins may not support calling arbitrary
- replaceable global (de)allocation functions, but do support calling at least
- ``::operator new(size_t)`` and ``::operator delete(void*)``.
-
-
-``__builtin_trivially_relocate``
------------------------------------
+### `__builtin_trivially_relocate`
**Syntax**:
-.. code-block:: c
+```c
+T* __builtin_trivially_relocate(T* dest, T* src, size_t count)
+```
- T* __builtin_trivially_relocate(T* dest, T* src, size_t count)
+Trivially relocates `count` objects of relocatable, complete type `T`
+from `src` to `dest` and returns `dest`.
+This builtin is used to implement `std::trivially_relocate`.
-Trivially relocates ``count`` objects of relocatable, complete type ``T``
-from ``src`` to ``dest`` and returns ``dest``.
-This builtin is used to implement ``std::trivially_relocate``.
-
-``__builtin_invoke``
---------------------
+### `__builtin_invoke`
**Syntax**:
-.. code-block:: c++
-
- template <class Callee, class... Args>
- decltype(auto) __builtin_invoke(Callee&& callee, Args&&... args);
+```c++
+template <class Callee, class... Args>
+decltype(auto) __builtin_invoke(Callee&& callee, Args&&... args);
+```
-``__builtin_invoke`` is equivalent to ``std::invoke``.
+`__builtin_invoke` is equivalent to `std::invoke`.
-``__builtin_preserve_access_index``
------------------------------------
+### `__builtin_preserve_access_index`
-``__builtin_preserve_access_index`` specifies a code section where
+`__builtin_preserve_access_index` specifies a code section where
array subscript access and structure/union member access are relocatable
under bpf compile-once run-everywhere framework. Debuginfo (typically
-with ``-g``) is needed, otherwise, the compiler will exit with an error.
+with `-g`) is needed, otherwise, the compiler will exit with an error.
The return type for the intrinsic is the same as the type of the
argument.
**Syntax**:
-.. code-block:: c
-
- type __builtin_preserve_access_index(type arg)
+```c
+type __builtin_preserve_access_index(type arg)
+```
**Example of Use**:
-.. code-block:: c
-
- struct t {
- int i;
- int j;
- union {
- int a;
- int b;
- } c[4];
- };
- struct t *v = ...;
- int *pb =__builtin_preserve_access_index(&v->c[3].b);
- __builtin_preserve_access_index(v->j);
+```c
+struct t {
+ int i;
+ int j;
+ union {
+ int a;
+ int b;
+ } c[4];
+};
+struct t *v = ...;
+int *pb =__builtin_preserve_access_index(&v->c[3].b);
+__builtin_preserve_access_index(v->j);
+```
-``__builtin_debugtrap``
------------------------
+### `__builtin_debugtrap`
-``__builtin_debugtrap`` causes the program to stop its execution in such a way that a debugger can catch it.
+`__builtin_debugtrap` causes the program to stop its execution in such a way that a debugger can catch it.
**Syntax**:
-.. code-block:: c++
-
- __builtin_debugtrap()
+```c++
+__builtin_debugtrap()
+```
**Description**
-``__builtin_debugtrap`` is lowered to the ` ``llvm.debugtrap`` <https://llvm.org/docs/LangRef.html#llvm-debugtrap-intrinsic>`_ builtin. It should have the same effect as setting a breakpoint on the line where the builtin is called.
+`__builtin_debugtrap` is lowered to the \` `llvm.debugtrap` \<<https://llvm.org/docs/LangRef.html#llvm-debugtrap-intrinsic>>\`\_ builtin. It should have the same effect as setting a breakpoint on the line where the builtin is called.
-Query for this feature with ``__has_builtin(__builtin_debugtrap)``.
+Query for this feature with `__has_builtin(__builtin_debugtrap)`.
+### `__builtin_trap`
-``__builtin_trap``
-------------------
-
-``__builtin_trap`` causes the program to stop its execution abnormally.
+`__builtin_trap` causes the program to stop its execution abnormally.
**Syntax**:
-.. code-block:: c++
-
- __builtin_trap()
+```c++
+__builtin_trap()
+```
**Description**
-``__builtin_trap`` is lowered to the ` ``llvm.trap`` <https://llvm.org/docs/LangRef.html#llvm-trap-intrinsic>`_ builtin.
+`__builtin_trap` is lowered to the \` `llvm.trap` \<<https://llvm.org/docs/LangRef.html#llvm-trap-intrinsic>>\`\_ builtin.
-Query for this feature with ``__has_builtin(__builtin_trap)``.
+Query for this feature with `__has_builtin(__builtin_trap)`.
-``__builtin_arm_trap``
-----------------------
+### `__builtin_arm_trap`
-``__builtin_arm_trap`` is an AArch64 extension to ``__builtin_trap`` which also accepts a compile-time constant value, encoded directly into the trap instruction for later inspection.
+`__builtin_arm_trap` is an AArch64 extension to `__builtin_trap` which also accepts a compile-time constant value, encoded directly into the trap instruction for later inspection.
**Syntax**:
-.. code-block:: c++
-
- __builtin_arm_trap(const unsigned short payload)
+```c++
+__builtin_arm_trap(const unsigned short payload)
+```
**Description**
-``__builtin_arm_trap`` is lowered to the ``llvm.aarch64.break`` builtin, and then to ``brk #payload``.
+`__builtin_arm_trap` is lowered to the `llvm.aarch64.break` builtin, and then to `brk #payload`.
-``__builtin_verbose_trap``
---------------------------
+### `__builtin_verbose_trap`
-``__builtin_verbose_trap`` causes the program to stop its execution abnormally
+`__builtin_verbose_trap` causes the program to stop its execution abnormally
and shows a human-readable description of the reason for the termination when a
debugger is attached or in a symbolicated crash log.
**Syntax**:
-.. code-block:: c++
-
- __builtin_verbose_trap(const char *category, const char *reason)
+```c++
+__builtin_verbose_trap(const char *category, const char *reason)
+```
**Description**
-``__builtin_verbose_trap`` is lowered to the ` ``llvm.trap`` <https://llvm.org/docs/LangRef.html#llvm-trap-intrinsic>`_ builtin.
+`__builtin_verbose_trap` is lowered to the \` `llvm.trap` \<<https://llvm.org/docs/LangRef.html#llvm-trap-intrinsic>>\`\_ builtin.
Additionally, clang emits debugging information that represents an artificial
inline frame whose name encodes the category and reason strings passed to the builtin,
prefixed by a "magic" prefix.
For example, consider the following code:
-.. code-block:: c++
-
- void foo(int* p) {
- if (p == nullptr)
- __builtin_verbose_trap("check null", "Argument must not be null!");
- }
+```c++
+void foo(int* p) {
+ if (p == nullptr)
+ __builtin_verbose_trap("check null", "Argument must not be null!");
+}
+```
The debugging information would look as if it were produced for the following code:
-.. code-block:: c++
-
- __attribute__((always_inline))
- inline void "__clang_trap_msg$check null$Argument must not be null!"() {
- __builtin_trap();
- }
+```c++
+__attribute__((always_inline))
+inline void "__clang_trap_msg$check null$Argument must not be null!"() {
+ __builtin_trap();
+}
- void foo(int* p) {
- if (p == nullptr)
- "__clang_trap_msg$check null$Argument must not be null!"();
- }
+void foo(int* p) {
+ if (p == nullptr)
+ "__clang_trap_msg$check null$Argument must not be null!"();
+}
+```
However, the generated code would not actually contain a call to the artificial
function — it only exists in the debugging information.
-Query for this feature with ``__has_builtin(__builtin_verbose_trap)``. Note that
+Query for this feature with `__has_builtin(__builtin_verbose_trap)`. Note that
users need to enable debug information to enable this feature. A call to this
-builtin is equivalent to a call to ``__builtin_trap`` if debug information isn't
+builtin is equivalent to a call to `__builtin_trap` if debug information isn't
enabled.
The optimizer can merge calls to trap with different messages, which degrades
the debugging experience.
-``__builtin_allow_runtime_check``
----------------------------------
+### `__builtin_allow_runtime_check`
-``__builtin_allow_runtime_check`` returns true if the check at the current
+`__builtin_allow_runtime_check` returns true if the check at the current
program location should be executed. It is expected to be used to implement
-``assert`` like checks which can be safely removed by the optimizer.
+`assert` like checks which can be safely removed by the optimizer.
**Syntax**:
-.. code-block:: c++
-
- bool __builtin_allow_runtime_check(const char* kind)
+```c++
+bool __builtin_allow_runtime_check(const char* kind)
+```
**Example of use**:
-.. code-block:: c++
-
- if (__builtin_allow_runtime_check("mycheck") && !ExpensiveCheck()) {
- abort();
- }
+```c++
+if (__builtin_allow_runtime_check("mycheck") && !ExpensiveCheck()) {
+ abort();
+}
+```
**Description**
-``__builtin_allow_runtime_check`` is lowered to the `llvm.allow.runtime.check
-<https://llvm.org/docs/LangRef.html#llvm-allow-runtime-check-intrinsic>`_
+`__builtin_allow_runtime_check` is lowered to the [llvm.allow.runtime.check](https://llvm.org/docs/LangRef.html#llvm-allow-runtime-check-intrinsic)
intrinsic.
-The ``__builtin_allow_runtime_check()`` can be used within control structures
-like ``if`` to guard expensive runtime checks. The return value is determined
+The `__builtin_allow_runtime_check()` can be used within control structures
+like `if` to guard expensive runtime checks. The return value is determined
by the following compiler options and may differ per call site:
-* ``-mllvm -lower-allow-check-percentile-cutoff-hot=N``: Disable checks in hot
+- `-mllvm -lower-allow-check-percentile-cutoff-hot=N`: Disable checks in hot
code marked by the profile summary with a hotness cutoff in the range
- ``[0, 999999]`` (a larger N disables more checks).
-* ``-mllvm -lower-allow-check-random-rate=P``: Keep a check with probability P,
- a floating point number in the range ``[0.0, 1.0]``.
-* If both options are specified, a check is disabled if either condition is satisfied.
-* If neither is specified, all checks are allowed.
+ `[0, 999999]` (a larger N disables more checks).
+- `-mllvm -lower-allow-check-random-rate=P`: Keep a check with probability P,
+ a floating point number in the range `[0.0, 1.0]`.
+- If both options are specified, a check is disabled if either condition is satisfied.
+- If neither is specified, all checks are allowed.
-Parameter ``kind``, currently unused, is a string literal specifying the check
+Parameter `kind`, currently unused, is a string literal specifying the check
kind. Future compiler versions may use this to allow for more granular control,
such as applying different hotness cutoffs to different check kinds.
-Query for this feature with ``__has_builtin(__builtin_allow_runtime_check)``.
+Query for this feature with `__has_builtin(__builtin_allow_runtime_check)`.
-``__builtin_nondeterministic_value``
-------------------------------------
+### `__builtin_nondeterministic_value`
-``__builtin_nondeterministic_value`` returns a valid nondeterministic value of the same type as the provided argument.
+`__builtin_nondeterministic_value` returns a valid nondeterministic value of the same type as the provided argument.
**Syntax**:
-.. code-block:: c++
-
- type __builtin_nondeterministic_value(type x)
+```c++
+type __builtin_nondeterministic_value(type x)
+```
**Examples**:
-.. code-block:: c++
-
- int x = __builtin_nondeterministic_value(x);
- float y = __builtin_nondeterministic_value(y);
- __m256i a = __builtin_nondeterministic_value(a);
+```c++
+int x = __builtin_nondeterministic_value(x);
+float y = __builtin_nondeterministic_value(y);
+__m256i a = __builtin_nondeterministic_value(a);
+```
**Description**
-Each call to ``__builtin_nondeterministic_value`` returns a valid value of the type given by the argument.
+Each call to `__builtin_nondeterministic_value` returns a valid value of the type given by the argument.
The types currently supported are: integer types, floating-point types, vector types.
-Query for this feature with ``__has_builtin(__builtin_nondeterministic_value)``.
+Query for this feature with `__has_builtin(__builtin_nondeterministic_value)`.
-``__builtin_sycl_unique_stable_name``
--------------------------------------
+### `__builtin_sycl_unique_stable_name`
-``__builtin_sycl_unique_stable_name()`` is a builtin that takes a type and
+`__builtin_sycl_unique_stable_name()` is a builtin that takes a type and
produces a string literal containing a unique name for the type that is stable
across split compilations, mainly to support SYCL/Data Parallel C++ language.
@@ -4594,358 +4282,348 @@ In order to produce the unique name, the current implementation of the builtin
uses Itanium mangling even if the host compilation uses a different name
mangling scheme at runtime. The mangler marks all the lambdas required to name
the SYCL kernel and emits a stable local ordering of the respective lambdas.
-The resulting pattern is demanglable. When non-lambda types are passed to the
+The resulting pattern is demanglable. When non-lambda types are passed to the
builtin, the mangler emits their usual pattern without any special treatment.
**Syntax**:
-.. code-block:: c
-
- // Computes a unique stable name for the given type.
- constexpr const char * __builtin_sycl_unique_stable_name( type-id );
+```c
+// Computes a unique stable name for the given type.
+constexpr const char * __builtin_sycl_unique_stable_name( type-id );
+```
-``__builtin_popcountg``
------------------------
+### `__builtin_popcountg`
-``__builtin_popcountg`` returns the number of 1 bits in the argument. The
+`__builtin_popcountg` returns the number of 1 bits in the argument. The
argument can be of any unsigned integer type or fixed boolean vector.
**Syntax**:
-.. code-block:: c++
-
- int __builtin_popcountg(type x)
+```c++
+int __builtin_popcountg(type x)
+```
**Examples**:
-.. code-block:: c++
-
- unsigned int x = 1;
- int x_pop = __builtin_popcountg(x);
+```c++
+unsigned int x = 1;
+int x_pop = __builtin_popcountg(x);
- unsigned long y = 3;
- int y_pop = __builtin_popcountg(y);
+unsigned long y = 3;
+int y_pop = __builtin_popcountg(y);
- unsigned _BitInt(128) z = 7;
- int z_pop = __builtin_popcountg(z);
+unsigned _BitInt(128) z = 7;
+int z_pop = __builtin_popcountg(z);
+```
**Description**:
-``__builtin_popcountg`` is meant to be a type-generic alternative to the
-``__builtin_popcount{,l,ll}`` builtins, with support for other integer types,
-such as ``unsigned __int128`` and C23 ``unsigned _BitInt(N)``.
+`__builtin_popcountg` is meant to be a type-generic alternative to the
+`__builtin_popcount{,l,ll}` builtins, with support for other integer types,
+such as `unsigned __int128` and C23 `unsigned _BitInt(N)`.
-``__builtin_clzg`` and ``__builtin_ctzg``
------------------------------------------
+### `__builtin_clzg` and `__builtin_ctzg`
-``__builtin_clzg`` (respectively ``__builtin_ctzg``) returns the number of
+`__builtin_clzg` (respectively `__builtin_ctzg`) returns the number of
leading (respectively trailing) 0 bits in the first argument. The first argument
can be of any unsigned integer type or fixed boolean vector.
For boolean vectors, these builtins interpret the vector like a bit-field where
the ith element of the vector is bit i of the bit-field, counting from the
-least significant end. ``__builtin_clzg`` returns the number of zero elements at
-the end of the vector, while ``__builtin_ctzg`` returns the number of zero
+least significant end. `__builtin_clzg` returns the number of zero elements at
+the end of the vector, while `__builtin_ctzg` returns the number of zero
elements at the start of the vector.
-If the first argument is 0 and an optional second argument of ``int`` type is
+If the first argument is 0 and an optional second argument of `int` type is
provided, then the second argument is returned. If the first argument is 0, but
only one argument is provided, then the behavior is undefined.
**Syntax**:
-.. code-block:: c++
-
- int __builtin_clzg(type x[, int fallback])
- int __builtin_ctzg(type x[, int fallback])
+```c++
+int __builtin_clzg(type x[, int fallback])
+int __builtin_ctzg(type x[, int fallback])
+```
**Examples**:
-.. code-block:: c++
-
- unsigned int x = 1;
- int x_lz = __builtin_clzg(x);
- int x_tz = __builtin_ctzg(x);
+```c++
+unsigned int x = 1;
+int x_lz = __builtin_clzg(x);
+int x_tz = __builtin_ctzg(x);
- unsigned long y = 2;
- int y_lz = __builtin_clzg(y);
- int y_tz = __builtin_ctzg(y);
+unsigned long y = 2;
+int y_lz = __builtin_clzg(y);
+int y_tz = __builtin_ctzg(y);
- unsigned _BitInt(128) z = 4;
- int z_lz = __builtin_clzg(z);
- int z_tz = __builtin_ctzg(z);
+unsigned _BitInt(128) z = 4;
+int z_lz = __builtin_clzg(z);
+int z_tz = __builtin_ctzg(z);
+```
**Description**:
-``__builtin_clzg`` (respectively ``__builtin_ctzg``) is meant to be a
-type-generic alternative to the ``__builtin_clz{,l,ll}`` (respectively
-``__builtin_ctz{,l,ll}``) builtins, with support for other integer types, such
-as ``unsigned __int128`` and C23 ``unsigned _BitInt(N)``.
+`__builtin_clzg` (respectively `__builtin_ctzg`) is meant to be a
+type-generic alternative to the `__builtin_clz{,l,ll}` (respectively
+`__builtin_ctz{,l,ll}`) builtins, with support for other integer types, such
+as `unsigned __int128` and C23 `unsigned _BitInt(N)`.
-``__builtin_counted_by_ref``
-----------------------------
+### `__builtin_counted_by_ref`
-``__builtin_counted_by_ref`` returns a pointer to the count field from the
-``counted_by`` attribute.
+`__builtin_counted_by_ref` returns a pointer to the count field from the
+`counted_by` attribute.
-The argument must be a flexible array member or a pointer with the ``counted_by``
-attribute. If the argument doesn't have the ``counted_by`` attribute, the builtin
-returns ``(void *)0``.
+The argument must be a flexible array member or a pointer with the `counted_by`
+attribute. If the argument doesn't have the `counted_by` attribute, the builtin
+returns `(void *)0`.
**Syntax**:
-.. code-block:: c
-
- T *__builtin_counted_by_ref(void *array)
+```c
+T *__builtin_counted_by_ref(void *array)
+```
**Examples**:
-.. code-block:: c
-
- #define alloc(P, FAM, COUNT) ({ \
- size_t __ignored_assignment; \
- typeof(P) __p = NULL; \
- __p = malloc(MAX(sizeof(*__p), \
- sizeof(*__p) + sizeof(*__p->FAM) * COUNT)); \
- \
- *_Generic( \
- __builtin_counted_by_ref(__p->FAM), \
- void *: &__ignored_assignment, \
- default: __builtin_counted_by_ref(__p->FAM)) = COUNT; \
- \
- __p; \
- })
+```c
+#define alloc(P, FAM, COUNT) ({ \
+ size_t __ignored_assignment; \
+ typeof(P) __p = NULL; \
+ __p = malloc(MAX(sizeof(*__p), \
+ sizeof(*__p) + sizeof(*__p->FAM) * COUNT)); \
+ \
+ *_Generic( \
+ __builtin_counted_by_ref(__p->FAM), \
+ void *: &__ignored_assignment, \
+ default: __builtin_counted_by_ref(__p->FAM)) = COUNT; \
+ \
+ __p; \
+})
+```
**Description**:
-The ``__builtin_counted_by_ref`` builtin allows the programmer to prevent a
-common error associated with the ``counted_by`` attribute. When using the
-``counted_by`` attribute, the ``count`` field **must** be set before the
+The `__builtin_counted_by_ref` builtin allows the programmer to prevent a
+common error associated with the `counted_by` attribute. When using the
+`counted_by` attribute, the `count` field **must** be set before the
flexible array member or pointer can be accessed. Otherwise, the sanitizers may
view such accesses as false positives. For instance, it's not uncommon for
-programmers to initialize the flexible array before setting the ``count`` field:
-
-.. code-block:: c
+programmers to initialize the flexible array before setting the `count` field:
- struct s {
- int dummy;
- short count;
- long array[] __attribute__((counted_by(count)));
- };
+```c
+struct s {
+ int dummy;
+ short count;
+ long array[] __attribute__((counted_by(count)));
+};
- struct s *ptr = malloc(sizeof(struct s) + sizeof(long) * COUNT);
+struct s *ptr = malloc(sizeof(struct s) + sizeof(long) * COUNT);
- for (int i = 0; i < COUNT; ++i)
- ptr->array[i] = i;
+for (int i = 0; i < COUNT; ++i)
+ ptr->array[i] = i;
- ptr->count = COUNT;
+ptr->count = COUNT;
+```
-Enforcing the rule that ``ptr->count = COUNT;`` must occur after every
-allocation of a struct with a ``counted_by`` member is prone to failure in large
+Enforcing the rule that `ptr->count = COUNT;` must occur after every
+allocation of a struct with a `counted_by` member is prone to failure in large
code bases. This builtin mitigates this for allocators (like in Linux) that are
implemented in a way where the counter assignment can happen automatically.
-**Note:** The value returned by ``__builtin_counted_by_ref`` cannot be assigned
+**Note:** The value returned by `__builtin_counted_by_ref` cannot be assigned
to a variable, have its address taken, or passed into or returned from a
function, because doing so violates bounds safety conventions.
-.. _builtin_stack_address-doc:
+(builtin-stack-address-doc)=
-``__builtin_stack_address``
----------------------------
+### `__builtin_stack_address`
-``__builtin_stack_address`` returns the address that separates the current
+`__builtin_stack_address` returns the address that separates the current
function's (i.e. the one calling the builtin) stack space and the region of the
stack that may be modified by called functions. The semantics match those of
GCC's builtin of the same name.
**Syntax**:
-.. code-block:: c++
-
- void *__builtin_stack_address()
+```c++
+void *__builtin_stack_address()
+```
**Example**:
-.. code-block:: c++
-
- void *sp = __builtin_stack_address();
+```c++
+void *sp = __builtin_stack_address();
+```
**Description**:
-The address returned by ``__builtin_stack_address`` identifies the starting
+The address returned by `__builtin_stack_address` identifies the starting
address of the stack region that may be used by called functions.
On some architectures (e.g. x86), it's sufficient to return the value in the
stack pointer register directly. On others (e.g. SPARCv9), adjustments are
required to the value of the stack pointer register.
-``__builtin_stack_address`` performs the necessary adjustments and returns the
+`__builtin_stack_address` performs the necessary adjustments and returns the
correct boundary address.
-Multiprecision Arithmetic Builtins
-----------------------------------
+### Multiprecision Arithmetic Builtins
Clang provides a set of builtins which expose multiprecision arithmetic in a
manner amenable to C. They all have the following form:
-.. code-block:: c
-
- unsigned x = ..., y = ..., carryin = ..., carryout;
- unsigned sum = __builtin_addc(x, y, carryin, &carryout);
+```c
+unsigned x = ..., y = ..., carryin = ..., carryout;
+unsigned sum = __builtin_addc(x, y, carryin, &carryout);
+```
Thus one can form a multiprecision addition chain in the following manner:
-.. code-block:: c
-
- unsigned *x, *y, *z, carryin=0, carryout;
- z[0] = __builtin_addc(x[0], y[0], carryin, &carryout);
- carryin = carryout;
- z[1] = __builtin_addc(x[1], y[1], carryin, &carryout);
- carryin = carryout;
- z[2] = __builtin_addc(x[2], y[2], carryin, &carryout);
- carryin = carryout;
- z[3] = __builtin_addc(x[3], y[3], carryin, &carryout);
+```c
+unsigned *x, *y, *z, carryin=0, carryout;
+z[0] = __builtin_addc(x[0], y[0], carryin, &carryout);
+carryin = carryout;
+z[1] = __builtin_addc(x[1], y[1], carryin, &carryout);
+carryin = carryout;
+z[2] = __builtin_addc(x[2], y[2], carryin, &carryout);
+carryin = carryout;
+z[3] = __builtin_addc(x[3], y[3], carryin, &carryout);
+```
The complete list of builtins are:
-.. code-block:: c
-
- unsigned char __builtin_addcb (unsigned char x, unsigned char y, unsigned char carryin, unsigned char *carryout);
- unsigned short __builtin_addcs (unsigned short x, unsigned short y, unsigned short carryin, unsigned short *carryout);
- unsigned __builtin_addc (unsigned x, unsigned y, unsigned carryin, unsigned *carryout);
- unsigned long __builtin_addcl (unsigned long x, unsigned long y, unsigned long carryin, unsigned long *carryout);
- unsigned long long __builtin_addcll(unsigned long long x, unsigned long long y, unsigned long long carryin, unsigned long long *carryout);
- unsigned char __builtin_subcb (unsigned char x, unsigned char y, unsigned char carryin, unsigned char *carryout);
- unsigned short __builtin_subcs (unsigned short x, unsigned short y, unsigned short carryin, unsigned short *carryout);
- unsigned __builtin_subc (unsigned x, unsigned y, unsigned carryin, unsigned *carryout);
- unsigned long __builtin_subcl (unsigned long x, unsigned long y, unsigned long carryin, unsigned long *carryout);
- unsigned long long __builtin_subcll(unsigned long long x, unsigned long long y, unsigned long long carryin, unsigned long long *carryout);
-
-Checked Arithmetic Builtins
----------------------------
+```c
+unsigned char __builtin_addcb (unsigned char x, unsigned char y, unsigned char carryin, unsigned char *carryout);
+unsigned short __builtin_addcs (unsigned short x, unsigned short y, unsigned short carryin, unsigned short *carryout);
+unsigned __builtin_addc (unsigned x, unsigned y, unsigned carryin, unsigned *carryout);
+unsigned long __builtin_addcl (unsigned long x, unsigned long y, unsigned long carryin, unsigned long *carryout);
+unsigned long long __builtin_addcll(unsigned long long x, unsigned long long y, unsigned long long carryin, unsigned long long *carryout);
+unsigned char __builtin_subcb (unsigned char x, unsigned char y, unsigned char carryin, unsigned char *carryout);
+unsigned short __builtin_subcs (unsigned short x, unsigned short y, unsigned short carryin, unsigned short *carryout);
+unsigned __builtin_subc (unsigned x, unsigned y, unsigned carryin, unsigned *carryout);
+unsigned long __builtin_subcl (unsigned long x, unsigned long y, unsigned long carryin, unsigned long *carryout);
+unsigned long long __builtin_subcll(unsigned long long x, unsigned long long y, unsigned long long carryin, unsigned long long *carryout);
+```
+
+### Checked Arithmetic Builtins
Clang provides a set of builtins that implement checked arithmetic for security
critical applications in a manner that is fast and easily expressible in C. As
an example of their usage:
-.. code-block:: c
-
- errorcode_t security_critical_application(...) {
- unsigned x, y, result;
- ...
- if (__builtin_mul_overflow(x, y, &result))
- return kErrorCodeHackers;
- ...
- use_multiply(result);
- ...
- }
+```c
+errorcode_t security_critical_application(...) {
+ unsigned x, y, result;
+ ...
+ if (__builtin_mul_overflow(x, y, &result))
+ return kErrorCodeHackers;
+ ...
+ use_multiply(result);
+ ...
+}
+```
Clang provides the following checked arithmetic builtins:
-.. code-block:: c
-
- bool __builtin_add_overflow (type1 x, type2 y, type3 *sum);
- bool __builtin_sub_overflow (type1 x, type2 y, type3 *diff);
- bool __builtin_mul_overflow (type1 x, type2 y, type3 *prod);
- bool __builtin_uadd_overflow (unsigned x, unsigned y, unsigned *sum);
- bool __builtin_uaddl_overflow (unsigned long x, unsigned long y, unsigned long *sum);
- bool __builtin_uaddll_overflow(unsigned long long x, unsigned long long y, unsigned long long *sum);
- bool __builtin_usub_overflow (unsigned x, unsigned y, unsigned *diff);
- bool __builtin_usubl_overflow (unsigned long x, unsigned long y, unsigned long *diff);
- bool __builtin_usubll_overflow(unsigned long long x, unsigned long long y, unsigned long long *diff);
- bool __builtin_umul_overflow (unsigned x, unsigned y, unsigned *prod);
- bool __builtin_umull_overflow (unsigned long x, unsigned long y, unsigned long *prod);
- bool __builtin_umulll_overflow(unsigned long long x, unsigned long long y, unsigned long long *prod);
- bool __builtin_sadd_overflow (int x, int y, int *sum);
- bool __builtin_saddl_overflow (long x, long y, long *sum);
- bool __builtin_saddll_overflow(long long x, long long y, long long *sum);
- bool __builtin_ssub_overflow (int x, int y, int *diff);
- bool __builtin_ssubl_overflow (long x, long y, long *diff);
- bool __builtin_ssubll_overflow(long long x, long long y, long long *diff);
- bool __builtin_smul_overflow (int x, int y, int *prod);
- bool __builtin_smull_overflow (long x, long y, long *prod);
- bool __builtin_smulll_overflow(long long x, long long y, long long *prod);
+```c
+bool __builtin_add_overflow (type1 x, type2 y, type3 *sum);
+bool __builtin_sub_overflow (type1 x, type2 y, type3 *diff);
+bool __builtin_mul_overflow (type1 x, type2 y, type3 *prod);
+bool __builtin_uadd_overflow (unsigned x, unsigned y, unsigned *sum);
+bool __builtin_uaddl_overflow (unsigned long x, unsigned long y, unsigned long *sum);
+bool __builtin_uaddll_overflow(unsigned long long x, unsigned long long y, unsigned long long *sum);
+bool __builtin_usub_overflow (unsigned x, unsigned y, unsigned *diff);
+bool __builtin_usubl_overflow (unsigned long x, unsigned long y, unsigned long *diff);
+bool __builtin_usubll_overflow(unsigned long long x, unsigned long long y, unsigned long long *diff);
+bool __builtin_umul_overflow (unsigned x, unsigned y, unsigned *prod);
+bool __builtin_umull_overflow (unsigned long x, unsigned long y, unsigned long *prod);
+bool __builtin_umulll_overflow(unsigned long long x, unsigned long long y, unsigned long long *prod);
+bool __builtin_sadd_overflow (int x, int y, int *sum);
+bool __builtin_saddl_overflow (long x, long y, long *sum);
+bool __builtin_saddll_overflow(long long x, long long y, long long *sum);
+bool __builtin_ssub_overflow (int x, int y, int *diff);
+bool __builtin_ssubl_overflow (long x, long y, long *diff);
+bool __builtin_ssubll_overflow(long long x, long long y, long long *diff);
+bool __builtin_smul_overflow (int x, int y, int *prod);
+bool __builtin_smull_overflow (long x, long y, long *prod);
+bool __builtin_smulll_overflow(long long x, long long y, long long *prod);
+```
Each builtin performs the specified mathematical operation on the
-first two arguments and stores the result in the third argument. If
+first two arguments and stores the result in the third argument. If
possible, the result will be equal to mathematically-correct result
-and the builtin will return 0. Otherwise, the builtin will return
+and the builtin will return 0. Otherwise, the builtin will return
1 and the result will be equal to the unique value that is equivalent
to the mathematically-correct result modulo two raised to the *k*
-power, where *k* is the number of bits in the result type. The
+power, where *k* is the number of bits in the result type. The
behavior of these builtins is well-defined for all argument values.
The first three builtins work generically for operands of any integer type,
-including boolean types. The operands need not have the same type as each
-other, or as the result. The other builtins may implicitly promote or
+including boolean types. The operands need not have the same type as each
+other, or as the result. The other builtins may implicitly promote or
convert their operands before performing the operation.
-Query for this feature with ``__has_builtin(__builtin_add_overflow)``, etc.
+Query for this feature with `__has_builtin(__builtin_add_overflow)`, etc.
-Floating point builtins
----------------------------------------
+### Floating point builtins
-``__builtin_isfpclass``
------------------------
+### `__builtin_isfpclass`
-``__builtin_isfpclass`` is used to test if the specified floating-point values
+`__builtin_isfpclass` is used to test if the specified floating-point values
fall into one of the specified floating-point classes.
**Syntax**:
-.. code-block:: c++
-
- int __builtin_isfpclass(fp_type expr, int mask)
- int_vector __builtin_isfpclass(fp_vector expr, int mask)
+```c++
+int __builtin_isfpclass(fp_type expr, int mask)
+int_vector __builtin_isfpclass(fp_vector expr, int mask)
+```
**Example of use**:
-.. code-block:: c++
-
- if (__builtin_isfpclass(x, 448)) {
- // `x` is positive finite value
- ...
- }
+```c++
+if (__builtin_isfpclass(x, 448)) {
+ // `x` is positive finite value
+ ...
+}
+```
**Description**:
-The ``__builtin_isfpclass()`` builtin is a generalization of functions ``isnan``,
-``isinf``, ``isfinite`` and some others defined by the C standard. It tests if
+The `__builtin_isfpclass()` builtin is a generalization of functions `isnan`,
+`isinf`, `isfinite` and some others defined by the C standard. It tests if
the floating-point value, specified by the first argument, falls into any of data
classes, specified by the second argument. The latter is an integer constant
bitmask expression, in which each data class is represented by a bit
using the encoding:
-========== =================== ======================
-Mask value Data class Macro
-========== =================== ======================
-0x0001 Signaling NaN __FPCLASS_SNAN
-0x0002 Quiet NaN __FPCLASS_QNAN
-0x0004 Negative infinity __FPCLASS_NEGINF
-0x0008 Negative normal __FPCLASS_NEGNORMAL
-0x0010 Negative subnormal __FPCLASS_NEGSUBNORMAL
-0x0020 Negative zero __FPCLASS_NEGZERO
-0x0040 Positive zero __FPCLASS_POSZERO
-0x0080 Positive subnormal __FPCLASS_POSSUBNORMAL
-0x0100 Positive normal __FPCLASS_POSNORMAL
-0x0200 Positive infinity __FPCLASS_POSINF
-========== =================== ======================
+| Mask value | Data class | Macro |
+| ---------- | ------------------ | ------------------------ |
+| 0x0001 | Signaling NaN | \_\_FPCLASS_SNAN |
+| 0x0002 | Quiet NaN | \_\_FPCLASS_QNAN |
+| 0x0004 | Negative infinity | \_\_FPCLASS_NEGINF |
+| 0x0008 | Negative normal | \_\_FPCLASS_NEGNORMAL |
+| 0x0010 | Negative subnormal | \_\_FPCLASS_NEGSUBNORMAL |
+| 0x0020 | Negative zero | \_\_FPCLASS_NEGZERO |
+| 0x0040 | Positive zero | \_\_FPCLASS_POSZERO |
+| 0x0080 | Positive subnormal | \_\_FPCLASS_POSSUBNORMAL |
+| 0x0100 | Positive normal | \_\_FPCLASS_POSNORMAL |
+| 0x0200 | Positive infinity | \_\_FPCLASS_POSINF |
For convenience preprocessor defines macros for these values. The function
-returns 1 if ``expr`` falls into one of the specified data classes, 0 otherwise.
+returns 1 if `expr` falls into one of the specified data classes, 0 otherwise.
In the example above the mask value 448 (0x1C0) contains the bits selecting
positive zero, positive subnormal and positive normal classes.
-``__builtin_isfpclass(x, 448)`` would return true only if ``x`` if of any of
+`__builtin_isfpclass(x, 448)` would return true only if `x` if of any of
these data classes. Using suitable mask value, the function can implement any of
-the standard classification functions, for example, ``__builtin_isfpclass(x, 3)``
-is identical to ``isnan``,``__builtin_isfpclass(x, 504)`` - to ``isfinite``
+the standard classification functions, for example, `__builtin_isfpclass(x, 3)`
+is identical to `isnan`,\`\`\_\_builtin_isfpclass(x, 504)\`\` - to `isfinite`
and so on.
If the first argument is a vector, the function is equivalent to the set of
-scalar calls of ``__builtin_isfpclass`` applied to the input elementwise.
+scalar calls of `__builtin_isfpclass` applied to the input elementwise.
-The result of ``__builtin_isfpclass`` is a boolean value, if the first argument
+The result of `__builtin_isfpclass` is a boolean value, if the first argument
is a scalar, or an integer vector with the same element count as the first
argument. The element type in this vector has the same bit length as the
element of the first argument type.
@@ -4954,220 +4632,207 @@ This function never raises floating-point exceptions and does not canonicalize
its input. The floating-point argument is not promoted, its data class is
determined based on its representation in its actual semantic type.
-``__builtin_canonicalize``
---------------------------
-
-.. code-block:: c
+### `__builtin_canonicalize`
- double __builtin_canonicalize(double);
- float __builtin_canonicalizef(float);
- long double __builtin_canonicalizel(long double);
+```c
+double __builtin_canonicalize(double);
+float __builtin_canonicalizef(float);
+long double __builtin_canonicalizel(long double);
+```
Returns the platform specific canonical encoding of a floating point
number. This canonicalization is useful for implementing certain
-numeric primitives such as frexp. See `LLVM canonicalize intrinsic
-<https://llvm.org/docs/LangRef.html#llvm-canonicalize-intrinsic>`_ for
+numeric primitives such as frexp. See [LLVM canonicalize intrinsic](https://llvm.org/docs/LangRef.html#llvm-canonicalize-intrinsic) for
more information on the semantics.
-``__builtin_flt_rounds`` and ``__builtin_set_flt_rounds``
----------------------------------------------------------
+### `__builtin_flt_rounds` and `__builtin_set_flt_rounds`
-.. code-block:: c
-
- int __builtin_flt_rounds();
- void __builtin_set_flt_rounds(int);
+```c
+int __builtin_flt_rounds();
+void __builtin_set_flt_rounds(int);
+```
Returns and sets current floating point rounding mode. The encoding of returned
values and input parameters is same as the result of FLT_ROUNDS, specified by C
standard:
-- ``0`` - toward zero
-- ``1`` - to nearest, ties to even
-- ``2`` - toward positive infinity
-- ``3`` - toward negative infinity
-- ``4`` - to nearest, ties away from zero
-The effect of passing some other value to ``__builtin_flt_rounds`` is
-implementation-defined. ``__builtin_set_flt_rounds`` is currently only supported
+\- `0` - toward zero
+\- `1` - to nearest, ties to even
+\- `2` - toward positive infinity
+\- `3` - toward negative infinity
+\- `4` - to nearest, ties away from zero
+The effect of passing some other value to `__builtin_flt_rounds` is
+implementation-defined. `__builtin_set_flt_rounds` is currently only supported
to work on x86, x86_64, powerpc, powerpc64, Arm and AArch64 targets. These builtins
read and modify the floating-point environment, which is not always allowed and may
-have unexpected behavior. Please see the section on `Accessing the floating point environment <https://clang.llvm.org/docs/UsersManual.html#accessing-the-floating-point-environment>`_ for more information.
+have unexpected behavior. Please see the section on [Accessing the floating point environment](https://clang.llvm.org/docs/UsersManual.html#accessing-the-floating-point-environment) for more information.
-String builtins
----------------
+### String builtins
Clang provides constant expression evaluation support for builtins forms of
the following functions from the C standard library headers
-``<string.h>`` and ``<wchar.h>``:
-
-* ``memchr``
-* ``memcmp`` (and its deprecated BSD / POSIX alias ``bcmp``)
-* ``strchr``
-* ``strcmp``
-* ``strlen``
-* ``strncmp``
-* ``wcschr``
-* ``wcscmp``
-* ``wcslen``
-* ``wcsncmp``
-* ``wmemchr``
-* ``wmemcmp``
+`<string.h>` and `<wchar.h>`:
+
+- `memchr`
+- `memcmp` (and its deprecated BSD / POSIX alias `bcmp`)
+- `strchr`
+- `strcmp`
+- `strlen`
+- `strncmp`
+- `wcschr`
+- `wcscmp`
+- `wcslen`
+- `wcsncmp`
+- `wmemchr`
+- `wmemcmp`
In each case, the builtin form has the name of the C library function prefixed
-by ``__builtin_``. Example:
-
-.. code-block:: c
+by `__builtin_`. Example:
- void *p = __builtin_memchr("foobar", 'b', 5);
+```c
+void *p = __builtin_memchr("foobar", 'b', 5);
+```
In addition to the above, one further builtin is provided:
-.. code-block:: c
+```c
+char *__builtin_char_memchr(const char *haystack, int needle, size_t size);
+```
- char *__builtin_char_memchr(const char *haystack, int needle, size_t size);
-
-``__builtin_char_memchr(a, b, c)`` is identical to
-``(char*)__builtin_memchr(a, b, c)`` except that its use is permitted within
-constant expressions in C++11 onwards (where a cast from ``void*`` to ``char*``
+`__builtin_char_memchr(a, b, c)` is identical to
+`(char*)__builtin_memchr(a, b, c)` except that its use is permitted within
+constant expressions in C++11 onwards (where a cast from `void*` to `char*`
is disallowed in general).
-Constant evaluation support for the ``__builtin_mem*`` functions is provided
-only for arrays of ``char``, ``signed char``, ``unsigned char``, or ``char8_t``,
-despite these functions accepting an argument of type ``const void*``.
+Constant evaluation support for the `__builtin_mem*` functions is provided
+only for arrays of `char`, `signed char`, `unsigned char`, or `char8_t`,
+despite these functions accepting an argument of type `const void*`.
Support for constant expression evaluation for the above builtins can be detected
-with ``__has_feature(cxx_constexpr_string_builtins)``.
+with `__has_feature(cxx_constexpr_string_builtins)`.
-Variadic function builtins
---------------------------
+### Variadic function builtins
Clang provides several builtins for working with variadic functions from the C
-standard library ``<stdarg.h>`` header:
+standard library `<stdarg.h>` header:
-* ``__builtin_va_list``
+- `__builtin_va_list`
-A predefined typedef for the target-specific ``va_list`` type. It is undefined
-behavior to use a byte-wise copy of this type produced by calling ``memcpy``,
-``memmove``, or similar. Valid explicit copies are only produced by calling
-``va_copy`` or ``__builtin_va_copy``.
+A predefined typedef for the target-specific `va_list` type. It is undefined
+behavior to use a byte-wise copy of this type produced by calling `memcpy`,
+`memmove`, or similar. Valid explicit copies are only produced by calling
+`va_copy` or `__builtin_va_copy`.
-* ``void __builtin_va_start(__builtin_va_list list, <parameter-name>)``
+- `void __builtin_va_start(__builtin_va_list list, <parameter-name>)`
-A builtin function for the target-specific ``va_start`` function-like macro.
-The ``parameter-name`` argument is the name of the parameter preceding the
-ellipsis (``...``) in the function signature. Alternatively, in C23 mode or
-later, it may be the integer literal ``0`` if there is no parameter preceding
-the ellipsis. This function initializes the given ``__builtin_va_list`` object.
+A builtin function for the target-specific `va_start` function-like macro.
+The `parameter-name` argument is the name of the parameter preceding the
+ellipsis (`...`) in the function signature. Alternatively, in C23 mode or
+later, it may be the integer literal `0` if there is no parameter preceding
+the ellipsis. This function initializes the given `__builtin_va_list` object.
It is undefined behavior to call this function on an already initialized
-``__builtin_va_list`` object.
+`__builtin_va_list` object.
-* ``void __builtin_c23_va_start(__builtin_va_list list, ...)``
+- `void __builtin_c23_va_start(__builtin_va_list list, ...)`
-A builtin function for the target-specific ``va_start`` function-like macro,
+A builtin function for the target-specific `va_start` function-like macro,
available only in C23 and later. The builtin accepts zero or one argument for
-the ellipsis (``...``). If such an argument is provided, it should be the name
+the ellipsis (`...`). If such an argument is provided, it should be the name
of the parameter preceding the ellipsis, which is used for compatibility with
C versions before C23. It is an error to provide two or more variadic arguments.
-This function initializes the given ``__builtin_va_list`` object. It is
+This function initializes the given `__builtin_va_list` object. It is
undefined behavior to call this function on an already initialized
-``__builtin_va_list`` object.
+`__builtin_va_list` object.
-* ``void __builtin_va_end(__builtin_va_list list)``
+- `void __builtin_va_end(__builtin_va_list list)`
-A builtin function for the target-specific ``va_end`` function-like macro. This
-function finalizes the given ``__builtin_va_list`` object such that it is no
-longer usable unless re-initialized with a call to ``__builtin_va_start`` or
-``__builtin_va_copy``. It is undefined behavior to call this function with a
-``list`` that has not been initialized by either ``__builtin_va_start`` or
-``__builtin_va_copy``.
+A builtin function for the target-specific `va_end` function-like macro. This
+function finalizes the given `__builtin_va_list` object such that it is no
+longer usable unless re-initialized with a call to `__builtin_va_start` or
+`__builtin_va_copy`. It is undefined behavior to call this function with a
+`list` that has not been initialized by either `__builtin_va_start` or
+`__builtin_va_copy`.
-* ``<type-name> __builtin_va_arg(__builtin_va_list list, <type-name>)``
+- `<type-name> __builtin_va_arg(__builtin_va_list list, <type-name>)`
-A builtin function for the target-specific ``va_arg`` function-like macro. This
+A builtin function for the target-specific `va_arg` function-like macro. This
function returns the value of the next variadic argument to the call. It is
undefined behavior to call this builtin when there is no next variadic argument
to retrieve or if the next variadic argument does not have a type compatible
-with the given ``type-name``. The return type of the function is the
-``type-name`` given as the second argument. It is undefined behavior to call
-this function with a ``list`` that has not been initialized by either
-``__builtin_va_start`` or ``__builtin_va_copy``.
+with the given `type-name`. The return type of the function is the
+`type-name` given as the second argument. It is undefined behavior to call
+this function with a `list` that has not been initialized by either
+`__builtin_va_start` or `__builtin_va_copy`.
-* ``void __builtin_va_copy(__builtin_va_list dest, __builtin_va_list src)``
+- `void __builtin_va_copy(__builtin_va_list dest, __builtin_va_list src)`
-A builtin function for the target-specific ``va_copy`` function-like macro.
-This function initializes ``dest`` as a copy of ``src``. It is undefined
-behavior to call this function with an already initialized ``dest`` argument.
+A builtin function for the target-specific `va_copy` function-like macro.
+This function initializes `dest` as a copy of `src`. It is undefined
+behavior to call this function with an already initialized `dest` argument.
-Memory builtins
----------------
+### Memory builtins
Clang provides constant expression evaluation support for builtin forms of the
following functions from the C standard library headers
-``<string.h>`` and ``<wchar.h>``:
+`<string.h>` and `<wchar.h>`:
-* ``memcpy``
-* ``memmove``
-* ``wmemcpy``
-* ``wmemmove``
+- `memcpy`
+- `memmove`
+- `wmemcpy`
+- `wmemmove`
In each case, the builtin form has the name of the C library function prefixed
-by ``__builtin_``.
+by `__builtin_`.
Constant evaluation support is only provided when the source and destination
are pointers to arrays with the same trivially copyable element type, and the
given size is an exact multiple of the element size that is no greater than
the number of elements accessible through the source and destination operands.
-Guaranteed inlined copy
-^^^^^^^^^^^^^^^^^^^^^^^
+#### Guaranteed inlined copy
-.. code-block:: c
+```c
+void __builtin_memcpy_inline(void *dst, const void *src, size_t size);
+```
- void __builtin_memcpy_inline(void *dst, const void *src, size_t size);
+`__builtin_memcpy_inline` has been designed as a building block for efficient
+`memcpy` implementations. It is identical to `__builtin_memcpy` but also
+guarantees not to call any external functions. See LLVM IR [llvm.memcpy.inline](https://llvm.org/docs/LangRef.html#llvm-memcpy-inline-intrinsic) intrinsic
+for more information.
-
-``__builtin_memcpy_inline`` has been designed as a building block for efficient
-``memcpy`` implementations. It is identical to ``__builtin_memcpy`` but also
-guarantees not to call any external functions. See LLVM IR `llvm.memcpy.inline
-<https://llvm.org/docs/LangRef.html#llvm-memcpy-inline-intrinsic>`_ intrinsic
-for more information.
-
-This is useful to implement a custom version of ``memcpy``, implement a
-``libc`` memcpy or work around the absence of a ``libc``.
+This is useful to implement a custom version of `memcpy`, implement a
+`libc` memcpy or work around the absence of a `libc`.
Note that the `size` argument must be a compile time constant.
-Note that this intrinsic cannot yet be called in a ``constexpr`` context.
-
-Guaranteed inlined memset
-^^^^^^^^^^^^^^^^^^^^^^^^^
-
-.. code-block:: c
+Note that this intrinsic cannot yet be called in a `constexpr` context.
- void __builtin_memset_inline(void *dst, int value, size_t size);
+#### Guaranteed inlined memset
+```c
+void __builtin_memset_inline(void *dst, int value, size_t size);
+```
-``__builtin_memset_inline`` has been designed as a building block for efficient
-``memset`` implementations. It is identical to ``__builtin_memset`` but also
-guarantees not to call any external functions. See LLVM IR `llvm.memset.inline
-<https://llvm.org/docs/LangRef.html#llvm-memset-inline-intrinsic>`_ intrinsic
+`__builtin_memset_inline` has been designed as a building block for efficient
+`memset` implementations. It is identical to `__builtin_memset` but also
+guarantees not to call any external functions. See LLVM IR [llvm.memset.inline](https://llvm.org/docs/LangRef.html#llvm-memset-inline-intrinsic) intrinsic
for more information.
-This is useful to implement a custom version of ``memset``, implement a
-``libc`` memset or work around the absence of a ``libc``.
+This is useful to implement a custom version of `memset`, implement a
+`libc` memset or work around the absence of a `libc`.
Note that the `size` argument must be a compile time constant.
-Note that this intrinsic cannot yet be called in a ``constexpr`` context.
+Note that this intrinsic cannot yet be called in a `constexpr` context.
-``__is_bitwise_cloneable``
---------------------------
+### `__is_bitwise_cloneable`
A type trait is used to check whether a type can be safely copied by memcpy.
**Syntax**:
-.. code-block:: c++
-
- bool __is_bitwise_cloneable(Type)
+```c++
+bool __is_bitwise_cloneable(Type)
+```
**Description**:
@@ -5182,218 +4847,210 @@ according to the C++ Standard.
This builtin can be used in constant expressions.
-Atomic Min/Max builtins with memory ordering
---------------------------------------------
+### Atomic Min/Max builtins with memory ordering
There are two atomic builtins with min/max in-memory comparison and swap.
-The syntax and semantics are similar to GCC-compatible __atomic_* builtins.
+The syntax and semantics are similar to GCC-compatible \_\_atomic\_\* builtins.
-* ``__atomic_fetch_min``
-* ``__atomic_fetch_max``
+- `__atomic_fetch_min`
+- `__atomic_fetch_max`
The builtins work with signed and unsigned integers and require to specify memory ordering.
The return value is the original value that was stored in memory before comparison.
Clang provides two additional atomic builtins with incrementing behavior. These
-builtins perform an unsigned increment or decrement modulo a wrap-around value.
+builtins perform an unsigned increment or decrement modulo a wrap-around value.
-* ``__atomic_fetch_uinc``
-* ``__atomic_fetch_udec``
+- `__atomic_fetch_uinc`
+- `__atomic_fetch_udec`
-See the LLVM IR `atomicrmw <https://llvm.org/docs/LangRef.html#atomicrmw-instruction>`_
+See the LLVM IR [atomicrmw](https://llvm.org/docs/LangRef.html#atomicrmw-instruction)
instruction for the complete semantics of uinc_wrap and udec_wrap.
Atomic memory scopes are designed to assist optimizations for systems with
several levels of memory hierarchy like GPUs. The following memory scopes are
currently supported:
-
Example:
-.. code-block:: c
-
- unsigned int val = __atomic_fetch_min(unsigned int *pi, unsigned int ui, __ATOMIC_RELAXED);
+```c
+unsigned int val = __atomic_fetch_min(unsigned int *pi, unsigned int ui, __ATOMIC_RELAXED);
+```
-The third argument is one of the memory ordering specifiers ``__ATOMIC_RELAXED``,
-``__ATOMIC_CONSUME``, ``__ATOMIC_ACQUIRE``, ``__ATOMIC_RELEASE``,
-``__ATOMIC_ACQ_REL``, or ``__ATOMIC_SEQ_CST`` following C++11 memory model semantics.
+The third argument is one of the memory ordering specifiers `__ATOMIC_RELAXED`,
+`__ATOMIC_CONSUME`, `__ATOMIC_ACQUIRE`, `__ATOMIC_RELEASE`,
+`__ATOMIC_ACQ_REL`, or `__ATOMIC_SEQ_CST` following C++11 memory model semantics.
In terms of acquire-release ordering barriers these two operations are always
considered as operations with *load-store* semantics, even when the original value
is not actually modified after comparison.
-.. _langext-__c11_atomic:
+(langext-c11-atomic)=
-__c11_atomic builtins
----------------------
+### \_\_c11_atomic builtins
Clang provides a set of builtins which are intended to be used to implement
-C11's ``<stdatomic.h>`` header. These builtins provide the semantics of the
-``_explicit`` form of the corresponding C11 operation, and are named with a
-``__c11_`` prefix. The supported operations, and the differences from
+C11's `<stdatomic.h>` header. These builtins provide the semantics of the
+`_explicit` form of the corresponding C11 operation, and are named with a
+`__c11_` prefix. The supported operations, and the differences from
the corresponding C11 operations, are:
-* ``__c11_atomic_init``
-* ``__c11_atomic_thread_fence``
-* ``__c11_atomic_signal_fence``
-* ``__c11_atomic_is_lock_free`` (The argument is the size of the
- ``_Atomic(...)`` object, instead of its address)
-* ``__c11_atomic_store``
-* ``__c11_atomic_load``
-* ``__c11_atomic_exchange``
-* ``__c11_atomic_compare_exchange_strong``
-* ``__c11_atomic_compare_exchange_weak``
-* ``__c11_atomic_fetch_add``
-* ``__c11_atomic_fetch_sub``
-* ``__c11_atomic_fetch_and``
-* ``__c11_atomic_fetch_or``
-* ``__c11_atomic_fetch_xor``
-* ``__c11_atomic_fetch_nand`` (Nand is not presented in ``<stdatomic.h>``)
-* ``__c11_atomic_fetch_max``
-* ``__c11_atomic_fetch_min``
-
-The macros ``__ATOMIC_RELAXED``, ``__ATOMIC_CONSUME``, ``__ATOMIC_ACQUIRE``,
-``__ATOMIC_RELEASE``, ``__ATOMIC_ACQ_REL``, and ``__ATOMIC_SEQ_CST`` are
+- `__c11_atomic_init`
+- `__c11_atomic_thread_fence`
+- `__c11_atomic_signal_fence`
+- `__c11_atomic_is_lock_free` (The argument is the size of the
+ `_Atomic(...)` object, instead of its address)
+- `__c11_atomic_store`
+- `__c11_atomic_load`
+- `__c11_atomic_exchange`
+- `__c11_atomic_compare_exchange_strong`
+- `__c11_atomic_compare_exchange_weak`
+- `__c11_atomic_fetch_add`
+- `__c11_atomic_fetch_sub`
+- `__c11_atomic_fetch_and`
+- `__c11_atomic_fetch_or`
+- `__c11_atomic_fetch_xor`
+- `__c11_atomic_fetch_nand` (Nand is not presented in `<stdatomic.h>`)
+- `__c11_atomic_fetch_max`
+- `__c11_atomic_fetch_min`
+
+The macros `__ATOMIC_RELAXED`, `__ATOMIC_CONSUME`, `__ATOMIC_ACQUIRE`,
+`__ATOMIC_RELEASE`, `__ATOMIC_ACQ_REL`, and `__ATOMIC_SEQ_CST` are
provided, with values corresponding to the enumerators of C11's
-``memory_order`` enumeration.
+`memory_order` enumeration.
-(Note that Clang additionally provides GCC-compatible ``__atomic_*``
-builtins and OpenCL 2.0 ``__opencl_atomic_*`` builtins. The OpenCL 2.0
+(Note that Clang additionally provides GCC-compatible `__atomic_*`
+builtins and OpenCL 2.0 `__opencl_atomic_*` builtins. The OpenCL 2.0
atomic builtins are an explicit form of the corresponding OpenCL 2.0
-builtin function, and are named with a ``__opencl_`` prefix. The macros
-``__OPENCL_MEMORY_SCOPE_WORK_ITEM``, ``__OPENCL_MEMORY_SCOPE_WORK_GROUP``,
-``__OPENCL_MEMORY_SCOPE_DEVICE``, ``__OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES``,
-and ``__OPENCL_MEMORY_SCOPE_SUB_GROUP`` are provided, with values
-corresponding to the enumerators of OpenCL's ``memory_scope`` enumeration.)
+builtin function, and are named with a `__opencl_` prefix. The macros
+`__OPENCL_MEMORY_SCOPE_WORK_ITEM`, `__OPENCL_MEMORY_SCOPE_WORK_GROUP`,
+`__OPENCL_MEMORY_SCOPE_DEVICE`, `__OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES`,
+and `__OPENCL_MEMORY_SCOPE_SUB_GROUP` are provided, with values
+corresponding to the enumerators of OpenCL's `memory_scope` enumeration.)
-.. _langext-__scoped_atomic:
+(langext-scoped-atomic)=
-__scoped_atomic builtins
-------------------------
+### \_\_scoped_atomic builtins
Clang provides a set of atomics taking a memory scope argument. These atomics
are identical to the standard GNU / GCC atomic builtins but taking an extra
memory scope argument. These are designed to be a generic alternative to the
-``__opencl_atomic_*`` builtin functions for targets that support atomic memory
+`__opencl_atomic_*` builtin functions for targets that support atomic memory
scopes.
-* ``__MEMORY_SCOPE_SYSTEM``
-* ``__MEMORY_SCOPE_DEVICE``
-* ``__MEMORY_SCOPE_WRKGRP``
-* ``__MEMORY_SCOPE_CLUSTR``
-* ``__MEMORY_SCOPE_WVFRNT``
-* ``__MEMORY_SCOPE_SINGLE``
+- `__MEMORY_SCOPE_SYSTEM`
+- `__MEMORY_SCOPE_DEVICE`
+- `__MEMORY_SCOPE_WRKGRP`
+- `__MEMORY_SCOPE_CLUSTR`
+- `__MEMORY_SCOPE_WVFRNT`
+- `__MEMORY_SCOPE_SINGLE`
This controls whether or not the atomic operation is ordered with respect to the
whole system, the current device, an OpenCL workgroup, wavefront, or just a
single thread. If these are used on a target that does not support atomic
scopes, then they will behave exactly as the standard GNU atomic builtins.
-Low-level ARM exclusive memory builtins
----------------------------------------
+### Low-level ARM exclusive memory builtins
Clang provides overloaded builtins giving direct access to the three key ARM
instructions for implementing atomic operations.
-.. code-block:: c
+```c
+T __builtin_arm_ldrex(const volatile T *addr);
+T __builtin_arm_ldaex(const volatile T *addr);
+int __builtin_arm_strex(T val, volatile T *addr);
+int __builtin_arm_stlex(T val, volatile T *addr);
+void __builtin_arm_clrex(void);
+```
- T __builtin_arm_ldrex(const volatile T *addr);
- T __builtin_arm_ldaex(const volatile T *addr);
- int __builtin_arm_strex(T val, volatile T *addr);
- int __builtin_arm_stlex(T val, volatile T *addr);
- void __builtin_arm_clrex(void);
+The types `T` currently supported are:
-The types ``T`` currently supported are:
-
-* Integer types with width at most 64 bits (or 128 bits on AArch64).
-* Floating-point types
-* Pointer types.
+- Integer types with width at most 64 bits (or 128 bits on AArch64).
+- Floating-point types
+- Pointer types.
Note that the compiler does not guarantee it will not insert stores which clear
-the exclusive monitor in between an ``ldrex`` type operation and its paired
-``strex``. In practice this is only usually a risk when the extra store is on
+the exclusive monitor in between an `ldrex` type operation and its paired
+`strex`. In practice this is only usually a risk when the extra store is on
the same cache line as the variable being modified and Clang will only insert
stack stores on its own, so it is best not to use these operations on variables
with automatic storage duration.
-Also, loads and stores may be implicit in code written between the ``ldrex`` and
-``strex``. Clang will not necessarily mitigate the effects of these either, so
+Also, loads and stores may be implicit in code written between the `ldrex` and
+`strex`. Clang will not necessarily mitigate the effects of these either, so
care should be exercised.
For these reasons the higher level atomic primitives should be preferred where
possible.
-Non-temporal load/store builtins
---------------------------------
+### Non-temporal load/store builtins
Clang provides overloaded builtins allowing generation of non-temporal memory
accesses.
-.. code-block:: c
-
- T __builtin_nontemporal_load(T *addr);
- void __builtin_nontemporal_store(T value, T *addr);
+```c
+T __builtin_nontemporal_load(T *addr);
+void __builtin_nontemporal_store(T value, T *addr);
+```
-The types ``T`` currently supported are:
+The types `T` currently supported are:
-* Integer types.
-* Floating-point types.
-* Vector types.
+- Integer types.
+- Floating-point types.
+- Vector types.
Note that the compiler does not guarantee that non-temporal loads or stores
will be used.
-C++ Coroutines support builtins
---------------------------------
+### C++ Coroutines support builtins
-.. warning::
- This is a work in progress. Compatibility across Clang/LLVM releases is not
- guaranteed.
+:::{warning}
+This is a work in progress. Compatibility across Clang/LLVM releases is not
+guaranteed.
+:::
Clang provides experimental builtins to support C++ Coroutines as defined by
-https://wg21.link/P0057. The following four are intended to be used by the
-standard library to implement the ``std::coroutine_handle`` type.
+<https://wg21.link/P0057>. The following four are intended to be used by the
+standard library to implement the `std::coroutine_handle` type.
**Syntax**:
-.. code-block:: c
-
- void __builtin_coro_resume(void *addr);
- void __builtin_coro_destroy(void *addr);
- bool __builtin_coro_done(void *addr);
- void *__builtin_coro_promise(void *addr, int alignment, bool from_promise)
+```c
+void __builtin_coro_resume(void *addr);
+void __builtin_coro_destroy(void *addr);
+bool __builtin_coro_done(void *addr);
+void *__builtin_coro_promise(void *addr, int alignment, bool from_promise)
+```
**Example of use**:
-.. code-block:: c++
-
- template <> struct coroutine_handle<void> {
- void resume() const { __builtin_coro_resume(ptr); }
- void destroy() const { __builtin_coro_destroy(ptr); }
- bool done() const { return __builtin_coro_done(ptr); }
- // ...
- protected:
- void *ptr;
- };
-
- template <typename Promise> struct coroutine_handle : coroutine_handle<> {
- // ...
- Promise &promise() const {
- return *reinterpret_cast<Promise *>(
- __builtin_coro_promise(ptr, alignof(Promise), /*from-promise=*/false));
- }
- static coroutine_handle from_promise(Promise &promise) {
- coroutine_handle p;
- p.ptr = __builtin_coro_promise(&promise, alignof(Promise),
- /*from-promise=*/true);
- return p;
- }
- };
-
+```c++
+template <> struct coroutine_handle<void> {
+ void resume() const { __builtin_coro_resume(ptr); }
+ void destroy() const { __builtin_coro_destroy(ptr); }
+ bool done() const { return __builtin_coro_done(ptr); }
+ // ...
+protected:
+ void *ptr;
+};
+
+template <typename Promise> struct coroutine_handle : coroutine_handle<> {
+ // ...
+ Promise &promise() const {
+ return *reinterpret_cast<Promise *>(
+ __builtin_coro_promise(ptr, alignof(Promise), /*from-promise=*/false));
+ }
+ static coroutine_handle from_promise(Promise &promise) {
+ coroutine_handle p;
+ p.ptr = __builtin_coro_promise(&promise, alignof(Promise),
+ /*from-promise=*/true);
+ return p;
+ }
+};
+```
Other coroutine builtins are either for internal clang use or for use during
-development of the coroutine feature. See `Coroutines in LLVM
-<https://llvm.org/docs/Coroutines.html#intrinsics>`_ for
+development of the coroutine feature. See [Coroutines in LLVM](https://llvm.org/docs/Coroutines.html#intrinsics) for
more information on their semantics. Note that builtins matching the intrinsics
that take token as the first parameter (llvm.coro.begin, llvm.coro.alloc,
llvm.coro.free and llvm.coro.suspend) omit the token parameter and fill it to
@@ -5401,72 +5058,71 @@ an appropriate value during the emission.
**Syntax**:
-.. code-block:: c
-
- size_t __builtin_coro_size()
- void *__builtin_coro_frame()
- void *__builtin_coro_free(void *coro_frame)
+```c
+size_t __builtin_coro_size()
+void *__builtin_coro_frame()
+void *__builtin_coro_free(void *coro_frame)
- void *__builtin_coro_id(int align, void *promise, void *fnaddr, void *parts)
- bool __builtin_coro_alloc()
- void *__builtin_coro_begin(void *memory)
- void __builtin_coro_end(void *coro_frame, bool unwind)
- char __builtin_coro_suspend(bool final)
+void *__builtin_coro_id(int align, void *promise, void *fnaddr, void *parts)
+bool __builtin_coro_alloc()
+void *__builtin_coro_begin(void *memory)
+void __builtin_coro_end(void *coro_frame, bool unwind)
+char __builtin_coro_suspend(bool final)
+```
Note that there is no builtin matching the `llvm.coro.save` intrinsic. LLVM
automatically will insert one if the first argument to `llvm.coro.suspend` is
token `none`. If a user calls `__builtin_suspend`, clang will insert `token none`
as the first argument to the intrinsic.
-Source location builtins
-------------------------
+### Source location builtins
Clang provides builtins to support C++ standard library implementation
-of ``std::source_location`` as specified in C++20. With the exception
-of ``__builtin_COLUMN``, ``__builtin_FILE_NAME`` and ``__builtin_FUNCSIG``,
+of `std::source_location` as specified in C++20. With the exception
+of `__builtin_COLUMN`, `__builtin_FILE_NAME` and `__builtin_FUNCSIG`,
these builtins are also implemented by GCC.
**Syntax**:
-.. code-block:: c
-
- const char *__builtin_FILE();
- const char *__builtin_FILE_NAME(); // Clang only
- const char *__builtin_FUNCTION();
- const char *__builtin_FUNCSIG(); // Microsoft
- unsigned __builtin_LINE();
- unsigned __builtin_COLUMN(); // Clang only
- const std::source_location::__impl *__builtin_source_location();
+```c
+const char *__builtin_FILE();
+const char *__builtin_FILE_NAME(); // Clang only
+const char *__builtin_FUNCTION();
+const char *__builtin_FUNCSIG(); // Microsoft
+unsigned __builtin_LINE();
+unsigned __builtin_COLUMN(); // Clang only
+const std::source_location::__impl *__builtin_source_location();
+```
**Example of use**:
-.. code-block:: c++
-
- void my_assert(bool pred, int line = __builtin_LINE(), // Captures line of caller
- const char* file = __builtin_FILE(),
- const char* function = __builtin_FUNCTION()) {
- if (pred) return;
- printf("%s:%d assertion failed in function %s\n", file, line, function);
- std::abort();
- }
-
- struct MyAggregateType {
- int x;
- int line = __builtin_LINE(); // captures line where aggregate initialization occurs
- };
- static_assert(MyAggregateType{42}.line == __LINE__);
-
- struct MyClassType {
- int line = __builtin_LINE(); // captures line of the constructor used during initialization
- constexpr MyClassType(int) { assert(line == __LINE__); }
- };
+```c++
+void my_assert(bool pred, int line = __builtin_LINE(), // Captures line of caller
+ const char* file = __builtin_FILE(),
+ const char* function = __builtin_FUNCTION()) {
+ if (pred) return;
+ printf("%s:%d assertion failed in function %s\n", file, line, function);
+ std::abort();
+}
+
+struct MyAggregateType {
+ int x;
+ int line = __builtin_LINE(); // captures line where aggregate initialization occurs
+};
+static_assert(MyAggregateType{42}.line == __LINE__);
+
+struct MyClassType {
+ int line = __builtin_LINE(); // captures line of the constructor used during initialization
+ constexpr MyClassType(int) { assert(line == __LINE__); }
+};
+```
**Description**:
-The builtins ``__builtin_LINE``, ``__builtin_FUNCTION``, ``__builtin_FUNCSIG``,
-``__builtin_FILE`` and ``__builtin_FILE_NAME`` return the values, at the
-"invocation point", for ``__LINE__``, ``__FUNCTION__``, ``__FUNCSIG__``,
-``__FILE__`` and ``__FILE_NAME__`` respectively. ``__builtin_COLUMN`` similarly
+The builtins `__builtin_LINE`, `__builtin_FUNCTION`, `__builtin_FUNCSIG`,
+`__builtin_FILE` and `__builtin_FILE_NAME` return the values, at the
+"invocation point", for `__LINE__`, `__FUNCTION__`, `__FUNCSIG__`,
+`__FILE__` and `__FILE_NAME__` respectively. `__builtin_COLUMN` similarly
returns the column, though there is no corresponding macro. These builtins are
constant expressions.
@@ -5476,24 +5132,22 @@ default member initializer, the invocation point is the location of the
constructor or aggregate initialization used to create the object. Otherwise
the invocation point is the same as the location of the builtin.
-When the invocation point of ``__builtin_FUNCTION`` is not a function scope, the
+When the invocation point of `__builtin_FUNCTION` is not a function scope, the
empty string is returned.
-The builtin ``__builtin_COLUMN`` returns the offset from the start of the line,
-beginning from column 1. `This may differ from other implementations.
-<https://eel.is/c++draft/support.srcloc#tab:support.srcloc.current-row-3-column-2-sentence-2>`_
+The builtin `__builtin_COLUMN` returns the offset from the start of the line,
+beginning from column 1. [This may differ from other implementations.](https://eel.is/c++draft/support.srcloc#tab:support.srcloc.current-row-3-column-2-sentence-2)
-The builtin ``__builtin_source_location`` returns a pointer to constant static
-data of type ``std::source_location::__impl``. This type must have already been
-defined, and must contain exactly four fields: ``const char *_M_file_name``,
-``const char *_M_function_name``, ``<any-integral-type> _M_line``, and
-``<any-integral-type> _M_column``. The fields will be populated in the same
-manner as the above four builtins, except that ``_M_function_name`` is populated
-with ``__PRETTY_FUNCTION__`` rather than ``__FUNCTION__``.
+The builtin `__builtin_source_location` returns a pointer to constant static
+data of type `std::source_location::__impl`. This type must have already been
+defined, and must contain exactly four fields: `const char *_M_file_name`,
+`const char *_M_function_name`, `<any-integral-type> _M_line`, and
+`<any-integral-type> _M_column`. The fields will be populated in the same
+manner as the above four builtins, except that `_M_function_name` is populated
+with `__PRETTY_FUNCTION__` rather than `__FUNCTION__`.
+### Alignment builtins
-Alignment builtins
-------------------
Clang provides builtins to support checking and adjusting alignment of
pointers and integers.
These builtins can be used to avoid relying on implementation-defined behavior
@@ -5503,115 +5157,107 @@ arithmetic, they can perform semantic checking on the alignment value.
**Syntax**:
-.. code-block:: c
-
- Type __builtin_align_up(Type value, size_t alignment);
- Type __builtin_align_down(Type value, size_t alignment);
- bool __builtin_is_aligned(Type value, size_t alignment);
-
+```c
+Type __builtin_align_up(Type value, size_t alignment);
+Type __builtin_align_down(Type value, size_t alignment);
+bool __builtin_is_aligned(Type value, size_t alignment);
+```
**Example of use**:
-.. code-block:: c++
-
- char* global_alloc_buffer;
- void* my_aligned_allocator(size_t alloc_size, size_t alignment) {
- char* result = __builtin_align_up(global_alloc_buffer, alignment);
- // result now contains the value of global_alloc_buffer rounded up to the
- // next multiple of alignment.
- global_alloc_buffer = result + alloc_size;
- return result;
- }
-
- void* get_start_of_page(void* ptr) {
- return __builtin_align_down(ptr, PAGE_SIZE);
- }
-
- void example(char* buffer) {
- if (__builtin_is_aligned(buffer, 64)) {
- do_fast_aligned_copy(buffer);
- } else {
- do_unaligned_copy(buffer);
- }
- }
-
- // In addition to pointers, the builtins can also be used on integer types
- // and are evaluatable inside constant expressions.
- static_assert(__builtin_align_up(123, 64) == 128, "");
- static_assert(__builtin_align_down(123u, 64) == 64u, "");
- static_assert(!__builtin_is_aligned(123, 64), "");
+```c++
+char* global_alloc_buffer;
+void* my_aligned_allocator(size_t alloc_size, size_t alignment) {
+ char* result = __builtin_align_up(global_alloc_buffer, alignment);
+ // result now contains the value of global_alloc_buffer rounded up to the
+ // next multiple of alignment.
+ global_alloc_buffer = result + alloc_size;
+ return result;
+}
+
+void* get_start_of_page(void* ptr) {
+ return __builtin_align_down(ptr, PAGE_SIZE);
+}
+
+void example(char* buffer) {
+ if (__builtin_is_aligned(buffer, 64)) {
+ do_fast_aligned_copy(buffer);
+ } else {
+ do_unaligned_copy(buffer);
+ }
+}
+// In addition to pointers, the builtins can also be used on integer types
+// and are evaluatable inside constant expressions.
+static_assert(__builtin_align_up(123, 64) == 128, "");
+static_assert(__builtin_align_down(123u, 64) == 64u, "");
+static_assert(!__builtin_is_aligned(123, 64), "");
+```
**Description**:
-The builtins ``__builtin_align_up``, ``__builtin_align_down``, return their
+The builtins `__builtin_align_up`, `__builtin_align_down`, return their
first argument aligned up/down to the next multiple of the second argument.
If the value is already sufficiently aligned, it is returned unchanged.
-The builtin ``__builtin_is_aligned`` returns whether the first argument is
+The builtin `__builtin_is_aligned` returns whether the first argument is
aligned to a multiple of the second argument.
All of these builtins expect the alignment to be expressed as a number of bytes.
These builtins can be used for all integer types as well as (non-function)
pointer types. For pointer types, these builtins operate in terms of the integer
address of the pointer and return a new pointer of the same type (including
-qualifiers such as ``const``) with an adjusted address.
+qualifiers such as `const`) with an adjusted address.
When aligning pointers up or down, the resulting value must be within the same
underlying allocation or one past the end (see C17 6.5.6p8, C++ [expr.add]).
This means that arbitrary integer values stored in pointer-type variables must
not be passed to these builtins. For those use cases, the builtins can still be
-used, but the operation must be performed on the pointer cast to ``uintptr_t``.
+used, but the operation must be performed on the pointer cast to `uintptr_t`.
If Clang can determine that the alignment is not a power of two at compile time,
it will result in a compilation failure. If the alignment argument is not a
power of two at run time, the behavior of these builtins is undefined.
-Non-standard C++11 Attributes
-=============================
+## Non-standard C++11 Attributes
-Clang's non-standard C++11 attributes live in the ``clang`` attribute
+Clang's non-standard C++11 attributes live in the `clang` attribute
namespace.
-Clang supports GCC's ``gnu`` attribute namespace. All GCC attributes which
-are accepted with the ``__attribute__((foo))`` syntax are also accepted as
-``[[gnu::foo]]``. This only extends to attributes which are specified by GCC
-(see the list of `GCC function attributes
-<https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_, `GCC variable
-attributes <https://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html>`_, and
-`GCC type attributes
-<https://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html>`_). As with the GCC
+Clang supports GCC's `gnu` attribute namespace. All GCC attributes which
+are accepted with the `__attribute__((foo))` syntax are also accepted as
+`[[gnu::foo]]`. This only extends to attributes which are specified by GCC
+(see the list of [GCC function attributes](https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html), [GCC variable
+attributes](https://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html), and
+[GCC type attributes](https://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html)). As with the GCC
implementation, these attributes must appertain to the *declarator-id* in a
declaration, which means they must go either at the start of the declaration or
immediately after the name being declared.
-For example, this applies the GNU ``unused`` attribute to ``a`` and ``f``, and
-also applies the GNU ``noreturn`` attribute to ``f``.
+For example, this applies the GNU `unused` attribute to `a` and `f`, and
+also applies the GNU `noreturn` attribute to `f`.
Examples:
.. code-block:: c++
- [[gnu::unused]] int a, f [[gnu::noreturn]] ();
+> \[[gnu::unused]\] int a, f \[[gnu::noreturn]\] ();
-Target-Specific Extensions
-==========================
+## Target-Specific Extensions
Clang supports some language features conditionally on some targets.
-AMDGPU Language Extensions
---------------------------
+### AMDGPU Language Extensions
-__builtin_amdgcn_fence
-^^^^^^^^^^^^^^^^^^^^^^
+#### \_\_builtin_amdgcn_fence
-``__builtin_amdgcn_fence`` emits a fence.
+`__builtin_amdgcn_fence` emits a fence.
-* ``unsigned`` atomic ordering, e.g., ``__ATOMIC_ACQUIRE``
-* ``const char *`` synchronization scope, e.g., ``workgroup``
-* Zero or more ``const char *`` address spaces names.
+- `unsigned` atomic ordering, e.g., `__ATOMIC_ACQUIRE`
+- `const char *` synchronization scope, e.g., `workgroup`
+- Zero or more `const char *` address spaces names.
The address spaces arguments must be one of the following string literals:
-* ``"local"``
-* ``"global"``
+- `"local"`
+- `"global"`
If one or more address space name are provided, the code generator will attempt
to emit potentially faster instructions that order access to at least those
@@ -5621,117 +5267,116 @@ to fence more aggressively.
If no address spaces names are provided, all address spaces are fenced.
-.. code-block:: c++
-
- // Fence all address spaces.
- __builtin_amdgcn_fence(__ATOMIC_SEQ_CST, "workgroup");
- __builtin_amdgcn_fence(__ATOMIC_ACQUIRE, "agent");
+```c++
+// Fence all address spaces.
+__builtin_amdgcn_fence(__ATOMIC_SEQ_CST, "workgroup");
+__builtin_amdgcn_fence(__ATOMIC_ACQUIRE, "agent");
- // Fence only requested address spaces.
- __builtin_amdgcn_fence(__ATOMIC_SEQ_CST, "workgroup", "local")
- __builtin_amdgcn_fence(__ATOMIC_SEQ_CST, "workgroup", "local", "global")
+// Fence only requested address spaces.
+__builtin_amdgcn_fence(__ATOMIC_SEQ_CST, "workgroup", "local")
+__builtin_amdgcn_fence(__ATOMIC_SEQ_CST, "workgroup", "local", "global")
+```
-__builtin_amdgcn_processor_is and __builtin_amdgcn_is_invocable
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### \_\_builtin_amdgcn_processor_is and \_\_builtin_amdgcn_is_invocable
-``__builtin_amdgcn_processor_is`` and ``__builtin_amdgcn_is_invocable`` provide
+`__builtin_amdgcn_processor_is` and `__builtin_amdgcn_is_invocable` provide
a functional mechanism for programatically querying:
-* the identity of the current target processor;
-* the capability of the current target processor to invoke a particular builtin.
+- the identity of the current target processor;
+- the capability of the current target processor to invoke a particular builtin.
**Syntax**:
-.. code-block:: c
-
- __amdgpu_feature_predicate_t __builtin_amdgcn_processor_is(const char*);
- __amdgpu_feature_predicate_t __builtin_amdgcn_is_invocable(builtin_name);
+```c
+__amdgpu_feature_predicate_t __builtin_amdgcn_processor_is(const char*);
+__amdgpu_feature_predicate_t __builtin_amdgcn_is_invocable(builtin_name);
+```
**Example of use**:
-.. code-block:: c++
-
- if (__builtin_amdgcn_processor_is("gfx1201") ||
- __builtin_amdgcn_is_invocable(__builtin_amdgcn_s_sleep_var))
- __builtin_amdgcn_s_sleep_var(x);
+```c++
+if (__builtin_amdgcn_processor_is("gfx1201") ||
+ __builtin_amdgcn_is_invocable(__builtin_amdgcn_s_sleep_var))
+ __builtin_amdgcn_s_sleep_var(x);
- if (!__builtin_amdgcn_processor_is("gfx906"))
- __builtin_amdgcn_s_wait_event_export_ready();
- else if (__builtin_amdgcn_processor_is("gfx1010") ||
- __builtin_amdgcn_processor_is("gfx1101"))
- __builtin_amdgcn_s_ttracedata_imm(1);
+if (!__builtin_amdgcn_processor_is("gfx906"))
+ __builtin_amdgcn_s_wait_event_export_ready();
+else if (__builtin_amdgcn_processor_is("gfx1010") ||
+ __builtin_amdgcn_processor_is("gfx1101"))
+ __builtin_amdgcn_s_ttracedata_imm(1);
- while (__builtin_amdgcn_processor_is("gfx1101")) *p += x;
+while (__builtin_amdgcn_processor_is("gfx1101")) *p += x;
- do {
- break;
- } while (__builtin_amdgcn_processor_is("gfx1010"));
+do {
+ break;
+} while (__builtin_amdgcn_processor_is("gfx1010"));
- for (; __builtin_amdgcn_processor_is("gfx1201"); ++*p) break;
+for (; __builtin_amdgcn_processor_is("gfx1201"); ++*p) break;
- if (__builtin_amdgcn_is_invocable(__builtin_amdgcn_s_wait_event_export_ready))
- __builtin_amdgcn_s_wait_event_export_ready();
- else if (__builtin_amdgcn_is_invocable(__builtin_amdgcn_s_ttracedata_imm))
- __builtin_amdgcn_s_ttracedata_imm(1);
+if (__builtin_amdgcn_is_invocable(__builtin_amdgcn_s_wait_event_export_ready))
+ __builtin_amdgcn_s_wait_event_export_ready();
+else if (__builtin_amdgcn_is_invocable(__builtin_amdgcn_s_ttracedata_imm))
+ __builtin_amdgcn_s_ttracedata_imm(1);
- do {
- break;
- } while (
- __builtin_amdgcn_is_invocable(__builtin_amdgcn_global_load_tr_b64_i32));
+do {
+ break;
+} while (
+ __builtin_amdgcn_is_invocable(__builtin_amdgcn_global_load_tr_b64_i32));
- for (; __builtin_amdgcn_is_invocable(__builtin_amdgcn_permlane64); ++*p)
- break;
+for (; __builtin_amdgcn_is_invocable(__builtin_amdgcn_permlane64); ++*p)
+ break;
+```
**Description**:
-The builtins return a value of type ``__amdgpu_feature_predicate_t``, which is a
+The builtins return a value of type `__amdgpu_feature_predicate_t`, which is a
target specific type that behaves as if its C++ definition was the following:
-.. code-block:: c++
+```c++
+struct __amdgpu_feature_predicate_t {
+ __amdgpu_feature_predicate_t() = delete;
+ __amdgpu_feature_predicate_t(const __amdgpu_feature_predicate_t&) = delete;
+ __amdgpu_feature_predicate_t(__amdgpu_feature_predicate_t&&) = delete;
- struct __amdgpu_feature_predicate_t {
- __amdgpu_feature_predicate_t() = delete;
- __amdgpu_feature_predicate_t(const __amdgpu_feature_predicate_t&) = delete;
- __amdgpu_feature_predicate_t(__amdgpu_feature_predicate_t&&) = delete;
-
- explicit
- operator bool() const noexcept;
- };
+ explicit
+ operator bool() const noexcept;
+};
+```
The builtins can be used in C as well, wherein the
-``__amdgpu_feature_predicate_t`` type behaves as an opaque, forward declared
-type with conditional automated conversion to ``_Bool`` when used as the
+`__amdgpu_feature_predicate_t` type behaves as an opaque, forward declared
+type with conditional automated conversion to `_Bool` when used as the
predicate argument to a control structure:
-.. code-block:: c
+```c
+struct __amdgpu_feature_predicate_t ret(); // Error
+void arg(struct __amdgpu_feature_predicate_t); // Error
+void local() {
+ struct __amdgpu_feature_predicate_t x; // Error
+ struct __amdgpu_feature_predicate_t y =
+ __builtin_amdgcn_processor_is("gfx900"); // Error
+}
+void valid_use() {
+ _Bool x = (_Bool)__builtin_amdgcn_processor_is("gfx900"); // OK
+ if (__builtin_amdgcn_processor_is("gfx900")) // Implicit cast to _Bool
+ return;
+ for (; __builtin_amdgcn_processor_is("gfx900");) // Implicit cast to _Bool
+ break;
+ while (__builtin_amdgcn_processor_is("gfx900")) // Implicit cast to _Bool
+ break;
+ do {
+ break;
+ } while (__builtin_amdgcn_processor_is("gfx900")); // Implicit cast to _Bool
- struct __amdgpu_feature_predicate_t ret(); // Error
- void arg(struct __amdgpu_feature_predicate_t); // Error
- void local() {
- struct __amdgpu_feature_predicate_t x; // Error
- struct __amdgpu_feature_predicate_t y =
- __builtin_amdgcn_processor_is("gfx900"); // Error
- }
- void valid_use() {
- _Bool x = (_Bool)__builtin_amdgcn_processor_is("gfx900"); // OK
- if (__builtin_amdgcn_processor_is("gfx900")) // Implicit cast to _Bool
- return;
- for (; __builtin_amdgcn_processor_is("gfx900");) // Implicit cast to _Bool
- break;
- while (__builtin_amdgcn_processor_is("gfx900")) // Implicit cast to _Bool
- break;
- do {
- break;
- } while (__builtin_amdgcn_processor_is("gfx900")); // Implicit cast to _Bool
-
- __builtin_amdgcn_processor_is("gfx900") ? x : !x;
- }
+ __builtin_amdgcn_processor_is("gfx900") ? x : !x;
+}
+```
The boolean interpretation of the predicate values returned by the builtins:
-* indicates whether the current target matches the argument; the argument MUST
+- indicates whether the current target matches the argument; the argument MUST
be a string literal and a valid AMDGPU target
-* indicates whether the builtin function passed as the argument can be invoked
+- indicates whether the builtin function passed as the argument can be invoked
by the current target; the argument MUST be either a generic or AMDGPU
specific builtin name
@@ -5745,130 +5390,119 @@ the latter's identity and features. Thus, it is possible to author high-level
code, in e.g. HIP, that is target adaptive in a dynamic fashion, contrary to
macro based mechanisms.
-__builtin_amdgcn_ballot_w{32,64}
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### \_\_builtin_amdgcn_ballot_w{32,64}
-``__builtin_amdgcn_ballot_w{32,64}`` returns a bitmask that contains its
+`__builtin_amdgcn_ballot_w{32,64}` returns a bitmask that contains its
boolean argument as a bit for every lane of the current wave that is currently
active (i.e., that is converged with the executing thread), and a 0 bit for
every lane that is not active.
The result is uniform, i.e., it is the same in every active thread of the wave.
-__builtin_amdgcn_inverse_ballot_w{32,64}
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### \_\_builtin_amdgcn_inverse_ballot_w{32,64}
-Given a wave-uniform bitmask, ``__builtin_amdgcn_inverse_ballot_w{32,64}(mask)``
+Given a wave-uniform bitmask, `__builtin_amdgcn_inverse_ballot_w{32,64}(mask)`
returns the bit at the position of the current lane. It is almost equivalent to
-``(mask & (1 << lane_id)) != 0``, except that its behavior is only defined if
+`(mask & (1 << lane_id)) != 0`, except that its behavior is only defined if
the given mask has the same value for all active lanes of the current wave.
-
-__builtin_amdgcn_av_{load,store}_b128
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### \_\_builtin_amdgcn_av\_{load,store}\_b128
Signature:
-.. code-block:: c
-
- typedef __attribute__((__vector_size__(4 * sizeof(unsigned int)))) unsigned int v4u;
+```c
+typedef __attribute__((__vector_size__(4 * sizeof(unsigned int)))) unsigned int v4u;
- v4u __builtin_amdgcn_av_load_b128(v4u *src, int scope);
+v4u __builtin_amdgcn_av_load_b128(v4u *src, int scope);
- void __builtin_amdgcn_av_store_b128(v4u *dst, v4u data, int scope);
+void __builtin_amdgcn_av_store_b128(v4u *dst, v4u data, int scope);
+```
Load or store a vector of 4 unsigned integers from or to memory with cache
-behavior specified by ``scope``, which is one of the ``__MEMORY_SCOPE_*`` macros
-defined for :ref:`scoped atomic builtins<langext-__c11_atomic>`.
+behavior specified by `scope`, which is one of the `__MEMORY_SCOPE_*` macros
+defined for {ref}`scoped atomic builtins<langext-__c11_atomic>`.
The pointer argument must point to the global or generic address space.
These builtins are supported on gfx9, gfx10, gfx11, and gfx12 targets.
-They map to the LLVM intrinsics ``llvm.amdgcn.av.load.b128`` and
-``llvm.amdgcn.av.store.b128`` documented in `User Guide for AMDGPU Backend
-<https://llvm.org/docs/AMDGPUUsage.html>`_.
+They map to the LLVM intrinsics `llvm.amdgcn.av.load.b128` and
+`llvm.amdgcn.av.store.b128` documented in [User Guide for AMDGPU Backend](https://llvm.org/docs/AMDGPUUsage.html).
-ARM/AArch64 Language Extensions
--------------------------------
+### ARM/AArch64 Language Extensions
-Memory Barrier Intrinsics
-^^^^^^^^^^^^^^^^^^^^^^^^^
-Clang implements the ``__dmb``, ``__dsb`` and ``__isb`` intrinsics as defined
-in the `Arm C Language Extensions
-<https://github.com/ARM-software/acle/releases>`_.
+#### Memory Barrier Intrinsics
+
+Clang implements the `__dmb`, `__dsb` and `__isb` intrinsics as defined
+in the [Arm C Language Extensions](https://github.com/ARM-software/acle/releases).
Note that these intrinsics are implemented as motion barriers that block
reordering of memory accesses and side effect instructions. Other instructions
like simple arithmetic may be reordered around the intrinsic. If you expect to
have no reordering at all, use inline assembly instead.
-Pointer Authentication
-^^^^^^^^^^^^^^^^^^^^^^
-See :doc:`PointerAuthentication`.
+#### Pointer Authentication
+
+See {doc}`PointerAuthentication`.
-X86/X86-64 Language Extensions
-------------------------------
+### X86/X86-64 Language Extensions
The X86 backend has these language extensions:
-Memory references to specified segments
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### Memory references to specified segments
Annotating a pointer with address space #256 causes it to be code generated
relative to the X86 GS segment register, address space #257 causes it to be
relative to the X86 FS segment, and address space #258 causes it to be
-relative to the X86 SS segment. Note that this is a very very low-level
+relative to the X86 SS segment. Note that this is a very very low-level
feature that should only be used if you know what you're doing (for example in
an OS kernel).
Here is an example:
-.. code-block:: c++
-
- #define GS_RELATIVE __attribute__((address_space(256)))
- int foo(int GS_RELATIVE *P) {
- return *P;
- }
+```c++
+#define GS_RELATIVE __attribute__((address_space(256)))
+int foo(int GS_RELATIVE *P) {
+ return *P;
+}
+```
Which compiles to (on X86-32):
-.. code-block:: gas
-
- _foo:
- movl 4(%esp), %eax
- movl %gs:(%eax), %eax
- ret
+```gas
+_foo:
+ movl 4(%esp), %eax
+ movl %gs:(%eax), %eax
+ ret
+```
-You can also use the GCC compatibility macros ``__seg_fs`` and ``__seg_gs`` for
-the same purpose. The preprocessor symbols ``__SEG_FS`` and ``__SEG_GS``
+You can also use the GCC compatibility macros `__seg_fs` and `__seg_gs` for
+the same purpose. The preprocessor symbols `__SEG_FS` and `__SEG_GS`
indicate their support.
-PowerPC Language Extensions
----------------------------
+### PowerPC Language Extensions
-Set the Floating Point Rounding Mode
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-PowerPC64/PowerPC64le supports the builtin function ``__builtin_setrnd`` to set
+#### Set the Floating Point Rounding Mode
+
+PowerPC64/PowerPC64le supports the builtin function `__builtin_setrnd` to set
the floating point rounding mode. This function will use the least significant
two bits of integer argument to set the floating point rounding mode.
-.. code-block:: c++
-
- double __builtin_setrnd(int mode);
+```c++
+double __builtin_setrnd(int mode);
+```
The effective values for mode are:
- - 0 - round to nearest
- - 1 - round to zero
- - 2 - round to +infinity
- - 3 - round to -infinity
+> - 0 - round to nearest
+> - 1 - round to zero
+> - 2 - round to +infinity
+> - 3 - round to -infinity
Note that the mode argument will modulo 4, so if the integer argument is greater
than 3, it will only use the least significant two bits of the mode.
-Namely, ``__builtin_setrnd(102))`` is equal to ``__builtin_setrnd(2)``.
+Namely, `__builtin_setrnd(102))` is equal to `__builtin_setrnd(2)`.
-PowerPC cache builtins
-^^^^^^^^^^^^^^^^^^^^^^
+#### PowerPC cache builtins
The PowerPC architecture specifies instructions implementing cache operations.
Clang provides builtins that give direct programmer access to these cache
@@ -5876,99 +5510,93 @@ instructions.
Currently the following builtins are implemented in clang:
-``__builtin_dcbf`` copies the contents of a modified block from the data cache
+`__builtin_dcbf` copies the contents of a modified block from the data cache
to main memory and flushes the copy from the data cache.
**Syntax**:
-.. code-block:: c
-
- void __dcbf(const void* addr); /* Data Cache Block Flush */
+```c
+void __dcbf(const void* addr); /* Data Cache Block Flush */
+```
**Example of Use**:
-.. code-block:: c
+```c
+int a = 1;
+__builtin_dcbf (&a);
+```
- int a = 1;
- __builtin_dcbf (&a);
-
-Extensions for Static Analysis
-==============================
+## Extensions for Static Analysis
Clang supports additional attributes that are useful for documenting program
-invariants and rules for static analysis tools, such as the `Clang Static
-Analyzer <https://clang-analyzer.llvm.org/>`_. These attributes are documented
-in the analyzer's `list of annotations for analysis
-<analyzer/user-docs/Annotations.html>`__.
-
+invariants and rules for static analysis tools, such as the [Clang Static
+Analyzer](https://clang-analyzer.llvm.org/). These attributes are documented
+in the analyzer's [list of annotations for analysis](analyzer/user-docs/Annotations.html).
-Extensions for Dynamic Analysis
-===============================
+## Extensions for Dynamic Analysis
-Use ``__has_feature(address_sanitizer)`` to check if the code is being built
-with :doc:`AddressSanitizer`.
+Use `__has_feature(address_sanitizer)` to check if the code is being built
+with {doc}`AddressSanitizer`.
-Use ``__has_feature(thread_sanitizer)`` to check if the code is being built
-with :doc:`ThreadSanitizer`.
+Use `__has_feature(thread_sanitizer)` to check if the code is being built
+with {doc}`ThreadSanitizer`.
-Use ``__has_feature(memory_sanitizer)`` to check if the code is being built
-with :doc:`MemorySanitizer`.
+Use `__has_feature(memory_sanitizer)` to check if the code is being built
+with {doc}`MemorySanitizer`.
-Use ``__has_feature(dataflow_sanitizer)`` to check if the code is being built
-with :doc:`DataFlowSanitizer`.
+Use `__has_feature(dataflow_sanitizer)` to check if the code is being built
+with {doc}`DataFlowSanitizer`.
-Use ``__has_feature(safe_stack)`` to check if the code is being built
-with :doc:`SafeStack`.
+Use `__has_feature(safe_stack)` to check if the code is being built
+with {doc}`SafeStack`.
-
-Extensions for selectively disabling optimization
-=================================================
+## Extensions for selectively disabling optimization
Clang provides a mechanism for selectively disabling optimizations in functions
and methods.
To disable optimizations in a single function definition, the GNU-style or C++11
-non-standard attribute ``optnone`` can be used.
-
-.. code-block:: c++
-
- // The following functions will not be optimized.
- // GNU-style attribute
- __attribute__((optnone)) int foo() {
- // ... code
- }
- // C++11 attribute
- [[clang::optnone]] int bar() {
- // ... code
- }
+non-standard attribute `optnone` can be used.
+
+```c++
+// The following functions will not be optimized.
+// GNU-style attribute
+__attribute__((optnone)) int foo() {
+ // ... code
+}
+// C++11 attribute
+[[clang::optnone]] int bar() {
+ // ... code
+}
+```
To facilitate disabling optimization for a range of function definitions, a
-range-based pragma is provided. Its syntax is ``#pragma clang optimize``
-followed by ``off`` or ``on``.
+range-based pragma is provided. Its syntax is `#pragma clang optimize`
+followed by `off` or `on`.
-All function definitions in the region between an ``off`` and the following
-``on`` will be decorated with the ``optnone`` attribute unless doing so would
+All function definitions in the region between an `off` and the following
+`on` will be decorated with the `optnone` attribute unless doing so would
conflict with explicit attributes already present on the function (e.g., the
ones that control inlining).
-.. code-block:: c++
-
- #pragma clang optimize off
- // This function will be decorated with optnone.
- int foo() {
- // ... code
- }
-
- // optnone conflicts with always_inline, so bar() will not be decorated.
- __attribute__((always_inline)) int bar() {
- // ... code
- }
- #pragma clang optimize on
-
-If no ``on`` is found to close an ``off`` region, the end of the region is the
+```c++
+#pragma clang optimize off
+// This function will be decorated with optnone.
+int foo() {
+ // ... code
+}
+
+// optnone conflicts with always_inline, so bar() will not be decorated.
+__attribute__((always_inline)) int bar() {
+ // ... code
+}
+#pragma clang optimize on
+```
+
+If no `on` is found to close an `off` region, the end of the region is the
end of the compilation unit.
-Note that a stray ``#pragma clang optimize on`` does not selectively enable
+Note that a stray `#pragma clang optimize on` does not selectively enable
additional optimizations when compiling at low optimization levels. This feature
can only be used to selectively disable optimizations.
@@ -5976,56 +5604,57 @@ The pragma has an effect on functions only at the point of their definition; for
function templates, this means that the state of the pragma at the point of an
instantiation is not necessarily relevant. Consider the following example:
-.. code-block:: c++
-
- template<typename T> T twice(T t) {
- return 2 * t;
- }
-
- #pragma clang optimize off
- template<typename T> T thrice(T t) {
- return 3 * t;
- }
-
- int container(int a, int b) {
- return twice(a) + thrice(b);
- }
- #pragma clang optimize on
-
-In this example, the definition of the template function ``twice`` is outside
-the pragma region, whereas the definition of ``thrice`` is inside the region.
-The ``container`` function is also in the region and will not be optimized, but
-it causes the instantiation of ``twice`` and ``thrice`` with an ``int`` type; of
-these two instantiations, ``twice`` will be optimized (because its definition
-was outside the region) and ``thrice`` will not be optimized.
+```c++
+template<typename T> T twice(T t) {
+ return 2 * t;
+}
+
+#pragma clang optimize off
+template<typename T> T thrice(T t) {
+ return 3 * t;
+}
+
+int container(int a, int b) {
+ return twice(a) + thrice(b);
+}
+#pragma clang optimize on
+```
+
+In this example, the definition of the template function `twice` is outside
+the pragma region, whereas the definition of `thrice` is inside the region.
+The `container` function is also in the region and will not be optimized, but
+it causes the instantiation of `twice` and `thrice` with an `int` type; of
+these two instantiations, `twice` will be optimized (because its definition
+was outside the region) and `thrice` will not be optimized.
Clang also implements MSVC's range-based pragma,
-``#pragma optimize("[optimization-list]", on | off)``. At the moment, Clang only
-supports an empty optimization list, whereas MSVC supports the arguments, ``s``,
-``g``, ``t``, and ``y``. Currently, the implementation of ``pragma optimize`` behaves
-the same as ``#pragma clang optimize``. All functions
-between ``off`` and ``on`` will be decorated with the ``optnone`` attribute.
-
-.. code-block:: c++
-
- #pragma optimize("", off)
- // This function will be decorated with optnone.
- void f1() {}
-
- #pragma optimize("", on)
- // This function will be optimized with whatever was specified on
- // the commandline.
- void f2() {}
-
- // This will warn with Clang's current implementation.
- #pragma optimize("g", on)
- void f3() {}
-
-For MSVC, an empty optimization list and ``off`` parameter will turn off
-all optimizations, ``s``, ``g``, ``t``, and ``y``. An empty optimization and
-``on`` parameter will reset the optimizations to the ones specified on the
+`#pragma optimize("[optimization-list]", on | off)`. At the moment, Clang only
+supports an empty optimization list, whereas MSVC supports the arguments, `s`,
+`g`, `t`, and `y`. Currently, the implementation of `pragma optimize` behaves
+the same as `#pragma clang optimize`. All functions
+between `off` and `on` will be decorated with the `optnone` attribute.
+
+```c++
+#pragma optimize("", off)
+// This function will be decorated with optnone.
+void f1() {}
+
+#pragma optimize("", on)
+// This function will be optimized with whatever was specified on
+// the commandline.
+void f2() {}
+
+// This will warn with Clang's current implementation.
+#pragma optimize("g", on)
+void f3() {}
+```
+
+For MSVC, an empty optimization list and `off` parameter will turn off
+all optimizations, `s`, `g`, `t`, and `y`. An empty optimization and
+`on` parameter will reset the optimizations to the ones specified on the
commandline.
+```{eval-rst}
.. list-table:: Parameters (unsupported by Clang)
* - Parameter
@@ -6036,11 +5665,11 @@ commandline.
- Short or fast sequences of machine code
* - y
- Enable frame pointers
+```
-Extensions for loop hint optimizations
-======================================
+## Extensions for loop hint optimizations
-The ``#pragma clang loop`` directive is used to specify hints for optimizing the
+The `#pragma clang loop` directive is used to specify hints for optimizing the
subsequent for, while, do-while, or c++11 range-based for loop. The directive
provides options for vectorization, interleaving, predication, unrolling and
distribution. Loop hints can be specified before any loop and will be ignored if
@@ -6048,14 +5677,13 @@ the optimization is not safe to apply.
There are loop hints that control transformations (e.g., vectorization, loop
unrolling) and there are loop hints that set transformation options (e.g.
-``vectorize_width``, ``unroll_count``). Pragmas setting transformation options
+`vectorize_width`, `unroll_count`). Pragmas setting transformation options
imply the transformation is enabled, as if it were enabled via the corresponding
-transformation pragma (e.g., ``vectorize(enable)``). If the transformation is
-disabled (e.g., ``vectorize(disable)``), that takes precedence over
+transformation pragma (e.g., `vectorize(enable)`). If the transformation is
+disabled (e.g., `vectorize(disable)`), that takes precedence over
transformations option pragmas implying that transformation.
-Vectorization, Interleaving, and Predication
---------------------------------------------
+### Vectorization, Interleaving, and Predication
A vectorized loop performs multiple iterations of the original loop
in parallel using vector instructions. The instruction set of the target
@@ -6070,61 +5698,60 @@ such as multiple execution units and out-of-order execution. The vectorizer uses
a cost model that depends on the register pressure and generated code size to
select the interleaving count.
-Vectorization is enabled by ``vectorize(enable)`` and interleaving is enabled
-by ``interleave(enable)``. This is useful when compiling with ``-Os`` to
+Vectorization is enabled by `vectorize(enable)` and interleaving is enabled
+by `interleave(enable)`. This is useful when compiling with `-Os` to
manually enable vectorization or interleaving.
-.. code-block:: c++
-
- #pragma clang loop vectorize(enable)
- #pragma clang loop interleave(enable)
- for(...) {
- ...
- }
+```c++
+#pragma clang loop vectorize(enable)
+#pragma clang loop interleave(enable)
+for(...) {
+ ...
+}
+```
The vector width is specified by
-``vectorize_width(_value_[, fixed|scalable])``, where _value_ is a positive
+`vectorize_width(_value_[, fixed|scalable])`, where \_value\_ is a positive
integer and the type of vectorization can be specified with an optional
second parameter. The default for the second parameter is 'fixed' and
refers to fixed width vectorization, whereas 'scalable' indicates the
compiler should use scalable vectors instead. Another use of vectorize_width
-is ``vectorize_width(fixed|scalable)`` where the user can hint at the type
+is `vectorize_width(fixed|scalable)` where the user can hint at the type
of vectorization to use without specifying the exact width. In both variants
of the pragma the vectorizer may decide to fall back on fixed width
vectorization if the target does not support scalable vectors.
-The interleave count is specified by ``interleave_count(_value_)``, where
-_value_ is a positive integer. This is useful for specifying the optimal
+The interleave count is specified by `interleave_count(_value_)`, where
+\_value\_ is a positive integer. This is useful for specifying the optimal
width/count of the set of target architectures supported by your application.
-.. code-block:: c++
-
- #pragma clang loop vectorize_width(2)
- #pragma clang loop interleave_count(2)
- for(...) {
- ...
- }
+```c++
+#pragma clang loop vectorize_width(2)
+#pragma clang loop interleave_count(2)
+for(...) {
+ ...
+}
+```
Specifying a width/count of 1 disables the optimization, and is equivalent to
-``vectorize(disable)`` or ``interleave(disable)``.
-
-Vector predication is enabled by ``vectorize_predicate(enable)``, for example:
+`vectorize(disable)` or `interleave(disable)`.
-.. code-block:: c++
+Vector predication is enabled by `vectorize_predicate(enable)`, for example:
- #pragma clang loop vectorize(enable)
- #pragma clang loop vectorize_predicate(enable)
- for(...) {
- ...
- }
+```c++
+#pragma clang loop vectorize(enable)
+#pragma clang loop vectorize_predicate(enable)
+for(...) {
+ ...
+}
+```
This predicates (masks) all instructions in the loop, which allows the scalar
remainder loop (the tail) to be folded into the main vectorized loop. This
might be more efficient when vector predication is efficiently supported by the
target platform.
-Loop Unrolling
---------------
+### Loop Unrolling
Unrolling a loop reduces the loop control overhead and exposes more
opportunities for ILP. Loops can be fully or partially unrolled. Full unrolling
@@ -6133,119 +5760,115 @@ iterations. Full unrolling is only possible if the loop trip count is known at
compile time. Partial unrolling replicates the loop body within the loop and
reduces the trip count.
-If ``unroll(enable)`` is specified the unroller will attempt to fully unroll the
+If `unroll(enable)` is specified the unroller will attempt to fully unroll the
loop if the trip count is known at compile time. If the fully unrolled code size
is greater than an internal limit the loop will be partially unrolled up to this
limit. If the trip count is not known at compile time the loop will be partially
unrolled with a heuristically chosen unroll factor.
-.. code-block:: c++
-
- #pragma clang loop unroll(enable)
- for(...) {
- ...
- }
+```c++
+#pragma clang loop unroll(enable)
+for(...) {
+ ...
+}
+```
-If ``unroll(full)`` is specified the unroller will attempt to fully unroll the
+If `unroll(full)` is specified the unroller will attempt to fully unroll the
loop if the trip count is known at compile time identically to
-``unroll(enable)``. However, with ``unroll(full)`` the loop will not be unrolled
+`unroll(enable)`. However, with `unroll(full)` the loop will not be unrolled
if the loop count is not known at compile time.
-.. code-block:: c++
-
- #pragma clang loop unroll(full)
- for(...) {
- ...
- }
+```c++
+#pragma clang loop unroll(full)
+for(...) {
+ ...
+}
+```
-The unroll count can be specified explicitly with ``unroll_count(_value_)`` where
-_value_ is a positive integer. If this value is greater than the trip count the
+The unroll count can be specified explicitly with `unroll_count(_value_)` where
+\_value\_ is a positive integer. If this value is greater than the trip count the
loop will be fully unrolled. Otherwise the loop is partially unrolled subject
-to the same code size limit as with ``unroll(enable)``.
-
-.. code-block:: c++
+to the same code size limit as with `unroll(enable)`.
- #pragma clang loop unroll_count(8)
- for(...) {
- ...
- }
+```c++
+#pragma clang loop unroll_count(8)
+for(...) {
+ ...
+}
+```
-Unrolling of a loop can be prevented by specifying ``unroll(disable)``.
+Unrolling of a loop can be prevented by specifying `unroll(disable)`.
Loop unroll parameters can be controlled by options
`-mllvm -unroll-count=n` and `-mllvm -pragma-unroll-threshold=n`.
-Loop Distribution
------------------
+### Loop Distribution
-Loop Distribution allows splitting a loop into multiple loops. This is
+Loop Distribution allows splitting a loop into multiple loops. This is
beneficial for example when the entire loop cannot be vectorized but some of the
resulting loops can.
-If ``distribute(enable))`` is specified and the loop has memory dependencies
+If `distribute(enable))` is specified and the loop has memory dependencies
that inhibit vectorization, the compiler will attempt to isolate the offending
-operations into a new loop. This optimization is not enabled by default, only
+operations into a new loop. This optimization is not enabled by default, only
loops marked with the pragma are considered.
-.. code-block:: c++
+```c++
+#pragma clang loop distribute(enable)
+for (i = 0; i < N; ++i) {
+ S1: A[i + 1] = A[i] + B[i];
+ S2: C[i] = D[i] * E[i];
+}
+```
- #pragma clang loop distribute(enable)
- for (i = 0; i < N; ++i) {
- S1: A[i + 1] = A[i] + B[i];
- S2: C[i] = D[i] * E[i];
- }
-
-This loop will be split into two loops between statements S1 and S2. The
+This loop will be split into two loops between statements S1 and S2. The
second loop containing S2 will be vectorized.
Loop Distribution is currently not enabled by default in the optimizer because
-it can hurt performance in some cases. For example, instruction-level
+it can hurt performance in some cases. For example, instruction-level
parallelism could be reduced by sequentializing the execution of the
statements S1 and S2 above.
If Loop Distribution is turned on globally with
-``-mllvm -enable-loop-distribution``, specifying ``distribute(disable)`` can
+`-mllvm -enable-loop-distribution`, specifying `distribute(disable)` can
be used the disable it on a per-loop basis.
-Disable Loop Invariant Code Motion
-----------------------------------
+### Disable Loop Invariant Code Motion
Loop Invariant Code Motion (LICM) moves loop invariant code outside of the loop.
-If ``licm(disable))`` is specified, compiler will skip LICM on the specific loop.
+If `licm(disable))` is specified, compiler will skip LICM on the specific loop.
-.. code-block:: c++
-
- #pragma clang loop licm(disable)
- while (i < Length) {
- List[i] = A[x] * i * 2;
- i++;
- }
+```c++
+#pragma clang loop licm(disable)
+while (i < Length) {
+ List[i] = A[x] * i * 2;
+ i++;
+}
+```
The load for A[x] is loop invariant, it will not be hoisted out of the loop
when LICM is disabled.
-Additional Information
-----------------------
+### Additional Information
For convenience multiple loop hints can be specified on a single line.
-.. code-block:: c++
-
- #pragma clang loop vectorize_width(4) interleave_count(8)
- for(...) {
- ...
- }
+```c++
+#pragma clang loop vectorize_width(4) interleave_count(8)
+for(...) {
+ ...
+}
+```
If an optimization cannot be applied any hints that apply to it will be ignored.
-For example, the hint ``vectorize_width(4)`` is ignored if the loop is not
+For example, the hint `vectorize_width(4)` is ignored if the loop is not
proven safe to vectorize. To identify and diagnose optimization issues use
`-Rpass`, `-Rpass-missed`, and `-Rpass-analysis` command line options. See the
user guide for details.
-Extensions to specify floating-point flags
-====================================================
+## Extensions to specify floating-point flags
-The ``#pragma clang fp`` pragma allows floating-point options to be specified
+The `#pragma clang fp` pragma allows floating-point options to be specified
for a section of the source code. This pragma can only appear at file scope or
at the start of a compound statement (excluding comments). When using within a
compound statement, the pragma is active within the scope of the compound
@@ -6253,182 +5876,180 @@ statement.
Currently, the following settings can be controlled with this pragma:
-``#pragma clang fp reassociate`` allows control over the reassociation
+`#pragma clang fp reassociate` allows control over the reassociation
of floating point expressions. When enabled, this pragma allows the expression
-``x + (y + z)`` to be reassociated as ``(x + y) + z``.
+`x + (y + z)` to be reassociated as `(x + y) + z`.
Reassociation can also occur across multiple statements.
This pragma can be used to disable reassociation when it is otherwise
-enabled for the translation unit with the ``-fassociative-math`` flag.
-The pragma can take two values: ``on`` and ``off``.
-
-.. code-block:: c++
-
- float f(float x, float y, float z)
- {
- // Enable floating point reassociation across statements
- #pragma clang fp reassociate(on)
- float t = x + y;
- float v = t + z;
- }
-
-``#pragma clang fp reciprocal`` allows control over using reciprocal
+enabled for the translation unit with the `-fassociative-math` flag.
+The pragma can take two values: `on` and `off`.
+
+```c++
+float f(float x, float y, float z)
+{
+ // Enable floating point reassociation across statements
+ #pragma clang fp reassociate(on)
+ float t = x + y;
+ float v = t + z;
+}
+```
+
+`#pragma clang fp reciprocal` allows control over using reciprocal
approximations in floating point expressions. When enabled, this
-pragma allows the expression ``x / y`` to be approximated as ``x *
-(1.0 / y)``. This pragma can be used to disable reciprocal
+pragma allows the expression `x / y` to be approximated as `x *
+(1.0 / y)`. This pragma can be used to disable reciprocal
approximation when it is otherwise enabled for the translation unit
-with the ``-freciprocal-math`` flag or other fast-math options. The
-pragma can take two values: ``on`` and ``off``.
-
-.. code-block:: c++
-
- float f(float x, float y)
- {
- // Enable floating point reciprocal approximation
- #pragma clang fp reciprocal(on)
- return x / y;
- }
-
-``#pragma clang fp contract`` specifies whether the compiler should
+with the `-freciprocal-math` flag or other fast-math options. The
+pragma can take two values: `on` and `off`.
+
+```c++
+float f(float x, float y)
+{
+ // Enable floating point reciprocal approximation
+ #pragma clang fp reciprocal(on)
+ return x / y;
+}
+```
+
+`#pragma clang fp contract` specifies whether the compiler should
contract a multiply and an addition (or subtraction) into a fused FMA
operation when supported by the target.
-The pragma can take three values: ``on``, ``fast`` and ``off``. The ``on``
-option is identical to using ``#pragma STDC FP_CONTRACT(ON)`` and it allows
-fusion as specified the language standard. The ``fast`` option allows fusion
+The pragma can take three values: `on`, `fast` and `off`. The `on`
+option is identical to using `#pragma STDC FP_CONTRACT(ON)` and it allows
+fusion as specified the language standard. The `fast` option allows fusion
in cases when the language standard does not make this possible (e.g., across
statements in C).
-.. code-block:: c++
-
- for(...) {
- #pragma clang fp contract(fast)
- a = b[i] * c[i];
- d[i] += a;
- }
-
+```c++
+for(...) {
+ #pragma clang fp contract(fast)
+ a = b[i] * c[i];
+ d[i] += a;
+}
+```
-The pragma can also be used with ``off`` which turns FP contraction off for a
+The pragma can also be used with `off` which turns FP contraction off for a
section of the code. This can be useful when fast contraction is otherwise
-enabled for the translation unit with the ``-ffp-contract=fast-honor-pragmas`` flag.
-Note that ``-ffp-contract=fast`` will override pragmas to fuse multiply and
+enabled for the translation unit with the `-ffp-contract=fast-honor-pragmas` flag.
+Note that `-ffp-contract=fast` will override pragmas to fuse multiply and
addition across statements regardless of any controlling pragmas.
-``#pragma clang fp exceptions`` specifies floating point exception behavior. It
-may take one of the values: ``ignore``, ``maytrap`` or ``strict``. Meaning of
-these values is same as for `constrained floating point intrinsics <http://llvm.org/docs/LangRef.html#constrained-floating-point-intrinsics>`_.
+`#pragma clang fp exceptions` specifies floating point exception behavior. It
+may take one of the values: `ignore`, `maytrap` or `strict`. Meaning of
+these values is same as for [constrained floating point intrinsics](http://llvm.org/docs/LangRef.html#constrained-floating-point-intrinsics).
-.. code-block:: c++
-
- {
- // Preserve floating point exceptions
- #pragma clang fp exceptions(strict)
- z = x + y;
- if (fetestexcept(FE_OVERFLOW))
- ...
- }
-
-A ``#pragma clang fp`` pragma may contain any number of options:
+```c++
+{
+ // Preserve floating point exceptions
+ #pragma clang fp exceptions(strict)
+ z = x + y;
+ if (fetestexcept(FE_OVERFLOW))
+ ...
+}
+```
-.. code-block:: c++
+A `#pragma clang fp` pragma may contain any number of options:
- void func(float *dest, float a, float b) {
- #pragma clang fp exceptions(maytrap) contract(fast) reassociate(on)
- ...
- }
+```c++
+void func(float *dest, float a, float b) {
+ #pragma clang fp exceptions(maytrap) contract(fast) reassociate(on)
+ ...
+}
+```
-``#pragma clang fp eval_method`` allows floating-point behavior to be specified
+`#pragma clang fp eval_method` allows floating-point behavior to be specified
for a section of the source code. This pragma can appear at file or namespace
scope, or at the start of a compound statement (excluding comments).
The pragma is active within the scope of the compound statement.
-When ``pragma clang fp eval_method(source)`` is enabled, the section of code
+When `pragma clang fp eval_method(source)` is enabled, the section of code
governed by the pragma behaves as though the command-line option
-``-ffp-eval-method=source`` is enabled. Rounds intermediate results to
+`-ffp-eval-method=source` is enabled. Rounds intermediate results to
source-defined precision.
-When ``pragma clang fp eval_method(double)`` is enabled, the section of code
+When `pragma clang fp eval_method(double)` is enabled, the section of code
governed by the pragma behaves as though the command-line option
-``-ffp-eval-method=double`` is enabled. Rounds intermediate results to
-``double`` precision.
+`-ffp-eval-method=double` is enabled. Rounds intermediate results to
+`double` precision.
-When ``pragma clang fp eval_method(extended)`` is enabled, the section of code
+When `pragma clang fp eval_method(extended)` is enabled, the section of code
governed by the pragma behaves as though the command-line option
-``-ffp-eval-method=extended`` is enabled. Rounds intermediate results to
-target-dependent ``long double`` precision. In Win32 programming, for instance,
+`-ffp-eval-method=extended` is enabled. Rounds intermediate results to
+target-dependent `long double` precision. In Win32 programming, for instance,
the long double data type maps to the double, 64-bit precision data type.
The full syntax this pragma supports is
-``#pragma clang fp eval_method(source|double|extended)``.
-
-.. code-block:: c++
-
- for(...) {
- // The compiler will use long double as the floating-point evaluation
- // method.
- #pragma clang fp eval_method(extended)
- a = b[i] * c[i] + e;
- }
-
-Note: ``math.h`` defines the typedefs ``float_t`` and ``double_t`` based on the active
+`#pragma clang fp eval_method(source|double|extended)`.
+
+```c++
+for(...) {
+ // The compiler will use long double as the floating-point evaluation
+ // method.
+ #pragma clang fp eval_method(extended)
+ a = b[i] * c[i] + e;
+}
+```
+
+Note: `math.h` defines the typedefs `float_t` and `double_t` based on the active
evaluation method at the point where the header is included, not where the
-typedefs are used. Because of this, it is unwise to combine these typedefs with
-``#pragma clang fp eval_method``. To catch obvious bugs, Clang will emit an
+typedefs are used. Because of this, it is unwise to combine these typedefs with
+`#pragma clang fp eval_method`. To catch obvious bugs, Clang will emit an
error for any references to these typedefs within the scope of this pragma;
however, this is not a fool-proof protection, and programmers must take care.
-The ``#pragma float_control`` pragma allows precise floating-point
+The `#pragma float_control` pragma allows precise floating-point
semantics and floating-point exception behavior to be specified
for a section of the source code. This pragma can only appear at file or
namespace scope, within a language linkage specification or at the start of a
compound statement (excluding comments). When used within a compound statement,
-the pragma is active within the scope of the compound statement. This pragma
-is modeled after a Microsoft pragma with the same spelling and syntax. For
+the pragma is active within the scope of the compound statement. This pragma
+is modeled after a Microsoft pragma with the same spelling and syntax. For
pragmas specified at file or namespace scope, or within a language linkage
-specification, a stack is supported so that the ``pragma float_control``
+specification, a stack is supported so that the `pragma float_control`
settings can be pushed or popped.
-When ``pragma float_control(precise, on)`` is enabled, the section of code
+When `pragma float_control(precise, on)` is enabled, the section of code
governed by the pragma uses precise floating point semantics, effectively
-``-ffast-math`` is disabled and ``-ffp-contract=on``
-(fused multiply add) is enabled. This pragma enables ``-fmath-errno``.
+`-ffast-math` is disabled and `-ffp-contract=on`
+(fused multiply add) is enabled. This pragma enables `-fmath-errno`.
-When ``pragma float_control(precise, off)`` is enabled, unsafe-floating point
+When `pragma float_control(precise, off)` is enabled, unsafe-floating point
optimizations are enabled in the section of code governed by the pragma.
-Effectively ``-ffast-math`` is enabled and ``-ffp-contract=fast``. This pragma
-disables ``-fmath-errno``.
+Effectively `-ffast-math` is enabled and `-ffp-contract=fast`. This pragma
+disables `-fmath-errno`.
-When ``pragma float_control(except, on)`` is enabled, the section of code
+When `pragma float_control(except, on)` is enabled, the section of code
governed by the pragma behaves as though the command-line option
-``-ffp-exception-behavior=strict`` is enabled,
-when ``pragma float_control(except, off)`` is enabled, the section of code
+`-ffp-exception-behavior=strict` is enabled,
+when `pragma float_control(except, off)` is enabled, the section of code
governed by the pragma behaves as though the command-line option
-``-ffp-exception-behavior=ignore`` is enabled.
+`-ffp-exception-behavior=ignore` is enabled.
The full syntax this pragma supports is
-``float_control(except|precise, on|off [, push])`` and
-``float_control(push|pop)``.
-The ``push`` and ``pop`` forms, including using ``push`` as the optional
+`float_control(except|precise, on|off [, push])` and
+`float_control(push|pop)`.
+The `push` and `pop` forms, including using `push` as the optional
third argument, can only occur at file scope.
-.. code-block:: c++
-
- for(...) {
- // This block will be compiled with -fno-fast-math and -ffp-contract=on
- #pragma float_control(precise, on)
- a = b[i] * c[i] + e;
- }
+```c++
+for(...) {
+ // This block will be compiled with -fno-fast-math and -ffp-contract=on
+ #pragma float_control(precise, on)
+ a = b[i] * c[i] + e;
+}
+```
-Extensions for controlling atomic code generation
-=================================================
+## Extensions for controlling atomic code generation
-The ``[[clang::atomic]]`` statement attribute enables users to control how
+The `[[clang::atomic]]` statement attribute enables users to control how
atomic operations are lowered in LLVM IR by conveying additional metadata to
the backend. The primary goal is to allow users to specify certain options,
like whether the affected atomic operations might be used with specific types of memory or
whether to ignore denormal mode correctness in floating-point operations,
without affecting the correctness of code that does not rely on these properties.
-In LLVM, lowering of atomic operations (e.g., ``atomicrmw``) can differ based
+In LLVM, lowering of atomic operations (e.g., `atomicrmw`) can differ based
on the target's capabilities. Some backends support native atomic instructions
only for certain operation types or alignments, or only in specific memory
regions. Likewise, floating-point atomic instructions may or may not respect
@@ -6445,32 +6066,31 @@ memory accessed via PCIe may only support a subset of atomic operations. To ensu
correct and efficient lowering, the compiler must know whether the user needs
the atomic operations to work with that type of memory.
-The allowed atomic attribute values are now ``remote_memory``, ``fine_grained_memory``,
-and ``ignore_denormal_mode``, each optionally prefixed with ``no_``. The meanings
+The allowed atomic attribute values are now `remote_memory`, `fine_grained_memory`,
+and `ignore_denormal_mode`, each optionally prefixed with `no_`. The meanings
are as follows:
-- ``remote_memory`` means atomic operations may be performed on remote
+- `remote_memory` means atomic operations may be performed on remote
memory, i.e., memory accessed through off-chip interconnects (e.g., PCIe).
On ROCm platforms using HIP, remote memory refers to memory accessed via
PCIe and is subject to specific atomic operation support. See
- `ROCm PCIe Atomics <https://rocm.docs.amd.com/en/latest/conceptual/
- pcie-atomics.html>`_ for further details. Prefixing with ``no_remote_memory`` indicates that
+ [ROCm PCIe Atomics](https://rocm.docs.amd.com/en/latest/conceptual/pcie-atomics.html) for further details. Prefixing with `no_remote_memory` indicates that
atomic operations should not be performed on remote memory.
-- ``fine_grained_memory`` means atomic operations may be performed on fine-grained
+- `fine_grained_memory` means atomic operations may be performed on fine-grained
memory, i.e., memory regions that support fine-grained coherence, where updates to
memory are visible to other parts of the system even while modifications are ongoing.
For example, in HIP, fine-grained coherence ensures that host and device share
up-to-date data without explicit synchronization (see
- `HIP Definition <https://rocm.docs.amd.com/projects/HIP/en/docs-6.3.3/how-to/hip_runtime_api/memory_management/coherence_control.html#coherence-control>`_).
+ [HIP Definition](https://rocm.docs.amd.com/projects/HIP/en/docs-6.3.3/how-to/hip_runtime_api/memory_management/coherence_control.html#coherence-control)).
Similarly, OpenCL 2.0 provides fine-grained synchronization in shared virtual memory
allocations, allowing concurrent modifications by host and device (see
- `OpenCL 2.0 Overview <https://www.intel.com/content/www/us/en/developer/articles/technical/opencl-20-shared-virtual-memory-overview.html>`_).
- Prefixing with ``no_fine_grained_memory`` indicates that atomic operations should not
+ [OpenCL 2.0 Overview](https://www.intel.com/content/www/us/en/developer/articles/technical/opencl-20-shared-virtual-memory-overview.html)).
+ Prefixing with `no_fine_grained_memory` indicates that atomic operations should not
be performed on fine-grained memory.
-- ``ignore_denormal_mode`` means that atomic operations are allowed to ignore
+- `ignore_denormal_mode` means that atomic operations are allowed to ignore
correctness for denormal mode in floating-point operations, potentially improving
performance on architectures that handle denormals inefficiently. The negated form,
- if specified as ``no_ignore_denormal_mode``, would enforce strict denormal mode
+ if specified as `no_ignore_denormal_mode`, would enforce strict denormal mode
correctness.
Any unspecified option is inherited from the global defaults, which can be set
@@ -6483,72 +6103,72 @@ allowed for the same compound statement, and the last atomic attribute wins.
Without any atomic metadata, LLVM IR defaults to conservative settings for
correctness: atomic operations enforce denormal mode correctness and are assumed
to potentially use remote and fine-grained memory (i.e., the equivalent of
-``remote_memory``, ``fine_grained_memory``, and ``no_ignore_denormal_mode``).
+`remote_memory`, `fine_grained_memory`, and `no_ignore_denormal_mode`).
The attribute may be applied only to a compound statement and looks like:
-.. code-block:: c++
-
- [[clang::atomic(remote_memory, fine_grained_memory, ignore_denormal_mode)]]
- {
- // Atomic instructions in this block carry extra metadata reflecting
- // these user-specified options.
- }
+```c++
+[[clang::atomic(remote_memory, fine_grained_memory, ignore_denormal_mode)]]
+{
+ // Atomic instructions in this block carry extra metadata reflecting
+ // these user-specified options.
+}
+```
A new compiler option now globally sets the defaults for these atomic-lowering
options. The command-line format has changed to:
-.. code-block:: console
-
- $ clang -fatomic-remote-memory -fno-atomic-fine-grained-memory -fatomic-ignore-denormal-mode file.cpp
+```console
+$ clang -fatomic-remote-memory -fno-atomic-fine-grained-memory -fatomic-ignore-denormal-mode file.cpp
+```
Each option has a corresponding flag:
-``-fatomic-remote-memory`` / ``-fno-atomic-remote-memory``,
-``-fatomic-fine-grained-memory`` / ``-fno-atomic-fine-grained-memory``,
-and ``-fatomic-ignore-denormal-mode`` / ``-fno-atomic-ignore-denormal-mode``.
+`-fatomic-remote-memory` / `-fno-atomic-remote-memory`,
+`-fatomic-fine-grained-memory` / `-fno-atomic-fine-grained-memory`,
+and `-fatomic-ignore-denormal-mode` / `-fno-atomic-ignore-denormal-mode`.
-Code using the ``[[clang::atomic]]`` attribute can then selectively override
+Code using the `[[clang::atomic]]` attribute can then selectively override
the command-line defaults on a per-block basis. For instance:
-.. code-block:: c++
+```c++
+// Suppose the global defaults assume:
+// remote_memory, fine_grained_memory, and no_ignore_denormal_mode
+// (for conservative correctness)
- // Suppose the global defaults assume:
- // remote_memory, fine_grained_memory, and no_ignore_denormal_mode
- // (for conservative correctness)
-
- void example() {
- // Locally override the settings: disable remote_memory and enable
- // fine_grained_memory.
- [[clang::atomic(no_remote_memory, fine_grained_memory)]]
- {
- // In this block:
- // - Atomic operations are not performed on remote memory.
- // - Atomic operations are performed on fine-grained memory.
- // - The setting for denormal mode remains as the global default
- // (typically no_ignore_denormal_mode, enforcing strict denormal mode correctness).
- // ...
- }
- }
+void example() {
+ // Locally override the settings: disable remote_memory and enable
+ // fine_grained_memory.
+ [[clang::atomic(no_remote_memory, fine_grained_memory)]]
+ {
+ // In this block:
+ // - Atomic operations are not performed on remote memory.
+ // - Atomic operations are performed on fine-grained memory.
+ // - The setting for denormal mode remains as the global default
+ // (typically no_ignore_denormal_mode, enforcing strict denormal mode correctness).
+ // ...
+ }
+}
+```
Function bodies do not accept statement attributes, so this will not work:
-.. code-block:: c++
-
- void func() [[clang::atomic(remote_memory)]] { // Wrong: applies to function type
- }
+```c++
+void func() [[clang::atomic(remote_memory)]] { // Wrong: applies to function type
+}
+```
Use the attribute on a compound statement within the function:
-.. code-block:: c++
-
- void func() {
- [[clang::atomic(remote_memory)]]
- {
- // Atomic operations in this block carry the specified metadata.
- }
- }
+```c++
+void func() {
+ [[clang::atomic(remote_memory)]]
+ {
+ // Atomic operations in this block carry the specified metadata.
+ }
+}
+```
-The ``[[clang::atomic]]`` attribute affects only the code generation of atomic
+The `[[clang::atomic]]` attribute affects only the code generation of atomic
instructions within the annotated compound statement. Clang attaches target-specific
metadata to those atomic instructions in the emitted LLVM IR to guide backend lowering.
This metadata is fixed at the Clang code generation phase and is not modified by later
@@ -6556,21 +6176,21 @@ LLVM passes (such as function inlining).
For example, consider:
-.. code-block:: cpp
-
- inline void func() {
- [[clang::atomic(remote_memory)]]
- {
- // Atomic instructions lowered with metadata.
- }
+```cpp
+inline void func() {
+ [[clang::atomic(remote_memory)]]
+ {
+ // Atomic instructions lowered with metadata.
}
+}
- void foo() {
- [[clang::atomic(no_remote_memory)]]
- {
- func(); // Inlined by LLVM, but the metadata from 'func()' remains unchanged.
- }
+void foo() {
+ [[clang::atomic(no_remote_memory)]]
+ {
+ func(); // Inlined by LLVM, but the metadata from 'func()' remains unchanged.
}
+}
+```
Although current usage focuses on AMDGPU, the mechanism is general. Other
backends can ignore or implement their own responses to these flags if desired.
@@ -6578,640 +6198,596 @@ If a target does not understand or enforce these hints, the IR remains valid,
and the resulting program is still correct (although potentially less optimized
for that user's needs).
-Specifying an attribute for multiple declarations (#pragma clang attribute)
-===========================================================================
+## Specifying an attribute for multiple declarations (#pragma clang attribute)
-The ``#pragma clang attribute`` directive can be used to apply an attribute to
-multiple declarations. The ``#pragma clang attribute push`` variation of the
-directive pushes a new "scope" of ``#pragma clang attribute`` that attributes
-can be added to. The ``#pragma clang attribute (...)`` variation adds an
-attribute to that scope, and the ``#pragma clang attribute pop`` variation pops
-the scope. You can also use ``#pragma clang attribute push (...)``, which is a
+The `#pragma clang attribute` directive can be used to apply an attribute to
+multiple declarations. The `#pragma clang attribute push` variation of the
+directive pushes a new "scope" of `#pragma clang attribute` that attributes
+can be added to. The `#pragma clang attribute (...)` variation adds an
+attribute to that scope, and the `#pragma clang attribute pop` variation pops
+the scope. You can also use `#pragma clang attribute push (...)`, which is a
shorthand for when you want to add one attribute to a new scope. Multiple push
directives can be nested inside each other.
-The attributes that are used in the ``#pragma clang attribute`` directives
+The attributes that are used in the `#pragma clang attribute` directives
can be written using the GNU-style syntax:
-.. code-block:: c++
+```c++
+#pragma clang attribute push (__attribute__((annotate("custom"))), apply_to = function)
- #pragma clang attribute push (__attribute__((annotate("custom"))), apply_to = function)
+void function(); // The function now has the annotate("custom") attribute
- void function(); // The function now has the annotate("custom") attribute
-
- #pragma clang attribute pop
+#pragma clang attribute pop
+```
The attributes can also be written using the C++11 style syntax:
-.. code-block:: c++
-
- #pragma clang attribute push ([[noreturn]], apply_to = function)
+```c++
+#pragma clang attribute push ([[noreturn]], apply_to = function)
- void function(); // The function now has the [[noreturn]] attribute
+void function(); // The function now has the [[noreturn]] attribute
- #pragma clang attribute pop
+#pragma clang attribute pop
+```
-The ``__declspec`` style syntax is also supported:
+The `__declspec` style syntax is also supported:
-.. code-block:: c++
+```c++
+#pragma clang attribute push (__declspec(dllexport), apply_to = function)
- #pragma clang attribute push (__declspec(dllexport), apply_to = function)
+void function(); // The function now has the __declspec(dllexport) attribute
- void function(); // The function now has the __declspec(dllexport) attribute
-
- #pragma clang attribute pop
+#pragma clang attribute pop
+```
A single push directive can contain multiple attributes, however,
only one syntax style can be used within a single directive:
-.. code-block:: c++
-
- #pragma clang attribute push ([[noreturn, noinline]], apply_to = function)
+```c++
+#pragma clang attribute push ([[noreturn, noinline]], apply_to = function)
- void function1(); // The function now has the [[noreturn]] and [[noinline]] attributes
+void function1(); // The function now has the [[noreturn]] and [[noinline]] attributes
- #pragma clang attribute pop
+#pragma clang attribute pop
- #pragma clang attribute push (__attribute((noreturn, noinline)), apply_to = function)
+#pragma clang attribute push (__attribute((noreturn, noinline)), apply_to = function)
- void function2(); // The function now has the __attribute((noreturn)) and __attribute((noinline)) attributes
+void function2(); // The function now has the __attribute((noreturn)) and __attribute((noinline)) attributes
- #pragma clang attribute pop
+#pragma clang attribute pop
+```
Because multiple push directives can be nested, if you're writing a macro that
-expands to ``_Pragma("clang attribute")`` it's good hygiene (though not
+expands to `_Pragma("clang attribute")` it's good hygiene (though not
required) to add a namespace to your push/pop directives. A pop directive with a
namespace will pop the innermost push that has that same namespace. This will
-ensure that another macro's ``pop`` won't inadvertently pop your attribute. Note
-that an ``pop`` without a namespace will pop the innermost ``push`` without a
-namespace. ``push``es with a namespace can only be popped by ``pop`` with the
+ensure that another macro's `pop` won't inadvertently pop your attribute. Note
+that an `pop` without a namespace will pop the innermost `push` without a
+namespace. ``` push``es with a namespace can only be popped by ``pop ``` with the
same namespace. For instance:
-.. code-block:: c++
-
- #define ASSUME_NORETURN_BEGIN _Pragma("clang attribute AssumeNoreturn.push ([[noreturn]], apply_to = function)")
- #define ASSUME_NORETURN_END _Pragma("clang attribute AssumeNoreturn.pop")
+```c++
+#define ASSUME_NORETURN_BEGIN _Pragma("clang attribute AssumeNoreturn.push ([[noreturn]], apply_to = function)")
+#define ASSUME_NORETURN_END _Pragma("clang attribute AssumeNoreturn.pop")
- #define ASSUME_UNAVAILABLE_BEGIN _Pragma("clang attribute Unavailable.push (__attribute__((unavailable)), apply_to=function)")
- #define ASSUME_UNAVAILABLE_END _Pragma("clang attribute Unavailable.pop")
+#define ASSUME_UNAVAILABLE_BEGIN _Pragma("clang attribute Unavailable.push (__attribute__((unavailable)), apply_to=function)")
+#define ASSUME_UNAVAILABLE_END _Pragma("clang attribute Unavailable.pop")
- ASSUME_NORETURN_BEGIN
- ASSUME_UNAVAILABLE_BEGIN
- void function(); // function has [[noreturn]] and __attribute__((unavailable))
- ASSUME_NORETURN_END
- void other_function(); // function has __attribute__((unavailable))
- ASSUME_UNAVAILABLE_END
+ASSUME_NORETURN_BEGIN
+ASSUME_UNAVAILABLE_BEGIN
+void function(); // function has [[noreturn]] and __attribute__((unavailable))
+ASSUME_NORETURN_END
+void other_function(); // function has __attribute__((unavailable))
+ASSUME_UNAVAILABLE_END
+```
-Without the namespaces on the macros, ``other_function`` will be annotated with
-``[[noreturn]]`` instead of ``__attribute__((unavailable))``. This may seem like
+Without the namespaces on the macros, `other_function` will be annotated with
+`[[noreturn]]` instead of `__attribute__((unavailable))`. This may seem like
a contrived example, but its very possible for this kind of situation to appear
in real code if the pragmas are spread out across a large file. You can test if
-your version of clang supports namespaces on ``#pragma clang attribute`` with
-``__has_extension(pragma_clang_attribute_namespaces)``.
+your version of clang supports namespaces on `#pragma clang attribute` with
+`__has_extension(pragma_clang_attribute_namespaces)`.
-Subject Match Rules
--------------------
+### Subject Match Rules
The set of declarations that receive a single attribute from the attribute stack
depends on the subject match rules that were specified in the pragma. Subject
match rules are specified after the attribute. The compiler expects an
-identifier that corresponds to the subject set specifier. The ``apply_to``
+identifier that corresponds to the subject set specifier. The `apply_to`
specifier is currently the only supported subject set specifier. It allows you
to specify match rules that form a subset of the attribute's allowed subject
set, i.e., the compiler doesn't require all of the attribute's subjects. For
-example, an attribute like ``[[nodiscard]]`` whose subject set includes
-``enum``, ``record`` and ``hasType(functionType)``, requires the presence of at
-least one of these rules after ``apply_to``:
-
-.. code-block:: c++
+example, an attribute like `[[nodiscard]]` whose subject set includes
+`enum`, `record` and `hasType(functionType)`, requires the presence of at
+least one of these rules after `apply_to`:
- #pragma clang attribute push([[nodiscard]], apply_to = enum)
+```c++
+#pragma clang attribute push([[nodiscard]], apply_to = enum)
- enum Enum1 { A1, B1 }; // The enum will receive [[nodiscard]]
+enum Enum1 { A1, B1 }; // The enum will receive [[nodiscard]]
- struct Record1 { }; // The struct will *not* receive [[nodiscard]]
+struct Record1 { }; // The struct will *not* receive [[nodiscard]]
- #pragma clang attribute pop
+#pragma clang attribute pop
- #pragma clang attribute push([[nodiscard]], apply_to = any(record, enum))
+#pragma clang attribute push([[nodiscard]], apply_to = any(record, enum))
- enum Enum2 { A2, B2 }; // The enum will receive [[nodiscard]]
+enum Enum2 { A2, B2 }; // The enum will receive [[nodiscard]]
- struct Record2 { }; // The struct *will* receive [[nodiscard]]
+struct Record2 { }; // The struct *will* receive [[nodiscard]]
- #pragma clang attribute pop
+#pragma clang attribute pop
- // This is an error, since [[nodiscard]] can't be applied to namespaces:
- #pragma clang attribute push([[nodiscard]], apply_to = any(record, namespace))
+// This is an error, since [[nodiscard]] can't be applied to namespaces:
+#pragma clang attribute push([[nodiscard]], apply_to = any(record, namespace))
- #pragma clang attribute pop
+#pragma clang attribute pop
+```
-Multiple match rules can be specified using the ``any`` match rule, as shown
-in the example above. The ``any`` rule applies attributes to all declarations
-that are matched by at least one of the rules in the ``any``. It doesn't nest
+Multiple match rules can be specified using the `any` match rule, as shown
+in the example above. The `any` rule applies attributes to all declarations
+that are matched by at least one of the rules in the `any`. It doesn't nest
and can't be used inside the other match rules. Redundant match rules or rules
-that conflict with one another should not be used inside of ``any``. Failing to
-specify a rule within the ``any`` rule results in an error.
+that conflict with one another should not be used inside of `any`. Failing to
+specify a rule within the `any` rule results in an error.
Clang supports the following match rules:
-- ``function``: Can be used to apply attributes to functions. This includes C++
+- `function`: Can be used to apply attributes to functions. This includes C++
member functions, static functions, operators, and constructors/destructors.
-
-- ``function(is_member)``: Can be used to apply attributes to C++ member
+- `function(is_member)`: Can be used to apply attributes to C++ member
functions. This includes members like static functions, operators, and
constructors/destructors.
-
-- ``hasType(functionType)``: Can be used to apply attributes to functions, C++
+- `hasType(functionType)`: Can be used to apply attributes to functions, C++
member functions, and variables/fields whose type is a function pointer. It
does not apply attributes to Objective-C methods or blocks.
-
-- ``type_alias``: Can be used to apply attributes to ``typedef`` declarations
+- `type_alias`: Can be used to apply attributes to `typedef` declarations
and C++11 type aliases.
-
-- ``record``: Can be used to apply attributes to ``struct``, ``class``, and
- ``union`` declarations.
-
-- ``record(unless(is_union))``: Can be used to apply attributes only to
- ``struct`` and ``class`` declarations.
-
-- ``enum``: Can be used to apply attributes to enumeration declarations.
-
-- ``enum_constant``: Can be used to apply attributes to enumerators.
-
-- ``variable``: Can be used to apply attributes to variables, including
+- `record`: Can be used to apply attributes to `struct`, `class`, and
+ `union` declarations.
+- `record(unless(is_union))`: Can be used to apply attributes only to
+ `struct` and `class` declarations.
+- `enum`: Can be used to apply attributes to enumeration declarations.
+- `enum_constant`: Can be used to apply attributes to enumerators.
+- `variable`: Can be used to apply attributes to variables, including
local variables, parameters, global variables, and static member variables.
It does not apply attributes to instance member variables or Objective-C
ivars.
-
-- ``variable(is_thread_local)``: Can be used to apply attributes to thread-local
+- `variable(is_thread_local)`: Can be used to apply attributes to thread-local
variables only.
-
-- ``variable(is_global)``: Can be used to apply attributes to global variables
+- `variable(is_global)`: Can be used to apply attributes to global variables
only.
-
-- ``variable(is_local)``: Can be used to apply attributes to local variables
+- `variable(is_local)`: Can be used to apply attributes to local variables
only.
-
-- ``variable(is_parameter)``: Can be used to apply attributes to parameters
+- `variable(is_parameter)`: Can be used to apply attributes to parameters
only.
-
-- ``variable(unless(is_parameter))``: Can be used to apply attributes to all
+- `variable(unless(is_parameter))`: Can be used to apply attributes to all
the variables that are not parameters.
-
-- ``field``: Can be used to apply attributes to non-static member variables
+- `field`: Can be used to apply attributes to non-static member variables
in a record. This includes Objective-C ivars.
-
-- ``namespace``: Can be used to apply attributes to ``namespace`` declarations.
-
-- ``objc_interface``: Can be used to apply attributes to ``@interface``
+- `namespace`: Can be used to apply attributes to `namespace` declarations.
+- `objc_interface`: Can be used to apply attributes to `@interface`
declarations.
-
-- ``objc_protocol``: Can be used to apply attributes to ``@protocol``
+- `objc_protocol`: Can be used to apply attributes to `@protocol`
declarations.
-
-- ``objc_category``: Can be used to apply attributes to category declarations,
+- `objc_category`: Can be used to apply attributes to category declarations,
including class extensions.
-
-- ``objc_method``: Can be used to apply attributes to Objective-C methods,
+- `objc_method`: Can be used to apply attributes to Objective-C methods,
including instance and class methods. Implicit methods like implicit property
getters and setters do not receive the attribute.
-
-- ``objc_method(is_instance)``: Can be used to apply attributes to Objective-C
+- `objc_method(is_instance)`: Can be used to apply attributes to Objective-C
instance methods.
-
-- ``objc_property``: Can be used to apply attributes to ``@property``
+- `objc_property`: Can be used to apply attributes to `@property`
declarations.
-
-- ``block``: Can be used to apply attributes to block declarations. This does
+- `block`: Can be used to apply attributes to block declarations. This does
not include variables/fields of block pointer type.
-The use of ``unless`` in match rules is currently restricted to a strict set of
+The use of `unless` in match rules is currently restricted to a strict set of
sub-rules that are used by the supported attributes. That means that even though
-``variable(unless(is_parameter))`` is a valid match rule,
-``variable(unless(is_thread_local))`` is not.
+`variable(unless(is_parameter))` is a valid match rule,
+`variable(unless(is_thread_local))` is not.
-Supported Attributes
---------------------
+### Supported Attributes
-Not all attributes can be used with the ``#pragma clang attribute`` directive.
-Notably, statement attributes like ``[[fallthrough]]`` or type attributes
-like ``address_space`` aren't supported by this directive. You can determine
+Not all attributes can be used with the `#pragma clang attribute` directive.
+Notably, statement attributes like `[[fallthrough]]` or type attributes
+like `address_space` aren't supported by this directive. You can determine
whether or not an attribute is supported by the pragma by referring to the
-:doc:`individual documentation for that attribute <AttributeReference>`.
+{doc}`individual documentation for that attribute <AttributeReference>`.
The attributes are applied to all matching declarations individually, even when
the attribute is semantically incorrect. The attributes that aren't applied to
any declaration are not verified semantically.
-Specifying section names for global objects (#pragma clang section)
-===================================================================
+## Specifying section names for global objects (#pragma clang section)
-The ``#pragma clang section`` directive provides a means to assign section-names
+The `#pragma clang section` directive provides a means to assign section-names
to global variables, functions and static variables.
The section names can be specified as:
-.. code-block:: c++
-
- #pragma clang section bss="myBSS" data="myData" rodata="myRodata" relro="myRelro" text="myText"
+```c++
+#pragma clang section bss="myBSS" data="myData" rodata="myRodata" relro="myRelro" text="myText"
+```
The section names can be reverted back to default name by supplying an empty
string to the section kind, for example:
-.. code-block:: c++
-
- #pragma clang section bss="" data="" text="" rodata="" relro=""
+```c++
+#pragma clang section bss="" data="" text="" rodata="" relro=""
+```
-The ``#pragma clang section`` directive obeys the following rules:
+The `#pragma clang section` directive obeys the following rules:
-* The pragma applies to all global variable, statics and function declarations
+- The pragma applies to all global variable, statics and function declarations
from the pragma to the end of the translation unit.
-
-* The pragma clang section is enabled automatically, without need of any flags.
-
-* This feature is only defined to work sensibly for ELF, Mach-O and COFF targets.
-
-* If section name is specified through _attribute_((section("myname"))), then
+- The pragma clang section is enabled automatically, without need of any flags.
+- This feature is only defined to work sensibly for ELF, Mach-O and COFF targets.
+- If section name is specified through \_attribute\_((section("myname"))), then
the attribute name gains precedence.
-
-* Global variables that are initialized to zero will be placed in the named
+- Global variables that are initialized to zero will be placed in the named
bss section, if one is present.
-
-* The ``#pragma clang section`` directive does not try to infer section-kind
- from the name. For example, naming a section "``.bss.mySec``" does NOT mean
+- The `#pragma clang section` directive does not try to infer section-kind
+ from the name. For example, naming a section "`.bss.mySec`" does NOT mean
it will be a bss section name.
-
-* The decision about which section-kind applies to each global is taken in the back-end.
+- The decision about which section-kind applies to each global is taken in the back-end.
Once the section-kind is known, appropriate section name, as specified by the user using
- ``#pragma clang section`` directive, is applied to that global.
+ `#pragma clang section` directive, is applied to that global.
-Specifying Linker Options on ELF Targets
-========================================
+## Specifying Linker Options on ELF Targets
-The ``#pragma comment(lib, ...)`` directive is supported on all ELF targets.
+The `#pragma comment(lib, ...)` directive is supported on all ELF targets.
The second parameter is the library name (without the traditional Unix prefix of
-``lib``). This allows you to provide an implicit link of dependent libraries.
+`lib`). This allows you to provide an implicit link of dependent libraries.
-Embedding Copyright Information on AIX
-======================================
-Clang supports the ``#pragma comment(copyright, "string")`` directive for AIX
+## Embedding Copyright Information on AIX
+
+Clang supports the `#pragma comment(copyright, "string")` directive for AIX
targets. This directive embeds a copyright or identifying string into the
compiled object file. The string is included in the final executable or shared
library and loaded into memory at program runtime. The directive is ignored on
non-AIX targets.
-.. code-block:: c
-
- #pragma comment(copyright, "string-literal")
+```c
+#pragma comment(copyright, "string-literal")
+```
The second argument is an ordinary string literal. Concatenated ordinary string
literals are also accepted. The directive is intended to appear at file scope;
Clang treats it as being at file scope when it appears within other scopes.
-Interaction with C++20 Modules
--------------------------------
+### Interaction with C++20 Modules
-When ``#pragma comment(copyright, ...)`` appears in a C++20 module interface
+When `#pragma comment(copyright, ...)` appears in a C++20 module interface
unit, the copyright string is embedded only in the object file compiled from
that interface unit. Importing TUs do not re-emit the string.
-Evaluating Object Size
-======================
+## Evaluating Object Size
-Clang supports the builtins ``__builtin_object_size`` and
-``__builtin_dynamic_object_size``. The semantics are compatible with GCC's
+Clang supports the builtins `__builtin_object_size` and
+`__builtin_dynamic_object_size`. The semantics are compatible with GCC's
builtins of the same names, but the details are slightly different.
-.. code-block:: c
+```c
+size_t __builtin_[dynamic_]object_size(const void *ptr, int type)
+```
- size_t __builtin_[dynamic_]object_size(const void *ptr, int type)
-
-Returns the number of accessible bytes ``n`` past ``ptr``. The value returned
-depends on ``type``, which is required to be an integer constant between 0 and
+Returns the number of accessible bytes `n` past `ptr`. The value returned
+depends on `type`, which is required to be an integer constant between 0 and
3:
-* If ``type & 2 == 0``, the least ``n`` is returned such that accesses to
- ``(const char*)ptr + n`` and beyond are known to be out of bounds. This is
- ``(size_t)-1`` if no better bound is known.
-* If ``type & 2 == 2``, the greatest ``n`` is returned such that accesses to
- ``(const char*)ptr + i`` are known to be in bounds, for 0 <= ``i`` < ``n``.
- This is ``(size_t)0`` if no better bound is known.
-
-.. code-block:: c
-
- char small[10], large[100];
- bool cond;
- // Returns 100: writes of more than 100 bytes are known to be out of bounds.
- int n100 = __builtin_object_size(cond ? small : large, 0);
- // Returns 10: writes of 10 or fewer bytes are known to be in bounds.
- int n10 = __builtin_object_size(cond ? small : large, 2);
-
-* If ``type & 1 == 0``, pointers are considered to be in bounds if they point
- into the same storage as ``ptr`` -- that is, the same stack object, global
+- If `type & 2 == 0`, the least `n` is returned such that accesses to
+ `(const char*)ptr + n` and beyond are known to be out of bounds. This is
+ `(size_t)-1` if no better bound is known.
+- If `type & 2 == 2`, the greatest `n` is returned such that accesses to
+ `(const char*)ptr + i` are known to be in bounds, for 0 \<= `i` < `n`.
+ This is `(size_t)0` if no better bound is known.
+
+```c
+char small[10], large[100];
+bool cond;
+// Returns 100: writes of more than 100 bytes are known to be out of bounds.
+int n100 = __builtin_object_size(cond ? small : large, 0);
+// Returns 10: writes of 10 or fewer bytes are known to be in bounds.
+int n10 = __builtin_object_size(cond ? small : large, 2);
+```
+
+- If `type & 1 == 0`, pointers are considered to be in bounds if they point
+ into the same storage as `ptr` -- that is, the same stack object, global
variable, or heap allocation.
-* If ``type & 1 == 1``, pointers are considered to be in bounds if they point
- to the same subobject that ``ptr`` points to. If ``ptr`` points to an array
+- If `type & 1 == 1`, pointers are considered to be in bounds if they point
+ to the same subobject that `ptr` points to. If `ptr` points to an array
element, other elements of the same array, but not of enclosing arrays, are
considered in bounds.
-.. code-block:: c
-
- struct X { char a, b, c; } x;
- static_assert(__builtin_object_size(&x, 0) == 3);
- static_assert(__builtin_object_size(&x.b, 0) == 2);
- static_assert(__builtin_object_size(&x.b, 1) == 1);
-
-.. code-block:: c
-
- char a[10][10][10];
- static_assert(__builtin_object_size(&a, 1) == 1000);
- static_assert(__builtin_object_size(&a[1], 1) == 900);
- static_assert(__builtin_object_size(&a[1][1], 1) == 90);
- static_assert(__builtin_object_size(&a[1][1][1], 1) == 9);
+```c
+struct X { char a, b, c; } x;
+static_assert(__builtin_object_size(&x, 0) == 3);
+static_assert(__builtin_object_size(&x.b, 0) == 2);
+static_assert(__builtin_object_size(&x.b, 1) == 1);
+```
+
+```c
+char a[10][10][10];
+static_assert(__builtin_object_size(&a, 1) == 1000);
+static_assert(__builtin_object_size(&a[1], 1) == 900);
+static_assert(__builtin_object_size(&a[1][1], 1) == 90);
+static_assert(__builtin_object_size(&a[1][1][1], 1) == 9);
+```
The values returned by this builtin are a best effort conservative approximation
-of the correct answers. When ``type & 2 == 0``, the true value is less than or
-equal to the value returned by the builtin, and when ``type & 2 == 1``, the true
+of the correct answers. When `type & 2 == 0`, the true value is less than or
+equal to the value returned by the builtin, and when `type & 2 == 1`, the true
value is greater than or equal to the value returned by the builtin.
-For ``__builtin_object_size``, the value is determined entirely at compile time.
+For `__builtin_object_size`, the value is determined entirely at compile time.
With optimization enabled, better results will be produced, especially when the
-call to ``__builtin_object_size`` is in a different function from the formation
+call to `__builtin_object_size` is in a different function from the formation
of the pointer. Unlike in GCC, enabling optimization in Clang does not allow
-more information about subobjects to be determined, so the ``type & 1 == 1``
+more information about subobjects to be determined, so the `type & 1 == 1`
case will often give imprecise results when used across a function call boundary
even when optimization is enabled.
-`The pass_object_size and pass_dynamic_object_size attributes <https://clang.llvm.org/docs/AttributeReference.html#pass-object-size-pass-dynamic-object-size>`_
+[The pass_object_size and pass_dynamic_object_size attributes](https://clang.llvm.org/docs/AttributeReference.html#pass-object-size-pass-dynamic-object-size)
can be used to invisibly pass the object size for a pointer parameter alongside
the pointer in a function call. This allows more precise object sizes to be
-determined both when building without optimizations and in the ``type & 1 == 1``
+determined both when building without optimizations and in the `type & 1 == 1`
case.
-For ``__builtin_dynamic_object_size``, the result is not limited to being a
+For `__builtin_dynamic_object_size`, the result is not limited to being a
compile time constant. Instead, a small amount of runtime evaluation is
permitted to determine the size of the object, in order to give a more precise
-result. ``__builtin_dynamic_object_size`` is meant to be used as a drop-in
-replacement for ``__builtin_object_size`` in libraries that support it. For
-instance, here is a program that ``__builtin_dynamic_object_size`` will make
+result. `__builtin_dynamic_object_size` is meant to be used as a drop-in
+replacement for `__builtin_object_size` in libraries that support it. For
+instance, here is a program that `__builtin_dynamic_object_size` will make
safer:
-.. code-block:: c
+```c
+void copy_into_buffer(size_t size) {
+ char* buffer = malloc(size);
+ strlcpy(buffer, "some string", strlen("some string"));
+ // Previous line preprocesses to:
+ // __builtin___strlcpy_chk(buffer, "some string", strlen("some string"), __builtin_object_size(buffer, 0))
+}
+```
- void copy_into_buffer(size_t size) {
- char* buffer = malloc(size);
- strlcpy(buffer, "some string", strlen("some string"));
- // Previous line preprocesses to:
- // __builtin___strlcpy_chk(buffer, "some string", strlen("some string"), __builtin_object_size(buffer, 0))
- }
-
-Since the size of ``buffer`` can't be known at compile time, Clang will fold
-``__builtin_object_size(buffer, 0)`` into ``-1``. However, if this was written
-as ``__builtin_dynamic_object_size(buffer, 0)``, Clang will fold it into
-``size``, providing some extra runtime safety.
+Since the size of `buffer` can't be known at compile time, Clang will fold
+`__builtin_object_size(buffer, 0)` into `-1`. However, if this was written
+as `__builtin_dynamic_object_size(buffer, 0)`, Clang will fold it into
+`size`, providing some extra runtime safety.
-Deprecating Macros
-==================
+## Deprecating Macros
-Clang supports the pragma ``#pragma clang deprecated``, which can be used to
+Clang supports the pragma `#pragma clang deprecated`, which can be used to
provide deprecation warnings for macro uses. For example:
-.. code-block:: c
+```c
+#define MIN(x, y) x < y ? x : y
+#pragma clang deprecated(MIN, "use std::min instead")
- #define MIN(x, y) x < y ? x : y
- #pragma clang deprecated(MIN, "use std::min instead")
-
- int min(int a, int b) {
- return MIN(a, b); // warning: MIN is deprecated: use std::min instead
- }
+int min(int a, int b) {
+ return MIN(a, b); // warning: MIN is deprecated: use std::min instead
+}
+```
-``#pragma clang deprecated`` should be preferred for this purpose over
-``#pragma GCC warning`` because the warning can be controlled with
-``-Wdeprecated``.
+`#pragma clang deprecated` should be preferred for this purpose over
+`#pragma GCC warning` because the warning can be controlled with
+`-Wdeprecated`.
-Restricted Expansion Macros
-===========================
+## Restricted Expansion Macros
-Clang supports the pragma ``#pragma clang restrict_expansion``, which can be
+Clang supports the pragma `#pragma clang restrict_expansion`, which can be
used restrict macro expansion in headers. This can be valuable when providing
headers with ABI stability requirements. Any expansion of the annotated macro
-processed by the preprocessor after the ``#pragma`` annotation will log a
+processed by the preprocessor after the `#pragma` annotation will log a
warning. Redefining the macro or undefining the macro will not be diagnosed, nor
will expansion of the macro within the main source file. For example:
-.. code-block:: c
-
- #define TARGET_ARM 1
- #pragma clang restrict_expansion(TARGET_ARM, "<reason>")
-
- /// Foo.h
- struct Foo {
- #if TARGET_ARM // warning: TARGET_ARM is marked unsafe in headers: <reason>
- uint32_t X;
- #else
- uint64_t X;
- #endif
- };
-
- /// main.c
- #include "foo.h"
- #if TARGET_ARM // No warning in main source file
- X_TYPE uint32_t
- #else
- X_TYPE uint64_t
- #endif
-
-This warning is controlled by ``-Wpedantic-macros``.
-
-Final Macros
-============
-
-Clang supports the pragma ``#pragma clang final``, which can be used to
+```c
+#define TARGET_ARM 1
+#pragma clang restrict_expansion(TARGET_ARM, "<reason>")
+
+/// Foo.h
+struct Foo {
+#if TARGET_ARM // warning: TARGET_ARM is marked unsafe in headers: <reason>
+ uint32_t X;
+#else
+ uint64_t X;
+#endif
+};
+
+/// main.c
+#include "foo.h"
+#if TARGET_ARM // No warning in main source file
+X_TYPE uint32_t
+#else
+X_TYPE uint64_t
+#endif
+```
+
+This warning is controlled by `-Wpedantic-macros`.
+
+## Final Macros
+
+Clang supports the pragma `#pragma clang final`, which can be used to
mark macros as final, meaning they cannot be undef'd or re-defined. For example:
-.. code-block:: c
+```c
+#define FINAL_MACRO 1
+#pragma clang final(FINAL_MACRO)
- #define FINAL_MACRO 1
- #pragma clang final(FINAL_MACRO)
-
- #define FINAL_MACRO // warning: FINAL_MACRO is marked final and should not be redefined
- #undef FINAL_MACRO // warning: FINAL_MACRO is marked final and should not be undefined
+#define FINAL_MACRO // warning: FINAL_MACRO is marked final and should not be redefined
+#undef FINAL_MACRO // warning: FINAL_MACRO is marked final and should not be undefined
+```
This is useful for enforcing system-provided macros that should not be altered
-in user headers or code. This is controlled by ``-Wpedantic-macros``. Final
+in user headers or code. This is controlled by `-Wpedantic-macros`. Final
macros will always warn on redefinition, including situations with identical
bodies and in system headers.
-Line Control
-============
+## Line Control
Clang supports an extension for source line control, which takes the
form of a preprocessor directive starting with an unsigned integral
-constant. In addition to the standard ``#line`` directive, this form
+constant. In addition to the standard `#line` directive, this form
allows control of an include stack and header file type, which is used
in issuing diagnostics. These lines are emitted in preprocessed
output.
-.. code-block:: c
-
- # <line:number> <filename:string> <header-type:numbers>
+```c
+# <line:number> <filename:string> <header-type:numbers>
+```
The filename is optional, and if unspecified indicates no change in
source filename. The header-type is an optional, whitespace-delimited,
sequence of magic numbers as follows.
-* ``1:`` Push the current source file name onto the include stack and
+- `1:` Push the current source file name onto the include stack and
enter a new file.
-
-* ``2``: Pop the include stack and return to the specified file. If
- the filename is ``""``, the name popped from the include stack is
+- `2`: Pop the include stack and return to the specified file. If
+ the filename is `""`, the name popped from the include stack is
used. Otherwise there is no requirement that the specified filename
matches the current source when originally pushed.
-
-* ``3``: Enter a system-header region. System headers often contain
+- `3`: Enter a system-header region. System headers often contain
implementation-specific source that would normally emit a diagnostic.
-
-* ``4``: Enter an implicit ``extern "C"`` region. This is not required on
+- `4`: Enter an implicit `extern "C"` region. This is not required on
modern systems where system headers are C++-aware.
-At most a single ``1`` or ``2`` can be present, and values must be in
+At most a single `1` or `2` can be present, and values must be in
ascending order.
Examples are:
-.. code-block:: c
+```c
+# 57 // Advance (or return) to line 57 of the current source file
+# 57 "frob" // Set to line 57 of "frob"
+# 1 "foo.h" 1 // Enter "foo.h" at line 1
+# 59 "main.c" 2 // Leave current include and return to "main.c"
+# 1 "/usr/include/stdio.h" 1 3 // Enter a system header
+# 60 "" 2 // return to "main.c"
+# 1 "/usr/ancient/header.h" 1 4 // Enter an implicit extern "C" header
+```
- # 57 // Advance (or return) to line 57 of the current source file
- # 57 "frob" // Set to line 57 of "frob"
- # 1 "foo.h" 1 // Enter "foo.h" at line 1
- # 59 "main.c" 2 // Leave current include and return to "main.c"
- # 1 "/usr/include/stdio.h" 1 3 // Enter a system header
- # 60 "" 2 // return to "main.c"
- # 1 "/usr/ancient/header.h" 1 4 // Enter an implicit extern "C" header
-
-Intrinsics Support within Constant Expressions
-==============================================
+## Intrinsics Support within Constant Expressions
The following builtin intrinsics can be used in constant expressions:
-* ``__builtin_addcb``
-* ``__builtin_addcs``
-* ``__builtin_addc``
-* ``__builtin_addcl``
-* ``__builtin_addcll``
-* ``__builtin_bitreverse8``
-* ``__builtin_bitreverse16``
-* ``__builtin_bitreverse32``
-* ``__builtin_bitreverse64``
-* ``__builtin_bswap16``
-* ``__builtin_bswap32``
-* ``__builtin_bswap64``
-* ``__builtin_clrsb``
-* ``__builtin_clrsbl``
-* ``__builtin_clrsbll``
-* ``__builtin_clz``
-* ``__builtin_clzl``
-* ``__builtin_clzll``
-* ``__builtin_clzs``
-* ``__builtin_clzg``
-* ``__builtin_ctz``
-* ``__builtin_ctzl``
-* ``__builtin_ctzll``
-* ``__builtin_ctzs``
-* ``__builtin_ctzg``
-* ``__builtin_ffs``
-* ``__builtin_ffsl``
-* ``__builtin_ffsll``
-* ``__builtin_fmax``
-* ``__builtin_fmin``
-* ``__builtin_fpclassify``
-* ``__builtin_inf``
-* ``__builtin_isinf``
-* ``__builtin_isinf_sign``
-* ``__builtin_isfinite``
-* ``__builtin_isnan``
-* ``__builtin_isnormal``
-* ``__builtin_nan``
-* ``__builtin_nans``
-* ``__builtin_parity``
-* ``__builtin_parityl``
-* ``__builtin_parityll``
-* ``__builtin_popcount``
-* ``__builtin_popcountl``
-* ``__builtin_popcountll``
-* ``__builtin_popcountg``
-* ``__builtin_rotateleft8``
-* ``__builtin_rotateleft16``
-* ``__builtin_rotateleft32``
-* ``__builtin_rotateleft64``
-* ``__builtin_rotateright8``
-* ``__builtin_rotateright16``
-* ``__builtin_rotateright32``
-* ``__builtin_rotateright64``
-* ``__builtin_subcb``
-* ``__builtin_subcs``
-* ``__builtin_subc``
-* ``__builtin_subcl``
-* ``__builtin_subcll``
+- `__builtin_addcb`
+- `__builtin_addcs`
+- `__builtin_addc`
+- `__builtin_addcl`
+- `__builtin_addcll`
+- `__builtin_bitreverse8`
+- `__builtin_bitreverse16`
+- `__builtin_bitreverse32`
+- `__builtin_bitreverse64`
+- `__builtin_bswap16`
+- `__builtin_bswap32`
+- `__builtin_bswap64`
+- `__builtin_clrsb`
+- `__builtin_clrsbl`
+- `__builtin_clrsbll`
+- `__builtin_clz`
+- `__builtin_clzl`
+- `__builtin_clzll`
+- `__builtin_clzs`
+- `__builtin_clzg`
+- `__builtin_ctz`
+- `__builtin_ctzl`
+- `__builtin_ctzll`
+- `__builtin_ctzs`
+- `__builtin_ctzg`
+- `__builtin_ffs`
+- `__builtin_ffsl`
+- `__builtin_ffsll`
+- `__builtin_fmax`
+- `__builtin_fmin`
+- `__builtin_fpclassify`
+- `__builtin_inf`
+- `__builtin_isinf`
+- `__builtin_isinf_sign`
+- `__builtin_isfinite`
+- `__builtin_isnan`
+- `__builtin_isnormal`
+- `__builtin_nan`
+- `__builtin_nans`
+- `__builtin_parity`
+- `__builtin_parityl`
+- `__builtin_parityll`
+- `__builtin_popcount`
+- `__builtin_popcountl`
+- `__builtin_popcountll`
+- `__builtin_popcountg`
+- `__builtin_rotateleft8`
+- `__builtin_rotateleft16`
+- `__builtin_rotateleft32`
+- `__builtin_rotateleft64`
+- `__builtin_rotateright8`
+- `__builtin_rotateright16`
+- `__builtin_rotateright32`
+- `__builtin_rotateright64`
+- `__builtin_subcb`
+- `__builtin_subcs`
+- `__builtin_subc`
+- `__builtin_subcl`
+- `__builtin_subcll`
The following x86-specific intrinsics can be used in constant expressions:
-* ``_addcarry_u32``
-* ``_addcarry_u64``
-* ``_bit_scan_forward``
-* ``_bit_scan_reverse``
-* ``__bsfd``
-* ``__bsfq``
-* ``__bsrd``
-* ``__bsrq``
-* ``__bswap``
-* ``__bswapd``
-* ``__bswap64``
-* ``__bswapq``
-* ``_castf32_u32``
-* ``_castf64_u64``
-* ``_castu32_f32``
-* ``_castu64_f64``
-* ``__lzcnt16``
-* ``__lzcnt``
-* ``__lzcnt64``
-* ``_mm_popcnt_u32``
-* ``_mm_popcnt_u64``
-* ``_popcnt32``
-* ``_popcnt64``
-* ``__popcntd``
-* ``__popcntq``
-* ``__popcnt16``
-* ``__popcnt``
-* ``__popcnt64``
-* ``__rolb``
-* ``__rolw``
-* ``__rold``
-* ``__rolq``
-* ``__rorb``
-* ``__rorw``
-* ``__rord``
-* ``__rorq``
-* ``_rotl``
-* ``_rotr``
-* ``_rotwl``
-* ``_rotwr``
-* ``_lrotl``
-* ``_lrotr``
-* ``_subborrow_u32``
-* ``_subborrow_u64``
-
-Debugging the Compiler
-======================
+- `_addcarry_u32`
+- `_addcarry_u64`
+- `_bit_scan_forward`
+- `_bit_scan_reverse`
+- `__bsfd`
+- `__bsfq`
+- `__bsrd`
+- `__bsrq`
+- `__bswap`
+- `__bswapd`
+- `__bswap64`
+- `__bswapq`
+- `_castf32_u32`
+- `_castf64_u64`
+- `_castu32_f32`
+- `_castu64_f64`
+- `__lzcnt16`
+- `__lzcnt`
+- `__lzcnt64`
+- `_mm_popcnt_u32`
+- `_mm_popcnt_u64`
+- `_popcnt32`
+- `_popcnt64`
+- `__popcntd`
+- `__popcntq`
+- `__popcnt16`
+- `__popcnt`
+- `__popcnt64`
+- `__rolb`
+- `__rolw`
+- `__rold`
+- `__rolq`
+- `__rorb`
+- `__rorw`
+- `__rord`
+- `__rorq`
+- `_rotl`
+- `_rotr`
+- `_rotwl`
+- `_rotwr`
+- `_lrotl`
+- `_lrotr`
+- `_subborrow_u32`
+- `_subborrow_u64`
+
+## Debugging the Compiler
Clang supports a number of pragma directives that help debugging the compiler itself.
Syntax is the following: `#pragma clang __debug <command> <arguments>`.
Note, all of debugging pragmas are subject to change.
-`dump`
-------
+### `dump`
+
Accepts either a single identifier or an expression. When a single identifier is passed,
the lookup results for the identifier are printed to `stderr`. When an expression is passed,
the AST for the expression is printed to `stderr`. The expression is an unevaluated operand,
@@ -7221,16 +6797,15 @@ Type- and value-dependent expressions are not supported yet.
This facility is designed to aid with testing name lookup machinery.
-Predefined Macros
-=================
+## Predefined Macros
+
+### `__GCC_DESTRUCTIVE_SIZE` and `__GCC_CONSTRUCTIVE_SIZE`
-`__GCC_DESTRUCTIVE_SIZE` and `__GCC_CONSTRUCTIVE_SIZE`
-------------------------------------------------------
Specify the mimum offset between two objects to avoid false sharing and the
maximum size of contiguous memory to promote true sharing, respectively. These
macros are predefined in all C and C++ language modes, but can be redefined on
-the command line with ``-D`` to specify different values as needed or can be
-undefined on the command line with ``-U`` to disable support for the feature.
+the command line with `-D` to specify different values as needed or can be
+undefined on the command line with `-U` to disable support for the feature.
**Note: the values the macros expand to are not guaranteed to be stable. They
are are affected by architectures and CPU tuning flags, can change between
@@ -7238,60 +6813,55 @@ releases of Clang and will not match the values defined by other compilers such
as GCC.**
Compiling different TUs depending on these flags (including use of
-``std::hardware_constructive_interference`` or
-``std::hardware_destructive_interference``) with different compilers, macro
+`std::hardware_constructive_interference` or
+`std::hardware_destructive_interference`) with different compilers, macro
definitions, or architecture flags will lead to ODR violations and should be
avoided.
-``#embed`` Parameters
-=====================
+## `#embed` Parameters
+
+### `clang::offset`
-``clang::offset``
------------------
-The ``clang::offset`` embed parameter may appear zero or one time in the
+The `clang::offset` embed parameter may appear zero or one time in the
embed parameter sequence. Its preprocessor argument clause shall be present and
have the form:
..code-block: text
- ( constant-expression )
+> ( constant-expression )
and shall be an integer constant expression. The integer constant expression
-shall not evaluate to a value less than 0. The token ``defined`` shall not
+shall not evaluate to a value less than 0. The token `defined` shall not
appear within the constant expression.
The offset will be used when reading the contents of the embedded resource to
specify the starting offset to begin embedding from. The resources is treated
as being empty if the specified offset is larger than the number of bytes in
-the resource. The offset will be applied *before* any ``limit`` parameters are
+the resource. The offset will be applied *before* any `limit` parameters are
applied.
-Union and aggregate initialization in C
-=======================================
+## Union and aggregate initialization in C
-In C23 (N2900), when an object is initialized from initializer ``= {}``, all
+In C23 (N2900), when an object is initialized from initializer `= {}`, all
elements of arrays, all members of structs, and the first members of unions are
empty-initialized recursively. In addition, all padding bits are initialized to
zero.
Clang guarantees the following behaviors:
-* ``1:`` Clang supports initializer ``= {}`` mentioned above in all C
+- `1:` Clang supports initializer `= {}` mentioned above in all C
standards.
-
-* ``2:`` When unions are initialized from initializer ``= {}``, bytes outside
+- `2:` When unions are initialized from initializer `= {}`, bytes outside
of the first members of unions are also initialized to zero.
-
-* ``3:`` When unions, structures and arrays are initialized from initializer
- ``= { initializer-list }``, all members not explicitly initialized in
+- `3:` When unions, structures and arrays are initialized from initializer
+ `= { initializer-list }`, all members not explicitly initialized in
the initializer list are empty-initialized recursively. In addition, all
padding bits are initialized to zero.
Currently, the above extension only applies to C source code, not C++.
+## Empty Objects in C
-Empty Objects in C
-==================
The declaration of a structure or union type which has no named members is
undefined behavior (C23 and earlier) or implementation-defined behavior (C2y).
Clang allows the declaration of a structure or union type with no named members
@@ -7299,94 +6869,91 @@ in all C language modes. `sizeof` for such a type returns `0`, which is
different behavior than in C++ (where the size of such an object is typically
`1`).
+## Qualified function types in C
-Qualified function types in C
-=============================
Declaring a function with a qualified type in C is undefined behavior (C23 and
earlier) or implementation-defined behavior (C2y). Clang allows a function type
-to be specified with the ``const`` and ``volatile`` qualifiers, but ignores the
+to be specified with the `const` and `volatile` qualifiers, but ignores the
qualifications.
-.. code-block:: c
+```c
+typedef int f(void);
+const volatile f func; // Qualifier on function type has no effect.
+```
- typedef int f(void);
- const volatile f func; // Qualifier on function type has no effect.
-
-
-Note, Clang does not allow an ``_Atomic`` function type because
+Note, Clang does not allow an `_Atomic` function type because
of explicit constraints against atomically qualified (arrays and) function
types.
+## Underspecified Object Declarations in C
-Underspecified Object Declarations in C
-=======================================
-
-C23 introduced the notion of `underspecified object declarations <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3006.htm>`_
+C23 introduced the notion of [underspecified object declarations](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3006.htm)
(note, the final standards text is different from WG14 N3006 due to changes
during national body comment review). When an object is declared with the
-``constexpr`` storage class specifier or has a deduced type (with the ``auto``
+`constexpr` storage class specifier or has a deduced type (with the `auto`
specifier), it is said to be "underspecified". Underspecified declarations have
different requirements than non-underspecified declarations. In particular, the
identifier being declared cannot be used in its initialization. e.g.,
-.. code-block:: c
-
- auto x = x; // Invalid
- constexpr int y = y; // Invalid
+```c
+auto x = x; // Invalid
+constexpr int y = y; // Invalid
+```
The standard leaves it implementation-defined whether an underspecified
declaration may introduce additional identifiers as part of the declaration.
Clang allows additional identifiers to be declared in the following cases:
-* A compound literal may introduce a new type. e.g.,
+- A compound literal may introduce a new type. e.g.,
-.. code-block:: c
+```c
+auto x = (struct S { int x, y; }){ 1, 2 }; // Accepted by Clang
+constexpr int i = (struct T { int x; }){ 1 }.x; // Accepted by Clang
+```
- auto x = (struct S { int x, y; }){ 1, 2 }; // Accepted by Clang
- constexpr int i = (struct T { int x; }){ 1 }.x; // Accepted by Clang
-
-* The type specifier for a ``constexpr`` declaration may define a new type.
+- The type specifier for a `constexpr` declaration may define a new type.
e.g.,
-.. code-block:: c
-
- constexpr struct S { int x; } s = { 1 }; // Accepted by Clang
+```c
+constexpr struct S { int x; } s = { 1 }; // Accepted by Clang
+```
-* A function declarator may be declared with parameters, including parameters
+- A function declarator may be declared with parameters, including parameters
which introduce a new type. e.g.,
-.. code-block:: c
+```c
+constexpr int (*fp)(int x) = nullptr; // Accepted by Clang
+auto f = (void (*)(struct S { int x; } s))nullptr; // Accepted by Clang
+```
- constexpr int (*fp)(int x) = nullptr; // Accepted by Clang
- auto f = (void (*)(struct S { int x; } s))nullptr; // Accepted by Clang
-
-* The initializer may contain a GNU statement expression which defines new
+- The initializer may contain a GNU statement expression which defines new
types or objects. e.g.,
-.. code-block:: c
-
- constexpr int i = ({ // Accepted by Clang
- constexpr int x = 12;
- constexpr struct S { int x; } s = { x };
- s.x;
- });
- auto x = ({ struct S { int x; } s = { 0 }; s; }); // Accepted by Clang
+```c
+constexpr int i = ({ // Accepted by Clang
+ constexpr int x = 12;
+ constexpr struct S { int x; } s = { x };
+ s.x;
+});
+auto x = ({ struct S { int x; } s = { 0 }; s; }); // Accepted by Clang
+```
Clang intentionally does not implement the changed scoping rules from C23
for underspecified declarations. Doing so would significantly complicate the
implementation in order to get reasonable diagnostic behavior and also means
Clang fails to reject some code that should be rejected. e.g.,
-.. code-block:: c
+```c
+// This should be rejected because 'x' is not in scope within the initializer
+// of an underspecified declaration. Clang accepts because it treats the scope
+// of the identifier as beginning immediately after the declarator, same as with
+// a non-underspecified declaration.
+constexpr int x = sizeof(x);
- // This should be rejected because 'x' is not in scope within the initializer
- // of an underspecified declaration. Clang accepts because it treats the scope
- // of the identifier as beginning immediately after the declarator, same as with
- // a non-underspecified declaration.
- constexpr int x = sizeof(x);
+// Clang rejects this code with a diagnostic about using the variable within its
+// own initializer rather than rejecting the code with an undeclared identifier
+// diagnostic.
+auto x = x;
+```
- // Clang rejects this code with a diagnostic about using the variable within its
- // own initializer rather than rejecting the code with an undeclared identifier
- // diagnostic.
- auto x = x;
diff --git a/clang/docs/LeakSanitizer.md b/clang/docs/LeakSanitizer.md
index ecdb87f0b259d..816c976c0e231 100644
--- a/clang/docs/LeakSanitizer.md
+++ b/clang/docs/LeakSanitizer.md
@@ -1,66 +1,61 @@
-================
-LeakSanitizer
-================
+# LeakSanitizer
-.. contents::
- :local:
+```{contents}
+:local: true
+```
-Introduction
-============
+## Introduction
LeakSanitizer is a run-time memory leak detector. It can be combined with
-:doc:`AddressSanitizer` to get both memory error and leak detection, or
+{doc}`AddressSanitizer` to get both memory error and leak detection, or
used in a stand-alone mode. LSan adds almost no performance overhead
until the very end of the process, at which point there is an extra leak
detection phase.
-Usage
-=====
+## Usage
-:doc:`AddressSanitizer`: integrates LeakSanitizer and enables it by default on
+{doc}`AddressSanitizer`: integrates LeakSanitizer and enables it by default on
supported platforms.
-.. code-block:: console
-
- $ cat memory-leak.c
- #include <stdlib.h>
- void *p;
- int main() {
- p = malloc(7);
- p = 0; // The memory is leaked here.
- return 0;
- }
- % clang -fsanitize=address -g memory-leak.c ; ASAN_OPTIONS=detect_leaks=1 ./a.out
- ==23646==ERROR: LeakSanitizer: detected memory leaks
- Direct leak of 7 byte(s) in 1 object(s) allocated from:
- #0 0x4af01b in __interceptor_malloc /projects/compiler-rt/lib/asan/asan_malloc_linux.cc:52:3
- #1 0x4da26a in main memory-leak.c:4:7
- #2 0x7f076fd9cec4 in __libc_start_main libc-start.c:287
- SUMMARY: AddressSanitizer: 7 byte(s) leaked in 1 allocation(s).
+```console
+$ cat memory-leak.c
+#include <stdlib.h>
+void *p;
+int main() {
+ p = malloc(7);
+ p = 0; // The memory is leaked here.
+ return 0;
+}
+% clang -fsanitize=address -g memory-leak.c ; ASAN_OPTIONS=detect_leaks=1 ./a.out
+==23646==ERROR: LeakSanitizer: detected memory leaks
+Direct leak of 7 byte(s) in 1 object(s) allocated from:
+ #0 0x4af01b in __interceptor_malloc /projects/compiler-rt/lib/asan/asan_malloc_linux.cc:52:3
+ #1 0x4da26a in main memory-leak.c:4:7
+ #2 0x7f076fd9cec4 in __libc_start_main libc-start.c:287
+SUMMARY: AddressSanitizer: 7 byte(s) leaked in 1 allocation(s).
+```
To use LeakSanitizer in stand-alone mode, link your program with
-``-fsanitize=leak`` flag. Make sure to use ``clang`` (not ``ld``) for the
+`-fsanitize=leak` flag. Make sure to use `clang` (not `ld`) for the
link step, so that it would link in proper LeakSanitizer run-time library
into the final executable.
-Security Considerations
-=======================
+## Security Considerations
LeakSanitizer is a bug detection tool and its runtime is not meant to be
linked against production executables. While it may be useful for testing,
LeakSanitizer's runtime was not developed with security-sensitive
constraints in mind and may compromise the security of the resulting executable.
-Supported Platforms
-===================
+## Supported Platforms
+
+- Android
+- Fuchsia
+- Linux
+- macOS
+- NetBSD
-* Android
-* Fuchsia
-* Linux
-* macOS
-* NetBSD
+## More Information
-More Information
-================
+[https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer)
-`<https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer>`_
diff --git a/clang/docs/LifetimeSafety.md b/clang/docs/LifetimeSafety.md
index be9b32f8d4b2d..ece233d3ec641 100644
--- a/clang/docs/LifetimeSafety.md
+++ b/clang/docs/LifetimeSafety.md
@@ -1,81 +1,77 @@
-========================
-Lifetime Safety Analysis
-========================
+# Lifetime Safety Analysis
-.. contents::
- :local:
+```{contents}
+:local: true
+```
-Introduction
-============
+## Introduction
Clang Lifetime Safety Analysis is a C++ language extension which warns about
potential dangling pointer defects in code. The analysis aims to detect
-when a pointer, reference or view type (such as ``std::string_view``) refers to an object
+when a pointer, reference or view type (such as `std::string_view`) refers to an object
that is no longer alive, a condition that leads to use-after-free bugs and
security vulnerabilities. Common examples include pointers to stack variables
that have gone out of scope, pointers to heap objects that have been
freed, fields holding views to stack-allocated objects (dangling-field),
returning pointers/references to stack variables (return stack address) or
iterators into container elements invalidated by container operations (e.g.,
-``std::vector::push_back``)
+`std::vector::push_back`)
-The analysis design is inspired by `Polonius, the Rust borrow checker <https://github.com/rust-lang/polonius>`_,
-but adapted to C++ idioms and constraints, such as the lack of exclusivity enforcement (alias-xor-mutability).
-Further details on the analysis method can be found in the `RFC on Discourse <https://discourse.llvm.org/t/rfc-intra-procedural-lifetime-analysis-in-clang/86291/>`_.
+The analysis design is inspired by [Polonius, the Rust borrow checker](https://github.com/rust-lang/polonius),
+but adapted to C++ idioms and constraints, such as the lack of exclusivity enforcement (alias-xor-mutability).
+Further details on the analysis method can be found in the [RFC on Discourse](https://discourse.llvm.org/t/rfc-intra-procedural-lifetime-analysis-in-clang/86291/).
-This is compile-time analysis; there is no run-time overhead.
+This is compile-time analysis; there is no run-time overhead.
It tracks pointer validity through intra-procedural data-flow analysis. While it does
not require lifetime annotations to get started, in their absence, the analysis
treats function calls optimistically, assuming no lifetime effects, thereby potentially missing dangling pointer issues. As more functions are annotated
-with attributes like `clang::lifetimebound <https://clang.llvm.org/docs/AttributeReference.html#lifetimebound>`_, `gsl::Owner <https://clang.llvm.org/docs/AttributeReference.html#gsl-owner>`_, and
-`gsl::Pointer <https://clang.llvm.org/docs/AttributeReference.html#gsl-pointer>`_, the analysis can see through these lifetime contracts and enforce
+with attributes like [clang::lifetimebound](https://clang.llvm.org/docs/AttributeReference.html#lifetimebound), [gsl::Owner](https://clang.llvm.org/docs/AttributeReference.html#gsl-owner), and
+[gsl::Pointer](https://clang.llvm.org/docs/AttributeReference.html#gsl-pointer), the analysis can see through these lifetime contracts and enforce
lifetime safety at call sites with higher accuracy. This approach supports
-gradual adoption in existing codebases.
+gradual adoption in existing codebases.
-.. note::
- This analysis is designed for bug finding, not verification. It may miss some
- lifetime issues and can produce false positives. It does not guarantee the
- absence of all lifetime bugs.
+:::{note}
+This analysis is designed for bug finding, not verification. It may miss some
+lifetime issues and can produce false positives. It does not guarantee the
+absence of all lifetime bugs.
+:::
-Getting Started
-----------------
+### Getting Started
-.. code-block:: c++
+```c++
+#include <string>
+#include <string_view>
- #include <string>
- #include <string_view>
-
- void simple_dangle() {
- std::string_view v;
- {
- std::string s = "hello";
- v = s; // warning: object whose reference is captured does not live long enough
- } // note: destroyed here
- std::cout << v; // note: later used here
- }
+void simple_dangle() {
+ std::string_view v;
+ {
+ std::string s = "hello";
+ v = s; // warning: object whose reference is captured does not live long enough
+ } // note: destroyed here
+ std::cout << v; // note: later used here
+}
+```
This example demonstrates
-a basic use-after-scope bug. The ``std::string_view`` object ``v`` holds a
-reference to ``s``, a ``std::string``. The lifetime of ``s`` ends at the end of
-the inner block, causing ``v`` to become a dangling reference.
-The analysis flags the assignment ``v = s`` as defective because ``s`` is
-destroyed while ``v`` is still alive and points to ``s``, and adds a note
-to where ``v`` is used after ``s`` has been destroyed.
-
-Running The Analysis
---------------------
+a basic use-after-scope bug. The `std::string_view` object `v` holds a
+reference to `s`, a `std::string`. The lifetime of `s` ends at the end of
+the inner block, causing `v` to become a dangling reference.
+The analysis flags the assignment `v = s` as defective because `s` is
+destroyed while `v` is still alive and points to `s`, and adds a note
+to where `v` is used after `s` has been destroyed.
-To run the analysis, compile with the ``-Wlifetime-safety-permissive`` flag, e.g.
+### Running The Analysis
-.. code-block:: bash
+To run the analysis, compile with the `-Wlifetime-safety-permissive` flag, e.g.
- clang -c -Wlifetime-safety-permissive example.cpp
+```bash
+clang -c -Wlifetime-safety-permissive example.cpp
+```
This flag enables a core set of lifetime safety checks. For more fine-grained
-control over warnings, see :ref:`warning_flags`.
+control over warnings, see {ref}`warning_flags`.
-Lifetime Annotations
-====================
+## Lifetime Annotations
While lifetime analysis can detect many issues without annotations, its
precision increases significantly when types and functions are annotated with
@@ -83,163 +79,159 @@ lifetime contracts. These annotations clarify ownership semantics and lifetime
dependencies, enabling the analysis to reason more accurately about pointer
validity across function calls.
-Owner and Pointer Types
------------------------
+### Owner and Pointer Types
Lifetime analysis distinguishes between types that own the data they point to
(Owners) and types that are non-owning views or references to data owned by
others (Pointers). This distinction is made using GSL-style attributes:
-* ``[[gsl::Owner]]``: For types that manage the lifetime of a resource,
- like ``std::string``, ``std::vector``, ``std::unique_ptr``.
-* ``[[gsl::Pointer]]``: For non-owning types that borrow resources,
- like ``std::string_view``, or raw pointers (which are
- implicitly treated as pointers).
+- `[[gsl::Owner]]`: For types that manage the lifetime of a resource,
+ like `std::string`, `std::vector`, `std::unique_ptr`.
+- `[[gsl::Pointer]]`: For non-owning types that borrow resources,
+ like `std::string_view`, or raw pointers (which are
+ implicitly treated as pointers).
-Many common STL types, such as ``std::string_view`` and container iterators,
+Many common STL types, such as `std::string_view` and container iterators,
are automatically recognized as Pointers or Owners. You can annotate your own
types using these attributes:
-.. code-block:: c++
-
- #include <string>
- #include <string_view>
-
- // Owner type
- struct [[gsl::Owner]] MyObj {
- std::string Data = "Hello";
- };
-
- // View type
- struct [[gsl::Pointer]] View {
- std::string_view SV;
- View() = default;
- View(const MyObj& O) : SV(O.Data) {}
- void use() const {}
- };
-
- void test() {
- View v;
- {
- MyObj o;
- v = o; // warning: object whose reference is captured does not live long enough
- } // note: destroyed here
- v.use(); // note: later used here
- }
+```c++
+#include <string>
+#include <string_view>
+
+// Owner type
+struct [[gsl::Owner]] MyObj {
+ std::string Data = "Hello";
+};
+
+// View type
+struct [[gsl::Pointer]] View {
+ std::string_view SV;
+ View() = default;
+ View(const MyObj& O) : SV(O.Data) {}
+ void use() const {}
+};
+
+void test() {
+ View v;
+ {
+ MyObj o;
+ v = o; // warning: object whose reference is captured does not live long enough
+ } // note: destroyed here
+ v.use(); // note: later used here
+}
+```
Without these annotations, the analysis may not be able to determine whether a
type is owning or borrowing, which can affect analysis precision. For more
details on these attributes, see the Clang attribute reference for
-`gsl::Owner <https://clang.llvm.org/docs/AttributeReference.html#gsl-owner>`_ and
-`gsl::Pointer <https://clang.llvm.org/docs/AttributeReference.html#gsl-pointer>`_.
-
-.. note::
- Types with mixed ownership semantics (owning some data while holding views to
- other data) or types with multiple view fields with different lifetimes should
- not be annotated. The analysis does not yet support expressing such nuanced
- lifetime relationships.
- Future enhancements, such as named lifetimes, may provide better support for
- these patterns.
-
-LifetimeBound
--------------
-
-The ``[[clang::lifetimebound]]`` attribute can be applied to function parameters
-or to the implicit ``this`` parameter of a method (by placing it after the
+[gsl::Owner](https://clang.llvm.org/docs/AttributeReference.html#gsl-owner) and
+[gsl::Pointer](https://clang.llvm.org/docs/AttributeReference.html#gsl-pointer).
+
+:::{note}
+Types with mixed ownership semantics (owning some data while holding views to
+other data) or types with multiple view fields with different lifetimes should
+not be annotated. The analysis does not yet support expressing such nuanced
+lifetime relationships.
+Future enhancements, such as named lifetimes, may provide better support for
+these patterns.
+:::
+
+### LifetimeBound
+
+The `[[clang::lifetimebound]]` attribute can be applied to function parameters
+or to the implicit `this` parameter of a method (by placing it after the
method declarator). It indicates that the returned value becomes invalid when
-the attributed parameter or ``this`` object is destroyed.
+the attributed parameter or `this` object is destroyed.
This is crucial for functions that return views or references to their
arguments.
-.. code-block:: c++
-
- #include <string>
- #include <string_view>
+```c++
+#include <string>
+#include <string_view>
- struct MyOwner {
- std::string s;
- std::string_view getView() const [[clang::lifetimebound]] { return s; }
- };
+struct MyOwner {
+ std::string s;
+ std::string_view getView() const [[clang::lifetimebound]] { return s; }
+};
- void test_lifetimebound() {
- std::string_view sv;
- sv = MyOwner().getView(); // getView() is called on a temporary MyOwner
- // warning: object whose reference is captured does not live long enough
- // note: destroyed here
- (void)sv; // note: later used here
- }
+void test_lifetimebound() {
+ std::string_view sv;
+ sv = MyOwner().getView(); // getView() is called on a temporary MyOwner
+ // warning: object whose reference is captured does not live long enough
+ // note: destroyed here
+ (void)sv; // note: later used here
+}
+```
-Without ``[[clang::lifetimebound]]`` on ``getView()``, the analysis would not
-know that the value returned by ``getView()`` depends on the temporary
-``MyOwner`` object, and it would not be able to diagnose the dangling ``sv``.
+Without `[[clang::lifetimebound]]` on `getView()`, the analysis would not
+know that the value returned by `getView()` depends on the temporary
+`MyOwner` object, and it would not be able to diagnose the dangling `sv`.
The analysis also tracks record types returned from functions and constructors
-with ``[[clang::lifetimebound]]`` annotated parameters:
+with `[[clang::lifetimebound]]` annotated parameters:
-.. code-block:: c++
+```c++
+#include <string>
- #include <string>
+struct StringView {
+ StringView();
+ StringView(const std::string &s [[clang::lifetimebound]]);
+};
- struct StringView {
- StringView();
- StringView(const std::string &s [[clang::lifetimebound]]);
- };
+StringView getStringView(const std::string &s [[clang::lifetimebound]]);
- StringView getStringView(const std::string &s [[clang::lifetimebound]]);
+void test() {
+ StringView a, b;
+ {
+ std::string s = "temp";
+ StringView tmp(s); // warning: object whose reference is captured does not live long enough
+ a = tmp;
+ b = getStringView(s); // warning: object whose reference is captured does not live long enough
+ } // note: destroyed here
+ (void)a; // note: later used here
+ (void)b; // note: later used here
+}
+```
- void test() {
- StringView a, b;
- {
- std::string s = "temp";
- StringView tmp(s); // warning: object whose reference is captured does not live long enough
- a = tmp;
- b = getStringView(s); // warning: object whose reference is captured does not live long enough
- } // note: destroyed here
- (void)a; // note: later used here
- (void)b; // note: later used here
- }
-
-For more details, see `lifetimebound <https://clang.llvm.org/docs/AttributeReference.html#lifetimebound>`_.
+For more details, see [lifetimebound](https://clang.llvm.org/docs/AttributeReference.html#lifetimebound).
-NoEscape
---------
+### NoEscape
-.. _Wlifetime-safety-noescape:
+(wlifetime-safety-noescape)=
-The ``[[clang::noescape]]`` attribute can be applied to function parameters of
+The `[[clang::noescape]]` attribute can be applied to function parameters of
pointer or reference type. It indicates that the function will not allow the
parameter to escape its scope, for example, by returning it or assigning it to
a field or global variable. This is useful for parameters passed to callbacks
or visitors that are only used during the call and not stored.
-For more details, see `noescape <https://clang.llvm.org/docs/AttributeReference.html#noescape>`_.
-
-Checks Performed
-================
+For more details, see [noescape](https://clang.llvm.org/docs/AttributeReference.html#noescape).
+## Checks Performed
-.. raw:: html
+```{raw} html
+<style>
+/* Align text to left and add red/green colors */
+table.colored-code-table td, table.colored-code-table th { text-align: left !important; }
+table.colored-code-table td:first-child, table.colored-code-table th:first-child { background-color: #ffeaea !important; }
+table.colored-code-table td:nth-child(2), table.colored-code-table th:nth-child(2) { background-color: #eafaea !important; }
+table.colored-code-table td .highlight, table.colored-code-table td pre { background-color: transparent !important; border: none !important; }
- <style>
- /* Align text to left and add red/green colors */
- table.colored-code-table td, table.colored-code-table th { text-align: left !important; }
- table.colored-code-table td:first-child, table.colored-code-table th:first-child { background-color: #ffeaea !important; }
- table.colored-code-table td:nth-child(2), table.colored-code-table th:nth-child(2) { background-color: #eafaea !important; }
- table.colored-code-table td .highlight, table.colored-code-table td pre { background-color: transparent !important; border: none !important; }
+div.bad-code { background-color: #ffeaea !important; padding: 5px; border-left: 4px solid #ff6b6b; text-align: left !important; }
+div.bad-code .highlight, div.bad-code pre { background-color: transparent !important; border: none !important; }
- div.bad-code { background-color: #ffeaea !important; padding: 5px; border-left: 4px solid #ff6b6b; text-align: left !important; }
- div.bad-code .highlight, div.bad-code pre { background-color: transparent !important; border: none !important; }
+div.good-code { background-color: #eafaea !important; padding: 5px; border-left: 4px solid #51cf66; text-align: left !important; }
+div.good-code .highlight, div.good-code pre { background-color: transparent !important; border: none !important; }
+</style>
+```
- div.good-code { background-color: #eafaea !important; padding: 5px; border-left: 4px solid #51cf66; text-align: left !important; }
- div.good-code .highlight, div.good-code pre { background-color: transparent !important; border: none !important; }
- </style>
-
-Use after scope
----------------
+### Use after scope
This check warns when a pointer or reference is used after the stack variable
it refers to has gone out of scope.
+```{eval-rst}
.. list-table::
:widths: 50 50
:header-rows: 1
@@ -269,13 +261,14 @@ it refers to has gone out of scope.
}
(void)*p;
}
+```
-Use after free
---------------
+### Use after free
This check warns when a pointer or reference is used after the object it refers
to has been freed.
+```{eval-rst}
.. list-table::
:widths: 50 50
:header-rows: 1
@@ -299,14 +292,15 @@ to has been freed.
(void)*p;
delete p; // OK!
}
+```
-Return of stack address
------------------------
+### Return of stack address
This check warns when a function returns a pointer or reference to a
stack-allocated variable, which will be destroyed when the function returns,
leaving the caller with a dangling pointer.
+```{eval-rst}
.. list-table::
:widths: 50 50
:header-rows: 1
@@ -338,13 +332,14 @@ leaving the caller with a dangling pointer.
return result; // OK!
}
+```
-Dangling field
---------------
+### Dangling field
This check warns when a constructor or method assigns a pointer to a
stack-allocated variable or temporary to a field of the class.
+```{eval-rst}
.. list-table::
:widths: 50 50
:header-rows: 1
@@ -385,20 +380,22 @@ stack-allocated variable or temporary to a field of the class.
};
};
+```
-Use after invalidation (experimental)
--------------------------------------
+### Use after invalidation (experimental)
This check warns when a pointer, reference or view is used after an operation
that may have invalidated it. This includes references to container elements
used after a container operation, and pointers to objects managed by owners such
-as ``std::unique_ptr`` after operations like ``reset``. For example, adding
-elements to ``std::vector`` may cause reallocation, invalidating all existing
+as `std::unique_ptr` after operations like `reset`. For example, adding
+elements to `std::vector` may cause reallocation, invalidating all existing
iterators, pointers and references to its elements.
-.. note::
- Invalidation checking is highly experimental and may produce false positives.
+:::{note}
+Invalidation checking is highly experimental and may produce false positives.
+:::
+```{eval-rst}
.. list-table::
:widths: 50 50
:header-rows: 1
@@ -427,123 +424,119 @@ iterators, pointers and references to its elements.
int* p = &v[0]; // OK!
*p = 10;
}
+```
The analysis also treats explicit destruction as invalidation. Explicit
-destructor calls and ``std::destroy_at`` invalidate pointers, references and
+destructor calls and `std::destroy_at` invalidate pointers, references and
views into the destroyed object.
-.. code-block:: c++
+```c++
+#include <memory>
+#include <string>
- #include <memory>
- #include <string>
+void explicit_destruction() {
+ std::string s = "hello";
+ const char *p = s.data(); // warning: object whose reference is captured is later invalidated
+ std::destroy_at(&s); // note: invalidated here
+ (void)*p; // note: later used here
+}
- void explicit_destruction() {
- std::string s = "hello";
- const char *p = s.data(); // warning: object whose reference is captured is later invalidated
- std::destroy_at(&s); // note: invalidated here
- (void)*p; // note: later used here
- }
+void unique_ptr_reset() {
+ std::unique_ptr<int> u(new int(0));
+ int *p = u.get(); // warning: object whose reference is captured is later invalidated
+ u.reset(); // note: invalidated here
+ (void)*p; // note: later used here
+}
+```
- void unique_ptr_reset() {
- std::unique_ptr<int> u(new int(0));
- int *p = u.get(); // warning: object whose reference is captured is later invalidated
- u.reset(); // note: invalidated here
- (void)*p; // note: later used here
- }
-
-Annotation Inference and Suggestions
-====================================
+## Annotation Inference and Suggestions
In addition to detecting lifetime violations, the analysis can suggest adding
-``[[clang::lifetimebound]]`` to function parameters or methods when it detects
-that a pointer/reference to a parameter or ``this`` escapes via the return
+`[[clang::lifetimebound]]` to function parameters or methods when it detects
+that a pointer/reference to a parameter or `this` escapes via the return
value. This helps improve API contracts and allows the analysis to perform
more accurate checks in calling code.
-To enable annotation suggestions, use ``-Wlifetime-safety-suggestions``.
+To enable annotation suggestions, use `-Wlifetime-safety-suggestions`.
-Fix-it hints normally insert ``[[clang::lifetimebound]]``. If a visible
-object-like macro expands to ``[[clang::lifetimebound]]`` or
-``__attribute__((lifetimebound))``, Clang will use the last such macro
+Fix-it hints normally insert `[[clang::lifetimebound]]`. If a visible
+object-like macro expands to `[[clang::lifetimebound]]` or
+`__attribute__((lifetimebound))`, Clang will use the last such macro
visible at the insertion point. To force a project-specific macro spelling,
-use ``-lifetime-safety-lifetimebound-macro=<macro>``.
-
-.. code-block:: c++
+use `-lifetime-safety-lifetimebound-macro=<macro>`.
- #include <string_view>
+```c++
+#include <string_view>
- // The analysis will suggest adding [[clang::lifetimebound]] to 'a'.
- std::string_view return_view(std::string_view a) {
- // ^^^^^^^^^^^^^^^^^^
- // warning: parameter 'a' should be marked [[clang::lifetimebound]]
- return a; // note: param returned here
- }
+// The analysis will suggest adding [[clang::lifetimebound]] to 'a'.
+std::string_view return_view(std::string_view a) {
+ // ^^^^^^^^^^^^^^^^^^
+ // warning: parameter 'a' should be marked [[clang::lifetimebound]]
+ return a; // note: param returned here
+}
+```
-Translation-Unit-Wide Analysis and Inference
---------------------------------------------
+### Translation-Unit-Wide Analysis and Inference
By default, lifetime analysis is intra-procedural for error checking.
However, for annotation inference to be effective, lifetime information needs
to propagate across function calls. You can enable experimental
translation-unit-wide analysis using:
-* ``-flifetime-safety-inference``: Enables inference of ``lifetimebound``
- attributes across functions in a TU.
-* ``-fexperimental-lifetime-safety-tu-analysis``: Enables TU-wide analysis
- for better inference results.
+- `-flifetime-safety-inference`: Enables inference of `lifetimebound`
+ attributes across functions in a TU.
+- `-fexperimental-lifetime-safety-tu-analysis`: Enables TU-wide analysis
+ for better inference results.
-.. _warning_flags:
+(warning-flags)=
-Warning flags
-=============
+## Warning flags
Lifetime safety warnings are organized into hierarchical groups, allowing users to
-enable categories of checks incrementally. For example, ``-Wlifetime-safety``
-enables all dangling pointer checks, while ``-Wlifetime-safety-permissive``
+enable categories of checks incrementally. For example, `-Wlifetime-safety`
+enables all dangling pointer checks, while `-Wlifetime-safety-permissive`
enables only the high-confidence subset of these checks.
-* ``-Wlifetime-safety-all``: Enables all lifetime safety warnings, including
- dangling pointer checks, annotation suggestions, and annotation validations.
-
-* ``-Wlifetime-safety``: Enables dangling pointer checks from both the ``permissive`` and ``strict`` groups listed below.
-
- * ``-Wlifetime-safety-permissive``: Enables high-confidence checks for dangling pointers. **Recommended for initial adoption.**
+- `-Wlifetime-safety-all`: Enables all lifetime safety warnings, including
+ : dangling pointer checks, annotation suggestions, and annotation validations.
+- `-Wlifetime-safety`: Enables dangling pointer checks from both the `permissive` and `strict` groups listed below.
- * ``-Wlifetime-safety-use-after-scope``: Warns when a pointer to a stack variable is used after the variable's lifetime has ended.
- * ``-Wlifetime-safety-use-after-free``: Warns when a pointer to an object is used after it's been freed.
- * ``-Wlifetime-safety-return-stack-addr``: Warns when a function returns a pointer or reference to one of its local stack variables.
- * ``-Wlifetime-safety-dangling-field``: Warns when a class field is assigned a pointer to a temporary or stack variable whose lifetime is shorter than the class instance.
-
- * ``-Wlifetime-safety-strict``: Enables stricter and experimental checks. These may produce false positives in code that uses move semantics heavily, as the analysis might conservatively assume a use-after-free even if ownership was transferred.
+> - `-Wlifetime-safety-permissive`: Enables high-confidence checks for dangling pointers. **Recommended for initial adoption.**
+>
+> - `-Wlifetime-safety-use-after-scope`: Warns when a pointer to a stack variable is used after the variable's lifetime has ended.
+> - `-Wlifetime-safety-use-after-free`: Warns when a pointer to an object is used after it's been freed.
+> - `-Wlifetime-safety-return-stack-addr`: Warns when a function returns a pointer or reference to one of its local stack variables.
+> - `-Wlifetime-safety-dangling-field`: Warns when a class field is assigned a pointer to a temporary or stack variable whose lifetime is shorter than the class instance.
+>
+> - `-Wlifetime-safety-strict`: Enables stricter and experimental checks. These may produce false positives in code that uses move semantics heavily, as the analysis might conservatively assume a use-after-free even if ownership was transferred.
+>
+> - `-Wlifetime-safety-use-after-scope-moved`: Same as `-Wlifetime-safety-use-after-scope` but for cases where the variable may have been moved from before its destruction.
+> - `-Wlifetime-safety-return-stack-addr-moved`: Same as `-Wlifetime-safety-return-stack-addr` but for cases where the variable may have been moved from.
+> - `-Wlifetime-safety-dangling-field-moved`: Same as `-Wlifetime-safety-dangling-field` but for cases where the variable may have been moved from.
+> - `-Wlifetime-safety-invalidation`: Warns when a pointer, reference, iterator or view is used after an operation that may invalidate it, such as container mutation or explicit destruction (e.g., `std::unique_ptr::reset`, `std::destroy_at`) (Experimental).
- * ``-Wlifetime-safety-use-after-scope-moved``: Same as ``-Wlifetime-safety-use-after-scope`` but for cases where the variable may have been moved from before its destruction.
- * ``-Wlifetime-safety-return-stack-addr-moved``: Same as ``-Wlifetime-safety-return-stack-addr`` but for cases where the variable may have been moved from.
- * ``-Wlifetime-safety-dangling-field-moved``: Same as ``-Wlifetime-safety-dangling-field`` but for cases where the variable may have been moved from.
- * ``-Wlifetime-safety-invalidation``: Warns when a pointer, reference, iterator or view is used after an operation that may invalidate it, such as container mutation or explicit destruction (e.g., ``std::unique_ptr::reset``, ``std::destroy_at``) (Experimental).
+- `-Wlifetime-safety-suggestions`: Enables suggestions to add `[[clang::lifetimebound]]` to function parameters and `this` parameters.
-* ``-Wlifetime-safety-suggestions``: Enables suggestions to add ``[[clang::lifetimebound]]`` to function parameters and ``this`` parameters.
+> - `-Wlifetime-safety-intra-tu-suggestions`: Suggestions for functions local to the translation unit.
+> - `-Wlifetime-safety-cross-tu-suggestions`: Suggestions for functions visible across translation units (e.g., in headers).
- * ``-Wlifetime-safety-intra-tu-suggestions``: Suggestions for functions local to the translation unit.
- * ``-Wlifetime-safety-cross-tu-suggestions``: Suggestions for functions visible across translation units (e.g., in headers).
+- `-Wlifetime-safety-validations`: Enables checks that validate existing lifetime annotations.
-* ``-Wlifetime-safety-validations``: Enables checks that validate existing lifetime annotations.
+ - `-Wlifetime-safety-noescape`: Warns when a parameter marked with `[[clang::noescape]]` escapes the function.
+ - `-Wlifetime-safety-lifetimebound-violation`: Warns when the analysis cannot verify that the return value can be lifetime bound to a parameter marked with `[[clang::lifetimebound]]`.
- * ``-Wlifetime-safety-noescape``: Warns when a parameter marked with ``[[clang::noescape]]`` escapes the function.
- * ``-Wlifetime-safety-lifetimebound-violation``: Warns when the analysis cannot verify that the return value can be lifetime bound to a parameter marked with ``[[clang::lifetimebound]]``.
+## Limitations
-Limitations
-===========
+### Move Semantics
-Move Semantics
---------------
The analysis does not currently track ownership transfers through move operations.
Instead, it uses scope-based lifetime tracking: when an owner goes out of scope,
the analysis assumes the resource is destroyed, even if ownership was transferred
-via ``std::move()`` or ``std::unique_ptr::release()``.
+via `std::move()` or `std::unique_ptr::release()`.
This means that if a pointer or view is created from an owner, and that owner is
later moved-from and goes out of scope, the analysis will issue a
-``-Wlifetime-safety-*-moved`` warning. This warning indicates that the pointer
+`-Wlifetime-safety-*-moved` warning. This warning indicates that the pointer
may be dangling, even though the resource may still be alive under a new owner.
These are often false positives when ownership has been safely transferred.
@@ -554,6 +547,7 @@ owner that will go out of scope.
For example:
+```{eval-rst}
.. list-table::
:widths: 50 50
:header-rows: 1
@@ -596,103 +590,104 @@ For example:
}
use(p);
}
+```
-The same principle applies when moving ownership using ``std::unique_ptr::release()``:
+The same principle applies when moving ownership using `std::unique_ptr::release()`:
-.. code-block:: c++
- :class: bad-code
+```{code-block} c++
+:class: bad-code
- #include <memory>
- #include <utility>
+#include <memory>
+#include <utility>
- void use(int*);
- void take_ownership(int*);
+void use(int*);
+void take_ownership(int*);
- void test_aliasing_before_release() {
- int* p;
- {
- auto u = std::make_unique<int>(1);
- p = u.get();
- // ^ warning: 'u' does not live long enough!
- take_ownership(u.release());
- }
- use(p);
+void test_aliasing_before_release() {
+ int* p;
+ {
+ auto u = std::make_unique<int>(1);
+ p = u.get();
+ // ^ warning: 'u' does not live long enough!
+ take_ownership(u.release());
}
+ use(p);
+}
+```
+
+### `std::unique_ptr` with custom deleters
-``std::unique_ptr`` with custom deleters
-----------------------------------------
The analysis assumes standard ownership semantics for owner types like
-``std::unique_ptr``: when a ``unique_ptr`` goes out of scope, it is assumed
+`std::unique_ptr`: when a `unique_ptr` goes out of scope, it is assumed
that the owned object is destroyed and its memory is deallocated.
-However, ``std::unique_ptr`` can be used with a custom deleter that modifies
+However, `std::unique_ptr` can be used with a custom deleter that modifies
this behavior. For example, a custom deleter might keep the memory alive
by transferring it to a memory pool, or simply do nothing, allowing
another system to manage the lifetime.
Because the analysis relies on scope-based lifetime for owners, it does not
support custom deleters that extend the lifetime of the owned object beyond
-the lifetime of the ``std::unique_ptr``. In such cases, the analysis will
-assume the object is destroyed when the ``std::unique_ptr`` goes out of scope,
+the lifetime of the `std::unique_ptr`. In such cases, the analysis will
+assume the object is destroyed when the `std::unique_ptr` goes out of scope,
leading to false positive warnings if pointers to the object are used afterward.
-.. code-block:: c++
-
- #include <memory>
-
- void use(int*);
+```c++
+#include <memory>
- struct NoOpDeleter {
- void operator()(int* p) const {
- // Do not delete p, memory is managed elsewhere.
- }
- };
+void use(int*);
- void test_custom_deleter() {
- int* p;
- {
- std::unique_ptr<int, NoOpDeleter> u(new int(42));
- p = u.get(); // warning: object whose reference is captured does not live long enough
- } // note: destroyed here
- // With NoOpDeleter, p would still be valid here.
- // But analysis assumes standard unique_ptr semantics and memory being freed.
- use(p); // note: later used here
+struct NoOpDeleter {
+ void operator()(int* p) const {
+ // Do not delete p, memory is managed elsewhere.
}
+};
+
+void test_custom_deleter() {
+ int* p;
+ {
+ std::unique_ptr<int, NoOpDeleter> u(new int(42));
+ p = u.get(); // warning: object whose reference is captured does not live long enough
+ } // note: destroyed here
+ // With NoOpDeleter, p would still be valid here.
+ // But analysis assumes standard unique_ptr semantics and memory being freed.
+ use(p); // note: later used here
+}
+```
+
+### Dangling Fields
-Dangling Fields
----------------
The lifetime analysis is intra-procedural. It analyzes one function or method at
a time.
This means if a field is assigned a pointer to a local variable or temporary
inside a constructor or method, and that local's lifetime ends before the method
-returns, the analysis will issue a ``-Wlifetime-safety-dangling-field`` warning.
+returns, the analysis will issue a `-Wlifetime-safety-dangling-field` warning.
It must do so even if no *other* method of the class ever accesses this field,
because it cannot see how other methods are implemented or used.
-.. code-block:: c++
+```c++
+#include <string>
+#include <string_view>
- #include <string>
- #include <string_view>
+struct MyWidget {
+ std::string_view name_; // note: this field dangles
+ MyWidget(std::string name) : name_(name) {} // warning: address of stack memory escapes to a field
+ const char* data() { return name_.data(); } // Potential use-after-free if called
+};
+```
- struct MyWidget {
- std::string_view name_; // note: this field dangles
- MyWidget(std::string name) : name_(name) {} // warning: address of stack memory escapes to a field
- const char* data() { return name_.data(); } // Potential use-after-free if called
- };
-
-In this case, ``name_`` dangles after the constructor finishes.
-Even if ``data()`` is never called, the analysis flags the dangling assignment
+In this case, `name_` dangles after the constructor finishes.
+Even if `data()` is never called, the analysis flags the dangling assignment
in the constructor because it represents a latent bug.
The recommended approach is to ensure fields only point to objects that outlive
-the field itself, for example by storing an owned object (e.g., ``std::string``)
-or ensuring the borrowed object (e.g., one passed by ``const&``) has a
+the field itself, for example by storing an owned object (e.g., `std::string`)
+or ensuring the borrowed object (e.g., one passed by `const&`) has a
sufficient lifetime.
-
-Performance
-===========
+## Performance
Lifetime analysis relies on Clang's CFG (Control Flow Graph). For functions
with very large or complex CFGs, analysis time can sometimes be significant. To mitigate
this, the analysis allows to skip functions where the number of CFG blocks exceeds
-a certain threshold, controlled by the ``-lifetime-safety-max-cfg-blocks=N`` language
+a certain threshold, controlled by the `-lifetime-safety-max-cfg-blocks=N` language
option.
+
diff --git a/clang/docs/MemorySanitizer.md b/clang/docs/MemorySanitizer.md
index b40846a75073c..b987167cdc6a3 100644
--- a/clang/docs/MemorySanitizer.md
+++ b/clang/docs/MemorySanitizer.md
@@ -1,12 +1,10 @@
-================
-MemorySanitizer
-================
+# MemorySanitizer
-.. contents::
- :local:
+```{contents}
+:local: true
+```
-Introduction
-============
+## Introduction
MemorySanitizer is a detector of uninitialized memory use. It consists of a
compiler instrumentation module and a run-time library.
@@ -15,112 +13,105 @@ Typical slowdown introduced by MemorySanitizer is **3x**.
Here is a not comprehensive of list cases when MemorySanitizer will report an error:
-* Uninitialized value was used in a conditional branch.
-* Uninitialized pointer was used for memory accesses.
-* Uninitialized value was passed or returned from a function call, which is considered an undefined behavior. The check can be disabled with ``-fno-sanitize-memory-param-retval``.
-* Uninitialized data was passed into some libc calls.
+- Uninitialized value was used in a conditional branch.
+- Uninitialized pointer was used for memory accesses.
+- Uninitialized value was passed or returned from a function call, which is considered an undefined behavior. The check can be disabled with `-fno-sanitize-memory-param-retval`.
+- Uninitialized data was passed into some libc calls.
-How to build
-============
+## How to build
-Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>`_.
+Build LLVM/Clang with [CMake](https://llvm.org/docs/CMake.html).
-Usage
-=====
+## Usage
-Simply compile and link your program with ``-fsanitize=memory`` flag.
+Simply compile and link your program with `-fsanitize=memory` flag.
The MemorySanitizer run-time library should be linked to the final
-executable, so make sure to use ``clang`` (not ``ld``) for the final
+executable, so make sure to use `clang` (not `ld`) for the final
link step. When linking shared libraries, the MemorySanitizer run-time
-is not linked, so ``-Wl,-z,defs`` may cause link errors (don't use it
-with MemorySanitizer). To get a reasonable performance add ``-O1`` or
+is not linked, so `-Wl,-z,defs` may cause link errors (don't use it
+with MemorySanitizer). To get a reasonable performance add `-O1` or
higher. To get meaningful stack traces in error messages add
-``-fno-omit-frame-pointer``. To get perfect stack traces you may need
-to disable inlining (just use ``-O1``) and tail call elimination
-(``-fno-optimize-sibling-calls``).
+`-fno-omit-frame-pointer`. To get perfect stack traces you may need
+to disable inlining (just use `-O1`) and tail call elimination
+(`-fno-optimize-sibling-calls`).
-.. code-block:: console
+```console
+% cat umr.cc
+#include <stdio.h>
- % cat umr.cc
- #include <stdio.h>
+int main(int argc, char** argv) {
+ int* a = new int[10];
+ a[5] = 0;
+ if (a[argc])
+ printf("xx\n");
+ return 0;
+}
- int main(int argc, char** argv) {
- int* a = new int[10];
- a[5] = 0;
- if (a[argc])
- printf("xx\n");
- return 0;
- }
-
- % clang -fsanitize=memory -fno-omit-frame-pointer -g -O2 umr.cc
+% clang -fsanitize=memory -fno-omit-frame-pointer -g -O2 umr.cc
+```
If a bug is detected, the program will print an error message to
stderr and exit with a non-zero exit code.
-.. code-block:: console
-
- % ./a.out
- WARNING: MemorySanitizer: use-of-uninitialized-value
- #0 0x7f45944b418a in main umr.cc:6
- #1 0x7f45938b676c in __libc_start_main libc-start.c:226
+```console
+% ./a.out
+WARNING: MemorySanitizer: use-of-uninitialized-value
+ #0 0x7f45944b418a in main umr.cc:6
+ #1 0x7f45938b676c in __libc_start_main libc-start.c:226
+```
By default, MemorySanitizer exits on the first detected error. If you
find the error report hard to understand, try enabling
-:ref:`origin tracking <msan-origins>`.
+{ref}`origin tracking <msan-origins>`.
-``__has_feature(memory_sanitizer)``
-------------------------------------
+### `__has_feature(memory_sanitizer)`
In some cases one may need to execute different code depending on
-whether MemorySanitizer is enabled. :ref:`\_\_has\_feature
+whether MemorySanitizer is enabled. {ref}`\_\_has\_feature
<langext-__has_feature-__has_extension>` can be used for this purpose.
-.. code-block:: c
+```c
+#if defined(__has_feature)
+# if __has_feature(memory_sanitizer)
+// code that builds only under MemorySanitizer
+# endif
+#endif
+```
- #if defined(__has_feature)
- # if __has_feature(memory_sanitizer)
- // code that builds only under MemorySanitizer
- # endif
- #endif
+### `__attribute__((no_sanitize("memory")))`
-``__attribute__((no_sanitize("memory")))``
------------------------------------------------
+Some code should not be checked by MemorySanitizer. One may use the function
+attribute `no_sanitize("memory")` to disable uninitialized checks in a
+particular function. MemorySanitizer may still instrument such functions to
+avoid false positives. This attribute may not be supported by other compilers,
+so we suggest to use it together with `__has_feature(memory_sanitizer)`.
-Some code should not be checked by MemorySanitizer. One may use the function
-attribute ``no_sanitize("memory")`` to disable uninitialized checks in a
-particular function. MemorySanitizer may still instrument such functions to
-avoid false positives. This attribute may not be supported by other compilers,
-so we suggest to use it together with ``__has_feature(memory_sanitizer)``.
+### `__attribute__((disable_sanitizer_instrumentation))`
-``__attribute__((disable_sanitizer_instrumentation))``
---------------------------------------------------------
-
-The ``disable_sanitizer_instrumentation`` attribute can be applied to functions
+The `disable_sanitizer_instrumentation` attribute can be applied to functions
to prevent all kinds of instrumentation. As a result, it may introduce false
positives and therefore should be used with care, and only if absolutely
required; for example for certain code that cannot tolerate any instrumentation
-and resulting side-effects. This attribute overrides ``no_sanitize("memory")``.
-
-Interaction of Inlining with Disabling Sanitizer Instrumentation
------------------------------------------------------------------
+and resulting side-effects. This attribute overrides `no_sanitize("memory")`.
-* A `no_sanitize` function will not be inlined heuristically by the compiler into a sanitized function.
-* An `always_inline` function will adopt the instrumentation status of the function it is inlined into.
-* Forcibly combining `no_sanitize` and ``__attribute__((always_inline))`` is not supported, and will often lead to unexpected results. To avoid mixing these attributes, use:
+### Interaction of Inlining with Disabling Sanitizer Instrumentation
-.. code-block:: c
+- A `no_sanitize` function will not be inlined heuristically by the compiler into a sanitized function.
+- An `always_inline` function will adopt the instrumentation status of the function it is inlined into.
+- Forcibly combining `no_sanitize` and `__attribute__((always_inline))` is not supported, and will often lead to unexpected results. To avoid mixing these attributes, use:
- // Note, __has_feature test for sanitizers is deprecated, and Clang will support __SANITIZE_<sanitizer>__ similar to GCC.
- #if __has_feature(memory_sanitizer) || defined(__SANITIZE_MEMORY__) || ... <other sanitizers>
- #define ALWAYS_INLINE_IF_UNINSTRUMENTED
- #else
- #define ALWAYS_INLINE_IF_UNINSTRUMENTED __attribute__((always_inline))
- #endif
+```c
+// Note, __has_feature test for sanitizers is deprecated, and Clang will support __SANITIZE_<sanitizer>__ similar to GCC.
+#if __has_feature(memory_sanitizer) || defined(__SANITIZE_MEMORY__) || ... <other sanitizers>
+#define ALWAYS_INLINE_IF_UNINSTRUMENTED
+#else
+#define ALWAYS_INLINE_IF_UNINSTRUMENTED __attribute__((always_inline))
+#endif
+```
-Explicit Sanitizer Checks with ``__builtin_allow_sanitize_check``
------------------------------------------------------------------
+### Explicit Sanitizer Checks with `__builtin_allow_sanitize_check`
-The ``__builtin_allow_sanitize_check("memory")`` builtin can be used to
+The `__builtin_allow_sanitize_check("memory")` builtin can be used to
conditionally execute code depending on whether MemorySanitizer checks are
enabled and permitted by the current policy (after inlining). This is
particularly useful for inserting explicit, sanitizer-specific checks around
@@ -129,113 +120,108 @@ by the sanitizer.
Example:
-.. code-block:: c
-
- void __msan_check_mem_is_initialized(const void *, size_t);
-
- inline __attribute__((always_inline))
- void my_send(void *addr, size_t size) {
- if (__builtin_allow_sanitize_check("memory"))
- __msan_check_mem_is_initialized(addr, size);
- // ... syscall or other logic where MSan may not see the access ...
- send(addr, size);
- }
-
- void instrumented_function() {
- ...
- my_send(buf, sizeof(buf)); // checks are active
- ...
- }
-
- __attribute__((no_sanitize("memory")))
- void uninstrumented_function() {
- ...
- my_send(buf, sizeof(buf)); // checks are skipped
- ...
- }
-
-Ignorelist
-----------
-
-MemorySanitizer supports ``src`` and ``fun`` entity types in
-:doc:`SanitizerSpecialCaseList`, that can be used to relax MemorySanitizer
+```c
+void __msan_check_mem_is_initialized(const void *, size_t);
+
+inline __attribute__((always_inline))
+void my_send(void *addr, size_t size) {
+ if (__builtin_allow_sanitize_check("memory"))
+ __msan_check_mem_is_initialized(addr, size);
+ // ... syscall or other logic where MSan may not see the access ...
+ send(addr, size);
+}
+
+void instrumented_function() {
+ ...
+ my_send(buf, sizeof(buf)); // checks are active
+ ...
+}
+
+__attribute__((no_sanitize("memory")))
+void uninstrumented_function() {
+ ...
+ my_send(buf, sizeof(buf)); // checks are skipped
+ ...
+}
+```
+
+### Ignorelist
+
+MemorySanitizer supports `src` and `fun` entity types in
+{doc}`SanitizerSpecialCaseList`, that can be used to relax MemorySanitizer
checks for certain source files and functions. All "Use of uninitialized value"
warnings will be suppressed and all values loaded from memory will be
considered fully initialized.
-Report symbolization
-====================
+## Report symbolization
MemorySanitizer uses an external symbolizer to print files and line numbers in
-reports. Make sure that ``llvm-symbolizer`` binary is in ``PATH``,
-or set environment variable ``MSAN_SYMBOLIZER_PATH`` to point to it.
+reports. Make sure that `llvm-symbolizer` binary is in `PATH`,
+or set environment variable `MSAN_SYMBOLIZER_PATH` to point to it.
-.. _msan-origins:
+(msan-origins)=
-Origin Tracking
-===============
+## Origin Tracking
MemorySanitizer can track origins of uninitialized values, similar to
Valgrind's --track-origins option. This feature is enabled by
-``-fsanitize-memory-track-origins=2`` (or simply
-``-fsanitize-memory-track-origins``) Clang option. With the code from
+`-fsanitize-memory-track-origins=2` (or simply
+`-fsanitize-memory-track-origins`) Clang option. With the code from
the example above,
-.. code-block:: console
-
- % cat umr2.cc
- #include <stdio.h>
-
- int main(int argc, char** argv) {
- int* a = new int[10];
- a[5] = 0;
- volatile int b = a[argc];
- if (b)
- printf("xx\n");
- return 0;
- }
-
- % clang -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -g -O2 umr2.cc
- % ./a.out
- WARNING: MemorySanitizer: use-of-uninitialized-value
- #0 0x7f7893912f0b in main umr2.cc:7
- #1 0x7f789249b76c in __libc_start_main libc-start.c:226
-
- Uninitialized value was stored to memory at
- #0 0x7f78938b5c25 in __msan_chain_origin msan.cc:484
- #1 0x7f7893912ecd in main umr2.cc:6
-
- Uninitialized value was created by a heap allocation
- #0 0x7f7893901cbd in operator new[](unsigned long) msan_new_delete.cc:44
- #1 0x7f7893912e06 in main umr2.cc:4
+```console
+% cat umr2.cc
+#include <stdio.h>
+
+int main(int argc, char** argv) {
+ int* a = new int[10];
+ a[5] = 0;
+ volatile int b = a[argc];
+ if (b)
+ printf("xx\n");
+ return 0;
+}
+
+% clang -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -g -O2 umr2.cc
+% ./a.out
+WARNING: MemorySanitizer: use-of-uninitialized-value
+ #0 0x7f7893912f0b in main umr2.cc:7
+ #1 0x7f789249b76c in __libc_start_main libc-start.c:226
+
+ Uninitialized value was stored to memory at
+ #0 0x7f78938b5c25 in __msan_chain_origin msan.cc:484
+ #1 0x7f7893912ecd in main umr2.cc:6
+
+ Uninitialized value was created by a heap allocation
+ #0 0x7f7893901cbd in operator new[](unsigned long) msan_new_delete.cc:44
+ #1 0x7f7893912e06 in main umr2.cc:4
+```
By default, MemorySanitizer collects both allocation points and all
-intermediate stores the uninitialized value went through. Origin
+intermediate stores the uninitialized value went through. Origin
tracking has proved to be very useful for debugging MemorySanitizer
reports. It slows down program execution by a factor of 1.5x-2x on top
of the usual MemorySanitizer slowdown and increases memory overhead.
-Clang option ``-fsanitize-memory-track-origins=1`` enables a slightly
+Clang option `-fsanitize-memory-track-origins=1` enables a slightly
faster mode when MemorySanitizer collects only allocation points but
not intermediate stores.
-Use-after-destruction detection
-===============================
+## Use-after-destruction detection
MemorySanitizer includes use-after-destruction detection. After invocation of
the destructor, the object will be considered no longer readable, and using
underlying memory will lead to error reports in runtime. Refer to the standard
-for `lifetime <https://eel.is/c++draft/basic.life#1>`_ definition.
+for [lifetime](https://eel.is/c++draft/basic.life#1) definition.
This feature can be disabled with either:
-#. Pass additional Clang option ``-fno-sanitize-memory-use-after-dtor`` during
+1. Pass additional Clang option `-fno-sanitize-memory-use-after-dtor` during
compilation.
-#. Set environment variable `MSAN_OPTIONS=poison_in_dtor=0` before running
+2. Set environment variable `MSAN_OPTIONS=poison_in_dtor=0` before running
the program.
-Handling external code
-======================
+## Handling external code
MemorySanitizer requires that all program code is instrumented. This
also includes any libraries that the program depends on, even libc.
@@ -251,48 +237,44 @@ uninstrumented libc. For example, the authors were able to bootstrap
MemorySanitizer-instrumented Clang compiler by linking it with
self-built instrumented libc++ (as a replacement for libstdc++).
-Security Considerations
-=======================
+## Security Considerations
MemorySanitizer is a bug detection tool and its runtime is not meant to be
linked against production executables. While it may be useful for testing,
MemorySanitizer's runtime was not developed with security-sensitive
constraints in mind and may compromise the security of the resulting executable.
-Supported Platforms
-===================
+## Supported Platforms
MemorySanitizer is supported on the following OS:
-* Linux
-* NetBSD
-* FreeBSD
+- Linux
+- NetBSD
+- FreeBSD
-Limitations
-===========
+## Limitations
-* MemorySanitizer uses 2x more real memory than a native run, 3x with
+- MemorySanitizer uses 2x more real memory than a native run, 3x with
origin tracking.
-* MemorySanitizer maps (but not reserves) 64 Terabytes of virtual
- address space. This means that tools like ``ulimit`` may not work as
+- MemorySanitizer maps (but not reserves) 64 Terabytes of virtual
+ address space. This means that tools like `ulimit` may not work as
usually expected.
-* Static linking is not supported.
-* Older versions of MSan (LLVM 3.7 and older) didn't work with
+- Static linking is not supported.
+- Older versions of MSan (LLVM 3.7 and older) didn't work with
non-position-independent executables, and could fail on some Linux
kernel versions with disabled ASLR. Refer to documentation for older versions
for more details.
-* MemorySanitizer might be incompatible with position-independent executables
+- MemorySanitizer might be incompatible with position-independent executables
from FreeBSD 13 but there is a check done at runtime and throws a warning
in this case.
-Current Status
-==============
+## Current Status
MemorySanitizer is known to work on large real-world programs
(like Clang/LLVM itself) that can be recompiled from source, including all
dependent libraries.
-More Information
-================
+## More Information
+
+[https://github.com/google/sanitizers/wiki/MemorySanitizer](https://github.com/google/sanitizers/wiki/MemorySanitizer)
-`<https://github.com/google/sanitizers/wiki/MemorySanitizer>`_
diff --git a/clang/docs/RealtimeSanitizer.md b/clang/docs/RealtimeSanitizer.md
index 4ce976a3fea29..629a5df0e6b8f 100644
--- a/clang/docs/RealtimeSanitizer.md
+++ b/clang/docs/RealtimeSanitizer.md
@@ -1,161 +1,155 @@
-=================
-RealtimeSanitizer
-=================
+# RealtimeSanitizer
-.. contents::
- :local:
+```{contents}
+:local: true
+```
+
+## Introduction
-Introduction
-============
RealtimeSanitizer (a.k.a. RTSan) is a real-time safety testing tool for C and C++
projects. RTSan can be used to detect real-time violations, i.e. calls to methods
that are not safe for use in functions with deterministic run time requirements.
-RTSan considers any function marked with the ``[[clang::nonblocking]]`` attribute
-to be a real-time function. At run-time, if RTSan detects a call to ``malloc``,
-``free``, ``pthread_mutex_lock``, or anything else known to have a
-non-deterministic execution time in a function marked ``[[clang::nonblocking]]``
-it raises an error.
-
-RTSan performs its analysis at run-time but shares the ``[[clang::nonblocking]]``
-attribute with the :doc:`FunctionEffectAnalysis` system, which operates at
-compile-time to detect potential real-time safety violations. For comprehensive
+RTSan considers any function marked with the `[[clang::nonblocking]]` attribute
+to be a real-time function. At run-time, if RTSan detects a call to `malloc`,
+`free`, `pthread_mutex_lock`, or anything else known to have a
+non-deterministic execution time in a function marked `[[clang::nonblocking]]`
+it raises an error.
+
+RTSan performs its analysis at run-time but shares the `[[clang::nonblocking]]`
+attribute with the {doc}`FunctionEffectAnalysis` system, which operates at
+compile-time to detect potential real-time safety violations. For comprehensive
detection of real-time safety issues, it is recommended to use both systems together.
The runtime slowdown introduced by RealtimeSanitizer is negligible.
-How to build
-============
+## How to build
-Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>`_ and enable the
-``compiler-rt`` runtime. An example CMake configuration that will allow for the
+Build LLVM/Clang with [CMake](https://llvm.org/docs/CMake.html) and enable the
+`compiler-rt` runtime. An example CMake configuration that will allow for the
use/testing of RealtimeSanitizer:
-.. code-block:: console
-
- $ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_ENABLE_RUNTIMES="compiler-rt" <path to source>/llvm
+```console
+$ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_ENABLE_RUNTIMES="compiler-rt" <path to source>/llvm
+```
-Usage
-=====
+## Usage
There are two requirements:
-1. The code must be compiled with the ``-fsanitize=realtime`` flag.
+1. The code must be compiled with the `-fsanitize=realtime` flag.
2. Functions that are subject to real-time constraints must be marked
- with the ``[[clang::nonblocking]]`` attribute.
+ with the `[[clang::nonblocking]]` attribute.
Typically, these attributes should be added onto the functions that are entry
points for threads with real-time priority. These threads are subject to a fixed
callback time, such as audio callback threads or rendering loops in video game
code.
-.. code-block:: console
-
- % cat example_realtime_violation.cpp
- #include <vector>
+```console
+% cat example_realtime_violation.cpp
+#include <vector>
- void violation() [[clang::nonblocking]]{
- std::vector<float> v;
- v.resize(100);
- }
+void violation() [[clang::nonblocking]]{
+ std::vector<float> v;
+ v.resize(100);
+}
- int main() {
- violation();
- return 0;
- }
- # Compile and link
- % clang++ -fsanitize=realtime example_realtime_violation.cpp
+int main() {
+ violation();
+ return 0;
+}
+# Compile and link
+% clang++ -fsanitize=realtime example_realtime_violation.cpp
+```
-If a real-time safety violation is detected in a ``[[clang::nonblocking]]``
+If a real-time safety violation is detected in a `[[clang::nonblocking]]`
context, or any function invoked by that function, the program will exit with a
non-zero exit code.
-.. code-block:: console
-
- % clang++ -fsanitize=realtime example_realtime_violation.cpp
- % ./a.out
- ==76290==ERROR: RealtimeSanitizer: unsafe-library-call
- Intercepted call to real-time unsafe function `malloc` in real-time context!
- #0 0x000102a7b884 in malloc rtsan_interceptors.cpp:426
- #1 0x00019c326bd0 in operator new(unsigned long)+0x1c (libc++abi.dylib:arm64+0x16bd0)
- #2 0xa30d0001024f79a8 (<unknown module>)
- #3 0x0001024f794c in std::__1::__libcpp_allocate[abi:ne200000](unsigned long, unsigned long)+0x44
- #4 0x0001024f78c4 in std::__1::allocator<float>::allocate[abi:ne200000](unsigned long)+0x44
- ... snip ...
- #9 0x0001024f6868 in std::__1::vector<float, std::__1::allocator<float>>::resize(unsigned long)+0x48
- #10 0x0001024f67b4 in violation()+0x24
- #11 0x0001024f68f0 in main+0x18 (a.out:arm64+0x1000028f0)
- #12 0x00019bfe3150 (<unknown module>)
- #13 0xed5efffffffffffc (<unknown module>)
-
-
-Blocking functions
-------------------
-
-Calls to system library functions such as ``malloc`` are automatically caught by
+```console
+% clang++ -fsanitize=realtime example_realtime_violation.cpp
+% ./a.out
+==76290==ERROR: RealtimeSanitizer: unsafe-library-call
+Intercepted call to real-time unsafe function `malloc` in real-time context!
+ #0 0x000102a7b884 in malloc rtsan_interceptors.cpp:426
+ #1 0x00019c326bd0 in operator new(unsigned long)+0x1c (libc++abi.dylib:arm64+0x16bd0)
+ #2 0xa30d0001024f79a8 (<unknown module>)
+ #3 0x0001024f794c in std::__1::__libcpp_allocate[abi:ne200000](unsigned long, unsigned long)+0x44
+ #4 0x0001024f78c4 in std::__1::allocator<float>::allocate[abi:ne200000](unsigned long)+0x44
+ ... snip ...
+ #9 0x0001024f6868 in std::__1::vector<float, std::__1::allocator<float>>::resize(unsigned long)+0x48
+ #10 0x0001024f67b4 in violation()+0x24
+ #11 0x0001024f68f0 in main+0x18 (a.out:arm64+0x1000028f0)
+ #12 0x00019bfe3150 (<unknown module>)
+ #13 0xed5efffffffffffc (<unknown module>)
+```
+
+### Blocking functions
+
+Calls to system library functions such as `malloc` are automatically caught by
RealtimeSanitizer. Real-time programmers may also write their own blocking
(real-time unsafe) functions that they wish RealtimeSanitizer to be aware of.
RealtimeSanitizer will raise an error at run time if any function attributed
-with ``[[clang::blocking]]`` is called in a ``[[clang::nonblocking]]`` context.
-
-.. code-block:: console
-
- $ cat example_blocking_violation.cpp
- #include <atomic>
- #include <thread>
-
- std::atomic<bool> has_permission{false};
-
- int wait_for_permission() [[clang::blocking]] {
- while (has_permission.load() == false)
- std::this_thread::yield();
- return 0;
- }
-
- int real_time_function() [[clang::nonblocking]] {
- return wait_for_permission();
- }
+with `[[clang::blocking]]` is called in a `[[clang::nonblocking]]` context.
- int main() {
- return real_time_function();
- }
+```console
+$ cat example_blocking_violation.cpp
+#include <atomic>
+#include <thread>
- $ clang++ -fsanitize=realtime example_blocking_violation.cpp && ./a.out
- ==76131==ERROR: RealtimeSanitizer: blocking-call
- Call to blocking function `wait_for_permission()` in real-time context!
- #0 0x0001000c3db0 in wait_for_permission()+0x10 (a.out:arm64+0x100003db0)
- #1 0x0001000c3e3c in real_time_function()+0x10 (a.out:arm64+0x100003e3c)
- #2 0x0001000c3e68 in main+0x10 (a.out:arm64+0x100003e68)
- #3 0x00019bfe3150 (<unknown module>)
- #4 0x5a27fffffffffffc (<unknown module>)
+std::atomic<bool> has_permission{false};
+int wait_for_permission() [[clang::blocking]] {
+ while (has_permission.load() == false)
+ std::this_thread::yield();
+ return 0;
+}
-Run-time flags
---------------
+int real_time_function() [[clang::nonblocking]] {
+ return wait_for_permission();
+}
-RealtimeSanitizer supports a number of run-time flags, which can be specified in the ``RTSAN_OPTIONS`` environment variable:
+int main() {
+ return real_time_function();
+}
-.. code-block:: console
+$ clang++ -fsanitize=realtime example_blocking_violation.cpp && ./a.out
+==76131==ERROR: RealtimeSanitizer: blocking-call
+Call to blocking function `wait_for_permission()` in real-time context!
+ #0 0x0001000c3db0 in wait_for_permission()+0x10 (a.out:arm64+0x100003db0)
+ #1 0x0001000c3e3c in real_time_function()+0x10 (a.out:arm64+0x100003e3c)
+ #2 0x0001000c3e68 in main+0x10 (a.out:arm64+0x100003e68)
+ #3 0x00019bfe3150 (<unknown module>)
+ #4 0x5a27fffffffffffc (<unknown module>)
+```
- % RTSAN_OPTIONS=option_1=true:path_option_2="/some/file.txt" ./a.out
- ...
+### Run-time flags
-Or at compile-time by providing the symbol ``__rtsan_default_options``:
+RealtimeSanitizer supports a number of run-time flags, which can be specified in the `RTSAN_OPTIONS` environment variable:
-.. code-block:: c
+```console
+% RTSAN_OPTIONS=option_1=true:path_option_2="/some/file.txt" ./a.out
+...
+```
- __attribute__((__visibility__("default")))
- extern "C" const char *__rtsan_default_options() {
- return "symbolize=false:abort_on_error=0:log_to_syslog=0";
- }
+Or at compile-time by providing the symbol `__rtsan_default_options`:
-You can see all sanitizer options (some of which are unsupported) by using the ``help`` flag:
+```c
+__attribute__((__visibility__("default")))
+extern "C" const char *__rtsan_default_options() {
+ return "symbolize=false:abort_on_error=0:log_to_syslog=0";
+}
+```
-.. code-block:: console
+You can see all sanitizer options (some of which are unsupported) by using the `help` flag:
- % RTSAN_OPTIONS=help=true ./a.out
+```console
+% RTSAN_OPTIONS=help=true ./a.out
+```
A **partial** list of flags RealtimeSanitizer respects:
+```{eval-rst}
.. list-table:: Run-time Flags
:widths: 20 10 10 70
:header-rows: 1
@@ -200,62 +194,62 @@ A **partial** list of flags RealtimeSanitizer respects:
- ``true``
- boolean
- If true, verifies interceptors are working at initialization. The program will abort with error ``==ERROR: Interceptors are not working. This may be because RealtimeSanitizer is loaded too late (e.g. via dlopen)`` if an issue is detected.
+```
-Some issues with flags can be debugged using the ``verbosity=$NUM`` flag:
-
-.. code-block:: console
-
- % RTSAN_OPTIONS=verbosity=1:misspelled_flag=true ./a.out
- WARNING: found 1 unrecognized flag(s):
- misspelled_flag
- ...
-
-Additional customization
-------------------------
+Some issues with flags can be debugged using the `verbosity=$NUM` flag:
-In addition to ``__rtsan_default_options`` outlined above, you can provide definitions of other functions that affect how RTSan operates.
+```console
+% RTSAN_OPTIONS=verbosity=1:misspelled_flag=true ./a.out
+WARNING: found 1 unrecognized flag(s):
+misspelled_flag
+...
+```
-To be notified on every error reported by RTsan, provide a definition of ``__sanitizer_report_error_summary``.
+### Additional customization
-.. code-block:: c
+In addition to `__rtsan_default_options` outlined above, you can provide definitions of other functions that affect how RTSan operates.
- extern "C" void __sanitizer_report_error_summary(const char *error_summary) {
- fprintf(stderr, "%s %s\n", "In custom handler! ", error_summary);
- /* do other custom things */
- }
+To be notified on every error reported by RTsan, provide a definition of `__sanitizer_report_error_summary`.
-The error summary will be of the form:
+```c
+extern "C" void __sanitizer_report_error_summary(const char *error_summary) {
+ fprintf(stderr, "%s %s\n", "In custom handler! ", error_summary);
+ /* do other custom things */
+}
+```
-.. code-block:: console
+The error summary will be of the form:
- SUMMARY: RealtimeSanitizer: unsafe-library-call main.cpp:8 in process(std::__1::vector<int, std::__1::allocator<int>>&)
+```console
+SUMMARY: RealtimeSanitizer: unsafe-library-call main.cpp:8 in process(std::__1::vector<int, std::__1::allocator<int>>&)
+```
To register a callback which will be invoked before a RTSan kills the process:
-.. code-block:: c
+```c
+extern "C" void __sanitizer_set_death_callback(void (*callback)(void));
- extern "C" void __sanitizer_set_death_callback(void (*callback)(void));
+void custom_on_die_callback() {
+ fprintf(stderr, "In custom handler!")
+ /* do other custom things */
+}
- void custom_on_die_callback() {
- fprintf(stderr, "In custom handler!")
- /* do other custom things */
- }
+int main()
+{
+ __sanitizer_set_death_callback(custom_on_die_callback);
+ ...
+}
+```
- int main()
- {
- __sanitizer_set_death_callback(custom_on_die_callback);
- ...
- }
+(disabling-and-suppressing)=
-.. _disabling-and-suppressing:
-
-Disabling and suppressing
--------------------------
+### Disabling and suppressing
There are multiple ways to disable error reporting when using RealtimeSanitizer.
-In general, ``ScopedDisabler`` should be preferred, as it is the most performant.
+In general, `ScopedDisabler` should be preferred, as it is the most performant.
+```{eval-rst}
.. list-table:: Suppression methods
:widths: 30 15 15 10 70
:header-rows: 1
@@ -280,77 +274,76 @@ In general, ``ScopedDisabler`` should be preferred, as it is the most performant
- Stack
- High
- Suppresses any stack trace containing the specified pattern.
-
-``ScopedDisabler``
-##################
+```
-At compile time, RealtimeSanitizer may be disabled using ``__rtsan::ScopedDisabler``. RTSan ignores any errors originating within the ``ScopedDisabler`` instance variable scope.
+#### `ScopedDisabler`
-.. code-block:: c++
+At compile time, RealtimeSanitizer may be disabled using `__rtsan::ScopedDisabler`. RTSan ignores any errors originating within the `ScopedDisabler` instance variable scope.
- #include <sanitizer/rtsan_interface.h>
+```c++
+#include <sanitizer/rtsan_interface.h>
- void process(const std::vector<float>& buffer) [[clang::nonblocking]] {
- {
- __rtsan::ScopedDisabler d;
- ...
- }
+void process(const std::vector<float>& buffer) [[clang::nonblocking]] {
+ {
+ __rtsan::ScopedDisabler d;
+ ...
}
+}
+```
-If RealtimeSanitizer is not enabled at compile time (i.e., the code is not compiled with the ``-fsanitize=realtime`` flag), the ``ScopedDisabler`` is compiled as a no-op.
+If RealtimeSanitizer is not enabled at compile time (i.e., the code is not compiled with the `-fsanitize=realtime` flag), the `ScopedDisabler` is compiled as a no-op.
-In C, you can use the ``__rtsan_disable()`` and ``rtsan_enable()`` functions to manually disable and re-enable RealtimeSanitizer checks.
+In C, you can use the `__rtsan_disable()` and `rtsan_enable()` functions to manually disable and re-enable RealtimeSanitizer checks.
-.. code-block:: c++
+```c++
+#include <sanitizer/rtsan_interface.h>
- #include <sanitizer/rtsan_interface.h>
-
- int process(const float* buffer) [[clang::nonblocking]]
+int process(const float* buffer) [[clang::nonblocking]]
+{
{
- {
- __rtsan_disable();
+ __rtsan_disable();
- ...
+ ...
- __rtsan_enable();
- }
+ __rtsan_enable();
}
+}
+```
-Each call to ``__rtsan_disable()`` must be paired with a subsequent call to ``__rtsan_enable()`` to restore normal sanitizer functionality. If a corresponding ``rtsan_enable()`` call is not made, the behavior is undefined.
-
-Suppression file
-################
+Each call to `__rtsan_disable()` must be paired with a subsequent call to `__rtsan_enable()` to restore normal sanitizer functionality. If a corresponding `rtsan_enable()` call is not made, the behavior is undefined.
-At run-time, suppressions may be specified using a suppressions file passed in ``RTSAN_OPTIONS``. Run-time suppression may be useful if the source cannot be changed.
+#### Suppression file
-.. code-block:: console
+At run-time, suppressions may be specified using a suppressions file passed in `RTSAN_OPTIONS`. Run-time suppression may be useful if the source cannot be changed.
- > cat suppressions.supp
- call-stack-contains:MallocViolation
- call-stack-contains:std::*vector
- function-name-matches:free
- function-name-matches:CustomMarkedBlocking*
- > RTSAN_OPTIONS="suppressions=suppressions.supp" ./a.out
- ...
+```console
+> cat suppressions.supp
+call-stack-contains:MallocViolation
+call-stack-contains:std::*vector
+function-name-matches:free
+function-name-matches:CustomMarkedBlocking*
+> RTSAN_OPTIONS="suppressions=suppressions.supp" ./a.out
+...
+```
Suppressions specified in this file are one of two flavors.
-``function-name-matches`` suppresses reporting of any intercepted library call, or function marked ``[[clang::blocking]]`` by name. If, for instance, you know that ``malloc`` is real-time safe on your system, you can disable the check for it via ``function-name-matches:malloc``.
+`function-name-matches` suppresses reporting of any intercepted library call, or function marked `[[clang::blocking]]` by name. If, for instance, you know that `malloc` is real-time safe on your system, you can disable the check for it via `function-name-matches:malloc`.
-``call-stack-contains`` suppresses reporting of errors in any stack that contains a string matching the pattern specified. For example, suppressing error reporting of any non-real-time-safe behavior in ``std::vector`` may be specified ``call-stack-contains:std::*vector``. You must include symbols in your build for this method to be effective, unsymbolicated stack traces cannot be matched. ``call-stack-contains`` has the highest run-time cost of any method of suppression.
+`call-stack-contains` suppresses reporting of errors in any stack that contains a string matching the pattern specified. For example, suppressing error reporting of any non-real-time-safe behavior in `std::vector` may be specified `call-stack-contains:std::*vector`. You must include symbols in your build for this method to be effective, unsymbolicated stack traces cannot be matched. `call-stack-contains` has the highest run-time cost of any method of suppression.
-Patterns may be exact matches or are "regex-light" patterns, containing special characters such as ``^$*``.
+Patterns may be exact matches or are "regex-light" patterns, containing special characters such as `^$*`.
-The number of potential errors suppressed via this method may be seen on exit when using the ``print_stats_on_exit`` flag.
+The number of potential errors suppressed via this method may be seen on exit when using the `print_stats_on_exit` flag.
-Compile-time sanitizer detection
---------------------------------
+### Compile-time sanitizer detection
-Clang provides the pre-processor macro ``__has_feature`` which may be used to detect if RealtimeSanitizer is enabled at compile-time.
+Clang provides the pre-processor macro `__has_feature` which may be used to detect if RealtimeSanitizer is enabled at compile-time.
-.. code-block:: c++
+```c++
+#if defined(__has_feature) && __has_feature(realtime_sanitizer)
+...
+#endif
+```
- #if defined(__has_feature) && __has_feature(realtime_sanitizer)
- ...
- #endif
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index a2439ccb0452a..70e62a46e3caa 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -1,106 +1,99 @@
-.. If you want to modify sections/contents permanently, you should modify both
- ReleaseNotes.rst and ReleaseNotesTemplate.txt.
+% If you want to modify sections/contents permanently, you should modify both
+% ReleaseNotes.rst and ReleaseNotesTemplate.txt.
-===========================================
-Clang |release| |ReleaseNotesTitle|
-===========================================
+# Clang {{ release }} {{ ReleaseNotesTitle }}
-.. contents::
- :local:
- :depth: 2
+```{contents}
+:depth: 2
+:local: true
+```
-Written by the `LLVM Team <https://llvm.org/>`_
+Written by the [LLVM Team](https://llvm.org/)
-.. only:: PreRelease
+::::{only} PreRelease
- .. warning::
- These are in-progress notes for the upcoming Clang |version| release.
- Release notes for previous releases can be found on
- `the Releases Page <https://llvm.org/releases/>`_.
+:::{warning}
+These are in-progress notes for the upcoming Clang {{ version }} release.
+Release notes for previous releases can be found on
+[the Releases Page](https://llvm.org/releases/).
+:::
+::::
-Introduction
-============
+## Introduction
This document contains the release notes for the Clang C/C++/Objective-C
-frontend, part of the LLVM Compiler Infrastructure, release |release|. Here we
+frontend, part of the LLVM Compiler Infrastructure, release {{ release }}. Here we
describe the status of Clang in some detail, including major
improvements from the previous release and new feature work. For the
-general LLVM release notes, see `the LLVM
-documentation <https://llvm.org/docs/ReleaseNotes.html>`_. For the libc++ release notes,
-see `this page <https://libcxx.llvm.org/ReleaseNotes.html>`_. All LLVM releases
-may be downloaded from the `LLVM releases web site <https://llvm.org/releases/>`_.
+general LLVM release notes, see [the LLVM
+documentation](https://llvm.org/docs/ReleaseNotes.html). For the libc++ release notes,
+see [this page](https://libcxx.llvm.org/ReleaseNotes.html). All LLVM releases
+may be downloaded from the [LLVM releases web site](https://llvm.org/releases/).
For more information about Clang or LLVM, including information about the
-latest release, please see the `Clang Web Site <https://clang.llvm.org>`_ or the
-`LLVM Web Site <https://llvm.org>`_.
+latest release, please see the [Clang Web Site](https://clang.llvm.org) or the
+[LLVM Web Site](https://llvm.org).
-Potentially Breaking Changes
-============================
+## Potentially Breaking Changes
-C/C++ Language Potentially Breaking Changes
--------------------------------------------
+### C/C++ Language Potentially Breaking Changes
-- Clang now makes it ill-formed to try to ``break`` out of or ``continue`` a loop inside its own condition,
+- Clang now makes it ill-formed to try to `break` out of or `continue` a loop inside its own condition,
increment, or init-statement in all C and C++ language modes. This means that code such as
- .. code-block:: c++
-
- while (({ break; })) {}
+ ```c++
+ while (({ break; })) {}
+ ```
is now ill-formed. An outer loop can still be broken out of or continued so long as the inner loop is
in the body of the outer loop:
- .. code-block:: c++
-
- // Ok, this breaks out of the 'for' loop.
- for (;;) {
- while (({ break; true; })) {}
- }
+ ```c++
+ // Ok, this breaks out of the 'for' loop.
+ for (;;) {
+ while (({ break; true; })) {}
+ }
- // Error: can't break out of the 'for' loop from within its own increment.
- for (;;({ while (({ break; true; })) {} })) {}
+ // Error: can't break out of the 'for' loop from within its own increment.
+ for (;;({ while (({ break; true; })) {} })) {}
+ ```
This also resolves a divergence from GCC: in a construct such as
- .. code-block:: c++
-
- for (;;) {
- while (({ break; true; })) {}
- }
+ ```c++
+ for (;;) {
+ while (({ break; true; })) {}
+ }
+ ```
- Clang would previously ``break`` out of the ``while`` loop, whereas GCC (since version 9) would
- ``break`` out of the ``for`` loop here. Now, Clang and GCC both break out of the ``for`` loop.
+ Clang would previously `break` out of the `while` loop, whereas GCC (since version 9) would
+ `break` out of the `for` loop here. Now, Clang and GCC both break out of the `for` loop.
-C++ Specific Potentially Breaking Changes
------------------------------------------
+### C++ Specific Potentially Breaking Changes
- Clang now more aggressively optimizes away stores to objects after they are
- dead. This behavior can be disabled with ``-fno-lifetime-dse``.
-
-- Clang now correctly rejects ``export`` declarations in module implementation
+ dead. This behavior can be disabled with `-fno-lifetime-dse`.
+- Clang now correctly rejects `export` declarations in module implementation
partitions. (#GH107602)
-
-- Template argument deduction now treats the ``N`` in ``_BitInt(N)``
- as being of type ``std::size_t`` instead of ``int``,
- matching the deduction of array sizes from ``int(&)[N]``.
+- Template argument deduction now treats the `N` in `_BitInt(N)`
+ as being of type `std::size_t` instead of `int`,
+ matching the deduction of array sizes from `int(&)[N]`.
This is a breaking change for code that depended on the previously deduced type. (#GH195033)
-
- Clang now rejects nested local classes defined in a different
block scope than their parent class. (#GH193472)
-ABI Changes in This Version
----------------------------
+### ABI Changes in This Version
-- Fixed incorrect struct layout for ``_BitInt`` bitfields wider than 255 bits
+- Fixed incorrect struct layout for `_BitInt` bitfields wider than 255 bits
on MSVC targets. Internal bitfield tracking fields were changed from
- ``unsigned char`` to ``uint64_t`` to prevent overflow. This might be an ABI
+ `unsigned char` to `uint64_t` to prevent overflow. This might be an ABI
break for such structs compared to earlier Clang versions.
-- Fixed a number of issues with the ``__regcall`` calling convention for passing
+- Fixed a number of issues with the `__regcall` calling convention for passing
structs on non-Windows x86-64 targets, including a crash when handling empty
struct arguments. This changes how structs that contain arrays, floating point
- types, or ``_Complex float`` types are passed, and may introduce
+ types, or `_Complex float` types are passed, and may introduce
incompatibilities with code compiled by earlier versions of Clang that uses
- the ``__regcall`` calling convention on these targets. (#GH62999) (#GH98635)
+ the `__regcall` calling convention on these targets. (#GH62999) (#GH98635)
- Fixed Itanium mangling for lambdas in instantiated non-static data member
initializers by preserving the field-name closure-prefix. This changes the
mangled names for affected lambdas. (#GH190555)
@@ -108,26 +101,24 @@ ABI Changes in This Version
types when targeting the Microsoft ABI. This changes symbol names for
affected declarations compared to previous Clang releases. (#GH196170)
- The resume and destroy functions of C++20 coroutines now use the platform C
- calling convention instead of LLVM's internal ``fastcc``. This makes the
+ calling convention instead of LLVM's internal `fastcc`. This makes the
coroutine ABI stable across LLVM versions and interoperable with other
- compilers. On most targets this is not a breaking change because ``fastcc``
- and the platform C calling convention agree for ``void(ptr)``. It is an ABI
+ compilers. On most targets this is not a breaking change because `fastcc`
+ and the platform C calling convention agree for `void(ptr)`. It is an ABI
break on i686, MIPS O32, PowerPC64 ELFv1, and Lanai.
- Fixed incorrect struct return when single large vector (256/512-bit) used on
x86-64 targets. (#GH203760) The bug was introduced since Clang 21. (#GH120670)
-AST Dumping Potentially Breaking Changes
-----------------------------------------
+### AST Dumping Potentially Breaking Changes
-- The JSON AST dump now includes all fields from ``AvailabilityAttr``: ``platform``,
- ``introduced``, ``deprecated``, ``obsoleted``, ``unavailable``, ``message``,
- ``strict``, ``replacement``, ``priority``, and ``environment``. Previously, these
+- The JSON AST dump now includes all fields from `AvailabilityAttr`: `platform`,
+ `introduced`, `deprecated`, `obsoleted`, `unavailable`, `message`,
+ `strict`, `replacement`, `priority`, and `environment`. Previously, these
fields were missing from the JSON output.
- Colons that appear at the end of a ParamCommentCommand name are not serialized
as part of the name.
-Clang Frontend Potentially Breaking Changes
--------------------------------------------
+### Clang Frontend Potentially Breaking Changes
- HIPSPV toolchain: `--offload-targets=spirv{32,64}` option is
deprecated and will be removed when the new offload driver becomes
@@ -138,504 +129,470 @@ Clang Frontend Potentially Breaking Changes
compilations. This changes the ABI for relocatable device code. Currently,
libraries will need to be recompiled, or used with
(`--no-offload-new-driver`). This option will be removed in the next release.
-
-- Clang no longer defines the ``__cpp_impl_coroutine`` feature test macro under the 32-bit x86 Microsoft ABI,
+- Clang no longer defines the `__cpp_impl_coroutine` feature test macro under the 32-bit x86 Microsoft ABI,
as support for coroutines on this target is incomplete.
When using coroutines on this target a warning is emmitted to indicate the lack of full support.
- That warning can be disabled with ``-Wno-coroutines-unsupported-target``. (see #GH59382)
-
-Clang Python Bindings Potentially Breaking Changes
---------------------------------------------------
-- Remove ``CompletionString.Availability``. No libclang interfaces returned instances of it.
-- ``CompletionString.availability`` now returns instances of ``CompletionString.AvailabilityKindCompat``.
-
- Instances of ``AvailabilityKindCompat`` have the same ``__str__`` representation
- as the previous ``CompletionChunk.Kind`` and are equality-comparable with
- the existing ``AvailabilityKind`` enum. It will be replaced by ``AvailabilityKind``
- in a future release. When this happens, the return type of ``CompletionString.availability``
- will change to ``AvailabilityKind``, so it is recommended to use ``AvailabilityKind``
- to compare with the return values of ``CompletionString.availability``.
-- Remove ``availabilityKinds``. In this release, uses of ``availabilityKinds``
- need to be replaced by ``CompletionString.AvailabilityKind``.
-- ``CompletionChunk.kind`` now returns instances of ``CompletionChunkKind``.
-
- Instances of ``CompletionChunkKind`` have the same ``__str__`` representation
- as the previous ``CompletionChunk.Kind`` for compatibility.
+ That warning can be disabled with `-Wno-coroutines-unsupported-target`. (see #GH59382)
+
+### Clang Python Bindings Potentially Breaking Changes
+
+- Remove `CompletionString.Availability`. No libclang interfaces returned instances of it.
+
+- `CompletionString.availability` now returns instances of `CompletionString.AvailabilityKindCompat`.
+
+ Instances of `AvailabilityKindCompat` have the same `__str__` representation
+ as the previous `CompletionChunk.Kind` and are equality-comparable with
+ the existing `AvailabilityKind` enum. It will be replaced by `AvailabilityKind`
+ in a future release. When this happens, the return type of `CompletionString.availability`
+ will change to `AvailabilityKind`, so it is recommended to use `AvailabilityKind`
+ to compare with the return values of `CompletionString.availability`.
+
+- Remove `availabilityKinds`. In this release, uses of `availabilityKinds`
+ need to be replaced by `CompletionString.AvailabilityKind`.
+
+- `CompletionChunk.kind` now returns instances of `CompletionChunkKind`.
+
+ Instances of `CompletionChunkKind` have the same `__str__` representation
+ as the previous `CompletionChunk.Kind` for compatibility.
These representations will be changed in a future release to match other enums.
-- Remove ``completionChunkKindMap``. In this release, uses of ``completionChunkKindMap``
- need to be replaced by ``CompletionChunkKind``.
-- Move ``SPELLING_CACHE`` into ``CompletionChunk`` and change it to use
- ``CompletionChunkKind`` instances as keys, instead of the enum values.
- An alias is kept in the form of a ``SPELLING_CACHE`` variable, but it only supports
- ``__getitem__`` and ``__contains__``. It will be removed in a future release.
- Please migrate to using ``CompletionChunk.SPELLING_CACHE`` instead.
-- ``SourceLocation`` and ``SourceRange`` now use ``NotImplemented`` to delegate
- equality checks (``__eq__``) to the other object they are compared with when
- they are of different classes. They previously returned ``False`` when compared
+
+- Remove `completionChunkKindMap`. In this release, uses of `completionChunkKindMap`
+ need to be replaced by `CompletionChunkKind`.
+
+- Move `SPELLING_CACHE` into `CompletionChunk` and change it to use
+ `CompletionChunkKind` instances as keys, instead of the enum values.
+ An alias is kept in the form of a `SPELLING_CACHE` variable, but it only supports
+ `__getitem__` and `__contains__`. It will be removed in a future release.
+ Please migrate to using `CompletionChunk.SPELLING_CACHE` instead.
+
+- `SourceLocation` and `SourceRange` now use `NotImplemented` to delegate
+ equality checks (`__eq__`) to the other object they are compared with when
+ they are of different classes. They previously returned `False` when compared
with objects of other classes.
-- ``TranslationUnit.get_tokens`` now throws an error if both the ``extent`` and
- ``locations`` argument are passed. Previousy, ``locations`` took precedence.
-- ``_CXUnsavedFile`` will be renamed to ``UnsavedFile`` for consistency.
- ``UnsavedFile`` is already available to use and existing uses should
- be adapted to refer to it instead. ``_CXUnsavedFile`` will be removed in a
+
+- `TranslationUnit.get_tokens` now throws an error if both the `extent` and
+ `locations` argument are passed. Previousy, `locations` took precedence.
+
+- `_CXUnsavedFile` will be renamed to `UnsavedFile` for consistency.
+ `UnsavedFile` is already available to use and existing uses should
+ be adapted to refer to it instead. `_CXUnsavedFile` will be removed in a
future release.
-OpenCL Potentially Breaking Changes
------------------------------------
+### OpenCL Potentially Breaking Changes
+
- Clang now diagnoses zero-length arrays as errors in OpenCL. OpenCL C 3.0
section 6.11.d states that "Variable length arrays and structures with
flexible (or unsized) arrays are not supported."
-What's New in Clang |release|?
-==============================
+## What's New in Clang {{ release }}?
-C++ Language Changes
---------------------
+### C++ Language Changes
-- ``__is_trivially_equality_comparable`` no longer returns false for all enum types. (#GH132672)
-- ``auto`` parameters are now available in all C++ language modes as an extension.
+- `__is_trivially_equality_comparable` no longer returns false for all enum types. (#GH132672)
+- `auto` parameters are now available in all C++ language modes as an extension.
-C++2c Feature Support
-^^^^^^^^^^^^^^^^^^^^^
+#### C++2c Feature Support
-- Clang now propagates ``constinit`` and ``constexpr`` in structured bindings with tuple-like initializers.
+- Clang now propagates `constinit` and `constexpr` in structured bindings with tuple-like initializers.
-C++23 Feature Support
-^^^^^^^^^^^^^^^^^^^^^
+#### C++23 Feature Support
- Partially implement Itanium mangling for pack indexing. Partially substituted packs are not yet supported. (#GH112003)
-C++20 Feature Support
-^^^^^^^^^^^^^^^^^^^^^
-
-- Clang now supports `P1857R3 <https://wg21.link/p1857r3>`_ Modules Dependency Discovery. (#GH54047)
+#### C++20 Feature Support
-C++17 Feature Support
-^^^^^^^^^^^^^^^^^^^^^
+- Clang now supports [P1857R3](https://wg21.link/p1857r3) Modules Dependency Discovery. (#GH54047)
-Resolutions to C++ Defect Reports
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- Implemented `CWG1780 Explicit instantiation/specialization of generic lambda
- operator() <https://cplusplus.github.io/CWG/issues/1780.html>`_
+#### C++17 Feature Support
-- Clang now allows omitting ``typename`` before a template name in a
- conversion operator, implementing `CWG2413 <https://wg21.link/cwg2413>`_.
+#### Resolutions to C++ Defect Reports
+- Implemented [CWG1780 Explicit instantiation/specialization of generic lambda
+ operator()](https://cplusplus.github.io/CWG/issues/1780.html)
+- Clang now allows omitting `typename` before a template name in a
+ conversion operator, implementing [CWG2413](https://wg21.link/cwg2413).
- Clang now uses non-reference types for structured bindings whose initializer
- returns a prvalue. This resolves `CWG3135 <https://wg21.link/cwg3135>`_.
+ returns a prvalue. This resolves [CWG3135](https://wg21.link/cwg3135).
-C Language Changes
-------------------
+### C Language Changes
-C2y Feature Support
-^^^^^^^^^^^^^^^^^^^
+#### C2y Feature Support
-- Implemented the type-specific C2y ``<stdbit.h>`` rotate functions with constexpr
+- Implemented the type-specific C2y `<stdbit.h>` rotate functions with constexpr
evaluation support:
- ``stdc_rotate_left_{uc,us,ui,ul,ull}`` and
- ``stdc_rotate_right_{uc,us,ui,ul,ull}``.
-
-- Implemented C2y ``<stdbit.h>`` memory reversal functions:
- ``__builtin_stdc_memreverse8`` / ``stdc_memreverse8`` (in-place byte
- reversal of a byte array) and ``stdc_memreverse8u{8,16,32,64}`` (byte-swap
+ `stdc_rotate_left_{uc,us,ui,ul,ull}` and
+ `stdc_rotate_right_{uc,us,ui,ul,ull}`.
+- Implemented C2y `<stdbit.h>` memory reversal functions:
+ `__builtin_stdc_memreverse8` / `stdc_memreverse8` (in-place byte
+ reversal of a byte array) and `stdc_memreverse8u{8,16,32,64}` (byte-swap
of an exact-width unsigned integer value, usable in constant expressions).
-C23 Feature Support
-^^^^^^^^^^^^^^^^^^^
-- Clang now allows C23 ``constexpr`` struct member access through the dot operator in constant expressions. (#GH178349)
+#### C23 Feature Support
+
+- Clang now allows C23 `constexpr` struct member access through the dot operator in constant expressions. (#GH178349)
- Fixed a failing assertion when validating an invalid structure redefinition
with a member which uses an incomplete enumeration type. (#GH190227)
-- Clang now supports the C23 ``wN`` and ``wfN`` length modifiers. (#GH116962)
-- Clang now recognizes the C23 ``H``, ``D``, and ``DD`` length modifiers in
+- Clang now supports the C23 `wN` and `wfN` length modifiers. (#GH116962)
+- Clang now recognizes the C23 `H`, `D`, and `DD` length modifiers in
format strings and diagnoses their use because Clang does not yet support
- the corresponding decimal floating-point types, ``_Decimal32``, ``_Decimal64``, and ``_Decimal128``. (#GH116962)
+ the corresponding decimal floating-point types, `_Decimal32`, `_Decimal64`, and `_Decimal128`. (#GH116962)
-Objective-C Language Changes
------------------------------
+### Objective-C Language Changes
- Clang now emits Objective-C number, array, and dictionary literals as
- compile-time constant data structures rather than runtime ``objc_msgSend``
+ compile-time constant data structures rather than runtime `objc_msgSend`
calls on targets whose runtime supports constant literal classes. The
- feature can be disabled altogether with ``-fno-objc-constant-literals``,
- or selectively per literal kind with ``-fno-constant-nsnumber-literals``,
- ``-fno-constant-nsarray-literals``, and
- ``-fno-constant-nsdictionary-literals``.
+ feature can be disabled altogether with `-fno-objc-constant-literals`,
+ or selectively per literal kind with `-fno-constant-nsnumber-literals`,
+ `-fno-constant-nsarray-literals`, and
+ `-fno-constant-nsdictionary-literals`.
-Non-comprehensive list of changes in this release
--------------------------------------------------
+### Non-comprehensive list of changes in this release
-- Added support for floating point and pointer values in most ``__atomic_``
+- Added support for floating point and pointer values in most `__atomic_`
builtins.
-
-- Added ``__builtin_stdc_rotate_left`` and ``__builtin_stdc_rotate_right``
- for bit rotation of unsigned integers including ``_BitInt`` types. Rotation
+- Added `__builtin_stdc_rotate_left` and `__builtin_stdc_rotate_right`
+ for bit rotation of unsigned integers including `_BitInt` types. Rotation
counts are normalized modulo the bit-width and support negative values.
Usable in constant expressions. Implicit conversion is supported for
class/struct types with conversion operators.
-- Implemented the following C23 ``<stdbit.h>`` builtins with ``_BitInt``
+- Implemented the following C23 `<stdbit.h>` builtins with `_BitInt`
support and constexpr evaluation:
- ``__builtin_stdc_leading_zeros``, ``__builtin_stdc_leading_ones``,
- ``__builtin_stdc_trailing_zeros``, ``__builtin_stdc_trailing_ones``,
- ``__builtin_stdc_first_leading_zero``, ``__builtin_stdc_first_leading_one``,
- ``__builtin_stdc_first_trailing_zero``, ``__builtin_stdc_first_trailing_one``,
- ``__builtin_stdc_count_zeros``, ``__builtin_stdc_count_ones``,
- ``__builtin_stdc_has_single_bit``, ``__builtin_stdc_bit_width``,
- ``__builtin_stdc_bit_floor``, and ``__builtin_stdc_bit_ceil``.
-
-- Implemented the type-specific C23 ``<stdbit.h>`` functions with constexpr
+ `__builtin_stdc_leading_zeros`, `__builtin_stdc_leading_ones`,
+ `__builtin_stdc_trailing_zeros`, `__builtin_stdc_trailing_ones`,
+ `__builtin_stdc_first_leading_zero`, `__builtin_stdc_first_leading_one`,
+ `__builtin_stdc_first_trailing_zero`, `__builtin_stdc_first_trailing_one`,
+ `__builtin_stdc_count_zeros`, `__builtin_stdc_count_ones`,
+ `__builtin_stdc_has_single_bit`, `__builtin_stdc_bit_width`,
+ `__builtin_stdc_bit_floor`, and `__builtin_stdc_bit_ceil`.
+- Implemented the type-specific C23 `<stdbit.h>` functions with constexpr
evaluation support:
- ``stdc_leading_zeros_{uc,us,ui,ul,ull}``,
- ``stdc_leading_ones_{uc,us,ui,ul,ull}``,
- ``stdc_trailing_zeros_{uc,us,ui,ul,ull}``,
- ``stdc_trailing_ones_{uc,us,ui,ul,ull}``,
- ``stdc_first_leading_zero_{uc,us,ui,ul,ull}``,
- ``stdc_first_leading_one_{uc,us,ui,ul,ull}``,
- ``stdc_first_trailing_zero_{uc,us,ui,ul,ull}``,
- ``stdc_first_trailing_one_{uc,us,ui,ul,ull}``,
- ``stdc_count_zeros_{uc,us,ui,ul,ull}``,
- ``stdc_count_ones_{uc,us,ui,ul,ull}``,
- ``stdc_has_single_bit_{uc,us,ui,ul,ull}``,
- ``stdc_bit_width_{uc,us,ui,ul,ull}``,
- ``stdc_bit_floor_{uc,us,ui,ul,ull}``, and
- ``stdc_bit_ceil_{uc,us,ui,ul,ull}``.
-
-- A new generic bit-reverse builtin function ``__builtin_bitreverseg`` that
+ `stdc_leading_zeros_{uc,us,ui,ul,ull}`,
+ `stdc_leading_ones_{uc,us,ui,ul,ull}`,
+ `stdc_trailing_zeros_{uc,us,ui,ul,ull}`,
+ `stdc_trailing_ones_{uc,us,ui,ul,ull}`,
+ `stdc_first_leading_zero_{uc,us,ui,ul,ull}`,
+ `stdc_first_leading_one_{uc,us,ui,ul,ull}`,
+ `stdc_first_trailing_zero_{uc,us,ui,ul,ull}`,
+ `stdc_first_trailing_one_{uc,us,ui,ul,ull}`,
+ `stdc_count_zeros_{uc,us,ui,ul,ull}`,
+ `stdc_count_ones_{uc,us,ui,ul,ull}`,
+ `stdc_has_single_bit_{uc,us,ui,ul,ull}`,
+ `stdc_bit_width_{uc,us,ui,ul,ull}`,
+ `stdc_bit_floor_{uc,us,ui,ul,ull}`, and
+ `stdc_bit_ceil_{uc,us,ui,ul,ull}`.
+- A new generic bit-reverse builtin function `__builtin_bitreverseg` that
extends bit-reversal support to all standard integers type, including
- ``_BitInt``
-
-- Added ``__builtin_elementwise_clmul`` for carry-less multiplication of
- integers including ``_BitInt`` types. This includes constexpr evaluation
+ `_BitInt`
+- Added `__builtin_elementwise_clmul` for carry-less multiplication of
+ integers including `_BitInt` types. This includes constexpr evaluation
support.
-
-- Added ``__builtin_elementwise_pext`` and ``__builtin_elementwise_pdep`` for
+- Added `__builtin_elementwise_pext` and `__builtin_elementwise_pdep` for
parallel bit extract and parallel bit deposit operations on integers including
- ``_BitInt`` types. This includes constexpr evaluation support.
-
-- Deprecated float types support from ``__builtin_elementwise_max`` and
- ``__builtin_elementwise_min``.
-
-- Added header ``endian.h`` which contains byte order helpers specified in POSIX
-
+ `_BitInt` types. This includes constexpr evaluation support.
+- Deprecated float types support from `__builtin_elementwise_max` and
+ `__builtin_elementwise_min`.
+- Added header `endian.h` which contains byte order helpers specified in POSIX
- Added #pragma loop licm(disable) for llvm.loop.licm.disable metadata
-
-- Added a new ``ExplicitInstantiationDecl`` AST node to represent explicit
- template instantiations (e.g., ``template void foo<int>();`` or
- ``extern template class S<int>;``). Previously, source location information
+- Added a new `ExplicitInstantiationDecl` AST node to represent explicit
+ template instantiations (e.g., `template void foo<int>();` or
+ `extern template class S<int>;`). Previously, source location information
for explicit instantiation statements was discarded after parsing. The new
- node preserves the full source range including the ``extern`` and ``template``
+ node preserves the full source range including the `extern` and `template`
keywords, qualifiers, template arguments as written, and the declared type,
enabling tools such as language servers and refactoring engines to accurately
map source locations back to explicit instantiation sites.
-
-- ``typeid`` on references and pointers of ``final`` types no longer emits a
+- `typeid` on references and pointers of `final` types no longer emits a
vtable lookup at runtime.
-
- Updated support for Unicode from 15.1 to 18.0.
-
- Linux and Windows toolchains now support Clang multilibs using
- ``-fmultilib-flag=``.
+ `-fmultilib-flag=`.
+- The SafeStack builtins `__builtin___get_unsafe_stack_ptr`,
+ `__builtin___get_unsafe_stack_bottom`, `__builtin___get_unsafe_stack_top`,
+ and `__builtin___get_unsafe_stack_start` are now deprecated. Use the
+ corresponding functions from `<sanitizer/safestack_interface.h>` instead.
-- The SafeStack builtins ``__builtin___get_unsafe_stack_ptr``,
- ``__builtin___get_unsafe_stack_bottom``, ``__builtin___get_unsafe_stack_top``,
- and ``__builtin___get_unsafe_stack_start`` are now deprecated. Use the
- corresponding functions from ``<sanitizer/safestack_interface.h>`` instead.
+### New Compiler Flags
-New Compiler Flags
-------------------
-- New option ``-fms-anonymous-structs`` / ``-fno-ms-anonymous-structs`` added
+- New option `-fms-anonymous-structs` / `-fno-ms-anonymous-structs` added
to enable or disable Microsoft's anonymous struct/union extension without
- enabling other ``-fms-extensions`` features (#GH177607).
-- New option ``--precompile-reduced-bmi`` allows build system to generate a
+ enabling other `-fms-extensions` features (#GH177607).
+- New option `--precompile-reduced-bmi` allows build system to generate a
reduced BMI only for a C++20 importable module unit. Previously the users
can only generate the reduced BMI as a by-product, e.g, an object files or
a full BMI.
-
-- New ``-cc1`` option ``-fexperimental-overflow-behavior-types`` added to
- enable parsing of the experimental ``overflow_behavior`` type attribute and
+- New `-cc1` option `-fexperimental-overflow-behavior-types` added to
+ enable parsing of the experimental `overflow_behavior` type attribute and
type specifiers.
-
-- New ``-cl`` option ``/d2guardnochecks`` added to match MSVC. When Windows
+- New `-cl` option `/d2guardnochecks` added to match MSVC. When Windows
Control Flow Guard (CFG) is enabled by other options, it will instruct Clang
to emit the CFG metadata, but disable adding checks.
-
-- New option ``-fdiagnostics-show-inlining-chain`` added to show inlining chain
- notes for ``[[gnu::warning]]`` and ``[[gnu::error]]`` diagnostics. When a
+- New option `-fdiagnostics-show-inlining-chain` added to show inlining chain
+ notes for `[[gnu::warning]]` and `[[gnu::error]]` diagnostics. When a
function with these attributes is called from an inlined context, Clang can
now show which functions were inlined to reach the call. When debug info is
- available (``-gline-directives-only`` (implicitly enabled at ``-g1``) or
+ available (`-gline-directives-only` (implicitly enabled at `-g1`) or
higher), accurate source locations are used; otherwise, a heuristic fallback
is used with a note suggesting how to enable debug info for better accuracy.
-
-- New option ``-fwin-cfg-mechanism=`` added to control the mechanism used by
- Control Flow Guard on Windows. Accepted values are ``automatic`` (default),
- ``dispatch``, and ``check``. The ``dispatch`` mechanism uses the dispatch
+- New option `-fwin-cfg-mechanism=` added to control the mechanism used by
+ Control Flow Guard on Windows. Accepted values are `automatic` (default),
+ `dispatch`, and `check`. The `dispatch` mechanism uses the dispatch
function to perform indirect call checks and can improve performance, while
- ``check`` uses the traditional check mechanism.
-- New ``-cl`` option ``/d2guardcfgdispatch`` added to match MSVC. This acts as a
- shorthand for ``-fwin-cfg-mechanism=dispatch``.
-- New ``-cl`` option ``/d2guardcfgdispatch-`` added to match MSVC. This acts as a
- shorthand for ``-fwin-cfg-mechanism=check``.
-
-- New option ``-f[no-]strict-bool`` added to control whether Clang can assume
- that ``bool`` values loaded from memory cannot have a bit pattern other
+ `check` uses the traditional check mechanism.
+- New `-cl` option `/d2guardcfgdispatch` added to match MSVC. This acts as a
+ shorthand for `-fwin-cfg-mechanism=dispatch`.
+- New `-cl` option `/d2guardcfgdispatch-` added to match MSVC. This acts as a
+ shorthand for `-fwin-cfg-mechanism=check`.
+- New option `-f[no-]strict-bool` added to control whether Clang can assume
+ that `bool` values loaded from memory cannot have a bit pattern other
than 0 or 1.
-
-- New option ``-fcrash-diagnostics-tar`` added to create an archive of crash
+- New option `-fcrash-diagnostics-tar` added to create an archive of crash
reproducer files for easier bug filing.
-
-- There are a new pair of flags for riscv32 called ``-mzilsd-word-align`` and
- ``-mzilsd-strict-align`` which control whether Zilsd accesses are allowed to
+- There are a new pair of flags for riscv32 called `-mzilsd-word-align` and
+ `-mzilsd-strict-align` which control whether Zilsd accesses are allowed to
be aligned to 4-byte alignment rather than fully unaligned or fully (8-byte)
aligned.
-
-- New ``-cl`` option ``/pathmap:`` added to match MSVC. This option acts as a
- clang's ``-ffile-prefix-map=value`` and has known differences in behaviour
+- New `-cl` option `/pathmap:` added to match MSVC. This option acts as a
+ clang's `-ffile-prefix-map=value` and has known differences in behaviour
with the CL's option that do not affect the functionality: nomalizes the
macro prefix map pathes -- removes `./` and uses the target's platform-
- specific path separator character when expanding the preprocessor macros --
- ``-ffile-reproducible`` (but not the debug and coverage prefix maps);
- does not require ``/experimental:deterministic`` as by MSVC. It needed for
+ specific path separator character when expanding the preprocessor macros --
+ `-ffile-reproducible` (but not the debug and coverage prefix maps);
+ does not require `/experimental:deterministic` as by MSVC. It needed for
removing a hostname from a mangling hash gen, but clang-cl does not use
a hostname when generates the hashes. Known issues -- does not remap the
source file pathes within PCH/PCM files.
-
-- New ``-cl`` option ``/experimental:deterministic`` added to match CL's option.
- This enables warning emission on usage of non-deterministic macros __DATE__,
- __TIME__ and __TIMESTAMP__ and provides reproducable COFF's timestamp for
+- New `-cl` option `/experimental:deterministic` added to match CL's option.
+ This enables warning emission on usage of non-deterministic macros \_\_DATE\_\_,
+ \_\_TIME\_\_ and \_\_TIMESTAMP\_\_ and provides reproducable COFF's timestamp for
the output object files.
-
-- New ``-cl`` option ``/d1nodatetime`` added to match CL's option. This option
- undefines the standard macros __DATE__, __TIME__ and __TIMESTAMP__ to allow
+- New `-cl` option `/d1nodatetime` added to match CL's option. This option
+ undefines the standard macros \_\_DATE\_\_, \_\_TIME\_\_ and \_\_TIMESTAMP\_\_ to allow
reproducable builds. These macros can be redefined from the command line if
- necessary. ``/d1nodatetime-`` can be used to turn this feature off if
+ necessary. `/d1nodatetime-` can be used to turn this feature off if
necessary to override the common build settings.
-Deprecated Compiler Flags
--------------------------
+### Deprecated Compiler Flags
+
+### Modified Compiler Flags
-Modified Compiler Flags
------------------------
- The `-mno-outline` and `-moutline` compiler flags are now allowed on RISC-V and X86, which both support the machine outliner.
- The `-mno-outline` flag will now add the `nooutline` IR attribute, so that
`-mno-outline` and `-moutline` objects can be mixed correctly during LTO.
- The `-fzero-call-used-regs` compiler flag is now allowed on RISC-V, only the
"skip", "used-gpr", "used-gpr-arg", "all-gpr" and "all-gpr-arg" options are
supported for the moment.
-
-- Slightly changed hash id generation to get the unique linkage symbols names
- by ``-unique-internal-linkage-names`` option. Now it uses a path that
+- Slightly changed hash id generation to get the unique linkage symbols names
+ by `-unique-internal-linkage-names` option. Now it uses a path that
normalized in favor of the target system (same as the preprocessor does
for the file macros) and allows the reproducable IDs on any build system.
-- ``-fprofile-update=atomic`` will now promote counter updates out of loops,
- similar to the non-atomic case ([#202487](https://github.com/llvm/llvm-project/pull/202487)).
-
-- The ``-cl`` ``/Brepro`` option was modified to match the original CL's option
- and now defines the standard macros __DATE__, __TIME__ and __TIMESTAMP__ to
+- `-fprofile-update=atomic` will now promote counter updates out of loops,
+ similar to the non-atomic case (\[#202487\](<https://github.com/llvm/llvm-project/pull/202487>)).
+- The `-cl` `/Brepro` option was modified to match the original CL's option
+ and now defines the standard macros \_\_DATE\_\_, \_\_TIME\_\_ and \_\_TIMESTAMP\_\_ to
"1". The previous functionality remains unchanged.
-Removed Compiler Flags
-----------------------
+### Removed Compiler Flags
-Attribute Changes in Clang
---------------------------
+### Attribute Changes in Clang
-- Added new attribute ``stack_protector_ignore`` to opt specific local variables out of
- the analysis which determines if a function should get a stack protector. A function
+- Added new attribute `stack_protector_ignore` to opt specific local variables out of
+ the analysis which determines if a function should get a stack protector. A function
will still generate a stack protector if other local variables or command line flags
require it.
-- Added a new attribute, ``[[clang::no_outline]]`` to suppress outlining from
+- Added a new attribute, `[[clang::no_outline]]` to suppress outlining from
annotated functions. This uses the LLVM `nooutline` attribute.
-- Introduced a new type attribute ``__attribute__((overflow_behavior))`` which
- currently accepts either ``wrap`` or ``trap`` as an argument, enabling
+- Introduced a new type attribute `__attribute__((overflow_behavior))` which
+ currently accepts either `wrap` or `trap` as an argument, enabling
type-level control over overflow behavior. There is also an accompanying type
specifier for each behavior kind via `__ob_wrap` and `__ob_trap`.
-- Introduced a new function attribute ``__attribute__((__personality__(...)))``
+- Introduced a new function attribute `__attribute__((__personality__(...)))`
to explicitly specify the personality routine for exception handling. THis is
meant to be a low level tool for language runtime authors to associate a
foreign language personality with a given function. Note that this does not
perform any ABI validation for the personality routine.
-- :doc:`ThreadSafetyAnalysis` attributes now correctly handle implicit member
+- {doc}`ThreadSafetyAnalysis` attributes now correctly handle implicit member
accesses in C, and parameter attributes in C++. This improves diagnostic
precision and fixes false positives.
-- The :doc:`ThreadSafetyAnalysis` attributes ``guarded_by`` and
- ``pt_guarded_by`` now accept multiple capability arguments with refined
+- The {doc}`ThreadSafetyAnalysis` attributes `guarded_by` and
+ `pt_guarded_by` now accept multiple capability arguments with refined
access semantics: *writing* requires all listed capabilities to be held
- exclusively, while *reading* requires at least one to be held. This is
+ exclusively, while *reading* requires at least one to be held. This is
sound because any writer must hold all capabilities, so holding any one
prevents concurrent writes.
-- :doc:`ThreadSafetyAnalysis` attributes like ``acquire_capability``,
- ``release_capability``, ``requires_capability``, ``locks_excluded``,
- ``try_acquire_capability``, and ``assert_capability`` can now be applied to
- function pointer variables and fields. The analysis checks calls through
+- {doc}`ThreadSafetyAnalysis` attributes like `acquire_capability`,
+ `release_capability`, `requires_capability`, `locks_excluded`,
+ `try_acquire_capability`, and `assert_capability` can now be applied to
+ function pointer variables and fields. The analysis checks calls through
annotated function pointers the same way it checks direct function calls.
Only plain function pointers are supported; pointers-to-member functions,
- blocks, or wrappers (e.g. ``std::function``) are not yet supported.
+ blocks, or wrappers (e.g. `std::function`) are not yet supported.
-- The ``[[clang::unsafe_buffer_usage]]`` attribute is now supported in API
+- The `[[clang::unsafe_buffer_usage]]` attribute is now supported in API
notes. For example:
-
- .. code-block:: yaml
- Functions:
- - Name: myUnsafeFunction
- UnsafeBufferUsage: true
+ ```yaml
+ Functions:
+ - Name: myUnsafeFunction
+ UnsafeBufferUsage: true
+ ```
-- When using ``-Wunsafe-buffer-usage`` without
- ``-fsafe-buffer-usage-suggestions``, warnings are now emitted only
+- When using `-Wunsafe-buffer-usage` without
+ `-fsafe-buffer-usage-suggestions`, warnings are now emitted only
once per source file. Pre-compiled code (such as PCH or module
headers) is no longer repeatedly analyzed, as it is analyzed during
its initial compilation. (Traditionally included headers are still
- analyzed within each translation unit that includes them). This
- behavior matches most of other ``-W`` diagnostics.
+ analyzed within each translation unit that includes them). This
+ behavior matches most of other `-W` diagnostics.
- When ``-fsafe-buffer-usage-suggestions`` is enabled, the behavior
+ When `-fsafe-buffer-usage-suggestions` is enabled, the behavior
remains the same as before: pre-compiled code is deserialized and
analyzed alongside the translation unit that uses it, because fix-it
suggestion analysis requires full visibility of the translation
unit.
-- Added support for ``[[msvc::forceinline]]`` for functions and
- ``[[msvc::forceinline_calls]]`` for statements. Both are aliases to
- ``[[clang::always_inline]]`` with additional checks to ensure that they
+- Added support for `[[msvc::forceinline]]` for functions and
+ `[[msvc::forceinline_calls]]` for statements. Both are aliases to
+ `[[clang::always_inline]]` with additional checks to ensure that they
are only accepted in places where MSVC also does.
-- The AMDGPU ``amdgpu_num_sgpr`` and ``amdgpu_num_vgpr`` attributes are now
- deprecated. Clang emits a ``-Wdeprecated-declarations`` warning when they
- are used. Use ``amdgpu_waves_per_eu`` instead to control SGPR and VGPR
+- The AMDGPU `amdgpu_num_sgpr` and `amdgpu_num_vgpr` attributes are now
+ deprecated. Clang emits a `-Wdeprecated-declarations` warning when they
+ are used. Use `amdgpu_waves_per_eu` instead to control SGPR and VGPR
usage.
- Clang now allows GNU attributes between a member declarator and bit-field width. (#GH184954)
-- The ``[[clang::noescape]]`` attribute now disallows deallocating memory
+- The `[[clang::noescape]]` attribute now disallows deallocating memory
through the annotated parameter. This information is currently not exposed to
LLVM for optimization purposes, to prevent breaking existing adopters. It may
instead be used by warnings and static analyses to provide more information
about pointer lifetimes. It may be used to power optimizations in the future,
however there are no concrete plans to do so at the moment.
-- The attributes ``[[clang::opencl_global_device]]`` and ``[[clang::opencl_global_host]]``
- are now deprecated. Clang emits a ``-Wdeprecated-attributes`` warning when
+- The attributes `[[clang::opencl_global_device]]` and `[[clang::opencl_global_host]]`
+ are now deprecated. Clang emits a `-Wdeprecated-attributes` warning when
they are used.
-
-- The ``modular_format`` attribute now supports the ``fixed`` aspect for C
- ISO 18037 fixed-point ``printf`` specifiers.
-Improvements to Clang's diagnostics
------------------------------------
-- Fixed bug in ``-Wdocumentation`` so that it correctly handles explicit
+- The `modular_format` attribute now supports the `fixed` aspect for C
+ ISO 18037 fixed-point `printf` specifiers.
+
+### Improvements to Clang's diagnostics
+
+- Fixed bug in `-Wdocumentation` so that it correctly handles explicit
function template instantiations (#64087).
-- Fixed concept template parameters not being recognized in ``-Wdocumentation``
+- Fixed concept template parameters not being recognized in `-Wdocumentation`
when mentioned in tparam comments. (#GH64087)
-- ``-Wunused-but-set-variable`` now diagnoses file-scope variables with
- internal linkage (``static`` storage class) that are assigned but never used.
- This new coverage is added under the subgroup ``-Wunused-but-set-global``,
- allowing it to be disabled independently with ``-Wno-unused-but-set-global``.
+- `-Wunused-but-set-variable` now diagnoses file-scope variables with
+ internal linkage (`static` storage class) that are assigned but never used.
+ This new coverage is added under the subgroup `-Wunused-but-set-global`,
+ allowing it to be disabled independently with `-Wno-unused-but-set-global`.
(#GH148361)
-- Added ``-Wlifetime-safety`` to enable lifetime safety analysis,
+- Added `-Wlifetime-safety` to enable lifetime safety analysis,
a CFG-based intra-procedural analysis that detects use-after-free and related
temporal safety bugs. See the
- `RFC <https://discourse.llvm.org/t/rfc-intra-procedural-lifetime-analysis-in-clang/86291>`_
- for more details. By design, this warning is enabled in ``-Weverything``. To disable
- the analysis, use ``-Wno-lifetime-safety`` or ``-fno-lifetime-safety``.
+ [RFC](https://discourse.llvm.org/t/rfc-intra-procedural-lifetime-analysis-in-clang/86291)
+ for more details. By design, this warning is enabled in `-Weverything`. To disable
+ the analysis, use `-Wno-lifetime-safety` or `-fno-lifetime-safety`.
-- Added ``-Wlifetime-safety-suggestions`` to enable lifetime annotation suggestions.
+- Added `-Wlifetime-safety-suggestions` to enable lifetime annotation suggestions.
This provides suggestions for function parameters that
- should be marked ``[[clang::lifetimebound]]`` based on lifetime analysis. For
+ should be marked `[[clang::lifetimebound]]` based on lifetime analysis. For
example, for the following function:
- .. code-block:: c++
-
- int* p(int *in) { return in; }
+ ```c++
+ int* p(int *in) { return in; }
+ ```
Clang will suggest:
- .. code-block:: c++
-
- warning: parameter in intra-TU function should be marked [[clang::lifetimebound]]
- int* p(int *in) { return in; }
- ^~~~~~~
- [[clang::lifetimebound]]
- note: param returned here
- int* p(int *in) { return in; }
- ^~
-
-- Added ``-Wlifetime-safety-noescape`` to detect misuse of ``[[clang::noescape]]``
+ ```c++
+ warning: parameter in intra-TU function should be marked [[clang::lifetimebound]]
+ int* p(int *in) { return in; }
+ ^~~~~~~
+ [[clang::lifetimebound]]
+ note: param returned here
+ int* p(int *in) { return in; }
+ ^~
+ ```
+
+- Added `-Wlifetime-safety-noescape` to detect misuse of `[[clang::noescape]]`
annotation where the parameter escapes through return. For example:
- .. code-block:: c++
-
- int* p(int *in [[clang::noescape]]) { return in; }
+ ```c++
+ int* p(int *in [[clang::noescape]]) { return in; }
+ ```
Clang will warn:
- .. code-block:: c++
-
- warning: parameter is marked [[clang::noescape]] but escapes
- int* p(int *in [[clang::noescape]]) { return in; }
- ^~~~~~~
- note: returned here
- int* p(int *in [[clang::noescape]]) { return in; }
- ^~
-
-- Added ``-Wlifetime-safety-dangling-field`` to detect dangling field references
- when stack memory escapes to class fields. This is part of ``-Wlifetime-safety``
+ ```c++
+ warning: parameter is marked [[clang::noescape]] but escapes
+ int* p(int *in [[clang::noescape]]) { return in; }
+ ^~~~~~~
+ note: returned here
+ int* p(int *in [[clang::noescape]]) { return in; }
+ ^~
+ ```
+
+- Added `-Wlifetime-safety-dangling-field` to detect dangling field references
+ when stack memory escapes to class fields. This is part of `-Wlifetime-safety`
and detects cases where local variables or parameters are stored in fields but
outlive their scope. For example:
- .. code-block:: c++
-
- struct DanglingView {
- std::string_view view;
- DanglingView(std::string s) : view(s) {} // warning: address of stack memory escapes to a field
- };
+ ```c++
+ struct DanglingView {
+ std::string_view view;
+ DanglingView(std::string s) : view(s) {} // warning: address of stack memory escapes to a field
+ };
+ ```
-- Improved ``-Wassign-enum`` performance by caching enum enumerator values. (#GH176454)
+- Improved `-Wassign-enum` performance by caching enum enumerator values. (#GH176454)
-- Fixed a false negative in ``-Warray-bounds`` where the warning was suppressed
+- Fixed a false negative in `-Warray-bounds` where the warning was suppressed
when accessing a member function on a past-the-end array element.
(#GH179128)
-- Added a missing space to the FixIt for the ``implicit-int`` group of diagnostics and
+- Added a missing space to the FixIt for the `implicit-int` group of diagnostics and
made sure that only one such diagnostic and FixIt is emitted per declaration group. (#GH179354)
-- Fixed the Fix-It insertion point for ``expected ';' after alias declaration``
- when parsing alias declarations involving a token-split ``>>`` sequence
- (for example, ``using A = X<int>>;``). (#GH184425)
+- Fixed the Fix-It insertion point for `expected ';' after alias declaration`
+ when parsing alias declarations involving a token-split `>>` sequence
+ (for example, `using A = X<int>>;`). (#GH184425)
-- Fixed incorrect ``implicitly deleted`` diagnostic for explicitly deleted
+- Fixed incorrect `implicitly deleted` diagnostic for explicitly deleted
candidate function. (#GH185693)
-- The ``-Wloop-analysis`` warning has been extended to catch more cases of
+- The `-Wloop-analysis` warning has been extended to catch more cases of
variable modification inside lambda expressions (#GH132038).
-- Clang now emits ``-Wsizeof-pointer-memaccess`` when snprintf/vsnprintf use the sizeof
+- Clang now emits `-Wsizeof-pointer-memaccess` when snprintf/vsnprintf use the sizeof
the destination buffer(dynamically allocated) in the len parameter(#GH162366)
-- Added ``-Wmodule-map-path-outside-directory`` (off by default) to warn on
- header and umbrella directory paths that use ``..`` to refer outside the module
+- Added `-Wmodule-map-path-outside-directory` (off by default) to warn on
+ header and umbrella directory paths that use `..` to refer outside the module
directory in module maps found via implicit search
- (``-fimplicit-module-maps``). This does not affect module maps specified
- explicitly via ``-fmodule-map-file=``.
+ (`-fimplicit-module-maps`). This does not affect module maps specified
+ explicitly via `-fmodule-map-file=`.
-- Honour ``[[maybe_unused]]`` attribute on private fields.
- ``-Wunused-private-field`` no longer emits a warning for annotated private
+- Honour `[[maybe_unused]]` attribute on private fields.
+ `-Wunused-private-field` no longer emits a warning for annotated private
fields.
-- Improved ``-Wgnu-zero-variadic-macro-arguments`` to suggest using
- ``__VA_OPT__`` if the current language version supports it(#GH188624)
+- Improved `-Wgnu-zero-variadic-macro-arguments` to suggest using
+ `__VA_OPT__` if the current language version supports it(#GH188624)
- Clang now emits an error when implicitly casting a complex type to a built-in vector type. (#GH186805)
-- Added ``-Wnonportable-include-path-separator`` (off by default) to catch
+- Added `-Wnonportable-include-path-separator` (off by default) to catch
#include directives that use backslashes as a path separator. The warning
includes a FixIt to change all the backslashes to forward slashes, so that the
code can automatically be made portable to other host platforms that don't
@@ -643,10 +600,10 @@ Improvements to Clang's diagnostics
- Clang now explains why template deduction fails for explicit template arguments.
-- No longer emitting a ``-Wpre-c2y-compat`` or extension diagnostic about use
- of octal literals with a ``0o`` prefix, and no longer emitting a
- ``-Wdeprecated-octal-literals`` diagnostic for use of octal literals without
- a ``0o`` prefix, when the literal is expanded from a macro defined in a
+- No longer emitting a `-Wpre-c2y-compat` or extension diagnostic about use
+ of octal literals with a `0o` prefix, and no longer emitting a
+ `-Wdeprecated-octal-literals` diagnostic for use of octal literals without
+ a `0o` prefix, when the literal is expanded from a macro defined in a
system header. (#GH192389)
- Improved error recovery for missing semicolons after class members. Clang now avoids
@@ -659,52 +616,49 @@ Improvements to Clang's diagnostics
- Clang now errors when a function declaration aliases a variable or vice versa. (#GH195550)
-- Added ``-Wattribute-alias`` to diagnose type mismatches between an alias and its aliased function. (#GH195550)
+- Added `-Wattribute-alias` to diagnose type mismatches between an alias and its aliased function. (#GH195550)
-- The diagnostics around ``__block`` now explain why a variable cannot be marked ``__block``. (#GH197213)
+- The diagnostics around `__block` now explain why a variable cannot be marked `__block`. (#GH197213)
-- Extended ``-Wnonportable-include-path`` to warn about trailing whitespace and dots in ``#include`` paths. (#GH190610)
+- Extended `-Wnonportable-include-path` to warn about trailing whitespace and dots in `#include` paths. (#GH190610)
-- Clang now emits error when attribute is missing closing ``]]`` followed by ``;;``. (#GH187223)
+- Clang now emits error when attribute is missing closing `]]` followed by `;;`. (#GH187223)
- Clang now rejects inline asm constraints and clobbers that contain an
embedded null character, instead of silently truncating them. (#GH173900)
-- Added ``-Wstringop-overread`` to warn when ``memcpy``, ``memmove``, ``memcmp``,
+- Added `-Wstringop-overread` to warn when `memcpy`, `memmove`, `memcmp`,
and related builtins read more bytes than the source buffer size (#GH83728).
-
+
- Diagnostics for the C++11 range-based for statement now report the correct
iterator type in notes for invalid iterator types.
-Improvements to Clang's time-trace
-----------------------------------
+### Improvements to Clang's time-trace
-Improvements to Coverage Mapping
---------------------------------
+### Improvements to Coverage Mapping
- [MC/DC] Nested expressions are handled as individual MC/DC expressions.
- "Single byte coverage" now supports branch coverage and can be used
- together with ``-fcoverage-mcdc``.
+ together with `-fcoverage-mcdc`.
- Consteval member functions are no longer emitted in coverage mappings,
matching the existing behavior for free consteval functions. (#GH164448)
-Bug Fixes in This Version
--------------------------
+### Bug Fixes in This Version
-- Fixed an assertion when comparing a fixed point type with a ``_BitInt`` type. (#GH196948)
+- Fixed an assertion when comparing a fixed point type with a `_BitInt` type. (#GH196948)
- Fixed atomic boolean compound assignment; the conversion back to atomic bool would be miscompiled. (#GH33210)
- Correctly handle default template argument when establishing subsumption. (#GH188640)
-- Fixed a failed assertion in the preprocessor when ``__has_embed`` parameters are missing parentheses. (#GH175088)
+- Fixed a failed assertion in the preprocessor when `__has_embed` parameters are missing parentheses. (#GH175088)
- Fix lifetime extension of temporaries in for-range-initializers in templates. (#GH165182)
-- Fixed a preprocessor crash in ``__has_cpp_attribute`` on incomplete scoped attributes. (#GH178098)
-- Fixes an assertion failure when evaluating ``__underlying_type`` on enum redeclarations. (#GH177943)
-- Fixed an assertion failure caused by nested macro expansion during header-name lexing (``__has_embed(__has_include)``). (#GH178635)
+- Fixed a preprocessor crash in `__has_cpp_attribute` on incomplete scoped attributes. (#GH178098)
+- Fixes an assertion failure when evaluating `__underlying_type` on enum redeclarations. (#GH177943)
+- Fixed an assertion failure caused by nested macro expansion during header-name lexing (`__has_embed(__has_include)`). (#GH178635)
- Clang now outputs relative paths of embeds for dependency output. (#GH161950)
- Fix the result type of a binary operation where both operands are 'void' l-values. (#GH111300)
-- Fixed an assertion failure when evaluating ``_Countof`` on invalid ``void``-typed operands. (#GH180893)
-- Fixed an assertion failure in the serialized diagnostic printer when it is destroyed without calling ``finish()``. (#GH140433)
+- Fixed an assertion failure when evaluating `_Countof` on invalid `void`-typed operands. (#GH180893)
+- Fixed an assertion failure in the serialized diagnostic printer when it is destroyed without calling `finish()`. (#GH140433)
- Fixed an assertion failure caused by error recovery while extending a nested name specifier with results from ordinary lookup. (#GH181470)
-- Fixed a crash when parsing ``#pragma clang attribute`` arguments for attributes that forbid arguments. (#GH182122)
+- Fixed a crash when parsing `#pragma clang attribute` arguments for attributes that forbid arguments. (#GH182122)
- Fixed a bug in how Clang re-transforms expressions produced from substititions
from type aliases and concept specializations. (#GH191738) (#GH196375)
- Fixed a bug with multiple-include optimization (MIOpt) state not being preserved in some cases during lexing, which could suppress header-guard mismatch diagnostics and interfere with include-guard optimization. (#GH180155)
@@ -712,66 +666,66 @@ Bug Fixes in This Version
- Fixed a crash caused by accessing dependent diagnostics of a non-dependent context.
- Fixed a crash when substituting into a non-type template parameter that has a type containing an undeduced placeholder type.
- Fixed several crashes and improved diagnostics when a multidimensional subscript operator is applied to a built-in type. (#GH187800)
-- Correctly diagnosing and no longer crashing when ``export module foo``
+- Correctly diagnosing and no longer crashing when `export module foo`
(without a semicolon) are the final tokens in a module file. (#GH187771)
- Fixed a crash in duplicate attribute checking caused by comparing constant arguments with different integer signedness. (#GH188259)
- Clang now emits an error when returning an initializer list from a lambda
with an explicit return type of void. The diagnostic now correctly refers
to "lambda" instead of "block". (#GH188661)
-- Fixed a crash on _BitInt(N) arrays where 129 ≤ N ≤ 192 due to incorrect array filler lowering. (#GH189643)
-- Fixed the behavior in C23 of ``auto``, by emitting an error when an array type is specified for a ``char *``. (#GH162694)
-- Fixed an issue where an assert was thrown instead of an error if no vulkan env was specified with ``--triple spirv``. (#GH189964)
-- Fixed incorrect rejection of ``auto`` with reordered declaration specifiers in C23. (#GH164121)
+- Fixed a crash on \_BitInt(N) arrays where 129 ≤ N ≤ 192 due to incorrect array filler lowering. (#GH189643)
+- Fixed the behavior in C23 of `auto`, by emitting an error when an array type is specified for a `char *`. (#GH162694)
+- Fixed an issue where an assert was thrown instead of an error if no vulkan env was specified with `--triple spirv`. (#GH189964)
+- Fixed incorrect rejection of `auto` with reordered declaration specifiers in C23. (#GH164121)
- Fixed a bug where Clang fails to find instantiation of Decls in constraint checking. (#GH173086)
-- Fixed a crash when assigning to an element of an ``ext_vector_type`` with ``bool`` element type. (#GH189260)
-- Fixed a crash caused by declaring multiple ``ownership_returns`` attributes with mismatched or missing arguments. (#GH188733)
+- Fixed a crash when assigning to an element of an `ext_vector_type` with `bool` element type. (#GH189260)
+- Fixed a crash caused by declaring multiple `ownership_returns` attributes with mismatched or missing arguments. (#GH188733)
- Clang now emits an error for friend declarations of lambda members. (#GH26540)
- Fixed a crash caused by lambda capture handling in delayed default arguments. (#GH176534)
-- Fixed a crash when parsing invalid ``static_assert`` declarations with string-literal messages (#GH187690).
+- Fixed a crash when parsing invalid `static_assert` declarations with string-literal messages (#GH187690).
- Fixed a potential stack-use-after-return issue in Clang when copy-initializing
an array via an element-at-a-time copy loop (#GH192026)
- Fixed an issue where certain designated initializers would be rejected for constexpr variables. (#GH193373)
-- Fixed ``clang::Preprocessor::recomputeCurLexerKind`` to avoid default fallback to ``CurLexerCallback = CLK_CachingLexer;``. This prevents code-completion
+- Fixed `clang::Preprocessor::recomputeCurLexerKind` to avoid default fallback to `CurLexerCallback = CLK_CachingLexer;`. This prevents code-completion
EOF handling from accidentally restoring CLK_CachingLexer while a tentative parse is still active, which could trigger a caching lexer re-entry assertion
in clangd signature help. (#GH200677)
-- Fixed a crash when ``#embed`` is used with C++ modules (#GH195350)
-- Fixed an assertion in constant evaluation when using a defaulted comparison operator in a ``union``. (#GH147127)
-- Fixed a bug where ``-x cuda`` caused clang to immediately resolve templates that should not be. (#GH200545)
-- Fixed an issue where ``__typeof_unqual`` and ``__typeof_unqual__`` were rejected as a declaration specifier in block scope in C++.
+- Fixed a crash when `#embed` is used with C++ modules (#GH195350)
+- Fixed an assertion in constant evaluation when using a defaulted comparison operator in a `union`. (#GH147127)
+- Fixed a bug where `-x cuda` caused clang to immediately resolve templates that should not be. (#GH200545)
+- Fixed an issue where `__typeof_unqual` and `__typeof_unqual__` were rejected as a declaration specifier in block scope in C++.
- Fixed crash when checking for overflow for unary operator that can't overflow (#GH170072)
- Clang no longer handles a `" q-char-sequence "` header name as a string literal (#GH132643).
- Fixed an assertion where we improperly handled implicit conversions to integral types from an atomic-type with a conversion function. (#GH201770)
-- Fixed a regression where calling a function that takes a class-type parameter by value inside ``decltype`` of a concept could be incorrectly rejected when used as a non-type template argument. (#GH175831)
+- Fixed a regression where calling a function that takes a class-type parameter by value inside `decltype` of a concept could be incorrectly rejected when used as a non-type template argument. (#GH175831)
+
+#### Bug Fixes to Compiler Builtins
-Bug Fixes to Compiler Builtins
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- Fix a crash when passing an unresolved overload set to ``__builtin_classify_type``. (#GH175589)
+- Fix a crash when passing an unresolved overload set to `__builtin_classify_type`. (#GH175589)
- Fixed a crash when calling `__builtin_allow_sanitize_check` with no arguments. (#GH183927)
-- ``__annotation`` is now diagnosed as unsupported on non-Windows/UEFI targets, fixing a
- crash when using it with ``-fms-extensions`` on other platforms. (#GH184318)
+- `__annotation` is now diagnosed as unsupported on non-Windows/UEFI targets, fixing a
+ crash when using it with `-fms-extensions` on other platforms. (#GH184318)
- Fixed a compiler crash due to an unresolved overloaded function type when
- calling ``__builtin_bit_cast``. (#GH200112)
+ calling `__builtin_bit_cast`. (#GH200112)
-Bug Fixes to Attribute Support
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- Fixed a behavioral discrepancy between deleted functions and private members when checking the ``enable_if`` attribute. (#GH175895)
-- Fixed ``init_priority`` attribute by delaying type checks until after the type is deduced.
-- Fixed a crash when a ``section`` attribute or ``#pragma clang section`` caused a
+#### Bug Fixes to Attribute Support
+
+- Fixed a behavioral discrepancy between deleted functions and private members when checking the `enable_if` attribute. (#GH175895)
+- Fixed `init_priority` attribute by delaying type checks until after the type is deduced.
+- Fixed a crash when a `section` attribute or `#pragma clang section` caused a
section type conflict with a declaration whose name is not a simple identifier,
such as a lambda's call operator. (#GH192264)
-- Fixed a regression where attributed types (such as those carrying ``_Nonnull``/``_Nullable`` attributes)
+- Fixed a regression where attributed types (such as those carrying `_Nonnull`/`_Nullable` attributes)
were not deduplicated, because the attributes' arguments were not taken into
account when uniquing them. The duplications could substantially increase the
size of precompiled headers and modules (PCH/PCM), and the time spent loading
them. (#GH200961)
-Bug Fixes to C++ Support
-^^^^^^^^^^^^^^^^^^^^^^^^
-- Fixed a preprocessor assertion failure triggered when parsing an invalid template-id starting with ``::template operator``. (#GH186582)
+#### Bug Fixes to C++ Support
+
+- Fixed a preprocessor assertion failure triggered when parsing an invalid template-id starting with `::template operator`. (#GH186582)
- Fixed a crash when a function template is defined as a non-template friend with a global scope qualifier. (#GH185341)
- Clang now rejects constant template parameters with block pointer types, since these are not implemented anyway and would lead to crashes. (#GH189247)
- Fixed a crash on error recovery when dealing with invalid templates. (#GH183075)
-- Fixed a crash when instantiating ``requires`` expressions involving substitution failures in C++ concepts. (#GH176402)
+- Fixed a crash when instantiating `requires` expressions involving substitution failures in C++ concepts. (#GH176402)
- Concepts appearing in the require-clause of a member function no longer have access to non-public members of that class,
or to a current class object. (#GH115838) (#GH194803) (#GH197067)
- We no longer caches invalid variable specializations. (#GH132592)
@@ -780,7 +734,7 @@ Bug Fixes to C++ Support
- Clang no longer errors on overloads with different ref-qualifiers and constraints. (#GH120812)
- Fixed a crash when a default argument is passed to an explicit object parameter. (#GH176639)
- Fixed an alias template CTAD crash.
-- Correctly diagnose uses of ``co_await`` / ``co_yield`` in the default argument of nested function declarations. (#GH98923)
+- Correctly diagnose uses of `co_await` / `co_yield` in the default argument of nested function declarations. (#GH98923)
- Fixed a crash when diagnosing an invalid static member function with an explicit object parameter (#GH177741)
- Clang incorrectly instantiated variable specializations outside of the immediate context. (#GH54439)
- Fixed a crash when pack expansions are used as arguments for non-pack parameters of built-in templates. (#GH180307)
@@ -790,15 +744,15 @@ Bug Fixes to C++ Support
- Fix a problem where pack index expressions where incorrectly being regarded as equivalent.
- Fixed a bug where captured variables in non-mutable lambdas were incorrectly treated as mutable
when used inside decltype in the return type. (#GH180460)
-- Fixed a crash when evaluating uninitialized GCC vector/ext_vector_type vectors in ``constexpr``. (#GH180044)
+- Fixed a crash when evaluating uninitialized GCC vector/ext_vector_type vectors in `constexpr`. (#GH180044)
- Fixed a crash when `explicit(bool)` is used with an incomplete enumeration. (#GH183887)
-- Fixed a crash on ``typeid`` of incomplete local types during template instantiation. (#GH63242), (#GH176397)
+- Fixed a crash on `typeid` of incomplete local types during template instantiation. (#GH63242), (#GH176397)
- Fixed spurious diagnostics produced when checking if constraints are equivalent for redeclarations,
which could make the program mistakenly ill-formed.
-- Fixed a crash when an immediate-invoked ``consteval`` lambda is used as an invalid initializer. (#GH185270)
+- Fixed a crash when an immediate-invoked `consteval` lambda is used as an invalid initializer. (#GH185270)
- Fixed an assertion failure when using a global destructor with a target with a non-default program address space. (#GH186484)
- Fixed a crash when instantiating an invalid out-of-line static data member definition in a local class. (#GH176152)
-- Inherited constructors in ``dllexport`` classes are now exported for ABI-compatible cases, matching
+- Inherited constructors in `dllexport` classes are now exported for ABI-compatible cases, matching
MSVC behavior. Constructors with variadic arguments or callee-cleanup parameters are not yet supported
and produce a warning. (#GH162640)
- Correctly diagnose invalid non-dependent calls in dependent contexts. (#GH135694)
@@ -807,112 +761,107 @@ Bug Fixes to C++ Support
- We no longer consider conversion operators when copy-initializing from the same type. This was non
conforming and could lead to recursive constraint satisfaction checking. (#GH149443)
- Fixed a crash in Itanium C++ name mangling for a lambda in a local class field initializer inside a constructor/destructor. (#GH176395)
-- Fixed a crash when Expr::ClassifyImpl computes a classification like CL_LValue or CL_PRValue, then asserts that this
+- Fixed a crash when Expr::ClassifyImpl computes a classification like CL_LValue or CL_PRValue, then asserts that this
agrees with the AST node's own value category. (#GH202693)
- Fixed crashes in Itanium C++ name mangling for lambdas with trailing requires-clauses involving requires-expressions. (#GH100774) (#GH123854)
-- Fixed an invalid rejection and assertion failure while generating ``operator=`` for fields with the ``__restrict`` qualifier. (#GH37979)
+- Fixed an invalid rejection and assertion failure while generating `operator=` for fields with the `__restrict` qualifier. (#GH37979)
- Fixed a use-after-free bug when parsing default arguments containing lambdas in declarations with template-id declarators. (#GH196725)
- Fixed a crash in constant evaluation using placement new on an array which was later initialized. (#GH196450)
- Fixed an issue where Clang incorrectly accepted invalid unqualified uses of local nested class names outside their declaring scope. (#GH184622)
- Fixed a crash when parsing invalid friend declaration with storage-class specifier. (#GH186569)
-- Fixed a missing vtable for ``dynamic_cast<FinalClass *>(this)`` in a function template. (#GH198511)
+- Fixed a missing vtable for `dynamic_cast<FinalClass *>(this)` in a function template. (#GH198511)
+
+#### Bug Fixes to AST Handling
-Bug Fixes to AST Handling
-^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed a bug where explicit nullability property attributes were not stored in AST nodes in Objective-C. (#GH179703)
- Fixed a bug where alias CTAD, or an invalid template template parameter, could create a template with an empty template
parameter list. This also adds asserts to prevent this from happening again.
-- Fixed a crash when parsing Doxygen ``@param`` commands attached to invalid declarations or non-function entities. (#GH182737)
+- Fixed a crash when parsing Doxygen `@param` commands attached to invalid declarations or non-function entities. (#GH182737)
- Fixed the SourceLocation and SourceRange of reversed rewritten CXXOperatorCallExpr. (#GH192467)
-- Fixed a assertion when ``__block`` is used on global variables in C mode. (#GH183974)
-- Added missing AST nodes representing the ``decltype`` specifiers in destructor call to AST.
+- Fixed a assertion when `__block` is used on global variables in C mode. (#GH183974)
+- Added missing AST nodes representing the `decltype` specifiers in destructor call to AST.
- Fixed a missing ODR violation diagnostic introduced by the inline assembly string or clobber list. (#GH198616)
-Miscellaneous Bug Fixes
-^^^^^^^^^^^^^^^^^^^^^^^
+#### Miscellaneous Bug Fixes
+
- Fixed a crash whith the AST text dumper, when dumping a reference to a
decomposition with no bindinds. (#GH198842)
-- Fixed the arguments of the format attribute on ``__builtin_os_log_format``. Previously, they were off by 1.
+- Fixed the arguments of the format attribute on `__builtin_os_log_format`. Previously, they were off by 1.
-Miscellaneous Clang Crashes Fixed
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### Miscellaneous Clang Crashes Fixed
- Fixed a crash when attempting to jump over initialization of a variable with variably modified type. (#GH175540)
- Fixed a crash when using loop hint with a value dependent argument inside a
generic lambda. (#GH172289)
-- Fixed a crash in C++ overload resolution with ``_Atomic``-qualified argument types. (#GH170433)
+- Fixed a crash in C++ overload resolution with `_Atomic`-qualified argument types. (#GH170433)
- Fixed a crash related to missing source locations (#GH186655)
- Fixed a crash when casting a parenthesized unresolved template-id or array section. (#GH183505)
-- Fixed a crash when initializing a ``constexpr`` pointer with a floating-point literal in C23. (#GH180313)
+- Fixed a crash when initializing a `constexpr` pointer with a floating-point literal in C23. (#GH180313)
- Fixed a lack of diagnostic for substitution failures in base classes when using `std::void_t`-like types.
- Fixed a crash when emitting debug info for base classes with instantiation-dependent-only types (#GH193932)
-- Fixed an assertion when diagnosing address-space qualified ``new``/``delete`` in language-defined address spaces such as OpenCL ``__local``. (#GH178319)
+- Fixed an assertion when diagnosing address-space qualified `new`/`delete` in language-defined address spaces such as OpenCL `__local`. (#GH178319)
- Fixed an assertion failure in ObjC++ ARC when binding a rvalue reference to reference with different lifetimes (#GH178524)
- Fixed a crash when subscripting a vector type with large unsigned integer values. (#GH180563)
- Fixed a crash when attempting to diagnose incompatible conversions involving function types (#GH182534)
-- Fixed a crash when evaluating ``__is_bitwise_cloneable`` on invalid record types. (#GH183707)
+- Fixed a crash when evaluating `__is_bitwise_cloneable` on invalid record types. (#GH183707)
- Fixed an assertion failure when casting a function pointer with a target with a non-default program address space. (#GH186210)
-- Fixed a crash when ``decltype(__builtin_FUNCTION())`` is used as a template type argument. (#GH167433)
-- Fixed an assertion failure when parsing an invalid ``decltype`` specifier with missing parentheses or extra semicolons. (#GH188014)
+- Fixed a crash when `decltype(__builtin_FUNCTION())` is used as a template type argument. (#GH167433)
+- Fixed an assertion failure when parsing an invalid `decltype` specifier with missing parentheses or extra semicolons. (#GH188014)
- Fixed a crash when explicitly casting a complex type to or from an atomic complex type. (#GH172208)
- Fixed a crash when explicitly casting a scalar to an atomic complex. (#GH114885)
- Fixed an assertion failure when parsing an invalid out-of-line enum definition with template parameters. (#GH187909)
- Fixed an assertion failure on invalid template template parameter during typo correction. (#GH183983)
-- Fixed an assertion failure in ``isAtEndOfMacroExpansion`` on macro expansions crossing the boundary of two fileIDs. (#GH115007), (#GH21755)
-- Fixed an assertion failure when ``__builtin_dump_struct`` is used with an
+- Fixed an assertion failure in `isAtEndOfMacroExpansion` on macro expansions crossing the boundary of two fileIDs. (#GH115007), (#GH21755)
+- Fixed an assertion failure when `__builtin_dump_struct` is used with an
immediate-escalated callable. (#GH192846)
-- Fixed a crash when passing one sized implicitly casted vector to a ``abs`` function. (#GH204777)
+- Fixed a crash when passing one sized implicitly casted vector to a `abs` function. (#GH204777)
- Fixed a crash when diagnosing an invalid out-of-line definition of a member class template. (#GH201490)
-OpenACC Specific Changes
-------------------------
+### OpenACC Specific Changes
+
+### OpenCL Specific Changes
-OpenCL Specific Changes
------------------------
-- Added support for OpenCL C 3.1 language version (``-cl-std=CL3.1``).
+- Added support for OpenCL C 3.1 language version (`-cl-std=CL3.1`).
-Target Specific Changes
------------------------
+### Target Specific Changes
-AMDGPU Support
-^^^^^^^^^^^^^^
-- Introduced a new target specific builtin ``__builtin_amdgcn_processor_is``,
+#### AMDGPU Support
+
+- Introduced a new target specific builtin `__builtin_amdgcn_processor_is`,
a late / deferred query for the current target processor.
-- Introduced a new target specific builtin ``__builtin_amdgcn_is_invocable``,
+- Introduced a new target specific builtin `__builtin_amdgcn_is_invocable`,
a late / deferred query for the availability of target specific builtins.
- Initial support for gfx1310
-- The ``amdgpu_num_sgpr`` and ``amdgpu_num_vgpr`` function attributes are now
- deprecated. Using them produces a ``-Wdeprecated-declarations`` warning. Use
- ``amdgpu_waves_per_eu`` instead.
+- The `amdgpu_num_sgpr` and `amdgpu_num_vgpr` function attributes are now
+ deprecated. Using them produces a `-Wdeprecated-declarations` warning. Use
+ `amdgpu_waves_per_eu` instead.
+
+#### NVPTX Support
-NVPTX Support
-^^^^^^^^^^^^^^
+#### X86 Support
-X86 Support
-^^^^^^^^^^^
-- ``march=znver6`` is now supported.
+- `march=znver6` is now supported.
-Arm and AArch64 Support
-^^^^^^^^^^^^^^^^^^^^^^^
+#### Arm and AArch64 Support
-Added support for the Arm AGI CPU via the ``-mcpu=armagicpu`` command-line option.
+Added support for the Arm AGI CPU via the `-mcpu=armagicpu` command-line option.
-Android Support
-^^^^^^^^^^^^^^^
+#### Android Support
-Windows Support
-^^^^^^^^^^^^^^^
+#### Windows Support
-- Clang now defines the ``_MSVC_TRADITIONAL`` macro as ``1`` when emulating MSVC
+- Clang now defines the `_MSVC_TRADITIONAL` macro as `1` when emulating MSVC
19.15 (Visual Studio 2017 version 15.8) and later. (#GH47114)
-- ``-fmacro-prefix-map=`` (``-ffile-prefix-map=``) now affects an anonymous namespace hash generation
+
+- `-fmacro-prefix-map=` (`-ffile-prefix-map=`) now affects an anonymous namespace hash generation
for the MSVC targets and allows deterministic symbol mangling for reproducible builds.
-- Added the ``-fwinx64-eh-unwind=`` flag to select the x64 Windows unwind info
- version (``v1``, ``v2-best-effort``, ``v2-required``, or ``v3``). The legacy
- ``-fwinx64-eh-unwindv2=`` flag is deprecated; it is still accepted and mapped
+- Added the `-fwinx64-eh-unwind=` flag to select the x64 Windows unwind info
+ version (`v1`, `v2-best-effort`, `v2-required`, or `v3`). The legacy
+ `-fwinx64-eh-unwindv2=` flag is deprecated; it is still accepted and mapped
onto the new flag as follows:
+ ```{eval-rst}
.. list-table::
:header-rows: 1
@@ -924,252 +873,227 @@ Windows Support
- ``v2-best-effort``
* - ``required``
- ``v2-required``
+ ```
- The MSVC-compatible ``/d2epilogunwind`` and ``/d2epilogunwindrequirev2``
- options map to ``v2-best-effort`` and ``v2-required`` respectively.
+ The MSVC-compatible `/d2epilogunwind` and `/d2epilogunwindrequirev2`
+ options map to `v2-best-effort` and `v2-required` respectively.
- When targeting Windows x64 with EGPR (`-mapx-features=egpr`), Clang now
automatically enables V3 unwind info (`-fwinx64-eh-unwind=v3`) if no
explicit unwind version was specified.
-LoongArch Support
-^^^^^^^^^^^^^^^^^
+#### LoongArch Support
- DWARF fission is now compatible with linker relaxations, allowing `-gsplit-dwarf` and `-mrelax`
to be used together when building for the LoongArch platform.
-RISC-V Support
-^^^^^^^^^^^^^^
+#### RISC-V Support
- Tenstorrent Ascalon D8 was renamed to Ascalon X. Use `tt-ascalon-x` with `-mcpu` or `-mtune`.
-- Intrinsics were added for the 'Zvabd` (RISC-V Integer Vector Absolute Difference) extension.
-- Intrinsics were added for the 'Zvzip` (Reordering Structured Data in Vector Registers) extension.
-- A new ``-mtune`` syntax was added to support processor-specific tuning feature string
- Currently this new syntax is gated by the ``-mexperimental-mtune-syntax`` flag.
+- Intrinsics were added for the 'Zvabd\` (RISC-V Integer Vector Absolute Difference) extension.
+- Intrinsics were added for the 'Zvzip\` (Reordering Structured Data in Vector Registers) extension.
+- A new `-mtune` syntax was added to support processor-specific tuning feature string
+ Currently this new syntax is gated by the `-mexperimental-mtune-syntax` flag.
-
-CUDA/HIP Language Changes
-^^^^^^^^^^^^^^^^^^^^^^^^^
+#### CUDA/HIP Language Changes
- The new offloading driver is now the default for HIP. Use
`--no-oflfoad-new-driver` to return to the old behavior.
-CUDA Support
-^^^^^^^^^^^^
+#### CUDA Support
- Fixed a bug where host-device ambiguities in CUDA/HIP when retrieving the
address of specializations of templated functions that have overloads for both
host and device. (#GH199299)
-AIX Support
-^^^^^^^^^^^
+#### AIX Support
- The driver default for the linker flag `-bcdtors` now defaults to `mbr`
(instead of `all`) which only extracts static init from archive members which
would otherwise be referenced.
- (See https://www.ibm.com/docs/en/aix/7.2.0?topic=l-ld-command for details).
-- The driver now uses ``-lcompiler_rt`` instead of ``-latomic``, and the compiler-rt
- archive has been renamed from ``libatomic.a`` to ``libcompiler_rt.a`` to avoid conflicts
+ (See <https://www.ibm.com/docs/en/aix/7.2.0?topic=l-ld-command> for details).
+- The driver now uses `-lcompiler_rt` instead of `-latomic`, and the compiler-rt
+ archive has been renamed from `libatomic.a` to `libcompiler_rt.a` to avoid conflicts
between the LLVM libatomic and the GNU libatomic from the AIX toolbox as they share
the same library name.
-- Added support for ``#pragma comment(copyright, "token_sequence")`` on AIX.
- This directive embeds a copyright or identifying string into the compiled object file.
+- Added support for `#pragma comment(copyright, "token_sequence")` on AIX.
+ This directive embeds a copyright or identifying string into the compiled object file.
The string is included in the final executable and loaded into memory at program runtime.
-NetBSD Support
-^^^^^^^^^^^^^^
+#### NetBSD Support
-WebAssembly Support
-^^^^^^^^^^^^^^^^^^^
+#### WebAssembly Support
-- Fixed a crash when ``__funcref`` is applied to a non-function pointer type.
+- Fixed a crash when `__funcref` is applied to a non-function pointer type.
(#GH118233)
-- WebAssembly reference types (``__externref_t`` and ``__funcref`` function
- pointers) now lower to the opaque IR types ``target("wasm.externref")`` and
- ``target("wasm.funcref")`` instead of ``ptr addrspace(10)`` /
- ``ptr addrspace(20)``.
-- Fixed a compiler crash at ``-O2`` when reference-type values were passed
+- WebAssembly reference types (`__externref_t` and `__funcref` function
+ pointers) now lower to the opaque IR types `target("wasm.externref")` and
+ `target("wasm.funcref")` instead of `ptr addrspace(10)` /
+ `ptr addrspace(20)`.
+- Fixed a compiler crash at `-O2` when reference-type values were passed
through control flow that the SLP vectorizer tried to vectorize.
-AVR Support
-^^^^^^^^^^^
+#### AVR Support
-SystemZ Support
-^^^^^^^^^^^^^^^
+#### SystemZ Support
-- Add support for `#pragma export` for z/OS. This is a pragma used to export functions and variables
- with external linkage from shared libraries. It provides compatibility with the IBM XL C/C++
+- Add support for `#pragma export` for z/OS. This is a pragma used to export functions and variables
+ with external linkage from shared libraries. It provides compatibility with the IBM XL C/C++
compiler.
-DWARF Support in Clang
-----------------------
+### DWARF Support in Clang
+
+### Floating Point Support in Clang
-Floating Point Support in Clang
--------------------------------
+### Fixed Point Support in Clang
-Fixed Point Support in Clang
-----------------------------
+### AST Matchers
-AST Matchers
-------------
-- Add ``functionTypeLoc`` matcher for matching ``FunctionTypeLoc``.
-- Add missing support for ``TraversalKind`` in some ``addMatcher()`` overloads.
+- Add `functionTypeLoc` matcher for matching `FunctionTypeLoc`.
+- Add missing support for `TraversalKind` in some `addMatcher()` overloads.
-clang-format
-------------
-- Add ``ObjCSpaceAfterMethodDeclarationPrefix`` option to control space between the
+### clang-format
+
+- Add `ObjCSpaceAfterMethodDeclarationPrefix` option to control space between the
'-'/'+' and the return type in Objective-C method declarations
-- Deprecate the ``BinPackParameters`` and ``BinPackArguments`` options and replace
- them with the ``PackParameters`` and ``PackArguments`` structs (respectively) to
- unify packing behavior. Add the ``BreakAfter`` option to the structs, allowing
- parameter and argument lists to be formatted with one parameter/argument on each
+- Deprecate the `BinPackParameters` and `BinPackArguments` options and replace
+ them with the `PackParameters` and `PackArguments` structs (respectively) to
+ unify packing behavior. Add the `BreakAfter` option to the structs, allowing
+ parameter and argument lists to be formatted with one parameter/argument on each
line if they exceed the specified count.
-- Add ``AfterComma`` value to ``BreakConstructorInitializers`` to allow breaking
+- Add `AfterComma` value to `BreakConstructorInitializers` to allow breaking
constructor initializers after commas, keeping the colon on the same line.
-- Extend ``BreakBinaryOperations`` to accept a structured configuration with
- per-operator break rules and minimum chain length gating via ``PerOperator``.
-- Add ``AllowShortRecordOnASingleLine`` option and set it to ``EmptyAndAttached`` for LLVM style.
-- Add ``BreakFunctionDeclarationParameters`` option to always break before function
+- Extend `BreakBinaryOperations` to accept a structured configuration with
+ per-operator break rules and minimum chain length gating via `PerOperator`.
+- Add `AllowShortRecordOnASingleLine` option and set it to `EmptyAndAttached` for LLVM style.
+- Add `BreakFunctionDeclarationParameters` option to always break before function
declaration parameters.
-- Add ``EnumAssignments`` option to ``AlignConsecutiveAssignments`` for aligning
+- Add `EnumAssignments` option to `AlignConsecutiveAssignments` for aligning
enum assignments without affecting other assignments.
-- Add ``BreakBeforeReturnType`` option to break before the function return
+- Add `BreakBeforeReturnType` option to break before the function return
type.
-libclang
---------
+### libclang
+
- Visit constraints of `auto` type to properly visit concept usages (#GH166580)
-- Visit switch initializer statements (https://bugs.kde.org/show_bug.cgi?id=415537#c2)
+- Visit switch initializer statements (<https://bugs.kde.org/show_bug.cgi?id=415537#c2>)
- Fix crash in clang_getBinaryOperatorKindSpelling and clang_getUnaryOperatorKindSpelling
- The clang_Module_getASTFile API is deprecated and now always returns nullptr
- The clang_Cursor_getCommentRange API will now return a comment range for macro definitions that have documentation comments.
-- Added CXType_PredefinedSugar for __ptrdiff_t, __size_t, and
- __signed_size_t types, which are no longer exposed as
+- Added CXType_PredefinedSugar for \_\_ptrdiff_t, \_\_size_t, and
+ \_\_signed_size_t types, which are no longer exposed as
CXType_Unexposed.
-Code Completion
----------------
+### Code Completion
- Fixed a crash in code completion when using a C-Style cast with a parenthesized
operand in Objective-C++ mode. (#GH180125)
-Static Analyzer
----------------
+### Static Analyzer
-Crash and bug fixes
-^^^^^^^^^^^^^^^^^^^
+#### Crash and bug fixes
-- Fixed ``security.VAList`` checker producing false positives when analyzing
- C23 code where ``va_start`` expands to ``__builtin_c23_va_start``.
+- Fixed `security.VAList` checker producing false positives when analyzing
+ C23 code where `va_start` expands to `__builtin_c23_va_start`.
-Improvements
-^^^^^^^^^^^^
+#### Improvements
-- ``alpha.unix.PthreadLock`` now emits path notes on lock, unlock, destroy,
+- `alpha.unix.PthreadLock` now emits path notes on lock, unlock, destroy,
and init operations.
-.. comment:
- This is for the Static Analyzer.
- Using the caret `^^^` underlining for subsections:
- - Crash and bug fixes
- - New checkers and features
- - Improvements
- - Moved checkers
-
+% comment:
+% This is for the Static Analyzer.
+% Using the caret `^^^` underlining for subsections:
+% - Crash and bug fixes
+% - New checkers and features
+% - Improvements
+% - Moved checkers
-Moved checkers
-^^^^^^^^^^^^^^
+#### Moved checkers
-- The checker ``unix.cstring.UninitializedRead`` is now out of alpha.
+- The checker `unix.cstring.UninitializedRead` is now out of alpha.
-.. _release-notes-sanitizers:
+(release-notes-sanitizers)=
-Sanitizers
-----------
-- UndefinedBehaviorSanitizer now supports ``__ubsan_default_suppressions``.
+### Sanitizers
-- Sanitizer Special Case Lists (``-fsanitize-ignorelist``) now support
+- UndefinedBehaviorSanitizer now supports `__ubsan_default_suppressions`.
+- Sanitizer Special Case Lists (`-fsanitize-ignorelist`) now support
Version 4 of the Special Case List format, which introduces a transition
- period for leading dot-slash (``./``) canonicalization in path matching.
+ period for leading dot-slash (`./`) canonicalization in path matching.
Version 4 matches both canonicalized and non-canonicalized paths but emits a
warning for deprecated matches. Version 5 drops backward compatibility and
- requires rules to match canonicalized paths (without leading ``./``).
+ requires rules to match canonicalized paths (without leading `./`).
+### Python Binding Changes
-Python Binding Changes
-----------------------
-- Add deprecation warnings to ``CompletionChunk.isKind...`` methods.
+- Add deprecation warnings to `CompletionChunk.isKind...` methods.
These will be removed in a future release. Existing uses should be adapted
- to directly compare equality of the ``CompletionChunk`` kind with
- the corresponding ``CompletionChunkKind`` variant.
+ to directly compare equality of the `CompletionChunk` kind with
+ the corresponding `CompletionChunkKind` variant.
- Affected methods: ``isKindOptional``, ``isKindTypedText``, ``isKindPlaceHolder``,
- ``isKindInformative`` and ``isKindResultType``.
-- Add a deprecation warning to ``CodeCompletionResults.results``.
+ Affected methods: `isKindOptional`, `isKindTypedText`, `isKindPlaceHolder`,
+ `isKindInformative` and `isKindResultType`.
+
+- Add a deprecation warning to `CodeCompletionResults.results`.
This property will become an implementation detail with changed behavior in a
future release and should not be used directly.. Existing uses of
- ``CodeCompletionResults.results`` should be changed to directly use
- ``CodeCompletionResults``: it nows supports ``__len__`` and ``__getitem__``,
- so it can be used the same as ``CodeCompletionResults.results``.
-- Added a new helper method ``get_clang_version`` to the class ``Config`` to
+ `CodeCompletionResults.results` should be changed to directly use
+ `CodeCompletionResults`: it nows supports `__len__` and `__getitem__`,
+ so it can be used the same as `CodeCompletionResults.results`.
+
+- Added a new helper method `get_clang_version` to the class `Config` to
read the version string of the libclang in use.
-OpenMP Support
---------------
-- Added support for ``transparent`` clause in task and taskloop directives.
-- Added support for ``use_device_ptr`` clause to accept an optional
- ``fallback`` modifier (``fb_nullify`` or ``fb_preserve``) with OpenMP >= 61.
-- Added support for ``local`` clause with declare_target directive when
+### OpenMP Support
+
+- Added support for `transparent` clause in task and taskloop directives.
+- Added support for `use_device_ptr` clause to accept an optional
+ `fallback` modifier (`fb_nullify` or `fb_preserve`) with OpenMP >= 61.
+- Added support for `local` clause with declare_target directive when
OpenMP >= 60.
-- Fixed the identity element used for ``reduction(* : x)`` over C++ class types
- (e.g. ``std::complex``). The private copy is now initialized to the
+- Fixed the identity element used for `reduction(* : x)` over C++ class types
+ (e.g. `std::complex`). The private copy is now initialized to the
multiplicative identity instead of being value-initialized, which previously
produced a wrong result (the product collapsed to the additive identity).
-SYCL Support
-------------
-- SYCL compilations now default to ``-std=c++17`` when no explicit language
- standard is specified. Standards below C++17 are rejected with a diagnostic.
+### SYCL Support
+- SYCL compilations now default to `-std=c++17` when no explicit language
+ standard is specified. Standards below C++17 are rejected with a diagnostic.
- Clang now assumes default target for SYCL device compilation is 64-bit SPIR-V
and it now diagnoses if a non-supporting target is specified via command line.
(#GH167358)
-
-- The SYCL runtime shared library has been renamed from ``libsycl.so`` to
- ``libLLVMSYCL.so`` to align with LLVM naming conventions.
-
+- The SYCL runtime shared library has been renamed from `libsycl.so` to
+ `libLLVMSYCL.so` to align with LLVM naming conventions.
- SYCL header include paths are now added automatically for both host and
device compilations.
-
-- SYCL runtime library linking is now supported on Windows. When ``-fsycl`` is
- specified, Clang automatically adds ``/MD`` if no explicit CRT flag is
- present, links the appropriate debug (``LLVMSYCLd.lib``) or release
- (``LLVMSYCL.lib``) library, and rejects static CRT flags (``/MT``,
- ``/MTd``) with a diagnostic. Use ``-nolibsycl`` to suppress automatic
+- SYCL runtime library linking is now supported on Windows. When `-fsycl` is
+ specified, Clang automatically adds `/MD` if no explicit CRT flag is
+ present, links the appropriate debug (`LLVMSYCLd.lib`) or release
+ (`LLVMSYCL.lib`) library, and rejects static CRT flags (`/MT`,
+ `/MTd`) with a diagnostic. Use `-nolibsycl` to suppress automatic
library linking.
-
-- Fixed ``-nolibsycl`` being silently ignored on Linux: the SYCL runtime
+- Fixed `-nolibsycl` being silently ignored on Linux: the SYCL runtime
library was unconditionally added to the link line even when the flag was
passed.
-Improvements
-^^^^^^^^^^^^
-- Improved substitution performance in concept checking. (#GH172266)
+#### Improvements
+- Improved substitution performance in concept checking. (#GH172266)
- Clang now preserves the left-hand side of a binary expression (such as an
- assignment or comparison) in a ``RecoveryExpr`` when the right-hand side fails
- to parse. This improves IDE features like go-to-definition in ``clangd``.
+ assignment or comparison) in a `RecoveryExpr` when the right-hand side fails
+ to parse. This improves IDE features like go-to-definition in `clangd`.
-Additional Information
-======================
+## Additional Information
-A wide variety of additional information is available on the `Clang web
-page <https://clang.llvm.org/>`_. The web page contains versions of the
+A wide variety of additional information is available on the [Clang web
+page](https://clang.llvm.org/). The web page contains versions of the
API documentation which are up-to-date with the Git version of
the source code. You can access versions of these documents specific to
-this release by going into the "``clang/docs/``" directory in the Clang
+this release by going into the "`clang/docs/`" directory in the Clang
tree.
If you have any questions or comments about Clang, please feel free to
-contact us on the `Discourse forums (Clang Frontend category)
-<https://discourse.llvm.org/c/clang/6>`_.
+contact us on the [Discourse forums (Clang Frontend category)](https://discourse.llvm.org/c/clang/6).
+
diff --git a/clang/docs/SafeBuffers.md b/clang/docs/SafeBuffers.md
index a11fc317736cf..844ca7f7618a4 100644
--- a/clang/docs/SafeBuffers.md
+++ b/clang/docs/SafeBuffers.md
@@ -1,13 +1,10 @@
-================
-C++ Safe Buffers
-================
+# C++ Safe Buffers
-.. contents::
- :local:
+```{contents}
+:local: true
+```
-
-Introduction
-============
+## Introduction
Clang can be used to harden your C++ code against buffer overflows, an otherwise
common security issue with C-based languages.
@@ -15,11 +12,11 @@ common security issue with C-based languages.
The solution described in this document is an integrated programming model as
it combines:
-- a family of opt-in Clang warnings (``-Wunsafe-buffer-usage``) emitted at
+- a family of opt-in Clang warnings (`-Wunsafe-buffer-usage`) emitted at
during compilation to help you update your code to encapsulate and propagate
the bounds information associated with pointers;
- runtime assertions implemented as part of
- (`libc++ hardening modes <https://libcxx.llvm.org/Hardening.html>`_)
+ ([libc++ hardening modes](https://libcxx.llvm.org/Hardening.html))
that eliminate undefined behavior as long as the coding convention
is followed and the bounds information is therefore available and correct.
@@ -34,28 +31,26 @@ but more work is being done to improve ergonomics and safety guarantees
and reduce adoption costs.
The solution aligns in spirit with the "Ranges" safety profile
-that was `proposed <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3274r0.pdf>`_
+that was [proposed](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3274r0.pdf)
by Bjarne Stroustrup for standardization alongside other C++ safety features.
-
-Pre-Requisites
-==============
+## Pre-Requisites
In order to achieve bounds safety, your codebase needs to have access to
well-encapsulated bounds-safe container, view, and iterator types.
If your project uses libc++, standard container and view types such as
-``std::vector`` and ``std::span`` can be made bounds-safe by enabling
-the "fast" `hardening mode <https://libcxx.llvm.org/Hardening.html>`_
-(passing ``-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST``) to your
+`std::vector` and `std::span` can be made bounds-safe by enabling
+the "fast" [hardening mode](https://libcxx.llvm.org/Hardening.html)
+(passing `-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST`) to your
compiler) or any of the stricter hardening modes.
In order to harden iterators, you'll need to also obtain a libc++ binary
-built with ``_LIBCPP_ABI_BOUNDED_ITERATORS`` -- which is a libc++ ABI setting
+built with `_LIBCPP_ABI_BOUNDED_ITERATORS` -- which is a libc++ ABI setting
that needs to be set for your entire target platform if you need to maintain
binary compatibility with the rest of the platform.
A relatively fresh version of C++ is recommended. In particular, the very useful
-standard view class ``std::span`` requires C++20.
+standard view class `std::span` requires C++20.
Other implementations of the C++ standard library may provide different
flags to enable such hardening.
@@ -69,7 +64,7 @@ acting as "hardened custom containers" to replace raw pointers.
However, such approach would be very unergonomic in C, and safety guarantees
will be lower due to lack of good encapsulation technology. A better approach
to bounds safety for non-C++ programs,
-`-fbounds-safety <https://clang.llvm.org/docs/BoundsSafety.html>`_,
+[-fbounds-safety](https://clang.llvm.org/docs/BoundsSafety.html),
is currently in development.
Technically, safety guarantees cannot be provided without hardening
@@ -77,19 +72,15 @@ the entire technology stack, including all of your dependencies.
However, applying such hardening technology to even a small portion
of your code may be significantly better than nothing.
-
-The Programming Model for C++
-=============================
+## The Programming Model for C++
Assuming that hardened container, view, and iterator classes are available,
what remains is to make sure they are used consistently in your code.
Below we define the specific coding convention that needs to be followed
in order to guarantee safety and how the compiler technology
-around ``-Wunsafe-buffer-usage`` assists with that.
-
+around `-Wunsafe-buffer-usage` assists with that.
-Buffer operations should never be performed over raw pointers
--------------------------------------------------------------
+### Buffer operations should never be performed over raw pointers
Every time a memory access is made, a bounds-safe program must guarantee
that the range of accessed memory addresses falls into the boundaries
@@ -112,15 +103,15 @@ the code that requires manual intervention, it is desirable to initially shift
the focus away from the pointers themselves, and instead focus on their
**usage patterns**.
-The compiler warning ``-Wunsafe-buffer-usage`` is built to assist you
-with this step of the process. A ``-Wunsafe-buffer-usage`` warning is
+The compiler warning `-Wunsafe-buffer-usage` is built to assist you
+with this step of the process. A `-Wunsafe-buffer-usage` warning is
emitted whenever one of the following **buffer operations** are performed
on a raw pointer:
-- array indexing with ``[]``,
+- array indexing with `[]`,
- pointer arithmetic,
-- bounds-unsafe standard C functions such as ``std::memcpy()``,
-- C++ smart pointer operations such as ``std::unique_ptr<T[N]>::operator[]()``,
+- bounds-unsafe standard C functions such as `std::memcpy()`,
+- C++ smart pointer operations such as `std::unique_ptr<T[N]>::operator[]()`,
which unfortunately cannot be made fully safe within the rules of
the C++ standard (as of C++23).
@@ -128,23 +119,23 @@ This is sufficient for identifying each raw buffer pointer in the program at
**at least one point** during its lifetime across your software stack.
For example, both of the following functions are flagged by
-``-Wunsafe-buffer-usage`` because ``pointer`` gets identified as an unsafe
+`-Wunsafe-buffer-usage` because `pointer` gets identified as an unsafe
buffer pointer. Even though the second function does not directly access
the buffer, the pointer arithmetic operation inside it may easily be
the only formal "hint" in the program that the pointer does indeed point
-to a buffer of multiple objects::
+to a buffer of multiple objects:
- int get_last_element(int *pointer, size_t size) {
- return ptr[size - 1]; // warning: unsafe buffer access
- }
+```
+int get_last_element(int *pointer, size_t size) {
+ return ptr[size - 1]; // warning: unsafe buffer access
+}
- int *get_last_element_ptr(int *pointer, size_t size) {
- return ptr + (size - 1); // warning: unsafe pointer arithmetic
- }
+int *get_last_element_ptr(int *pointer, size_t size) {
+ return ptr + (size - 1); // warning: unsafe pointer arithmetic
+}
+```
-
-All buffers need to be encapsulated into safe container and view types
-----------------------------------------------------------------------
+### All buffers need to be encapsulated into safe container and view types
It immediately follows from the previous requirement that once an unsafe pointer
is identified at any point during its lifetime, it should be immediately wrapped
@@ -153,14 +144,14 @@ view type (if the allocation site is "far away"). Not only memory accesses,
but also non-access operations such as pointer arithmetic need to be covered
this way in order to benefit from the respective runtime bounds checks.
-If a **container** type (``std::array``, ``std::vector``, ``std::string``)
+If a **container** type (`std::array`, `std::vector`, `std::string`)
is used for allocating the buffer, this is the best-case scenario because
the container naturally has access to the correct bounds information for the
buffer, and the runtime bounds checks immediately kick in. Additionally,
the container type may provide automatic lifetime management for the buffer
(which may or may not be desirable).
-If a **view** type is used (``std::span``, ``std::string_view``), this typically
+If a **view** type is used (`std::span`, `std::string_view`), this typically
means that the bounds information for the "adopted" pointer needs to be passed
to the view's constructor manually. This makes runtime checks immediately
kick in with respect to the provided bounds information, which is an immediate
@@ -168,46 +159,52 @@ improvement over the raw pointer. However, this situation is still fundamentally
insufficient for security purposes, because **bounds information provided
this way cannot be guaranteed to be correct**.
-For example, the function ``get_last_element()`` we've seen in the previous
-section can be made **slightly** safer this way::
+For example, the function `get_last_element()` we've seen in the previous
+section can be made **slightly** safer this way:
- int get_last_element(int *pointer, size_t size) {
- std::span<int> sp(pointer, size);
- return sp[size - 1]; // warning addressed
- }
+```
+int get_last_element(int *pointer, size_t size) {
+ std::span<int> sp(pointer, size);
+ return sp[size - 1]; // warning addressed
+}
+```
-Here ``std::span`` eliminates the potential concern that the operation
-``size - 1`` may overflow when ``size`` is equal to ``0``, leading to a buffer
+Here `std::span` eliminates the potential concern that the operation
+`size - 1` may overflow when `size` is equal to `0`, leading to a buffer
"underrun". However, such program does not provide a guarantee that
-the variable ``size`` correctly represents the **actual** size fo the buffer
-pointed to by ``ptr``. The ``std::span`` constructed this way may be ill-formed.
+the variable `size` correctly represents the **actual** size fo the buffer
+pointed to by `ptr`. The `std::span` constructed this way may be ill-formed.
It may fail to protect you from overrunning the original buffer.
The following example demonstrates one of the most dangerous anti-patterns
-of this nature::
-
- void convert_data(int *source_buf, size_t source_size,
- int *target_buf, size_t target_size) {
- // Terrible: mismatched pointer / size.
- std::span<int> target_span(target_buf, source_size);
- // ...
- }
-
-The second parameter of ``std::span`` should never be the **desired** size
+of this nature:
+
+```
+void convert_data(int *source_buf, size_t source_size,
+ int *target_buf, size_t target_size) {
+ // Terrible: mismatched pointer / size.
+ std::span<int> target_span(target_buf, source_size);
+ // ...
+}
+```
+
+The second parameter of `std::span` should never be the **desired** size
of the buffer. It should always be the **actual** size of the buffer.
Such code often indicates that the original code has already contained
a vulnerability -- and the use of a safe view class failed to prevent it.
-If ``target_span`` actually needs to be of size ``source_size``, a significantly
+If `target_span` actually needs to be of size `source_size`, a significantly
safer way to produce such a span would be to build it with the correct size
-first, and then resize it to the desired size by calling ``.first()``::
+first, and then resize it to the desired size by calling `.first()`:
- void convert_data(int *source_buf, size_t source_size,
- int *target_buf, size_t target_size) {
- // Safer.
- std::span<int> target_span(target_buf, target_size).first(source_size);
- // ...
- }
+```
+void convert_data(int *source_buf, size_t source_size,
+ int *target_buf, size_t target_size) {
+ // Safer.
+ std::span<int> target_span(target_buf, target_size).first(source_size);
+ // ...
+}
+```
However, these are still half-measures. This code still accepts the
bounds information from the caller in an **informal** manner, and such bounds
@@ -216,9 +213,7 @@ information cannot be guaranteed to be correct.
In order to mitigate problems of this nature in their entirety,
the third guideline is imposed.
-
-Encapsulation of bounds information must be respected continuously
-------------------------------------------------------------------
+### Encapsulation of bounds information must be respected continuously
The allocation site of the object is the only reliable source of bounds
information for that object. For objects with long lifespans across
@@ -231,51 +226,57 @@ correctly **by construction**. However, they offer a number of ways to "break"
encapsulation, which may cause you to temporarily lose track of the correct
bounds information:
-- The two-parameter constructor ``std::span(ptr, size)`` allows you to
- assemble an ill-formed ``std::span``;
+- The two-parameter constructor `std::span(ptr, size)` allows you to
+ assemble an ill-formed `std::span`;
- Conversely, you can unwrap a container or a view object into a raw pointer
- and a raw size by calling its ``.data()`` and ``.size()`` methods.
-- The overloaded ``operator&()`` found on container and iterator classes
- acts similarly to ``.data()`` in this regard; operations such as
- ``&span[0]`` and ``&*span.begin()`` are effectively unsafe.
+ and a raw size by calling its `.data()` and `.size()` methods.
+- The overloaded `operator&()` found on container and iterator classes
+ acts similarly to `.data()` in this regard; operations such as
+ `&span[0]` and `&*span.begin()` are effectively unsafe.
-Additional ``-Wunsafe-buffer-usage`` warnings are emitted when encapsulation
+Additional `-Wunsafe-buffer-usage` warnings are emitted when encapsulation
of **standard** containers is broken in this manner. If you're using
non-standard containers, you can achieve a similar effect with facilities
-described in the next section: :ref:`customization`.
+described in the next section: {ref}`customization`.
For example, our previous attempt to address the warning in
-``get_last_element()`` has actually introduced a new warning along the way,
+`get_last_element()` has actually introduced a new warning along the way,
that notifies you about the potentially incorrect bounds information
-passed into the two-parameter constructor of ``std::span``::
+passed into the two-parameter constructor of `std::span`:
- int get_last_element(int *pointer, size_t size) {
- std::span<int> sp(pointer, size); // warning: unsafe constructor
- return sp[size - 1];
- }
+```
+int get_last_element(int *pointer, size_t size) {
+ std::span<int> sp(pointer, size); // warning: unsafe constructor
+ return sp[size - 1];
+}
+```
In order to address this warning, you need to make the function receive
the bounds information from the allocation site in a formal manner.
The function doesn't necessarily need to know where the allocation site is;
it simply needs to be able to accept bounds information **when** it's available.
-You can achieve this by refactoring the function to accept a ``std::span``
-as a parameter::
+You can achieve this by refactoring the function to accept a `std::span`
+as a parameter:
- int get_last_element(std::span<int> sp) {
- return sp[sp.size() - 1];
- }
+```
+int get_last_element(std::span<int> sp) {
+ return sp[sp.size() - 1];
+}
+```
This solution puts the responsibility for making sure the span is well-formed
on the **caller**. They should do the same, so that eventually the
responsibility is placed on the allocation site!
Such definition is also very ergonomic as it naturally accepts arbitrary
-standard containers without any additional code at the call site::
+standard containers without any additional code at the call site:
- void use_last_element() {
- std::vector<int> vec { 1, 2, 3 };
- int x = get_last_element(vec); // x = 3
- }
+```
+void use_last_element() {
+ std::vector<int> vec { 1, 2, 3 };
+ int x = get_last_element(vec); // x = 3
+}
+```
Such code is naturally bounds-safe because bounds-information is passed down
from the allocation site to the buffer access site. Only safe operations
@@ -283,64 +284,62 @@ are performed on container types. The containers are never "unforged" into
raw pointer-size pairs and never "reforged" again. This is what ideal
bounds-safe C++ code looks like.
+(customization)=
-.. _customization:
-
-Backwards Compatibility, Interoperation with Unsafe Code, Customization
-=======================================================================
+## Backwards Compatibility, Interoperation with Unsafe Code, Customization
Some of the code changes described above can be somewhat intrusive.
For example, changing a function that previously accepted a pointer and a size
-separately, to accept a ``std::span`` instead, may require you to update
+separately, to accept a `std::span` instead, may require you to update
every call site of the function. This is often undesirable and sometimes
completely unacceptable when backwards compatibility is required.
In order to facilitate **incremental adoption** of the coding convention
described above, as well as to handle various unusual situations, the compiler
provides two additional facilities to give the user more control over
-``-Wunsafe-buffer-usage`` diagnostics:
+`-Wunsafe-buffer-usage` diagnostics:
-- ``#pragma clang unsafe_buffer_usage`` to mark code as unsafe and **suppress**
- ``-Wunsafe-buffer-usage`` warnings in that code.
-- ``[[clang::unsafe_buffer_usage]]`` to annotate potential sources of
+- `#pragma clang unsafe_buffer_usage` to mark code as unsafe and **suppress**
+ `-Wunsafe-buffer-usage` warnings in that code.
+- `[[clang::unsafe_buffer_usage]]` to annotate potential sources of
discontinuity of bounds information -- thus introducing
- **additional** ``-Wunsafe-buffer-usage`` warnings.
+ **additional** `-Wunsafe-buffer-usage` warnings.
In this section we describe these facilities in detail and show how they can
help you with various unusual situations.
-Suppress unwanted warnings with ``#pragma clang unsafe_buffer_usage``
----------------------------------------------------------------------
+### Suppress unwanted warnings with `#pragma clang unsafe_buffer_usage`
If you really need to write unsafe code, you can always suppress all
-``-Wunsafe-buffer-usage`` warnings in a section of code by surrounding
-that code with the ``unsafe_buffer_usage`` pragma. For example, if you don't
-want to address the warning in our example function ``get_last_element()``,
-here is how you can suppress it::
-
- int get_last_element(int *pointer, size_t size) {
- #pragma clang unsafe_buffer_usage begin
- return ptr[size - 1]; // warning suppressed
- #pragma clang unsafe_buffer_usage end
- }
-
-This behavior is analogous to ``#pragma clang diagnostic`` (`documentation
-<https://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas>`_)
-However, ``#pragma clang unsafe_buffer_usage`` is specialized and recommended
-over ``#pragma clang diagnostic`` for a number of technical and non-technical
-reasons. Most importantly, ``#pragma clang unsafe_buffer_usage`` is more
+`-Wunsafe-buffer-usage` warnings in a section of code by surrounding
+that code with the `unsafe_buffer_usage` pragma. For example, if you don't
+want to address the warning in our example function `get_last_element()`,
+here is how you can suppress it:
+
+```
+int get_last_element(int *pointer, size_t size) {
+ #pragma clang unsafe_buffer_usage begin
+ return ptr[size - 1]; // warning suppressed
+ #pragma clang unsafe_buffer_usage end
+}
+```
+
+This behavior is analogous to `#pragma clang diagnostic` ([documentation](https://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas))
+However, `#pragma clang unsafe_buffer_usage` is specialized and recommended
+over `#pragma clang diagnostic` for a number of technical and non-technical
+reasons. Most importantly, `#pragma clang unsafe_buffer_usage` is more
suitable for security audits because it is significantly simpler and
describes unsafe code in a more formal manner. On the contrary,
-``#pragma clang diagnostic`` comes with a push/pop syntax (as opposed to
+`#pragma clang diagnostic` comes with a push/pop syntax (as opposed to
the begin/end syntax) and it offers ways to suppress warnings without
-mentioning them by name (such as ``-Weverything``), which can make it
+mentioning them by name (such as `-Weverything`), which can make it
difficult to determine at a glance whether the warning is suppressed
on any given line of code.
There are a few natural reasons to use this pragma:
- In implementations of safe custom containers. You need this because ultimately
- ``-Wunsafe-buffer-usage`` cannot help you verify that your custom container
+ `-Wunsafe-buffer-usage` cannot help you verify that your custom container
is safe. It will naturally remind you to audit your container's implementation
to make sure it has all the necessary runtime checks, but ultimately you'll
need to suppress it once the audit is complete.
@@ -350,10 +349,10 @@ There are a few natural reasons to use this pragma:
a single check before the loop) but it is not guaranteed to do that.
- For incremental adoption purposes. If you want to adopt the coding convention
gradually, you can always surround an entire file with the
- ``unsafe_buffer_usage`` pragma and then "make holes" in it whenever
+ `unsafe_buffer_usage` pragma and then "make holes" in it whenever
you address warnings on specific portions of the code.
- In the code that interoperates with unsafe code. This may be code that
- will never follow the programming model (such as plain C code that will
+ will never follow the programming model (such as plain C code that will
never be converted to C++) or with the code that simply haven't been converted
yet.
@@ -362,39 +361,40 @@ You are encouraged to introduce "unsafe wrapper functions" for various unsafe
operations that you need to perform regularly.
For example, if you regularly receive pointer/size pairs from unsafe code,
-you may want to introduce a wrapper function for the unsafe span constructor::
+you may want to introduce a wrapper function for the unsafe span constructor:
- #pragma clang unsafe_buffer_usage begin
+```
+#pragma clang unsafe_buffer_usage begin
- template <typename T>
- std::span<T> unsafe_forge_span(T *pointer, size_t size) {
- return std::span(pointer, size);
- }
+template <typename T>
+std::span<T> unsafe_forge_span(T *pointer, size_t size) {
+ return std::span(pointer, size);
+}
- #pragma clang unsafe_buffer_usage end
+#pragma clang unsafe_buffer_usage end
+```
Such wrapper function can be used to suppress warnings about unsafe span
-constructor usage in a more ergonomic manner::
+constructor usage in a more ergonomic manner:
- void use_unsafe_c_struct(unsafe_c_struct *s) {
- // No warning here.
- std::span<int> sp = unsafe_forge_span(s->pointer, s->size);
- // ...
- }
+```
+void use_unsafe_c_struct(unsafe_c_struct *s) {
+ // No warning here.
+ std::span<int> sp = unsafe_forge_span(s->pointer, s->size);
+ // ...
+}
+```
The code remains unsafe but it also continues to be nicely readable, and it
-proves that ``-Wunsafe-buffer-usage`` has done it best to notify you about
+proves that `-Wunsafe-buffer-usage` has done it best to notify you about
the potential unsafety. A security auditor will need to keep an eye on such
unsafe wrappers. **It is still up to you to confirm that the bounds information
passed into the wrapper is correct.**
+### Flag bounds information discontinuities with `[[clang::unsafe_buffer_usage]]`
-Flag bounds information discontinuities with ``[[clang::unsafe_buffer_usage]]``
--------------------------------------------------------------------------------
-
-The clang attribute ``[[clang::unsafe_buffer_usage]]``
-(`attribute documentation
-<https://clang.llvm.org/docs/AttributeReference.html#unsafe-buffer-usage>`_)
+The clang attribute `[[clang::unsafe_buffer_usage]]`
+([attribute documentation](https://clang.llvm.org/docs/AttributeReference.html#unsafe-buffer-usage))
allows the user to annotate various objects, such as functions or member
variables, as incompatible with the Safe Buffers programming model.
You are encouraged to do that for arbitrary reasons, but typically the main
@@ -402,65 +402,70 @@ reason to do that is when an unsafe function needs to be provided for
backwards compatibility.
For example, in the previous section we've seen how the example function
-``get_last_element()`` needed to have its parameter types changed in order
+`get_last_element()` needed to have its parameter types changed in order
to preserve the continuity of bounds information when receiving a buffer pointer
from the caller. However, such a change breaks both API and ABI compatibility.
The code that previously used this function will no longer compile, nor link,
until every call site of that function is updated. You can reclaim the
backwards compatibility -- in terms of both API and ABI -- by adding
-a "compatibility overload"::
-
- int get_last_element(std::span<int> sp) {
- return sp[sp.size() - 1];
- }
-
- [[clang::unsafe_buffer_usage]] // Please use the new function.
- int get_last_element(int *pointer, size_t size) {
- // Avoid code duplication - simply invoke the safe function!
- // The pragma suppresses the unsafe constructor warning.
- #pragma clang unsafe_buffer_usage begin
- return get_last_element(std::span(pointer, size));
- #pragma clang unsafe_buffer_usage end
- }
-
+a "compatibility overload":
+
+```
+int get_last_element(std::span<int> sp) {
+ return sp[sp.size() - 1];
+}
+
+[[clang::unsafe_buffer_usage]] // Please use the new function.
+int get_last_element(int *pointer, size_t size) {
+ // Avoid code duplication - simply invoke the safe function!
+ // The pragma suppresses the unsafe constructor warning.
+ #pragma clang unsafe_buffer_usage begin
+ return get_last_element(std::span(pointer, size));
+ #pragma clang unsafe_buffer_usage end
+}
+```
Such an overload allows the surrounding code to continue to work.
It is both source-compatible and binary-compatible. It is also strictly safer
than the original function because the unsafe buffer access through raw pointer
-is replaced with a safe ``std::span`` access no matter how it's called. However,
+is replaced with a safe `std::span` access no matter how it's called. However,
because it requires the caller to pass the pointer and the size separately,
it violates our "bounds information continuity" principle. This means that
the callers who care about bounds safety needs to be encouraged to use the
-``std::span``-based overload instead. Luckily, the attribute
-``[[clang::unsafe_buffer_usage]]`` causes a ``-Wunsafe-buffer-usage`` warning
+`std::span`-based overload instead. Luckily, the attribute
+`[[clang::unsafe_buffer_usage]]` causes a `-Wunsafe-buffer-usage` warning
to be displayed at every call site of the compatibility overload in order to
-remind the callers to update their code::
+remind the callers to update their code:
- void use_last_element() {
- std::vector<int> vec { 1, 2, 3 };
+```
+void use_last_element() {
+ std::vector<int> vec { 1, 2, 3 };
- // no warning
- int x = get_last_element(vec);
+ // no warning
+ int x = get_last_element(vec);
- // warning: this overload introduces unsafe buffer manipulation
- int x = get_last_element(vec.data(), vec.size());
- }
+ // warning: this overload introduces unsafe buffer manipulation
+ int x = get_last_element(vec.data(), vec.size());
+}
+```
The compatibility overload can be further simplified with the help of the
-``unsafe_forge_span()`` wrapper as described in the previous section --
-and it even makes the pragmas unnecessary::
-
- [[clang::unsafe_buffer_usage]] // Please use the new function.
- int get_last_element(int *pointer, size_t size) {
- // Avoid code duplication - simply invoke the safe function!
- return get_last_element(unsafe_forge_span(pointer, size));
- }
-
-Notice how the attribute ``[[clang::unsafe_buffer_usage]]`` does **not**
+`unsafe_forge_span()` wrapper as described in the previous section --
+and it even makes the pragmas unnecessary:
+
+```
+[[clang::unsafe_buffer_usage]] // Please use the new function.
+int get_last_element(int *pointer, size_t size) {
+ // Avoid code duplication - simply invoke the safe function!
+ return get_last_element(unsafe_forge_span(pointer, size));
+}
+```
+
+Notice how the attribute `[[clang::unsafe_buffer_usage]]` does **not**
suppress the warnings within the function on its own. Similarly, functions whose
-entire definitions are covered by ``#pragma clang unsafe_buffer_usage`` do
+entire definitions are covered by `#pragma clang unsafe_buffer_usage` do
**not** become automatically annotated with the attribute
-``[[clang::unsafe_buffer_usage]]``. They serve two different purposes:
+`[[clang::unsafe_buffer_usage]]`. They serve two different purposes:
- The pragma says that the function isn't safely **written**;
- The attribute says that the function isn't safe to **use**.
@@ -468,36 +473,38 @@ entire definitions are covered by ``#pragma clang unsafe_buffer_usage`` do
Also notice how we've made an **unsafe** wrapper for a **safe** function.
This is significantly better than making a **safe** wrapper for an **unsafe**
function. In other words, the following solution is significantly more unsafe
-and undesirable than the previous solution::
-
- int get_last_element(std::span<int> sp) {
- // You've just added that attribute, and now you need to
- // immediately suppress the warning that comes with it?
- #pragma clang unsafe_buffer_usage begin
- return get_last_element(sp.data(), sp.size());
- #pragma clang unsafe_buffer_usage end
- }
-
-
- [[clang::unsafe_buffer_usage]]
- int get_last_element(int *pointer, size_t size) {
- // This access is still completely unchecked. What's the point of having
- // perfect bounds information if you aren't performing runtime checks?
- #pragma clang unsafe_buffer_usage begin
- return ptr[size - 1];
- #pragma clang unsafe_buffer_usage end
- }
+and undesirable than the previous solution:
+
+```
+int get_last_element(std::span<int> sp) {
+ // You've just added that attribute, and now you need to
+ // immediately suppress the warning that comes with it?
+ #pragma clang unsafe_buffer_usage begin
+ return get_last_element(sp.data(), sp.size());
+ #pragma clang unsafe_buffer_usage end
+}
+
+
+[[clang::unsafe_buffer_usage]]
+int get_last_element(int *pointer, size_t size) {
+ // This access is still completely unchecked. What's the point of having
+ // perfect bounds information if you aren't performing runtime checks?
+ #pragma clang unsafe_buffer_usage begin
+ return ptr[size - 1];
+ #pragma clang unsafe_buffer_usage end
+}
+```
**Structs and classes**, unlike functions, cannot be overloaded. If a struct
contains an unsafe buffer (in the form of a nested array or a pointer/size pair)
then it is typically impossible to replace them with a safe container (such as
-``std::array`` or ``std::span`` respectively) without breaking the layout
+`std::array` or `std::span` respectively) without breaking the layout
of the struct and introducing both source and binary incompatibilities with
the surrounding client code.
Additionally, member variables of a class cannot be naturally "hidden" from
client code. If a class needs to be used by clients who haven't updated to
-C++20 yet, you cannot use the C++20-specific ``std::span`` as a member variable
+C++20 yet, you cannot use the C++20-specific `std::span` as a member variable
type. If the definition of a struct is shared with plain C code that manipulates
member variables directly, you cannot use any C++-specific types for these
member variables.
@@ -505,81 +512,82 @@ member variables.
In such cases there's usually no backwards-compatible way to use safe types
directly. The best option is usually to discourage the clients from using
member variables directly by annotating the member variables with the attribute
-``[[clang::unsafe_buffer_usage]]``, and then to change the interface
+`[[clang::unsafe_buffer_usage]]`, and then to change the interface
of the class to provide safe "accessors" to the unsafe data.
-For example, let's assume the worst-case scenario: ``struct foo`` is an unsafe
-struct type fully defined in a header shared between plain C code and C++ code::
+For example, let's assume the worst-case scenario: `struct foo` is an unsafe
+struct type fully defined in a header shared between plain C code and C++ code:
- struct foo {
- int *pointer;
- size_t size;
- };
+```
+struct foo {
+ int *pointer;
+ size_t size;
+};
+```
In this case you can achieve safety in C++ code by annotating the member
-variables as unsafe and encapsulating them into safe accessor methods::
-
- struct foo {
- [[clang::unsafe_buffer_usage]]
- int *pointer;
- [[clang::unsafe_buffer_usage]]
- size_t size;
-
- // Avoid showing this code to clients who are unable to digest it.
- #if __cplusplus >= 202002L
- std::span<int> get_pointer_as_span() {
- #pragma clang unsafe_buffer_usage begin
- return std::span(pointer, size);
- #pragma clang unsafe_buffer_usage end
- }
-
- void set_pointer_from_span(std::span<int> sp) {
- #pragma clang unsafe_buffer_usage begin
- pointer = sp.data();
- size = sp.size();
- #pragma clang unsafe_buffer_usage end
- }
-
- // Potentially more utility functions.
- #endif
- };
-
-Future Work
-===========
-
-The ``-Wunsafe-buffer-usage`` technology is in active development. The warning
+variables as unsafe and encapsulating them into safe accessor methods:
+
+```
+struct foo {
+ [[clang::unsafe_buffer_usage]]
+ int *pointer;
+ [[clang::unsafe_buffer_usage]]
+ size_t size;
+
+// Avoid showing this code to clients who are unable to digest it.
+#if __cplusplus >= 202002L
+ std::span<int> get_pointer_as_span() {
+ #pragma clang unsafe_buffer_usage begin
+ return std::span(pointer, size);
+ #pragma clang unsafe_buffer_usage end
+ }
+
+ void set_pointer_from_span(std::span<int> sp) {
+ #pragma clang unsafe_buffer_usage begin
+ pointer = sp.data();
+ size = sp.size();
+ #pragma clang unsafe_buffer_usage end
+ }
+
+ // Potentially more utility functions.
+#endif
+};
+```
+
+## Future Work
+
+The `-Wunsafe-buffer-usage` technology is in active development. The warning
is largely ready for everyday use but it is continuously improved to reduce
unnecessary noise as well as cover some of the trickier unsafe operations.
-Fix-It Hints for ``-Wunsafe-buffer-usage``
-------------------------------------------
+### Fix-It Hints for `-Wunsafe-buffer-usage`
A code transformation tool is in development that can semi-automatically
transform large bodies of code to follow the C++ Safe Buffers programming model.
It can currently be accessed by passing the experimental flag
-``-fsafe-buffer-usage-suggestions`` in addition to ``-Wunsafe-buffer-usage``.
+`-fsafe-buffer-usage-suggestions` in addition to `-Wunsafe-buffer-usage`.
Fixits produced this way currently assume the default approach described
in this document as they suggest standard containers and views (most notably
-``std::span`` and ``std::array``) as replacements for raw buffer pointers.
+`std::span` and `std::array`) as replacements for raw buffer pointers.
This also additionally requires libc++ hardening in order to make the runtime
bounds checks actually happen.
-Static Analysis to Identify Suspicious Sources of Bounds Information
---------------------------------------------------------------------
+### Static Analysis to Identify Suspicious Sources of Bounds Information
-The unsafe constructor ``span(pointer, size)`` is often a necessary evil
+The unsafe constructor `span(pointer, size)` is often a necessary evil
when it comes to interoperation with unsafe code. However, passing the
correct bounds information to such constructor is often difficult.
-In order to detect those ``span(target_pointer, source_size)`` anti-patterns,
-path-sensitive analysis performed by `the clang static analyzer
-<https://clang-analyzer.llvm.org>`_ can be taught to identify situations
+In order to detect those `span(target_pointer, source_size)` anti-patterns,
+path-sensitive analysis performed by [the clang static analyzer](https://clang-analyzer.llvm.org) can be taught to identify situations
when the pointer and the size are coming from "suspiciously different" sources.
Such analysis will be able to identify the source of information with
significantly higher precision than that of the compiler, making it much better
at identifying incorrect bounds information in your code while producing
significantly fewer warnings. It will also need to bypass
-``#pragma clang unsafe_buffer_usage`` suppressions and "see through"
-unsafe wrappers such as ``unsafe_forge_span`` -- something that
+`#pragma clang unsafe_buffer_usage` suppressions and "see through"
+unsafe wrappers such as `unsafe_forge_span` -- something that
the static analyzer is naturally capable of doing.
+
diff --git a/clang/docs/SanitizerCoverage.md b/clang/docs/SanitizerCoverage.md
index c01863adebb2d..c48298bd8ffc3 100644
--- a/clang/docs/SanitizerCoverage.md
+++ b/clang/docs/SanitizerCoverage.md
@@ -1,357 +1,341 @@
-=================
-SanitizerCoverage
-=================
+# SanitizerCoverage
-.. contents::
- :local:
+```{contents}
+:local: true
+```
-Introduction
-============
+## Introduction
LLVM has a simple code coverage instrumentation built in (SanitizerCoverage).
It inserts calls to user-defined functions on function-, basic-block-, and edge- levels.
Default implementations of those callbacks are provided and implement
simple coverage reporting and visualization,
however if you need *just* coverage visualization you may want to use
-:doc:`SourceBasedCodeCoverage <SourceBasedCodeCoverage>` instead.
+{doc}`SourceBasedCodeCoverage <SourceBasedCodeCoverage>` instead.
-Tracing PCs with guards
-=======================
+## Tracing PCs with guards
-With ``-fsanitize-coverage=trace-pc-guard`` the compiler will insert the following code
+With `-fsanitize-coverage=trace-pc-guard` the compiler will insert the following code
on every edge:
-.. code-block:: none
-
- __sanitizer_cov_trace_pc_guard(&guard_variable)
+```none
+__sanitizer_cov_trace_pc_guard(&guard_variable)
+```
Every edge will have its own `guard_variable` (uint32_t).
The compiler will also insert calls to a module constructor:
-.. code-block:: c++
-
- // The guards are [start, stop).
- // This function will be called at least once per DSO and may be called
- // more than once with the same values of start/stop.
- __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop);
+```c++
+// The guards are [start, stop).
+// This function will be called at least once per DSO and may be called
+// more than once with the same values of start/stop.
+__sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop);
+```
-With an additional ``...=trace-pc,indirect-calls`` flag
-``__sanitizer_cov_trace_pc_indirect(void *callee)`` will be inserted on every indirect call.
+With an additional `...=trace-pc,indirect-calls` flag
+`__sanitizer_cov_trace_pc_indirect(void *callee)` will be inserted on every indirect call.
The functions `__sanitizer_cov_trace_pc_*` should be defined by the user.
Example:
-.. code-block:: c++
-
- // trace-pc-guard-cb.cc
- #include <stdint.h>
- #include <stdio.h>
- #include <sanitizer/coverage_interface.h>
-
- // This callback is inserted by the compiler as a module constructor
- // into every DSO. 'start' and 'stop' correspond to the
- // beginning and end of the section with the guards for the entire
- // binary (executable or DSO). The callback will be called at least
- // once per DSO and may be called multiple times with the same parameters.
- extern "C" void __sanitizer_cov_trace_pc_guard_init(uint32_t *start,
- uint32_t *stop) {
- static uint64_t N; // Counter for the guards.
- if (start == stop || *start) return; // Initialize only once.
- printf("INIT: %p %p\n", start, stop);
- for (uint32_t *x = start; x < stop; x++)
- *x = ++N; // Guards should start from 1.
- }
-
- // This callback is inserted by the compiler on every edge in the
- // control flow (some optimizations apply).
- // Typically, the compiler will emit the code like this:
- // if(*guard)
- // __sanitizer_cov_trace_pc_guard(guard);
- // But for large functions it will emit a simple call:
- // __sanitizer_cov_trace_pc_guard(guard);
- extern "C" void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
- if (!*guard) return; // Duplicate the guard check.
- // If you set *guard to 0 this code will not be called again for this edge.
- // Now you can get the PC and do whatever you want:
- // store it somewhere or symbolize it and print right away.
- // The values of `*guard` are as you set them in
- // __sanitizer_cov_trace_pc_guard_init and so you can make them consecutive
- // and use them to dereference an array or a bit vector.
- void *PC = __builtin_return_address(0);
- char PcDescr[1024];
- // This function is a part of the sanitizer run-time.
- // To use it, link with AddressSanitizer or other sanitizer.
- __sanitizer_symbolize_pc(PC, "%p %F %L", PcDescr, sizeof(PcDescr));
- printf("guard: %p %x PC %s\n", guard, *guard, PcDescr);
- }
-
-.. code-block:: c++
-
- // trace-pc-guard-example.cc
- void foo() { }
- int main(int argc, char **argv) {
- if (argc > 1) foo();
- }
-
-.. code-block:: console
-
- clang++ -g -fsanitize-coverage=trace-pc-guard trace-pc-guard-example.cc -c
- clang++ trace-pc-guard-cb.cc trace-pc-guard-example.o -fsanitize=address
- ASAN_OPTIONS=strip_path_prefix=`pwd`/ ./a.out
-
-.. code-block:: console
-
- INIT: 0x71bcd0 0x71bce0
- guard: 0x71bcd4 2 PC 0x4ecd5b in main trace-pc-guard-example.cc:2
- guard: 0x71bcd8 3 PC 0x4ecd9e in main trace-pc-guard-example.cc:3:7
-
-.. code-block:: console
-
- ASAN_OPTIONS=strip_path_prefix=`pwd`/ ./a.out with-foo
-
-
-.. code-block:: console
-
- INIT: 0x71bcd0 0x71bce0
- guard: 0x71bcd4 2 PC 0x4ecd5b in main trace-pc-guard-example.cc:3
- guard: 0x71bcdc 4 PC 0x4ecdc7 in main trace-pc-guard-example.cc:4:17
- guard: 0x71bcd0 1 PC 0x4ecd20 in foo() trace-pc-guard-example.cc:2:14
-
-Inline 8bit-counters
-====================
+```c++
+// trace-pc-guard-cb.cc
+#include <stdint.h>
+#include <stdio.h>
+#include <sanitizer/coverage_interface.h>
+
+// This callback is inserted by the compiler as a module constructor
+// into every DSO. 'start' and 'stop' correspond to the
+// beginning and end of the section with the guards for the entire
+// binary (executable or DSO). The callback will be called at least
+// once per DSO and may be called multiple times with the same parameters.
+extern "C" void __sanitizer_cov_trace_pc_guard_init(uint32_t *start,
+ uint32_t *stop) {
+ static uint64_t N; // Counter for the guards.
+ if (start == stop || *start) return; // Initialize only once.
+ printf("INIT: %p %p\n", start, stop);
+ for (uint32_t *x = start; x < stop; x++)
+ *x = ++N; // Guards should start from 1.
+}
+
+// This callback is inserted by the compiler on every edge in the
+// control flow (some optimizations apply).
+// Typically, the compiler will emit the code like this:
+// if(*guard)
+// __sanitizer_cov_trace_pc_guard(guard);
+// But for large functions it will emit a simple call:
+// __sanitizer_cov_trace_pc_guard(guard);
+extern "C" void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
+ if (!*guard) return; // Duplicate the guard check.
+ // If you set *guard to 0 this code will not be called again for this edge.
+ // Now you can get the PC and do whatever you want:
+ // store it somewhere or symbolize it and print right away.
+ // The values of `*guard` are as you set them in
+ // __sanitizer_cov_trace_pc_guard_init and so you can make them consecutive
+ // and use them to dereference an array or a bit vector.
+ void *PC = __builtin_return_address(0);
+ char PcDescr[1024];
+ // This function is a part of the sanitizer run-time.
+ // To use it, link with AddressSanitizer or other sanitizer.
+ __sanitizer_symbolize_pc(PC, "%p %F %L", PcDescr, sizeof(PcDescr));
+ printf("guard: %p %x PC %s\n", guard, *guard, PcDescr);
+}
+```
+
+```c++
+// trace-pc-guard-example.cc
+void foo() { }
+int main(int argc, char **argv) {
+ if (argc > 1) foo();
+}
+```
+
+```console
+clang++ -g -fsanitize-coverage=trace-pc-guard trace-pc-guard-example.cc -c
+clang++ trace-pc-guard-cb.cc trace-pc-guard-example.o -fsanitize=address
+ASAN_OPTIONS=strip_path_prefix=`pwd`/ ./a.out
+```
+
+```console
+INIT: 0x71bcd0 0x71bce0
+guard: 0x71bcd4 2 PC 0x4ecd5b in main trace-pc-guard-example.cc:2
+guard: 0x71bcd8 3 PC 0x4ecd9e in main trace-pc-guard-example.cc:3:7
+```
+
+```console
+ASAN_OPTIONS=strip_path_prefix=`pwd`/ ./a.out with-foo
+```
+
+```console
+INIT: 0x71bcd0 0x71bce0
+guard: 0x71bcd4 2 PC 0x4ecd5b in main trace-pc-guard-example.cc:3
+guard: 0x71bcdc 4 PC 0x4ecdc7 in main trace-pc-guard-example.cc:4:17
+guard: 0x71bcd0 1 PC 0x4ecd20 in foo() trace-pc-guard-example.cc:2:14
+```
+
+## Inline 8bit-counters
**Experimental, may change or disappear in future**
-With ``-fsanitize-coverage=inline-8bit-counters`` the compiler will insert
+With `-fsanitize-coverage=inline-8bit-counters` the compiler will insert
inline counter increments on every edge.
-This is similar to ``-fsanitize-coverage=trace-pc-guard`` but instead of a
+This is similar to `-fsanitize-coverage=trace-pc-guard` but instead of a
callback the instrumentation simply increments a counter.
Users need to implement a single function to capture the counters at startup.
-.. code-block:: c++
-
- extern "C"
- void __sanitizer_cov_8bit_counters_init(char *start, char *end) {
- // [start,end) is the array of 8-bit counters created for the current DSO.
- // Capture this array in order to read/modify the counters.
- }
-
+```c++
+extern "C"
+void __sanitizer_cov_8bit_counters_init(char *start, char *end) {
+ // [start,end) is the array of 8-bit counters created for the current DSO.
+ // Capture this array in order to read/modify the counters.
+}
+```
-Inline bool-flag
-================
+## Inline bool-flag
**Experimental, may change or disappear in future**
-With ``-fsanitize-coverage=inline-bool-flag`` the compiler will insert
+With `-fsanitize-coverage=inline-bool-flag` the compiler will insert
setting an inline boolean to true on every edge.
-This is similar to ``-fsanitize-coverage=inline-8bit-counter`` but instead of
+This is similar to `-fsanitize-coverage=inline-8bit-counter` but instead of
an increment of a counter, it just sets a boolean to true.
Users need to implement a single function to capture the flags at startup.
-.. code-block:: c++
+```c++
+extern "C"
+void __sanitizer_cov_bool_flag_init(bool *start, bool *end) {
+ // [start,end) is the array of boolean flags created for the current DSO.
+ // Capture this array in order to read/modify the flags.
+}
+```
- extern "C"
- void __sanitizer_cov_bool_flag_init(bool *start, bool *end) {
- // [start,end) is the array of boolean flags created for the current DSO.
- // Capture this array in order to read/modify the flags.
- }
-
-
-PC-Table
-========
+## PC-Table
**Experimental, may change or disappear in future**
**Note:** this instrumentation might be incompatible with dead code stripping
-(``-Wl,-gc-sections``) for linkers other than LLD, thus resulting in a
+(`-Wl,-gc-sections`) for linkers other than LLD, thus resulting in a
significant binary size overhead. For more information, see
-`Bug 34636 <https://bugs.llvm.org/show_bug.cgi?id=34636>`_.
+[Bug 34636](https://bugs.llvm.org/show_bug.cgi?id=34636).
-With ``-fsanitize-coverage=pc-table`` the compiler will create a table of
-instrumented PCs. Requires either ``-fsanitize-coverage=inline-8bit-counters``,
-or ``-fsanitize-coverage=inline-bool-flag``, or ``-fsanitize-coverage=trace-pc-guard``.
+With `-fsanitize-coverage=pc-table` the compiler will create a table of
+instrumented PCs. Requires either `-fsanitize-coverage=inline-8bit-counters`,
+or `-fsanitize-coverage=inline-bool-flag`, or `-fsanitize-coverage=trace-pc-guard`.
Users need to implement a single function to capture the PC table at startup:
-.. code-block:: c++
-
- extern "C"
- void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
- const uintptr_t *pcs_end) {
- // [pcs_beg,pcs_end) is the array of ptr-sized integers representing
- // pairs [PC,PCFlags] for every instrumented block in the current DSO.
- // Capture this array in order to read the PCs and their Flags.
- // The number of PCs and PCFlags for a given DSO is the same as the number
- // of 8-bit counters (-fsanitize-coverage=inline-8bit-counters), or
- // boolean flags (-fsanitize-coverage=inline=bool-flags), or trace_pc_guard
- // callbacks (-fsanitize-coverage=trace-pc-guard).
- // A PCFlags describes the basic block:
- // * bit0: 1 if the block is the function entry block, 0 otherwise.
- }
-
-
-Tracing PCs
-===========
-
-With ``-fsanitize-coverage=trace-pc`` the compiler will insert
-``__sanitizer_cov_trace_pc()`` on every edge.
-With an additional ``...=trace-pc,indirect-calls`` flag
-``__sanitizer_cov_trace_pc_indirect(void *callee)`` will be inserted on every indirect call.
-
-With ``-fsanitize-coverage=trace-pc-entry-exit`` the compiler will insert
-``__sanitizer_cov_trace_pc_entry()`` on function entry, and insert
-``__sanitizer_cov_trace_pc_exit()`` on function return;
-``-fsanitize-coverage=trace-pc`` or ``-fsanitize-coverage=trace-pc-guard`` must
+```c++
+extern "C"
+void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
+ const uintptr_t *pcs_end) {
+ // [pcs_beg,pcs_end) is the array of ptr-sized integers representing
+ // pairs [PC,PCFlags] for every instrumented block in the current DSO.
+ // Capture this array in order to read the PCs and their Flags.
+ // The number of PCs and PCFlags for a given DSO is the same as the number
+ // of 8-bit counters (-fsanitize-coverage=inline-8bit-counters), or
+ // boolean flags (-fsanitize-coverage=inline=bool-flags), or trace_pc_guard
+ // callbacks (-fsanitize-coverage=trace-pc-guard).
+ // A PCFlags describes the basic block:
+ // * bit0: 1 if the block is the function entry block, 0 otherwise.
+}
+```
+
+## Tracing PCs
+
+With `-fsanitize-coverage=trace-pc` the compiler will insert
+`__sanitizer_cov_trace_pc()` on every edge.
+With an additional `...=trace-pc,indirect-calls` flag
+`__sanitizer_cov_trace_pc_indirect(void *callee)` will be inserted on every indirect call.
+
+With `-fsanitize-coverage=trace-pc-entry-exit` the compiler will insert
+`__sanitizer_cov_trace_pc_entry()` on function entry, and insert
+`__sanitizer_cov_trace_pc_exit()` on function return;
+`-fsanitize-coverage=trace-pc` or `-fsanitize-coverage=trace-pc-guard` must
still be passed to instrument all basic blocks.
-With the combination ``-fsanitize-coverage=trace-pc-entry-exit,trace-pc``,
-``__sanitizer_cov_trace_pc()`` will be omitted in the entry basic block because
-the block is already covered by ``__sanitizer_cov_trace_pc_entry()``, which can
+With the combination `-fsanitize-coverage=trace-pc-entry-exit,trace-pc`,
+`__sanitizer_cov_trace_pc()` will be omitted in the entry basic block because
+the block is already covered by `__sanitizer_cov_trace_pc_entry()`, which can
be used to both record that the function has been entered and record coverage of
the entry basic block.
-However, with ``-fsanitize-coverage=trace-pc-entry-exit,trace-pc-guard``, both
+However, with `-fsanitize-coverage=trace-pc-entry-exit,trace-pc-guard`, both
callbacks are called for the entry block because
-``__sanitizer_cov_trace_pc_entry()`` does not provide a `guard_variable`.
+`__sanitizer_cov_trace_pc_entry()` does not provide a `guard_variable`.
These callbacks are not implemented in the Sanitizer run-time and should be defined
by the user.
This mechanism is used for fuzzing the Linux kernel
-(https://github.com/google/syzkaller).
+(<https://github.com/google/syzkaller>).
+
+## Instrumentation points
-Instrumentation points
-======================
Sanitizer Coverage offers different levels of instrumentation.
-* ``edge`` (default): edges are instrumented (see below).
-* ``bb``: basic blocks are instrumented.
-* ``func``: only the entry block of every function will be instrumented.
+- `edge` (default): edges are instrumented (see below).
+- `bb`: basic blocks are instrumented.
+- `func`: only the entry block of every function will be instrumented.
-Use these flags together with ``trace-pc-guard`` or ``trace-pc``,
-like this: ``-fsanitize-coverage=func,trace-pc-guard``.
+Use these flags together with `trace-pc-guard` or `trace-pc`,
+like this: `-fsanitize-coverage=func,trace-pc-guard`.
-When ``edge`` or ``bb`` is used, some of the edges/blocks may still be left
+When `edge` or `bb` is used, some of the edges/blocks may still be left
uninstrumented (pruned) if such instrumentation is considered redundant.
-Use ``no-prune`` (e.g. ``-fsanitize-coverage=bb,no-prune,trace-pc-guard``)
+Use `no-prune` (e.g. `-fsanitize-coverage=bb,no-prune,trace-pc-guard`)
to disable pruning. This could be useful for better coverage visualization.
-
-Edge coverage
--------------
+### Edge coverage
Consider this code:
-.. code-block:: c++
-
- void foo(int *a) {
- if (a)
- *a = 0;
- }
+```c++
+void foo(int *a) {
+ if (a)
+ *a = 0;
+}
+```
It contains 3 basic blocks, let's name them A, B, C:
-.. code-block:: none
-
- A
- |\
- | \
- | B
- | /
- |/
- C
+```none
+A
+|\
+| \
+| B
+| /
+|/
+C
+```
If blocks A, B, and C are all covered we know for certain that the edges A=>B
and B=>C were executed, but we still don't know if the edge A=>C was executed.
Such edges of control flow graph are called
-`critical <https://en.wikipedia.org/wiki/Control_flow_graph#Special_edges>`_.
+[critical](https://en.wikipedia.org/wiki/Control_flow_graph#Special_edges).
The edge-level coverage simply splits all critical edges by introducing new
dummy blocks and then instruments those blocks:
-.. code-block:: none
+```none
+A
+|\
+| \
+D B
+| /
+|/
+C
+```
- A
- |\
- | \
- D B
- | /
- |/
- C
-
-Tracing data flow
-=================
+## Tracing data flow
Support for data-flow-guided fuzzing.
-With ``-fsanitize-coverage=trace-cmp`` the compiler will insert extra instrumentation
+With `-fsanitize-coverage=trace-cmp` the compiler will insert extra instrumentation
around comparison instructions and switch statements.
-Similarly, with ``-fsanitize-coverage=trace-div`` the compiler will instrument
+Similarly, with `-fsanitize-coverage=trace-div` the compiler will instrument
integer division instructions (to capture the right argument of division)
-and with ``-fsanitize-coverage=trace-gep`` --
-the `LLVM GEP instructions <https://llvm.org/docs/GetElementPtr.html>`_
+and with `-fsanitize-coverage=trace-gep` --
+the [LLVM GEP instructions](https://llvm.org/docs/GetElementPtr.html)
(to capture array indices).
-Similarly, with ``-fsanitize-coverage=trace-loads`` and ``-fsanitize-coverage=trace-stores``
+Similarly, with `-fsanitize-coverage=trace-loads` and `-fsanitize-coverage=trace-stores`
the compiler will instrument loads and stores, respectively.
Currently, these flags do not work by themselves - they require one
-of ``-fsanitize-coverage={trace-pc,inline-8bit-counters,inline-bool}``
+of `-fsanitize-coverage={trace-pc,inline-8bit-counters,inline-bool}`
flags to work.
-Unless ``no-prune`` option is provided, some of the comparison instructions
+Unless `no-prune` option is provided, some of the comparison instructions
will not be instrumented.
-.. code-block:: c++
-
- // Called before a comparison instruction.
- // Arg1 and Arg2 are arguments of the comparison.
- void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2);
- void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2);
- void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2);
- void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2);
-
- // Called before a comparison instruction if exactly one of the arguments is constant.
- // Arg1 and Arg2 are arguments of the comparison, Arg1 is a compile-time constant.
- // These callbacks are emitted by -fsanitize-coverage=trace-cmp since 2017-08-11
- void __sanitizer_cov_trace_const_cmp1(uint8_t Arg1, uint8_t Arg2);
- void __sanitizer_cov_trace_const_cmp2(uint16_t Arg1, uint16_t Arg2);
- void __sanitizer_cov_trace_const_cmp4(uint32_t Arg1, uint32_t Arg2);
- void __sanitizer_cov_trace_const_cmp8(uint64_t Arg1, uint64_t Arg2);
-
- // Called before a switch statement.
- // Val is the switch operand.
- // Cases[0] is the number of case constants.
- // Cases[1] is the size of Val in bits.
- // Cases[2:] are the case constants.
- void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases);
-
- // Called before a division statement.
- // Val is the second argument of division.
- void __sanitizer_cov_trace_div4(uint32_t Val);
- void __sanitizer_cov_trace_div8(uint64_t Val);
-
- // Called before a GetElementPtr (GEP) instruction
- // for every non-constant array index.
- void __sanitizer_cov_trace_gep(uintptr_t Idx);
-
- // Called before a load of appropriate size. Addr is the address of the load.
- void __sanitizer_cov_load1(uint8_t *addr);
- void __sanitizer_cov_load2(uint16_t *addr);
- void __sanitizer_cov_load4(uint32_t *addr);
- void __sanitizer_cov_load8(uint64_t *addr);
- void __sanitizer_cov_load16(__int128 *addr);
- // Called before a store of appropriate size. Addr is the address of the store.
- void __sanitizer_cov_store1(uint8_t *addr);
- void __sanitizer_cov_store2(uint16_t *addr);
- void __sanitizer_cov_store4(uint32_t *addr);
- void __sanitizer_cov_store8(uint64_t *addr);
- void __sanitizer_cov_store16(__int128 *addr);
-
-
-Tracing control flow
-====================
-
-With ``-fsanitize-coverage=control-flow`` the compiler will create a table to collect
+```c++
+// Called before a comparison instruction.
+// Arg1 and Arg2 are arguments of the comparison.
+void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2);
+void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2);
+void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2);
+void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2);
+
+// Called before a comparison instruction if exactly one of the arguments is constant.
+// Arg1 and Arg2 are arguments of the comparison, Arg1 is a compile-time constant.
+// These callbacks are emitted by -fsanitize-coverage=trace-cmp since 2017-08-11
+void __sanitizer_cov_trace_const_cmp1(uint8_t Arg1, uint8_t Arg2);
+void __sanitizer_cov_trace_const_cmp2(uint16_t Arg1, uint16_t Arg2);
+void __sanitizer_cov_trace_const_cmp4(uint32_t Arg1, uint32_t Arg2);
+void __sanitizer_cov_trace_const_cmp8(uint64_t Arg1, uint64_t Arg2);
+
+// Called before a switch statement.
+// Val is the switch operand.
+// Cases[0] is the number of case constants.
+// Cases[1] is the size of Val in bits.
+// Cases[2:] are the case constants.
+void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases);
+
+// Called before a division statement.
+// Val is the second argument of division.
+void __sanitizer_cov_trace_div4(uint32_t Val);
+void __sanitizer_cov_trace_div8(uint64_t Val);
+
+// Called before a GetElementPtr (GEP) instruction
+// for every non-constant array index.
+void __sanitizer_cov_trace_gep(uintptr_t Idx);
+
+// Called before a load of appropriate size. Addr is the address of the load.
+void __sanitizer_cov_load1(uint8_t *addr);
+void __sanitizer_cov_load2(uint16_t *addr);
+void __sanitizer_cov_load4(uint32_t *addr);
+void __sanitizer_cov_load8(uint64_t *addr);
+void __sanitizer_cov_load16(__int128 *addr);
+// Called before a store of appropriate size. Addr is the address of the store.
+void __sanitizer_cov_store1(uint8_t *addr);
+void __sanitizer_cov_store2(uint16_t *addr);
+void __sanitizer_cov_store4(uint32_t *addr);
+void __sanitizer_cov_store8(uint64_t *addr);
+void __sanitizer_cov_store16(__int128 *addr);
+```
+
+## Tracing control flow
+
+With `-fsanitize-coverage=control-flow` the compiler will create a table to collect
control flow for each function. More specifically, for each basic block in the function,
two lists are populated. One list for successors of the basic block and another list for
non-intrinsic called functions.
@@ -360,96 +344,94 @@ non-intrinsic called functions.
and are only marked with special value (-1) in the list.
Each table row consists of the basic block address
-followed by ``null``-ended lists of successors and callees.
-The table is encoded in a special section named ``sancov_cfs``
+followed by `null`-ended lists of successors and callees.
+The table is encoded in a special section named `sancov_cfs`
Example:
-.. code-block:: c++
-
- int foo (int x) {
- if (x > 0)
- bar(x);
- else
- x = 0;
- return x;
- }
+```c++
+int foo (int x) {
+ if (x > 0)
+ bar(x);
+ else
+ x = 0;
+ return x;
+}
+```
The code above contains 4 basic blocks, let's name them A, B, C, D:
-.. code-block:: none
-
- A
- |\
- | \
- B C
- | /
- |/
- D
+```none
+A
+|\
+| \
+B C
+| /
+|/
+D
+```
The collected control flow table is as follows:
-``A, B, C, null, null, B, D, null, @bar, null, C, D, null, null, D, null, null.``
+`A, B, C, null, null, B, D, null, @bar, null, C, D, null, null, D, null, null.`
Users need to implement a single function to capture the CF table at startup:
-.. code-block:: c++
+```c++
+extern "C"
+void __sanitizer_cov_cfs_init(const uintptr_t *cfs_beg,
+ const uintptr_t *cfs_end) {
+ // [cfs_beg,cfs_end) is the array of ptr-sized integers representing
+ // the collected control flow.
+}
+```
- extern "C"
- void __sanitizer_cov_cfs_init(const uintptr_t *cfs_beg,
- const uintptr_t *cfs_end) {
- // [cfs_beg,cfs_end) is the array of ptr-sized integers representing
- // the collected control flow.
- }
+## Tracing Stack Depth
-Tracing Stack Depth
-===================
-
-With ``-fsanitize-coverage=stack-depth`` the compiler will track how much
+With `-fsanitize-coverage=stack-depth` the compiler will track how much
stack space has been used for a function call chain. Leaf functions are
not included in this tracing.
The maximum depth of a function call graph is stored in the thread-local
-``__sancov_lowest_stack`` variable. Instrumentation is inserted in every
+`__sancov_lowest_stack` variable. Instrumentation is inserted in every
non-leaf function to check the frame pointer against this variable,
and if it is lower, store the current frame pointer. This effectively
inserts the following:
-.. code-block:: c++
-
- extern thread_local uintptr_t __sancov_lowest_stack;
+```c++
+extern thread_local uintptr_t __sancov_lowest_stack;
- uintptr_t stack = (uintptr_t)__builtin_frame_address(0);
- if (stack < __sancov_lowest_stack)
- __sancov_lowest_stack = stack;
+uintptr_t stack = (uintptr_t)__builtin_frame_address(0);
+if (stack < __sancov_lowest_stack)
+ __sancov_lowest_stack = stack;
+```
-If ``-fsanitize-coverage-stack-depth-callback-min=N`` (where
-``N > 0``) is also used, the tracking is delegated to a callback,
-``__sanitizer_cov_stack_depth``, instead of adding instrumentation to
-update ``__sancov_lowest_stack``. The ``N`` of the argument is used
+If `-fsanitize-coverage-stack-depth-callback-min=N` (where
+`N > 0`) is also used, the tracking is delegated to a callback,
+`__sanitizer_cov_stack_depth`, instead of adding instrumentation to
+update `__sancov_lowest_stack`. The `N` of the argument is used
to determine which functions to instrument. Only functions estimated
-to be using ``N`` bytes or more of stack space will be instrumented to
+to be using `N` bytes or more of stack space will be instrumented to
call the tracing callback. In the case of a dynamically sized stack,
the callback is unconditionally added.
The callback takes no arguments and is responsible for determining
the stack usage and doing any needed comparisons and storage. A roughly
-equivalent implementation of ``__sancov_lowest_stack`` using the callback
+equivalent implementation of `__sancov_lowest_stack` using the callback
would look like this:
-.. code-block:: c++
-
- void __sanitizer_cov_stack_depth(void) {
- uintptr_t stack = (uintptr_t)__builtin_frame_address(0);
+```c++
+void __sanitizer_cov_stack_depth(void) {
+ uintptr_t stack = (uintptr_t)__builtin_frame_address(0);
- if (stack < __sancov_lowest_stack)
- __sancov_lowest_stack = stack;
- }
+ if (stack < __sancov_lowest_stack)
+ __sancov_lowest_stack = stack;
+}
+```
-Gated Trace Callbacks
-=====================
+## Gated Trace Callbacks
Gate the invocation of the tracing callbacks with
-``-sanitizer-coverage-gated-trace-callbacks``.
+`-sanitizer-coverage-gated-trace-callbacks`.
When this option is enabled, the instrumentation will not call into the
runtime-provided callbacks for tracing, thus only incurring in a trivial
@@ -460,21 +442,19 @@ enable tracing.
This option is only supported for trace-pc-guard and trace-cmp.
-Disabling instrumentation with ``__attribute__((no_sanitize("coverage")))``
-===========================================================================
+## Disabling instrumentation with `__attribute__((no_sanitize("coverage")))`
It is possible to disable coverage instrumentation for select functions via the
-function attribute ``__attribute__((no_sanitize("coverage")))``. Because this
+function attribute `__attribute__((no_sanitize("coverage")))`. Because this
attribute may not be supported by other compilers, it is recommended to use it
-together with ``__has_feature(coverage_sanitizer)``.
+together with `__has_feature(coverage_sanitizer)`.
-Disabling instrumentation without source modification
-=====================================================
+## Disabling instrumentation without source modification
It is sometimes useful to tell SanitizerCoverage to instrument only a subset of the
functions in your target without modifying source files.
-With ``-fsanitize-coverage-allowlist=allowlist.txt``
-and ``-fsanitize-coverage-ignorelist=blocklist.txt``,
+With `-fsanitize-coverage-allowlist=allowlist.txt`
+and `-fsanitize-coverage-ignorelist=blocklist.txt`,
you can specify such a subset through the combination of an allowlist and a blocklist.
SanitizerCoverage will only instrument functions that satisfy two conditions.
@@ -492,36 +472,35 @@ files or functions that the allowlist loosely allowed.
Here is an example allowlist:
-.. code-block:: none
-
- # Enable instrumentation for a whole folder
- src:bar/*
- # Enable instrumentation for a specific source file
- src:foo/a.cpp
- # Enable instrumentation for all functions in those files
- fun:*
+```none
+# Enable instrumentation for a whole folder
+src:bar/*
+# Enable instrumentation for a specific source file
+src:foo/a.cpp
+# Enable instrumentation for all functions in those files
+fun:*
+```
And an example blocklist:
-.. code-block:: none
-
- # Disable instrumentation for a specific source file that the allowlist allowed
- src:bar/b.cpp
- # Disable instrumentation for a specific function that the allowlist allowed
- fun:*myFunc*
+```none
+# Disable instrumentation for a specific source file that the allowlist allowed
+src:bar/b.cpp
+# Disable instrumentation for a specific function that the allowlist allowed
+fun:*myFunc*
+```
-The use of ``*`` wildcards above is required because function names are matched after mangling.
+The use of `*` wildcards above is required because function names are matched after mangling.
Without the wildcards, one would have to write the whole mangled name.
Be careful that the paths of source files are matched exactly as they are provided on the clang
command line.
-For example, the allowlist above would include file ``bar/b.cpp`` if the path was provided
+For example, the allowlist above would include file `bar/b.cpp` if the path was provided
exactly like this, but would it would fail to include it with other ways to refer to the same
-file such as ``./bar/b.cpp``, or ``bar\b.cpp`` on Windows.
+file such as `./bar/b.cpp`, or `bar\b.cpp` on Windows.
So, please make sure to always double check that your lists are correctly applied.
-Default implementation
-======================
+## Default implementation
The sanitizer run-time (AddressSanitizer, MemorySanitizer, etc) provide a
default implementations of some of the coverage callbacks.
@@ -530,117 +509,113 @@ exit.
Example:
-.. code-block:: console
-
- % cat -n cov.cc
- 1 #include <stdio.h>
- 2 __attribute__((noinline))
- 3 void foo() { printf("foo\n"); }
- 4
- 5 int main(int argc, char **argv) {
- 6 if (argc == 2)
- 7 foo();
- 8 printf("main\n");
- 9 }
- % clang++ -g cov.cc -fsanitize=address -fsanitize-coverage=trace-pc-guard
- % ASAN_OPTIONS=coverage=1 ./a.out; wc -c *.sancov
- main
- SanitizerCoverage: ./a.out.7312.sancov 2 PCs written
- 24 a.out.7312.sancov
- % ASAN_OPTIONS=coverage=1 ./a.out foo ; wc -c *.sancov
- foo
- main
- SanitizerCoverage: ./a.out.7316.sancov 3 PCs written
- 24 a.out.7312.sancov
- 32 a.out.7316.sancov
+```console
+% cat -n cov.cc
+ 1 #include <stdio.h>
+ 2 __attribute__((noinline))
+ 3 void foo() { printf("foo\n"); }
+ 4
+ 5 int main(int argc, char **argv) {
+ 6 if (argc == 2)
+ 7 foo();
+ 8 printf("main\n");
+ 9 }
+% clang++ -g cov.cc -fsanitize=address -fsanitize-coverage=trace-pc-guard
+% ASAN_OPTIONS=coverage=1 ./a.out; wc -c *.sancov
+main
+SanitizerCoverage: ./a.out.7312.sancov 2 PCs written
+24 a.out.7312.sancov
+% ASAN_OPTIONS=coverage=1 ./a.out foo ; wc -c *.sancov
+foo
+main
+SanitizerCoverage: ./a.out.7316.sancov 3 PCs written
+24 a.out.7312.sancov
+32 a.out.7316.sancov
+```
Every time you run an executable instrumented with SanitizerCoverage
-one ``*.sancov`` file is created during the process shutdown.
+one `*.sancov` file is created during the process shutdown.
If the executable is dynamically linked against instrumented DSOs,
-one ``*.sancov`` file will be also created for every DSO.
+one `*.sancov` file will be also created for every DSO.
-Sancov data format
-------------------
+### Sancov data format
-The format of ``*.sancov`` files is very simple: the first 8 bytes is the magic,
-one of ``0xC0BFFFFFFFFFFF64`` and ``0xC0BFFFFFFFFFFF32``. The last byte of the
+The format of `*.sancov` files is very simple: the first 8 bytes is the magic,
+one of `0xC0BFFFFFFFFFFF64` and `0xC0BFFFFFFFFFFF32`. The last byte of the
magic defines the size of the following offsets. The rest of the data is the
offsets in the corresponding binary/DSO that were executed during the run.
-Sancov Tool
------------
+### Sancov Tool
-A simple ``sancov`` tool is provided to process coverage files.
+A simple `sancov` tool is provided to process coverage files.
The tool is part of LLVM project and is currently supported only on Linux.
It can handle symbolization tasks autonomously without any extra support
from the environment. You need to pass .sancov files (named
-``<module_name>.<pid>.sancov`` and paths to all corresponding binary elf files.
+`<module_name>.<pid>.sancov` and paths to all corresponding binary elf files.
Sancov matches these files using module names and binaries file names.
-.. code-block:: console
-
- USAGE: sancov [options] <action> <binary files...> <.sancov files...> <.symcov files...>
-
- Action (required):
- -covered-functions Print all covered funcions.
- -diff Compute difference between two sancov files (A - B) and write to the new output sancov file
- -html-report REMOVED. Use -symbolize & coverage-report-server.py.
- -merge Merges reports.
- -not-covered-functions Print all not covered funcions.
- -print-coverage-pcs Print coverage instrumentation points addresses.
- -print-coverage-stats Print coverage statistics.
- -print Print coverage addresses
- -symbolize Produces a symbolized JSON report from binary report.
- -union Compute union of multiple sancov files and write to the new output sancov file
-
- Generic Options:
- -help Display this help
- -h Alias for --help
- -version Display the version
- -v Alias for --version
-
- OPTIONS:
- -demangle=0 Alias for --no-demangle
- -demangle Demangle function names
- -ignorelist=<string> Ignorelist file (sanitizer ignorelist format)
- -no-demangle Do not demangle function names
- -no-skip-dead-files List dead source files in reports
- -output=<string> Output file for diff and union actions
- -skip-dead-files=0 Alias for --no-skip-dead-files
- -skip-dead-files Do not list dead source files in reports
- -strip_path_prefix=<string>
- Strip this prefix from files paths in reports
- -use_default_ignorelist=0
- Alias for --no-use_default_ignore_list
-
-
-Coverage Reports
-----------------
+```console
+USAGE: sancov [options] <action> <binary files...> <.sancov files...> <.symcov files...>
+
+Action (required):
+ -covered-functions Print all covered funcions.
+ -diff Compute difference between two sancov files (A - B) and write to the new output sancov file
+ -html-report REMOVED. Use -symbolize & coverage-report-server.py.
+ -merge Merges reports.
+ -not-covered-functions Print all not covered funcions.
+ -print-coverage-pcs Print coverage instrumentation points addresses.
+ -print-coverage-stats Print coverage statistics.
+ -print Print coverage addresses
+ -symbolize Produces a symbolized JSON report from binary report.
+ -union Compute union of multiple sancov files and write to the new output sancov file
+
+Generic Options:
+ -help Display this help
+ -h Alias for --help
+ -version Display the version
+ -v Alias for --version
+
+OPTIONS:
+ -demangle=0 Alias for --no-demangle
+ -demangle Demangle function names
+ -ignorelist=<string> Ignorelist file (sanitizer ignorelist format)
+ -no-demangle Do not demangle function names
+ -no-skip-dead-files List dead source files in reports
+ -output=<string> Output file for diff and union actions
+ -skip-dead-files=0 Alias for --no-skip-dead-files
+ -skip-dead-files Do not list dead source files in reports
+ -strip_path_prefix=<string>
+ Strip this prefix from files paths in reports
+ -use_default_ignorelist=0
+ Alias for --no-use_default_ignore_list
+```
+
+### Coverage Reports
**Experimental**
-``.sancov`` files do not contain enough information to generate a source-level
+`.sancov` files do not contain enough information to generate a source-level
coverage report. The missing information is contained
-in debug info of the binary. Thus the ``.sancov`` has to be symbolized
-to produce a ``.symcov`` file first:
-
-.. code-block:: console
+in debug info of the binary. Thus the `.sancov` has to be symbolized
+to produce a `.symcov` file first:
- sancov -symbolize my_program.123.sancov my_program > my_program.123.symcov
+```console
+sancov -symbolize my_program.123.sancov my_program > my_program.123.symcov
+```
-The ``.symcov`` file can be browsed overlaid over the source code by
-running ``tools/sancov/coverage-report-server.py`` script that will start
+The `.symcov` file can be browsed overlaid over the source code by
+running `tools/sancov/coverage-report-server.py` script that will start
an HTTP server.
-Output directory
-----------------
+### Output directory
By default, .sancov files are created in the current working directory.
-This can be changed with ``ASAN_OPTIONS=coverage_dir=/path``:
+This can be changed with `ASAN_OPTIONS=coverage_dir=/path`:
-.. code-block:: console
+```console
+% ASAN_OPTIONS="coverage=1:coverage_dir=/tmp/cov" ./a.out foo
+% ls -l /tmp/cov/*sancov
+-rw-r----- 1 kcc eng 4 Nov 27 12:21 a.out.22673.sancov
+-rw-r----- 1 kcc eng 8 Nov 27 12:21 a.out.22679.sancov
+```
- % ASAN_OPTIONS="coverage=1:coverage_dir=/tmp/cov" ./a.out foo
- % ls -l /tmp/cov/*sancov
- -rw-r----- 1 kcc eng 4 Nov 27 12:21 a.out.22673.sancov
- -rw-r----- 1 kcc eng 8 Nov 27 12:21 a.out.22679.sancov
diff --git a/clang/docs/ScalableStaticAnalysis/index.md b/clang/docs/ScalableStaticAnalysis/index.md
index 1a2699fd7423f..841fbb1bd3bc5 100644
--- a/clang/docs/ScalableStaticAnalysis/index.md
+++ b/clang/docs/ScalableStaticAnalysis/index.md
@@ -1,19 +1,20 @@
-==================================
-Scalable Static Analysis Framework
-==================================
+# Scalable Static Analysis Framework
This is a framework for writing cross-translation unit analyses in a scalable and extensible setting.
-.. toctree::
- :numbered:
- :maxdepth: 2
- :glob:
+```{toctree}
+:glob: true
+:maxdepth: 2
+:numbered: true
- user-docs/*
+user-docs/*
+```
-:doc:`Developer documentation <developer-docs/index>`
+{doc}`Developer documentation <developer-docs/index>`
-.. toctree::
- :hidden:
+```{toctree}
+:hidden: true
+
+developer-docs/index
+```
- developer-docs/index
diff --git a/clang/docs/ThreadSafetyAnalysis.md b/clang/docs/ThreadSafetyAnalysis.md
index fee1c2b778c01..686493874901d 100644
--- a/clang/docs/ThreadSafetyAnalysis.md
+++ b/clang/docs/ThreadSafetyAnalysis.md
@@ -1,466 +1,438 @@
+# Thread Safety Analysis
-======================
-Thread Safety Analysis
-======================
-
-Introduction
-============
+## Introduction
Clang Thread Safety Analysis is a C++ language extension which warns about
-potential race conditions in code. The analysis is completely static (i.e.
-compile-time); there is no run-time overhead. The analysis is still
+potential race conditions in code. The analysis is completely static (i.e.
+compile-time); there is no run-time overhead. The analysis is still
under active development, but it is mature enough to be deployed in an
-industrial setting. It is being developed by Google, in collaboration with
+industrial setting. It is being developed by Google, in collaboration with
CERT/SEI, and is used extensively in Google's internal code base.
Thread safety analysis works very much like a type system for multi-threaded
-programs. In addition to declaring the *type* of data (e.g. ``int``, ``float``,
+programs. In addition to declaring the *type* of data (e.g. `int`, `float`,
etc.), the programmer can (optionally) declare how access to that data is
-controlled in a multi-threaded environment. For example, if ``foo`` is
-*guarded by* the mutex ``mu``, then the analysis will issue a warning whenever
-a piece of code reads or writes to ``foo`` without first locking ``mu``.
+controlled in a multi-threaded environment. For example, if `foo` is
+*guarded by* the mutex `mu`, then the analysis will issue a warning whenever
+a piece of code reads or writes to `foo` without first locking `mu`.
Similarly, if there are particular routines that should only be called by
the GUI thread, then the analysis will warn if other threads call those
routines.
-Getting Started
-----------------
-
-.. code-block:: c++
-
- #include "mutex.h"
-
- class BankAccount {
- private:
- Mutex mu;
- int balance GUARDED_BY(mu);
-
- void depositImpl(int amount) {
- balance += amount; // WARNING! Cannot write balance without locking mu.
- }
-
- void withdrawImpl(int amount) REQUIRES(mu) {
- balance -= amount; // OK. Caller must have locked mu.
- }
-
- public:
- void withdraw(int amount) {
- mu.Lock();
- withdrawImpl(amount); // OK. We've locked mu.
- } // WARNING! Failed to unlock mu.
-
- void transferFrom(BankAccount& b, int amount) {
- mu.Lock();
- b.withdrawImpl(amount); // WARNING! Calling withdrawImpl() requires locking b.mu.
- depositImpl(amount); // OK. depositImpl() has no requirements.
- mu.Unlock();
- }
- };
-
-This example demonstrates the basic concepts behind the analysis. The
-``GUARDED_BY`` attribute declares that a thread must lock ``mu`` before it can
-read or write to ``balance``, thus ensuring that the increment and decrement
-operations are atomic. Similarly, ``REQUIRES`` declares that
-the calling thread must lock ``mu`` before calling ``withdrawImpl``.
-Because the caller is assumed to have locked ``mu``, it is safe to modify
-``balance`` within the body of the method.
-
-The ``depositImpl()`` method does not have ``REQUIRES``, so the
-analysis issues a warning. Thread safety analysis is not inter-procedural, so
+### Getting Started
+
+```c++
+#include "mutex.h"
+
+class BankAccount {
+private:
+ Mutex mu;
+ int balance GUARDED_BY(mu);
+
+ void depositImpl(int amount) {
+ balance += amount; // WARNING! Cannot write balance without locking mu.
+ }
+
+ void withdrawImpl(int amount) REQUIRES(mu) {
+ balance -= amount; // OK. Caller must have locked mu.
+ }
+
+public:
+ void withdraw(int amount) {
+ mu.Lock();
+ withdrawImpl(amount); // OK. We've locked mu.
+ } // WARNING! Failed to unlock mu.
+
+ void transferFrom(BankAccount& b, int amount) {
+ mu.Lock();
+ b.withdrawImpl(amount); // WARNING! Calling withdrawImpl() requires locking b.mu.
+ depositImpl(amount); // OK. depositImpl() has no requirements.
+ mu.Unlock();
+ }
+};
+```
+
+This example demonstrates the basic concepts behind the analysis. The
+`GUARDED_BY` attribute declares that a thread must lock `mu` before it can
+read or write to `balance`, thus ensuring that the increment and decrement
+operations are atomic. Similarly, `REQUIRES` declares that
+the calling thread must lock `mu` before calling `withdrawImpl`.
+Because the caller is assumed to have locked `mu`, it is safe to modify
+`balance` within the body of the method.
+
+The `depositImpl()` method does not have `REQUIRES`, so the
+analysis issues a warning. Thread safety analysis is not inter-procedural, so
caller requirements must be explicitly declared.
-There is also a warning in ``transferFrom()``, because although the method
-locks ``this->mu``, it does not lock ``b.mu``. The analysis understands
+There is also a warning in `transferFrom()`, because although the method
+locks `this->mu`, it does not lock `b.mu`. The analysis understands
that these are two separate mutexes, in two different objects.
-Finally, there is a warning in the ``withdraw()`` method, because it fails to
-unlock ``mu``. Every lock must have a corresponding unlock, and the analysis
-will detect both double locks, and double unlocks. A function is allowed to
+Finally, there is a warning in the `withdraw()` method, because it fails to
+unlock `mu`. Every lock must have a corresponding unlock, and the analysis
+will detect both double locks, and double unlocks. A function is allowed to
acquire a lock without releasing it, (or vice versa), but it must be annotated
-as such (using ``ACQUIRE``/``RELEASE``).
-
-
-Running The Analysis
---------------------
+as such (using `ACQUIRE`/`RELEASE`).
-To run the analysis, simply compile with the ``-Wthread-safety`` flag, e.g.
+### Running The Analysis
-.. code-block:: bash
+To run the analysis, simply compile with the `-Wthread-safety` flag, e.g.
- clang -c -Wthread-safety example.cpp
+```bash
+clang -c -Wthread-safety example.cpp
+```
Note that this example assumes the presence of a suitably annotated
-:ref:`mutexheader` that declares which methods perform locking,
+{ref}`mutexheader` that declares which methods perform locking,
unlocking, and so on.
-
-Basic Concepts: Capabilities
-============================
+## Basic Concepts: Capabilities
Thread safety analysis provides a way of protecting *resources* with
-*capabilities*. A resource is either a data member, or a function/method
-that provides access to some underlying resource. The analysis ensures that
+*capabilities*. A resource is either a data member, or a function/method
+that provides access to some underlying resource. The analysis ensures that
the calling thread cannot access the *resource* (i.e. call the function, or
read/write the data) unless it has the *capability* to do so.
Capabilities are associated with named C++ objects which declare specific
-methods to acquire and release the capability. The name of the object serves
-to identify the capability. The most common example is a mutex. For example,
-if ``mu`` is a mutex, then calling ``mu.Lock()`` causes the calling thread
-to acquire the capability to access data that is protected by ``mu``. Similarly,
-calling ``mu.Unlock()`` releases that capability.
+methods to acquire and release the capability. The name of the object serves
+to identify the capability. The most common example is a mutex. For example,
+if `mu` is a mutex, then calling `mu.Lock()` causes the calling thread
+to acquire the capability to access data that is protected by `mu`. Similarly,
+calling `mu.Unlock()` releases that capability.
-A thread may hold a capability either *exclusively* or *shared*. An exclusive
+A thread may hold a capability either *exclusively* or *shared*. An exclusive
capability can be held by only one thread at a time, while a shared capability
-can be held by many threads at the same time. This mechanism enforces a
-multiple-reader, single-writer pattern. Write operations to protected data
+can be held by many threads at the same time. This mechanism enforces a
+multiple-reader, single-writer pattern. Write operations to protected data
require exclusive access, while read operations require only shared access.
At any given moment during program execution, a thread holds a specific set of
-capabilities (e.g. the set of mutexes that it has locked.) These act like keys
-or tokens that allow the thread to access a given resource. Just like physical
+capabilities (e.g. the set of mutexes that it has locked.) These act like keys
+or tokens that allow the thread to access a given resource. Just like physical
security keys, a thread cannot make a copy of a capability, nor can it destroy
-one. A thread can only release a capability to another thread, or acquire one
-from another thread. The annotations are deliberately agnostic about the
+one. A thread can only release a capability to another thread, or acquire one
+from another thread. The annotations are deliberately agnostic about the
exact mechanism used to acquire and release capabilities; it assumes that the
underlying implementation (e.g. the Mutex implementation) does the handoff in
an appropriate manner.
The set of capabilities that are actually held by a given thread at a given
-point in program execution is a run-time concept. The static analysis works
+point in program execution is a run-time concept. The static analysis works
by calculating an approximation of that set, called the *capability
-environment*. The capability environment is calculated for every program point,
+environment*. The capability environment is calculated for every program point,
and describes the set of capabilities that are statically known to be held, or
-not held, at that particular point. This environment is a conservative
+not held, at that particular point. This environment is a conservative
approximation of the full set of capabilities that will actually be held by a
thread at run-time.
-
-Reference Guide
-===============
+## Reference Guide
The thread safety analysis uses attributes to declare threading constraints.
Attributes must be attached to named declarations, such as classes, methods,
and data members. Users are *strongly advised* to define macros for the various
-attributes; example definitions can be found in :ref:`mutexheader`, below.
+attributes; example definitions can be found in {ref}`mutexheader`, below.
The following documentation assumes the use of macros.
The attributes only control assumptions made by thread safety analysis and the
-warnings it issues. They don't affect generated code or behavior at run-time.
+warnings it issues. They don't affect generated code or behavior at run-time.
For historical reasons, prior versions of thread safety used macro names that
-were very lock-centric. These macros have since been renamed to fit a more
-general capability model. The prior names are still in use, and will be
+were very lock-centric. These macros have since been renamed to fit a more
+general capability model. The prior names are still in use, and will be
mentioned under the tag *previously* where appropriate.
+### GUARDED_BY(...) and PT_GUARDED_BY(...)
-GUARDED_BY(...) and PT_GUARDED_BY(...)
---------------------------------------
-
-``GUARDED_BY`` is an attribute on data members, which declares that the data
-member is protected by the given capability. Read operations on the data
+`GUARDED_BY` is an attribute on data members, which declares that the data
+member is protected by the given capability. Read operations on the data
require shared access, while write operations require exclusive access.
Multiple capabilities may be specified, subject to the following rules:
a writer must hold *all* listed capabilities exclusively, so holding *any one*
of them is sufficient to guarantee at least shared (read) access.
-``PT_GUARDED_BY`` is similar, but is intended for use on pointers and smart
+`PT_GUARDED_BY` is similar, but is intended for use on pointers and smart
pointers. There is no constraint on the data member itself, but the *data that
it points to* is protected by the given capabilities.
-.. code-block:: c++
+```c++
+Mutex mu;
+int *p1 GUARDED_BY(mu);
+int *p2 PT_GUARDED_BY(mu);
+unique_ptr<int> p3 PT_GUARDED_BY(mu);
- Mutex mu;
- int *p1 GUARDED_BY(mu);
- int *p2 PT_GUARDED_BY(mu);
- unique_ptr<int> p3 PT_GUARDED_BY(mu);
-
- void test() {
- p1 = 0; // Warning!
+void test() {
+ p1 = 0; // Warning!
- *p2 = 42; // Warning!
- p2 = new int; // OK.
+ *p2 = 42; // Warning!
+ p2 = new int; // OK.
- *p3 = 42; // Warning!
- p3.reset(new int); // OK.
- }
+ *p3 = 42; // Warning!
+ p3.reset(new int); // OK.
+}
+```
When multiple capabilities are listed:
-* **Write** access requires all listed capabilities to be held exclusively.
-* **Read** access requires at least one of them to be held (shared or exclusive).
+- **Write** access requires all listed capabilities to be held exclusively.
+- **Read** access requires at least one of them to be held (shared or exclusive).
-.. code-block:: c++
+```c++
+Mutex mu1, mu2;
+int a GUARDED_BY(mu1, mu2);
- Mutex mu1, mu2;
- int a GUARDED_BY(mu1, mu2);
+void reader() REQUIRES_SHARED(mu1) {
+ int x = a; // OK: at least one capability is held.
+ a = 0; // Warning! Writing requires both mu1 and mu2.
+}
- void reader() REQUIRES_SHARED(mu1) {
- int x = a; // OK: at least one capability is held.
- a = 0; // Warning! Writing requires both mu1 and mu2.
- }
-
- void writer() REQUIRES(mu1, mu2) {
- a = 0; // OK: both capabilities are held exclusively.
- }
+void writer() REQUIRES(mu1, mu2) {
+ a = 0; // OK: both capabilities are held exclusively.
+}
+```
+### REQUIRES(...), REQUIRES_SHARED(...)
-REQUIRES(...), REQUIRES_SHARED(...)
------------------------------------
+*Previously*: `EXCLUSIVE_LOCKS_REQUIRED`, `SHARED_LOCKS_REQUIRED`
-*Previously*: ``EXCLUSIVE_LOCKS_REQUIRED``, ``SHARED_LOCKS_REQUIRED``
-
-``REQUIRES`` is an attribute on functions, methods or function parameters of
-reference to :ref:`scoped_capability`-annotated type, which
+`REQUIRES` is an attribute on functions, methods or function parameters of
+reference to {ref}`scoped_capability`-annotated type, which
declares that the calling thread must have exclusive access to the given
-capabilities. More than one capability may be specified. The capabilities
+capabilities. More than one capability may be specified. The capabilities
must be held on entry to the function, *and must still be held on exit*.
Additionally, if the attribute is on a function parameter, it declares that
the scoped capability manages the specified capabilities in the given order.
-``REQUIRES_SHARED`` is similar, but requires only shared access.
-
-.. code-block:: c++
-
- Mutex mu1, mu2;
- int a GUARDED_BY(mu1);
- int b GUARDED_BY(mu2);
-
- void foo() REQUIRES(mu1, mu2) {
- a = 0;
- b = 0;
- }
-
- void test() {
- mu1.Lock();
- foo(); // Warning! Requires mu2.
- mu1.Unlock();
- }
-
- void require(MutexLocker& scope REQUIRES(mu1)) {
- scope.Unlock();
- a = 0; // Warning! Requires mu1.
- scope.Lock();
- }
-
- void testParameter() {
- MutexLocker scope(&mu1), scope2(&mu2);
- require(scope2); // Warning! Mutex managed by 'scope2' is 'mu2' instead of 'mu1'
- require(scope); // OK.
- scope.Unlock();
- require(scope); // Warning! Requires mu1.
- }
-
-
-ACQUIRE(...), ACQUIRE_SHARED(...), RELEASE(...), RELEASE_SHARED(...), RELEASE_GENERIC(...)
-------------------------------------------------------------------------------------------
-
-*Previously*: ``EXCLUSIVE_LOCK_FUNCTION``, ``SHARED_LOCK_FUNCTION``,
-``UNLOCK_FUNCTION``
-
-``ACQUIRE`` and ``ACQUIRE_SHARED`` are attributes on functions, methods
-or function parameters of reference to :ref:`scoped_capability`-annotated type,
+`REQUIRES_SHARED` is similar, but requires only shared access.
+
+```c++
+Mutex mu1, mu2;
+int a GUARDED_BY(mu1);
+int b GUARDED_BY(mu2);
+
+void foo() REQUIRES(mu1, mu2) {
+ a = 0;
+ b = 0;
+}
+
+void test() {
+ mu1.Lock();
+ foo(); // Warning! Requires mu2.
+ mu1.Unlock();
+}
+
+void require(MutexLocker& scope REQUIRES(mu1)) {
+ scope.Unlock();
+ a = 0; // Warning! Requires mu1.
+ scope.Lock();
+}
+
+void testParameter() {
+ MutexLocker scope(&mu1), scope2(&mu2);
+ require(scope2); // Warning! Mutex managed by 'scope2' is 'mu2' instead of 'mu1'
+ require(scope); // OK.
+ scope.Unlock();
+ require(scope); // Warning! Requires mu1.
+}
+```
+
+### ACQUIRE(...), ACQUIRE_SHARED(...), RELEASE(...), RELEASE_SHARED(...), RELEASE_GENERIC(...)
+
+*Previously*: `EXCLUSIVE_LOCK_FUNCTION`, `SHARED_LOCK_FUNCTION`,
+`UNLOCK_FUNCTION`
+
+`ACQUIRE` and `ACQUIRE_SHARED` are attributes on functions, methods
+or function parameters of reference to {ref}`scoped_capability`-annotated type,
which declare that the function acquires a capability, but does not release it.
The given capability must not be held on entry, and will be held on exit
-(exclusively for ``ACQUIRE``, shared for ``ACQUIRE_SHARED``).
+(exclusively for `ACQUIRE`, shared for `ACQUIRE_SHARED`).
Additionally, if the attribute is on a function parameter, it declares that
the scoped capability manages the specified capabilities in the given order.
-``RELEASE``, ``RELEASE_SHARED``, and ``RELEASE_GENERIC`` declare that the
-function releases the given capability. The capability must be held on entry
-(exclusively for ``RELEASE``, shared for ``RELEASE_SHARED``, exclusively or
-shared for ``RELEASE_GENERIC``), and will no longer be held on exit.
-
-.. code-block:: c++
-
+`RELEASE`, `RELEASE_SHARED`, and `RELEASE_GENERIC` declare that the
+function releases the given capability. The capability must be held on entry
+(exclusively for `RELEASE`, shared for `RELEASE_SHARED`, exclusively or
+shared for `RELEASE_GENERIC`), and will no longer be held on exit.
+
+```c++
+Mutex mu;
+MyClass myObject GUARDED_BY(mu);
+
+void lockAndInit() ACQUIRE(mu) {
+ mu.Lock();
+ myObject.init();
+}
+
+void cleanupAndUnlock() RELEASE(mu) {
+ myObject.cleanup();
+} // Warning! Need to unlock mu.
+
+void test() {
+ lockAndInit();
+ myObject.doSomething();
+ cleanupAndUnlock();
+ myObject.doSomething(); // Warning, mu is not locked.
+}
+
+void release(MutexLocker& scope RELEASE(mu)) {
+} // Warning! Need to unlock mu.
+
+void testParameter() {
+ MutexLocker scope(&mu);
+ release(scope);
+}
+```
+
+If no argument is passed to `ACQUIRE` or `RELEASE`, then the argument is
+assumed to be `this`, and the analysis will not check the body of the
+function. This pattern is intended for use by classes which hide locking
+details behind an abstract interface. For example:
+
+```c++
+template <class T>
+class CAPABILITY("mutex") Container {
+private:
Mutex mu;
- MyClass myObject GUARDED_BY(mu);
-
- void lockAndInit() ACQUIRE(mu) {
- mu.Lock();
- myObject.init();
- }
-
- void cleanupAndUnlock() RELEASE(mu) {
- myObject.cleanup();
- } // Warning! Need to unlock mu.
+ T* data;
- void test() {
- lockAndInit();
- myObject.doSomething();
- cleanupAndUnlock();
- myObject.doSomething(); // Warning, mu is not locked.
- }
-
- void release(MutexLocker& scope RELEASE(mu)) {
- } // Warning! Need to unlock mu.
+public:
+ // Hide mu from public interface.
+ void Lock() ACQUIRE() { mu.Lock(); }
+ void Unlock() RELEASE() { mu.Unlock(); }
- void testParameter() {
- MutexLocker scope(&mu);
- release(scope);
- }
+ T& getElem(int i) { return data[i]; }
+};
-If no argument is passed to ``ACQUIRE`` or ``RELEASE``, then the argument is
-assumed to be ``this``, and the analysis will not check the body of the
-function. This pattern is intended for use by classes which hide locking
-details behind an abstract interface. For example:
+void test() {
+ Container<int> c;
+ c.Lock();
+ int i = c.getElem(0);
+ c.Unlock();
+}
+```
-.. code-block:: c++
+### EXCLUDES(...)
- template <class T>
- class CAPABILITY("mutex") Container {
- private:
- Mutex mu;
- T* data;
+*Previously*: `LOCKS_EXCLUDED`
- public:
- // Hide mu from public interface.
- void Lock() ACQUIRE() { mu.Lock(); }
- void Unlock() RELEASE() { mu.Unlock(); }
-
- T& getElem(int i) { return data[i]; }
- };
-
- void test() {
- Container<int> c;
- c.Lock();
- int i = c.getElem(0);
- c.Unlock();
- }
-
-
-EXCLUDES(...)
--------------
-
-*Previously*: ``LOCKS_EXCLUDED``
-
-``EXCLUDES`` is an attribute on functions, methods or function parameters
-of reference to :ref:`scoped_capability`-annotated type, which declares that
-the caller must *not* hold the given capabilities. This annotation is
-used to prevent deadlock. Many mutex implementations are not re-entrant, so
+`EXCLUDES` is an attribute on functions, methods or function parameters
+of reference to {ref}`scoped_capability`-annotated type, which declares that
+the caller must *not* hold the given capabilities. This annotation is
+used to prevent deadlock. Many mutex implementations are not re-entrant, so
deadlock can occur if the function acquires the mutex a second time.
Additionally, if the attribute is on a function parameter, it declares that
the scoped capability manages the specified capabilities in the given order.
-.. code-block:: c++
-
- Mutex mu;
- int a GUARDED_BY(mu);
-
- void clear() EXCLUDES(mu) {
- mu.Lock();
- a = 0;
- mu.Unlock();
- }
-
- void reset() {
- mu.Lock();
- clear(); // Warning! Caller cannot hold 'mu'.
- mu.Unlock();
- }
-
- void exclude(MutexLocker& scope LOCKS_EXCLUDED(mu)) {
- scope.Unlock(); // Warning! mu is not locked.
- scope.Lock();
- } // Warning! mu still held at the end of function.
-
- void testParameter() {
- MutexLocker scope(&mu);
- exclude(scope); // Warning, mu is held.
- }
-
-Unlike ``REQUIRES``, ``EXCLUDES`` is optional. The analysis will not issue a
+```c++
+Mutex mu;
+int a GUARDED_BY(mu);
+
+void clear() EXCLUDES(mu) {
+ mu.Lock();
+ a = 0;
+ mu.Unlock();
+}
+
+void reset() {
+ mu.Lock();
+ clear(); // Warning! Caller cannot hold 'mu'.
+ mu.Unlock();
+}
+
+void exclude(MutexLocker& scope LOCKS_EXCLUDED(mu)) {
+ scope.Unlock(); // Warning! mu is not locked.
+ scope.Lock();
+} // Warning! mu still held at the end of function.
+
+void testParameter() {
+ MutexLocker scope(&mu);
+ exclude(scope); // Warning, mu is held.
+}
+```
+
+Unlike `REQUIRES`, `EXCLUDES` is optional. The analysis will not issue a
warning if the attribute is missing, which can lead to false negatives in some
-cases. This issue is discussed further in :ref:`negative`.
-
+cases. This issue is discussed further in {ref}`negative`.
-NO_THREAD_SAFETY_ANALYSIS
--------------------------
+### NO_THREAD_SAFETY_ANALYSIS
-``NO_THREAD_SAFETY_ANALYSIS`` is an attribute on functions or methods, which
-turns off thread safety checking for that method. It provides an escape hatch
+`NO_THREAD_SAFETY_ANALYSIS` is an attribute on functions or methods, which
+turns off thread safety checking for that method. It provides an escape hatch
for functions which are either (1) deliberately thread-unsafe, or (2) are
-thread-safe, but too complicated for the analysis to understand. Reasons for
-(2) will be described in the :ref:`limitations`, below.
-
-.. code-block:: c++
+thread-safe, but too complicated for the analysis to understand. Reasons for
+(2) will be described in the {ref}`limitations`, below.
- class Counter {
- Mutex mu;
- int a GUARDED_BY(mu);
+```c++
+class Counter {
+ Mutex mu;
+ int a GUARDED_BY(mu);
- void unsafeIncrement() NO_THREAD_SAFETY_ANALYSIS { a++; }
- };
+ void unsafeIncrement() NO_THREAD_SAFETY_ANALYSIS { a++; }
+};
+```
-Unlike the other attributes, ``NO_THREAD_SAFETY_ANALYSIS`` is not part of the
+Unlike the other attributes, `NO_THREAD_SAFETY_ANALYSIS` is not part of the
interface of a function, and should thus be placed on the function definition
-(in the ``.cc`` or ``.cpp`` file) rather than on the function declaration
+(in the `.cc` or `.cpp` file) rather than on the function declaration
(in the header).
+### RETURN_CAPABILITY(c)
-RETURN_CAPABILITY(c)
---------------------
-
-*Previously*: ``LOCK_RETURNED``
+*Previously*: `LOCK_RETURNED`
-``RETURN_CAPABILITY`` is an attribute on functions or methods, which declares
-that the function returns a reference to the given capability. It is used to
+`RETURN_CAPABILITY` is an attribute on functions or methods, which declares
+that the function returns a reference to the given capability. It is used to
annotate getter methods that return mutexes.
-.. code-block:: c++
-
- class MyClass {
- private:
- Mutex mu;
- int a GUARDED_BY(mu);
-
- public:
- Mutex* getMu() RETURN_CAPABILITY(mu) { return μ }
+```c++
+class MyClass {
+private:
+ Mutex mu;
+ int a GUARDED_BY(mu);
- // analysis knows that getMu() == mu
- void clear() REQUIRES(getMu()) { a = 0; }
- };
+public:
+ Mutex* getMu() RETURN_CAPABILITY(mu) { return μ }
+ // analysis knows that getMu() == mu
+ void clear() REQUIRES(getMu()) { a = 0; }
+};
+```
-ACQUIRED_BEFORE(...), ACQUIRED_AFTER(...)
------------------------------------------
+### ACQUIRED_BEFORE(...), ACQUIRED_AFTER(...)
-``ACQUIRED_BEFORE`` and ``ACQUIRED_AFTER`` are attributes on member
+`ACQUIRED_BEFORE` and `ACQUIRED_AFTER` are attributes on member
declarations, specifically declarations of mutexes or other capabilities.
These declarations enforce a particular order in which the mutexes must be
acquired, in order to prevent deadlock.
-.. code-block:: c++
-
- Mutex m1;
- Mutex m2 ACQUIRED_AFTER(m1);
-
- // Alternative declaration
- // Mutex m2;
- // Mutex m1 ACQUIRED_BEFORE(m2);
+```c++
+Mutex m1;
+Mutex m2 ACQUIRED_AFTER(m1);
- void foo() {
- m2.Lock();
- m1.Lock(); // Warning! m2 must be acquired after m1.
- m1.Unlock();
- m2.Unlock();
- }
+// Alternative declaration
+// Mutex m2;
+// Mutex m1 ACQUIRED_BEFORE(m2);
+void foo() {
+ m2.Lock();
+ m1.Lock(); // Warning! m2 must be acquired after m1.
+ m1.Unlock();
+ m2.Unlock();
+}
+```
-CAPABILITY(<string>)
---------------------
+### CAPABILITY(\<string>)
-*Previously*: ``LOCKABLE``
+*Previously*: `LOCKABLE`
-``CAPABILITY`` is an attribute on classes, which specifies that objects of the
-class can be used as a capability. The string argument specifies the kind of
-capability in error messages, e.g. ``"mutex"``. See the ``Container`` example
-given above, or the ``Mutex`` class in :ref:`mutexheader`.
+`CAPABILITY` is an attribute on classes, which specifies that objects of the
+class can be used as a capability. The string argument specifies the kind of
+capability in error messages, e.g. `"mutex"`. See the `Container` example
+given above, or the `Mutex` class in {ref}`mutexheader`.
-REENTRANT_CAPABILITY
---------------------
+### REENTRANT_CAPABILITY
-``REENTRANT_CAPABILITY`` is an attribute on capability classes, denoting that
+`REENTRANT_CAPABILITY` is an attribute on capability classes, denoting that
they are reentrant. Marking a capability as reentrant means that acquiring the
same capability multiple times is safe. Acquiring the same capability with
different access privileges (exclusive vs. shared) again is not considered
@@ -472,341 +444,314 @@ helpers. Otherwise, best practice is to avoid explicitly acquiring a capability
multiple times within the same function, and letting the analysis produce
warnings on double-acquisition attempts.
-.. _scoped_capability:
+(scoped-capability)=
-SCOPED_CAPABILITY
------------------
+### SCOPED_CAPABILITY
-*Previously*: ``SCOPED_LOCKABLE``
+*Previously*: `SCOPED_LOCKABLE`
-``SCOPED_CAPABILITY`` is an attribute on classes that implement RAII-style
+`SCOPED_CAPABILITY` is an attribute on classes that implement RAII-style
locking, in which a capability is acquired in the constructor, and released in
-the destructor. Such classes require special handling because the constructor
+the destructor. Such classes require special handling because the constructor
and destructor refer to the capability via different names; see the
-``MutexLocker`` class in :ref:`mutexheader`, below.
+`MutexLocker` class in {ref}`mutexheader`, below.
Scoped capabilities are treated as capabilities that are implicitly acquired
on construction and released on destruction. They are associated with
the set of (regular) capabilities named in thread safety attributes on the
constructor or function returning them by value (using C++17 guaranteed copy
elision). Acquire-type attributes on other member functions are treated as
-applying to that set of associated capabilities, while ``RELEASE`` implies that
+applying to that set of associated capabilities, while `RELEASE` implies that
a function releases all associated capabilities in whatever mode they're held.
+### TRY_ACQUIRE(\<bool>, ...), TRY_ACQUIRE_SHARED(\<bool>, ...)
-TRY_ACQUIRE(<bool>, ...), TRY_ACQUIRE_SHARED(<bool>, ...)
----------------------------------------------------------
-
-*Previously:* ``EXCLUSIVE_TRYLOCK_FUNCTION``, ``SHARED_TRYLOCK_FUNCTION``
+*Previously:* `EXCLUSIVE_TRYLOCK_FUNCTION`, `SHARED_TRYLOCK_FUNCTION`
These are attributes on a function or method that tries to acquire the given
capability, and returns a boolean value indicating success or failure.
-The first argument must be ``true`` or ``false``, to specify which return value
+The first argument must be `true` or `false`, to specify which return value
indicates success, and the remaining arguments are interpreted in the same way
-as ``ACQUIRE``. See :ref:`mutexheader`, below, for example uses.
+as `ACQUIRE`. See {ref}`mutexheader`, below, for example uses.
Because the analysis doesn't support conditional locking, a capability is
treated as acquired after the first branch on the return value of a try-acquire
function.
-.. code-block:: c++
+```c++
+Mutex mu;
+int a GUARDED_BY(mu);
- Mutex mu;
- int a GUARDED_BY(mu);
-
- void foo() {
- bool success = mu.TryLock();
- a = 0; // Warning, mu is not locked.
- if (success) {
- a = 0; // Ok.
- mu.Unlock();
- } else {
- a = 0; // Warning, mu is not locked.
- }
+void foo() {
+ bool success = mu.TryLock();
+ a = 0; // Warning, mu is not locked.
+ if (success) {
+ a = 0; // Ok.
+ mu.Unlock();
+ } else {
+ a = 0; // Warning, mu is not locked.
}
+}
+```
+### ASSERT_CAPABILITY(...) and ASSERT_SHARED_CAPABILITY(...)
-ASSERT_CAPABILITY(...) and ASSERT_SHARED_CAPABILITY(...)
---------------------------------------------------------
-
-*Previously:* ``ASSERT_EXCLUSIVE_LOCK``, ``ASSERT_SHARED_LOCK``
+*Previously:* `ASSERT_EXCLUSIVE_LOCK`, `ASSERT_SHARED_LOCK`
These are attributes on a function or method which asserts the calling thread
already holds the given capability, for example, by performing a run-time test
-and terminating if the capability is not held. Presence of this annotation
+and terminating if the capability is not held. Presence of this annotation
causes the analysis to assume the capability is held after calls to the
-annotated function. See :ref:`mutexheader`, below, for example uses.
+annotated function. See {ref}`mutexheader`, below, for example uses.
-
-GUARDED_VAR and PT_GUARDED_VAR
-------------------------------
+### GUARDED_VAR and PT_GUARDED_VAR
Use of these attributes has been deprecated.
-
-Function Pointers
------------------
+### Function Pointers
Thread safety attributes may also be applied to function pointer variables and
-fields. The attributes describe the locking behavior of calling through that
+fields. The attributes describe the locking behavior of calling through that
pointer, and the analysis will check calls through the pointer accordingly.
-.. code-block:: c++
-
- Mutex mu;
- int x GUARDED_BY(mu);
+```c++
+Mutex mu;
+int x GUARDED_BY(mu);
- void (*lock_fn)(void) ACQUIRE(mu);
- void (*unlock_fn)(void) RELEASE(mu);
+void (*lock_fn)(void) ACQUIRE(mu);
+void (*unlock_fn)(void) RELEASE(mu);
- struct Ops {
- void (*read)(void) REQUIRES(mu);
- };
+struct Ops {
+ void (*read)(void) REQUIRES(mu);
+};
- void test(Ops *ops) {
- lock_fn();
- x = 1;
- ops->read();
- unlock_fn();
- }
+void test(Ops *ops) {
+ lock_fn();
+ x = 1;
+ ops->read();
+ unlock_fn();
+}
+```
Note that the attributes are on the *variable* (or field), not on the function
-pointer type. Assigning a function with different (or no) attributes to an
-annotated function pointer variable is not diagnosed. The analysis trusts the
+pointer type. Assigning a function with different (or no) attributes to an
+annotated function pointer variable is not diagnosed. The analysis trusts the
annotations on the variable at the call site.
-This support is limited to plain function pointers. Pointers-to-member
-functions, blocks, and wrapper types such as ``std::function`` are not
+This support is limited to plain function pointers. Pointers-to-member
+functions, blocks, and wrapper types such as `std::function` are not
supported yet.
+### Warning flags
-Warning flags
--------------
-
-* ``-Wthread-safety``: Umbrella flag which turns on the following:
+- `-Wthread-safety`: Umbrella flag which turns on the following:
- + ``-Wthread-safety-attributes``: Semantic checks for thread safety attributes.
- + ``-Wthread-safety-analysis``: The core analysis.
- + ``-Wthread-safety-precise``: Requires that mutex expressions match precisely.
- This warning can be disabled for code which has a lot of aliases.
- + ``-Wthread-safety-reference``: Checks when guarded members are passed or
+ - `-Wthread-safety-attributes`: Semantic checks for thread safety attributes.
+ - `-Wthread-safety-analysis`: The core analysis.
+ - `-Wthread-safety-precise`: Requires that mutex expressions match precisely.
+ : This warning can be disabled for code which has a lot of aliases.
+ - `-Wthread-safety-reference`: Checks when guarded members are passed or
returned by reference.
-* ``-Wthread-safety-pointer``: Checks when passing or returning pointers to
+- `-Wthread-safety-pointer`: Checks when passing or returning pointers to
guarded variables, or pointers to guarded data, as function argument or
return value respectively.
-:ref:`negative` are an experimental feature, which are enabled with:
+{ref}`negative` are an experimental feature, which are enabled with:
-* ``-Wthread-safety-negative``: Negative capabilities. Off by default.
+- `-Wthread-safety-negative`: Negative capabilities. Off by default.
When new features and checks are added to the analysis, they can often introduce
-additional warnings. Those warnings are initially released as *beta* warnings
+additional warnings. Those warnings are initially released as *beta* warnings
for a period of time, after which they are migrated into the standard analysis.
-* ``-Wthread-safety-beta``: New features. Off by default.
+- `-Wthread-safety-beta`: New features. Off by default.
+(negative)=
-.. _negative:
-
-Negative Capabilities
-=====================
+## Negative Capabilities
Thread Safety Analysis is designed to prevent both race conditions and
-deadlock. The ``GUARDED_BY`` and ``REQUIRES`` attributes prevent race conditions, by
+deadlock. The `GUARDED_BY` and `REQUIRES` attributes prevent race conditions, by
ensuring that a capability is held before reading or writing to guarded data,
-and the ``EXCLUDES`` attribute prevents deadlock, by making sure that a mutex is
+and the `EXCLUDES` attribute prevents deadlock, by making sure that a mutex is
*not* held.
-However, ``EXCLUDES`` is an optional attribute, and does not provide the same
-safety guarantee as ``REQUIRES``. In particular:
-
- * A function which acquires a capability does not have to exclude it.
- * A function which calls a function that excludes a capability does not
- have to transitively exclude that capability.
-
-As a result, ``EXCLUDES`` can easily produce false negatives:
+However, `EXCLUDES` is an optional attribute, and does not provide the same
+safety guarantee as `REQUIRES`. In particular:
-.. code-block:: c++
+> - A function which acquires a capability does not have to exclude it.
+> - A function which calls a function that excludes a capability does not
+> have to transitively exclude that capability.
- class Foo {
- Mutex mu;
+As a result, `EXCLUDES` can easily produce false negatives:
- void foo() {
- mu.Lock();
- bar(); // No warning.
- baz(); // No warning.
- mu.Unlock();
- }
+```c++
+class Foo {
+ Mutex mu;
- void bar() { // No warning. (Should have EXCLUDES(mu)).
- mu.Lock();
- // ...
- mu.Unlock();
- }
+ void foo() {
+ mu.Lock();
+ bar(); // No warning.
+ baz(); // No warning.
+ mu.Unlock();
+ }
- void baz() {
- bif(); // No warning. (Should have EXCLUDES(mu)).
- }
+ void bar() { // No warning. (Should have EXCLUDES(mu)).
+ mu.Lock();
+ // ...
+ mu.Unlock();
+ }
- void bif() EXCLUDES(mu);
- };
+ void baz() {
+ bif(); // No warning. (Should have EXCLUDES(mu)).
+ }
+ void bif() EXCLUDES(mu);
+};
+```
-Negative requirements are an alternative to ``EXCLUDES`` that provide
-a stronger safety guarantee. A negative requirement uses the ``REQUIRES``
-attribute, in conjunction with the ``!`` operator, to indicate that a capability
+Negative requirements are an alternative to `EXCLUDES` that provide
+a stronger safety guarantee. A negative requirement uses the `REQUIRES`
+attribute, in conjunction with the `!` operator, to indicate that a capability
should *not* be held.
-For example, using ``REQUIRES(!mu)`` instead of ``EXCLUDES(mu)`` will produce
+For example, using `REQUIRES(!mu)` instead of `EXCLUDES(mu)` will produce
the appropriate warnings:
-.. code-block:: c++
-
- class FooNeg {
- Mutex mu;
-
- void foo() REQUIRES(!mu) { // foo() now requires !mu.
- mu.Lock();
- bar();
- baz();
- mu.Unlock();
- }
+```c++
+class FooNeg {
+ Mutex mu;
- void bar() {
- mu.Lock(); // WARNING! Missing REQUIRES(!mu).
- // ...
- mu.Unlock();
- }
+ void foo() REQUIRES(!mu) { // foo() now requires !mu.
+ mu.Lock();
+ bar();
+ baz();
+ mu.Unlock();
+ }
- void baz() {
- bif(); // WARNING! Missing REQUIRES(!mu).
- }
+ void bar() {
+ mu.Lock(); // WARNING! Missing REQUIRES(!mu).
+ // ...
+ mu.Unlock();
+ }
- void bif() REQUIRES(!mu);
- };
+ void baz() {
+ bif(); // WARNING! Missing REQUIRES(!mu).
+ }
+ void bif() REQUIRES(!mu);
+};
+```
Negative requirements are an experimental feature which is off by default,
-because it will produce many warnings in existing code. It can be enabled
-by passing ``-Wthread-safety-negative``.
-
+because it will produce many warnings in existing code. It can be enabled
+by passing `-Wthread-safety-negative`.
-.. _faq:
+(faq)=
-Frequently Asked Questions
-==========================
+## Frequently Asked Questions
-(Q) Should I put attributes in the header file, or in the .cc/.cpp/.cxx file?
+17. Should I put attributes in the header file, or in the .cc/.cpp/.cxx file?
(A) Attributes are part of the formal interface of a function, and should
always go in the header, where they are visible to anything that includes
-the header. Attributes in the ``.cpp`` file are not visible outside of the
+the header. Attributes in the `.cpp` file are not visible outside of the
immediate translation unit, which leads to false negatives and false positives.
+17. "*Mutex is not locked on every path through here?*" What does that mean?
-(Q) "*Mutex is not locked on every path through here?*" What does that mean?
+1) See {ref}`conditional_locks`, below.
-(A) See :ref:`conditional_locks`, below.
+(limitations)=
+## Known Limitations
-.. _limitations:
-
-Known Limitations
-=================
-
-Lexical scope
--------------
+### Lexical scope
Thread safety attributes contain ordinary C++ expressions, and thus follow
-ordinary C++ scoping rules. In particular, this means that mutexes and other
+ordinary C++ scoping rules. In particular, this means that mutexes and other
capabilities must be declared before they can be used in an attribute.
Use-before-declaration is okay within a single class, because attributes are
parsed at the same time as method bodies. (C++ delays parsing of method bodies
-until the end of the class.) However, use-before-declaration is not allowed
+until the end of the class.) However, use-before-declaration is not allowed
between classes, as illustrated below.
-.. code-block:: c++
-
- class Foo;
+```c++
+class Foo;
- class Bar {
- void bar(Foo* f) REQUIRES(f->mu); // Error: mu undeclared.
- };
-
- class Foo {
- Mutex mu;
- };
+class Bar {
+ void bar(Foo* f) REQUIRES(f->mu); // Error: mu undeclared.
+};
+class Foo {
+ Mutex mu;
+};
+```
-Private Mutexes
----------------
+### Private Mutexes
Good software engineering practice dictates that mutexes should be private
members because the locking mechanism used by a thread-safe class is part of
-its internal implementation. However, private mutexes can sometimes leak into
+its internal implementation. However, private mutexes can sometimes leak into
the public interface of a class.
-Thread safety attributes follow normal C++ access restrictions, so if ``mu``
-is a private member of ``c``, then it is an error to write ``c.mu`` in an
+Thread safety attributes follow normal C++ access restrictions, so if `mu`
+is a private member of `c`, then it is an error to write `c.mu` in an
attribute.
-One workaround is to (ab)use the ``RETURN_CAPABILITY`` attribute to provide a
+One workaround is to (ab)use the `RETURN_CAPABILITY` attribute to provide a
public *name* for a private mutex, without actually exposing the underlying
-mutex. For example:
-
-.. code-block:: c++
+mutex. For example:
- class MyClass {
- private:
- Mutex mu;
+```c++
+class MyClass {
+private:
+ Mutex mu;
- public:
- // For thread safety analysis only. Does not need to be defined.
- Mutex* getMu() RETURN_CAPABILITY(mu);
+public:
+ // For thread safety analysis only. Does not need to be defined.
+ Mutex* getMu() RETURN_CAPABILITY(mu);
- void doSomething() REQUIRES(mu);
- };
+ void doSomething() REQUIRES(mu);
+};
- void doSomethingTwice(MyClass& c) REQUIRES(c.getMu()) {
- // The analysis thinks that c.getMu() == c.mu
- c.doSomething();
- c.doSomething();
- }
+void doSomethingTwice(MyClass& c) REQUIRES(c.getMu()) {
+ // The analysis thinks that c.getMu() == c.mu
+ c.doSomething();
+ c.doSomething();
+}
+```
-In the above example, ``doSomethingTwice()`` is an external routine that
-requires ``c.mu`` to be locked, which cannot be declared directly because ``mu``
-is private. This pattern is discouraged because it
+In the above example, `doSomethingTwice()` is an external routine that
+requires `c.mu` to be locked, which cannot be declared directly because `mu`
+is private. This pattern is discouraged because it
violates encapsulation, but it is sometimes necessary, especially when adding
-annotations to an existing code base. The workaround is to define ``getMu()``
+annotations to an existing code base. The workaround is to define `getMu()`
as a fake getter method, which is provided only for the benefit of thread
safety analysis.
+(conditional-locks)=
-.. _conditional_locks:
-
-No conditionally held locks.
-----------------------------
+### No conditionally held locks.
The analysis must be able to determine whether a lock is held, or not held, at
-every program point. Thus, sections of code where a lock *might be held* will
-generate spurious warnings (false positives). For example:
-
-.. code-block:: c++
-
- void foo() {
- bool b = needsToLock();
- if (b) mu.Lock();
- ... // Warning! Mutex 'mu' is not held on every path through here.
- if (b) mu.Unlock();
- }
+every program point. Thus, sections of code where a lock *might be held* will
+generate spurious warnings (false positives). For example:
+```c++
+void foo() {
+ bool b = needsToLock();
+ if (b) mu.Lock();
+ ... // Warning! Mutex 'mu' is not held on every path through here.
+ if (b) mu.Unlock();
+}
+```
-No checking inside constructors and destructors.
-------------------------------------------------
+### No checking inside constructors and destructors.
The analysis currently does not do any checking inside constructors or
-destructors. In other words, every constructor and destructor is treated as
-if it was annotated with ``NO_THREAD_SAFETY_ANALYSIS``.
+destructors. In other words, every constructor and destructor is treated as
+if it was annotated with `NO_THREAD_SAFETY_ANALYSIS`.
The reason for this is that during initialization, only one thread typically
has access to the object which is being initialized, and it is thus safe (and
common practice) to initialize guarded members without acquiring any locks.
@@ -814,369 +759,362 @@ The same is true of destructors.
Ideally, the analysis would allow initialization of guarded members inside the
object being initialized or destroyed, while still enforcing the usual access
-restrictions on everything else. However, this is difficult to enforce in
+restrictions on everything else. However, this is difficult to enforce in
practice, because in complex pointer-based data structures, it is hard to
determine what data is owned by the enclosing object.
-No inlining.
-------------
+### No inlining.
Thread safety analysis is strictly intra-procedural, just like ordinary type
-checking. It relies only on the declared attributes of a function, and will
-not attempt to inline any method calls. As a result, code such as the
+checking. It relies only on the declared attributes of a function, and will
+not attempt to inline any method calls. As a result, code such as the
following will not work:
-.. code-block:: c++
-
- template<class T>
- class AutoCleanup {
- T* object;
- void (T::*mp)();
-
- public:
- AutoCleanup(T* obj, void (T::*imp)()) : object(obj), mp(imp) { }
- ~AutoCleanup() { (object->*mp)(); }
- };
-
- Mutex mu;
- void foo() {
- mu.Lock();
- AutoCleanup<Mutex>(&mu, &Mutex::Unlock);
- // ...
- } // Warning, mu is not unlocked.
-
-In this case, the destructor of ``Autocleanup`` calls ``mu.Unlock()``, so
-the warning is bogus. However,
+```c++
+template<class T>
+class AutoCleanup {
+ T* object;
+ void (T::*mp)();
+
+public:
+ AutoCleanup(T* obj, void (T::*imp)()) : object(obj), mp(imp) { }
+ ~AutoCleanup() { (object->*mp)(); }
+};
+
+Mutex mu;
+void foo() {
+ mu.Lock();
+ AutoCleanup<Mutex>(&mu, &Mutex::Unlock);
+ // ...
+} // Warning, mu is not unlocked.
+```
+
+In this case, the destructor of `Autocleanup` calls `mu.Unlock()`, so
+the warning is bogus. However,
thread safety analysis cannot see the unlock, because it does not attempt to
-inline the destructor. Moreover, there is no way to annotate the destructor,
+inline the destructor. Moreover, there is no way to annotate the destructor,
because the destructor is calling a function that is not statically known.
This pattern is simply not supported.
+### No alias analysis.
-No alias analysis.
-------------------
-
-The analysis currently does not track pointer aliases. Thus, there can be
+The analysis currently does not track pointer aliases. Thus, there can be
false positives if two pointers both point to the same mutex.
+```c++
+class MutexUnlocker {
+ Mutex* mu;
-.. code-block:: c++
-
- class MutexUnlocker {
- Mutex* mu;
-
- public:
- MutexUnlocker(Mutex* m) RELEASE(m) : mu(m) { mu->Unlock(); }
- ~MutexUnlocker() ACQUIRE(mu) { mu->Lock(); }
- };
+public:
+ MutexUnlocker(Mutex* m) RELEASE(m) : mu(m) { mu->Unlock(); }
+ ~MutexUnlocker() ACQUIRE(mu) { mu->Lock(); }
+};
- Mutex mutex;
- void test() REQUIRES(mutex) {
- {
- MutexUnlocker munl(&mutex); // unlocks mutex
- doSomeIO();
- } // Warning: locks munl.mu
- }
+Mutex mutex;
+void test() REQUIRES(mutex) {
+ {
+ MutexUnlocker munl(&mutex); // unlocks mutex
+ doSomeIO();
+ } // Warning: locks munl.mu
+}
+```
The MutexUnlocker class is intended to be the dual of the MutexLocker class,
-defined in :ref:`mutexheader`. However, it doesn't work because the analysis
-doesn't know that munl.mu == mutex. The SCOPED_CAPABILITY attribute handles
+defined in {ref}`mutexheader`. However, it doesn't work because the analysis
+doesn't know that munl.mu == mutex. The SCOPED_CAPABILITY attribute handles
aliasing for MutexLocker, but does so only for that particular pattern.
+(mutexheader)=
-.. _mutexheader:
-
-mutex.h
-=======
+## mutex.h
Thread safety analysis can be used with any threading library, but it does
require that the threading API be wrapped in classes and methods which have the
-appropriate annotations. The following code provides ``mutex.h`` as an example;
+appropriate annotations. The following code provides `mutex.h` as an example;
these methods should be filled in to call the appropriate underlying
implementation.
+```c++
+#ifndef THREAD_SAFETY_ANALYSIS_MUTEX_H
+#define THREAD_SAFETY_ANALYSIS_MUTEX_H
+
+// Enable thread safety attributes only with clang.
+// The attributes can be safely erased when compiling with other compilers.
+#if defined(__clang__) && (!defined(SWIG))
+#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
+#else
+#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
+#endif
+
+#define CAPABILITY(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
+
+#define REENTRANT_CAPABILITY \
+ THREAD_ANNOTATION_ATTRIBUTE__(reentrant_capability)
+
+#define SCOPED_CAPABILITY \
+ THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
+
+#define GUARDED_BY(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(__VA_ARGS__))
+
+#define PT_GUARDED_BY(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(__VA_ARGS__))
+
+#define ACQUIRED_BEFORE(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
+
+#define ACQUIRED_AFTER(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
+
+#define REQUIRES(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))
+
+#define REQUIRES_SHARED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__))
+
+#define ACQUIRE(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))
+
+#define ACQUIRE_SHARED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__))
+
+#define RELEASE(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))
+
+#define RELEASE_SHARED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__))
+
+#define RELEASE_GENERIC(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(release_generic_capability(__VA_ARGS__))
+
+#define TRY_ACQUIRE(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))
+
+#define TRY_ACQUIRE_SHARED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
+
+#define EXCLUDES(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
+
+#define ASSERT_CAPABILITY(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
+
+#define ASSERT_SHARED_CAPABILITY(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
+
+#define RETURN_CAPABILITY(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
+
+#define NO_THREAD_SAFETY_ANALYSIS \
+ THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
-.. code-block:: c++
+// Defines an annotated interface for mutexes.
+// These methods can be implemented to use any internal mutex implementation.
+class CAPABILITY("mutex") Mutex {
+public:
+ // Acquire/lock this mutex exclusively. Only one thread can have exclusive
+ // access at any one time. Write operations to guarded data require an
+ // exclusive lock.
+ void Lock() ACQUIRE();
- #ifndef THREAD_SAFETY_ANALYSIS_MUTEX_H
- #define THREAD_SAFETY_ANALYSIS_MUTEX_H
+ // Acquire/lock this mutex for read operations, which require only a shared
+ // lock. This assumes a multiple-reader, single writer semantics. Multiple
+ // threads may acquire the mutex simultaneously as readers, but a writer
+ // must wait for all of them to release the mutex before it can acquire it
+ // exclusively.
+ void ReaderLock() ACQUIRE_SHARED();
- // Enable thread safety attributes only with clang.
- // The attributes can be safely erased when compiling with other compilers.
- #if defined(__clang__) && (!defined(SWIG))
- #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
- #else
- #define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
- #endif
+ // Release/unlock an exclusive mutex.
+ void Unlock() RELEASE();
- #define CAPABILITY(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
+ // Release/unlock a shared mutex.
+ void ReaderUnlock() RELEASE_SHARED();
- #define REENTRANT_CAPABILITY \
- THREAD_ANNOTATION_ATTRIBUTE__(reentrant_capability)
+ // Generic unlock, can unlock exclusive and shared mutexes.
+ void GenericUnlock() RELEASE_GENERIC();
- #define SCOPED_CAPABILITY \
- THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
+ // Try to acquire the mutex. Returns true on success, and false on failure.
+ bool TryLock() TRY_ACQUIRE(true);
- #define GUARDED_BY(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(__VA_ARGS__))
+ // Try to acquire the mutex for read operations.
+ bool ReaderTryLock() TRY_ACQUIRE_SHARED(true);
- #define PT_GUARDED_BY(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(__VA_ARGS__))
+ // Assert that this mutex is currently held by the calling thread.
+ void AssertHeld() ASSERT_CAPABILITY(this);
- #define ACQUIRED_BEFORE(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
+ // Assert that is mutex is currently held for read operations.
+ void AssertReaderHeld() ASSERT_SHARED_CAPABILITY(this);
- #define ACQUIRED_AFTER(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
+ // For negative capabilities.
+ const Mutex& operator!() const { return *this; }
+};
- #define REQUIRES(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))
+// Tag types for selecting a constructor.
+struct adopt_lock_t {} inline constexpr adopt_lock = {};
+struct defer_lock_t {} inline constexpr defer_lock = {};
+struct shared_lock_t {} inline constexpr shared_lock = {};
- #define REQUIRES_SHARED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__))
+// MutexLocker is an RAII class that acquires a mutex in its constructor, and
+// releases it in its destructor.
+class SCOPED_CAPABILITY MutexLocker {
+private:
+ Mutex* mut;
+ bool locked;
- #define ACQUIRE(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))
+public:
+ // Acquire mu, implicitly acquire *this and associate it with mu.
+ MutexLocker(Mutex *mu) ACQUIRE(mu) : mut(mu), locked(true) {
+ mu->Lock();
+ }
+
+ // Assume mu is held, implicitly acquire *this and associate it with mu.
+ MutexLocker(Mutex *mu, adopt_lock_t) REQUIRES(mu) : mut(mu), locked(true) {}
+
+ // Acquire mu in shared mode, implicitly acquire *this and associate it with mu.
+ MutexLocker(Mutex *mu, shared_lock_t) ACQUIRE_SHARED(mu) : mut(mu), locked(true) {
+ mu->ReaderLock();
+ }
+
+ // Assume mu is held in shared mode, implicitly acquire *this and associate it with mu.
+ MutexLocker(Mutex *mu, adopt_lock_t, shared_lock_t) REQUIRES_SHARED(mu)
+ : mut(mu), locked(true) {}
+
+ // Assume mu is not held, implicitly acquire *this and associate it with mu.
+ MutexLocker(Mutex *mu, defer_lock_t) EXCLUDES(mu) : mut(mu), locked(false) {}
+
+ // Same as constructors, but without tag types. (Requires C++17 copy elision.)
+ static MutexLocker Lock(Mutex *mu) ACQUIRE(mu) {
+ return MutexLocker(mu);
+ }
+
+ static MutexLocker Adopt(Mutex *mu) REQUIRES(mu) {
+ return MutexLocker(mu, adopt_lock);
+ }
+
+ static MutexLocker ReaderLock(Mutex *mu) ACQUIRE_SHARED(mu) {
+ return MutexLocker(mu, shared_lock);
+ }
- #define ACQUIRE_SHARED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__))
+ static MutexLocker AdoptReaderLock(Mutex *mu) REQUIRES_SHARED(mu) {
+ return MutexLocker(mu, adopt_lock, shared_lock);
+ }
+
+ static MutexLocker DeferLock(Mutex *mu) EXCLUDES(mu) {
+ return MutexLocker(mu, defer_lock);
+ }
+
+ // Release *this and all associated mutexes, if they are still held.
+ // There is no warning if the scope was already unlocked before.
+ ~MutexLocker() RELEASE() {
+ if (locked)
+ mut->GenericUnlock();
+ }
+
+ // Acquire all associated mutexes exclusively.
+ void Lock() ACQUIRE() {
+ mut->Lock();
+ locked = true;
+ }
- #define RELEASE(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))
+ // Try to acquire all associated mutexes exclusively.
+ bool TryLock() TRY_ACQUIRE(true) {
+ return locked = mut->TryLock();
+ }
- #define RELEASE_SHARED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__))
+ // Acquire all associated mutexes in shared mode.
+ void ReaderLock() ACQUIRE_SHARED() {
+ mut->ReaderLock();
+ locked = true;
+ }
- #define RELEASE_GENERIC(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(release_generic_capability(__VA_ARGS__))
+ // Try to acquire all associated mutexes in shared mode.
+ bool ReaderTryLock() TRY_ACQUIRE_SHARED(true) {
+ return locked = mut->ReaderTryLock();
+ }
- #define TRY_ACQUIRE(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))
+ // Release all associated mutexes. Warn on double unlock.
+ void Unlock() RELEASE() {
+ mut->Unlock();
+ locked = false;
+ }
- #define TRY_ACQUIRE_SHARED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
+ // Release all associated mutexes. Warn on double unlock.
+ void ReaderUnlock() RELEASE() {
+ mut->ReaderUnlock();
+ locked = false;
+ }
+};
- #define EXCLUDES(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
- #define ASSERT_CAPABILITY(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
+#ifdef USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES
+// The original version of thread safety analysis the following attribute
+// definitions. These use a lock-based terminology. They are still in use
+// by existing thread safety code, and will continue to be supported.
- #define ASSERT_SHARED_CAPABILITY(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
+// Deprecated.
+#define PT_GUARDED_VAR \
+ THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_var)
- #define RETURN_CAPABILITY(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
+// Deprecated.
+#define GUARDED_VAR \
+ THREAD_ANNOTATION_ATTRIBUTE__(guarded_var)
- #define NO_THREAD_SAFETY_ANALYSIS \
- THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
+// Replaced by REQUIRES
+#define EXCLUSIVE_LOCKS_REQUIRED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
+// Replaced by REQUIRES_SHARED
+#define SHARED_LOCKS_REQUIRED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
- // Defines an annotated interface for mutexes.
- // These methods can be implemented to use any internal mutex implementation.
- class CAPABILITY("mutex") Mutex {
- public:
- // Acquire/lock this mutex exclusively. Only one thread can have exclusive
- // access at any one time. Write operations to guarded data require an
- // exclusive lock.
- void Lock() ACQUIRE();
+// Replaced by CAPABILITY
+#define LOCKABLE \
+ THREAD_ANNOTATION_ATTRIBUTE__(lockable)
- // Acquire/lock this mutex for read operations, which require only a shared
- // lock. This assumes a multiple-reader, single writer semantics. Multiple
- // threads may acquire the mutex simultaneously as readers, but a writer
- // must wait for all of them to release the mutex before it can acquire it
- // exclusively.
- void ReaderLock() ACQUIRE_SHARED();
+// Replaced by SCOPED_CAPABILITY
+#define SCOPED_LOCKABLE \
+ THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
- // Release/unlock an exclusive mutex.
- void Unlock() RELEASE();
+// Replaced by ACQUIRE
+#define EXCLUSIVE_LOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
- // Release/unlock a shared mutex.
- void ReaderUnlock() RELEASE_SHARED();
+// Replaced by ACQUIRE_SHARED
+#define SHARED_LOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
- // Generic unlock, can unlock exclusive and shared mutexes.
- void GenericUnlock() RELEASE_GENERIC();
+// Replaced by RELEASE and RELEASE_SHARED
+#define UNLOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
- // Try to acquire the mutex. Returns true on success, and false on failure.
- bool TryLock() TRY_ACQUIRE(true);
+// Replaced by TRY_ACQUIRE
+#define EXCLUSIVE_TRYLOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
- // Try to acquire the mutex for read operations.
- bool ReaderTryLock() TRY_ACQUIRE_SHARED(true);
+// Replaced by TRY_ACQUIRE_SHARED
+#define SHARED_TRYLOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
- // Assert that this mutex is currently held by the calling thread.
- void AssertHeld() ASSERT_CAPABILITY(this);
+// Replaced by ASSERT_CAPABILITY
+#define ASSERT_EXCLUSIVE_LOCK(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))
- // Assert that is mutex is currently held for read operations.
- void AssertReaderHeld() ASSERT_SHARED_CAPABILITY(this);
+// Replaced by ASSERT_SHARED_CAPABILITY
+#define ASSERT_SHARED_LOCK(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))
- // For negative capabilities.
- const Mutex& operator!() const { return *this; }
- };
+// Replaced by EXCLUDE_CAPABILITY.
+#define LOCKS_EXCLUDED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
- // Tag types for selecting a constructor.
- struct adopt_lock_t {} inline constexpr adopt_lock = {};
- struct defer_lock_t {} inline constexpr defer_lock = {};
- struct shared_lock_t {} inline constexpr shared_lock = {};
+// Replaced by RETURN_CAPABILITY
+#define LOCK_RETURNED(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
- // MutexLocker is an RAII class that acquires a mutex in its constructor, and
- // releases it in its destructor.
- class SCOPED_CAPABILITY MutexLocker {
- private:
- Mutex* mut;
- bool locked;
+#endif // USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES
- public:
- // Acquire mu, implicitly acquire *this and associate it with mu.
- MutexLocker(Mutex *mu) ACQUIRE(mu) : mut(mu), locked(true) {
- mu->Lock();
- }
+#endif // THREAD_SAFETY_ANALYSIS_MUTEX_H
+```
- // Assume mu is held, implicitly acquire *this and associate it with mu.
- MutexLocker(Mutex *mu, adopt_lock_t) REQUIRES(mu) : mut(mu), locked(true) {}
-
- // Acquire mu in shared mode, implicitly acquire *this and associate it with mu.
- MutexLocker(Mutex *mu, shared_lock_t) ACQUIRE_SHARED(mu) : mut(mu), locked(true) {
- mu->ReaderLock();
- }
-
- // Assume mu is held in shared mode, implicitly acquire *this and associate it with mu.
- MutexLocker(Mutex *mu, adopt_lock_t, shared_lock_t) REQUIRES_SHARED(mu)
- : mut(mu), locked(true) {}
-
- // Assume mu is not held, implicitly acquire *this and associate it with mu.
- MutexLocker(Mutex *mu, defer_lock_t) EXCLUDES(mu) : mut(mu), locked(false) {}
-
- // Same as constructors, but without tag types. (Requires C++17 copy elision.)
- static MutexLocker Lock(Mutex *mu) ACQUIRE(mu) {
- return MutexLocker(mu);
- }
-
- static MutexLocker Adopt(Mutex *mu) REQUIRES(mu) {
- return MutexLocker(mu, adopt_lock);
- }
-
- static MutexLocker ReaderLock(Mutex *mu) ACQUIRE_SHARED(mu) {
- return MutexLocker(mu, shared_lock);
- }
-
- static MutexLocker AdoptReaderLock(Mutex *mu) REQUIRES_SHARED(mu) {
- return MutexLocker(mu, adopt_lock, shared_lock);
- }
-
- static MutexLocker DeferLock(Mutex *mu) EXCLUDES(mu) {
- return MutexLocker(mu, defer_lock);
- }
-
- // Release *this and all associated mutexes, if they are still held.
- // There is no warning if the scope was already unlocked before.
- ~MutexLocker() RELEASE() {
- if (locked)
- mut->GenericUnlock();
- }
-
- // Acquire all associated mutexes exclusively.
- void Lock() ACQUIRE() {
- mut->Lock();
- locked = true;
- }
-
- // Try to acquire all associated mutexes exclusively.
- bool TryLock() TRY_ACQUIRE(true) {
- return locked = mut->TryLock();
- }
-
- // Acquire all associated mutexes in shared mode.
- void ReaderLock() ACQUIRE_SHARED() {
- mut->ReaderLock();
- locked = true;
- }
-
- // Try to acquire all associated mutexes in shared mode.
- bool ReaderTryLock() TRY_ACQUIRE_SHARED(true) {
- return locked = mut->ReaderTryLock();
- }
-
- // Release all associated mutexes. Warn on double unlock.
- void Unlock() RELEASE() {
- mut->Unlock();
- locked = false;
- }
-
- // Release all associated mutexes. Warn on double unlock.
- void ReaderUnlock() RELEASE() {
- mut->ReaderUnlock();
- locked = false;
- }
- };
-
-
- #ifdef USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES
- // The original version of thread safety analysis the following attribute
- // definitions. These use a lock-based terminology. They are still in use
- // by existing thread safety code, and will continue to be supported.
-
- // Deprecated.
- #define PT_GUARDED_VAR \
- THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_var)
-
- // Deprecated.
- #define GUARDED_VAR \
- THREAD_ANNOTATION_ATTRIBUTE__(guarded_var)
-
- // Replaced by REQUIRES
- #define EXCLUSIVE_LOCKS_REQUIRED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
-
- // Replaced by REQUIRES_SHARED
- #define SHARED_LOCKS_REQUIRED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
-
- // Replaced by CAPABILITY
- #define LOCKABLE \
- THREAD_ANNOTATION_ATTRIBUTE__(lockable)
-
- // Replaced by SCOPED_CAPABILITY
- #define SCOPED_LOCKABLE \
- THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
-
- // Replaced by ACQUIRE
- #define EXCLUSIVE_LOCK_FUNCTION(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
-
- // Replaced by ACQUIRE_SHARED
- #define SHARED_LOCK_FUNCTION(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
-
- // Replaced by RELEASE and RELEASE_SHARED
- #define UNLOCK_FUNCTION(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
-
- // Replaced by TRY_ACQUIRE
- #define EXCLUSIVE_TRYLOCK_FUNCTION(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
-
- // Replaced by TRY_ACQUIRE_SHARED
- #define SHARED_TRYLOCK_FUNCTION(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
-
- // Replaced by ASSERT_CAPABILITY
- #define ASSERT_EXCLUSIVE_LOCK(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))
-
- // Replaced by ASSERT_SHARED_CAPABILITY
- #define ASSERT_SHARED_LOCK(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))
-
- // Replaced by EXCLUDE_CAPABILITY.
- #define LOCKS_EXCLUDED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
-
- // Replaced by RETURN_CAPABILITY
- #define LOCK_RETURNED(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
-
- #endif // USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES
-
- #endif // THREAD_SAFETY_ANALYSIS_MUTEX_H
diff --git a/clang/docs/ThreadSanitizer.md b/clang/docs/ThreadSanitizer.md
index 45d902d2a7d59..44b7b20bfe538 100644
--- a/clang/docs/ThreadSanitizer.md
+++ b/clang/docs/ThreadSanitizer.md
@@ -1,135 +1,125 @@
-ThreadSanitizer
-===============
+# ThreadSanitizer
-Introduction
-------------
+## Introduction
-ThreadSanitizer is a tool that detects data races. It consists of a compiler
-instrumentation module and a run-time library. Typical slowdown introduced by
-ThreadSanitizer is about **5x-15x**. Typical memory overhead introduced by
+ThreadSanitizer is a tool that detects data races. It consists of a compiler
+instrumentation module and a run-time library. Typical slowdown introduced by
+ThreadSanitizer is about **5x-15x**. Typical memory overhead introduced by
ThreadSanitizer is about **5x-10x**.
-How to build
-------------
+## How to build
-Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>`_.
+Build LLVM/Clang with [CMake](https://llvm.org/docs/CMake.html).
-Supported Platforms
--------------------
+## Supported Platforms
ThreadSanitizer is supported on the following OS:
-* Android aarch64, x86_64
-* Darwin arm64, x86_64
-* FreeBSD
-* Linux aarch64, x86_64, powerpc64, powerpc64le
-* NetBSD
+- Android aarch64, x86_64
+- Darwin arm64, x86_64
+- FreeBSD
+- Linux aarch64, x86_64, powerpc64, powerpc64le
+- NetBSD
Support for other 64-bit architectures is possible, contributions are welcome.
Support for 32-bit platforms is problematic and is not planned.
-Usage
------
+## Usage
-Simply compile and link your program with ``-fsanitize=thread``. To get a
-reasonable performance add ``-O1`` or higher. Use ``-g`` to get file names
+Simply compile and link your program with `-fsanitize=thread`. To get a
+reasonable performance add `-O1` or higher. Use `-g` to get file names
and line numbers in the warning messages.
Example:
-.. code-block:: console
-
- % cat projects/compiler-rt/lib/tsan/lit_tests/tiny_race.c
- #include <pthread.h>
- int Global;
- void *Thread1(void *x) {
- Global = 42;
- return x;
- }
- int main() {
- pthread_t t;
- pthread_create(&t, NULL, Thread1, NULL);
- Global = 43;
- pthread_join(t, NULL);
- return Global;
- }
-
- $ clang -fsanitize=thread -g -O1 tiny_race.c
+```console
+% cat projects/compiler-rt/lib/tsan/lit_tests/tiny_race.c
+#include <pthread.h>
+int Global;
+void *Thread1(void *x) {
+ Global = 42;
+ return x;
+}
+int main() {
+ pthread_t t;
+ pthread_create(&t, NULL, Thread1, NULL);
+ Global = 43;
+ pthread_join(t, NULL);
+ return Global;
+}
+
+$ clang -fsanitize=thread -g -O1 tiny_race.c
+```
If a bug is detected, the program will print an error message to stderr.
Currently, ThreadSanitizer symbolizes its output using an external
-``addr2line`` process (this will be fixed in future).
+`addr2line` process (this will be fixed in future).
-.. code-block:: bash
+```bash
+% ./a.out
+WARNING: ThreadSanitizer: data race (pid=19219)
+ Write of size 4 at 0x7fcf47b21bc0 by thread T1:
+ #0 Thread1 tiny_race.c:4 (exe+0x00000000a360)
- % ./a.out
- WARNING: ThreadSanitizer: data race (pid=19219)
- Write of size 4 at 0x7fcf47b21bc0 by thread T1:
- #0 Thread1 tiny_race.c:4 (exe+0x00000000a360)
+ Previous write of size 4 at 0x7fcf47b21bc0 by main thread:
+ #0 main tiny_race.c:10 (exe+0x00000000a3b4)
- Previous write of size 4 at 0x7fcf47b21bc0 by main thread:
- #0 main tiny_race.c:10 (exe+0x00000000a3b4)
+ Thread T1 (running) created at:
+ #0 pthread_create tsan_interceptors.cc:705 (exe+0x00000000c790)
+ #1 main tiny_race.c:9 (exe+0x00000000a3a4)
+```
- Thread T1 (running) created at:
- #0 pthread_create tsan_interceptors.cc:705 (exe+0x00000000c790)
- #1 main tiny_race.c:9 (exe+0x00000000a3a4)
-
-``__has_feature(thread_sanitizer)``
-------------------------------------
+## `__has_feature(thread_sanitizer)`
In some cases one may need to execute different code depending on whether
ThreadSanitizer is enabled.
-:ref:`\_\_has\_feature <langext-__has_feature-__has_extension>` can be used for
+{ref}`\_\_has\_feature <langext-__has_feature-__has_extension>` can be used for
this purpose.
-.. code-block:: c
-
- #if defined(__has_feature)
- # if __has_feature(thread_sanitizer)
- // code that builds only under ThreadSanitizer
- # endif
- #endif
+```c
+#if defined(__has_feature)
+# if __has_feature(thread_sanitizer)
+// code that builds only under ThreadSanitizer
+# endif
+#endif
+```
-``__attribute__((no_sanitize("thread")))``
------------------------------------------------
+## `__attribute__((no_sanitize("thread")))`
-Some code should not be instrumented by ThreadSanitizer. One may use the
-function attribute ``no_sanitize("thread")`` to disable instrumentation of plain
-(non-atomic) loads/stores in a particular function. ThreadSanitizer still
+Some code should not be instrumented by ThreadSanitizer. One may use the
+function attribute `no_sanitize("thread")` to disable instrumentation of plain
+(non-atomic) loads/stores in a particular function. ThreadSanitizer still
instruments such functions to avoid false positives and provide meaningful stack
-traces. This attribute may not be supported by other compilers, so we suggest
-to use it together with ``__has_feature(thread_sanitizer)``.
+traces. This attribute may not be supported by other compilers, so we suggest
+to use it together with `__has_feature(thread_sanitizer)`.
-``__attribute__((disable_sanitizer_instrumentation))``
---------------------------------------------------------
+## `__attribute__((disable_sanitizer_instrumentation))`
-The ``disable_sanitizer_instrumentation`` attribute can be applied to functions
+The `disable_sanitizer_instrumentation` attribute can be applied to functions
to prevent all kinds of instrumentation. As a result, it may introduce false
positives and incorrect stack traces. Therefore, it should be used with care,
and only if absolutely required; for example for certain code that cannot
tolerate any instrumentation and resulting side-effects. This attribute
-overrides ``no_sanitize("thread")``.
+overrides `no_sanitize("thread")`.
-Interaction of Inlining with Disabling Sanitizer Instrumentation
------------------------------------------------------------------
+## Interaction of Inlining with Disabling Sanitizer Instrumentation
-* A `no_sanitize` function will not be inlined heuristically by the compiler into a sanitized function.
-* An `always_inline` function will adopt the instrumentation status of the function it is inlined into.
-* Forcibly combining `no_sanitize` and ``__attribute__((always_inline))`` is not supported, and will often lead to unexpected results. To avoid mixing these attributes, use:
+- A `no_sanitize` function will not be inlined heuristically by the compiler into a sanitized function.
+- An `always_inline` function will adopt the instrumentation status of the function it is inlined into.
+- Forcibly combining `no_sanitize` and `__attribute__((always_inline))` is not supported, and will often lead to unexpected results. To avoid mixing these attributes, use:
-.. code-block:: c
+```c
+// Note, __has_feature test for sanitizers is deprecated, and Clang will support __SANITIZE_<sanitizer>__ similar to GCC.
+#if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__) || ... <other sanitizers>
+#define ALWAYS_INLINE_IF_UNINSTRUMENTED
+#else
+#define ALWAYS_INLINE_IF_UNINSTRUMENTED __attribute__((always_inline))
+#endif
+```
- // Note, __has_feature test for sanitizers is deprecated, and Clang will support __SANITIZE_<sanitizer>__ similar to GCC.
- #if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__) || ... <other sanitizers>
- #define ALWAYS_INLINE_IF_UNINSTRUMENTED
- #else
- #define ALWAYS_INLINE_IF_UNINSTRUMENTED __attribute__((always_inline))
- #endif
+## Explicit Sanitizer Checks with `__builtin_allow_sanitize_check`
-Explicit Sanitizer Checks with ``__builtin_allow_sanitize_check``
------------------------------------------------------------------
-
-The ``__builtin_allow_sanitize_check("thread")`` builtin can be used to
+The `__builtin_allow_sanitize_check("thread")` builtin can be used to
conditionally execute code depending on whether ThreadSanitizer checks are
enabled and permitted by the current policy (after inlining). This is
particularly useful for inserting explicit, sanitizer-specific checks around
@@ -138,80 +128,74 @@ by the sanitizer.
Example:
-.. code-block:: c
-
- void __tsan_read8(void *);
-
- inline __attribute__((always_inline))
- void my_helper(void *addr) {
- if (__builtin_allow_sanitize_check("thread"))
- __tsan_read8(addr);
- // ... actual logic, e.g. inline assembly ...
- asm volatile ("..." : : "r" (addr) : "memory");
- }
-
- void instrumented_function() {
- ...
- my_helper(&shared_data); // checks are active
- ...
- }
-
- __attribute__((no_sanitize("thread")))
- void uninstrumented_function() {
- ...
- my_helper(&shared_data); // checks are skipped
- ...
- }
-
-Ignorelist
-----------
-
-ThreadSanitizer supports ``src`` and ``fun`` entity types in
-:doc:`SanitizerSpecialCaseList`, that can be used to suppress data race reports
+```c
+void __tsan_read8(void *);
+
+inline __attribute__((always_inline))
+void my_helper(void *addr) {
+ if (__builtin_allow_sanitize_check("thread"))
+ __tsan_read8(addr);
+ // ... actual logic, e.g. inline assembly ...
+ asm volatile ("..." : : "r" (addr) : "memory");
+}
+
+void instrumented_function() {
+ ...
+ my_helper(&shared_data); // checks are active
+ ...
+}
+
+__attribute__((no_sanitize("thread")))
+void uninstrumented_function() {
+ ...
+ my_helper(&shared_data); // checks are skipped
+ ...
+}
+```
+
+## Ignorelist
+
+ThreadSanitizer supports `src` and `fun` entity types in
+{doc}`SanitizerSpecialCaseList`, that can be used to suppress data race reports
in the specified source files or functions. Unlike functions marked with
-``no_sanitize("thread")`` attribute, ignored functions are not instrumented
+`no_sanitize("thread")` attribute, ignored functions are not instrumented
at all. This can lead to false positives due to missed synchronization via
atomic operations and missed stack frames in reports.
-Limitations
------------
+## Limitations
-* ThreadSanitizer uses more real memory than a native run. At the default
+- ThreadSanitizer uses more real memory than a native run. At the default
settings the memory overhead is 5x plus 1Mb per each thread. Settings with 3x
(less accurate analysis) and 9x (more accurate analysis) overhead are also
available.
-* ThreadSanitizer maps (but does not reserve) a lot of virtual address space.
- This means that tools like ``ulimit`` may not work as usually expected.
-* Libc/libstdc++ static linking is not supported.
-* Non-position-independent executables are not supported. Therefore, the
- ``fsanitize=thread`` flag will cause Clang to act as though the ``-fPIE``
- flag had been supplied if compiling without ``-fPIC``, and as though the
- ``-pie`` flag had been supplied if linking an executable.
+- ThreadSanitizer maps (but does not reserve) a lot of virtual address space.
+ This means that tools like `ulimit` may not work as usually expected.
+- Libc/libstdc++ static linking is not supported.
+- Non-position-independent executables are not supported. Therefore, the
+ `fsanitize=thread` flag will cause Clang to act as though the `-fPIE`
+ flag had been supplied if compiling without `-fPIC`, and as though the
+ `-pie` flag had been supplied if linking an executable.
-Security Considerations
------------------------
+## Security Considerations
ThreadSanitizer is a bug detection tool and its runtime is not meant to be
linked against production executables. While it may be useful for testing,
ThreadSanitizer's runtime was not developed with security-sensitive
constraints in mind and may compromise the security of the resulting executable.
-Current Status
---------------
+## Current Status
-ThreadSanitizer is in beta stage. It is known to work on large C++ programs
-using pthreads, but we do not promise anything (yet). C++11 threading is
-supported with llvm libc++. The test suite is integrated into CMake build
-and can be run with ``make check-tsan`` command.
+ThreadSanitizer is in beta stage. It is known to work on large C++ programs
+using pthreads, but we do not promise anything (yet). C++11 threading is
+supported with llvm libc++. The test suite is integrated into CMake build
+and can be run with `make check-tsan` command.
-We are actively working on enhancing the tool --- stay tuned. Any help,
+We are actively working on enhancing the tool --- stay tuned. Any help,
especially in the form of minimized standalone tests is more than welcome.
-Adaptive Delay
---------------
+## Adaptive Delay
-Overview
-~~~~~~~~
+### Overview
Adaptive Delay is an optional ThreadSanitizer feature that injects delays at
synchronization points to explore novel thread interleavings and increase the
@@ -221,40 +205,39 @@ improving race detection.
Adaptive delay is particularly useful for:
-* Detecting races in rarely-executed thread interleavings or code paths
-* Testing parallel data structures and algorithms
+- Detecting races in rarely-executed thread interleavings or code paths
+- Testing parallel data structures and algorithms
When enabled, adaptive delay maintains a configurable time budget to balance
race exposure against performance overhead. The delays can be
- * random amount of spin cycles
- * a single yield to the OS scheduler
- * random usleep
+> - random amount of spin cycles
+> - a single yield to the OS scheduler
+> - random usleep
The strategy prioritizes high-value synchronization points:
-* Relaxed atomic operations receive cheap delays (spin cycles) with low sampling
-* Synchronizing atomic operations (acquire/release/seq_cst) receive moderate
+- Relaxed atomic operations receive cheap delays (spin cycles) with low sampling
+- Synchronizing atomic operations (acquire/release/seq_cst) receive moderate
delays with higher sampling
-* Mutex and thread lifecycle operations receive the longest delays with highest
+- Mutex and thread lifecycle operations receive the longest delays with highest
sampling
The delays focus on synchronization points with clear happens-before relationships,
as those are most likely to expose data races.
-Enabling Adaptive Delay
-~~~~~~~~~~~~~~~~~~~~~~~
+### Enabling Adaptive Delay
Adaptive delay is disabled by default. Enable it by setting the
-``enable_adaptive_delay`` flag:
-
-.. code-block:: console
+`enable_adaptive_delay` flag:
- $ TSAN_OPTIONS=enable_adaptive_delay=1 ./myapp
+```console
+$ TSAN_OPTIONS=enable_adaptive_delay=1 ./myapp
+```
-Configuration Options
-~~~~~~~~~~~~~~~~~~~~~
+### Configuration Options
+```{eval-rst}
.. list-table:: Adaptive Delay Options
:name: adaptive-delay-options-table
:header-rows: 1
@@ -305,28 +288,29 @@ Configuration Options
operations). Format: same as ``adaptive_delay_max_atomic``. Typically set
longer than atomic delays since these operations involve waking blocked threads
and may be more likely to expose races.
+```
-Examples
-~~~~~~~~
+### Examples
Enable adaptive delay with moderate aggressiveness:
-.. code-block:: console
-
- $ TSAN_OPTIONS=enable_adaptive_delay=1:adaptive_delay_aggressiveness=50 ./myapp
+```console
+$ TSAN_OPTIONS=enable_adaptive_delay=1:adaptive_delay_aggressiveness=50 ./myapp
+```
Enable aggressive delay injection:
-.. code-block:: console
-
- $ TSAN_OPTIONS=enable_adaptive_delay=1:adaptive_delay_aggressiveness=200 ./myapp
+```console
+$ TSAN_OPTIONS=enable_adaptive_delay=1:adaptive_delay_aggressiveness=200 ./myapp
+```
Increase sampling frequency for mutex operations:
-.. code-block:: console
+```console
+$ TSAN_OPTIONS=enable_adaptive_delay=1:adaptive_delay_mutex_sample_rate=5 ./myapp
+```
+
+## More Information
- $ TSAN_OPTIONS=enable_adaptive_delay=1:adaptive_delay_mutex_sample_rate=5 ./myapp
+[https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual](https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual)
-More Information
-----------------
-`<https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual>`_
diff --git a/clang/docs/Toolchain.md b/clang/docs/Toolchain.md
index d56b21d74c7e3..2c30792c6bc93 100644
--- a/clang/docs/Toolchain.md
+++ b/clang/docs/Toolchain.md
@@ -1,13 +1,11 @@
-===============================
-Assembling a Complete Toolchain
-===============================
+# Assembling a Complete Toolchain
-.. contents::
- :local:
- :depth: 2
+```{contents}
+:depth: 2
+:local: true
+```
-Introduction
-============
+## Introduction
Clang is only one component in a complete tool chain for C family
programming languages. In order to assemble a complete toolchain,
@@ -20,51 +18,45 @@ This document describes the required and optional components in a
complete toolchain, where to find them, and the supported versions
and limitations of each option.
-.. warning::
+:::{warning}
+This document currently describes Clang configurations on POSIX-like
+operating systems with the GCC-compatible `clang` driver. When
+targeting Windows with the MSVC-compatible `clang-cl` driver, some
+of the details are different.
+:::
- This document currently describes Clang configurations on POSIX-like
- operating systems with the GCC-compatible ``clang`` driver. When
- targeting Windows with the MSVC-compatible ``clang-cl`` driver, some
- of the details are different.
+## Tools
-Tools
-=====
-
-.. FIXME: Describe DWARF-related tools
+% FIXME: Describe DWARF-related tools
A complete compilation of C family programming languages typically
involves the following pipeline of tools, some of which are omitted
in some compilations:
-* **Preprocessor**: This performs the actions of the C preprocessor:
+- **Preprocessor**: This performs the actions of the C preprocessor:
expanding #includes and #defines.
- The ``-E`` flag instructs Clang to stop after this step.
-
-* **Parsing**: This parses and semantically analyzes the source language and
+ The `-E` flag instructs Clang to stop after this step.
+- **Parsing**: This parses and semantically analyzes the source language and
builds a source-level intermediate representation ("AST"), producing a
- :ref:`precompiled header (PCH) <usersmanual-precompiled-headers>`,
+ {ref}`precompiled header (PCH) <usersmanual-precompiled-headers>`,
preamble, or
- :doc:`precompiled module file (PCM) <Modules>`,
+ {doc}`precompiled module file (PCM) <Modules>`,
depending on the input.
- The ``-precompile`` flag instructs Clang to stop after this step. This is
+ The `-precompile` flag instructs Clang to stop after this step. This is
the default when the input is a header file.
-
-* **IR generation**: This converts the source-level intermediate representation
+- **IR generation**: This converts the source-level intermediate representation
into an optimizer-specific intermediate representation (IR); for Clang, this
is LLVM IR.
- The ``-emit-llvm`` flag instructs Clang to stop after this step. If combined
- with ``-S``, Clang will produce textual LLVM IR; otherwise, it will produce
+ The `-emit-llvm` flag instructs Clang to stop after this step. If combined
+ with `-S`, Clang will produce textual LLVM IR; otherwise, it will produce
LLVM IR bitcode.
-
-* **Compiler backend**: This converts the intermediate representation
+- **Compiler backend**: This converts the intermediate representation
into target-specific assembly code.
- The ``-S`` flag instructs Clang to stop after this step.
-
-* **Assembler**: This converts target-specific assembly code into
+ The `-S` flag instructs Clang to stop after this step.
+- **Assembler**: This converts target-specific assembly code into
target-specific machine code object files.
- The ``-c`` flag instructs Clang to stop after this step.
-
-* **Linker**: This combines multiple object files into a single image
+ The `-c` flag instructs Clang to stop after this step.
+- **Linker**: This combines multiple object files into a single image
(either a shared object or an executable).
Clang provides all of these pieces other than the linker. When multiple
@@ -72,85 +64,81 @@ steps are performed by the same tool, it is common for the steps to be
fused together to avoid creating intermediate files.
When given an output of one of the above steps as an input, earlier steps
-are skipped (for instance, a ``.s`` file input will be assembled and linked).
+are skipped (for instance, a `.s` file input will be assembled and linked).
-The Clang driver can be invoked with the ``-###`` flag (this argument will need
+The Clang driver can be invoked with the `-###` flag (this argument will need
to be escaped under most shells) to see which commands it would run for the
-above steps, without running them. The ``-v`` (verbose) flag will print the
+above steps, without running them. The `-v` (verbose) flag will print the
commands in addition to running them.
-Clang frontend
---------------
+### Clang frontend
-The Clang frontend (``clang -cc1``) is used to compile C family languages. The
+The Clang frontend (`clang -cc1`) is used to compile C family languages. The
command-line interface of the frontend is considered to be an implementation
detail, intentionally has no external documentation, and is subject to change
without notice.
-Language frontends for other languages
---------------------------------------
+### Language frontends for other languages
Clang can be provided with inputs written in non-C-family languages. In such
cases, an external tool will be used to compile the input. The
currently-supported languages are:
-* Ada (``-x ada``, ``.ad[bs]``)
-* Fortran (``-x f95``, ``.f``, ``.f9[05]``, ``.for``, ``.fpp``, case-insensitive)
-* Java (``-x java``)
+- Ada (`-x ada`, `.ad[bs]`)
+- Fortran (`-x f95`, `.f`, `.f9[05]`, `.for`, `.fpp`, case-insensitive)
+- Java (`-x java`)
In each case, GCC will be invoked to compile the input.
-Assembler
----------
+### Assembler
Clang can either use LLVM's integrated assembler or an external system-specific
tool (for instance, the GNU Assembler on GNU OSes) to produce machine code from
assembly.
By default, Clang uses LLVM's integrated assembler on all targets where it is
supported. If you wish to use the system assembler instead, use the
-``-fno-integrated-as`` option.
+`-fno-integrated-as` option.
-Linker
-------
+### Linker
Clang can be configured to use one of several different linkers:
-* GNU ld
-* GNU gold
-* LLVM's `lld <https://lld.llvm.org>`_
-* MSVC's link.exe
+- GNU ld
+- GNU gold
+- LLVM's [lld](https://lld.llvm.org)
+- MSVC's link.exe
Link-time optimization is natively supported by lld, and supported via
-a `linker plugin <https://llvm.org/docs/GoldPlugin.html>`_ when using gold.
+a [linker plugin](https://llvm.org/docs/GoldPlugin.html) when using gold.
The default linker varies between targets, and can be overridden via the
-``-fuse-ld=<linker name>`` flag.
+`-fuse-ld=<linker name>` flag.
-Runtime libraries
-=================
+## Runtime libraries
A number of different runtime libraries are required to provide different
layers of support for C family programs. Clang will implicitly link an
appropriate implementation of each runtime library, selected based on
-target defaults or explicitly selected by the ``--rtlib=`` and ``--stdlib=``
+target defaults or explicitly selected by the `--rtlib=` and `--stdlib=`
flags.
The set of implicitly-linked libraries depend on the language mode. As a
-consequence, you should use ``clang++`` when linking C++ programs in order
+consequence, you should use `clang++` when linking C++ programs in order
to ensure the C++ runtimes are provided.
-.. note::
+:::{note}
+There may exist other implementations for these components not described
+below. Please let us know how well those other implementations work with
+Clang so they can be added to this list!
+:::
- There may exist other implementations for these components not described
- below. Please let us know how well those other implementations work with
- Clang so they can be added to this list!
+% FIXME: Describe Objective-C runtime libraries
-.. FIXME: Describe Objective-C runtime libraries
-.. FIXME: Describe profiling runtime library
-.. FIXME: Describe cuda/openmp/opencl/... runtime libraries
+% FIXME: Describe profiling runtime library
-Compiler runtime
-----------------
+% FIXME: Describe cuda/openmp/opencl/... runtime libraries
+
+### Compiler runtime
The compiler runtime library provides definitions of functions implicitly
invoked by the compiler to support operations not natively supported by
@@ -161,130 +149,115 @@ The default runtime library is target-specific. For targets where GCC is
the dominant compiler, Clang currently defaults to using libgcc_s. On most
other targets, compiler-rt is used by default.
-compiler-rt (LLVM)
-^^^^^^^^^^^^^^^^^^
+#### compiler-rt (LLVM)
-`LLVM's compiler runtime library <https://compiler-rt.llvm.org/>`_ provides a
+[LLVM's compiler runtime library](https://compiler-rt.llvm.org/) provides a
complete set of runtime library functions containing all functions that
-Clang will implicitly call, in ``libclang_rt.builtins.<arch>.a``.
+Clang will implicitly call, in `libclang_rt.builtins.<arch>.a`.
-You can instruct Clang to use compiler-rt with the ``--rtlib=compiler-rt`` flag.
+You can instruct Clang to use compiler-rt with the `--rtlib=compiler-rt` flag.
This is not supported on every platform.
If using libc++ and/or libc++abi, you may need to configure them to use
-compiler-rt rather than libgcc_s by passing ``-DLIBCXX_USE_COMPILER_RT=YES``
-and/or ``-DLIBCXXABI_USE_COMPILER_RT=YES`` to ``cmake``. Otherwise, you
+compiler-rt rather than libgcc_s by passing `-DLIBCXX_USE_COMPILER_RT=YES`
+and/or `-DLIBCXXABI_USE_COMPILER_RT=YES` to `cmake`. Otherwise, you
may end up with both runtime libraries linked into your program (this is
typically harmless, but wasteful).
-libgcc_s (GNU)
-^^^^^^^^^^^^^^
+#### libgcc_s (GNU)
-`GCC's runtime library <https://gcc.gnu.org/onlinedocs/gccint/Libgcc.html>`_
+[GCC's runtime library](https://gcc.gnu.org/onlinedocs/gccint/Libgcc.html)
can be used in place of compiler-rt. However, it lacks several functions
that LLVM may emit references to, particularly when using Clang's
-``__builtin_*_overflow`` family of intrinsics.
+`__builtin_*_overflow` family of intrinsics.
-You can instruct Clang to use libgcc_s with the ``--rtlib=libgcc`` flag.
+You can instruct Clang to use libgcc_s with the `--rtlib=libgcc` flag.
This is not supported on every platform.
-Atomics library
----------------
+### Atomics library
If your program makes use of atomic operations and the compiler is not able
to lower them all directly to machine instructions (because there either is
no known suitable machine instruction or the operand is not known to be
-suitably aligned), a call to a runtime library ``__atomic_*`` function
+suitably aligned), a call to a runtime library `__atomic_*` function
will be generated. A runtime library containing these atomics functions is
necessary for such programs.
-compiler-rt (LLVM)
-^^^^^^^^^^^^^^^^^^
+#### compiler-rt (LLVM)
compiler-rt contains an implementation of an atomics library.
-libatomic (GNU)
-^^^^^^^^^^^^^^^
+#### libatomic (GNU)
libgcc_s does not provide an implementation of an atomics library. Instead,
-`GCC's libatomic library <https://gcc.gnu.org/wiki/Atomic/GCCMM>`_ can be
+[GCC's libatomic library](https://gcc.gnu.org/wiki/Atomic/GCCMM) can be
used to supply these when using libgcc_s.
-.. note::
-
- Clang does not currently automatically link against libatomic when using
- libgcc_s. You may need to manually add ``-latomic`` to support this
- configuration when using non-native atomic operations (if you see link errors
- referring to ``__atomic_*`` functions).
+:::{note}
+Clang does not currently automatically link against libatomic when using
+libgcc_s. You may need to manually add `-latomic` to support this
+configuration when using non-native atomic operations (if you see link errors
+referring to `__atomic_*` functions).
+:::
-Unwind library
---------------
+### Unwind library
-The unwind library provides a family of ``_Unwind_*`` functions implementing
+The unwind library provides a family of `_Unwind_*` functions implementing
the language-neutral stack unwinding portion of the Itanium C++ ABI
-(`Level I <https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#base-abi>`_).
+([Level I](https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#base-abi)).
It is a dependency of the C++ ABI library, and sometimes is a dependency
of other runtimes.
-libunwind (LLVM)
-^^^^^^^^^^^^^^^^
+#### libunwind (LLVM)
LLVM's unwinder library is part of the llvm-project git repository. To
-build it, pass ``-DLLVM_ENABLE_RUNTIMES=libunwind`` to the cmake invocation.
+build it, pass `-DLLVM_ENABLE_RUNTIMES=libunwind` to the cmake invocation.
If using libc++abi, you may need to configure it to use libunwind
-rather than libgcc_s by passing ``-DLIBCXXABI_USE_LLVM_UNWINDER=YES``
-to ``cmake``. If libc++abi is configured to use some version of
+rather than libgcc_s by passing `-DLIBCXXABI_USE_LLVM_UNWINDER=YES`
+to `cmake`. If libc++abi is configured to use some version of
libunwind, that library will be implicitly linked into binaries that
link to libc++abi.
-libgcc_s (GNU)
-^^^^^^^^^^^^^^
+#### libgcc_s (GNU)
libgcc_s has an integrated unwinder, and does not need an external unwind
library to be provided.
-libunwind (nongnu.org)
-^^^^^^^^^^^^^^^^^^^^^^
+#### libunwind (nongnu.org)
This is another implementation of the libunwind specification.
-See `libunwind (nongnu.org) <https://www.nongnu.org/libunwind>`_.
+See [libunwind (nongnu.org)](https://www.nongnu.org/libunwind).
-libunwind (PathScale)
-^^^^^^^^^^^^^^^^^^^^^
+#### libunwind (PathScale)
This is another implementation of the libunwind specification.
-See `libunwind (pathscale) <https://github.com/pathscale/libunwind>`_.
+See [libunwind (pathscale)](https://github.com/pathscale/libunwind).
-Sanitizer runtime
------------------
+### Sanitizer runtime
-The instrumentation added by Clang's sanitizers (``-fsanitize=...``) implicitly
+The instrumentation added by Clang's sanitizers (`-fsanitize=...`) implicitly
makes calls to a runtime library, in order to maintain side state about the
execution of the program and to issue diagnostic messages when a problem is
detected.
The only supported implementation of these runtimes is provided by LLVM's
compiler-rt, and the relevant portion of that library
-(``libclang_rt.<sanitizer>.<arch>.a``)
-will be implicitly linked when linking with a ``-fsanitize=...`` flag.
+(`libclang_rt.<sanitizer>.<arch>.a`)
+will be implicitly linked when linking with a `-fsanitize=...` flag.
-C standard library
-------------------
+### C standard library
Clang supports a wide variety of
-`C standard library <https://en.cppreference.com/w/c>`_
+[C standard library](https://en.cppreference.com/w/c)
implementations.
-C++ ABI library
----------------
+### C++ ABI library
The C++ ABI library provides an implementation of the library portion of
the Itanium C++ ABI, covering both the
-`support functionality in the main Itanium C++ ABI document
-<https://itanium-cxx-abi.github.io/cxx-abi/abi.html>`_ and
-`Level II of the exception handling support
-<https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#cxx-abi>`_.
+[support functionality in the main Itanium C++ ABI document](https://itanium-cxx-abi.github.io/cxx-abi/abi.html) and
+[Level II of the exception handling support](https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#cxx-abi).
References to the functions and objects in this library are implicitly
generated by Clang when compiling C++ code.
@@ -297,58 +270,53 @@ The version of the C++ ABI library used by Clang will be the one that the
chosen C++ standard library was linked against. Several implementations are
available:
-libc++abi (LLVM)
-^^^^^^^^^^^^^^^^
+#### libc++abi (LLVM)
-`libc++abi <https://libcxxabi.llvm.org/>`_ is LLVM's implementation of this
+[libc++abi](https://libcxxabi.llvm.org/) is LLVM's implementation of this
specification.
-libsupc++ (GNU)
-^^^^^^^^^^^^^^^
+#### libsupc++ (GNU)
libsupc++ is GCC's implementation of this specification. However, this
library is only used when libstdc++ is linked statically. The dynamic
library version of libstdc++ contains a copy of libsupc++.
-.. note::
-
- Clang does not currently automatically link against libsupc++ when statically
- linking libstdc++. You may need to manually add ``-lsupc++`` to support this
- configuration when using ``-static`` or ``-static-libstdc++``.
+:::{note}
+Clang does not currently automatically link against libsupc++ when statically
+linking libstdc++. You may need to manually add `-lsupc++` to support this
+configuration when using `-static` or `-static-libstdc++`.
+:::
-libcxxrt (PathScale)
-^^^^^^^^^^^^^^^^^^^^
+#### libcxxrt (PathScale)
This is another implementation of the Itanium C++ ABI specification.
-See `libcxxrt <https://github.com/pathscale/libcxxrt>`_.
+See [libcxxrt](https://github.com/pathscale/libcxxrt).
-C++ standard library
---------------------
+### C++ standard library
Clang supports use of either LLVM's libc++ or GCC's libstdc++ implementation
-of the `C++ standard library <https://en.cppreference.com/w/cpp>`_.
+of the [C++ standard library](https://en.cppreference.com/w/cpp).
-libc++ (LLVM)
-^^^^^^^^^^^^^
+#### libc++ (LLVM)
-`libc++ <https://libcxx.llvm.org/>`_ is LLVM's implementation of the C++
+[libc++](https://libcxx.llvm.org/) is LLVM's implementation of the C++
standard library, aimed at being a complete implementation of the C++
standards from C++11 onwards.
-You can instruct Clang to use libc++ with the ``-stdlib=libc++`` flag.
+You can instruct Clang to use libc++ with the `-stdlib=libc++` flag.
-libstdc++ (GNU)
-^^^^^^^^^^^^^^^
+#### libstdc++ (GNU)
-`libstdc++ <https://gcc.gnu.org/onlinedocs/libstdc++/>`_ is GCC's
+[libstdc++](https://gcc.gnu.org/onlinedocs/libstdc++/) is GCC's
implementation of the C++ standard library. Clang supports libstdc++
4.8.3 (released 2014-05-22) and later. Historically Clang implemented
workarounds for issues discovered in libstdc++, and these are removed
as fixed libstdc++ becomes sufficiently old.
-You can instruct Clang to use libstdc++ with the ``-stdlib=libstdc++`` flag.
+You can instruct Clang to use libstdc++ with the `-stdlib=libstdc++` flag.
+
+## GCC Installation
+
+Users can point to their GCC installation by using the `-gcc-toolchain` or by
+using `-gcc-install-dir` flag.
-GCC Installation
-=================
-Users can point to their GCC installation by using the ``-gcc-toolchain`` or by
-using ``-gcc-install-dir`` flag.
diff --git a/clang/docs/TypeSanitizer.md b/clang/docs/TypeSanitizer.md
index ce0aaaf62ac98..29589d0186abd 100644
--- a/clang/docs/TypeSanitizer.md
+++ b/clang/docs/TypeSanitizer.md
@@ -1,221 +1,208 @@
-=============
-TypeSanitizer
-=============
+# TypeSanitizer
-.. contents::
- :local:
+```{contents}
+:local: true
+```
-Introduction
-============
+## Introduction
The TypeSanitizer is a detector for strict type aliasing violations. It consists of a compiler
-instrumentation module and a run-time library. C/C++ has type-based aliasing rules, and LLVM
-can exploit these for optimizations given the TBAA metadata Clang emits. In general, a pointer
-of a given type cannot access an object of a different type, with only a few exceptions.
+instrumentation module and a run-time library. C/C++ has type-based aliasing rules, and LLVM
+can exploit these for optimizations given the TBAA metadata Clang emits. In general, a pointer
+of a given type cannot access an object of a different type, with only a few exceptions.
These rules aren't always apparent to users, which leads to code that violates these rules
-(e.g. for type punning). This can lead to optimization passes introducing bugs unless the
-code is build with ``-fno-strict-aliasing``, sacrificing performance.
+(e.g. for type punning). This can lead to optimization passes introducing bugs unless the
+code is build with `-fno-strict-aliasing`, sacrificing performance.
-TypeSanitizer is built to catch when these strict aliasing rules have been violated, helping
+TypeSanitizer is built to catch when these strict aliasing rules have been violated, helping
users find where such bugs originate in their code despite the code looking valid at first glance.
Typical memory overhead introduced by TypeSanitizer is about **8x**. Runtime slowdown varies greatly
depending on how often the instrumented code relies on type aliasing. In the best case slowdown is
**2x-3x**.
-The TypeSanitizer Algorithm
-===========================
-For each TBAA type-access descriptor, encoded in LLVM IR using TBAA Metadata, the instrumentation
+## The TypeSanitizer Algorithm
+
+For each TBAA type-access descriptor, encoded in LLVM IR using TBAA Metadata, the instrumentation
pass generates descriptor tables. Thus there is a unique pointer to each type (and access descriptor).
-These tables are comdat (except for anonymous-namespace types), so the pointer values are unique
+These tables are comdat (except for anonymous-namespace types), so the pointer values are unique
across the program.
-The descriptors refer to other descriptors to form a type aliasing tree, like how LLVM's TBAA data
+The descriptors refer to other descriptors to form a type aliasing tree, like how LLVM's TBAA data
does.
-The runtime uses 8 bytes of shadow memory, the size of the pointer to the type descriptor, for
-every byte of accessed data in the program. The first byte of a type will have its shadow memory
+The runtime uses 8 bytes of shadow memory, the size of the pointer to the type descriptor, for
+every byte of accessed data in the program. The first byte of a type will have its shadow memory
be set to the pointer to its type descriptor. Aside from that, there are some other values it may be.
-* 0 is used to represent an unknown type
-* Negative numbers represent an interior byte: A byte inside a type that is not the first one. As an
+- 0 is used to represent an unknown type
+- Negative numbers represent an interior byte: A byte inside a type that is not the first one. As an
example, a value of -2 means you are in the third byte of a type.
-The Instrumentation first checks for an exact match between the type of the current access and the
-type for that address in the shadow memory. This can quickly be done by checking pointer values. If
-it matches, it checks the remaining shadow memory of the type to ensure they are the correct negative
-numbers. If this fails, it calls the "slow path" check. If the exact match fails, we check to see if
-the value, and the remainder of the shadow bytes, is 0. If they are, we can set the shadow memory to
-the correct type descriptor pointer for the first byte, and the correct negative numbers for the rest
+The Instrumentation first checks for an exact match between the type of the current access and the
+type for that address in the shadow memory. This can quickly be done by checking pointer values. If
+it matches, it checks the remaining shadow memory of the type to ensure they are the correct negative
+numbers. If this fails, it calls the "slow path" check. If the exact match fails, we check to see if
+the value, and the remainder of the shadow bytes, is 0. If they are, we can set the shadow memory to
+the correct type descriptor pointer for the first byte, and the correct negative numbers for the rest
of the type's shadow.
-If the type in shadow memory is neither an exact match nor 0, we call the slower runtime check. It
-uses the full TBAA algorithm, just as the compiler does, to determine when two types are permitted to
+If the type in shadow memory is neither an exact match nor 0, we call the slower runtime check. It
+uses the full TBAA algorithm, just as the compiler does, to determine when two types are permitted to
alias.
-The instrumentation pass inserts calls to the memset intrinsic to set the memory updated by memset,
-memcpy, and memmove, as well as allocas/byval (and for lifetime.start/end) to reset the shadow memory
-to reflect that the type is now unknown. The runtime intercepts memset, memcpy, etc. to perform the
+The instrumentation pass inserts calls to the memset intrinsic to set the memory updated by memset,
+memcpy, and memmove, as well as allocas/byval (and for lifetime.start/end) to reset the shadow memory
+to reflect that the type is now unknown. The runtime intercepts memset, memcpy, etc. to perform the
same function for the library calls.
-How to build
-============
+## How to build
-Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>`_ and enable
-the ``compiler-rt`` runtime. An example CMake configuration that will allow
+Build LLVM/Clang with [CMake](https://llvm.org/docs/CMake.html) and enable
+the `compiler-rt` runtime. An example CMake configuration that will allow
for the use/testing of TypeSanitizer:
-.. code-block:: console
-
- $ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_ENABLE_RUNTIMES="compiler-rt" <path to source>/llvm
+```console
+$ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_ENABLE_RUNTIMES="compiler-rt" <path to source>/llvm
+```
-Usage
-=====
+## Usage
-Compile and link your program with ``-fsanitize=type`` flag. The
+Compile and link your program with `-fsanitize=type` flag. The
TypeSanitizer run-time library should be linked to the final executable, so
-make sure to use ``clang`` (not ``ld``) for the final link step. To
-get a reasonable performance add ``-O1`` or higher.
-TypeSanitizer by default doesn't print the full stack trace in error messages. Use ``TYSAN_OPTIONS=print_stacktrace=1``
-to print the full trace. To get nicer stack traces in error messages add ``-fno-omit-frame-pointer`` and
-``-g``. To get perfect stack traces you may need to disable inlining (just use ``-O1``) and tail call elimination
-(``-fno-optimize-sibling-calls``).
-
-.. code-block:: console
-
- % cat example_AliasViolation.c
- int main(int argc, char **argv) {
- int x = 100;
- float *y = (float*)&x;
- *y += 2.0f; // Strict aliasing violation
- return 0;
- }
-
- # Compile and link
- % clang++ -g -fsanitize=type example_AliasViolation.c
-
-The program will print an error message to ``stderr`` each time a strict aliasing violation is detected.
-The program won't terminate, which will allow you to detect many strict aliasing violations in one
+make sure to use `clang` (not `ld`) for the final link step. To
+get a reasonable performance add `-O1` or higher.
+TypeSanitizer by default doesn't print the full stack trace in error messages. Use `TYSAN_OPTIONS=print_stacktrace=1`
+to print the full trace. To get nicer stack traces in error messages add `-fno-omit-frame-pointer` and
+`-g`. To get perfect stack traces you may need to disable inlining (just use `-O1`) and tail call elimination
+(`-fno-optimize-sibling-calls`).
+
+```console
+% cat example_AliasViolation.c
+int main(int argc, char **argv) {
+ int x = 100;
+ float *y = (float*)&x;
+ *y += 2.0f; // Strict aliasing violation
+ return 0;
+}
+
+# Compile and link
+% clang++ -g -fsanitize=type example_AliasViolation.c
+```
+
+The program will print an error message to `stderr` each time a strict aliasing violation is detected.
+The program won't terminate, which will allow you to detect many strict aliasing violations in one
run.
-.. code-block:: console
-
- % ./a.out
- ==1375532==ERROR: TypeSanitizer: type-aliasing-violation on address 0x7ffeebf1a72c (pc 0x5b3b1145ff41 bp 0x7ffeebf1a660 sp 0x7ffeebf19e08 tid 1375532)
- READ of size 4 at 0x7ffeebf1a72c with type float accesses an existing object of type int
- #0 0x5b3b1145ff40 in main example_AliasViolation.c:4:10
+```console
+% ./a.out
+==1375532==ERROR: TypeSanitizer: type-aliasing-violation on address 0x7ffeebf1a72c (pc 0x5b3b1145ff41 bp 0x7ffeebf1a660 sp 0x7ffeebf19e08 tid 1375532)
+READ of size 4 at 0x7ffeebf1a72c with type float accesses an existing object of type int
+ #0 0x5b3b1145ff40 in main example_AliasViolation.c:4:10
- ==1375532==ERROR: TypeSanitizer: type-aliasing-violation on address 0x7ffeebf1a72c (pc 0x5b3b1146008a bp 0x7ffeebf1a660 sp 0x7ffeebf19e08 tid 1375532)
- WRITE of size 4 at 0x7ffeebf1a72c with type float accesses an existing object of type int
- #0 0x5b3b11460089 in main example_AliasViolation.c:4:10
+==1375532==ERROR: TypeSanitizer: type-aliasing-violation on address 0x7ffeebf1a72c (pc 0x5b3b1146008a bp 0x7ffeebf1a660 sp 0x7ffeebf19e08 tid 1375532)
+WRITE of size 4 at 0x7ffeebf1a72c with type float accesses an existing object of type int
+ #0 0x5b3b11460089 in main example_AliasViolation.c:4:10
+```
-Error terminology
-------------------
+### Error terminology
-There are some terms that may appear in TypeSanitizer errors that are derived from
-`TBAA Metadata <https://llvm.org/docs/LangRef.html#tbaa-metadata>`_. This section hopes to provide a
+There are some terms that may appear in TypeSanitizer errors that are derived from
+[TBAA Metadata](https://llvm.org/docs/LangRef.html#tbaa-metadata). This section hopes to provide a
brief dictionary of these terms.
-* ``omnipotent char``: This is a special type which can alias with anything. Its name comes from the C/C++
- type ``char``.
-* ``type p[x]``: This signifies pointers to the type. ``x`` is the number of indirections to reach the final value.
- As an example, a pointer to a pointer to an integer would be ``type p2 int``.
+- `omnipotent char`: This is a special type which can alias with anything. Its name comes from the C/C++
+ type `char`.
+- `type p[x]`: This signifies pointers to the type. `x` is the number of indirections to reach the final value.
+ As an example, a pointer to a pointer to an integer would be `type p2 int`.
-TypeSanitizer is still experimental. User-facing error messages should be improved in the future to remove
+TypeSanitizer is still experimental. User-facing error messages should be improved in the future to remove
references to LLVM IR specific terms.
-Sanitizer features
-==================
+## Sanitizer features
-Instrumentation code inlining
-------------------------------
+### Instrumentation code inlining
By default TypeSanitizer inserts instrumentation through function calls. This may lead to a reduction in
-runtime performance. ``-fno-sanitize-type-outline-instrumentation`` (default: ``false``) forces all
+runtime performance. `-fno-sanitize-type-outline-instrumentation` (default: `false`) forces all
code instrumentation to be inlined. This will increase the size of the generated code and compiler
overhead, but may improve the runtime performance of the resulting code.
-``__has_feature(type_sanitizer)``
-------------------------------------
+### `__has_feature(type_sanitizer)`
In some cases one may need to execute different code depending on whether
TypeSanitizer is enabled.
-:ref:`\_\_has\_feature <langext-__has_feature-__has_extension>` can be used for
+{ref}`\_\_has\_feature <langext-__has_feature-__has_extension>` can be used for
this purpose.
-.. code-block:: c
+```c
+#if defined(__has_feature)
+# if __has_feature(type_sanitizer)
+// code that builds only under TypeSanitizer
+# endif
+#endif
+```
- #if defined(__has_feature)
- # if __has_feature(type_sanitizer)
- // code that builds only under TypeSanitizer
- # endif
- #endif
+### `__attribute__((no_sanitize("type")))`
-``__attribute__((no_sanitize("type")))``
------------------------------------------------
+Some code you may not want to be instrumented by TypeSanitizer. One may use the
+function attribute `no_sanitize("type")` to disable instrumenting type aliasing.
+It is possible, depending on what happens in non-instrumented code, that instrumented code
+emits false-positives/ false-negatives. This attribute may not be supported by other
+compilers, so we suggest to use it together with `__has_feature(type_sanitizer)`.
-Some code you may not want to be instrumented by TypeSanitizer. One may use the
-function attribute ``no_sanitize("type")`` to disable instrumenting type aliasing.
-It is possible, depending on what happens in non-instrumented code, that instrumented code
-emits false-positives/ false-negatives. This attribute may not be supported by other
-compilers, so we suggest to use it together with ``__has_feature(type_sanitizer)``.
+### `__attribute__((disable_sanitizer_instrumentation))`
-``__attribute__((disable_sanitizer_instrumentation))``
---------------------------------------------------------
-
-The ``disable_sanitizer_instrumentation`` attribute can be applied to functions
+The `disable_sanitizer_instrumentation` attribute can be applied to functions
to prevent all kinds of instrumentation. As a result, it may introduce false
positives and incorrect stack traces. Therefore, it should be used with care,
and only if absolutely required; for example for certain code that cannot
tolerate any instrumentation and resulting side-effects. This attribute
-overrides ``no_sanitize("type")``.
+overrides `no_sanitize("type")`.
-Ignorelist
-----------
+### Ignorelist
-TypeSanitizer supports ``src`` and ``fun`` entity types in
-:doc:`SanitizerSpecialCaseList`, that can be used to suppress aliasing
-violation reports in the specified source files or functions. Like
-with other methods of ignoring instrumentation, this can result in false
+TypeSanitizer supports `src` and `fun` entity types in
+{doc}`SanitizerSpecialCaseList`, that can be used to suppress aliasing
+violation reports in the specified source files or functions. Like
+with other methods of ignoring instrumentation, this can result in false
positives/ false-negatives.
-Runtime Options
----------------
+### Runtime Options
-Similar to other sanitizers, you can modify TypeSanitizers runtime behaviour by
-using an environment variable. These flags should be provided as a colon separated
-list. For example, ``TYSAN_OPTIONS=print_stacktrace=1:halt_on_error=1``
+Similar to other sanitizers, you can modify TypeSanitizers runtime behaviour by
+using an environment variable. These flags should be provided as a colon separated
+list. For example, `TYSAN_OPTIONS=print_stacktrace=1:halt_on_error=1`
-* ``print_stacktrace`` when true will tell the sanitizer to emit more lengthy
+- `print_stacktrace` when true will tell the sanitizer to emit more lengthy
and detailed stack traces on error.
-* ``halt_on_error`` when true will make the instrumented program abort after
+- `halt_on_error` when true will make the instrumented program abort after
the first type violation detected.
-Limitations
------------
+### Limitations
-* TypeSanitizer uses more real memory than a native run. It uses 8 bytes of
+- TypeSanitizer uses more real memory than a native run. It uses 8 bytes of
shadow memory for each byte of user memory.
-* There are transformation passes which run before TypeSanitizer. If these
+- There are transformation passes which run before TypeSanitizer. If these
passes optimize out an aliasing violation, TypeSanitizer cannot catch it.
-* Codebases that use unions and struct-initialized variables can see incorrect
+- Codebases that use unions and struct-initialized variables can see incorrect
results, as TypeSanitizer doesn't yet instrument these reliably.
-* Since Clang & LLVM's TBAA system is used to generate the checks used by the
- instrumentation, TypeSanitizer follows Clang & LLVM's rules for type aliasing.
- There may be situations where that disagrees with the standard. However this
- does at least mean that TypeSanitizer will catch any aliasing violations that
+- Since Clang & LLVM's TBAA system is used to generate the checks used by the
+ instrumentation, TypeSanitizer follows Clang & LLVM's rules for type aliasing.
+ There may be situations where that disagrees with the standard. However this
+ does at least mean that TypeSanitizer will catch any aliasing violations that
would cause bugs when compiling with Clang & LLVM.
-* TypeSanitizer cannot currently be run alongside other sanitizers such as
+- TypeSanitizer cannot currently be run alongside other sanitizers such as
AddressSanitizer or ThreadSanitizer.
-Current Status
---------------
+### Current Status
-TypeSanitizer is brand new, and still in development. There are some known
-issues, especially in areas where Clang's emitted TBAA data isn't extensive
+TypeSanitizer is brand new, and still in development. There are some known
+issues, especially in areas where Clang's emitted TBAA data isn't extensive
enough for TypeSanitizer's runtime.
-We are actively working on enhancing the tool --- stay tuned. Any help,
-issues, pull requests, ideas, is more than welcome. You can find the
-`issue tracker here. <https://github.com/llvm/llvm-project/issues?q=is%3Aissue%20state%3Aopen%20TySan%20label%3Acompiler-rt%3Atysan>`_
+We are actively working on enhancing the tool --- stay tuned. Any help,
+issues, pull requests, ideas, is more than welcome. You can find the
+[issue tracker here.](https://github.com/llvm/llvm-project/issues?q=is%3Aissue%20state%3Aopen%20TySan%20label%3Acompiler-rt%3Atysan)
+
diff --git a/clang/docs/UndefinedBehaviorSanitizer.md b/clang/docs/UndefinedBehaviorSanitizer.md
index 3ff1a77e33a6c..383b95cfcd4ac 100644
--- a/clang/docs/UndefinedBehaviorSanitizer.md
+++ b/clang/docs/UndefinedBehaviorSanitizer.md
@@ -1,303 +1,294 @@
-==========================
-UndefinedBehaviorSanitizer
-==========================
+# UndefinedBehaviorSanitizer
-.. contents::
- :local:
+```{contents}
+:local: true
+```
-Introduction
-============
+## Introduction
UndefinedBehaviorSanitizer (UBSan) is a fast undefined behavior detector.
UBSan modifies the program at compile-time to catch various kinds of undefined
behavior during program execution, for example:
-* Array subscript out of bounds, where the bounds can be statically determined
-* Bitwise shifts that are out of bounds for their data type
-* Dereferencing misaligned or null pointers
-* Signed integer overflow
-* Conversion to, from, or between floating-point types which would
+- Array subscript out of bounds, where the bounds can be statically determined
+- Bitwise shifts that are out of bounds for their data type
+- Dereferencing misaligned or null pointers
+- Signed integer overflow
+- Conversion to, from, or between floating-point types which would
overflow the destination
-See the full list of available :ref:`checks <ubsan-checks>` below.
+See the full list of available {ref}`checks <ubsan-checks>` below.
UBSan has an optional run-time library which provides better error reporting.
The checks have small runtime cost and no impact on address space layout or ABI.
-How to build
-============
+## How to build
-Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>`_.
+Build LLVM/Clang with [CMake](https://llvm.org/docs/CMake.html).
-Usage
-=====
+## Usage
-Use ``clang++`` to compile and link your program with the ``-fsanitize=undefined``
-option. Make sure to use ``clang++`` (not ``ld``) as a linker, so that your
+Use `clang++` to compile and link your program with the `-fsanitize=undefined`
+option. Make sure to use `clang++` (not `ld`) as a linker, so that your
executable is linked with proper UBSan runtime libraries, unless all enabled
-checks use trap mode. You can use ``clang`` instead of ``clang++`` if you're
+checks use trap mode. You can use `clang` instead of `clang++` if you're
compiling/linking C code.
-.. code-block:: console
-
- % cat test.cc
- int main(int argc, char **argv) {
- int k = 0x7fffffff;
- k += argc;
- return 0;
- }
- % clang++ -fsanitize=undefined test.cc
- % ./a.out
- test.cc:3:5: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'
-
-You can use ``-fsanitize=...`` and ``-fno-sanitize=`` to enable and disable one
+```console
+% cat test.cc
+int main(int argc, char **argv) {
+ int k = 0x7fffffff;
+ k += argc;
+ return 0;
+}
+% clang++ -fsanitize=undefined test.cc
+% ./a.out
+test.cc:3:5: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'
+```
+
+You can use `-fsanitize=...` and `-fno-sanitize=` to enable and disable one
check or one check group. For an individual check, the last option that enabling
or disabling it wins.
-.. code-block:: console
-
- # Enable all checks in the "undefined" group, but disable "alignment".
- % clang -fsanitize=undefined -fno-sanitize=alignment a.c
+```console
+# Enable all checks in the "undefined" group, but disable "alignment".
+% clang -fsanitize=undefined -fno-sanitize=alignment a.c
- # Enable just "alignment".
- % clang -fsanitize=alignment a.c
+# Enable just "alignment".
+% clang -fsanitize=alignment a.c
- # The same. -fno-sanitize=undefined nullifies the previous -fsanitize=undefined.
- % clang -fsanitize=undefined -fno-sanitize=undefined -fsanitize=alignment a.c
+# The same. -fno-sanitize=undefined nullifies the previous -fsanitize=undefined.
+% clang -fsanitize=undefined -fno-sanitize=undefined -fsanitize=alignment a.c
+```
-For most checks (:ref:`checks <ubsan-checks>`), the instrumented program prints
+For most checks ({ref}`checks <ubsan-checks>`), the instrumented program prints
a verbose error report and continues execution upon a failed check.
You can use the following options to change the error reporting behavior:
-* ``-fno-sanitize-recover=...``: print a verbose error report and exit the program;
-* ``-fsanitize-trap=...``: execute a trap instruction (doesn't require UBSan
+- `-fno-sanitize-recover=...`: print a verbose error report and exit the program;
+- `-fsanitize-trap=...`: execute a trap instruction (doesn't require UBSan
run-time support). If the signal is not caught, the program will typically
- terminate due to a ``SIGILL`` or ``SIGTRAP`` signal.
+ terminate due to a `SIGILL` or `SIGTRAP` signal.
For example:
-.. code-block:: console
-
- % clang++ -fsanitize=signed-integer-overflow,null,alignment -fno-sanitize-recover=null -fsanitize-trap=alignment a.cc
+```console
+% clang++ -fsanitize=signed-integer-overflow,null,alignment -fno-sanitize-recover=null -fsanitize-trap=alignment a.cc
+```
The program will continue execution after signed integer overflows, exit after
the first invalid use of a null pointer, and trap after the first use of misaligned
pointer.
-.. code-block:: console
-
- % clang++ -fsanitize=undefined -fsanitize-trap=all a.cc
+```console
+% clang++ -fsanitize=undefined -fsanitize-trap=all a.cc
+```
All checks in the "undefined" group are put into trap mode. Since no check
needs run-time support, the UBSan run-time library it not linked. Note that
-some other sanitizers also support trap mode and ``-fsanitize-trap=all``
+some other sanitizers also support trap mode and `-fsanitize-trap=all`
enables trap mode for them.
-.. code-block:: console
+```console
+% clang -fsanitize-trap=undefined -fsanitize-recover=all a.c
+```
- % clang -fsanitize-trap=undefined -fsanitize-recover=all a.c
+`-fsanitize-trap=` and `-fsanitize-recover=` are a no-op in the absence of
+a `-fsanitize=` option. There is no unused command line option warning.
-``-fsanitize-trap=`` and ``-fsanitize-recover=`` are a no-op in the absence of
-a ``-fsanitize=`` option. There is no unused command line option warning.
+(ubsan-checks)=
-.. _ubsan-checks:
-
-Available checks
-================
+## Available checks
Available checks are:
- - ``-fsanitize=alignment``: Use of a misaligned pointer or creation
- of a misaligned reference. Also sanitizes assume_aligned-like attributes.
- - ``-fsanitize=bool``: Load of a ``bool`` value which is neither
- ``true`` nor ``false``.
- - ``-fsanitize=builtin``: Passing invalid values to compiler builtins.
- - ``-fsanitize=bounds``: Out of bounds array indexing, in cases
- where the array bound can be statically determined. The check includes
- ``-fsanitize=array-bounds`` and ``-fsanitize=local-bounds``. Note that
- ``-fsanitize=local-bounds`` is not included in ``-fsanitize=undefined``.
- - ``-fsanitize=enum``: Load of a value of an enumerated type which
- is not in the range of representable values for that enumerated
- type.
- - ``-fsanitize=float-cast-overflow``: Conversion to, from, or
- between floating-point types which would overflow the
- destination. Because the range of representable values for all
- floating-point types supported by Clang is [-inf, +inf], the only
- cases detected are conversions from floating point to integer types.
- - ``-fsanitize=float-divide-by-zero``: Floating point division by
- zero. This is undefined per the C and C++ standards, but is defined
- by Clang (and by ISO/IEC/IEEE 60559 / IEEE 754) as producing either an
- infinity or NaN value, so is not included in ``-fsanitize=undefined``.
- - ``-fsanitize=function``: Indirect call of a function through a
- function pointer of the wrong type.
- - ``-fsanitize=implicit-unsigned-integer-truncation``,
- ``-fsanitize=implicit-signed-integer-truncation``: Implicit conversion from
- integer of larger bit width to smaller bit width, if that results in data
- loss. That is, if the demoted value, after casting back to the original
- width, is not equal to the original value before the downcast.
- The ``-fsanitize=implicit-unsigned-integer-truncation`` handles conversions
- between two ``unsigned`` types, while
- ``-fsanitize=implicit-signed-integer-truncation`` handles the rest of the
- conversions - when either one, or both of the types are signed.
- Issues caught by these sanitizers are not undefined behavior,
- but are often unintentional.
- - ``-fsanitize=implicit-integer-sign-change``: Implicit conversion between
- integer types, if that changes the sign of the value. That is, if the
- original value was negative and the new value is positive (or zero),
- or the original value was positive, and the new value is negative.
- Issues caught by this sanitizer are not undefined behavior,
- but are often unintentional.
- - ``-fsanitize=integer-divide-by-zero``: Integer division by zero.
- - ``-fsanitize=implicit-bitfield-conversion``: Implicit conversion from
- integer of larger bit width to smaller bitfield, if that results in data
- loss. This includes unsigned/signed truncations and sign changes, similarly
- to how the ``-fsanitize=implicit-integer-conversion`` group works, but
- explicitly for bitfields.
- - ``-fsanitize=nonnull-attribute``: Passing null pointer as a function
- parameter which is declared to never be null.
- - ``-fsanitize=null``: Use of a null pointer or creation of a null
- reference.
- - ``-fsanitize=nullability-arg``: Passing null as a function parameter
- which is annotated with ``_Nonnull``.
- - ``-fsanitize=nullability-assign``: Assigning null to an lvalue which
- is annotated with ``_Nonnull``.
- - ``-fsanitize=nullability-return``: Returning null from a function with
- a return type annotated with ``_Nonnull``.
- - ``-fsanitize=objc-cast``: Invalid implicit cast of an ObjC object pointer
- to an incompatible type. This is often unintentional, but is not undefined
- behavior, therefore the check is not a part of the ``undefined`` group.
- Currently only supported on Darwin.
- - ``-fsanitize=object-size``: An attempt to potentially use bytes which
- the optimizer can determine are not part of the object being accessed.
- This will also detect some types of undefined behavior that may not
- directly access memory, but are provably incorrect given the size of
- the objects involved, such as invalid downcasts and calling methods on
- invalid pointers. These checks are made in terms of
- ``__builtin_object_size``, and consequently may be able to detect more
- problems at higher optimization levels.
- - ``-fsanitize=pointer-overflow``: Performing pointer arithmetic which
- overflows, or where either the old or new pointer value is a null pointer
- (excluding the case where both are null pointers).
- - ``-fsanitize=return``: In C++, reaching the end of a
- value-returning function without returning a value.
- - ``-fsanitize=returns-nonnull-attribute``: Returning null pointer
- from a function which is declared to never return null.
- - ``-fsanitize=shift``: Shift operators where the amount shifted is
- greater or equal to the promoted bit-width of the left hand side
- or less than zero, or where the left hand side is negative. For a
- signed left shift, also checks for signed overflow in C, and for
- unsigned overflow in C++. You can use ``-fsanitize=shift-base`` or
- ``-fsanitize=shift-exponent`` to check only left-hand side or
- right-hand side of shift operation, respectively.
- - ``-fsanitize=unsigned-shift-base``: check that an unsigned left-hand side of
- a left shift operation doesn't overflow. Issues caught by this sanitizer are
- not undefined behavior, but are often unintentional.
- - ``-fsanitize=signed-integer-overflow``: Signed integer overflow, where the
- result of a signed integer computation cannot be represented in its type.
- This includes all the checks covered by ``-ftrapv``, as well as checks for
- signed division overflow (``INT_MIN/-1``). Note that checks are still
- added even when ``-fwrapv`` is enabled. This sanitizer does not check for
- lossy implicit conversions performed before the computation (see
- ``-fsanitize=implicit-integer-conversion``). Both of these two issues are handled
- by ``-fsanitize=implicit-integer-conversion`` group of checks.
- - ``-fsanitize=unreachable``: If control flow reaches an unreachable
- program point.
- - ``-fsanitize=unsigned-integer-overflow``: Unsigned integer overflow, where
- the result of an unsigned integer computation cannot be represented in its
- type. Unlike signed integer overflow, this is not undefined behavior, but
- it is often unintentional. This sanitizer does not check for lossy implicit
- conversions performed before such a computation
- (see ``-fsanitize=implicit-integer-conversion``).
- - ``-fsanitize=vla-bound``: A variable-length array whose bound
- does not evaluate to a positive value.
- - ``-fsanitize=vptr``: Use of an object whose vptr indicates that it is of
- the wrong dynamic type, or that its lifetime has not begun or has ended.
- Incompatible with ``-fno-rtti``. Link must be performed by ``clang++``, not
- ``clang``, to make sure C++-specific parts of the runtime library and C++
- standard libraries are present. The check is not a part of the ``undefined``
- group. Also it does not support ``-fsanitize-trap=vptr``.
+> - `-fsanitize=alignment`: Use of a misaligned pointer or creation
+> of a misaligned reference. Also sanitizes assume_aligned-like attributes.
+> - `-fsanitize=bool`: Load of a `bool` value which is neither
+> `true` nor `false`.
+> - `-fsanitize=builtin`: Passing invalid values to compiler builtins.
+> - `-fsanitize=bounds`: Out of bounds array indexing, in cases
+> where the array bound can be statically determined. The check includes
+> `-fsanitize=array-bounds` and `-fsanitize=local-bounds`. Note that
+> `-fsanitize=local-bounds` is not included in `-fsanitize=undefined`.
+> - `-fsanitize=enum`: Load of a value of an enumerated type which
+> is not in the range of representable values for that enumerated
+> type.
+> - `-fsanitize=float-cast-overflow`: Conversion to, from, or
+> between floating-point types which would overflow the
+> destination. Because the range of representable values for all
+> floating-point types supported by Clang is [-inf, +inf], the only
+> cases detected are conversions from floating point to integer types.
+> - `-fsanitize=float-divide-by-zero`: Floating point division by
+> zero. This is undefined per the C and C++ standards, but is defined
+> by Clang (and by ISO/IEC/IEEE 60559 / IEEE 754) as producing either an
+> infinity or NaN value, so is not included in `-fsanitize=undefined`.
+> - `-fsanitize=function`: Indirect call of a function through a
+> function pointer of the wrong type.
+> - `-fsanitize=implicit-unsigned-integer-truncation`,
+> `-fsanitize=implicit-signed-integer-truncation`: Implicit conversion from
+> integer of larger bit width to smaller bit width, if that results in data
+> loss. That is, if the demoted value, after casting back to the original
+> width, is not equal to the original value before the downcast.
+> The `-fsanitize=implicit-unsigned-integer-truncation` handles conversions
+> between two `unsigned` types, while
+> `-fsanitize=implicit-signed-integer-truncation` handles the rest of the
+> conversions - when either one, or both of the types are signed.
+> Issues caught by these sanitizers are not undefined behavior,
+> but are often unintentional.
+> - `-fsanitize=implicit-integer-sign-change`: Implicit conversion between
+> integer types, if that changes the sign of the value. That is, if the
+> original value was negative and the new value is positive (or zero),
+> or the original value was positive, and the new value is negative.
+> Issues caught by this sanitizer are not undefined behavior,
+> but are often unintentional.
+> - `-fsanitize=integer-divide-by-zero`: Integer division by zero.
+> - `-fsanitize=implicit-bitfield-conversion`: Implicit conversion from
+> integer of larger bit width to smaller bitfield, if that results in data
+> loss. This includes unsigned/signed truncations and sign changes, similarly
+> to how the `-fsanitize=implicit-integer-conversion` group works, but
+> explicitly for bitfields.
+> - `-fsanitize=nonnull-attribute`: Passing null pointer as a function
+> parameter which is declared to never be null.
+> - `-fsanitize=null`: Use of a null pointer or creation of a null
+> reference.
+> - `-fsanitize=nullability-arg`: Passing null as a function parameter
+> which is annotated with `_Nonnull`.
+> - `-fsanitize=nullability-assign`: Assigning null to an lvalue which
+> is annotated with `_Nonnull`.
+> - `-fsanitize=nullability-return`: Returning null from a function with
+> a return type annotated with `_Nonnull`.
+> - `-fsanitize=objc-cast`: Invalid implicit cast of an ObjC object pointer
+> to an incompatible type. This is often unintentional, but is not undefined
+> behavior, therefore the check is not a part of the `undefined` group.
+> Currently only supported on Darwin.
+> - `-fsanitize=object-size`: An attempt to potentially use bytes which
+> the optimizer can determine are not part of the object being accessed.
+> This will also detect some types of undefined behavior that may not
+> directly access memory, but are provably incorrect given the size of
+> the objects involved, such as invalid downcasts and calling methods on
+> invalid pointers. These checks are made in terms of
+> `__builtin_object_size`, and consequently may be able to detect more
+> problems at higher optimization levels.
+> - `-fsanitize=pointer-overflow`: Performing pointer arithmetic which
+> overflows, or where either the old or new pointer value is a null pointer
+> (excluding the case where both are null pointers).
+> - `-fsanitize=return`: In C++, reaching the end of a
+> value-returning function without returning a value.
+> - `-fsanitize=returns-nonnull-attribute`: Returning null pointer
+> from a function which is declared to never return null.
+> - `-fsanitize=shift`: Shift operators where the amount shifted is
+> greater or equal to the promoted bit-width of the left hand side
+> or less than zero, or where the left hand side is negative. For a
+> signed left shift, also checks for signed overflow in C, and for
+> unsigned overflow in C++. You can use `-fsanitize=shift-base` or
+> `-fsanitize=shift-exponent` to check only left-hand side or
+> right-hand side of shift operation, respectively.
+> - `-fsanitize=unsigned-shift-base`: check that an unsigned left-hand side of
+> a left shift operation doesn't overflow. Issues caught by this sanitizer are
+> not undefined behavior, but are often unintentional.
+> - `-fsanitize=signed-integer-overflow`: Signed integer overflow, where the
+> result of a signed integer computation cannot be represented in its type.
+> This includes all the checks covered by `-ftrapv`, as well as checks for
+> signed division overflow (`INT_MIN/-1`). Note that checks are still
+> added even when `-fwrapv` is enabled. This sanitizer does not check for
+> lossy implicit conversions performed before the computation (see
+> `-fsanitize=implicit-integer-conversion`). Both of these two issues are handled
+> by `-fsanitize=implicit-integer-conversion` group of checks.
+> - `-fsanitize=unreachable`: If control flow reaches an unreachable
+> program point.
+> - `-fsanitize=unsigned-integer-overflow`: Unsigned integer overflow, where
+> the result of an unsigned integer computation cannot be represented in its
+> type. Unlike signed integer overflow, this is not undefined behavior, but
+> it is often unintentional. This sanitizer does not check for lossy implicit
+> conversions performed before such a computation
+> (see `-fsanitize=implicit-integer-conversion`).
+> - `-fsanitize=vla-bound`: A variable-length array whose bound
+> does not evaluate to a positive value.
+> - `-fsanitize=vptr`: Use of an object whose vptr indicates that it is of
+> the wrong dynamic type, or that its lifetime has not begun or has ended.
+> Incompatible with `-fno-rtti`. Link must be performed by `clang++`, not
+> `clang`, to make sure C++-specific parts of the runtime library and C++
+> standard libraries are present. The check is not a part of the `undefined`
+> group. Also it does not support `-fsanitize-trap=vptr`.
You can also use the following check groups:
- - ``-fsanitize=undefined``: All of the checks listed above other than
- ``float-divide-by-zero``, ``unsigned-integer-overflow``,
- ``implicit-conversion``, ``local-bounds``, ``vptr`` and the
- ``nullability-*`` group of checks.
- - ``-fsanitize=undefined-trap``: Deprecated alias of
- ``-fsanitize=undefined``.
- - ``-fsanitize=implicit-integer-truncation``: Catches lossy integral
- conversions. Enables ``implicit-signed-integer-truncation`` and
- ``implicit-unsigned-integer-truncation``.
- - ``-fsanitize=implicit-integer-arithmetic-value-change``: Catches implicit
- conversions that change the arithmetic value of the integer. Enables
- ``implicit-signed-integer-truncation`` and ``implicit-integer-sign-change``.
- - ``-fsanitize=implicit-integer-conversion``: Checks for suspicious
- behavior of implicit integer conversions. Enables
- ``implicit-unsigned-integer-truncation``,
- ``implicit-signed-integer-truncation``, and
- ``implicit-integer-sign-change``.
- - ``-fsanitize=implicit-conversion``: Checks for suspicious
- behavior of implicit conversions. Enables
- ``implicit-integer-conversion``, and
- ``implicit-bitfield-conversion``.
- - ``-fsanitize=integer``: Checks for undefined or suspicious integer
- behavior (e.g. unsigned integer overflow).
- Enables ``signed-integer-overflow``, ``unsigned-integer-overflow``,
- ``shift``, ``integer-divide-by-zero``,
- ``implicit-unsigned-integer-truncation``,
- ``implicit-signed-integer-truncation``, and
- ``implicit-integer-sign-change``.
- - ``-fsanitize=nullability``: Enables ``nullability-arg``,
- ``nullability-assign``, and ``nullability-return``. While violating
- nullability does not have undefined behavior, it is often unintentional,
- so UBSan offers to catch it.
-
-Volatile
---------
-
-The ``null``, ``alignment``, ``object-size``, ``local-bounds``, and ``vptr`` checks do not apply
-to pointers to types with the ``volatile`` qualifier.
-
-.. _minimal-runtime:
-
-Minimal Runtime
-===============
+: - `-fsanitize=undefined`: All of the checks listed above other than
+ `float-divide-by-zero`, `unsigned-integer-overflow`,
+ `implicit-conversion`, `local-bounds`, `vptr` and the
+ `nullability-*` group of checks.
+ - `-fsanitize=undefined-trap`: Deprecated alias of
+ `-fsanitize=undefined`.
+ - `-fsanitize=implicit-integer-truncation`: Catches lossy integral
+ conversions. Enables `implicit-signed-integer-truncation` and
+ `implicit-unsigned-integer-truncation`.
+ - `-fsanitize=implicit-integer-arithmetic-value-change`: Catches implicit
+ conversions that change the arithmetic value of the integer. Enables
+ `implicit-signed-integer-truncation` and `implicit-integer-sign-change`.
+ - `-fsanitize=implicit-integer-conversion`: Checks for suspicious
+ behavior of implicit integer conversions. Enables
+ `implicit-unsigned-integer-truncation`,
+ `implicit-signed-integer-truncation`, and
+ `implicit-integer-sign-change`.
+ - `-fsanitize=implicit-conversion`: Checks for suspicious
+ behavior of implicit conversions. Enables
+ `implicit-integer-conversion`, and
+ `implicit-bitfield-conversion`.
+ - `-fsanitize=integer`: Checks for undefined or suspicious integer
+ behavior (e.g. unsigned integer overflow).
+ Enables `signed-integer-overflow`, `unsigned-integer-overflow`,
+ `shift`, `integer-divide-by-zero`,
+ `implicit-unsigned-integer-truncation`,
+ `implicit-signed-integer-truncation`, and
+ `implicit-integer-sign-change`.
+ - `-fsanitize=nullability`: Enables `nullability-arg`,
+ `nullability-assign`, and `nullability-return`. While violating
+ nullability does not have undefined behavior, it is often unintentional,
+ so UBSan offers to catch it.
+
+### Volatile
+
+The `null`, `alignment`, `object-size`, `local-bounds`, and `vptr` checks do not apply
+to pointers to types with the `volatile` qualifier.
+
+(minimal-runtime)=
+
+## Minimal Runtime
There is a minimal UBSan runtime available suitable for use in production
environments. This runtime has a small attack surface. It only provides very
-basic issue logging and deduplication, and does not support ``-fsanitize=vptr``
+basic issue logging and deduplication, and does not support `-fsanitize=vptr`
checking.
-To use the minimal runtime, add ``-fsanitize-minimal-runtime`` to the clang
+To use the minimal runtime, add `-fsanitize-minimal-runtime` to the clang
command line options. For example, if you're used to compiling with
-``-fsanitize=undefined``, you could enable the minimal runtime with
-``-fsanitize=undefined -fsanitize-minimal-runtime``.
+`-fsanitize=undefined`, you could enable the minimal runtime with
+`-fsanitize=undefined -fsanitize-minimal-runtime`.
+
+## Stack traces and report symbolization
-Stack traces and report symbolization
-=====================================
If you want UBSan to print symbolized stack trace for each error report, you
will need to:
-#. Compile with ``-g``, ``-fno-sanitize-merge`` and ``-fno-omit-frame-pointer``
+1. Compile with `-g`, `-fno-sanitize-merge` and `-fno-omit-frame-pointer`
to get proper debug information in your binary.
-#. Run your program with environment variable
- ``UBSAN_OPTIONS=print_stacktrace=1``.
-#. Make sure ``llvm-symbolizer`` binary is in ``PATH``.
+2. Run your program with environment variable
+ `UBSAN_OPTIONS=print_stacktrace=1`.
+3. Make sure `llvm-symbolizer` binary is in `PATH`.
-Logging
-=======
+## Logging
The default log file for diagnostics is "stderr". To log diagnostics to another
-file, you can set ``UBSAN_OPTIONS=log_path=...``.
+file, you can set `UBSAN_OPTIONS=log_path=...`.
+
+## Silencing Unsigned Integer Overflow
-Silencing Unsigned Integer Overflow
-===================================
To silence reports from unsigned integer overflow, you can set
-``UBSAN_OPTIONS=silence_unsigned_overflow=1``. This feature, combined with
-``-fsanitize-recover=unsigned-integer-overflow``, is particularly useful for
+`UBSAN_OPTIONS=silence_unsigned_overflow=1`. This feature, combined with
+`-fsanitize-recover=unsigned-integer-overflow`, is particularly useful for
providing fuzzing signal without blowing up logs.
-Disabling instrumentation for common overflow patterns
-------------------------------------------------------
+### Disabling instrumentation for common overflow patterns
There are certain overflow-dependent or overflow-prone code patterns which
produce a lot of noise for integer overflow/truncation sanitizers. Negated
@@ -305,34 +296,35 @@ unsigned constants, post-decrements in a while loop condition and simple
overflow checks are accepted and pervasive code patterns. However, the signal
received from sanitizers instrumenting these code patterns may be too noisy for
some projects. To disable instrumentation for these common patterns one should
-use ``-fsanitize-undefined-ignore-overflow-pattern=``.
+use `-fsanitize-undefined-ignore-overflow-pattern=`.
Currently, this option supports three overflow-dependent code idioms:
-``negated-unsigned-const``
-
-.. code-block:: c++
-
- /// -fsanitize-undefined-ignore-overflow-pattern=negated-unsigned-const
- unsigned long foo = -1UL; // No longer causes a negation overflow warning
- unsigned long bar = -2UL; // and so on...
+`negated-unsigned-const`
-``unsigned-post-decr-while``
+```c++
+/// -fsanitize-undefined-ignore-overflow-pattern=negated-unsigned-const
+unsigned long foo = -1UL; // No longer causes a negation overflow warning
+unsigned long bar = -2UL; // and so on...
+```
-.. code-block:: c++
+`unsigned-post-decr-while`
- /// -fsanitize-undefined-ignore-overflow-pattern=unsigned-post-decr-while
- unsigned char count = 16;
- while (count--) { /* ... */ } // No longer causes unsigned-integer-overflow sanitizer to trip
+```c++
+/// -fsanitize-undefined-ignore-overflow-pattern=unsigned-post-decr-while
+unsigned char count = 16;
+while (count--) { /* ... */ } // No longer causes unsigned-integer-overflow sanitizer to trip
+```
-``add-signed-overflow-test,add-unsigned-overflow-test``
+`add-signed-overflow-test,add-unsigned-overflow-test`
-.. code-block:: c++
-
- /// -fsanitize-undefined-ignore-overflow-pattern=add-(signed|unsigned)-overflow-test
- if (base + offset < base) { /* ... */ } // The pattern of `a + b < a`, and other re-orderings,
- // won't be instrumented (signed or unsigned types)
+```c++
+/// -fsanitize-undefined-ignore-overflow-pattern=add-(signed|unsigned)-overflow-test
+if (base + offset < base) { /* ... */ } // The pattern of `a + b < a`, and other re-orderings,
+ // won't be instrumented (signed or unsigned types)
+```
+```{eval-rst}
.. list-table:: Overflow Pattern Types
:widths: 30 50
:header-rows: 1
@@ -349,67 +341,64 @@ Currently, this option supports three overflow-dependent code idioms:
- signed-integer-overflow
+```
-Note: ``add-signed-overflow-test`` suppresses only the check for Undefined
+Note: `add-signed-overflow-test` suppresses only the check for Undefined
Behavior. Eager Undefined Behavior optimizations are still possible. One may
-remedy this with ``-fwrapv`` or ``-fno-strict-overflow``.
+remedy this with `-fwrapv` or `-fno-strict-overflow`.
You can enable all exclusions with
-``-fsanitize-undefined-ignore-overflow-pattern=all`` or disable all exclusions
-with ``-fsanitize-undefined-ignore-overflow-pattern=none``. If
-``-fsanitize-undefined-ignore-overflow-pattern`` is not specified ``none`` is
-implied. Specifying ``none`` alongside other values also implies ``none`` as
-``none`` has precedence over other values -- including ``all``.
+`-fsanitize-undefined-ignore-overflow-pattern=all` or disable all exclusions
+with `-fsanitize-undefined-ignore-overflow-pattern=none`. If
+`-fsanitize-undefined-ignore-overflow-pattern` is not specified `none` is
+implied. Specifying `none` alongside other values also implies `none` as
+`none` has precedence over other values -- including `all`.
-Issue Suppression
-=================
+## Issue Suppression
UndefinedBehaviorSanitizer is not expected to produce false positives.
If you see one, look again; most likely it is a true positive!
-Disabling Instrumentation with ``__attribute__((no_sanitize("undefined")))``
-----------------------------------------------------------------------------
+### Disabling Instrumentation with `__attribute__((no_sanitize("undefined")))`
You disable UBSan checks for particular functions with
-``__attribute__((no_sanitize("undefined")))``. You can use all values of
-``-fsanitize=`` flag in this attribute, e.g. if your function deliberately
+`__attribute__((no_sanitize("undefined")))`. You can use all values of
+`-fsanitize=` flag in this attribute, e.g. if your function deliberately
contains possible signed integer overflow, you can use
-``__attribute__((no_sanitize("signed-integer-overflow")))``.
+`__attribute__((no_sanitize("signed-integer-overflow")))`.
This attribute may not be
supported by other compilers, so consider using it together with
-``#if defined(__clang__)``.
+`#if defined(__clang__)`.
-Interaction of Inlining with Disabling Sanitizer Instrumentation
------------------------------------------------------------------
+### Interaction of Inlining with Disabling Sanitizer Instrumentation
Unlike many of the other sanitizers (e.g., ASan/MSan, TSan), UBSan is largely
compatible with inlining, both the compiler's heuristic inlining as well as
-``__attribute__((always_inline))``.
+`__attribute__((always_inline))`.
There are (at least) two exceptions:
-* inlining may change the layout of variables, which can affect whether
+- inlining may change the layout of variables, which can affect whether
the `alignment` check detects an under-aligned variable
-* combining `__attribute((no_sanitize("local-bounds")))` with
+- combining `__attribute((no_sanitize("local-bounds")))` with
`__attribute((always_inline))` is not supported
-Disabling Overflow Instrumentation with ``__attribute__((overflow_behavior(wrap)))``
-------------------------------------------------------------------------------------
+### Disabling Overflow Instrumentation with `__attribute__((overflow_behavior(wrap)))`
For more fine-grained control over how integer overflow is handled, you can use
-the ``__attribute__((overflow_behavior(wrap)))`` attribute. This attribute can
-be applied to ``typedef`` declarations and integer types to specify that
+the `__attribute__((overflow_behavior(wrap)))` attribute. This attribute can
+be applied to `typedef` declarations and integer types to specify that
arithmetic operations on that type should wrap on overflow. This can be used to
disable overflow sanitization for specific types, while leaving it enabled for
all other types.
-The ``overflow_behavior`` attribute not only affects UBSan instrumentation
+The `overflow_behavior` attribute not only affects UBSan instrumentation
but also changes the fundamental overflow behavior of arithmetic operations
-on the annotated type. Operations on types marked with ``wrap`` will have
+on the annotated type. Operations on types marked with `wrap` will have
well-defined wrapping semantics, while operations on types marked with
-``trap`` will be checked for overflow (regardless of global flags like
-``-fwrapv``).
+`trap` will be checked for overflow (regardless of global flags like
+`-fwrapv`).
The attribute also affects implicit type promotion rules: when an overflow
behavior type participates in arithmetic operations with standard integer
@@ -418,130 +407,119 @@ including its bit-width. This means annotated types can preserve narrower
widths that would normally be promoted, allowing operations to stay within
the constraints of the smallest annotated type in the expression.
-For more information, see :doc:`OverflowBehaviorTypes`.
+For more information, see {doc}`OverflowBehaviorTypes`.
-Enforcing Overflow Instrumentation with ``__attribute__((overflow_behavior(trap)))``
----------------------------------------------------------------------------------------
+### Enforcing Overflow Instrumentation with `__attribute__((overflow_behavior(trap)))`
-Conversely, you can use ``__attribute__((overflow_behavior(trap)))`` to
-enforce overflow checks for a specific type, even when ``-fwrapv`` is enabled
+Conversely, you can use `__attribute__((overflow_behavior(trap)))` to
+enforce overflow checks for a specific type, even when `-fwrapv` is enabled
globally. This is useful for ensuring that critical calculations are always
checked for overflow, regardless of the global compiler settings.
-For more information, see :doc:`OverflowBehaviorTypes`.
+For more information, see {doc}`OverflowBehaviorTypes`.
-Suppressing Errors in Recompiled Code (Ignorelist)
---------------------------------------------------
+### Suppressing Errors in Recompiled Code (Ignorelist)
-UndefinedBehaviorSanitizer supports ``src`` and ``fun`` entity types in
-:doc:`SanitizerSpecialCaseList`, that can be used to suppress error reports
+UndefinedBehaviorSanitizer supports `src` and `fun` entity types in
+{doc}`SanitizerSpecialCaseList`, that can be used to suppress error reports
in the specified source files or functions.
-Runtime suppressions
---------------------
+### Runtime suppressions
Sometimes you can suppress UBSan error reports for specific files, functions,
or libraries without recompiling the code. You need to pass a path to
-suppression file in a ``UBSAN_OPTIONS`` environment variable.
-
-.. code-block:: bash
+suppression file in a `UBSAN_OPTIONS` environment variable.
- UBSAN_OPTIONS=suppressions=MyUBSan.supp
+```bash
+UBSAN_OPTIONS=suppressions=MyUBSan.supp
+```
Alternatively, you can provide default suppressions by defining a
-``__ubsan_default_suppressions`` function:
-
-.. code-block:: c++
+`__ubsan_default_suppressions` function:
- extern "C" const char *__ubsan_default_suppressions() {
- return "signed-integer-overflow:file-with-known-overflow.cpp\n"
- "alignment:function_doing_unaligned_access\n";
- }
+```c++
+extern "C" const char *__ubsan_default_suppressions() {
+ return "signed-integer-overflow:file-with-known-overflow.cpp\n"
+ "alignment:function_doing_unaligned_access\n";
+}
+```
-You need to specify a :ref:`check <ubsan-checks>` you are suppressing and the
+You need to specify a {ref}`check <ubsan-checks>` you are suppressing and the
bug location. For example:
-.. code-block:: bash
-
- signed-integer-overflow:file-with-known-overflow.cpp
- alignment:function_doing_unaligned_access
- vptr:shared_object_with_vptr_failures.so
+```bash
+signed-integer-overflow:file-with-known-overflow.cpp
+alignment:function_doing_unaligned_access
+vptr:shared_object_with_vptr_failures.so
+```
There are several limitations:
-* Sometimes your binary must have enough debug info and/or symbol table, so
+- Sometimes your binary must have enough debug info and/or symbol table, so
that the runtime could figure out source file or function name to match
against the suppression.
-* It is only possible to suppress recoverable checks. For the example above,
+- It is only possible to suppress recoverable checks. For the example above,
you can additionally pass
- ``-fsanitize-recover=signed-integer-overflow,alignment,vptr``, although
+ `-fsanitize-recover=signed-integer-overflow,alignment,vptr`, although
most of UBSan checks are recoverable by default.
-* Check groups (like ``undefined``) can't be used in suppressions file, only
+- Check groups (like `undefined`) can't be used in suppressions file, only
fine-grained checks are supported.
-Security Considerations
-=======================
+## Security Considerations
UndefinedBehaviorSanitizer's runtime is meant for testing purposes and its usage
in production environment should be carefully considered from security
perspective as it may compromise the security of the resulting executable.
-For security-sensitive applications consider using :ref:`Minimal Runtime
+For security-sensitive applications consider using {ref}`Minimal Runtime
<minimal-runtime>` or trap mode for all checks.
-Supported Platforms
-===================
+## Supported Platforms
UndefinedBehaviorSanitizer is supported on the following operating systems:
-* Android
-* Linux
-* NetBSD
-* FreeBSD
-* OpenBSD
-* macOS
-* Windows
+- Android
+- Linux
+- NetBSD
+- FreeBSD
+- OpenBSD
+- macOS
+- Windows
The runtime library is relatively portable and platform independent. If the OS
you need is not listed above, UndefinedBehaviorSanitizer may already work for
it, or could be made to work with a minor porting effort.
-Current Status
-==============
+## Current Status
UndefinedBehaviorSanitizer is available on selected platforms starting from LLVM
3.3. The test suite is integrated into the CMake build and can be run with
-``check-ubsan`` command.
+`check-ubsan` command.
-Additional Configuration
-========================
+## Additional Configuration
UndefinedBehaviorSanitizer adds static check data for each check unless it is
in trap mode. This check data includes the full file name. The option
-``-fsanitize-undefined-strip-path-components=N`` can be used to trim this
-information. If ``N`` is positive, file information emitted by
-UndefinedBehaviorSanitizer will drop the first ``N`` components from the file
-path. If ``N`` is negative, the last ``N`` components will be kept.
-
-Example
--------
-
-For a file called ``/code/library/file.cpp``, here is what would be emitted:
-
-* Default (No flag, or ``-fsanitize-undefined-strip-path-components=0``): ``/code/library/file.cpp``
-* ``-fsanitize-undefined-strip-path-components=1``: ``code/library/file.cpp``
-* ``-fsanitize-undefined-strip-path-components=2``: ``library/file.cpp``
-* ``-fsanitize-undefined-strip-path-components=-1``: ``file.cpp``
-* ``-fsanitize-undefined-strip-path-components=-2``: ``library/file.cpp``
-
-More Information
-================
-
-* From Oracle blog, including a discussion of error messages:
- `Improving Application Security with UndefinedBehaviorSanitizer (UBSan) and GCC
- <https://blogs.oracle.com/linux/improving-application-security-with-undefinedbehaviorsanitizer-ubsan-and-gcc>`_
-* From LLVM project blog:
- `What Every C Programmer Should Know About Undefined Behavior
- <http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html>`_
-* From John Regehr's *Embedded in Academia* blog:
- `A Guide to Undefined Behavior in C and C++
- <https://blog.regehr.org/archives/213>`_
+`-fsanitize-undefined-strip-path-components=N` can be used to trim this
+information. If `N` is positive, file information emitted by
+UndefinedBehaviorSanitizer will drop the first `N` components from the file
+path. If `N` is negative, the last `N` components will be kept.
+
+### Example
+
+For a file called `/code/library/file.cpp`, here is what would be emitted:
+
+- Default (No flag, or `-fsanitize-undefined-strip-path-components=0`): `/code/library/file.cpp`
+- `-fsanitize-undefined-strip-path-components=1`: `code/library/file.cpp`
+- `-fsanitize-undefined-strip-path-components=2`: `library/file.cpp`
+- `-fsanitize-undefined-strip-path-components=-1`: `file.cpp`
+- `-fsanitize-undefined-strip-path-components=-2`: `library/file.cpp`
+
+## More Information
+
+- From Oracle blog, including a discussion of error messages:
+ [Improving Application Security with UndefinedBehaviorSanitizer (UBSan) and GCC](https://blogs.oracle.com/linux/improving-application-security-with-undefinedbehaviorsanitizer-ubsan-and-gcc)
+- From LLVM project blog:
+ [What Every C Programmer Should Know About Undefined Behavior](http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html)
+- From John Regehr's *Embedded in Academia* blog:
+ [A Guide to Undefined Behavior in C and C++](https://blog.regehr.org/archives/213)
+
diff --git a/clang/docs/WarningSuppressionMappings.md b/clang/docs/WarningSuppressionMappings.md
index d8af856f64ef0..345b7ce5002fc 100644
--- a/clang/docs/WarningSuppressionMappings.md
+++ b/clang/docs/WarningSuppressionMappings.md
@@ -1,22 +1,19 @@
-============================
-Warning suppression mappings
-============================
+# Warning suppression mappings
-.. contents::
- :local:
+```{contents}
+:local: true
+```
-Introduction
-============
+## Introduction
Warning suppression mappings enable users to suppress Clang's diagnostics at a
per-file granularity. This allows enforcing diagnostics in specific parts of the
project even if there are violations in some headers.
-Goal and usage
-==============
+## Goal and usage
Clang allows diagnostics to be configured at a translation-unit granularity.
-If a ``foo.cpp`` is compiled with ``-Wfoo``, all transitively included headers
+If a `foo.cpp` is compiled with `-Wfoo`, all transitively included headers
also need to be clean. Hence, turning on new warnings in large codebases
requires cleaning up all the existing warnings. This might not be possible when
some dependencies aren't in the project owner's control or because new
@@ -25,51 +22,48 @@ violations are creeping up quicker than the clean up.
Warning suppression mappings aim to alleviate some of these concerns by making
diagnostic configuration granularity finer, at a source file level.
-To achieve this, user can create a file that lists which :doc:`diagnostic
+To achieve this, user can create a file that lists which {doc}`diagnostic
groups <DiagnosticsReference>` to suppress in which files or paths, and pass it
-as a command line argument to Clang with the ``--warning-suppression-mappings``
+as a command line argument to Clang with the `--warning-suppression-mappings`
flag.
Note that this mechanism won't enable any diagnostics on its own. Users should
-still turn on warnings in their compilations with explicit ``-Wfoo`` flags.
-`Controlling diagnostics pragmas
-<https://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas>`_
+still turn on warnings in their compilations with explicit `-Wfoo` flags.
+[Controlling diagnostics pragmas](https://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas)
take precedence over suppression mappings. Ensuring code author's explicit
intent is always preserved.
-Example
-=======
+## Example
-.. code-block:: bash
+```bash
+$ cat my/user/code.cpp
+#include <foo/bar.h>
+namespace { void unused_func1(); }
- $ cat my/user/code.cpp
- #include <foo/bar.h>
- namespace { void unused_func1(); }
+$ cat foo/bar.h
+namespace { void unused_func2(); }
- $ cat foo/bar.h
- namespace { void unused_func2(); }
+$ cat suppression_mappings.txt
+# Suppress -Wunused warnings in all files, apart from the ones under `foo/`.
+[unused]
+src:*
+src:*foo/*=emit
+$ clang -Wunused --warning-suppression-mappings=suppression_mappings.txt my/user/code.cpp
+# prints warning: unused function 'unused_func2', but no warnings for `unused_func1`.
+```
- $ cat suppression_mappings.txt
- # Suppress -Wunused warnings in all files, apart from the ones under `foo/`.
- [unused]
- src:*
- src:*foo/*=emit
- $ clang -Wunused --warning-suppression-mappings=suppression_mappings.txt my/user/code.cpp
- # prints warning: unused function 'unused_func2', but no warnings for `unused_func1`.
-
-Format
-======
+## Format
Warning suppression mappings uses the same format as
-:doc:`SanitizerSpecialCaseList`.
+{doc}`SanitizerSpecialCaseList`.
Sections describe which diagnostic group's behavior to change, e.g.
-``[unused]``. When a diagnostic is matched by multiple sections, the latest
+`[unused]`. When a diagnostic is matched by multiple sections, the latest
section takes precedence.
Afterwards in each section, users can have multiple entities that match source
-files based on the globs. These entities look like ``src:*/my/dir/*``.
-Users can also use the ``emit`` category to exclude a subdirectory from
+files based on the globs. These entities look like `src:*/my/dir/*`.
+Users can also use the `emit` category to exclude a subdirectory from
suppression.
Source files are matched against these globs either:
@@ -79,19 +73,20 @@ Source files are matched against these globs either:
When a source file matches multiple globs in a section, the last one takes
precedence.
-.. code-block:: bash
-
- # Lines starting with # are ignored.
- # Configure suppression globs for `-Wunused` warnings
- [unused]
- # Suppress on all files by default.
- src:*
- # But enforce for all the sources under foo/.
- src:*foo/*=emit
-
- # unused-function warnings are a subgroup of `-Wunused`. So this section
- # takes precedence over the previous one for unused-function warnings, but
- # not for unused-variable warnings.
- [unused-function]
- # Only suppress for sources under bar/.
- src:*bar/*
+```bash
+# Lines starting with # are ignored.
+# Configure suppression globs for `-Wunused` warnings
+[unused]
+# Suppress on all files by default.
+src:*
+# But enforce for all the sources under foo/.
+src:*foo/*=emit
+
+# unused-function warnings are a subgroup of `-Wunused`. So this section
+# takes precedence over the previous one for unused-function warnings, but
+# not for unused-variable warnings.
+[unused-function]
+# Only suppress for sources under bar/.
+src:*bar/*
+```
+
>From 7ec99a57be60c4497a545ff5f7ab4fae6d64a4bc Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Thu, 25 Jun 2026 22:21:19 +0000
Subject: [PATCH 2/2] [docs] Finish MyST migration for selected docs
---
clang/docs/DataFlowSanitizer.md | 4 +-
clang/docs/FunctionEffectAnalysis.md | 25 +-
clang/docs/LanguageExtensions.md | 182 +++++-----
clang/docs/LifetimeSafety.md | 414 +++++++++++------------
clang/docs/RealtimeSanitizer.md | 139 ++++----
clang/docs/ReleaseNotes.md | 68 ++--
clang/docs/SanitizerCoverage.md | 3 +-
clang/docs/ThreadSafetyAnalysis.md | 19 +-
clang/docs/ThreadSanitizer.md | 102 +++---
clang/docs/Toolchain.md | 17 +-
clang/docs/UndefinedBehaviorSanitizer.md | 257 +++++++-------
clang/docs/conf.py | 2 +
12 files changed, 614 insertions(+), 618 deletions(-)
diff --git a/clang/docs/DataFlowSanitizer.md b/clang/docs/DataFlowSanitizer.md
index 565c05b3c4b92..6a143e0bdb8c5 100644
--- a/clang/docs/DataFlowSanitizer.md
+++ b/clang/docs/DataFlowSanitizer.md
@@ -22,7 +22,7 @@ detect application-specific issues within their own code.
## How to build libc++ with DFSan
DFSan requires either all of your code to be instrumented or for uninstrumented
-functions to be listed as `uninstrumented` in the [ABI list].
+functions to be listed as `uninstrumented` in the {ref}`ABI list`.
If you'd like to have instrumented libc++ functions, then you need to build it
with DFSan instrumentation from source. Here is an example of how to build
@@ -57,6 +57,7 @@ For further information about each function, please refer to the header
file.
(abi-list)=
+(ABI list)=
### ABI List
@@ -376,4 +377,3 @@ x86_64 Linux.
## Design
Please refer to the {doc}`design document<DataFlowSanitizerDesign>`.
-
diff --git a/clang/docs/FunctionEffectAnalysis.md b/clang/docs/FunctionEffectAnalysis.md
index 9d49df44866f8..5bba219917b7b 100644
--- a/clang/docs/FunctionEffectAnalysis.md
+++ b/clang/docs/FunctionEffectAnalysis.md
@@ -2,7 +2,7 @@
```{contents}
:depth: 3
-:local: true
+:local:
```
## Introduction
@@ -245,16 +245,16 @@ following rules. Such functions:
`nonblocking` or `nonallocating` attribute (or stronger).
4. May not make direct calls to any other function, with the following exceptions:
-> 1. The callee is also explicitly declared with the same `nonblocking` or `nonallocating`
-> attribute (or stronger).
-> 2. The callee is defined in the same translation unit as the caller, does not have the `false`
-> form of the required attribute, and can be verified to have the same attribute or stronger,
-> according to these same rules.
-> 3. The callee is a built-in function that is known not to block or allocate.
-> 4. The callee is declared `noreturn` and, if compiling C++, the callee is also declared
-> `noexcept`. This special case excludes functions such as `abort()` and `std::terminate()`
-> from the analysis. (The reason for requiring `noexcept` in C++ is that a function declared
-> `noreturn` could be a wrapper for `throw`.)
+ 1. The callee is also explicitly declared with the same `nonblocking` or `nonallocating`
+ attribute (or stronger).
+ 2. The callee is defined in the same translation unit as the caller, does not have the `false`
+ form of the required attribute, and can be verified to have the same attribute or stronger,
+ according to these same rules.
+ 3. The callee is a built-in function that is known not to block or allocate.
+ 4. The callee is declared `noreturn` and, if compiling C++, the callee is also declared
+ `noexcept`. This special case excludes functions such as `abort()` and `std::terminate()`
+ from the analysis. (The reason for requiring `noexcept` in C++ is that a function declared
+ `noreturn` could be a wrapper for `throw`.)
5. May not invoke or access an Objective-C method or property, since `objc_msgSend()` calls into
the Objective-C runtime, which may allocate memory or otherwise block.
@@ -460,7 +460,7 @@ nonblocking_fp( R(*)(ArgTypes...) ) -> nonblocking_fp<R(ArgTypes...)>;
// --
-// Wrap the function pointer in a functor which preserves ``nonblocking``.
+// Wrap the function pointer in a functor which preserves nonblocking.
std::sort(vec.begin(), vec.end(), nonblocking_fp{ compare_elems });
```
@@ -494,4 +494,3 @@ are treated as built-in functions by Clang, which the diagnosis understands to b
Much of the C++ standard library consists of inline templated functions which work well with
inference. A small number of primitives may need explicit `nonblocking/nonallocating` attributes.
-
diff --git a/clang/docs/LanguageExtensions.md b/clang/docs/LanguageExtensions.md
index 71ee369347e93..59ebe04875fa9 100644
--- a/clang/docs/LanguageExtensions.md
+++ b/clang/docs/LanguageExtensions.md
@@ -24,6 +24,7 @@ to the language extensions listed here, Clang aims to support a broad range of
GCC extensions. Please see the [GCC manual](https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html) for more information on
these extensions.
+(langext-feature_check)=
(langext-feature-check)=
## Feature Checking Macros
@@ -56,7 +57,7 @@ It can be used like this:
...
```
-:::{note}
+```{note}
Prior to Clang 10, `__has_builtin` could not be used to detect most builtin
pseudo-functions.
@@ -65,7 +66,7 @@ use `#ifdef` instead.
When compiling with target offloading, `__has_builtin` only considers the
currently active target.
-:::
+```
### `__has_constexpr_builtin`
@@ -95,6 +96,7 @@ the `<cmath>` header file to conditionally make a function constexpr whenever
the constant evaluation of the corresponding builtin (for example,
`std::fmax` calls `__builtin_fmax`) is supported in Clang.
+(langext-__has_feature-__has_extension)=
(langext-has-feature-has-extension)=
### `__has_feature` and `__has_extension`
@@ -281,11 +283,12 @@ __wchar_t WideCharacter;
## Include File Checking Macros
Not all developments systems have the same include files. The
-{ref}`langext-__has_include` and {ref}`langext-__has_include_next` macros allow
+{ref}`__has_include <langext-has-include>` and {ref}`__has_include_next <langext-has-include-next>` macros allow
you to check for the existence of an include file before doing a possibly
failing `#include` directive. Include file checking macros must be used
as expressions in `#if` or `#elif` preprocessing directives.
+(langext-__has_include)=
(langext-has-include)=
### `__has_include`
@@ -312,6 +315,7 @@ To test for this feature, use `#if defined(__has_include)`:
#endif
```
+(langext-__has_include_next)=
(langext-has-include-next)=
### `__has_include_next`
@@ -357,69 +361,57 @@ option for a warning and returns `true` if that is a valid warning option.
## Builtin Macros
`__BASE_FILE__`
-
: Defined to a string that contains the name of the main input file passed to
Clang.
`__FILE_NAME__`
-
: Clang-specific extension that functions similar to `__FILE__` but only
renders the last path component (the filename) instead of an
invocation-dependent full path to that file.
`__COUNTER__`
-
: Defined to an integer value that starts at zero and is incremented each time
the `__COUNTER__` macro is expanded. This is a standard feature in C2y but
is an extension in earlier language modes and in C++. This macro can only be
expanded 2147483647 times at most.
`__INCLUDE_LEVEL__`
-
: Defined to an integral value that is the include depth of the file currently
being translated. For the main file, this value is zero.
`__TIMESTAMP__`
-
: Defined to the date and time of the last modification of the current source
file.
`__clang__`
-
: Defined when compiling with Clang.
`__clang_major__`
-
: Defined to the major marketing version number of Clang (e.g., the 2 in
2.0.1). Note that marketing version numbers should not be used to check for
language features, as different vendors use different numbering schemes.
- Instead, use the {ref}`langext-feature_check`.
+ Instead, use the {ref}`langext-feature-check`.
`__clang_minor__`
-
: Defined to the minor version number of Clang (e.g., the 0 in 2.0.1). Note
that marketing version numbers should not be used to check for language
features, as different vendors use different numbering schemes. Instead, use
- the {ref}`langext-feature_check`.
+ the {ref}`langext-feature-check`.
`__clang_patchlevel__`
-
: Defined to the marketing patch level of Clang (e.g., the 1 in 2.0.1).
`__clang_version__`
-
: Defined to a string that captures the Clang marketing version, including the
Subversion tag or revision number, e.g., "`1.5 (trunk 102332)`".
`__clang_literal_encoding__`
-
: Defined to a narrow string literal that represents the current encoding of
narrow string literals, e.g., `"hello"`. This macro typically expands to
"UTF-8" (but may change in the future if the
`-fexec-charset="Encoding-Name"` option is implemented.)
`__clang_wide_literal_encoding__`
-
: Defined to a narrow string literal that represents the current encoding of
wide string literals, e.g., `L"hello"`. This macro typically expands to
"UTF-16" or "UTF-32" (but may change in the future if the
@@ -670,24 +662,24 @@ The table below shows the support for each operation by vector extension. A
dash indicates that an operation is not accepted according to a corresponding
specification.
-| Operator | OpenCL | AltiVec | GCC | NEON | SVE | RVV |
-| -------------------------- | ------ | ------- | ---------------- | ---- | ---------- | ---------- |
-| [] | yes | yes | yes | yes | yes | yes |
-| unary operators +, -- | yes | yes | yes | yes | yes | yes |
-| ++, -- -- | yes | yes | yes | no | no | no |
-| +,--,\*,/,% | yes | yes | yes | yes | yes | yes |
-| bitwise operators &,\|,^,~ | yes | yes | yes | yes | yes | yes |
-| >>,\<< | yes | yes | yes | yes | yes | yes |
-| !, &&, \|\| | yes | -- | yes | yes | yes | yes |
-| ==, !=, >, \<, >=, \<= | yes | yes | yes | yes | yes | yes |
-| = | yes | yes | yes | yes | yes | yes |
-| ?: [^footnote-1] | yes | -- | yes | yes | yes | yes |
-| sizeof | yes | yes | yes | yes | yes [^vls] | yes [^vls] |
-| C-style cast | yes | yes | yes | no | no | yes |
-| reinterpret_cast | yes | no | yes | no | no | yes |
-| static_cast | yes | no | yes | no | no | yes |
-| const_cast | no | no | no | no | no | no |
-| address &v[i] | no | no | no [^footnote-2] | no | no | no |
+| Operator | OpenCL | AltiVec | GCC | NEON | SVE | RVV |
+| --- | --- | --- | --- | --- | --- | --- |
+| [] | yes | yes | yes | yes | yes | yes |
+| unary operators +, -- | yes | yes | yes | yes | yes | yes |
+| ++, -- -- | yes | yes | yes | no | no | no |
+| +,--,*,/,% | yes | yes | yes | yes | yes | yes |
+| bitwise operators &,\|,^,~ | yes | yes | yes | yes | yes | yes |
+| >>,<< | yes | yes | yes | yes | yes | yes |
+| !, &&, \|\| | yes | -- | yes | yes | yes | yes |
+| ==, !=, >, <, >=, <= | yes | yes | yes | yes | yes | yes |
+| = | yes | yes | yes | yes | yes | yes |
+| ?: <span class="footnote-reference brackets">[1]</span> | yes | -- | yes | yes | yes | yes |
+| sizeof | yes | yes | yes | yes | yes <a class="footnote-reference brackets" href="#vls" role="doc-noteref">[2]</a> | yes <a class="footnote-reference brackets" href="#vls" role="doc-noteref">[2]</a> |
+| C-style cast | yes | yes | yes | no | no | yes |
+| reinterpret_cast | yes | no | yes | no | no | yes |
+| static_cast | yes | no | yes | no | no | yes |
+| const_cast | no | no | no | no | no | no |
+| address &v[i] | no | no | no <span class="footnote-reference brackets">[3]</span> | no | no | no |
Both SVE and RVV define sizeless vector types which cannot be used in globals,
structs, unions, or arrays. Both provide an attribute (`arm_sve_vector_bits`
@@ -698,20 +690,32 @@ these attributes requires the command line option `-msve-vector-bits=<N>` or
supported on both sizeless and VLS types. For RVV, the operators are only
supported on VLS types.
-See also {ref}`langext-__builtin_shufflevector`, {ref}`langext-__builtin_convertvector`.
-
-[^footnote-1]: ternary operator(?:) has different behaviors depending on the condition
- operand's vector type. If the condition is a GNU vector (i.e., `__vector_size__`),
- a NEON vector, an SVE vector or an RVV vector, it's only available in C++
- and uses normal bool conversions (that is, != 0).
- If it's an extension (OpenCL) vector, it's only available in C and OpenCL C.
- And it selects based on the signedness of the condition operands (OpenCL v1.1 s6.3.9).
-
-[^vls]: sizeof can only be used on vector length specific SVE and RVV types.
-
-[^footnote-2]: Clang does not allow the address of an element to be taken while GCC
- allows this. This is intentional for vectors with a boolean element type and
- not implemented otherwise.
+See also {ref}`langext-builtin-shufflevector`, {ref}`langext-builtin-convertvector`.
+
+```{raw} html
+<aside class="footnote-list brackets">
+<aside class="footnote brackets" role="note">
+<span class="label"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></span>
+<p>ternary operator(?:) has different behaviors depending on the condition
+operand's vector type. If the condition is a GNU vector (i.e., <code class="docutils literal notranslate"><span class="pre">__vector_size__</span></code>),
+a NEON vector, an SVE vector or an RVV vector, it's only available in C++
+and uses normal bool conversions (that is, != 0).
+If it's an extension (OpenCL) vector, it's only available in C and OpenCL C.
+And it selects based on the signedness of the condition operands (OpenCL v1.1 s6.3.9).</p>
+</aside>
+<aside class="footnote brackets" id="vls" role="note">
+<span class="label"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></span>
+<span class="backrefs">(<a role="doc-backlink">1</a>,<a role="doc-backlink">2</a>)</span>
+<p>sizeof can only be used on vector length specific SVE and RVV types.</p>
+</aside>
+<aside class="footnote brackets" role="note">
+<span class="label"><span class="fn-bracket">[</span>3<span class="fn-bracket">]</span></span>
+<p>Clang does not allow the address of an element to be taken while GCC
+allows this. This is intentional for vectors with a boolean element type and
+not implemented otherwise.</p>
+</aside>
+</aside>
+```
### Vector Builtins
@@ -1671,7 +1675,7 @@ if support for the `_Alignof` keyword is enabled.
Use `__has_feature(c_atomic)` or `__has_extension(c_atomic)` to determine
if support for atomic types using `_Atomic` is enabled. Clang also provides
-{ref}`a set of builtins <langext-__c11_atomic>` which can be used to implement
+{ref}`a set of builtins <langext-c11-atomic>` which can be used to implement
the `<stdatomic.h>` operations on `_Atomic` types. Use
`__has_include(<stdatomic.h>)` to determine if C11's `<stdatomic.h>` header
is available.
@@ -1856,7 +1860,7 @@ template <template <class IntSeqT, IntSeqT... Ints> class IntSeq, class T, T N>
using __make_integer_seq = ...;
```
-This alias returns `IntSeq` instantiated with ``` IntSeqT = T``and ``Ints ``` being the pack `0, ..., N - 1`.
+This alias returns `IntSeq` instantiated with `IntSeqT = T` and `Ints` being the pack `0, ..., N - 1`.
### \_\_builtin_dedup_pack
@@ -2048,9 +2052,10 @@ The following type trait primitives are supported by Clang. Those traits marked
- `__reference_constructs_from_temporary(T, U)` (C++)
Returns true if a reference `T` can be direct-initialized from a temporary of type
a non-cv-qualified `U`.
-- `__reference_converts_from_temporary(T, U)` (C++)
- : Returns true if a reference `T` can be copy-initialized from a temporary of type
- a non-cv-qualified `U`.
+
+`__reference_converts_from_temporary(T, U)` (C++)
+: Returns true if a reference `T` can be copy-initialized from a temporary of type
+ a non-cv-qualified `U`.
- `__underlying_type` (C++, GNU, Microsoft)
- `__builtin_lt_synthesizes_from_spaceship`, `__builtin_gt_synthesizes_from_spaceship`,
`__builtin_le_synthesizes_from_spaceship`, `__builtin_ge_synthesizes_from_spaceship` (Clang):
@@ -2116,6 +2121,7 @@ struct is_convertible_to {
#endif
```
+(builtin_structured_binding_size-doc)=
(builtin-structured-binding-size-doc)=
### \_\_builtin_structured_binding_size (C++)
@@ -2419,10 +2425,11 @@ of types containing such declarations are affected accordingly.
This extension can be controlled independently of other Microsoft extensions:
-- `-fms-anonymous-structs`
- : Enable named anonymous struct/union support
-- `-fno-ms-anonymous-structs`
- : Disable anonymous struct/union support
+`-fms-anonymous-structs`
+: Enable named anonymous struct/union support
+
+`-fno-ms-anonymous-structs`
+: Disable anonymous struct/union support
This extension is also **implicitly enabled** when either of the following options is used:
@@ -2555,7 +2562,7 @@ void foo(__attribute__((ns_consumed)) NSString *string);
```
Further examples of these attributes are available in the static analyzer's
-[list of annotations for analysis](analyzer/user-docs/Annotations.html#cocoa-mem).
+{ref}`list of annotations for analysis <cocoa_mem>`.
Query for these features with `__has_attribute(ns_consumed)`,
`__has_attribute(ns_returns_retained)`, etc.
@@ -3111,6 +3118,7 @@ argument whose value is the alignment constraint, as a power of 2 in *bits*.
Query for this feature with `__has_builtin(__builtin_alloca_with_align)`.
+(langext-__builtin_assume)=
(langext-builtin-assume)=
### `__builtin_assume`
@@ -3146,6 +3154,7 @@ evaluated, so any side effects of the expression will be discarded.
Query for this feature with `__has_builtin(__builtin_assume)`.
+(langext-__builtin_assume_separate_storage)=
(langext-builtin-assume-separate-storage)=
### `__builtin_assume_separate_storage`
@@ -3500,6 +3509,7 @@ This builtin can be used in constant expressions.
Query for this feature with `__has_builtin(__builtin_dump_struct)`
+(langext-__builtin_shufflevector)=
(langext-builtin-shufflevector)=
### `__builtin_shufflevector`
@@ -3555,6 +3565,7 @@ indices specified.
Query for this feature with `__has_builtin(__builtin_shufflevector)`.
+(langext-__builtin_convertvector)=
(langext-builtin-convertvector)=
### `__builtin_convertvector`
@@ -4106,7 +4117,7 @@ __builtin_debugtrap()
**Description**
-`__builtin_debugtrap` is lowered to the \` `llvm.debugtrap` \<<https://llvm.org/docs/LangRef.html#llvm-debugtrap-intrinsic>>\`\_ builtin. It should have the same effect as setting a breakpoint on the line where the builtin is called.
+`__builtin_debugtrap` is lowered to the [`llvm.debugtrap`](https://llvm.org/docs/LangRef.html#llvm-debugtrap-intrinsic) builtin. It should have the same effect as setting a breakpoint on the line where the builtin is called.
Query for this feature with `__has_builtin(__builtin_debugtrap)`.
@@ -4122,7 +4133,7 @@ __builtin_trap()
**Description**
-`__builtin_trap` is lowered to the \` `llvm.trap` \<<https://llvm.org/docs/LangRef.html#llvm-trap-intrinsic>>\`\_ builtin.
+`__builtin_trap` is lowered to the [`llvm.trap`](https://llvm.org/docs/LangRef.html#llvm-trap-intrinsic) builtin.
Query for this feature with `__has_builtin(__builtin_trap)`.
@@ -4154,7 +4165,7 @@ __builtin_verbose_trap(const char *category, const char *reason)
**Description**
-`__builtin_verbose_trap` is lowered to the \` `llvm.trap` \<<https://llvm.org/docs/LangRef.html#llvm-trap-intrinsic>>\`\_ builtin.
+`__builtin_verbose_trap` is lowered to the [`llvm.trap`](https://llvm.org/docs/LangRef.html#llvm-trap-intrinsic) builtin.
Additionally, clang emits debugging information that represents an artificial
inline frame whose name encodes the category and reason strings passed to the builtin,
prefixed by a "magic" prefix.
@@ -4434,6 +4445,7 @@ implemented in a way where the counter assignment can happen automatically.
to a variable, have its address taken, or passed into or returned from a
function, because doing so violates bounds safety conventions.
+(builtin_stack_address-doc)=
(builtin-stack-address-doc)=
### `__builtin_stack_address`
@@ -4617,7 +4629,7 @@ positive zero, positive subnormal and positive normal classes.
`__builtin_isfpclass(x, 448)` would return true only if `x` if of any of
these data classes. Using suitable mask value, the function can implement any of
the standard classification functions, for example, `__builtin_isfpclass(x, 3)`
-is identical to `isnan`,\`\`\_\_builtin_isfpclass(x, 504)\`\` - to `isfinite`
+is identical to `isnan`, `__builtin_isfpclass(x, 504)` - to `isfinite`
and so on.
If the first argument is a vector, the function is equivalent to the set of
@@ -4885,6 +4897,7 @@ In terms of acquire-release ordering barriers these two operations are always
considered as operations with *load-store* semantics, even when the original value
is not actually modified after comparison.
+(langext-__c11_atomic)=
(langext-c11-atomic)=
### \_\_c11_atomic builtins
@@ -4928,6 +4941,7 @@ builtin function, and are named with a `__opencl_` prefix. The macros
and `__OPENCL_MEMORY_SCOPE_SUB_GROUP` are provided, with values
corresponding to the enumerators of OpenCL's `memory_scope` enumeration.)
+(langext-__scoped_atomic)=
(langext-scoped-atomic)=
### \_\_scoped_atomic builtins
@@ -5004,10 +5018,10 @@ will be used.
### C++ Coroutines support builtins
-:::{warning}
+```{warning}
This is a work in progress. Compatibility across Clang/LLVM releases is not
guaranteed.
-:::
+```
Clang provides experimental builtins to support C++ Coroutines as defined by
<https://wg21.link/P0057>. The following four are intended to be used by the
@@ -5236,9 +5250,10 @@ For example, this applies the GNU `unused` attribute to `a` and `f`, and
also applies the GNU `noreturn` attribute to `f`.
Examples:
-.. code-block:: c++
-> \[[gnu::unused]\] int a, f \[[gnu::noreturn]\] ();
+```c++
+[[gnu::unused]] int a, f [[gnu::noreturn]] ();
+```
## Target-Specific Extensions
@@ -5420,7 +5435,7 @@ void __builtin_amdgcn_av_store_b128(v4u *dst, v4u data, int scope);
Load or store a vector of 4 unsigned integers from or to memory with cache
behavior specified by `scope`, which is one of the `__MEMORY_SCOPE_*` macros
-defined for {ref}`scoped atomic builtins<langext-__c11_atomic>`.
+defined for {ref}`scoped atomic builtins <langext-c11-atomic>`.
The pointer argument must point to the global or generic address space.
@@ -5531,7 +5546,7 @@ __builtin_dcbf (&a);
Clang supports additional attributes that are useful for documenting program
invariants and rules for static analysis tools, such as the [Clang Static
Analyzer](https://clang-analyzer.llvm.org/). These attributes are documented
-in the analyzer's [list of annotations for analysis](analyzer/user-docs/Annotations.html).
+in the analyzer's {doc}`list of annotations for analysis <analyzer/user-docs/Annotations>`.
## Extensions for Dynamic Analysis
@@ -5654,17 +5669,17 @@ all optimizations, `s`, `g`, `t`, and `y`. An empty optimization and
`on` parameter will reset the optimizations to the ones specified on the
commandline.
-```{eval-rst}
-.. list-table:: Parameters (unsupported by Clang)
+```{list-table} Parameters (unsupported by Clang)
+:header-rows: 1
- * - Parameter
- - Type of optimization
- * - g
- - Deprecated
- * - s or t
- - Short or fast sequences of machine code
- * - y
- - Enable frame pointers
+* - Parameter
+ - Type of optimization
+* - g
+ - Deprecated
+* - s or t
+ - Short or fast sequences of machine code
+* - y
+ - Enable frame pointers
```
## Extensions for loop hint optimizations
@@ -6263,7 +6278,7 @@ required) to add a namespace to your push/pop directives. A pop directive with a
namespace will pop the innermost push that has that same namespace. This will
ensure that another macro's `pop` won't inadvertently pop your attribute. Note
that an `pop` without a namespace will pop the innermost `push` without a
-namespace. ``` push``es with a namespace can only be popped by ``pop ``` with the
+namespace. `push`es with a namespace can only be popped by `pop` with the
same namespace. For instance:
```c++
@@ -6826,9 +6841,9 @@ The `clang::offset` embed parameter may appear zero or one time in the
embed parameter sequence. Its preprocessor argument clause shall be present and
have the form:
-..code-block: text
-
-> ( constant-expression )
+```text
+( constant-expression )
+```
and shall be an integer constant expression. The integer constant expression
shall not evaluate to a value less than 0. The token `defined` shall not
@@ -6956,4 +6971,3 @@ constexpr int x = sizeof(x);
// diagnostic.
auto x = x;
```
-
diff --git a/clang/docs/LifetimeSafety.md b/clang/docs/LifetimeSafety.md
index ece233d3ec641..11393db4c9373 100644
--- a/clang/docs/LifetimeSafety.md
+++ b/clang/docs/LifetimeSafety.md
@@ -30,11 +30,11 @@ with attributes like [clang::lifetimebound](https://clang.llvm.org/docs/Attribut
lifetime safety at call sites with higher accuracy. This approach supports
gradual adoption in existing codebases.
-:::{note}
+```{note}
This analysis is designed for bug finding, not verification. It may miss some
lifetime issues and can produce false positives. It does not guarantee the
absence of all lifetime bugs.
-:::
+```
### Getting Started
@@ -128,14 +128,14 @@ details on these attributes, see the Clang attribute reference for
[gsl::Owner](https://clang.llvm.org/docs/AttributeReference.html#gsl-owner) and
[gsl::Pointer](https://clang.llvm.org/docs/AttributeReference.html#gsl-pointer).
-:::{note}
+```{note}
Types with mixed ownership semantics (owning some data while holding views to
other data) or types with multiple view fields with different lifetimes should
not be annotated. The analysis does not yet support expressing such nuanced
lifetime relationships.
Future enhancements, such as named lifetimes, may provide better support for
these patterns.
-:::
+```
### LifetimeBound
@@ -231,68 +231,66 @@ div.good-code .highlight, div.good-code pre { background-color: transparent !imp
This check warns when a pointer or reference is used after the stack variable
it refers to has gone out of scope.
-```{eval-rst}
-.. list-table::
- :widths: 50 50
- :header-rows: 1
- :class: colored-code-table
-
- * - Use after scope
- - Correct
- * -
- .. code-block:: c++
-
- void foo() {
- int* p;
- {
- int i = 0;
- p = &i; // warning: 'p' does not live long enough
- } // note: destroyed here
- (void)*p; // note: later used here
- }
- -
- .. code-block:: c++
-
- void foo() {
- int i = 0;
- int* p;
- {
- p = &i; // OK!
- }
- (void)*p;
- }
-```
+````{list-table}
+:widths: 50 50
+:header-rows: 1
+:class: colored-code-table
+
+* - Use after scope
+ - Correct
+* -
+ ```c++
+ void foo() {
+ int* p;
+ {
+ int i = 0;
+ p = &i; // warning: 'p' does not live long enough
+ } // note: destroyed here
+ (void)*p; // note: later used here
+ }
+ ```
+ -
+ ```c++
+ void foo() {
+ int i = 0;
+ int* p;
+ {
+ p = &i; // OK!
+ }
+ (void)*p;
+ }
+ ```
+````
### Use after free
This check warns when a pointer or reference is used after the object it refers
to has been freed.
-```{eval-rst}
-.. list-table::
- :widths: 50 50
- :header-rows: 1
- :class: colored-code-table
-
- * - Use after free
- - Correct
- * -
- .. code-block:: c++
-
- void foo() {
- int *p = new int(0); // warning: allocated object does not live long enough
- delete p; // note: freed here
- (void)*p; // note: later used here
- }
- -
- .. code-block:: c++
-
- void foo() {
- int *p = new int(0);
- (void)*p;
- delete p; // OK!
- }
-```
+````{list-table}
+:widths: 50 50
+:header-rows: 1
+:class: colored-code-table
+
+* - Use after free
+ - Correct
+* -
+ ```c++
+ void foo() {
+ int *p = new int(0); // warning: allocated object does not live long enough
+ delete p; // note: freed here
+ (void)*p; // note: later used here
+ }
+ ```
+ -
+ ```c++
+ void foo() {
+ int *p = new int(0);
+ (void)*p;
+ delete p; // OK!
+ }
+ ```
+````
### Return of stack address
@@ -300,87 +298,82 @@ This check warns when a function returns a pointer or reference to a
stack-allocated variable, which will be destroyed when the function returns,
leaving the caller with a dangling pointer.
-```{eval-rst}
-.. list-table::
- :widths: 50 50
- :header-rows: 1
- :class: colored-code-table
-
- * - Return of stack address
- - Correct
- * -
- .. code-block:: c++
-
- #include <string>
- #include <string_view>
-
- std::string_view bar() {
- std::string s = "on stack";
- std::string_view result = s;
- // warning: address of stack variable 's' is returned later
- return result; // note: returned here
- }
- -
- .. code-block:: c++
-
- #include <string>
- #include <string_view>
-
- std::string bar() {
- std::string s = "on stack";
- std::string_view result = s;
- return result; // OK!
- }
-
-```
+````{list-table}
+:widths: 50 50
+:header-rows: 1
+:class: colored-code-table
+
+* - Return of stack address
+ - Correct
+* -
+ ```c++
+ #include <string>
+ #include <string_view>
+
+ std::string_view bar() {
+ std::string s = "on stack";
+ std::string_view result = s;
+ // warning: address of stack variable 's' is returned later
+ return result; // note: returned here
+ }
+ ```
+ -
+ ```c++
+ #include <string>
+ #include <string_view>
+
+ std::string bar() {
+ std::string s = "on stack";
+ std::string_view result = s;
+ return result; // OK!
+ }
+ ```
+````
### Dangling field
This check warns when a constructor or method assigns a pointer to a
stack-allocated variable or temporary to a field of the class.
-```{eval-rst}
-.. list-table::
- :widths: 50 50
- :header-rows: 1
- :class: colored-code-table
-
-
- * - Dangling field
- - Correct
- * -
- .. code-block:: c++
-
- #include <string>
- #include <string_view>
-
- // Constructor finishes, leaving 'field' dangling.
- struct DanglingField {
- std::string_view field; // note: this field dangles
- DanglingField(std::string s) {
- field = s; // warning: stack variable 's' escapes to a field
- }
- };
- -
- .. code-block:: c++
-
- // Make the field an owner.
- struct DanglingField {
- std::string field;
- DanglingField(std::string s) {
- field = s;
- }
- };
- // Or take a string_view parameter.
- struct DanglingField {
- std::string_view field;
- DanglingField(std::string_view s [[clang::lifetimebound]]) {
- field = s;
- }
- };
- };
-
-```
+````{list-table}
+:widths: 50 50
+:header-rows: 1
+:class: colored-code-table
+
+* - Dangling field
+ - Correct
+* -
+ ```c++
+ #include <string>
+ #include <string_view>
+
+ // Constructor finishes, leaving 'field' dangling.
+ struct DanglingField {
+ std::string_view field; // note: this field dangles
+ DanglingField(std::string s) {
+ field = s; // warning: stack variable 's' escapes to a field
+ }
+ };
+ ```
+ -
+ ```c++
+ // Make the field an owner.
+ struct DanglingField {
+ std::string field;
+ DanglingField(std::string s) {
+ field = s;
+ }
+ };
+ // Or take a string_view parameter.
+ struct DanglingField {
+ std::string_view field;
+ DanglingField(std::string_view s [[clang::lifetimebound]]) {
+ field = s;
+ }
+ };
+ };
+ ```
+````
### Use after invalidation (experimental)
@@ -391,41 +384,39 @@ as `std::unique_ptr` after operations like `reset`. For example, adding
elements to `std::vector` may cause reallocation, invalidating all existing
iterators, pointers and references to its elements.
-:::{note}
+```{note}
Invalidation checking is highly experimental and may produce false positives.
-:::
-
-```{eval-rst}
-.. list-table::
- :widths: 50 50
- :header-rows: 1
- :class: colored-code-table
-
-
- * - Use after invalidation (experimental)
- - Correct
- * -
- .. code-block:: c++
-
- #include <vector>
-
- void baz(std::vector<int>& v) {
- int* p = &v[0]; // warning: 'v' is later invalidated
- v.push_back(4); // note: invalidated here
- *p = 10; // note: later used here
- }
- -
- .. code-block:: c++
-
- #include <vector>
-
- void baz(std::vector<int>& v) {
- v.push_back(4);
- int* p = &v[0]; // OK!
- *p = 10;
- }
```
+````{list-table}
+:widths: 50 50
+:header-rows: 1
+:class: colored-code-table
+
+* - Use after invalidation (experimental)
+ - Correct
+* -
+ ```c++
+ #include <vector>
+
+ void baz(std::vector<int>& v) {
+ int* p = &v[0]; // warning: 'v' is later invalidated
+ v.push_back(4); // note: invalidated here
+ *p = 10; // note: later used here
+ }
+ ```
+ -
+ ```c++
+ #include <vector>
+
+ void baz(std::vector<int>& v) {
+ v.push_back(4);
+ int* p = &v[0]; // OK!
+ *p = 10;
+ }
+ ```
+````
+
The analysis also treats explicit destruction as invalidation. Explicit
destructor calls and `std::destroy_at` invalidate pointers, references and
views into the destroyed object.
@@ -488,6 +479,7 @@ translation-unit-wide analysis using:
- `-fexperimental-lifetime-safety-tu-analysis`: Enables TU-wide analysis
for better inference results.
+(warning_flags)=
(warning-flags)=
## Warning flags
@@ -547,50 +539,49 @@ owner that will go out of scope.
For example:
-```{eval-rst}
-.. list-table::
- :widths: 50 50
- :header-rows: 1
- :align: left
- :class: colored-code-table
-
- * - Anti-Pattern: Aliasing Before Move
- - Good Practice: Move-First-Then-Alias
- * -
- .. code-block:: c++
-
- #include <memory>
-
- void use(int*);
-
- void bar() {
- std::unique_ptr<int> b;
- int* p;
- {
- auto a = std::make_unique<int>(42);
- p = a.get(); // warning!
- b = std::move(a);
- }
- use(p);
- }
- -
- .. code-block:: c++
-
- #include <memory>
-
- void use(int*);
-
- void bar() {
- std::unique_ptr<int> b;
- int* p;
- {
- auto a = std::make_unique<int>(42);
- b = std::move(a);
- p = b.get(); // OK!
- }
- use(p);
- }
-```
+````{list-table}
+:widths: 50 50
+:header-rows: 1
+:align: left
+:class: colored-code-table
+
+* - Anti-Pattern: Aliasing Before Move
+ - Good Practice: Move-First-Then-Alias
+* -
+ ```c++
+ #include <memory>
+
+ void use(int*);
+
+ void bar() {
+ std::unique_ptr<int> b;
+ int* p;
+ {
+ auto a = std::make_unique<int>(42);
+ p = a.get(); // warning!
+ b = std::move(a);
+ }
+ use(p);
+ }
+ ```
+ -
+ ```c++
+ #include <memory>
+
+ void use(int*);
+
+ void bar() {
+ std::unique_ptr<int> b;
+ int* p;
+ {
+ auto a = std::make_unique<int>(42);
+ b = std::move(a);
+ p = b.get(); // OK!
+ }
+ use(p);
+ }
+ ```
+````
The same principle applies when moving ownership using `std::unique_ptr::release()`:
@@ -690,4 +681,3 @@ with very large or complex CFGs, analysis time can sometimes be significant. To
this, the analysis allows to skip functions where the number of CFG blocks exceeds
a certain threshold, controlled by the `-lifetime-safety-max-cfg-blocks=N` language
option.
-
diff --git a/clang/docs/RealtimeSanitizer.md b/clang/docs/RealtimeSanitizer.md
index 629a5df0e6b8f..ee77ed7c4ab29 100644
--- a/clang/docs/RealtimeSanitizer.md
+++ b/clang/docs/RealtimeSanitizer.md
@@ -149,51 +149,50 @@ You can see all sanitizer options (some of which are unsupported) by using the `
A **partial** list of flags RealtimeSanitizer respects:
-```{eval-rst}
-.. list-table:: Run-time Flags
- :widths: 20 10 10 70
- :header-rows: 1
-
- * - Flag name
- - Default value
- - Type
- - Short description
- * - ``halt_on_error``
- - ``true``
- - boolean
- - Exit after first reported error.
- * - ``suppress_equal_stacks``
- - ``true``
- - boolean
- - If true, suppress duplicate reports (i.e. only print each unique error once). Only particularly useful when ``halt_on_error=false``.
- * - ``print_stats_on_exit``
- - ``false``
- - boolean
- - Print stats on exit. Includes total and unique errors.
- * - ``color``
- - ``"auto"``
- - string
- - Colorize reports: (always|never|auto).
- * - ``fast_unwind_on_fatal``
- - ``false``
- - boolean
- - If available, use the fast frame-pointer-based unwinder on detected errors. If true, ensure the code under test has been compiled with frame pointers with ``-fno-omit-frame-pointers`` or similar.
- * - ``abort_on_error``
- - OS dependent
- - boolean
- - If true, the tool calls ``abort()`` instead of ``_exit()`` after printing the error report. On some OSes (macOS, for example) this is beneficial because a better stack trace is emitted on crash.
- * - ``symbolize``
- - ``true``
- - boolean
- - If set, use the symbolizer to turn virtual addresses to file/line locations. If false, can greatly speed up the error reporting.
- * - ``suppressions``
- - ``""``
- - path
- - If set to a valid suppressions file, will suppress issue reporting. See details in `Disabling and Suppressing`_.
- * - ``verify_interceptors``
- - ``true``
- - boolean
- - If true, verifies interceptors are working at initialization. The program will abort with error ``==ERROR: Interceptors are not working. This may be because RealtimeSanitizer is loaded too late (e.g. via dlopen)`` if an issue is detected.
+```{list-table} Run-time Flags
+:widths: 20 10 10 70
+:header-rows: 1
+
+* - Flag name
+ - Default value
+ - Type
+ - Short description
+* - `halt_on_error`
+ - `true`
+ - boolean
+ - Exit after first reported error.
+* - `suppress_equal_stacks`
+ - `true`
+ - boolean
+ - If true, suppress duplicate reports (i.e. only print each unique error once). Only particularly useful when `halt_on_error=false`.
+* - `print_stats_on_exit`
+ - `false`
+ - boolean
+ - Print stats on exit. Includes total and unique errors.
+* - `color`
+ - `"auto"`
+ - string
+ - Colorize reports: (always|never|auto).
+* - `fast_unwind_on_fatal`
+ - `false`
+ - boolean
+ - If available, use the fast frame-pointer-based unwinder on detected errors. If true, ensure the code under test has been compiled with frame pointers with `-fno-omit-frame-pointers` or similar.
+* - `abort_on_error`
+ - OS dependent
+ - boolean
+ - If true, the tool calls `abort()` instead of `_exit()` after printing the error report. On some OSes (macOS, for example) this is beneficial because a better stack trace is emitted on crash.
+* - `symbolize`
+ - `true`
+ - boolean
+ - If set, use the symbolizer to turn virtual addresses to file/line locations. If false, can greatly speed up the error reporting.
+* - `suppressions`
+ - `""`
+ - path
+ - If set to a valid suppressions file, will suppress issue reporting. See details in [Disabling and Suppressing](#disabling-and-suppressing).
+* - `verify_interceptors`
+ - `true`
+ - boolean
+ - If true, verifies interceptors are working at initialization. The program will abort with error `==ERROR: Interceptors are not working. This may be because RealtimeSanitizer is loaded too late (e.g. via dlopen)` if an issue is detected.
```
Some issues with flags can be debugged using the `verbosity=$NUM` flag:
@@ -249,31 +248,30 @@ There are multiple ways to disable error reporting when using RealtimeSanitizer.
In general, `ScopedDisabler` should be preferred, as it is the most performant.
-```{eval-rst}
-.. list-table:: Suppression methods
- :widths: 30 15 15 10 70
- :header-rows: 1
-
- * - Method
- - Specified at?
- - Scope
- - Run-time cost
- - Description
- * - ``ScopedDisabler``
- - Compile-time
- - Stack
- - Very low
- - Violations are ignored for the lifetime of the ``ScopedDisabler`` object.
- * - ``function-name-matches`` suppression
- - Run-time
- - Single function
- - Medium
- - Suppresses intercepted and ``[[clang::blocking]]`` function calls by name.
- * - ``call-stack-contains`` suppression
- - Run-time
- - Stack
- - High
- - Suppresses any stack trace containing the specified pattern.
+```{list-table} Suppression methods
+:widths: 30 15 15 10 70
+:header-rows: 1
+
+* - Method
+ - Specified at?
+ - Scope
+ - Run-time cost
+ - Description
+* - `ScopedDisabler`
+ - Compile-time
+ - Stack
+ - Very low
+ - Violations are ignored for the lifetime of the `ScopedDisabler` object.
+* - `function-name-matches` suppression
+ - Run-time
+ - Single function
+ - Medium
+ - Suppresses intercepted and `[[clang::blocking]]` function calls by name.
+* - `call-stack-contains` suppression
+ - Run-time
+ - Stack
+ - High
+ - Suppresses any stack trace containing the specified pattern.
```
@@ -346,4 +344,3 @@ Clang provides the pre-processor macro `__has_feature` which may be used to dete
...
#endif
```
-
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 70e62a46e3caa..d38c581abc575 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -1,28 +1,36 @@
+---
+myst:
+ enable_extensions:
+ - attrs_block
+ - substitution
+---
+
% If you want to modify sections/contents permanently, you should modify both
-% ReleaseNotes.rst and ReleaseNotesTemplate.txt.
+% ReleaseNotes.md and ReleaseNotesTemplate.txt.
-# Clang {{ release }} {{ ReleaseNotesTitle }}
+{#clang-release-releasenotestitle}
+# Clang {{ (('(In-Progress) ' if env.app.tags.has('PreRelease') else '') ~ 'Release Notes') if env.config.project == 'Clang' else '|ReleaseNotesTitle|' }}
```{contents}
:depth: 2
-:local: true
+:local:
```
Written by the [LLVM Team](https://llvm.org/)
-::::{only} PreRelease
+````{only} PreRelease
-:::{warning}
-These are in-progress notes for the upcoming Clang {{ version }} release.
+```{warning}
+These are in-progress notes for the upcoming Clang {{env.config.version}} release.
Release notes for previous releases can be found on
[the Releases Page](https://llvm.org/releases/).
-:::
-::::
+```
+````
## Introduction
This document contains the release notes for the Clang C/C++/Objective-C
-frontend, part of the LLVM Compiler Infrastructure, release {{ release }}. Here we
+frontend, part of the LLVM Compiler Infrastructure, release {{env.config.release}}. Here we
describe the status of Clang in some detail, including major
improvements from the previous release and new feature work. For the
general LLVM release notes, see [the LLVM
@@ -184,7 +192,8 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the
section 6.11.d states that "Variable length arrays and structures with
flexible (or unsized) arrays are not supported."
-## What's New in Clang {{ release }}?
+{#what-s-new-in-clang-release}
+## What's New in Clang {{env.config.release}}?
### C++ Language Changes
@@ -363,11 +372,11 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the
a hostname when generates the hashes. Known issues -- does not remap the
source file pathes within PCH/PCM files.
- New `-cl` option `/experimental:deterministic` added to match CL's option.
- This enables warning emission on usage of non-deterministic macros \_\_DATE\_\_,
- \_\_TIME\_\_ and \_\_TIMESTAMP\_\_ and provides reproducable COFF's timestamp for
+ This enables warning emission on usage of non-deterministic macros `__DATE__`,
+ `__TIME__` and `__TIMESTAMP__` and provides reproducable COFF's timestamp for
the output object files.
- New `-cl` option `/d1nodatetime` added to match CL's option. This option
- undefines the standard macros \_\_DATE\_\_, \_\_TIME\_\_ and \_\_TIMESTAMP\_\_ to allow
+ undefines the standard macros `__DATE__`, `__TIME__` and `__TIMESTAMP__` to allow
reproducable builds. These macros can be redefined from the command line if
necessary. `/d1nodatetime-` can be used to turn this feature off if
necessary to override the common build settings.
@@ -387,9 +396,9 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the
normalized in favor of the target system (same as the preprocessor does
for the file macros) and allows the reproducable IDs on any build system.
- `-fprofile-update=atomic` will now promote counter updates out of loops,
- similar to the non-atomic case (\[#202487\](<https://github.com/llvm/llvm-project/pull/202487>)).
+ similar to the non-atomic case ([#202487](https://github.com/llvm/llvm-project/pull/202487)).
- The `-cl` `/Brepro` option was modified to match the original CL's option
- and now defines the standard macros \_\_DATE\_\_, \_\_TIME\_\_ and \_\_TIMESTAMP\_\_ to
+ and now defines the standard macros `__DATE__`, `__TIME__` and `__TIMESTAMP__` to
"1". The previous functionality remains unchanged.
### Removed Compiler Flags
@@ -672,7 +681,7 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the
- Clang now emits an error when returning an initializer list from a lambda
with an explicit return type of void. The diagnostic now correctly refers
to "lambda" instead of "block". (#GH188661)
-- Fixed a crash on \_BitInt(N) arrays where 129 ≤ N ≤ 192 due to incorrect array filler lowering. (#GH189643)
+- Fixed a crash on `_BitInt(N)` arrays where 129 ≤ N ≤ 192 due to incorrect array filler lowering. (#GH189643)
- Fixed the behavior in C23 of `auto`, by emitting an error when an array type is specified for a `char *`. (#GH162694)
- Fixed an issue where an assert was thrown instead of an error if no vulkan env was specified with `--triple spirv`. (#GH189964)
- Fixed incorrect rejection of `auto` with reordered declaration specifiers in C23. (#GH164121)
@@ -861,19 +870,11 @@ Added support for the Arm AGI CPU via the `-mcpu=armagicpu` command-line option.
`-fwinx64-eh-unwindv2=` flag is deprecated; it is still accepted and mapped
onto the new flag as follows:
- ```{eval-rst}
- .. list-table::
- :header-rows: 1
-
- * - Legacy ``-fwinx64-eh-unwindv2=``
- - New ``-fwinx64-eh-unwind=``
- * - ``disabled``
- - ``v1`` (default; no flag forwarded)
- * - ``best-effort``
- - ``v2-best-effort``
- * - ``required``
- - ``v2-required``
- ```
+ | Legacy `-fwinx64-eh-unwindv2=` | New `-fwinx64-eh-unwind=` |
+ | --- | --- |
+ | `disabled` | `v1` (default; no flag forwarded) |
+ | `best-effort` | `v2-best-effort` |
+ | `required` | `v2-required` |
The MSVC-compatible `/d2epilogunwind` and `/d2epilogunwindrequirev2`
options map to `v2-best-effort` and `v2-required` respectively.
@@ -890,8 +891,8 @@ Added support for the Arm AGI CPU via the `-mcpu=armagicpu` command-line option.
#### RISC-V Support
- Tenstorrent Ascalon D8 was renamed to Ascalon X. Use `tt-ascalon-x` with `-mcpu` or `-mtune`.
-- Intrinsics were added for the 'Zvabd\` (RISC-V Integer Vector Absolute Difference) extension.
-- Intrinsics were added for the 'Zvzip\` (Reordering Structured Data in Vector Registers) extension.
+- Intrinsics were added for the `Zvabd` (RISC-V Integer Vector Absolute Difference) extension.
+- Intrinsics were added for the `Zvzip` (Reordering Structured Data in Vector Registers) extension.
- A new `-mtune` syntax was added to support processor-specific tuning feature string
Currently this new syntax is gated by the `-mexperimental-mtune-syntax` flag.
@@ -980,8 +981,8 @@ Added support for the Arm AGI CPU via the `-mcpu=armagicpu` command-line option.
- Fix crash in clang_getBinaryOperatorKindSpelling and clang_getUnaryOperatorKindSpelling
- The clang_Module_getASTFile API is deprecated and now always returns nullptr
- The clang_Cursor_getCommentRange API will now return a comment range for macro definitions that have documentation comments.
-- Added CXType_PredefinedSugar for \_\_ptrdiff_t, \_\_size_t, and
- \_\_signed_size_t types, which are no longer exposed as
+- Added CXType_PredefinedSugar for `__ptrdiff_t`, `__size_t`, and
+ `__signed_size_t` types, which are no longer exposed as
CXType_Unexposed.
### Code Completion
@@ -1096,4 +1097,3 @@ tree.
If you have any questions or comments about Clang, please feel free to
contact us on the [Discourse forums (Clang Frontend category)](https://discourse.llvm.org/c/clang/6).
-
diff --git a/clang/docs/SanitizerCoverage.md b/clang/docs/SanitizerCoverage.md
index c48298bd8ffc3..f859838616b49 100644
--- a/clang/docs/SanitizerCoverage.md
+++ b/clang/docs/SanitizerCoverage.md
@@ -1,7 +1,7 @@
# SanitizerCoverage
```{contents}
-:local: true
+:local:
```
## Introduction
@@ -618,4 +618,3 @@ This can be changed with `ASAN_OPTIONS=coverage_dir=/path`:
-rw-r----- 1 kcc eng 4 Nov 27 12:21 a.out.22673.sancov
-rw-r----- 1 kcc eng 8 Nov 27 12:21 a.out.22679.sancov
```
-
diff --git a/clang/docs/ThreadSafetyAnalysis.md b/clang/docs/ThreadSafetyAnalysis.md
index 686493874901d..012c8a4c41373 100644
--- a/clang/docs/ThreadSafetyAnalysis.md
+++ b/clang/docs/ThreadSafetyAnalysis.md
@@ -444,7 +444,7 @@ helpers. Otherwise, best practice is to avoid explicitly acquiring a capability
multiple times within the same function, and letting the analysis produce
warnings on double-acquisition attempts.
-(scoped-capability)=
+(scoped_capability)=
### SCOPED_CAPABILITY
@@ -544,12 +544,14 @@ supported yet.
### Warning flags
-- `-Wthread-safety`: Umbrella flag which turns on the following:
+- `-Wthread-safety`: Umbrella flag which turns on the following:
- `-Wthread-safety-attributes`: Semantic checks for thread safety attributes.
- `-Wthread-safety-analysis`: The core analysis.
- - `-Wthread-safety-precise`: Requires that mutex expressions match precisely.
- : This warning can be disabled for code which has a lot of aliases.
+
+ `-Wthread-safety-precise`: Requires that mutex expressions match precisely.
+ : This warning can be disabled for code which has a lot of aliases.
+
- `-Wthread-safety-reference`: Checks when guarded members are passed or
returned by reference.
@@ -652,16 +654,16 @@ by passing `-Wthread-safety-negative`.
## Frequently Asked Questions
-17. Should I put attributes in the header file, or in the .cc/.cpp/.cxx file?
+(Q) Should I put attributes in the header file, or in the .cc/.cpp/.cxx file?
(A) Attributes are part of the formal interface of a function, and should
always go in the header, where they are visible to anything that includes
the header. Attributes in the `.cpp` file are not visible outside of the
immediate translation unit, which leads to false negatives and false positives.
-17. "*Mutex is not locked on every path through here?*" What does that mean?
+(Q) "*Mutex is not locked on every path through here?*" What does that mean?
-1) See {ref}`conditional_locks`, below.
+(A) See {ref}`conditional_locks`, below.
(limitations)=
@@ -730,7 +732,7 @@ annotations to an existing code base. The workaround is to define `getMu()`
as a fake getter method, which is provided only for the benefit of thread
safety analysis.
-(conditional-locks)=
+(conditional_locks)=
### No conditionally held locks.
@@ -1117,4 +1119,3 @@ public:
#endif // THREAD_SAFETY_ANALYSIS_MUTEX_H
```
-
diff --git a/clang/docs/ThreadSanitizer.md b/clang/docs/ThreadSanitizer.md
index 44b7b20bfe538..5383ccf1cc777 100644
--- a/clang/docs/ThreadSanitizer.md
+++ b/clang/docs/ThreadSanitizer.md
@@ -237,57 +237,56 @@ $ TSAN_OPTIONS=enable_adaptive_delay=1 ./myapp
### Configuration Options
-```{eval-rst}
-.. list-table:: Adaptive Delay Options
- :name: adaptive-delay-options-table
- :header-rows: 1
- :widths: 35 10 15 40
-
- * - Flag
- - Type
- - Default
- - Description
- * - ``enable_adaptive_delay``
- - bool
- - false
- - Enable adaptive delay injection to expose data races.
- * - ``adaptive_delay_aggressiveness``
- - int
- - 25
- - Controls delay injection intensity for race detection. Higher values inject
- more delays to expose races. Value must be greater than 0. Suggested values:
- 10 (minimal), 50 (moderate), 200 (aggressive). This is a tuning parameter;
- actual overhead varies by workload and platform.
- * - ``adaptive_delay_relaxed_sample_rate``
- - int
- - 10000
- - Sample 1 in N relaxed atomic operations for delay injection. Relaxed atomics
- have minimal synchronization, so sampling helps avoid excessive overhead.
- * - ``adaptive_delay_sync_atomic_sample_rate``
- - int
- - 100
- - Sample 1 in N acquire/release/seq_cst atomic operations for delay injection.
- These synchronizing atomics are more likely to expose races, so are sampled
- more often.
- * - ``adaptive_delay_mutex_sample_rate``
- - int
- - 10
- - Sample 1 in N mutex/condition variable operations for delay injection. Mutex
- ops are high-value synchronization points and are sampled frequently.
- * - ``adaptive_delay_max_atomic``
- - string
- - ``"sleep_us=50"``
- - Maximum delay for atomic operations. Format: ``"spin=N"`` (N spin cycles,
- 1 <= N <= 10,000), ``"yield"`` (one yield to the OS), or ``"sleep_us=N"``
- (up to N microseconds). The delay is randomly chosen up to the specified
- maximum N.
- * - ``adaptive_delay_max_sync``
- - string
- - ``"sleep_us=500"``
- - Maximum delay for synchronization operations (mutex and thread lifecycle
- operations). Format: same as ``adaptive_delay_max_atomic``. Typically set
- longer than atomic delays since these operations involve waking blocked threads
- and may be more likely to expose races.
+```{list-table} Adaptive Delay Options
+:name: adaptive-delay-options-table
+:header-rows: 1
+:widths: 35 10 15 40
+
+* - Flag
+ - Type
+ - Default
+ - Description
+* - `enable_adaptive_delay`
+ - bool
+ - false
+ - Enable adaptive delay injection to expose data races.
+* - `adaptive_delay_aggressiveness`
+ - int
+ - 25
+ - Controls delay injection intensity for race detection. Higher values inject
+ more delays to expose races. Value must be greater than 0. Suggested values:
+ 10 (minimal), 50 (moderate), 200 (aggressive). This is a tuning parameter;
+ actual overhead varies by workload and platform.
+* - `adaptive_delay_relaxed_sample_rate`
+ - int
+ - 10000
+ - Sample 1 in N relaxed atomic operations for delay injection. Relaxed atomics
+ have minimal synchronization, so sampling helps avoid excessive overhead.
+* - `adaptive_delay_sync_atomic_sample_rate`
+ - int
+ - 100
+ - Sample 1 in N acquire/release/seq_cst atomic operations for delay injection.
+ These synchronizing atomics are more likely to expose races, so are sampled
+ more often.
+* - `adaptive_delay_mutex_sample_rate`
+ - int
+ - 10
+ - Sample 1 in N mutex/condition variable operations for delay injection. Mutex
+ ops are high-value synchronization points and are sampled frequently.
+* - `adaptive_delay_max_atomic`
+ - string
+ - `"sleep_us=50"`
+ - Maximum delay for atomic operations. Format: `"spin=N"` (N spin cycles,
+ 1 <= N <= 10,000), `"yield"` (one yield to the OS), or `"sleep_us=N"`
+ (up to N microseconds). The delay is randomly chosen up to the specified
+ maximum N.
+* - `adaptive_delay_max_sync`
+ - string
+ - `"sleep_us=500"`
+ - Maximum delay for synchronization operations (mutex and thread lifecycle
+ operations). Format: same as `adaptive_delay_max_atomic`. Typically set
+ longer than atomic delays since these operations involve waking blocked threads
+ and may be more likely to expose races.
```
### Examples
@@ -313,4 +312,3 @@ $ TSAN_OPTIONS=enable_adaptive_delay=1:adaptive_delay_mutex_sample_rate=5 ./myap
## More Information
[https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual](https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual)
-
diff --git a/clang/docs/Toolchain.md b/clang/docs/Toolchain.md
index 2c30792c6bc93..a5578b5904a60 100644
--- a/clang/docs/Toolchain.md
+++ b/clang/docs/Toolchain.md
@@ -18,12 +18,12 @@ This document describes the required and optional components in a
complete toolchain, where to find them, and the supported versions
and limitations of each option.
-:::{warning}
+```{warning}
This document currently describes Clang configurations on POSIX-like
operating systems with the GCC-compatible `clang` driver. When
targeting Windows with the MSVC-compatible `clang-cl` driver, some
of the details are different.
-:::
+```
## Tools
@@ -126,11 +126,11 @@ The set of implicitly-linked libraries depend on the language mode. As a
consequence, you should use `clang++` when linking C++ programs in order
to ensure the C++ runtimes are provided.
-:::{note}
+```{note}
There may exist other implementations for these components not described
below. Please let us know how well those other implementations work with
Clang so they can be added to this list!
-:::
+```
% FIXME: Describe Objective-C runtime libraries
@@ -193,12 +193,12 @@ libgcc_s does not provide an implementation of an atomics library. Instead,
[GCC's libatomic library](https://gcc.gnu.org/wiki/Atomic/GCCMM) can be
used to supply these when using libgcc_s.
-:::{note}
+```{note}
Clang does not currently automatically link against libatomic when using
libgcc_s. You may need to manually add `-latomic` to support this
configuration when using non-native atomic operations (if you see link errors
referring to `__atomic_*` functions).
-:::
+```
### Unwind library
@@ -281,11 +281,11 @@ libsupc++ is GCC's implementation of this specification. However, this
library is only used when libstdc++ is linked statically. The dynamic
library version of libstdc++ contains a copy of libsupc++.
-:::{note}
+```{note}
Clang does not currently automatically link against libsupc++ when statically
linking libstdc++. You may need to manually add `-lsupc++` to support this
configuration when using `-static` or `-static-libstdc++`.
-:::
+```
#### libcxxrt (PathScale)
@@ -319,4 +319,3 @@ You can instruct Clang to use libstdc++ with the `-stdlib=libstdc++` flag.
Users can point to their GCC installation by using the `-gcc-toolchain` or by
using `-gcc-install-dir` flag.
-
diff --git a/clang/docs/UndefinedBehaviorSanitizer.md b/clang/docs/UndefinedBehaviorSanitizer.md
index 383b95cfcd4ac..8fe4af0e8fb60 100644
--- a/clang/docs/UndefinedBehaviorSanitizer.md
+++ b/clang/docs/UndefinedBehaviorSanitizer.md
@@ -1,7 +1,7 @@
# UndefinedBehaviorSanitizer
```{contents}
-:local: true
+:local:
```
## Introduction
@@ -102,117 +102,118 @@ a `-fsanitize=` option. There is no unused command line option warning.
Available checks are:
-> - `-fsanitize=alignment`: Use of a misaligned pointer or creation
-> of a misaligned reference. Also sanitizes assume_aligned-like attributes.
-> - `-fsanitize=bool`: Load of a `bool` value which is neither
-> `true` nor `false`.
-> - `-fsanitize=builtin`: Passing invalid values to compiler builtins.
-> - `-fsanitize=bounds`: Out of bounds array indexing, in cases
-> where the array bound can be statically determined. The check includes
-> `-fsanitize=array-bounds` and `-fsanitize=local-bounds`. Note that
-> `-fsanitize=local-bounds` is not included in `-fsanitize=undefined`.
-> - `-fsanitize=enum`: Load of a value of an enumerated type which
-> is not in the range of representable values for that enumerated
-> type.
-> - `-fsanitize=float-cast-overflow`: Conversion to, from, or
-> between floating-point types which would overflow the
-> destination. Because the range of representable values for all
-> floating-point types supported by Clang is [-inf, +inf], the only
-> cases detected are conversions from floating point to integer types.
-> - `-fsanitize=float-divide-by-zero`: Floating point division by
-> zero. This is undefined per the C and C++ standards, but is defined
-> by Clang (and by ISO/IEC/IEEE 60559 / IEEE 754) as producing either an
-> infinity or NaN value, so is not included in `-fsanitize=undefined`.
-> - `-fsanitize=function`: Indirect call of a function through a
-> function pointer of the wrong type.
-> - `-fsanitize=implicit-unsigned-integer-truncation`,
-> `-fsanitize=implicit-signed-integer-truncation`: Implicit conversion from
-> integer of larger bit width to smaller bit width, if that results in data
-> loss. That is, if the demoted value, after casting back to the original
-> width, is not equal to the original value before the downcast.
-> The `-fsanitize=implicit-unsigned-integer-truncation` handles conversions
-> between two `unsigned` types, while
-> `-fsanitize=implicit-signed-integer-truncation` handles the rest of the
-> conversions - when either one, or both of the types are signed.
-> Issues caught by these sanitizers are not undefined behavior,
-> but are often unintentional.
-> - `-fsanitize=implicit-integer-sign-change`: Implicit conversion between
-> integer types, if that changes the sign of the value. That is, if the
-> original value was negative and the new value is positive (or zero),
-> or the original value was positive, and the new value is negative.
-> Issues caught by this sanitizer are not undefined behavior,
-> but are often unintentional.
-> - `-fsanitize=integer-divide-by-zero`: Integer division by zero.
-> - `-fsanitize=implicit-bitfield-conversion`: Implicit conversion from
-> integer of larger bit width to smaller bitfield, if that results in data
-> loss. This includes unsigned/signed truncations and sign changes, similarly
-> to how the `-fsanitize=implicit-integer-conversion` group works, but
-> explicitly for bitfields.
-> - `-fsanitize=nonnull-attribute`: Passing null pointer as a function
-> parameter which is declared to never be null.
-> - `-fsanitize=null`: Use of a null pointer or creation of a null
-> reference.
-> - `-fsanitize=nullability-arg`: Passing null as a function parameter
-> which is annotated with `_Nonnull`.
-> - `-fsanitize=nullability-assign`: Assigning null to an lvalue which
-> is annotated with `_Nonnull`.
-> - `-fsanitize=nullability-return`: Returning null from a function with
-> a return type annotated with `_Nonnull`.
-> - `-fsanitize=objc-cast`: Invalid implicit cast of an ObjC object pointer
-> to an incompatible type. This is often unintentional, but is not undefined
-> behavior, therefore the check is not a part of the `undefined` group.
-> Currently only supported on Darwin.
-> - `-fsanitize=object-size`: An attempt to potentially use bytes which
-> the optimizer can determine are not part of the object being accessed.
-> This will also detect some types of undefined behavior that may not
-> directly access memory, but are provably incorrect given the size of
-> the objects involved, such as invalid downcasts and calling methods on
-> invalid pointers. These checks are made in terms of
-> `__builtin_object_size`, and consequently may be able to detect more
-> problems at higher optimization levels.
-> - `-fsanitize=pointer-overflow`: Performing pointer arithmetic which
-> overflows, or where either the old or new pointer value is a null pointer
-> (excluding the case where both are null pointers).
-> - `-fsanitize=return`: In C++, reaching the end of a
-> value-returning function without returning a value.
-> - `-fsanitize=returns-nonnull-attribute`: Returning null pointer
-> from a function which is declared to never return null.
-> - `-fsanitize=shift`: Shift operators where the amount shifted is
-> greater or equal to the promoted bit-width of the left hand side
-> or less than zero, or where the left hand side is negative. For a
-> signed left shift, also checks for signed overflow in C, and for
-> unsigned overflow in C++. You can use `-fsanitize=shift-base` or
-> `-fsanitize=shift-exponent` to check only left-hand side or
-> right-hand side of shift operation, respectively.
-> - `-fsanitize=unsigned-shift-base`: check that an unsigned left-hand side of
-> a left shift operation doesn't overflow. Issues caught by this sanitizer are
-> not undefined behavior, but are often unintentional.
-> - `-fsanitize=signed-integer-overflow`: Signed integer overflow, where the
-> result of a signed integer computation cannot be represented in its type.
-> This includes all the checks covered by `-ftrapv`, as well as checks for
-> signed division overflow (`INT_MIN/-1`). Note that checks are still
-> added even when `-fwrapv` is enabled. This sanitizer does not check for
-> lossy implicit conversions performed before the computation (see
-> `-fsanitize=implicit-integer-conversion`). Both of these two issues are handled
-> by `-fsanitize=implicit-integer-conversion` group of checks.
-> - `-fsanitize=unreachable`: If control flow reaches an unreachable
-> program point.
-> - `-fsanitize=unsigned-integer-overflow`: Unsigned integer overflow, where
-> the result of an unsigned integer computation cannot be represented in its
-> type. Unlike signed integer overflow, this is not undefined behavior, but
-> it is often unintentional. This sanitizer does not check for lossy implicit
-> conversions performed before such a computation
-> (see `-fsanitize=implicit-integer-conversion`).
-> - `-fsanitize=vla-bound`: A variable-length array whose bound
-> does not evaluate to a positive value.
-> - `-fsanitize=vptr`: Use of an object whose vptr indicates that it is of
-> the wrong dynamic type, or that its lifetime has not begun or has ended.
-> Incompatible with `-fno-rtti`. Link must be performed by `clang++`, not
-> `clang`, to make sure C++-specific parts of the runtime library and C++
-> standard libraries are present. The check is not a part of the `undefined`
-> group. Also it does not support `-fsanitize-trap=vptr`.
+- `-fsanitize=alignment`: Use of a misaligned pointer or creation
+ of a misaligned reference. Also sanitizes assume_aligned-like attributes.
+- `-fsanitize=bool`: Load of a `bool` value which is neither
+ `true` nor `false`.
+- `-fsanitize=builtin`: Passing invalid values to compiler builtins.
+- `-fsanitize=bounds`: Out of bounds array indexing, in cases
+ where the array bound can be statically determined. The check includes
+ `-fsanitize=array-bounds` and `-fsanitize=local-bounds`. Note that
+ `-fsanitize=local-bounds` is not included in `-fsanitize=undefined`.
+- `-fsanitize=enum`: Load of a value of an enumerated type which
+ is not in the range of representable values for that enumerated
+ type.
+- `-fsanitize=float-cast-overflow`: Conversion to, from, or
+ between floating-point types which would overflow the
+ destination. Because the range of representable values for all
+ floating-point types supported by Clang is [-inf, +inf], the only
+ cases detected are conversions from floating point to integer types.
+- `-fsanitize=float-divide-by-zero`: Floating point division by
+ zero. This is undefined per the C and C++ standards, but is defined
+ by Clang (and by ISO/IEC/IEEE 60559 / IEEE 754) as producing either an
+ infinity or NaN value, so is not included in `-fsanitize=undefined`.
+- `-fsanitize=function`: Indirect call of a function through a
+ function pointer of the wrong type.
+- `-fsanitize=implicit-unsigned-integer-truncation`,
+ `-fsanitize=implicit-signed-integer-truncation`: Implicit conversion from
+ integer of larger bit width to smaller bit width, if that results in data
+ loss. That is, if the demoted value, after casting back to the original
+ width, is not equal to the original value before the downcast.
+ The `-fsanitize=implicit-unsigned-integer-truncation` handles conversions
+ between two `unsigned` types, while
+ `-fsanitize=implicit-signed-integer-truncation` handles the rest of the
+ conversions - when either one, or both of the types are signed.
+ Issues caught by these sanitizers are not undefined behavior,
+ but are often unintentional.
+- `-fsanitize=implicit-integer-sign-change`: Implicit conversion between
+ integer types, if that changes the sign of the value. That is, if the
+ original value was negative and the new value is positive (or zero),
+ or the original value was positive, and the new value is negative.
+ Issues caught by this sanitizer are not undefined behavior,
+ but are often unintentional.
+- `-fsanitize=integer-divide-by-zero`: Integer division by zero.
+- `-fsanitize=implicit-bitfield-conversion`: Implicit conversion from
+ integer of larger bit width to smaller bitfield, if that results in data
+ loss. This includes unsigned/signed truncations and sign changes, similarly
+ to how the `-fsanitize=implicit-integer-conversion` group works, but
+ explicitly for bitfields.
+- `-fsanitize=nonnull-attribute`: Passing null pointer as a function
+ parameter which is declared to never be null.
+- `-fsanitize=null`: Use of a null pointer or creation of a null
+ reference.
+- `-fsanitize=nullability-arg`: Passing null as a function parameter
+ which is annotated with `_Nonnull`.
+- `-fsanitize=nullability-assign`: Assigning null to an lvalue which
+ is annotated with `_Nonnull`.
+- `-fsanitize=nullability-return`: Returning null from a function with
+ a return type annotated with `_Nonnull`.
+- `-fsanitize=objc-cast`: Invalid implicit cast of an ObjC object pointer
+ to an incompatible type. This is often unintentional, but is not undefined
+ behavior, therefore the check is not a part of the `undefined` group.
+ Currently only supported on Darwin.
+- `-fsanitize=object-size`: An attempt to potentially use bytes which
+ the optimizer can determine are not part of the object being accessed.
+ This will also detect some types of undefined behavior that may not
+ directly access memory, but are provably incorrect given the size of
+ the objects involved, such as invalid downcasts and calling methods on
+ invalid pointers. These checks are made in terms of
+ `__builtin_object_size`, and consequently may be able to detect more
+ problems at higher optimization levels.
+- `-fsanitize=pointer-overflow`: Performing pointer arithmetic which
+ overflows, or where either the old or new pointer value is a null pointer
+ (excluding the case where both are null pointers).
+- `-fsanitize=return`: In C++, reaching the end of a
+ value-returning function without returning a value.
+- `-fsanitize=returns-nonnull-attribute`: Returning null pointer
+ from a function which is declared to never return null.
+- `-fsanitize=shift`: Shift operators where the amount shifted is
+ greater or equal to the promoted bit-width of the left hand side
+ or less than zero, or where the left hand side is negative. For a
+ signed left shift, also checks for signed overflow in C, and for
+ unsigned overflow in C++. You can use `-fsanitize=shift-base` or
+ `-fsanitize=shift-exponent` to check only left-hand side or
+ right-hand side of shift operation, respectively.
+- `-fsanitize=unsigned-shift-base`: check that an unsigned left-hand side of
+ a left shift operation doesn't overflow. Issues caught by this sanitizer are
+ not undefined behavior, but are often unintentional.
+- `-fsanitize=signed-integer-overflow`: Signed integer overflow, where the
+ result of a signed integer computation cannot be represented in its type.
+ This includes all the checks covered by `-ftrapv`, as well as checks for
+ signed division overflow (`INT_MIN/-1`). Note that checks are still
+ added even when `-fwrapv` is enabled. This sanitizer does not check for
+ lossy implicit conversions performed before the computation (see
+ `-fsanitize=implicit-integer-conversion`). Both of these two issues are handled
+ by `-fsanitize=implicit-integer-conversion` group of checks.
+- `-fsanitize=unreachable`: If control flow reaches an unreachable
+ program point.
+- `-fsanitize=unsigned-integer-overflow`: Unsigned integer overflow, where
+ the result of an unsigned integer computation cannot be represented in its
+ type. Unlike signed integer overflow, this is not undefined behavior, but
+ it is often unintentional. This sanitizer does not check for lossy implicit
+ conversions performed before such a computation
+ (see `-fsanitize=implicit-integer-conversion`).
+- `-fsanitize=vla-bound`: A variable-length array whose bound
+ does not evaluate to a positive value.
+- `-fsanitize=vptr`: Use of an object whose vptr indicates that it is of
+ the wrong dynamic type, or that its lifetime has not begun or has ended.
+ Incompatible with `-fno-rtti`. Link must be performed by `clang++`, not
+ `clang`, to make sure C++-specific parts of the runtime library and C++
+ standard libraries are present. The check is not a part of the `undefined`
+ group. Also it does not support `-fsanitize-trap=vptr`.
You can also use the following check groups:
+
: - `-fsanitize=undefined`: All of the checks listed above other than
`float-divide-by-zero`, `unsigned-integer-overflow`,
`implicit-conversion`, `local-bounds`, `vptr` and the
@@ -324,23 +325,20 @@ if (base + offset < base) { /* ... */ } // The pattern of `a + b < a`, and other
// won't be instrumented (signed or unsigned types)
```
-```{eval-rst}
-.. list-table:: Overflow Pattern Types
- :widths: 30 50
- :header-rows: 1
-
- * - Pattern
- - Sanitizer
- * - negated-unsigned-const
- - unsigned-integer-overflow
- * - unsigned-post-decr-while
- - unsigned-integer-overflow
- * - add-unsigned-overflow-test
- - unsigned-integer-overflow
- * - add-signed-overflow-test
- - signed-integer-overflow
-
-
+```{list-table} Overflow Pattern Types
+:widths: 30 50
+:header-rows: 1
+
+* - Pattern
+ - Sanitizer
+* - negated-unsigned-const
+ - unsigned-integer-overflow
+* - unsigned-post-decr-while
+ - unsigned-integer-overflow
+* - add-unsigned-overflow-test
+ - unsigned-integer-overflow
+* - add-signed-overflow-test
+ - signed-integer-overflow
```
Note: `add-signed-overflow-test` suppresses only the check for Undefined
@@ -470,8 +468,8 @@ There are several limitations:
UndefinedBehaviorSanitizer's runtime is meant for testing purposes and its usage
in production environment should be carefully considered from security
perspective as it may compromise the security of the resulting executable.
-For security-sensitive applications consider using {ref}`Minimal Runtime
-<minimal-runtime>` or trap mode for all checks.
+For security-sensitive applications consider using {ref}`Minimal Runtime <minimal-runtime>`
+or trap mode for all checks.
## Supported Platforms
@@ -522,4 +520,3 @@ For a file called `/code/library/file.cpp`, here is what would be emitted:
[What Every C Programmer Should Know About Undefined Behavior](http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html)
- From John Regehr's *Embedded in Academia* blog:
[A Guide to Undefined Behavior in C and C++](https://blog.regehr.org/archives/213)
-
diff --git a/clang/docs/conf.py b/clang/docs/conf.py
index cac0686d7f426..b80c859d1dbdf 100644
--- a/clang/docs/conf.py
+++ b/clang/docs/conf.py
@@ -19,6 +19,8 @@
globals().update(common_conf(tags, markdown=Markdown.EXCEPT_MAN))
+myst_enable_extensions += ["deflist"]
+
# -- General configuration -----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
More information about the llvm-branch-commits
mailing list