mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-02 08:26:29 +00:00
Make StringRef::getAsInteger work with all integer types. Before this change
it would fail with {,u}int64_t on x86-64 Linux. This also removes code duplication. llvm-svn: 152517
This commit is contained in:
parent
e68be7638b
commit
69772efcb2
@ -10,16 +10,26 @@
|
||||
#ifndef LLVM_ADT_STRINGREF_H
|
||||
#define LLVM_ADT_STRINGREF_H
|
||||
|
||||
#include "llvm/Support/type_traits.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
template<typename T>
|
||||
class SmallVectorImpl;
|
||||
class APInt;
|
||||
class hash_code;
|
||||
class StringRef;
|
||||
|
||||
/// Helper functions for StringRef::getAsInteger.
|
||||
bool getAsUnsignedInteger(StringRef Str, unsigned Radix,
|
||||
unsigned long long &Result);
|
||||
|
||||
bool getAsSignedInteger(StringRef Str, unsigned Radix, long long &Result);
|
||||
|
||||
/// StringRef - Represent a constant reference to a string, i.e. a character
|
||||
/// array and a length, which need not be null terminated.
|
||||
@ -305,14 +315,29 @@ namespace llvm {
|
||||
///
|
||||
/// If the string is invalid or if only a subset of the string is valid,
|
||||
/// this returns true to signify the error. The string is considered
|
||||
/// erroneous if empty.
|
||||
/// erroneous if empty or if it overflows T.
|
||||
///
|
||||
bool getAsInteger(unsigned Radix, long long &Result) const;
|
||||
bool getAsInteger(unsigned Radix, unsigned long long &Result) const;
|
||||
bool getAsInteger(unsigned Radix, int &Result) const;
|
||||
bool getAsInteger(unsigned Radix, unsigned &Result) const;
|
||||
template <typename T>
|
||||
typename enable_if_c<std::numeric_limits<T>::is_signed, bool>::type
|
||||
getAsInteger(unsigned Radix, T &Result) const {
|
||||
long long LLVal;
|
||||
if (getAsSignedInteger(*this, Radix, LLVal) ||
|
||||
static_cast<T>(LLVal) != LLVal)
|
||||
return true;
|
||||
Result = LLVal;
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Provide overloads for int/unsigned that check for overflow.
|
||||
template <typename T>
|
||||
typename enable_if_c<!std::numeric_limits<T>::is_signed, bool>::type
|
||||
getAsInteger(unsigned Radix, T &Result) const {
|
||||
unsigned long long ULLVal;
|
||||
if (getAsUnsignedInteger(*this, Radix, ULLVal) ||
|
||||
static_cast<T>(ULLVal) != ULLVal)
|
||||
return true;
|
||||
Result = ULLVal;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getAsInteger - Parse the current string as an integer of the
|
||||
/// specified radix, or of an autosensed radix if the radix given
|
||||
|
@ -285,8 +285,8 @@ static unsigned GetAutoSenseRadix(StringRef &Str) {
|
||||
|
||||
/// GetAsUnsignedInteger - Workhorse method that converts a integer character
|
||||
/// sequence of radix up to 36 to an unsigned long long value.
|
||||
static bool GetAsUnsignedInteger(StringRef Str, unsigned Radix,
|
||||
unsigned long long &Result) {
|
||||
bool llvm::getAsUnsignedInteger(StringRef Str, unsigned Radix,
|
||||
unsigned long long &Result) {
|
||||
// Autosense radix if not specified.
|
||||
if (Radix == 0)
|
||||
Radix = GetAutoSenseRadix(Str);
|
||||
@ -326,17 +326,13 @@ static bool GetAsUnsignedInteger(StringRef Str, unsigned Radix,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StringRef::getAsInteger(unsigned Radix, unsigned long long &Result) const {
|
||||
return GetAsUnsignedInteger(*this, Radix, Result);
|
||||
}
|
||||
|
||||
|
||||
bool StringRef::getAsInteger(unsigned Radix, long long &Result) const {
|
||||
bool llvm::getAsSignedInteger(StringRef Str, unsigned Radix,
|
||||
long long &Result) {
|
||||
unsigned long long ULLVal;
|
||||
|
||||
// Handle positive strings first.
|
||||
if (empty() || front() != '-') {
|
||||
if (GetAsUnsignedInteger(*this, Radix, ULLVal) ||
|
||||
if (Str.empty() || Str.front() != '-') {
|
||||
if (getAsUnsignedInteger(Str, Radix, ULLVal) ||
|
||||
// Check for value so large it overflows a signed value.
|
||||
(long long)ULLVal < 0)
|
||||
return true;
|
||||
@ -345,7 +341,7 @@ bool StringRef::getAsInteger(unsigned Radix, long long &Result) const {
|
||||
}
|
||||
|
||||
// Get the positive part of the value.
|
||||
if (GetAsUnsignedInteger(substr(1), Radix, ULLVal) ||
|
||||
if (getAsUnsignedInteger(Str.substr(1), Radix, ULLVal) ||
|
||||
// Reject values so large they'd overflow as negative signed, but allow
|
||||
// "-0". This negates the unsigned so that the negative isn't undefined
|
||||
// on signed overflow.
|
||||
@ -356,24 +352,6 @@ bool StringRef::getAsInteger(unsigned Radix, long long &Result) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StringRef::getAsInteger(unsigned Radix, int &Result) const {
|
||||
long long Val;
|
||||
if (getAsInteger(Radix, Val) ||
|
||||
(int)Val != Val)
|
||||
return true;
|
||||
Result = Val;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StringRef::getAsInteger(unsigned Radix, unsigned &Result) const {
|
||||
unsigned long long Val;
|
||||
if (getAsInteger(Radix, Val) ||
|
||||
(unsigned)Val != Val)
|
||||
return true;
|
||||
Result = Val;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StringRef::getAsInteger(unsigned Radix, APInt &Result) const {
|
||||
StringRef Str = *this;
|
||||
|
||||
|
@ -310,4 +310,122 @@ TEST(StringRefTest, Hashing) {
|
||||
hash_value(StringRef("hello world").slice(1, -1)));
|
||||
}
|
||||
|
||||
struct UnsignedPair {
|
||||
const char *Str;
|
||||
uint64_t Expected;
|
||||
} Unsigned[] =
|
||||
{ {"0", 0}
|
||||
, {"255", 255}
|
||||
, {"256", 256}
|
||||
, {"65535", 65535}
|
||||
, {"65536", 65536}
|
||||
, {"4294967295", 4294967295}
|
||||
, {"4294967296", 4294967296}
|
||||
, {"18446744073709551615", 18446744073709551615ULL}
|
||||
, {"042", 34}
|
||||
, {"0x42", 66}
|
||||
, {"0b101010", 42}
|
||||
};
|
||||
|
||||
struct SignedPair {
|
||||
const char *Str;
|
||||
int64_t Expected;
|
||||
} Signed[] =
|
||||
{ {"0", 0}
|
||||
, {"-0", 0}
|
||||
, {"127", 127}
|
||||
, {"128", 128}
|
||||
, {"-128", -128}
|
||||
, {"-129", -129}
|
||||
, {"32767", 32767}
|
||||
, {"32768", 32768}
|
||||
, {"-32768", -32768}
|
||||
, {"-32769", -32769}
|
||||
, {"2147483647", 2147483647}
|
||||
, {"2147483648", 2147483648}
|
||||
, {"-2147483648", -2147483648LL}
|
||||
, {"-2147483649", -2147483649LL}
|
||||
, {"-9223372036854775808", -(9223372036854775807LL) - 1}
|
||||
, {"042", 34}
|
||||
, {"0x42", 66}
|
||||
, {"0b101010", 42}
|
||||
, {"-042", -34}
|
||||
, {"-0x42", -66}
|
||||
, {"-0b101010", -42}
|
||||
};
|
||||
|
||||
TEST(StringRefTest, getAsInteger) {
|
||||
uint8_t U8;
|
||||
uint16_t U16;
|
||||
uint32_t U32;
|
||||
uint64_t U64;
|
||||
|
||||
for (size_t i = 0; i < array_lengthof(Unsigned); ++i) {
|
||||
bool U8Success = StringRef(Unsigned[i].Str).getAsInteger(0, U8);
|
||||
if (static_cast<uint8_t>(Unsigned[i].Expected) == Unsigned[i].Expected) {
|
||||
ASSERT_FALSE(U8Success);
|
||||
EXPECT_EQ(U8, Unsigned[i].Expected);
|
||||
} else {
|
||||
ASSERT_TRUE(U8Success);
|
||||
}
|
||||
bool U16Success = StringRef(Unsigned[i].Str).getAsInteger(0, U16);
|
||||
if (static_cast<uint16_t>(Unsigned[i].Expected) == Unsigned[i].Expected) {
|
||||
ASSERT_FALSE(U16Success);
|
||||
EXPECT_EQ(U16, Unsigned[i].Expected);
|
||||
} else {
|
||||
ASSERT_TRUE(U16Success);
|
||||
}
|
||||
bool U32Success = StringRef(Unsigned[i].Str).getAsInteger(0, U32);
|
||||
if (static_cast<uint32_t>(Unsigned[i].Expected) == Unsigned[i].Expected) {
|
||||
ASSERT_FALSE(U32Success);
|
||||
EXPECT_EQ(U32, Unsigned[i].Expected);
|
||||
} else {
|
||||
ASSERT_TRUE(U32Success);
|
||||
}
|
||||
bool U64Success = StringRef(Unsigned[i].Str).getAsInteger(0, U64);
|
||||
if (static_cast<uint64_t>(Unsigned[i].Expected) == Unsigned[i].Expected) {
|
||||
ASSERT_FALSE(U64Success);
|
||||
EXPECT_EQ(U64, Unsigned[i].Expected);
|
||||
} else {
|
||||
ASSERT_TRUE(U64Success);
|
||||
}
|
||||
}
|
||||
|
||||
int8_t S8;
|
||||
int16_t S16;
|
||||
int32_t S32;
|
||||
int64_t S64;
|
||||
|
||||
for (size_t i = 0; i < array_lengthof(Signed); ++i) {
|
||||
bool S8Success = StringRef(Signed[i].Str).getAsInteger(0, S8);
|
||||
if (static_cast<int8_t>(Signed[i].Expected) == Signed[i].Expected) {
|
||||
ASSERT_FALSE(S8Success);
|
||||
EXPECT_EQ(S8, Signed[i].Expected);
|
||||
} else {
|
||||
ASSERT_TRUE(S8Success);
|
||||
}
|
||||
bool S16Success = StringRef(Signed[i].Str).getAsInteger(0, S16);
|
||||
if (static_cast<int16_t>(Signed[i].Expected) == Signed[i].Expected) {
|
||||
ASSERT_FALSE(S16Success);
|
||||
EXPECT_EQ(S16, Signed[i].Expected);
|
||||
} else {
|
||||
ASSERT_TRUE(S16Success);
|
||||
}
|
||||
bool S32Success = StringRef(Signed[i].Str).getAsInteger(0, S32);
|
||||
if (static_cast<int32_t>(Signed[i].Expected) == Signed[i].Expected) {
|
||||
ASSERT_FALSE(S32Success);
|
||||
EXPECT_EQ(S32, Signed[i].Expected);
|
||||
} else {
|
||||
ASSERT_TRUE(S32Success);
|
||||
}
|
||||
bool S64Success = StringRef(Signed[i].Str).getAsInteger(0, S64);
|
||||
if (static_cast<int64_t>(Signed[i].Expected) == Signed[i].Expected) {
|
||||
ASSERT_FALSE(S64Success);
|
||||
EXPECT_EQ(S64, Signed[i].Expected);
|
||||
} else {
|
||||
ASSERT_TRUE(S64Success);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
Loading…
Reference in New Issue
Block a user