Author: sstwcw Date: 2023-02-06T00:58:11Z New Revision: cad708b9a1ecbf5645706056bb7c4fc0ea4721b6
URL: https://github.com/llvm/llvm-project/commit/cad708b9a1ecbf5645706056bb7c4fc0ea4721b6 DIFF: https://github.com/llvm/llvm-project/commit/cad708b9a1ecbf5645706056bb7c4fc0ea4721b6.diff LOG: [clang-format] Recognize Verilog non-blocking assignment Reviewed By: HazardyKnusperkeks, owenpan Differential Revision: https://reviews.llvm.org/D142891 Added: Modified: clang/lib/Format/TokenAnnotator.cpp clang/lib/Format/WhitespaceManager.cpp clang/unittests/Format/FormatTestVerilog.cpp clang/unittests/Format/TokenAnnotatorTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 161720ecb770a..40e1951872243 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1647,6 +1647,7 @@ class AnnotatingParser { bool CaretFound = false; bool InCpp11AttributeSpecifier = false; bool InCSharpAttributeSpecifier = false; + bool VerilogAssignmentFound = false; enum { Unknown, // Like the part after `:` in a constructor. @@ -1944,6 +1945,17 @@ class AnnotatingParser { (!Current.Previous || Current.Previous->isNot(tok::l_square)) && (!Current.is(tok::greater) && Style.Language != FormatStyle::LK_TextProto)) { + if (Style.isVerilog()) { + if (Current.is(tok::lessequal) && Contexts.size() == 1 && + !Contexts.back().VerilogAssignmentFound) { + // In Verilog `<=` is assignment if in its own statement. It is a + // statement instead of an expression, that is it can not be chained. + Current.ForcedPrecedence = prec::Assignment; + Current.setFinalizedType(TT_BinaryOperator); + } + if (Current.getPrecedence() == prec::Assignment) + Contexts.back().VerilogAssignmentFound = true; + } Current.setType(TT_BinaryOperator); } else if (Current.is(tok::comment)) { if (Current.TokenText.startswith("/*")) { diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index 9951906b6af01..a68759418d595 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -838,7 +838,12 @@ void WhitespaceManager::alignConsecutiveAssignments() { return Style.AlignConsecutiveAssignments.AlignCompound ? C.Tok->getPrecedence() == prec::Assignment - : C.Tok->is(tok::equal); + : (C.Tok->is(tok::equal) || + // In Verilog the '<=' is not a compound assignment, thus + // it is aligned even when the AlignCompound option is not + // set. + (Style.isVerilog() && C.Tok->is(tok::lessequal) && + C.Tok->getPrecedence() == prec::Assignment)); }, Changes, /*StartAt=*/0, Style.AlignConsecutiveAssignments, /*RightJustify=*/true); diff --git a/clang/unittests/Format/FormatTestVerilog.cpp b/clang/unittests/Format/FormatTestVerilog.cpp index 92931d3e5e74c..7931a31decfa5 100644 --- a/clang/unittests/Format/FormatTestVerilog.cpp +++ b/clang/unittests/Format/FormatTestVerilog.cpp @@ -45,6 +45,58 @@ class FormatTestVerilog : public ::testing::Test { } }; +TEST_F(FormatTestVerilog, Align) { + FormatStyle Style = getLLVMStyle(FormatStyle::LK_Verilog); + Style.AlignConsecutiveAssignments.Enabled = true; + verifyFormat("x <= x;\n" + "sfdbddfbdfbb <= x;\n" + "x = x;", + Style); + verifyFormat("x = x;\n" + "sfdbddfbdfbb = x;\n" + "x = x;", + Style); + // Compound assignments are not aligned by default. '<=' is not a compound + // assignment. + verifyFormat("x <= x;\n" + "sfdbddfbdfbb <= x;", + Style); + verifyFormat("x += x;\n" + "sfdbddfbdfbb <= x;", + Style); + verifyFormat("x <<= x;\n" + "sfdbddfbdfbb <= x;", + Style); + verifyFormat("x <<<= x;\n" + "sfdbddfbdfbb <= x;", + Style); + verifyFormat("x >>= x;\n" + "sfdbddfbdfbb <= x;", + Style); + verifyFormat("x >>>= x;\n" + "sfdbddfbdfbb <= x;", + Style); + Style.AlignConsecutiveAssignments.AlignCompound = true; + verifyFormat("x <= x;\n" + "sfdbddfbdfbb <= x;", + Style); + verifyFormat("x += x;\n" + "sfdbddfbdfbb <= x;", + Style); + verifyFormat("x <<= x;\n" + "sfdbddfbdfbb <= x;", + Style); + verifyFormat("x <<<= x;\n" + "sfdbddfbdfbb <= x;", + Style); + verifyFormat("x >>= x;\n" + "sfdbddfbdfbb <= x;", + Style); + verifyFormat("x >>>= x;\n" + "sfdbddfbdfbb <= x;", + Style); +} + TEST_F(FormatTestVerilog, BasedLiteral) { verifyFormat("x = '0;"); verifyFormat("x = '1;"); diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index b27bb69d6aceb..87d86ec602708 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1314,6 +1314,21 @@ TEST_F(TokenAnnotatorTest, UnderstandsVerilogOperators) { EXPECT_TOKEN(Tokens[5], tok::question, TT_ConditionalExpr); EXPECT_TOKEN(Tokens[7], tok::colon, TT_ConditionalExpr); EXPECT_TOKEN(Tokens[9], tok::colon, TT_GotoLabelColon); + // Non-blocking assignments. + Tokens = Annotate("a <= b;"); + ASSERT_EQ(Tokens.size(), 5u); + EXPECT_TOKEN(Tokens[1], tok::lessequal, TT_BinaryOperator); + EXPECT_TOKEN_PRECEDENCE(Tokens[1], prec::Assignment); + Tokens = Annotate("if (a <= b) break;"); + ASSERT_EQ(Tokens.size(), 9u); + EXPECT_TOKEN(Tokens[3], tok::lessequal, TT_BinaryOperator); + EXPECT_TOKEN_PRECEDENCE(Tokens[3], prec::Relational); + Tokens = Annotate("a <= b <= a;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[1], tok::lessequal, TT_BinaryOperator); + EXPECT_TOKEN_PRECEDENCE(Tokens[1], prec::Assignment); + EXPECT_TOKEN(Tokens[3], tok::lessequal, TT_BinaryOperator); + EXPECT_TOKEN_PRECEDENCE(Tokens[3], prec::Relational); } TEST_F(TokenAnnotatorTest, UnderstandConstructors) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits