Author: owenca Date: 2022-04-21T14:56:30-07:00 New Revision: 221c2b68ddc6efc97739ab8ab8e41f1a086fef6c
URL: https://github.com/llvm/llvm-project/commit/221c2b68ddc6efc97739ab8ab8e41f1a086fef6c DIFF: https://github.com/llvm/llvm-project/commit/221c2b68ddc6efc97739ab8ab8e41f1a086fef6c.diff LOG: [clang-format] Fix a crash on AllowShortFunctionsOnASingleLine Fixes #55008. Differential Revision: https://reviews.llvm.org/D124152 Added: Modified: clang/lib/Format/TokenAnnotator.h clang/lib/Format/UnwrappedLineFormatter.cpp clang/unittests/Format/FormatTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index 96e03967ff60a..3da68a1aad2eb 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -76,6 +76,10 @@ class AnnotatedLine { } } + bool isComment() const { + return First && First->is(tok::comment) && !First->getNextNonComment(); + } + /// \c true if this line starts with the given tokens in order, ignoring /// comments. template <typename... Ts> bool startsWith(Ts... Tokens) const { diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 6137cdf344bc0..30755ef1086b2 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -306,24 +306,26 @@ class LineJoiner { // TODO: Use IndentTracker to avoid loop? // Find the last line with lower level. - auto J = I - 1; - if (!TheLine->InPPDirective) { - for (; J != AnnotatedLines.begin(); --J) { - if (!(*J)->InPPDirective && (*J)->Level < TheLine->Level) - break; + const AnnotatedLine *Line = nullptr; + for (auto J = I - 1; J >= AnnotatedLines.begin(); --J) { + assert(*J); + if (!(*J)->InPPDirective && !(*J)->isComment() && + (*J)->Level < TheLine->Level) { + Line = *J; + break; } } - if ((*J)->Level >= TheLine->Level) + if (!Line) return false; // Check if the found line starts a record. - const FormatToken *LastNonComment = (*J)->Last; + const FormatToken *LastNonComment = Line->Last; assert(LastNonComment); if (LastNonComment->is(tok::comment)) { LastNonComment = LastNonComment->getPreviousNonComment(); // There must be another token (usually `{`), because we chose a - // line that has a smaller level. + // non-PPDirective and non-comment line that has a smaller level. assert(LastNonComment); } return isRecordLBrace(*LastNonComment); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index d727ef2254fde..a805f8ed15f46 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -12773,6 +12773,14 @@ TEST_F(FormatTest, PullInlineFunctionDefinitionsIntoSingleLine) { "};", MergeInlineOnly); + verifyFormat("struct S {\n" + "// comment\n" + "#ifdef FOO\n" + " int foo() { bar(); }\n" + "#endif\n" + "};", + MergeInlineOnly); + // Also verify behavior when BraceWrapping.AfterFunction = true MergeInlineOnly.BreakBeforeBraces = FormatStyle::BS_Custom; MergeInlineOnly.BraceWrapping.AfterFunction = true; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits