Project

General

Profile

Bug #10027

Incorrect handling of an unused shared variable in the conversion process.

Added by Paula Păstrăguș about 1 year ago. Updated about 1 year ago.

Status:
Test
Priority:
Normal
Target version:
-
Start date:
Due date:
% Done:

100%

billable:
No
vendor_id:
GCD
case_num:
CA-24875
version_reported:
version_resolved:
reviewer:
production:
No
env_name:
topics:

ast.png (175 KB) Paula Păstrăguș, 05/21/2025 06:02 AM

History

#2 Updated by Paula Păstrăguș about 1 year ago

Here's the testcase:

def  shared var var1              as date no-undo. 
def  shared var var2        like var1 no-undo.

The var1 variable should be converted as SharedVariableManager.lookupVariableUnreferenced, not as SharedVariableManager.lookupVariable.

#4 Updated by Paula Păstrăguș about 1 year ago

Constantin, I looked into the conversion process, and the AST looks like this:

In the VAR_DATE node, we can see that a refid annotation is being added by post_parse_fixups.xml. Based on my analysis, this annotation likely should not be added in this context.
Here’s the relevant rule definition:

         <rule>
            !(type == prog.wid_dialog or type == prog.wid_frame or type == prog.wid_window) and 
            (evalLib("variables") or evalLib("widget_references"))      and
            type != prog.sys_handle                                     and
            isNote("tempidx")                                           and
            (!isNote('tempidx-file')        or 
             ancestor(prog.method_def, -1)  or 
             ancestor(prog.constructor, -1) or
             evalLib("widget_references"))                              and
            dictionaryContains("var_defs", #(java.lang.String) execLib("compute_key"))

The problem is that later in variable_definitions_unrefd.rules, there's a rule that checks for the presence of the refid annotation. If it's found, the node’s ID is removed from the unrefd hash set, which results in the generation of a SharedVariable.lookupVariable(...) instead of the expected lookupVariableUnreferenced(...).

      <!-- any reference to a variable in the set means that it should be
           removed since it must be a "live" var -->
      <!-- aside from  a like clause for a shared var that is not defined yet -->
      <rule>isNote("refid")
         <action>unrefd.remove(getNoteLong("refid"))</action>
      </rule>

#5 Updated by Paula Păstrăguș about 1 year ago

Regarding the rule I mentioned earlier, I would suggest adding a new condition like the following at a first glance:

!(this.parent.parent.type == prog.DEFINE_VARIABLE and this.parent.parent.descendant(1, prog.KW_SHARED) and this.parent.parent.descendant(1, prog.KW_LIKE))

#6 Updated by Constantin Asofiei about 1 year ago

We need to exclude the 'meta' usage when checking the 'refid' - so in variable_definitions_unrefd.rules, do not use a refid if the parent is a KW_LIKE.

The same can be said about def temp-table tt1 field f1 like var1. - this is a 'meta' reference of the variable. Can you think of other syntax where a var can be used as a 'meta' reference?

#7 Updated by Constantin Asofiei about 1 year ago

Paula Păstrăguș wrote:

Regarding the rule I mentioned earlier, I would suggest adding a new condition like the following at a first glance:
[...]

KW_LIKE is processed later on in the conversion pipe-line - so the refid annotation there is required, to resolve the reference from which the definition is read.

#8 Updated by Paula Păstrăguș about 1 year ago

Alright, I tried my quick workaround and the conversion completed successfully... However, I see your point. So just to confirm, you're suggesting that the better solution would be to update variable_definitions_unrefd.rules so that it doesn't remove the ID from the unrefd set?

#9 Updated by Constantin Asofiei about 1 year ago

Paula Păstrăguș wrote:

So just to confirm, you're suggesting that the better solution would be to update variable_definitions_unrefd.rules so that it doesn't remove the ID from the unrefd set?

Yes, for KW_LIKE parent and anything else you can find. 'unreferenced' in 4GL I think means 'is not read/written', not that is not used as a 'like'.

#10 Updated by Paula Păstrăguș about 1 year ago

Okay, I’ll also look for other test cases that involve those kind of variables.

#11 Updated by Holly Brown about 1 year ago

Please can you add CA-24875 to the case_num?
thank you

#12 Updated by Radu Apetrii about 1 year ago

  • case_num set to CA-24875

#13 Updated by Paula Păstrăguș about 1 year ago

I looked for other scenarios, but it seems that LIKE remains the only problematic case in this context.

Here's a patch:

=== modified file 'rules/annotations/variable_definitions_unrefd.rules'
--- old/rules/annotations/variable_definitions_unrefd.rules    2023-05-10 07:41:38 +0000
+++ new/rules/annotations/variable_definitions_unrefd.rules    2025-05-21 12:19:13 +0000
@@ -135,7 +135,7 @@

       <!-- any reference to a variable in the set means that it should be
            removed since it must be a "live" var -->
-      <rule>isNote("refid")
+      <rule>isNote("refid") and parent.type != prog.KW_LIKE
          <action>unrefd.remove(getNoteLong("refid"))</action>
       </rule>

I performed an incremental conversion of a customer application, and everything went smoothly. Of course, to properly validate the fix, a full conversion should eventually be done. However, until then, Constantin, does the fix meet your expectations?

#14 Updated by Constantin Asofiei about 1 year ago

Paula Păstrăguș wrote:

However, until then, Constantin, does the fix meet your expectations?

Yes, thank you.

#15 Updated by Paula Păstrăguș about 1 year ago

  • Status changed from New to Internal Test
  • Assignee set to Paula Păstrăguș
  • % Done changed from 0 to 100

Conversion testing passed: unused variables were successfully dropped, and unused shared variables were emitted using lookupVariableUnreferenced.

Runtime testing also passed for both ChUI and a large GUI application.

#16 Updated by Paula Păstrăguș about 1 year ago

Committed to 10027a/15933.

Constantin, please double-check the revision.

If everything looks good, Radu, we’d like to add this to the merging queue.

#17 Updated by Constantin Asofiei about 1 year ago

Paula Păstrăguș wrote:

Committed to 10027a/15933.

Constantin, please double-check the revision.

The branch is OK.

If everything looks good, Radu, we’d like to add this to the merging queue.

Radu: lets plan to merge this on Monday.

Do we need this in #8966 branch?

#18 Updated by Radu Apetrii about 1 year ago

Constantin Asofiei wrote:

Do we need this in #8966 branch?

We'll see in #9945 if these changes should be ported to 9866a.

#19 Updated by Constantin Asofiei about 1 year ago

  • Status changed from Internal Test to Merge Pending

Please merge 10027a after 9583b.

#20 Updated by Paula Păstrăguș about 1 year ago

  • Assignee deleted (Paula Păstrăguș)
  • Status changed from Merge Pending to Test

10027a was merged to trunk as rev 15935 and archived.

#21 Updated by Paula Păstrăguș about 1 year ago

  • Assignee set to Paula Păstrăguș

Also available in: Atom PDF