https://github.com/owenca created https://github.com/llvm/llvm-project/pull/82278
Fixes #79833. >From 4bcf6dba8b97096801be550c4a8d1626ed57e475 Mon Sep 17 00:00:00 2001 From: Owen Pan <owenpi...@gmail.com> Date: Mon, 19 Feb 2024 13:11:29 -0800 Subject: [PATCH] [clang-format] Fix RemoveSemicolon for empty ctors/dtors Fixes #79833. --- clang/lib/Format/Format.cpp | 23 ++++++++++++++++------- clang/unittests/Format/FormatTest.cpp | 19 +++++++++++++------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index e67b2101f5821b..d6ecb3ecad1f9b 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -2261,27 +2261,36 @@ class SemiRemover : public TokenAnalyzer { FormatTokenLexer &Tokens) override { AffectedRangeMgr.computeAffectedLines(AnnotatedLines); tooling::Replacements Result; - removeSemi(AnnotatedLines, Result); + removeSemi(Annotator, AnnotatedLines, Result); return {Result, 0}; } private: - void removeSemi(SmallVectorImpl<AnnotatedLine *> &Lines, + void removeSemi(TokenAnnotator &Annotator, + SmallVectorImpl<AnnotatedLine *> &Lines, tooling::Replacements &Result) { + auto PrecededByFunctionRBrace = [](const FormatToken &Tok) { + const auto *Prev = Tok.Previous; + if (!Prev || Prev->isNot(tok::r_brace)) + return false; + const auto *LBrace = Prev->MatchingParen; + return LBrace && LBrace->is(TT_FunctionLBrace); + }; const auto &SourceMgr = Env.getSourceManager(); const auto End = Lines.end(); for (auto I = Lines.begin(); I != End; ++I) { const auto Line = *I; - removeSemi(Line->Children, Result); + removeSemi(Annotator, Line->Children, Result); if (!Line->Affected) continue; + Annotator.calculateFormattingInformation(*Line); const auto NextLine = I + 1 == End ? nullptr : I[1]; for (auto Token = Line->First; Token && !Token->Finalized; Token = Token->Next) { - if (!Token->Optional) - continue; - if (Token->isNot(tok::semi)) + if (Token->isNot(tok::semi) || + (!Token->Optional && !PrecededByFunctionRBrace(*Token))) { continue; + } auto Next = Token->Next; assert(Next || Token == Line->Last); if (!Next && NextLine) @@ -3677,7 +3686,7 @@ reformat(const FormatStyle &Style, StringRef Code, FormatStyle S = Expanded; S.RemoveSemicolon = true; Passes.emplace_back([&, S = std::move(S)](const Environment &Env) { - return SemiRemover(Env, S).process(/*SkipAnnotation=*/true); + return SemiRemover(Env, S).process(); }); } diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index d9e369296eed16..b60f1e27e30b0c 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -26707,13 +26707,20 @@ TEST_F(FormatTest, RemoveSemicolon) { verifyIncompleteFormat("class C final [[deprecated(l]] {});", Style); - // These tests are here to show a problem that may not be easily - // solved, our implementation to remove semicolons is only as good - // as our FunctionLBrace detection and this fails for empty braces - // because we can't distringuish this from a bracelist. - // We will enable when that is resolved. -#if 0 verifyFormat("void main() {}", "void main() {};", Style); + + verifyFormat("struct Foo {\n" + " Foo() {}\n" + " ~Foo() {}\n" + "};", + "struct Foo {\n" + " Foo() {};\n" + " ~Foo() {};\n" + "};", + Style); + +// We can't (and probably shouldn't) support the following. +#if 0 verifyFormat("void foo() {} //\n" "int bar;", "void foo() {}; //\n" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits