varusage

Variable usage

Rule "varusage" tests for two different events:

  • variable [identifier] is never accessed
  • variable [identifier] in procedure [procname] hides object in program scope

variable [identifier] is never accessed

This means your program defines a variable and perhaps assigns a value to that variable,
but the value of that variable is never accessed. It does not necessarily mean that the variable
itself appears nowhere in the source.

Let's have a look at a small example program:

DEFINE VARIABLE var_1 AS DECIMAL NO-UNDO.
DEFINE VARIABLE var_2 AS DECIMAL NO-UNDO.
DEFINE VARIABLE var_3 AS DECIMAL NO-UNDO.
  
var_1 = SQRT(var_2 * var_2 + var_3 * var_3).

In this example, variable var_1 is never accessed.
It has a value, but this value is never used for output or assignment to another field/variable. It may be a left-over from a piece of obsolete code that was
supposed to be deleted.

the risc:

variable var_1 is a waste of space, both in the sourcefile as in memory at runtime, and assigning a value to it is also a waste of time.

how to solve this:

You can simply delete the definition of variable var_1.
This may cause a compile error if the variable appears anywhere in the source like in the given example.
Disclaimer: read the source carefully before you delete the variable, Prolint may have reported a false positive!

variable [identifier] in procedure [procname] hides object in program scope

This means that a local variable inside an internal procedure has the same name as a variable which is defined at the program scope.
An example:

DEFINE VARIABLE firstname AS CHARACTER NO-UNDO.
PROCEDURE FindSalesRep :     
   DEFINE VARIABLE firstname AS CHARACTER NO-UNDO.
   DEFINE VARIABLE lastname  AS CHARACTER NO-UNDO.
   
   FIND FIRST salesrep EXCLUSIVE-LOCK NO-ERROR.
   ASSIGN 
      firstname = ENTRY(1,salesrep.repname," ":U)
      lastname  = ENTRY(2,salesrep.repname," ":U)
      salesrep.repname = lastname + ", ":U + firstname.
      
END PROCEDURE.

Because procedure FindSalesRep defines a local variable firstname, there is no way it can access the variable firstname which was
defined at the program level.

the risc:

Well, technically this is not a bad thing, but a programmer could easily get confused when he/she reads the sourcecode.


One might argue that the variable at the program level should not have been
defined at all, or should at least have been defined with a different name that indicates its large scope.

how to solve this:

Remove one of the variables, or rename one of them. It is usually preferred to remove the variable at the program level; keep the scope of variables as short as possible.


How to suppress these warnings:

You can put the directive {&_proparse_ prolint-nowarn(varusage)} directly before
the DEFINE statement that defines the variable (or parameter). See also: suppress warnings.

Be careful though, because in this particular case the directive may cause confusion. Example:

DEFINE VARIABLE firstname AS CHARACTER NO-UNDO.
PROCEDURE FindSalesRep :     
   {&_proparse_ prolint-nowarn(varusage)}
   DEFINE VARIABLE firstname AS CHARACTER NO-UNDO.
   DEFINE VARIABLE lastname  AS CHARACTER NO-UNDO.
   
   FIND FIRST salesrep EXCLUSIVE-LOCK NO-ERROR.
   ASSIGN 
      firstname = ENTRY(1,salesrep.repname," ":U)
      lastname  = ENTRY(2,salesrep.repname," ":U)
      salesrep.repname = lastname + ", ":U + firstname.
      
END PROCEDURE.

In this example the directive was placed at the local variable. As a result, this definition is now completely invisible to Prolint, so Prolint
will:

  • a. not notice that "firstname" is defined twice, so will not warn about hiding objects,
  • b. think that 'salesrep.repname = lastname + ", ":U + firstname' actually accesses the variable at the program scope.
  • Same source, different placement of the directive:

    {&_proparse_ prolint-nowarn(varusage)}
    DEFINE VARIABLE firstname AS CHARACTER NO-UNDO.
    PROCEDURE FindSalesRep :     
       DEFINE VARIABLE firstname AS CHARACTER NO-UNDO.
       DEFINE VARIABLE lastname  AS CHARACTER NO-UNDO.
       
       FIND FIRST salesrep EXCLUSIVE-LOCK NO-ERROR.
       ASSIGN 
          firstname = ENTRY(1,salesrep.repname," ":U)
          lastname  = ENTRY(2,salesrep.repname," ":U)
          salesrep.repname = lastname + ", ":U + firstname.
          
    END PROCEDURE.
    

    In this case the large-scoped definition is hidden for Prolint. Prolint will not check if this large-scoped variable is ever accessed.

    The difference between these two placements may not be clear until there are more internal procedures and functions, some of which actually do access the variable at the program-level.

    implementation:
    This rule is implemented in Turbolint.


    Comments

    Comment viewing options

    Select your preferred way to display the comments and click "Save settings" to activate your changes.
    jurjen's picture

    rule "Varusage" skips shared variables now

    In Prolint release 73 the "varusage" rule will ignore shared variables. I mean, it will not report that a variable is not used when it is defined as a shared variable. The motivation is, that the variable is probably used in a different compilation unit.

    This new behavior is configurable. The (new) default is that shared variables are skipped but you can change that back to the previous behavior. To do so, have a look at file "prolint/prolint.properties.p" and search for the setting of "rules.varusage.SkipNewShared".
    As always with file "prolint.properties.p" take into consideration that changes to this file will be lost when you upgrade Prolint. So don't change the file, instead create your own private "prolint/custom/prolint.properties.p" with no more than just those properties you'd like to override.