checkWriteToStaticFromInstanceMethod: if (f.getName().indexOf("class$") != 0) {
int priority = LOW_PRIORITY;
if (f.isReferenceType()) {
try {
ValueNumberDataflow vnaDataflow = getClassContext().getValueNumberDataflow(getMethod());
IsNullValueDataflow invDataflow = getClassContext().getIsNullValueDataflow(getMethod());
ValueNumberFrame vFrame = vnaDataflow.getAnalysis().getFactAtPC(vnaDataflow.getCFG(), getPC());
IsNullValueFrame iFrame = invDataflow.getAnalysis().getFactAtPC(invDataflow.getCFG(), getPC());
AvailableLoad l = new AvailableLoad(f);
ValueNumber[] availableLoads = vFrame.getAvailableLoad(l);
if (availableLoads != null && iFrame.isTrackValueNumbers()) {
for (ValueNumber v : availableLoads) {
IsNullValue knownValue = iFrame.getKnownValue(v);
if (knownValue == null) {
continue;
}
if (knownValue.isDefinitelyNotNull()) {
if (valuePut.isNull()) {
priority++;
} else {
priority--;
}
break;
} else if (knownValue.isDefinitelyNull()) {
break checkWriteToStaticFromInstanceMethod;
}
}
}
} catch (CheckedAnalysisException e) {
AnalysisContext.logError("foo", e);
}
}
if (!publicOrProtectedConstructor) {
priority--;
}
if (seenMonitorEnter) {
priority++;
}
if (!seenInvokeStatic && data.staticFieldsReadInThisMethod.isEmpty()) {
priority--;
}
if (getThisClass().isPublic() && getMethod().isPublic()) {
priority--;
}
if (getThisClass().isPrivate() || getMethod().isPrivate()) {
priority++;
}
if (getClassName().indexOf('$') != -1 || BCELUtil.isSynthetic(getMethod()) || f.isSynthetic()
|| f.getName().indexOf('$') >= 0) {
priority++;
}
// Decrease priority for boolean fields used to control
// debug/test settings
if (f.getName().indexOf("DEBUG") >= 0 || f.getName().indexOf("VERBOSE") >= 0 && f.getSignature().equals("Z")) {
priority++;
priority++;
}
// Eclipse bundles which implements start/stop *very* often
// assigns static instances there
if ((getMethodName().equals("start") || getMethodName().equals("stop"))
&& getMethodSig().equals("(Lorg/osgi/framework/BundleContext;)V")) {
try {
JavaClass bundleClass = Repository.lookupClass("org.osgi.framework.BundleActivator");
if (getThisClass().instanceOf(bundleClass)) {
priority++;
}
if (f.isReferenceType()) {
FieldDescriptor fieldInfo = f.getFieldDescriptor();
String dottedClass = DeepSubtypeAnalysis.getComponentClass(fieldInfo.getSignature());
JavaClass fieldClass = Repository.lookupClass(dottedClass);
if (fieldClass != null && fieldClass.instanceOf(bundleClass)) {
// the code "plugin = this;" unfortunately
// exists in the
// template for new Eclipse plugin classes, so
// nearly every one
// plugin has this pattern => decrease to very
// low prio
priority = Priorities.IGNORE_PRIORITY;
}
}
} catch (ClassNotFoundException e) {
bugReporter.reportMissingClass(e);
}
}
bugAccumulator.accumulateBug(new BugInstance(this, "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", priority)
.addClassAndMethod(this).addField(f), this);
}
}
if (seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE || seen == INVOKESPECIAL || seen == INVOKESTATIC) {
String sig = getSigConstantOperand();
String invokedClassName = getClassConstantOperand();
if (invokedClassName.equals(getClassName())
&& (getMethodName().equals("<init>") || getMethodName().equals("<clinit>"))) {
data.calledFromConstructors.add(getNameConstantOperand() + ":" + sig);
}
int pos = PreorderVisitor.getNumberArguments(sig);
if (stack.getStackDepth() > pos) {
OpcodeStack.Item item = stack.getStackItem(pos);
boolean superCall = seen == INVOKESPECIAL && !invokedClassName.equals(getClassName());
if (DEBUG) {
System.out.println("In " + getFullyQualifiedMethodName() + " saw call on " + item);
}
boolean selfCall = item.getRegisterNumber() == 0 && !superCall;
if (selfCall && getMethodName().equals("<init>")) {
sawSelfCallInConstructor = true;
if (DEBUG) {
System.out.println("Saw self call in " + getFullyQualifiedMethodName() + " to " + invokedClassName + "."
+ getNameConstantOperand());
}
}
}
}
if ((seen == IFNULL || seen == IFNONNULL) && stack.getStackDepth() > 0) {
OpcodeStack.Item item = stack.getStackItem(0);
XField f = item.getXField();
if (f != null) {
data.nullTested.add(f);
if (DEBUG) {
System.out.println(f + " null checked in " + getFullyQualifiedMethodName());
}
}
}
if ((seen == IF_ACMPEQ || seen == IF_ACMPNE) && stack.getStackDepth() >= 2) {
OpcodeStack.Item item0 = stack.getStackItem(0);
OpcodeStack.Item item1 = stack.getStackItem(1);
XField field1 = item1.getXField();
if (item0.isNull() && field1 != null) {
data.nullTested.add(field1);
} else {
XField field0 = item0.getXField();
if (item1.isNull() && field0 != null) {
data.nullTested.add(field0);
}
}
}
computePlacesAssumedNonnull: if (seen == GETFIELD || seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE
|| seen == INVOKESPECIAL || seen == PUTFIELD || seen == IALOAD || seen == AALOAD || seen == BALOAD
|| seen == CALOAD || seen == SALOAD || seen == IASTORE || seen == AASTORE || seen == BASTORE || seen == CASTORE
|| seen == SASTORE || seen == ARRAYLENGTH) {
int pos = 0;
switch (seen) {
case ARRAYLENGTH:
case GETFIELD:
pos = 0;
break;
case INVOKEVIRTUAL:
case INVOKEINTERFACE:
case INVOKESPECIAL:
String sig = getSigConstantOperand();
pos = PreorderVisitor.getNumberArguments(sig);
break;
case PUTFIELD:
case IALOAD:
case AALOAD:
case BALOAD:
case CALOAD:
case SALOAD:
pos = 1;
break;
case IASTORE:
case AASTORE:
case BASTORE:
case CASTORE:
case SASTORE:
pos = 2;
break;
default:
throw new RuntimeException("Impossible");
}
if (stack.getStackDepth() >= pos) {
OpcodeStack.Item item = stack.getStackItem(pos);
XField f = item.getXField();
if (f != null
&& !f.isStatic()
&& !data.nullTested.contains(f)
&& !((data.writtenInConstructorFields.contains(f) || data.writtenInInitializationFields.contains(f)) && data.writtenNonNullFields
.contains(f))) {
try {
IsNullValueDataflow invDataflow = getClassContext().getIsNullValueDataflow(getMethod());
IsNullValueFrame iFrame = invDataflow.getAnalysis().getFactBeforeExceptionCheck(invDataflow.getCFG(),
getPC());
if (!iFrame.isValid() || iFrame.getStackValue(pos).isDefinitelyNotNull()) {
break computePlacesAssumedNonnull;
}