[clang] 04fbc46 - [clang-format] Fix RemoveSemicolon for empty functions (#82278)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 20 21:51:55 PST 2024
Author: Owen Pan
Date: 2024-02-20T21:51:51-08:00
New Revision: 04fbc461e0fd1c6f2b014761e9c03ca80d17b33b
URL: https://github.com/llvm/llvm-project/commit/04fbc461e0fd1c6f2b014761e9c03ca80d17b33b
DIFF: https://github.com/llvm/llvm-project/commit/04fbc461e0fd1c6f2b014761e9c03ca80d17b33b.diff
LOG: [clang-format] Fix RemoveSemicolon for empty functions (#82278)
Fixes #79833.
Added:
Modified:
clang/lib/Format/Format.cpp
clang/unittests/Format/FormatTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 2c815128b1a59d..10ab406a15c6e1 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 24f62af8ddcb87..8282e75bd847f4 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -26720,13 +26720,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"
More information about the cfe-commits
mailing list