+ return locTuple;
+ }
+
+ private boolean calculateCompositeLocationForLocalVar(FlowGraph flowGraph,
+ SSJavaLattice<String> methodLattice, MethodLocationInfo methodInfo, FlowNode flowNode) {
+
+ Set<FlowNode> inNodeSet = flowGraph.getIncomingFlowNodeSet(flowNode);
+ Set<FlowNode> reachableNodeSet = flowGraph.getReachableFlowNodeSet(flowNode);
+
+ Map<NTuple<Location>, Set<NTuple<Location>>> mapPrefixToIncomingLocTupleSet =
+ new HashMap<NTuple<Location>, Set<NTuple<Location>>>();
+
+ List<NTuple<Location>> prefixList = new ArrayList<NTuple<Location>>();
+
+ for (Iterator iterator = inNodeSet.iterator(); iterator.hasNext();) {
+ FlowNode inNode = (FlowNode) iterator.next();
+ NTuple<Location> inTuple = getLocationTuple(methodInfo, flowGraph, inNode);
+
+ if (inTuple.size() > 1) {
+ for (int i = 1; i < inTuple.size(); i++) {
+ NTuple<Location> prefix = inTuple.subList(0, i);
+ if (!prefixList.contains(prefix)) {
+ prefixList.add(prefix);
+ }
+ addPrefixMapping(mapPrefixToIncomingLocTupleSet, prefix, inTuple);
+ }
+ }
+ }
+
+ Collections.sort(prefixList, new Comparator<NTuple<Location>>() {
+ public int compare(NTuple<Location> arg0, NTuple<Location> arg1) {
+ int s0 = arg0.size();
+ int s1 = arg1.size();
+ if (s0 > s1) {
+ return -1;
+ } else if (s0 == s1) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+ });
+
+ // find out reachable nodes that have the longest common prefix
+ for (int i = 0; i < prefixList.size(); i++) {
+ NTuple<Location> curPrefix = prefixList.get(i);
+ Set<NTuple<Location>> reachableCommonPrefixSet = new HashSet<NTuple<Location>>();
+
+ for (Iterator iterator2 = reachableNodeSet.iterator(); iterator2.hasNext();) {
+ FlowNode reachableNode = (FlowNode) iterator2.next();
+ NTuple<Location> reachLocTuple = flowGraph.getLocationTuple(reachableNode);
+ if (reachLocTuple.startsWith(curPrefix)) {
+ reachableCommonPrefixSet.add(reachLocTuple);
+ }
+ }
+
+ if (!reachableCommonPrefixSet.isEmpty()) {
+ Set<NTuple<Location>> incomingCommonPrefixSet =
+ mapPrefixToIncomingLocTupleSet.get(curPrefix);
+
+ int idx = curPrefix.size();
+ NTuple<Location> element = incomingCommonPrefixSet.iterator().next();
+ Descriptor desc = element.get(idx).getDescriptor();
+
+ SSJavaLattice<String> lattice = getLattice(desc);
+ LocationInfo locInfo = getLocationInfo(desc);
+
+ CompositeLocation inferNode = methodInfo.getInferLocation(flowNode);
+ String nodeSymbol;
+ if (inferNode != null) {
+
+ } else {
+ String newLocSymbol = "Loc" + (SSJavaLattice.seed++);
+ inferNode = new CompositeLocation();
+ for (int locIdx = 0; locIdx < curPrefix.size(); locIdx++) {
+ inferNode.addLocation(curPrefix.get(locIdx));
+ }
+ inferNode.addLocation(new Location(desc, newLocSymbol));
+ methodInfo.mapFlowNodeToInferLocation(flowNode, inferNode);
+ if (flowNode.getDescTuple().size() == 1) {
+ // local variable case
+ modifyLocalLatticeAccrodingToNewlyAddedCompositeLocation(methodLattice, methodInfo,
+ inferNode, flowNode);
+ }
+ }
+
+ nodeSymbol = inferNode.get(inferNode.getSize() - 1).getLocIdentifier();
+
+ for (Iterator iterator = incomingCommonPrefixSet.iterator(); iterator.hasNext();) {
+ NTuple<Location> tuple = (NTuple<Location>) iterator.next();
+ Location loc = tuple.get(idx);
+ String higher = locInfo.getLocName(loc.getLocIdentifier());
+ lattice.addRelationHigherToLower(higher, nodeSymbol);
+ }
+
+ for (Iterator iterator = reachableCommonPrefixSet.iterator(); iterator.hasNext();) {
+ NTuple<Location> tuple = (NTuple<Location>) iterator.next();
+ Location loc = tuple.get(idx);
+ String lower = locInfo.getLocName(loc.getLocIdentifier());
+ lattice.addRelationHigherToLower(nodeSymbol, lower);
+ }
+
+ return true;
+ }
+
+ }
+
+ return false;
+
+ }
+
+ private void modifyLocalLatticeAccrodingToNewlyAddedCompositeLocation(
+ SSJavaLattice<String> methodLattice, MethodLocationInfo methodInfo,
+ CompositeLocation inferNode, FlowNode flowNode) {
+
+ Location localLocation = inferNode.get(0);
+ String newLocName = methodInfo.getLocName(localLocation.getLocIdentifier());
+ String oldLocName = methodInfo.getLocName(flowNode.getDescTuple().get(0).getSymbol());
+
+ methodInfo.mapDescSymbolToLocName(oldLocName, newLocName);
+ methodLattice.substituteLocation(oldLocName, newLocName);
+
+ }
+
+ public boolean isPrimitiveLocalVariable(FlowNode node) {
+ VarDescriptor varDesc = (VarDescriptor) node.getDescTuple().get(0);
+ return varDesc.getType().isPrimitive();
+ }
+
+ private SSJavaLattice<String> getLattice(Descriptor d) {
+ if (d instanceof MethodDescriptor) {
+ return getMethodLattice((MethodDescriptor) d);
+ } else {
+ return getFieldLattice((ClassDescriptor) d);
+ }