[clang] [clang-format] Introduce "ReflowComments: IndentOnly" to re-indent comments without breaking internal structure (think Doxygen). (PR #96804)
@@ -855,7 +859,8 @@ bool BreakableBlockComment::mayReflow( StringRef IndentContent = Content[LineIndex]; if (Lines[LineIndex].ltrim(Blanks).starts_with("*")) IndentContent = Lines[LineIndex].ltrim(Blanks).substr(1); - return LineIndex > 0 && !CommentPragmasRegex.match(IndentContent) && + return LineIndex > 0 && Style.ReflowComments == FormatStyle::RCS_Always && owenca wrote: ```suggestion return LineIndex > 0 && AlwaysReflow && ``` https://github.com/llvm/llvm-project/pull/96804 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Introduce "ReflowComments: IndentOnly" to re-indent comments without breaking internal structure (think Doxygen). (PR #96804)
@@ -4588,11 +4588,11 @@ bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) { // Checks if \p FormatTok is a line comment that continues the line comment // section on \p Line. -static bool -continuesLineCommentSection(const FormatToken &FormatTok, -const UnwrappedLine &Line, -const llvm::Regex &CommentPragmasRegex) { - if (Line.Tokens.empty()) +static bool continuesLineCommentSection( +const FormatToken &FormatTok, const UnwrappedLine &Line, +const FormatStyle::ReflowCommentsStyle ReflowCommentsStyle, owenca wrote: ```suggestion const FormatStyle &Style, ``` https://github.com/llvm/llvm-project/pull/96804 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Introduce "ReflowComments: IndentOnly" to re-indent comments without breaking internal structure (think Doxygen). (PR #96804)
@@ -4588,11 +4588,11 @@ bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) { // Checks if \p FormatTok is a line comment that continues the line comment // section on \p Line. -static bool -continuesLineCommentSection(const FormatToken &FormatTok, -const UnwrappedLine &Line, -const llvm::Regex &CommentPragmasRegex) { - if (Line.Tokens.empty()) +static bool continuesLineCommentSection( +const FormatToken &FormatTok, const UnwrappedLine &Line, +const FormatStyle::ReflowCommentsStyle ReflowCommentsStyle, +const llvm::Regex &CommentPragmasRegex) { + if (Line.Tokens.empty() || ReflowCommentsStyle != FormatStyle::RCS_Always) owenca wrote: ```suggestion if (Line.Tokens.empty() || Style.ReflowComments != FormatStyle::RCS_Always) ``` https://github.com/llvm/llvm-project/pull/96804 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Introduce "ReflowComments: IndentOnly" to re-indent comments without breaking internal structure (think Doxygen). (PR #96804)
@@ -3750,24 +3750,43 @@ struct FormatStyle { ReferenceAlignmentStyle ReferenceAlignment; // clang-format off - /// If ``true``, clang-format will attempt to re-flow comments. That is it - /// will touch a comment and *reflow* long comments into new lines, trying to - /// obey the ``ColumnLimit``. - /// \code - ///false: - ///// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information - ////* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */ - /// - ///true: - ///// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of - ///// information - ////* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of - /// * information */ - /// \endcode - /// \version 3.8 - bool ReflowComments; + /// \brief Types of comment re-flow style. owenca wrote: ```suggestion /// \brief Types of comment reflow style. ``` https://github.com/llvm/llvm-project/pull/96804 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Introduce "ReflowComments: IndentOnly" to re-indent comments without breaking internal structure (think Doxygen). (PR #96804)
@@ -497,6 +497,16 @@ template <> struct MappingTraits { } }; +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, FormatStyle::ReflowCommentsStyle &Value) { +IO.enumCase(Value, "Never", FormatStyle::RCS_Never); +IO.enumCase(Value, "IndentOnly", FormatStyle::RCS_IndentOnly); +IO.enumCase(Value, "Always", FormatStyle::RCS_Always); owenca wrote: ```suggestion IO.enumCase(Value, "Always", FormatStyle::RCS_Always); // For backward compatibility: ``` https://github.com/llvm/llvm-project/pull/96804 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix annotation of braces enclosing stringification (PR #102998)
owenca wrote: /cherry-pick ee2359968fa307ef45254c816e14df33374168cd https://github.com/llvm/llvm-project/pull/102998 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix annotation of braces enclosing stringification (PR #102998)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/102998 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix annotation of braces enclosing stringification (PR #102998)
https://github.com/owenca milestoned https://github.com/llvm/llvm-project/pull/102998 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix annotation of braces enclosing stringification (PR #102998)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/102998 Fixes #102937. >From bd4a32c90f6148d27b010a5a1497c0f447144d9a Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Mon, 12 Aug 2024 20:58:04 -0700 Subject: [PATCH] [clang-format] Fix annotation of braces enclosing stringification Fixes #102937. --- clang/lib/Format/UnwrappedLineParser.cpp | 3 +++ clang/unittests/Format/TokenAnnotatorTest.cpp | 11 +++ 2 files changed, 14 insertions(+) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index cafbba0a0d0c5b..5f1a88d4bcd729 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -507,6 +507,9 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) { if (!Line->InMacroBody && !Style.isTableGen()) { // Skip PPDirective lines and comments. while (NextTok->is(tok::hash)) { +NextTok = Tokens->getNextToken(); +if (NextTok->is(tok::pp_not_keyword)) + break; do { NextTok = Tokens->getNextToken(); } while (NextTok->NewlinesBefore == 0 && NextTok->isNot(tok::eof)); diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index cbbe550a79ebc2..256bbd49c424fa 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -3216,6 +3216,17 @@ TEST_F(TokenAnnotatorTest, BraceKind) { EXPECT_BRACE_KIND(Tokens[17], BK_Block); EXPECT_BRACE_KIND(Tokens[22], BK_Block); EXPECT_BRACE_KIND(Tokens[26], BK_Block); + + Tokens = annotate("{\n" +"#define M(x) \\\n" +" return {#x};\n" +"}"); + ASSERT_EQ(Tokens.size(), 15u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_brace, TT_BlockLBrace); + EXPECT_BRACE_KIND(Tokens[0], BK_Block); + EXPECT_BRACE_KIND(Tokens[8], BK_BracedInit); + EXPECT_BRACE_KIND(Tokens[11], BK_BracedInit); + EXPECT_BRACE_KIND(Tokens[13], BK_Block); } TEST_F(TokenAnnotatorTest, UnderstandsElaboratedTypeSpecifier) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Correctly handle C# attribute on auto property (PR #102921)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/102921 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Correctly handle C# attribute on auto property (PR #102921)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/102921 Fixes #101487. >From 5fd35e3d2b9775867a259457879fc7030c901724 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Mon, 12 Aug 2024 08:24:12 -0700 Subject: [PATCH] [clang-format] Correctly handle C# attribute on auto property Fixes #101487. --- clang/lib/Format/UnwrappedLineParser.cpp| 14 +- clang/unittests/Format/FormatTestCSharp.cpp | 11 +++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 66485c91f64de9..cafbba0a0d0c5b 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -2155,12 +2155,16 @@ bool UnwrappedLineParser::tryToParsePropertyAccessor() { // Track these as they do not require line breaks to be introduced. bool HasSpecialAccessor = false; bool IsTrivialPropertyAccessor = true; + bool HasAttribute = false; while (!eof()) { -if (Tok->isAccessSpecifierKeyword() || -Tok->isOneOf(tok::semi, Keywords.kw_internal, Keywords.kw_get, - Keywords.kw_init, Keywords.kw_set)) { - if (Tok->isOneOf(Keywords.kw_get, Keywords.kw_init, Keywords.kw_set)) +if (const bool IsAccessorKeyword = +Tok->isOneOf(Keywords.kw_get, Keywords.kw_init, Keywords.kw_set); +IsAccessorKeyword || Tok->isAccessSpecifierKeyword() || +Tok->isOneOf(tok::l_square, tok::semi, Keywords.kw_internal)) { + if (IsAccessorKeyword) HasSpecialAccessor = true; + else if (Tok->is(tok::l_square)) +HasAttribute = true; Tok = Tokens->getNextToken(); continue; } @@ -2169,7 +2173,7 @@ bool UnwrappedLineParser::tryToParsePropertyAccessor() { break; } - if (!HasSpecialAccessor) { + if (!HasSpecialAccessor || HasAttribute) { Tokens->setPosition(StoredPosition); return false; } diff --git a/clang/unittests/Format/FormatTestCSharp.cpp b/clang/unittests/Format/FormatTestCSharp.cpp index 7166e4ec4de30d..3b04238b9b48b0 100644 --- a/clang/unittests/Format/FormatTestCSharp.cpp +++ b/clang/unittests/Format/FormatTestCSharp.cpp @@ -1149,6 +1149,17 @@ public class SaleItem public decimal Price { get; set; } })", MicrosoftStyle); + + verifyFormat("internal class Program\n" + "{\n" + "bool AutoAllowKnownApps\n" + "{\n" + "get;\n" + "[Simple]\n" + "set;\n" + "}\n" + "}", + MicrosoftStyle); } TEST_F(FormatTestCSharp, DefaultLiteral) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a serious bug in `git clang-format -f` (PR #102629)
owenca wrote: You need to use the clang-format built from this patch, which adds the new clang-format `-list-ignored` option. https://github.com/llvm/llvm-project/pull/102629 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a serious bug in `git clang-format -f` (PR #102629)
https://github.com/owenca milestoned https://github.com/llvm/llvm-project/pull/102629 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a serious bug in `git clang-format -f` (PR #102629)
owenca wrote: /cherry-pick 986bc3d0719af653fecb77e8cfc59f39bec148fd https://github.com/llvm/llvm-project/pull/102629 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a serious bug in `git clang-format -f` (PR #102629)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/102629 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add BreakBinaryOperations configuration (PR #95013)
https://github.com/owenca closed 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 serious bug in `git clang-format -f` (PR #102629)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/102629 >From 9b71b289feb75cdc6d67a6ac696ff0ba7969549d Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Fri, 9 Aug 2024 08:15:43 -0700 Subject: [PATCH 1/4] [clang-format] Fix a serious bug in `git clang-format -f` With the --force (or -f) option, git-clang-format wipes out input files excluded by a .clang-format-ignore file if they have unstaged changes. This patch adds a hidden clang-format option --list-ignored that lists such excluded files for git-clang-format to filter out. Fixes #102459. --- clang/test/Format/list-ignored.cpp| 60 +++ clang/tools/clang-format/ClangFormat.cpp | 12 - clang/tools/clang-format/git-clang-format | 12 - 3 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 clang/test/Format/list-ignored.cpp diff --git a/clang/test/Format/list-ignored.cpp b/clang/test/Format/list-ignored.cpp new file mode 100644 index 00..91f2b5175d6395 --- /dev/null +++ b/clang/test/Format/list-ignored.cpp @@ -0,0 +1,60 @@ +// RUN: rm -rf %t.dir +// RUN: mkdir -p %t.dir/level1/level2 + +// RUN: cd %t.dir +// RUN: echo "*" > .clang-format-ignore +// RUN: echo "level*/*.c*" >> .clang-format-ignore +// RUN: echo "*/*2/foo.*" >> .clang-format-ignore + +// RUN: touch foo.cc +// RUN: clang-format -list-ignored .clang-format-ignore foo.cc \ +// RUN: | FileCheck %s -match-full-lines +// CHECK: .clang-format-ignore +// CHECK-NEXT: foo.cc + +// RUN: cd level1 +// RUN: touch bar.cc baz.c +// RUN: clang-format -list-ignored bar.cc baz.c \ +// RUN: | FileCheck %s -check-prefix=CHECK2 -match-full-lines +// CHECK2: bar.cc +// CHECK2-NEXT: baz.c + +// RUN: cd level2 +// RUN: touch foo.c foo.js +// RUN: clang-format -list-ignored foo.c foo.js \ +// RUN: | FileCheck %s -check-prefix=CHECK3 -match-full-lines +// CHECK3: foo.c +// CHECK3-NEXT: foo.js + +// RUN: touch .clang-format-ignore +// RUN: clang-format -list-ignored foo.c foo.js \ +// RUN: | FileCheck %s -allow-empty -check-prefix=CHECK4 +// CHECK4-NOT: foo.c +// CHECK4-NOT: foo.js + +// RUN: echo "*.js" > .clang-format-ignore +// RUN: clang-format -list-ignored foo.c foo.js \ +// RUN: | FileCheck %s -check-prefix=CHECK5 -match-full-lines +// CHECK5-NOT: foo.c +// CHECK5: foo.js + +// RUN: cd ../.. +// RUN: clang-format -list-ignored *.cc level1/*.c* level1/level2/foo.* \ +// RUN: | FileCheck %s -check-prefix=CHECK6 -match-full-lines +// CHECK6-NOT: level1/levle2/foo.c +// CHECK6: foo.cc +// CHECK6-NEXT: level1/bar.cc +// CHECK6-NEXT: level1/baz.c +// CHECK6-NEXT: level1/level2/foo.js + +// RUN: rm .clang-format-ignore +// RUN: clang-format -list-ignored *.cc level1/*.c* level1/level2/foo.* \ +// RUN: | FileCheck %s -check-prefix=CHECK7 -match-full-lines +// CHECK7-NOT: foo.cc +// CHECK7-NOT: level1/bar.cc +// CHECK7-NOT: level1/baz.c +// CHECK7-NOT: level1/level2/foo.c +// CHECK7: level1/level2/foo.js + +// RUN: cd .. +// RUN: rm -r %t.dir diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp index 6582d73eae40ea..50dd5345a6db33 100644 --- a/clang/tools/clang-format/ClangFormat.cpp +++ b/clang/tools/clang-format/ClangFormat.cpp @@ -210,6 +210,10 @@ static cl::opt FailOnIncompleteFormat( cl::desc("If set, fail with exit code 1 on incomplete format."), cl::init(false), cl::cat(ClangFormatCategory)); +static cl::opt ListIgnored("list-ignored", + cl::desc("List ignored files."), + cl::cat(ClangFormatCategory), cl::Hidden); + namespace clang { namespace format { @@ -715,7 +719,13 @@ int main(int argc, const char **argv) { unsigned FileNo = 1; bool Error = false; for (const auto &FileName : FileNames) { -if (isIgnored(FileName)) +const bool Ignored = isIgnored(FileName); +if (ListIgnored) { + if (Ignored) +outs() << FileName << "\n"; + continue; +} +if (Ignored) continue; if (Verbose) { errs() << "Formatting [" << FileNo++ << "/" << FileNames.size() << "] " diff --git a/clang/tools/clang-format/git-clang-format b/clang/tools/clang-format/git-clang-format index d33fd478d77fd9..8f7eb38d72e738 100755 --- a/clang/tools/clang-format/git-clang-format +++ b/clang/tools/clang-format/git-clang-format @@ -173,11 +173,12 @@ def main(): # those files. cd_to_toplevel() filter_symlinks(changed_lines) + filter_ignored_files(changed_lines, binary=opts.binary) if opts.verbose >= 1: ignored_files.difference_update(changed_lines) if ignored_files: - print( -'Ignoring changes in the following files (wrong extension or symlink):') + print('Ignoring the following files (wrong extension, symlink, or ' +'ignored by clang-format):') for filename in ignored_files: print('%s' % filename) if changed_lines: @@ -399,6 +400,13 @@ def filter_symlinks(dictionary): del diction
[clang] [clang-format] Fix a serious bug in `git clang-format -f` (PR #102629)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/102629 >From 9b71b289feb75cdc6d67a6ac696ff0ba7969549d Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Fri, 9 Aug 2024 08:15:43 -0700 Subject: [PATCH 1/3] [clang-format] Fix a serious bug in `git clang-format -f` With the --force (or -f) option, git-clang-format wipes out input files excluded by a .clang-format-ignore file if they have unstaged changes. This patch adds a hidden clang-format option --list-ignored that lists such excluded files for git-clang-format to filter out. Fixes #102459. --- clang/test/Format/list-ignored.cpp| 60 +++ clang/tools/clang-format/ClangFormat.cpp | 12 - clang/tools/clang-format/git-clang-format | 12 - 3 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 clang/test/Format/list-ignored.cpp diff --git a/clang/test/Format/list-ignored.cpp b/clang/test/Format/list-ignored.cpp new file mode 100644 index 00..91f2b5175d6395 --- /dev/null +++ b/clang/test/Format/list-ignored.cpp @@ -0,0 +1,60 @@ +// RUN: rm -rf %t.dir +// RUN: mkdir -p %t.dir/level1/level2 + +// RUN: cd %t.dir +// RUN: echo "*" > .clang-format-ignore +// RUN: echo "level*/*.c*" >> .clang-format-ignore +// RUN: echo "*/*2/foo.*" >> .clang-format-ignore + +// RUN: touch foo.cc +// RUN: clang-format -list-ignored .clang-format-ignore foo.cc \ +// RUN: | FileCheck %s -match-full-lines +// CHECK: .clang-format-ignore +// CHECK-NEXT: foo.cc + +// RUN: cd level1 +// RUN: touch bar.cc baz.c +// RUN: clang-format -list-ignored bar.cc baz.c \ +// RUN: | FileCheck %s -check-prefix=CHECK2 -match-full-lines +// CHECK2: bar.cc +// CHECK2-NEXT: baz.c + +// RUN: cd level2 +// RUN: touch foo.c foo.js +// RUN: clang-format -list-ignored foo.c foo.js \ +// RUN: | FileCheck %s -check-prefix=CHECK3 -match-full-lines +// CHECK3: foo.c +// CHECK3-NEXT: foo.js + +// RUN: touch .clang-format-ignore +// RUN: clang-format -list-ignored foo.c foo.js \ +// RUN: | FileCheck %s -allow-empty -check-prefix=CHECK4 +// CHECK4-NOT: foo.c +// CHECK4-NOT: foo.js + +// RUN: echo "*.js" > .clang-format-ignore +// RUN: clang-format -list-ignored foo.c foo.js \ +// RUN: | FileCheck %s -check-prefix=CHECK5 -match-full-lines +// CHECK5-NOT: foo.c +// CHECK5: foo.js + +// RUN: cd ../.. +// RUN: clang-format -list-ignored *.cc level1/*.c* level1/level2/foo.* \ +// RUN: | FileCheck %s -check-prefix=CHECK6 -match-full-lines +// CHECK6-NOT: level1/levle2/foo.c +// CHECK6: foo.cc +// CHECK6-NEXT: level1/bar.cc +// CHECK6-NEXT: level1/baz.c +// CHECK6-NEXT: level1/level2/foo.js + +// RUN: rm .clang-format-ignore +// RUN: clang-format -list-ignored *.cc level1/*.c* level1/level2/foo.* \ +// RUN: | FileCheck %s -check-prefix=CHECK7 -match-full-lines +// CHECK7-NOT: foo.cc +// CHECK7-NOT: level1/bar.cc +// CHECK7-NOT: level1/baz.c +// CHECK7-NOT: level1/level2/foo.c +// CHECK7: level1/level2/foo.js + +// RUN: cd .. +// RUN: rm -r %t.dir diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp index 6582d73eae40ea..50dd5345a6db33 100644 --- a/clang/tools/clang-format/ClangFormat.cpp +++ b/clang/tools/clang-format/ClangFormat.cpp @@ -210,6 +210,10 @@ static cl::opt FailOnIncompleteFormat( cl::desc("If set, fail with exit code 1 on incomplete format."), cl::init(false), cl::cat(ClangFormatCategory)); +static cl::opt ListIgnored("list-ignored", + cl::desc("List ignored files."), + cl::cat(ClangFormatCategory), cl::Hidden); + namespace clang { namespace format { @@ -715,7 +719,13 @@ int main(int argc, const char **argv) { unsigned FileNo = 1; bool Error = false; for (const auto &FileName : FileNames) { -if (isIgnored(FileName)) +const bool Ignored = isIgnored(FileName); +if (ListIgnored) { + if (Ignored) +outs() << FileName << "\n"; + continue; +} +if (Ignored) continue; if (Verbose) { errs() << "Formatting [" << FileNo++ << "/" << FileNames.size() << "] " diff --git a/clang/tools/clang-format/git-clang-format b/clang/tools/clang-format/git-clang-format index d33fd478d77fd9..8f7eb38d72e738 100755 --- a/clang/tools/clang-format/git-clang-format +++ b/clang/tools/clang-format/git-clang-format @@ -173,11 +173,12 @@ def main(): # those files. cd_to_toplevel() filter_symlinks(changed_lines) + filter_ignored_files(changed_lines, binary=opts.binary) if opts.verbose >= 1: ignored_files.difference_update(changed_lines) if ignored_files: - print( -'Ignoring changes in the following files (wrong extension or symlink):') + print('Ignoring the following files (wrong extension, symlink, or ' +'ignored by clang-format):') for filename in ignored_files: print('%s' % filename) if changed_lines: @@ -399,6 +400,13 @@ def filter_symlinks(dictionary): del diction
[clang] [clang-format] Add BreakBinaryOperations configuration (PR #95013)
owenca wrote: > Thanks for the review feedback @owenca @HazardyKnusperkeks Please merge this > PR for me if you feel it is ready as I don't have merge permissions I wonder if anyone can come up with a better name than `OnePerLine`. See https://github.com/llvm/llvm-project/pull/101882#issuecomment-2272907960. @mydeveloperday @HazardyKnusperkeks @rymiel? If not, I can merge this patch as is. 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 serious bug in `git clang-format -f` (PR #102629)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/102629 >From 9b71b289feb75cdc6d67a6ac696ff0ba7969549d Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Fri, 9 Aug 2024 08:15:43 -0700 Subject: [PATCH 1/2] [clang-format] Fix a serious bug in `git clang-format -f` With the --force (or -f) option, git-clang-format wipes out input files excluded by a .clang-format-ignore file if they have unstaged changes. This patch adds a hidden clang-format option --list-ignored that lists such excluded files for git-clang-format to filter out. Fixes #102459. --- clang/test/Format/list-ignored.cpp| 60 +++ clang/tools/clang-format/ClangFormat.cpp | 12 - clang/tools/clang-format/git-clang-format | 12 - 3 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 clang/test/Format/list-ignored.cpp diff --git a/clang/test/Format/list-ignored.cpp b/clang/test/Format/list-ignored.cpp new file mode 100644 index 00..91f2b5175d6395 --- /dev/null +++ b/clang/test/Format/list-ignored.cpp @@ -0,0 +1,60 @@ +// RUN: rm -rf %t.dir +// RUN: mkdir -p %t.dir/level1/level2 + +// RUN: cd %t.dir +// RUN: echo "*" > .clang-format-ignore +// RUN: echo "level*/*.c*" >> .clang-format-ignore +// RUN: echo "*/*2/foo.*" >> .clang-format-ignore + +// RUN: touch foo.cc +// RUN: clang-format -list-ignored .clang-format-ignore foo.cc \ +// RUN: | FileCheck %s -match-full-lines +// CHECK: .clang-format-ignore +// CHECK-NEXT: foo.cc + +// RUN: cd level1 +// RUN: touch bar.cc baz.c +// RUN: clang-format -list-ignored bar.cc baz.c \ +// RUN: | FileCheck %s -check-prefix=CHECK2 -match-full-lines +// CHECK2: bar.cc +// CHECK2-NEXT: baz.c + +// RUN: cd level2 +// RUN: touch foo.c foo.js +// RUN: clang-format -list-ignored foo.c foo.js \ +// RUN: | FileCheck %s -check-prefix=CHECK3 -match-full-lines +// CHECK3: foo.c +// CHECK3-NEXT: foo.js + +// RUN: touch .clang-format-ignore +// RUN: clang-format -list-ignored foo.c foo.js \ +// RUN: | FileCheck %s -allow-empty -check-prefix=CHECK4 +// CHECK4-NOT: foo.c +// CHECK4-NOT: foo.js + +// RUN: echo "*.js" > .clang-format-ignore +// RUN: clang-format -list-ignored foo.c foo.js \ +// RUN: | FileCheck %s -check-prefix=CHECK5 -match-full-lines +// CHECK5-NOT: foo.c +// CHECK5: foo.js + +// RUN: cd ../.. +// RUN: clang-format -list-ignored *.cc level1/*.c* level1/level2/foo.* \ +// RUN: | FileCheck %s -check-prefix=CHECK6 -match-full-lines +// CHECK6-NOT: level1/levle2/foo.c +// CHECK6: foo.cc +// CHECK6-NEXT: level1/bar.cc +// CHECK6-NEXT: level1/baz.c +// CHECK6-NEXT: level1/level2/foo.js + +// RUN: rm .clang-format-ignore +// RUN: clang-format -list-ignored *.cc level1/*.c* level1/level2/foo.* \ +// RUN: | FileCheck %s -check-prefix=CHECK7 -match-full-lines +// CHECK7-NOT: foo.cc +// CHECK7-NOT: level1/bar.cc +// CHECK7-NOT: level1/baz.c +// CHECK7-NOT: level1/level2/foo.c +// CHECK7: level1/level2/foo.js + +// RUN: cd .. +// RUN: rm -r %t.dir diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp index 6582d73eae40ea..50dd5345a6db33 100644 --- a/clang/tools/clang-format/ClangFormat.cpp +++ b/clang/tools/clang-format/ClangFormat.cpp @@ -210,6 +210,10 @@ static cl::opt FailOnIncompleteFormat( cl::desc("If set, fail with exit code 1 on incomplete format."), cl::init(false), cl::cat(ClangFormatCategory)); +static cl::opt ListIgnored("list-ignored", + cl::desc("List ignored files."), + cl::cat(ClangFormatCategory), cl::Hidden); + namespace clang { namespace format { @@ -715,7 +719,13 @@ int main(int argc, const char **argv) { unsigned FileNo = 1; bool Error = false; for (const auto &FileName : FileNames) { -if (isIgnored(FileName)) +const bool Ignored = isIgnored(FileName); +if (ListIgnored) { + if (Ignored) +outs() << FileName << "\n"; + continue; +} +if (Ignored) continue; if (Verbose) { errs() << "Formatting [" << FileNo++ << "/" << FileNames.size() << "] " diff --git a/clang/tools/clang-format/git-clang-format b/clang/tools/clang-format/git-clang-format index d33fd478d77fd9..8f7eb38d72e738 100755 --- a/clang/tools/clang-format/git-clang-format +++ b/clang/tools/clang-format/git-clang-format @@ -173,11 +173,12 @@ def main(): # those files. cd_to_toplevel() filter_symlinks(changed_lines) + filter_ignored_files(changed_lines, binary=opts.binary) if opts.verbose >= 1: ignored_files.difference_update(changed_lines) if ignored_files: - print( -'Ignoring changes in the following files (wrong extension or symlink):') + print('Ignoring the following files (wrong extension, symlink, or ' +'ignored by clang-format):') for filename in ignored_files: print('%s' % filename) if changed_lines: @@ -399,6 +400,13 @@ def filter_symlinks(dictionary): del diction
[clang] [clang-format] Fix a serious bug in `git clang-format -f` (PR #102629)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/102629 With the --force (or -f) option, git-clang-format wipes out input files excluded by a .clang-format-ignore file if they have unstaged changes. This patch adds a hidden clang-format option --list-ignored that lists such excluded files for git-clang-format to filter out. Fixes #102459. >From 9b71b289feb75cdc6d67a6ac696ff0ba7969549d Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Fri, 9 Aug 2024 08:15:43 -0700 Subject: [PATCH] [clang-format] Fix a serious bug in `git clang-format -f` With the --force (or -f) option, git-clang-format wipes out input files excluded by a .clang-format-ignore file if they have unstaged changes. This patch adds a hidden clang-format option --list-ignored that lists such excluded files for git-clang-format to filter out. Fixes #102459. --- clang/test/Format/list-ignored.cpp| 60 +++ clang/tools/clang-format/ClangFormat.cpp | 12 - clang/tools/clang-format/git-clang-format | 12 - 3 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 clang/test/Format/list-ignored.cpp diff --git a/clang/test/Format/list-ignored.cpp b/clang/test/Format/list-ignored.cpp new file mode 100644 index 00..91f2b5175d6395 --- /dev/null +++ b/clang/test/Format/list-ignored.cpp @@ -0,0 +1,60 @@ +// RUN: rm -rf %t.dir +// RUN: mkdir -p %t.dir/level1/level2 + +// RUN: cd %t.dir +// RUN: echo "*" > .clang-format-ignore +// RUN: echo "level*/*.c*" >> .clang-format-ignore +// RUN: echo "*/*2/foo.*" >> .clang-format-ignore + +// RUN: touch foo.cc +// RUN: clang-format -list-ignored .clang-format-ignore foo.cc \ +// RUN: | FileCheck %s -match-full-lines +// CHECK: .clang-format-ignore +// CHECK-NEXT: foo.cc + +// RUN: cd level1 +// RUN: touch bar.cc baz.c +// RUN: clang-format -list-ignored bar.cc baz.c \ +// RUN: | FileCheck %s -check-prefix=CHECK2 -match-full-lines +// CHECK2: bar.cc +// CHECK2-NEXT: baz.c + +// RUN: cd level2 +// RUN: touch foo.c foo.js +// RUN: clang-format -list-ignored foo.c foo.js \ +// RUN: | FileCheck %s -check-prefix=CHECK3 -match-full-lines +// CHECK3: foo.c +// CHECK3-NEXT: foo.js + +// RUN: touch .clang-format-ignore +// RUN: clang-format -list-ignored foo.c foo.js \ +// RUN: | FileCheck %s -allow-empty -check-prefix=CHECK4 +// CHECK4-NOT: foo.c +// CHECK4-NOT: foo.js + +// RUN: echo "*.js" > .clang-format-ignore +// RUN: clang-format -list-ignored foo.c foo.js \ +// RUN: | FileCheck %s -check-prefix=CHECK5 -match-full-lines +// CHECK5-NOT: foo.c +// CHECK5: foo.js + +// RUN: cd ../.. +// RUN: clang-format -list-ignored *.cc level1/*.c* level1/level2/foo.* \ +// RUN: | FileCheck %s -check-prefix=CHECK6 -match-full-lines +// CHECK6-NOT: level1/levle2/foo.c +// CHECK6: foo.cc +// CHECK6-NEXT: level1/bar.cc +// CHECK6-NEXT: level1/baz.c +// CHECK6-NEXT: level1/level2/foo.js + +// RUN: rm .clang-format-ignore +// RUN: clang-format -list-ignored *.cc level1/*.c* level1/level2/foo.* \ +// RUN: | FileCheck %s -check-prefix=CHECK7 -match-full-lines +// CHECK7-NOT: foo.cc +// CHECK7-NOT: level1/bar.cc +// CHECK7-NOT: level1/baz.c +// CHECK7-NOT: level1/level2/foo.c +// CHECK7: level1/level2/foo.js + +// RUN: cd .. +// RUN: rm -r %t.dir diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp index 6582d73eae40ea..50dd5345a6db33 100644 --- a/clang/tools/clang-format/ClangFormat.cpp +++ b/clang/tools/clang-format/ClangFormat.cpp @@ -210,6 +210,10 @@ static cl::opt FailOnIncompleteFormat( cl::desc("If set, fail with exit code 1 on incomplete format."), cl::init(false), cl::cat(ClangFormatCategory)); +static cl::opt ListIgnored("list-ignored", + cl::desc("List ignored files."), + cl::cat(ClangFormatCategory), cl::Hidden); + namespace clang { namespace format { @@ -715,7 +719,13 @@ int main(int argc, const char **argv) { unsigned FileNo = 1; bool Error = false; for (const auto &FileName : FileNames) { -if (isIgnored(FileName)) +const bool Ignored = isIgnored(FileName); +if (ListIgnored) { + if (Ignored) +outs() << FileName << "\n"; + continue; +} +if (Ignored) continue; if (Verbose) { errs() << "Formatting [" << FileNo++ << "/" << FileNames.size() << "] " diff --git a/clang/tools/clang-format/git-clang-format b/clang/tools/clang-format/git-clang-format index d33fd478d77fd9..8f7eb38d72e738 100755 --- a/clang/tools/clang-format/git-clang-format +++ b/clang/tools/clang-format/git-clang-format @@ -173,11 +173,12 @@ def main(): # those files. cd_to_toplevel() filter_symlinks(changed_lines) + filter_ignored_files(changed_lines, binary=opts.binary) if opts.verbose >= 1: ignored_files.difference_update(changed_lines) if ignored_files: - print( -'Ignoring changes in the following files (wrong extension or symlink):')
[clang] [clang-format] Fix a bug in annotating CastRParen (PR #102261)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/102261 ___ 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 CastRParen (PR #102261)
owenca wrote: > I'm sorry I'm not familiar with LLVM release cycle, but is it too late for > this to make it into the `release/19.x` branch? It's not too late, but in general we backport bug fixes only if the bugs are labeled as `invalid-code-generation`, `crash-on-valid`, or `regression`. In this particular case though, the fix is localized and fairly simple, and has been approved by all clang-format maintainers, so I've decided to backport it to 19.x per your request. https://github.com/llvm/llvm-project/pull/102261 ___ 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 CastRParen (PR #102261)
https://github.com/owenca milestoned https://github.com/llvm/llvm-project/pull/102261 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Change BinPackParameters to an enum to add a BreakAlways (PR #101882)
owenca wrote: > When you say rename, do you mean deprecate `BinPackParameters` like in these > changes > [6739bb5](https://github.com/llvm/llvm-project/commit/6739bb5006bc28e2bdbdb2326eb2c957546634aa) > but using `BreakParameters` and `Never`/`OnePerLine`/`Always` for the names? Yes, deprecate `BinPackParameters` and rename it to either `PackParameters` (with `enum` values `Leave`, `Always`, `OnePerLine`, and `Never`) or `BreakParameters` (with `enum` values `Leave`, `Never`, `OnePerLine`, and `Always`). I don't really like `OnePerLine` but can't think of a better alternative that's not wordy. If adding `Leave` is not trivial, we can support it in another patch. Have you given any thought about https://github.com/llvm/llvm-project/issues/53190#issuecomment-1973631975? https://github.com/llvm/llvm-project/pull/101882 ___ 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 CastRParen (PR #102261)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/102261 Fixes #102102. >From b72a629d16d5bc3ce800a562fd41ba2dfd1fe1eb Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Tue, 6 Aug 2024 18:10:20 -0700 Subject: [PATCH] [clang-format] Fix a bug in annotating CastRParen Fixes #102102. --- clang/lib/Format/TokenAnnotator.cpp | 11 ++- clang/unittests/Format/TokenAnnotatorTest.cpp | 7 +++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 4ed3e9d0e8e85..e1c9f37c6e8dc 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2874,9 +2874,18 @@ class AnnotatingParser { return false; // Search for unexpected tokens. -for (auto *Prev = BeforeRParen; Prev != LParen; Prev = Prev->Previous) +for (auto *Prev = BeforeRParen; Prev != LParen; Prev = Prev->Previous) { + if (Prev->is(tok::r_paren)) { +Prev = Prev->MatchingParen; +if (!Prev) + return false; +if (Prev->is(TT_FunctionTypeLParen)) + break; +continue; + } if (!Prev->isOneOf(tok::kw_const, tok::identifier, tok::coloncolon)) return false; +} return true; } diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 6b71d0d18cf7a..cbbe550a79ebc 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -740,6 +740,13 @@ TEST_F(TokenAnnotatorTest, UnderstandsCasts) { EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_Unknown); EXPECT_TOKEN(Tokens[11], tok::amp, TT_BinaryOperator); + Tokens = annotate("func((void (*)())&a);"); + ASSERT_EQ(Tokens.size(), 15u) << Tokens; + EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_FunctionTypeLParen); + EXPECT_TOKEN(Tokens[5], tok::star, TT_PointerOrReference); + EXPECT_TOKEN(Tokens[9], tok::r_paren, TT_CastRParen); + EXPECT_TOKEN(Tokens[10], tok::amp, TT_UnaryOperator); + auto Style = getLLVMStyle(); Style.TypeNames.push_back("Foo"); Tokens = annotate("#define FOO(bar) foo((Foo)&bar)", Style); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Change BinPackParameters to an enum to add a BreakAlways (PR #101882)
owenca wrote: We should rename the option and its values to e.g. `BreakParameters` and `Never`/`OnePerLine`/`Always`. See also https://github.com/llvm/llvm-project/pull/95013#discussion_r1703578003. https://github.com/llvm/llvm-project/pull/101882 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Add BreakBinaryOperations configuration (PR #95013)
https://github.com/owenca approved this pull request. 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 BreakBinaryOperations 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 BreakBinaryOperations configuration (PR #95013)
@@ -27630,6 +27630,245 @@ TEST_F(FormatTest, SpaceBetweenKeywordAndLiteral) { verifyFormat("return sizeof \"5\";"); } +TEST_F(FormatTest, BreakBinaryOperations) { + auto Style = getLLVMStyleWithColumns(60); + // Logical operations owenca wrote: ```suggestion EXPECT_EQ(Style.BreakBinaryOperations, FormatStyle::BBO_Never); // Logical operations ``` 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 BreakBinaryOperations configuration (PR #95013)
@@ -146,6 +147,33 @@ static bool startsNextParameter(const FormatToken &Current, Style.BreakInheritanceList != FormatStyle::BILS_BeforeComma)); } +// Returns \c true if \c Token in an alignable binary operator +static bool isAlignableBinaryOperator(const FormatToken &Token) { + // No need to align binary operators that only have two operands. + bool HasTwoOperands = Token.OperatorIndex == 0 && !Token.NextOperator && +Token.isNot(TT_ConditionalExpr); + return Token.is(TT_BinaryOperator) && !HasTwoOperands && + Token.getPrecedence() > prec::Conditional && + Token.getPrecedence() < prec::PointerToMember; +} + +// Returns \c true if \c Current starts the next operand in a binary operation. +static bool startsNextOperand(const FormatToken &Current) { + assert(Current.Previous); + const auto &Previous = *Current.Previous; + return isAlignableBinaryOperator(Previous) && !Current.isTrailingComment(); +} + +// Returns \c true if \c Current is a binary operation that must break. +static bool mustBreakBinaryOperation(const FormatToken &Current, + const FormatStyle &Style) { + return Style.BreakBinaryOperations != FormatStyle::BBO_Never && + ((isAlignableBinaryOperator(Current) && + Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None) || + (startsNextOperand(Current) && + Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None)); owenca wrote: ```suggestion (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None ? startsNextOperand : isAlignableBinaryOperator)(Current); ``` 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 BreakBinaryOperations configuration (PR #95013)
@@ -27630,6 +27630,245 @@ TEST_F(FormatTest, SpaceBetweenKeywordAndLiteral) { verifyFormat("return sizeof \"5\";"); } +TEST_F(FormatTest, BreakBinaryOperations) { + 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);", + Style); + + Style.BreakBinaryOperations = FormatStyle::BBO_BreakAll; + + // 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;", Style); + + verifyFormat("result = loongop1 +\n" + " loongop2 +\n" + " loongop3;", + Style); + + verifyFormat("const int result =\n" + "operand1 + operand2 - (operand3 + operand4);", + Style); + + verifyFormat("result = longOperand1 +\n" + " longOperand2 -\n" + " (longOperand3 + longOperand4) -\n" + " longOperand5 +\n" + " longOperand6;", + Style); + + verifyFormat("result = operand1 +\n" + " operand2 -\n" + " operand3 +\n" + " operand4 -\n" + " operand5 +\n" + " operand6;", + Style); + + // Ensure mixed precedence operations are handled properly + Style.BreakBinaryOperations = FormatStyle::BBO_BreakAll; + verifyFormat("result = op1 + op2 * op3 - op4;", Style); + + verifyFormat("result = operand1 +\n" + " operand2 /\n" + " operand3 +\n" + " operand4 /\n" + " operand5 *\n" + " operand6;", + Style); + + verifyFormat("result = operand1 *\n" + " operand2 -\n" + " operand3 *\n" + " operand4 -\n" + " operand5 +\n" + " operand6;", + Style); + + verifyFormat("result = operand1 *\n" + " (operand2 - operand3 * operand4) -\n" + " operand5 +\n" + " operand6;", + Style); + + verifyFormat("result = operand1.member *\n" + " (operand2.member() - operand3->mem * operand4) -\n" + " operand5.member() +\n" + " operand6->member;", + Style); + + Style.BreakBinaryOperations = FormatStyle::BBO_BreakRespectPrecedence; + verifyFormat("result = op1 + op2 * op3 - op4;", Style); + + verifyFormat("result = operand1 +\n" + " operand2 / operand3 +\n" + " operand4 / operand5 * operand6;", + Style); + + verifyFormat("result = operand1 * operand2 -\n" + " operand3 * operand4 -\n" + " operand5 +\n" + " operand6;", + Style); + + verifyFormat("result = operand1 * (operand2 - operand3 * operand4) -\n" + " operand5 +\n" + " operand6;", + Style); + + verifyFormat("std::uint32_t a = byte_buffer[0] |\n" + " byte_buffer[1] << 8 |\n" + " byte_buffer[2] << 16 |\n" + " byte_buffer[3] << 24;", +
[clang] [clang-format] Add BreakBinaryOperations configuration (PR #95013)
@@ -2231,6 +2231,41 @@ struct FormatStyle { /// \version 3.7 bool BreakBeforeTernaryOperators; + /// Different ways to break binary operations. + enum BreakBinaryOperationsStyle : int8_t { +/// Don't break binary operations +/// \code +///aaa + * c - d + +///; +/// \endcode +BBO_Never, + +/// Binary operations will either be all on the same line, or each operation +/// will have one line each. +/// \code +///aaa + +/// * +///c - +///d + +///; +/// \endcode +BBO_BreakAll, owenca wrote: I suggest that we use `OnePerLine` here. (We can't use `Always` because we break only if the expression can't fit into a single line.) 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 BreakBinaryOperations configuration (PR #95013)
@@ -2231,6 +2231,41 @@ struct FormatStyle { /// \version 3.7 bool BreakBeforeTernaryOperators; + /// Different ways to break binary operations. + enum BreakBinaryOperationsStyle : int8_t { +/// Don't break binary operations +/// \code +///aaa + * c - d + +///; +/// \endcode +BBO_Never, owenca wrote: Should we use `BinPack` instead? I'm ok with leaving it as `Never` though. 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 BreakBinaryOperations configuration (PR #95013)
@@ -2231,6 +2231,41 @@ struct FormatStyle { /// \version 3.7 bool BreakBeforeTernaryOperators; + /// Different ways to break binary operations. + enum BreakBinaryOperationsStyle : int8_t { +/// Don't break binary operations +/// \code +///aaa + * c - d + +///; +/// \endcode +BBO_Never, + +/// Binary operations will either be all on the same line, or each operation +/// will have one line each. +/// \code +///aaa + +/// * +///c - +///d + +///; +/// \endcode +BBO_BreakAll, + +/// Binary operations of a particular precedence that go beyond the column +/// limit will have one line each. +/// \code +///aaa + +/// * c - +///d + +///; +/// \endcode +BBO_BreakRespectPrecedence owenca wrote: ```suggestion BBO_RespectPrecedence ``` 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 BreakBinaryOperations configuration (PR #95013)
@@ -27630,6 +27630,245 @@ TEST_F(FormatTest, SpaceBetweenKeywordAndLiteral) { verifyFormat("return sizeof \"5\";"); } +TEST_F(FormatTest, BreakBinaryOperations) { + 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);", + Style); + + Style.BreakBinaryOperations = FormatStyle::BBO_BreakAll; + + // 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;", Style); + + verifyFormat("result = loongop1 +\n" + " loongop2 +\n" + " loongop3;", + Style); + + verifyFormat("const int result =\n" + "operand1 + operand2 - (operand3 + operand4);", + Style); + + verifyFormat("result = longOperand1 +\n" + " longOperand2 -\n" + " (longOperand3 + longOperand4) -\n" + " longOperand5 +\n" + " longOperand6;", + Style); + + verifyFormat("result = operand1 +\n" + " operand2 -\n" + " operand3 +\n" + " operand4 -\n" + " operand5 +\n" + " operand6;", + Style); + + // Ensure mixed precedence operations are handled properly + Style.BreakBinaryOperations = FormatStyle::BBO_BreakAll; owenca wrote: Redundant. 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 BreakBinaryOperations configuration (PR #95013)
https://github.com/owenca commented: This patch also fixes #58014 and #57280, so you can include them in the commit message. 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 BreakBinaryOperations 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 BreakBinaryOperations configuration (PR #95013)
@@ -146,6 +147,33 @@ static bool startsNextParameter(const FormatToken &Current, Style.BreakInheritanceList != FormatStyle::BILS_BeforeComma)); } +// Returns \c true if \c Token in an alignable binary operator +static bool isAlignableBinaryOperator(const FormatToken &Token) { + // No need to align binary operators that only have two operands. + bool HasTwoOperands = Token.OperatorIndex == 0 && !Token.NextOperator && +Token.isNot(TT_ConditionalExpr); owenca wrote: This is unnecessary because `TT_BinaryOperator` below ensures not `TT_ConditionalExpr `. 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] d86a995 - [clang-format][doc] Fix a typo.
Author: Owen Pan Date: 2024-08-04T21:14:52-07:00 New Revision: d86a995ab78905cd055f8a93812c3b94cf042499 URL: https://github.com/llvm/llvm-project/commit/d86a995ab78905cd055f8a93812c3b94cf042499 DIFF: https://github.com/llvm/llvm-project/commit/d86a995ab78905cd055f8a93812c3b94cf042499.diff LOG: [clang-format][doc] Fix a typo. Added: Modified: clang/docs/ClangFormatStyleOptions.rst clang/include/clang/Format/Format.h Removed: diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 6c2e6da594847..29b08bca6a407 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1484,7 +1484,7 @@ the configuration (without a prefix: ``Auto``). * ``OAS_AlignAfterOperator`` (in configuration: ``AlignAfterOperator``) Horizontally align operands of binary and ternary expressions. -This is similar to ``AO_Align``, except when +This is similar to ``OAS_Align``, except when ``BreakBeforeBinaryOperators`` is set, the operator is un-indented so that the wrapped operand is aligned with the operand on the first line. diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index c454ab2bc0ce2..fea5d2e17a0e2 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -533,7 +533,7 @@ struct FormatStyle { OAS_Align, /// Horizontally align operands of binary and ternary expressions. /// -/// This is similar to ``AO_Align``, except when +/// This is similar to ``OAS_Align``, except when /// ``BreakBeforeBinaryOperators`` is set, the operator is un-indented so /// that the wrapped operand is aligned with the operand on the first line. /// \code ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Handle parenthesized list in RemoveParentheses (PR #100852)
https://github.com/owenca demilestoned https://github.com/llvm/llvm-project/pull/100852 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Handle parenthesized list in RemoveParentheses (PR #100852)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/100852 >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 &Replaces, 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, Newline) { TEST_F(MatchFilePathTest, Star) { EXPECT_TRUE(match(std::string(50, 'a'), "*a*a*a*a*a*a*a*a*a*a"
[clang] [clang-format] Fix a misannotation of PointerOrReference (PR #101291)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/101291 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a misannotation of PointerOrReference (PR #101291)
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/101291 >From c59345d3b70a5343af22f78837ef8a47bea35e41 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Tue, 30 Jul 2024 23:20:12 -0700 Subject: [PATCH] [clang-format] Fix a misannotation of PointerOrReference Fixes #101138. --- clang/lib/Format/TokenAnnotator.cpp | 29 ++- clang/unittests/Format/TokenAnnotatorTest.cpp | 6 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 8cd5cf2484160..4ed3e9d0e8e85 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -3682,17 +3682,17 @@ static bool isFunctionDeclarationName(const LangOptions &LangOpts, const FormatToken &Current, const AnnotatedLine &Line, FormatToken *&ClosingParen) { - assert(Current.Previous); - if (Current.is(TT_FunctionDeclarationName)) return true; if (!Current.Tok.getIdentifierInfo()) return false; - const auto &Previous = *Current.Previous; + const auto *Prev = Current.getPreviousNonComment(); + assert(Prev); + const auto &Previous = *Prev; - if (const auto *PrevPrev = Previous.Previous; + if (const auto *PrevPrev = Previous.getPreviousNonComment(); PrevPrev && PrevPrev->is(TT_ObjCDecl)) { return false; } @@ -3859,20 +3859,20 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { First->TotalLength = First->IsMultiline ? Style.ColumnLimit : Line.FirstStartColumn + First->ColumnWidth; - FormatToken *Current = First->Next; - bool InFunctionDecl = Line.MightBeFunctionDecl; bool AlignArrayOfStructures = (Style.AlignArrayOfStructures != FormatStyle::AIAS_None && Line.Type == LT_ArrayOfStructInitializer); if (AlignArrayOfStructures) calculateArrayInitializerColumnList(Line); + const auto *FirstNonComment = Line.getFirstNonComment(); bool SeenName = false; bool LineIsFunctionDeclaration = false; - FormatToken *ClosingParen = nullptr; FormatToken *AfterLastAttribute = nullptr; + FormatToken *ClosingParen = nullptr; - for (auto *Tok = Current; Tok; Tok = Tok->Next) { + for (auto *Tok = FirstNonComment ? FirstNonComment->Next : nullptr; Tok; + Tok = Tok->Next) { if (Tok->is(TT_StartOfName)) SeenName = true; if (Tok->Previous->EndsCppAttributeGroup) @@ -3894,7 +3894,9 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { } } - if (IsCpp && (LineIsFunctionDeclaration || First->is(TT_CtorDtorDeclName)) && + if (IsCpp && + (LineIsFunctionDeclaration || + (FirstNonComment && FirstNonComment->is(TT_CtorDtorDeclName))) && Line.endsWith(tok::semi, tok::r_brace)) { auto *Tok = Line.Last->Previous; while (Tok->isNot(tok::r_brace)) @@ -3917,7 +3919,7 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { if (IsCpp) { if (!LineIsFunctionDeclaration) { // Annotate */&/&& in `operator` function calls as binary operators. - for (const auto *Tok = First; Tok; Tok = Tok->Next) { + for (const auto *Tok = FirstNonComment; Tok; Tok = Tok->Next) { if (Tok->isNot(tok::kw_operator)) continue; do { @@ -3960,7 +3962,8 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { } } - while (Current) { + bool InFunctionDecl = Line.MightBeFunctionDecl; + for (auto *Current = First->Next; Current; Current = Current->Next) { const FormatToken *Prev = Current->Previous; if (Current->is(TT_LineComment)) { if (Prev->is(BK_BracedInit) && Prev->opensScope()) { @@ -4050,13 +4053,11 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { } else { Current->SplitPenalty += 20 * Current->BindingStrength; } - -Current = Current->Next; } calculateUnbreakableTailLengths(Line); unsigned IndentLevel = Line.Level; - for (Current = First; Current; Current = Current->Next) { + for (auto *Current = First; Current; Current = Current->Next) { if (Current->Role) Current->Role->precomputeFormattingInfos(Current); if (Current->MatchingParen && diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index f432b95cc1e2b..6b71d0d18cf7a 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -269,6 +269,12 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) { ASSERT_EQ(Tokens.size(), 11u) << Tokens; EXPECT_TOKEN(Tokens[3], tok::ampamp, TT_PointerOrReference); + Tokens = annotate("template \n" +"enable_if_t, bool> // comment\n"
[clang] [clang-format] Fix a misannotation of PointerOrReference (PR #101291)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/101291 Fixes #101138. >From 0a162016899abb8a477e0fedad5be0416464ad4a Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Tue, 30 Jul 2024 23:20:12 -0700 Subject: [PATCH] [clang-format] Fix a misannotation of PointerOrReference Fixes #101138. --- clang/lib/Format/TokenAnnotator.cpp | 29 ++- clang/unittests/Format/TokenAnnotatorTest.cpp | 15 ++ 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 8cd5cf2484160..4ed3e9d0e8e85 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -3682,17 +3682,17 @@ static bool isFunctionDeclarationName(const LangOptions &LangOpts, const FormatToken &Current, const AnnotatedLine &Line, FormatToken *&ClosingParen) { - assert(Current.Previous); - if (Current.is(TT_FunctionDeclarationName)) return true; if (!Current.Tok.getIdentifierInfo()) return false; - const auto &Previous = *Current.Previous; + const auto *Prev = Current.getPreviousNonComment(); + assert(Prev); + const auto &Previous = *Prev; - if (const auto *PrevPrev = Previous.Previous; + if (const auto *PrevPrev = Previous.getPreviousNonComment(); PrevPrev && PrevPrev->is(TT_ObjCDecl)) { return false; } @@ -3859,20 +3859,20 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { First->TotalLength = First->IsMultiline ? Style.ColumnLimit : Line.FirstStartColumn + First->ColumnWidth; - FormatToken *Current = First->Next; - bool InFunctionDecl = Line.MightBeFunctionDecl; bool AlignArrayOfStructures = (Style.AlignArrayOfStructures != FormatStyle::AIAS_None && Line.Type == LT_ArrayOfStructInitializer); if (AlignArrayOfStructures) calculateArrayInitializerColumnList(Line); + const auto *FirstNonComment = Line.getFirstNonComment(); bool SeenName = false; bool LineIsFunctionDeclaration = false; - FormatToken *ClosingParen = nullptr; FormatToken *AfterLastAttribute = nullptr; + FormatToken *ClosingParen = nullptr; - for (auto *Tok = Current; Tok; Tok = Tok->Next) { + for (auto *Tok = FirstNonComment ? FirstNonComment->Next : nullptr; Tok; + Tok = Tok->Next) { if (Tok->is(TT_StartOfName)) SeenName = true; if (Tok->Previous->EndsCppAttributeGroup) @@ -3894,7 +3894,9 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { } } - if (IsCpp && (LineIsFunctionDeclaration || First->is(TT_CtorDtorDeclName)) && + if (IsCpp && + (LineIsFunctionDeclaration || + (FirstNonComment && FirstNonComment->is(TT_CtorDtorDeclName))) && Line.endsWith(tok::semi, tok::r_brace)) { auto *Tok = Line.Last->Previous; while (Tok->isNot(tok::r_brace)) @@ -3917,7 +3919,7 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { if (IsCpp) { if (!LineIsFunctionDeclaration) { // Annotate */&/&& in `operator` function calls as binary operators. - for (const auto *Tok = First; Tok; Tok = Tok->Next) { + for (const auto *Tok = FirstNonComment; Tok; Tok = Tok->Next) { if (Tok->isNot(tok::kw_operator)) continue; do { @@ -3960,7 +3962,8 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { } } - while (Current) { + bool InFunctionDecl = Line.MightBeFunctionDecl; + for (auto *Current = First->Next; Current; Current = Current->Next) { const FormatToken *Prev = Current->Previous; if (Current->is(TT_LineComment)) { if (Prev->is(BK_BracedInit) && Prev->opensScope()) { @@ -4050,13 +4053,11 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { } else { Current->SplitPenalty += 20 * Current->BindingStrength; } - -Current = Current->Next; } calculateUnbreakableTailLengths(Line); unsigned IndentLevel = Line.Level; - for (Current = First; Current; Current = Current->Next) { + for (auto *Current = First; Current; Current = Current->Next) { if (Current->Role) Current->Role->precomputeFormattingInfos(Current); if (Current->MatchingParen && diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index f432b95cc1e2b..ce8fdaaa91647 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -904,6 +904,21 @@ TEST_F(TokenAnnotatorTest, UnderstandsOverloadedOperators) { EXPECT_TOKEN(Tokens[9], tok::l_paren, TT_OverloadedOperatorLParen); EXPECT_TOKEN(Tokens[11], tok::amp, TT_PointerOrReference); + Tokens = annotate("template \n" +
[clang] [clang-format] Fix misannotations of `<` in ternary expressions (PR #100980)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/100980 Fixes #100300. >From 594a3517f9074cd2794366d3fba5fb4679785ce8 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Mon, 29 Jul 2024 00:19:02 -0700 Subject: [PATCH] [clang-format] Fix misannotations of `<` in ternary expressions Fixes #100300. --- clang/lib/Format/TokenAnnotator.cpp | 42 --- clang/unittests/Format/TokenAnnotatorTest.cpp | 15 +++ 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 16ab18e1af959..800a08bf9d3e7 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -155,8 +155,8 @@ class AnnotatingParser { if (NonTemplateLess.count(CurrentToken->Previous) > 0) return false; -const FormatToken &Previous = *CurrentToken->Previous; // The '<'. -if (Previous.Previous) { +if (const auto &Previous = *CurrentToken->Previous; // The '<'. +Previous.Previous) { if (Previous.Previous->Tok.isLiteral()) return false; if (Previous.Previous->is(tok::r_brace)) @@ -176,11 +176,13 @@ class AnnotatingParser { FormatToken *Left = CurrentToken->Previous; Left->ParentBracket = Contexts.back().ContextKind; ScopedContextCreator ContextCreator(*this, tok::less, 12); - Contexts.back().IsExpression = false; + +const auto *BeforeLess = Left->Previous; + // If there's a template keyword before the opening angle bracket, this is a // template parameter, not an argument. -if (Left->Previous && Left->Previous->isNot(tok::kw_template)) +if (BeforeLess && BeforeLess->isNot(tok::kw_template)) Contexts.back().ContextType = Context::TemplateArgument; if (Style.Language == FormatStyle::LK_Java && @@ -188,19 +190,24 @@ class AnnotatingParser { next(); } -while (CurrentToken) { +for (bool SeenTernaryOperator = false; CurrentToken;) { + const bool InExpr = Contexts[Contexts.size() - 2].IsExpression; if (CurrentToken->is(tok::greater)) { +const auto *Next = CurrentToken->Next; // Try to do a better job at looking for ">>" within the condition of // a statement. Conservatively insert spaces between consecutive ">" // tokens to prevent splitting right bitshift operators and potentially // altering program semantics. This check is overly conservative and // will prevent spaces from being inserted in select nested template // parameter cases, but should not alter program semantics. -if (CurrentToken->Next && CurrentToken->Next->is(tok::greater) && +if (Next && Next->is(tok::greater) && Left->ParentBracket != tok::less && CurrentToken->getStartOfNonWhitespace() == -CurrentToken->Next->getStartOfNonWhitespace().getLocWithOffset( --1)) { +Next->getStartOfNonWhitespace().getLocWithOffset(-1)) { + return false; +} +if (InExpr && SeenTernaryOperator && +(!Next || Next->isNot(tok::l_paren))) { return false; } Left->MatchingParen = CurrentToken; @@ -211,14 +218,14 @@ class AnnotatingParser { // msg: < item: data > // In TT_TextProto, map does not occur. if (Style.Language == FormatStyle::LK_TextProto || -(Style.Language == FormatStyle::LK_Proto && Left->Previous && - Left->Previous->isOneOf(TT_SelectorName, TT_DictLiteral))) { +(Style.Language == FormatStyle::LK_Proto && BeforeLess && + BeforeLess->isOneOf(TT_SelectorName, TT_DictLiteral))) { CurrentToken->setType(TT_DictLiteral); } else { CurrentToken->setType(TT_TemplateCloser); CurrentToken->Tok.setLength(1); } -if (CurrentToken->Next && CurrentToken->Next->Tok.isLiteral()) +if (Next && Next->Tok.isLiteral()) return false; next(); return true; @@ -230,18 +237,21 @@ class AnnotatingParser { } if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace)) return false; + const auto &Prev = *CurrentToken->Previous; // If a && or || is found and interpreted as a binary operator, this set // of angles is likely part of something like "a < b && c > d". If the // angles are inside an expression, the ||/&& might also be a binary // operator that was misinterpreted because we are parsing template // parameters. // FIXME: This is getting out of hand, write a decent parser. - if (CurrentToken->Previous->isOneOf(tok::pipepipe, tok::ampamp) && - CurrentToken->Previous->is(TT_BinaryOperator) && - Contexts[Contexts.size() - 2].IsExpression && - !Line.startsWith(tok::kw_template)) { -return false; + if (InExpr &&
[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 &Replaces, 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 = [&OpeningParen] { -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 &b)"); - 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 &State, 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 &Tok) { +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 &Tok) { +return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous && + Tok.Previous->is(tok::identifier); + }; + const auto IsInTemplateString = [&](const FormatToken &Tok) { +if (!Style.isJavaScript()) + return false; +for (const FormatToken *Prev = &Tok; 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 &Tok) { +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 &State, 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 &State, 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 TokenAn
[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 &a, const void *aa\n" + ") const {\n" + " return true;\n" + "}", + Style); + verifyFormat("bool (\n" + "const bool &aa, 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" + "[&b](\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 &a, const void *aa\n" + ") const {\n" + " return true;\n" + "}", + Style); + verifyFormat("bool (\n" + "const bool &aa, 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); EXP
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
@@ -803,6 +803,51 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, 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 &Tok) { +return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous && + Tok.Previous->is(tok::identifier); + }; + const auto IsInTemplateString = [&](const FormatToken &Tok) { 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 &State, 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 &Tok) { +return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous && + Tok.Previous->is(tok::identifier); + }; + const auto IsInTemplateString = [&](const FormatToken &Tok) { +if (!Style.isJavaScript()) + return false; +for (const FormatToken *Prev = &Tok; 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 &Tok) { +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 &Tok) { + const auto IsSimpleFunctionCall = [&](const FormatToken &Tok) { +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 &State, 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 &Tok) { +return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous && + Tok.Previous->is(tok::identifier); + }; + const auto IsInTemplateString = [&](const FormatToken &Tok) { +if (!Style.isJavaScript()) + return false; +for (const FormatToken *Prev = &Tok; Prev; Prev = Prev->Previous) { owenca wrote: ```suggestion for (const auto *Prev = &Tok; 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 &State, 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 &Tok) { 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 &State, 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 &State, 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 &Tok) { /// 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(&OpeningParen)) { // 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 &a or &&a. 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 &LParen) { +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 &LParen) { +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 &Line, 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 &Options = 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 &Line, 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 &Options = 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 &Current, Style.BreakInheritanceList != FormatStyle::BILS_BeforeComma)); } +// Returns \c true if \c Current starts a new operand in a binary operation. +static bool startsNextOperand(const FormatToken &Current) { + const FormatToken &Previous = *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 &Current, Style.BreakInheritanceList != FormatStyle::BILS_BeforeComma)); } +// Returns \c true if \c Current starts a new operand in a binary operation. +static bool startsNextOperand(const FormatToken &Current) { + const FormatToken &Previous = *Current.Previous; owenca wrote: Assert `Current.Previous` before dereferencing it. ```suggestion const auto &Previous = *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 &Current, 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 &Line) 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 +284
[clang] [clang-format] Improve BlockIndent at ColumnLimit (PR #93140)
@@ -803,6 +803,60 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, 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 &Line) 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 +2
[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