Imagix 4D User Guide


Variable Dependencies

For global, static and local variables, Variable Dependencies shows the calculations that effect the value of the variable. This is the same information that's presented in the Variable Table display of the Calculation Trees, but the report spans all of the variables in the project. Consider the following example:

int gv = 1, gv2;
int *pgv = &gv2;

int func1 (int p1, int *p2) {
    p1++;
    gv2 = *p2;
    if (p1)
	*p2 = 5;
    else
	*p2 = p1 + *p2;

    int z = p1 + *p2;
    pgv = &gv;

    return z + gv;
}

void func2() {
    int x = 1, y = 2;
    if (gv) gv = 2;
    int ret = func1 (x, &y);
    int t = gv2;
    *pgv = 5;
    if (gv)
	int d = x + y;
    gv++;
    y = x + gv;
    gv = ret + x;
}

In the report settings, you choose to examine either the upstream (fan-in) assignments that contribute to the value of the variable or the downstream (fan-out) statements that are impacted by the assignments to the variable. Which choice to make depends on what you're trying to accomplish.

Contributing Statements modeIf you're examining the reading of the value of a variable in the program, then you often want to know how this value is calculated from other values earlier. This is typically used for understanding or debugging the code.
Impacted Statements modeIf you want to know what happens if the assignment to a variable in a particular location is changed, then you normally want to know what statements could be affected. This is typically used for what-if or change analysis.

The choice you make is indicated in the header file of the report:

Variable Dependencies

Settings:
        Global Variables:                       displayed
        Static Variables:                       displayed
        Local Variables:                        displayed
        Show Contributing Statements (Fan-in):  displayed
        Show Impacted Statements (Fan-out):     omitted

Variable                                          File
    Category of Usage
        Containing Function
            Usage
                Contributing Statements

The report then lists the results for each variable. Each variable-specific section shows the assignments and statements related directly to that variable. With the report configured to Show Contributing Statements (Fan-in), here is the corresponding section for the global variable gv in the above sample code:

gv                                                calls.cpp  (1)
    Assignments through Reference
        func2                                             calls.cpp
             23 *pgv = 5;
            Contributing Statements
                file level                                        calls.cpp
                      2 int *pgv = &gv2;
                func1                                             calls.cpp
                     13 pgv = &gv;

    Direct Assignments
        file level                                        calls.cpp
              1 int gv = 1, gv2;
        func2                                             calls.cpp
             20 if (gv) gv = 2;
             26 gv++;
            Contributing Statements
                file level                                        calls.cpp
                      1 int gv = 1, gv2;
                func2                                             calls.cpp
                     20 if (gv) gv = 2;
                     23 *pgv = 5;

             28 gv = ret + x;
            Contributing Statements
                func2                                             calls.cpp
                     19 int x = 1, y = 2;
                     21 int ret = func1 (x, &y);

    Return Value
        func1                                             calls.cpp
             15 return z + gv;
            Contributing Statements
                file level                                        calls.cpp
                      1 int gv = 1, gv2;
                func2                                             calls.cpp
                     20 if (gv) gv = 2;

    Used in Condition
        func2                                             calls.cpp
             20 if (gv) gv = 2;
            Contributing Statements
                file level                                        calls.cpp
                      1 int gv = 1, gv2;

             24 if (gv)
            Contributing Statements
                file level                                        calls.cpp
                      1 int gv = 1, gv2;
                func2                                             calls.cpp
                     20 if (gv) gv = 2;
                     23 *pgv = 5;

    Used in Expression
        func2                                             calls.cpp
             27 y = x + gv;
            Contributing Statements
                file level                                        calls.cpp
                      1 int gv = 1, gv2;
                func2                                             calls.cpp
                     20 if (gv) gv = 2;
                     23 *pgv = 5;
                     26 gv++;

In the section for a variable, the statements involving the variable are organized, first by category of use, then by containing function, then by the usage itself, displayed as the line number and source code snippet of where the actual statement occurs.

In this section for gv, in the Direct Assignments category, is a list of every statement where the value of gv is directly set. At the containing function/location level, you can see that gv is initialized at the file level, and is also directly set in func2. And at the usage statement level, within func2, gv is set at three lines (20, 26 and 28).

For each of these usage statements being reported, any directly related statements in the data flow are displayed.

Consider the direct assignment of gv at line 28, where "gv = ret + x;". Because this report has been configured to show fan-in, the subsection for line 28 is named Contributing Statements and displays upstream dependencies. There are two variables, ret and x, that contribute to value assigned to gv at this line, and the Contributing Statements subsection lists the statements where the values of each of those variables are set.

Here is the section for the same variable when the report is configured to Show Impacted Statements (Fan-out):

gv                                                calls.cpp  (1)
    Assignments through Reference
        func2                                             calls.cpp
             23 *pgv = 5;
            Impacted Statements
                func2                                             calls.cpp
                     24 if (gv)
                     26 gv++;
                     27 y = x + gv;

    Direct Assignments
        file level                                        calls.cpp
              1 int gv = 1, gv2;
            Impacted Statements
                func1                                             calls.cpp
                     15 return z + gv;
                func2                                             calls.cpp
                     20 if (gv) gv = 2;
                     24 if (gv)
                     26 gv++;
                     27 y = x + gv;

        func2                                             calls.cpp
             20 if (gv) gv = 2;
            Impacted Statements
                func1                                             calls.cpp
                     15 return z + gv;
                func2                                             calls.cpp
                     24 if (gv)
                     26 gv++;
                     27 y = x + gv;

             26 gv++;
            Impacted Statements
                func2                                             calls.cpp
                     26 gv++;
                     27 y = x + gv;

             28 gv = ret + x;
    Reference Taken
        func1                                             calls.cpp
             13 pgv = &gv;
            Impacted Statements
                func1                                             calls.cpp
                     13 pgv = &gv;
                     15 return z + gv;
                func2                                             calls.cpp
                     24 if (gv)
                     26 gv++;
                     27 y = x + gv;

While the section for gv has the same organization (category of use > location of use > usage statement), different statements (and correspondingly different categories of use) are reported. In Contributing Statements mode, the report lists all ways the variable is used (right hand-side of assignments, parameter passing, or conditions). For each usage, the Contributing Statements subsection that follows shows where the values come from which are either assignments or parameter passing.

For Impacted Statements mode, the opposite is displayed. The report lists assignments and parameter passing; for each reported usage, an Impacted Statements subsection that follows lists all the ways the variable is used.

The categories are not completely different, there is some overlap between the two modes, but because of the flow direction, certain types are not meaningful.

The file-level Direct Assignment of gv at line 1 provides an example of how the subsection changes depending upon which mode is selected. When Show Impacted Statements is selected, this assignment has an associated subsection. As the usage of gv at line 1 is a simple initialization, there are no Contributing Statements. But because gv is used in the code, the report lists each of the downstream statements where gv is directly used, because these statements are effected by the initialization.

Categories of Use

Direct AssignmentsThese are assignments to the variable with the variable name explicitly on the left hand side of the assignment statement.
Assignments through ReferenceThese are assignments to the variable through a pointer that can be a reference to the variable.
Reference TakenThese are assignments to some pointer variable with the reference of the variable on the right hand side of the assignment. It is expected that that pointer can be later used to read or set that variable.
Used in ExpressionThese are uses of the variable, or uses of a pointer to the variable that are dereferenced, in an expression in an assignment to some other variable. It can also be in index expressions for arrays.
Used in ConditionThese are uses of the variable, or uses of a pointer to the variable that are dereferenced, in a condition of an if, while, do, or switch statement.
Used as Actual ParameterThese are uses of the variable, or uses of a pointer to the variable that are dereferenced, in an expression that is passed to a function.
Root Function ParameterThese are for formal parameters of root functions which have no caller. It is a placeholder to indicate that the variable has a value but nothing is known about that value.
Parameter AssignmentsThese are for formal parameters of non-root functions in the locations of their calls. They indicate the assignment of the actual parameter to the formal parameter.
Assignments through Reference ParameterThese are assignments to the variable through a pointer that can be a reference to the variable. The pointer is a parameter of the function and the reference to the variable is set in the call.
Return ValueThese are uses of the variable, or uses of a pointer to the variable that are dereferenced, in a return statement.

Comparison to Calculation Tree

The Variable Dependencies report and the Calculation Tree tool are closely related. Both determine and display the calculations that effect the value of the variable. Both offer the choice of analyzing the upstream data flow (Show Contributing Statements) or tracking the downstream flow (Show Impacted Statements). The Variable Table display of the Calculation Tree in particular resembles the Variable Dependencies report.

Because the Calculation Tree focuses on one specific variable in your software, typically at a specific line in the source code, there are a couple of significant ways in which the report and the tool differ.

When the right-click menu in the File Editor is used to invoke the Calculation Tree from a specific line in the source code, all the data flow dependency analysis is done with respect to that specific statement. In contrast, for a given variable, the Variable Dependencies analyzes all possible starting points. It is these starting points that are listed under Usage, and organized by category and function location. The full list of usage entries may itself be valuable in studying a variable. To use the report to study a specific usage, find the statement of interest, and examine the Contributing Statements or Impacted Statements subsection that follows it.

The limited scope of the Calculation Tree focus permits display of the full hierarchy of the data flow for the target statement or variable, transitively tracking assignments across the full chain of variables leading into or out from the target. With the Variable Dependencies report, where all usage statements are reported for all variables, the Contributing Statements or Impacted Statements subsection for each usage statement is necessarily limited to the directly effected statements.

As a result, tracking the data flow transitively across variables can involve examining the sections in Variable Dependencies for related variables. A given related variable can be identified through the source code snippet displayed in the Contributing Statements or Impacted Statements subsection. Moving to the section for that related variable is aided by the report window's symbol-based and string-based search functions.

Even with these aids, this process can be cumbersome if you limit your analysis to using just the Variable Dependencies report. First using the Variable Dependencies report to identify any assignments of interest, and then launching the Calculation Tree to examine such assignments in detail is the quickest and easiest approach to exploring full transitive data flows in your software.