[clang] [clang-format] Handle parenthesized list in RemoveParentheses (PR #100852)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/100852 Also, reformat clang-format source to remove redundant parentheses enclosing single list items. Fixes #100768. >From f06f3ab5e59217348e72179c9581be338efa8789 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Fri, 26 Jul 2024 19:17:33 -0700 Subject: [PATCH] [clang-format] Handle parenthesized list in RemoveParentheses Also, reformat clang-format source to remove redundant parentheses enclosing single list items. Fixes #100768. --- clang/lib/Format/UnwrappedLineParser.cpp | 12 +++- clang/tools/clang-format/ClangFormat.cpp | 2 +- clang/unittests/Format/FormatTest.cpp| 4 clang/unittests/Format/MatchFilePathTest.cpp | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index d406a531a5c0c..3ebf8a44acc0f 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -2534,6 +2534,7 @@ bool UnwrappedLineParser::parseBracedList(bool IsAngleBracket, bool IsEnum) { bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { assert(FormatTok->is(tok::l_paren) && "'(' expected."); auto *LeftParen = FormatTok; + bool SeenComma = false; bool SeenEqual = false; bool MightBeFoldExpr = false; const bool MightBeStmtExpr = Tokens->peekNextToken()->is(tok::l_brace); @@ -2553,10 +2554,14 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { const auto *Next = Tokens->peekNextToken(); const bool DoubleParens = Prev && Prev->is(tok::l_paren) && Next && Next->is(tok::r_paren); +const bool CommaSeparated = +!DoubleParens && Prev && Prev->isOneOf(tok::l_paren, tok::comma) && +Next && Next->isOneOf(tok::comma, tok::r_paren); const auto *PrevPrev = Prev ? Prev->getPreviousNonComment() : nullptr; const bool Blacklisted = PrevPrev && (PrevPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) || + SeenComma || (SeenEqual && (PrevPrev->isOneOf(tok::kw_if, tok::kw_while) || PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if; @@ -2566,7 +2571,8 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { (!NestedLambdas.empty() && !NestedLambdas.back())) && Prev && Prev->isOneOf(tok::kw_return, tok::kw_co_return) && Next && Next->is(tok::semi); -if ((DoubleParens && !Blacklisted) || ReturnParens) { +if ((DoubleParens && !Blacklisted) || (CommaSeparated && !SeenComma) || +ReturnParens) { LeftParen->Optional = true; FormatTok->Optional = true; } @@ -2595,6 +2601,10 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { parseBracedList(); } break; +case tok::comma: + SeenComma = true; + nextToken(); + break; case tok::ellipsis: MightBeFoldExpr = true; nextToken(); diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp index 6cba1267f3b0d..6582d73eae40e 100644 --- a/clang/tools/clang-format/ClangFormat.cpp +++ b/clang/tools/clang-format/ClangFormat.cpp @@ -364,7 +364,7 @@ emitReplacementWarnings(const Replacements , StringRef AssumedFileName, : SourceMgr::DiagKind::DK_Warning, "code should be clang-formatted [-Wclang-format-violations]"); - Diag.print(nullptr, llvm::errs(), (ShowColors && !NoShowColors)); + Diag.print(nullptr, llvm::errs(), ShowColors && !NoShowColors); if (ErrorLimit && ++Errors >= ErrorLimit) break; } diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index d7f81813835fa..2a754a29e81e7 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -27445,6 +27445,10 @@ TEST_F(FormatTest, RemoveParentheses) { verifyFormat("static_assert((std::is_constructible_v && ...));", "static_assert(((std::is_constructible_v && ...)));", Style); + verifyFormat("foo((a, b));", "foo(((a, b)));", Style); + verifyFormat("foo((a, b));", "foo(((a), b));", Style); + verifyFormat("foo((a, b));", "foo((a, (b)));", Style); + verifyFormat("foo((a, b, c));", "foo((a, ((b)), c));", Style); verifyFormat("return (0);", "return (((0)));", Style); verifyFormat("return (({ 0; }));", "return ((({ 0; })));", Style); verifyFormat("return ((... && std::is_convertible_v));", diff --git a/clang/unittests/Format/MatchFilePathTest.cpp b/clang/unittests/Format/MatchFilePathTest.cpp index f41cf7f971596..28f665635718e 100644 --- a/clang/unittests/Format/MatchFilePathTest.cpp +++ b/clang/unittests/Format/MatchFilePathTest.cpp @@ -53,7 +53,7 @@ TEST_F(MatchFilePathTest,
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/93140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 7e7a906 - Revert "[clang-format] Fix a bug in annotating `*` in `#define`s (#99433)"
Author: Owen Pan Date: 2024-07-24T19:33:44-07:00 New Revision: 7e7a9069d4240d2ae619cb50eba09f948c537ce3 URL: https://github.com/llvm/llvm-project/commit/7e7a9069d4240d2ae619cb50eba09f948c537ce3 DIFF: https://github.com/llvm/llvm-project/commit/7e7a9069d4240d2ae619cb50eba09f948c537ce3.diff LOG: Revert "[clang-format] Fix a bug in annotating `*` in `#define`s (#99433)" This reverts commit ce1a87437cc143889665c41046107e84cdf6246e. Closes #100304. Added: Modified: clang/lib/Format/TokenAnnotator.cpp clang/unittests/Format/TokenAnnotatorTest.cpp Removed: diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 21924a8fe17d1..5c11f3cb1a874 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -372,6 +372,10 @@ class AnnotatingParser { OpeningParen.Previous->is(tok::kw__Generic)) { Contexts.back().ContextType = Context::C11GenericSelection; Contexts.back().IsExpression = true; +} else if (Line.InPPDirective && + (!OpeningParen.Previous || +OpeningParen.Previous->isNot(tok::identifier))) { + Contexts.back().IsExpression = true; } else if (Contexts[Contexts.size() - 2].CaretFound) { // This is the parameter list of an ObjC block. Contexts.back().IsExpression = false; @@ -384,20 +388,7 @@ class AnnotatingParser { OpeningParen.Previous->MatchingParen->isOneOf( TT_ObjCBlockLParen, TT_FunctionTypeLParen)) { Contexts.back().IsExpression = false; -} else if (Line.InPPDirective) { - auto IsExpr = [] { -const auto *Tok = OpeningParen.Previous; -if (!Tok || Tok->isNot(tok::identifier)) - return true; -Tok = Tok->Previous; -while (Tok && Tok->endsSequence(tok::coloncolon, tok::identifier)) { - assert(Tok->Previous); - Tok = Tok->Previous->Previous; -} -return !Tok || !Tok->Tok.getIdentifierInfo(); - }; - Contexts.back().IsExpression = IsExpr(); -} else if (!Line.MustBeDeclaration) { +} else if (!Line.MustBeDeclaration && !Line.InPPDirective) { bool IsForOrCatch = OpeningParen.Previous && OpeningParen.Previous->isOneOf(tok::kw_for, tok::kw_catch); diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index b01ca322505b1..51810ad047a26 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -75,26 +75,6 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) { EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_TypeDeclarationParen); EXPECT_TOKEN(Tokens[11], tok::star, TT_PointerOrReference); - Tokens = annotate("#define FOO bar(a * b)"); - ASSERT_EQ(Tokens.size(), 10u) << Tokens; - EXPECT_TOKEN(Tokens[6], tok::star, TT_BinaryOperator); - - Tokens = annotate("#define FOO foo.bar(a & b)"); - ASSERT_EQ(Tokens.size(), 12u) << Tokens; - EXPECT_TOKEN(Tokens[8], tok::amp, TT_BinaryOperator); - - Tokens = annotate("#define FOO foo::bar(a && b)"); - ASSERT_EQ(Tokens.size(), 12u) << Tokens; - EXPECT_TOKEN(Tokens[8], tok::ampamp, TT_BinaryOperator); - - Tokens = annotate("#define FOO foo bar(a *b)"); - ASSERT_EQ(Tokens.size(), 11u) << Tokens; - EXPECT_TOKEN(Tokens[7], tok::star, TT_PointerOrReference); - - Tokens = annotate("#define FOO void foo::bar(a )"); - ASSERT_EQ(Tokens.size(), 13u) << Tokens; - EXPECT_TOKEN(Tokens[9], tok::amp, TT_PointerOrReference); - Tokens = annotate("void f() {\n" " while (p < a && *p == 'a')\n" "p++;\n" ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
https://github.com/owenca approved this pull request. https://github.com/llvm/llvm-project/pull/93140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
https://github.com/owenca edited https://github.com/llvm/llvm-project/pull/93140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/93140 >From 09bd1f04730f0accad7ce041b0121f716cc7a18d Mon Sep 17 00:00:00 2001 From: Gedare Bloom Date: Tue, 21 May 2024 22:21:59 -0600 Subject: [PATCH 01/13] [clang-format] Improve BlockIndent at ColumnLimit Fixes #55731 Fixes #73584 The reported formatting problems were related to ignoring deep nesting of "simple" functions (causing #54808) and to allowing the trailing annotation to become separated from the closing parens, which allowed a break to occur between the closing parens and the trailing annotation. The fix for the nesting of "simple" functions is to detect them more carefully. "Simple" was defined in a comment as being a single non-expression argument. I tried to stay as close to the original intent of the implementation while fixing the various bad formatting reports. In the process of fixing these bugs, some latent bugs were discovered related to how JavaScript Template Strings are handled. Those are also fixed here. --- clang/lib/Format/ContinuationIndenter.cpp | 47 +-- clang/lib/Format/TokenAnnotator.cpp | 6 +++ clang/unittests/Format/FormatTest.cpp | 22 +++ 3 files changed, 72 insertions(+), 3 deletions(-) diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index b07360425ca6e..516cfd8b1af61 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -803,6 +803,46 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState , bool DryRun, return !Tok.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while, tok::kw_switch); }; + // Detecting functions is brittle. It would be better if we could annotate + // the LParen type of functions/calls. + const auto IsFunctionDeclParen = [&](const FormatToken ) { +return Tok.is(tok::l_paren) && Tok.Previous && + (Tok.Previous->is(TT_FunctionDeclarationName) || +(Tok.Previous->Previous && + Tok.Previous->Previous->is(tok::coloncolon) && + Tok.Previous->Previous->Previous && + Tok.Previous->Previous->Previous->is(TT_FunctionDeclarationName))); + }; + const auto IsFunctionCallParen = [&](const FormatToken ) { +return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous && + Tok.Previous->is(tok::identifier); + }; + const auto IsInTemplateString = [&](const FormatToken ) { +if (!Style.isJavaScript()) + return false; +for (const FormatToken *Prev = Prev; Prev = Prev->Previous) { + if (Prev->is(TT_TemplateString) && Prev->opensScope()) +return true; + if (Prev->is(TT_TemplateString) && Prev->closesScope()) +break; +} +return false; + }; + const auto IsNotSimpleFunction = [&](const FormatToken ) { +const auto *Previous = Tok.Previous; +const auto *Next = Tok.Next; +if (Tok.FakeLParens.size() > 0 && Tok.FakeLParens.back() > prec::Unknown) + return true; +if (Previous && +(IsFunctionDeclParen(*Previous) || IsFunctionCallParen(*Previous))) { + if (!IsOpeningBracket(Tok) && Next && !Next->isMemberAccess() && + !IsInTemplateString(Tok) && !IsFunctionDeclParen(*Next) && + !IsFunctionCallParen(*Next)) { +return true; + } +} +return false; + }; if ((Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak || Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent) && IsOpeningBracket(Previous) && State.Column > getNewLineColumn(State) && @@ -813,10 +853,10 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState , bool DryRun, // cll( // cll( // caaall(aa, a; - Current.FakeLParens.size() > 0 && - Current.FakeLParens.back() > prec::Unknown) { + IsNotSimpleFunction(Current)) { CurrentState.NoLineBreak = true; } + if (Previous.is(TT_TemplateString) && Previous.opensScope()) CurrentState.NoLineBreak = true; @@ -831,7 +871,8 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState , bool DryRun, Previous.isNot(TT_TableGenDAGArgOpenerToBreak) && !(Current.MacroParent && Previous.MacroParent) && (Current.isNot(TT_LineComment) || - Previous.isOneOf(BK_BracedInit, TT_VerilogMultiLineListLParen))) { + Previous.isOneOf(BK_BracedInit, TT_VerilogMultiLineListLParen)) && + !IsInTemplateString(Current)) { CurrentState.Indent = State.Column + Spaces; CurrentState.IsAligned = true; } diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 21924a8fe17d1..faef1dba9d890 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -6205,6 +6205,12 @@ bool TokenAnnotator::canBreakBefore(const
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
owenca wrote: > Fixes #73584 Seems it's not fixed yet: ``` $ cat test.cpp { PyObjectPtr const readinto_method_obj{ PyObject_GetAttrString(input_stream, "readinto")}; } $ clang-format test.cpp { PyObjectPtr const readinto_method_obj{PyObject_GetAttrString(input_stream, "readinto") }; } ``` You can correct the commit message and fix the issue in another patch. https://github.com/llvm/llvm-project/pull/93140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
@@ -9337,6 +9337,32 @@ TEST_F(FormatTest, AlignsAfterOpenBracket) { "\n" ");", Style); + verifyFormat("bool aaa(\n" + "const bool , const void *aa\n" + ") const {\n" + " return true;\n" + "}", + Style); + verifyFormat("bool (\n" + "const bool , const void *aa\n" + ") const;", + Style); + verifyFormat("void a(\n" + "int aa, int bb, int cc, int dd\n" + ") const noexcept -> std::vector;", + Style); + verifyFormat( + "x = aaa(\n" + "\"a aaa a aaa a\"\n" + ");", + Style); + verifyFormat( + "auto lambda =\n" + "[](\n" + "auto " + "a\n" owenca wrote: ```suggestion "auto a\n" ``` https://github.com/llvm/llvm-project/pull/93140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
@@ -9337,6 +9337,32 @@ TEST_F(FormatTest, AlignsAfterOpenBracket) { "\n" ");", Style); + verifyFormat("bool aaa(\n" + "const bool , const void *aa\n" + ") const {\n" + " return true;\n" + "}", + Style); + verifyFormat("bool (\n" + "const bool , const void *aa\n" + ") const;", + Style); + verifyFormat("void a(\n" + "int aa, int bb, int cc, int dd\n" + ") const noexcept -> std::vector;", + Style); + verifyFormat( + "x = aaa(\n" + "\"a aaa a aaa a\"\n" + ");", + Style); + verifyFormat( owenca wrote: ```suggestion Style.ColumnLimit = 60; verifyFormat( ``` https://github.com/llvm/llvm-project/pull/93140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
owenca wrote: Please also add the following: ``` $ git diff TokenAnnotatorTest.cpp diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index c5e8aa72cd2c..4994498c389b 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1645,38 +1645,45 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { auto Tokens = annotate("[]() constexpr {}"); ASSERT_EQ(Tokens.size(), 8u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() consteval {}"); ASSERT_EQ(Tokens.size(), 8u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() mutable {}"); ASSERT_EQ(Tokens.size(), 8u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() static {}"); ASSERT_EQ(Tokens.size(), 8u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() -> auto {}"); ASSERT_EQ(Tokens.size(), 9u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow); EXPECT_TOKEN(Tokens[6], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() -> auto & {}"); ASSERT_EQ(Tokens.size(), 10u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow); EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() -> auto * {}"); ASSERT_EQ(Tokens.size(), 10u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow); EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_LambdaLBrace); @@ -1705,6 +1712,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { Tokens = annotate("foo([&](u32 bar) __attribute__((attr)) -> void {});"); ASSERT_EQ(Tokens.size(), 22u) << Tokens; EXPECT_TOKEN(Tokens[2], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[5], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[15], tok::arrow, TT_TrailingReturnArrow); EXPECT_TOKEN(Tokens[17], tok::l_brace, TT_LambdaLBrace); @@ -1712,6 +1720,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 11u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[8], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] {}"); @@ -1724,6 +1733,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 12u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[9], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] {}"); @@ -1736,6 +1746,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 12u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[9], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] {}"); @@ -1748,6 +1759,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 12u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[9], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] {}"); @@ -1761,6 +1773,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 18u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[10], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[14]->ClosesRequiresClause);
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
@@ -803,6 +803,51 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState , bool DryRun, return !Tok.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while, tok::kw_switch); }; + auto IsLambdaParameterList = [](const FormatToken *Tok) { +// adapted from TokenAnnotator.cpp:isLambdaParameterList() +// Skip <...> if present. +if (Tok->Previous && Tok->Previous->is(tok::greater) && +Tok->Previous->MatchingParen && +Tok->Previous->MatchingParen->is(TT_TemplateOpener)) { + Tok = Tok->Previous->MatchingParen; +} + +// Check for `[...]`. +return Tok->Previous && Tok->Previous->is(tok::r_square) && + Tok->Previous->MatchingParen && + Tok->Previous->MatchingParen->is(TT_LambdaLSquare); + }; + auto IsFunctionCallParen = [&](const FormatToken ) { +return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous && + Tok.Previous->is(tok::identifier); + }; + const auto IsInTemplateString = [&](const FormatToken ) { owenca wrote: You only need to capture `this`. https://github.com/llvm/llvm-project/pull/93140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
@@ -803,6 +803,51 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState , bool DryRun, return !Tok.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while, tok::kw_switch); }; + auto IsLambdaParameterList = [](const FormatToken *Tok) { +// adapted from TokenAnnotator.cpp:isLambdaParameterList() +// Skip <...> if present. +if (Tok->Previous && Tok->Previous->is(tok::greater) && +Tok->Previous->MatchingParen && +Tok->Previous->MatchingParen->is(TT_TemplateOpener)) { + Tok = Tok->Previous->MatchingParen; +} + +// Check for `[...]`. +return Tok->Previous && Tok->Previous->is(tok::r_square) && + Tok->Previous->MatchingParen && + Tok->Previous->MatchingParen->is(TT_LambdaLSquare); + }; + auto IsFunctionCallParen = [&](const FormatToken ) { +return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous && + Tok.Previous->is(tok::identifier); + }; + const auto IsInTemplateString = [&](const FormatToken ) { +if (!Style.isJavaScript()) + return false; +for (const FormatToken *Prev = Prev; Prev = Prev->Previous) { + if (Prev->is(TT_TemplateString) && Prev->opensScope()) +return true; + if (Prev->is(TT_TemplateString) && Prev->closesScope()) +break; +} +return false; + }; + // Identifies simple (no expression) one-argument function calls. + const auto IsNotSimpleFunction = [&](const FormatToken ) { +const auto *Previous = Tok.Previous; +const auto *Next = Tok.Next; +if (Tok.FakeLParens.size() > 0 && Tok.FakeLParens.back() > prec::Unknown) + return true; +if (Previous && +(Previous->is(TT_FunctionDeclarationLParen) || + IsFunctionCallParen(*Previous) || IsLambdaParameterList(Previous))) { + return !IsOpeningBracket(Tok) && Next && !Next->isMemberAccess() && + !IsInTemplateString(Tok) && + !Next->is(TT_FunctionDeclarationLParen) && + !IsFunctionCallParen(*Next); +} +return false; + }; owenca wrote: I'd drop the `Not` and rewrite it as something like below: ``` // Identifies simple (no expression) one-argument function calls. - const auto IsNotSimpleFunction = [&](const FormatToken ) { + const auto IsSimpleFunctionCall = [&](const FormatToken ) { +if (!Tok.FakeLParens.empty() && Tok.FakeLParens.back() > prec::Unknown) + return false; const auto *Previous = Tok.Previous; -const auto *Next = Tok.Next; -if (Tok.FakeLParens.size() > 0 && Tok.FakeLParens.back() > prec::Unknown) +if (!Previous || (!Previous->isOneOf(TT_FunctionDeclarationLParen, + TT_LambdaDefinitionLParen) && + !IsFunctionCallParen(*Previous))) { return true; -if (Previous && -(Previous->is(TT_FunctionDeclarationLParen) || - IsFunctionCallParen(*Previous) || IsLambdaParameterList(Previous))) { - return !IsOpeningBracket(Tok) && Next && !Next->isMemberAccess() && - !IsInTemplateString(Tok) && - !Next->is(TT_FunctionDeclarationLParen) && - !IsFunctionCallParen(*Next); } -return false; +if (IsOpeningBracket(Tok) || IsInTemplateString(Tok)) + return true; +const auto *Next = Tok.Next; +return !Next || Next->isMemberAccess() || + Next->is(TT_FunctionDeclarationLParen) || IsFunctionCallParen(*Next); }; ``` https://github.com/llvm/llvm-project/pull/93140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
@@ -803,6 +803,51 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState , bool DryRun, return !Tok.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while, tok::kw_switch); }; + auto IsLambdaParameterList = [](const FormatToken *Tok) { +// adapted from TokenAnnotator.cpp:isLambdaParameterList() +// Skip <...> if present. +if (Tok->Previous && Tok->Previous->is(tok::greater) && +Tok->Previous->MatchingParen && +Tok->Previous->MatchingParen->is(TT_TemplateOpener)) { + Tok = Tok->Previous->MatchingParen; +} + +// Check for `[...]`. +return Tok->Previous && Tok->Previous->is(tok::r_square) && + Tok->Previous->MatchingParen && + Tok->Previous->MatchingParen->is(TT_LambdaLSquare); + }; + auto IsFunctionCallParen = [&](const FormatToken ) { +return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous && + Tok.Previous->is(tok::identifier); + }; + const auto IsInTemplateString = [&](const FormatToken ) { +if (!Style.isJavaScript()) + return false; +for (const FormatToken *Prev = Prev; Prev = Prev->Previous) { owenca wrote: ```suggestion for (const auto *Prev = Prev; Prev = Prev->Previous) { ``` https://github.com/llvm/llvm-project/pull/93140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
@@ -803,6 +803,51 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState , bool DryRun, return !Tok.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while, tok::kw_switch); }; + auto IsLambdaParameterList = [](const FormatToken *Tok) { +// adapted from TokenAnnotator.cpp:isLambdaParameterList() +// Skip <...> if present. +if (Tok->Previous && Tok->Previous->is(tok::greater) && +Tok->Previous->MatchingParen && +Tok->Previous->MatchingParen->is(TT_TemplateOpener)) { + Tok = Tok->Previous->MatchingParen; +} + +// Check for `[...]`. +return Tok->Previous && Tok->Previous->is(tok::r_square) && + Tok->Previous->MatchingParen && + Tok->Previous->MatchingParen->is(TT_LambdaLSquare); + }; + auto IsFunctionCallParen = [&](const FormatToken ) { owenca wrote: You don't need to capture anything. https://github.com/llvm/llvm-project/pull/93140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
@@ -813,10 +858,10 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState , bool DryRun, // cll( // cll( // caaall(aa, a; - Current.FakeLParens.size() > 0 && - Current.FakeLParens.back() > prec::Unknown) { + IsNotSimpleFunction(Current)) { owenca wrote: ```suggestion !IsSimpleFunctionCall(Current)) { ``` https://github.com/llvm/llvm-project/pull/93140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
@@ -803,6 +803,51 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState , bool DryRun, return !Tok.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while, tok::kw_switch); }; + auto IsLambdaParameterList = [](const FormatToken *Tok) { +// adapted from TokenAnnotator.cpp:isLambdaParameterList() +// Skip <...> if present. +if (Tok->Previous && Tok->Previous->is(tok::greater) && +Tok->Previous->MatchingParen && +Tok->Previous->MatchingParen->is(TT_TemplateOpener)) { + Tok = Tok->Previous->MatchingParen; +} + +// Check for `[...]`. +return Tok->Previous && Tok->Previous->is(tok::r_square) && + Tok->Previous->MatchingParen && + Tok->Previous->MatchingParen->is(TT_LambdaLSquare); + }; owenca wrote: Delete. https://github.com/llvm/llvm-project/pull/93140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
owenca wrote: You can annotate the lambda l_paren: ``` $ git diff FormatToken.h diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index cc45d5a8c5c1..abcedb66b57c 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -102,6 +102,7 @@ namespace format { TYPE(JsTypeColon) \ TYPE(JsTypeOperator) \ TYPE(JsTypeOptionalQuestion) \ + TYPE(LambdaDefinitionLParen) \ TYPE(LambdaLBrace) \ TYPE(LambdaLSquare) \ TYPE(LeadingJavaAnnotation) \ $ git diff TokenAnnotator.cpp diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index fe8a126e2547..fa1489402559 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -62,6 +62,7 @@ static bool canBeObjCSelectorComponent(const FormatToken ) { /// With `Left` being '(', check if we're at either `[...](` or /// `[...]<...>(`, where the [ opens a lambda capture list. +// FIXME: this doesn't cover attributes/constraints before the l_paren. static bool isLambdaParameterList(const FormatToken *Left) { // Skip <...> if present. if (Left->Previous && Left->Previous->is(tok::greater) && @@ -365,6 +366,7 @@ private: Contexts.back().IsExpression = false; } else if (isLambdaParameterList()) { // This is a parameter list of a lambda expression. + OpeningParen.setType(TT_LambdaDefinitionLParen); Contexts.back().IsExpression = false; } else if (OpeningParen.is(TT_RequiresExpressionLParen)) { Contexts.back().IsExpression = false; $ ``` https://github.com/llvm/llvm-project/pull/93140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in annotating FunctionAnnotationRParen (PR #99802)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/99802 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in annotating FunctionAnnotationRParen (PR #99802)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/99802 >From a24f1411ba233e9f14ffa87e6abd139616b8cfed Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Sun, 21 Jul 2024 00:08:20 -0700 Subject: [PATCH 1/2] [clang-format] Fix a bug in annotating FunctionAnnotationRParen Fixes #37906. --- clang/lib/Format/TokenAnnotator.cpp | 6 +++--- clang/unittests/Format/TokenAnnotatorTest.cpp | 4 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index db66911f00f63..2978dbb86494d 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2467,9 +2467,9 @@ class AnnotatingParser { Current.setType(TT_CastRParen); if (Current.MatchingParen && Current.Next && !Current.Next->isBinaryOperator() && - !Current.Next->isOneOf(tok::semi, tok::colon, tok::l_brace, - tok::comma, tok::period, tok::arrow, - tok::coloncolon, tok::kw_noexcept)) { + !Current.Next->isOneOf( + tok::semi, tok::colon, tok::l_brace, tok::l_paren, tok::comma, + tok::period, tok::arrow, tok::coloncolon, tok::kw_noexcept)) { if (FormatToken *AfterParen = Current.MatchingParen->Next; AfterParen && AfterParen->isNot(tok::caret)) { // Make sure this isn't the return type of an Obj-C block declaration. diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index f70424c3ee060..ac5f8f4ac47b6 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1930,6 +1930,10 @@ TEST_F(TokenAnnotatorTest, UnderstandsFunctionAnnotations) { "A(T) noexcept;"); ASSERT_EQ(Tokens.size(), 12u) << Tokens; EXPECT_TOKEN(Tokens[8], tok::r_paren, TT_Unknown); + + Tokens = annotate("FOO()();"); + ASSERT_EQ(Tokens.size(), 7u) << Tokens; + EXPECT_TOKEN(Tokens[2], tok::r_paren, TT_Unknown); } TEST_F(TokenAnnotatorTest, UnderstandsFunctionDeclarationNames) { >From 040b60f89cac71663c3461968eda11f0f80b07f3 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Sun, 21 Jul 2024 13:30:28 -0700 Subject: [PATCH 2/2] Make the annotation test real-world like and add a format test. --- clang/unittests/Format/FormatTest.cpp | 1 + clang/unittests/Format/TokenAnnotatorTest.cpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index d01ce137b8fcb..39fcbab3447a7 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -8742,6 +8742,7 @@ TEST_F(FormatTest, FunctionAnnotations) { "<< abc;"); verifyFormat("MACRO(abc)::function() // wrap\n" "<< abc;"); + verifyFormat("FOO(bar)();", getLLVMStyleWithColumns(0)); } TEST_F(FormatTest, BreaksDesireably) { diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index ac5f8f4ac47b6..614d294e832ee 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1931,9 +1931,9 @@ TEST_F(TokenAnnotatorTest, UnderstandsFunctionAnnotations) { ASSERT_EQ(Tokens.size(), 12u) << Tokens; EXPECT_TOKEN(Tokens[8], tok::r_paren, TT_Unknown); - Tokens = annotate("FOO()();"); - ASSERT_EQ(Tokens.size(), 7u) << Tokens; - EXPECT_TOKEN(Tokens[2], tok::r_paren, TT_Unknown); + Tokens = annotate("FOO(bar)();"); + ASSERT_EQ(Tokens.size(), 8u) << Tokens; + EXPECT_TOKEN(Tokens[3], tok::r_paren, TT_Unknown); } TEST_F(TokenAnnotatorTest, UnderstandsFunctionDeclarationNames) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in annotating StartOfName (PR #99791)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/99791 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in annotating FunctionAnnotationRParen (PR #99802)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/99802 Fixes #37906. >From a24f1411ba233e9f14ffa87e6abd139616b8cfed Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Sun, 21 Jul 2024 00:08:20 -0700 Subject: [PATCH] [clang-format] Fix a bug in annotating FunctionAnnotationRParen Fixes #37906. --- clang/lib/Format/TokenAnnotator.cpp | 6 +++--- clang/unittests/Format/TokenAnnotatorTest.cpp | 4 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index db66911f00f63..2978dbb86494d 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2467,9 +2467,9 @@ class AnnotatingParser { Current.setType(TT_CastRParen); if (Current.MatchingParen && Current.Next && !Current.Next->isBinaryOperator() && - !Current.Next->isOneOf(tok::semi, tok::colon, tok::l_brace, - tok::comma, tok::period, tok::arrow, - tok::coloncolon, tok::kw_noexcept)) { + !Current.Next->isOneOf( + tok::semi, tok::colon, tok::l_brace, tok::l_paren, tok::comma, + tok::period, tok::arrow, tok::coloncolon, tok::kw_noexcept)) { if (FormatToken *AfterParen = Current.MatchingParen->Next; AfterParen && AfterParen->isNot(tok::caret)) { // Make sure this isn't the return type of an Obj-C block declaration. diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index f70424c3ee060..ac5f8f4ac47b6 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1930,6 +1930,10 @@ TEST_F(TokenAnnotatorTest, UnderstandsFunctionAnnotations) { "A(T) noexcept;"); ASSERT_EQ(Tokens.size(), 12u) << Tokens; EXPECT_TOKEN(Tokens[8], tok::r_paren, TT_Unknown); + + Tokens = annotate("FOO()();"); + ASSERT_EQ(Tokens.size(), 7u) << Tokens; + EXPECT_TOKEN(Tokens[2], tok::r_paren, TT_Unknown); } TEST_F(TokenAnnotatorTest, UnderstandsFunctionDeclarationNames) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in annotating StartOfName (PR #99791)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/99791 Fixes #99758. >From f38256c028e1600bc6b957f851ffcc0dedab589c Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Sat, 20 Jul 2024 16:43:39 -0700 Subject: [PATCH] [clang-format] Fix a bug in annotating StartOfName Fixes #99758. --- clang/lib/Format/TokenAnnotator.cpp | 4 +++- clang/unittests/Format/TokenAnnotatorTest.cpp | 14 ++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index db66911f00f63..06c34bd45eb31 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2625,8 +2625,10 @@ class AnnotatingParser { return false; // int a or auto a. -if (PreviousNotConst->isOneOf(tok::identifier, tok::kw_auto)) +if (PreviousNotConst->isOneOf(tok::identifier, tok::kw_auto) && +PreviousNotConst->isNot(TT_StatementAttributeLikeMacro)) { return true; +} // *a or or & if (PreviousNotConst->is(TT_PointerOrReference)) diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index f70424c3ee060..e7bc15d7e1dfa 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -2125,6 +2125,13 @@ TEST_F(TokenAnnotatorTest, UnderstandsTrailingReturnArrow) { ASSERT_EQ(Tokens.size(), 21u) << Tokens; EXPECT_TOKEN(Tokens[13], tok::arrow, TT_Unknown); + auto Style = getLLVMStyle(); + Style.StatementAttributeLikeMacros.push_back("emit"); + Tokens = annotate("emit foo()->bar;", Style); + ASSERT_EQ(Tokens.size(), 8u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::identifier, TT_StatementAttributeLikeMacro); + EXPECT_TOKEN(Tokens[4], tok::arrow, TT_Unknown); + // Mixed Tokens = annotate("auto f() -> int { auto a = b()->c; }"); ASSERT_EQ(Tokens.size(), 18u) << Tokens; @@ -2950,6 +2957,13 @@ TEST_F(TokenAnnotatorTest, StartOfName) { ASSERT_EQ(Tokens.size(), 7u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::at, TT_ObjCDecl); EXPECT_TOKEN(Tokens[2], tok::identifier, TT_StartOfName); + + auto Style = getLLVMStyle(); + Style.StatementAttributeLikeMacros.push_back("emit"); + Tokens = annotate("emit foo = 0;", Style); + ASSERT_EQ(Tokens.size(), 6u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::identifier, TT_StatementAttributeLikeMacro); + EXPECT_TOKEN(Tokens[1], tok::identifier, TT_Unknown); } TEST_F(TokenAnnotatorTest, BraceKind) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in annotating `*` in `#define`s (PR #99433)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/99433 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in annotating `*` in `#define`s (PR #99433)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/99433 >From ebf25d890ff47be48bd153942d943906943a247b Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Wed, 17 Jul 2024 22:30:21 -0700 Subject: [PATCH 1/3] [clang-format] Fix a bug in annotating `*` in `#define`s Fixes #99271. --- clang/lib/Format/TokenAnnotator.cpp | 3 ++- clang/unittests/Format/TokenAnnotatorTest.cpp | 4 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index b6d6e52ccb8f8..f1125fd35b427 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -374,7 +374,8 @@ class AnnotatingParser { Contexts.back().IsExpression = true; } else if (Line.InPPDirective && (!OpeningParen.Previous || -OpeningParen.Previous->isNot(tok::identifier))) { +OpeningParen.Previous->isNot(tok::identifier) || +!OpeningParen.Previous->Previous)) { Contexts.back().IsExpression = true; } else if (Contexts[Contexts.size() - 2].CaretFound) { // This is the parameter list of an ObjC block. diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index c5e8aa72cd2cb..82c9be0f4df71 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -75,6 +75,10 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) { EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_TypeDeclarationParen); EXPECT_TOKEN(Tokens[11], tok::star, TT_PointerOrReference); + Tokens = annotate("#define FOO bar(a * b)"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[6], tok::star, TT_BinaryOperator); + Tokens = annotate("void f() {\n" " while (p < a && *p == 'a')\n" "p++;\n" >From 70af6643045a6ded03fe1b3bbb21c55a2c5971b1 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Fri, 19 Jul 2024 08:59:14 -0700 Subject: [PATCH 2/3] Handles tokens before the function name. --- clang/lib/Format/TokenAnnotator.cpp | 20 +-- clang/unittests/Format/TokenAnnotatorTest.cpp | 16 +++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index f1125fd35b427..50201c970ab60 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -372,11 +372,6 @@ class AnnotatingParser { OpeningParen.Previous->is(tok::kw__Generic)) { Contexts.back().ContextType = Context::C11GenericSelection; Contexts.back().IsExpression = true; -} else if (Line.InPPDirective && - (!OpeningParen.Previous || -OpeningParen.Previous->isNot(tok::identifier) || -!OpeningParen.Previous->Previous)) { - Contexts.back().IsExpression = true; } else if (Contexts[Contexts.size() - 2].CaretFound) { // This is the parameter list of an ObjC block. Contexts.back().IsExpression = false; @@ -389,7 +384,20 @@ class AnnotatingParser { OpeningParen.Previous->MatchingParen->isOneOf( TT_ObjCBlockLParen, TT_FunctionTypeLParen)) { Contexts.back().IsExpression = false; -} else if (!Line.MustBeDeclaration && !Line.InPPDirective) { +} else if (Line.InPPDirective) { + auto IsExpr = [](const FormatToken ) { +const auto *Tok = LParen.Previous; +if (!Tok || Tok->isNot(tok::identifier)) + return true; +Tok = Tok->Previous; +while (Tok && Tok->endsSequence(tok::coloncolon, tok::identifier)) { + assert(Tok->Previous); + Tok = Tok->Previous->Previous; +} +return !Tok || !Tok->Tok.getIdentifierInfo(); + }; + Contexts.back().IsExpression = IsExpr(OpeningParen); +} else if (!Line.MustBeDeclaration) { bool IsForOrCatch = OpeningParen.Previous && OpeningParen.Previous->isOneOf(tok::kw_for, tok::kw_catch); diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 82c9be0f4df71..f70424c3ee060 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -79,6 +79,22 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) { ASSERT_EQ(Tokens.size(), 10u) << Tokens; EXPECT_TOKEN(Tokens[6], tok::star, TT_BinaryOperator); + Tokens = annotate("#define FOO foo.bar(a & b)"); + ASSERT_EQ(Tokens.size(), 12u) << Tokens; + EXPECT_TOKEN(Tokens[8], tok::amp, TT_BinaryOperator); + + Tokens = annotate("#define FOO foo::bar(a && b)"); + ASSERT_EQ(Tokens.size(), 12u) << Tokens; + EXPECT_TOKEN(Tokens[8], tok::ampamp, TT_BinaryOperator); + + Tokens = annotate("#define FOO foo bar(a *b)"); + ASSERT_EQ(Tokens.size(), 11u) << Tokens; +
[clang] [clang-format] Fix a bug in annotating `*` in `#define`s (PR #99433)
owenca wrote: > How about judging whether the FunctionLBrace exists as the opener of the > outer context? That wouldn't work as we must also handle function calls at the top level when dealing with macro definitions. https://github.com/llvm/llvm-project/pull/99433 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in annotating `*` in `#define`s (PR #99433)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/99433 >From ebf25d890ff47be48bd153942d943906943a247b Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Wed, 17 Jul 2024 22:30:21 -0700 Subject: [PATCH 1/2] [clang-format] Fix a bug in annotating `*` in `#define`s Fixes #99271. --- clang/lib/Format/TokenAnnotator.cpp | 3 ++- clang/unittests/Format/TokenAnnotatorTest.cpp | 4 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index b6d6e52ccb8f8..f1125fd35b427 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -374,7 +374,8 @@ class AnnotatingParser { Contexts.back().IsExpression = true; } else if (Line.InPPDirective && (!OpeningParen.Previous || -OpeningParen.Previous->isNot(tok::identifier))) { +OpeningParen.Previous->isNot(tok::identifier) || +!OpeningParen.Previous->Previous)) { Contexts.back().IsExpression = true; } else if (Contexts[Contexts.size() - 2].CaretFound) { // This is the parameter list of an ObjC block. diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index c5e8aa72cd2cb..82c9be0f4df71 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -75,6 +75,10 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) { EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_TypeDeclarationParen); EXPECT_TOKEN(Tokens[11], tok::star, TT_PointerOrReference); + Tokens = annotate("#define FOO bar(a * b)"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[6], tok::star, TT_BinaryOperator); + Tokens = annotate("void f() {\n" " while (p < a && *p == 'a')\n" "p++;\n" >From 70af6643045a6ded03fe1b3bbb21c55a2c5971b1 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Fri, 19 Jul 2024 08:59:14 -0700 Subject: [PATCH 2/2] Handles tokens before the function name. --- clang/lib/Format/TokenAnnotator.cpp | 20 +-- clang/unittests/Format/TokenAnnotatorTest.cpp | 16 +++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index f1125fd35b427..50201c970ab60 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -372,11 +372,6 @@ class AnnotatingParser { OpeningParen.Previous->is(tok::kw__Generic)) { Contexts.back().ContextType = Context::C11GenericSelection; Contexts.back().IsExpression = true; -} else if (Line.InPPDirective && - (!OpeningParen.Previous || -OpeningParen.Previous->isNot(tok::identifier) || -!OpeningParen.Previous->Previous)) { - Contexts.back().IsExpression = true; } else if (Contexts[Contexts.size() - 2].CaretFound) { // This is the parameter list of an ObjC block. Contexts.back().IsExpression = false; @@ -389,7 +384,20 @@ class AnnotatingParser { OpeningParen.Previous->MatchingParen->isOneOf( TT_ObjCBlockLParen, TT_FunctionTypeLParen)) { Contexts.back().IsExpression = false; -} else if (!Line.MustBeDeclaration && !Line.InPPDirective) { +} else if (Line.InPPDirective) { + auto IsExpr = [](const FormatToken ) { +const auto *Tok = LParen.Previous; +if (!Tok || Tok->isNot(tok::identifier)) + return true; +Tok = Tok->Previous; +while (Tok && Tok->endsSequence(tok::coloncolon, tok::identifier)) { + assert(Tok->Previous); + Tok = Tok->Previous->Previous; +} +return !Tok || !Tok->Tok.getIdentifierInfo(); + }; + Contexts.back().IsExpression = IsExpr(OpeningParen); +} else if (!Line.MustBeDeclaration) { bool IsForOrCatch = OpeningParen.Previous && OpeningParen.Previous->isOneOf(tok::kw_for, tok::kw_catch); diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 82c9be0f4df71..f70424c3ee060 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -79,6 +79,22 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) { ASSERT_EQ(Tokens.size(), 10u) << Tokens; EXPECT_TOKEN(Tokens[6], tok::star, TT_BinaryOperator); + Tokens = annotate("#define FOO foo.bar(a & b)"); + ASSERT_EQ(Tokens.size(), 12u) << Tokens; + EXPECT_TOKEN(Tokens[8], tok::amp, TT_BinaryOperator); + + Tokens = annotate("#define FOO foo::bar(a && b)"); + ASSERT_EQ(Tokens.size(), 12u) << Tokens; + EXPECT_TOKEN(Tokens[8], tok::ampamp, TT_BinaryOperator); + + Tokens = annotate("#define FOO foo bar(a *b)"); + ASSERT_EQ(Tokens.size(), 11u) << Tokens; +
[clang] [clang-format] Fix a bug in annotating `*` in `#define`s (PR #99433)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/99433 Fixes #99271. >From ebf25d890ff47be48bd153942d943906943a247b Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Wed, 17 Jul 2024 22:30:21 -0700 Subject: [PATCH] [clang-format] Fix a bug in annotating `*` in `#define`s Fixes #99271. --- clang/lib/Format/TokenAnnotator.cpp | 3 ++- clang/unittests/Format/TokenAnnotatorTest.cpp | 4 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index b6d6e52ccb8f8..f1125fd35b427 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -374,7 +374,8 @@ class AnnotatingParser { Contexts.back().IsExpression = true; } else if (Line.InPPDirective && (!OpeningParen.Previous || -OpeningParen.Previous->isNot(tok::identifier))) { +OpeningParen.Previous->isNot(tok::identifier) || +!OpeningParen.Previous->Previous)) { Contexts.back().IsExpression = true; } else if (Contexts[Contexts.size() - 2].CaretFound) { // This is the parameter list of an ObjC block. diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index c5e8aa72cd2cb..82c9be0f4df71 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -75,6 +75,10 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) { EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_TypeDeclarationParen); EXPECT_TOKEN(Tokens[11], tok::star, TT_PointerOrReference); + Tokens = annotate("#define FOO bar(a * b)"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[6], tok::star, TT_BinaryOperator); + Tokens = annotate("void f() {\n" " while (p < a && *p == 'a')\n" "p++;\n" ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add BinPackBinaryOperations configuration (PR #95013)
owenca wrote: It seems [AlignOperands](https://clang.llvm.org/docs/ClangFormatStyleOptions.html#alignoperands) is supposed to do what this new option would, so maybe we should fix/extend `AlignOperands` instead? https://github.com/llvm/llvm-project/pull/95013 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add BinPackBinaryOperations configuration (PR #95013)
owenca wrote: It seems that this patch implements the new option without regard to the relative precedence of the binary operators: ``` $ cat bar.cc f1 = f2 * f3 + f4 / f5 - f6; $ clang-format -style='{BinPackBinaryOperations: false}' bar.cc f1 = f2 * f3 + f4 / f5 - f6; $ ``` @mydeveloperday @HazardyKnusperkeks @rymiel are you okay with this? https://github.com/llvm/llvm-project/pull/95013 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add BinPackBinaryOperations configuration (PR #95013)
owenca wrote: This patch doesn't seem to work with the last two examples in #79487: ``` $ cat foo.cc template concept my_concept = std::is_object_v && std::is_const_v && std::default_initializable; std::uint32_t a = byte_buffer[0] | byte_buffer[1] << 8 | byte_buffer[2] << 16 | byte_buffer[3] << 24; $ clang-format -style='{BinPackBinaryOperations: false, BreakBeforeBinaryOperators: NonAssignment, ColumnLimit: 50}' foo.cc template concept my_concept = std::is_object_v && std::is_const_v && std::default_initializable; std::uint32_t a = byte_buffer[0] | byte_buffer[1] << 8 | byte_buffer[2] << 16 | byte_buffer[3] << 24; $ ``` The logical `&&` and bitwise `|` operations are not broken up into one per line, and the column limit is exceeded. https://github.com/llvm/llvm-project/pull/95013 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in SpaceBeforeParensOptions (PR #98849)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/98849 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add BinPackBinaryOperations configuration (PR #95013)
@@ -27628,6 +27628,119 @@ TEST_F(FormatTest, SpaceBetweenKeywordAndLiteral) { verifyFormat("return sizeof \"5\";"); } +TEST_F(FormatTest, BinPackBinaryOperations) { + auto Style = getLLVMStyleWithColumns(60); + // Logical operations + verifyFormat("if (condition1 && condition2) {\n" + "}", + Style); + + verifyFormat("if (condition1 && condition2 &&\n" + "(condition3 || condition4) && condition5 &&\n" + "condition6) {\n" + "}", + Style); + + verifyFormat("if (loongcondition1 &&\n" + "loongcondition2) {\n" + "}", + Style); + + // Arithmetic + verifyFormat("const int result = lhs + rhs;", Style); + + verifyFormat("const int result = lngop1 + longop2 +\n" + " loongop3;", + Style); + + verifyFormat("result = longOperand1 + longOperand2 -\n" + " (longOperand3 + longOperand4) -\n" + " longOperand5 * longOperand6;", + Style); + + verifyFormat("const int result =\n" + "operand1 + operand2 - (operand3 + operand4);\n", owenca wrote: ```suggestion "operand1 + operand2 - (operand3 + operand4);", ``` https://github.com/llvm/llvm-project/pull/95013 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add BinPackBinaryOperations configuration (PR #95013)
@@ -27628,6 +27628,119 @@ TEST_F(FormatTest, SpaceBetweenKeywordAndLiteral) { verifyFormat("return sizeof \"5\";"); } +TEST_F(FormatTest, BinPackBinaryOperations) { + auto Style = getLLVMStyleWithColumns(60); + // Logical operations + verifyFormat("if (condition1 && condition2) {\n" + "}", + Style); + + verifyFormat("if (condition1 && condition2 &&\n" + "(condition3 || condition4) && condition5 &&\n" + "condition6) {\n" + "}", + Style); + + verifyFormat("if (loongcondition1 &&\n" + "loongcondition2) {\n" + "}", + Style); + + // Arithmetic + verifyFormat("const int result = lhs + rhs;", Style); + + verifyFormat("const int result = lngop1 + longop2 +\n" + " loongop3;", + Style); + + verifyFormat("result = longOperand1 + longOperand2 -\n" + " (longOperand3 + longOperand4) -\n" + " longOperand5 * longOperand6;", + Style); + + verifyFormat("const int result =\n" + "operand1 + operand2 - (operand3 + operand4);\n", + Style); + + Style.BinPackBinaryOperations = false; + + // Logical operations + verifyFormat("if (condition1 && condition2) {\n" + "}", + Style); + + verifyFormat("if (condition1 && // comment\n" + "condition2 &&\n" + "(condition3 || condition4) && // comment\n" + "condition5 &&\n" + "condition6) {\n" + "}", + Style); + + verifyFormat("if (loongcondition1 &&\n" + "loongcondition2) {\n" + "}", + Style); + + // Arithmetic + verifyFormat("const int result = lhs + rhs;\n", Style); owenca wrote: Ditto. https://github.com/llvm/llvm-project/pull/95013 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in SpaceBeforeParensOptions (PR #98849)
owenca wrote: > Are there tests for #98820? I've added a test case. https://github.com/llvm/llvm-project/pull/98849 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in SpaceBeforeParensOptions (PR #98849)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/98849 >From 24f3b4f03f217e578aa2a2585d7d1742b7d7c09b Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Sun, 14 Jul 2024 17:52:23 -0700 Subject: [PATCH 1/2] [clang-format] Fix a bug in SpaceBeforeParensOptions Handle constructors/destructors for AfterFunctionDeclarationName and AfterFunctionDefinitionName. Fixes #98812. --- clang/lib/Format/TokenAnnotator.cpp | 15 +++ clang/unittests/Format/FormatTest.cpp | 4 ++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 1fd309afd697e..b6d6e52ccb8f8 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -4713,14 +4713,13 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine , if (Right.is(TT_OverloadedOperatorLParen)) return spaceRequiredBeforeParens(Right); // Function declaration or definition -if (Line.MightBeFunctionDecl && (Left.is(TT_FunctionDeclarationName))) { - if (Line.mightBeFunctionDefinition()) { -return Style.SpaceBeforeParensOptions.AfterFunctionDefinitionName || - spaceRequiredBeforeParens(Right); - } else { -return Style.SpaceBeforeParensOptions.AfterFunctionDeclarationName || - spaceRequiredBeforeParens(Right); - } +if (Line.MightBeFunctionDecl && Right.is(TT_FunctionDeclarationLParen)) { + if (spaceRequiredBeforeParens(Right)) +return true; + const auto = Style.SpaceBeforeParensOptions; + return Line.mightBeFunctionDefinition() + ? Options.AfterFunctionDefinitionName + : Options.AfterFunctionDeclarationName; } // Lambda if (Line.Type != LT_PreprocessorDirective && Left.is(tok::r_square) && diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 283843ad7ab47..911f0ea8e57e8 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -16875,7 +16875,7 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) { verifyFormat("int f();", SpaceFuncDef); verifyFormat("void f (int a, T b) {}", SpaceFuncDef); verifyFormat("void __attribute__((asdf)) f (int a, T b) {}", SpaceFuncDef); - verifyFormat("A::A() : a(1) {}", SpaceFuncDef); + verifyFormat("A::A () : a(1) {}", SpaceFuncDef); verifyFormat("void f() __attribute__((asdf));", SpaceFuncDef); verifyFormat("void __attribute__((asdf)) f();", SpaceFuncDef); verifyFormat("#define A(x) x", SpaceFuncDef); @@ -16901,7 +16901,7 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) { verifyFormat("T A::operator()() {}", SpaceFuncDef); verifyFormat("auto lambda = [] () { return 0; };", SpaceFuncDef); verifyFormat("int x = int(y);", SpaceFuncDef); - verifyFormat("M(std::size_t R, std::size_t C) : C(C), data(R) {}", + verifyFormat("M (std::size_t R, std::size_t C) : C(C), data(R) {}", SpaceFuncDef); FormatStyle SpaceIfMacros = getLLVMStyle(); >From 59d30d669d15770cea770a4b546de8601ad84105 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Sun, 14 Jul 2024 22:51:17 -0700 Subject: [PATCH 2/2] Add a test case for #98820. --- clang/unittests/Format/FormatTest.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 911f0ea8e57e8..d01ce137b8fcb 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -16901,6 +16901,7 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) { verifyFormat("T A::operator()() {}", SpaceFuncDef); verifyFormat("auto lambda = [] () { return 0; };", SpaceFuncDef); verifyFormat("int x = int(y);", SpaceFuncDef); + verifyFormat("void foo::bar () {}", SpaceFuncDef); verifyFormat("M (std::size_t R, std::size_t C) : C(C), data(R) {}", SpaceFuncDef); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in SpaceBeforeParensOptions (PR #98849)
https://github.com/owenca edited https://github.com/llvm/llvm-project/pull/98849 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in SpaceBeforeParensOptions (PR #98849)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/98849 Handle constructors/destructors for AfterFunctionDeclarationName and AfterFunctionDefinitionName. Fixes #98812. >From 24f3b4f03f217e578aa2a2585d7d1742b7d7c09b Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Sun, 14 Jul 2024 17:52:23 -0700 Subject: [PATCH] [clang-format] Fix a bug in SpaceBeforeParensOptions Handle constructors/destructors for AfterFunctionDeclarationName and AfterFunctionDefinitionName. Fixes #98812. --- clang/lib/Format/TokenAnnotator.cpp | 15 +++ clang/unittests/Format/FormatTest.cpp | 4 ++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 1fd309afd697e..b6d6e52ccb8f8 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -4713,14 +4713,13 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine , if (Right.is(TT_OverloadedOperatorLParen)) return spaceRequiredBeforeParens(Right); // Function declaration or definition -if (Line.MightBeFunctionDecl && (Left.is(TT_FunctionDeclarationName))) { - if (Line.mightBeFunctionDefinition()) { -return Style.SpaceBeforeParensOptions.AfterFunctionDefinitionName || - spaceRequiredBeforeParens(Right); - } else { -return Style.SpaceBeforeParensOptions.AfterFunctionDeclarationName || - spaceRequiredBeforeParens(Right); - } +if (Line.MightBeFunctionDecl && Right.is(TT_FunctionDeclarationLParen)) { + if (spaceRequiredBeforeParens(Right)) +return true; + const auto = Style.SpaceBeforeParensOptions; + return Line.mightBeFunctionDefinition() + ? Options.AfterFunctionDefinitionName + : Options.AfterFunctionDeclarationName; } // Lambda if (Line.Type != LT_PreprocessorDirective && Left.is(tok::r_square) && diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 283843ad7ab47..911f0ea8e57e8 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -16875,7 +16875,7 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) { verifyFormat("int f();", SpaceFuncDef); verifyFormat("void f (int a, T b) {}", SpaceFuncDef); verifyFormat("void __attribute__((asdf)) f (int a, T b) {}", SpaceFuncDef); - verifyFormat("A::A() : a(1) {}", SpaceFuncDef); + verifyFormat("A::A () : a(1) {}", SpaceFuncDef); verifyFormat("void f() __attribute__((asdf));", SpaceFuncDef); verifyFormat("void __attribute__((asdf)) f();", SpaceFuncDef); verifyFormat("#define A(x) x", SpaceFuncDef); @@ -16901,7 +16901,7 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) { verifyFormat("T A::operator()() {}", SpaceFuncDef); verifyFormat("auto lambda = [] () { return 0; };", SpaceFuncDef); verifyFormat("int x = int(y);", SpaceFuncDef); - verifyFormat("M(std::size_t R, std::size_t C) : C(C), data(R) {}", + verifyFormat("M (std::size_t R, std::size_t C) : C(C), data(R) {}", SpaceFuncDef); FormatStyle SpaceIfMacros = getLLVMStyle(); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in TCAS_Leave using tabs for indentation (PR #98427)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/98427 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add BinPackBinaryOperations configuration (PR #95013)
@@ -27628,6 +27628,109 @@ TEST_F(FormatTest, SpaceBetweenKeywordAndLiteral) { verifyFormat("return sizeof \"5\";"); } +TEST_F(FormatTest, BinPackBinaryOperations) { + auto Style = getLLVMStyleWithColumns(60); + // Logical operations + verifyFormat("if (condition1 && condition2) {\n" + "}", + Style); + + verifyFormat("if (condition1 && condition2 &&\n" + "(condition3 || condition4) && condition5 &&\n" + "condition6) {\n" + "}", + Style); + + verifyFormat("if (loongcondition1 &&\n" + "loongcondition2) {\n" + "}", + Style); + + // Arithmetic + verifyFormat("const int result = lhs + rhs;\n", Style); owenca wrote: The trailing newlines are still present. https://github.com/llvm/llvm-project/pull/95013 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add BinPackBinaryOperations configuration (PR #95013)
@@ -3153,6 +3153,15 @@ class ExpressionParser { parse(Precedence + 1); int CurrentPrecedence = getCurrentPrecedence(); + if (!Style.BinPackBinaryOperations && + (CurrentPrecedence > prec::Conditional) && + (CurrentPrecedence < prec::PointerToMember)) { owenca wrote: The redundant parens are still present. https://github.com/llvm/llvm-project/pull/95013 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add BinPackBinaryOperations configuration (PR #95013)
https://github.com/owenca edited https://github.com/llvm/llvm-project/pull/95013 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add BinPackBinaryOperations configuration (PR #95013)
https://github.com/owenca commented: Also, we need ConfigParseTest for the new option. https://github.com/llvm/llvm-project/pull/95013 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in TCAS_Leave using tabs for indentation (PR #98427)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/98427 Fixes #92530. >From fa1da3d06ed2207902df4911933bd40f0d514e51 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Wed, 10 Jul 2024 20:52:18 -0700 Subject: [PATCH] [clang-format] Fix a bug in TCAS_Leave using tabs for indentation Fixes #92530. --- clang/lib/Format/WhitespaceManager.cpp| 2 +- clang/unittests/Format/FormatTestComments.cpp | 17 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index 50531aee9d597..a31874a7c3195 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -1116,7 +1116,7 @@ void WhitespaceManager::alignTrailingComments() { // leave the comments. if (RestoredLineLength >= Style.ColumnLimit && Style.ColumnLimit > 0) break; - C.Spaces = OriginalSpaces; + C.Spaces = C.NewlinesBefore > 0 ? C.Tok->OriginalColumn : OriginalSpaces; continue; } diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp index 3e75707a9faec..8f84d59cbb2e2 100644 --- a/clang/unittests/Format/FormatTestComments.cpp +++ b/clang/unittests/Format/FormatTestComments.cpp @@ -3145,6 +3145,23 @@ TEST_F(FormatTestComments, AlignTrailingCommentsLeave) { "int bar = 1234; // This is a very long comment\n" " // which is wrapped arround.", Style)); + + Style = getLLVMStyle(); + Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Leave; + Style.TabWidth = 2; + Style.UseTab = FormatStyle::UT_ForIndentation; + verifyNoChange("{\n" + "\t// f\n" + "\tf();\n" + "\n" + "\t// g\n" + "\tg();\n" + "\t{\n" + "\t\t// h(); // h\n" + "\t\tfoo(); // foo\n" + "\t}\n" + "}", + Style); } TEST_F(FormatTestComments, DontAlignNamespaceComments) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add BinPackBinaryOperations configuration (PR #95013)
@@ -27628,6 +27628,109 @@ TEST_F(FormatTest, SpaceBetweenKeywordAndLiteral) { verifyFormat("return sizeof \"5\";"); } +TEST_F(FormatTest, BinPackBinaryOperations) { + auto Style = getLLVMStyleWithColumns(60); + // Logical operations + verifyFormat("if (condition1 && condition2) {\n" + "}", + Style); + + verifyFormat("if (condition1 && condition2 &&\n" + "(condition3 || condition4) && condition5 &&\n" + "condition6) {\n" + "}", + Style); + + verifyFormat("if (loongcondition1 &&\n" + "loongcondition2) {\n" + "}", + Style); + + // Arithmetic + verifyFormat("const int result = lhs + rhs;\n", Style); owenca wrote: No trailing newline at the end of the test cases here and below. https://github.com/llvm/llvm-project/pull/95013 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add BinPackBinaryOperations configuration (PR #95013)
@@ -146,6 +146,14 @@ static bool startsNextParameter(const FormatToken , Style.BreakInheritanceList != FormatStyle::BILS_BeforeComma)); } +// Returns \c true if \c Current starts a new operand in a binary operation. +static bool startsNextOperand(const FormatToken ) { + const FormatToken = *Current.Previous; + return Previous.is(TT_BinaryOperator) && !Current.isTrailingComment() && + (Previous.getPrecedence() > prec::Conditional) && + (Previous.getPrecedence() < prec::PointerToMember); owenca wrote: Please remove the redundant parens. https://github.com/llvm/llvm-project/pull/95013 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add BinPackBinaryOperations configuration (PR #95013)
@@ -146,6 +146,14 @@ static bool startsNextParameter(const FormatToken , Style.BreakInheritanceList != FormatStyle::BILS_BeforeComma)); } +// Returns \c true if \c Current starts a new operand in a binary operation. +static bool startsNextOperand(const FormatToken ) { + const FormatToken = *Current.Previous; owenca wrote: Assert `Current.Previous` before dereferencing it. ```suggestion const auto = *Current.Previous; ``` https://github.com/llvm/llvm-project/pull/95013 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add BinPackBinaryOperations configuration (PR #95013)
@@ -3153,6 +3153,15 @@ class ExpressionParser { parse(Precedence + 1); int CurrentPrecedence = getCurrentPrecedence(); + if (!Style.BinPackBinaryOperations && + (CurrentPrecedence > prec::Conditional) && + (CurrentPrecedence < prec::PointerToMember)) { owenca wrote: Remove redundant parens. https://github.com/llvm/llvm-project/pull/95013 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add BinPackBinaryOperations configuration (PR #95013)
@@ -146,6 +146,14 @@ static bool startsNextParameter(const FormatToken , Style.BreakInheritanceList != FormatStyle::BILS_BeforeComma)); } +// Returns \c true if \c Current starts a new operand in a binary operation. owenca wrote: Did you mean `Current is the right operand of a binary operator`? https://github.com/llvm/llvm-project/pull/95013 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format][NFC] Annotate function/ctor/dtor declaration l_paren (PR #97938)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/97938 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format][NFC] Annotate function/ctor/dtor declaration l_paren (PR #97938)
https://github.com/owenca edited https://github.com/llvm/llvm-project/pull/97938 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format][NFC] Annotate function decl l_paren (PR #97938)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/97938 >From eb53318b3c5dec2452c4a0d5aed7944ebdd99380 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Sat, 6 Jul 2024 22:21:26 -0700 Subject: [PATCH 1/2] [clang-format][NFC] Annotate function decl l_paren --- clang/lib/Format/FormatToken.h| 1 + clang/lib/Format/TokenAnnotator.cpp | 6 ++ clang/unittests/Format/TokenAnnotatorTest.cpp | 18 ++ 3 files changed, 25 insertions(+) diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index 4ffd745bf9307..cc45d5a8c5c1e 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -77,6 +77,7 @@ namespace format { TYPE(ForEachMacro) \ TYPE(FunctionAnnotationRParen) \ TYPE(FunctionDeclarationName) \ + TYPE(FunctionDeclarationLParen) \ TYPE(FunctionLBrace) \ TYPE(FunctionLikeOrFreestandingMacro) \ TYPE(FunctionTypeLParen) \ diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 0fd0214d16615..d453fd6d4d224 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -3864,6 +3864,12 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine ) const { Tok->setFinalizedType(TT_FunctionDeclarationName); LineIsFunctionDeclaration = true; SeenName = true; + if (ClosingParen) { +auto *OpeningParen = ClosingParen->MatchingParen; +assert(OpeningParen); +if (OpeningParen->is(TT_Unknown)) + OpeningParen->setType(TT_FunctionDeclarationLParen); + } break; } } diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 5d83d8a0c4429..d109bf2ba5327 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1037,6 +1037,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) { EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[9]->ClosesRequiresClause); EXPECT_TOKEN(Tokens[11], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[12], tok::l_paren, TT_FunctionDeclarationLParen); Tokens = annotate("template \n" "requires Bar\n" @@ -1045,6 +1046,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) { EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[9]->ClosesRequiresClause); EXPECT_TOKEN(Tokens[14], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[15], tok::l_paren, TT_FunctionDeclarationLParen); Tokens = annotate("template \n" "struct S {\n" @@ -1914,15 +1916,18 @@ TEST_F(TokenAnnotatorTest, UnderstandsFunctionDeclarationNames) { auto Tokens = annotate("void f [[noreturn]] ();"); ASSERT_EQ(Tokens.size(), 11u) << Tokens; EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_FunctionDeclarationLParen); Tokens = annotate("void f [[noreturn]] () {}"); ASSERT_EQ(Tokens.size(), 12u) << Tokens; EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_FunctionDeclarationLParen); Tokens = annotate("#define FOO Foo::\n" "FOO Foo();"); ASSERT_EQ(Tokens.size(), 11u) << Tokens; EXPECT_TOKEN(Tokens[6], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_FunctionDeclarationLParen); Tokens = annotate("struct Foo {\n" " Bar (*func)();\n" @@ -1934,16 +1939,19 @@ TEST_F(TokenAnnotatorTest, UnderstandsFunctionDeclarationNames) { Tokens = annotate("void instanceof();"); ASSERT_EQ(Tokens.size(), 6u); EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_FunctionDeclarationLParen); Tokens = annotate("int iso_time(time_t);"); ASSERT_EQ(Tokens.size(), 7u) << Tokens; EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_FunctionDeclarationLParen); auto Style = getLLVMStyle(); Style.TypeNames.push_back("MyType"); Tokens = annotate("int iso_time(MyType);", Style); ASSERT_EQ(Tokens.size(), 7u) << Tokens; EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_FunctionDeclarationLParen); EXPECT_TOKEN(Tokens[3], tok::identifier, TT_TypeName); } @@ -2836,6 +2844,7
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
@@ -803,6 +803,60 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState , bool DryRun, return !Tok.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while, tok::kw_switch); }; + // Detecting functions is brittle. It would be better if we could annotate + // the LParen type of functions/calls. owenca wrote: I've done it in #97938. Can you use it after it's merged? https://github.com/llvm/llvm-project/pull/93140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format][NFC] Annotate function decl l_paren (PR #97938)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/97938 None >From eb53318b3c5dec2452c4a0d5aed7944ebdd99380 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Sat, 6 Jul 2024 22:21:26 -0700 Subject: [PATCH] [clang-format][NFC] Annotate function decl l_paren --- clang/lib/Format/FormatToken.h| 1 + clang/lib/Format/TokenAnnotator.cpp | 6 ++ clang/unittests/Format/TokenAnnotatorTest.cpp | 18 ++ 3 files changed, 25 insertions(+) diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index 4ffd745bf9307..cc45d5a8c5c1e 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -77,6 +77,7 @@ namespace format { TYPE(ForEachMacro) \ TYPE(FunctionAnnotationRParen) \ TYPE(FunctionDeclarationName) \ + TYPE(FunctionDeclarationLParen) \ TYPE(FunctionLBrace) \ TYPE(FunctionLikeOrFreestandingMacro) \ TYPE(FunctionTypeLParen) \ diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 0fd0214d16615..d453fd6d4d224 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -3864,6 +3864,12 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine ) const { Tok->setFinalizedType(TT_FunctionDeclarationName); LineIsFunctionDeclaration = true; SeenName = true; + if (ClosingParen) { +auto *OpeningParen = ClosingParen->MatchingParen; +assert(OpeningParen); +if (OpeningParen->is(TT_Unknown)) + OpeningParen->setType(TT_FunctionDeclarationLParen); + } break; } } diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 5d83d8a0c4429..d109bf2ba5327 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1037,6 +1037,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) { EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[9]->ClosesRequiresClause); EXPECT_TOKEN(Tokens[11], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[12], tok::l_paren, TT_FunctionDeclarationLParen); Tokens = annotate("template \n" "requires Bar\n" @@ -1045,6 +1046,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) { EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[9]->ClosesRequiresClause); EXPECT_TOKEN(Tokens[14], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[15], tok::l_paren, TT_FunctionDeclarationLParen); Tokens = annotate("template \n" "struct S {\n" @@ -1914,15 +1916,18 @@ TEST_F(TokenAnnotatorTest, UnderstandsFunctionDeclarationNames) { auto Tokens = annotate("void f [[noreturn]] ();"); ASSERT_EQ(Tokens.size(), 11u) << Tokens; EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_FunctionDeclarationLParen); Tokens = annotate("void f [[noreturn]] () {}"); ASSERT_EQ(Tokens.size(), 12u) << Tokens; EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_FunctionDeclarationLParen); Tokens = annotate("#define FOO Foo::\n" "FOO Foo();"); ASSERT_EQ(Tokens.size(), 11u) << Tokens; EXPECT_TOKEN(Tokens[6], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_FunctionDeclarationLParen); Tokens = annotate("struct Foo {\n" " Bar (*func)();\n" @@ -1934,16 +1939,19 @@ TEST_F(TokenAnnotatorTest, UnderstandsFunctionDeclarationNames) { Tokens = annotate("void instanceof();"); ASSERT_EQ(Tokens.size(), 6u); EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_FunctionDeclarationLParen); Tokens = annotate("int iso_time(time_t);"); ASSERT_EQ(Tokens.size(), 7u) << Tokens; EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_FunctionDeclarationLParen); auto Style = getLLVMStyle(); Style.TypeNames.push_back("MyType"); Tokens = annotate("int iso_time(MyType);", Style); ASSERT_EQ(Tokens.size(), 7u) << Tokens; EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_FunctionDeclarationLParen); EXPECT_TOKEN(Tokens[3], tok::identifier, TT_TypeName); } @@ -2836,6
[clang] [clang-format] Skip block commented out includes when sorting them (PR #97787)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/97787 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Skip block commented out includes when sorting them (PR #97787)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/97787 Fixes #97539. >From 73d92b38268e5b44d6ed7e6ac9219267003cc7fb Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Thu, 4 Jul 2024 21:39:38 -0700 Subject: [PATCH] [clang-format] Skip block commented out includes when sorting them Fixes #97539. --- clang/lib/Format/Format.cpp | 15 +++ clang/unittests/Format/SortIncludesTest.cpp | 9 + 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 6a8883b77a730..7fd42e46e0ccb 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -3222,10 +3222,16 @@ tooling::Replacements sortCppIncludes(const FormatStyle , StringRef Code, if (Trimmed.contains(RawStringTermination)) FormattingOff = false; -if (isClangFormatOff(Trimmed)) +bool IsBlockComment = false; + +if (isClangFormatOff(Trimmed)) { FormattingOff = true; -else if (isClangFormatOn(Trimmed)) +} else if (isClangFormatOn(Trimmed)) { FormattingOff = false; +} else if (Trimmed.starts_with("/*")) { + IsBlockComment = true; + Pos = Code.find("*/", SearchFrom + 2); +} const bool EmptyLineSkipped = Trimmed.empty() && @@ -3235,9 +3241,10 @@ tooling::Replacements sortCppIncludes(const FormatStyle , StringRef Code, bool MergeWithNextLine = Trimmed.ends_with("\\"); if (!FormattingOff && !MergeWithNextLine) { - if (tooling::HeaderIncludes::IncludeRegex.match(Line, )) { + if (!IsBlockComment && + tooling::HeaderIncludes::IncludeRegex.match(Trimmed, )) { StringRef IncludeName = Matches[2]; -if (Line.contains("/*") && !Line.contains("*/")) { +if (Trimmed.contains("/*") && !Trimmed.contains("*/")) { // #include with a start of a block comment, but without the end. // Need to keep all the lines until the end of the comment together. // FIXME: This is somehow simplified check that probably does not work diff --git a/clang/unittests/Format/SortIncludesTest.cpp b/clang/unittests/Format/SortIncludesTest.cpp index 2eeb16b4ab9f5..3175382564637 100644 --- a/clang/unittests/Format/SortIncludesTest.cpp +++ b/clang/unittests/Format/SortIncludesTest.cpp @@ -1455,6 +1455,15 @@ TEST_F(SortIncludesTest, DisableRawStringLiteralSorting) { #undef X } +TEST_F(SortIncludesTest, BlockCommentedOutIncludes) { + StringRef Code{"/* #include \"foo.h\"\n" + "#include \"bar.h\" */\n" + "#include "}; + + FmtStyle = getGoogleStyle(FormatStyle::LK_Cpp); + verifyFormat(Code, sort(Code, "input.cpp", 0)); +} + } // end namespace } // end namespace format } // end namespace clang ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Code implementing SpacesInParensOptions.ExceptDoubleParentheses logic (PR #93439)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/93439 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add SpacesInParensOption for filtering repeated parens (PR #77522)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/77522 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add SpacesInParensOption for filtering repeated parens (PR #77522)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/77522 >From 4a7489251b842da778dd839bd5af3db12ba0fe0b Mon Sep 17 00:00:00 2001 From: Gedare Bloom Date: Mon, 17 Jul 2023 18:24:30 -0600 Subject: [PATCH 1/5] Add SpaceInParensOption ExceptDoubleParentheses This change allows finer control over addition of spaces between a pair of consecutive opening parentheses with a pair of closing parentheses. --- clang/docs/ClangFormatStyleOptions.rst | 28 +- clang/docs/ReleaseNotes.rst| 3 + clang/include/clang/Format/Format.h| 40 ++- clang/lib/Format/Format.cpp| 5 +- clang/lib/Format/TokenAnnotator.cpp| 70 +++-- clang/unittests/Format/ConfigParseTest.cpp | 21 +- clang/unittests/Format/FormatTest.cpp | 314 + 7 files changed, 441 insertions(+), 40 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index bb00c20922d36..d5cda03e55f26 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -6214,6 +6214,7 @@ the configuration (without a prefix: ``Auto``). # Example of usage: SpacesInParens: Custom SpacesInParensOptions: + ExceptDoubleParentheses: false InConditionalStatements: true InEmptyParentheses: true @@ -6226,9 +6227,23 @@ the configuration (without a prefix: ``Auto``). # Should be declared this way: SpacesInParens: Custom SpacesInParensOptions: + ExceptDoubleParentheses: false InConditionalStatements: true Other: true + * ``bool ExceptDoubleParentheses`` Override any of the following options to prevent addition of space +between the first two parentheses in situations where a pair of +parentheses have been used. + +.. code-block:: c++ + + true: + __attribute__(( noreturn )) + __decltype__(( x )) + if (( a = b )) + false: + Uses the applicable option. + * ``bool InConditionalStatements`` Put a space in parentheses only inside conditional statements (``for/if/while/switch...``). @@ -6242,8 +6257,9 @@ the configuration (without a prefix: ``Auto``). .. code-block:: c++ - true: false: - x = ( int32 )y vs. x = (int32)y + true: false: + x = ( int32 )y vs.x = (int32)y + y = (( int (*)(int) )foo)(x); y = ((int (*)(int))foo)(x); * ``bool InEmptyParentheses`` Insert a space in empty parentheses, i.e. ``()``. @@ -6261,8 +6277,12 @@ the configuration (without a prefix: ``Auto``). .. code-block:: c++ - true: false: - t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete; + true: false: + t f( Deleted & ) & = delete;vs. t f(Deleted &) & = delete; + decltype( ( x ) ) decltype((x)) + x = ( (int32)y ) x = ((int32))y + y = ( (int ( * )( int ))foo )( x ); y = ((int (*)(int))foo)(x); + __attribute__( ( noreturn ) )__attribute__((noreturn)) .. _SpacesInParentheses: diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 92ada517acae3..bbb24a59191fa 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -1079,6 +1079,9 @@ clang-format - Adds ``AllowShortCaseExpressionOnASingleLine`` option. - Adds ``AlignCaseArrows`` suboption to ``AlignConsecutiveShortCaseStatements``. - Adds ``LeftWithLastLine`` suboption to ``AlignEscapedNewlines``. +- Add ``ExceptDoubleParentheses`` sub-option for ``SpacesInParensOptions`` + to override addition of spaces between multiple, non-redundant parentheses + similar to the rules used for ``RemoveParentheses``. libclang diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 7d257be10af42..3469cbad027c2 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -4650,10 +4650,23 @@ struct FormatStyle { /// # Should be declared this way: /// SpacesInParens: Custom /// SpacesInParensOptions: + /// ExceptDoubleParentheses: false /// InConditionalStatements: true /// Other: true /// \endcode struct SpacesInParensCustom { +/// Override any of the following options to prevent addition of space +/// between the first two parentheses in situations where a pair of +/// parentheses have been used. +/// \code +/// true: +/// __attribute__(( noreturn )) +/// __decltype__(( x )) +/// if (( a = b )) +/// \endcode +/// false: +///Uses the applicable option. +bool ExceptDoubleParentheses; /// Put a space in parentheses only inside conditional statements /// (``for/if/while/switch...``). ///
[clang] [clang-format] Allow ternary in all templates (PR #96801)
https://github.com/owenca approved this pull request. https://github.com/llvm/llvm-project/pull/96801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang-format] Aggregate options regarding empty lines (PR #96770)
owenca wrote: > This patch was initially part of > [9267f8f](https://github.com/llvm/llvm-project/commit/9267f8f19a2e502ef5a216c0d52b352b3699d399). > I neglected to check the server builds before I added it. It broke clangd. > Jie Fu fixed the problem in > [4c91b49](https://github.com/llvm/llvm-project/commit/4c91b49bab0728d4bc136aa33c4aeb4e8ea37d01). > I was unaware of it. I thought the main branch was still broken. I reverted > the first patch in > [70cfece](https://github.com/llvm/llvm-project/commit/70cfece24d6cbb57e35dd961cc97eb2a6bf1e387). > It broke his fix. He reverted it in > [c69ea04](https://github.com/llvm/llvm-project/commit/c69ea04fb9738db283263eb350669e00b77ee4fd). Instead, can you reland 9267f8f19a2e502ef5a216c0d52b352b3699d399 with the 1-line change in 4c91b49bab0728d4bc136aa33c4aeb4e8ea37d01 so that we don't need to review it again? https://github.com/llvm/llvm-project/pull/96770 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add SpacesInParensOption for filtering repeated parens (PR #77522)
https://github.com/owenca approved this pull request. https://github.com/llvm/llvm-project/pull/77522 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add SpacesInParensOption for filtering repeated parens (PR #77522)
https://github.com/owenca approved this pull request. https://github.com/llvm/llvm-project/pull/77522 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add SpacesInParensOption for filtering repeated parens (PR #77522)
@@ -17203,6 +17238,23 @@ TEST_F(FormatTest, ConfigurableSpacesInParens) { verifyFormat("SomeType *__attribute__((attr)) *a = NULL;", Spaces); verifyFormat("void __attribute__((naked)) foo(int bar)", Spaces); verifyFormat("void f( ) __attribute__((asdf));", Spaces); + verifyFormat("x = ( int32 )y;", Spaces); + verifyFormat("y = (( int (*)(int) )foo)(x);", Spaces); + verifyFormat("decltype(x) y = 42;", Spaces); + verifyFormat("decltype((x)) y = z;", Spaces); + verifyFormat("decltype((foo( ))) a = foo( );", Spaces); + verifyFormat("decltype((bar(10))) a = bar(11);", Spaces); + verifyFormat("if ((x - y) && (a ^ b))\n" + " f( );\n", owenca wrote: Ditto. https://github.com/llvm/llvm-project/pull/77522 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add SpacesInParensOption for filtering repeated parens (PR #77522)
@@ -17125,6 +17125,23 @@ TEST_F(FormatTest, ConfigurableSpacesInParens) { verifyFormat("SomeType *__attribute__((attr)) *a = NULL;", Spaces); verifyFormat("void __attribute__((naked)) foo(int bar)", Spaces); verifyFormat("void f() __attribute__((asdf));", Spaces); + verifyFormat("x = (int32)y;", Spaces); + verifyFormat("y = ((int (*)(int))foo)(x);", Spaces); + verifyFormat("decltype(x) y = 42;", Spaces); + verifyFormat("decltype((x)) y = z;", Spaces); + verifyFormat("decltype((foo())) a = foo();", Spaces); + verifyFormat("decltype((bar(10))) a = bar(11);", Spaces); + verifyFormat("if ((x - y) && (a ^ b))\n" + " f();\n", owenca wrote: No newline at the end of test cases. https://github.com/llvm/llvm-project/pull/77522 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add SpacesInParensOption for filtering repeated parens (PR #77522)
@@ -17159,6 +17176,23 @@ TEST_F(FormatTest, ConfigurableSpacesInParens) { verifyFormat("SomeType *__attribute__( ( attr ) ) *a = NULL;", Spaces); verifyFormat("void __attribute__( ( naked ) ) foo( int bar )", Spaces); verifyFormat("void f() __attribute__( ( asdf ) );", Spaces); + verifyFormat("x = (int32)y;", Spaces); + verifyFormat("y = ( (int ( * )( int ))foo )( x );", Spaces); + verifyFormat("decltype( x ) y = 42;", Spaces); + verifyFormat("decltype( ( x ) ) y = z;", Spaces); + verifyFormat("decltype( ( foo() ) ) a = foo();", Spaces); + verifyFormat("decltype( ( bar( 10 ) ) ) a = bar( 11 );", Spaces); + verifyFormat("if ( ( x - y ) && ( a ^ b ) )\n" + " f();\n", owenca wrote: Ditto. https://github.com/llvm/llvm-project/pull/77522 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add SpacesInParensOption for filtering repeated parens (PR #77522)
@@ -17310,6 +17362,63 @@ TEST_F(FormatTest, ConfigurableSpacesInParens) { verifyFormat("size_t idx = (a->foo)(a - 1);", Spaces); verifyFormat("size_t idx = (*foo)(a - 1);", Spaces); verifyFormat("size_t idx = (*(foo))(a - 1);", Spaces); + + // Check ExceptDoubleParentheses spaces + Spaces.IndentWidth = 2; + Spaces.SpacesInParens = FormatStyle::SIPO_Custom; + Spaces.SpacesInParensOptions = {}; + Spaces.SpacesInParensOptions.Other = true; + Spaces.SpacesInParensOptions.ExceptDoubleParentheses = true; + verifyFormat("SomeType *__attribute__(( attr )) *a = NULL;", Spaces); + verifyFormat("void __attribute__(( naked )) foo( int bar )", Spaces); + verifyFormat("void f() __attribute__(( asdf ));", Spaces); + verifyFormat("__attribute__(( __aligned__( x ) )) z;", Spaces); + verifyFormat("int x __attribute__(( aligned( 16 ) )) = 0;", Spaces); + verifyFormat("class __declspec( dllimport ) X {};", Spaces); + verifyFormat("class __declspec(( dllimport )) X {};", Spaces); + verifyFormat("int x = ( ( a - 1 ) * 3 );", Spaces); + verifyFormat("int x = ( 3 * ( a - 1 ) );", Spaces); + verifyFormat("decltype( x ) y = 42;", Spaces); + verifyFormat("decltype(( bar( 10 ) )) a = bar( 11 );", Spaces); + verifyFormat("if (( i = j ))\n" + " do_something( i );", + Spaces); + + Spaces.SpacesInParens = FormatStyle::SIPO_Custom; + Spaces.SpacesInParensOptions = {}; + Spaces.SpacesInParensOptions.InConditionalStatements = true; + Spaces.SpacesInParensOptions.ExceptDoubleParentheses = true; + verifyFormat("while ( (bool)1 )\n" + " continue;", + Spaces); + verifyFormat("while ((i = j))\n" + " continue;", + Spaces); + verifyFormat("do {\n" + " do_something((int)i);\n" + "} while ( something() );", + Spaces); + verifyFormat("do {\n" + " do_something((int)i);\n" + "} while ((i = i + 1));", + Spaces); + verifyFormat("if ( (x - y) && (a ^ b) )\n" + " f();\n", owenca wrote: Ditto. https://github.com/llvm/llvm-project/pull/77522 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add SpacesInParensOption for filtering repeated parens (PR #77522)
https://github.com/owenca edited https://github.com/llvm/llvm-project/pull/77522 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Don't count template template parameter as declaration (PR #96396)
https://github.com/owenca approved this pull request. https://github.com/llvm/llvm-project/pull/96396 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Don't count template template parameter as declaration (PR #95025)
https://github.com/owenca approved this pull request. https://github.com/llvm/llvm-project/pull/95025 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Annotate r_paren before braced list as TT_CastRParen (PR #96271)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/96271 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format][NFC] Add CMake target clang-format-check-format (PR #95873)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/95873 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Annotate r_paren before braced list as TT_CastRParen (PR #96271)
https://github.com/owenca edited https://github.com/llvm/llvm-project/pull/96271 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Annotate r_paren before braced list as TT_CastRParen (PR #96271)
https://github.com/owenca edited https://github.com/llvm/llvm-project/pull/96271 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Annotate r_paren before braced list as TT_CastRParen (PR #96271)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/96271 None >From 44eec3e8d4bec1de03428d42dce98a998f282825 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Thu, 20 Jun 2024 19:38:38 -0700 Subject: [PATCH] [clang-format] Annotate r_paren before braced list as TT_CastRParen --- clang/lib/Format/TokenAnnotator.cpp | 5 + clang/unittests/Format/TokenAnnotatorTest.cpp | 4 2 files changed, 9 insertions(+) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 63a028a6f4779..55c5ecee45e0c 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2837,6 +2837,11 @@ class AnnotatingParser { if (!AfterRParen->Next) return false; +if (AfterRParen->is(tok::l_brace) && +AfterRParen->getBlockKind() == BK_BracedInit) { + return true; +} + // If the next token after the parenthesis is a unary operator, assume // that this is cast, unless there are unexpected tokens inside the // parenthesis. diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 0dc506458f7c3..12c4b7fdd5ac2 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -662,6 +662,10 @@ TEST_F(TokenAnnotatorTest, UnderstandsCasts) { EXPECT_TOKEN(Tokens[3], tok::r_paren, TT_Unknown); EXPECT_TOKEN(Tokens[4], tok::amp, TT_BinaryOperator); + Tokens = annotate("return (struct foo){};"); + ASSERT_EQ(Tokens.size(), 9u) << Tokens; + EXPECT_TOKEN(Tokens[4], tok::r_paren, TT_CastRParen); + Tokens = annotate("#define FOO(bar) foo((uint64_t))"); ASSERT_EQ(Tokens.size(), 15u) << Tokens; EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_CastRParen); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format[NFC] Clean up AnnotatingParser::rParenEndsCast() (PR #96128)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/96128 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format[NFC] Clean up AnnotatingParser::rParenEndsCast() (PR #96128)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/96128 >From 420cde9e46d8eb3f3043d18cf78fbaef0f89ccbb Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Wed, 19 Jun 2024 18:07:56 -0700 Subject: [PATCH] [clang-format[NFC] Clean up AnnotatingParser::rParenEndsCast() --- clang/lib/Format/TokenAnnotator.cpp | 83 - 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 87e3e712d6993..63a028a6f4779 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2661,18 +2661,27 @@ class AnnotatingParser { /// Determine whether ')' is ending a cast. bool rParenEndsCast(const FormatToken ) { +assert(Tok.is(tok::r_paren)); + +if (!Tok.MatchingParen || !Tok.Previous) + return false; + // C-style casts are only used in C++, C# and Java. -if (!Style.isCSharp() && !IsCpp && Style.Language != FormatStyle::LK_Java) +if (!IsCpp && !Style.isCSharp() && Style.Language != FormatStyle::LK_Java) return false; +const auto *LParen = Tok.MatchingParen; +const auto *BeforeRParen = Tok.Previous; +const auto *AfterRParen = Tok.Next; + // Empty parens aren't casts and there are no casts at the end of the line. -if (Tok.Previous == Tok.MatchingParen || !Tok.Next || !Tok.MatchingParen) +if (BeforeRParen == LParen || !AfterRParen) return false; -if (Tok.MatchingParen->is(TT_OverloadedOperatorLParen)) +if (LParen->is(TT_OverloadedOperatorLParen)) return false; -FormatToken *LeftOfParens = Tok.MatchingParen->getPreviousNonComment(); +auto *LeftOfParens = LParen->getPreviousNonComment(); if (LeftOfParens) { // If there is a closing parenthesis left of the current // parentheses, look past it as these might be chained casts. @@ -2728,37 +2737,38 @@ class AnnotatingParser { } } -if (Tok.Next->is(tok::question) || -(Tok.Next->is(tok::ampamp) && !Tok.Previous->isTypeName(LangOpts))) { +if (AfterRParen->is(tok::question) || +(AfterRParen->is(tok::ampamp) && !BeforeRParen->isTypeName(LangOpts))) { return false; } // `foreach((A a, B b) in someList)` should not be seen as a cast. -if (Tok.Next->is(Keywords.kw_in) && Style.isCSharp()) +if (AfterRParen->is(Keywords.kw_in) && Style.isCSharp()) return false; // Functions which end with decorations like volatile, noexcept are unlikely // to be casts. -if (Tok.Next->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const, - tok::kw_requires, tok::kw_throw, tok::arrow, - Keywords.kw_override, Keywords.kw_final) || -isCppAttribute(IsCpp, *Tok.Next)) { +if (AfterRParen->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const, + tok::kw_requires, tok::kw_throw, tok::arrow, + Keywords.kw_override, Keywords.kw_final) || +isCppAttribute(IsCpp, *AfterRParen)) { return false; } // As Java has no function types, a "(" after the ")" likely means that this // is a cast. -if (Style.Language == FormatStyle::LK_Java && Tok.Next->is(tok::l_paren)) +if (Style.Language == FormatStyle::LK_Java && AfterRParen->is(tok::l_paren)) return true; // If a (non-string) literal follows, this is likely a cast. -if (Tok.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof) || -(Tok.Next->Tok.isLiteral() && Tok.Next->isNot(tok::string_literal))) { +if (AfterRParen->isOneOf(tok::kw_sizeof, tok::kw_alignof) || +(AfterRParen->Tok.isLiteral() && + AfterRParen->isNot(tok::string_literal))) { return true; } // Heuristically try to determine whether the parentheses contain a type. -auto IsQualifiedPointerOrReference = [](FormatToken *T, +auto IsQualifiedPointerOrReference = [](const FormatToken *T, const LangOptions ) { // This is used to handle cases such as x = (foo *const) assert(!T->isTypeName(LangOpts) && "Should have already been checked"); @@ -2791,12 +2801,11 @@ class AnnotatingParser { return T && T->is(TT_PointerOrReference); }; bool ParensAreType = -!Tok.Previous || -Tok.Previous->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) || -Tok.Previous->isTypeName(LangOpts) || -IsQualifiedPointerOrReference(Tok.Previous, LangOpts); +BeforeRParen->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) || +BeforeRParen->isTypeName(LangOpts) || +IsQualifiedPointerOrReference(BeforeRParen, LangOpts); bool ParensCouldEndDecl = -Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater); +AfterRParen->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater); if
[clang] [clang-format[NFC] Clean up AnnotatingParser::rParenEndsCast() (PR #96128)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/96128 None >From 04618d27f9ebd045dfae5bfc341056c483fab0d1 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Wed, 19 Jun 2024 18:07:56 -0700 Subject: [PATCH] [clang-format[NFC] Clean up AnnotatingParser::rParenEndsCast() --- clang/lib/Format/TokenAnnotator.cpp | 81 - 1 file changed, 46 insertions(+), 35 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 87e3e712d6993..67c8f7f5c8bdd 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2661,18 +2661,27 @@ class AnnotatingParser { /// Determine whether ')' is ending a cast. bool rParenEndsCast(const FormatToken ) { +assert(Tok.is(tok::r_paren)); + +if (!Tok.Previous || !Tok.MatchingParen) + return false; + // C-style casts are only used in C++, C# and Java. -if (!Style.isCSharp() && !IsCpp && Style.Language != FormatStyle::LK_Java) +if (!IsCpp && !Style.isCSharp() && Style.Language != FormatStyle::LK_Java) return false; +const auto *LParen = Tok.MatchingParen; +const auto *BeforeRParen = Tok.Previous; +const auto *AfterRParen = Tok.Next; + // Empty parens aren't casts and there are no casts at the end of the line. -if (Tok.Previous == Tok.MatchingParen || !Tok.Next || !Tok.MatchingParen) +if (BeforeRParen == LParen || !AfterRParen) return false; -if (Tok.MatchingParen->is(TT_OverloadedOperatorLParen)) +if (LParen->is(TT_OverloadedOperatorLParen)) return false; -FormatToken *LeftOfParens = Tok.MatchingParen->getPreviousNonComment(); +FormatToken *LeftOfParens = LParen->getPreviousNonComment(); if (LeftOfParens) { // If there is a closing parenthesis left of the current // parentheses, look past it as these might be chained casts. @@ -2728,37 +2737,38 @@ class AnnotatingParser { } } -if (Tok.Next->is(tok::question) || -(Tok.Next->is(tok::ampamp) && !Tok.Previous->isTypeName(LangOpts))) { +if (AfterRParen->is(tok::question) || +(AfterRParen->is(tok::ampamp) && !BeforeRParen->isTypeName(LangOpts))) { return false; } // `foreach((A a, B b) in someList)` should not be seen as a cast. -if (Tok.Next->is(Keywords.kw_in) && Style.isCSharp()) +if (AfterRParen->is(Keywords.kw_in) && Style.isCSharp()) return false; // Functions which end with decorations like volatile, noexcept are unlikely // to be casts. -if (Tok.Next->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const, - tok::kw_requires, tok::kw_throw, tok::arrow, - Keywords.kw_override, Keywords.kw_final) || -isCppAttribute(IsCpp, *Tok.Next)) { +if (AfterRParen->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const, + tok::kw_requires, tok::kw_throw, tok::arrow, + Keywords.kw_override, Keywords.kw_final) || +isCppAttribute(IsCpp, *AfterRParen)) { return false; } // As Java has no function types, a "(" after the ")" likely means that this // is a cast. -if (Style.Language == FormatStyle::LK_Java && Tok.Next->is(tok::l_paren)) +if (Style.Language == FormatStyle::LK_Java && AfterRParen->is(tok::l_paren)) return true; // If a (non-string) literal follows, this is likely a cast. -if (Tok.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof) || -(Tok.Next->Tok.isLiteral() && Tok.Next->isNot(tok::string_literal))) { +if (AfterRParen->isOneOf(tok::kw_sizeof, tok::kw_alignof) || +(AfterRParen->Tok.isLiteral() && + AfterRParen->isNot(tok::string_literal))) { return true; } // Heuristically try to determine whether the parentheses contain a type. -auto IsQualifiedPointerOrReference = [](FormatToken *T, +auto IsQualifiedPointerOrReference = [](const FormatToken *T, const LangOptions ) { // This is used to handle cases such as x = (foo *const) assert(!T->isTypeName(LangOpts) && "Should have already been checked"); @@ -2791,12 +2801,11 @@ class AnnotatingParser { return T && T->is(TT_PointerOrReference); }; bool ParensAreType = -!Tok.Previous || -Tok.Previous->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) || -Tok.Previous->isTypeName(LangOpts) || -IsQualifiedPointerOrReference(Tok.Previous, LangOpts); +BeforeRParen->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) || +BeforeRParen->isTypeName(LangOpts) || +IsQualifiedPointerOrReference(BeforeRParen, LangOpts); bool ParensCouldEndDecl = -Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater); +AfterRParen->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater);
[clang] [clang-format] Correctly annotate l_brace after TypenameMacro (PR #96026)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/96026 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Correctly annotate l_brace after TypenameMacro (PR #96026)
@@ -3180,6 +3180,18 @@ TEST_F(TokenAnnotatorTest, FunctionTryBlock) { EXPECT_TOKEN(Tokens[36], tok::l_brace, TT_FunctionLBrace); } +TEST_F(TokenAnnotatorTest, TypenameMacro) { + auto Style = getLLVMStyle(); + Style.TypenameMacros.push_back("STRUCT"); + + auto Tokens = annotate("STRUCT(T, B) { int i; };", Style); + ASSERT_EQ(Tokens.size(), 13u); + EXPECT_TOKEN(Tokens[0], tok::identifier, TT_TypenameMacro); + EXPECT_TOKEN(Tokens[1], tok::l_paren, TT_TypeDeclarationParen); + EXPECT_TOKEN(Tokens[5], tok::r_paren, TT_TypeDeclarationParen); + EXPECT_TOKEN(Tokens[6], tok::l_brace, TT_Unknown); owenca wrote: > Is `TT_Unknown` the correct type? Yes. We use it to verify that a token is not annotated (incorrectly). > I know we can't really say if it's a `TT_StructLBrace` or `TT_ClassLBrace` > (or even `TT_UnionLBrace`), but would it harm to just guess one of them? Or `TT_EnumLBrace` or anyone in [here](https://github.com/llvm/llvm-project/pull/93634#issuecomment-2156968344). We shouldn’t make a wild guess because the type of the braces depends on how the macro is defined (and on what’s between the braces). https://github.com/llvm/llvm-project/pull/96026 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Correctly annotate l_brace after TypenameMacro (PR #96026)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/96026 Closes #95418. >From cc4cd4d9e7eea3ba670a29a053d18739b40058ab Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Tue, 18 Jun 2024 22:29:53 -0700 Subject: [PATCH] [clang-format] Correctly annotate l_brace after TypenameMacro Closes #95418. --- clang/lib/Format/UnwrappedLineParser.cpp | 12 +--- clang/unittests/Format/FormatTest.cpp | 3 +++ clang/unittests/Format/TokenAnnotatorTest.cpp | 12 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index ce877ac2bb9ef..d406a531a5c0c 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -1910,7 +1910,8 @@ void UnwrappedLineParser::parseStructuralElement( } else if (Style.BraceWrapping.AfterFunction) { addUnwrappedLine(); } -FormatTok->setFinalizedType(TT_FunctionLBrace); +if (!Previous || Previous->isNot(TT_TypeDeclarationParen)) + FormatTok->setFinalizedType(TT_FunctionLBrace); parseBlock(); IsDecltypeAutoFunction = false; addUnwrappedLine(); @@ -2545,10 +2546,10 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::l_brace)) parseChildBlock(); break; -case tok::r_paren: +case tok::r_paren: { + const auto *Prev = LeftParen->Previous; if (!MightBeStmtExpr && !MightBeFoldExpr && !Line->InMacroBody && Style.RemoveParentheses > FormatStyle::RPS_Leave) { -const auto *Prev = LeftParen->Previous; const auto *Next = Tokens->peekNextToken(); const bool DoubleParens = Prev && Prev->is(tok::l_paren) && Next && Next->is(tok::r_paren); @@ -2570,8 +2571,13 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { FormatTok->Optional = true; } } + if (Prev && Prev->is(TT_TypenameMacro)) { +LeftParen->setFinalizedType(TT_TypeDeclarationParen); +FormatTok->setFinalizedType(TT_TypeDeclarationParen); + } nextToken(); return SeenEqual; +} case tok::r_brace: // A "}" inside parenthesis is an error if there wasn't a matching "{". return SeenEqual; diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index fc63afce70042..db1decb20d626 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -27007,6 +27007,9 @@ TEST_F(FormatTest, RemoveSemicolon) { "; int bar;", Style); #endif + + Style.TypenameMacros.push_back("STRUCT"); + verifyFormat("STRUCT(T, B) { int i; };", Style); } TEST_F(FormatTest, BreakAfterAttributes) { diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 3735316dc3478..0dc506458f7c3 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -3180,6 +3180,18 @@ TEST_F(TokenAnnotatorTest, FunctionTryBlock) { EXPECT_TOKEN(Tokens[36], tok::l_brace, TT_FunctionLBrace); } +TEST_F(TokenAnnotatorTest, TypenameMacro) { + auto Style = getLLVMStyle(); + Style.TypenameMacros.push_back("STRUCT"); + + auto Tokens = annotate("STRUCT(T, B) { int i; };", Style); + ASSERT_EQ(Tokens.size(), 13u); + EXPECT_TOKEN(Tokens[0], tok::identifier, TT_TypenameMacro); + EXPECT_TOKEN(Tokens[1], tok::l_paren, TT_TypeDeclarationParen); + EXPECT_TOKEN(Tokens[5], tok::r_paren, TT_TypeDeclarationParen); + EXPECT_TOKEN(Tokens[6], tok::l_brace, TT_Unknown); +} + } // namespace } // namespace format } // namespace clang ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Handle function try block with ctor-initializer (PR #95878)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/95878 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Handle function try block with ctor-initializer (PR #95878)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/95878 >From 299924c9f9485e7a784ffedcb6ec4fbccf5ad6f7 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Mon, 17 Jun 2024 21:13:10 -0700 Subject: [PATCH 1/2] [clang-format] Handle function try block with ctor-initializer Fixes #58987. Fixes #95679. --- clang/lib/Format/UnwrappedLineParser.cpp | 17 +++-- clang/unittests/Format/TokenAnnotatorTest.cpp | 15 +++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index df5bb757a99ec..ce877ac2bb9ef 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -2955,9 +2955,15 @@ void UnwrappedLineParser::parseTryCatch() { assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) && "'try' expected"); nextToken(); bool NeedsUnwrappedLine = false; + bool HasCtorInitializer = false; if (FormatTok->is(tok::colon)) { +auto *Colon = FormatTok; // We are in a function try block, what comes is an initializer list. nextToken(); +if (FormatTok->is(tok::identifier)) { + HasCtorInitializer = true; + Colon->setFinalizedType(TT_CtorInitializerColon); +} // In case identifiers were removed by clang-tidy, what might follow is // multiple commas in sequence - before the first identifier. @@ -2966,14 +2972,11 @@ void UnwrappedLineParser::parseTryCatch() { while (FormatTok->is(tok::identifier)) { nextToken(); - if (FormatTok->is(tok::l_paren)) + if (FormatTok->is(tok::l_paren)) { parseParens(); - if (FormatTok->Previous && FormatTok->Previous->is(tok::identifier) && - FormatTok->is(tok::l_brace)) { -do { - nextToken(); -} while (FormatTok->isNot(tok::r_brace)); + } else if (FormatTok->is(tok::l_brace)) { nextToken(); +parseBracedList(); } // In case identifiers were removed by clang-tidy, what might follow is @@ -2989,6 +2992,8 @@ void UnwrappedLineParser::parseTryCatch() { keepAncestorBraces(); if (FormatTok->is(tok::l_brace)) { +if (HasCtorInitializer) + FormatTok->setFinalizedType(TT_FunctionLBrace); CompoundStatementIndenter Indenter(this, Style, Line->Level); parseBlock(); if (Style.BraceWrapping.BeforeCatch) diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 3e9638d9f3c56..487582ee4e10d 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -3164,6 +3164,21 @@ TEST_F(TokenAnnotatorTest, CppAltOperatorKeywords) { EXPECT_TOKEN(Tokens[1], tok::identifier, TT_StartOfName); } +TEST_F(TokenAnnotatorTest, FunctionTryBlock) { + auto Tokens = + annotate("Ctor::Ctor(int x, int y) try\n" + ": foo{[]() -> std::string { return {}; }(), x}, bar{y} {\n" + "} catch (...) {\n" + "}"); + ASSERT_EQ(Tokens.size(), 47u); + EXPECT_TOKEN(Tokens[11], tok::colon, TT_CtorInitializerColon); + EXPECT_TOKEN(Tokens[14], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[18], tok::arrow, TT_TrailingReturnArrow); + EXPECT_TOKEN(Tokens[22], tok::l_brace, TT_LambdaLBrace); + EXPECT_TOKEN(Tokens[33], tok::comma, TT_CtorInitializerComma); + EXPECT_TOKEN(Tokens[38], tok::l_brace, TT_FunctionLBrace); +} + } // namespace } // namespace format } // namespace clang >From 733592d7cebd0b54ad9b08b506ab971f4549d7f0 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Tue, 18 Jun 2024 17:53:51 -0700 Subject: [PATCH 2/2] Tweak the test case. --- clang/unittests/Format/TokenAnnotatorTest.cpp | 15 --- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 487582ee4e10d..3735316dc3478 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -3166,17 +3166,18 @@ TEST_F(TokenAnnotatorTest, CppAltOperatorKeywords) { TEST_F(TokenAnnotatorTest, FunctionTryBlock) { auto Tokens = - annotate("Ctor::Ctor(int x, int y) try\n" - ": foo{[]() -> std::string { return {}; }(), x}, bar{y} {\n" + annotate("Foo::Foo(int x, int y) try\n" + ": foo{[] -> std::string { return {}; }(), x}, bar{y} {\n" "} catch (...) {\n" "}"); - ASSERT_EQ(Tokens.size(), 47u); + ASSERT_EQ(Tokens.size(), 45u); + EXPECT_TOKEN(Tokens[2], tok::identifier, TT_CtorDtorDeclName); EXPECT_TOKEN(Tokens[11], tok::colon, TT_CtorInitializerColon); EXPECT_TOKEN(Tokens[14], tok::l_square, TT_LambdaLSquare); - EXPECT_TOKEN(Tokens[18], tok::arrow, TT_TrailingReturnArrow); - EXPECT_TOKEN(Tokens[22], tok::l_brace, TT_LambdaLBrace); - EXPECT_TOKEN(Tokens[33], tok::comma,
[clang] [clang-format] Add option to remove leading blank lines (PR #91221)
@@ -45,6 +45,9 @@ TEST_F(FormatTest, FormatsGlobalStatementsAt0) { verifyFormat("\nint i;", " \n\t \v \f int i;"); verifyFormat("int i;\nint j;", "int i; int j;"); verifyFormat("int i;\nint j;", "int i;\n int j;"); + auto Style = getLLVMStyle(); owenca wrote: An empty line before `auto Style = ...`? https://github.com/llvm/llvm-project/pull/91221 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add option to remove leading blank lines (PR #91221)
@@ -21947,6 +21950,10 @@ TEST_F(FormatTest, HandlesUTF8BOM) { verifyFormat("\xef\xbb\xbf"); verifyFormat("\xef\xbb\xbf#include "); verifyFormat("\xef\xbb\xbf\n#include "); + auto Style = getLLVMStyle(); owenca wrote: Ditto. https://github.com/llvm/llvm-project/pull/91221 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add option to remove leading blank lines (PR #91221)
https://github.com/owenca edited https://github.com/llvm/llvm-project/pull/91221 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add option to remove leading blank lines (PR #91221)
https://github.com/owenca approved this pull request. https://github.com/llvm/llvm-project/pull/91221 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Handle function try block with ctor-initializer (PR #95878)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/95878 Fixes #58987. Fixes #95679. >From 299924c9f9485e7a784ffedcb6ec4fbccf5ad6f7 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Mon, 17 Jun 2024 21:13:10 -0700 Subject: [PATCH] [clang-format] Handle function try block with ctor-initializer Fixes #58987. Fixes #95679. --- clang/lib/Format/UnwrappedLineParser.cpp | 17 +++-- clang/unittests/Format/TokenAnnotatorTest.cpp | 15 +++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index df5bb757a99ec..ce877ac2bb9ef 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -2955,9 +2955,15 @@ void UnwrappedLineParser::parseTryCatch() { assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) && "'try' expected"); nextToken(); bool NeedsUnwrappedLine = false; + bool HasCtorInitializer = false; if (FormatTok->is(tok::colon)) { +auto *Colon = FormatTok; // We are in a function try block, what comes is an initializer list. nextToken(); +if (FormatTok->is(tok::identifier)) { + HasCtorInitializer = true; + Colon->setFinalizedType(TT_CtorInitializerColon); +} // In case identifiers were removed by clang-tidy, what might follow is // multiple commas in sequence - before the first identifier. @@ -2966,14 +2972,11 @@ void UnwrappedLineParser::parseTryCatch() { while (FormatTok->is(tok::identifier)) { nextToken(); - if (FormatTok->is(tok::l_paren)) + if (FormatTok->is(tok::l_paren)) { parseParens(); - if (FormatTok->Previous && FormatTok->Previous->is(tok::identifier) && - FormatTok->is(tok::l_brace)) { -do { - nextToken(); -} while (FormatTok->isNot(tok::r_brace)); + } else if (FormatTok->is(tok::l_brace)) { nextToken(); +parseBracedList(); } // In case identifiers were removed by clang-tidy, what might follow is @@ -2989,6 +2992,8 @@ void UnwrappedLineParser::parseTryCatch() { keepAncestorBraces(); if (FormatTok->is(tok::l_brace)) { +if (HasCtorInitializer) + FormatTok->setFinalizedType(TT_FunctionLBrace); CompoundStatementIndenter Indenter(this, Style, Line->Level); parseBlock(); if (Style.BraceWrapping.BeforeCatch) diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 3e9638d9f3c56..487582ee4e10d 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -3164,6 +3164,21 @@ TEST_F(TokenAnnotatorTest, CppAltOperatorKeywords) { EXPECT_TOKEN(Tokens[1], tok::identifier, TT_StartOfName); } +TEST_F(TokenAnnotatorTest, FunctionTryBlock) { + auto Tokens = + annotate("Ctor::Ctor(int x, int y) try\n" + ": foo{[]() -> std::string { return {}; }(), x}, bar{y} {\n" + "} catch (...) {\n" + "}"); + ASSERT_EQ(Tokens.size(), 47u); + EXPECT_TOKEN(Tokens[11], tok::colon, TT_CtorInitializerColon); + EXPECT_TOKEN(Tokens[14], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[18], tok::arrow, TT_TrailingReturnArrow); + EXPECT_TOKEN(Tokens[22], tok::l_brace, TT_LambdaLBrace); + EXPECT_TOKEN(Tokens[33], tok::comma, TT_CtorInitializerComma); + EXPECT_TOKEN(Tokens[38], tok::l_brace, TT_FunctionLBrace); +} + } // namespace } // namespace format } // namespace clang ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format][NFC] Add CMake target clang-format-check-format (PR #95873)
https://github.com/owenca edited https://github.com/llvm/llvm-project/pull/95873 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format][NFC] Add CMake target clang-format-check-format (PR #95873)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/95873 Adpated from polly-check-format. >From ab2a61d1939f4be4551949e979fd43b9e11c5c49 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Mon, 17 Jun 2024 18:49:22 -0700 Subject: [PATCH] [clang-format][NFC] Add CMake target clang-format-check-format Adpated from polly-check-format. --- clang/lib/Format/CMakeLists.txt | 24 1 file changed, 24 insertions(+) diff --git a/clang/lib/Format/CMakeLists.txt b/clang/lib/Format/CMakeLists.txt index 84a3c136f650a..b787b11ac7b74 100644 --- a/clang/lib/Format/CMakeLists.txt +++ b/clang/lib/Format/CMakeLists.txt @@ -29,3 +29,27 @@ add_clang_library(clangFormat clangToolingCore clangToolingInclusions ) + +file(GLOB_RECURSE files + *.cpp + *.h + ../../include/clang/Format/*.h + ../../tools/clang-format/*.cpp + ../../unittests/Format/*.cpp + ../../unittests/Format/*.h + ) + +set(check_format_depends) +set(i 0) +foreach (file IN LISTS files) + add_custom_command(OUTPUT clang-format-check-format${i} +COMMAND clang-format ${file} | diff -u ${file} - +VERBATIM +COMMENT "Checking format of ${file}..." + ) + list(APPEND check_format_depends "clang-format-check-format${i}") + + math(EXPR i ${i}+1) +endforeach () + +add_custom_target(clang-format-check-format DEPENDS ${check_format_depends}) ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format][NFC] Add FormatToken::isAccessSpecifierKeyword() (PR #95727)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/95727 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format][NFC] Add FormatToken::isAccessSpecifierKeyword() (PR #95727)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/95727 None >From ec9b902518ef09d77e8b32777032a852d33476fd Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Sun, 16 Jun 2024 17:47:56 -0700 Subject: [PATCH] [clang-format][NFC] Add FormatToken::isAccessSpecifierKeyword() --- clang/lib/Format/FormatToken.h | 20 ++- clang/lib/Format/TokenAnnotator.cpp | 44 +++- clang/lib/Format/UnwrappedLineParser.cpp | 23 ++--- 3 files changed, 43 insertions(+), 44 deletions(-) diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index e4a4f27e502b1..4ffd745bf9307 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -667,12 +667,16 @@ struct FormatToken { return Tok.isObjCAtKeyword(Kind); } + bool isAccessSpecifierKeyword() const { +return isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private); + } + bool isAccessSpecifier(bool ColonRequired = true) const { -if (!isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private)) +if (!isAccessSpecifierKeyword()) return false; if (!ColonRequired) return true; -const auto NextNonComment = getNextNonComment(); +const auto *NextNonComment = getNextNonComment(); return NextNonComment && NextNonComment->is(tok::colon); } @@ -1656,10 +1660,12 @@ struct AdditionalKeywords { /// If \c AcceptIdentifierName is true, returns true not only for keywords, // but also for IdentifierName tokens (aka pseudo-keywords), such as // ``yield``. - bool IsJavaScriptIdentifier(const FormatToken , + bool isJavaScriptIdentifier(const FormatToken , bool AcceptIdentifierName = true) const { // Based on the list of JavaScript & TypeScript keywords here: // https://github.com/microsoft/TypeScript/blob/main/src/compiler/scanner.ts#L74 +if (Tok.isAccessSpecifierKeyword()) + return false; switch (Tok.Tok.getKind()) { case tok::kw_break: case tok::kw_case: @@ -1679,9 +1685,6 @@ struct AdditionalKeywords { case tok::kw_import: case tok::kw_module: case tok::kw_new: -case tok::kw_private: -case tok::kw_protected: -case tok::kw_public: case tok::kw_return: case tok::kw_static: case tok::kw_switch: @@ -1724,6 +1727,8 @@ struct AdditionalKeywords { /// Returns \c true if \p Tok is a C# keyword, returns /// \c false if it is a anything else. bool isCSharpKeyword(const FormatToken ) const { +if (Tok.isAccessSpecifierKeyword()) + return true; switch (Tok.Tok.getKind()) { case tok::kw_bool: case tok::kw_break: @@ -1750,9 +1755,6 @@ struct AdditionalKeywords { case tok::kw_namespace: case tok::kw_new: case tok::kw_operator: -case tok::kw_private: -case tok::kw_protected: -case tok::kw_public: case tok::kw_return: case tok::kw_short: case tok::kw_sizeof: diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 1332445070314..5a256fc7ebd9f 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -647,8 +647,8 @@ class AnnotatingParser { return true; // Limit this to being an access modifier that follows. -if (AttrTok->isOneOf(tok::kw_public, tok::kw_private, tok::kw_protected, - tok::comment, tok::kw_class, tok::kw_static, +if (AttrTok->isAccessSpecifierKeyword() || +AttrTok->isOneOf(tok::comment, tok::kw_class, tok::kw_static, tok::l_square, Keywords.kw_internal)) { return true; } @@ -1419,7 +1419,7 @@ class AnnotatingParser { Tok->setType(TT_CtorInitializerColon); } else { Tok->setType(TT_InheritanceColon); - if (Prev->isOneOf(tok::kw_public, tok::kw_private, tok::kw_protected)) + if (Prev->isAccessSpecifierKeyword()) Line.Type = LT_AccessModifier; } } else if (canBeObjCSelectorComponent(*Tok->Previous) && Tok->Next && @@ -2333,7 +2333,7 @@ class AnnotatingParser { if (Current.Previous) { bool IsIdentifier = Style.isJavaScript() -? Keywords.IsJavaScriptIdentifier( +? Keywords.isJavaScriptIdentifier( *Current.Previous, /* AcceptIdentifierName= */ true) : Current.Previous->is(tok::identifier); if (IsIdentifier || @@ -4948,11 +4948,11 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine , // space between method modifier and opening parenthesis of a tuple return // type -if (Left.isOneOf(tok::kw_public, tok::kw_private, tok::kw_protected, - tok::kw_virtual, tok::kw_extern, tok::kw_static, - Keywords.kw_internal, Keywords.kw_abstract, - Keywords.kw_sealed, Keywords.kw_override, -
[clang] 527e732 - [clang-format][NFC] Suppress diagnostic noise in GetStyleOfFile test
Author: Owen Pan Date: 2024-06-16T14:56:02-07:00 New Revision: 527e7328607ea0a55855e53a59c5030a7d07a554 URL: https://github.com/llvm/llvm-project/commit/527e7328607ea0a55855e53a59c5030a7d07a554 DIFF: https://github.com/llvm/llvm-project/commit/527e7328607ea0a55855e53a59c5030a7d07a554.diff LOG: [clang-format][NFC] Suppress diagnostic noise in GetStyleOfFile test Added: Modified: clang/unittests/Format/ConfigParseTest.cpp Removed: diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 2513ab3939595..aded3ed2a6596 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -15,6 +15,7 @@ namespace clang { namespace format { namespace { +void dropDiagnosticHandler(const llvm::SMDiagnostic &, void *) {} FormatStyle getGoogleStyle() { return getGoogleStyle(FormatStyle::LK_Cpp); } #define EXPECT_ALL_STYLES_EQUAL(Styles) \ @@ -1240,7 +1241,8 @@ TEST(ConfigParseTest, GetStyleOfFile) { llvm::consumeError(Style4.takeError()); // Test 5: error on invalid yaml on command line - auto Style5 = getStyle("{invalid_key=invalid_value}", "a.h", "LLVM", "", ); + auto Style5 = getStyle("{invalid_key=invalid_value}", "a.h", "LLVM", "", , + /*AllowUnknownOptions=*/false, dropDiagnosticHandler); ASSERT_FALSE((bool)Style5); llvm::consumeError(Style5.takeError()); @@ -1256,11 +1258,13 @@ TEST(ConfigParseTest, GetStyleOfFile) { "InvalidKey: InvalidValue"))); ASSERT_TRUE( FS.addFile("/d/test.cpp", 0, llvm::MemoryBuffer::getMemBuffer("int i;"))); - auto Style7a = getStyle("file", "/d/.clang-format", "LLVM", "", ); + auto Style7a = getStyle("file", "/d/.clang-format", "LLVM", "", , + /*AllowUnknownOptions=*/false, dropDiagnosticHandler); ASSERT_FALSE((bool)Style7a); llvm::consumeError(Style7a.takeError()); - auto Style7b = getStyle("file", "/d/.clang-format", "LLVM", "", , true); + auto Style7b = getStyle("file", "/d/.clang-format", "LLVM", "", , + /*AllowUnknownOptions=*/true, dropDiagnosticHandler); ASSERT_TRUE((bool)Style7b); // Test 8: inferred per-language defaults apply. @@ -1466,8 +1470,7 @@ TEST(ConfigParseTest, GetStyleOutput) { // Suppress stderr. testing::internal::CaptureStderr(); Style = getStyle("{invalid_key=invalid_value}", "a.h", "LLVM", "", , - /*AllowUnknownOptions=*/true, - [](const llvm::SMDiagnostic &, void *) {}); + /*AllowUnknownOptions=*/true, dropDiagnosticHandler); Output = testing::internal::GetCapturedStderr(); ASSERT_TRUE((bool)Style); ASSERT_TRUE(Output.empty()); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add DiagHandler parameter to format::getStyle() (PR #91317)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/91317 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Handle AttributeMacro before access modifiers (PR #95634)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/95634 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Handle Verilog delay control (PR #95703)
https://github.com/owenca approved this pull request. https://github.com/llvm/llvm-project/pull/95703 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Handle AttributeMacro before access modifiers (PR #95503)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/95503 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Handle AttributeMacro before access modifiers (PR #95634)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/95634 >From 1c4ab4a5fd869de44795abd48bbaa43176e7275e Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Fri, 14 Jun 2024 23:36:58 -0700 Subject: [PATCH 1/5] [clang-format] Handle AttributeMacro before access modifiers Closes #95094. --- clang/lib/Format/TokenAnnotator.cpp | 7 - clang/lib/Format/TokenAnnotator.h | 1 + clang/lib/Format/UnwrappedLineFormatter.cpp | 35 ++--- clang/unittests/Format/FormatTest.cpp | 15 + 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 1fe3b61a5a81f..ff00e772a75f4 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1970,6 +1970,7 @@ class AnnotatingParser { } } +bool SeenAccessModifier = false; bool KeywordVirtualFound = false; bool ImportStatement = false; @@ -1978,7 +1979,9 @@ class AnnotatingParser { ImportStatement = true; while (CurrentToken) { - if (CurrentToken->is(tok::kw_virtual)) + if (CurrentToken->isAccessSpecifier()) +SeenAccessModifier = true; + else if (CurrentToken->is(tok::kw_virtual)) KeywordVirtualFound = true; if (Style.isJavaScript()) { // export {...} from '...'; @@ -1998,6 +2001,8 @@ class AnnotatingParser { if (!consumeToken()) return LT_Invalid; } +if (SeenAccessModifier) + return LT_AccessModifier; if (KeywordVirtualFound) return LT_VirtualFunctionDecl; if (ImportStatement) diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index d19d3d061e40c..136880eca718b 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -22,6 +22,7 @@ namespace format { enum LineType { LT_Invalid, + LT_AccessModifier, // Contains public/protected/private followed by colon. LT_ImportStatement, LT_ObjCDecl, // An @interface, @implementation, or @protocol line. LT_ObjCMethodDecl, diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 4d53361aaf333..729f3d78f4a35 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -57,7 +57,7 @@ class LevelIndentTracker { /// Update the indent state given that \p Line is going to be formatted /// next. void nextLine(const AnnotatedLine ) { -Offset = getIndentOffset(*Line.First); +Offset = getIndentOffset(Line); // Update the indent level cache size so that we can rely on it // having the right size in adjustToUnmodifiedline. if (Line.Level >= IndentForLevel.size()) @@ -111,42 +111,41 @@ class LevelIndentTracker { /// /// For example, 'public:' labels in classes are offset by 1 or 2 /// characters to the left from their level. - int getIndentOffset(const FormatToken ) { + int getIndentOffset(const AnnotatedLine ) { if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() || Style.isCSharp()) { return 0; } -auto IsAccessModifier = [this, ]() { - if (RootToken.isAccessSpecifier(Style.isCpp())) { +auto IsAccessModifier = [&](const FormatToken ) { + if (Line.Type == LT_AccessModifier || RootToken.isObjCAccessSpecifier()) return true; - } else if (RootToken.isObjCAccessSpecifier()) { -return true; - } + + const auto *Next = RootToken.Next; + // Handle Qt signals. - else if (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) && - RootToken.Next && RootToken.Next->is(tok::colon)) { -return true; - } else if (RootToken.Next && - RootToken.Next->isOneOf(Keywords.kw_slots, - Keywords.kw_qslots) && - RootToken.Next->Next && RootToken.Next->Next->is(tok::colon)) { + if (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) && + Next && Next->is(tok::colon)) { return true; } - // Handle malformed access specifier e.g. 'private' without trailing ':'. - else if (!RootToken.Next && RootToken.isAccessSpecifier(false)) { + + if (Next && Next->isOneOf(Keywords.kw_slots, Keywords.kw_qslots) && + Next->Next && Next->Next->is(tok::colon)) { return true; } - return false; + + // Handle malformed access specifier e.g. 'private' without trailing ':'. + return !Next && RootToken.isAccessSpecifier(false); }; -if (IsAccessModifier()) { +if (IsAccessModifier(*Line.First)) { // The AccessModifierOffset may be overridden by IndentAccessModifiers, // in which case we take a negative value of the IndentWidth to simulate // the upper indent level. return Style.IndentAccessModifiers ?
[clang] [clang-format] Handle AttributeMacro before access modifiers (PR #95634)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/95634 >From 1c4ab4a5fd869de44795abd48bbaa43176e7275e Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Fri, 14 Jun 2024 23:36:58 -0700 Subject: [PATCH 1/4] [clang-format] Handle AttributeMacro before access modifiers Closes #95094. --- clang/lib/Format/TokenAnnotator.cpp | 7 - clang/lib/Format/TokenAnnotator.h | 1 + clang/lib/Format/UnwrappedLineFormatter.cpp | 35 ++--- clang/unittests/Format/FormatTest.cpp | 15 + 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 1fe3b61a5a81f..ff00e772a75f4 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1970,6 +1970,7 @@ class AnnotatingParser { } } +bool SeenAccessModifier = false; bool KeywordVirtualFound = false; bool ImportStatement = false; @@ -1978,7 +1979,9 @@ class AnnotatingParser { ImportStatement = true; while (CurrentToken) { - if (CurrentToken->is(tok::kw_virtual)) + if (CurrentToken->isAccessSpecifier()) +SeenAccessModifier = true; + else if (CurrentToken->is(tok::kw_virtual)) KeywordVirtualFound = true; if (Style.isJavaScript()) { // export {...} from '...'; @@ -1998,6 +2001,8 @@ class AnnotatingParser { if (!consumeToken()) return LT_Invalid; } +if (SeenAccessModifier) + return LT_AccessModifier; if (KeywordVirtualFound) return LT_VirtualFunctionDecl; if (ImportStatement) diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index d19d3d061e40c..136880eca718b 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -22,6 +22,7 @@ namespace format { enum LineType { LT_Invalid, + LT_AccessModifier, // Contains public/protected/private followed by colon. LT_ImportStatement, LT_ObjCDecl, // An @interface, @implementation, or @protocol line. LT_ObjCMethodDecl, diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 4d53361aaf333..729f3d78f4a35 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -57,7 +57,7 @@ class LevelIndentTracker { /// Update the indent state given that \p Line is going to be formatted /// next. void nextLine(const AnnotatedLine ) { -Offset = getIndentOffset(*Line.First); +Offset = getIndentOffset(Line); // Update the indent level cache size so that we can rely on it // having the right size in adjustToUnmodifiedline. if (Line.Level >= IndentForLevel.size()) @@ -111,42 +111,41 @@ class LevelIndentTracker { /// /// For example, 'public:' labels in classes are offset by 1 or 2 /// characters to the left from their level. - int getIndentOffset(const FormatToken ) { + int getIndentOffset(const AnnotatedLine ) { if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() || Style.isCSharp()) { return 0; } -auto IsAccessModifier = [this, ]() { - if (RootToken.isAccessSpecifier(Style.isCpp())) { +auto IsAccessModifier = [&](const FormatToken ) { + if (Line.Type == LT_AccessModifier || RootToken.isObjCAccessSpecifier()) return true; - } else if (RootToken.isObjCAccessSpecifier()) { -return true; - } + + const auto *Next = RootToken.Next; + // Handle Qt signals. - else if (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) && - RootToken.Next && RootToken.Next->is(tok::colon)) { -return true; - } else if (RootToken.Next && - RootToken.Next->isOneOf(Keywords.kw_slots, - Keywords.kw_qslots) && - RootToken.Next->Next && RootToken.Next->Next->is(tok::colon)) { + if (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) && + Next && Next->is(tok::colon)) { return true; } - // Handle malformed access specifier e.g. 'private' without trailing ':'. - else if (!RootToken.Next && RootToken.isAccessSpecifier(false)) { + + if (Next && Next->isOneOf(Keywords.kw_slots, Keywords.kw_qslots) && + Next->Next && Next->Next->is(tok::colon)) { return true; } - return false; + + // Handle malformed access specifier e.g. 'private' without trailing ':'. + return !Next && RootToken.isAccessSpecifier(false); }; -if (IsAccessModifier()) { +if (IsAccessModifier(*Line.First)) { // The AccessModifierOffset may be overridden by IndentAccessModifiers, // in which case we take a negative value of the IndentWidth to simulate // the upper indent level. return Style.IndentAccessModifiers ?
[clang] [clang-format] Handle AttributeMacro before access modifiers (PR #95634)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/95634 >From 1c4ab4a5fd869de44795abd48bbaa43176e7275e Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Fri, 14 Jun 2024 23:36:58 -0700 Subject: [PATCH 1/3] [clang-format] Handle AttributeMacro before access modifiers Closes #95094. --- clang/lib/Format/TokenAnnotator.cpp | 7 - clang/lib/Format/TokenAnnotator.h | 1 + clang/lib/Format/UnwrappedLineFormatter.cpp | 35 ++--- clang/unittests/Format/FormatTest.cpp | 15 + 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 1fe3b61a5a81f..ff00e772a75f4 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1970,6 +1970,7 @@ class AnnotatingParser { } } +bool SeenAccessModifier = false; bool KeywordVirtualFound = false; bool ImportStatement = false; @@ -1978,7 +1979,9 @@ class AnnotatingParser { ImportStatement = true; while (CurrentToken) { - if (CurrentToken->is(tok::kw_virtual)) + if (CurrentToken->isAccessSpecifier()) +SeenAccessModifier = true; + else if (CurrentToken->is(tok::kw_virtual)) KeywordVirtualFound = true; if (Style.isJavaScript()) { // export {...} from '...'; @@ -1998,6 +2001,8 @@ class AnnotatingParser { if (!consumeToken()) return LT_Invalid; } +if (SeenAccessModifier) + return LT_AccessModifier; if (KeywordVirtualFound) return LT_VirtualFunctionDecl; if (ImportStatement) diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index d19d3d061e40c..136880eca718b 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -22,6 +22,7 @@ namespace format { enum LineType { LT_Invalid, + LT_AccessModifier, // Contains public/protected/private followed by colon. LT_ImportStatement, LT_ObjCDecl, // An @interface, @implementation, or @protocol line. LT_ObjCMethodDecl, diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 4d53361aaf333..729f3d78f4a35 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -57,7 +57,7 @@ class LevelIndentTracker { /// Update the indent state given that \p Line is going to be formatted /// next. void nextLine(const AnnotatedLine ) { -Offset = getIndentOffset(*Line.First); +Offset = getIndentOffset(Line); // Update the indent level cache size so that we can rely on it // having the right size in adjustToUnmodifiedline. if (Line.Level >= IndentForLevel.size()) @@ -111,42 +111,41 @@ class LevelIndentTracker { /// /// For example, 'public:' labels in classes are offset by 1 or 2 /// characters to the left from their level. - int getIndentOffset(const FormatToken ) { + int getIndentOffset(const AnnotatedLine ) { if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() || Style.isCSharp()) { return 0; } -auto IsAccessModifier = [this, ]() { - if (RootToken.isAccessSpecifier(Style.isCpp())) { +auto IsAccessModifier = [&](const FormatToken ) { + if (Line.Type == LT_AccessModifier || RootToken.isObjCAccessSpecifier()) return true; - } else if (RootToken.isObjCAccessSpecifier()) { -return true; - } + + const auto *Next = RootToken.Next; + // Handle Qt signals. - else if (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) && - RootToken.Next && RootToken.Next->is(tok::colon)) { -return true; - } else if (RootToken.Next && - RootToken.Next->isOneOf(Keywords.kw_slots, - Keywords.kw_qslots) && - RootToken.Next->Next && RootToken.Next->Next->is(tok::colon)) { + if (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) && + Next && Next->is(tok::colon)) { return true; } - // Handle malformed access specifier e.g. 'private' without trailing ':'. - else if (!RootToken.Next && RootToken.isAccessSpecifier(false)) { + + if (Next && Next->isOneOf(Keywords.kw_slots, Keywords.kw_qslots) && + Next->Next && Next->Next->is(tok::colon)) { return true; } - return false; + + // Handle malformed access specifier e.g. 'private' without trailing ':'. + return !Next && RootToken.isAccessSpecifier(false); }; -if (IsAccessModifier()) { +if (IsAccessModifier(*Line.First)) { // The AccessModifierOffset may be overridden by IndentAccessModifiers, // in which case we take a negative value of the IndentWidth to simulate // the upper indent level. return Style.IndentAccessModifiers ?
[clang] [clang-format] Handle AttributeMacro before access modifiers (PR #95634)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/95634 >From 1c4ab4a5fd869de44795abd48bbaa43176e7275e Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Fri, 14 Jun 2024 23:36:58 -0700 Subject: [PATCH 1/2] [clang-format] Handle AttributeMacro before access modifiers Closes #95094. --- clang/lib/Format/TokenAnnotator.cpp | 7 - clang/lib/Format/TokenAnnotator.h | 1 + clang/lib/Format/UnwrappedLineFormatter.cpp | 35 ++--- clang/unittests/Format/FormatTest.cpp | 15 + 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 1fe3b61a5a81f..ff00e772a75f4 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1970,6 +1970,7 @@ class AnnotatingParser { } } +bool SeenAccessModifier = false; bool KeywordVirtualFound = false; bool ImportStatement = false; @@ -1978,7 +1979,9 @@ class AnnotatingParser { ImportStatement = true; while (CurrentToken) { - if (CurrentToken->is(tok::kw_virtual)) + if (CurrentToken->isAccessSpecifier()) +SeenAccessModifier = true; + else if (CurrentToken->is(tok::kw_virtual)) KeywordVirtualFound = true; if (Style.isJavaScript()) { // export {...} from '...'; @@ -1998,6 +2001,8 @@ class AnnotatingParser { if (!consumeToken()) return LT_Invalid; } +if (SeenAccessModifier) + return LT_AccessModifier; if (KeywordVirtualFound) return LT_VirtualFunctionDecl; if (ImportStatement) diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index d19d3d061e40c..136880eca718b 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -22,6 +22,7 @@ namespace format { enum LineType { LT_Invalid, + LT_AccessModifier, // Contains public/protected/private followed by colon. LT_ImportStatement, LT_ObjCDecl, // An @interface, @implementation, or @protocol line. LT_ObjCMethodDecl, diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 4d53361aaf333..729f3d78f4a35 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -57,7 +57,7 @@ class LevelIndentTracker { /// Update the indent state given that \p Line is going to be formatted /// next. void nextLine(const AnnotatedLine ) { -Offset = getIndentOffset(*Line.First); +Offset = getIndentOffset(Line); // Update the indent level cache size so that we can rely on it // having the right size in adjustToUnmodifiedline. if (Line.Level >= IndentForLevel.size()) @@ -111,42 +111,41 @@ class LevelIndentTracker { /// /// For example, 'public:' labels in classes are offset by 1 or 2 /// characters to the left from their level. - int getIndentOffset(const FormatToken ) { + int getIndentOffset(const AnnotatedLine ) { if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() || Style.isCSharp()) { return 0; } -auto IsAccessModifier = [this, ]() { - if (RootToken.isAccessSpecifier(Style.isCpp())) { +auto IsAccessModifier = [&](const FormatToken ) { + if (Line.Type == LT_AccessModifier || RootToken.isObjCAccessSpecifier()) return true; - } else if (RootToken.isObjCAccessSpecifier()) { -return true; - } + + const auto *Next = RootToken.Next; + // Handle Qt signals. - else if (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) && - RootToken.Next && RootToken.Next->is(tok::colon)) { -return true; - } else if (RootToken.Next && - RootToken.Next->isOneOf(Keywords.kw_slots, - Keywords.kw_qslots) && - RootToken.Next->Next && RootToken.Next->Next->is(tok::colon)) { + if (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) && + Next && Next->is(tok::colon)) { return true; } - // Handle malformed access specifier e.g. 'private' without trailing ':'. - else if (!RootToken.Next && RootToken.isAccessSpecifier(false)) { + + if (Next && Next->isOneOf(Keywords.kw_slots, Keywords.kw_qslots) && + Next->Next && Next->Next->is(tok::colon)) { return true; } - return false; + + // Handle malformed access specifier e.g. 'private' without trailing ':'. + return !Next && RootToken.isAccessSpecifier(false); }; -if (IsAccessModifier()) { +if (IsAccessModifier(*Line.First)) { // The AccessModifierOffset may be overridden by IndentAccessModifiers, // in which case we take a negative value of the IndentWidth to simulate // the upper indent level. return Style.IndentAccessModifiers ?