From 2cad9a0f22c3203f1d1dd9d35613558bf443f4a4 Mon Sep 17 00:00:00 2001 From: David Fang Date: Mon, 30 Mar 2020 14:05:17 -0700 Subject: [PATCH] Allow identifier-like symbols for the import alias name. Fixes crash in verilog::MakeDPIImport() with signature like: Check failed: E(leaf.get().token_enum) == expected_token_enum (293 vs. 292) PiperOrigin-RevId: 303818326 --- verilog/CST/BUILD | 2 ++ verilog/CST/DPI.h | 25 ++++++++++++++++++++++- verilog/parser/verilog_parser_unittest.cc | 10 +++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/verilog/CST/BUILD b/verilog/CST/BUILD index d9ac37055..537f34529 100644 --- a/verilog/CST/BUILD +++ b/verilog/CST/BUILD @@ -152,9 +152,11 @@ cc_library( ":verilog_nonterminals", ":verilog_treebuilder_utils", "//common/analysis:syntax_tree_search", + "//common/text:concrete_syntax_leaf", "//common/text:concrete_syntax_tree", "//common/text:symbol", "//common/text:tree_utils", + "//verilog/parser:verilog_token_classifications", "//verilog/parser:verilog_token_enum", ], ) diff --git a/verilog/CST/DPI.h b/verilog/CST/DPI.h index 3dc3e2314..7ecdbc780 100644 --- a/verilog/CST/DPI.h +++ b/verilog/CST/DPI.h @@ -23,11 +23,13 @@ #include #include "common/analysis/syntax_tree_search.h" +#include "common/text/concrete_syntax_leaf.h" #include "common/text/concrete_syntax_tree.h" #include "common/text/symbol.h" #include "common/text/tree_utils.h" #include "verilog/CST/verilog_nonterminals.h" #include "verilog/CST/verilog_treebuilder_utils.h" +#include "verilog/parser/verilog_token_classifications.h" #include "verilog/parser/verilog_token_enum.h" namespace verilog { @@ -38,7 +40,10 @@ verible::SymbolPtr MakeDPIImport(T0&& keyword, T1&& spec, T2&& property, T3&& id, T4&& equals, T5&& proto, T6&& semi) { verible::CheckSymbolAsLeaf(*keyword, verilog_tokentype::TK_import); verible::CheckSymbolAsLeaf(*spec, verilog_tokentype::TK_StringLiteral); - verible::CheckOptionalSymbolAsLeaf(id, verilog_tokentype::SymbolIdentifier); + if (id != nullptr) { + CHECK(IsIdentifierLike( + verilog_tokentype(verible::SymbolCastToLeaf(*id).get().token_enum))); + } verible::CheckOptionalSymbolAsLeaf(equals, '='); CHECK(verible::SymbolCastToNode(*proto).MatchesTagAnyOf( {NodeEnum::kFunctionPrototype, NodeEnum::kTaskPrototype})); @@ -50,6 +55,24 @@ verible::SymbolPtr MakeDPIImport(T0&& keyword, T1&& spec, T2&& property, verible::ExtendNode(std::forward(proto), std::forward(semi))); } +// Partial specialization provided as a workaround to passing nullptr +// in positions 3 and 4 (optional symbols). Compiler is not guaranteed +// to deduce to that some paths are not reachble/applicable. +template +verible::SymbolPtr MakeDPIImport(T0&& keyword, T1&& spec, T2&& property, + nullptr_t id, nullptr_t equals, T3&& proto, + T4&& semi) { + verible::CheckSymbolAsLeaf(*keyword, verilog_tokentype::TK_import); + verible::CheckSymbolAsLeaf(*spec, verilog_tokentype::TK_StringLiteral); + CHECK(verible::SymbolCastToNode(*proto).MatchesTagAnyOf( + {NodeEnum::kFunctionPrototype, NodeEnum::kTaskPrototype})); + ExpectString(semi, ";"); + return verible::MakeTaggedNode( + NodeEnum::kDPIImportItem, std::forward(keyword), + std::forward(spec), std::forward(property), id, equals, + verible::ExtendNode(std::forward(proto), std::forward(semi))); +} + // Find all DPI imports. std::vector FindAllDPIImports(const verible::Symbol&); diff --git a/verilog/parser/verilog_parser_unittest.cc b/verilog/parser/verilog_parser_unittest.cc index e7cd40a65..ab380edb5 100644 --- a/verilog/parser/verilog_parser_unittest.cc +++ b/verilog/parser/verilog_parser_unittest.cc @@ -2627,6 +2627,16 @@ static const char* kModuleTests[] = { "import pkg::ident;\n" "export \"name\" task rabbit;\n" "endmodule", + "import \"DPI\" function bar;\n", + "import \"DPI-C\" function bar;\n", + "import \"DPI-C\" foo = function bar;\n", + "import \"DPI-C\" foo = function void bar;\n", + "import \"DPI-C\" foo = function void bar();\n", + "import \"DPI-C\" foo = function void bar(input chandle ch);\n", + // using escaped identifier as alias: + "import \"DPI-C\" \\foo = function void bar(input chandle ch);\n", + "import \"DPI-C\" `foo = function void bar(input chandle ch);\n", // macro + "import \"DPI-C\" foo = function longint unsigned bar(input chandle ch);\n", "module zoobar ();\n" "import \"DPI-C\" function void fizzbuzz (\n" " input in val, output int nothing);\n"