diff options
Diffstat (limited to 'clang/lib/Lex')
| -rw-r--r-- | clang/lib/Lex/LiteralSupport.cpp | 153 | 
1 files changed, 151 insertions, 2 deletions
diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp index af64ffef6c0..e414f85e021 100644 --- a/clang/lib/Lex/LiteralSupport.cpp +++ b/clang/lib/Lex/LiteralSupport.cpp @@ -538,6 +538,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,    saw_exponent = false;    saw_period = false;    saw_ud_suffix = false; +  saw_fixed_point_suffix = false;    isLong = false;    isUnsigned = false;    isLongLong = false; @@ -547,6 +548,8 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,    isFloat16 = false;    isFloat128 = false;    MicrosoftInteger = 0; +  isFract = false; +  isAccum = false;    hadError = false;    if (*s == '0') { // parse radix @@ -568,6 +571,14 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,    SuffixBegin = s;    checkSeparator(TokLoc, s, CSK_AfterDigits); +  // Initial scan to lookahead for fixed point suffix. +  for (const char *c = s; c != ThisTokEnd; ++c) { +    if (*c == 'r' || *c == 'k' || *c == 'R' || *c == 'K') { +      saw_fixed_point_suffix = true; +      break; +    } +  } +    // Parse the suffix.  At this point we can classify whether we have an FP or    // integer constant.    bool isFPConstant = isFloatingLiteral(); @@ -576,11 +587,21 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,    // we break out of the loop.    for (; s != ThisTokEnd; ++s) {      switch (*s) { +    case 'R': +    case 'r': +      if (isFract || isAccum) break; +      isFract = true; +      continue; +    case 'K': +    case 'k': +      if (isFract || isAccum) break; +      isAccum = true; +      continue;      case 'h':      // FP Suffix for "half".      case 'H':        // OpenCL Extension v1.2 s9.5 - h or H suffix for half type. -      if (!PP.getLangOpts().Half) break; -      if (!isFPConstant) break;  // Error for integer constant. +      if (!(PP.getLangOpts().Half || PP.getLangOpts().FixedPoint)) break; +      if (isIntegerLiteral()) break;  // Error for integer constant.        if (isHalf || isFloat || isLong) break; // HH, FH, LH invalid.        isHalf = true;        continue;  // Success. @@ -693,6 +714,9 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,          isHalf = false;          isImaginary = false;          MicrosoftInteger = 0; +        saw_fixed_point_suffix = false; +        isFract = false; +        isAccum = false;        }        saw_ud_suffix = true; @@ -707,6 +731,11 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,        hadError = true;      }    } + +  if (!hadError && saw_fixed_point_suffix) { +    assert(isFract || isAccum); +    assert(radix == 16 || radix == 10); +  }  }  /// ParseDecimalOrOctalCommon - This method is called for decimal or octal @@ -1012,6 +1041,126 @@ NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) {    return Result.convertFromString(Str, APFloat::rmNearestTiesToEven);  } +static inline bool IsExponentPart(char c) { +  return c == 'p' || c == 'P' || c == 'e' || c == 'E'; +} + +bool NumericLiteralParser::GetFixedPointValue(llvm::APInt &StoreVal, unsigned Scale) { +  assert(radix == 16 || radix == 10); + +  // Find how many digits are needed to store the whole literal. +  unsigned NumDigits = SuffixBegin - DigitsBegin; +  if (saw_period) --NumDigits; + +  // Initial scan of the exponent if it exists +  bool ExpOverflowOccurred = false; +  bool NegativeExponent = false; +  const char *ExponentBegin; +  uint64_t Exponent = 0; +  int64_t BaseShift = 0; +  if (saw_exponent) { +    const char *Ptr = DigitsBegin; + +    while (!IsExponentPart(*Ptr)) ++Ptr; +    ExponentBegin = Ptr; +    ++Ptr; +    NegativeExponent = *Ptr == '-'; +    if (NegativeExponent) ++Ptr; + +    unsigned NumExpDigits = SuffixBegin - Ptr; +    if (alwaysFitsInto64Bits(radix, NumExpDigits)) { +      llvm::StringRef ExpStr(Ptr, NumExpDigits); +      llvm::APInt ExpInt(/*numBits=*/64, ExpStr, /*radix=*/10); +      Exponent = ExpInt.getZExtValue(); +    } else { +      ExpOverflowOccurred = true; +    } + +    if (NegativeExponent) BaseShift -= Exponent; +    else BaseShift += Exponent; +  } + +  // Number of bits needed for decimal literal is +  //   ceil(NumDigits * log2(10))       Integral part +  // + Scale                            Fractional part +  // + ceil(Exponent * log2(10))        Exponent +  // -------------------------------------------------- +  //   ceil((NumDigits + Exponent) * log2(10)) + Scale +  // +  // But for simplicity in handling integers, we can round up log2(10) to 4, +  // making: +  // 4 * (NumDigits + Exponent) + Scale +  // +  // Number of digits needed for hexadecimal literal is +  //   4 * NumDigits                    Integral part +  // + Scale                            Fractional part +  // + Exponent                         Exponent +  // -------------------------------------------------- +  //   (4 * NumDigits) + Scale + Exponent +  uint64_t NumBitsNeeded; +  if (radix == 10) +    NumBitsNeeded = 4 * (NumDigits + Exponent) + Scale; +  else +    NumBitsNeeded = 4 * NumDigits + Exponent + Scale; + +  if (NumBitsNeeded > std::numeric_limits<unsigned>::max()) +    ExpOverflowOccurred = true; +  llvm::APInt Val(static_cast<unsigned>(NumBitsNeeded), 0, /*isSigned=*/false); + +  bool FoundDecimal = false; + +  int64_t FractBaseShift = 0; +  const char *End = saw_exponent ? ExponentBegin : SuffixBegin; +  for (const char *Ptr = DigitsBegin; Ptr < End; ++Ptr) { +    if (*Ptr == '.') { +      FoundDecimal = true; +      continue; +    } + +    // Normal reading of an integer +    unsigned C = llvm::hexDigitValue(*Ptr); +    assert(C < radix && "NumericLiteralParser ctor should have rejected this"); + +    Val *= radix; +    Val += C; + +    if (FoundDecimal) +      // Keep track of how much we will need to adjust this value by from the +      // number of digits past the radix point. +      --FractBaseShift; +  } + +  // For a radix of 16, we will be multiplying by 2 instead of 16. +  if (radix == 16) FractBaseShift *= 4; +  BaseShift += FractBaseShift; + +  Val <<= Scale; + +  uint64_t Base = (radix == 16) ? 2 : 10; +  if (BaseShift > 0) { +    for (int64_t i = 0; i < BaseShift; ++i) { +      Val *= Base; +    } +  } else if (BaseShift < 0) { +    for (int64_t i = BaseShift; i < 0 && !Val.isNullValue(); ++i) +      Val = Val.udiv(Base); +  } + +  bool IntOverflowOccurred = false; +  auto MaxVal = llvm::APInt::getMaxValue(StoreVal.getBitWidth()); +  if (Val.getBitWidth() > StoreVal.getBitWidth()) { +    IntOverflowOccurred |= Val.ugt(MaxVal.zext(Val.getBitWidth())); +    StoreVal = Val.trunc(StoreVal.getBitWidth()); +  } else if (Val.getBitWidth() < StoreVal.getBitWidth()) { +    IntOverflowOccurred |= Val.zext(MaxVal.getBitWidth()).ugt(MaxVal); +    StoreVal = Val.zext(StoreVal.getBitWidth()); +  } else { +    StoreVal = Val; +  } + +  return IntOverflowOccurred || ExpOverflowOccurred; +} +  /// \verbatim  ///       user-defined-character-literal: [C++11 lex.ext]  ///         character-literal ud-suffix  | 

