use JDT again
[eclipsethinslicer.git] / Svelte / WALA-bugfixes-200803061634-against-v1.1.2.patch
blobdde9798986e94f58eab2b6420a23f2a087e641c6
1 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
2 index 691baf7..05489ef 100644
3 --- a/com.ibm.wala.cast.java.test/src/com/ibm/wala/cast/java/test/JavaIRTests.java
4 +++ b/com.ibm.wala.cast.java.test/src/com/ibm/wala/cast/java/test/JavaIRTests.java
5 @@ -14,6 +14,7 @@
6 package com.ibm.wala.cast.java.test;
8 import java.io.File;
9 +import java.util.ArrayList;
10 import java.util.Arrays;
11 import java.util.Collection;
12 import java.util.Iterator;
13 @@ -25,6 +26,7 @@ import junit.framework.Assert;
14 import com.ibm.wala.cast.java.client.JavaSourceAnalysisEngine;
15 import com.ibm.wala.cast.java.ipa.slicer.AstJavaSlicer;
16 import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl;
17 +import com.ibm.wala.cast.java.ssa.EnclosingObjectReference;
18 import com.ibm.wala.classLoader.IClass;
19 import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil;
20 import com.ibm.wala.core.tests.slicer.SlicerTest;
21 @@ -35,6 +37,8 @@ import com.ibm.wala.ipa.callgraph.CGNode;
22 import com.ibm.wala.ipa.callgraph.CallGraph;
23 import com.ibm.wala.ipa.callgraph.Entrypoint;
24 import com.ibm.wala.ipa.callgraph.impl.Util;
25 +import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
26 +import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey;
27 import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
28 import com.ibm.wala.ipa.cha.IClassHierarchy;
29 import com.ibm.wala.ipa.slicer.SDG;
30 @@ -374,6 +378,94 @@ public class JavaIRTests extends IRTests {
31 }), true);
34 + public void testInnerClassA() {
35 + Pair x = runTest(singleTestSrc(), rtJar, simpleTestEntryPoint(), new ArrayList<IRAssertion>(), true);
37 + // can't do an IRAssertion() -- we need the pointer analysis
39 + CallGraph cg = (CallGraph) x.fst;
40 + PointerAnalysis pa = (PointerAnalysis) x.snd;
42 + Iterator<CGNode> iter = cg.iterator();
43 + while ( iter.hasNext() ) {
44 + CGNode n = iter.next();
46 + // assume in the test we have one enclosing instruction for each of the methods here.
47 + String methodSigs[] = { "InnerClassA$AB.getA_X_from_AB()I",
48 + "InnerClassA$AB.getA_X_thru_AB()I",
49 + "InnerClassA$AB$ABSubA.getA_X()I",
50 + "InnerClassA$AB$ABA$ABAA.getABA_X()I",
51 + "InnerClassA$AB$ABA$ABAA.getA_X()I",
52 + "InnerClassA$AB$ABA$ABAB.getABA_X()I",
53 + "InnerClassA$AB$ABSubA$ABSubAA.getABA_X()I",
54 + "InnerClassA$AB$ABSubA$ABSubAA.getA_X()I", };
56 + // each type suffixed by ","
57 + String ikConcreteTypeStrings[ ]= {
58 + "LInnerClassA,",
59 + "LInnerClassA,",
60 + "LInnerClassA,",
61 + "LInnerClassA$AB$ABSubA,LInnerClassA$AB$ABA,",
62 + "LInnerClassA,",
63 + "LInnerClassA$AB$ABA,",
64 + "LInnerClassA$AB$ABSubA,",
65 + "LInnerClassA,",
66 + };
68 + Assert.assertTrue ( "Buggy test", methodSigs.length == ikConcreteTypeStrings.length );
69 + for ( int i = 0; i < methodSigs.length; i++ ) {
70 + if ( n.getMethod().getSignature().equals(methodSigs[i]) ) {
71 + // find enclosing instruction
72 + for ( SSAInstruction instr: n.getIR().getInstructions() ) {
73 + if ( instr instanceof EnclosingObjectReference ) {
74 + String allIks = "";
75 + for (InstanceKey ik: pa.getPointsToSet(new LocalPointerKey(n,instr.getDef())))
76 + allIks += ik.getConcreteType().getName() +",";
77 + System.out.printf("in method %s, got ik %s\n", methodSigs[i], allIks);
79 + Assert.assertTrue("assertion failed: expecting ik " + ikConcreteTypeStrings[i] + " in method " + methodSigs[i] + ", got " + allIks + "\n",
80 + allIks.equals(ikConcreteTypeStrings[i]));
82 + break;
83 + }
84 + }
85 + }
86 + }
87 + }
90 + }
92 + public void testInnerClassSuper() {
93 + Pair x = runTest(singleTestSrc(), rtJar, simpleTestEntryPoint(), new ArrayList<IRAssertion>(), true);
95 + // can't do an IRAssertion() -- we need the pointer analysis
97 + CallGraph cg = (CallGraph) x.fst;
98 + PointerAnalysis pa = (PointerAnalysis) x.snd;
100 + Iterator<CGNode> iter = cg.iterator();
101 + while ( iter.hasNext() ) {
102 + CGNode n = iter.next();
103 + if ( n.getMethod().getSignature().equals("LInnerClassSuper$SuperOuter.test()V") ) {
104 + // find enclosing instruction
105 + for ( SSAInstruction instr: n.getIR().getInstructions() ) {
106 + if ( instr instanceof EnclosingObjectReference ) {
107 + String allIks = "";
108 + for (InstanceKey ik: pa.getPointsToSet(new LocalPointerKey(n,instr.getDef())))
109 + allIks += ik.getConcreteType().getName() +",";
110 + Assert.assertTrue("assertion failed: expecting ik \"LSub,\" in method, got \"" + allIks + "\"\n",
111 + allIks.equals("LSub,"));
113 + break;
122 public void testLocalClass() {
123 runTest(singleTestSrc(), rtJar, simpleTestEntryPoint(), Arrays.asList(
125 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
126 new file mode 100644
127 index 0000000..de1024f
128 --- /dev/null
129 +++ b/com.ibm.wala.cast.java.test/src/com/ibm/wala/cast/java/test/JavaOneContainerIRTests.java
130 @@ -0,0 +1,68 @@
131 +/******************************************************************************
132 + * Copyright (c) 2002 - 2006 IBM Corporation.
133 + * All rights reserved. This program and the accompanying materials
134 + * are made available under the terms of the Eclipse Public License v1.0
135 + * which accompanies this distribution, and is available at
136 + * http://www.eclipse.org/legal/epl-v10.html
138 + * Contributors:
139 + * IBM Corporation - initial API and implementation
140 + *****************************************************************************/
142 + * Created on Oct 21, 2005
143 + */
144 +package com.ibm.wala.cast.java.test;
146 +import java.io.File;
147 +import java.util.ArrayList;
149 +import com.ibm.wala.cast.java.client.JavaSourceAnalysisEngine;
150 +import com.ibm.wala.cast.java.client.impl.ZeroOneContainerCFABuilderFactory;
151 +import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil;
152 +import com.ibm.wala.eclipse.util.EclipseProjectPath;
153 +import com.ibm.wala.ipa.callgraph.AnalysisCache;
154 +import com.ibm.wala.ipa.callgraph.AnalysisOptions;
155 +import com.ibm.wala.ipa.callgraph.AnalysisScope;
156 +import com.ibm.wala.ipa.callgraph.CallGraphBuilder;
157 +import com.ibm.wala.ipa.callgraph.Entrypoint;
158 +import com.ibm.wala.ipa.callgraph.impl.Util;
159 +import com.ibm.wala.ipa.cha.IClassHierarchy;
161 +public class JavaOneContainerIRTests extends IRTests {
162 + public JavaOneContainerIRTests(String name) {
163 + super(name);
166 + protected JavaSourceAnalysisEngine getAnalysisEngine(final String[] mainClassDescriptors) {
167 + JavaSourceAnalysisEngine engine = new JavaSourceAnalysisEngine() {
168 + @Override
169 + protected CallGraphBuilder getCallGraphBuilder(IClassHierarchy cha,
170 + AnalysisOptions options, AnalysisCache cache) {
171 + return new ZeroOneContainerCFABuilderFactory().make(options, cache, cha, scope, false);
174 + protected Iterable<Entrypoint> makeDefaultEntrypoints(AnalysisScope scope, IClassHierarchy cha) {
175 + return Util.makeMainEntrypoints(EclipseProjectPath.SOURCE_REF, cha, mainClassDescriptors);
177 + };
178 + engine.setExclusionsFile(CallGraphTestUtil.REGRESSION_EXCLUSIONS);
179 + return engine;
182 + protected String singleInputForTest() {
183 + return getName().substring(4) + ".java";
186 + protected String singleInputForTestNoExt() {
187 + return getName().substring(4);
190 + protected String singlePkgInputForTest(String pkgName) {
191 + return pkgName + File.separator + getName().substring(4) + ".java";
194 + public void testInnerClassLexicalReads() {
195 + // throws UnimplementedError on failure (expecting ScopeMappingInstanceKeys but not generating them)
196 + runTest(singleTestSrc(), rtJar, simpleTestEntryPoint(), new ArrayList<IRAssertion>(), true);
199 diff --git a/com.ibm.wala.cast.java.test/testSrc/InnerClassA.java b/com.ibm.wala.cast.java.test/testSrc/InnerClassA.java
200 new file mode 100644
201 index 0000000..f51541a
202 --- /dev/null
203 +++ b/com.ibm.wala.cast.java.test/testSrc/InnerClassA.java
204 @@ -0,0 +1,125 @@
205 +// other stranger test cases
207 +// combininations of:
208 +// o.new() form
209 +// function calls
210 +// getting enclosings from one AND multiple levels up
211 +// new Foo() which requires an enclosing instruction before (ie calling new Inner() from ReallyInner()
212 +// invariants and non-invariants (immediate 'new' in that function)
213 +// subclasses
215 +public class InnerClassA {
216 + int a_x;
218 + public static void main(String args[]) {
219 + // prints out 5 5 9 7 5 5 7 5 7 5
220 + InnerClassA a = new InnerClassA();
221 + AA aa = a.new AA();
222 + AB ab = aa.makeAB();
223 + a.a_x = 5;
225 + // tests
226 + int myx = ab.getA_X_from_AB();
227 + System.out.println(myx); // 5
228 + int myx2 = ab.getA_X_thru_AB();
229 + System.out.println(myx2); // 5
231 + aa.doSomeCrazyStuff();
234 + public int getA_X() {
235 + return a_x;
238 + class AA {
239 + int a2a_var;
241 + public AB makeAB() {
242 + return new AB();
245 + public void doSomeCrazyStuff() {
246 + AB ab = new AB();
247 + AB.ABSubA absuba = ab.new ABSubA();
248 + absuba.aba_x = 7;
249 + AB.ABA.ABAA abaa2 = ab.new ABA().new ABAA(); // just used to add ABA instance key in ABAA.getABA_X()
251 + AB.ABA aba = ab.new ABA();
252 + aba.aba_x = 9;
253 + AB.ABA.ABAB abab = aba.new ABAB();
254 + System.out.println(abab.getABA_X()); // 9
256 + AB.ABA.ABAA abaa = absuba.new ABAA();
257 + int myaba_x = abaa.getABA_X();
258 + int mya_x = abaa.getA_X();
259 + System.out.println(myaba_x); // 7
260 + System.out.println(mya_x); // 5
263 + doMoreWithABSubA(absuba);
266 + private void doMoreWithABSubA(InnerClassA.AB.ABSubA absuba) {
267 + System.out.println(absuba.getA_X()); // 5
269 + AB.ABSubA.ABSubAA absubaa = absuba.new ABSubAA();
270 + int myaba_x2 = absubaa.getABA_X();
271 + int mya_x2 = absubaa.getA_X();
272 + System.out.println(myaba_x2); // 7
273 + System.out.println(mya_x2); // 5
274 + // TODO Auto-generated method stub
276 + AB.ABA.ABAA abaa = absubaa.makeABAA();
277 + int myaba_x3 = abaa.getABA_X();
278 + int mya_x3 = abaa.getA_X();
279 + System.out.println(myaba_x3); // 7
280 + System.out.println(mya_x3); // 5
285 + class AB {
286 + public int getA_X_from_AB() {
287 + return a_x; // CHECK enclosing is an A
290 + public int getA_X_thru_AB() {
291 + return getA_X(); // CHECK enclosing is an A
294 + class ABA {
295 + int aba_x;
296 + class ABAA {
297 + int getABA_X() {
298 + return aba_x; // CHECK enclosing is an ABA or ABSubA
300 + int getA_X() {
301 + return a_x; // CHECK enclosing is an A
304 + class ABAB {
305 + int getABA_X() {
306 + return aba_x; // CHECK enclosing is an ABA
311 + class ABSubA extends ABA {
312 + class ABSubAA {
313 + int getABA_X() {
314 + return aba_x; // CHECK enclosing is an ABSubA
316 + int getA_X() {
317 + return a_x; // CHECK enclosing is an A
319 + ABA.ABAA makeABAA() {
320 + return new ABAA(); // this new instruction requires us to know that ABSubA is a subclass of ABA.
321 + // thus when we call getABA_X() on the result, it will need to find a EORK(this site,class ABA) -> THIS (of type ABSubAA)
324 + int getA_X() {
325 + return a_x; // CHECK enclosing is an A
330 diff --git a/com.ibm.wala.cast.java.test/testSrc/InnerClassLexicalReads.java b/com.ibm.wala.cast.java.test/testSrc/InnerClassLexicalReads.java
331 new file mode 100644
332 index 0000000..6d15249
333 --- /dev/null
334 +++ b/com.ibm.wala.cast.java.test/testSrc/InnerClassLexicalReads.java
335 @@ -0,0 +1,47 @@
336 +interface IntConstant {
337 + int getConstant();
340 +public class InnerClassLexicalReads {
342 + /*
343 + * CAst Instructions:
344 + * 2 v3 = new <Source,LInnerClassLexicalReads/makeIntConstant(I)LIntConstant;/<anonymous subtype of IntConstant>$9$9>@2[9:9] -> [13:3]
345 + * 3 invokespecial < Source, LInnerClassLexicalReads/makeIntConstant(I)LIntConstant;/<anonymous subtype of IntConstant>$9$9, <init>()V > v3 @3 exception:v5[9:9] -> [13:3]
346 + * 4 return v3 [9:2] -> [13:4]
347 + */
348 + public static IntConstant makeIntConstant(int x) {
349 + final int y = x * x;
350 + return new IntConstant() {
351 +// CAst CONSTRUCTOR Instructions:
352 +// 1 invokespecial < Source, Ljava/lang/Object, <init>()V > v1 @1 exception:v3[20:9] -> [32:3]
354 + /*
355 + * CAst Instructions:
356 + * 0 v2:com.ibm.wala.ssa.SymbolTable$1@16b18b6 = lexical:y@LInnerClassLexicalReads/makeIntConstant(I)LIntConstant;
357 + * 1 return v2:com.ibm.wala.ssa.SymbolTable$1@16b18b6[11:4] -> [11:13]
358 + */
359 + public int getConstant() {
360 + return y;
362 + };
366 + /*
367 + * CAst Instructions:
368 + * 1 v2:com.ibm.wala.ssa.SymbolTable$1@4272b2 = invokestatic < Source, LInnerClassLexicalReads, makeIntConstant(I)LIntConstant; > v3:#123 @1 exception:v4[17:19] -> [17:39]
369 + * 2 v7 = getstatic < Source, Ljava/lang/System, out, <Source,Ljava/io/PrintStream> >[18:2] -> [18:12]
370 + * 3 v8 = invokeinterface < Source, LIntConstant, getConstant()I > v2:com.ibm.wala.ssa.SymbolTable$1@4272b2 @3 exception:v9[18:21] -> [18:37]
371 + * 4 invokevirtual < Source, Ljava/io/PrintStream, println(I)V > v7,v8 @4 exception:v10[18:2] -> [18:38]
372 + */
373 + public static void main(String args[]) {
374 + InnerClassLexicalReads ignored = new InnerClassLexicalReads(); // call this just to make <init> reachable (test checks for unreachable methods)
375 + int foo = 5;
376 + int haha = foo * foo;
377 + IntConstant ic = makeIntConstant(haha);
378 + System.out.println(ic.getConstant());
379 + int x = ic.getConstant();
380 + System.out.println(x);
383 diff --git a/com.ibm.wala.cast.java.test/testSrc/InnerClassSuper.java b/com.ibm.wala.cast.java.test/testSrc/InnerClassSuper.java
384 new file mode 100644
385 index 0000000..d61a986
386 --- /dev/null
387 +++ b/com.ibm.wala.cast.java.test/testSrc/InnerClassSuper.java
388 @@ -0,0 +1,19 @@
389 +public class InnerClassSuper {
390 + int x = 5;
391 + class SuperOuter {
392 + public void test() {
393 + System.out.println(x);
396 + public static void main(String args[]) {
397 + new Sub().new SubInner();
400 +class Sub extends InnerClassSuper {
401 + class SubInner {
402 + public SubInner() {
403 + InnerClassSuper.SuperOuter so = new InnerClassSuper.SuperOuter();
404 + so.test();
408 \ No newline at end of file
409 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
410 index 94993c1..b94db65 100644
411 --- a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/callgraph/AstJavaSSAPropagationCallGraphBuilder.java
412 +++ b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/callgraph/AstJavaSSAPropagationCallGraphBuilder.java
413 @@ -16,6 +16,7 @@ import com.ibm.wala.cast.java.analysis.typeInference.AstJavaTypeInference;
414 import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl.JavaClass;
415 import com.ibm.wala.cast.java.ssa.AstJavaInstructionVisitor;
416 import com.ibm.wala.cast.java.ssa.AstJavaInvokeInstruction;
417 +import com.ibm.wala.cast.java.ssa.AstJavaNewEnclosingInstruction;
418 import com.ibm.wala.cast.java.ssa.EnclosingObjectReference;
419 import com.ibm.wala.classLoader.IClass;
420 import com.ibm.wala.fixedpoint.impl.UnaryOperator;
421 @@ -182,6 +183,14 @@ public class AstJavaSSAPropagationCallGraphBuilder extends AstSSAPropagationCall
422 super(builder, node);
425 + /**
426 + * For each of objKey's instance keys ik, adds the constraint lvalKey = EORK(ik,cls),
427 + * where EORK(ik,cls) will be made equivalent to the actual enclosing class by
428 + * the handleNew() function below.
429 + * @param lvalKey
430 + * @param cls
431 + * @param objKey
432 + */
433 private void handleEnclosingObject(final PointerKey lvalKey, final IClass cls, final PointerKey objKey) {
434 SymbolTable symtab = ir.getSymbolTable();
435 int objVal;
436 @@ -246,12 +255,33 @@ public class AstJavaSSAPropagationCallGraphBuilder extends AstSSAPropagationCall
437 if (iKey != null) {
438 IClass klass = iKey.getConcreteType();
440 + // in the case of a AstJavaNewEnclosingInstruction (a new instruction like outer.new Bla()),
441 + // we may need to record the instance keys if the pointer key outer is invariant (and thus implicit)
442 + InstanceKey enclosingInvariantKeys[] = null;
444 if (klass instanceof JavaClass) {
445 - IClass enclosingClass = ((JavaClass) klass).getEnclosingClass();
446 + IClass enclosingClass = ((JavaClass) klass).getEnclosingClass(); // the immediate enclosing class.
447 if (enclosingClass != null) {
448 IClass currentCls = node.getMethod().getDeclaringClass();
449 - PointerKey objKey = getPointerKeyForLocal(1);
450 - boolean needIndirection = false;
451 + PointerKey objKey;
453 + if ( instruction instanceof AstJavaNewEnclosingInstruction ) {
456 + int enclosingVal = ((AstJavaNewEnclosingInstruction) instruction).getEnclosing();
457 + SymbolTable symtab = ir.getSymbolTable();
459 + // pk 'outer' is invariant, which means it's implicit, so can't add a constraint with the pointer key.
460 + // we should just add constraints directly to the instance keys (below)
461 + if ( contentsAreInvariant(symtab, du, enclosingVal) )
462 + enclosingInvariantKeys = getInvariantContents(enclosingVal);
464 + // what happens if objKey is implicit but the contents aren't invariant?! (it this possible?) big trouble!
466 + objKey = getPointerKeyForLocal(enclosingVal);
468 + else
469 + objKey = getPointerKeyForLocal(1);
471 Trace.println("class is " + klass + ", enclosing is " + enclosingClass + ", method is " + node.getMethod());
473 @@ -259,31 +289,30 @@ public class AstJavaSSAPropagationCallGraphBuilder extends AstSSAPropagationCall
474 return;
477 - while (!getClassHierarchy().isSubclassOf(currentCls, enclosingClass)) {
478 - Assertions._assert(currentCls instanceof JavaClass);
479 + currentCls = enclosingClass;
481 + PointerKey x = new EnclosingObjectReferenceKey(iKey, currentCls);
482 + if ( enclosingInvariantKeys != null )
483 + for ( InstanceKey obj: enclosingInvariantKeys )
484 + system.newConstraint(x, obj);
485 + else
486 + system.newConstraint(x, assignOperator, objKey);
488 + // If the immediate inclosing class is not a top-level class, we must make EORKs for all enclosing classes up to the top level.
489 + // 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
490 + // 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).
491 + // We do this by getting the enclosing class of C and making a link from EORK(d,B) -> EORK(c,B), etc.
492 + currentCls = ((JavaClass) currentCls).getEnclosingClass();
493 + while (currentCls != null) {
494 + x = new EnclosingObjectReferenceKey(iKey, currentCls); // make EORK(d,B), EORK(d,A), etc.
495 + handleEnclosingObject(x, currentCls, objKey);
496 + // objKey is the pointer key representing the immediate inner class.
497 + // handleEnclosingObject finds x's instance keys and for each one "ik" links x to EORK(ik,currentCls)
498 + // thus, for currentCls=B, it will find the allocation site of c and make a link from EORK(d,B) to EORK(c,B)
500 currentCls = ((JavaClass) currentCls).getEnclosingClass();
501 - needIndirection = true;
504 - while (enclosingClass != null) {
505 - PointerKey x = new EnclosingObjectReferenceKey(iKey, enclosingClass);
506 - if (needIndirection) {
507 - handleEnclosingObject(x, currentCls, objKey);
508 - Trace.println("at " + instruction + ": adding " + iKey + ", " + enclosingClass + " <-- " + objKey + ", "
509 - + currentCls);
510 - } else {
511 - system.newConstraint(x, assignOperator, objKey);
512 - Trace.println("at " + instruction + ": adding " + iKey + ", " + enclosingClass + " <-- " + objKey);
515 - if (enclosingClass instanceof JavaClass) {
516 - needIndirection = true;
517 - enclosingClass = ((JavaClass) enclosingClass).getEnclosingClass();
518 - currentCls = ((JavaClass) currentCls).getEnclosingClass();
519 - } else {
520 - break;
527 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
528 index cf12e87..d6d9b5e 100644
529 --- a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/callgraph/AstJavaZeroOneContainerCFABuilder.java
530 +++ b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/callgraph/AstJavaZeroOneContainerCFABuilder.java
531 @@ -62,9 +62,9 @@ public class AstJavaZeroOneContainerCFABuilder extends AstJavaCFABuilder {
532 setContextInterpreter(contextInterpreter);
534 ZeroXInstanceKeys zik = makeInstanceKeys(cha, options, contextInterpreter);
535 - setInstanceKeys(zik);
536 + setInstanceKeys(new JavaScopeMappingInstanceKeys(cha, this, zik));
538 - ContextSelector CCS = makeContainerContextSelector(cha,(ZeroXInstanceKeys) getInstanceKeys());
539 + ContextSelector CCS = makeContainerContextSelector(cha,zik);
540 DelegatingContextSelector DCS = new DelegatingContextSelector(CCS, contextSelector);
541 setContextSelector(DCS);
543 diff --git a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/modref/AstJavaModRef.java b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/modref/AstJavaModRef.java
544 index b02a769..71ea191 100644
545 --- a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/modref/AstJavaModRef.java
546 +++ b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/modref/AstJavaModRef.java
547 @@ -1,25 +1,55 @@
548 package com.ibm.wala.cast.java.ipa.modref;
550 +import java.util.ArrayList;
551 import java.util.Collection;
552 +import java.util.HashSet;
554 +import com.ibm.wala.cast.ipa.callgraph.ScopeMappingInstanceKeys.ScopeMappingInstanceKey;
555 import com.ibm.wala.cast.ipa.modref.AstModRef;
556 +import com.ibm.wala.cast.ir.ssa.AstLexicalRead;
557 +import com.ibm.wala.cast.ir.ssa.AstLexicalAccess.Access;
558 import com.ibm.wala.cast.java.ssa.AstJavaInstructionVisitor;
559 import com.ibm.wala.cast.java.ssa.AstJavaInvokeInstruction;
560 import com.ibm.wala.cast.java.ssa.EnclosingObjectReference;
561 import com.ibm.wala.ipa.callgraph.CGNode;
562 +import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
563 +import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey;
564 import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
565 import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
566 import com.ibm.wala.ipa.modref.ExtendedHeapModel;
567 +import com.ibm.wala.ipa.slicer.HeapExclusions;
568 +import com.ibm.wala.ssa.SSAInstruction;
570 public class AstJavaModRef extends AstModRef {
572 - protected static class AstJavaRefVisitor
573 - extends AstRefVisitor
574 - implements AstJavaInstructionVisitor
577 - protected AstJavaRefVisitor(CGNode n, Collection<PointerKey> result, PointerAnalysis pa, ExtendedHeapModel h) {
578 + HashSet<Statement> lexicalReadMods = new HashSet<Statement>();
580 + private static class Statement implements PointerKey {
581 + public CGNode node;
583 + public SSAInstruction inst;
585 + public Statement(CGNode node, SSAInstruction inst) {
586 + this.node = node;
587 + this.inst = inst;
590 + public boolean equals(Object o) {
591 + return (o instanceof Statement && ((Statement) o).node == node && ((Statement) o).inst == inst);
594 + public int hashCode() {
595 + return node.hashCode() + 19 * inst.hashCode();
599 + protected static class AstJavaRefVisitor extends AstRefVisitor implements AstJavaInstructionVisitor {
600 + private HashSet<Statement> lexicalReadMods;
602 + protected AstJavaRefVisitor(CGNode n, Collection<PointerKey> result, PointerAnalysis pa, ExtendedHeapModel h,
603 + HashSet<Statement> lexicalReadMods) {
604 super(n, result, pa, h);
605 + this.lexicalReadMods = lexicalReadMods;
608 public void visitJavaInvoke(AstJavaInvokeInstruction instruction) {
609 @@ -30,22 +60,48 @@ public class AstJavaModRef extends AstModRef {
613 + /**
614 + * Finds the instruction the lexical read came from, and make a special pointer key unique to that statement and say
615 + * we ref that. Later on, we will have the statement mod this pointer key, thus linking the two statements.
616 + * @see AstJavaModRef.getMod(...)
617 + */
618 + @Override
619 + public void visitAstLexicalRead(AstLexicalRead instruction) {
620 + AstLexicalRead alr = instruction;
622 + Access[] accesses = alr.getAccesses();
623 + // inner node & alr.getAccesses();
625 + for (int i = 0; i < accesses.length; i++) {
626 + final String definer = accesses[i].variableDefiner;
627 + final int vn = accesses[i].valueNumber;
629 + PointerKey pk = new LocalPointerKey(n, 1);
630 + for (InstanceKey ik : pa.getPointsToSet(pk)) {
631 + if (ik instanceof ScopeMappingInstanceKey) {
632 + // TODO: isn't there only one place in the source this could have come from? why the loop?
633 + // find the instruction that the lexical read's value came from
634 + CGNode defNode = ((ScopeMappingInstanceKey) ik).getDefiningNode(definer);
635 + SSAInstruction defInst = defNode.getDU().getDef(vn);
636 + Statement s = new Statement(defNode, defInst);
637 + result.add(s);
638 + lexicalReadMods.add(s);
645 protected RefVisitor makeRefVisitor(CGNode n, Collection<PointerKey> result, PointerAnalysis pa, ExtendedHeapModel h) {
646 - return new AstJavaRefVisitor(n, result, pa, h);
647 + return new AstJavaRefVisitor(n, result, pa, h, lexicalReadMods);
650 - protected static class AstJavaModVisitor
651 - extends AstModVisitor
652 - implements AstJavaInstructionVisitor
655 + protected static class AstJavaModVisitor extends AstModVisitor implements AstJavaInstructionVisitor {
657 protected AstJavaModVisitor(CGNode n, Collection<PointerKey> result, ExtendedHeapModel h, PointerAnalysis pa) {
658 super(n, result, h, pa);
662 public void visitJavaInvoke(AstJavaInvokeInstruction instruction) {
665 @@ -54,11 +110,34 @@ public class AstJavaModRef extends AstModRef {
671 @Override
672 - protected ModVisitor makeModVisitor(CGNode n, Collection<PointerKey> result, PointerAnalysis pa, ExtendedHeapModel h, boolean ignoreAllocHeapDefs) {
673 + protected ModVisitor makeModVisitor(CGNode n, Collection<PointerKey> result, PointerAnalysis pa, ExtendedHeapModel h,
674 + boolean ignoreAllocHeapDefs) {
675 return new AstJavaModVisitor(n, result, h, pa);
679 + /**
680 + * Overridden to provide support for Ast Java lexical reads (in Shrike things like this.val$y -- fields of enclosing
681 + * objects). During the ref phase, lexical read instructions find out the instructions defining their values, and make
682 + * a pointer key (a "Statement" which is 1-1 mapping to the statement that defined the value) which is their result
683 + * set. We also add this Statement to a hashset of "statements that have been referenced by lexical reads".
684 + *
685 + * Then here, we see if any lexical reads have ref'd us (i.e., we are in the set of "statements referenced by some
686 + * lexical read") and if so, add that Statement pointer key to the result set. In that manner, the statement that
687 + * defined the value mods the same Statement PointerKey that the lexical read refs. However, for this to work REFS
688 + * MUST BE DONE BEFORE MODS!
689 + *
690 + */
691 + @Override
692 + public Collection<PointerKey> getMod(CGNode n, ExtendedHeapModel h, PointerAnalysis pa, SSAInstruction s, HeapExclusions hexcl,
693 + boolean ignoreAllocHeapDefs) {
694 + Collection<PointerKey> pks = super.getMod(n, h, pa, s, hexcl, ignoreAllocHeapDefs);
696 + Statement statement = new Statement(n, s);
697 + if (lexicalReadMods.contains(statement))
698 + pks.add(statement);
699 + return pks;
703 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
704 new file mode 100644
705 index 0000000..45718e5
706 --- /dev/null
707 +++ b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ssa/AstJavaNewEnclosingInstruction.java
708 @@ -0,0 +1,25 @@
709 +package com.ibm.wala.cast.java.ssa;
711 +import com.ibm.wala.classLoader.NewSiteReference;
712 +import com.ibm.wala.ssa.SSANewInstruction;
714 +// A new instruction with an explicit outer class, i.e. "Inner inner = outer.new Inner();"
715 +public class AstJavaNewEnclosingInstruction extends SSANewInstruction {
717 + int enclosing;
719 + public AstJavaNewEnclosingInstruction(int result, NewSiteReference site, int enclosing) throws IllegalArgumentException {
720 + super(result, site);
721 + this.enclosing = enclosing;
724 + public int getEnclosing() {
725 + return this.enclosing;
728 + public String toString() {
729 + return super.toString() + " ENCLOSING v" + enclosing;
734 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
735 index 9d302ae..774eaaf 100644
736 --- a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/JavaCAst2IRTranslator.java
737 +++ b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/JavaCAst2IRTranslator.java
738 @@ -19,6 +19,7 @@ import java.util.Iterator;
739 import com.ibm.wala.cast.ir.translator.AstTranslator;
740 import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl;
741 import com.ibm.wala.cast.java.ssa.AstJavaInvokeInstruction;
742 +import com.ibm.wala.cast.java.ssa.AstJavaNewEnclosingInstruction;
743 import com.ibm.wala.cast.java.ssa.EnclosingObjectReference;
744 import com.ibm.wala.cast.loader.AstMethod.DebuggingInformation;
745 import com.ibm.wala.cast.loader.AstMethod.LexicalInformation;
746 @@ -156,11 +157,14 @@ public class JavaCAst2IRTranslator extends AstTranslator {
747 NewSiteReference site =
748 NewSiteReference.make(context.cfg().getCurrentInstruction(), typeRef);
750 - context.cfg().addInstruction(
751 - (arguments == null)?
752 - SSAInstructionFactory.NewInstruction(result, site):
753 - new SSANewInstruction(result, site, arguments));
755 + if ( newNode.getKind() == CAstNode.NEW_ENCLOSING ) {
756 + context.cfg().addInstruction ( new AstJavaNewEnclosingInstruction(result, site, arguments[0]));
757 + } else {
758 + context.cfg().addInstruction(
759 + (arguments == null)?
760 + SSAInstructionFactory.NewInstruction(result, site):
761 + new SSANewInstruction(result, site, arguments));
763 processExceptions(newNode, context);
766 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
767 index f9f1222..17910ce 100644
768 --- a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/polyglot/PolyglotJava2CAstTranslator.java
769 +++ b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/polyglot/PolyglotJava2CAstTranslator.java
770 @@ -746,7 +746,16 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
771 String tmpName = "ctor temp"; // this name is an illegal Java
772 // identifier
774 - CAstNode newNode = makeNode(wc, fFactory, n, CAstNode.NEW, fFactory.makeConstant(newTypeRef));
775 + // new nodes with an explicit enclosing argument, e.g. "outer.new Inner()". They are mostly treated the same, except in JavaCAst2IRTranslator.doNewObject
776 + CAstNode newNode;
777 + Expr enclosing = n.qualifier();
778 + if ( enclosing != null ) {
779 + CAstNode encNode = walkNodes(enclosing, wc);
780 + newNode = makeNode(wc, fFactory, n, CAstNode.NEW_ENCLOSING, fFactory.makeConstant(newTypeRef), encNode);
782 + else
783 + newNode = makeNode(wc, fFactory, n, CAstNode.NEW, fFactory.makeConstant(newTypeRef));
784 + // end enclosing new stuff
786 if (n.body() != null)
787 wc.addScopedEntity(newNode, anonClass);
788 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
789 index 381a8cf..711617c 100644
790 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java
791 +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java
792 @@ -128,7 +128,7 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
793 return base.getConcreteType();
796 - CGNode getDefiningNode(String definer) {
797 + public CGNode getDefiningNode(String definer) {
798 return map.getDefiningNode(definer);
801 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
802 index 18bf26f..b420421 100644
803 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/CAstNode.java
804 +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/CAstNode.java
805 @@ -155,6 +155,9 @@ public interface CAstNode {
806 public static final int TYPE_LITERAL_EXPR = 127;
807 public static final int IS_DEFINED_EXPR = 128;
809 + // new nodes with an explicit enclosing argument, e.g. "outer.new Inner()". They are mostly treated the same, except in JavaCAst2IRTranslator.doNewObject
810 + public static final int NEW_ENCLOSING = 129;
812 // explicit lexical scopes
813 public static final int LOCAL_SCOPE = 200;
815 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
816 index 44f7055..e3ad94f 100644
817 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/visit/CAstVisitor.java
818 +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/visit/CAstVisitor.java
819 @@ -554,6 +554,7 @@ public abstract class CAstVisitor {
820 break;
823 + case CAstNode.NEW_ENCLOSING:
824 case CAstNode.NEW: {
825 if (visitor.visitNew(n, context, visitor))
826 break;
827 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
828 index 05ef170..ef226b7 100644
829 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/CAstPrinter.java
830 +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/CAstPrinter.java
831 @@ -71,6 +71,7 @@ public class CAstPrinter {
832 case CAstNode.IF_EXPR: return "IF_EXPR";
833 case CAstNode.ANDOR_EXPR: return "ANDOR_EXPR";
834 case CAstNode.NEW: return "NEW";
835 + case CAstNode.NEW_ENCLOSING: return "NEW_ENCLOSING";
836 case CAstNode.OBJECT_LITERAL: return "LITERAL";
837 case CAstNode.VAR: return "VAR";
838 case CAstNode.OBJECT_REF: return "OBJECT_REF";
839 diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/HeapModel.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/HeapModel.java
840 index 324a7b7..6a4ee23 100644
841 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/HeapModel.java
842 +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/HeapModel.java
843 @@ -13,6 +13,7 @@ package com.ibm.wala.ipa.callgraph.propagation;
844 import java.util.Iterator;
846 import com.ibm.wala.ipa.cha.IClassHierarchy;
847 +import com.ibm.wala.ipa.modref.ModRef;
851 @@ -32,5 +33,4 @@ public interface HeapModel extends InstanceKeyFactory, PointerKeyFactory {
852 * @return the governing class hierarchy for this heap model
854 IClassHierarchy getClassHierarchy();
857 diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/modref/ModRef.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/modref/ModRef.java
858 index e19a6ce..1f6f533 100644
859 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/modref/ModRef.java
860 +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/modref/ModRef.java
861 @@ -191,13 +191,13 @@ public class ModRef {
864 protected static class RefVisitor extends SSAInstruction.Visitor {
865 - private final CGNode n;
866 + protected final CGNode n;
868 - private final Collection<PointerKey> result;
869 + protected final Collection<PointerKey> result;
871 - private final PointerAnalysis pa;
872 + protected final PointerAnalysis pa;
874 - private final ExtendedHeapModel h;
875 + protected final ExtendedHeapModel h;
877 protected RefVisitor(CGNode n, Collection<PointerKey> result, PointerAnalysis pa, ExtendedHeapModel h) {
878 this.n = n;
879 @@ -239,15 +239,15 @@ public class ModRef {
882 protected static class ModVisitor extends SSAInstruction.Visitor {
883 - private final CGNode n;
884 + protected final CGNode n;
886 - private final Collection<PointerKey> result;
887 + protected final Collection<PointerKey> result;
889 - private final ExtendedHeapModel h;
890 + protected final ExtendedHeapModel h;
892 - private final PointerAnalysis pa;
893 + protected final PointerAnalysis pa;
895 - private final boolean ignoreAllocHeapDefs;
896 + protected final boolean ignoreAllocHeapDefs;
898 protected ModVisitor(CGNode n, Collection<PointerKey> result, ExtendedHeapModel h, PointerAnalysis pa, boolean ignoreAllocHeapDefs) {
899 this.n = n;