Home | History | Annotate | Download | only in PathSensitive
      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_STATICANALYZER_CORE_PATHSENSITIVE_APSINTTYPE_H
     11 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_APSINTTYPE_H
     12 
     13 #include "llvm/ADT/APSInt.h"
     14 #include <tuple>
     15 
     16 namespace clang {
     17 namespace ento {
     18 
     19 /// \brief A record of the "type" of an APSInt, used for conversions.
     20 class APSIntType {
     21   uint32_t BitWidth;
     22   bool IsUnsigned;
     23 
     24 public:
     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