// don't create a new variable if the type is STRING
if (argument.getType() == VariableType.STRING)
return argument;
Value val = box.getValue();
Variable result = factory.createVariable(VariableType.STRING);
switch (argument.getType()) {
case STRINGBUFFER:
if (isStringBuffer(val.getType()) || isStringBuilder(val.getType())) {
factory.addStatement(new StringFromStringBuffer(result, argument));
} else {
// if the type implements Appendable, we can't really know its value
factory.addStatement(new StringInit(result, Basic.makeAnyString()));
}
break;
case ARRAY:
if (val.getType() instanceof ArrayType) { // the argument's type only says it *might* be an array
// TODO because of covariant arrays, we might not actually know it is a String array??
factory.addStatement(new StringInit(result, ARRAY_OBJECT_AUTOMATON));
} else {
factory.addStatement(new StringInit(result, Basic.makeAnyString()));
}
break;
case OBJECT:
Automaton auto = Basic.makeAnyString();
if (val.getType() instanceof RefType) {
Automaton resolved = factory.resolveToStringMethod(((RefType)val.getType()).getSootClass());
if (resolved != null)
auto = resolved;
}
factory.addStatement(new StringInit(result, auto));
break;
case NULL:
factory.addStatement(new StringInit(result, Automatons.getNull()));
break;
case NONE:
if (val instanceof Constant) {
String s = constantToString((Constant) val, radix, type);
if (s != null)
factory.addStatement(new StringInit(result, Basic.makeConstString(s)));
else
factory.addStatement(new StringInit(result, Basic.makeAnyString()));
} else if (radix == 10 && Automatons.fromType(type.toString()) != null) { // TODO: handle radix!=10
factory.addStatement(new StringInit(result, Automatons.fromType(type.toString())));
} else if (val.getType() instanceof RefType) {
// Call the corresponding toString method
Method tostring_method = factory.getToStringMethod(((RefType) val.getType()).getSootClass());
if (tostring_method != null && !isInterface(val.getType())) {
factory.addStatement(new Call(result, tostring_method, new Variable[0]));
} else {
factory.addStatement(new StringInit(result, Basic.makeAnyString()));
}
} else { // If all else fails, give any string
factory.addStatement(new StringInit(result, Basic.makeAnyString())); // not currently reachable, but good to have here
}
break;
case PRIMITIVE:
// TODO: If type is another primitive type, add a UnaryOp to extract this primitive type as a boolean, int, etc.
if (val instanceof Constant) {
// NOTE: This for char-variables, this does the same as the if-clause below, but is a bit more efficient
factory.addStatement(new StringInit(result, Basic.makeConstString(constantToString((Constant) val, radix, type))));
} else if (type.equals(CharType.v())) {
// create a string buffer, append the char, convert it to a string and return that
Variable tmp = factory.createVariable(VariableType.STRINGBUFFER);
factory.addStatement(new StringBufferInit(tmp, makeStringConstant("", factory)));
factory.addStatement(new StringBufferAppendChar(tmp, argument));
factory.addStatement(new StringFromStringBuffer(result, tmp));
} else if (type.equals(BooleanType.v())) {