diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index d833130a538f1..56abd702aaafe 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -1170,6 +1170,7 @@ struct AdditionalKeywords { kw_checker = &IdentTable.get("checker"); kw_clocking = &IdentTable.get("clocking"); kw_constraint = &IdentTable.get("constraint"); + kw_context = &IdentTable.get("context"); kw_cover = &IdentTable.get("cover"); kw_covergroup = &IdentTable.get("covergroup"); kw_coverpoint = &IdentTable.get("coverpoint"); @@ -1325,50 +1326,138 @@ struct AdditionalKeywords { // Some keywords are not included here because they don't need special // treatment like `showcancelled` or they should be treated as identifiers // like `int` and `logic`. - VerilogExtraKeywords = std::unordered_set( - {kw_always, kw_always_comb, kw_always_ff, - kw_always_latch, kw_assert, kw_assign, - kw_assume, kw_automatic, kw_before, - kw_begin, kw_bins, kw_binsof, - kw_casex, kw_casez, kw_celldefine, - kw_checker, kw_clocking, kw_constraint, - kw_cover, kw_covergroup, kw_coverpoint, - kw_disable, kw_dist, kw_edge, - kw_end, kw_endcase, kw_endchecker, - kw_endclass, kw_endclocking, kw_endfunction, - kw_endgenerate, kw_endgroup, kw_endinterface, - kw_endmodule, kw_endpackage, kw_endprimitive, - kw_endprogram, kw_endproperty, kw_endsequence, - kw_endspecify, kw_endtable, kw_endtask, - kw_extends, kw_final, kw_foreach, - kw_forever, kw_fork, kw_function, - kw_generate, kw_highz0, kw_highz1, - kw_iff, kw_ifnone, kw_ignore_bins, - kw_illegal_bins, kw_implements, kw_import, - kw_initial, kw_inout, kw_input, - kw_inside, kw_interconnect, kw_interface, - kw_intersect, kw_join, kw_join_any, - kw_join_none, kw_large, kw_let, - kw_local, kw_localparam, kw_macromodule, - kw_matches, kw_medium, kw_negedge, - kw_output, kw_package, kw_packed, - kw_parameter, kw_posedge, kw_primitive, - kw_priority, kw_program, kw_property, - kw_pull0, kw_pull1, kw_pure, - kw_rand, kw_randc, kw_randcase, - kw_randsequence, kw_ref, kw_repeat, - kw_sample, kw_scalared, kw_sequence, - kw_small, kw_soft, kw_solve, - kw_specify, kw_specparam, kw_strong0, - kw_strong1, kw_supply0, kw_supply1, - kw_table, kw_tagged, kw_task, - kw_tri, kw_tri0, kw_tri1, - kw_triand, kw_trior, kw_trireg, - kw_unique, kw_unique0, kw_uwire, - kw_var, kw_vectored, kw_wait, - kw_wand, kw_weak0, kw_weak1, - kw_wildcard, kw_wire, kw_with, - kw_wor, kw_verilogHash, kw_verilogHashHash}); + VerilogExtraKeywords = + std::unordered_set({kw_always, + kw_always_comb, + kw_always_ff, + kw_always_latch, + kw_assert, + kw_assign, + kw_assume, + kw_automatic, + kw_before, + kw_begin, + kw_bins, + kw_binsof, + kw_casex, + kw_casez, + kw_celldefine, + kw_checker, + kw_clocking, + kw_constraint, + kw_context, + kw_cover, + kw_covergroup, + kw_coverpoint, + kw_disable, + kw_dist, + kw_edge, + kw_end, + kw_endcase, + kw_endchecker, + kw_endclass, + kw_endclocking, + kw_endfunction, + kw_endgenerate, + kw_endgroup, + kw_endinterface, + kw_endmodule, + kw_endpackage, + kw_endprimitive, + kw_endprogram, + kw_endproperty, + kw_endsequence, + kw_endspecify, + kw_endtable, + kw_endtask, + kw_extends, + kw_final, + kw_foreach, + kw_forever, + kw_fork, + kw_function, + kw_generate, + kw_highz0, + kw_highz1, + kw_iff, + kw_ifnone, + kw_ignore_bins, + kw_illegal_bins, + kw_implements, + kw_import, + kw_initial, + kw_inout, + kw_input, + kw_inside, + kw_interconnect, + kw_interface, + kw_intersect, + kw_join, + kw_join_any, + kw_join_none, + kw_large, + kw_let, + kw_local, + kw_localparam, + kw_macromodule, + kw_matches, + kw_medium, + kw_module, + kw_negedge, + kw_output, + kw_package, + kw_packed, + kw_parameter, + kw_posedge, + kw_primitive, + kw_priority, + kw_program, + kw_property, + kw_pull0, + kw_pull1, + kw_pure, + kw_rand, + kw_randc, + kw_randcase, + kw_randsequence, + kw_ref, + kw_repeat, + kw_sample, + kw_scalared, + kw_sequence, + kw_small, + kw_soft, + kw_solve, + kw_specify, + kw_specparam, + kw_strong0, + kw_strong1, + kw_supply0, + kw_supply1, + kw_table, + kw_tagged, + kw_task, + kw_tri, + kw_tri0, + kw_tri1, + kw_triand, + kw_trior, + kw_trireg, + kw_unique, + kw_unique0, + kw_uwire, + kw_var, + kw_vectored, + kw_wait, + kw_wand, + kw_weak0, + kw_weak1, + kw_wildcard, + kw_wire, + kw_with, + kw_wor, + kw_verilogHash, + kw_verilogHashHash}); TableGenExtraKeywords = std::unordered_set({ kw_assert, @@ -1516,6 +1605,7 @@ struct AdditionalKeywords { IdentifierInfo *kw_checker; IdentifierInfo *kw_clocking; IdentifierInfo *kw_constraint; + IdentifierInfo *kw_context; IdentifierInfo *kw_cover; IdentifierInfo *kw_covergroup; IdentifierInfo *kw_coverpoint; @@ -1800,11 +1890,13 @@ struct AdditionalKeywords { case tok::kw_continue: case tok::kw_default: case tok::kw_do: - case tok::kw_extern: case tok::kw_else: case tok::kw_enum: + case tok::kw_export: + case tok::kw_extern: case tok::kw_for: case tok::kw_if: + case tok::kw_import: case tok::kw_restrict: case tok::kw_signed: case tok::kw_static: diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 8b7dd02d548af..50edca43ebb92 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -1592,15 +1592,14 @@ void UnwrappedLineParser::parseStructuralElement( parseTryCatch(); return; case tok::kw_extern: - nextToken(); if (Style.isVerilog()) { - // In Verilog and extern module declaration looks like a start of module. + // In Verilog an extern module declaration looks like a start of module. // But there is no body and endmodule. So we handle it separately. - if (Keywords.isVerilogHierarchy(*FormatTok)) { - parseVerilogHierarchyHeader(); - return; - } - } else if (FormatTok->is(tok::string_literal)) { + parseVerilogExtern(); + return; + } + nextToken(); + if (FormatTok->is(tok::string_literal)) { nextToken(); if (FormatTok->is(tok::l_brace)) { if (Style.BraceWrapping.AfterExternBlock) @@ -1625,6 +1624,10 @@ void UnwrappedLineParser::parseStructuralElement( parseJavaScriptEs6ImportExport(); return; } + if (Style.isVerilog()) { + parseVerilogExtern(); + return; + } if (IsCpp) { nextToken(); if (FormatTok->is(tok::kw_namespace)) { @@ -1673,6 +1676,10 @@ void UnwrappedLineParser::parseStructuralElement( addUnwrappedLine(); return; } + if (Style.isVerilog()) { + parseVerilogExtern(); + return; + } if (IsCpp && parseModuleImport()) return; } @@ -4559,6 +4566,23 @@ void UnwrappedLineParser::parseVerilogCaseLabel() { Line->Level = OrigLevel; } +void UnwrappedLineParser::parseVerilogExtern() { + assert( + FormatTok->isOneOf(tok::kw_extern, tok::kw_export, Keywords.kw_import)); + nextToken(); + // "DPI-C" + if (FormatTok->is(tok::string_literal)) + nextToken(); + if (FormatTok->isOneOf(Keywords.kw_context, Keywords.kw_pure)) + nextToken(); + if (Keywords.isVerilogIdentifier(*FormatTok)) + nextToken(); + if (FormatTok->is(tok::equal)) + nextToken(); + if (Keywords.isVerilogHierarchy(*FormatTok)) + parseVerilogHierarchyHeader(); +} + bool UnwrappedLineParser::containsExpansion(const UnwrappedLine &Line) const { for (const auto &N : Line.Tokens) { if (N.Tok->MacroCtx) diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h index 8b8ad84896f1a..0161a5063ad40 100644 --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -205,6 +205,8 @@ class UnwrappedLineParser { unsigned parseVerilogHierarchyHeader(); void parseVerilogTable(); void parseVerilogCaseLabel(); + // For import, export, and extern. + void parseVerilogExtern(); std::optional, 1>> parseMacroCall(); diff --git a/clang/unittests/Format/FormatTestVerilog.cpp b/clang/unittests/Format/FormatTestVerilog.cpp index 63e2cadfdd7a1..eee2bbdf551e6 100644 --- a/clang/unittests/Format/FormatTestVerilog.cpp +++ b/clang/unittests/Format/FormatTestVerilog.cpp @@ -676,6 +676,16 @@ TEST_F(FormatTestVerilog, Hierarchy) { " endprogram\n" "endmodule"); // Test that an extern declaration doesn't change the indentation. + verifyFormat("import \"DPI-C\" context MyCFunc = function integer MapID\n" + " (int portID);\n" + "x = x;"); + verifyFormat("export \"DPI-C\" function exported_sv_func;\n" + "x = x;"); + verifyFormat("import \"DPI-C\" function void f1\n" + " (input int i1,\n" + " pair i2,\n" + " output logic [63 : 0] o3);\n" + "x = x;"); verifyFormat("extern module x;\n" "x = x;"); // Test complex headers