forked from OSchip/llvm-project
Minor enhancements to GetIntegerValue(APInt):
* Detect overflow correctly. When it occurs, return the truncated value. * Add fixme for radix analysis. llvm-svn: 39382
This commit is contained in:
parent
5b743d3801
commit
871b4e101c
|
@ -266,32 +266,45 @@ bool NumericLiteralParser::GetIntegerValue(int &val) {
|
|||
}
|
||||
|
||||
/// GetIntegerValue - Convert this numeric literal value to an APInt that
|
||||
/// matches Val's input width. If there is an overflow, saturate Val to zero
|
||||
/// and return false. Otherwise, set Val and return true.
|
||||
/// matches Val's input width. If there is an overflow, set Val to the low bits
|
||||
/// of the result and return true. Otherwise, return false.
|
||||
bool NumericLiteralParser::GetIntegerValue(APInt &Val) {
|
||||
Val = 0;
|
||||
s = DigitsBegin;
|
||||
|
||||
// FIXME: This doesn't handle sign right, doesn't autopromote to wider
|
||||
// integer, and is generally not conformant.
|
||||
APInt RadixVal(Val.getBitWidth(), radix);
|
||||
APInt CharVal(Val.getBitWidth(), 0);
|
||||
APInt OldVal = Val;
|
||||
|
||||
bool OverflowOccurred = false;
|
||||
while (s < SuffixBegin) {
|
||||
unsigned C = HexLetterToVal(*s++);
|
||||
|
||||
// If this letter is out of bound for this radix, reject it.
|
||||
if (C >= radix) { Val = 0; return false; }
|
||||
if (C >= radix) {
|
||||
// FIXME: This is an error, not a warning. This should be caught by
|
||||
// NumericLiteralParser ctor.
|
||||
C = C % radix;
|
||||
OverflowOccurred = true;
|
||||
}
|
||||
|
||||
CharVal = C;
|
||||
|
||||
// Add the digit to the value in the appropriate radix. If adding in digits
|
||||
// made the value smaller, then this overflowed.
|
||||
OldVal = Val;
|
||||
|
||||
// Multiply by radix, did overflow occur on the multiply?
|
||||
Val *= RadixVal;
|
||||
OverflowOccurred |= Val.udiv(RadixVal) != OldVal;
|
||||
|
||||
OldVal = Val;
|
||||
// Add value, did overflow occur on the value?
|
||||
Val += CharVal;
|
||||
if (OldVal.ugt(Val))
|
||||
return false; // Overflow!
|
||||
OverflowOccurred |= Val.ult(OldVal);
|
||||
OverflowOccurred |= Val.ult(CharVal);
|
||||
}
|
||||
return true;
|
||||
return OverflowOccurred;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -63,9 +63,15 @@ public:
|
|||
/// type (int, unsigned, long, unsigned long, long long, unsigned long long)
|
||||
/// will be done elsewhere - the size computation is target dependent. We
|
||||
/// return true if the value fit into "val", false otherwise.
|
||||
/// NOTE: The api of these returns an inverted value for 'overflow' than the
|
||||
/// version below does.
|
||||
bool GetIntegerValue(uintmax_t &val);
|
||||
bool GetIntegerValue(int &val);
|
||||
bool GetIntegerValue(APInt &Val); //< Return the same width as Val.
|
||||
|
||||
/// GetIntegerValue - Convert this numeric literal value to an APInt that
|
||||
/// matches Val's input width. If there is an overflow, set Val to the low
|
||||
/// bits of the result and return true. Otherwise, return false.
|
||||
bool GetIntegerValue(APInt &Val);
|
||||
|
||||
private:
|
||||
void Diag(SourceLocation Loc, unsigned DiagID,
|
||||
|
|
Loading…
Reference in New Issue