[clang] cad708b - [clang-format] Recognize Verilog non-blocking assignment
via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 5 17:03:44 PST 2023
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) {
More information about the cfe-commits
mailing list