]> granicus.if.org Git - clang/commitdiff
Fixes parsing of hash tokens in the middle of a line.
authorManuel Klimek <klimek@google.com>
Sat, 5 Jan 2013 22:56:06 +0000 (22:56 +0000)
committerManuel Klimek <klimek@google.com>
Sat, 5 Jan 2013 22:56:06 +0000 (22:56 +0000)
To parse # correctly, we need to know whether it is the first token in a
line - we can deduct this either from the whitespace or seeing that the
token is the first in the file - we already calculate this information.
This patch moves the identification of the first token into the
getNextToken method and stores it inside the FormatToken, so the
UnwrappedLineParser can stay independent of the SourceManager.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@171640 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Format/Format.cpp
lib/Format/UnwrappedLineParser.cpp
lib/Format/UnwrappedLineParser.h
unittests/Format/FormatTest.cpp

index effe0bc2482106e5b0148a90b2474c9562c63050..4d401a5be9e19efcdec31bc364651e2697fa631a 100644 (file)
@@ -483,8 +483,7 @@ private:
 
     unsigned Newlines =
         std::min(Token.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
-    unsigned Offset = SourceMgr.getFileOffset(Token.WhiteSpaceStart);
-    if (Newlines == 0 && Offset != 0)
+    if (Newlines == 0 && !Token.IsFirst)
       Newlines = 1;
     unsigned Indent = Line.Level * 2;
     if ((Token.Tok.is(tok::kw_public) || Token.Tok.is(tok::kw_protected) ||
@@ -685,9 +684,10 @@ public:
       next();
       if (Index >= Tokens.size())
         return;
-      // It is the responsibility of the UnwrappedLineParser to make sure
-      // this sequence is not produced inside an unwrapped line.
-      assert(Tokens[Index].Tok.getIdentifierInfo() != NULL);
+      // Hashes in the middle of a line can lead to any strange token
+      // sequence.
+      if (Tokens[Index].Tok.getIdentifierInfo() == NULL)
+        return;
       switch (Tokens[Index].Tok.getIdentifierInfo()->getPPKeywordID()) {
       case tok::pp_include:
       case tok::pp_import:
@@ -1033,6 +1033,8 @@ public:
     Lex.LexFromRawLexer(FormatTok.Tok);
     StringRef Text = tokenText(FormatTok.Tok);
     FormatTok.WhiteSpaceStart = FormatTok.Tok.getLocation();
+    if (SourceMgr.getFileOffset(FormatTok.WhiteSpaceStart) == 0)
+      FormatTok.IsFirst = true;
 
     // Consume and record whitespace until we find a significant token.
     while (FormatTok.Tok.is(tok::unknown)) {
index 2f3a6034bcff8f029511a38f4edd200e034d9903..72b47503ee8976d758c38f54563e4fb75f4ceebb 100644 (file)
@@ -470,7 +470,9 @@ void UnwrappedLineParser::nextToken() {
 
 void UnwrappedLineParser::readToken() {
   FormatTok = Tokens->getNextToken();
-  while (!Line.InPPDirective && FormatTok.Tok.is(tok::hash)) {
+  while (!Line.InPPDirective && FormatTok.Tok.is(tok::hash) &&
+         ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
+          FormatTok.IsFirst)) {
     // FIXME: This is incorrect - the correct way is to create a
     // data structure that will construct the parts around the preprocessor
     // directive as a structured \c UnwrappedLine.
index a8e5b739bc87d8f7ec383a9aaece8ee64f11dded..287143dae29cce1b83f312c218be7f32a725d092 100644 (file)
@@ -31,7 +31,8 @@ namespace format {
 /// whitespace characters preceeding it.
 struct FormatToken {
   FormatToken()
-      : NewlinesBefore(0), HasUnescapedNewline(false), WhiteSpaceLength(0) {
+      : NewlinesBefore(0), HasUnescapedNewline(false), WhiteSpaceLength(0),
+        IsFirst(false) {
   }
 
   /// \brief The \c Token.
@@ -56,6 +57,9 @@ struct FormatToken {
   /// \brief The length in characters of the whitespace immediately preceeding
   /// the \c Token.
   unsigned WhiteSpaceLength;
+
+  /// \brief Indicates that this is the first token.
+  bool IsFirst;
 };
 
 /// \brief An unwrapped line is a sequence of \c Token, that we would like to
index 2165056a7f1dfcefad844641c84d683c8f6363d3..8d95538b16bb717b01b35d624a39f4713cb438f2 100644 (file)
@@ -470,6 +470,10 @@ TEST_F(FormatTest, IndentPreprocessorDirectivesAtZero) {
   EXPECT_EQ("{\n  {\n#define A\n  }\n}", format("{{\n#define A\n}}"));
 }
 
+TEST_F(FormatTest, FormatHashIfNotAtStartOfLine) {
+  verifyFormat("{\n  {\n    a #c;\n  }\n}");
+}
+
 // FIXME: write test for unbalanced braces in macros...
 // FIXME: test # inside a normal statement (like {#define A b})