Skip to content

Commit 748a0e1

Browse files
authored
Merge pull request #4111 from roccomao/fix-function-parse
Verilog: Fix function parse when return type contains `::`
2 parents f63e6ae + 68ef8d6 commit 748a0e1

File tree

5 files changed

+391
-14
lines changed

5 files changed

+391
-14
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--sort=no
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
new_test_case input.sv /^package new_test_case; \/\/ for better readability$/;" K
2+
test_func_A input.sv /^ function signed test_func_A();$/;" f package:new_test_case
3+
test_task_A input.sv /^ task test_task_A; endtask$/;" t package:new_test_case
4+
test_func_B input.sv /^ function not_care_class test_func_B();$/;" f package:new_test_case
5+
test_func_C input.sv /^ function not_care_class#(int) test_func_C ();$/;" f package:new_test_case
6+
test_func_D input.sv /^ function not_care_class #(int) test_func_D ( );$/;" f package:new_test_case
7+
test_func_E input.sv /^ function not_care_class #( .T(int) ) test_func_E();$/;" f package:new_test_case
8+
test_func_F input.sv /^ function unsigned [7:0] class_scope::test_func_F();$/;" f class:new_test_case.class_scope
9+
test_func_G input.sv /^ function not_care_class class_scope::test_func_G();$/;" f class:new_test_case.class_scope
10+
test_func_H input.sv /^ function not_care_class#(IF) class_scope::test_func_H();$/;" f class:new_test_case.class_scope
11+
test_func_I input.sv /^ function not_care_class #(IF) class_scope::test_func_I;$/;" f class:new_test_case.class_scope
12+
test_func_J input.sv /^ function not_care_class#(.T(real), .size(4)) class_scope::test_func_J;$/;" f class:new_test_case.class_scope
13+
new input.sv /^ function class_scope::new;$/;" f class:new_test_case.class_scope
14+
test_task_B input.sv /^ task class_scope::test_task_B () ;$/;" t class:new_test_case.class_scope
15+
test_func_K input.sv /^ function not_care_class::TYPE test_func_K ();$/;" f package:new_test_case
16+
test_func_L input.sv /^ function automatic bit signed [15:0] test_func_L();$/;" f package:new_test_case
17+
test_func_M input.sv /^ function not_care_class#(bit [2:0]) :: TYPE test_func_M;$/;" f package:new_test_case
18+
test_func_N input.sv /^ function not_care_class #(.T(bit [2:0]))::TYPE test_func_N;$/;" f package:new_test_case
19+
test_func_O input.sv /^ function not_care_class # (100) ::TYPE test_func_O () ;$/;" f package:new_test_case
20+
test_var_A input.sv /^ int test_var_A = 100;$/;" r package:new_test_case
21+
test_func_P input.sv /^ function static bit test_func_P; endfunction$/;" f package:new_test_case
22+
new input.sv /^ function new; endfunction$/;" f package:new_test_case
23+
test_task_C input.sv /^ task test_task_C; endtask$/;" t package:new_test_case
24+
test_func_Q input.sv /^ function not_care_class :: TYPE scope::test_func_Q;$/;" f class:new_test_case.scope
25+
test_func_R input.sv /^ function void test_func_R ();$/;" f package:new_test_case
26+
test_func_S input.sv /^ function not_care_class#(shortint)::TYPE scope::test_func_S ( );$/;" f class:new_test_case.scope
27+
test_func_T input.sv /^ function not_care_class # ( .IF( IF ) )::TYPE scope:: test_func_T;$/;" f class:new_test_case.scope
28+
test_var_B input.sv /^ longint test_var_B = 1024;$/;" r package:new_test_case
29+
test_task_D input.sv /^ task test_task_D ( );$/;" t package:new_test_case
30+
test_func_U input.sv /^ function void test_func_U; endfunction$/;" f package:new_test_case
31+
new input.sv /^ function scope::new ();$/;" f class:new_test_case.scope
32+
test_task_E input.sv /^ task scope:: test_task_E;$/;" t class:new_test_case.scope
33+
LOW input.sv /^ localparam LOW = 8;$/;" c package:new_test_case
34+
HIGH input.sv /^ localparam HIGH = 15;$/;" c package:new_test_case
35+
test_func_V input.sv /^ function automatic logic [ LOW : HIGH ] test_func_V ();$/;" f package:new_test_case
36+
test_func_W input.sv /^ function automatic int signed [LOW-1:HIGH-1] test_func_W;$/;" f package:new_test_case
37+
test_func_EA input.sv /^ function automatic A:: B#(IF) ::TYPE test_func_EA ();$/;" f package:new_test_case
38+
test_func_EB input.sv /^ function automatic unsigned [ LOW -1: HIGH -1] scope:: test_func_EB;$/;" f class:new_test_case.scope
39+
test_wrong_task input.sv /^ task static A :: B :: C # (.T (int)) :: test_wrong_task ();$/;" t class:new_test_case.A.B.C
40+
test_wrong_function input.sv /^ function static A::B::TYPE scope # ( .T (IF) ) :: test_wrong_function;$/;" f class:new_test_case.scope
41+
test_specifier_A input.sv /^ function :initial void test_specifier_A (); endfunction$/;" f package:new_test_case
42+
test_specifier_B input.sv /^ function :extends void test_specifier_B (); endfunction$/;" f package:new_test_case
43+
test_specifier_C input.sv /^ function :final void test_specifier_C (); endfunction$/;" f package:new_test_case
44+
test_specifier_D input.sv /^ function : initial : final void test_specifier_D (); endfunction$/;" f package:new_test_case
45+
test_specifier_E input.sv /^ function : extends : final void test_specifier_E (); endfunction$/;" f package:new_test_case
46+
test_specifier_F input.sv /^ function : final : initial void test_specifier_F (); endfunction$/;" f package:new_test_case
47+
test_specifier_G input.sv /^ function : final : extends void test_specifier_G (); endfunction$/;" f package:new_test_case
48+
test_specifier_H input.sv /^ virtual function : initial A :: B :: TYPE test_specifier_H ();$/;" f package:new_test_case
49+
test_specifier_I input.sv /^ virtual function :extends :final A::B::C A::B::test_specifier_I;$/;" f class:new_test_case.A.B
50+
test_specifier_J input.sv /^ task :initial :final A :: B :: test_specifier_J ;$/;" t class:new_test_case.A.B
51+
test_specifier_K input.sv /^ task :final : extends A #(IF)::B ::test_specifier_K () ;$/;" t class:new_test_case.A.B
52+
new input.sv /^ function corner_A::corner_B :: new ( );$/;" f class:new_test_case.corner_A.corner_B
53+
test_func_XA input.sv /^ function A::B::C::D #(int) corner_A:: test_func_XA();$/;" f class:new_test_case.corner_A
54+
test_func_XB input.sv /^ function void corner_A # ( .T(real) ) :: test_func_XB;$/;" f class:new_test_case.corner_A
55+
test_func_XC input.sv /^ function A # ( IF ) :: B :: C corner_A :: test_func_XC ();$/;" f class:new_test_case.corner_A
56+
test_func_XD input.sv /^ function A :: B # ( 100 )::C::D#(int) test_func_XD;$/;" f package:new_test_case
57+
test_task_F input.sv /^ task A::B::C::test_task_F ;$/;" t class:new_test_case.A.B.C
58+
test_func_Y input.sv /^ function void test_func_Y ( int Y_in_A, int Y_in_B );$/;" f package:new_test_case
59+
Y_in_A input.sv /^ function void test_func_Y ( int Y_in_A, int Y_in_B );$/;" p function:new_test_case.test_func_Y
60+
Y_in_B input.sv /^ function void test_func_Y ( int Y_in_A, int Y_in_B );$/;" p function:new_test_case.test_func_Y
61+
test_task_G input.sv /^ task A #(real):: B#(IF)::C#( .size(64) ) :: D :: test_task_G ();$/;" t class:new_test_case.A.B.C.D
62+
test_var_C input.sv /^ int test_var_C = 1024;$/;" r package:new_test_case
63+
test_func_Z input.sv /^ function logic [LOW:HIGH] test_func_Z ();$/;" f package:new_test_case
64+
test_class input.sv /^ class test_class;$/;" C package:new_test_case
65+
test_func_EC input.sv /^ static function A::B::C::D test_func_EC () ;$/;" f class:new_test_case.test_class
66+
test_task_EB input.sv /^ static task test_class::test_task_EB ; endtask$/;" t class:new_test_case.test_class
67+
test_func_ED input.sv /^ static function A:: B ::C::D test_class :: test_func_ED;$/;" f class:new_test_case.test_class
68+
uvm_component input.sv /^virtual class uvm_component extends uvm_report_object;$/;" C
69+
config_mode_t input.sv /^ typedef bit [1:0] config_mode_t;$/;" T class:uvm_component
70+
test_ok input.sv /^function void uvm_component::test_ok();$/;" f class:uvm_component
71+
return_scope_res input.sv /^function uvm_component::config_mode_t uvm_component::return_scope_res();$/;" f class:uvm_component
72+
test_scope_variable input.sv /^int test_scope_variable;$/;" r
73+
m_set_cl_msg_args input.sv /^function void uvm_component::m_set_cl_msg_args();$/;" f class:uvm_component
74+
m_set_cl_verb input.sv /^function void uvm_component::m_set_cl_verb; return; endfunction$/;" f class:uvm_component
75+
m_set_cl_action input.sv /^function void uvm_component::m_set_cl_action; return; endfunction$/;" f class:uvm_component
76+
m_set_cl_sev input.sv /^function void uvm_component::m_set_cl_sev; return; endfunction$/;" f class:uvm_component
77+
test_case_A input.sv /^package test_case_A;$/;" K
78+
test_ok input.sv /^ function void test_ok;$/;" f package:test_case_A
79+
oops input.sv /^ function extern_class::data_type oops();$/;" f package:test_case_A
80+
OOPS input.sv /^ function extern_class#(int)::data_type OOPS();$/;" f package:test_case_A
81+
still_ok input.sv /^ function void still_ok();$/;" f package:test_case_A
82+
test_case_B input.sv /^package test_case_B;$/;" K
83+
foo input.sv /^ function void foo; \/\/ OK$/;" f package:test_case_B
84+
test_ok input.sv /^ function uvm_queue#(uvm_callback) test_ok(uvm_object obj);$/;" f package:test_case_B
85+
obj input.sv /^ function uvm_queue#(uvm_callback) test_ok(uvm_object obj);$/;" p function:test_case_B.test_ok
86+
TEST_OK input.sv /^ function uvm_queue #(uvm_callback) TEST_OK(uvm_object obj);$/;" f package:test_case_B
87+
obj input.sv /^ function uvm_queue #(uvm_callback) TEST_OK(uvm_object obj);$/;" p function:test_case_B.TEST_OK
88+
bar input.sv /^ function void bar(); \/\/ OK$/;" f package:test_case_B
89+
oops input.sv /^ function uvm_queue #(uvm_callback)::data_type oops(uvm_object obj);$/;" f package:test_case_B
90+
obj input.sv /^ function uvm_queue #(uvm_callback)::data_type oops(uvm_object obj);$/;" p function:test_case_B.oops
91+
test_scope_var input.sv /^ int test_scope_var = 1;$/;" r function:test_case_B.oops
92+
still_ok input.sv /^ function void still_ok();$/;" f package:test_case_B
Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
2+
// ---------------------------------------------------------------------------
3+
// TEST CASE for `processFunction()` to parse `function` and `task` body
4+
// ---------------------------------------------------------------------------
5+
6+
package new_test_case; // for better readability
7+
8+
// 1. Normal function.
9+
// -----------------------------------------------------------------
10+
function signed test_func_A();
11+
endfunction
12+
task test_task_A; endtask
13+
14+
// 2. Normal function return class type.
15+
// -----------------------------------------------------------------
16+
// 2.1 return Normal class.
17+
function not_care_class test_func_B();
18+
endfunction
19+
// 2.2 return parameterized class without space.
20+
function not_care_class#(int) test_func_C ();
21+
endfunction
22+
// 2.3 return parameterized class with space.
23+
function not_care_class #(int) test_func_D ( );
24+
endfunction
25+
// 2.4 return parameterized class with parameter.
26+
function not_care_class #( .T(int) ) test_func_E();
27+
endfunction
28+
29+
// 3. The prototype of the class is declared in another file,
30+
// and the specific implementation is here.
31+
// -----------------------------------------------------------------
32+
// 3.1 Normal function.
33+
function unsigned [7:0] class_scope::test_func_F();
34+
endfunction
35+
// 3.2 return Normal class.
36+
function not_care_class class_scope::test_func_G();
37+
endfunction
38+
// 3.3 return parameterized class without space.
39+
function not_care_class#(IF) class_scope::test_func_H();
40+
endfunction
41+
// 3.4 return parameterized class with space.
42+
function not_care_class #(IF) class_scope::test_func_I;
43+
endfunction
44+
// 3.5 return parameterized class with parameter.
45+
function not_care_class#(.T(real), .size(4)) class_scope::test_func_J;
46+
endfunction
47+
// 3.6 task or new function
48+
function class_scope::new;
49+
endfunction
50+
task class_scope::test_task_B () ;
51+
endtask
52+
53+
// 4. Normal function: return type from a class ( with `::` ).
54+
// -----------------------------------------------------------------
55+
// 4.1 from a Normal class
56+
function not_care_class::TYPE test_func_K ();
57+
endfunction
58+
// Subsequent parsing is not affected.
59+
function automatic bit signed [15:0] test_func_L();
60+
endfunction
61+
// 4.2 from a parameterized class
62+
function not_care_class#(bit [2:0]) :: TYPE test_func_M;
63+
endfunction
64+
function not_care_class #(.T(bit [2:0]))::TYPE test_func_N;
65+
endfunction
66+
function not_care_class # (100) ::TYPE test_func_O () ;
67+
endfunction
68+
// Subsequent parsing is not affected.
69+
int test_var_A = 100;
70+
function static bit test_func_P; endfunction
71+
// 4.3 task or new function
72+
function new; endfunction
73+
task test_task_C; endtask
74+
75+
// 5. function with class_scope && return type with class_scope
76+
// -----------------------------------------------------------------
77+
// 5.1 from a Normal class
78+
function not_care_class :: TYPE scope::test_func_Q;
79+
endfunction
80+
// Subsequent parsing is not affected
81+
function void test_func_R ();
82+
endfunction
83+
// 5.2 from a parameterized class
84+
function not_care_class#(shortint)::TYPE scope::test_func_S ( );
85+
endfunction
86+
function not_care_class # ( .IF( IF ) )::TYPE scope:: test_func_T;
87+
endfunction
88+
// Subsequent parsing is not affected
89+
longint test_var_B = 1024;
90+
task test_task_D ( );
91+
endtask
92+
function void test_func_U; endfunction
93+
// 5.3 task or new function
94+
function scope::new ();
95+
endfunction
96+
task scope:: test_task_E;
97+
endtask
98+
99+
// 6. Corner TEST
100+
// -----------------------------------------------------------------
101+
localparam LOW = 8;
102+
localparam HIGH = 15;
103+
function automatic logic [ LOW : HIGH ] test_func_V ();
104+
endfunction
105+
function automatic int signed [LOW-1:HIGH-1] test_func_W;
106+
endfunction
107+
function automatic A:: B#(IF) ::TYPE test_func_EA ();
108+
endfunction
109+
function automatic unsigned [ LOW -1: HIGH -1] scope:: test_func_EB;
110+
endfunction
111+
task static A :: B :: C # (.T (int)) :: test_wrong_task ();
112+
endtask
113+
function static A::B::TYPE scope # ( .T (IF) ) :: test_wrong_function;
114+
endfunction
115+
function :initial void test_specifier_A (); endfunction
116+
function :extends void test_specifier_B (); endfunction
117+
function :final void test_specifier_C (); endfunction
118+
function : initial : final void test_specifier_D (); endfunction
119+
function : extends : final void test_specifier_E (); endfunction
120+
function : final : initial void test_specifier_F (); endfunction
121+
function : final : extends void test_specifier_G (); endfunction
122+
virtual function : initial A :: B :: TYPE test_specifier_H ();
123+
endfunction
124+
virtual function :extends :final A::B::C A::B::test_specifier_I;
125+
endfunction
126+
task :initial :final A :: B :: test_specifier_J ;
127+
endtask
128+
task :final : extends A #(IF)::B ::test_specifier_K () ;
129+
endtask
130+
function corner_A::corner_B :: new ( );
131+
endfunction
132+
function A::B::C::D #(int) corner_A:: test_func_XA();
133+
endfunction
134+
function void corner_A # ( .T(real) ) :: test_func_XB;
135+
endfunction
136+
function A # ( IF ) :: B :: C corner_A :: test_func_XC ();
137+
endfunction
138+
function A :: B # ( 100 )::C::D#(int) test_func_XD;
139+
endfunction
140+
task A::B::C::test_task_F ;
141+
endtask
142+
function void test_func_Y ( int Y_in_A, int Y_in_B );
143+
endfunction
144+
task A #(real):: B#(IF)::C#( .size(64) ) :: D :: test_task_G ();
145+
endtask
146+
int test_var_C = 1024;
147+
function logic [LOW:HIGH] test_func_Z ();
148+
endfunction
149+
class test_class;
150+
static function A::B::C::D test_func_EC () ;
151+
endfunction
152+
extern static task test_task_EB ();
153+
extern static function A :: B :: C :: D test_func_ED ();
154+
endclass
155+
static task test_class::test_task_EB ; endtask
156+
static function A:: B ::C::D test_class :: test_func_ED;
157+
endfunction
158+
159+
endpackage : new_test_case
160+
161+
// ---------------------------------------------------------------------------
162+
// REF : https://github.com/universal-ctags/ctags/issues/4109
163+
// ---------------------------------------------------------------------------
164+
165+
virtual class uvm_component extends uvm_report_object;
166+
typedef bit [1:0] config_mode_t;
167+
extern virtual function void test_ok();
168+
// ------------------------------------------------------
169+
extern virtual function config_mode_t return_scope_res();
170+
// ------------------------------------------------------
171+
extern function void m_set_cl_msg_args();
172+
extern function void m_set_cl_verb;
173+
extern function void m_set_cl_action;
174+
extern function void m_set_cl_sev;
175+
endclass
176+
177+
function void uvm_component::test_ok();
178+
// function body, this function is parsed OK
179+
endfunction
180+
181+
// ---------------------------------------------------------------------
182+
function uvm_component::config_mode_t uvm_component::return_scope_res();
183+
return 2'b00;
184+
endfunction
185+
// ---------------------------------------------------------------------
186+
187+
int test_scope_variable;
188+
189+
function void uvm_component::m_set_cl_msg_args();
190+
endfunction
191+
function void uvm_component::m_set_cl_verb; return; endfunction
192+
function void uvm_component::m_set_cl_action; return; endfunction
193+
function void uvm_component::m_set_cl_sev; return; endfunction
194+
195+
package test_case_A;
196+
typedef class extern_class;
197+
198+
function void test_ok;
199+
endfunction
200+
201+
function extern_class::data_type oops();
202+
endfunction
203+
204+
function extern_class#(int)::data_type OOPS();
205+
endfunction
206+
207+
function void still_ok();
208+
endfunction
209+
endpackage
210+
211+
package test_case_B;
212+
function void foo; // OK
213+
// something
214+
endfunction
215+
216+
// return type is a parameterized class, OK
217+
function uvm_queue#(uvm_callback) test_ok(uvm_object obj);
218+
return null;
219+
endfunction
220+
221+
// OK, even if there is a space between `uvm_queue` and `#(`
222+
function uvm_queue #(uvm_callback) TEST_OK(uvm_object obj);
223+
return null;
224+
endfunction
225+
226+
// Subsequent parsing is not affected
227+
function void bar(); // OK
228+
// something
229+
endfunction
230+
231+
// ----------------------------------------------------------------
232+
function uvm_queue #(uvm_callback)::data_type oops(uvm_object obj);
233+
int test_scope_var = 1;
234+
return null;
235+
endfunction
236+
// ----------------------------------------------------------------
237+
238+
function void still_ok();
239+
// function body
240+
endfunction
241+
endpackage

Units/parser-verilog.r/systemverilog-parameter.d/expected.tags

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ x input.sv /^ int x = C::p; \/\/ C::p disambiguates p$/;" r task:C.t
77
C input.sv /^class C #($/;" C
88
p input.sv /^ int p = 1,$/;" c class:C parameter:
99
T input.sv /^ type T = int$/;" c class:C parameter:
10-
f input.sv /^function C::T C::f();$/;" f class:C.C
11-
C input.sv /^virtual class C#(parameter DECODE_W, parameter ENCODE_W = $clog2(DECODE_W));$/;" C class:C
12-
DECODE_W input.sv /^virtual class C#(parameter DECODE_W, parameter ENCODE_W = $clog2(DECODE_W));$/;" c class:C.C parameter:
13-
ENCODE_W input.sv /^virtual class C#(parameter DECODE_W, parameter ENCODE_W = $clog2(DECODE_W));$/;" c class:C.C parameter:
14-
ENCODER_f input.sv /^ static function logic [ENCODE_W-1:0] ENCODER_f$/;" f class:C.C
15-
DecodeIn input.sv /^ (input logic [DECODE_W-1:0] DecodeIn);$/;" p function:C.C.ENCODER_f
16-
DECODER_f input.sv /^ static function logic [DECODE_W-1:0] DECODER_f$/;" f class:C.C
17-
EncodeIn input.sv /^ (input logic [ENCODE_W-1:0] EncodeIn);$/;" p function:C.C.DECODER_f
10+
f input.sv /^function C::T C::f();$/;" f class:C
11+
C input.sv /^virtual class C#(parameter DECODE_W, parameter ENCODE_W = $clog2(DECODE_W));$/;" C
12+
DECODE_W input.sv /^virtual class C#(parameter DECODE_W, parameter ENCODE_W = $clog2(DECODE_W));$/;" c class:C parameter:
13+
ENCODE_W input.sv /^virtual class C#(parameter DECODE_W, parameter ENCODE_W = $clog2(DECODE_W));$/;" c class:C parameter:
14+
ENCODER_f input.sv /^ static function logic [ENCODE_W-1:0] ENCODER_f$/;" f class:C
15+
DecodeIn input.sv /^ (input logic [DECODE_W-1:0] DecodeIn);$/;" p function:C.ENCODER_f
16+
DECODER_f input.sv /^ static function logic [DECODE_W-1:0] DECODER_f$/;" f class:C
17+
EncodeIn input.sv /^ (input logic [ENCODE_W-1:0] EncodeIn);$/;" p function:C.DECODER_f
1818
PutImp input.sv /^interface class PutImp #(type PUT_T = logic);$/;" l
1919
PUT_T input.sv /^interface class PutImp #(type PUT_T = logic);$/;" c ifclass:PutImp parameter:
2020
GetImp input.sv /^interface class GetImp #(type GET_T = logic);$/;" l

0 commit comments

Comments
 (0)