Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

FGExpr.java

00001 package edu.ksu.cis.bandera.bofa;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * Bandera, a Java(TM) analysis and transformation toolkit           *
00005  * Copyright (C) 1998, 1999                                          *
00006  * John Hatcliff (hatcliff@cis.ksu.edu)
00007  * All rights reserved.                                              *
00008  *                                                                   *
00009  * This work was done as a project in the SAnToS Laboratory,         *
00010  * Department of Computing and Information Sciences, Kansas State    *
00011  * University, USA (http://www.cis.ksu.edu/santos).                  *
00012  * It is understood that any modification not identified as such is  *
00013  * not covered by the preceding statement.                           *
00014  *                                                                   *
00015  * This work is free software; you can redistribute it and/or        *
00016  * modify it under the terms of the GNU Library General Public       *
00017  * License as published by the Free Software Foundation; either      *
00018  * version 2 of the License, or (at your option) any later version.  *
00019  *                                                                   *
00020  * This work is distributed in the hope that it will be useful,      *
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *
00023  * Library General Public License for more details.                  *
00024  *                                                                   *
00025  * You should have received a copy of the GNU Library General Public *
00026  * License along with this toolkit; if not, write to the             *
00027  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,      *
00028  * Boston, MA  02111-1307, USA.                                      *
00029  *                                                                   *
00030  * Java is a trademark of Sun Microsystems, Inc.                     *
00031  *                                                                   *
00032  * To submit a bug report, send a comment, or get the latest news on *
00033  * this project and other SAnToS projects, please visit the web-site *
00034  *                http://www.cis.ksu.edu/santos                      *
00035  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00036 
00037 import java.util.Hashtable;
00038 import ca.mcgill.sable.soot.*;
00039 import ca.mcgill.sable.soot.jimple.*;
00040 import ca.mcgill.sable.soot.jimple.Stmt;
00041 import ca.mcgill.sable.util.*;
00042 import edu.ksu.cis.bandera.jjjc.CompilationManager;
00043 import org.apache.log4j.Category;
00044 // robbyjo's patch begin
00045 import edu.ksu.cis.bandera.jext.*;
00046 // robbyjo's patch end
00047 /*
00048  * FGExpr.java
00049  * $Id: FGExpr.java,v 1.1.1.1 2002/01/24 03:42:07 pserver Exp $
00050  */
00051 
00052 /**
00053  * This class provides methods to create various FGNodes for various expressions
00054  * that may occur in the Jimple statment.
00055  *
00056  * @author <A HREF="http://www.cis.ksu.edu/~hatcliff">John Hatcliff</A>
00057  * @author 
00058  * <A HREF="http://www.cis.ksu.edu/~rvprasad">Venkatesh Prasad Ranganath</A>
00059  * @version $Name:  $($Revision: 1.1.1.1 $)
00060  */
00061 //public class FGExpr extends AbstractJimpleValueSwitch
00062 // robbyjo's patch begin
00063 //public class FGExpr extends AbstractJimpleValueSwitch
00064 public class FGExpr extends AbstractBanderaValueSwitch
00065 // robbyjo's patch end
00066 {
00067     /** 
00068      * Stores the common set of class tokens used during analysis.  An example
00069      * would be a class corresponding to null object.
00070      */
00071     private static Hashtable commonTokens = new Hashtable();
00072 
00073     /** 
00074      * Represents the method enclosing the expressions being processed by this
00075      * object.
00076      */
00077     private MethodVariant methodVariant;
00078 
00079     /** 
00080      * Maps AST nodes and flow graph nodes.
00081      */
00082     private Map astNodes;
00083 
00084     /** 
00085      * Represents the expression being processed.  We shall use the the Jimple
00086      * expression to denote the allocator site. This will be unique in terms of
00087      * object involved and not the value of the object
00088      */
00089     private Value value; 
00090 
00091     /** 
00092      * Represents the statement in which the expression being processed
00093      * occurs. <code>stmt</code> is used to map the <code>value</code> to jimple
00094      * statements
00095      */
00096     private Stmt stmt;   
00097     
00098     /**
00099      * Provides logging capabilities through log4j.
00100      *
00101      */
00102     private static Category cat;
00103     
00104     static {
00105         cat = Category.getInstance(FGExpr.class.getName());
00106     }
00107 
00108     /** 
00109      * Constructor of the class. 
00110      *
00111      * @param methodVariant the method enclosing the expression being processed.
00112      * @param astNodes the map of AST nodes to flow graph nodes in the method. 
00113      */
00114     public FGExpr(MethodVariant methodVariant, Map astNodes)
00115     {
00116         this.methodVariant = methodVariant;
00117         this.astNodes      = astNodes;
00118     }
00119     /** Note: there must be many LHSs that aren't handled now:
00120      *  field access, array indexing, etc.
00121      */
00122 
00123     /** 
00124      * Builds the flow graph node for the given expression.
00125      *
00126      * @param v the expression for which the flow graph node should be
00127      * constructed. 
00128      * @param s the statement in which the expression occurs.
00129      * @return the flow graph node associated with the expression.
00130      */
00131     public FGNodeAST build(Value v, Stmt s)
00132     {
00133         stmt = s;
00134         value = v;
00135         v.apply(this);
00136         FGNodeAST astNode = (FGNodeAST)this.getResult();
00137         if (astNode != null) {
00138             astNode.setStmt(stmt);
00139         } // end of if (astNode != null)
00140         return astNode;
00141     }
00142     /**
00143      * We donot handle expressions that do not evaluate to objects.
00144      *
00145      * @param v an <code>AddExpr</code> value
00146      */
00147     public void caseAddExpr(AddExpr v)
00148     {
00149         setResult(null);
00150     }
00151     /**
00152      * We donot handle expressions that do not evaluate to objects.
00153      *
00154      * @param v an <code>AndExpr</code> value
00155      */
00156     public void caseAndExpr(AndExpr v)
00157     {
00158         setResult(null);
00159     }
00160     /** 
00161      * Handles the case when the expression is an array reference on RHS.
00162      *
00163      * @param v the expression for array reference. 
00164      */
00165     public void caseArrayRef(ArrayRef v)
00166     {
00167         FGNode baseNode = build(v.getBase(), stmt);
00168 
00169         // The "type" attribute of the array ref AST is the component type
00170         // of the array.  Make an array type to use in ClassTokenArray.select
00171         ArrayType arrayType = ClassTokenArray.componentToArrayType(v.getType()); 
00172 
00173         ClassTokenArray classTokenArray = ClassTokenArray.select(arrayType);
00174         // Here, we need to attach an action to the flowgraph as in 
00175         // method invocation.
00176         FGNodeAST arrayRefNode = new FGNodeAST(v);
00177         /* generate action: Different array objects (represented by value
00178          *  variants) may flow into the base node.
00179          *
00180          * For any new value variant that flows into the base node, the array
00181          * variant FGNode that summarizes the contents of the array will be
00182          * found and an FG arc will be made from the contents node to the AST
00183          * node for the current array reference AST node
00184          */
00185         baseNode.addAction(new FGActionArrayRef(classTokenArray,
00186                                                 arrayRefNode, methodVariant));
00187         setResult(arrayRefNode);
00188         astNodes.put(v,arrayRefNode);
00189     }
00190     /** 
00191      * Handles a case when the expression is a cast expression.
00192      *
00193      * @param v the cast expression.
00194      */
00195     public void caseCastExpr(CastExpr v)
00196     {
00197         /* 
00198          * Since we donot perform type checking in our analysis, we just pass on
00199          * all the values flowing into the base node into the node corresponding
00200          * to the cast expression.  We achieve this by just creating an arc. 
00201          */
00202         FGNode baseNode = build(v.getOp(), stmt);
00203         FGNodeAST node = new FGNodeAST(v); 
00204         FGNode.makeArc(baseNode, node);
00205         setResult(node);
00206     }
00207     /**
00208      * We donot handle expressions that do not evaluate to objects.
00209      *
00210      * @param v a <code>CaughtExceptionRef</code> value
00211      */
00212     public void caseCaughtExceptionRef(CaughtExceptionRef v)
00213     {
00214         defaultCase(v);
00215     }
00216 /**
00217  * This method was created in VisualAge by robbyjo.
00218  * @param v edu.ksu.cis.bandera.jext.ChooseExpr
00219  */
00220 public void caseChooseExpr(ChooseExpr v) {
00221     SootClass sc = null;
00222     try {
00223         sc = FA.classManager.getClass("Bandera");
00224     } catch (Exception e) { }
00225 
00226     if (sc == null)
00227     {
00228         System.out.println("WARNING: Bandera class is not handled!");
00229         defaultCase(null);
00230         return;
00231     }
00232 
00233     // For the time being, we'd use Bandera.choose
00234     // It should be Abstraction.choose. I dunno why JJJC hasn't
00235     // produce this kind of code? Or probably the abstraction code
00236     // isn't mature yet or what?
00237     SootMethod sm = null;
00238     List args = new LinkedList();
00239     try {
00240         sm = sc.getMethod("choose", args);
00241     } catch(Exception e) {}
00242     if (sm == null)
00243     {
00244         System.out.println("WARNING: Invalid Bandera class detected: No valid choose() method");
00245     }
00246     StaticInvokeExpr choose = Jimple.v().newStaticInvokeExpr(sm, args);
00247 
00248     caseStaticInvokeExpr(choose);
00249     // args = v.getChoices(); // This is needed when we shift into Abstraction.choose()
00250 //  defaultCase(v);
00251 }
00252     /**
00253      * We donot handle expressions that do not evaluate to objects.
00254      *
00255      * @param v a <code>CmpExpr</code> value
00256      */
00257     public void caseCmpExpr(CmpExpr v)
00258     {
00259         setResult(null);
00260     }
00261     /**
00262      * We donot handle expressions that do not evaluate to objects.
00263      *
00264      * @param v a <code>CmpgExpr</code> value
00265      */
00266     public void caseCmpgExpr(CmpgExpr v)
00267     {
00268         setResult(null);
00269     }
00270     /**
00271      * We donot handle expressions that do not evaluate to objects.
00272      *
00273      * @param v a <code>CmplExpr</code> value
00274      */
00275     public void caseCmplExpr(CmplExpr v)
00276     {
00277         setResult(null);
00278     }
00279 /**
00280  * This method was created in VisualAge by robbyjo.
00281  * @param expr edu.ksu.cis.bandera.jext.ComplementExpr
00282  */
00283 public void caseComplementExpr(ComplementExpr expr) {
00284     defaultCase(expr);
00285 }
00286     /**
00287      * We donot handle expressions that do not evaluate to objects.
00288      *
00289      * @param v a <code>DivExpr</code> value
00290      */
00291     public void caseDivExpr(DivExpr v)
00292     {
00293         setResult(null);
00294     }
00295     /* 
00296      * We are interested in the object values created by the expressions and not
00297      * the constants generated 
00298      */
00299 
00300     /**
00301      * We do not handle double values.
00302      *
00303      * @param v a <code>DoubleConstant</code> value
00304      */
00305     public void caseDoubleConstant(DoubleConstant v)
00306     {
00307         setResult(null);
00308     }
00309     /**
00310      * We donot handle expressions that do not evaluate to objects.
00311      *
00312      * @param v an <code>EqExpr</code> value
00313      */
00314     public void caseEqExpr(EqExpr v)
00315     {
00316         setResult(null);
00317     }
00318     /**
00319      * We do not handle float values.
00320      *
00321      * @param v a <code>FloatConstant</code> value
00322      */
00323     public void caseFloatConstant(FloatConstant v)
00324     {
00325         setResult(null);
00326     }
00327     /**
00328      * We donot handle expressions that do not evaluate to objects.
00329      *
00330      * @param v a <code>GeExpr</code> value
00331      */
00332     public void caseGeExpr(GeExpr v)
00333     {
00334         setResult(null);
00335     }
00336     /**
00337      * We donot handle expressions that do not evaluate to objects.
00338      *
00339      * @param v a <code>GtExpr</code> value
00340      */
00341     public void caseGtExpr(GtExpr v)
00342     {
00343         setResult(null);
00344     }
00345 /**
00346  * This method was created in VisualAge by robbyjo.
00347  * @param v edu.ksu.cis.bandera.jext.InExpr
00348  */
00349 public void caseInExpr(InExpr v) {
00350     defaultCase(v);
00351 }
00352     /* 
00353      * Create a node for this expression.  For each ValueVariant flowing into
00354      * the base, create an arc from the instance variable of that class into
00355      * this node.
00356      *
00357      * Currently, we ignore inheritance and keep track of only one variant of
00358      * the instance.  The instance in the declaring class.  This means that we
00359      * can totally avoid examining the set of values found in the base
00360      * expression. (This will probably result in a lot of imprecision.
00361      */
00362 
00363     /** 
00364      * Handles the case when the expression is an instance field reference
00365      * expression. 
00366      *
00367      * @param v the instance field reference expression.
00368      */
00369     public void caseInstanceFieldRef(InstanceFieldRef v)
00370     {
00371         SootField sootField = v.getField();
00372         InstanceVariant instanceVariant 
00373             = InstanceVariantManager.select(sootField);
00374         FGNodeAST astNode   = new FGNodeAST(v);
00375         FGNode.makeArc(instanceVariant.getNode(), astNode);
00376         astNodes.put(v,astNode);
00377 
00378         setResult(astNode);
00379     }
00380     /**
00381      * We donot handle expressions that do not evaluate to objects.
00382      *
00383      * @param v an <code>InstanceOfExpr</code> value
00384      */
00385     public void caseInstanceOfExpr(InstanceOfExpr v)
00386     {
00387         defaultCase(v);
00388     }
00389     /**
00390      * We do not handle integer values.
00391      *
00392      * @param v an <code>IntConstant</code> value
00393      */
00394     public void caseIntConstant(IntConstant v)
00395     {
00396         ValueVariant valueVariant = 
00397             ValueVariantManager.select(ClassTokenSimple.intClassToken, 
00398                                        methodVariant, value, stmt);
00399 
00400         FGNodeAST node = new FGNodeAST(v);
00401         FGWork work = new FGWorkSendVals(new FASet(valueVariant), node);
00402         FA.workList.insert(work);
00403 
00404         astNodes.put(v, node);
00405         setResult(node);
00406     }
00407     /** 
00408      * Handles the case when the expression is an interface invoke expression.
00409      *
00410      * @param v the expression for the interface invocation
00411      */
00412     public void caseInterfaceInvokeExpr(InterfaceInvokeExpr v)
00413     {
00414         /* 
00415          * We assume that the analysis needs to be done on object of the class
00416          * that implements the interface.  So, it is reasonable to treat a call
00417          * to a method inherited from an interface as equivalent to virtual
00418          * invoke.
00419          */
00420         SootMethod sootMethod     = v.getMethod();
00421         int        argCount       = v.getArgCount(); 
00422         FGNode     baseNode       = build(v.getBase(), stmt);
00423 
00424         /* 
00425          * With interface method invoke, we generate flowgraphs for
00426          * subexpressions (base and args), but arg value and return flows cannot
00427          * be connected now.  An action is attached to the node that will fire
00428          * each time a value flows into the node.  When a new value flows in,
00429          * the action will be fired.
00430          */
00431 
00432         // Now loop through args and generate graphs for the arcs.
00433         FGNode[] argNodes = new FGNode[argCount];
00434 
00435         for (int i=0; i<argCount; i++) {
00436             argNodes[i] = build(v.getArg(i), stmt);
00437         }
00438 
00439         FGNodeAST invokeNode = new FGNodeAST(v);
00440 
00441         // generate action
00442         baseNode.addAction(new FGActionInvoke(argCount,
00443                                               argNodes,
00444                                               invokeNode,
00445                                               sootMethod.getName(),
00446                                               sootMethod.getParameterTypes(),
00447                                               sootMethod.getReturnType()));
00448         setResult(invokeNode);
00449         astNodes.put(v,invokeNode);
00450     }
00451     /**
00452      * We donot handle expressions that do not evaluate to objects.
00453      *
00454      * @param v a <code>LeExpr</code> value
00455      */
00456     public void caseLeExpr(LeExpr v)
00457     {
00458         setResult(null);
00459     }
00460     /**
00461      * We donot handle expressions that do not evaluate to objects.
00462      *
00463      * @param v a <code>LengthExpr</code> value
00464      */
00465     public void caseLengthExpr(LengthExpr v)
00466     {
00467         defaultCase(v);
00468     }
00469     /** 
00470      * Handles the case when the expression is an local variable reference
00471      * expression. 
00472      * 
00473      * @param v the local variable reference expression.
00474      */
00475     public void caseLocal(Local v)
00476     {
00477         FGNodeLocal localNode = methodVariant.getLocalNode(v);
00478         FGNodeAST   astNode   = new FGNodeAST(v);
00479         FGNode.makeArc(localNode, astNode);
00480         astNodes.put(v, astNode);
00481 
00482         setResult(astNode);
00483     }
00484 /**
00485  * This method was created in VisualAge by robbyjo.
00486  * @param v edu.ksu.cis.bandera.jext.LocalExpr
00487  */
00488 public void caseLocalExpr(LocalExpr v) {
00489     defaultCase(v);
00490 }
00491 /**
00492  * This method was created in VisualAge by robbyjo.
00493  * @param e edu.ksu.cis.bandera.jext.LocationTestExpr
00494  */
00495 public void caseLocationTestExpr(LocationTestExpr e) {
00496     defaultCase(e);
00497 }
00498 /**
00499  * This method was created in VisualAge by robbyjo.
00500  * @param expr edu.ksu.cis.bandera.jext.LogicalAndExpr
00501  */
00502 public void caseLogicalAndExpr(LogicalAndExpr expr)
00503 {
00504     defaultCase(expr);
00505 }
00506 /**
00507  * This method was created in VisualAge by robbyjo. 
00508  * @param expr edu.ksu.cis.bandera.jext.LogicalOrExpr
00509  */
00510 public void caseLogicalOrExpr(LogicalOrExpr expr) {
00511     defaultCase(expr);
00512 }
00513     /**
00514      * We do not handle long values.
00515      *
00516      * @param v a <code>LongConstant</code> value
00517      */
00518     public void caseLongConstant(LongConstant v)
00519     {
00520         this.setResult(null);
00521     }
00522     /**
00523      * We donot handle expressions that do not evaluate to objects.
00524      *
00525      * @param v a <code>LtExpr</code> value
00526      */
00527     public void caseLtExpr(LtExpr v)
00528     {
00529         setResult(null);
00530     }
00531     /**
00532      * We donot handle expressions that do not evaluate to objects.
00533      *
00534      * @param v a <code>MulExpr</code> value
00535      */
00536     public void caseMulExpr(MulExpr v)
00537     {
00538         setResult(null);
00539     }
00540     /**
00541      * We donot handle expressions that do not evaluate to objects.
00542      *
00543      * @param v a <code>NeExpr</code> value
00544      */
00545     public void caseNeExpr(NeExpr v)
00546     {
00547         setResult(null);
00548     }
00549     /**
00550      * We donot handle expressions that do not evaluate to objects.
00551      *
00552      * @param v a <code>NegExpr</code> value
00553      */
00554     public void caseNegExpr(NegExpr v)
00555     {
00556         setResult(null);
00557     }
00558     /** 
00559      * Handles the case when the expression is an new array object creation
00560      * expression. 
00561      *
00562      * @param v the array object creation expression.
00563      */
00564     public void caseNewArrayExpr(NewArrayExpr v)
00565     {
00566         ArrayType  arrayType = (ArrayType) v.getType();
00567         ClassToken classToken = ClassTokenArray.select(arrayType);
00568 
00569         /* 
00570          * WARNING: the interface to ValueVariantManager is not completely
00571          * settled, since we may want to adjust the way that events/code
00572          * positions are indexed.  For now, the third argument is some int
00573          * representing a position in the code.
00574          */
00575         ValueVariant valueVariant = ValueVariantManager.select(classToken,
00576                                                                methodVariant,
00577                                                                v, stmt);
00578         FGNodeAST node = new FGNodeAST(v);
00579         FA.workList.insert(new FGWorkSendVals(new FASet(valueVariant), node));
00580 
00581         /* 
00582          * Note: at this point we have NOT created the flow graph node
00583          * corresponding to the components of the newly created array.  I'm not
00584          * sure if this is the right thing to do, but it follows what we are
00585          * currently doing for instance variables of newly created instances.
00586          */
00587         astNodes.put(v,node);
00588         setResult(node);    
00589 
00590         /* 
00591          * Get an arrayVariant for the given class of array and new arrayVariant
00592          * that needs to be created by the new expression.
00593          */
00594         ArrayVariant arrayVariant = ArrayVariantManager.select(classToken,
00595                                                                valueVariant);  
00596         /* 
00597          * We get the element type of the array object and create a
00598          * constant(value) of that type.  We obtain a value variant for this
00599          * constant and push this value into the values set of arrayNode.  We
00600          * donot want to create a new SootClass for the base type whereas we
00601          * need to use the one already in use.
00602          */
00603         valueVariant =
00604             ValueVariantManager.select(ClassTokenSimple.nullClassToken, 
00605                                        methodVariant, v, stmt); 
00606         if ( !(v.getBaseType() instanceof RefType)) {
00607              String elementClassStr =
00608                  ((ArrayType)v.getType()).baseType.toString();  
00609              Value temp = getValue(elementClassStr);
00610 
00611              /* we can use getToken(elementType) instead of
00612               * ClassTokenSimple.select(new SootClass(elementType)) for the
00613               * following case
00614               * arr = new t[3];  (1)
00615               * i = arr;
00616               * arr1 = new t[4]; (2)
00617               * it will only contain one null value resulting from site (1) and
00618               * not (2).  It will contain null value from site (1) and (2) if
00619               * ClassTokenSimple.select(elementClass) is used. */
00620              ClassTokenSimple elementClass =ClassTokenSimple
00621                  .select(FA.classManager.getClass(elementClassStr));
00622 
00623              valueVariant = ValueVariantManager.select(elementClass, 
00624                                                        methodVariant, temp, stmt); 
00625         } // end of else
00626         
00627         arrayVariant.getNode().values.add(valueVariant);
00628     }
00629     /** Handles the case when the expression is an new object creation
00630      * expression. 
00631      *
00632      * @param v the object creation expression.
00633      */
00634     public void caseNewExpr(NewExpr v)
00635     {
00636         RefType      refType   = v.getBaseType();
00637         String       className = refType.className;
00638 
00639         /* 
00640          * If this class is "external" (something that we don't want to analyze
00641          * the code for, we could insert a marker here and avoid calling the
00642          * class manager (which loads the class). 
00643          */
00644         SootClass    sootClass = FA.classManager.getClass(className);
00645         ClassToken   classToken = ClassTokenSimple.select(sootClass);
00646 
00647         /* 
00648          * WARNING: the interface to ValueVariantManager is not completely
00649          * settled, since we may want to adjust the way that events/code
00650          * positions are indexed.  For now, the third argument is some int
00651          * representing a position in the code.
00652          */
00653         ValueVariant valueVariant = ValueVariantManager.select(classToken,
00654                                                                methodVariant,
00655                                                                v, stmt);
00656 
00657         FGNodeAST node = new FGNodeAST(v);
00658 
00659         FGWork work = new FGWorkSendVals(new FASet(valueVariant), node);
00660 
00661         FA.workList.insert(work);
00662 
00663         astNodes.put(v,node);
00664         setResult(node);
00665     }
00666     /** 
00667      * Handles the case when the expression is an new multidimensional array
00668      * object creation expression.
00669      *
00670      * @param v the multidimensional array expression.  
00671      */
00672     public void caseNewMultiArrayExpr(NewMultiArrayExpr v)
00673     {
00674         ArrayType  arrayType = (ArrayType) v.getType();
00675         ClassToken classToken = ClassTokenArray.select(arrayType);
00676 
00677         /* 
00678          * WARNING: the interface to ValueVariantManager is not completely
00679          * settled, since we may want to adjust the way that events/code
00680          * positions are indexed.  For now, the third argument is some int
00681          * representing a position in the code.  
00682          */
00683         ValueVariant valueVariant = ValueVariantManager.select(classToken,
00684                                                                methodVariant,
00685                                                                value, stmt);
00686 
00687         FGNodeAST node = new FGNodeAST(v);
00688         FGWork work = new FGWorkSendVals(new FASet(valueVariant), node);
00689         FA.workList.insert(work);
00690 
00691         /* 
00692          * Note: at this point we have NOT created the flow graph node
00693          * corresponding to the components of the newly created array.  I'm not
00694          * sure if this is the right thing to do, but it follows what we are
00695          * currently doing for instance variables of newly created instances.
00696          */
00697         astNodes.put(v,node);
00698         setResult(node);
00699         
00700         /* 
00701          * v.getSizeCount() gives us the number of dimensions for which size has
00702          * been specified.  During declaring new array, the sizes of all the
00703          * dimension following the dimension whose size is unspecified should
00704          * also be unspecified.  So, it is safe only to plug in the values for
00705          * dimensions whose size is specified.
00706          */
00707         int numSpecDim = v.getSizeCount();
00708         int count;
00709         Value valueOfCountDim;
00710         ArrayType componentType;
00711         ArrayVariant arrayVariant;
00712         
00713         for (int j = arrayType.numDimensions - 1; j > arrayType.numDimensions -
00714              numSpecDim; j--) { 
00715             // Create a new ArrayType for the immediate component array object,
00716             // an array less by one dimension. 
00717             componentType = arrayType.v(arrayType.baseType, j); 
00718 
00719             // Get an arrayVariant for the given class of array and new
00720             // arrayVariant that needs to be created by the new expression.  
00721             arrayVariant = ArrayVariantManager.select(classToken, valueVariant);
00722             // Get a new ClassToken for component type of array
00723             classToken = ClassTokenArray.select(componentType);
00724             // Obtain the valuevariant and inject it into the arrayNode value set
00725             valueVariant = ValueVariantManager.select(classToken,
00726                                                       methodVariant,
00727                                                       value, stmt);
00728             // inject the valuevariant into the value set of the arrayvariant
00729             arrayVariant.getNode().values.add(valueVariant);
00730         } // end of for ()
00731         
00732         // if the new expressions does specify the size of all dimension then we
00733         // need to inject the value for the base type of the array object.
00734         if ( numSpecDim == arrayType.numDimensions) {
00735             // Get an arrayVariant for the last array component
00736             arrayVariant = ArrayVariantManager.select(classToken, valueVariant);
00737             // Get a new Value object for the base type's default initial value
00738             Value value = getValue(arrayType.baseType.toString());
00739             /* 
00740              * Get the classToken for the base type.  To do so we must use the
00741              * SootClass corresponding to the base type and should not create a
00742              * new SootClass. Also obtain the valuevariant and inject it into
00743              * the arrayNode value set. 
00744              */ 
00745             valueVariant =
00746                 ValueVariantManager.select(ClassTokenSimple.nullClassToken,
00747                                            methodVariant, value, stmt); 
00748             if ( !(v.getType() instanceof RefType)) {
00749                 String elementClassStr =
00750                     ((ArrayType)v.getType()).baseType.toString();  
00751                 Value temp = getValue(elementClassStr);
00752                 ClassTokenSimple elementClass =
00753                     ClassTokenSimple.select
00754                     (FA.classManager.getClass(elementClassStr)); 
00755                 valueVariant = ValueVariantManager.select(elementClass,
00756                                                           methodVariant, temp, 
00757                                                           stmt);
00758             } // end of else
00759         
00760             // inject the value into the value set associated with the
00761             // arrayvariant
00762             arrayVariant.getNode().values.add(valueVariant);
00763         } // end of if ()
00764     }
00765     /**
00766      * Handles the case where the expression evaluates to a null object.  This
00767      * is necessary as reference types can evaluate to null values.
00768      *
00769      * @param v a <code>NullConstant</code> value
00770      */
00771     public void caseNullConstant(NullConstant v)
00772     {
00773         ValueVariant nullVariant =
00774             ValueVariantManager.select(ClassTokenSimple.nullClassToken, 
00775                                        methodVariant, v, stmt);
00776         FGNodeAST NullNode = new FGNodeAST(v); 
00777         FGWork work = new FGWorkSendVals(new FASet(nullVariant), NullNode);
00778         FA.workList.insert(work);
00779         astNodes.put(v, NullNode);
00780         setResult(NullNode);
00781     }
00782     /**
00783      * We donot handle expressions that do not evaluate to objects.
00784      *
00785      * @param v an <code>OrExpr</code> value
00786      */
00787     public void caseOrExpr(OrExpr v)
00788     {
00789         setResult(null);
00790     }
00791     /** 
00792      * Handles the case when the expression is an parameter reference
00793      * expression.
00794      *
00795      * @param v the parameter reference expression.
00796      */
00797     public void caseParameterRef(ParameterRef v)
00798     {
00799         int index            = v.getIndex();
00800         FGNodeParameter parameterNode = methodVariant.getParameterNode(index);
00801         FGNodeAST astNode    = new FGNodeAST(v);
00802         FGNode.makeArc(parameterNode, astNode);
00803         astNodes.put(v,astNode);
00804 
00805         setResult(astNode);
00806     }
00807     /**
00808      * We donot handle expressions that do not evaluate to objects.
00809      *
00810      * @param v a <code>RemExpr</code> value
00811      */
00812     public void caseRemExpr(RemExpr v)
00813     {
00814         setResult(null);
00815     }
00816     /**
00817      * We donot handle expressions that do not evaluate to objects.
00818      *
00819      * @param v a <code>ShlExpr</code> value
00820      */
00821     public void caseShlExpr(ShlExpr v)
00822     {
00823         setResult(null);
00824     }
00825     /**
00826      * We donot handle expressions that do not evaluate to objects.
00827      *
00828      * @param v a <code>ShrExpr</code> value
00829      */
00830     public void caseShrExpr(ShrExpr v)
00831     {
00832         setResult(null);
00833     }
00834     /** 
00835      * Handles the case when the expression is an special invoke expression.
00836      *
00837      * @param v the expression for the special invocation.
00838      */
00839     public void caseSpecialInvokeExpr(SpecialInvokeExpr v)
00840     {
00841         /* 
00842          * invokespecial does not leave a value on the stack and so we don't
00843          * need to do anything with a return value here, i.e., there is no need
00844          * to hook something into the flow graph for this node.
00845          */
00846 
00847         /* The specialinvoke is just another method invocation with no return
00848          * values.  We can treat them as static methods at class level, but this
00849          * would result in polluting the value space for all objects of a class.
00850          * So, it is better to treat them like virtual invoke in the context of
00851          * object flow analysis even though the exact method implementation to
00852          * be executed is embedded in the invoke expression and may not
00853          * correspond to the static or dynamic type of the receiver, but may be
00854          * to it's super type.
00855          */
00856         SootMethod sootMethod     = v.getMethod();
00857         int        argCount       = v.getArgCount();
00858         FGNode     baseNode       = build(v.getBase(), stmt);
00859 
00860         /* 
00861          * With virtual method invoke, we generate flowgraphs for subexpressions
00862          * (base and args), but arg value and return flows cannot be connected
00863          * now.  An action is attached to the node that will fire each time a
00864          * value flows into the node.  When a new value flows in, the action
00865          * will be fired
00866          */
00867 
00868         // Now loop through args and generate graphs for the arcs.
00869         FGNode[] argNodes = new FGNode[argCount];
00870 
00871         for (int i=0; i<argCount; i++) {
00872             argNodes[i] = build(v.getArg(i), stmt);
00873         }
00874 
00875         FGNodeAST invokeNode = new FGNodeAST(v);
00876 
00877         // generate action to handle constructor call
00878         baseNode.addAction(new FGActionInvoke(argCount,
00879                                               argNodes,
00880                                               invokeNode,
00881                                               sootMethod.getName(),
00882                                               sootMethod.getParameterTypes(),
00883                                               sootMethod.getReturnType(),
00884                                               v.getMethod().getDeclaringClass()));
00885         setResult(invokeNode);
00886         astNodes.put(v,invokeNode);
00887         
00888     }
00889     /** 
00890      * Handles the case when the expression is an static field reference
00891      * expression. 
00892      * 
00893      * @param v the static field reference expression.
00894      */
00895     public void caseStaticFieldRef(StaticFieldRef v)
00896     {
00897         SootField sootField = v.getField();
00898         FGNodeAST astNode   = new FGNodeAST(v);
00899         FGNode.makeArc(StaticFieldManager.select(sootField), astNode);
00900         astNodes.put(v, astNode);
00901         
00902         setResult(astNode);
00903     }
00904     /* 
00905      * With static invoke, no action needs to be generated.  We can simple
00906      * connect the arcs.  However, there is a question of when the call graph
00907      * gets built.  Should it be built now, in a depth-first manner?  In fact,
00908      * if this is simply a reference to another stored class, then we would have
00909      * already generated the flowgraph for that method (or we will generate it).
00910      *
00911      * Well, hmmm, maybe it should still be action driven.  No the variant
00912      * manager should take care of that caching the generation of flowgraphs in
00913      * any order.
00914      */
00915 
00916     /** 
00917      * Handles the case when the expression is an static invoke expression.
00918      * 
00919      * @param v the expression for the invocation
00920      */
00921     public void caseStaticInvokeExpr(StaticInvokeExpr v)
00922     {
00923         SootMethod sootMethod     = v.getMethod();
00924         int        argCount       = v.getArgCount(); 
00925         FGNode[]   argNodes       = new FGNode[argCount];
00926         FGNode paramNode;
00927 
00928         // assume argCount matches method parameter count
00929         MethodVariant methodVariant  = MethodVariantManager.select(sootMethod);
00930 
00931         /* Now loop through args and generate graphs for the arcs, and
00932          * make arcs from each arg to corresponding parameter node.
00933          */
00934         for (int i=0; i<argCount; i++) {
00935             argNodes[i]      = build(v.getArg(i), stmt);
00936             paramNode = methodVariant.getParameterNode(i);
00937             FGNode.makeArc(argNodes[i], paramNode);
00938         }
00939 
00940         FGNodeAST invokeNode = new FGNodeAST(v);
00941         /* make arc from last node of method to AST node. */
00942         FGNode lastNode = methodVariant.getReturnNode();
00943         FGNode.makeArc(lastNode, invokeNode);
00944 
00945         astNodes.put(v,invokeNode);
00946         setResult(invokeNode);
00947     }
00948     /** 
00949      * Handles the case where the expression evaluates to a string.
00950      *
00951      * @param v the string constant involved. 
00952      */
00953     public void caseStringConstant(StringConstant v)
00954     {
00955         SootClass sootClass =
00956             FA.classManager.getClass(RefType.v("java.lang.String").className); 
00957         ClassToken classToken = ClassTokenSimple.select(sootClass);
00958         ValueVariant valueVariant = ValueVariantManager.select(classToken,
00959                                                                methodVariant,
00960                                                                v, stmt);
00961 
00962         // create new node with a string class object in it.
00963         FGNodeAST node = new FGNodeAST(v);
00964         FGWork work = new FGWorkSendVals(new FASet(valueVariant), node);
00965         FA.workList.insert(work);
00966 
00967         astNodes.put(v,node);
00968         setResult(node);
00969     }
00970     /**
00971      * We donot handle expressions that do not evaluate to objects.
00972      *
00973      * @param v a <code>SubExpr</code> value
00974      */
00975     public void caseSubExpr(SubExpr v)
00976     {
00977         setResult(null);
00978     }
00979     /** 
00980      * Handles the case when the expression is an "this" variable reference
00981      * expression. 
00982      *
00983      * @param v the "this" variable reference expression.
00984      */
00985     public void caseThisRef(ThisRef v)
00986     {
00987         FGNodeThis thisNode  = methodVariant.getThisNode();
00988         FGNodeAST astNode   = new FGNodeAST(v);
00989         FGNode.makeArc(thisNode, astNode);
00990         astNodes.put(v,astNode);
00991 
00992         setResult(astNode);
00993     }
00994     /**
00995      * We donot handle expressions that do not evaluate to objects.
00996      *
00997      * @param v an <code>UshrExpr</code> value
00998      */
00999     public void caseUshrExpr(UshrExpr v)
01000     {
01001         setResult(null);
01002     }
01003     /** 
01004      * Handles the case when the expression is an virtual invoke expression.
01005      *
01006      * @param v the expression for the invocation
01007      */
01008     public void caseVirtualInvokeExpr(VirtualInvokeExpr v)
01009     {
01010         SootMethod sootMethod     = v.getMethod();
01011         int        argCount       = v.getArgCount(); 
01012         FGNode     baseNode       = build(v.getBase(), stmt);
01013 
01014         /*
01015          * With virtual method invoke, we generate flowgraphs for subexpressions
01016          * (base and args), but arg value and return flows cannot be connected
01017          * now.  An action is attached to the node that will fire each time a
01018          * value flows into the node.  When a new value flows in, the action
01019          * will be fired.
01020          */
01021 
01022         // Now loop through args and generate graphs for the arcs.
01023         FGNode[] argNodes = new FGNode[argCount];
01024 
01025         for (int i=0; i<argCount; i++) {
01026             argNodes[i] = build(v.getArg(i), stmt);
01027         }
01028 
01029         FGNodeAST invokeNode = new FGNodeAST(v);
01030 
01031         // generate action 
01032         baseNode.addAction(new FGActionInvoke(argCount,
01033                                               argNodes,
01034                                               invokeNode,
01035                                               sootMethod.getName(),
01036                                               sootMethod.getParameterTypes(),
01037                                               sootMethod.getReturnType()));
01038         setResult(invokeNode);
01039         astNodes.put(v,invokeNode);
01040         BOFA.callbackReg.callVInvoke(v, this);
01041     }
01042     /**
01043      * We donot handle expressions that do not evaluate to objects.
01044      *
01045      * @param v a <code>XorExpr</code> value
01046      */
01047     public void caseXorExpr(XorExpr v)
01048     {
01049         setResult(null);
01050     }
01051     /**
01052      * Handles the cases which BOFA is not interested in.
01053      *
01054      * @param v an <code>Object</code> value
01055      */
01056     public void defaultCase(Object v)
01057     {
01058         cat.debug("Unhandled expression in" + " FGExpr:" + v.getClass() + " " + v);
01059     }
01060     /**
01061      * Returns ClassTokenSimple object for the class, type.  A New ClassToken
01062      * is created if one doesnot exist of the given class and registered along
01063      * with type.  If a ClassToken already exists then it is returned.
01064      * @param type the class for which the ClassToken is requested.
01065      *
01066      * @return the class token associated with the given type.
01067      */
01068     protected static ClassTokenSimple getToken(String type)
01069     {
01070         if (!commonTokens.containsKey(type)) {
01071             commonTokens.put(type, ClassTokenSimple.select(new SootClass(type))); 
01072         } // end of if
01073         return (ClassTokenSimple)commonTokens.get(type);
01074     }
01075     /**
01076      * Returns the value representing the default initial values of type,
01077      * base. 
01078      *
01079      * @param base the type for which default value is requested.
01080      * @return the default value for the given type.
01081      */
01082     protected Value getValue(String base)
01083     {
01084         if (base.equals("int"))
01085             return IntConstant.v(0);
01086         else if (base.equals("float"))
01087             return FloatConstant.v(0f);
01088         else if (base.equals("double"))
01089             return DoubleConstant.v(0);
01090         else if (base.equals("long"))
01091             return LongConstant.v(0);
01092         else
01093             return NullConstant.v();
01094     } 
01095 }

Generated at Thu Feb 7 06:45:32 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001