refactoring of CAst front end machinery to allow more reuse

This commit is contained in:
Julian Dolby 2018-01-25 14:42:27 -05:00
parent 8796653292
commit cd944a8f12
16 changed files with 265 additions and 186 deletions

View File

@ -11,3 +11,4 @@ javacProjectSettings = true
bin.excludes = dat/core-modules/.eslintrc,\ bin.excludes = dat/core-modules/.eslintrc,\
dat/core-modules/.gitignore,\ dat/core-modules/.gitignore,\
dat/core-modules/.gitkeep dat/core-modules/.gitkeep
javacDefaultEncoding.. = UTF-8

View File

@ -38,15 +38,15 @@ public class FieldBasedCGGamesTest extends AbstractFieldBasedTest {
runTestExceptOnTravis(new URL("http://www.inmensia.com/files/solitaire1.0.html"), new Object[][]{}, BuilderType.OPTIMISTIC); 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 { public void testWorldOfSolitaire() throws IOException, WalaException, Error, CancelException {
runTestExceptOnTravis(new URL("http://worldofsolitaire.com/"), new Object[][]{}, BuilderType.OPTIMISTIC); runTestExceptOnTravis(new URL("http://worldofsolitaire.com/"), new Object[][]{}, BuilderType.OPTIMISTIC);
if (System.getenv("TRAVIS") != null) { if (System.getenv("TRAVIS") != null) {
// fake it // fake it
throw new CancelException(null); // throw new CancelException(null);
} }
} }
@Test @Test
public void testMinesweeper() throws IOException, WalaException, Error, CancelException { public void testMinesweeper() throws IOException, WalaException, Error, CancelException {
runTestExceptOnTravis(new URL("http://www.inmensia.com/files/minesweeper1.0.html"), new Object[][]{}, BuilderType.OPTIMISTIC_WORKLIST); runTestExceptOnTravis(new URL("http://www.inmensia.com/files/minesweeper1.0.html"), new Object[][]{}, BuilderType.OPTIMISTIC_WORKLIST);

View File

@ -15,8 +15,8 @@ compilers.p.discouraged-class=0
compilers.p.internal=0 compilers.p.internal=0
compilers.p.missing-packages=0 compilers.p.missing-packages=0
compilers.p.missing-version-export-package=2 compilers.p.missing-version-export-package=2
compilers.p.missing-version-import-package=0 compilers.p.missing-version-import-package=2
compilers.p.missing-version-require-bundle=0 compilers.p.missing-version-require-bundle=2
compilers.p.no-required-att=0 compilers.p.no-required-att=0
compilers.p.not-externalized-att=0 compilers.p.not-externalized-att=0
compilers.p.unknown-attribute=0 compilers.p.unknown-attribute=0

View File

@ -4,9 +4,10 @@ Bundle-Name: %Bundle-Name
Bundle-SymbolicName: com.ibm.wala.cast.js.rhino Bundle-SymbolicName: com.ibm.wala.cast.js.rhino
Bundle-Version: 1.4.4.qualifier Bundle-Version: 1.4.4.qualifier
Bundle-Vendor: %Bundle-Vendor Bundle-Vendor: %Bundle-Vendor
Require-Bundle: com.ibm.wala.cast;bundle-version="1.0.0", Require-Bundle: com.ibm.wala.cast;bundle-version="1.4.4",
com.ibm.wala.cast.js;bundle-version="1.0.0", com.ibm.wala.cast.js;bundle-version="1.4.4",
com.ibm.wala.core;bundle-version="1.1.3" com.ibm.wala.core;bundle-version="1.4.4",
com.ibm.wala.util;bundle-version="1.4.4"
Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy Bundle-ActivationPolicy: lazy
Export-Package: com.ibm.wala.cast.js.translator, Export-Package: com.ibm.wala.cast.js.translator,

View File

@ -159,10 +159,9 @@ public class RhinoToAstTranslator implements TranslatorToCAst {
*/ */
private static class FunctionContext extends JavaScriptTranslatorToCAst.FunctionContext<WalkContext,Node> implements WalkContext { private static class FunctionContext extends JavaScriptTranslatorToCAst.FunctionContext<WalkContext,Node> implements WalkContext {
FunctionContext(WalkContext parent, Node s) { FunctionContext(WalkContext parent, Node s) {
super(parent, s); super(parent, s);
} }
}
}
/** /**
* context used for top-level script declarations * context used for top-level script declarations
@ -191,26 +190,41 @@ public class RhinoToAstTranslator implements TranslatorToCAst {
private static class BreakContext extends JavaScriptTranslatorToCAst.BreakContext<WalkContext, Node> implements WalkContext { private static class BreakContext extends JavaScriptTranslatorToCAst.BreakContext<WalkContext, Node> implements WalkContext {
@Override
public WalkContext getParent() {
return (WalkContext) super.getParent();
}
BreakContext(WalkContext parent, Node breakTo, String label) { BreakContext(WalkContext parent, Node breakTo, String label) {
super(parent, breakTo, label); super(parent, breakTo, label);
} }
} }
private static class LoopContext extends JavaScriptTranslatorToCAst.LoopContext<WalkContext, Node> implements WalkContext { private static class LoopContext extends TranslatorToCAst.LoopContext<WalkContext, Node> implements WalkContext {
LoopContext(WalkContext parent, Node breakTo, Node continueTo, String label) { LoopContext(WalkContext parent, Node breakTo, Node continueTo, String label) {
super(parent, breakTo, continueTo, label); super(parent, breakTo, continueTo, label);
} }
@Override
public WalkContext getParent() {
return (WalkContext) super.getParent();
} }
private static class TryCatchContext extends JavaScriptTranslatorToCAst.TryCatchContext<WalkContext, Node> implements WalkContext { }
private static class TryCatchContext extends TranslatorToCAst.TryCatchContext<WalkContext, Node> implements WalkContext {
TryCatchContext(WalkContext parent, CAstNode catchNode) { TryCatchContext(WalkContext parent, CAstNode catchNode) {
super(parent, catchNode); super(parent, catchNode);
} }
@Override
public WalkContext getParent() {
return (WalkContext) super.getParent();
}
} }
private static String operationReceiverName(int operationIndex) { private static String operationReceiverName(int operationIndex) {

View File

@ -12,26 +12,24 @@ package com.ibm.wala.cast.js.translator;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.Vector; import java.util.Vector;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst; import com.ibm.wala.cast.ir.translator.TranslatorToCAst;
import com.ibm.wala.cast.tree.CAstControlFlowMap; 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.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; import com.ibm.wala.util.debug.Assertions;
public interface JavaScriptTranslatorToCAst extends TranslatorToCAst { public interface JavaScriptTranslatorToCAst extends TranslatorToCAst {
interface WalkContext<C extends WalkContext<C, T>, T> extends TranslatorToCAst.WalkContext<C, T> { interface WalkContext<C extends WalkContext<C, T>, T> extends TranslatorToCAst.WalkContext<C, T> {
String script(); @Override
WalkContext<C, T> getParent();
T top(); default String script() {
return getParent().script();
}
/** /**
* Add a name declaration to this context. For variables or constants, n * 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 * variable (if any) may occur in a separate assignment. For functions, n
* should be a {@link CAstNode#FUNCTION_STMT}, including the function body. * should be a {@link CAstNode#FUNCTION_STMT}, including the function body.
*/ */
void addNameDecl(CAstNode n); default void addNameDecl(CAstNode n) {
getParent().addNameDecl(n);
}
Collection<CAstNode> getNameDecls(); default Collection<CAstNode> getNameDecls() {
return getParent().getNameDecls();
}
CAstNode getCatchTarget(); default int setOperation(T node) {
return getParent().setOperation(node);
}
int setOperation(T node); default boolean foundMemberOperation(T node) {
return getParent().foundMemberOperation(node);
boolean foundMemberOperation(T node); }
void copyOperation(T from, T to);
default void copyOperation(T from, T to) {
getParent().copyOperation(from, to);
}
} }
public static class RootContext<C extends WalkContext<C, T>, T> extends TranslatorToCAst.RootContext<C, T> implements WalkContext<C,T> { public static class RootContext<C extends WalkContext<C, T>, T> extends TranslatorToCAst.RootContext<C, T> implements WalkContext<C,T> {
@Override
public WalkContext<C, T> getParent() {
assert false;
return null;
}
@Override @Override
public String script() { return null; } public String script() { return null; }
@ -98,35 +109,34 @@ public interface JavaScriptTranslatorToCAst extends TranslatorToCAst {
} }
class DelegatingContext<C extends WalkContext<C, T>, T> extends TranslatorToCAst.DelegatingContext<C, T> implements WalkContext<C,T> { public static class FunctionContext<C extends WalkContext<C, T>, T> extends TranslatorToCAst.FunctionContext<C, T> implements WalkContext<C,T> {
protected DelegatingContext(C parent) { private final Vector<CAstNode> initializers = new Vector<>();
super(parent);
@Override
public WalkContext<C, T> getParent() {
return (WalkContext<C, T>) super.getParent();
} }
protected FunctionContext(C parent, T s) {
super(parent, s);
}
@Override
public void addNameDecl(CAstNode v) { initializers.add(v); }
@Override
public Collection<CAstNode> getNameDecls() { return initializers; }
@Override @Override
public String script() { public String script() {
return parent.script(); return parent.script();
} }
@Override
public T top() {
return parent.top();
}
@Override
public void addNameDecl(CAstNode n) {
parent.addNameDecl(n);
}
@Override
public Collection<CAstNode> getNameDecls() {
return parent.getNameDecls();
}
@Override @Override
public CAstNode getCatchTarget() { public CAstNode getCatchTarget() {
return parent.getCatchTarget(); return CAstControlFlowMap.EXCEPTION_TO_EXIT;
} }
@Override @Override
@ -143,51 +153,6 @@ public interface JavaScriptTranslatorToCAst extends TranslatorToCAst {
public void copyOperation(T from, T to) { public void copyOperation(T from, T to) {
parent.copyOperation(from, to); parent.copyOperation(from, to);
} }
}
public static class FunctionContext<C extends WalkContext<C, T>, T> extends DelegatingContext<C,T> {
private final T topNode;
private final CAstSourcePositionRecorder pos = new CAstSourcePositionRecorder();
private final CAstControlFlowRecorder cfg = new CAstControlFlowRecorder(pos);
private final Map<CAstNode, Collection<CAstEntity>> scopedEntities = HashMapFactory.make();
private final Vector<CAstNode> 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<CAstEntity>(1));
}
scopedEntities.get(construct).add(e);
}
@Override
public Map<CAstNode, Collection<CAstEntity>> getScopedEntities() {
return scopedEntities;
}
@Override
public void addNameDecl(CAstNode v) { initializers.add(v); }
@Override
public Collection<CAstNode> getNameDecls() { return initializers; }
@Override
public CAstControlFlowRecorder cfg() { return cfg; }
@Override
public CAstSourcePositionRecorder pos() { return pos; }
} }
public static class ScriptContext<C extends WalkContext<C, T>, T> extends FunctionContext<C,T> { public static class ScriptContext<C extends WalkContext<C, T>, T> extends FunctionContext<C,T> {
@ -202,48 +167,6 @@ public interface JavaScriptTranslatorToCAst extends TranslatorToCAst {
public String script() { return script; } public String script() { return script; }
} }
public static class TryCatchContext<C extends WalkContext<C, T>, T> extends DelegatingContext<C,T> {
private final CAstNode catchNode;
protected TryCatchContext(C parent, CAstNode catchNode) {
super(parent);
this.catchNode = catchNode;
}
@Override
public CAstNode getCatchTarget() { return catchNode; }
}
class BreakContext<C extends WalkContext<C, T>, T> extends DelegatingContext<C,T> {
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<C extends WalkContext<C, T>, T> extends BreakContext<C,T> {
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 * 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 * 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 * 'this' parameter in baseVar, and then to use baseVar as the actual argument
* sub-node for the CAst call node * sub-node for the CAst call node
*/ */
public class MemberDestructuringContext<C extends WalkContext<C, T>, T> extends DelegatingContext<C,T> { public class MemberDestructuringContext<C extends WalkContext<C, T>, T> implements WalkContext<C,T> {
private final WalkContext<C, T> parent;
/** /**
* node for which we actually care about what the base pointer is. this * 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; private boolean foundBase = false;
protected MemberDestructuringContext(C parent, T initialBaseFor, int operationIndex) { protected MemberDestructuringContext(C parent, T initialBaseFor, int operationIndex) {
super(parent); this.parent = parent;
baseFor.add( initialBaseFor ); baseFor.add( initialBaseFor );
this.operationIndex = operationIndex; this.operationIndex = operationIndex;
} }
@ -296,6 +220,11 @@ public interface JavaScriptTranslatorToCAst extends TranslatorToCAst {
public void copyOperation(T from, T to) { public void copyOperation(T from, T to) {
if (baseFor.contains(from)) baseFor.add(to); if (baseFor.contains(from)) baseFor.add(to);
} }
@Override
public WalkContext<C, T> getParent() {
return parent;
}
} }
} }

View File

@ -16,7 +16,6 @@ package com.ibm.wala.cast.ir.translator;
import com.ibm.wala.cast.tree.CAstControlFlowMap; import com.ibm.wala.cast.tree.CAstControlFlowMap;
import com.ibm.wala.cast.tree.CAstNode; 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;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.cast.tree.CAstType; import com.ibm.wala.cast.tree.CAstType;
@ -60,7 +59,7 @@ public abstract class AbstractCodeEntity extends AbstractEntity {
} }
@Override @Override
public CAstNodeTypeMap getNodeTypeMap() { public CAstNodeTypeMapRecorder getNodeTypeMap() {
return types; return types;
} }

View File

@ -23,7 +23,7 @@ import com.ibm.wala.cast.tree.CAstQualifier;
import com.ibm.wala.cast.tree.CAstType; import com.ibm.wala.cast.tree.CAstType;
import com.ibm.wala.util.debug.Assertions; import com.ibm.wala.util.debug.Assertions;
class AbstractFieldEntity extends AbstractDataEntity { public class AbstractFieldEntity extends AbstractDataEntity {
private final String name; private final String name;
private final Set<CAstQualifier> modifiers; private final Set<CAstQualifier> modifiers;

View File

@ -13,6 +13,7 @@ package com.ibm.wala.cast.ir.translator;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; 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.CAstRewriter.RewriteContext;
import com.ibm.wala.cast.tree.rewrite.CAstRewriterFactory; import com.ibm.wala.cast.tree.rewrite.CAstRewriterFactory;
import com.ibm.wala.util.WalaException; import com.ibm.wala.util.WalaException;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.warnings.Warning; import com.ibm.wala.util.warnings.Warning;
public interface TranslatorToCAst { public interface TranslatorToCAst {
@ -48,42 +50,70 @@ public interface TranslatorToCAst {
public interface WalkContext<C extends WalkContext<C, T>, T> { public interface WalkContext<C extends WalkContext<C, T>, T> {
WalkContext<C, T> getParent();
/** /**
* get a mapping from CAstNodes to the scoped entities (e.g. functions or * get a mapping from CAstNodes to the scoped entities (e.g. functions or
* local classes) introduced by those nodes. Also maps <code>null</code> to * local classes) introduced by those nodes. Also maps <code>null</code> to
* those entities not corresponding to any node (e.g nested classes) * those entities not corresponding to any node (e.g nested classes)
*/ */
Map<CAstNode, Collection<CAstEntity>> getScopedEntities(); default Map<CAstNode, Collection<CAstEntity>> 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 * 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 * for recording control-flow relationships among the CAst nodes
*/ */
CAstControlFlowRecorder cfg(); default CAstControlFlowRecorder cfg() {
return getParent().cfg();
}
/** /**
* for recording source positions * for recording source positions
*/ */
CAstSourcePositionRecorder pos(); default CAstSourcePositionRecorder pos() {
return getParent().pos();
}
/** /**
* for recording types of nodes * for recording types of nodes
*/ */
CAstNodeTypeMapRecorder getNodeTypeMap(); default CAstNodeTypeMapRecorder getNodeTypeMap() {
return getParent().getNodeTypeMap();
}
/** /**
* for a 'continue' style goto, return the control flow target * 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 * 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; assert false;
return null; return null;
} }
@Override
public T top() {
assert false;
return null;
}
@Override
public WalkContext<C, T> getParent() {
assert false;
return null;
}
} }
@ -139,42 +181,106 @@ public interface TranslatorToCAst {
} }
@Override @Override
public CAstControlFlowRecorder cfg() { public T top() {
return parent.cfg(); return parent.top();
} }
@Override @Override
public CAstSourcePositionRecorder pos() { public WalkContext<C, T> getParent() {
return parent.pos(); return parent;
}
@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<CAstNode, Collection<CAstEntity>> getScopedEntities() {
return parent.getScopedEntities();
} }
} }
class BreakContext<C extends WalkContext<C, T>, T> extends DelegatingContext<C,T> {
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<C extends WalkContext<C, T>, T> extends BreakContext<C,T> {
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<C extends WalkContext<C, T>, T> implements WalkContext<C,T> {
private final Map<String,CAstNode> catchNode;
private final WalkContext<C,T> parent;
protected TryCatchContext(C parent, CAstNode catchNode) {
this(parent, Collections.singletonMap(null, catchNode));
}
protected TryCatchContext(C parent, Map<String,CAstNode> 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<C, T> getParent() {
return parent;
}
}
public static class FunctionContext<C extends WalkContext<C, T>, T> extends DelegatingContext<C,T> {
private final T topNode;
private final CAstSourcePositionRecorder pos = new CAstSourcePositionRecorder();
private final CAstControlFlowRecorder cfg = new CAstControlFlowRecorder(pos);
private final Map<CAstNode, Collection<CAstEntity>> 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<CAstEntity>(1));
}
scopedEntities.get(construct).add(e);
}
@Override
public Map<CAstNode, Collection<CAstEntity>> getScopedEntities() {
return scopedEntities;
}
@Override
public CAstControlFlowRecorder cfg() { return cfg; }
@Override
public CAstSourcePositionRecorder pos() { return pos; }
}
public static class DoLoopTranslator { public static class DoLoopTranslator {
private final boolean replicateForDoLoops; private final boolean replicateForDoLoops;

View File

@ -158,9 +158,9 @@ public interface CAstNode {
public static final int IS_DEFINED_EXPR = 128; public static final int IS_DEFINED_EXPR = 128;
public static final int MACRO_VAR = 129; public static final int MACRO_VAR = 129;
public static final int NARY_EXPR = 130; 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 // 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 NEW_ENCLOSING = 131;
public static final int COMPREHENSION_EXPR = 132;
// explicit lexical scopes // explicit lexical scopes
public static final int LOCAL_SCOPE = 200; public static final int LOCAL_SCOPE = 200;

View File

@ -79,7 +79,9 @@ public class CAstImpl implements CAst {
public int hashCode() { public int hashCode() {
int code = getKind() * (getChildCount() + 13); int code = getKind() * (getChildCount() + 13);
for (int i = 0; i < getChildCount() && i < 15; i++) { for (int i = 0; i < getChildCount() && i < 15; i++) {
code *= getChild(i).getKind(); if (getChild(i) != null) {
code *= getChild(i).getKind();
}
} }
return code; return code;

View File

@ -87,5 +87,7 @@ public class CAstOperator implements CAstNode {
public final static CAstOperator OP_REL_OR = new CAstOperator("||"); public final static CAstOperator OP_REL_OR = new CAstOperator("||");
public final static CAstOperator OP_BIT_XOR = 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_REL_XOR = new CAstOperator("^^");
public final static CAstOperator OP_IN = new CAstOperator("in");
} }

View File

@ -330,13 +330,19 @@ public class ShrikeCFG extends AbstractCFG<IInstruction, ShrikeCFG.BasicBlock> i
} else { } else {
TypeReference caughtException = null; TypeReference caughtException = null;
if (element.getCatchClass() != 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()); caughtException = ShrikeUtil.makeTypeReference(loader, element.getCatchClass());
if (DEBUG) { //if (DEBUG) {
System.err.println(" caughtException " + caughtException); System.err.println(" caughtException " + caughtException);
} //}
IClass caughtClass = cha.lookupClass(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 // conservatively add the edge, and raise a warning
addExceptionalEdgeTo(b); addExceptionalEdgeTo(b);
Warnings.add(FailedExceptionResolutionWarning.create(caughtException)); Warnings.add(FailedExceptionResolutionWarning.create(caughtException));

View File

@ -147,7 +147,7 @@ public class ClassHierarchy implements IClassHierarchy {
klass = klass.getSuperclass(); klass = klass.getSuperclass();
while (klass != null) { while (klass != null) {
if (DEBUG) { if (DEBUG) {
System.err.println("got superclass " + klass); System.err.println("got superclass " + klass);
} }
@ -295,6 +295,7 @@ public class ClassHierarchy implements IClassHierarchy {
*/ */
@Override @Override
public boolean addClass(IClass klass) { public boolean addClass(IClass klass) {
if (klass == null) { if (klass == null) {
throw new IllegalArgumentException("klass is null"); throw new IllegalArgumentException("klass is null");
} }
@ -325,7 +326,7 @@ public class ClassHierarchy implements IClassHierarchy {
if (klass.getReference().equals(this.rootTypeRef)) { if (klass.getReference().equals(this.rootTypeRef)) {
// there is only one root // there is only one root
assert root == null; assert root == null || root == node;
root = node; root = node;
} }
@ -342,6 +343,10 @@ public class ClassHierarchy implements IClassHierarchy {
} }
supernode.addChild(node); supernode.addChild(node);
if (supernode.getJavaClass().getReference().equals(rootTypeRef)) { if (supernode.getJavaClass().getReference().equals(rootTypeRef)) {
assert root == null || root == supernode;
root = supernode;
node = null; node = null;
} else { } else {
node = supernode; node = supernode;

View File

@ -30,6 +30,7 @@ import com.ibm.wala.classLoader.IClassLoader;
import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.shrikeBT.ExceptionHandler; import com.ibm.wala.shrikeBT.ExceptionHandler;
import com.ibm.wala.shrikeBT.IInstruction; import com.ibm.wala.shrikeBT.IInstruction;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.types.TypeReference; import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.collections.EmptyIterator; import com.ibm.wala.util.collections.EmptyIterator;
import com.ibm.wala.util.collections.HashMapFactory; import com.ibm.wala.util.collections.HashMapFactory;
@ -168,6 +169,8 @@ public class SSACFG implements ControlFlowGraph<SSAInstruction, ISSABasicBlock>,
if (handler.getCatchClass() == null) { if (handler.getCatchClass() == null) {
// by convention, in ShrikeCT this means catch everything // by convention, in ShrikeCT this means catch everything
t = TypeReference.JavaLangThrowable; t = TypeReference.JavaLangThrowable;
} else if (handler.getCatchClassLoader() instanceof ClassLoaderReference) {
t = ShrikeUtil.makeTypeReference((ClassLoaderReference)handler.getCatchClassLoader(), handler.getCatchClass());
} else { } else {
TypeReference exceptionType = ShrikeUtil.makeTypeReference(loader.getReference(), handler.getCatchClass()); TypeReference exceptionType = ShrikeUtil.makeTypeReference(loader.getReference(), handler.getCatchClass());
IClass klass = null; IClass klass = null;

View File

@ -34,17 +34,24 @@ final public class ExceptionHandler {
int handler; int handler;
final String catchClass; final String catchClass;
final Object catchClassLoader;
/** /**
* @param handler the label for the handler code * @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 * @param catchClass the type of exception that should be caught (in JVM format), or null if all exceptions should be caught (as
* with 'finally') * with 'finally')
*/ */
public ExceptionHandler(int handler, String catchClass) { public ExceptionHandler(int handler, String catchClass, Object catchClassLoader) {
this.handler = handler; this.handler = handler;
this.catchClass = catchClass; this.catchClass = catchClass;
this.catchClassLoader = catchClassLoader;
} }
public ExceptionHandler(int handler, String catchClass) {
this(handler, catchClass, null);
}
/** /**
* @return the label of the handler code * @return the label of the handler code
*/ */
@ -52,6 +59,10 @@ final public class ExceptionHandler {
return handler; return handler;
} }
public Object getCatchClassLoader() {
return catchClassLoader;
}
/** /**
* @return the type of exceptions to be caught, or null if all exceptions should be caught * @return the type of exceptions to be caught, or null if all exceptions should be caught
*/ */