@@ -195,26 +195,33 @@ void FstData::extractVarNames()
195195 fst_scope_name = fstReaderPushScope (ctx, h->u .scope .name , NULL );
196196 break ;
197197 }
198- case FST_HT_SCOPE : {
199- // Handle tracking for potential union structs with $fork.
200- if (!detect_union && h->u .scope .typ == FST_ST_VCD_FORK ) {
201- detect_union = true ;
202- fork_parent_scope = fst_scope_name;
203- fork_name = h->u .scope .name ;
204- fork_vars.clear ();
205- } else if (detect_union && h->u .scope .typ == FST_ST_VCD_FORK ) {
206- // Nested $fork: abandon union detection. Warning is emitted
207- // at upscope time, only if the outer fork would have been a union.
208- for (auto &v : fork_vars) registerVar (v);
198+ case FST_HT_UPSCOPE : {
199+ if (detect_union) {
200+ // A union is detected if there are at least 2 variables in the fork scope and they all have the same fstHandle.
201+ bool is_union = fork_vars.size () >= 2 &&
202+ std::all_of (fork_vars.begin () + 1 , fork_vars.end (),
203+ [&](const FstVar &v) { return v.id == fork_vars[0 ].id ; });
204+ if (is_union) {
205+ // If a union, register the fork name as the variable at the parent scope.
206+ FstVar u = fork_vars[0 ];
207+ u.name = fork_name;
208+ u.scope = fork_parent_scope;
209+ normalize_brackets (u.scope );
210+ u.is_alias = false ;
211+ registerVar (u);
212+ } else {
213+ // If not a union, register all variables in the fork scope as normal.
214+ for (auto &v : fork_vars) {
215+ registerVar (v);
216+ }
217+ }
209218 detect_union = false ;
210219 fork_vars.clear ();
211- fork_vars_had_nested_fork = true ;
212220 }
213- // Push the scope onto the stack to 'descend' into the hierarchy .
214- fst_scope_name = fstReaderPushScope (ctx, h-> u . scope . name , NULL );
221+ // Pop the scope off the stack.
222+ fst_scope_name = fstReaderPopScope (ctx);
215223 break ;
216224 }
217- }
218225 case FST_HT_VAR : {
219226 FstVar var;
220227 var.id = h->u .var .handle ;
0 commit comments