}
public void buildtree(ParseNode pn, Set toanalyze, String sourcefile) {
- parseFile(pn, toanalyze,sourcefile);
+ parseFile(pn, toanalyze, sourcefile);
// numering the interfaces
int if_num = 0;
NameDescriptor packages;
/** Parse the classes in this file */
- public void parseFile(ParseNode pn, Set toanalyze,String sourcefile) {
- singleimports= new Hashtable();
+ public void parseFile(ParseNode pn, Set toanalyze, String sourcefile) {
+ singleimports=new Hashtable();
multiimports=new Vector();
ParseNode ipn=pn.getChild("imports").getChild("import_decls_list");
if (ipn!=null) {
// TODO need to implement
if (isNode(pnimport,"import_single"))
if(!singleimports.containsKey(nd.getIdentifier())) {
- //map name to full name (includes package/directory
- singleimports.put(nd.getIdentifier(), nd.getPathFromRootToHere(nd.getIdentifier()));
- } else {
- throw new Error("Error: class " + nd.getIdentifier() + " is already more than once in a single type import inside "+sourcefile);
- }
+ //map name to full name (includes package/directory
+ singleimports.put(nd.getIdentifier(), nd.getPathFromRootToHere(nd.getIdentifier()));
+ } else {
+ throw new Error("Error: class " + nd.getIdentifier() + " is already more than once in a single type import inside "+sourcefile);
+ }
else
- //TODO MULTI-IMPORTS!
+ //TODO MULTI-IMPORTS!
multiimports.add(nd);
}
}
continue;
if (isNode(type_pn, "class_declaration")) {
ClassDescriptor cn = parseTypeDecl(type_pn, packageName);
- cn.setImports(singleimports, multiimports);
cn.setSourceFileName(sourcefile);
parseInitializers(cn);
if (toanalyze != null)
private ClassDescriptor parseEnumDecl(ClassDescriptor cn, ParseNode pn) {
ClassDescriptor ecd=new ClassDescriptor(pn.getChild("name").getTerminal(), false);
+ ecd.setImports(singleimports, multiimports);
ecd.setAsEnum();
if(cn != null) {
ecd.setSurroundingClass(cn.getSymbol());
public ClassDescriptor parseInterfaceDecl(ParseNode pn) {
ClassDescriptor cn=new ClassDescriptor(pn.getChild("name").getTerminal(), true);
+ cn.setImports(singleimports, multiimports);
//cn.setAsInterface();
if (!isEmpty(pn.getChild("superIF").getTerminal())) {
/* parse inherited interface name */
String newClassname = packageName + "___________" + pn.getChild("name").getTerminal();
cn= new ClassDescriptor(packageName, newClassname.replaceAll("\\.", "___________") , false);
}
+ cn.setImports(singleimports, multiimports);
if (!isEmpty(pn.getChild("super").getTerminal())) {
/* parse superclass name */
ParseNode snn=pn.getChild("super").getChild("type").getChild("class").getChild("name");
private ClassDescriptor parseInnerClassDecl(ClassDescriptor cn, ParseNode pn) {
ClassDescriptor icn=new ClassDescriptor(pn.getChild("name").getTerminal(), false);
+ icn.setImports(singleimports, multiimports);
icn.setAsInnerClass();
icn.setSurroundingClass(cn.getSymbol());
icn.setSurrounding(cn);
TypeDescriptor td=parseTypeDescriptor(pn);
innerCount++;
ClassDescriptor cnnew=new ClassDescriptor(td.getSymbol()+"$"+innerCount, false);
+ cnnew.setImports(singleimports, multiimports);
cnnew.setSuper(td.getSymbol());
parseClassBody(cnnew, pn.getChild("decl").getChild("classbody"));
Vector args=parseArgumentList(pn);
return aan;
} else if (isNode(pn,"cast1")) {
try {
- CastNode cn=new CastNode(parseTypeDescriptor(pn.getChild("type")),parseExpression(pn.getChild("exp").getFirstChild()));
- cn.setNumLine(pn.getLine());
+ CastNode cn=new CastNode(parseTypeDescriptor(pn.getChild("type")),parseExpression(pn.getChild("exp").getFirstChild()));
+ cn.setNumLine(pn.getLine());
return cn;
} catch (Exception e) {
System.out.println(pn.PPrint(1,true));
import java.util.*;
import java.io.*;
import Util.Pair;
+import Analysis.CallGraph.CallGraph;
-public class JavaBuilder {
+public class JavaBuilder implements CallGraph {
State state;
HashSet<Descriptor> checkedDesc=new HashSet<Descriptor>();
HashMap<ClassDescriptor, Integer> classStatus=new HashMap<ClassDescriptor, Integer>();
BuildFlat bf;
Stack<MethodDescriptor> toprocess=new Stack<MethodDescriptor>();
HashSet<MethodDescriptor> discovered=new HashSet<MethodDescriptor>();
+ HashMap<MethodDescriptor, Set<MethodDescriptor>> canCall=new HashMap<MethodDescriptor, Set<MethodDescriptor>>();
+ MethodDescriptor mainMethod;
/* Maps class/interfaces to all instantiated classes that extend or
* implement those classes or interfaces */
HashMap<MethodDescriptor, Set<MethodDescriptor>> callMap=new HashMap<MethodDescriptor, Set<MethodDescriptor>>();
+ HashMap<MethodDescriptor, Set<MethodDescriptor>> revCallMap=new HashMap<MethodDescriptor, Set<MethodDescriptor>>();
+
/* Invocation map */
HashMap<ClassDescriptor, Set<Pair<MethodDescriptor, MethodDescriptor>>> invocationMap=new HashMap<ClassDescriptor, Set<Pair<MethodDescriptor, MethodDescriptor>>>();
+
+ public Set getAllMethods(Descriptor d) {
+ HashSet tovisit=new HashSet();
+ tovisit.add(d);
+ HashSet callable=new HashSet();
+ while(!tovisit.isEmpty()) {
+ Descriptor md=(Descriptor)tovisit.iterator().next();
+ tovisit.remove(md);
+ Set s=getCalleeSet(md);
+
+ if (s!=null) {
+ for(Iterator it=s.iterator(); it.hasNext();) {
+ MethodDescriptor md2=(MethodDescriptor)it.next();
+ if( !callable.contains(md2) ) {
+ callable.add(md2);
+ tovisit.add(md2);
+ }
+ }
+ }
+ }
+ return callable;
+ }
+
+ public Set getMethods(MethodDescriptor md, TypeDescriptor type) {
+ if (canCall.containsKey(md))
+ return canCall.get(md);
+ else
+ return new HashSet();
+ }
+
+ public Set getMethods(MethodDescriptor md) {
+ return getMethods(md, null);
+ }
+
+ public Set getMethodCalls(Descriptor d) {
+ Set set=getAllMethods(d);
+ set.add(d);
+ return set;
+ }
+ public boolean isCalled(MethodDescriptor md) {
+ return !getMethods(md).isEmpty();
+ }
+
+ public boolean isCallable(MethodDescriptor md) {
+ return !getCallerSet(md).isEmpty()||md==mainMethod;
+ }
+
+ public Set getCalleeSet(Descriptor d) {
+ Set calleeset=callMap.get((MethodDescriptor)d);
+ if (calleeset==null)
+ return new HashSet();
+ else
+ return calleeset;
+ }
+
+ public Set getCallerSet(MethodDescriptor md) {
+ Set callerset=revCallMap.get(md);
+ if (callerset==null)
+ return new HashSet();
+ else
+ return callerset;
+ }
+
+ public Set getFirstReachableMethodContainingSESE(Descriptor d,
+ Set<MethodDescriptor> methodsContainingSESEs) {
+ throw new Error("");
+ }
+
+ public boolean hasLayout(ClassDescriptor cd) {
+ return sc.hasLayout(cd);
+ }
public JavaBuilder(State state) {
this.state=state;
}
public void build() {
+ //Initialize Strings to keep runtime happy
+ ClassDescriptor stringClass=sc.getClass(null, TypeUtil.StringClass, SemanticCheck.INIT);
+ instantiateClass(stringClass);
+
ClassDescriptor mainClass=sc.getClass(null, state.main, SemanticCheck.INIT);
- MethodDescriptor mainMethod=tu.getMain();
+ mainMethod=tu.getMain();
+
+ canCall.put(mainMethod, new HashSet<MethodDescriptor>());
+ canCall.get(mainMethod).add(mainMethod);
+
toprocess.push(mainMethod);
computeFixPoint();
+ tu.createFullTable();
}
void checkMethod(MethodDescriptor md) {
}
}
- void initClassDesc(ClassDescriptor cd) {
- if (classStatus.get(cd)==null) {
- classStatus.put(cd, CDINIT);
- //TODO...LOOK FOR STATIC INITIALIZERS
+ public boolean isInit(ClassDescriptor cd) {
+ return classStatus.get(cd)!=null&&classStatus.get(cd)>=CDINIT;
+ }
+
+ void initClassDesc(ClassDescriptor cd, int init) {
+ if (classStatus.get(cd)==null||classStatus.get(cd)!=init) {
+ if (classStatus.get(cd)==null) {
+ MethodDescriptor mdstaticinit = (MethodDescriptor)cd.getMethodTable().get("staticblocks");
+ if (mdstaticinit!=null) {
+ discovered.add(mdstaticinit);
+ toprocess.push(mdstaticinit);
+ }
+ }
+ classStatus.put(cd, init);
}
}
while(!toprocess.isEmpty()) {
MethodDescriptor md=toprocess.pop();
checkMethod(md);
- initClassDesc(md.getClassDesc());
+ initClassDesc(md.getClassDesc(), CDINIT);
bf.flattenMethod(md.getClassDesc(), md);
processFlatMethod(md);
}
+
+ //make sure every called method descriptor has a flat method
+ for(MethodDescriptor callmd:canCall.keySet())
+ bf.addJustFlatMethod(callmd);
}
void processCall(MethodDescriptor md, FlatCall fcall) {
MethodDescriptor callmd=fcall.getMethod();
+ //make sure we have a FlatMethod for the base method...
+ if (!canCall.containsKey(callmd))
+ canCall.put(callmd, new HashSet<MethodDescriptor>());
//First handle easy cases...
if (callmd.isStatic()||callmd.isConstructor()) {
discovered.add(callmd);
toprocess.push(callmd);
}
+ if (!revCallMap.containsKey(callmd))
+ revCallMap.put(callmd, new HashSet<MethodDescriptor>());
+ revCallMap.get(callmd).add(md);
callMap.get(md).add(callmd);
+ canCall.get(callmd).add(callmd);
return;
}
if (!invocationMap.containsKey(cn))
invocationMap.put(cn, new HashSet<Pair<MethodDescriptor,MethodDescriptor>>());
invocationMap.get(cn).add(new Pair<MethodDescriptor, MethodDescriptor>(md, callmd));
+
+ if (impSet!=null) {
+ for(ClassDescriptor cdactual:impSet) {
+ searchimp:
+ while(cdactual!=null) {
+ Set possiblematches=cdactual.getMethodTable().getSetFromSameScope(callmd.getSymbol());
+
+ for(Iterator matchit=possiblematches.iterator(); matchit.hasNext();) {
+ MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
+ if (callmd.matches(matchmd)) {
+ //Found the method that will be called
+ if (!discovered.contains(matchmd)) {
+ discovered.add(matchmd);
+ toprocess.push(matchmd);
+ }
+
+ if (!revCallMap.containsKey(matchmd))
+ revCallMap.put(matchmd, new HashSet<MethodDescriptor>());
+ revCallMap.get(matchmd).add(md);
- for(ClassDescriptor cdactual:impSet) {
- searchimp:
- while(cdactual!=null) {
- Set possiblematches=cdactual.getMethodTable().getSetFromSameScope(callmd.getSymbol());
-
- for(Iterator matchit=possiblematches.iterator(); matchit.hasNext();) {
- MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
- if (callmd.matches(matchmd)) {
- //Found the method that will be called
- if (!discovered.contains(matchmd)) {
- discovered.add(matchmd);
- toprocess.push(matchmd);
+ callMap.get(md).add(matchmd);
+ canCall.get(callmd).add(matchmd);
+ break searchimp;
}
- callMap.get(md).add(matchmd);
-
- break searchimp;
}
+
+ //Didn't find method...look in super class
+ cdactual=cdactual.getSuperDesc();
}
-
- //Didn't find method...look in super class
- cdactual=cdactual.getSuperDesc();
}
}
}
if (!tdnew.isClass())
return;
ClassDescriptor cdnew=tdnew.getClassDesc();
+ //Make sure class is fully initialized
+ sc.checkClass(cdnew, SemanticCheck.INIT);
+ instantiateClass(cdnew);
+ }
+
+ void instantiateClass(ClassDescriptor cdnew) {
+ if (classStatus.containsKey(cdnew)&&classStatus.get(cdnew)==CDINSTANTIATED)
+ return;
+ initClassDesc(cdnew, CDINSTANTIATED);
+
Stack<ClassDescriptor> tovisit=new Stack<ClassDescriptor>();
tovisit.add(cdnew);
discovered.add(matchmd);
toprocess.push(matchmd);
}
+ if (!revCallMap.containsKey(matchmd))
+ revCallMap.put(matchmd, new HashSet<MethodDescriptor>());
+ revCallMap.get(matchmd).add(md);
callMap.get(md).add(matchmd);
+ canCall.get(callmd).add(matchmd);
break searchimp;
}
}
}
}
}
-
- public static ParseNode readSourceFile(State state, String sourcefile) {
- try {
- Reader fr= new BufferedReader(new FileReader(sourcefile));
- Lex.Lexer l = new Lex.Lexer(fr);
- java_cup.runtime.lr_parser g;
- g = new Parse.Parser(l);
- ParseNode p=null;
- try {
- p=(ParseNode) g./*debug_*/parse().value;
- } catch (Exception e) {
- System.err.println("Error parsing file:"+sourcefile);
- e.printStackTrace();
- System.exit(-1);
- }
- state.addParseNode(p);
- if (l.numErrors()!=0) {
- System.out.println("Error parsing "+sourcefile);
- System.exit(l.numErrors());
- }
- state.lines+=l.line_num;
- return p;
-
- } catch (Exception e) {
- throw new Error(e);
- }
- }
-
- public void loadClass(BuildIR bir, String sourcefile) {
- try {
- ParseNode pn=readSourceFile(state, sourcefile);
- bir.buildtree(pn, null,sourcefile);
- } catch (Exception e) {
- System.out.println("Error in sourcefile:"+sourcefile);
- e.printStackTrace();
- System.exit(-1);
- } catch (Error e) {
- System.out.println("Error in sourcefile:"+sourcefile);
- e.printStackTrace();
- System.exit(-1);
- }
- }
}
\ No newline at end of file
boolean checkAll;
+ public boolean hasLayout(ClassDescriptor cd) {
+ return completed.get(cd)!=null&&completed.get(cd)==INIT;
+ }
+
public SemanticCheck(State state, TypeUtil tu) {
this(state, tu, true);
}
return cd;
}
- private void checkClass(ClassDescriptor cd) {
+ public void checkClass(ClassDescriptor cd) {
checkClass(cd, INIT);
}
- private void checkClass(ClassDescriptor cd, int fullcheck) {
+ public void checkClass(ClassDescriptor cd, int fullcheck) {
if (!completed.containsKey(cd)||completed.get(cd)<fullcheck) {
int oldstatus=completed.containsKey(cd)?completed.get(cd):0;
completed.put(cd, fullcheck);
- if (fullcheck>=REFERENCE&&oldstatus<REFERENCE) {
+ if (fullcheck>=REFERENCE&&oldstatus<INIT) {
//Set superclass link up
if (cd.getSuper()!=null) {
cd.setSuper(getClass(cd, cd.getSuper(), fullcheck));
}
// Link together Field, Method, and Flag tables so classes
// inherit these from their superclasses
- cd.getFieldTable().setParent(cd.getSuperDesc().getFieldTable());
- cd.getMethodTable().setParent(cd.getSuperDesc().getMethodTable());
- cd.getFlagTable().setParent(cd.getSuperDesc().getFlagTable());
+ if (oldstatus<REFERENCE) {
+ cd.getFieldTable().setParent(cd.getSuperDesc().getFieldTable());
+ cd.getMethodTable().setParent(cd.getSuperDesc().getMethodTable());
+ cd.getFlagTable().setParent(cd.getSuperDesc().getFlagTable());
+ }
}
// Link together Field, Method tables do classes inherit these from
// their ancestor interfaces
if(!superif.isInterface()) {
throw new Error("Error! Class " + cd.getSymbol() + " implements non-interface " + superif.getSymbol());
}
- cd.addSuperInterfaces(superif);
- cd.getFieldTable().addParentIF(superif.getFieldTable());
- cd.getMethodTable().addParentIF(superif.getMethodTable());
+ if (oldstatus<REFERENCE) {
+ cd.addSuperInterfaces(superif);
+ cd.getFieldTable().addParentIF(superif.getFieldTable());
+ cd.getMethodTable().addParentIF(superif.getMethodTable());
+ }
}
}
if (oldstatus<INIT&&fullcheck>=INIT) {
if (!typetolookin.isArray()) {
// Array's don't need constructor calls
ClassDescriptor classtolookin = typetolookin.getClassDesc();
+ checkClass(classtolookin, INIT);
Set methoddescriptorset = classtolookin.getMethodTable().getSet(typetolookin.getSymbol());
MethodDescriptor bestmd = null;
if (!typetolookin.isClass())
throw new Error("Error with method call to "+min.getMethodName());
ClassDescriptor classtolookin=typetolookin.getClassDesc();
+ checkClass(classtolookin, INIT);
//System.out.println("Method name="+min.getMethodName());
Set methoddescriptorset=classtolookin.getMethodTable().getSet(min.getMethodName());