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#include <tuple>
15
16namespace clang {
17namespace ento {
18
19/// \brief A record of the "type" of an APSInt, used for conversions.
20class APSIntType {
21  uint32_t BitWidth;
22  bool IsUnsigned;
23
24public:
25  APSIntType(uint32_t Width, bool Unsigned)
26    : BitWidth(Width), IsUnsigned(Unsigned) {}
27
28  /* implicit */ APSIntType(const llvm::APSInt &Value)
29    : BitWidth(Value.getBitWidth()), IsUnsigned(Value.isUnsigned()) {}
30
31  uint32_t getBitWidth() const { return BitWidth; }
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).
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
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.
56  llvm::APSInt getZeroValue() const LLVM_READONLY {
57    return llvm::APSInt(BitWidth, IsUnsigned);
58  }
59
60  /// Returns the minimum value for this type.
61  llvm::APSInt getMinValue() const LLVM_READONLY {
62    return llvm::APSInt::getMinValue(BitWidth, IsUnsigned);
63  }
64
65  /// Returns the maximum value for this type.
66  llvm::APSInt getMaxValue() const LLVM_READONLY {
67    return llvm::APSInt::getMaxValue(BitWidth, IsUnsigned);
68  }
69
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