File indexing completed on 2026-05-10 08:44:28
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_SUPPORT_CHECKEDARITHMETIC_H
0015 #define LLVM_SUPPORT_CHECKEDARITHMETIC_H
0016
0017 #include "llvm/ADT/APInt.h"
0018
0019 #include <optional>
0020 #include <type_traits>
0021
0022 namespace {
0023
0024
0025
0026
0027 template <typename T, typename F>
0028 std::enable_if_t<std::is_integral_v<T> && sizeof(T) * 8 <= 64, std::optional<T>>
0029 checkedOp(T LHS, T RHS, F Op, bool Signed = true) {
0030 llvm::APInt ALHS(sizeof(T) * 8, LHS, Signed);
0031 llvm::APInt ARHS(sizeof(T) * 8, RHS, Signed);
0032 bool Overflow;
0033 llvm::APInt Out = (ALHS.*Op)(ARHS, Overflow);
0034 if (Overflow)
0035 return std::nullopt;
0036 return Signed ? Out.getSExtValue() : Out.getZExtValue();
0037 }
0038 }
0039
0040 namespace llvm {
0041
0042
0043
0044
0045 template <typename T>
0046 std::enable_if_t<std::is_signed_v<T>, std::optional<T>> checkedAdd(T LHS,
0047 T RHS) {
0048 return checkedOp(LHS, RHS, &llvm::APInt::sadd_ov);
0049 }
0050
0051
0052
0053
0054 template <typename T>
0055 std::enable_if_t<std::is_signed_v<T>, std::optional<T>> checkedSub(T LHS,
0056 T RHS) {
0057 return checkedOp(LHS, RHS, &llvm::APInt::ssub_ov);
0058 }
0059
0060
0061
0062
0063 template <typename T>
0064 std::enable_if_t<std::is_signed_v<T>, std::optional<T>> checkedMul(T LHS,
0065 T RHS) {
0066 return checkedOp(LHS, RHS, &llvm::APInt::smul_ov);
0067 }
0068
0069
0070
0071
0072 template <typename T>
0073 std::enable_if_t<std::is_signed_v<T>, std::optional<T>> checkedMulAdd(T A, T B,
0074 T C) {
0075 if (auto Product = checkedMul(A, B))
0076 return checkedAdd(*Product, C);
0077 return std::nullopt;
0078 }
0079
0080
0081
0082
0083 template <typename T>
0084 std::enable_if_t<std::is_unsigned_v<T>, std::optional<T>>
0085 checkedAddUnsigned(T LHS, T RHS) {
0086 return checkedOp(LHS, RHS, &llvm::APInt::uadd_ov, false);
0087 }
0088
0089
0090
0091
0092 template <typename T>
0093 std::enable_if_t<std::is_unsigned_v<T>, std::optional<T>>
0094 checkedMulUnsigned(T LHS, T RHS) {
0095 return checkedOp(LHS, RHS, &llvm::APInt::umul_ov, false);
0096 }
0097
0098
0099
0100
0101 template <typename T>
0102 std::enable_if_t<std::is_unsigned_v<T>, std::optional<T>>
0103 checkedMulAddUnsigned(T A, T B, T C) {
0104 if (auto Product = checkedMulUnsigned(A, B))
0105 return checkedAddUnsigned(*Product, C);
0106 return std::nullopt;
0107 }
0108
0109 }
0110
0111 #endif