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