@@ -8101,3 +8101,72 @@ Attribute used by `clspv`_ (OpenCL-C to Vulkan SPIR-V compiler) to identify func
81018101.. _`libclc`: https://libclc.llvm.org
81028102}];
81038103}
8104+
8105+ def WrapsDocs : Documentation {
8106+ let Category = DocCatField;
8107+ let Content = [{
8108+ This attribute can be used with type or variable declarations to denote that
8109+ arithmetic containing these marked components have defined overflow behavior.
8110+ Specifically, the behavior is defined as being consistent with two's complement
8111+ wrap-around. For the purposes of sanitizers or warnings that concern themselves
8112+ with the definedness of integer arithmetic, they will cease to instrument or
8113+ warn about arithmetic that directly involves a "wrapping" component.
8114+
8115+ For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
8116+ will not warn about suspicious overflowing arithmetic -- assuming correct usage
8117+ of the wraps attribute.
8118+
8119+ This example shows some basic usage of ``__attribute__((wraps))`` on a type
8120+ definition when building with ``-fsanitize=signed-integer-overflow``
8121+
8122+ .. code-block:: c
8123+
8124+ typedef int __attribute__((wraps)) wrapping_int;
8125+
8126+ void foo() {
8127+ wrapping_int a = INT_MAX;
8128+ ++a; // no sanitizer warning
8129+ }
8130+
8131+ int main() { foo(); }
8132+
8133+ In the following example, we use ``__attribute__((wraps))`` on a variable to
8134+ disable overflow instrumentation for arithmetic expressions it appears in. We
8135+ do so with a popular overflow-checking pattern which we might not want to trip
8136+ sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
8137+
8138+ .. code-block:: c
8139+
8140+ void foo(int offset) {
8141+ unsigned int A __attribute__((wraps)) = UINT_MAX;
8142+
8143+ // to check for overflow using this pattern, we may perform a real overflow
8144+ // thus triggering sanitizers to step in. Since A is "wrapping", we can be
8145+ // sure there are no sanitizer warnings.
8146+ if (A + offset < A) {
8147+ // handle overflow manually
8148+ // ...
8149+ return;
8150+ }
8151+
8152+ // now, handle non-overflow case ...
8153+ }
8154+
8155+ The above example demonstrates some of the power and elegance this attribute
8156+ provides. We can use code patterns we are already familiar with (like ``if (x +
8157+ y < x)``) while gaining control over the overflow behavior on a case-by-case
8158+ basis.
8159+
8160+ When combined with ``-fwrapv``, this attribute can still be applied as normal
8161+ but has no function apart from annotating types and variables for readers. This
8162+ is because ``-fwrapv`` defines all arithmetic as being "wrapping", rending this
8163+ attribute's efforts redundant.
8164+
8165+ When using this attribute without ``-fwrapv`` and without any sanitizers, it
8166+ still has an impact on the definedness of arithmetic expressions containing
8167+ wrapping components. Since the behavior of said expressions is now technically
8168+ defined, the compiler will forgo some eager optimizations that are used on
8169+ expressions containing UB.
8170+ }];
8171+ }
8172+
0 commit comments