• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_SA_CORE_APSINTTYPE_H
11 #define LLVM_CLANG_SA_CORE_APSINTTYPE_H
12 
13 #include "llvm/ADT/APSInt.h"
14 
15 namespace clang {
16 namespace ento {
17 
18 /// \brief 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   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   /// \brief 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   /// Note that signedness conversions will be rejected, even with the same bit
85   /// pattern. For example, -1s8 is not in range for 'unsigned char' (u8).
86   RangeTestResultKind testInRange(const llvm::APSInt &Val) const LLVM_READONLY;
87 
88   bool operator==(const APSIntType &Other) const {
89     return BitWidth == Other.BitWidth && IsUnsigned == Other.IsUnsigned;
90   }
91 
92   /// \brief Provide an ordering for finding a common conversion type.
93   ///
94   /// Unsigned integers are considered to be better conversion types than
95   /// signed integers of the same width.
96   bool operator<(const APSIntType &Other) const {
97     if (BitWidth < Other.BitWidth)
98       return true;
99     if (BitWidth > Other.BitWidth)
100       return false;
101     if (!IsUnsigned && Other.IsUnsigned)
102       return true;
103     return false;
104   }
105 };
106 
107 } // end ento namespace
108 } // end clang namespace
109 
110 #endif
111