[clang] [clang-format] Correctly annotate C++ alternative operators in C (PR #92880)
https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/92880 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Correctly annotate C++ alternative operators in C (PR #92880)
https://github.com/HazardyKnusperkeks approved this pull request. https://github.com/llvm/llvm-project/pull/92880 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Correctly annotate C++ alternative operators in C (PR #92880)
https://github.com/rymiel approved this pull request. https://github.com/llvm/llvm-project/pull/92880 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Correctly annotate C++ alternative operators in C (PR #92880)
llvmbot wrote: @llvm/pr-subscribers-clang-format Author: Owen Pan (owenca) Changes PR #90161 uncovered a bug that annotates C++ xor as UnaryOperator if followed by a binary operator. This patch fixes that and all other C++ alternative operator keywords when followed by a binary operator in C. Fixes #92688. --- Full diff: https://github.com/llvm/llvm-project/pull/92880.diff 3 Files Affected: - (modified) clang/lib/Format/UnwrappedLineParser.cpp (+17-4) - (modified) clang/unittests/Format/FormatTest.cpp (+2) - (modified) clang/unittests/Format/TokenAnnotatorTest.cpp (+54) ``diff diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 3dd10f6bd2b31..b6f7567adc140 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -1410,6 +1410,13 @@ void UnwrappedLineParser::readTokenWithJavaScriptASI() { } } +static bool isAltOperator(const FormatToken &Tok) { + return isalpha(Tok.TokenText[0]) && + Tok.isOneOf(tok::ampamp, tok::ampequal, tok::amp, tok::pipe, + tok::tilde, tok::exclaim, tok::exclaimequal, tok::pipepipe, + tok::pipeequal, tok::caret, tok::caretequal); +} + void UnwrappedLineParser::parseStructuralElement( const FormatToken *OpeningBrace, IfStmtKind *IfKind, FormatToken **IfLeftBrace, bool *HasDoWhile, bool *HasLabel) { @@ -1689,9 +1696,15 @@ void UnwrappedLineParser::parseStructuralElement( break; } - const bool InRequiresExpression = - OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace); - do { + for (const bool InRequiresExpression = + OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace); + !eof();) { +if (IsCpp && isAltOperator(*FormatTok)) { + if (auto *Next = Tokens->peekNextToken(/*SkipComment=*/true); + Next && Next->isBinaryOperator()) { +FormatTok->Tok.setKind(tok::identifier); + } +} const FormatToken *Previous = FormatTok->Previous; switch (FormatTok->Tok.getKind()) { case tok::at: @@ -2122,7 +2135,7 @@ void UnwrappedLineParser::parseStructuralElement( nextToken(); break; } - } while (!eof()); + } } bool UnwrappedLineParser::tryToParsePropertyAccessor() { diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 2f0c0f0266774..a9df994189f00 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -17340,12 +17340,14 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeAssignmentOperators) { verifyFormat("int a = 5;"); verifyFormat("a += 42;"); verifyFormat("a or_eq 8;"); + verifyFormat("xor = foo;"); FormatStyle Spaces = getLLVMStyle(); Spaces.SpaceBeforeAssignmentOperators = false; verifyFormat("int a= 5;", Spaces); verifyFormat("a+= 42;", Spaces); verifyFormat("a or_eq 8;", Spaces); + verifyFormat("xor= foo;", Spaces); } TEST_F(FormatTest, ConfigurableSpaceBeforeColon) { diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 45c1554308c9b..6ea9c4a241dc5 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -3015,6 +3015,60 @@ TEST_F(TokenAnnotatorTest, SwitchExpression) { EXPECT_TOKEN(Tokens[20], tok::arrow, TT_CaseLabelArrow); } +TEST_F(TokenAnnotatorTest, CppAltOperatorKeywords) { + auto Tokens = annotate("a = b and c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::ampamp, TT_BinaryOperator); + + Tokens = annotate("a = b and_eq c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::ampequal, TT_BinaryOperator); + + Tokens = annotate("a = b bitand c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::amp, TT_BinaryOperator); + + Tokens = annotate("a = b bitor c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::pipe, TT_BinaryOperator); + + Tokens = annotate("a = b compl c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::tilde, TT_UnaryOperator); + + Tokens = annotate("a = b not c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::exclaim, TT_UnaryOperator); + + Tokens = annotate("a = b not_eq c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::exclaimequal, TT_BinaryOperator); + + Tokens = annotate("a = b or c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::pipepipe, TT_BinaryOperator); + + Tokens = annotate("a = b or_eq c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::pipeequal, TT_BinaryOperator); + + Tokens = annotate("a = b xor c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::caret, TT_BinaryOperator); + + Tokens = annotate("a = b xor_eq c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::caretequal, TT_BinaryOperator); + +
[clang] [clang-format] Correctly annotate C++ alternative operators in C (PR #92880)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/92880 PR #90161 uncovered a bug that annotates C++ xor as UnaryOperator if followed by a binary operator. This patch fixes that and all other C++ alternative operator keywords when followed by a binary operator in C. Fixes #92688. >From 6d5fc044d8b221ea0643e1df0d511e693b500f07 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Tue, 21 May 2024 01:11:20 -0700 Subject: [PATCH] [clang-format] Correctly annotate C++ alternative operators in C PR #90161 uncovered a bug that annotates C++ xor as UnaryOperator if followed by a binary operator. This patch fixes that and all other C++ alternative operator keywords when followed by a binary operator in C. Fixes #92688. --- clang/lib/Format/UnwrappedLineParser.cpp | 21 ++-- clang/unittests/Format/FormatTest.cpp | 2 + clang/unittests/Format/TokenAnnotatorTest.cpp | 54 +++ 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 3dd10f6bd2b31..b6f7567adc140 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -1410,6 +1410,13 @@ void UnwrappedLineParser::readTokenWithJavaScriptASI() { } } +static bool isAltOperator(const FormatToken &Tok) { + return isalpha(Tok.TokenText[0]) && + Tok.isOneOf(tok::ampamp, tok::ampequal, tok::amp, tok::pipe, + tok::tilde, tok::exclaim, tok::exclaimequal, tok::pipepipe, + tok::pipeequal, tok::caret, tok::caretequal); +} + void UnwrappedLineParser::parseStructuralElement( const FormatToken *OpeningBrace, IfStmtKind *IfKind, FormatToken **IfLeftBrace, bool *HasDoWhile, bool *HasLabel) { @@ -1689,9 +1696,15 @@ void UnwrappedLineParser::parseStructuralElement( break; } - const bool InRequiresExpression = - OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace); - do { + for (const bool InRequiresExpression = + OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace); + !eof();) { +if (IsCpp && isAltOperator(*FormatTok)) { + if (auto *Next = Tokens->peekNextToken(/*SkipComment=*/true); + Next && Next->isBinaryOperator()) { +FormatTok->Tok.setKind(tok::identifier); + } +} const FormatToken *Previous = FormatTok->Previous; switch (FormatTok->Tok.getKind()) { case tok::at: @@ -2122,7 +2135,7 @@ void UnwrappedLineParser::parseStructuralElement( nextToken(); break; } - } while (!eof()); + } } bool UnwrappedLineParser::tryToParsePropertyAccessor() { diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 2f0c0f0266774..a9df994189f00 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -17340,12 +17340,14 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeAssignmentOperators) { verifyFormat("int a = 5;"); verifyFormat("a += 42;"); verifyFormat("a or_eq 8;"); + verifyFormat("xor = foo;"); FormatStyle Spaces = getLLVMStyle(); Spaces.SpaceBeforeAssignmentOperators = false; verifyFormat("int a= 5;", Spaces); verifyFormat("a+= 42;", Spaces); verifyFormat("a or_eq 8;", Spaces); + verifyFormat("xor= foo;", Spaces); } TEST_F(FormatTest, ConfigurableSpaceBeforeColon) { diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 45c1554308c9b..6ea9c4a241dc5 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -3015,6 +3015,60 @@ TEST_F(TokenAnnotatorTest, SwitchExpression) { EXPECT_TOKEN(Tokens[20], tok::arrow, TT_CaseLabelArrow); } +TEST_F(TokenAnnotatorTest, CppAltOperatorKeywords) { + auto Tokens = annotate("a = b and c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::ampamp, TT_BinaryOperator); + + Tokens = annotate("a = b and_eq c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::ampequal, TT_BinaryOperator); + + Tokens = annotate("a = b bitand c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::amp, TT_BinaryOperator); + + Tokens = annotate("a = b bitor c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::pipe, TT_BinaryOperator); + + Tokens = annotate("a = b compl c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::tilde, TT_UnaryOperator); + + Tokens = annotate("a = b not c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::exclaim, TT_UnaryOperator); + + Tokens = annotate("a = b not_eq c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::exclaimequal, TT_BinaryOperator); + + Tokens = annotate("a = b or c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::pipepipe, TT_BinaryOperator); + + Tokens = annotate("a = b or_eq