From: Alexander Kornienko Date: Fri, 24 May 2013 18:24:24 +0000 (+0000) Subject: Ignore contents of #if 0 blocks. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6fb46b02599493d16e5130eff61050c72f65f89e;p=clang Ignore contents of #if 0 blocks. Summary: Added stack of preprocessor branching directives, and ignore all tokens inside #if 0 except for preprocessor directives. Reviewers: klimek, djasper Reviewed By: klimek CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D855 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182658 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index 9ef5d1514d..aaed97c302 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -323,6 +323,22 @@ void UnwrappedLineParser::parsePPDirective() { 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(); @@ -330,6 +346,48 @@ void UnwrappedLineParser::parsePPDirective() { } } +void UnwrappedLineParser::pushPPConditional() { + if (!PPStack.empty() && PPStack.back() == PP_Unreachable) + PPStack.push_back(PP_Unreachable); + else + PPStack.push_back(PP_Conditional); +} + +void UnwrappedLineParser::parsePPIf() { + nextToken(); + if ((FormatTok.Tok.isLiteral() && + StringRef(FormatTok.Tok.getLiteralData(), FormatTok.Tok.getLength()) == + "0") || + FormatTok.Tok.is(tok::kw_false)) { + PPStack.push_back(PP_Unreachable); + } else { + pushPPConditional(); + } + parsePPUnknown(); +} + +void UnwrappedLineParser::parsePPIfdef() { + pushPPConditional(); + parsePPUnknown(); +} + +void UnwrappedLineParser::parsePPElse() { + if (!PPStack.empty()) + PPStack.pop_back(); + pushPPConditional(); + parsePPUnknown(); +} + +void UnwrappedLineParser::parsePPElIf() { + parsePPElse(); +} + +void UnwrappedLineParser::parsePPEndIf() { + if (!PPStack.empty()) + PPStack.pop_back(); + parsePPUnknown(); +} + void UnwrappedLineParser::parsePPDefine() { nextToken(); @@ -1020,6 +1078,12 @@ void UnwrappedLineParser::readToken() { flushComments(FormatTok.NewlinesBefore > 0); parsePPDirective(); } + + if (!PPStack.empty() && (PPStack.back() == PP_Unreachable) && + !Line->InPPDirective) { + continue; + } + if (!FormatTok.Tok.is(tok::comment)) return; if (FormatTok.NewlinesBefore > 0 || FormatTok.IsFirst) { diff --git a/lib/Format/UnwrappedLineParser.h b/lib/Format/UnwrappedLineParser.h index 4746951dcd..bf3db1ea03 100644 --- a/lib/Format/UnwrappedLineParser.h +++ b/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 @@ -140,6 +139,11 @@ private: 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(); @@ -167,6 +171,7 @@ private: void flushComments(bool NewlineBeforeNext); void pushToken(const FormatToken &Tok); void calculateBraceTypes(); + void pushPPConditional(); // Represents what type of block a left brace opens. enum LBraceState { @@ -224,6 +229,16 @@ private: // position of the token in the stream (see \c AllTokens). SmallVector LBraces; + // Represents preprocessor branch type, so we can find matching + // #if/#else/#endif directives. + enum PPBranchKind { + PP_Conditional, // Any #if, #ifdef, #ifndef, #elif, block outside #if 0 + PP_Unreachable // #if 0 or a conditional preprocessor block inside #if 0 + }; + + // Keeps a stack of currently active preprocessor branching directives. + SmallVector PPStack; + friend class ScopedLineState; }; diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index f72013a448..add7466116 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -1035,6 +1035,144 @@ TEST_F(FormatTest, CommentsInStaticInitializers) { "};"); } +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("#if false\n" + "void f( ) { }\n" + "#endif\n" + "void g() {}\n", + format("#if false\n" + "void f( ) { }\n" + "#endif\n" + "void g( ) { }\n")); + 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" + "#if 1\n" + " Two,\n" + "#if 0\n" + "Three,\n" + " Four,\n" + "#endif\n" + " Five\n" + "#endif\n" + "};", + format("enum F {\n" + "One,\n" + "#if 1\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. //===----------------------------------------------------------------------===//