Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//==-- llvm/Support/CheckedArithmetic.h - Safe arithmetical operations *- C++ //
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file contains generic functions for operating on integers which
10
// give the indication on whether the operation has overflown.
11
//
12
//===----------------------------------------------------------------------===//
13
 
14
#ifndef LLVM_SUPPORT_CHECKEDARITHMETIC_H
15
#define LLVM_SUPPORT_CHECKEDARITHMETIC_H
16
 
17
#include "llvm/ADT/APInt.h"
18
 
19
#include <optional>
20
#include <type_traits>
21
 
22
namespace {
23
 
24
/// Utility function to apply a given method of \c APInt \p F to \p LHS and
25
/// \p RHS.
26
/// \return Empty optional if the operation overflows, or result otherwise.
27
template <typename T, typename F>
28
std::enable_if_t<std::is_integral<T>::value && sizeof(T) * 8 <= 64,
29
                 std::optional<T>>
30
checkedOp(T LHS, T RHS, F Op, bool Signed = true) {
31
  llvm::APInt ALHS(sizeof(T) * 8, LHS, Signed);
32
  llvm::APInt ARHS(sizeof(T) * 8, RHS, Signed);
33
  bool Overflow;
34
  llvm::APInt Out = (ALHS.*Op)(ARHS, Overflow);
35
  if (Overflow)
36
    return std::nullopt;
37
  return Signed ? Out.getSExtValue() : Out.getZExtValue();
38
}
39
}
40
 
41
namespace llvm {
42
 
43
/// Add two signed integers \p LHS and \p RHS.
44
/// \return Optional of sum if no signed overflow occurred,
45
/// \c std::nullopt otherwise.
46
template <typename T>
47
std::enable_if_t<std::is_signed<T>::value, std::optional<T>>
48
checkedAdd(T LHS, T RHS) {
49
  return checkedOp(LHS, RHS, &llvm::APInt::sadd_ov);
50
}
51
 
52
/// Subtract two signed integers \p LHS and \p RHS.
53
/// \return Optional of sum if no signed overflow occurred,
54
/// \c std::nullopt otherwise.
55
template <typename T>
56
std::enable_if_t<std::is_signed<T>::value, std::optional<T>>
57
checkedSub(T LHS, T RHS) {
58
  return checkedOp(LHS, RHS, &llvm::APInt::ssub_ov);
59
}
60
 
61
/// Multiply two signed integers \p LHS and \p RHS.
62
/// \return Optional of product if no signed overflow occurred,
63
/// \c std::nullopt otherwise.
64
template <typename T>
65
std::enable_if_t<std::is_signed<T>::value, std::optional<T>>
66
checkedMul(T LHS, T RHS) {
67
  return checkedOp(LHS, RHS, &llvm::APInt::smul_ov);
68
}
69
 
70
/// Multiply A and B, and add C to the resulting product.
71
/// \return Optional of result if no signed overflow occurred,
72
/// \c std::nullopt otherwise.
73
template <typename T>
74
std::enable_if_t<std::is_signed<T>::value, std::optional<T>>
75
checkedMulAdd(T A, T B, T C) {
76
  if (auto Product = checkedMul(A, B))
77
    return checkedAdd(*Product, C);
78
  return std::nullopt;
79
}
80
 
81
/// Add two unsigned integers \p LHS and \p RHS.
82
/// \return Optional of sum if no unsigned overflow occurred,
83
/// \c std::nullopt otherwise.
84
template <typename T>
85
std::enable_if_t<std::is_unsigned<T>::value, std::optional<T>>
86
checkedAddUnsigned(T LHS, T RHS) {
87
  return checkedOp(LHS, RHS, &llvm::APInt::uadd_ov, /*Signed=*/false);
88
}
89
 
90
/// Multiply two unsigned integers \p LHS and \p RHS.
91
/// \return Optional of product if no unsigned overflow occurred,
92
/// \c std::nullopt otherwise.
93
template <typename T>
94
std::enable_if_t<std::is_unsigned<T>::value, std::optional<T>>
95
checkedMulUnsigned(T LHS, T RHS) {
96
  return checkedOp(LHS, RHS, &llvm::APInt::umul_ov, /*Signed=*/false);
97
}
98
 
99
/// Multiply unsigned integers A and B, and add C to the resulting product.
100
/// \return Optional of result if no unsigned overflow occurred,
101
/// \c std::nullopt otherwise.
102
template <typename T>
103
std::enable_if_t<std::is_unsigned<T>::value, std::optional<T>>
104
checkedMulAddUnsigned(T A, T B, T C) {
105
  if (auto Product = checkedMulUnsigned(A, B))
106
    return checkedAddUnsigned(*Product, C);
107
  return std::nullopt;
108
}
109
 
110
} // End llvm namespace
111
 
112
#endif