aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Lex/LiteralSupport.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Lex/LiteralSupport.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Lex/LiteralSupport.cpp68
1 files changed, 53 insertions, 15 deletions
diff --git a/contrib/llvm-project/clang/lib/Lex/LiteralSupport.cpp b/contrib/llvm-project/clang/lib/Lex/LiteralSupport.cpp
index 0a78638f6805..9d2720af5dbd 100644
--- a/contrib/llvm-project/clang/lib/Lex/LiteralSupport.cpp
+++ b/contrib/llvm-project/clang/lib/Lex/LiteralSupport.cpp
@@ -974,6 +974,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
bool isFixedPointConstant = isFixedPointLiteral();
bool isFPConstant = isFloatingLiteral();
bool HasSize = false;
+ bool DoubleUnderscore = false;
// Loop over all of the characters of the suffix. If we see something bad,
// we break out of the loop.
@@ -1117,6 +1118,32 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
if (isImaginary) break; // Cannot be repeated.
isImaginary = true;
continue; // Success.
+ case '_':
+ if (isFPConstant)
+ break; // Invalid for floats
+ if (HasSize)
+ break;
+ // There is currently no way to reach this with DoubleUnderscore set.
+ // If new double underscope literals are added handle it here as above.
+ assert(!DoubleUnderscore && "unhandled double underscore case");
+ if (LangOpts.CPlusPlus && s + 2 < ThisTokEnd &&
+ s[1] == '_') { // s + 2 < ThisTokEnd to ensure some character exists
+ // after __
+ DoubleUnderscore = true;
+ s += 2; // Skip both '_'
+ if (s + 1 < ThisTokEnd &&
+ (*s == 'u' || *s == 'U')) { // Ensure some character after 'u'/'U'
+ isUnsigned = true;
+ ++s;
+ }
+ if (s + 1 < ThisTokEnd &&
+ ((*s == 'w' && *(++s) == 'b') || (*s == 'W' && *(++s) == 'B'))) {
+ isBitInt = true;
+ HasSize = true;
+ continue;
+ }
+ }
+ break;
case 'w':
case 'W':
if (isFPConstant)
@@ -1127,9 +1154,9 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
// wb and WB are allowed, but a mixture of cases like Wb or wB is not. We
// explicitly do not support the suffix in C++ as an extension because a
// library-based UDL that resolves to a library type may be more
- // appropriate there.
- if (!LangOpts.CPlusPlus && ((s[0] == 'w' && s[1] == 'b') ||
- (s[0] == 'W' && s[1] == 'B'))) {
+ // appropriate there. The same rules apply for __wb/__WB.
+ if ((!LangOpts.CPlusPlus || DoubleUnderscore) && s + 1 < ThisTokEnd &&
+ ((s[0] == 'w' && s[1] == 'b') || (s[0] == 'W' && s[1] == 'B'))) {
isBitInt = true;
HasSize = true;
++s; // Skip both characters (2nd char skipped on continue).
@@ -1241,7 +1268,9 @@ bool NumericLiteralParser::isValidUDSuffix(const LangOptions &LangOpts,
return false;
// By C++11 [lex.ext]p10, ud-suffixes starting with an '_' are always valid.
- if (Suffix[0] == '_')
+ // Suffixes starting with '__' (double underscore) are for use by
+ // the implementation.
+ if (Suffix.starts_with("_") && !Suffix.starts_with("__"))
return true;
// In C++11, there are no library suffixes.
@@ -1358,11 +1387,17 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
// Handle simple binary numbers 0b01010
if ((c1 == 'b' || c1 == 'B') && (s[1] == '0' || s[1] == '1')) {
- // 0b101010 is a C++1y / GCC extension.
- Diags.Report(TokLoc, LangOpts.CPlusPlus14
- ? diag::warn_cxx11_compat_binary_literal
- : LangOpts.CPlusPlus ? diag::ext_binary_literal_cxx14
- : diag::ext_binary_literal);
+ // 0b101010 is a C++14 and C23 extension.
+ unsigned DiagId;
+ if (LangOpts.CPlusPlus14)
+ DiagId = diag::warn_cxx11_compat_binary_literal;
+ else if (LangOpts.C23)
+ DiagId = diag::warn_c23_compat_binary_literal;
+ else if (LangOpts.CPlusPlus)
+ DiagId = diag::ext_binary_literal_cxx14;
+ else
+ DiagId = diag::ext_binary_literal;
+ Diags.Report(TokLoc, DiagId);
++s;
assert(s < ThisTokEnd && "didn't maximally munch?");
radix = 2;
@@ -1486,7 +1521,8 @@ bool NumericLiteralParser::GetIntegerValue(llvm::APInt &Val) {
}
llvm::APFloat::opStatus
-NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) {
+NumericLiteralParser::GetFloatValue(llvm::APFloat &Result,
+ llvm::RoundingMode RM) {
using llvm::APFloat;
unsigned n = std::min(SuffixBegin - ThisTokBegin, ThisTokEnd - ThisTokBegin);
@@ -1500,15 +1536,16 @@ NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) {
Str = Buffer;
}
- auto StatusOrErr =
- Result.convertFromString(Str, APFloat::rmNearestTiesToEven);
+ auto StatusOrErr = Result.convertFromString(Str, RM);
assert(StatusOrErr && "Invalid floating point representation");
return !errorToBool(StatusOrErr.takeError()) ? *StatusOrErr
: APFloat::opInvalidOp;
}
-static inline bool IsExponentPart(char c) {
- return c == 'p' || c == 'P' || c == 'e' || c == 'E';
+static inline bool IsExponentPart(char c, bool isHex) {
+ if (isHex)
+ return c == 'p' || c == 'P';
+ return c == 'e' || c == 'E';
}
bool NumericLiteralParser::GetFixedPointValue(llvm::APInt &StoreVal, unsigned Scale) {
@@ -1527,7 +1564,8 @@ bool NumericLiteralParser::GetFixedPointValue(llvm::APInt &StoreVal, unsigned Sc
if (saw_exponent) {
const char *Ptr = DigitsBegin;
- while (!IsExponentPart(*Ptr)) ++Ptr;
+ while (!IsExponentPart(*Ptr, radix == 16))
+ ++Ptr;
ExponentBegin = Ptr;
++Ptr;
NegativeExponent = *Ptr == '-';