if (method.getCode().getLocalVariableTable() != null) {
continue;
}
}
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen,
sourceFileName, location.getHandle());
if (DEBUG) {
System.out.println(" Store at " + sourceLineAnnotation.getStartLine() + "@"
+ location.getHandle().getPosition() + " is " + (storeLive ? "live" : "dead"));
System.out.println("Previous is: " + location.getHandle().getPrev());
}
// Note source lines of live stores.
if (storeLive && sourceLineAnnotation.getStartLine() > 0) {
liveStoreSourceLineSet.set(sourceLineAnnotation.getStartLine());
}
String lvName = lvAnnotation.getName();
if (lvName.charAt(0) == '$' || lvName.charAt(0) == '_') {
propertySet.addProperty(DeadLocalStoreProperty.SYNTHETIC_NAME);
}
if (EXCLUDED_LOCALS.contains(lvName)) {
continue;
}
propertySet.setProperty(DeadLocalStoreProperty.LOCAL_NAME, lvName);
boolean isParameter = local < localsThatAreParameters;
if (isParameter) {
propertySet.addProperty(DeadLocalStoreProperty.IS_PARAMETER);
}
Field shadowedField = null;
for (Field f : javaClass.getFields()) {
if (f.getName().equals(lvName) && f.isStatic() == method.isStatic()) {
shadowedField = f;
propertySet.addProperty(DeadLocalStoreProperty.SHADOWS_FIELD);
break;
}
}
// Is this a store to a parameter which was dead on entry to the
// method?
boolean parameterThatIsDeadAtEntry = isParameter
&& !llsaDataflow.getAnalysis().isStoreAlive(liveStoreSetAtEntry, local);
if (parameterThatIsDeadAtEntry && !complainedAbout.get(local)) {
int priority = storeLive ? LOW_PRIORITY : NORMAL_PRIORITY;
if (shadowedField != null) {
priority--;
}
pendingBugReportAboutOverwrittenParameter = new BugInstance(this, "IP_PARAMETER_IS_DEAD_BUT_OVERWRITTEN",
priority).addClassAndMethod(methodGen, sourceFileName).add(lvAnnotation);
if (shadowedField != null) {
pendingBugReportAboutOverwrittenParameter.addField(
FieldAnnotation.fromBCELField(classContext.getJavaClass(), shadowedField)).describe(
FieldAnnotation.DID_YOU_MEAN_ROLE);
}
pendingBugReportAboutOverwrittenParameter.addSourceLine(classContext, methodGen, sourceFileName,
location.getHandle());
complainedAbout.set(local);
}
if (storeLive) {
continue;
}
TypeFrame typeFrame = typeDataflow.getAnalysis().getFactAtLocation(location);
Type typeOfValue = null;
if (typeFrame.isValid() && typeFrame.getStackDepth() > 0) {
typeOfValue = typeFrame.getTopValue();
}
boolean storeOfNull = false;
InstructionHandle prevInsHandle = location.getHandle().getPrev();
if (prevInsHandle != null) {
Instruction prevIns = prevInsHandle.getInstruction();
boolean foundDeadClassInitialization = false;
String initializationOf = null;
if (prevIns instanceof ConstantPushInstruction) {
continue; // not an interesting dead store
} else if (prevIns instanceof GETSTATIC) {
GETSTATIC getStatic = (GETSTATIC) prevIns;
ConstantPoolGen cpg = methodGen.getConstantPool();
foundDeadClassInitialization = getStatic.getFieldName(cpg).startsWith("class$")
&& getStatic.getSignature(cpg).equals("Ljava/lang/Class;");
for (Iterator<Location> j = cfg.locationIterator(); j.hasNext();) {
Location location2 = j.next();
if (location2.getHandle().getPosition() + 15 == location.getHandle().getPosition()) {
Instruction instruction2 = location2.getHandle().getInstruction();
if (instruction2 instanceof LDC) {
Object value = ((LDC) instruction2).getValue(methodGen.getConstantPool());
if (value instanceof String) {
String n = (String) value;
if (n.length() > 0) {
initializationOf = ClassName.toSignature(n);
}
}
}
}
}
} else if (prevIns instanceof LDC) {
LDC ldc = (LDC) prevIns;
Type t = ldc.getType(methodGen.getConstantPool());
if (t.getSignature().equals("Ljava/lang/Class;")) {
Object value = ldc.getValue(methodGen.getConstantPool());
if (value instanceof ConstantClass) {
ConstantClass v = (ConstantClass) value;
initializationOf = ClassName.toSignature(v.getBytes(javaClass.getConstantPool()));
foundDeadClassInitialization = true;
} else if (value instanceof ObjectType) {
ObjectType v = (ObjectType) value;
initializationOf = ClassName.toSignature(v.getClassName());
foundDeadClassInitialization = true;
} else {
AnalysisContext.logError("LDC loaded " + value + "at " + location.getHandle().getPosition() + " in " + classContext.getFullyQualifiedMethodName(method));
}
}
else {
continue; // not an interesting DLS
}
} else if (prevIns instanceof DUP2) {
// Check for the case where, due to the bytecode
// compiler, a long is needlessly stored just
// after we've DUP2'ed the stack and just
// before we return
Instruction cur = location.getHandle().getInstruction();
Instruction nxt = location.getHandle().getNext().getInstruction();
if (cur instanceof LSTORE && nxt instanceof LRETURN) {
continue; // not an interesting DLS
}
}
if (foundDeadClassInitialization) {
if (classContext.getJavaClass().getSuperclassName().equals("org.apache.axis.client.Stub")) {
continue;
}
BugInstance bugInstance = new BugInstance(this, "DLS_DEAD_STORE_OF_CLASS_LITERAL",
Priorities.NORMAL_PRIORITY).addClassAndMethod(methodGen, sourceFileName).add(lvAnnotation)
.addType(initializationOf);
accumulator.accumulateBug(bugInstance, sourceLineAnnotation);
continue;
}
if (prevIns instanceof LDC || prevIns instanceof ConstantPushInstruction) {
propertySet.addProperty(DeadLocalStoreProperty.STORE_OF_CONSTANT);
} else if (prevIns instanceof ACONST_NULL) {
storeOfNull = true;
propertySet.addProperty(DeadLocalStoreProperty.STORE_OF_NULL);
}
}
if (typeOfValue instanceof BasicType || Type.STRING.equals(typeOfValue)) {
propertySet.addProperty(DeadLocalStoreProperty.BASE_VALUE);
}
// Ignore assignments that were killed by a subsequent
// assignment.
boolean killedBySubsequentStore = llsaDataflow.getAnalysis().killedByStore(liveStoreSet, local);
if (killedBySubsequentStore) {
if (propertySet.containsProperty(DeadLocalStoreProperty.STORE_OF_NULL)
|| propertySet.containsProperty(DeadLocalStoreProperty.STORE_OF_CONSTANT)) {
continue;
}
propertySet.addProperty(DeadLocalStoreProperty.KILLED_BY_SUBSEQUENT_STORE);
}
// Ignore dead assignments of null and 0.
// These often indicate defensive programming.
InstructionHandle prev = location.getBasicBlock().getPredecessorOf(location.getHandle());
// int prevOpCode = -1;
if (prev != null) {
if (defensiveConstantValueOpcodes.get(prev.getInstruction().getOpcode())) {
propertySet.addProperty(DeadLocalStoreProperty.DEFENSIVE_CONSTANT_OPCODE);
// prevOpCode = prev.getInstruction().getOpcode();
}
if (prev.getInstruction() instanceof GETFIELD) {
InstructionHandle prev2 = prev.getPrev();
if (prev2 != null && prev2.getInstruction() instanceof ALOAD) {
propertySet.addProperty(DeadLocalStoreProperty.CACHING_VALUE);
}
}
if (prev.getInstruction() instanceof LoadInstruction) {
propertySet.addProperty(DeadLocalStoreProperty.COPY_VALUE);
}
if (prev.getInstruction() instanceof InvokeInstruction) {
propertySet.addProperty(DeadLocalStoreProperty.METHOD_RESULT);
}
}
boolean deadObjectStore = false;
if (ins instanceof IINC) {
// special handling of IINC
if (method.getName().equals("main") && method.isStatic()
&& method.getSignature().equals("([Ljava/lang/String;)V")) {
propertySet.addProperty(DeadLocalStoreProperty.DEAD_INCREMENT_IN_MAIN);
}
InstructionHandle next = location.getHandle().getNext();
if (next != null && next.getInstruction() instanceof IRETURN) {
propertySet.addProperty(DeadLocalStoreProperty.DEAD_INCREMENT_IN_RETURN);
} else {
propertySet.addProperty(DeadLocalStoreProperty.DEAD_INCREMENT);
}
if (localIncrementCount[local] == 1) {
propertySet.addProperty(DeadLocalStoreProperty.SINGLE_DEAD_INCREMENT);
} else {
propertySet.removeProperty(DeadLocalStoreProperty.IS_PARAMETER);
}
} else if (ins instanceof ASTORE && prev != null) {
// Look for objects created but never used
Instruction prevIns = prev.getInstruction();
if ((prevIns instanceof INVOKESPECIAL && ((INVOKESPECIAL) prevIns).getMethodName(methodGen.getConstantPool())
.equals("<init>"))
|| prevIns instanceof ANEWARRAY
|| prevIns instanceof NEWARRAY
|| prevIns instanceof MULTIANEWARRAY) {
deadObjectStore = true;
} else if (prevIns instanceof DUP) {
propertySet.addProperty(DeadLocalStoreProperty.DUP_THEN_STORE);
}
}
if (deadObjectStore) {
propertySet.addProperty(DeadLocalStoreProperty.DEAD_OBJECT_STORE);
} else if (!killedBySubsequentStore && localStoreCount[local] == 2 && localLoadCount[local] > 0) {
// TODO: why is this significant?
propertySet.addProperty(DeadLocalStoreProperty.TWO_STORES_MULTIPLE_LOADS);
} else if (!parameterThatIsDeadAtEntry && localStoreCount[local] == 1 && localLoadCount[local] == 0
&& propertySet.containsProperty(DeadLocalStoreProperty.DEFENSIVE_CONSTANT_OPCODE)) {
// might be final local constant
propertySet.addProperty(DeadLocalStoreProperty.SINGLE_STORE);
} else if (!parameterThatIsDeadAtEntry && !propertySet.containsProperty(DeadLocalStoreProperty.SHADOWS_FIELD)
&& localLoadCount[local] == 0) {
// TODO: why is this significant?
propertySet.addProperty(DeadLocalStoreProperty.NO_LOADS);
}
if (!storeOfNull && typeOfValue != null
&& !propertySet.containsProperty(DeadLocalStoreProperty.EXCEPTION_HANDLER)) {
String signatureOfValue = typeOfValue.getSignature();
if ((signatureOfValue.startsWith("Ljava/sql/") || signatureOfValue.startsWith("Ljavax/sql/"))
&& !signatureOfValue.endsWith("Exception")) {
propertySet.addProperty(DeadLocalStoreProperty.STORE_OF_DATABASE_VALUE);
}
}
if (parameterThatIsDeadAtEntry) {
propertySet.addProperty(DeadLocalStoreProperty.PARAM_DEAD_ON_ENTRY);
if (pendingBugReportAboutOverwrittenParameter != null) {
pendingBugReportAboutOverwrittenParameter.setPriority(Priorities.HIGH_PRIORITY);
}
}
if (localStoreCount[local] > 3) {
propertySet.addProperty(DeadLocalStoreProperty.MANY_STORES);
}
int occurrences = cfg.getLocationsContainingInstructionWithOffset(pc).size();
if (occurrences > 2 || sourceLineAnnotation.getStartLine() > 0
&& linesMentionedMultipleTimes.get(sourceLineAnnotation.getStartLine())) {
propertySet.addProperty(DeadLocalStoreProperty.CLONED_STORE);
}
String sourceFile = javaClass.getSourceFileName();
if (Subtypes2.isJSP(javaClass)) {
propertySet.addProperty(DeadLocalStoreProperty.IN_JSP_PAGE);