summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp263
1 files changed, 178 insertions, 85 deletions
diff --git a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
index 9e3c778..e30612e 100644
--- a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
@@ -49,12 +49,46 @@ static unsigned getCharWidth(tok::TokenKind kind, const TargetInfo &Target) {
}
}
+static CharSourceRange MakeCharSourceRange(const LangOptions &Features,
+ FullSourceLoc TokLoc,
+ const char *TokBegin,
+ const char *TokRangeBegin,
+ const char *TokRangeEnd) {
+ SourceLocation Begin =
+ Lexer::AdvanceToTokenCharacter(TokLoc, TokRangeBegin - TokBegin,
+ TokLoc.getManager(), Features);
+ SourceLocation End =
+ Lexer::AdvanceToTokenCharacter(Begin, TokRangeEnd - TokRangeBegin,
+ TokLoc.getManager(), Features);
+ return CharSourceRange::getCharRange(Begin, End);
+}
+
+/// \brief Produce a diagnostic highlighting some portion of a literal.
+///
+/// Emits the diagnostic \p DiagID, highlighting the range of characters from
+/// \p TokRangeBegin (inclusive) to \p TokRangeEnd (exclusive), which must be
+/// a substring of a spelling buffer for the token beginning at \p TokBegin.
+static DiagnosticBuilder Diag(DiagnosticsEngine *Diags,
+ const LangOptions &Features, FullSourceLoc TokLoc,
+ const char *TokBegin, const char *TokRangeBegin,
+ const char *TokRangeEnd, unsigned DiagID) {
+ SourceLocation Begin =
+ Lexer::AdvanceToTokenCharacter(TokLoc, TokRangeBegin - TokBegin,
+ TokLoc.getManager(), Features);
+ return Diags->Report(Begin, DiagID) <<
+ MakeCharSourceRange(Features, TokLoc, TokBegin, TokRangeBegin, TokRangeEnd);
+}
+
/// ProcessCharEscape - Parse a standard C escape sequence, which can occur in
/// either a character or a string literal.
-static unsigned ProcessCharEscape(const char *&ThisTokBuf,
+static unsigned ProcessCharEscape(const char *ThisTokBegin,
+ const char *&ThisTokBuf,
const char *ThisTokEnd, bool &HadError,
FullSourceLoc Loc, unsigned CharWidth,
- DiagnosticsEngine *Diags) {
+ DiagnosticsEngine *Diags,
+ const LangOptions &Features) {
+ const char *EscapeBegin = ThisTokBuf;
+
// Skip the '\' char.
++ThisTokBuf;
@@ -75,12 +109,14 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf,
break;
case 'e':
if (Diags)
- Diags->Report(Loc, diag::ext_nonstandard_escape) << "e";
+ Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
+ diag::ext_nonstandard_escape) << "e";
ResultChar = 27;
break;
case 'E':
if (Diags)
- Diags->Report(Loc, diag::ext_nonstandard_escape) << "E";
+ Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
+ diag::ext_nonstandard_escape) << "E";
ResultChar = 27;
break;
case 'f':
@@ -102,7 +138,8 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf,
ResultChar = 0;
if (ThisTokBuf == ThisTokEnd || !isxdigit(*ThisTokBuf)) {
if (Diags)
- Diags->Report(Loc, diag::err_hex_escape_no_digits);
+ Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
+ diag::err_hex_escape_no_digits);
HadError = 1;
break;
}
@@ -126,7 +163,8 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf,
// Check for overflow.
if (Overflow && Diags) // Too many digits to fit in
- Diags->Report(Loc, diag::warn_hex_escape_too_large);
+ Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
+ diag::warn_hex_escape_too_large);
break;
}
case '0': case '1': case '2': case '3':
@@ -148,7 +186,8 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf,
// Check for overflow. Reject '\777', but not L'\777'.
if (CharWidth != 32 && (ResultChar >> CharWidth) != 0) {
if (Diags)
- Diags->Report(Loc, diag::warn_octal_escape_too_large);
+ Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
+ diag::warn_octal_escape_too_large);
ResultChar &= ~0U >> (32-CharWidth);
}
break;
@@ -158,19 +197,22 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf,
case '(': case '{': case '[': case '%':
// GCC accepts these as extensions. We warn about them as such though.
if (Diags)
- Diags->Report(Loc, diag::ext_nonstandard_escape)
- << std::string()+(char)ResultChar;
+ Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
+ diag::ext_nonstandard_escape)
+ << std::string(1, ResultChar);
break;
default:
if (Diags == 0)
break;
-
+
if (isgraph(ResultChar))
- Diags->Report(Loc, diag::ext_unknown_escape)
- << std::string()+(char)ResultChar;
+ Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
+ diag::ext_unknown_escape)
+ << std::string(1, ResultChar);
else
- Diags->Report(Loc, diag::ext_unknown_escape)
- << "x"+llvm::utohexstr(ResultChar);
+ Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
+ diag::ext_unknown_escape)
+ << "x" + llvm::utohexstr(ResultChar);
break;
}
@@ -185,9 +227,6 @@ static bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
FullSourceLoc Loc, DiagnosticsEngine *Diags,
const LangOptions &Features,
bool in_char_string_literal = false) {
- if (!Features.CPlusPlus && !Features.C99 && Diags)
- Diags->Report(Loc, diag::warn_ucn_not_valid_in_c89);
-
const char *UcnBegin = ThisTokBuf;
// Skip the '\u' char's.
@@ -195,7 +234,8 @@ static bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
if (ThisTokBuf == ThisTokEnd || !isxdigit(*ThisTokBuf)) {
if (Diags)
- Diags->Report(Loc, diag::err_ucn_escape_no_digits);
+ Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf,
+ diag::err_ucn_escape_no_digits);
return false;
}
UcnLen = (ThisTokBuf[-1] == 'u' ? 4 : 8);
@@ -208,12 +248,9 @@ static bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
}
// If we didn't consume the proper number of digits, there is a problem.
if (UcnLenSave) {
- if (Diags) {
- SourceLocation L =
- Lexer::AdvanceToTokenCharacter(Loc, UcnBegin - ThisTokBegin,
- Loc.getManager(), Features);
- Diags->Report(L, diag::err_ucn_escape_incomplete);
- }
+ if (Diags)
+ Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf,
+ diag::err_ucn_escape_incomplete);
return false;
}
@@ -221,7 +258,8 @@ static bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
if ((0xD800 <= UcnVal && UcnVal <= 0xDFFF) || // surrogate codepoints
UcnVal > 0x10FFFF) { // maximum legal UTF32 value
if (Diags)
- Diags->Report(Loc, diag::err_ucn_escape_invalid);
+ Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf,
+ diag::err_ucn_escape_invalid);
return false;
}
@@ -231,22 +269,25 @@ static bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
(UcnVal != 0x24 && UcnVal != 0x40 && UcnVal != 0x60)) { // $, @, `
bool IsError = (!Features.CPlusPlus0x || !in_char_string_literal);
if (Diags) {
- SourceLocation UcnBeginLoc =
- Lexer::AdvanceToTokenCharacter(Loc, UcnBegin - ThisTokBegin,
- Loc.getManager(), Features);
char BasicSCSChar = UcnVal;
if (UcnVal >= 0x20 && UcnVal < 0x7f)
- Diags->Report(UcnBeginLoc, IsError ? diag::err_ucn_escape_basic_scs :
- diag::warn_cxx98_compat_literal_ucn_escape_basic_scs)
- << StringRef(&BasicSCSChar, 1);
+ Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf,
+ IsError ? diag::err_ucn_escape_basic_scs :
+ diag::warn_cxx98_compat_literal_ucn_escape_basic_scs)
+ << StringRef(&BasicSCSChar, 1);
else
- Diags->Report(UcnBeginLoc, IsError ? diag::err_ucn_control_character :
- diag::warn_cxx98_compat_literal_ucn_control_character);
+ Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf,
+ IsError ? diag::err_ucn_control_character :
+ diag::warn_cxx98_compat_literal_ucn_control_character);
}
if (IsError)
return false;
}
+ if (!Features.CPlusPlus && !Features.C99 && Diags)
+ Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf,
+ diag::warn_ucn_not_valid_in_c89);
+
return true;
}
@@ -365,10 +406,10 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
// Finally, we write the bytes into ResultBuf.
ResultBuf += bytesToWrite;
switch (bytesToWrite) { // note: everything falls through.
- case 4: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6;
- case 3: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6;
- case 2: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6;
- case 1: *--ResultBuf = (UTF8) (UcnVal | firstByteMark[bytesToWrite]);
+ case 4: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6;
+ case 3: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6;
+ case 2: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6;
+ case 1: *--ResultBuf = (UTF8) (UcnVal | firstByteMark[bytesToWrite]);
}
// Update the buffer.
ResultBuf += bytesToWrite;
@@ -417,19 +458,19 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
/// floating-constant: [C99 6.4.4.2]
/// TODO: add rules...
///
-NumericLiteralParser::
-NumericLiteralParser(const char *begin, const char *end,
- SourceLocation TokLoc, Preprocessor &pp)
- : PP(pp), ThisTokBegin(begin), ThisTokEnd(end) {
+NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
+ SourceLocation TokLoc,
+ Preprocessor &PP)
+ : PP(PP), ThisTokBegin(TokSpelling.begin()), ThisTokEnd(TokSpelling.end()) {
// This routine assumes that the range begin/end matches the regex for integer
// and FP constants (specifically, the 'pp-number' regex), and assumes that
// the byte at "*end" is both valid and not part of the regex. Because of
// this, it doesn't have to check for 'overscan' in various places.
- assert(!isalnum(*end) && *end != '.' && *end != '_' &&
+ assert(!isalnum(*ThisTokEnd) && *ThisTokEnd != '.' && *ThisTokEnd != '_' &&
"Lexer didn't maximally munch?");
- s = DigitsBegin = begin;
+ s = DigitsBegin = ThisTokBegin;
saw_exponent = false;
saw_period = false;
saw_ud_suffix = false;
@@ -451,7 +492,7 @@ NumericLiteralParser(const char *begin, const char *end,
if (s == ThisTokEnd) {
// Done.
} else if (isxdigit(*s) && !(*s == 'e' || *s == 'E')) {
- PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-begin),
+ PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin),
diag::err_invalid_decimal_digit) << StringRef(s, 1);
hadError = true;
return;
@@ -469,7 +510,7 @@ NumericLiteralParser(const char *begin, const char *end,
if (first_non_digit != s) {
s = first_non_digit;
} else {
- PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-begin),
+ PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent - ThisTokBegin),
diag::err_exponent_has_no_digits);
hadError = true;
return;
@@ -565,7 +606,7 @@ NumericLiteralParser(const char *begin, const char *end,
case 'j':
case 'J':
if (isImaginary) break; // Cannot be repeated.
- PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-begin),
+ PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin),
diag::ext_imaginary_constant);
isImaginary = true;
continue; // Success.
@@ -583,7 +624,7 @@ NumericLiteralParser(const char *begin, const char *end,
}
// Report an error if there are any.
- PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, SuffixBegin-begin),
+ PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, SuffixBegin - ThisTokBegin),
isFPConstant ? diag::err_invalid_suffix_float_constant :
diag::err_invalid_suffix_integer_constant)
<< StringRef(SuffixBegin, ThisTokEnd-SuffixBegin);
@@ -619,7 +660,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
}
if (noSignificand) {
- PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), \
+ PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin),
diag::err_hexconstant_requires_digits);
hadError = true;
return;
@@ -722,6 +763,20 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
}
}
+static bool alwaysFitsInto64Bits(unsigned Radix, unsigned NumDigits) {
+ switch (Radix) {
+ case 2:
+ return NumDigits <= 64;
+ case 8:
+ return NumDigits <= 64 / 3; // Digits are groups of 3 bits.
+ case 10:
+ return NumDigits <= 19; // floor(log10(2^64))
+ case 16:
+ return NumDigits <= 64 / 4; // Digits are groups of 4 bits.
+ default:
+ llvm_unreachable("impossible Radix");
+ }
+}
/// 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
@@ -733,13 +788,11 @@ bool NumericLiteralParser::GetIntegerValue(llvm::APInt &Val) {
// integer. This avoids the expensive overflow checking below, and
// handles the common cases that matter (small decimal integers and
// hex/octal values which don't overflow).
- unsigned MaxBitsPerDigit = 1;
- while ((1U << MaxBitsPerDigit) < radix)
- MaxBitsPerDigit += 1;
- if ((SuffixBegin - DigitsBegin) * MaxBitsPerDigit <= 64) {
+ const unsigned NumDigits = SuffixBegin - DigitsBegin;
+ if (alwaysFitsInto64Bits(radix, NumDigits)) {
uint64_t N = 0;
- for (s = DigitsBegin; s != SuffixBegin; ++s)
- N = N*radix + HexDigitValue(*s);
+ for (const char *Ptr = DigitsBegin; Ptr != SuffixBegin; ++Ptr)
+ N = N * radix + HexDigitValue(*Ptr);
// This will truncate the value to Val's input width. Simply check
// for overflow by comparing.
@@ -748,15 +801,15 @@ bool NumericLiteralParser::GetIntegerValue(llvm::APInt &Val) {
}
Val = 0;
- s = DigitsBegin;
+ const char *Ptr = DigitsBegin;
llvm::APInt RadixVal(Val.getBitWidth(), radix);
llvm::APInt CharVal(Val.getBitWidth(), 0);
llvm::APInt OldVal = Val;
bool OverflowOccurred = false;
- while (s < SuffixBegin) {
- unsigned C = HexDigitValue(*s++);
+ while (Ptr < SuffixBegin) {
+ unsigned C = HexDigitValue(*Ptr++);
// If this letter is out of bound for this radix, reject it.
assert(C < radix && "NumericLiteralParser ctor should have rejected this");
@@ -943,7 +996,7 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end,
HadError = true;
} else if (*buffer_begin > largest_character_for_kind) {
HadError = true;
- PP.Diag(Loc,diag::err_character_too_large);
+ PP.Diag(Loc, diag::err_character_too_large);
}
++buffer_begin;
@@ -951,9 +1004,9 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end,
}
unsigned CharWidth = getCharWidth(Kind, PP.getTargetInfo());
uint64_t result =
- ProcessCharEscape(begin, end, HadError,
- FullSourceLoc(Loc,PP.getSourceManager()),
- CharWidth, &PP.getDiagnostics());
+ ProcessCharEscape(TokBegin, begin, end, HadError,
+ FullSourceLoc(Loc,PP.getSourceManager()),
+ CharWidth, &PP.getDiagnostics(), PP.getLangOpts());
*buffer_begin++ = result;
}
@@ -1110,7 +1163,7 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){
Kind = StringToks[i].getKind();
} else {
if (Diags)
- Diags->Report(FullSourceLoc(StringToks[i].getLocation(), SM),
+ Diags->Report(StringToks[i].getLocation(),
diag::err_unsupported_string_concat);
hadError = true;
}
@@ -1218,9 +1271,9 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){
assert(ThisTokEnd >= ThisTokBuf && "malformed raw string literal");
// Copy the string over
- if (CopyStringFragment(StringRef(ThisTokBuf, ThisTokEnd - ThisTokBuf)))
- if (DiagnoseBadString(StringToks[i]))
- hadError = true;
+ if (CopyStringFragment(StringToks[i], ThisTokBegin,
+ StringRef(ThisTokBuf, ThisTokEnd - ThisTokBuf)))
+ hadError = true;
} else {
if (ThisTokBuf[0] != '"') {
// The file may have come from PCH and then changed after loading the
@@ -1251,9 +1304,9 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){
} while (ThisTokBuf != ThisTokEnd && ThisTokBuf[0] != '\\');
// Copy the character span over.
- if (CopyStringFragment(StringRef(InStart, ThisTokBuf - InStart)))
- if (DiagnoseBadString(StringToks[i]))
- hadError = true;
+ if (CopyStringFragment(StringToks[i], ThisTokBegin,
+ StringRef(InStart, ThisTokBuf - InStart)))
+ hadError = true;
continue;
}
// Is this a Universal Character Name escape?
@@ -1266,9 +1319,9 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){
}
// Otherwise, this is a non-UCN escape character. Process it.
unsigned ResultChar =
- ProcessCharEscape(ThisTokBuf, ThisTokEnd, hadError,
+ ProcessCharEscape(ThisTokBegin, ThisTokBuf, ThisTokEnd, hadError,
FullSourceLoc(StringToks[i].getLocation(), SM),
- CharByteWidth*8, Diags);
+ CharByteWidth*8, Diags, Features);
if (CharByteWidth == 4) {
// FIXME: Make the type of the result buffer correct instead of
@@ -1308,8 +1361,8 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){
// Verify that pascal strings aren't too large.
if (GetStringLength() > 256) {
- if (Diags)
- Diags->Report(FullSourceLoc(StringToks[0].getLocation(), SM),
+ if (Diags)
+ Diags->Report(StringToks[0].getLocation(),
diag::err_pascal_string_too_long)
<< SourceRange(StringToks[0].getLocation(),
StringToks[NumStringToks-1].getLocation());
@@ -1319,9 +1372,9 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){
} else if (Diags) {
// Complain if this string literal has too many characters.
unsigned MaxChars = Features.CPlusPlus? 65536 : Features.C99 ? 4095 : 509;
-
+
if (GetNumStringChars() > MaxChars)
- Diags->Report(FullSourceLoc(StringToks[0].getLocation(), SM),
+ Diags->Report(StringToks[0].getLocation(),
diag::ext_string_too_long)
<< GetNumStringChars() << MaxChars
<< (Features.CPlusPlus ? 2 : Features.C99 ? 1 : 0)
@@ -1330,21 +1383,61 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){
}
}
-/// copyStringFragment - This function copies from Start to End into ResultPtr.
-/// Performs widening for multi-byte characters.
-bool StringLiteralParser::CopyStringFragment(StringRef Fragment) {
- return !ConvertUTF8toWide(CharByteWidth, Fragment, ResultPtr);
+static const char *resyncUTF8(const char *Err, const char *End) {
+ if (Err == End)
+ return End;
+ End = Err + std::min<unsigned>(getNumBytesForUTF8(*Err), End-Err);
+ while (++Err != End && (*Err & 0xC0) == 0x80)
+ ;
+ return Err;
}
-bool StringLiteralParser::DiagnoseBadString(const Token &Tok) {
+/// \brief This function copies from Fragment, which is a sequence of bytes
+/// within Tok's contents (which begin at TokBegin) into ResultPtr.
+/// Performs widening for multi-byte characters.
+bool StringLiteralParser::CopyStringFragment(const Token &Tok,
+ const char *TokBegin,
+ StringRef Fragment) {
+ const UTF8 *ErrorPtrTmp;
+ if (ConvertUTF8toWide(CharByteWidth, Fragment, ResultPtr, ErrorPtrTmp))
+ return false;
+
// If we see bad encoding for unprefixed string literals, warn and
// simply copy the byte values, for compatibility with gcc and older
// versions of clang.
bool NoErrorOnBadEncoding = isAscii();
- unsigned Msg = NoErrorOnBadEncoding ? diag::warn_bad_string_encoding :
- diag::err_bad_string_encoding;
- if (Diags)
- Diags->Report(FullSourceLoc(Tok.getLocation(), SM), Msg);
+ if (NoErrorOnBadEncoding) {
+ memcpy(ResultPtr, Fragment.data(), Fragment.size());
+ ResultPtr += Fragment.size();
+ }
+
+ if (Diags) {
+ const char *ErrorPtr = reinterpret_cast<const char *>(ErrorPtrTmp);
+
+ FullSourceLoc SourceLoc(Tok.getLocation(), SM);
+ const DiagnosticBuilder &Builder =
+ Diag(Diags, Features, SourceLoc, TokBegin,
+ ErrorPtr, resyncUTF8(ErrorPtr, Fragment.end()),
+ NoErrorOnBadEncoding ? diag::warn_bad_string_encoding
+ : diag::err_bad_string_encoding);
+
+ const char *NextStart = resyncUTF8(ErrorPtr, Fragment.end());
+ StringRef NextFragment(NextStart, Fragment.end()-NextStart);
+
+ // Decode into a dummy buffer.
+ SmallString<512> Dummy;
+ Dummy.reserve(Fragment.size() * CharByteWidth);
+ char *Ptr = Dummy.data();
+
+ while (!Builder.hasMaxRanges() &&
+ !ConvertUTF8toWide(CharByteWidth, NextFragment, Ptr, ErrorPtrTmp)) {
+ const char *ErrorPtr = reinterpret_cast<const char *>(ErrorPtrTmp);
+ NextStart = resyncUTF8(ErrorPtr, Fragment.end());
+ Builder << MakeCharSourceRange(Features, SourceLoc, TokBegin,
+ ErrorPtr, NextStart);
+ NextFragment = StringRef(NextStart, Fragment.end()-NextStart);
+ }
+ }
return !NoErrorOnBadEncoding;
}
@@ -1422,9 +1515,9 @@ unsigned StringLiteralParser::getOffsetOfStringByte(const Token &Tok,
}
ByteNo -= Len;
} else {
- ProcessCharEscape(SpellingPtr, SpellingEnd, HadError,
+ ProcessCharEscape(SpellingStart, SpellingPtr, SpellingEnd, HadError,
FullSourceLoc(Tok.getLocation(), SM),
- CharByteWidth*8, Diags);
+ CharByteWidth*8, Diags, Features);
--ByteNo;
}
assert(!HadError && "This method isn't valid on erroneous strings");
OpenPOWER on IntegriCloud