sstwcw created this revision. sstwcw added reviewers: HazardyKnusperkeks, MyDeveloperDay, curdeius, owenpan. sstwcw added a project: clang-format. Herald added a project: All. sstwcw requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
Previously the program would crash on this input: #else #if X The problem was that in `parsePPElse`, `PPBranchLevel` would be incremented when the first `#else` gets parsed, but `PPLevelBranchCount` and `PPLevelBranchIndex` would not be updated together. I found the problem when working on D135740 <https://reviews.llvm.org/D135740>. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D135972 Files: clang/lib/Format/UnwrappedLineParser.cpp clang/unittests/Format/FormatTest.cpp Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -5193,6 +5193,17 @@ verifyNoCrash("a={0,1\n#if a\n#else\n;\n#endif\n}"); verifyNoCrash("#if a\na(\n#else\n#endif\n) a {a,b,c,d,f,g};"); verifyNoCrash("#ifdef A\n a(\n #else\n #endif\n) = []() { \n)}"); + std::function<void(std::string, unsigned)> FormatBadBranches = + [&](std::string Prefix, unsigned Lines) { + const std::string Directives[] = {"", "#if X\n", "#else X\n", + "#endif\n"}; + if (Lines == 0) + verifyNoCrash(Prefix); + else + for (const auto &Part : Directives) + FormatBadBranches(Prefix + Part, Lines - 1); + }; + FormatBadBranches("", 6); } TEST_F(FormatTest, MacrosWithoutTrailingSemicolon) { Index: clang/lib/Format/UnwrappedLineParser.cpp =================================================================== --- clang/lib/Format/UnwrappedLineParser.cpp +++ clang/lib/Format/UnwrappedLineParser.cpp @@ -1212,9 +1212,13 @@ // If a potential include guard has an #else, it's not an include guard. if (IncludeGuard == IG_Defined && PPBranchLevel == 0) IncludeGuard = IG_Rejected; + // Don't crash when there is an #else without and #if. + if (PPBranchLevel <= -1) { + conditionalCompilationStart(/*Unreachable=*/true); + assert(PPBranchLevel == 0); + } conditionalCompilationAlternative(); - if (PPBranchLevel > -1) - --PPBranchLevel; + --PPBranchLevel; parsePPUnknown(); ++PPBranchLevel; }
Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -5193,6 +5193,17 @@ verifyNoCrash("a={0,1\n#if a\n#else\n;\n#endif\n}"); verifyNoCrash("#if a\na(\n#else\n#endif\n) a {a,b,c,d,f,g};"); verifyNoCrash("#ifdef A\n a(\n #else\n #endif\n) = []() { \n)}"); + std::function<void(std::string, unsigned)> FormatBadBranches = + [&](std::string Prefix, unsigned Lines) { + const std::string Directives[] = {"", "#if X\n", "#else X\n", + "#endif\n"}; + if (Lines == 0) + verifyNoCrash(Prefix); + else + for (const auto &Part : Directives) + FormatBadBranches(Prefix + Part, Lines - 1); + }; + FormatBadBranches("", 6); } TEST_F(FormatTest, MacrosWithoutTrailingSemicolon) { Index: clang/lib/Format/UnwrappedLineParser.cpp =================================================================== --- clang/lib/Format/UnwrappedLineParser.cpp +++ clang/lib/Format/UnwrappedLineParser.cpp @@ -1212,9 +1212,13 @@ // If a potential include guard has an #else, it's not an include guard. if (IncludeGuard == IG_Defined && PPBranchLevel == 0) IncludeGuard = IG_Rejected; + // Don't crash when there is an #else without and #if. + if (PPBranchLevel <= -1) { + conditionalCompilationStart(/*Unreachable=*/true); + assert(PPBranchLevel == 0); + } conditionalCompilationAlternative(); - if (PPBranchLevel > -1) - --PPBranchLevel; + --PPBranchLevel; parsePPUnknown(); ++PPBranchLevel; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits