summaryrefslogtreecommitdiff
path: root/docs/ReleaseNotes.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/ReleaseNotes.rst')
-rw-r--r--docs/ReleaseNotes.rst45
1 files changed, 44 insertions, 1 deletions
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index d6c734a53a..8e9d298c95 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -60,6 +60,16 @@ Improvements to Clang's diagnostics
Non-comprehensive list of changes in this release
-------------------------------------------------
+* In both C and C++ (C17 ``6.5.6p8``, C++ ``[expr.add]``), pointer arithmetic is
+ only permitted within arrays. In particular, the behavior of a program is not
+ defined if it adds a non-zero offset (or in C, any offset) to a null pointer,
+ or if it forms a null pointer by subtracting an integer from a non-null
+ pointer, and the LLVM optimizer now uses those guarantees for transformations.
+ This may lead to unintended behavior in code that performs these operations.
+ The Undefined Behavior Sanitizer ``-fsanitize=pointer-overflow`` check has
+ been extended to detect these cases, so that code relying on them can be
+ detected and fixed.
+
- For X86 target, -march=skylake-avx512, -march=icelake-client,
-march=icelake-server, -march=cascadelake, -march=cooperlake will default to
not using 512-bit zmm registers in vectorized code unless 512-bit intrinsics
@@ -238,7 +248,40 @@ Static Analyzer
Undefined Behavior Sanitizer (UBSan)
------------------------------------
-- ...
+- * The ``pointer-overflow`` check was extended added to catch the cases where
+ a non-zero offset is applied to a null pointer, or the result of
+ applying the offset is a null pointer.
+
+ .. code-block:: c++
+
+ #include <cstdint> // for intptr_t
+
+ static char *getelementpointer_inbounds(char *base, unsigned long offset) {
+ // Potentially UB.
+ return base + offset;
+ }
+
+ char *getelementpointer_unsafe(char *base, unsigned long offset) {
+ // Always apply offset. UB if base is ``nullptr`` and ``offset`` is not
+ // zero, or if ``base`` is non-``nullptr`` and ``offset`` is
+ // ``-reinterpret_cast<intptr_t>(base)``.
+ return getelementpointer_inbounds(base, offset);
+ }
+
+ char *getelementpointer_safe(char *base, unsigned long offset) {
+ // Cast pointer to integer, perform usual arithmetic addition,
+ // and cast to pointer. This is legal.
+ char *computed =
+ reinterpret_cast<char *>(reinterpret_cast<intptr_t>(base) + offset);
+ // If either the pointer becomes non-``nullptr``, or becomes
+ // ``nullptr``, we must use ``computed`` result.
+ if (((base == nullptr) && (computed != nullptr)) ||
+ ((base != nullptr) && (computed == nullptr)))
+ return computed;
+ // Else we can use ``getelementpointer_inbounds()``.
+ return getelementpointer_inbounds(base, offset);
+ }
+
Core Analysis Improvements
==========================