From 58bba37f798b8e926981ed1f2b9d851e39c8b34c Mon Sep 17 00:00:00 2001 From: Evan Battaglia Date: Tue, 19 Feb 2008 11:59:13 -0800 Subject: [PATCH] WALA bugfix patch v1.1.2 local changes --- Svelte/README | 3 + ...WALA-bugfixes-200802191150-against-v1.1.2.patch | 693 +++++++++++++++++++++ 2 files changed, 696 insertions(+) create mode 100644 Svelte/README create mode 100644 Svelte/WALA-bugfixes-200802191150-against-v1.1.2.patch diff --git a/Svelte/README b/Svelte/README new file mode 100644 index 0000000..3fd4ffb --- /dev/null +++ b/Svelte/README @@ -0,0 +1,3 @@ +Svelte is built upon WALA v1.1.2 (r2484), with eclipse/ directory from SVN incubator directory from r2489. +In addition, there are necessary bugfixes/workarounds for WALA v1.1.2 given in WALA-bugfixes-yyyymmddhhmm-against-v1.1.2.patch + diff --git a/Svelte/WALA-bugfixes-200802191150-against-v1.1.2.patch b/Svelte/WALA-bugfixes-200802191150-against-v1.1.2.patch new file mode 100644 index 0000000..5e79034 --- /dev/null +++ b/Svelte/WALA-bugfixes-200802191150-against-v1.1.2.patch @@ -0,0 +1,693 @@ +diff --git a/com.ibm.wala.cast.java.test/src/com/ibm/wala/cast/java/test/JavaIRTests.java b/com.ibm.wala.cast.java.test/src/com/ibm/wala/cast/java/test/JavaIRTests.java +index 691baf7..05489ef 100644 +--- a/com.ibm.wala.cast.java.test/src/com/ibm/wala/cast/java/test/JavaIRTests.java ++++ b/com.ibm.wala.cast.java.test/src/com/ibm/wala/cast/java/test/JavaIRTests.java +@@ -14,6 +14,7 @@ + package com.ibm.wala.cast.java.test; + + import java.io.File; ++import java.util.ArrayList; + import java.util.Arrays; + import java.util.Collection; + import java.util.Iterator; +@@ -25,6 +26,7 @@ import junit.framework.Assert; + import com.ibm.wala.cast.java.client.JavaSourceAnalysisEngine; + import com.ibm.wala.cast.java.ipa.slicer.AstJavaSlicer; + import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl; ++import com.ibm.wala.cast.java.ssa.EnclosingObjectReference; + import com.ibm.wala.classLoader.IClass; + import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil; + import com.ibm.wala.core.tests.slicer.SlicerTest; +@@ -35,6 +37,8 @@ import com.ibm.wala.ipa.callgraph.CGNode; + import com.ibm.wala.ipa.callgraph.CallGraph; + import com.ibm.wala.ipa.callgraph.Entrypoint; + import com.ibm.wala.ipa.callgraph.impl.Util; ++import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; ++import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey; + import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; + import com.ibm.wala.ipa.cha.IClassHierarchy; + import com.ibm.wala.ipa.slicer.SDG; +@@ -374,6 +378,94 @@ public class JavaIRTests extends IRTests { + }), true); + } + ++ public void testInnerClassA() { ++ Pair x = runTest(singleTestSrc(), rtJar, simpleTestEntryPoint(), new ArrayList(), true); ++ ++ // can't do an IRAssertion() -- we need the pointer analysis ++ ++ CallGraph cg = (CallGraph) x.fst; ++ PointerAnalysis pa = (PointerAnalysis) x.snd; ++ ++ Iterator iter = cg.iterator(); ++ while ( iter.hasNext() ) { ++ CGNode n = iter.next(); ++ ++ // assume in the test we have one enclosing instruction for each of the methods here. ++ String methodSigs[] = { "InnerClassA$AB.getA_X_from_AB()I", ++ "InnerClassA$AB.getA_X_thru_AB()I", ++ "InnerClassA$AB$ABSubA.getA_X()I", ++ "InnerClassA$AB$ABA$ABAA.getABA_X()I", ++ "InnerClassA$AB$ABA$ABAA.getA_X()I", ++ "InnerClassA$AB$ABA$ABAB.getABA_X()I", ++ "InnerClassA$AB$ABSubA$ABSubAA.getABA_X()I", ++ "InnerClassA$AB$ABSubA$ABSubAA.getA_X()I", }; ++ ++ // each type suffixed by "," ++ String ikConcreteTypeStrings[ ]= { ++ "LInnerClassA,", ++ "LInnerClassA,", ++ "LInnerClassA,", ++ "LInnerClassA$AB$ABSubA,LInnerClassA$AB$ABA,", ++ "LInnerClassA,", ++ "LInnerClassA$AB$ABA,", ++ "LInnerClassA$AB$ABSubA,", ++ "LInnerClassA,", ++ }; ++ ++ Assert.assertTrue ( "Buggy test", methodSigs.length == ikConcreteTypeStrings.length ); ++ for ( int i = 0; i < methodSigs.length; i++ ) { ++ if ( n.getMethod().getSignature().equals(methodSigs[i]) ) { ++ // find enclosing instruction ++ for ( SSAInstruction instr: n.getIR().getInstructions() ) { ++ if ( instr instanceof EnclosingObjectReference ) { ++ String allIks = ""; ++ for (InstanceKey ik: pa.getPointsToSet(new LocalPointerKey(n,instr.getDef()))) ++ allIks += ik.getConcreteType().getName() +","; ++ System.out.printf("in method %s, got ik %s\n", methodSigs[i], allIks); ++ ++ Assert.assertTrue("assertion failed: expecting ik " + ikConcreteTypeStrings[i] + " in method " + methodSigs[i] + ", got " + allIks + "\n", ++ allIks.equals(ikConcreteTypeStrings[i])); ++ ++ break; ++ } ++ } ++ } ++ } ++ } ++ ++ ++ } ++ ++ public void testInnerClassSuper() { ++ Pair x = runTest(singleTestSrc(), rtJar, simpleTestEntryPoint(), new ArrayList(), true); ++ ++ // can't do an IRAssertion() -- we need the pointer analysis ++ ++ CallGraph cg = (CallGraph) x.fst; ++ PointerAnalysis pa = (PointerAnalysis) x.snd; ++ ++ Iterator iter = cg.iterator(); ++ while ( iter.hasNext() ) { ++ CGNode n = iter.next(); ++ if ( n.getMethod().getSignature().equals("LInnerClassSuper$SuperOuter.test()V") ) { ++ // find enclosing instruction ++ for ( SSAInstruction instr: n.getIR().getInstructions() ) { ++ if ( instr instanceof EnclosingObjectReference ) { ++ String allIks = ""; ++ for (InstanceKey ik: pa.getPointsToSet(new LocalPointerKey(n,instr.getDef()))) ++ allIks += ik.getConcreteType().getName() +","; ++ Assert.assertTrue("assertion failed: expecting ik \"LSub,\" in method, got \"" + allIks + "\"\n", ++ allIks.equals("LSub,")); ++ ++ break; ++ } ++ } ++ } ++ } ++ ++ ++ } ++ + public void testLocalClass() { + runTest(singleTestSrc(), rtJar, simpleTestEntryPoint(), Arrays.asList( + +diff --git a/com.ibm.wala.cast.java.test/src/com/ibm/wala/cast/java/test/JavaOneContainerIRTests.java b/com.ibm.wala.cast.java.test/src/com/ibm/wala/cast/java/test/JavaOneContainerIRTests.java +new file mode 100644 +index 0000000..de1024f +--- /dev/null ++++ b/com.ibm.wala.cast.java.test/src/com/ibm/wala/cast/java/test/JavaOneContainerIRTests.java +@@ -0,0 +1,68 @@ ++/****************************************************************************** ++ * Copyright (c) 2002 - 2006 IBM Corporation. ++ * All rights reserved. This program and the accompanying materials ++ * are made available under the terms of the Eclipse Public License v1.0 ++ * which accompanies this distribution, and is available at ++ * http://www.eclipse.org/legal/epl-v10.html ++ * ++ * Contributors: ++ * IBM Corporation - initial API and implementation ++ *****************************************************************************/ ++/* ++ * Created on Oct 21, 2005 ++ */ ++package com.ibm.wala.cast.java.test; ++ ++import java.io.File; ++import java.util.ArrayList; ++ ++import com.ibm.wala.cast.java.client.JavaSourceAnalysisEngine; ++import com.ibm.wala.cast.java.client.impl.ZeroOneContainerCFABuilderFactory; ++import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil; ++import com.ibm.wala.eclipse.util.EclipseProjectPath; ++import com.ibm.wala.ipa.callgraph.AnalysisCache; ++import com.ibm.wala.ipa.callgraph.AnalysisOptions; ++import com.ibm.wala.ipa.callgraph.AnalysisScope; ++import com.ibm.wala.ipa.callgraph.CallGraphBuilder; ++import com.ibm.wala.ipa.callgraph.Entrypoint; ++import com.ibm.wala.ipa.callgraph.impl.Util; ++import com.ibm.wala.ipa.cha.IClassHierarchy; ++ ++public class JavaOneContainerIRTests extends IRTests { ++ public JavaOneContainerIRTests(String name) { ++ super(name); ++ } ++ ++ protected JavaSourceAnalysisEngine getAnalysisEngine(final String[] mainClassDescriptors) { ++ JavaSourceAnalysisEngine engine = new JavaSourceAnalysisEngine() { ++ @Override ++ protected CallGraphBuilder getCallGraphBuilder(IClassHierarchy cha, ++ AnalysisOptions options, AnalysisCache cache) { ++ return new ZeroOneContainerCFABuilderFactory().make(options, cache, cha, scope, false); ++ } ++ ++ protected Iterable makeDefaultEntrypoints(AnalysisScope scope, IClassHierarchy cha) { ++ return Util.makeMainEntrypoints(EclipseProjectPath.SOURCE_REF, cha, mainClassDescriptors); ++ } ++ }; ++ engine.setExclusionsFile(CallGraphTestUtil.REGRESSION_EXCLUSIONS); ++ return engine; ++ } ++ ++ protected String singleInputForTest() { ++ return getName().substring(4) + ".java"; ++ } ++ ++ protected String singleInputForTestNoExt() { ++ return getName().substring(4); ++ } ++ ++ protected String singlePkgInputForTest(String pkgName) { ++ return pkgName + File.separator + getName().substring(4) + ".java"; ++ } ++ ++ public void testInnerClassLexicalReads() { ++ // throws UnimplementedError on failure (expecting ScopeMappingInstanceKeys but not generating them) ++ runTest(singleTestSrc(), rtJar, simpleTestEntryPoint(), new ArrayList(), true); ++ } ++} +diff --git a/com.ibm.wala.cast.java.test/testSrc/InnerClassA.java b/com.ibm.wala.cast.java.test/testSrc/InnerClassA.java +new file mode 100644 +index 0000000..f51541a +--- /dev/null ++++ b/com.ibm.wala.cast.java.test/testSrc/InnerClassA.java +@@ -0,0 +1,125 @@ ++// other stranger test cases ++// ++// combininations of: ++// o.new() form ++// function calls ++// getting enclosings from one AND multiple levels up ++// new Foo() which requires an enclosing instruction before (ie calling new Inner() from ReallyInner() ++// invariants and non-invariants (immediate 'new' in that function) ++// subclasses ++ ++public class InnerClassA { ++ int a_x; ++ ++ public static void main(String args[]) { ++ // prints out 5 5 9 7 5 5 7 5 7 5 ++ InnerClassA a = new InnerClassA(); ++ AA aa = a.new AA(); ++ AB ab = aa.makeAB(); ++ a.a_x = 5; ++ ++ // tests ++ int myx = ab.getA_X_from_AB(); ++ System.out.println(myx); // 5 ++ int myx2 = ab.getA_X_thru_AB(); ++ System.out.println(myx2); // 5 ++ ++ aa.doSomeCrazyStuff(); ++ } ++ ++ public int getA_X() { ++ return a_x; ++ } ++ ++ class AA { ++ int a2a_var; ++ ++ public AB makeAB() { ++ return new AB(); ++ } ++ ++ public void doSomeCrazyStuff() { ++ AB ab = new AB(); ++ AB.ABSubA absuba = ab.new ABSubA(); ++ absuba.aba_x = 7; ++ AB.ABA.ABAA abaa2 = ab.new ABA().new ABAA(); // just used to add ABA instance key in ABAA.getABA_X() ++ ++ AB.ABA aba = ab.new ABA(); ++ aba.aba_x = 9; ++ AB.ABA.ABAB abab = aba.new ABAB(); ++ System.out.println(abab.getABA_X()); // 9 ++ ++ AB.ABA.ABAA abaa = absuba.new ABAA(); ++ int myaba_x = abaa.getABA_X(); ++ int mya_x = abaa.getA_X(); ++ System.out.println(myaba_x); // 7 ++ System.out.println(mya_x); // 5 ++ ++ ++ doMoreWithABSubA(absuba); ++ } ++ ++ private void doMoreWithABSubA(InnerClassA.AB.ABSubA absuba) { ++ System.out.println(absuba.getA_X()); // 5 ++ ++ AB.ABSubA.ABSubAA absubaa = absuba.new ABSubAA(); ++ int myaba_x2 = absubaa.getABA_X(); ++ int mya_x2 = absubaa.getA_X(); ++ System.out.println(myaba_x2); // 7 ++ System.out.println(mya_x2); // 5 ++ // TODO Auto-generated method stub ++ ++ AB.ABA.ABAA abaa = absubaa.makeABAA(); ++ int myaba_x3 = abaa.getABA_X(); ++ int mya_x3 = abaa.getA_X(); ++ System.out.println(myaba_x3); // 7 ++ System.out.println(mya_x3); // 5 ++ ++ } ++ } ++ ++ class AB { ++ public int getA_X_from_AB() { ++ return a_x; // CHECK enclosing is an A ++ } ++ ++ public int getA_X_thru_AB() { ++ return getA_X(); // CHECK enclosing is an A ++ } ++ ++ class ABA { ++ int aba_x; ++ class ABAA { ++ int getABA_X() { ++ return aba_x; // CHECK enclosing is an ABA or ABSubA ++ } ++ int getA_X() { ++ return a_x; // CHECK enclosing is an A ++ } ++ } ++ class ABAB { ++ int getABA_X() { ++ return aba_x; // CHECK enclosing is an ABA ++ } ++ } ++ } ++ ++ class ABSubA extends ABA { ++ class ABSubAA { ++ int getABA_X() { ++ return aba_x; // CHECK enclosing is an ABSubA ++ } ++ int getA_X() { ++ return a_x; // CHECK enclosing is an A ++ } ++ ABA.ABAA makeABAA() { ++ return new ABAA(); // this new instruction requires us to know that ABSubA is a subclass of ABA. ++ // thus when we call getABA_X() on the result, it will need to find a EORK(this site,class ABA) -> THIS (of type ABSubAA) ++ } ++ } ++ int getA_X() { ++ return a_x; // CHECK enclosing is an A ++ } ++ } ++ } ++} +diff --git a/com.ibm.wala.cast.java.test/testSrc/InnerClassLexicalReads.java b/com.ibm.wala.cast.java.test/testSrc/InnerClassLexicalReads.java +new file mode 100644 +index 0000000..6d15249 +--- /dev/null ++++ b/com.ibm.wala.cast.java.test/testSrc/InnerClassLexicalReads.java +@@ -0,0 +1,47 @@ ++interface IntConstant { ++ int getConstant(); ++} ++ ++public class InnerClassLexicalReads { ++ ++ /* ++ * CAst Instructions: ++ * 2 v3 = new $9$9>@2[9:9] -> [13:3] ++ * 3 invokespecial < Source, LInnerClassLexicalReads/makeIntConstant(I)LIntConstant;/$9$9, ()V > v3 @3 exception:v5[9:9] -> [13:3] ++ * 4 return v3 [9:2] -> [13:4] ++ */ ++ public static IntConstant makeIntConstant(int x) { ++ final int y = x * x; ++ return new IntConstant() { ++// CAst CONSTRUCTOR Instructions: ++// 1 invokespecial < Source, Ljava/lang/Object, ()V > v1 @1 exception:v3[20:9] -> [32:3] ++ ++ /* ++ * CAst Instructions: ++ * 0 v2:com.ibm.wala.ssa.SymbolTable$1@16b18b6 = lexical:y@LInnerClassLexicalReads/makeIntConstant(I)LIntConstant; ++ * 1 return v2:com.ibm.wala.ssa.SymbolTable$1@16b18b6[11:4] -> [11:13] ++ */ ++ public int getConstant() { ++ return y; ++ } ++ }; ++ } ++ ++ ++ /* ++ * CAst Instructions: ++ * 1 v2:com.ibm.wala.ssa.SymbolTable$1@4272b2 = invokestatic < Source, LInnerClassLexicalReads, makeIntConstant(I)LIntConstant; > v3:#123 @1 exception:v4[17:19] -> [17:39] ++ * 2 v7 = getstatic < Source, Ljava/lang/System, out, >[18:2] -> [18:12] ++ * 3 v8 = invokeinterface < Source, LIntConstant, getConstant()I > v2:com.ibm.wala.ssa.SymbolTable$1@4272b2 @3 exception:v9[18:21] -> [18:37] ++ * 4 invokevirtual < Source, Ljava/io/PrintStream, println(I)V > v7,v8 @4 exception:v10[18:2] -> [18:38] ++ */ ++ public static void main(String args[]) { ++ InnerClassLexicalReads ignored = new InnerClassLexicalReads(); // call this just to make reachable (test checks for unreachable methods) ++ int foo = 5; ++ int haha = foo * foo; ++ IntConstant ic = makeIntConstant(haha); ++ System.out.println(ic.getConstant()); ++ int x = ic.getConstant(); ++ System.out.println(x); ++ } ++} +diff --git a/com.ibm.wala.cast.java.test/testSrc/InnerClassSuper.java b/com.ibm.wala.cast.java.test/testSrc/InnerClassSuper.java +new file mode 100644 +index 0000000..d61a986 +--- /dev/null ++++ b/com.ibm.wala.cast.java.test/testSrc/InnerClassSuper.java +@@ -0,0 +1,19 @@ ++public class InnerClassSuper { ++ int x = 5; ++ class SuperOuter { ++ public void test() { ++ System.out.println(x); ++ } ++ } ++ public static void main(String args[]) { ++ new Sub().new SubInner(); ++ } ++} ++class Sub extends InnerClassSuper { ++ class SubInner { ++ public SubInner() { ++ InnerClassSuper.SuperOuter so = new InnerClassSuper.SuperOuter(); ++ so.test(); ++ } ++ } ++} +\ No newline at end of file +diff --git a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/callgraph/AstJavaSSAPropagationCallGraphBuilder.java b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/callgraph/AstJavaSSAPropagationCallGraphBuilder.java +index 94993c1..b94db65 100644 +--- a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/callgraph/AstJavaSSAPropagationCallGraphBuilder.java ++++ b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/callgraph/AstJavaSSAPropagationCallGraphBuilder.java +@@ -16,6 +16,7 @@ import com.ibm.wala.cast.java.analysis.typeInference.AstJavaTypeInference; + import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl.JavaClass; + import com.ibm.wala.cast.java.ssa.AstJavaInstructionVisitor; + import com.ibm.wala.cast.java.ssa.AstJavaInvokeInstruction; ++import com.ibm.wala.cast.java.ssa.AstJavaNewEnclosingInstruction; + import com.ibm.wala.cast.java.ssa.EnclosingObjectReference; + import com.ibm.wala.classLoader.IClass; + import com.ibm.wala.fixedpoint.impl.UnaryOperator; +@@ -182,6 +183,14 @@ public class AstJavaSSAPropagationCallGraphBuilder extends AstSSAPropagationCall + super(builder, node); + } + ++ /** ++ * For each of objKey's instance keys ik, adds the constraint lvalKey = EORK(ik,cls), ++ * where EORK(ik,cls) will be made equivalent to the actual enclosing class by ++ * the handleNew() function below. ++ * @param lvalKey ++ * @param cls ++ * @param objKey ++ */ + private void handleEnclosingObject(final PointerKey lvalKey, final IClass cls, final PointerKey objKey) { + SymbolTable symtab = ir.getSymbolTable(); + int objVal; +@@ -246,12 +255,33 @@ public class AstJavaSSAPropagationCallGraphBuilder extends AstSSAPropagationCall + if (iKey != null) { + IClass klass = iKey.getConcreteType(); + ++ // in the case of a AstJavaNewEnclosingInstruction (a new instruction like outer.new Bla()), ++ // we may need to record the instance keys if the pointer key outer is invariant (and thus implicit) ++ InstanceKey enclosingInvariantKeys[] = null; ++ + if (klass instanceof JavaClass) { +- IClass enclosingClass = ((JavaClass) klass).getEnclosingClass(); ++ IClass enclosingClass = ((JavaClass) klass).getEnclosingClass(); // the immediate enclosing class. + if (enclosingClass != null) { + IClass currentCls = node.getMethod().getDeclaringClass(); +- PointerKey objKey = getPointerKeyForLocal(1); +- boolean needIndirection = false; ++ PointerKey objKey; ++ ++ if ( instruction instanceof AstJavaNewEnclosingInstruction ) { ++ ++ ++ int enclosingVal = ((AstJavaNewEnclosingInstruction) instruction).getEnclosing(); ++ SymbolTable symtab = ir.getSymbolTable(); ++ ++ // pk 'outer' is invariant, which means it's implicit, so can't add a constraint with the pointer key. ++ // we should just add constraints directly to the instance keys (below) ++ if ( contentsAreInvariant(symtab, du, enclosingVal) ) ++ enclosingInvariantKeys = getInvariantContents(enclosingVal); ++ ++ // what happens if objKey is implicit but the contents aren't invariant?! (it this possible?) big trouble! ++ ++ objKey = getPointerKeyForLocal(enclosingVal); ++ } ++ else ++ objKey = getPointerKeyForLocal(1); + + Trace.println("class is " + klass + ", enclosing is " + enclosingClass + ", method is " + node.getMethod()); + +@@ -259,31 +289,30 @@ public class AstJavaSSAPropagationCallGraphBuilder extends AstSSAPropagationCall + return; + } + +- while (!getClassHierarchy().isSubclassOf(currentCls, enclosingClass)) { +- Assertions._assert(currentCls instanceof JavaClass); ++ currentCls = enclosingClass; ++ ++ PointerKey x = new EnclosingObjectReferenceKey(iKey, currentCls); ++ if ( enclosingInvariantKeys != null ) ++ for ( InstanceKey obj: enclosingInvariantKeys ) ++ system.newConstraint(x, obj); ++ else ++ system.newConstraint(x, assignOperator, objKey); ++ ++ // If the immediate inclosing class is not a top-level class, we must make EORKs for all enclosing classes up to the top level. ++ // for instance, if we have "D d = c.new D()", and c is of type A$B$C, methods in D may reference variables and functions from ++ // A, B, and C. Therefore we must also make the links from EORK(allocsite of d,enc class B) and EORK(allocsite of d,en class A). ++ // We do this by getting the enclosing class of C and making a link from EORK(d,B) -> EORK(c,B), etc. ++ currentCls = ((JavaClass) currentCls).getEnclosingClass(); ++ while (currentCls != null) { ++ x = new EnclosingObjectReferenceKey(iKey, currentCls); // make EORK(d,B), EORK(d,A), etc. ++ handleEnclosingObject(x, currentCls, objKey); ++ // objKey is the pointer key representing the immediate inner class. ++ // handleEnclosingObject finds x's instance keys and for each one "ik" links x to EORK(ik,currentCls) ++ // thus, for currentCls=B, it will find the allocation site of c and make a link from EORK(d,B) to EORK(c,B) ++ + currentCls = ((JavaClass) currentCls).getEnclosingClass(); +- needIndirection = true; +- } +- +- while (enclosingClass != null) { +- PointerKey x = new EnclosingObjectReferenceKey(iKey, enclosingClass); +- if (needIndirection) { +- handleEnclosingObject(x, currentCls, objKey); +- Trace.println("at " + instruction + ": adding " + iKey + ", " + enclosingClass + " <-- " + objKey + ", " +- + currentCls); +- } else { +- system.newConstraint(x, assignOperator, objKey); +- Trace.println("at " + instruction + ": adding " + iKey + ", " + enclosingClass + " <-- " + objKey); +- } +- +- if (enclosingClass instanceof JavaClass) { +- needIndirection = true; +- enclosingClass = ((JavaClass) enclosingClass).getEnclosingClass(); +- currentCls = ((JavaClass) currentCls).getEnclosingClass(); +- } else { +- break; +- } + } ++ + } + } + } +diff --git a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/callgraph/AstJavaZeroOneContainerCFABuilder.java b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/callgraph/AstJavaZeroOneContainerCFABuilder.java +index cf12e87..d6d9b5e 100644 +--- a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/callgraph/AstJavaZeroOneContainerCFABuilder.java ++++ b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/callgraph/AstJavaZeroOneContainerCFABuilder.java +@@ -62,9 +62,9 @@ public class AstJavaZeroOneContainerCFABuilder extends AstJavaCFABuilder { + setContextInterpreter(contextInterpreter); + + ZeroXInstanceKeys zik = makeInstanceKeys(cha, options, contextInterpreter); +- setInstanceKeys(zik); ++ setInstanceKeys(new JavaScopeMappingInstanceKeys(cha, this, zik)); + +- ContextSelector CCS = makeContainerContextSelector(cha,(ZeroXInstanceKeys) getInstanceKeys()); ++ ContextSelector CCS = makeContainerContextSelector(cha,zik); + DelegatingContextSelector DCS = new DelegatingContextSelector(CCS, contextSelector); + setContextSelector(DCS); + } +diff --git a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ssa/AstJavaNewEnclosingInstruction.java b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ssa/AstJavaNewEnclosingInstruction.java +new file mode 100644 +index 0000000..45718e5 +--- /dev/null ++++ b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ssa/AstJavaNewEnclosingInstruction.java +@@ -0,0 +1,25 @@ ++package com.ibm.wala.cast.java.ssa; ++ ++import com.ibm.wala.classLoader.NewSiteReference; ++import com.ibm.wala.ssa.SSANewInstruction; ++ ++// A new instruction with an explicit outer class, i.e. "Inner inner = outer.new Inner();" ++public class AstJavaNewEnclosingInstruction extends SSANewInstruction { ++ ++ int enclosing; ++ ++ public AstJavaNewEnclosingInstruction(int result, NewSiteReference site, int enclosing) throws IllegalArgumentException { ++ super(result, site); ++ this.enclosing = enclosing; ++ } ++ ++ public int getEnclosing() { ++ return this.enclosing; ++ } ++ ++ public String toString() { ++ return super.toString() + " ENCLOSING v" + enclosing; ++ } ++ ++ ++} +diff --git a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/JavaCAst2IRTranslator.java b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/JavaCAst2IRTranslator.java +index 9d302ae..774eaaf 100644 +--- a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/JavaCAst2IRTranslator.java ++++ b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/JavaCAst2IRTranslator.java +@@ -19,6 +19,7 @@ import java.util.Iterator; + import com.ibm.wala.cast.ir.translator.AstTranslator; + import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl; + import com.ibm.wala.cast.java.ssa.AstJavaInvokeInstruction; ++import com.ibm.wala.cast.java.ssa.AstJavaNewEnclosingInstruction; + import com.ibm.wala.cast.java.ssa.EnclosingObjectReference; + import com.ibm.wala.cast.loader.AstMethod.DebuggingInformation; + import com.ibm.wala.cast.loader.AstMethod.LexicalInformation; +@@ -156,11 +157,14 @@ public class JavaCAst2IRTranslator extends AstTranslator { + NewSiteReference site = + NewSiteReference.make(context.cfg().getCurrentInstruction(), typeRef); + +- context.cfg().addInstruction( +- (arguments == null)? +- SSAInstructionFactory.NewInstruction(result, site): +- new SSANewInstruction(result, site, arguments)); +- ++ if ( newNode.getKind() == CAstNode.NEW_ENCLOSING ) { ++ context.cfg().addInstruction ( new AstJavaNewEnclosingInstruction(result, site, arguments[0])); ++ } else { ++ context.cfg().addInstruction( ++ (arguments == null)? ++ SSAInstructionFactory.NewInstruction(result, site): ++ new SSANewInstruction(result, site, arguments)); ++ } + processExceptions(newNode, context); + } + +diff --git a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/polyglot/PolyglotJava2CAstTranslator.java b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/polyglot/PolyglotJava2CAstTranslator.java +index f9f1222..17910ce 100644 +--- a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/polyglot/PolyglotJava2CAstTranslator.java ++++ b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/polyglot/PolyglotJava2CAstTranslator.java +@@ -746,7 +746,16 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst { + String tmpName = "ctor temp"; // this name is an illegal Java + // identifier + +- CAstNode newNode = makeNode(wc, fFactory, n, CAstNode.NEW, fFactory.makeConstant(newTypeRef)); ++ // new nodes with an explicit enclosing argument, e.g. "outer.new Inner()". They are mostly treated the same, except in JavaCAst2IRTranslator.doNewObject ++ CAstNode newNode; ++ Expr enclosing = n.qualifier(); ++ if ( enclosing != null ) { ++ CAstNode encNode = walkNodes(enclosing, wc); ++ newNode = makeNode(wc, fFactory, n, CAstNode.NEW_ENCLOSING, fFactory.makeConstant(newTypeRef), encNode); ++ } ++ else ++ newNode = makeNode(wc, fFactory, n, CAstNode.NEW, fFactory.makeConstant(newTypeRef)); ++ // end enclosing new stuff + + if (n.body() != null) + wc.addScopedEntity(newNode, anonClass); +diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java +index 381a8cf..711617c 100644 +--- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java ++++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java +@@ -128,7 +128,7 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory { + return base.getConcreteType(); + } + +- CGNode getDefiningNode(String definer) { ++ public CGNode getDefiningNode(String definer) { + return map.getDefiningNode(definer); + } + +diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java +index 1c41365..ec8cd1e 100644 +--- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java ++++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java +@@ -2610,8 +2610,8 @@ public abstract class AstTranslator extends CAstVisitor + int result = getValue(n); + CAstNode l = n.getChild(1); + CAstNode r = n.getChild(2); +- Assertions._assert(getValue(r) != -1, CAstPrinter.print(n)); +- Assertions._assert(getValue(l) != -1, CAstPrinter.print(n)); ++// Assertions._assert(getValue(r) != -1, CAstPrinter.print(n)); ++// Assertions._assert(getValue(l) != -1, CAstPrinter.print(n)); + + boolean mayBeInteger = handleBinaryOpThrow(n, n.getChild(0), context); + +diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/CAstNode.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/CAstNode.java +index 18bf26f..b420421 100644 +--- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/CAstNode.java ++++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/CAstNode.java +@@ -155,6 +155,9 @@ public interface CAstNode { + public static final int TYPE_LITERAL_EXPR = 127; + public static final int IS_DEFINED_EXPR = 128; + ++ // new nodes with an explicit enclosing argument, e.g. "outer.new Inner()". They are mostly treated the same, except in JavaCAst2IRTranslator.doNewObject ++ public static final int NEW_ENCLOSING = 129; ++ + // explicit lexical scopes + public static final int LOCAL_SCOPE = 200; + +diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/visit/CAstVisitor.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/visit/CAstVisitor.java +index 44f7055..e3ad94f 100644 +--- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/visit/CAstVisitor.java ++++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/visit/CAstVisitor.java +@@ -554,6 +554,7 @@ public abstract class CAstVisitor { + break; + } + ++ case CAstNode.NEW_ENCLOSING: + case CAstNode.NEW: { + if (visitor.visitNew(n, context, visitor)) + break; +diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/CAstPrinter.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/CAstPrinter.java +index 05ef170..ef226b7 100644 +--- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/CAstPrinter.java ++++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/CAstPrinter.java +@@ -71,6 +71,7 @@ public class CAstPrinter { + case CAstNode.IF_EXPR: return "IF_EXPR"; + case CAstNode.ANDOR_EXPR: return "ANDOR_EXPR"; + case CAstNode.NEW: return "NEW"; ++ case CAstNode.NEW_ENCLOSING: return "NEW_ENCLOSING"; + case CAstNode.OBJECT_LITERAL: return "LITERAL"; + case CAstNode.VAR: return "VAR"; + case CAstNode.OBJECT_REF: return "OBJECT_REF"; -- 2.11.4.GIT