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
15namespace clang {
16namespace ento {
17
18/// \brief A record of the "type" of an APSInt, used for conversions.
19class APSIntType {
20  uint32_t BitWidth;
21  bool IsUnsigned;
22
23public:
24  APSIntType(uint32_t Width, bool Unsigned)
25    : BitWidth(Width), IsUnsigned(Unsigned) {}
26
27  /* implicit */ APSIntType(const llvm::APSInt &Value)
28    : BitWidth(Value.getBitWidth()), IsUnsigned(Value.isUnsigned()) {}
29
30  uint32_t getBitWidth() const { return BitWidth; }
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).
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
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.
55  llvm::APSInt getZeroValue() const LLVM_READONLY {
56    return llvm::APSInt(BitWidth, IsUnsigned);
57  }
58
59  /// Returns the minimum value for this type.
60  llvm::APSInt getMinValue() const LLVM_READONLY {
61    return llvm::APSInt::getMinValue(BitWidth, IsUnsigned);
62  }
63
64  /// Returns the maximum value for this type.
65  llvm::APSInt getMaxValue() const LLVM_READONLY {
66    return llvm::APSInt::getMaxValue(BitWidth, IsUnsigned);
67  }
68
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  /// \brief 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    if (BitWidth < Other.BitWidth)
101      return true;
102    if (BitWidth > Other.BitWidth)
103      return false;
104    if (!IsUnsigned && Other.IsUnsigned)
105      return true;
106    return false;
107  }
108};
109
110} // end ento namespace
111} // end clang namespace
112
113#endif
114