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

TypeResolver.java

00001 package ca.mcgill.sable.soot.jimple;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * Jimple, a 3-address code Java(TM) bytecode representation.        *
00005  * Copyright (C) 1998, 1999 Etienne Gagnon (gagnon@sable.mcgill.ca). *
00006  * All rights reserved.                                              *
00007  *                                                                   *
00008  * Modifications by Raja Vallee-Rai (rvallerai@sable.mcgill.ca) are  *
00009  * Copyright (C) 1998 Raja Vallee-Rai.  All rights reserved.         *
00010  *                                                                   *
00011  * This work was done as a project of the Sable Research Group,      *
00012  * School of Computer Science, McGill University, Canada             *
00013  * (http://www.sable.mcgill.ca/).  It is understood that any         *
00014  * modification not identified as such is not covered by the         *
00015  * preceding statement.                                              *
00016  *                                                                   *
00017  * This work is free software; you can redistribute it and/or        *
00018  * modify it under the terms of the GNU Library General Public       *
00019  * License as published by the Free Software Foundation; either      *
00020  * version 2 of the License, or (at your option) any later version.  *
00021  *                                                                   *
00022  * This work is distributed in the hope that it will be useful,      *
00023  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
00024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *
00025  * Library General Public License for more details.                  *
00026  *                                                                   *
00027  * You should have received a copy of the GNU Library General Public *
00028  * License along with this library; if not, write to the             *
00029  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,      *
00030  * Boston, MA  02111-1307, USA.                                      *
00031  *                                                                   *
00032  * Java is a trademark of Sun Microsystems, Inc.                     *
00033  *                                                                   *
00034  * To submit a bug report, send a comment, or get the latest news on *
00035  * this project and other Sable Research Group projects, please      *
00036  * visit the web site: http://www.sable.mcgill.ca/                   *
00037  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00038 
00039 /*
00040  Reference Version
00041  -----------------
00042  This is the latest official version on which this file is based.
00043  The reference version is: $SootVersion: 1.beta.4 $
00044 
00045  Change History
00046  --------------
00047  A) Notes:
00048 
00049  Please use the following template.  Most recent changes should
00050  appear at the top of the list.
00051 
00052  - Modified on [date (March 1, 1900)] by [name]. [(*) if appropriate]
00053    [description of modification].
00054 
00055  Any Modification flagged with "(*)" was done as a project of the
00056  Sable Research Group, School of Computer Science,
00057  McGill University, Canada (http://www.sable.mcgill.ca/).
00058 
00059  You should add your copyright, using the following template, at
00060  the top of this file, along with other copyrights.
00061 
00062  *                                                                   *
00063  * Modifications by [name] are                                       *
00064  * Copyright (C) [year(s)] [your name (or company)].  All rights     *
00065  * reserved.                                                         *
00066  *                                                                   *
00067 
00068  B) Changes:
00069  - Modified on January 20, 1999 by Etienne Gagnon (gagnon@sable.mcgill.ca). (*)
00070    Fixed a fixed a basic type array typing problem.
00071 
00072  - Modified on January 15, 1999 by Etienne Gagnon (gagnon@sable.mcgill.ca). (*)
00073    Fixed typing bug in null assignment to array variables.
00074 
00075  - Modified on November 13, 1998 by Raja Vallee-Rai (kor@sable.mcgill.ca) (*)
00076    Added type information for @caughtexception
00077 
00078  - Modified on November 2, 1998 by Raja Vallee-Rai (kor@sable.mcgill.ca) (*)
00079    Repackaged all source files and performed extensive modifications.
00080    First initial release of Soot.
00081 
00082  - Modified on October 14, 1998 by Etienne Gagnon (gagnon@sable.mcgill.ca). (*)
00083    Implemented fast typing algorithm for arrays.
00084 
00085  - Modified on October 1, 1998 by Raja Vallee-Rai (kor@sable.mcgill.ca) (*)
00086    Fixed the inference of <<, >> and >>>.
00087 
00088  - Modified on 2-Sep-1998 by Raja Vallee-Rai (kor@sable.mcgill.ca) (*)
00089    getBaseType() on NewArrayExpr does not always yield a BaseType.
00090 
00091  - Modified on 2-Sep-1998 by Raja Vallee-Rai (kor@sable.mcgill.ca) (*)
00092    Applied Etienne's patch.
00093 
00094  - Modified on July 29, 1998 by Etienne Gagnon (gagnon@sable.mcgill.ca). (*)
00095    Initial version.
00096 
00097 */
00098 
00099 import ca.mcgill.sable.soot.*;
00100 import ca.mcgill.sable.soot.jimple.*;
00101 import ca.mcgill.sable.util.*;
00102 import java.util.Enumeration;
00103 import java.util.Vector;
00104 import java.util.BitSet;
00105 import java.util.Hashtable;
00106 
00107 /**
00108  * This class resolves the type of local variables.
00109  **/
00110 class TypeResolver
00111 {
00112     private static final boolean DEBUG = false;
00113 
00114     /** Reference to the class hierarchy **/
00115     ClassHierarchy classHierarchy;
00116 
00117     /** Reference to the current method **/
00118     SootMethod currentMethod;
00119 
00120     static String lastClass;
00121     /** All type variable instances **/
00122     Vector typeVariableInstances = new Vector();
00123 
00124     /** Hashtable: [TypeNode or Local] -> TypeVariable **/
00125     private Hashtable typeVariableHashtable = new Hashtable();
00126 
00127     /** Hashtable: TypeVariable -> String **/
00128     private Hashtable typeVariableStringHashtable = new Hashtable();
00129 
00130     /** Used to collect type constraints **/
00131     private ConstraintCollector constraintCollector = new ConstraintCollector();
00132 
00133     /** Type variables left to resolve **/
00134     IntSet unresolvedTypeVariables = new IntSet();
00135 
00136     /** Indicates that a new relation due to merging isArrayOf has be added **/
00137     boolean new_relation;
00138 
00139     private JimpleBody stmtBody;
00140 
00141     /** Represents a type variable. **/
00142     class TypeVariable
00143     {
00144         /** Unique id **/
00145         private int id;
00146 
00147         IntSet parents = new IntSet();
00148         IntSet children = new IntSet();
00149 
00150         private ClassHierarchy.TypeNode typeNode;
00151 
00152         private boolean cannotBeInt;
00153         private boolean cannotBeLong;
00154         private boolean cannotBeFloat;
00155         private boolean cannotBeDouble;
00156         private boolean cannotBeAddress;
00157         private boolean cannotBeRef;
00158 
00159         TypeVariable isArrayOf;
00160         IntSet isElementOf = new IntSet();
00161         int arrayDepth;
00162         TypeVariable base;
00163         int count;
00164 
00165         private TypeVariable rep = this;
00166         private int rank = 0;
00167 
00168         private BitSet ancestors = new BitSet();
00169 
00170         TypeVariable()
00171         {
00172             id = typeVariableInstances.size();
00173             typeVariableInstances.addElement(this);
00174             unresolvedTypeVariables.set(id);
00175         }
00176 
00177         TypeVariable(Local local)
00178         {
00179             this();
00180             typeVariableHashtable.put(local, this);
00181             typeVariableStringHashtable.put(this, local.toString());
00182         }
00183 
00184         TypeVariable(ClassHierarchy.TypeNode typeNode)
00185         {
00186             this();
00187             typeVariableHashtable.put(typeNode, this);
00188             typeVariableStringHashtable.put(this, typeNode.toString());
00189             this.typeNode = typeNode;
00190             unresolvedTypeVariables.clear(id);
00191 
00192             if(typeNode.getType() instanceof ArrayType)
00193             {
00194                 ArrayType type = (ArrayType) typeNode.getType();
00195 
00196                 if(type.numDimensions > 1)
00197                 {
00198                     new_relation = true;
00199                     getTypeVariable(
00200                         ArrayType.v(type.baseType,
00201                         type.numDimensions - 1)).ecrUnion(
00202                         getEcrIsArrayOf());
00203                 }
00204                 else
00205                 {
00206                     new_relation = true;
00207                     getTypeVariable(type.baseType).ecrUnion(
00208                         getEcrIsArrayOf());
00209                 }
00210             }
00211         }
00212 
00213         TypeVariable ecr()
00214         {
00215             if(rep != this)
00216             {
00217                 rep = rep.ecr();
00218             }
00219 
00220             return rep;
00221         }
00222 
00223         TypeVariable ecrUnion(TypeVariable var)
00224         {
00225             new_relation = true;
00226 
00227             TypeVariable x = ecr();
00228             TypeVariable y = var.ecr();
00229 
00230             if(x == y)
00231             {
00232                 return x;
00233             }
00234 
00235             if(x.rank > y.rank)
00236             {
00237                 x.merge(y);
00238 
00239                 y.rep = x;
00240                 return x;
00241             }
00242 
00243             y.merge(x);
00244 
00245             x.rep = y;
00246 
00247             if(y.rank == x.rank)
00248             {
00249                 y.rank++;
00250             }
00251 
00252             return y;
00253         }
00254 
00255         private void merge(TypeVariable var)
00256         {
00257             new_relation = true;
00258             // Merge types
00259             if(typeNode == null)
00260             {
00261                 typeNode = var.typeNode;
00262             }
00263             else if(var.typeNode != null)
00264             {
00265                 var.typeNode = typeNode = classHierarchy.getTypeNode(ErroneousType.v());
00266                 error("Type Error(1): Attempt to merge incompatible types.");
00267             }
00268 
00269             unresolvedTypeVariables.clear(var.id);
00270             if(typeNode != null)
00271             {
00272                 unresolvedTypeVariables.clear(id);
00273             }
00274 
00275             // Merge properties
00276             cannotBeInt |= var.cannotBeInt;
00277             cannotBeLong |= var.cannotBeLong;
00278             cannotBeFloat |= var.cannotBeFloat;
00279             cannotBeDouble |= var.cannotBeDouble;
00280             cannotBeAddress |= var.cannotBeAddress;
00281             cannotBeRef |= var.cannotBeRef;
00282 
00283             // Merge isElementOf & isArrayOf
00284             isElementOf.or(var.isElementOf);
00285 
00286             if(isArrayOf == null)
00287             {
00288                 if(var.isArrayOf != null)
00289                 {
00290                     isArrayOf = var.isArrayOf.ecr();
00291                     isArrayOf.isElementOf.clear(var.id);
00292                     isArrayOf.isElementOf.set(id);
00293                 }
00294             }
00295             else if(var.isArrayOf != null)
00296             {
00297                 new_relation = true;
00298                 isArrayOf.ecrUnion(var.isArrayOf);
00299                 isArrayOf = isArrayOf.ecr();
00300                 isArrayOf.isElementOf.clear(var.id);
00301                 isArrayOf.isElementOf.set(id);
00302             }
00303 
00304             // Merge parents
00305             parents.or(var.parents);
00306             int[] elements = var.parents.elements();
00307             for(int i = 0; i < elements.length; i++)
00308             {
00309                 TypeVariable parent =
00310                     (TypeVariable) typeVariableInstances.elementAt(elements[i]);
00311                 parent.children.clear(var.id);
00312                 parent.children.set(id);
00313             }
00314 
00315             // Merge children
00316             children.or(var.children);
00317             elements = var.children.elements();
00318             for(int i = 0; i < elements.length; i++)
00319             {
00320                 TypeVariable child =
00321                     (TypeVariable) typeVariableInstances.elementAt(elements[i]);
00322                 child.parents.clear(var.id);
00323                 child.parents.set(id);
00324             }
00325             parents.clear(id);
00326             children.clear(id);
00327             parents.clear(var.id);
00328             children.clear(var.id);
00329 
00330             // Verify "concrete" relations.
00331             if(typeNode != null)
00332             {
00333                 if(cannotBeInt && (typeNode.getType() instanceof IntType))
00334                 {
00335                     typeNode = classHierarchy.getTypeNode(ErroneousType.v());
00336                     error("Type Error(2): Should not be an IntType.");
00337                 }
00338 
00339                 if(cannotBeLong && (typeNode.getType() instanceof LongType))
00340                 {
00341                     typeNode = classHierarchy.getTypeNode(ErroneousType.v());
00342                     error("Type Error(3): Should not be a LongType.");
00343                 }
00344 
00345                 if(cannotBeFloat && (typeNode.getType() instanceof FloatType))
00346                 {
00347                     typeNode = classHierarchy.getTypeNode(ErroneousType.v());
00348                     error("Type Error(4): Should not be a FloatType.");
00349                 }
00350 
00351                 if(cannotBeDouble && (typeNode.getType() instanceof DoubleType))
00352                 {
00353                     typeNode = classHierarchy.getTypeNode(ErroneousType.v());
00354                     error("Type Error(5): Should not be a DoubleType.");
00355                 }
00356 
00357                 if(cannotBeAddress && (typeNode.getType() instanceof StmtAddressType))
00358                 {
00359                     typeNode = classHierarchy.getTypeNode(ErroneousType.v());
00360                     error("Type Error(6): Should not be a StmtAddressType.");
00361                 }
00362 
00363                 if(cannotBeRef &&
00364                     ((typeNode.getType() instanceof RefType) ||
00365                     (typeNode.getType() instanceof ArrayType)))
00366                 {
00367                     typeNode = classHierarchy.getTypeNode(ErroneousType.v());
00368                     error("Type Error(7): Should not be a RefType nor an ArrayType.");
00369                 }
00370 
00371                 elements = parents.elements();
00372                 for(int i = 0; i < elements.length; i++)
00373                 {
00374                     TypeVariable parent =
00375                         (TypeVariable) typeVariableInstances.elementAt(elements[i]);
00376                     if(parent.typeNode != null)
00377                     {
00378                         if(!typeNode.hasAncestor(parent.typeNode))
00379                         {
00380                             parent.typeNode = typeNode =
00381                                 classHierarchy.getTypeNode(ErroneousType.v());
00382                             error("Type Error(8): Parent type is not a valid ancestor.");
00383                         }
00384                     }
00385                 }
00386 
00387                 elements = children.elements();
00388                 for(int i = 0; i < elements.length; i++)
00389                 {
00390                     TypeVariable child =
00391                         (TypeVariable) typeVariableInstances.elementAt(elements[i]);
00392                     if(child.typeNode != null)
00393                     {
00394                         if(!typeNode.hasDescendant(child.typeNode))
00395                         {
00396                             child.typeNode = typeNode =
00397                                 classHierarchy.getTypeNode(ErroneousType.v());
00398                             error("Type Error(9): Child type is not a valid descendant.");
00399                         }
00400                     }
00401                 }
00402             }
00403 
00404             var.parents = new IntSet();
00405             var.children = new IntSet();
00406             var.isElementOf = new IntSet();
00407             var.isArrayOf = null;
00408         }
00409 
00410         void removeEcrIndirectRelations()
00411         {
00412             TypeVariable x = ecr();
00413             x.ancestors = new BitSet();
00414 
00415             TypeVariable[] parents = getEcrParents();
00416             for(int i = 0; i < parents.length; i++)
00417             {
00418                 x.ancestors.or(parents[i].ancestors);
00419             }
00420             for(int i = 0; i < parents.length; i++)
00421             {
00422                 if(x.ancestors.get(parents[i].id))
00423                 {
00424                     x.parents.clear(parents[i].id);
00425                     parents[i].children.clear(x.id);
00426                 }
00427                 else
00428                 {
00429                     x.ancestors.set(parents[i].id);
00430                 }
00431             }
00432         }
00433 
00434         void ecrAddParent(TypeVariable variable)
00435         {
00436             if(ecr() != variable.ecr())
00437             {
00438                 if(DEBUG)
00439                 {
00440                     System.out.println(typeVariableStringHashtable.get(variable.ecr()) + " < " +
00441                         typeVariableStringHashtable.get(ecr()));
00442                 }
00443 
00444                 ecr().parents.set(variable.ecr().id);
00445                 variable.ecr().children.set(ecr().id);
00446             }
00447         }
00448 
00449         void ecrAddChild(TypeVariable variable)
00450         {
00451             if(ecr() != variable.ecr())
00452             {
00453                 if(DEBUG)
00454                 {
00455                     System.out.println(typeVariableStringHashtable.get(ecr()) + " < " +
00456                         typeVariableStringHashtable.get(variable.ecr()));
00457                 }
00458 
00459                 ecr().children.set(variable.ecr().id);
00460                 variable.ecr().parents.set(ecr().id);
00461             }
00462         }
00463 
00464         void ecrCannotBeInt()
00465         {
00466             ecr().cannotBeInt = true;
00467         }
00468 
00469         void ecrCannotBeLong()
00470         {
00471             ecr().cannotBeLong = true;
00472         }
00473 
00474         void ecrCannotBeFloat()
00475         {
00476             ecr().cannotBeFloat = true;
00477         }
00478 
00479         void ecrCannotBeDouble()
00480         {
00481             ecr().cannotBeDouble = true;
00482         }
00483 
00484         void ecrCannotBeAddress()
00485         {
00486             ecr().cannotBeAddress = true;
00487         }
00488 
00489         void ecrCannotBeRef()
00490         {
00491             ecr().cannotBeRef = true;
00492         }
00493 
00494         int getEcrId()
00495         {
00496             return ecr().id;
00497         }
00498 
00499         boolean isEcrArray()
00500         {
00501             return ecr().isArrayOf != null;
00502         }
00503 
00504         int ecrArrayDepth()
00505         {
00506             return ecr().arrayDepth;
00507         }
00508 
00509         TypeVariable getEcrIsArrayOf()
00510         {
00511             TypeVariable x = ecr();
00512 
00513             if(x.isArrayOf == null)
00514             {
00515                 x.isArrayOf = new TypeVariable();
00516                 x.isArrayOf.isElementOf.set(x.id);
00517             }
00518 
00519             return x.isArrayOf;
00520         }
00521 
00522         IntSet getEcrParentIds()
00523         {
00524             return (IntSet) ecr().parents.clone();
00525         }
00526 
00527         TypeVariable[] getEcrParents()
00528         {
00529             TypeVariable x = ecr();
00530             int[] elements = x.parents.elements();
00531             TypeVariable[] result = new TypeVariable[elements.length];
00532 
00533             for(int i = 0; i < elements.length; i++)
00534             {
00535                 result[i] = (TypeVariable) typeVariableInstances.elementAt(elements[i]);
00536             }
00537 
00538             return result;
00539         }
00540 
00541         TypeVariable[] getEcrChildren()
00542         {
00543             TypeVariable x = ecr();
00544             int[] elements = x.children.elements();
00545             TypeVariable[] result = new TypeVariable[elements.length];
00546 
00547             for(int i = 0; i < elements.length; i++)
00548             {
00549                 result[i] = (TypeVariable) typeVariableInstances.elementAt(elements[i]);
00550             }
00551 
00552             return result;
00553         }
00554 
00555         ClassHierarchy.TypeNode getEcrTypeNode()
00556         {
00557             return ecr().typeNode;
00558         }
00559 
00560         boolean setEcrTypeNode(ClassHierarchy.TypeNode typeNode)
00561         {
00562             TypeVariable[] elements = getEcrParents();
00563             for(int i = 0; i < elements.length; i++)
00564             {
00565                 if(elements[i].typeNode != null)
00566                 {
00567                     if((!typeNode.hasAncestor(elements[i].typeNode)) &&
00568                         (typeNode != elements[i].typeNode))
00569                     {
00570                         return false;
00571                     }
00572                 }
00573             }
00574 
00575             elements = getEcrChildren();
00576             for(int i = 0; i < elements.length; i++)
00577             {
00578                 if(elements[i].typeNode != null)
00579                 {
00580                     if((!typeNode.hasDescendant(elements[i].typeNode)) &&
00581                         (typeNode != elements[i].typeNode))
00582                     {
00583                         return false;
00584                     }
00585                 }
00586             }
00587 
00588             if(isEcrArray())
00589             {
00590                 if(!(typeNode.getType() instanceof ArrayType))
00591                 {
00592                     return false;
00593                 }
00594                 else
00595                 {
00596                     ArrayType at = (ArrayType) typeNode.getType();
00597                     ClassHierarchy.TypeNode tn = (at.numDimensions > 1) ?
00598                         classHierarchy.getTypeNode(
00599                         ArrayType.v(at.baseType, at.numDimensions - 1)) :
00600                         classHierarchy.getTypeNode(at.baseType);
00601 
00602                     if(!tn.hasDescendant(getEcrIsArrayOf().getEcrTypeNode()))
00603                     {
00604                         return false;
00605                     }
00606                 }
00607             }
00608 
00609             ecr().typeNode = typeNode;
00610             return true;
00611         }
00612 
00613         void unsetEcrTypeNode()
00614         {
00615            ecr().typeNode = null;
00616         }
00617     }
00618 
00619     private class ConstraintCollector extends AbstractStmtSwitch
00620     {
00621         private void handleInvokeExpr(InvokeExpr ie)
00622         {
00623             if(ie instanceof InterfaceInvokeExpr)
00624             {
00625                 InterfaceInvokeExpr invoke = (InterfaceInvokeExpr) ie;
00626 
00627                 SootMethod method = invoke.getMethod();
00628                 Value base = invoke.getBase();
00629 
00630                 if(base instanceof Local)
00631                 {
00632                     Local local = (Local) base;
00633 
00634                     TypeVariable localType = getTypeVariable(local);
00635 
00636                     localType.ecrAddParent(getTypeVariable(method.getDeclaringClass()));
00637                 }
00638 
00639                 int count = invoke.getArgCount();
00640 
00641                 for(int i = 0; i < count; i++)
00642                 {
00643                     if(invoke.getArg(i) instanceof Local)
00644                     {
00645                         Local local = (Local) invoke.getArg(i);
00646 
00647                         TypeVariable localType = getTypeVariable(local);
00648 
00649                         localType.ecrAddParent(getTypeVariable(method.getParameterType(i)));
00650                     }
00651                 }
00652             }
00653             else if(ie instanceof SpecialInvokeExpr)
00654             {
00655                 SpecialInvokeExpr invoke = (SpecialInvokeExpr) ie;
00656 
00657                 SootMethod method = invoke.getMethod();
00658                 Value base = invoke.getBase();
00659 
00660                 if(base instanceof Local)
00661                 {
00662                     Local local = (Local) base;
00663 
00664                     TypeVariable localType = getTypeVariable(local);
00665 
00666                     localType.ecrAddParent(getTypeVariable(method.getDeclaringClass()));
00667                 }
00668 
00669                 int count = invoke.getArgCount();
00670 
00671                 for(int i = 0; i < count; i++)
00672                 {
00673                     if(invoke.getArg(i) instanceof Local)
00674                     {
00675                         Local local = (Local) invoke.getArg(i);
00676 
00677                         TypeVariable localType = getTypeVariable(local);
00678 
00679                         localType.ecrAddParent(getTypeVariable(method.getParameterType(i)));
00680                     }
00681                 }
00682             }
00683             else if(ie instanceof VirtualInvokeExpr)
00684             {
00685                 VirtualInvokeExpr invoke = (VirtualInvokeExpr) ie;
00686 
00687                 SootMethod method = invoke.getMethod();
00688                 Value base = invoke.getBase();
00689 
00690                 if(base instanceof Local)
00691                 {
00692                     Local local = (Local) base;
00693 
00694                     TypeVariable localType = getTypeVariable(local);
00695 
00696                     localType.ecrAddParent(getTypeVariable(method.getDeclaringClass()));
00697                 }
00698 
00699                 int count = invoke.getArgCount();
00700 
00701                 for(int i = 0; i < count; i++)
00702                 {
00703                     if(invoke.getArg(i) instanceof Local)
00704                     {
00705                         Local local = (Local) invoke.getArg(i);
00706 
00707                         TypeVariable localType = getTypeVariable(local);
00708 
00709                         localType.ecrAddParent(getTypeVariable(method.getParameterType(i)));
00710                     }
00711                 }
00712             }
00713             else if(ie instanceof StaticInvokeExpr)
00714             {
00715                 StaticInvokeExpr invoke = (StaticInvokeExpr) ie;
00716 
00717                 SootMethod method = invoke.getMethod();
00718 
00719                 int count = invoke.getArgCount();
00720 
00721                 for(int i = 0; i < count; i++)
00722                 {
00723                     if(invoke.getArg(i) instanceof Local)
00724                     {
00725                         Local local = (Local) invoke.getArg(i);
00726 
00727                         TypeVariable localType = getTypeVariable(local);
00728 
00729                         localType.ecrAddParent(getTypeVariable(method.getParameterType(i)));
00730                     }
00731                 }
00732             }
00733             else
00734             {
00735                 throw new RuntimeException("Unhandled invoke expression type: " + ie.getClass());
00736             }
00737         }
00738 
00739         public void caseBreakpointStmt(BreakpointStmt stmt)
00740         {
00741             // Do nothing
00742         }
00743 
00744         public void caseInvokeStmt(InvokeStmt stmt)
00745         {
00746             handleInvokeExpr((InvokeExpr) stmt.getInvokeExpr());
00747         }
00748 
00749         public void caseAssignStmt(AssignStmt stmt)
00750         {
00751             Value l = stmt.getLeftOp();
00752             Value r = stmt.getRightOp();
00753 
00754 //            System.out.println(l + " = " + r);
00755 
00756             TypeVariable left = null;
00757             TypeVariable right = null;
00758 
00759             if(l instanceof ArrayRef)
00760             {
00761                 ArrayRef ref = (ArrayRef) l;
00762                 Value base = ref.getBase();
00763                 Value index = ref.getIndex();
00764 
00765                 TypeVariable baseType = getTypeVariable((Local) base);
00766                 left = baseType.getEcrIsArrayOf();
00767 
00768                 if(index instanceof Local)
00769                 {
00770                     getTypeVariable((Local) index).ecrCannotBeLong();
00771                     getTypeVariable((Local) index).ecrCannotBeFloat();
00772                     getTypeVariable((Local) index).ecrCannotBeDouble();
00773                     getTypeVariable((Local) index).ecrCannotBeAddress();
00774                     getTypeVariable((Local) index).ecrCannotBeRef();
00775                 }
00776             }
00777             else if(l instanceof Local)
00778             {
00779                 left = getTypeVariable((Local) l);
00780             }
00781             else if(l instanceof InstanceFieldRef)
00782             {
00783                 InstanceFieldRef ref = (InstanceFieldRef) l;
00784 
00785                 TypeVariable baseType = getTypeVariable((Local) ref.getBase());
00786                 baseType.ecrAddParent(getTypeVariable(ref.getField().getDeclaringClass()));
00787                 left = getTypeVariable(ref.getField().getType());
00788             }
00789             else if(l instanceof StaticFieldRef)
00790             {
00791                 StaticFieldRef ref = (StaticFieldRef) l;
00792 
00793                 left = getTypeVariable(ref.getField().getType());
00794             }
00795             else
00796             {
00797                 throw new RuntimeException("Unhandled variable type: " + l.getClass());
00798             }
00799 
00800             if(r instanceof ArrayRef)
00801             {
00802                 ArrayRef ref = (ArrayRef) r;
00803                 Value base = ref.getBase();
00804                 Value index = ref.getIndex();
00805 
00806                 TypeVariable baseType = getTypeVariable((Local) base);
00807                 right = baseType.getEcrIsArrayOf();
00808 
00809                 if(index instanceof Local)
00810                 {
00811                     getTypeVariable((Local) index).ecrCannotBeLong();
00812                     getTypeVariable((Local) index).ecrCannotBeFloat();
00813                     getTypeVariable((Local) index).ecrCannotBeDouble();
00814                     getTypeVariable((Local) index).ecrCannotBeAddress();
00815                     getTypeVariable((Local) index).ecrCannotBeRef();
00816                 }
00817             }
00818             else if(r instanceof DoubleConstant)
00819             {
00820                 right = getTypeVariable(DoubleType.v());
00821             }
00822             else if(r instanceof FloatConstant)
00823             {
00824                 right = getTypeVariable(FloatType.v());
00825             }
00826             else if(r instanceof IntConstant)
00827             {
00828                 right = getTypeVariable(IntType.v());
00829             }
00830             else if(r instanceof LongConstant)
00831             {
00832                 right = getTypeVariable(LongType.v());
00833             }
00834             else if(r instanceof NullConstant)
00835             {
00836                 right = null; // getTypeVariable(NullType.v());
00837             }
00838             else if(r instanceof StringConstant)
00839             {
00840                 right = getTypeVariable(RefType.v("java.lang.String"));
00841             }
00842             else if(r instanceof BinopExpr)
00843             {
00844                 BinopExpr be = (BinopExpr) r;
00845 
00846                 if(be.getOp1() instanceof Local)
00847                 {
00848                     TypeVariable var  = getTypeVariable((Local) be.getOp1());
00849 
00850                     if((r instanceof AddExpr) ||
00851                         (r instanceof SubExpr) ||
00852                         (r instanceof MulExpr) ||
00853                         (r instanceof DivExpr) ||
00854                         (r instanceof RemExpr))
00855                     {
00856                         var.ecrCannotBeAddress();
00857                         var.ecrCannotBeRef();
00858                         var.ecrAddParent(left);
00859                     }
00860                     else if((r instanceof AndExpr) ||
00861                         (r instanceof OrExpr) ||
00862                         (r instanceof XorExpr) ||
00863                         (r instanceof ShlExpr) ||
00864                         (r instanceof ShrExpr) ||
00865                         (r instanceof UshrExpr))
00866                     {
00867                         var.ecrCannotBeFloat();
00868                         var.ecrCannotBeDouble();
00869                         var.ecrCannotBeAddress();
00870                         var.ecrCannotBeRef();
00871                         var.ecrAddParent(left);
00872                         right = var;
00873                     }
00874                     else if(r instanceof CmpExpr)
00875                     {
00876                         var.ecrCannotBeInt();
00877                         var.ecrCannotBeFloat();
00878                         var.ecrCannotBeDouble();
00879                         var.ecrCannotBeAddress();
00880                         var.ecrCannotBeRef();
00881                     }
00882                     else if((r instanceof CmpgExpr) ||
00883                         (r instanceof CmplExpr))
00884                     {
00885                         var.ecrCannotBeInt();
00886                         var.ecrCannotBeLong();
00887                         var.ecrCannotBeAddress();
00888                         var.ecrCannotBeRef();
00889                     }
00890                     else if((r instanceof EqExpr) ||
00891                         (r instanceof NeExpr))
00892                     {
00893                         var.ecrCannotBeLong();
00894                         var.ecrCannotBeFloat();
00895                         var.ecrCannotBeDouble();
00896                         var.ecrCannotBeAddress();
00897                     }
00898                     else if((r instanceof GeExpr) ||
00899                         (r instanceof GtExpr) ||
00900                         (r instanceof LeExpr) ||
00901                         (r instanceof LtExpr))
00902                     {
00903                         var.ecrCannotBeLong();
00904                         var.ecrCannotBeFloat();
00905                         var.ecrCannotBeDouble();
00906                         var.ecrCannotBeAddress();
00907                         var.ecrCannotBeRef();
00908                     }
00909                 }
00910                 else if(be.getOp1() instanceof DoubleConstant)
00911                 {
00912                     if((r instanceof AddExpr) ||
00913                         (r instanceof SubExpr) ||
00914                         (r instanceof MulExpr) ||
00915                         (r instanceof DivExpr) ||
00916                         (r instanceof RemExpr) ||
00917                         (r instanceof AndExpr) ||
00918                         (r instanceof OrExpr) ||
00919                         (r instanceof XorExpr) ||
00920                         (r instanceof ShlExpr) ||
00921                         (r instanceof ShrExpr) ||
00922                         (r instanceof UshrExpr))
00923                     {
00924                         getTypeVariable(DoubleType.v()).ecrAddParent(left);
00925                         right = getTypeVariable(DoubleType.v());
00926                     }
00927                 }
00928                 else if(be.getOp1() instanceof FloatConstant)
00929                 {
00930                     if((r instanceof AddExpr) ||
00931                         (r instanceof SubExpr) ||
00932                         (r instanceof MulExpr) ||
00933                         (r instanceof DivExpr) ||
00934                         (r instanceof RemExpr) ||
00935                         (r instanceof AndExpr) ||
00936                         (r instanceof OrExpr) ||
00937                         (r instanceof XorExpr) ||
00938                         (r instanceof ShlExpr) ||
00939                         (r instanceof ShrExpr) ||
00940                         (r instanceof UshrExpr))
00941                     {
00942                         getTypeVariable(FloatType.v()).ecrAddParent(left);
00943                         right = getTypeVariable(FloatType.v());
00944                     }
00945                 }
00946                 else if(be.getOp1() instanceof IntConstant)
00947                 {
00948                     if((r instanceof AddExpr) ||
00949                         (r instanceof SubExpr) ||
00950                         (r instanceof MulExpr) ||
00951                         (r instanceof DivExpr) ||
00952                         (r instanceof RemExpr) ||
00953                         (r instanceof AndExpr) ||
00954                         (r instanceof OrExpr) ||
00955                         (r instanceof XorExpr) ||
00956                         (r instanceof ShlExpr) ||
00957                         (r instanceof ShrExpr) ||
00958                         (r instanceof UshrExpr))
00959                     {
00960                         getTypeVariable(IntType.v()).ecrAddParent(left);
00961                         right = getTypeVariable(IntType.v());
00962                     }
00963                 }
00964                 else if(be.getOp1() instanceof LongConstant)
00965                 {
00966                     if((r instanceof AddExpr) ||
00967                         (r instanceof SubExpr) ||
00968                         (r instanceof MulExpr) ||
00969                         (r instanceof DivExpr) ||
00970                         (r instanceof RemExpr) ||
00971                         (r instanceof AndExpr) ||
00972                         (r instanceof OrExpr) ||
00973                         (r instanceof XorExpr) ||
00974                         (r instanceof ShlExpr) ||
00975                         (r instanceof ShrExpr) ||
00976                         (r instanceof UshrExpr))
00977                     {
00978                         getTypeVariable(LongType.v()).ecrAddParent(left);
00979                         right = getTypeVariable(LongType.v());
00980                     }
00981                 }
00982                 else if(be.getOp1() instanceof NullConstant)
00983                 {
00984                     if((r instanceof AddExpr) ||
00985                         (r instanceof SubExpr) ||
00986                         (r instanceof MulExpr) ||
00987                         (r instanceof DivExpr) ||
00988                         (r instanceof RemExpr) ||
00989                         (r instanceof AndExpr) ||
00990                         (r instanceof OrExpr) ||
00991                         (r instanceof XorExpr) ||
00992                         (r instanceof ShlExpr) ||
00993                         (r instanceof ShrExpr) ||
00994                         (r instanceof UshrExpr))
00995                     {
00996                         // getTypeVariable(NullType.v()).ecrAddParent(left);
00997                         right = null; // getTypeVariable(NullType.v());
00998                     }
00999                 }
01000                 else if(be.getOp1() instanceof StringConstant)
01001                 {
01002                     if((r instanceof AddExpr) ||
01003                         (r instanceof SubExpr) ||
01004                         (r instanceof MulExpr) ||
01005                         (r instanceof DivExpr) ||
01006                         (r instanceof RemExpr) ||
01007                         (r instanceof AndExpr) ||
01008                         (r instanceof OrExpr) ||
01009                         (r instanceof XorExpr) ||
01010                         (r instanceof ShlExpr) ||
01011                         (r instanceof ShrExpr) ||
01012                         (r instanceof UshrExpr))
01013                     {
01014                         getTypeVariable(RefType.v("java.lang.String")).ecrAddParent(left);
01015                         right = getTypeVariable(RefType.v("java.lang.String"));
01016                     }
01017                 }
01018 
01019                 if(be.getOp2() instanceof Local)
01020                 {
01021                     TypeVariable var  = getTypeVariable((Local) be.getOp2());
01022 
01023                     if((r instanceof AddExpr) ||
01024                         (r instanceof SubExpr) ||
01025                         (r instanceof MulExpr) ||
01026                         (r instanceof DivExpr) ||
01027                         (r instanceof RemExpr))
01028                     {
01029                         var.ecrCannotBeAddress();
01030                         var.ecrCannotBeRef();
01031                         right = var;
01032                     }
01033                     else if((r instanceof AndExpr) ||
01034                         (r instanceof OrExpr) ||
01035                         (r instanceof XorExpr))
01036                     {
01037                         var.ecrCannotBeFloat();
01038                         var.ecrCannotBeDouble();
01039                         var.ecrCannotBeAddress();
01040                         var.ecrCannotBeRef();
01041                         right = var;
01042                     }
01043                     else if((r instanceof ShlExpr) ||
01044                         (r instanceof ShrExpr) ||
01045                         (r instanceof UshrExpr))
01046                     {
01047                         var.ecrCannotBeLong();
01048                         var.ecrCannotBeFloat();
01049                         var.ecrCannotBeDouble();
01050                         var.ecrCannotBeAddress();
01051                         var.ecrCannotBeRef();
01052                     }
01053                     else if(r instanceof CmpExpr)
01054                     {
01055                         var.ecrCannotBeInt();
01056                         var.ecrCannotBeFloat();
01057                         var.ecrCannotBeDouble();
01058                         var.ecrCannotBeAddress();
01059                         var.ecrCannotBeRef();
01060                         right = getTypeVariable(IntType.v());
01061                     }
01062                     else if((r instanceof CmpgExpr) ||
01063                         (r instanceof CmplExpr))
01064                     {
01065                         var.ecrCannotBeInt();
01066                         var.ecrCannotBeLong();
01067                         var.ecrCannotBeAddress();
01068                         var.ecrCannotBeRef();
01069                         right = getTypeVariable(IntType.v());
01070                     }
01071                     else if((r instanceof EqExpr) ||
01072                         (r instanceof NeExpr))
01073                     {
01074                         var.ecrCannotBeLong();
01075                         var.ecrCannotBeFloat();
01076                         var.ecrCannotBeDouble();
01077                         var.ecrCannotBeAddress();
01078                         right = getTypeVariable(IntType.v());
01079                     }
01080                     else if((r instanceof GeExpr) ||
01081                         (r instanceof GtExpr) ||
01082                         (r instanceof LeExpr) ||
01083                         (r instanceof LtExpr))
01084                     {
01085                         var.ecrCannotBeLong();
01086                         var.ecrCannotBeFloat();
01087                         var.ecrCannotBeDouble();
01088                         var.ecrCannotBeAddress();
01089                         var.ecrCannotBeRef();
01090                         right = getTypeVariable(IntType.v());
01091                     }
01092                 }
01093                 else if(be.getOp2() instanceof DoubleConstant)
01094                 {
01095                     if((r instanceof AddExpr) ||
01096                         (r instanceof SubExpr) ||
01097                         (r instanceof MulExpr) ||
01098                         (r instanceof DivExpr) ||
01099                         (r instanceof RemExpr) ||
01100                         (r instanceof AndExpr) ||
01101                         (r instanceof OrExpr) ||
01102                         (r instanceof XorExpr))
01103                     {
01104                         right = getTypeVariable(DoubleType.v());
01105                     }
01106                     else
01107                     {
01108                         right = getTypeVariable(IntType.v());
01109                     }
01110                 }
01111                 else if(be.getOp2() instanceof FloatConstant)
01112                 {
01113                     if((r instanceof AddExpr) ||
01114                         (r instanceof SubExpr) ||
01115                         (r instanceof MulExpr) ||
01116                         (r instanceof DivExpr) ||
01117                         (r instanceof RemExpr) ||
01118                         (r instanceof AndExpr) ||
01119                         (r instanceof OrExpr) ||
01120                         (r instanceof XorExpr))
01121                     {
01122                         right = getTypeVariable(FloatType.v());
01123                     }
01124                     else
01125                     {
01126                         right = getTypeVariable(IntType.v());
01127                     }
01128                 }
01129                 else if(be.getOp2() instanceof IntConstant)
01130                 {
01131                     if((r instanceof AddExpr) ||
01132                         (r instanceof SubExpr) ||
01133                         (r instanceof MulExpr) ||
01134                         (r instanceof DivExpr) ||
01135                         (r instanceof RemExpr) ||
01136                         (r instanceof AndExpr) ||
01137                         (r instanceof OrExpr) ||
01138                         (r instanceof XorExpr))
01139                     {
01140                         right = getTypeVariable(IntType.v());
01141                     }
01142                     else if(!((r instanceof ShlExpr) ||
01143                         (r instanceof UshrExpr) ||
01144                         (r instanceof ShrExpr)))
01145                     {
01146                         right = getTypeVariable(IntType.v());
01147                     }
01148                 }
01149                 else if(be.getOp2() instanceof LongConstant)
01150                 {
01151                     if((r instanceof AddExpr) ||
01152                         (r instanceof SubExpr) ||
01153                         (r instanceof MulExpr) ||
01154                         (r instanceof DivExpr) ||
01155                         (r instanceof RemExpr) ||
01156                         (r instanceof AndExpr) ||
01157                         (r instanceof OrExpr) ||
01158                         (r instanceof XorExpr))
01159                     {
01160                         right = getTypeVariable(LongType.v());
01161                     }
01162                     else
01163                     {
01164                         right = getTypeVariable(IntType.v());
01165                     }
01166                 }
01167                 else if(be.getOp2() instanceof NullConstant)
01168                 {
01169                     if((r instanceof AddExpr) ||
01170                         (r instanceof SubExpr) ||
01171                         (r instanceof MulExpr) ||
01172                         (r instanceof DivExpr) ||
01173                         (r instanceof RemExpr) ||
01174                         (r instanceof AndExpr) ||
01175                         (r instanceof OrExpr) ||
01176                         (r instanceof XorExpr))
01177                     {
01178                         right = null; // getTypeVariable(NullType.v());
01179                     }
01180                     else
01181                     {
01182                         right = getTypeVariable(IntType.v());
01183                     }
01184                 }
01185                 else if(be.getOp2() instanceof StringConstant)
01186                 {
01187                     if((r instanceof AddExpr) ||
01188                         (r instanceof SubExpr) ||
01189                         (r instanceof MulExpr) ||
01190                         (r instanceof DivExpr) ||
01191                         (r instanceof RemExpr) ||
01192                         (r instanceof AndExpr) ||
01193                         (r instanceof OrExpr) ||
01194                         (r instanceof XorExpr))
01195                     {
01196                         right = getTypeVariable(RefType.v("java.lang.String"));
01197                     }
01198                     else
01199                     {
01200                         right = getTypeVariable(IntType.v());
01201                     }
01202                 }
01203             }
01204             else if(r instanceof CastExpr)
01205             {
01206                 CastExpr ce = (CastExpr) r;
01207 
01208                 right = getTypeVariable(ce.getCastType());
01209             }
01210             else if(r instanceof InstanceOfExpr)
01211             {
01212                 InstanceOfExpr ioe = (InstanceOfExpr) r;
01213 
01214                 TypeVariable var = getTypeVariable((Local) ioe.getOp());
01215 
01216                 var.ecrCannotBeInt();
01217                 var.ecrCannotBeLong();
01218                 var.ecrCannotBeFloat();
01219                 var.ecrCannotBeDouble();
01220                 var.ecrCannotBeAddress();
01221 
01222                 right = getTypeVariable(IntType.v());
01223             }
01224             else if(r instanceof InvokeExpr)
01225             {
01226                 InvokeExpr ie = (InvokeExpr) r;
01227 
01228                 handleInvokeExpr(ie);
01229 
01230                 right = getTypeVariable(ie.getMethod().getReturnType());
01231             }
01232             else if(r instanceof NewArrayExpr)
01233             {
01234                 NewArrayExpr nae = (NewArrayExpr) r;
01235 
01236                 Type baseType = nae.getBaseType();
01237 
01238                 if(baseType instanceof ArrayType)
01239                 {
01240                     right = getTypeVariable(ArrayType.v(((ArrayType) baseType).
01241                         baseType, ((ArrayType) baseType).numDimensions + 1));
01242                 }
01243                 else
01244                     right = getTypeVariable(ArrayType.v((BaseType) baseType, 1));
01245 
01246                 Value size = nae.getSize();
01247                 if(size instanceof Local)
01248                 {
01249                     TypeVariable var = getTypeVariable((Local) size);
01250                     var.ecrCannotBeLong();
01251                     var.ecrCannotBeFloat();
01252                     var.ecrCannotBeDouble();
01253                     var.ecrCannotBeAddress();
01254                     var.ecrCannotBeRef();
01255                 }
01256             }
01257             else if(r instanceof NewExpr)
01258             {
01259                 NewExpr na = (NewExpr) r;
01260 
01261                 right = getTypeVariable(na.getBaseType());
01262             }
01263             else if(r instanceof NewMultiArrayExpr)
01264             {
01265                 NewMultiArrayExpr nmae = (NewMultiArrayExpr) r;
01266 
01267                 right = getTypeVariable(nmae.getBaseType());
01268 
01269                 for(int i = 0; i < nmae.getSizeCount(); i++)
01270                 {
01271                     Value size = nmae.getSize(i);
01272                     if(size instanceof Local)
01273                     {
01274                         TypeVariable var = getTypeVariable((Local) size);
01275                         var.ecrCannotBeLong();
01276                         var.ecrCannotBeFloat();
01277                         var.ecrCannotBeDouble();
01278                         var.ecrCannotBeAddress();
01279                         var.ecrCannotBeRef();
01280                     }
01281                 }
01282             }
01283             else if(r instanceof LengthExpr)
01284             {
01285                 LengthExpr le = (LengthExpr) r;
01286 
01287                 if(le.getOp() instanceof Local)
01288                 {
01289                     getTypeVariable((Local) le.getOp()).getEcrIsArrayOf();
01290                 }
01291 
01292                 right = getTypeVariable(IntType.v());
01293             }
01294             else if(r instanceof NegExpr)
01295             {
01296                 NegExpr ne = (NegExpr) r;
01297 
01298                 if(ne.getOp() instanceof Local)
01299                 {
01300                     right = getTypeVariable((Local) ne.getOp());
01301 
01302                     right.ecrCannotBeAddress();
01303                     right.ecrCannotBeRef();
01304                 }
01305                 else if(ne.getOp() instanceof DoubleConstant)
01306                 {
01307                     right = getTypeVariable(DoubleType.v());
01308                 }
01309                 else if(ne.getOp() instanceof FloatConstant)
01310                 {
01311                     right = getTypeVariable(FloatType.v());
01312                 }
01313                 else if(ne.getOp() instanceof IntConstant)
01314                 {
01315                     right = getTypeVariable(IntType.v());
01316                 }
01317                 else if(ne.getOp() instanceof LongConstant)
01318                 {
01319                     right = getTypeVariable(LongType.v());
01320                 }
01321             }
01322             else if(r instanceof Local)
01323             {
01324                 right = getTypeVariable((Local) r);
01325             }
01326             else if(r instanceof InstanceFieldRef)
01327             {
01328                 InstanceFieldRef ref = (InstanceFieldRef) r;
01329 
01330                 TypeVariable baseType = getTypeVariable((Local) ref.getBase());
01331                 baseType.ecrAddParent(getTypeVariable(ref.getField().getDeclaringClass()));
01332                 right = getTypeVariable(ref.getField().getType());
01333             }
01334             else if(r instanceof StaticFieldRef)
01335             {
01336                 StaticFieldRef ref = (StaticFieldRef) r;
01337 
01338                 right = getTypeVariable(ref.getField().getType());
01339             }
01340             else if(r instanceof NextNextStmtRef)
01341             {
01342                 right = getTypeVariable(StmtAddressType.v());
01343             }
01344             else
01345             {
01346                 throw new RuntimeException("Unhandled variable type: " + r.getClass());
01347             }
01348 
01349             if(right != null)
01350             {
01351                 right.ecrAddParent(left);
01352             }
01353         }
01354 
01355         public void caseIdentityStmt(IdentityStmt stmt)
01356         {
01357             Value l = stmt.getLeftOp();
01358             Value r = stmt.getRightOp();
01359 
01360             if(l instanceof Local)
01361             {
01362                 TypeVariable left = getTypeVariable((Local) l);
01363 
01364                 if(!(r instanceof CaughtExceptionRef))
01365                 {
01366                     TypeVariable right = getTypeVariable(r.getType());
01367                     right.ecrAddParent(left);
01368                 }
01369                 else
01370                 {
01371                     List exceptionTypes = ((CaughtExceptionRef) r).getExceptionTypes();
01372                     Iterator typeIt = exceptionTypes.iterator();
01373 
01374                     while(typeIt.hasNext())
01375                     {
01376                         Type t = (Type) typeIt.next();
01377 
01378                         left.ecrAddChild(getTypeVariable(t));
01379                     }
01380 
01381                     left.ecrAddParent(getTypeVariable(RefType.v("java.lang.Throwable")));
01382                 }
01383             }
01384         }
01385 
01386         public void caseEnterMonitorStmt(EnterMonitorStmt stmt)
01387         {
01388             if(stmt.getOp() instanceof Local)
01389             {
01390                 TypeVariable op = getTypeVariable((Local) stmt.getOp());
01391 
01392                 op.ecrAddParent(getTypeVariable(RefType.v("java.lang.Object")));
01393             }
01394         }
01395 
01396         public void caseExitMonitorStmt(ExitMonitorStmt stmt)
01397         {
01398             if(stmt.getOp() instanceof Local)
01399             {
01400                 TypeVariable op = getTypeVariable((Local) stmt.getOp());
01401 
01402                 op.ecrAddParent(getTypeVariable(RefType.v("java.lang.Object")));
01403             }
01404         }
01405 
01406         public void caseGotoStmt(GotoStmt stmt)
01407         {
01408         }
01409 
01410         public void caseIfStmt(IfStmt stmt)
01411         {
01412             ConditionExpr cond = (ConditionExpr) stmt.getCondition();
01413 
01414             BinopExpr expr = (BinopExpr) cond;
01415             Value l = expr.getOp1();
01416             Value r = expr.getOp2();
01417 
01418             if(l instanceof Local)
01419             {
01420                 TypeVariable var = getTypeVariable((Local) l);
01421 
01422                 if((cond instanceof EqExpr) ||
01423                     (cond instanceof NeExpr))
01424                 {
01425                     var.ecrCannotBeLong();
01426                     var.ecrCannotBeFloat();
01427                     var.ecrCannotBeDouble();
01428                     var.ecrCannotBeAddress();
01429                 }
01430                 else if((cond instanceof GeExpr) ||
01431                     (cond instanceof GtExpr) ||
01432                     (cond instanceof LeExpr) ||
01433                     (cond instanceof LtExpr))
01434                 {
01435                     var.ecrCannotBeLong();
01436                     var.ecrCannotBeFloat();
01437                     var.ecrCannotBeDouble();
01438                     var.ecrCannotBeAddress();
01439                     var.ecrCannotBeRef();
01440                 }
01441             }
01442 
01443             if(r instanceof Local)
01444             {
01445                 TypeVariable var = getTypeVariable((Local) r);
01446 
01447                 if((cond instanceof EqExpr) ||
01448                     (cond instanceof NeExpr))
01449                 {
01450                     var.ecrCannotBeLong();
01451                     var.ecrCannotBeFloat();
01452                     var.ecrCannotBeDouble();
01453                     var.ecrCannotBeAddress();
01454                 }
01455                 else if((cond instanceof GeExpr) ||
01456                     (cond instanceof GtExpr) ||
01457                     (cond instanceof LeExpr) ||
01458                     (cond instanceof LtExpr))
01459                 {
01460                     var.ecrCannotBeLong();
01461                     var.ecrCannotBeFloat();
01462                     var.ecrCannotBeDouble();
01463                     var.ecrCannotBeAddress();
01464                     var.ecrCannotBeRef();
01465                 }
01466             }
01467         }
01468 
01469         public void caseLookupSwitchStmt(LookupSwitchStmt stmt)
01470         {
01471             Value key = stmt.getKey();
01472 
01473             if(key instanceof Local)
01474             {
01475                 getTypeVariable((Local) key).ecrCannotBeLong();
01476                 getTypeVariable((Local) key).ecrCannotBeFloat();
01477                 getTypeVariable((Local) key).ecrCannotBeDouble();
01478                 getTypeVariable((Local) key).ecrCannotBeAddress();
01479                 getTypeVariable((Local) key).ecrCannotBeRef();
01480             }
01481         }
01482 
01483         public void caseNopStmt(NopStmt stmt)
01484         {
01485         }
01486 
01487         public void caseRetStmt(RetStmt stmt)
01488         {
01489             getTypeVariable((Local) stmt.getStmtAddress()).
01490                 ecrAddParent(getTypeVariable(StmtAddressType.v()));
01491         }
01492 
01493         public void caseReturnStmt(ReturnStmt stmt)
01494         {
01495             if(stmt.getReturnValue() instanceof Local)
01496             {
01497                 getTypeVariable((Local) stmt.getReturnValue()).ecrAddParent(
01498                     getTypeVariable(currentMethod.getReturnType()));
01499             }
01500         }
01501 
01502         public void caseReturnVoidStmt(ReturnVoidStmt stmt)
01503         {
01504         }
01505 
01506         public void caseTableSwitchStmt(TableSwitchStmt stmt)
01507         {
01508             Value key = stmt.getKey();
01509 
01510             if(key instanceof Local)
01511             {
01512                 getTypeVariable((Local) key).ecrCannotBeLong();
01513                 getTypeVariable((Local) key).ecrCannotBeFloat();
01514                 getTypeVariable((Local) key).ecrCannotBeDouble();
01515                 getTypeVariable((Local) key).ecrCannotBeAddress();
01516                 getTypeVariable((Local) key).ecrCannotBeRef();
01517             }
01518         }
01519 
01520         public void caseThrowStmt(ThrowStmt stmt)
01521         {
01522             if(stmt.getOp() instanceof Local)
01523             {
01524                 TypeVariable op = getTypeVariable((Local) stmt.getOp());
01525 
01526                 op.ecrAddParent(getTypeVariable(RefType.v("java.lang.Throwable")));
01527             }
01528         }
01529 
01530         public void defaultCase(Stmt stmt)
01531         {
01532             throw new RuntimeException("Unhandled statement type: " + stmt.getClass());
01533         }
01534     }
01535 
01536     private static class SCC
01537     {
01538         TypeVariable[] variables;
01539         boolean[] black;
01540         TypeVariable[] finished;
01541         int time;
01542 
01543         LinkedList forest = new LinkedList();
01544         LinkedList current_tree;
01545 
01546         SCC(Vector typeVariableInstances)
01547         {
01548             variables = new TypeVariable[typeVariableInstances.size()];
01549 
01550             int counter = 0;
01551             for(Enumeration e = typeVariableInstances.elements(); e.hasMoreElements();)
01552             {
01553                 variables[counter++] = (TypeVariable) e.nextElement();
01554             }
01555 
01556             black = new boolean[variables.length];
01557             finished = new TypeVariable[variables.length];
01558 
01559             for(int i = 0; i < variables.length; i++)
01560             {
01561                 if((variables[i] == variables[i].ecr()) &&
01562                     (variables[i].arrayDepth == 0))
01563                 {
01564                     if(!black[variables[i].id])
01565                     {
01566                         black[variables[i].id] = true;
01567                         dfsg_visit(variables[i]);
01568                     }
01569                 }
01570             }
01571 
01572             black = new boolean[variables.length];
01573 
01574             for(int i = variables.length - 1; i >= 0; i--)
01575             {
01576                 if(finished[i] == null)
01577                 {
01578                     continue;
01579                 }
01580 
01581                 if((finished[i] == finished[i].ecr()) &&
01582                     (finished[i].arrayDepth == 0))
01583                 {
01584                     if(!black[finished[i].id])
01585                     {
01586                         current_tree = new LinkedList();
01587                         forest.add(current_tree);
01588 
01589                         black[finished[i].id] = true;
01590                         dfsgt_visit(finished[i]);
01591                     }
01592                 }
01593             }
01594 
01595             for(Iterator i = forest.iterator(); i.hasNext();)
01596             {
01597                 LinkedList list = (LinkedList) i.next();
01598                 TypeVariable previous = null;
01599 
01600                 for(Iterator j = list.iterator(); j.hasNext();)
01601                 {
01602                     TypeVariable current = (TypeVariable) j.next();
01603 
01604                     if(previous == null)
01605                     {
01606                         previous = current;
01607                     }
01608                     else
01609                     {
01610                         previous.ecrUnion(current);
01611                     }
01612                 }
01613             }
01614         }
01615 
01616         void dfsg_visit(TypeVariable var)
01617         {
01618             TypeVariable[] parents = var.getEcrParents();
01619 
01620             for(int i = 0; i < parents.length; i++)
01621             {
01622                 if(!black[parents[i].id])
01623                 {
01624                     black[parents[i].id] = true;
01625                     dfsg_visit(parents[i]);
01626                 }
01627             }
01628 
01629             finished[time++] = var;
01630         }
01631 
01632         void dfsgt_visit(TypeVariable var)
01633         {
01634             current_tree.add(var);
01635 
01636             TypeVariable[] children = var.getEcrChildren();
01637 
01638             for(int i = 0; i < children.length; i++)
01639             {
01640                 if(!black[children[i].id])
01641                 {
01642                     if(children[i].arrayDepth == 0)
01643                     {
01644                         black[children[i].id] = true;
01645                         dfsgt_visit(children[i]);
01646                     }
01647                 }
01648             }
01649         }
01650     }
01651 
01652     private static class TypeException extends RuntimeException
01653     {
01654     }
01655 
01656     /** This constructor triggers the type resolution of
01657         local variables of the given statement list body. **/
01658     private TypeResolver(JimpleBody stmtBody)
01659     {
01660         try {
01661 
01662         this.stmtBody = stmtBody;
01663 
01664         currentMethod = stmtBody.getMethod();
01665         if(!currentMethod.getDeclaringClass().getName().equals(lastClass))
01666         {
01667             // System.out.println();
01668             lastClass = currentMethod.getDeclaringClass().getName();
01669         }
01670 
01671         classHierarchy = ClassHierarchy.getClassHierarchy(
01672             currentMethod.getDeclaringClass().getManager());
01673 
01674         if(DEBUG)
01675         {
01676             System.out.println();
01677             System.out.println("****" + currentMethod.getName());
01678         }
01679 
01680 //        System.gc();
01681 //        long st = System.currentTimeMillis();
01682 
01683         // Collect constraints
01684         for(Iterator i = stmtBody.getStmtList().iterator(); i.hasNext();)
01685         {
01686             Stmt stmt = (Stmt) i.next();
01687             if(DEBUG)
01688             {
01689                 System.out.println("** " + stmt);
01690             }
01691             stmt.apply(constraintCollector);
01692         }
01693 
01694         getTypeVariable(RefType.v("java.lang.Object"));
01695         getTypeVariable(RefType.v("java.lang.Cloneable"));
01696         getTypeVariable(NullType.v());
01697 
01698 //        debug();
01699 
01700 //        long en = System.currentTimeMillis();
01701 
01702 /*        {
01703             int edges = 0, nodes = 0, unresolved = 0;
01704 
01705 //            System.out.println();
01706 //            System.out.print(currentMethod.getDeclaringClass().getName() + "." + currentMethod.getName() + ":");
01707 //            System.out.print("\t" + stmtBody.getStmtList().size());
01708 
01709             for(Enumeration e = typeVariableInstances.elements(); e.hasMoreElements();)
01710             {
01711                 TypeVariable var = (TypeVariable) e.nextElement();
01712                 nodes++;
01713                 edges += var.parents.elementCount();
01714                 if(var.getEcrTypeNode() == null)
01715                 {
01716                     unresolved++;
01717                 }
01718             }
01719             // System.out.print("\t" + nodes + "\t" + unresolved + "\t" + (nodes - unresolved) + "\t" + edges);
01720         } */
01721 
01722 //        System.gc();
01723 //    long start = System.currentTimeMillis();
01724 
01725         // Collapse basic types
01726         mergeAll(getTypeVariable(IntType.v()));
01727         mergeAll(getTypeVariable(LongType.v()));
01728         mergeAll(getTypeVariable(FloatType.v()));
01729         mergeAll(getTypeVariable(DoubleType.v()));
01730         mergeAll(getTypeVariable(StmtAddressType.v()));
01731 
01732 //        debug();
01733 
01734         // Collapse connected components
01735         do
01736         {
01737             new_relation = false;
01738             collapseStronglyConnectedComponents();
01739         }
01740         while(new_relation == true);
01741 //        collapseStronglyConnectedComponents();
01742 
01743 //        debug();
01744 
01745 /*        if(currentMethod.getName().equals("decapitalize"))
01746         {
01747         System.out.println();
01748         for(Enumeration e = typeVariableInstances.elements(); e.hasMoreElements();)
01749         {
01750             TypeVariable var = (TypeVariable) e.nextElement();
01751 
01752             if(var == var.ecr())
01753             {
01754             System.out.println(
01755                 var.getEcrId() + ": count=" + var.count + " parents=" + var.parents + " children=" + var.children +
01756                 " isArrayOf=" + ((var.isArrayOf == null) ? "" : ("" + var.isArrayOf.getEcrId())) + " isElementOf=" + var.isElementOf +
01757                 " type=" + ((var.getEcrTypeNode() == null) ? "" : ("" + var.getEcrTypeNode().getType())) + " arrayDepth=" + var.arrayDepth
01758             );
01759             }
01760         }
01761         }*/
01762 
01763         // Propagate array constraints
01764         propagateArrayConstraints();
01765 
01766 //        debug();
01767 
01768         addRelationsBetweenHardNodes();
01769 //        removeRelationsBetweenNonEcrs();
01770 
01771 //        debug();
01772 
01773         // Collapse basic types (again)
01774         mergeAll(getTypeVariable(IntType.v()));
01775         mergeAll(getTypeVariable(LongType.v()));
01776         mergeAll(getTypeVariable(FloatType.v()));
01777         mergeAll(getTypeVariable(DoubleType.v()));
01778         mergeAll(getTypeVariable(StmtAddressType.v()));
01779 
01780 //        debug();
01781 
01782         // Collapse connected components (again)
01783         collapseStronglyConnectedComponents();
01784 
01785 //        debug();
01786 
01787 /*        {
01788             int edges = 0, nodes = 0, unresolved = 0;
01789 
01790             for(Enumeration e = typeVariableInstances.elements(); e.hasMoreElements();)
01791             {
01792                 TypeVariable var = (TypeVariable) e.nextElement();
01793 
01794                 if((var != var.ecr()) || (var.arrayDepth != 0))
01795                 {
01796                     continue;
01797                 }
01798 
01799                 nodes++;
01800                 edges += var.parents.elementCount();
01801 
01802                 if(var.getEcrTypeNode() == null)
01803                 {
01804                     unresolved++;
01805                 }
01806             }
01807 //            System.out.print("\t" + nodes + "\t" + unresolved + "\t" + (nodes - unresolved) + "\t" + edges);
01808         } */
01809 
01810 //    {
01811 //    int count = 0;
01812 
01813         // Main algorithm
01814         if(unresolvedTypeVariables.size() != 0)
01815         {
01816             resolveSingleRelations();
01817 //            count++;
01818         }
01819 
01820 //        debug();
01821 
01822         boolean modified = true;
01823         while((unresolvedTypeVariables.size() != 0) && modified)
01824         {
01825             removeIndirectRelations();
01826             modified = resolveSingleRelations();
01827 //        count++;
01828         }
01829 
01830 /*      System.out.print("\t" + count); */
01831 //    }
01832 
01833 
01834         // NP-Complete hard case!
01835         if(unresolvedTypeVariables.size() != 0)
01836         {
01837 /*          System.out.print("\t1"); */
01838 
01839             resolveComplexRelations();
01840             if(unresolvedTypeVariables.size() != 0)
01841             {
01842 /*              System.out.print("\t1"); */
01843             }
01844             else
01845             {
01846 /*              System.out.print("\t0"); */
01847             }
01848         }
01849         else
01850         {
01851 /*          System.out.print("\t0\t0"); */
01852         }
01853 
01854 
01855 //    long end = System.currentTimeMillis();
01856 /*      System.out.print("\t" + (end - start)); */
01857 /*      System.out.print("\t" + (en - st)); */
01858         } catch(TypeException e)
01859         {
01860 ///**/        System.out.print(" error=1");
01861         }
01862 
01863 /*      System.out.println(); */
01864 
01865         for(Iterator i = stmtBody.getLocals().iterator(); i.hasNext(); )
01866         {
01867             Local local = (Local) i.next();
01868 
01869             TypeVariable var = getTypeVariable(local).ecr();
01870             if(var == null)
01871             {
01872                 local.setType(UnknownType.v());
01873             }
01874             else if (var.arrayDepth == 0)
01875             {
01876                 if(var.getEcrTypeNode() == null)
01877                 {
01878                     local.setType(UnknownType.v());
01879                 }
01880                 else
01881                 {
01882                     local.setType(var.getEcrTypeNode().getType());
01883                 }
01884             }
01885             else
01886             {
01887                 if/*(*/(var.getEcrTypeNode() != null) /*&&
01888                     (!(var.base.getEcrTypeNode().getType() instanceof RefType)))*/
01889                 {
01890                     local.setType(var.getEcrTypeNode().getType());
01891                 }
01892                 else if(var.base.getEcrTypeNode() == null)
01893                 {
01894                     local.setType(UnknownType.v());
01895                 }
01896                 else if(var.base.getEcrTypeNode().getType() instanceof ErroneousType)
01897                 {
01898                     local.setType(ErroneousType.v());
01899                 }
01900                 else
01901                 {
01902                     local.setType(ArrayType.v(
01903                         (BaseType) var.base.getEcrTypeNode().getType(),
01904                         var.arrayDepth));
01905                 }
01906             }
01907         }
01908     }
01909     private void addRelationsBetweenHardNodes()
01910     {
01911         LinkedList workList = new LinkedList();
01912 
01913         for(Enumeration e = typeVariableInstances.elements(); e.hasMoreElements();)
01914         {
01915             TypeVariable var = (TypeVariable) e.nextElement();
01916 
01917             if((var == var.ecr()) &&
01918                 (var.getEcrTypeNode() != null) &&
01919                 (!(var.getEcrTypeNode().getType() instanceof ArrayType)))
01920             {
01921                 workList.add(var);
01922             }
01923         }
01924 
01925         while(workList.size() > 0)
01926         {
01927             TypeVariable var = (TypeVariable) workList.removeFirst();
01928 
01929             TypeVariable[] elements = new TypeVariable[workList.size()];
01930             workList.toArray(elements);
01931 
01932             for(int i = 0; i < elements.length; i++)
01933             {
01934                 TypeVariable other = elements[i];
01935 
01936                 if(var.getEcrTypeNode().hasAncestor(other.getEcrTypeNode()))
01937                 {
01938                     var.ecrAddParent(other);
01939                 }
01940                 else if(var.getEcrTypeNode().hasDescendant(other.getEcrTypeNode()))
01941                 {
01942                     var.ecrAddChild(other);
01943                 }
01944             }
01945 
01946         }
01947     }
01948     /** Assign types to local variables. **/
01949     public static void assignTypesToLocals(JimpleBody stmtBody)
01950     {
01951         new TypeResolver(stmtBody);
01952     }
01953     /** Merge together variables involved in a dependence cycle.
01954         Use the set of all type variables **/
01955     private void collapseStronglyConnectedComponents()
01956     {
01957         new SCC(typeVariableInstances);
01958     }
01959     private void computeArrayDepths()
01960     {
01961         LinkedList workList = new LinkedList();
01962         LinkedList workList2 = new LinkedList();
01963 
01964         int counter = 0;
01965 
01966         for(Enumeration e = typeVariableInstances.elements(); e.hasMoreElements();)
01967         {
01968             TypeVariable var = (TypeVariable) e.nextElement();
01969 
01970             if(var == var.ecr())
01971             {
01972                 counter++;
01973                 var.count = var.parents.elementCount();
01974 
01975                 if((var.isArrayOf != null) &&
01976                     (!var.parents.get(var.isArrayOf.getEcrId())))
01977                 {
01978                    var.count++;
01979                 }
01980 
01981                 if(var.count == 0)
01982                 {
01983                     var.arrayDepth = 0;
01984                     workList.add(var);
01985                 }
01986             }
01987         }
01988 
01989         while(workList.size() > 0)
01990         {
01991             TypeVariable var = (TypeVariable) workList.removeFirst();
01992 
01993             int[] elements = var.children.elements();
01994             for(int i = 0; i < elements.length; i++)
01995             {
01996                 TypeVariable child =
01997                     (TypeVariable) typeVariableInstances.elementAt(elements[i]);
01998                 child.arrayDepth = Math.max(child.arrayDepth, var.arrayDepth);
01999                 if(--child.count == 0)
02000                 {
02001                     workList.add(child);
02002                 }
02003             }
02004 
02005             elements = var.isElementOf.elements();
02006             for(int i = 0; i < elements.length; i++)
02007             {
02008                 TypeVariable array =
02009                     ((TypeVariable) typeVariableInstances.
02010                     elementAt(elements[i])).ecr();
02011 
02012                 array.arrayDepth = Math.max(array.arrayDepth, var.arrayDepth + 1);
02013                 if(--array.count == 0)
02014                 {
02015                     workList.add(array);
02016                 }
02017             }
02018 
02019             workList2.add(var);
02020         }
02021 
02022         if(counter != workList2.size())
02023         {
02024             // System.out.println(currentMethod.getName() + ": counter = " + counter + ", worlist = " + workList2.size());
02025         for(Enumeration e = typeVariableInstances.elements(); e.hasMoreElements();)
02026         {
02027             TypeVariable var = (TypeVariable) e.nextElement();
02028 
02029             if(var == var.ecr())
02030             {
02031             /*
02032             System.out.println(
02033                 var.getEcrId() + ": count=" + var.count + " parents=" + var.parents + " children=" + var.children +
02034                 " isArrayOf=" + ((var.isArrayOf == null) ? "" : ("" + var.isArrayOf.getEcrId())) + " isElementOf=" + var.isElementOf +
02035                 " type=" + ((var.getEcrTypeNode() == null) ? "" : ("" + var.getEcrTypeNode().getType()))
02036             );
02037             */
02038 
02039             }
02040         }
02041         }
02042 
02043         while(workList2.size() > 0)
02044         {
02045             TypeVariable var = (TypeVariable) workList2.removeFirst();
02046             var.count = 0;
02047 
02048             if((var.isArrayOf != null) &&
02049                 (var.arrayDepth < var.isArrayOf.ecr().arrayDepth + 1))
02050             {
02051                 var.arrayDepth = var.isArrayOf.ecr().arrayDepth + 1;
02052             }
02053 
02054             int[] elements = var.isElementOf.elements();
02055             for(int i = 0; i < elements.length; i++)
02056             {
02057                 TypeVariable array =
02058                     ((TypeVariable) typeVariableInstances.elementAt(elements[i])).ecr();
02059 
02060                 if(var.arrayDepth < array.arrayDepth - 1)
02061                 {
02062                     var.arrayDepth = array.arrayDepth - 1;
02063                 }
02064             }
02065 
02066             elements = var.parents.elements();
02067             for(int i = 0; i < elements.length; i++)
02068             {
02069                 TypeVariable parent =
02070                     ((TypeVariable) typeVariableInstances.elementAt(elements[i])).ecr();
02071 
02072                 if(var.arrayDepth < parent.arrayDepth)
02073                 {
02074                     var.arrayDepth = parent.arrayDepth;
02075                 }
02076             }
02077 
02078             if((var.isArrayOf != null) &&
02079                 (var.arrayDepth > var.isArrayOf.ecr().arrayDepth + 1))
02080             {
02081                 var.isArrayOf.ecr().arrayDepth = var.arrayDepth - 1;
02082 
02083                 if(var.isArrayOf.ecr().count++ == 0)
02084                 {
02085                     workList2.add(var.isArrayOf.ecr());
02086                 }
02087             }
02088 
02089             elements = var.isElementOf.elements();
02090             for(int i = 0; i < elements.length; i++)
02091             {
02092                 TypeVariable array =
02093                     ((TypeVariable) typeVariableInstances.elementAt(elements[i])).ecr();
02094 
02095                 if(var.arrayDepth > array.arrayDepth - 1)
02096                 {
02097                     array.arrayDepth = var.arrayDepth + 1;
02098 
02099                     if(array.count++ == 0)
02100                     {
02101                         workList2.add(array);
02102                     }
02103                 }
02104             }
02105 
02106             elements = var.children.elements();
02107             for(int i = 0; i < elements.length; i++)
02108             {
02109                 TypeVariable child =
02110                     (TypeVariable) typeVariableInstances.elementAt(elements[i]);
02111 
02112                 if(var.arrayDepth > child.arrayDepth)
02113                 {
02114                     child.arrayDepth = var.arrayDepth;
02115 
02116                     if(child.count++ == 0)
02117                     {
02118                         workList2.add(child);
02119                     }
02120                 }
02121             }
02122         }
02123     }
02124     private void debug()
02125     {
02126       System.out.println("*** DEBUG ***");
02127       debug_locals();
02128       int size = typeVariableInstances.size();
02129       for(int i = 0; i < size; i++)
02130       {
02131         TypeVariable a = (TypeVariable) typeVariableInstances.elementAt(i);
02132 
02133         if(a == a.ecr())
02134         {
02135           System.out.print(i + ":");
02136 
02137           ClassHierarchy.TypeNode node = a.getEcrTypeNode();
02138           if(node != null)
02139           {
02140             System.out.print(" " + node.getType());
02141           }
02142           System.out.println();
02143 
02144           TypeVariable[] parents = a.getEcrParents();
02145           if(parents.length != 0)
02146           {
02147             System.out.print("  Parents:");
02148 
02149             for(int j = 0; j < parents.length; j++)
02150             {
02151               System.out.print(" " + parents[j].getEcrId());
02152             }
02153 
02154             System.out.println();
02155           }
02156 
02157           TypeVariable[] children = a.getEcrChildren();
02158           if(children.length != 0)
02159           {
02160             System.out.print("  Children:");
02161 
02162             for(int j = 0; j < children.length; j++)
02163             {
02164               System.out.print(" " + children[j].getEcrId());
02165             }
02166 
02167             System.out.println();
02168           }
02169 
02170           if(a.isArrayOf != null)
02171           {
02172             System.out.println("  Array of: " + a.isArrayOf.getEcrId());
02173           }
02174 
02175           System.out.println("  Array depth: " + a.arrayDepth);
02176         }
02177       }
02178     }
02179     private void debug_locals()
02180     {
02181       for(Iterator i = stmtBody.getLocals().iterator(); i.hasNext(); )
02182       {
02183         Local local = (Local) i.next();
02184 
02185         System.out.print(local + ": ");
02186 
02187         TypeVariable var = getTypeVariable(local).ecr();
02188         if(var == null)
02189         {
02190           System.out.println("null");
02191         }
02192         else
02193         {
02194           System.out.println(var.getEcrId());
02195         }
02196       }
02197     }
02198     private static void error(String message)
02199     {
02200         if(DEBUG)
02201         {
02202           System.out.println(message);
02203         }
02204 
02205         throw new TypeException();
02206     }
02207     /** Get type variable for the given type node. **/
02208     TypeVariable getTypeVariable(ClassHierarchy.TypeNode typeNode)
02209     {
02210         TypeVariable result = (TypeVariable) typeVariableHashtable.get(typeNode);
02211 
02212         if(result == null)
02213         {
02214             result = new TypeVariable(typeNode);
02215         }
02216 
02217         return result;
02218     }
02219     /** Get type variable for the given local. **/
02220     TypeVariable getTypeVariable(Local local)
02221     {
02222         TypeVariable result = (TypeVariable) typeVariableHashtable.get(local);
02223 
02224         if(result == null)
02225         {
02226             result = new TypeVariable(local);
02227 //            System.out.println(local + ": " + result.getEcrId());
02228         }
02229 
02230         return result;
02231     }
02232     /** Get type variable for the given  SootClass. **/
02233     TypeVariable getTypeVariable(SootClass sClass)
02234     {
02235         return getTypeVariable(classHierarchy.getTypeNode(RefType.v(sClass.getName())));
02236     }
02237     /** Get type variable for the given type. **/
02238     TypeVariable getTypeVariable(Type type)
02239     {
02240         return getTypeVariable(classHierarchy.getTypeNode(type));
02241     }
02242     /** Merge the given type variable with all its ancestors and descentants. **/
02243     private boolean mergeAll(TypeVariable var)
02244     {
02245         TypeVariable[] parents = var.getEcrParents();
02246         TypeVariable[] children = var.getEcrChildren();
02247         boolean changed = true;
02248         boolean modif = false;
02249 
02250         while(changed)
02251         {
02252             changed = false;
02253 
02254             for(int i = 0; i < parents.length; i++)
02255             {
02256                 if(parents[i].ecr().arrayDepth == var.ecr().arrayDepth)
02257                 {
02258                     modif = true;
02259                     changed = true;
02260                     var.ecrUnion(parents[i]);
02261                 }
02262             }
02263 
02264             for(int i = 0; i < children.length; i++)
02265             {
02266                 if(children[i].ecr().arrayDepth == var.ecr().arrayDepth)
02267                 {
02268                     modif = true;
02269                     changed = true;
02270                     var.ecrUnion(children[i]);
02271                 }
02272             }
02273 
02274             parents = var.getEcrParents();
02275             children = var.getEcrChildren();
02276         }
02277 
02278         return modif;
02279     }
02280     private void mergeBaseTypeArrays()
02281     {
02282         boolean changed;
02283 
02284         do
02285         {
02286           changed = false;
02287 
02288           for(Enumeration e = typeVariableInstances.elements(); e.hasMoreElements();)
02289           {
02290             TypeVariable var = (TypeVariable) e.nextElement();
02291 
02292             if((var == var.ecr()) &&
02293                 (var.getEcrTypeNode() != null) &&
02294                 (var.getEcrTypeNode().getType() instanceof ArrayType))
02295             {
02296                 ArrayType type = (ArrayType) var.getEcrTypeNode().getType();
02297 
02298                 if(!(type.baseType instanceof RefType))
02299                 {
02300                     if(mergeAll(var))
02301                     {
02302                         changed = true;
02303                     }
02304                 }
02305             }
02306           }
02307         } while(changed);
02308     }
02309     /** Propagate array constraints to base elements, so that the typing problem is
02310         simplified. **/
02311     private void propagateArrayConstraints()
02312     {
02313         computeArrayDepths();
02314 //        debug();
02315         propagateConstrains();
02316 //        debug();
02317         mergeBaseTypeArrays();
02318     }
02319     private void propagateConstrains()
02320     {
02321         for(Enumeration e = typeVariableInstances.elements(); e.hasMoreElements();)
02322         {
02323             TypeVariable var = (TypeVariable) e.nextElement();
02324 
02325             if(var == var.ecr())
02326             {
02327                 if(var.isArrayOf == null)
02328                 {
02329                     if(var.arrayDepth == 0)
02330                     {
02331                         var.base = var;
02332                     }
02333                     else
02334                     {
02335                         var.base = new TypeVariable();
02336                         var.base.base = var.base;
02337                     }
02338 
02339                     LinkedList workList = new LinkedList();
02340                     workList.add(var);
02341 
02342                     while(workList.size() > 0)
02343                     {
02344                         TypeVariable tv = (TypeVariable) workList.removeFirst();
02345 
02346                         int[] elements = tv.isElementOf.elements();
02347                         for(int i = 0; i < elements.length; i++)
02348                         {
02349                             TypeVariable array =
02350                                 ((TypeVariable) typeVariableInstances.
02351                                 elementAt(elements[i])).ecr();
02352                             array.base = var.base;
02353                             workList.add(array);
02354                         }
02355                     }
02356                 }
02357             }
02358         }
02359 
02360         for(Enumeration e = typeVariableInstances.elements(); e.hasMoreElements();)
02361         {
02362             TypeVariable var = (TypeVariable) e.nextElement();
02363 
02364             if(var == var.ecr())
02365             {
02366                 int[] elements = var.parents.elements();
02367                 for(int i = 0; i < elements.length; i++)
02368                 {
02369                     TypeVariable parent =
02370                         (TypeVariable) typeVariableInstances.elementAt(elements[i]);
02371 
02372                     if(parent.arrayDepth == var.arrayDepth)
02373                     {
02374                         var.base.ecrAddParent(parent.base);
02375                     }
02376                     else
02377                     {
02378                         parent.base.ecrAddChild(getTypeVariable(
02379                             RefType.v("java.lang.Cloneable")));
02380                     }
02381                 }
02382 
02383                 if(var.arrayDepth != 0)
02384                 {
02385                     unresolvedTypeVariables.clear(var.id);
02386                 }
02387             }
02388         }
02389     }
02390     /** Remove a parent if it is an ancestor of another parent. **/
02391     private void removeIndirectRelations()
02392     {
02393         LinkedList workList = new LinkedList();
02394         workList.addLast(getTypeVariable(RefType.v("java.lang.Object")));
02395         IntSet processed = new IntSet();
02396 
02397         while(workList.size() != 0)
02398         {
02399             TypeVariable var = (TypeVariable) workList.removeFirst();
02400 
02401             var.removeEcrIndirectRelations();
02402             processed.set(var.getEcrId());
02403 
02404             TypeVariable[] children = var.getEcrChildren();
02405             for(int i = 0; i < children.length; i++)
02406             {
02407                 IntSet temp = children[i].getEcrParentIds();
02408                 temp.and(processed);
02409                 if(temp.equals(children[i].getEcrParentIds()))
02410                 {
02411                     workList.addLast(children[i]);
02412                 }
02413             }
02414         }
02415     }
02416     private void removeRelationsBetweenNonEcrs()
02417     {
02418         for(Enumeration e = typeVariableInstances.elements(); e.hasMoreElements();)
02419         {
02420             TypeVariable var = (TypeVariable) e.nextElement();
02421 
02422             if((var != var.ecr()) ||
02423                 (var.arrayDepth != 0))
02424             {
02425                 var.parents = new IntSet();
02426                 var.children = new IntSet();
02427             }
02428         }
02429     }
02430     /** Do the exponential search of a solution. This is an NP-Complete problem. **/
02431     private boolean resolveComplexRelations()
02432     {
02433         if(unresolvedTypeVariables.size() == 0)
02434         {
02435             return true;
02436         }
02437 
02438         final TypeVariable[] ecrInstances;
02439         {
02440             Vector ecrs = new Vector();
02441             TypeVariable nullVar = null;
02442             for(Enumeration e = typeVariableInstances.elements(); e.hasMoreElements();)
02443             {
02444                 TypeVariable var = (TypeVariable) e.nextElement();
02445                 if((var.ecr() == var) && (var.getEcrTypeNode() != null))
02446                 {
02447                     if(var.getEcrTypeNode().getType().equals(NullType.v()))
02448                     {
02449                         nullVar = var;
02450                     }
02451                     else
02452                     {
02453                         ecrs.addElement(var);
02454                     }
02455                 }
02456             }
02457 
02458             // Make sure that *null* is tried last.
02459             if(nullVar != null)
02460             {
02461                 ecrs.addElement(nullVar);
02462             }
02463 
02464             ecrInstances = new TypeVariable[ecrs.size()];
02465             int index = 0;
02466             for(Enumeration e = ecrs.elements(); e.hasMoreElements();)
02467             {
02468                 TypeVariable var = (TypeVariable) e.nextElement();
02469                 ecrInstances[index++] = var;
02470             }
02471         }
02472 
02473         final int[] elements;
02474         {
02475             IntSet processed = new IntSet();
02476             LinkedList processedList = new LinkedList();
02477 
02478             while(!processed.equals(unresolvedTypeVariables))
02479             {
02480                 IntSet unprocessed = (IntSet) unresolvedTypeVariables.clone();
02481                 unprocessed.xor(processed);
02482                 int[] unprocessedElements = unprocessed.elements();
02483 
02484                 for(int i = 0; i < unprocessedElements.length; i++)
02485                 {
02486                     TypeVariable var =
02487                         (TypeVariable) typeVariableInstances.elementAt(unprocessedElements[i]);
02488 
02489                     if((!var.isEcrArray()) ||
02490                         processed.get(var.getEcrIsArrayOf().getEcrId()) ||
02491                         (!unresolvedTypeVariables.get(var.getEcrIsArrayOf().getEcrId())))
02492                     {
02493                         processed.set(var.getEcrId());
02494                         processedList.add(var);
02495                     }
02496                 }
02497             }
02498 
02499             elements = new int[processedList.size()];
02500             int index = 0;
02501             for(Iterator i = processedList.iterator(); i.hasNext();)
02502             {
02503                 elements[index++] = ((TypeVariable) i.next()).getEcrId();
02504             }
02505         }
02506 
02507         class RecursiveFunction
02508         {
02509             int index = 0;
02510 
02511             public boolean resolve()
02512             {
02513                 if(index == elements.length)
02514                 {
02515                     return true;
02516                 }
02517 
02518                 TypeVariable var =
02519                     (TypeVariable) typeVariableInstances.elementAt(elements[index++]);
02520 
02521                 for(int i = 0; i < ecrInstances.length; i++)
02522                 {
02523                     if(var.setEcrTypeNode(ecrInstances[i].getEcrTypeNode()))
02524                     {
02525                         if(resolve())
02526                         {
02527                             return true;
02528                         }
02529                         var.unsetEcrTypeNode();
02530                     }
02531                 }
02532                 index--;
02533 
02534                 return false;
02535             }
02536         }
02537 
02538         return new RecursiveFunction().resolve();
02539     }
02540     /** Resolve single relations.
02541         <P> <UL> <LI> No Parent -> "java.lang.Object"
02542         <LI> No Child -> "*null*"
02543         <LI> One parent -> merge with parent
02544         <LI> One child -> merge with child
02545         <UL> **/
02546     private boolean resolveSingleRelations()
02547     {
02548         boolean modified = false;
02549 
02550         int[] elements = unresolvedTypeVariables.elements();
02551         for(int i = 0; i < elements.length; i++)
02552         {
02553             TypeVariable var = (TypeVariable) typeVariableInstances.elementAt(elements[i]);
02554 
02555             if(var.getEcrTypeNode() == null)
02556             {
02557                 TypeVariable[] parents = var.getEcrParents();
02558                 TypeVariable[] children = var.getEcrChildren();
02559 
02560                 if(children.length == 1 && children[0] != getTypeVariable(NullType.v()))
02561                 {
02562                     modified = true;
02563                     var.ecrUnion(children[0]);
02564                 }
02565                 else if(parents.length == 1)
02566                 {
02567                     modified = true;
02568                     var.ecrUnion(parents[0]);
02569                 }
02570                 else if(parents.length == 0)
02571                 {
02572                     TypeVariable var2 = getTypeVariable(RefType.v("java.lang.Object"));
02573                     modified = true;
02574                     var.ecrUnion(var2);
02575                 }
02576                 else if(children.length == 0)
02577                 {
02578                     TypeVariable var2 = getTypeVariable(NullType.v());
02579                     modified = true;
02580                     var.ecrUnion(var2);
02581                 }
02582                 else if(children.length == 1)
02583                 {
02584                     modified = true;
02585                     var.ecrUnion(children[0]);
02586                 }
02587             }
02588         }
02589 
02590         return modified;
02591     }
02592 }

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