From cd944a8f127a37741c07088339a682db6592ba59 Mon Sep 17 00:00:00 2001 From: Julian Dolby Date: Thu, 25 Jan 2018 14:42:27 -0500 Subject: [PATCH] refactoring of CAst front end machinery to allow more reuse --- com.ibm.wala.cast.js.nodejs/build.properties | 1 + .../test/FieldBasedCGGamesTest.java | 6 +- .../.settings/org.eclipse.pde.prefs | 4 +- .../META-INF/MANIFEST.MF | 7 +- .../js/translator/RhinoToAstTranslator.java | 26 ++- .../JavaScriptTranslatorToCAst.java | 175 +++++------------ .../ir/translator/AbstractCodeEntity.java | 3 +- .../ir/translator/AbstractFieldEntity.java | 2 +- .../cast/ir/translator/TranslatorToCAst.java | 180 ++++++++++++++---- .../java/com/ibm/wala/cast/tree/CAstNode.java | 2 +- .../com/ibm/wala/cast/tree/impl/CAstImpl.java | 4 +- .../ibm/wala/cast/tree/impl/CAstOperator.java | 2 + .../src/com/ibm/wala/cfg/ShrikeCFG.java | 14 +- .../com/ibm/wala/ipa/cha/ClassHierarchy.java | 9 +- .../src/com/ibm/wala/ssa/SSACFG.java | 3 + .../ibm/wala/shrikeBT/ExceptionHandler.java | 13 +- 16 files changed, 265 insertions(+), 186 deletions(-) diff --git a/com.ibm.wala.cast.js.nodejs/build.properties b/com.ibm.wala.cast.js.nodejs/build.properties index 1e594bfcb..9c86a3abf 100644 --- a/com.ibm.wala.cast.js.nodejs/build.properties +++ b/com.ibm.wala.cast.js.nodejs/build.properties @@ -11,3 +11,4 @@ javacProjectSettings = true bin.excludes = dat/core-modules/.eslintrc,\ dat/core-modules/.gitignore,\ dat/core-modules/.gitkeep +javacDefaultEncoding.. = UTF-8 diff --git a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/rhino/callgraph/fieldbased/test/FieldBasedCGGamesTest.java b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/rhino/callgraph/fieldbased/test/FieldBasedCGGamesTest.java index f273c4ba1..2684e7af3 100644 --- a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/rhino/callgraph/fieldbased/test/FieldBasedCGGamesTest.java +++ b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/rhino/callgraph/fieldbased/test/FieldBasedCGGamesTest.java @@ -38,15 +38,15 @@ public class FieldBasedCGGamesTest extends AbstractFieldBasedTest { runTestExceptOnTravis(new URL("http://www.inmensia.com/files/solitaire1.0.html"), new Object[][]{}, BuilderType.OPTIMISTIC); } - @Test(expected = CancelException.class) + @Test // (expected = CancelException.class) public void testWorldOfSolitaire() throws IOException, WalaException, Error, CancelException { runTestExceptOnTravis(new URL("http://worldofsolitaire.com/"), new Object[][]{}, BuilderType.OPTIMISTIC); if (System.getenv("TRAVIS") != null) { // fake it - throw new CancelException(null); + // throw new CancelException(null); } } - + @Test public void testMinesweeper() throws IOException, WalaException, Error, CancelException { runTestExceptOnTravis(new URL("http://www.inmensia.com/files/minesweeper1.0.html"), new Object[][]{}, BuilderType.OPTIMISTIC_WORKLIST); diff --git a/com.ibm.wala.cast.js.rhino/.settings/org.eclipse.pde.prefs b/com.ibm.wala.cast.js.rhino/.settings/org.eclipse.pde.prefs index 6dd146ef8..f33115355 100644 --- a/com.ibm.wala.cast.js.rhino/.settings/org.eclipse.pde.prefs +++ b/com.ibm.wala.cast.js.rhino/.settings/org.eclipse.pde.prefs @@ -15,8 +15,8 @@ compilers.p.discouraged-class=0 compilers.p.internal=0 compilers.p.missing-packages=0 compilers.p.missing-version-export-package=2 -compilers.p.missing-version-import-package=0 -compilers.p.missing-version-require-bundle=0 +compilers.p.missing-version-import-package=2 +compilers.p.missing-version-require-bundle=2 compilers.p.no-required-att=0 compilers.p.not-externalized-att=0 compilers.p.unknown-attribute=0 diff --git a/com.ibm.wala.cast.js.rhino/META-INF/MANIFEST.MF b/com.ibm.wala.cast.js.rhino/META-INF/MANIFEST.MF index 2c19f0ca8..99259b787 100644 --- a/com.ibm.wala.cast.js.rhino/META-INF/MANIFEST.MF +++ b/com.ibm.wala.cast.js.rhino/META-INF/MANIFEST.MF @@ -4,9 +4,10 @@ Bundle-Name: %Bundle-Name Bundle-SymbolicName: com.ibm.wala.cast.js.rhino Bundle-Version: 1.4.4.qualifier Bundle-Vendor: %Bundle-Vendor -Require-Bundle: com.ibm.wala.cast;bundle-version="1.0.0", - com.ibm.wala.cast.js;bundle-version="1.0.0", - com.ibm.wala.core;bundle-version="1.1.3" +Require-Bundle: com.ibm.wala.cast;bundle-version="1.4.4", + com.ibm.wala.cast.js;bundle-version="1.4.4", + com.ibm.wala.core;bundle-version="1.4.4", + com.ibm.wala.util;bundle-version="1.4.4" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy Export-Package: com.ibm.wala.cast.js.translator, diff --git a/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/RhinoToAstTranslator.java b/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/RhinoToAstTranslator.java index 662728edd..638788619 100644 --- a/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/RhinoToAstTranslator.java +++ b/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/RhinoToAstTranslator.java @@ -159,10 +159,9 @@ public class RhinoToAstTranslator implements TranslatorToCAst { */ private static class FunctionContext extends JavaScriptTranslatorToCAst.FunctionContext implements WalkContext { FunctionContext(WalkContext parent, Node s) { - super(parent, s); - } - - } + super(parent, s); + } + } /** * context used for top-level script declarations @@ -191,26 +190,41 @@ public class RhinoToAstTranslator implements TranslatorToCAst { private static class BreakContext extends JavaScriptTranslatorToCAst.BreakContext implements WalkContext { + @Override + public WalkContext getParent() { + return (WalkContext) super.getParent(); + } + BreakContext(WalkContext parent, Node breakTo, String label) { super(parent, breakTo, label); } } - private static class LoopContext extends JavaScriptTranslatorToCAst.LoopContext implements WalkContext { + private static class LoopContext extends TranslatorToCAst.LoopContext implements WalkContext { LoopContext(WalkContext parent, Node breakTo, Node continueTo, String label) { super(parent, breakTo, continueTo, label); } + @Override + public WalkContext getParent() { + return (WalkContext) super.getParent(); } - private static class TryCatchContext extends JavaScriptTranslatorToCAst.TryCatchContext implements WalkContext { + } + + private static class TryCatchContext extends TranslatorToCAst.TryCatchContext implements WalkContext { TryCatchContext(WalkContext parent, CAstNode catchNode) { super(parent, catchNode); } + @Override + public WalkContext getParent() { + return (WalkContext) super.getParent(); + } + } private static String operationReceiverName(int operationIndex) { diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/JavaScriptTranslatorToCAst.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/JavaScriptTranslatorToCAst.java index 483f62d4c..247660885 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/JavaScriptTranslatorToCAst.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/JavaScriptTranslatorToCAst.java @@ -12,26 +12,24 @@ package com.ibm.wala.cast.js.translator; import java.util.Collection; import java.util.HashSet; -import java.util.Map; import java.util.Set; import java.util.Vector; import com.ibm.wala.cast.ir.translator.TranslatorToCAst; import com.ibm.wala.cast.tree.CAstControlFlowMap; -import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.CAstNode; -import com.ibm.wala.cast.tree.impl.CAstControlFlowRecorder; -import com.ibm.wala.cast.tree.impl.CAstSourcePositionRecorder; -import com.ibm.wala.util.collections.HashMapFactory; import com.ibm.wala.util.debug.Assertions; public interface JavaScriptTranslatorToCAst extends TranslatorToCAst { interface WalkContext, T> extends TranslatorToCAst.WalkContext { - String script(); + @Override + WalkContext getParent(); - T top(); + default String script() { + return getParent().script(); + } /** * Add a name declaration to this context. For variables or constants, n @@ -39,22 +37,35 @@ public interface JavaScriptTranslatorToCAst extends TranslatorToCAst { * variable (if any) may occur in a separate assignment. For functions, n * should be a {@link CAstNode#FUNCTION_STMT}, including the function body. */ - void addNameDecl(CAstNode n); + default void addNameDecl(CAstNode n) { + getParent().addNameDecl(n); + } - Collection getNameDecls(); + default Collection getNameDecls() { + return getParent().getNameDecls(); + } - CAstNode getCatchTarget(); + default int setOperation(T node) { + return getParent().setOperation(node); + } - int setOperation(T node); - - boolean foundMemberOperation(T node); - - void copyOperation(T from, T to); + default boolean foundMemberOperation(T node) { + return getParent().foundMemberOperation(node); + } + default void copyOperation(T from, T to) { + getParent().copyOperation(from, to); + } } public static class RootContext, T> extends TranslatorToCAst.RootContext implements WalkContext { + @Override + public WalkContext getParent() { + assert false; + return null; + } + @Override public String script() { return null; } @@ -98,35 +109,34 @@ public interface JavaScriptTranslatorToCAst extends TranslatorToCAst { } - class DelegatingContext, T> extends TranslatorToCAst.DelegatingContext implements WalkContext { + public static class FunctionContext, T> extends TranslatorToCAst.FunctionContext implements WalkContext { - protected DelegatingContext(C parent) { - super(parent); + private final Vector initializers = new Vector<>(); + + + @Override + public WalkContext getParent() { + return (WalkContext) super.getParent(); } + protected FunctionContext(C parent, T s) { + super(parent, s); + } + + @Override + public void addNameDecl(CAstNode v) { initializers.add(v); } + + @Override + public Collection getNameDecls() { return initializers; } + @Override public String script() { return parent.script(); } - @Override - public T top() { - return parent.top(); - } - - @Override - public void addNameDecl(CAstNode n) { - parent.addNameDecl(n); - } - - @Override - public Collection getNameDecls() { - return parent.getNameDecls(); - } - @Override public CAstNode getCatchTarget() { - return parent.getCatchTarget(); + return CAstControlFlowMap.EXCEPTION_TO_EXIT; } @Override @@ -143,51 +153,6 @@ public interface JavaScriptTranslatorToCAst extends TranslatorToCAst { public void copyOperation(T from, T to) { parent.copyOperation(from, to); } - - } - - public static class FunctionContext, T> extends DelegatingContext { - private final T topNode; - private final CAstSourcePositionRecorder pos = new CAstSourcePositionRecorder(); - private final CAstControlFlowRecorder cfg = new CAstControlFlowRecorder(pos); - private final Map> scopedEntities = HashMapFactory.make(); - private final Vector initializers = new Vector<>(); - - protected FunctionContext(C parent, T s) { - super(parent); - this.topNode = s; - } - - @Override - public T top() { return topNode; } - - @Override - public CAstNode getCatchTarget() { return CAstControlFlowMap.EXCEPTION_TO_EXIT; } - - @Override - public void addScopedEntity(CAstNode construct, CAstEntity e) { - if (! scopedEntities.containsKey(construct)) { - scopedEntities.put(construct, new HashSet(1)); - } - scopedEntities.get(construct).add(e); - } - - @Override - public Map> getScopedEntities() { - return scopedEntities; - } - - @Override - public void addNameDecl(CAstNode v) { initializers.add(v); } - - @Override - public Collection getNameDecls() { return initializers; } - - @Override - public CAstControlFlowRecorder cfg() { return cfg; } - - @Override - public CAstSourcePositionRecorder pos() { return pos; } } public static class ScriptContext, T> extends FunctionContext { @@ -202,48 +167,6 @@ public interface JavaScriptTranslatorToCAst extends TranslatorToCAst { public String script() { return script; } } - public static class TryCatchContext, T> extends DelegatingContext { - private final CAstNode catchNode; - - protected TryCatchContext(C parent, CAstNode catchNode) { - super(parent); - this.catchNode = catchNode; - } - - @Override - public CAstNode getCatchTarget() { return catchNode; } - } - - class BreakContext, T> extends DelegatingContext { - private final T breakTarget; - protected final String label; - - protected BreakContext(C parent, T breakTarget, String label) { - super(parent); - this.breakTarget = breakTarget; - this.label = label; - } - - @Override - public T getBreakFor(String l) { - return (l == null || l.equals(label))? breakTarget: super.getBreakFor(l); - } - } - - public class LoopContext, T> extends BreakContext { - private final T continueTo; - - protected LoopContext(C parent, T breakTo, T continueTo, String label) { - super(parent, breakTo, label); - this.continueTo = continueTo; - } - - @Override - public T getContinueFor(String l) { - return (l == null || l.equals(label))? continueTo: super.getContinueFor(l); - } - } - /** * Used to determine the value to be passed as the 'this' argument for a * function call. This is needed since in JavaScript, you can write a call @@ -255,7 +178,8 @@ public interface JavaScriptTranslatorToCAst extends TranslatorToCAst { * 'this' parameter in baseVar, and then to use baseVar as the actual argument * sub-node for the CAst call node */ - public class MemberDestructuringContext, T> extends DelegatingContext { + public class MemberDestructuringContext, T> implements WalkContext { + private final WalkContext parent; /** * node for which we actually care about what the base pointer is. this @@ -272,7 +196,7 @@ public interface JavaScriptTranslatorToCAst extends TranslatorToCAst { private boolean foundBase = false; protected MemberDestructuringContext(C parent, T initialBaseFor, int operationIndex) { - super(parent); + this.parent = parent; baseFor.add( initialBaseFor ); this.operationIndex = operationIndex; } @@ -296,6 +220,11 @@ public interface JavaScriptTranslatorToCAst extends TranslatorToCAst { public void copyOperation(T from, T to) { if (baseFor.contains(from)) baseFor.add(to); } + + @Override + public WalkContext getParent() { + return parent; + } } } diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AbstractCodeEntity.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AbstractCodeEntity.java index d288d5f5e..1a771e04b 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AbstractCodeEntity.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AbstractCodeEntity.java @@ -16,7 +16,6 @@ package com.ibm.wala.cast.ir.translator; import com.ibm.wala.cast.tree.CAstControlFlowMap; import com.ibm.wala.cast.tree.CAstNode; -import com.ibm.wala.cast.tree.CAstNodeTypeMap; import com.ibm.wala.cast.tree.CAstSourcePositionMap; import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; import com.ibm.wala.cast.tree.CAstType; @@ -60,7 +59,7 @@ public abstract class AbstractCodeEntity extends AbstractEntity { } @Override - public CAstNodeTypeMap getNodeTypeMap() { + public CAstNodeTypeMapRecorder getNodeTypeMap() { return types; } diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AbstractFieldEntity.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AbstractFieldEntity.java index f159b2707..ac74817f4 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AbstractFieldEntity.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AbstractFieldEntity.java @@ -23,7 +23,7 @@ import com.ibm.wala.cast.tree.CAstQualifier; import com.ibm.wala.cast.tree.CAstType; import com.ibm.wala.util.debug.Assertions; -class AbstractFieldEntity extends AbstractDataEntity { +public class AbstractFieldEntity extends AbstractDataEntity { private final String name; private final Set modifiers; diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/TranslatorToCAst.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/TranslatorToCAst.java index ed27770e0..7e92d280a 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/TranslatorToCAst.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/TranslatorToCAst.java @@ -13,6 +13,7 @@ package com.ibm.wala.cast.ir.translator; import java.io.IOException; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -28,6 +29,7 @@ import com.ibm.wala.cast.tree.rewrite.CAstRewriter.CopyKey; import com.ibm.wala.cast.tree.rewrite.CAstRewriter.RewriteContext; import com.ibm.wala.cast.tree.rewrite.CAstRewriterFactory; import com.ibm.wala.util.WalaException; +import com.ibm.wala.util.collections.HashMapFactory; import com.ibm.wala.util.warnings.Warning; public interface TranslatorToCAst { @@ -48,42 +50,70 @@ public interface TranslatorToCAst { public interface WalkContext, T> { + WalkContext getParent(); + /** * get a mapping from CAstNodes to the scoped entities (e.g. functions or * local classes) introduced by those nodes. Also maps null to * those entities not corresponding to any node (e.g nested classes) */ - Map> getScopedEntities(); + default Map> getScopedEntities() { + return getParent().getScopedEntities(); + } + + default CAstNode getCatchTarget() { + return getParent().getCatchTarget(); + } + + default CAstNode getCatchTarget(String s) { + return getParent().getCatchTarget(s); + } + + default T top() { + return getParent().top(); + } /** * associate a child entity with a given CAstNode, e.g. for a function declaration */ - void addScopedEntity(CAstNode newNode, CAstEntity visit); + default void addScopedEntity(CAstNode newNode, CAstEntity visit) { + getParent().addScopedEntity(newNode, visit); + } /** * for recording control-flow relationships among the CAst nodes */ - CAstControlFlowRecorder cfg(); + default CAstControlFlowRecorder cfg() { + return getParent().cfg(); + } /** * for recording source positions */ - CAstSourcePositionRecorder pos(); + default CAstSourcePositionRecorder pos() { + return getParent().pos(); + } /** * for recording types of nodes */ - CAstNodeTypeMapRecorder getNodeTypeMap(); + default CAstNodeTypeMapRecorder getNodeTypeMap() { + return getParent().getNodeTypeMap(); + } /** * for a 'continue' style goto, return the control flow target */ - T getContinueFor(String label); - + default T getContinueFor(String label) { + return getParent().getContinueFor(label); + } + /** * for a 'break' style goto, return the control flow target */ - T getBreakFor(String label); + default T getBreakFor(String label) { + return getParent().getBreakFor(label); + } } @@ -128,6 +158,18 @@ public interface TranslatorToCAst { assert false; return null; } + + @Override + public T top() { + assert false; + return null; + } + + @Override + public WalkContext getParent() { + assert false; + return null; + } } @@ -139,42 +181,106 @@ public interface TranslatorToCAst { } @Override - public CAstControlFlowRecorder cfg() { - return parent.cfg(); + public T top() { + return parent.top(); } @Override - public CAstSourcePositionRecorder pos() { - return parent.pos(); - } - - @Override - public CAstNodeTypeMapRecorder getNodeTypeMap() { - return parent.getNodeTypeMap(); - } - - @Override - public T getContinueFor(String label) { - return parent.getContinueFor(label); - } - - @Override - public T getBreakFor(String label) { - return parent.getBreakFor(label); - } - - @Override - public void addScopedEntity(CAstNode newNode, CAstEntity visit) { - parent.addScopedEntity(newNode, visit); - } - - @Override - public Map> getScopedEntities() { - return parent.getScopedEntities(); + public WalkContext getParent() { + return parent; } } + class BreakContext, T> extends DelegatingContext { + private final T breakTarget; + protected final String label; + + protected BreakContext(C parent, T breakTarget, String label) { + super(parent); + this.breakTarget = breakTarget; + this.label = label; + } + + @Override + public T getBreakFor(String l) { + return (l == null || l.equals(label))? breakTarget: super.getBreakFor(l); + } + } + + public class LoopContext, T> extends BreakContext { + private final T continueTo; + + protected LoopContext(C parent, T breakTo, T continueTo, String label) { + super(parent, breakTo, label); + this.continueTo = continueTo; + } + + @Override + public T getContinueFor(String l) { + return (l == null || l.equals(label))? continueTo: super.getContinueFor(l); + } + } + + public static class TryCatchContext, T> implements WalkContext { + private final Map catchNode; + private final WalkContext parent; + + protected TryCatchContext(C parent, CAstNode catchNode) { + this(parent, Collections.singletonMap(null, catchNode)); + } + + protected TryCatchContext(C parent, Map catchNode) { + this.parent = parent; + this.catchNode = catchNode; + } + + @Override + public CAstNode getCatchTarget() { return getCatchTarget(null); } + + @Override + public CAstNode getCatchTarget(String s) { return catchNode.get(s); } + + @Override + public WalkContext getParent() { + return parent; + } + } + + public static class FunctionContext, T> extends DelegatingContext { + private final T topNode; + private final CAstSourcePositionRecorder pos = new CAstSourcePositionRecorder(); + private final CAstControlFlowRecorder cfg = new CAstControlFlowRecorder(pos); + private final Map> scopedEntities = HashMapFactory.make(); + + protected FunctionContext(C parent, T s) { + super(parent); + this.topNode = s; + } + + @Override + public T top() { return topNode; } + + @Override + public void addScopedEntity(CAstNode construct, CAstEntity e) { + if (! scopedEntities.containsKey(construct)) { + scopedEntities.put(construct, new HashSet(1)); + } + scopedEntities.get(construct).add(e); + } + + @Override + public Map> getScopedEntities() { + return scopedEntities; + } + + @Override + public CAstControlFlowRecorder cfg() { return cfg; } + + @Override + public CAstSourcePositionRecorder pos() { return pos; } + } + public static class DoLoopTranslator { private final boolean replicateForDoLoops; 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 8f16af2a1..7930098a2 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 @@ -158,9 +158,9 @@ public interface CAstNode { public static final int IS_DEFINED_EXPR = 128; public static final int MACRO_VAR = 129; public static final int NARY_EXPR = 130; - // 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 = 131; + public static final int COMPREHENSION_EXPR = 132; // explicit lexical scopes public static final int LOCAL_SCOPE = 200; diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstImpl.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstImpl.java index 86c265f4a..77dde1712 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstImpl.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstImpl.java @@ -79,7 +79,9 @@ public class CAstImpl implements CAst { public int hashCode() { int code = getKind() * (getChildCount() + 13); for (int i = 0; i < getChildCount() && i < 15; i++) { - code *= getChild(i).getKind(); + if (getChild(i) != null) { + code *= getChild(i).getKind(); + } } return code; diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstOperator.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstOperator.java index 192668fdb..f0106832f 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstOperator.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstOperator.java @@ -87,5 +87,7 @@ public class CAstOperator implements CAstNode { public final static CAstOperator OP_REL_OR = new CAstOperator("||"); public final static CAstOperator OP_BIT_XOR = new CAstOperator("^"); public final static CAstOperator OP_REL_XOR = new CAstOperator("^^"); + public final static CAstOperator OP_IN = new CAstOperator("in"); + } diff --git a/com.ibm.wala.core/src/com/ibm/wala/cfg/ShrikeCFG.java b/com.ibm.wala.core/src/com/ibm/wala/cfg/ShrikeCFG.java index 7ac141fcf..1d5146a31 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/cfg/ShrikeCFG.java +++ b/com.ibm.wala.core/src/com/ibm/wala/cfg/ShrikeCFG.java @@ -330,13 +330,19 @@ public class ShrikeCFG extends AbstractCFG i } else { TypeReference caughtException = null; if (element.getCatchClass() != null) { - ClassLoaderReference loader = ShrikeCFG.this.getMethod().getDeclaringClass().getReference().getClassLoader(); + ClassLoaderReference loader = + element.getCatchClassLoader() == null? + ShrikeCFG.this.getMethod().getDeclaringClass().getReference().getClassLoader(): + (ClassLoaderReference)element.getCatchClassLoader(); caughtException = ShrikeUtil.makeTypeReference(loader, element.getCatchClass()); - if (DEBUG) { + //if (DEBUG) { System.err.println(" caughtException " + caughtException); - } + //} IClass caughtClass = cha.lookupClass(caughtException); - if (caughtClass == null) { + //if (DEBUG) { + System.err.println(" caughtException class " + caughtClass); + //} + if (caughtClass == null) { // conservatively add the edge, and raise a warning addExceptionalEdgeTo(b); Warnings.add(FailedExceptionResolutionWarning.create(caughtException)); diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/ClassHierarchy.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/ClassHierarchy.java index a02126813..9195473ed 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/ClassHierarchy.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/ClassHierarchy.java @@ -147,7 +147,7 @@ public class ClassHierarchy implements IClassHierarchy { klass = klass.getSuperclass(); - while (klass != null) { + while (klass != null) { if (DEBUG) { System.err.println("got superclass " + klass); } @@ -295,6 +295,7 @@ public class ClassHierarchy implements IClassHierarchy { */ @Override public boolean addClass(IClass klass) { + if (klass == null) { throw new IllegalArgumentException("klass is null"); } @@ -325,7 +326,7 @@ public class ClassHierarchy implements IClassHierarchy { if (klass.getReference().equals(this.rootTypeRef)) { // there is only one root - assert root == null; + assert root == null || root == node; root = node; } @@ -342,6 +343,10 @@ public class ClassHierarchy implements IClassHierarchy { } supernode.addChild(node); if (supernode.getJavaClass().getReference().equals(rootTypeRef)) { + + assert root == null || root == supernode; + root = supernode; + node = null; } else { node = supernode; diff --git a/com.ibm.wala.core/src/com/ibm/wala/ssa/SSACFG.java b/com.ibm.wala.core/src/com/ibm/wala/ssa/SSACFG.java index 0350c0fce..508afb0a2 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ssa/SSACFG.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ssa/SSACFG.java @@ -30,6 +30,7 @@ import com.ibm.wala.classLoader.IClassLoader; import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.shrikeBT.ExceptionHandler; import com.ibm.wala.shrikeBT.IInstruction; +import com.ibm.wala.types.ClassLoaderReference; import com.ibm.wala.types.TypeReference; import com.ibm.wala.util.collections.EmptyIterator; import com.ibm.wala.util.collections.HashMapFactory; @@ -168,6 +169,8 @@ public class SSACFG implements ControlFlowGraph, if (handler.getCatchClass() == null) { // by convention, in ShrikeCT this means catch everything t = TypeReference.JavaLangThrowable; + } else if (handler.getCatchClassLoader() instanceof ClassLoaderReference) { + t = ShrikeUtil.makeTypeReference((ClassLoaderReference)handler.getCatchClassLoader(), handler.getCatchClass()); } else { TypeReference exceptionType = ShrikeUtil.makeTypeReference(loader.getReference(), handler.getCatchClass()); IClass klass = null; diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/ExceptionHandler.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/ExceptionHandler.java index 86f8c4df8..9287f8e26 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/ExceptionHandler.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/ExceptionHandler.java @@ -34,17 +34,24 @@ final public class ExceptionHandler { int handler; final String catchClass; + + final Object catchClassLoader; /** * @param handler the label for the handler code * @param catchClass the type of exception that should be caught (in JVM format), or null if all exceptions should be caught (as * with 'finally') */ - public ExceptionHandler(int handler, String catchClass) { + public ExceptionHandler(int handler, String catchClass, Object catchClassLoader) { this.handler = handler; this.catchClass = catchClass; + this.catchClassLoader = catchClassLoader; } + public ExceptionHandler(int handler, String catchClass) { + this(handler, catchClass, null); + } + /** * @return the label of the handler code */ @@ -52,6 +59,10 @@ final public class ExceptionHandler { return handler; } + public Object getCatchClassLoader() { + return catchClassLoader; + } + /** * @return the type of exceptions to be caught, or null if all exceptions should be caught */