APSIntType.h revision 239313
1239313Sdim//== APSIntType.h - Simple record of the type of APSInts --------*- C++ -*--==//
2239313Sdim//
3239313Sdim//                     The LLVM Compiler Infrastructure
4239313Sdim//
5239313Sdim// This file is distributed under the University of Illinois Open Source
6239313Sdim// License. See LICENSE.TXT for details.
7239313Sdim//
8239313Sdim//===----------------------------------------------------------------------===//
9239313Sdim
10239313Sdim#ifndef LLVM_CLANG_SA_CORE_APSINTTYPE_H
11239313Sdim#define LLVM_CLANG_SA_CORE_APSINTTYPE_H
12239313Sdim
13239313Sdim#include "llvm/ADT/APSInt.h"
14239313Sdim
15239313Sdimnamespace clang {
16239313Sdimnamespace ento {
17239313Sdim
18239313Sdim/// \brief A record of the "type" of an APSInt, used for conversions.
19239313Sdimclass APSIntType {
20239313Sdim  uint32_t BitWidth;
21239313Sdim  bool IsUnsigned;
22239313Sdim
23239313Sdimpublic:
24239313Sdim  APSIntType(uint32_t Width, bool Unsigned)
25239313Sdim    : BitWidth(Width), IsUnsigned(Unsigned) {}
26239313Sdim
27239313Sdim  /* implicit */ APSIntType(const llvm::APSInt &Value)
28239313Sdim    : BitWidth(Value.getBitWidth()), IsUnsigned(Value.isUnsigned()) {}
29239313Sdim
30239313Sdim  uint32_t getBitWidth() const { return BitWidth; }
31239313Sdim  bool isUnsigned() const { return IsUnsigned; }
32239313Sdim
33239313Sdim  /// \brief Convert a given APSInt, in place, to match this type.
34239313Sdim  ///
35239313Sdim  /// This behaves like a C cast: converting 255u8 (0xFF) to s16 gives
36239313Sdim  /// 255 (0x00FF), and converting -1s8 (0xFF) to u16 gives 65535 (0xFFFF).
37239313Sdim  void apply(llvm::APSInt &Value) const {
38239313Sdim    // Note the order here. We extend first to preserve the sign, if this value
39239313Sdim    // is signed, /then/ match the signedness of the result type.
40239313Sdim    Value = Value.extOrTrunc(BitWidth);
41239313Sdim    Value.setIsUnsigned(IsUnsigned);
42239313Sdim  }
43239313Sdim
44239313Sdim  /// Convert and return a new APSInt with the given value, but this
45239313Sdim  /// type's bit width and signedness.
46239313Sdim  ///
47239313Sdim  /// \see apply
48239313Sdim  llvm::APSInt convert(const llvm::APSInt &Value) const LLVM_READONLY {
49239313Sdim    llvm::APSInt Result(Value, Value.isUnsigned());
50239313Sdim    apply(Result);
51239313Sdim    return Result;
52239313Sdim  }
53239313Sdim
54239313Sdim  /// Returns an all-zero value for this type.
55239313Sdim  llvm::APSInt getZeroValue() const LLVM_READONLY {
56239313Sdim    return llvm::APSInt(BitWidth, IsUnsigned);
57239313Sdim  }
58239313Sdim
59239313Sdim  /// Returns the minimum value for this type.
60239313Sdim  llvm::APSInt getMinValue() const LLVM_READONLY {
61239313Sdim    return llvm::APSInt::getMinValue(BitWidth, IsUnsigned);
62239313Sdim  }
63239313Sdim
64239313Sdim  /// Returns the maximum value for this type.
65239313Sdim  llvm::APSInt getMaxValue() const LLVM_READONLY {
66239313Sdim    return llvm::APSInt::getMaxValue(BitWidth, IsUnsigned);
67239313Sdim  }
68239313Sdim
69239313Sdim  /// Used to classify whether a value is representable using this type.
70239313Sdim  ///
71239313Sdim  /// \see testInRange
72239313Sdim  enum RangeTestResultKind {
73239313Sdim    RTR_Below = -1, ///< Value is less than the minimum representable value.
74239313Sdim    RTR_Within = 0, ///< Value is representable using this type.
75239313Sdim    RTR_Above = 1   ///< Value is greater than the maximum representable value.
76239313Sdim  };
77239313Sdim
78239313Sdim  /// Tests whether a given value is losslessly representable using this type.
79239313Sdim  ///
80239313Sdim  /// Note that signedness conversions will be rejected, even with the same bit
81239313Sdim  /// pattern. For example, -1s8 is not in range for 'unsigned char' (u8).
82239313Sdim  RangeTestResultKind testInRange(const llvm::APSInt &Val) const LLVM_READONLY;
83239313Sdim
84239313Sdim  bool operator==(const APSIntType &Other) const {
85239313Sdim    return BitWidth == Other.BitWidth && IsUnsigned == Other.IsUnsigned;
86239313Sdim  }
87239313Sdim
88239313Sdim  /// \brief Provide an ordering for finding a common conversion type.
89239313Sdim  ///
90239313Sdim  /// Unsigned integers are considered to be better conversion types than
91239313Sdim  /// signed integers of the same width.
92239313Sdim  bool operator<(const APSIntType &Other) const {
93239313Sdim    if (BitWidth < Other.BitWidth)
94239313Sdim      return true;
95239313Sdim    if (BitWidth > Other.BitWidth)
96239313Sdim      return false;
97239313Sdim    if (!IsUnsigned && Other.IsUnsigned)
98239313Sdim      return true;
99239313Sdim    return false;
100239313Sdim  }
101239313Sdim};
102239313Sdim
103239313Sdim} // end ento namespace
104239313Sdim} // end clang namespace
105239313Sdim
106239313Sdim#endif
107