diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -76,6 +76,10 @@ } } + 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 bool startsWith(Ts... Tokens) const { diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -306,24 +306,26 @@ // 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 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -12773,6 +12773,14 @@ "};", 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;