[Prev][Next][Index]

bug report




We fixed a bug in Sage++ similar to yours when we implement
interprocedural analysis including global variable in our project on
top of Sage++.  The bug we fixed is related
to common statement of Fortran, but I believe that error is the same.
The following is the bug report. I hope it will help you find the right
place to fix your bug.

Cheers,

A/Prof. Peiyi Tang                             
Department of Mathematics and Computing          
The University of Southern Queensland               email: ptang@usq.edu.au
Toowoomba QLD 4350				    phone: (61-76) 31 1686
Australia					    fax:   (61-76) 31 1775 
*****************************************************


            Bug Fix 5: Variable list problem for COMMON statement in
                       the Fortran Parser (cftn.gram)

Sage++ Version: 1.00 

Test Program:
       program test
       common /u/ d,g /v/ x,y
       end

   Call this program ``ex1.f''.

       
How to test:
1. Run f2dep for the above fortran program and produece ex1.dep file

2. Run the ``main'' program in /data3/ptang/research/anu_ext/unil/synTree/
    to dump the syntax tree of the common statement. (type ``main ex1.proj'')
  
   The source code of program main is main.C which will uses
   wzClassFix.h. 


Problem:
The output of the above test is
Line    0: GLOBAL
Line    1: PROG_HEDR: test,233bd8 
Line    2: COMM_STAT: 2 
  list(0)
  COMM_LIST <u,233be8> 1 
    EXPR_LIST 
      VAR_REF <d,233bf8>
    COMM_LIST  0 
      EXPR_LIST 
        VAR_REF <g,233c08>
  list(1)
  COMM_LIST <v,233c18> 0 
    EXPR_LIST 
      VAR_REF <x,233c28>
    COMM_LIST  0 
      EXPR_LIST 
        VAR_REF <y,233c38>
Line    3: CONTROL_END

This is wrong, because variable d and g should belong to the same list
in the named common statement ( the same for x and y). That is, we
should have 
Line    0: GLOBAL
Line    1: PROG_HEDR: test,233bd8 
Line    2: COMM_STAT: 2 
  list(0)
  COMM_LIST <u,233be8> 1 
    EXPR_LIST 
      VAR_REF <d,233bf8>
    EXPR_LIST 
      VAR_REF <g,233c08>
  list(1)
  COMM_LIST <v,233c18> 0 
    EXPR_LIST 
      VAR_REF <x,233c28>
    EXPR_LIST 
      VAR_REF <y,233c38>
Line    3: CONTROL_END

The problem is that the syntax rule for ``common'' in
SAGEROOT/f2dep/cftn.gram fails to recogize lists of variables in
common statement. Following is the original rule for ``common'':
common:	  COMMON in_dcl var
	    { PTR_LLND p, q;

              p = make_llnd(fi,EXPR_LIST, $3, LLNULL, SMNULL);
	      q = make_llnd(fi,COMM_LIST, p, LLNULL, SMNULL);
	      $$ = get_bfnd(fi,COMM_STAT, SMNULL, q, LLNULL, LLNULL);
	    }
	| COMMON in_dcl comblock var
	    { PTR_LLND p, q;

              p = make_llnd(fi,EXPR_LIST, $4, LLNULL, SMNULL);
	      q = make_llnd(fi,COMM_LIST, p, LLNULL, $3);
	      $$ = get_bfnd(fi,COMM_STAT, SMNULL, q, LLNULL, LLNULL);
	    }
	| PROCESS_COMMON in_dcl var
	    { PTR_LLND p, q;

              p = make_llnd(fi,EXPR_LIST, $3, LLNULL, SMNULL);
	      q = make_llnd(fi,COMM_LIST, p, LLNULL, SMNULL);
	      $$ = get_bfnd(fi,PROC_COM, SMNULL, q, LLNULL, LLNULL);
	    }
	| PROCESS_COMMON in_dcl comblock var
	    { PTR_LLND p, q;

              p = make_llnd(fi,EXPR_LIST, $4, LLNULL, SMNULL);
	      q = make_llnd(fi,COMM_LIST, p, LLNULL, $3);
	      $$ = get_bfnd(fi,PROC_COM, SMNULL, q, LLNULL, LLNULL);
	    }
	| common opt_comma comblock opt_comma var
	    { PTR_LLND p, q;

              p = make_llnd(fi,EXPR_LIST, $5, LLNULL, SMNULL);
	      q = make_llnd(fi,COMM_LIST, p, LLNULL, $3);
	      add_to_lowList(q, $1->entry.Template.ll_ptr1);
	    }
	| common COMMA var
	    { PTR_LLND p, q, r;

              p = make_llnd(fi,EXPR_LIST, $3, LLNULL, SMNULL);
	      q = make_llnd(fi,COMM_LIST, p, LLNULL, SMNULL);
	      for (r = $1->entry.Template.ll_ptr1;
		   r->entry.list.next;
		   r = r->entry.list.next);
	      add_to_lowLevelList(q, r->entry.Template.ll_ptr1);
	    }
	;


How to fix:

The problem is fixed by adding two non-terminals ``comlist'' and
``comvarlist'' and make changes to the rule for common.

Step1: Add  the following new line
%type <ll_node> comlist comvarlist
after the line
%type <ll_node> savelist saveitem

Step2: change the first two subrules for common. In, particular, you
can do it by
commenting out the original rule for common and adding the following
new rule for common entirely:

common:   COMMON in_dcl comlist
            {
              $$ = get_bfnd(fi,COMM_STAT, SMNULL, $3, LLNULL, LLNULL);
            }
        | COMMON in_dcl comvarlist
            { PTR_LLND p;
              p = make_llnd(fi,COMM_LIST, $3, LLNULL, SMNULL);
              $$ = get_bfnd(fi,COMM_STAT, SMNULL, p, LLNULL, LLNULL);
            }
        | PROCESS_COMMON in_dcl var
            { PTR_LLND p, q;
 
              p = make_llnd(fi,EXPR_LIST, $3, LLNULL, SMNULL);
              q = make_llnd(fi,COMM_LIST, p, LLNULL, SMNULL);
              $$ = get_bfnd(fi,PROC_COM, SMNULL, q, LLNULL, LLNULL);
            }
        | PROCESS_COMMON in_dcl comblock var
            { PTR_LLND p, q;
 
              p = make_llnd(fi,EXPR_LIST, $4, LLNULL, SMNULL);
              q = make_llnd(fi,COMM_LIST, p, LLNULL, $3);
              $$ = get_bfnd(fi,PROC_COM, SMNULL, q, LLNULL, LLNULL);
            }
        | common opt_comma comblock opt_comma var
            { PTR_LLND p, q;
 
              p = make_llnd(fi,EXPR_LIST, $5, LLNULL, SMNULL);
              q = make_llnd(fi,COMM_LIST, p, LLNULL, $3);
              add_to_lowList(q, $1->entry.Template.ll_ptr1);
            }
        | common COMMA var
            { PTR_LLND p, q, r;
 
              p = make_llnd(fi,EXPR_LIST, $3, LLNULL, SMNULL);
              q = make_llnd(fi,COMM_LIST, p, LLNULL, SMNULL);
              for (r = $1->entry.Template.ll_ptr1;
                   r->entry.list.next;
                   r = r->entry.list.next);
              add_to_lowLevelList(q, r->entry.Template.ll_ptr1);
            }
        ;

Step3: add the following two new rules after the rule for common:
comvarlist:  comvarlist COMMA var
            { PTR_LLND p;
 
              p = make_llnd(fi,EXPR_LIST, $3, LLNULL, SMNULL);
              add_to_lowLevelList(p, $1);
            }
        | var
            { 
               $$ = make_llnd(fi,EXPR_LIST, $1, LLNULL, SMNULL);
            }
        ;
comlist:  comlist comblock comvarlist
            { PTR_LLND p;
              p = make_llnd(fi,COMM_LIST,$3,LLNULL,$2);
              add_to_lowLevelList(p, $1);
            }
        | comblock comvarlist
            { 
              $$ = make_llnd(fi,COMM_LIST,$2,LLNULL,$1);
            }
        ;
 



Note: I notice that the rule for common in later version of sage++ is
split to common and pcommon. pcommon is for common statement in
Fortran M. Whe you make changes, please make changes to rule for
common only for the time being, i.e. change the first two subrules for
common only.

-ptang (14/4/95)