This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
add probe for __builtin_{add,sub,mul}_overflow
authorH.Merijn Brand - Tux <h.m.brand@xs4all.nl>
Tue, 17 Oct 2017 13:57:40 +0000 (15:57 +0200)
committerH.Merijn Brand - Tux <h.m.brand@xs4all.nl>
Tue, 17 Oct 2017 13:57:40 +0000 (15:57 +0200)
Merge remote-tracking branch 'origin/mauke/builtin-overflow'

U/perl/d_builtin_overflow.U [new file with mode: 0644]

diff --git a/U/perl/d_builtin_overflow.U b/U/perl/d_builtin_overflow.U
new file mode 100644 (file)
index 0000000..d357180
--- /dev/null
@@ -0,0 +1,157 @@
+?RCS: Copyright (c) 2017, Lukas Mai
+?RCS:
+?RCS: You may distribute this file under the terms of either
+?RCS:     a) the "Artistic License" which comes with Perl, or
+?RCS:     b) the "Artistic License" which comes with dist, or
+?RCS:     c) the GNU General Public License as published by the Free
+?RCS:     Software Foundation; either version 1, or (at your option) any
+?RCS:     later version (see the file "Copying" that comes with the
+?RCS:     Perl distribution).
+?RCS: Which one to use is your choice.
+?RCS: See the U/README file.
+?MAKE:d_builtin_add_overflow d_builtin_sub_overflow d_builtin_mul_overflow : Compile Setvar cat run rm_try
+?MAKE: -pick add $@ %<
+?S:d_builtin_add_overflow:
+?S:    This variable conditionally defines HAS_BUILTIN_ADD_OVERFLOW, which
+?S:    indicates that the compiler supports __builtin_add_overflow(x,y,&z)
+?S:    for safely adding x and y into z while checking for overflow.
+?S:.
+?S:d_builtin_sub_overflow:
+?S:    This variable conditionally defines HAS_BUILTIN_SUB_OVERFLOW, which
+?S:    indicates that the compiler supports __builtin_sub_overflow(x,y,&z)
+?S:    for safely subtracting y from x into z while checking for overflow.
+?S:.
+?S:d_builtin_mul_overflow:
+?S:    This variable conditionally defines HAS_BUILTIN_MUL_OVERFLOW, which
+?S:    indicates that the compiler supports __builtin_mul_overflow(x,y,&z)
+?S:    for safely multiplying x and y into z while checking for overflow.
+?S:.
+?C:HAS_BUILTIN_ADD_OVERFLOW:
+?C:    This symbol, if defined, indicates that the compiler supports
+?C:    __builtin_add_overflow for adding integers with overflow checks.
+?C:.
+?C:HAS_BUILTIN_SUB_OVERFLOW:
+?C:    This symbol, if defined, indicates that the compiler supports
+?C:    __builtin_sub_overflow for subtracting integers with overflow checks.
+?C:.
+?C:HAS_BUILTIN_MUL_OVERFLOW:
+?C:    This symbol, if defined, indicates that the compiler supports
+?C:    __builtin_mul_overflow for multiplying integers with overflow checks.
+?C:.
+?H:#$d_builtin_add_overflow HAS_BUILTIN_ADD_OVERFLOW   /**/
+?H:#$d_builtin_sub_overflow HAS_BUILTIN_SUB_OVERFLOW   /**/
+?H:#$d_builtin_mul_overflow HAS_BUILTIN_MUL_OVERFLOW   /**/
+?H:.
+?F:!try
+?LINT:set d_builtin_add_overflow d_builtin_sub_overflow d_builtin_mul_overflow
+: Look for GCC-style __builtin_add_overflow
+case "$d_builtin_add_overflow" in
+'')
+    echo " "
+    echo "Checking whether your compiler can handle __builtin_add_overflow ..." >&4
+    $cat >try.c <<'EOCP'
+int main(void) {
+    const unsigned int uint_max = ~0u;
+    int target_int = 0;
+    if (__builtin_add_overflow(1, 2, &target_int) || target_int != 3) {
+        return 1;
+    }
+    if (!__builtin_add_overflow((int)(uint_max >> 1), 1, &target_int)) {
+        return 1;
+    }
+    if (!__builtin_add_overflow(uint_max, -1, &target_int)) {
+        return 1;
+    }
+    return 0;
+}
+EOCP
+    set try
+    if eval $compile && $run ./try; then
+        echo "Your C compiler supports __builtin_add_overflow."
+        val="$define"
+    else
+        echo "Your C compiler doesn't seem to understand __builtin_add_overflow."
+        val="$undef"
+    fi
+    ;;
+*) val="$d_builtin_add_overflow" ;;
+esac
+
+set d_builtin_add_overflow
+eval $setvar
+$rm_try
+
+: Look for GCC-style __builtin_sub_overflow
+case "$d_builtin_sub_overflow" in
+'')
+    echo " "
+    echo "Checking whether your compiler can handle __builtin_sub_overflow ..." >&4
+    $cat >try.c <<'EOCP'
+int main(void) {
+    const unsigned int uint_max = ~0u;
+    int target_int = 0;
+    if (__builtin_sub_overflow(1, -2, &target_int) || target_int != 3) {
+        return 1;
+    }
+    if (!__builtin_sub_overflow(-(int)(uint_max >> 1), 2, &target_int)) {
+        return 1;
+    }
+    if (!__builtin_sub_overflow(uint_max, 1, &target_int)) {
+        return 1;
+    }
+    return 0;
+}
+EOCP
+    set try
+    if eval $compile && $run ./try; then
+        echo "Your C compiler supports __builtin_sub_overflow."
+        val="$define"
+    else
+        echo "Your C compiler doesn't seem to understand __builtin_sub_overflow."
+        val="$undef"
+    fi
+    ;;
+*) val="$d_builtin_sub_overflow" ;;
+esac
+
+set d_builtin_sub_overflow
+eval $setvar
+$rm_try
+
+: Look for GCC-style __builtin_mul_overflow
+case "$d_builtin_mul_overflow" in
+'')
+    echo " "
+    echo "Checking whether your compiler can handle __builtin_mul_overflow ..." >&4
+    $cat >try.c <<'EOCP'
+int main(void) {
+    const unsigned int uint_max = ~0u;
+    int target_int = 0;
+    if (__builtin_mul_overflow(2, 3, &target_int) || target_int != 6) {
+        return 1;
+    }
+    if (!__builtin_mul_overflow((int)(uint_max >> 1), 2, &target_int)) {
+        return 1;
+    }
+    if (!__builtin_mul_overflow(uint_max, 1, &target_int)) {
+        return 1;
+    }
+    return 0;
+}
+EOCP
+    set try
+    if eval $compile && $run ./try; then
+        echo "Your C compiler supports __builtin_mul_overflow."
+        val="$define"
+    else
+        echo "Your C compiler doesn't seem to understand __builtin_mul_overflow."
+        val="$undef"
+    fi
+    ;;
+*) val="$d_builtin_mul_overflow" ;;
+esac
+
+set d_builtin_mul_overflow
+eval $setvar
+$rm_try
+