Hi klimek, djasper,

Added stack of preprocessor branching directives, and ignore all tokens
inside #if 0 except for preprocessor directives.

http://llvm-reviews.chandlerc.com/D855

Files:
  lib/Format/UnwrappedLineParser.cpp
  lib/Format/UnwrappedLineParser.h
  unittests/Format/FormatTest.cpp
Index: lib/Format/UnwrappedLineParser.cpp
===================================================================
--- lib/Format/UnwrappedLineParser.cpp
+++ lib/Format/UnwrappedLineParser.cpp
@@ -163,7 +163,7 @@
                                          UnwrappedLineConsumer &Callback)
     : Line(new UnwrappedLine), MustBreakBeforeNextToken(false),
       CurrentLines(&Lines), StructuralError(false), Style(Style),
-      Tokens(NULL), Callback(Callback) {
+      Tokens(NULL), Callback(Callback), InsideIf0(0) {
   FormatToken Tok;
   do {
     Tok = Tokens.getNextToken();
@@ -323,13 +323,72 @@
   switch (FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
   case tok::pp_define:
     parsePPDefine();
+    return;
+  case tok::pp_if:
+    parsePPIf();
+    break;
+  case tok::pp_ifdef:
+  case tok::pp_ifndef:
+    parsePPIfdef();
+    break;
+  case tok::pp_else:
+    parsePPElse();
+    break;
+  case tok::pp_elif:
+    parsePPElIf();
+    break;
+  case tok::pp_endif:
+    parsePPEndIf();
     break;
   default:
     parsePPUnknown();
     break;
   }
 }
 
+void UnwrappedLineParser::parsePPIf() {
+  nextToken();
+  if (FormatTok.Tok.isLiteral() &&
+      StringRef(FormatTok.Tok.getLiteralData(), FormatTok.Tok.getLength()) ==
+          "0") {
+    PPStack.push_back(PP_If0);
+    ++InsideIf0;
+  } else {
+    PPStack.push_back(PP_If);
+  }
+  parsePPUnknown();
+}
+
+void UnwrappedLineParser::parsePPIfdef() {
+  PPStack.push_back(PP_If);
+  parsePPUnknown();
+}
+
+void UnwrappedLineParser::parsePPElse() {
+  if (!PPStack.empty() && PPStack.back() != PP_Else) {
+    if (PPStack.back() == PP_If0)
+      --InsideIf0;
+    PPStack.pop_back();
+  } // else unmatched pp directives.
+  PPStack.push_back(PP_Else);
+  parsePPUnknown();
+}
+
+void UnwrappedLineParser::parsePPElIf() {
+  parsePPElse();
+  PPStack.pop_back();
+  PPStack.push_back(PP_If);
+}
+
+void UnwrappedLineParser::parsePPEndIf() {
+  if (!PPStack.empty()) {
+    if (PPStack.back() == PP_If0)
+      --InsideIf0;
+    PPStack.pop_back();
+  } // else unmatched pp directives.
+  parsePPUnknown();
+}
+
 void UnwrappedLineParser::parsePPDefine() {
   nextToken();
 
@@ -1020,6 +1079,10 @@
       flushComments(FormatTok.NewlinesBefore > 0);
       parsePPDirective();
     }
+
+    if (InsideIf0 && !Line->InPPDirective)
+      continue;
+
     if (!FormatTok.Tok.is(tok::comment))
       return;
     if (FormatTok.NewlinesBefore > 0 || FormatTok.IsFirst) {
Index: lib/Format/UnwrappedLineParser.h
===================================================================
--- lib/Format/UnwrappedLineParser.h
+++ lib/Format/UnwrappedLineParser.h
@@ -17,7 +17,6 @@
 #define LLVM_CLANG_FORMAT_UNWRAPPED_LINE_PARSER_H
 
 #include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/SourceManager.h"
 #include "clang/Format/Format.h"
 #include "clang/Lex/Lexer.h"
 #include <list>
@@ -140,6 +139,11 @@
   void parseBlock(bool MustBeDeclaration, unsigned AddLevels = 1);
   void parsePPDirective();
   void parsePPDefine();
+  void parsePPIf();
+  void parsePPIfdef();
+  void parsePPElIf();
+  void parsePPElse();
+  void parsePPEndIf();
   void parsePPUnknown();
   void parseStructuralElement();
   bool tryToParseBracedList();
@@ -224,6 +228,20 @@
   // position of the token in the stream (see \c AllTokens).
   SmallVector<LBraceState, 16> LBraces;
 
+  // Represents preprocessor branch type, so we can find matching
+  // #if/#else/#endif directives.
+  enum PPBranchKind {
+    PP_If,  // Any #if, #ifdef, #ifndef, #elif, except for #if 0
+    PP_If0, // #if 0
+    PP_Else // #else
+  };
+
+  // Keeps a stack of currently active preprocessor branching directives.
+  SmallVector<PPBranchKind, 16> PPStack;
+
+  // Holds the number of PP_If0 on PPStack.
+  int InsideIf0;
+
   friend class ScopedLineState;
 };
 
Index: unittests/Format/FormatTest.cpp
===================================================================
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -1008,6 +1008,136 @@
                "};");
 }
 
+TEST_F(FormatTest, IgnoresIf0Contents) {
+  EXPECT_EQ("#if 0\n"
+            "}{)(&*(^%%#%@! fsadj f;ldjs ,:;| <<<>>>][)(][\n"
+            "#endif\n"
+            "void f() {}",
+            format("#if 0\n"
+                   "}{)(&*(^%%#%@! fsadj f;ldjs ,:;| <<<>>>][)(][\n"
+                   "#endif\n"
+                   "void f(  ) {  }"));
+  EXPECT_EQ("enum E {\n"
+            "  One,\n"
+            "  Two,\n"
+            "#if 0\n"
+            "Three,\n"
+            "      Four,\n"
+            "#endif\n"
+            "  Five\n"
+            "};",
+            format("enum E {\n"
+                   "  One,Two,\n"
+                   "#if 0\n"
+                   "Three,\n"
+                   "      Four,\n"
+                   "#endif\n"
+                   "  Five};"));
+  EXPECT_EQ("enum F {\n"
+            "  One,\n"
+            "#ifdef Q\n"
+            "  Two,\n"
+            "#if 0\n"
+            "Three,\n"
+            "      Four,\n"
+            "#endif\n"
+            "  Five\n"
+            "#endif\n"
+            "};",
+            format("enum F {\n"
+                   "One,\n"
+                   "#ifdef Q\n"
+                   "Two,\n"
+                   "#if 0\n"
+                   "Three,\n"
+                   "      Four,\n"
+                   "#endif\n"
+                   "Five\n"
+                   "#endif\n"
+                   "};"));
+  EXPECT_EQ("enum G {\n"
+            "  One,\n"
+            "#if 0\n"
+            "Two,\n"
+            "#else\n"
+            "  Three,\n"
+            "#endif\n"
+            "  Four\n"
+            "};",
+            format("enum G {\n"
+                   "One,\n"
+                   "#if 0\n"
+                   "Two,\n"
+                   "#else\n"
+                   "Three,\n"
+                   "#endif\n"
+                   "Four\n"
+                   "};"));
+  EXPECT_EQ("enum H {\n"
+            "  One,\n"
+            "#if 0\n"
+            "#ifdef Q\n"
+            "Two,\n"
+            "#else\n"
+            "Three,\n"
+            "#endif\n"
+            "#endif\n"
+            "  Four\n"
+            "};",
+            format("enum H {\n"
+                   "One,\n"
+                   "#if 0\n"
+                   "#ifdef Q\n"
+                   "Two,\n"
+                   "#else\n"
+                   "Three,\n"
+                   "#endif\n"
+                   "#endif\n"
+                   "Four\n"
+                   "};"));
+  EXPECT_EQ("enum I {\n"
+            "  One,\n"
+            "#if /* test */ 0 || 1\n"
+            "Two,\n"
+            "Three,\n"
+            "#endif\n"
+            "  Four\n"
+            "};",
+            format("enum I {\n"
+                   "One,\n"
+                   "#if /* test */ 0 || 1\n"
+                   "Two,\n"
+                   "Three,\n"
+                   "#endif\n"
+                   "Four\n"
+                   "};"));
+  EXPECT_EQ("enum J {\n"
+            "  One,\n"
+            "#if 0\n"
+            "#if 0\n"
+            "Two,\n"
+            "#else\n"
+            "Three,\n"
+            "#endif\n"
+            "Four,\n"
+            "#endif\n"
+            "  Five\n"
+            "};",
+            format("enum J {\n"
+                   "One,\n"
+                   "#if 0\n"
+                   "#if 0\n"
+                   "Two,\n"
+                   "#else\n"
+                   "Three,\n"
+                   "#endif\n"
+                   "Four,\n"
+                   "#endif\n"
+                   "Five\n"
+                   "};"));
+
+}
+
 //===----------------------------------------------------------------------===//
 // Tests for classes, namespaces, etc.
 //===----------------------------------------------------------------------===//
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to