1 //== APSIntType.h - Simple record of the type of APSInts --------*- 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 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_APSINTTYPE_H 10 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_APSINTTYPE_H 11 12 #include "llvm/ADT/APSInt.h" 13 #include <tuple> 14 15 namespace clang { 16 namespace ento { 17 18 /// A record of the "type" of an APSInt, used for conversions. 19 class APSIntType { 20 uint32_t BitWidth; 21 bool IsUnsigned; 22 23 public: APSIntType(uint32_t Width,bool Unsigned)24 constexpr APSIntType(uint32_t Width, bool Unsigned) 25 : BitWidth(Width), IsUnsigned(Unsigned) {} 26 APSIntType(const llvm::APSInt & Value)27 /* implicit */ APSIntType(const llvm::APSInt &Value) 28 : BitWidth(Value.getBitWidth()), IsUnsigned(Value.isUnsigned()) {} 29 getBitWidth()30 uint32_t getBitWidth() const { return BitWidth; } isUnsigned()31 bool isUnsigned() const { return IsUnsigned; } 32 33 /// Convert a given APSInt, in place, to match this type. 34 /// 35 /// This behaves like a C cast: converting 255u8 (0xFF) to s16 gives 36 /// 255 (0x00FF), and converting -1s8 (0xFF) to u16 gives 65535 (0xFFFF). apply(llvm::APSInt & Value)37 void apply(llvm::APSInt &Value) const { 38 // Note the order here. We extend first to preserve the sign, if this value 39 // is signed, /then/ match the signedness of the result type. 40 Value = Value.extOrTrunc(BitWidth); 41 Value.setIsUnsigned(IsUnsigned); 42 } 43 44 /// Convert and return a new APSInt with the given value, but this 45 /// type's bit width and signedness. 46 /// 47 /// \see apply convert(const llvm::APSInt & Value)48 llvm::APSInt convert(const llvm::APSInt &Value) const LLVM_READONLY { 49 llvm::APSInt Result(Value, Value.isUnsigned()); 50 apply(Result); 51 return Result; 52 } 53 54 /// Returns an all-zero value for this type. getZeroValue()55 llvm::APSInt getZeroValue() const LLVM_READONLY { 56 return llvm::APSInt(BitWidth, IsUnsigned); 57 } 58 59 /// Returns the minimum value for this type. getMinValue()60 llvm::APSInt getMinValue() const LLVM_READONLY { 61 return llvm::APSInt::getMinValue(BitWidth, IsUnsigned); 62 } 63 64 /// Returns the maximum value for this type. getMaxValue()65 llvm::APSInt getMaxValue() const LLVM_READONLY { 66 return llvm::APSInt::getMaxValue(BitWidth, IsUnsigned); 67 } 68 getValue(uint64_t RawValue)69 llvm::APSInt getValue(uint64_t RawValue) const LLVM_READONLY { 70 return (llvm::APSInt(BitWidth, IsUnsigned) = RawValue); 71 } 72 73 /// Used to classify whether a value is representable using this type. 74 /// 75 /// \see testInRange 76 enum RangeTestResultKind { 77 RTR_Below = -1, ///< Value is less than the minimum representable value. 78 RTR_Within = 0, ///< Value is representable using this type. 79 RTR_Above = 1 ///< Value is greater than the maximum representable value. 80 }; 81 82 /// Tests whether a given value is losslessly representable using this type. 83 /// 84 /// \param Val The value to test. 85 /// \param AllowMixedSign Whether or not to allow signedness conversions. 86 /// This determines whether -1s8 is considered in range 87 /// for 'unsigned char' (u8). 88 RangeTestResultKind testInRange(const llvm::APSInt &Val, 89 bool AllowMixedSign) const LLVM_READONLY; 90 91 bool operator==(const APSIntType &Other) const { 92 return BitWidth == Other.BitWidth && IsUnsigned == Other.IsUnsigned; 93 } 94 95 /// Provide an ordering for finding a common conversion type. 96 /// 97 /// Unsigned integers are considered to be better conversion types than 98 /// signed integers of the same width. 99 bool operator<(const APSIntType &Other) const { 100 return std::tie(BitWidth, IsUnsigned) < 101 std::tie(Other.BitWidth, Other.IsUnsigned); 102 } 103 }; 104 105 } // end ento namespace 106 } // end clang namespace 107 108 #endif 109