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
6 package com.ibm.wala.cast.java.test;
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 {
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[ ]= {
61 + "LInnerClassA$AB$ABSubA,LInnerClassA$AB$ABA,",
63 + "LInnerClassA$AB$ABA,",
64 + "LInnerClassA$AB$ABSubA,",
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 ) {
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]));
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,"));
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
127 index 0000000..de1024f
129 +++ b/com.ibm.wala.cast.java.test/src/com/ibm/wala/cast/java/test/JavaOneContainerIRTests.java
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
139 + * IBM Corporation - initial API and implementation
140 + *****************************************************************************/
142 + * Created on Oct 21, 2005
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) {
166 + protected JavaSourceAnalysisEngine getAnalysisEngine(final String[] mainClassDescriptors) {
167 + JavaSourceAnalysisEngine engine = new JavaSourceAnalysisEngine() {
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);
178 + engine.setExclusionsFile(CallGraphTestUtil.REGRESSION_EXCLUSIONS);
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
201 index 0000000..f51541a
203 +++ b/com.ibm.wala.cast.java.test/testSrc/InnerClassA.java
205 +// other stranger test cases
207 +// combininations of:
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)
215 +public class InnerClassA {
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();
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() {
241 + public AB makeAB() {
245 + public void doSomeCrazyStuff() {
247 + AB.ABSubA absuba = ab.new ABSubA();
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();
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
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
298 + return aba_x; // CHECK enclosing is an ABA or ABSubA
301 + return a_x; // CHECK enclosing is an A
306 + return aba_x; // CHECK enclosing is an ABA
311 + class ABSubA extends ABA {
314 + return aba_x; // CHECK enclosing is an ABSubA
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)
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
332 index 0000000..6d15249
334 +++ b/com.ibm.wala.cast.java.test/testSrc/InnerClassLexicalReads.java
336 +interface IntConstant {
340 +public class InnerClassLexicalReads {
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]
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]
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]
359 + public int getConstant() {
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]
373 + public static void main(String args[]) {
374 + InnerClassLexicalReads ignored = new InnerClassLexicalReads(); // call this just to make <init> reachable (test checks for unreachable methods)
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
385 index 0000000..d61a986
387 +++ b/com.ibm.wala.cast.java.test/testSrc/InnerClassSuper.java
389 +public class InnerClassSuper {
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 {
402 + public SubInner() {
403 + InnerClassSuper.SuperOuter so = new InnerClassSuper.SuperOuter();
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);
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.
433 private void handleEnclosingObject(final PointerKey lvalKey, final IClass cls, final PointerKey objKey) {
434 SymbolTable symtab = ir.getSymbolTable();
436 @@ -246,12 +255,33 @@ public class AstJavaSSAPropagationCallGraphBuilder extends AstSSAPropagationCall
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;
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);
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
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);
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 + ", "
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();
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
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) {
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 {
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(...)
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);
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 {
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);
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".
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!
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);
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
705 index 0000000..45718e5
707 +++ b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ssa/AstJavaNewEnclosingInstruction.java
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 {
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]));
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
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
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);
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.js/META-INF/MANIFEST.MF b/com.ibm.wala.cast.js/META-INF/MANIFEST.MF
790 index 0000000..f23aeaf
792 +++ b/com.ibm.wala.cast.js/META-INF/MANIFEST.MF
794 +Manifest-Version: 1.0
795 +Bundle-ManifestVersion: 2
796 +Bundle-Name: Javascript Source WALA Front End
797 +Bundle-SymbolicName: com.ibm.wala.cast.js
798 +Bundle-Version: 1.0.0
799 +Bundle-Activator: com.ibm.wala.cast.js.JavaScriptPlugin
800 +Bundle-Vendor: rfuhrer@watson.ibm.com
801 +Require-Bundle: com.ibm.wala.cast;visibility:=reexport,
802 + com.ibm.wala.core;visibility:=reexport
803 +Eclipse-LazyStart: true
804 +Export-Package: com.ibm.wala.cast.js,
805 + com.ibm.wala.cast.js.analysis.typeInference,
806 + com.ibm.wala.cast.js.cfg,
807 + com.ibm.wala.cast.js.client,
808 + com.ibm.wala.cast.js.client.impl,
809 + com.ibm.wala.cast.js.ipa.callgraph,
810 + com.ibm.wala.cast.js.ipa.summaries,
811 + com.ibm.wala.cast.js.loader,
812 + com.ibm.wala.cast.js.ssa,
813 + com.ibm.wala.cast.js.translator,
814 + com.ibm.wala.cast.js.types,
815 + com.ibm.wala.cast.js.util,
818 + org.apache.bcel.classfile,
819 + org.apache.bcel.generic,
820 + org.apache.bcel.util,
821 + org.apache.bcel.verifier,
822 + org.apache.bcel.verifier.exc,
823 + org.apache.bcel.verifier.statics,
824 + org.apache.bcel.verifier.structurals,
827 + org.apache.xalan.client,
828 + org.apache.xalan.extensions,
829 + org.apache.xalan.lib,
830 + org.apache.xalan.lib.sql,
831 + org.apache.xalan.processor,
832 + org.apache.xalan.res,
833 + org.apache.xalan.serialize,
834 + org.apache.xalan.templates,
835 + org.apache.xalan.trace,
836 + org.apache.xalan.transformer,
837 + org.apache.xalan.xslt,
838 + org.apache.xalan.xsltc,
839 + org.apache.xalan.xsltc.cmdline,
840 + org.apache.xalan.xsltc.cmdline.getopt,
841 + org.apache.xalan.xsltc.compiler,
842 + org.apache.xalan.xsltc.compiler.util,
843 + org.apache.xalan.xsltc.dom,
844 + org.apache.xalan.xsltc.runtime,
845 + org.apache.xalan.xsltc.runtime.output,
846 + org.apache.xalan.xsltc.trax,
847 + org.apache.xalan.xsltc.util,
848 + org.apache.xml.dtm,
849 + org.apache.xml.dtm.ref,
850 + org.apache.xml.dtm.ref.dom2dtm,
851 + org.apache.xml.dtm.ref.sax2dtm,
852 + org.apache.xml.res,
853 + org.apache.xml.utils,
854 + org.apache.xml.utils.res,
856 + org.apache.xpath.axes,
857 + org.apache.xpath.compiler,
858 + org.apache.xpath.domapi,
859 + org.apache.xpath.functions,
860 + org.apache.xpath.jaxp,
861 + org.apache.xpath.objects,
862 + org.apache.xpath.operations,
863 + org.apache.xpath.patterns,
864 + org.apache.xpath.res,
865 + org.mozilla.classfile,
866 + org.mozilla.javascript,
867 + org.mozilla.javascript.continuations,
868 + org.mozilla.javascript.debug,
869 + org.mozilla.javascript.jdk11,
870 + org.mozilla.javascript.jdk13,
871 + org.mozilla.javascript.optimizer,
872 + org.mozilla.javascript.regexp,
873 + org.mozilla.javascript.serialize,
874 + org.mozilla.javascript.tools,
875 + org.mozilla.javascript.tools.debugger,
876 + org.mozilla.javascript.tools.debugger.downloaded,
877 + org.mozilla.javascript.tools.idswitch,
878 + org.mozilla.javascript.tools.jsc,
879 + org.mozilla.javascript.tools.shell,
880 + org.mozilla.javascript.xml,
881 + org.mozilla.javascript.xmlimpl
882 +Bundle-ClassPath: .,
885 diff --git a/com.ibm.wala.cast.js/build.properties b/com.ibm.wala.cast.js/build.properties
886 index 36e03bf..999ffb1 100644
887 --- a/com.ibm.wala.cast.js/build.properties
888 +++ b/com.ibm.wala.cast.js/build.properties
891 -bin.includes = plugin.xml,\
892 +bin.includes = META-INF/,\
897 diff --git a/com.ibm.wala.cast.js/plugin.xml b/com.ibm.wala.cast.js/plugin.xml
898 deleted file mode 100644
899 index 7d47caf..0000000
900 --- a/com.ibm.wala.cast.js/plugin.xml
903 -<?xml version="1.0" encoding="UTF-8"?>
904 -<?eclipse version="3.0"?>
906 - id="com.ibm.wala.cast.js"
907 - name="JavaScript Plug-in"
909 - provider-name="IBM"
910 - class="com.ibm.wala.cast.js.JavaScriptPlugin">
913 - <library name="lib/js.jar">
916 - <library name="lib/xalan.jar">
922 - <import plugin="com.ibm.wala.cast"/>
923 - <import plugin="com.ibm.wala.core"/>
927 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
928 index 381a8cf..711617c 100644
929 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java
930 +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java
931 @@ -128,7 +128,7 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
932 return base.getConcreteType();
935 - CGNode getDefiningNode(String definer) {
936 + public CGNode getDefiningNode(String definer) {
937 return map.getDefiningNode(definer);
940 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
941 index 1c41365..ec8cd1e 100644
942 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java
943 +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java
944 @@ -2610,8 +2610,8 @@ public abstract class AstTranslator extends CAstVisitor
945 int result = getValue(n);
946 CAstNode l = n.getChild(1);
947 CAstNode r = n.getChild(2);
948 - Assertions._assert(getValue(r) != -1, CAstPrinter.print(n));
949 - Assertions._assert(getValue(l) != -1, CAstPrinter.print(n));
950 +// Assertions._assert(getValue(r) != -1, CAstPrinter.print(n));
951 +// Assertions._assert(getValue(l) != -1, CAstPrinter.print(n));
953 boolean mayBeInteger = handleBinaryOpThrow(n, n.getChild(0), context);
955 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
956 index 18bf26f..b420421 100644
957 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/CAstNode.java
958 +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/CAstNode.java
959 @@ -155,6 +155,9 @@ public interface CAstNode {
960 public static final int TYPE_LITERAL_EXPR = 127;
961 public static final int IS_DEFINED_EXPR = 128;
963 + // new nodes with an explicit enclosing argument, e.g. "outer.new Inner()". They are mostly treated the same, except in JavaCAst2IRTranslator.doNewObject
964 + public static final int NEW_ENCLOSING = 129;
966 // explicit lexical scopes
967 public static final int LOCAL_SCOPE = 200;
969 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
970 index 44f7055..e3ad94f 100644
971 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/visit/CAstVisitor.java
972 +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/visit/CAstVisitor.java
973 @@ -554,6 +554,7 @@ public abstract class CAstVisitor {
977 + case CAstNode.NEW_ENCLOSING:
979 if (visitor.visitNew(n, context, visitor))
981 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
982 index 05ef170..ef226b7 100644
983 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/CAstPrinter.java
984 +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/CAstPrinter.java
985 @@ -71,6 +71,7 @@ public class CAstPrinter {
986 case CAstNode.IF_EXPR: return "IF_EXPR";
987 case CAstNode.ANDOR_EXPR: return "ANDOR_EXPR";
988 case CAstNode.NEW: return "NEW";
989 + case CAstNode.NEW_ENCLOSING: return "NEW_ENCLOSING";
990 case CAstNode.OBJECT_LITERAL: return "LITERAL";
991 case CAstNode.VAR: return "VAR";
992 case CAstNode.OBJECT_REF: return "OBJECT_REF";
993 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
994 index 324a7b7..6a4ee23 100644
995 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/HeapModel.java
996 +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/HeapModel.java
997 @@ -13,6 +13,7 @@ package com.ibm.wala.ipa.callgraph.propagation;
998 import java.util.Iterator;
1000 import com.ibm.wala.ipa.cha.IClassHierarchy;
1001 +import com.ibm.wala.ipa.modref.ModRef;
1005 @@ -32,5 +33,4 @@ public interface HeapModel extends InstanceKeyFactory, PointerKeyFactory {
1006 * @return the governing class hierarchy for this heap model
1008 IClassHierarchy getClassHierarchy();
1011 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
1012 index e19a6ce..1f6f533 100644
1013 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/modref/ModRef.java
1014 +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/modref/ModRef.java
1015 @@ -191,13 +191,13 @@ public class ModRef {
1018 protected static class RefVisitor extends SSAInstruction.Visitor {
1019 - private final CGNode n;
1020 + protected final CGNode n;
1022 - private final Collection<PointerKey> result;
1023 + protected final Collection<PointerKey> result;
1025 - private final PointerAnalysis pa;
1026 + protected final PointerAnalysis pa;
1028 - private final ExtendedHeapModel h;
1029 + protected final ExtendedHeapModel h;
1031 protected RefVisitor(CGNode n, Collection<PointerKey> result, PointerAnalysis pa, ExtendedHeapModel h) {
1033 @@ -239,15 +239,15 @@ public class ModRef {
1036 protected static class ModVisitor extends SSAInstruction.Visitor {
1037 - private final CGNode n;
1038 + protected final CGNode n;
1040 - private final Collection<PointerKey> result;
1041 + protected final Collection<PointerKey> result;
1043 - private final ExtendedHeapModel h;
1044 + protected final ExtendedHeapModel h;
1046 - private final PointerAnalysis pa;
1047 + protected final PointerAnalysis pa;
1049 - private final boolean ignoreAllocHeapDefs;
1050 + protected final boolean ignoreAllocHeapDefs;
1052 protected ModVisitor(CGNode n, Collection<PointerKey> result, ExtendedHeapModel h, PointerAnalysis pa, boolean ignoreAllocHeapDefs) {