[cfe-commits] r38709 - in /cfe/cfe/trunk: Lex/MacroExpander.cpp include/clang/Basic/DiagnosticKinds.def

sabre at cs.uiuc.edu sabre at cs.uiuc.edu
Wed Jul 11 09:24:00 PDT 2007


Author: sabre
Date: Wed Jul 11 11:23:59 2007
New Revision: 38709

URL: http://llvm.org/viewvc/llvm-project?rev=38709&view=rev
Log:
Implement stringification.

Modified:
    cfe/cfe/trunk/Lex/MacroExpander.cpp
    cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def

Modified: cfe/cfe/trunk/Lex/MacroExpander.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/MacroExpander.cpp?rev=38709&r1=38708&r2=38709&view=diff

==============================================================================
--- cfe/cfe/trunk/Lex/MacroExpander.cpp (original)
+++ cfe/cfe/trunk/Lex/MacroExpander.cpp Wed Jul 11 11:23:59 2007
@@ -15,6 +15,7 @@
 #include "clang/Lex/MacroInfo.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Diagnostic.h"
 using namespace llvm;
 using namespace clang;
 
@@ -33,16 +34,54 @@
   ArgTokens.reserve(NumArgs);
 }
 
-/// StringifyArgument - Implement C99 6.10.3.2p2.
+/// StringifyArgument - Implement C99 6.10.3.2p2, converting a sequence of
+/// tokens into the literal string token that should be produced by the C #
+/// preprocessor operator.
+///
 static LexerToken StringifyArgument(const std::vector<LexerToken> &Toks,
                                     Preprocessor &PP) {
   LexerToken Tok;
   Tok.StartToken();
   Tok.SetKind(tok::string_literal);
+
+  // Stringify all the tokens.
+  std::string Result = "\"";
+  for (unsigned i = 0, e = Toks.size(); i != e; ++i) {
+    const LexerToken &Tok = Toks[i];
+    // FIXME: Optimize this.
+    if (i != 0 && Tok.hasLeadingSpace())
+      Result += ' ';
+    
+    // If this is a string or character constant, escape the token as specified
+    // by 6.10.3.2p2.
+    if (Tok.getKind() == tok::string_literal ||  // "foo" and L"foo".
+        Tok.getKind() == tok::char_constant) {   // 'x' and L'x'.
+      Result += Lexer::Stringify(PP.getSpelling(Tok));
+    } else {
+      // Otherwise, just append the token.
+      Result += PP.getSpelling(Tok);
+    }
+  }
+  
+  // If the last character of the string is a \, and if it isn't escaped, this
+  // is an invalid string literal, diagnose it as specified in C99.
+  if (Result[Result.size()-1] == '\\') {
+    // Count the number of consequtive \ characters.  If even, then they are
+    // just escaped backslashes, otherwise it's an error.
+    unsigned FirstNonSlash = Result.size()-2;
+    // Guaranteed to find the starting " if nothing else.
+    while (Result[FirstNonSlash] == '\\')
+      --FirstNonSlash;
+    if ((Result.size()-1-FirstNonSlash) & 1) {
+      PP.Diag(Toks.back(), diag::pp_invalid_string_literal);
+      Result.erase(Result.end()-1);  // remove one of the \'s.
+    }
+  }
+  
+  Result += '"';
   
-  std::string Val = "\"XXYZLAKSDFJAS\"";
-  Tok.SetLength(Val.size());
-  Tok.SetLocation(PP.CreateString(&Val[0], Val.size()));
+  Tok.SetLength(Result.size());
+  Tok.SetLocation(PP.CreateString(&Result[0], Result.size()));
   return Tok;
 }
 

Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=38709&r1=38708&r2=38709&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:23:59 2007
@@ -98,6 +98,8 @@
      "redefining builtin macro")
 DIAG(pp_macro_not_used, WARNING,    // -Wunused-macros
      "macro is not used")
+DIAG(pp_invalid_string_literal, WARNING,
+     "invalid string literal, ignoring final '\'")
 
 DIAG(ext_pp_import_directive, EXTENSION,
      "#import is a language extension")





More information about the cfe-commits mailing list