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

Analysis.java

00001 package edu.ksu.cis.bandera.bofa;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * Bandera, a Java(TM) analysis and transformation toolkit           *
00005  * Copyright (C) 2000, 2001                                    *
00006  * Venkatesh Prasad Ranganath (rvprasad@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 ca.mcgill.sable.soot.SootClass;
00038 import ca.mcgill.sable.soot.SootMethod;
00039 import ca.mcgill.sable.soot.jimple.AbstractJimpleValueSwitch;
00040 import ca.mcgill.sable.soot.jimple.ArrayRef;
00041 import ca.mcgill.sable.soot.jimple.InstanceFieldRef;
00042 import ca.mcgill.sable.soot.jimple.Local;
00043 import ca.mcgill.sable.soot.jimple.NonStaticInvokeExpr;
00044 import ca.mcgill.sable.soot.jimple.ParameterRef;
00045 import ca.mcgill.sable.soot.jimple.SpecialInvokeExpr;
00046 import ca.mcgill.sable.soot.jimple.StaticFieldRef;
00047 import ca.mcgill.sable.soot.jimple.Stmt;
00048 import ca.mcgill.sable.soot.jimple.ThisRef;
00049 import ca.mcgill.sable.soot.jimple.Value;
00050 import ca.mcgill.sable.util.ArrayList;
00051 import ca.mcgill.sable.util.Collection;
00052 import ca.mcgill.sable.util.Comparator;
00053 import ca.mcgill.sable.util.HashSet;
00054 import ca.mcgill.sable.util.Iterator;
00055 import ca.mcgill.sable.util.LinkedList;
00056 import ca.mcgill.sable.util.Set;
00057 import edu.ksu.cis.bandera.annotation.Annotation;
00058 import edu.ksu.cis.bandera.annotation.AnnotationManager;
00059 import edu.ksu.cis.bandera.annotation.ConstructorDeclarationAnnotation;
00060 import edu.ksu.cis.bandera.annotation.MethodDeclarationAnnotation;
00061 import edu.ksu.cis.bandera.jjjc.CompilationManager;
00062 import java.sql.Ref;
00063 import org.apache.log4j.Category;
00064 import ca.mcgill.sable.soot.NullType;
00065 
00066 /*
00067  * Analysis.java
00068  * $Id: Analysis.java,v 1.1.1.1 2002/01/24 03:42:07 pserver Exp $
00069  */
00070 
00071 /**
00072  * This class is the interface provided by BOFA to the external world.
00073  *
00074  * The nasty details of Object Flow engine is hidden behind this class.  This
00075  * class provides the necessary interface using types defined in
00076  * ca.mcgill.sable.* packages, in particular, soot and soot.jimple, to query the
00077  * Object Flow Analysis engine for information.
00078  *
00079  * Created: Wed Nov 15 22:15:07 2000
00080  *
00081  * @author 
00082  * <a href="http://www.cis.ksu.edu/~rvprasad">Venkatesh Prasad Ranganath</a>
00083  * @version  $Name:  $($Revision: 1.1.1.1 $)
00084  */
00085 public class Analysis {
00086     
00087     /**
00088      * Stores the singleton object corresponding to the Analysis class.
00089      */
00090     private static Analysis singleton;
00091 
00092     /**
00093      * Provides logging capability through log4j.
00094      *
00095      */
00096     private static Category cat;
00097 
00098     /**
00099      * Indicates that the "defining" statements are required.
00100      *
00101      */
00102     private final static int DEFS = 1;
00103     
00104     /**
00105      * Indicates that the "using" statement are required.
00106      *
00107      */
00108     private final static int USES = 2;
00109 
00110     /**
00111      * This class is acts as a large switch statement.  
00112      * 
00113      * The switch is implemented in the parent class but the code to be
00114      * executed is provided in this class.  In each of the cases, a particular
00115      * type of reference is handled.
00116      *
00117      * AbstractJimpleValueSwitch is extended because RefValueSwitch does not
00118      * handle switching on objects of class Local.
00119      *
00120      * @author 
00121      * <a href="http://www.cis.ksu.edu/~rvprasad">Venkatesh Prasad Ranganath</a> 
00122      */
00123     class RefValueSwitch extends AbstractJimpleValueSwitch
00124     {
00125         /**
00126          * A collection of values which the given reference or
00127          * <code>Local</code> can refer to.
00128          *
00129          */
00130         Collection result;
00131 
00132         /**
00133          * The <code>MethodVariant</code> corresponding to a SootMethod. 
00134          *
00135          */
00136         MethodVariant method;
00137 
00138         /**
00139          * This is entry method which builds the collection of expression
00140          * <code>Value</code>s which the reference might evaluate to.
00141          *
00142          * @param v the value of interest.  Mostly <code>Local</code>s and
00143          * <code>Ref</code> types.  
00144          * @param sm the method in which the value occurs.
00145          * @return a collection of Jimple Values which the given
00146          * reference/locals will evaluate to. 
00147          */
00148         Set build(Value v, SootMethod sm)
00149         {
00150             method = MethodVariantManager.select(sm);
00151             v.apply(this);
00152             return collect();
00153         }
00154 
00155         /**
00156          * This method collects the <code>Value</code>s from the
00157          * <code>ValueVariant</code> objects.
00158          * 
00159          * After the <code>ValueVariant</code>s are collected for the given
00160          * <code>Value</code> object, <code>Value</code> objects need to be
00161          * extracted from them to keep the transaction with the external world
00162          * in terms of Jimple entities.  This will be called from build.
00163          * 
00164          * @return a collection of <code>Value</code>s that may flow into the
00165          * <code>Value</code> given to <code>build</code>.
00166          * @see #build build
00167          */
00168         private Set collect()
00169         {
00170             HashSet temp;
00171             temp = new HashSet();
00172             for (Iterator i = result.iterator(); i.hasNext();) {
00173                 ValueVariant v = (ValueVariant)i.next();
00174                 temp.add(new 
00175                          ExprStmtMethodTriple(v.getExpr(), 
00176                                               getStmtMethodPair(v.getStmt())));  
00177             } // end of for ()
00178             return temp;
00179         }
00180 
00181         /**
00182          * This method collects <code>Value</code> objects for the given
00183          * <code>ArrayRef</code> object.
00184          *
00185          * @param v <code>ArrayRef</code> representing the array variable.
00186          */
00187         public void caseArrayRef(ArrayRef v)
00188         {
00189             result = method.getASTValues(v);
00190         }
00191 
00192         /**
00193          * This method collects <code>Value</code> objects for the given
00194          * <code>InstanceFieldRef</code> object.
00195          *
00196          * @param v <code>InstanceFieldRef</code> representing the instance
00197          * field.
00198          */
00199         public void caseInstanceFieldRef(InstanceFieldRef v)
00200         {
00201             Collection temp = InstanceVariantManager.getVariants(v.getField());
00202             result = new HashSet();
00203             for (Iterator i = temp.iterator(); i.hasNext();) {
00204                 result.addAll(((InstanceVariant)i.next()).getNode()
00205                               .getValues());
00206             } // end of for ()
00207         }
00208 
00209         /**
00210          * This method gets the collection of Value objects for the given
00211          * <code>ParameterRef</code> object.
00212          *
00213          * @param v <code>ParameterRef</code> representing the parameter.
00214          */
00215         public void caseParameterRef(ParameterRef v)
00216         {
00217             result = method.getParameterValues(v.getIndex());
00218         }
00219         
00220         /**
00221          * This method gets the collection of Value objects for the given
00222          * <code>StaticFieldRef</code> object.
00223          *
00224          * @param v <code>StaticFieldRef</code> representing the static field.
00225          */
00226         public void caseStaticFieldRef(StaticFieldRef v)
00227         {
00228             result = StaticFieldManager.get(v.getField()).getValues();
00229         }
00230 
00231         /**
00232          * This method gets the collection of Value objects for the given
00233          * <code>ThisRef</code> object.
00234          *
00235          * @param v <code>ThisRef</code> representing <i>this</i> variable. 
00236          */
00237         public void caseThisRef(ThisRef v)
00238         {
00239             result = method.getThisValues();
00240         }
00241 
00242         /**
00243          * This method gets the collection of Value objects for the given
00244          * <code>Local</code> object.
00245          *
00246          * @param v <code>Value</code> representing the local variable. 
00247          */
00248         public void caseLocal(Local v)
00249         {
00250             result = method.getLocalNode(v).getValues();
00251         }
00252         
00253         /**
00254          * For all the cases which we donot provide value set information, we
00255          * execute this method.
00256          *
00257          * @param o Any object type for which we donot cater the data.
00258          */
00259         public void defaultCase(Object o)
00260         {
00261             cat.warn("ANALYSIS: We donot handle " + o + " of type " + 
00262                      o.getClass() + "."); 
00263         }
00264     }
00265 
00266     /**
00267      * A class that encapsulates the statement and the method in which that
00268      * statement occurs.
00269      *
00270      */
00271     public class StmtMethodPair {
00272         /**
00273          * The statement to be paired with the containing Method.
00274          *
00275          */
00276         Stmt stmt;
00277 
00278         /**
00279          * The method to be paired with the enclosed statement.
00280          *
00281          */
00282         SootMethod sm;
00283 
00284         /**
00285          * Creates a new <code>StmtMethodPair</code> instance.
00286          *
00287          * @param s statement to be stored.
00288          * @param m method to be stored.
00289          */
00290         StmtMethodPair(Stmt s, SootMethod m)
00291         {
00292             stmt = s;
00293             sm = m;
00294         }
00295 
00296         /**
00297          * Provides the stored statment object.
00298          *
00299          * @return statement stored in this object.
00300          */
00301         public Stmt getStmt() 
00302         {
00303             return stmt;
00304         }
00305         
00306         /**
00307          * Provides the stored method object.
00308          *
00309          * @return method stored in this object.
00310          */
00311         public SootMethod getSootMethod() 
00312         {
00313             return sm;
00314         }
00315 
00316         /**
00317          * Provides equality checking for two <code>StmtMethodPair</code>
00318          * objects.  It checks if both the objects contain references to the
00319          * same <code>Stmt</code> and <code>SootMethod</code> objects.
00320          *
00321          * @param smp the <code>StmtMethodPair</code> object to be compared with.
00322          * @return <code>true</code> if the given object is the "equal" to this
00323          * object. <code>false</code> otherwise.
00324          */
00325         public boolean equals(Object o) 
00326         {
00327             if (!(o instanceof StmtMethodPair)) return false;
00328             StmtMethodPair smp = (StmtMethodPair) o;
00329             return (stmt == smp.stmt && sm == smp.sm);
00330         }
00331 
00332         public int hashCode() { return toString().hashCode(); }
00333         public String toString()
00334         {
00335             return sm + "::" + stmt;
00336         }
00337     }
00338 
00339     /**
00340      * A class the encapsulates the expression and it's enclosinging statement
00341      * and method. 
00342      *
00343      */
00344     public class ExprStmtMethodTriple
00345     {
00346         /**
00347          * The expression couple with the statement and method.
00348          *
00349          */
00350         Value expr;
00351 
00352         /**
00353          * The object containing the enclosing statement and method.
00354          *
00355          */
00356         StmtMethodPair smp;
00357         
00358         /**
00359          * Creates a new <code>ExprStmtMethodTriple</code> instance.
00360          *
00361          * @param expr is the expression to be encapsulated.
00362          * @param smp is the <code>StmtMethodPair</code> object conatining the
00363          * enclsoing statement and method.
00364          */
00365         ExprStmtMethodTriple(Value expr, StmtMethodPair smp)
00366         {
00367             this.expr = expr;
00368             this.smp = smp;
00369         }
00370 
00371         /**
00372          * Returns the stored expression.
00373          *
00374          * @return returns the stored expression.
00375          */
00376         public Value getExpr()
00377         {
00378             return expr;
00379         }
00380 
00381         /**
00382          * Returns the associated <code>StmtMethodPair</code> object.
00383          *
00384          * @return the associated <code>StmtMethodPair</code> object.
00385          */
00386         public StmtMethodPair getStmtMethodPair() 
00387         {
00388             return smp;
00389         }
00390         
00391         /**
00392          *  Provides equality checking for two <code>StmtMethodPair</code>
00393          * objects.  It checks if both the objects contain references to the
00394          * same expression, statement, and method object. 
00395          *
00396          * @param esmt is the object with which equivalence test needs to be done.
00397          * @return <code>true</code> if the given object is the "equal" to this
00398          * object. <code>false</code> otherwise.
00399          */
00400         public boolean equals(Object o) 
00401         {
00402             if (!(o instanceof ExprStmtMethodTriple)) return false;
00403             ExprStmtMethodTriple esmt = (ExprStmtMethodTriple) o;
00404             return (expr == esmt.expr) && smp.equals(esmt.smp);
00405         }
00406 
00407         public int hashCode() { return toString().hashCode(); }
00408         public String toString()
00409         {
00410             return smp + "--" + expr;
00411         }
00412     }
00413 
00414     /**
00415      * This class implements the Comparator interface to aid sort classes and
00416      * interfaces depending on hierarchy.
00417      *
00418      * @author 
00419      * <a href="http://www.cis.ksu.edu/~rvprasad">Venkatesh Prasad Ranganath</a>
00420      */
00421     class classComparator implements Comparator
00422     {
00423         /**
00424          * Compares two classes in the order of hierarchy.
00425          *
00426          * @param o1 the first SootClass object in the comparison
00427          * @param o2 the second SootClass object in the comparison
00428          * @return -1 if o1 and o2 are the same SootClasses
00429          *          0 if o2 is the immediate superclass of o1
00430          *          1 if o1 has no superclass
00431          */
00432         public int compare(Object o1, Object o2)
00433         {
00434             if (o1 == o2)
00435                 return -1;
00436             else if (((SootClass)o1).hasSuperClass())
00437                 if (((SootClass)o1).getSuperClass() !=  (SootClass)o2)
00438                     return compare(((SootClass)o1).getSuperClass(), o2);
00439                 else
00440                     return 0;
00441             else
00442                 return 1;
00443         }
00444     }
00445 
00446     /**
00447      * Creates a new <code>Analysis</code> instance.  This a private constructor
00448      * to implement the <i>singleton</i> pattern.
00449      */
00450     private Analysis() { }
00451     /**
00452      * Provides a set of <code>Stmt</code>(from the soot library)in which the
00453      * given <code>Value</code> is defined.  A copy of annotationmanager is
00454      * obtained from compilationmanager to provide the information.
00455      *
00456      * @param v the variable which is of interest.  This should be a valid
00457      * reference variable not a expression.
00458      * @param enclosingMethod the method in which the variable occurs.
00459      * @return a collection of "defining" <code>StmtMethodPair</code>s.
00460      */
00461     public Collection getDefs(Value v, SootMethod enclosingMethod) {
00462         return getDefsOrUses(v, enclosingMethod, DEFS);
00463     }
00464     /**
00465      * Provides a set of <code>Stmt</code>(from the soot library)in which the
00466      * given <code>Value</code> is defined or used.  A copy of annotationmanager
00467      * is obtained from compilationmanager to provide the information.
00468      *
00469      * @param v the reference variable or local which is of interest.
00470      * @param enclosingMethod the method in which the reference variable or
00471      * local occurs.
00472      * @param mode defines the nature of the return value.  It should be USES or
00473      * DEFS only.
00474      * @return a collection of "defining" or "using" <code>Stmt</code>s.
00475      */
00476     private Collection getDefsOrUses(Value v, SootMethod enclosingMethod, 
00477                                       int mode) {
00478         HashSet ud = new HashSet();
00479         Collection c = new ArrayList();
00480         Collection temp = new ArrayList();
00481         MethodVariant m =  MethodVariantManager.select(enclosingMethod);
00482         FGNode f = null;
00483         if (v instanceof ThisRef) {
00484             temp.add(m.getThisNode());
00485         } else if  (v instanceof ParameterRef) {
00486             temp.add(m.getParameterNode(((ParameterRef)v).getIndex()));
00487         } else if (v instanceof InstanceFieldRef) {
00488             temp.add(InstanceVariantManager
00489                      .select(((InstanceFieldRef)v).getField()).getNode());
00490         } else if (v instanceof ArrayRef) {
00491             temp.addAll(m.getASTNode(v).getPreds());
00492         } else if (v instanceof StaticFieldRef) {
00493             temp.add(StaticFieldManager.select(((StaticFieldRef)v).getField()));
00494         } else if (v instanceof Local) {
00495             temp.add(m.getLocalNode((Local)v)); 
00496         } // end of else 
00497         
00498         if (mode == DEFS) {
00499             for (Iterator i = temp.iterator(); i.hasNext();) {
00500                 c.addAll(((FGNode)i.next()).getPreds());
00501             } // end of for
00502         } else if (mode == USES) {
00503             for (Iterator i = temp.iterator(); i.hasNext();) {
00504                 c.addAll(((FGNode)i.next()).getSuccs());
00505             } // end of for
00506         } // end of else
00507         
00508         for (Iterator i =  c.iterator(); i.hasNext();) {
00509             Stmt s = ((FGNodeAST)i.next()).getStmt();
00510             ud.add(getStmtMethodPair(s));
00511         }
00512         return ud;
00513     }
00514     /**
00515      * Provides a <code>StmtMethodPair</code> object containing the given
00516      * statement and the method enclosing the statement.  This method obtains the
00517      * current annotationmanager from compilationmanager to provide the
00518      * information. 
00519      *
00520      * @param s the statement for which the enclosing method is requested.
00521      * @return a <code>StmtMethodPair</code> object containing the given
00522      * statement and it's enclosing method, if one exists.  Otherwise null is
00523      * returned.  This should not occur as all statements in Java should occur
00524      * inside a method at the JVM level.
00525      */
00526     private StmtMethodPair getStmtMethodPair(Stmt s)
00527     {
00528         StmtMethodPair smp = null;
00529         try {
00530             AnnotationManager am = CompilationManager.getAnnotationManager();
00531             Annotation a = am.getMethodAnnotationContainingAnnotation(
00532                              am.getContainingAnnotation(s));
00533             if (a instanceof ConstructorDeclarationAnnotation) {
00534                 smp = new StmtMethodPair(s, 
00535                                          ((ConstructorDeclarationAnnotation)a)
00536                                          .getSootMethod());
00537             } else if (a instanceof MethodDeclarationAnnotation) {
00538                 smp = new StmtMethodPair(s, 
00539                                          ((MethodDeclarationAnnotation)a)
00540                                          .getSootMethod());
00541             } // end of else
00542         } catch (Exception  e) {
00543             smp = null;
00544             e.printStackTrace();
00545         } // end of try-catch
00546         return smp;
00547     }
00548     /**
00549      * Provides a set of <code>Stmt</code>(from the soot library)in which the
00550      * given <code>Value</code> is used.  A copy of annotationmanager is
00551      * obtained from compilationmanager to provide the information.
00552      *
00553      * @param v the variable which is of interest.  This should be a valid
00554      * reference variable not a expression.
00555      * @param enclosingMethod the method in which the variable occurs.
00556      * @return a collection of "using" <code>StmtMethodPair</code>s.
00557      */
00558     public Collection getUses(Value v, SootMethod enclosingMethod) {
00559         return getDefsOrUses(v, enclosingMethod, USES);
00560     }
00561     /**
00562      * The singleton object corresponding to the Analysis class is created here.
00563      * 
00564      * @return an Analysis object.
00565      */
00566     public static Analysis init()
00567     {
00568         if (singleton == null) {
00569             singleton = new Analysis();
00570             cat = Category.getInstance(singleton.getClass().toString());
00571         } // end of if ()
00572         return singleton;
00573     }
00574     /** 
00575      * Provides a collection of classes of objects that may flow into the
00576      * receiver object at the point of a non-static invocation.
00577      *
00578      * @param expr the virtual invocation expression as expressed in Jimple.
00579      * @param enclosingMethod the method inside which the invocation occurs.
00580      * @return collection of possible classes, represented as
00581      * <code>SootClass</code>, from which the method implementation may be
00582      * invoked after resolution.  
00583      */
00584     public Collection invokeExprResolution(NonStaticInvokeExpr expr,
00585                                            SootMethod enclosingMethod)
00586     {
00587         // Get the method to be resolved in the invocation expression.
00588         SootMethod sootMethod = expr.getMethod();
00589         
00590         SootMethod methodImpl;
00591         SootClass sootClass;
00592         Collection classes = new ArrayList();
00593         ValueVariant variant;
00594         MethodVariant methodVariant;
00595         if (expr instanceof SpecialInvokeExpr) {
00596             classes.add(expr.getMethod().getDeclaringClass());
00597         } else {
00598             /* 
00599              * Get the receiver object.  It will be a local as a result of using
00600              * Jimple representation. 
00601              */
00602             Local l = (Local)expr.getBase();
00603             
00604             // Iterate over the variants that flow into the receiver object
00605             for (Iterator variants = 
00606                      FA.summarizeLocalValueVariants(enclosingMethod,
00607                                                     l).iterator(); 
00608                  variants.hasNext();) { 
00609                 variant = (ValueVariant)variants.next();
00610                 methodVariant = MethodVariantManager.select(enclosingMethod);
00611                 if (variant.getClassToken()
00612                     .equals(ClassTokenSimple.nullClassToken) ||
00613                     variant.getClassToken()
00614                     .equals(ClassTokenSimple.unknownClassToken)){ 
00615                     cat.warn("BOFA: Null may be flowing into invocation site."); 
00616                     continue;
00617                 }
00618                 // Get the class of which the current variant is of.
00619                 sootClass =
00620                     ((ClassTokenSimple)variant.getClassToken()).getSootClass();
00621                 // Get the class in which the method of interest is implemented.
00622                 methodImpl = MethodVariantManager.findDeclaringMethod(sootClass,
00623                                                                       sootMethod);
00624                 // Add it to the set of possible class implementation.
00625                 classes.add(methodImpl.getDeclaringClass());
00626             } // end of for ()
00627         } // end of else
00628 
00629         /* sort the set of possible classes in the reverse order of
00630          * inheritence */
00631         classes = sortUnique(classes, new classComparator());
00632         return classes;
00633     }
00634     /**
00635      * Tells if the given <code>Value</code>, representing a reference, can ever
00636      * evaluate to null during run-time.
00637      *
00638      * @param v the reference variable of interest.
00639      * @param enclosingMethod the method in which the variable occurs.
00640      * @return true - if <i>v</i> may contain null value; otherwise false.
00641      */
00642     public boolean nullReference(Value v, SootMethod enclosingMethod)
00643     {
00644         RefValueSwitch temp = new RefValueSwitch();
00645         Iterator i = temp.build(v, enclosingMethod).iterator();
00646         boolean retval = false;
00647         for (; i.hasNext() && !retval; ) {
00648              Analysis.ExprStmtMethodTriple a = 
00649                  (Analysis.ExprStmtMethodTriple)i.next();
00650              retval = a.getExpr().getType().equals(NullType.v());
00651         } // end of for
00652         return retval;
00653     }
00654     /**
00655      * This method provides a set of objects the given reference variable
00656      * may or will refer. 
00657      *
00658      * The set consists of <code>Value</code> objects representing the
00659      * object creation expressions.  It is the objects created at this site the
00660      * given reference may or will refer to.
00661      *
00662      * @param v the reference variable of interest.
00663      * @param enclosingMethod the method in which the value occurs.
00664      * @return a set of <code>Value</code>s which the variable may refer.
00665      */
00666     public Set referenceValueSet(Value v, SootMethod enclosingMethod)
00667     {
00668         RefValueSwitch temp = new RefValueSwitch();
00669         return temp.build(v, enclosingMethod); 
00670     }
00671     /**
00672      * Sorts the given collection using the given comparator and returns the
00673      * sorted collection with the duplicate removed.
00674      *
00675      * @param c the collection to be sorted.
00676      * @param comparator the comparator that dictates the sorting.
00677      * @return the sorted collection.
00678      */
00679     static Collection sortUnique(Collection c, Comparator comparator)
00680     {
00681         int i, j, t = 0;
00682         Object temp;
00683         Object[] obj;
00684         LinkedList l = new LinkedList();
00685         obj = c.toArray();
00686         if (obj.length == 0) {
00687             return l;
00688         } // end of if ()
00689         
00690     outer:
00691         for (i = 0; i < obj.length - 1; i++) {
00692             for (j = i + 1; j < obj.length; j++) {
00693                 /* if we have same class appearing twice we will remove
00694                  * duplicates */
00695                 if (obj[i] == obj[j])
00696                     continue outer;
00697                 t = comparator.compare(obj[i], obj[j]);
00698                 if (t != 0) {
00699                     temp = obj[j];
00700                     obj[j] = obj[i];
00701                     obj[i] = temp;
00702                 } // end of if ()
00703             } // end of for ()
00704             if (t != -1)
00705                 l.add(obj[i]);
00706         } // end of for ()
00707         l.add(obj[obj.length - 1]);
00708         return l;
00709     }
00710 }

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