Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:28

0001 //==-- llvm/Support/CheckedArithmetic.h - Safe arithmetical operations *- C++ //
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file contains generic functions for operating on integers which
0010 // give the indication on whether the operation has overflown.
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 /// Utility function to apply a given method of \c APInt \p F to \p LHS and
0025 /// \p RHS.
0026 /// \return Empty optional if the operation overflows, or result otherwise.
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 /// Add two signed integers \p LHS and \p RHS.
0043 /// \return Optional of sum if no signed overflow occurred,
0044 /// \c std::nullopt otherwise.
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 /// Subtract two signed integers \p LHS and \p RHS.
0052 /// \return Optional of sum if no signed overflow occurred,
0053 /// \c std::nullopt otherwise.
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 /// Multiply two signed integers \p LHS and \p RHS.
0061 /// \return Optional of product if no signed overflow occurred,
0062 /// \c std::nullopt otherwise.
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 /// Multiply A and B, and add C to the resulting product.
0070 /// \return Optional of result if no signed overflow occurred,
0071 /// \c std::nullopt otherwise.
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 /// Add two unsigned integers \p LHS and \p RHS.
0081 /// \return Optional of sum if no unsigned overflow occurred,
0082 /// \c std::nullopt otherwise.
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, /*Signed=*/false);
0087 }
0088 
0089 /// Multiply two unsigned integers \p LHS and \p RHS.
0090 /// \return Optional of product if no unsigned overflow occurred,
0091 /// \c std::nullopt otherwise.
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, /*Signed=*/false);
0096 }
0097 
0098 /// Multiply unsigned integers A and B, and add C to the resulting product.
0099 /// \return Optional of result if no unsigned overflow occurred,
0100 /// \c std::nullopt otherwise.
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 } // End llvm namespace
0110 
0111 #endif