Skip to content

Commit d719876

Browse files
authored
[clang-format] Recognize Verilog DPI export and import (#165595)
The directives should not change the indentation level. Previously the program erroneously added an indentation level when it saw the `function` keyword.
1 parent 7a0f7db commit d719876

File tree

4 files changed

+180
-52
lines changed

4 files changed

+180
-52
lines changed

clang/lib/Format/FormatToken.h

Lines changed: 137 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,6 +1170,7 @@ struct AdditionalKeywords {
11701170
kw_checker = &IdentTable.get("checker");
11711171
kw_clocking = &IdentTable.get("clocking");
11721172
kw_constraint = &IdentTable.get("constraint");
1173+
kw_context = &IdentTable.get("context");
11731174
kw_cover = &IdentTable.get("cover");
11741175
kw_covergroup = &IdentTable.get("covergroup");
11751176
kw_coverpoint = &IdentTable.get("coverpoint");
@@ -1325,50 +1326,138 @@ struct AdditionalKeywords {
13251326
// Some keywords are not included here because they don't need special
13261327
// treatment like `showcancelled` or they should be treated as identifiers
13271328
// like `int` and `logic`.
1328-
VerilogExtraKeywords = std::unordered_set<IdentifierInfo *>(
1329-
{kw_always, kw_always_comb, kw_always_ff,
1330-
kw_always_latch, kw_assert, kw_assign,
1331-
kw_assume, kw_automatic, kw_before,
1332-
kw_begin, kw_bins, kw_binsof,
1333-
kw_casex, kw_casez, kw_celldefine,
1334-
kw_checker, kw_clocking, kw_constraint,
1335-
kw_cover, kw_covergroup, kw_coverpoint,
1336-
kw_disable, kw_dist, kw_edge,
1337-
kw_end, kw_endcase, kw_endchecker,
1338-
kw_endclass, kw_endclocking, kw_endfunction,
1339-
kw_endgenerate, kw_endgroup, kw_endinterface,
1340-
kw_endmodule, kw_endpackage, kw_endprimitive,
1341-
kw_endprogram, kw_endproperty, kw_endsequence,
1342-
kw_endspecify, kw_endtable, kw_endtask,
1343-
kw_extends, kw_final, kw_foreach,
1344-
kw_forever, kw_fork, kw_function,
1345-
kw_generate, kw_highz0, kw_highz1,
1346-
kw_iff, kw_ifnone, kw_ignore_bins,
1347-
kw_illegal_bins, kw_implements, kw_import,
1348-
kw_initial, kw_inout, kw_input,
1349-
kw_inside, kw_interconnect, kw_interface,
1350-
kw_intersect, kw_join, kw_join_any,
1351-
kw_join_none, kw_large, kw_let,
1352-
kw_local, kw_localparam, kw_macromodule,
1353-
kw_matches, kw_medium, kw_negedge,
1354-
kw_output, kw_package, kw_packed,
1355-
kw_parameter, kw_posedge, kw_primitive,
1356-
kw_priority, kw_program, kw_property,
1357-
kw_pull0, kw_pull1, kw_pure,
1358-
kw_rand, kw_randc, kw_randcase,
1359-
kw_randsequence, kw_ref, kw_repeat,
1360-
kw_sample, kw_scalared, kw_sequence,
1361-
kw_small, kw_soft, kw_solve,
1362-
kw_specify, kw_specparam, kw_strong0,
1363-
kw_strong1, kw_supply0, kw_supply1,
1364-
kw_table, kw_tagged, kw_task,
1365-
kw_tri, kw_tri0, kw_tri1,
1366-
kw_triand, kw_trior, kw_trireg,
1367-
kw_unique, kw_unique0, kw_uwire,
1368-
kw_var, kw_vectored, kw_wait,
1369-
kw_wand, kw_weak0, kw_weak1,
1370-
kw_wildcard, kw_wire, kw_with,
1371-
kw_wor, kw_verilogHash, kw_verilogHashHash});
1329+
VerilogExtraKeywords =
1330+
std::unordered_set<IdentifierInfo *>({kw_always,
1331+
kw_always_comb,
1332+
kw_always_ff,
1333+
kw_always_latch,
1334+
kw_assert,
1335+
kw_assign,
1336+
kw_assume,
1337+
kw_automatic,
1338+
kw_before,
1339+
kw_begin,
1340+
kw_bins,
1341+
kw_binsof,
1342+
kw_casex,
1343+
kw_casez,
1344+
kw_celldefine,
1345+
kw_checker,
1346+
kw_clocking,
1347+
kw_constraint,
1348+
kw_context,
1349+
kw_cover,
1350+
kw_covergroup,
1351+
kw_coverpoint,
1352+
kw_disable,
1353+
kw_dist,
1354+
kw_edge,
1355+
kw_end,
1356+
kw_endcase,
1357+
kw_endchecker,
1358+
kw_endclass,
1359+
kw_endclocking,
1360+
kw_endfunction,
1361+
kw_endgenerate,
1362+
kw_endgroup,
1363+
kw_endinterface,
1364+
kw_endmodule,
1365+
kw_endpackage,
1366+
kw_endprimitive,
1367+
kw_endprogram,
1368+
kw_endproperty,
1369+
kw_endsequence,
1370+
kw_endspecify,
1371+
kw_endtable,
1372+
kw_endtask,
1373+
kw_extends,
1374+
kw_final,
1375+
kw_foreach,
1376+
kw_forever,
1377+
kw_fork,
1378+
kw_function,
1379+
kw_generate,
1380+
kw_highz0,
1381+
kw_highz1,
1382+
kw_iff,
1383+
kw_ifnone,
1384+
kw_ignore_bins,
1385+
kw_illegal_bins,
1386+
kw_implements,
1387+
kw_import,
1388+
kw_initial,
1389+
kw_inout,
1390+
kw_input,
1391+
kw_inside,
1392+
kw_interconnect,
1393+
kw_interface,
1394+
kw_intersect,
1395+
kw_join,
1396+
kw_join_any,
1397+
kw_join_none,
1398+
kw_large,
1399+
kw_let,
1400+
kw_local,
1401+
kw_localparam,
1402+
kw_macromodule,
1403+
kw_matches,
1404+
kw_medium,
1405+
kw_module,
1406+
kw_negedge,
1407+
kw_output,
1408+
kw_package,
1409+
kw_packed,
1410+
kw_parameter,
1411+
kw_posedge,
1412+
kw_primitive,
1413+
kw_priority,
1414+
kw_program,
1415+
kw_property,
1416+
kw_pull0,
1417+
kw_pull1,
1418+
kw_pure,
1419+
kw_rand,
1420+
kw_randc,
1421+
kw_randcase,
1422+
kw_randsequence,
1423+
kw_ref,
1424+
kw_repeat,
1425+
kw_sample,
1426+
kw_scalared,
1427+
kw_sequence,
1428+
kw_small,
1429+
kw_soft,
1430+
kw_solve,
1431+
kw_specify,
1432+
kw_specparam,
1433+
kw_strong0,
1434+
kw_strong1,
1435+
kw_supply0,
1436+
kw_supply1,
1437+
kw_table,
1438+
kw_tagged,
1439+
kw_task,
1440+
kw_tri,
1441+
kw_tri0,
1442+
kw_tri1,
1443+
kw_triand,
1444+
kw_trior,
1445+
kw_trireg,
1446+
kw_unique,
1447+
kw_unique0,
1448+
kw_uwire,
1449+
kw_var,
1450+
kw_vectored,
1451+
kw_wait,
1452+
kw_wand,
1453+
kw_weak0,
1454+
kw_weak1,
1455+
kw_wildcard,
1456+
kw_wire,
1457+
kw_with,
1458+
kw_wor,
1459+
kw_verilogHash,
1460+
kw_verilogHashHash});
13721461

13731462
TableGenExtraKeywords = std::unordered_set<IdentifierInfo *>({
13741463
kw_assert,
@@ -1516,6 +1605,7 @@ struct AdditionalKeywords {
15161605
IdentifierInfo *kw_checker;
15171606
IdentifierInfo *kw_clocking;
15181607
IdentifierInfo *kw_constraint;
1608+
IdentifierInfo *kw_context;
15191609
IdentifierInfo *kw_cover;
15201610
IdentifierInfo *kw_covergroup;
15211611
IdentifierInfo *kw_coverpoint;
@@ -1800,11 +1890,13 @@ struct AdditionalKeywords {
18001890
case tok::kw_continue:
18011891
case tok::kw_default:
18021892
case tok::kw_do:
1803-
case tok::kw_extern:
18041893
case tok::kw_else:
18051894
case tok::kw_enum:
1895+
case tok::kw_export:
1896+
case tok::kw_extern:
18061897
case tok::kw_for:
18071898
case tok::kw_if:
1899+
case tok::kw_import:
18081900
case tok::kw_restrict:
18091901
case tok::kw_signed:
18101902
case tok::kw_static:

clang/lib/Format/UnwrappedLineParser.cpp

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,15 +1592,14 @@ void UnwrappedLineParser::parseStructuralElement(
15921592
parseTryCatch();
15931593
return;
15941594
case tok::kw_extern:
1595-
nextToken();
15961595
if (Style.isVerilog()) {
1597-
// In Verilog and extern module declaration looks like a start of module.
1596+
// In Verilog an extern module declaration looks like a start of module.
15981597
// But there is no body and endmodule. So we handle it separately.
1599-
if (Keywords.isVerilogHierarchy(*FormatTok)) {
1600-
parseVerilogHierarchyHeader();
1601-
return;
1602-
}
1603-
} else if (FormatTok->is(tok::string_literal)) {
1598+
parseVerilogExtern();
1599+
return;
1600+
}
1601+
nextToken();
1602+
if (FormatTok->is(tok::string_literal)) {
16041603
nextToken();
16051604
if (FormatTok->is(tok::l_brace)) {
16061605
if (Style.BraceWrapping.AfterExternBlock)
@@ -1625,6 +1624,10 @@ void UnwrappedLineParser::parseStructuralElement(
16251624
parseJavaScriptEs6ImportExport();
16261625
return;
16271626
}
1627+
if (Style.isVerilog()) {
1628+
parseVerilogExtern();
1629+
return;
1630+
}
16281631
if (IsCpp) {
16291632
nextToken();
16301633
if (FormatTok->is(tok::kw_namespace)) {
@@ -1673,6 +1676,10 @@ void UnwrappedLineParser::parseStructuralElement(
16731676
addUnwrappedLine();
16741677
return;
16751678
}
1679+
if (Style.isVerilog()) {
1680+
parseVerilogExtern();
1681+
return;
1682+
}
16761683
if (IsCpp && parseModuleImport())
16771684
return;
16781685
}
@@ -4559,6 +4566,23 @@ void UnwrappedLineParser::parseVerilogCaseLabel() {
45594566
Line->Level = OrigLevel;
45604567
}
45614568

4569+
void UnwrappedLineParser::parseVerilogExtern() {
4570+
assert(
4571+
FormatTok->isOneOf(tok::kw_extern, tok::kw_export, Keywords.kw_import));
4572+
nextToken();
4573+
// "DPI-C"
4574+
if (FormatTok->is(tok::string_literal))
4575+
nextToken();
4576+
if (FormatTok->isOneOf(Keywords.kw_context, Keywords.kw_pure))
4577+
nextToken();
4578+
if (Keywords.isVerilogIdentifier(*FormatTok))
4579+
nextToken();
4580+
if (FormatTok->is(tok::equal))
4581+
nextToken();
4582+
if (Keywords.isVerilogHierarchy(*FormatTok))
4583+
parseVerilogHierarchyHeader();
4584+
}
4585+
45624586
bool UnwrappedLineParser::containsExpansion(const UnwrappedLine &Line) const {
45634587
for (const auto &N : Line.Tokens) {
45644588
if (N.Tok->MacroCtx)

clang/lib/Format/UnwrappedLineParser.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@ class UnwrappedLineParser {
205205
unsigned parseVerilogHierarchyHeader();
206206
void parseVerilogTable();
207207
void parseVerilogCaseLabel();
208+
// For import, export, and extern.
209+
void parseVerilogExtern();
208210
std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>>
209211
parseMacroCall();
210212

clang/unittests/Format/FormatTestVerilog.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,16 @@ TEST_F(FormatTestVerilog, Hierarchy) {
676676
" endprogram\n"
677677
"endmodule");
678678
// Test that an extern declaration doesn't change the indentation.
679+
verifyFormat("import \"DPI-C\" context MyCFunc = function integer MapID\n"
680+
" (int portID);\n"
681+
"x = x;");
682+
verifyFormat("export \"DPI-C\" function exported_sv_func;\n"
683+
"x = x;");
684+
verifyFormat("import \"DPI-C\" function void f1\n"
685+
" (input int i1,\n"
686+
" pair i2,\n"
687+
" output logic [63 : 0] o3);\n"
688+
"x = x;");
679689
verifyFormat("extern module x;\n"
680690
"x = x;");
681691
// Test complex headers

0 commit comments

Comments
 (0)