Skip to content

Commit cad708b

Browse files
committed
[clang-format] Recognize Verilog non-blocking assignment
Reviewed By: HazardyKnusperkeks, owenpan Differential Revision: https://reviews.llvm.org/D142891
1 parent 26182df commit cad708b

File tree

4 files changed

+85
-1
lines changed

4 files changed

+85
-1
lines changed

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,6 +1647,7 @@ class AnnotatingParser {
16471647
bool CaretFound = false;
16481648
bool InCpp11AttributeSpecifier = false;
16491649
bool InCSharpAttributeSpecifier = false;
1650+
bool VerilogAssignmentFound = false;
16501651
enum {
16511652
Unknown,
16521653
// Like the part after `:` in a constructor.
@@ -1944,6 +1945,17 @@ class AnnotatingParser {
19441945
(!Current.Previous || Current.Previous->isNot(tok::l_square)) &&
19451946
(!Current.is(tok::greater) &&
19461947
Style.Language != FormatStyle::LK_TextProto)) {
1948+
if (Style.isVerilog()) {
1949+
if (Current.is(tok::lessequal) && Contexts.size() == 1 &&
1950+
!Contexts.back().VerilogAssignmentFound) {
1951+
// In Verilog `<=` is assignment if in its own statement. It is a
1952+
// statement instead of an expression, that is it can not be chained.
1953+
Current.ForcedPrecedence = prec::Assignment;
1954+
Current.setFinalizedType(TT_BinaryOperator);
1955+
}
1956+
if (Current.getPrecedence() == prec::Assignment)
1957+
Contexts.back().VerilogAssignmentFound = true;
1958+
}
19471959
Current.setType(TT_BinaryOperator);
19481960
} else if (Current.is(tok::comment)) {
19491961
if (Current.TokenText.startswith("/*")) {

clang/lib/Format/WhitespaceManager.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,12 @@ void WhitespaceManager::alignConsecutiveAssignments() {
838838

839839
return Style.AlignConsecutiveAssignments.AlignCompound
840840
? C.Tok->getPrecedence() == prec::Assignment
841-
: C.Tok->is(tok::equal);
841+
: (C.Tok->is(tok::equal) ||
842+
// In Verilog the '<=' is not a compound assignment, thus
843+
// it is aligned even when the AlignCompound option is not
844+
// set.
845+
(Style.isVerilog() && C.Tok->is(tok::lessequal) &&
846+
C.Tok->getPrecedence() == prec::Assignment));
842847
},
843848
Changes, /*StartAt=*/0, Style.AlignConsecutiveAssignments,
844849
/*RightJustify=*/true);

clang/unittests/Format/FormatTestVerilog.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,58 @@ class FormatTestVerilog : public ::testing::Test {
4545
}
4646
};
4747

48+
TEST_F(FormatTestVerilog, Align) {
49+
FormatStyle Style = getLLVMStyle(FormatStyle::LK_Verilog);
50+
Style.AlignConsecutiveAssignments.Enabled = true;
51+
verifyFormat("x <= x;\n"
52+
"sfdbddfbdfbb <= x;\n"
53+
"x = x;",
54+
Style);
55+
verifyFormat("x = x;\n"
56+
"sfdbddfbdfbb = x;\n"
57+
"x = x;",
58+
Style);
59+
// Compound assignments are not aligned by default. '<=' is not a compound
60+
// assignment.
61+
verifyFormat("x <= x;\n"
62+
"sfdbddfbdfbb <= x;",
63+
Style);
64+
verifyFormat("x += x;\n"
65+
"sfdbddfbdfbb <= x;",
66+
Style);
67+
verifyFormat("x <<= x;\n"
68+
"sfdbddfbdfbb <= x;",
69+
Style);
70+
verifyFormat("x <<<= x;\n"
71+
"sfdbddfbdfbb <= x;",
72+
Style);
73+
verifyFormat("x >>= x;\n"
74+
"sfdbddfbdfbb <= x;",
75+
Style);
76+
verifyFormat("x >>>= x;\n"
77+
"sfdbddfbdfbb <= x;",
78+
Style);
79+
Style.AlignConsecutiveAssignments.AlignCompound = true;
80+
verifyFormat("x <= x;\n"
81+
"sfdbddfbdfbb <= x;",
82+
Style);
83+
verifyFormat("x += x;\n"
84+
"sfdbddfbdfbb <= x;",
85+
Style);
86+
verifyFormat("x <<= x;\n"
87+
"sfdbddfbdfbb <= x;",
88+
Style);
89+
verifyFormat("x <<<= x;\n"
90+
"sfdbddfbdfbb <= x;",
91+
Style);
92+
verifyFormat("x >>= x;\n"
93+
"sfdbddfbdfbb <= x;",
94+
Style);
95+
verifyFormat("x >>>= x;\n"
96+
"sfdbddfbdfbb <= x;",
97+
Style);
98+
}
99+
48100
TEST_F(FormatTestVerilog, BasedLiteral) {
49101
verifyFormat("x = '0;");
50102
verifyFormat("x = '1;");

clang/unittests/Format/TokenAnnotatorTest.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,21 @@ TEST_F(TokenAnnotatorTest, UnderstandsVerilogOperators) {
13141314
EXPECT_TOKEN(Tokens[5], tok::question, TT_ConditionalExpr);
13151315
EXPECT_TOKEN(Tokens[7], tok::colon, TT_ConditionalExpr);
13161316
EXPECT_TOKEN(Tokens[9], tok::colon, TT_GotoLabelColon);
1317+
// Non-blocking assignments.
1318+
Tokens = Annotate("a <= b;");
1319+
ASSERT_EQ(Tokens.size(), 5u);
1320+
EXPECT_TOKEN(Tokens[1], tok::lessequal, TT_BinaryOperator);
1321+
EXPECT_TOKEN_PRECEDENCE(Tokens[1], prec::Assignment);
1322+
Tokens = Annotate("if (a <= b) break;");
1323+
ASSERT_EQ(Tokens.size(), 9u);
1324+
EXPECT_TOKEN(Tokens[3], tok::lessequal, TT_BinaryOperator);
1325+
EXPECT_TOKEN_PRECEDENCE(Tokens[3], prec::Relational);
1326+
Tokens = Annotate("a <= b <= a;");
1327+
ASSERT_EQ(Tokens.size(), 7u);
1328+
EXPECT_TOKEN(Tokens[1], tok::lessequal, TT_BinaryOperator);
1329+
EXPECT_TOKEN_PRECEDENCE(Tokens[1], prec::Assignment);
1330+
EXPECT_TOKEN(Tokens[3], tok::lessequal, TT_BinaryOperator);
1331+
EXPECT_TOKEN_PRECEDENCE(Tokens[3], prec::Relational);
13171332
}
13181333

13191334
TEST_F(TokenAnnotatorTest, UnderstandConstructors) {

0 commit comments

Comments
 (0)