diff options
-rw-r--r-- | include/clang/Lex/LiteralSupport.h | 4 | ||||
-rw-r--r-- | lib/Lex/LiteralSupport.cpp | 55 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 5 | ||||
-rw-r--r-- | test/Sema/format-strings.c | 3 |
4 files changed, 43 insertions, 24 deletions
diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index 2334d728f6..ba46fb18a6 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -147,7 +147,7 @@ class StringLiteralParser { char *ResultPtr; // cursor public: StringLiteralParser(const Token *StringToks, unsigned NumStringToks, - Preprocessor &PP); + Preprocessor &PP, bool Complain = true); bool hadError; bool AnyWide; bool Pascal; @@ -164,7 +164,7 @@ public: /// specified byte of the string data represented by Token. This handles /// advancing over escape sequences in the string. static unsigned getOffsetOfStringByte(const Token &TheTok, unsigned ByteNo, - Preprocessor &PP); + Preprocessor &PP, bool Complain = true); }; } // end namespace clang diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp index f425582264..b73f236641 100644 --- a/lib/Lex/LiteralSupport.cpp +++ b/lib/Lex/LiteralSupport.cpp @@ -34,7 +34,7 @@ static int HexDigitValue(char C) { static unsigned ProcessCharEscape(const char *&ThisTokBuf, const char *ThisTokEnd, bool &HadError, SourceLocation Loc, bool IsWide, - Preprocessor &PP) { + Preprocessor &PP, bool Complain) { // Skip the '\' char. ++ThisTokBuf; @@ -54,11 +54,13 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, ResultChar = 8; break; case 'e': - PP.Diag(Loc, diag::ext_nonstandard_escape) << "e"; + if (Complain) + PP.Diag(Loc, diag::ext_nonstandard_escape) << "e"; ResultChar = 27; break; case 'E': - PP.Diag(Loc, diag::ext_nonstandard_escape) << "E"; + if (Complain) + PP.Diag(Loc, diag::ext_nonstandard_escape) << "E"; ResultChar = 27; break; case 'f': @@ -79,7 +81,8 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, case 'x': { // Hex escape. ResultChar = 0; if (ThisTokBuf == ThisTokEnd || !isxdigit(*ThisTokBuf)) { - PP.Diag(Loc, diag::err_hex_escape_no_digits); + if (Complain) + PP.Diag(Loc, diag::err_hex_escape_no_digits); HadError = 1; break; } @@ -106,7 +109,7 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, } // Check for overflow. - if (Overflow) // Too many digits to fit in + if (Overflow && Complain) // Too many digits to fit in PP.Diag(Loc, diag::warn_hex_escape_too_large); break; } @@ -132,7 +135,8 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, : PP.getTargetInfo().getCharWidth(); if (CharWidth != 32 && (ResultChar >> CharWidth) != 0) { - PP.Diag(Loc, diag::warn_octal_escape_too_large); + if (Complain) + PP.Diag(Loc, diag::warn_octal_escape_too_large); ResultChar &= ~0U >> (32-CharWidth); } break; @@ -141,10 +145,14 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, // Otherwise, these are not valid escapes. case '(': case '{': case '[': case '%': // GCC accepts these as extensions. We warn about them as such though. - PP.Diag(Loc, diag::ext_nonstandard_escape) - << std::string()+(char)ResultChar; + if (Complain) + PP.Diag(Loc, diag::ext_nonstandard_escape) + << std::string()+(char)ResultChar; break; default: + if (!Complain) + break; + if (isgraph(ThisTokBuf[0])) PP.Diag(Loc, diag::ext_unknown_escape) << std::string()+(char)ResultChar; else @@ -161,7 +169,8 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, /// we will likely rework our support for UCN's. static void ProcessUCNEscape(const char *&ThisTokBuf, const char *ThisTokEnd, char *&ResultBuf, bool &HadError, - SourceLocation Loc, bool IsWide, Preprocessor &PP) + SourceLocation Loc, bool IsWide, Preprocessor &PP, + bool Complain) { // FIXME: Add a warning - UCN's are only valid in C++ & C99. // FIXME: Handle wide strings. @@ -173,7 +182,8 @@ static void ProcessUCNEscape(const char *&ThisTokBuf, const char *ThisTokEnd, ThisTokBuf += 2; if (ThisTokBuf == ThisTokEnd || !isxdigit(*ThisTokBuf)) { - PP.Diag(Loc, diag::err_ucn_escape_no_digits); + if (Complain) + PP.Diag(Loc, diag::err_ucn_escape_no_digits); HadError = 1; return; } @@ -189,8 +199,9 @@ static void ProcessUCNEscape(const char *&ThisTokBuf, const char *ThisTokEnd, } // If we didn't consume the proper number of digits, there is a problem. if (UcnLen) { - PP.Diag(PP.AdvanceToTokenCharacter(Loc, ThisTokBuf-ThisTokBegin), - diag::err_ucn_escape_incomplete); + if (Complain) + PP.Diag(PP.AdvanceToTokenCharacter(Loc, ThisTokBuf-ThisTokBegin), + diag::err_ucn_escape_incomplete); HadError = 1; return; } @@ -199,7 +210,8 @@ static void ProcessUCNEscape(const char *&ThisTokBuf, const char *ThisTokEnd, (UcnVal != 0x24 && UcnVal != 0x40 && UcnVal != 0x60 )) // $, @, ` || (UcnVal >= 0xD800 && UcnVal <= 0xDFFF) || (UcnVal > 0x10FFFF)) /* the maximum legal UTF32 value */ { - PP.Diag(Loc, diag::err_ucn_escape_invalid); + if (Complain) + PP.Diag(Loc, diag::err_ucn_escape_invalid); HadError = 1; return; } @@ -660,7 +672,8 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end, if (begin[0] != '\\') // If this is a normal character, consume it. ResultChar = *begin++; else // Otherwise, this is an escape character. - ResultChar = ProcessCharEscape(begin, end, HadError, Loc, IsWide, PP); + ResultChar = ProcessCharEscape(begin, end, HadError, Loc, IsWide, PP, + /*Complain=*/true); // If this is a multi-character constant (e.g. 'abc'), handle it. These are // implementation defined (C99 6.4.4.4p10). @@ -746,7 +759,7 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end, /// StringLiteralParser:: StringLiteralParser(const Token *StringToks, unsigned NumStringToks, - Preprocessor &pp) : PP(pp) { + Preprocessor &pp, bool Complain) : PP(pp) { // Scan all of the string portions, remember the max individual token length, // computing a bound on the concatenated string length, and see whether any // piece is a wide-string. If any of the string portions is a wide-string @@ -871,13 +884,14 @@ StringLiteralParser(const Token *StringToks, unsigned NumStringToks, // Is this a Universal Character Name escape? if (ThisTokBuf[1] == 'u' || ThisTokBuf[1] == 'U') { ProcessUCNEscape(ThisTokBuf, ThisTokEnd, ResultPtr, - hadError, StringToks[i].getLocation(), ThisIsWide, PP); + hadError, StringToks[i].getLocation(), ThisIsWide, PP, + Complain); continue; } // Otherwise, this is a non-UCN escape character. Process it. unsigned ResultChar = ProcessCharEscape(ThisTokBuf, ThisTokEnd, hadError, StringToks[i].getLocation(), - ThisIsWide, PP); + ThisIsWide, PP, Complain); // Note: our internal rep of wide char tokens is always little-endian. *ResultPtr++ = ResultChar & 0xFF; @@ -893,7 +907,7 @@ StringLiteralParser(const Token *StringToks, unsigned NumStringToks, ResultBuf[0] = ResultPtr-&ResultBuf[0]-1; // Verify that pascal strings aren't too large. - if (GetStringLength() > 256) { + if (GetStringLength() > 256 && Complain) { PP.Diag(StringToks[0].getLocation(), diag::err_pascal_string_too_long) << SourceRange(StringToks[0].getLocation(), StringToks[NumStringToks-1].getLocation()); @@ -909,7 +923,8 @@ StringLiteralParser(const Token *StringToks, unsigned NumStringToks, /// advancing over escape sequences in the string. unsigned StringLiteralParser::getOffsetOfStringByte(const Token &Tok, unsigned ByteNo, - Preprocessor &PP) { + Preprocessor &PP, + bool Complain) { // Get the spelling of the token. llvm::SmallString<16> SpellingBuffer; SpellingBuffer.resize(Tok.getLength()); @@ -945,7 +960,7 @@ unsigned StringLiteralParser::getOffsetOfStringByte(const Token &Tok, // Otherwise, this is an escape character. Advance over it. bool HadError = false; ProcessCharEscape(SpellingPtr, SpellingEnd, HadError, - Tok.getLocation(), false, PP); + Tok.getLocation(), false, PP, Complain); assert(!HadError && "This method isn't valid on erroneous strings"); --ByteNo; } diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 8474944f06..4f3f41b715 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -75,14 +75,15 @@ SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL, TheLexer.LexFromRawLexer(TheTok); // Use the StringLiteralParser to compute the length of the string in bytes. - StringLiteralParser SLP(&TheTok, 1, PP); + StringLiteralParser SLP(&TheTok, 1, PP, /*Complain=*/false); unsigned TokNumBytes = SLP.GetStringLength(); // If the byte is in this token, return the location of the byte. if (ByteNo < TokNumBytes || (ByteNo == TokNumBytes && TokNo == SL->getNumConcatenated())) { unsigned Offset = - StringLiteralParser::getOffsetOfStringByte(TheTok, ByteNo, PP); + StringLiteralParser::getOffsetOfStringByte(TheTok, ByteNo, PP, + /*Complain=*/false); // Now that we know the offset of the token in the spelling, use the // preprocessor to get the offset in the original source. diff --git a/test/Sema/format-strings.c b/test/Sema/format-strings.c index bdc2bb0c9a..d6d37961d9 100644 --- a/test/Sema/format-strings.c +++ b/test/Sema/format-strings.c @@ -251,3 +251,6 @@ void test_pr_6697() { myprintf_PR_6697("%1$s\n", 1, (int) 0); // expected-warning{{conversion specifies type 'char *' but the argument has type 'int'}} } +void rdar8026030(FILE *fp) { + fprintf(fp, "\%"); // expected-warning{{incomplete format specifier}} +} |