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
69245431Sdim  llvm::APSInt getValue(uint64_t RawValue) const LLVM_READONLY {
70245431Sdim    return (llvm::APSInt(BitWidth, IsUnsigned) = RawValue);
71245431Sdim  }
72245431Sdim
73239313Sdim  /// Used to classify whether a value is representable using this type.
74239313Sdim  ///
75239313Sdim  /// \see testInRange
76239313Sdim  enum RangeTestResultKind {
77239313Sdim    RTR_Below = -1, ///< Value is less than the minimum representable value.
78239313Sdim    RTR_Within = 0, ///< Value is representable using this type.
79239313Sdim    RTR_Above = 1   ///< Value is greater than the maximum representable value.
80239313Sdim  };
81239313Sdim
82239313Sdim  /// Tests whether a given value is losslessly representable using this type.
83239313Sdim  ///
84252723Sdim  /// \param Val The value to test.
85252723Sdim  /// \param AllowMixedSign Whether or not to allow signedness conversions.
86252723Sdim  ///                       This determines whether -1s8 is considered in range
87252723Sdim  ///                       for 'unsigned char' (u8).
88252723Sdim  RangeTestResultKind testInRange(const llvm::APSInt &Val,
89252723Sdim                                  bool AllowMixedSign) const LLVM_READONLY;
90239313Sdim
91239313Sdim  bool operator==(const APSIntType &Other) const {
92239313Sdim    return BitWidth == Other.BitWidth && IsUnsigned == Other.IsUnsigned;
93239313Sdim  }
94239313Sdim
95239313Sdim  /// \brief Provide an ordering for finding a common conversion type.
96239313Sdim  ///
97239313Sdim  /// Unsigned integers are considered to be better conversion types than
98239313Sdim  /// signed integers of the same width.
99239313Sdim  bool operator<(const APSIntType &Other) const {
100239313Sdim    if (BitWidth < Other.BitWidth)
101239313Sdim      return true;
102239313Sdim    if (BitWidth > Other.BitWidth)
103239313Sdim      return false;
104239313Sdim    if (!IsUnsigned && Other.IsUnsigned)
105239313Sdim      return true;
106239313Sdim    return false;
107239313Sdim  }
108239313Sdim};
109239313Sdim
110239313Sdim} // end ento namespace
111239313Sdim} // end clang namespace
112239313Sdim
113239313Sdim#endif
114