[cfe-commits] r104684 - in /cfe/trunk: include/clang/Lex/LiteralSupport.h lib/Lex/LiteralSupport.cpp lib/Sema/SemaChecking.cpp test/Sema/format-strings.c

Douglas Gregor dgregor at apple.com
Tue May 25 22:35:51 PDT 2010


Author: dgregor
Date: Wed May 26 00:35:51 2010
New Revision: 104684

URL: http://llvm.org/viewvc/llvm-project?rev=104684&view=rev
Log:
Tell the string literal parser when it's not permitted to emit
diagnostics. That would be while we're parsing string literals for the
sole purpose of producing a diagnostic about them. Fixes
<rdar://problem/8026030>.

Modified:
    cfe/trunk/include/clang/Lex/LiteralSupport.h
    cfe/trunk/lib/Lex/LiteralSupport.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/test/Sema/format-strings.c

Modified: cfe/trunk/include/clang/Lex/LiteralSupport.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/LiteralSupport.h?rev=104684&r1=104683&r2=104684&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/LiteralSupport.h (original)
+++ cfe/trunk/include/clang/Lex/LiteralSupport.h Wed May 26 00:35:51 2010
@@ -147,7 +147,7 @@
   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 @@
   /// 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

Modified: cfe/trunk/lib/Lex/LiteralSupport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/LiteralSupport.cpp?rev=104684&r1=104683&r2=104684&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/LiteralSupport.cpp (original)
+++ cfe/trunk/lib/Lex/LiteralSupport.cpp Wed May 26 00:35:51 2010
@@ -34,7 +34,7 @@
 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 @@
     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 @@
   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 @@
     }
 
     // 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 @@
                        : 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 @@
     // 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 @@
 /// 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 @@
   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 @@
   }
   // 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 @@
       (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 @@
     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 @@
 ///
 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 @@
       // 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 @@
     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 @@
 /// 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 @@
     // 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;
   }

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=104684&r1=104683&r2=104684&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Wed May 26 00:35:51 2010
@@ -75,14 +75,15 @@
     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.

Modified: cfe/trunk/test/Sema/format-strings.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings.c?rev=104684&r1=104683&r2=104684&view=diff
==============================================================================
--- cfe/trunk/test/Sema/format-strings.c (original)
+++ cfe/trunk/test/Sema/format-strings.c Wed May 26 00:35:51 2010
@@ -251,3 +251,6 @@
   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}}
+}





More information about the cfe-commits mailing list