[clang] [clang-format] Fix RemoveSemicolon for empty ctors/dtors (PR #82278)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 19 13:14:24 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-format
Author: Owen Pan (owenca)
<details>
<summary>Changes</summary>
Fixes #<!-- -->79833.
---
Full diff: https://github.com/llvm/llvm-project/pull/82278.diff
2 Files Affected:
- (modified) clang/lib/Format/Format.cpp (+16-7)
- (modified) clang/unittests/Format/FormatTest.cpp (+13-6)
``````````diff
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"
``````````
</details>
https://github.com/llvm/llvm-project/pull/82278
More information about the cfe-commits
mailing list