Fix #670: Allow class methods named same as class

Modified grammar in parse.y to use identifier_name instead of IDENTIFIER
in function/task declaration rules and hierarchy_identifier rule. This
allows TYPE_IDENTIFIER tokens (which class names become after definition)
to be used as method names.

Changes:
- Function declaration rules (lines 1585, 1605, 1631)
- Task declaration rules (lines 2445, 2472, 2501)
- hierarchy_identifier member access (line 4471)

Includes regression test: br_gh670

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Andrew Pullin 2026-01-23 11:05:52 -08:00
parent 5b8fac5441
commit b6042215ff
3 changed files with 33 additions and 7 deletions

View File

@ -0,0 +1,25 @@
// Test for GitHub issue #670
// Class method can have the same name as the class
program main;
class test;
int value;
// Method with same name as class - should be valid
function void test();
$display("test method called");
value = 42;
endfunction
endclass
test tst;
initial begin
tst = new();
tst.test();
if (tst.value !== 42) begin
$display("FAILED: value = %0d, expected 42", tst.value);
$finish;
end
$display("PASSED");
end
endprogram

View File

@ -990,3 +990,4 @@ ipsdownsel_real_idx CE,-g2012 ivltests gold=ipsdownsel_real_idx.gold
ipsupsel_real_idx CE,-g2012 ivltests gold=ipsupsel_real_idx.gold
real_edges CE,-g2012 ivltests gold=real_edges.gold
br_gh1112 CE,-g2009 ivltests gold=br_gh1112.gold
br_gh670 normal,-g2009 ivltests

14
parse.y
View File

@ -1582,7 +1582,7 @@ for_step_opt
definitions in the func_body to take on the scope of the function
instead of the module. */
function_declaration /* IEEE1800-2005: A.2.6 */
: K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER ';'
: K_function lifetime_opt data_type_or_implicit_or_void identifier_name ';'
{ assert(current_function == 0);
current_function = pform_push_function_scope(@1, $4, $2);
}
@ -1602,7 +1602,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
delete[]$4;
}
| K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER
| K_function lifetime_opt data_type_or_implicit_or_void identifier_name
{ assert(current_function == 0);
current_function = pform_push_function_scope(@1, $4, $2);
}
@ -1628,7 +1628,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
/* Detect and recover from some errors. */
| K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER error K_endfunction
| K_function lifetime_opt data_type_or_implicit_or_void identifier_name error K_endfunction
{ /* */
if (current_function) {
pform_pop_scope();
@ -2442,7 +2442,7 @@ streaming_concatenation /* IEEE1800-2005: A.8.1 */
task_declaration /* IEEE1800-2005: A.2.7 */
: K_task lifetime_opt IDENTIFIER ';'
: K_task lifetime_opt identifier_name ';'
{ assert(current_task == 0);
current_task = pform_push_task_scope(@1, $3, $2);
}
@ -2469,7 +2469,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
delete[]$3;
}
| K_task lifetime_opt IDENTIFIER '('
| K_task lifetime_opt identifier_name '('
{ assert(current_task == 0);
current_task = pform_push_task_scope(@1, $3, $2);
}
@ -2498,7 +2498,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
delete[]$3;
}
| K_task lifetime_opt IDENTIFIER error K_endtask
| K_task lifetime_opt identifier_name error K_endtask
{
if (current_task) {
pform_pop_scope();
@ -4468,7 +4468,7 @@ hierarchy_identifier
$$->push_back(name_component_t(lex_strings.make($1)));
delete[]$1;
}
| hierarchy_identifier '.' IDENTIFIER
| hierarchy_identifier '.' identifier_name
{ pform_name_t * tmp = $1;
tmp->push_back(name_component_t(lex_strings.make($3)));
delete[]$3;