public override VarType GetExprType() { VarType exprType = array.GetExprType(); if (exprType.Equals(VarType.Vartype_Null)) { return(hardType.Copy()); } else { return(exprType.DecreaseArrayDim()); } }
public override CheckTypesResult CheckExprTypeBounds() { CheckTypesResult result = new CheckTypesResult(); VarType typeLeft = left.GetExprType(); VarType typeRight = right.GetExprType(); if (typeLeft.typeFamily > typeRight.typeFamily) { result.AddMinTypeExprent(right, VarType.GetMinTypeInFamily(typeLeft.typeFamily)); } else if (typeLeft.typeFamily < typeRight.typeFamily) { result.AddMinTypeExprent(left, typeRight); } else { result.AddMinTypeExprent(left, VarType.GetCommonSupertype(typeLeft, typeRight)); } return(result); }
public override VarType GetExprType() { return(value.GetExprType()); }
public override VarType GetExprType() { return(left.GetExprType()); }
public override TextBuffer ToJava(int indent, BytecodeMappingTracer tracer) { tracer.AddMapping(bytecode); if (funcType <= Function_Ushr) { return(WrapOperandString(lstOperands[0], false, indent, tracer).Append(Operators[ funcType]).Append(WrapOperandString(lstOperands[1], true, indent, tracer))); } // try to determine more accurate type for 'char' literals if (funcType >= Function_Eq) { if (funcType <= Function_Le) { Exprent left = lstOperands[0]; Exprent right = lstOperands[1]; if (right.type == Exprent_Const) { ((ConstExprent)right).AdjustConstType(left.GetExprType()); } else if (left.type == Exprent_Const) { ((ConstExprent)left).AdjustConstType(right.GetExprType()); } } return(WrapOperandString(lstOperands[0], false, indent, tracer).Append(Operators[ funcType - Function_Eq + 11]).Append(WrapOperandString(lstOperands[1], true, indent , tracer))); } switch (funcType) { case Function_Bit_Not: { return(WrapOperandString(lstOperands[0], true, indent, tracer).Prepend("~")); } case Function_Bool_Not: { return(WrapOperandString(lstOperands[0], true, indent, tracer).Prepend("!")); } case Function_Neg: { return(WrapOperandString(lstOperands[0], true, indent, tracer).Prepend("-")); } case Function_Cast: { return(lstOperands[1].ToJava(indent, tracer).Enclose("(", ")").Append(WrapOperandString (lstOperands[0], true, indent, tracer))); } case Function_Array_Length: { Exprent arr = lstOperands[0]; TextBuffer res = WrapOperandString(arr, false, indent, tracer); if (arr.GetExprType().arrayDim == 0) { VarType objArr = VarType.Vartype_Object.ResizeArrayDim(1); // type family does not change res.Enclose("((" + ExprProcessor.GetCastTypeName(objArr) + ")", ")"); } return(res.Append(".length")); } case Function_Iif: { return(WrapOperandString(lstOperands[0], true, indent, tracer).Append(" ? ").Append (WrapOperandString(lstOperands[1], true, indent, tracer)).Append(" : ").Append(WrapOperandString (lstOperands[2], true, indent, tracer))); } case Function_Ipp: { return(WrapOperandString(lstOperands[0], true, indent, tracer).Append("++")); } case Function_Ppi: { return(WrapOperandString(lstOperands[0], true, indent, tracer).Prepend("++")); } case Function_Imm: { return(WrapOperandString(lstOperands[0], true, indent, tracer).Append("--")); } case Function_Mmi: { return(WrapOperandString(lstOperands[0], true, indent, tracer).Prepend("--")); } case Function_Instanceof: { return(WrapOperandString(lstOperands[0], true, indent, tracer).Append(" instanceof " ).Append(WrapOperandString(lstOperands[1], true, indent, tracer))); } case Function_Lcmp: { // shouldn't appear in the final code return(WrapOperandString(lstOperands[0], true, indent, tracer).Prepend("__lcmp__(" ).Append(", ").Append(WrapOperandString(lstOperands[1], true, indent, tracer)).Append (")")); } case Function_Fcmpl: { // shouldn't appear in the final code return(WrapOperandString(lstOperands[0], true, indent, tracer).Prepend("__fcmpl__(" ).Append(", ").Append(WrapOperandString(lstOperands[1], true, indent, tracer)).Append (")")); } case Function_Fcmpg: { // shouldn't appear in the final code return(WrapOperandString(lstOperands[0], true, indent, tracer).Prepend("__fcmpg__(" ).Append(", ").Append(WrapOperandString(lstOperands[1], true, indent, tracer)).Append (")")); } case Function_Dcmpl: { // shouldn't appear in the final code return(WrapOperandString(lstOperands[0], true, indent, tracer).Prepend("__dcmpl__(" ).Append(", ").Append(WrapOperandString(lstOperands[1], true, indent, tracer)).Append (")")); } case Function_Dcmpg: { // shouldn't appear in the final code return(WrapOperandString(lstOperands[0], true, indent, tracer).Prepend("__dcmpg__(" ).Append(", ").Append(WrapOperandString(lstOperands[1], true, indent, tracer)).Append (")")); } } if (funcType <= Function_I2s) { return(WrapOperandString(lstOperands[0], true, indent, tracer).Prepend("(" + ExprProcessor .GetTypeName(Types[funcType - Function_I2l]) + ")")); } // return "<unknown function>"; throw new Exception("invalid function"); }
public override CheckTypesResult CheckExprTypeBounds() { CheckTypesResult result = new CheckTypesResult(); Exprent param1 = lstOperands[0]; VarType type1 = param1.GetExprType(); Exprent param2 = null; VarType type2 = null; if (lstOperands.Count > 1) { param2 = lstOperands[1]; type2 = param2.GetExprType(); } switch (funcType) { case Function_Iif: { VarType supertype = GetExprType(); result.AddMinTypeExprent(param1, VarType.Vartype_Boolean); result.AddMinTypeExprent(param2, VarType.GetMinTypeInFamily(supertype.typeFamily) ); result.AddMinTypeExprent(lstOperands[2], VarType.GetMinTypeInFamily(supertype.typeFamily )); break; } case Function_I2l: case Function_I2f: case Function_I2d: case Function_I2b: case Function_I2c: case Function_I2s: { result.AddMinTypeExprent(param1, VarType.Vartype_Bytechar); result.AddMaxTypeExprent(param1, VarType.Vartype_Int); break; } case Function_Imm: case Function_Ipp: case Function_Mmi: case Function_Ppi: { result.AddMinTypeExprent(param1, implicitType); result.AddMaxTypeExprent(param1, implicitType); break; } case Function_Add: case Function_Sub: case Function_Mul: case Function_Div: case Function_Rem: case Function_Shl: case Function_Shr: case Function_Ushr: case Function_Lt: case Function_Ge: case Function_Gt: case Function_Le: { result.AddMinTypeExprent(param2, VarType.Vartype_Bytechar); goto case Function_Bit_Not; } case Function_Bit_Not: case Function_Neg: { // case FUNCTION_BOOL_NOT: result.AddMinTypeExprent(param1, VarType.Vartype_Bytechar); break; } case Function_And: case Function_Or: case Function_Xor: case Function_Eq: case Function_Ne: { if (type1.type == ICodeConstants.Type_Boolean) { if (type2.IsStrictSuperset(type1)) { result.AddMinTypeExprent(param1, VarType.Vartype_Bytechar); } else { // both are booleans bool param1_false_boolean = type1.IsFalseBoolean() || (param1.type == Exprent.Exprent_Const && !((ConstExprent)param1).HasBooleanValue()); bool param2_false_boolean = type1.IsFalseBoolean() || (param2.type == Exprent.Exprent_Const && !((ConstExprent)param2).HasBooleanValue()); if (param1_false_boolean || param2_false_boolean) { result.AddMinTypeExprent(param1, VarType.Vartype_Bytechar); result.AddMinTypeExprent(param2, VarType.Vartype_Bytechar); } } } else if (type2.type == ICodeConstants.Type_Boolean) { if (type1.IsStrictSuperset(type2)) { result.AddMinTypeExprent(param2, VarType.Vartype_Bytechar); } } break; } } return(result); }
public override VarType GetExprType() { VarType exprType = null; if (funcType <= Function_Neg || funcType == Function_Ipp || funcType == Function_Ppi || funcType == Function_Imm || funcType == Function_Mmi) { VarType type1 = lstOperands[0].GetExprType(); VarType type2 = null; if (lstOperands.Count > 1) { type2 = lstOperands[1].GetExprType(); } switch (funcType) { case Function_Imm: case Function_Mmi: case Function_Ipp: case Function_Ppi: { exprType = implicitType; break; } case Function_Bool_Not: { exprType = VarType.Vartype_Boolean; break; } case Function_Shl: case Function_Shr: case Function_Ushr: case Function_Bit_Not: case Function_Neg: { exprType = GetMaxVarType(new VarType[] { type1 }); break; } case Function_Add: case Function_Sub: case Function_Mul: case Function_Div: case Function_Rem: { exprType = GetMaxVarType(new VarType[] { type1, type2 }); break; } case Function_And: case Function_Or: case Function_Xor: { if (type1.type == ICodeConstants.Type_Boolean & type2.type == ICodeConstants.Type_Boolean) { exprType = VarType.Vartype_Boolean; } else { exprType = GetMaxVarType(new VarType[] { type1, type2 }); } break; } } } else if (funcType == Function_Cast) { exprType = lstOperands[1].GetExprType(); } else if (funcType == Function_Iif) { Exprent param1 = lstOperands[1]; Exprent param2 = lstOperands[2]; VarType supertype = VarType.GetCommonSupertype(param1.GetExprType(), param2.GetExprType ()); if (param1.type == Exprent.Exprent_Const && param2.type == Exprent.Exprent_Const && supertype.type != ICodeConstants.Type_Boolean && VarType.Vartype_Int.IsSuperset (supertype)) { exprType = VarType.Vartype_Int; } else { exprType = supertype; } } else if (funcType == Function_Str_Concat) { exprType = VarType.Vartype_String; } else if (funcType >= Function_Eq || funcType == Function_Instanceof) { exprType = VarType.Vartype_Boolean; } else if (funcType >= Function_Array_Length) { exprType = VarType.Vartype_Int; } else { exprType = Types[funcType - Function_I2l]; } return(exprType); }
public override TextBuffer ToJava(int indent, BytecodeMappingTracer tracer) { TextBuffer buf = new TextBuffer(); string super_qualifier = null; bool isInstanceThis = false; tracer.AddMapping(bytecode); if (instance is InvocationExprent) { ((InvocationExprent)instance).MarkUsingBoxingResult(); } if (isStatic__) { if (IsBoxingCall() && canIgnoreBoxing) { // process general "boxing" calls, e.g. 'Object[] data = { true }' or 'Byte b = 123' // here 'byte' and 'short' values do not need an explicit narrowing type cast ExprProcessor.GetCastedExprent(lstParameters[0], descriptor.@params[0], buf, indent , false, false, false, false, tracer); return(buf); } ClassesProcessor.ClassNode node = (ClassesProcessor.ClassNode)DecompilerContext.GetProperty (DecompilerContext.Current_Class_Node); if (node == null || !classname.Equals(node.classStruct.qualifiedName)) { buf.Append(DecompilerContext.GetImportCollector().GetShortNameInClassContext(ExprProcessor .BuildJavaClassName(classname))); } } else { if (instance != null && instance.type == Exprent.Exprent_Var) { VarExprent instVar = (VarExprent)instance; VarVersionPair varPair = new VarVersionPair(instVar); VarProcessor varProc = instVar.GetProcessor(); if (varProc == null) { MethodWrapper currentMethod = (MethodWrapper)DecompilerContext.GetProperty(DecompilerContext .Current_Method_Wrapper); if (currentMethod != null) { varProc = currentMethod.varproc; } } string this_classname = null; if (varProc != null) { this_classname = varProc.GetThisVars().GetOrNull(varPair); } if (this_classname != null) { isInstanceThis = true; if (invocationTyp == Invoke_Special) { if (!classname.Equals(this_classname)) { // TODO: direct comparison to the super class? StructClass cl = DecompilerContext.GetStructContext().GetClass(classname); bool isInterface = cl != null && cl.HasModifier(ICodeConstants.Acc_Interface); super_qualifier = !isInterface ? this_classname : classname; } } } } if (functype == Typ_General) { if (super_qualifier != null) { TextUtil.WriteQualifiedSuper(buf, super_qualifier); } else if (instance != null) { TextBuffer res = instance.ToJava(indent, tracer); if (IsUnboxingCall()) { // we don't print the unboxing call - no need to bother with the instance wrapping / casting buf.Append(res); return(buf); } VarType rightType = instance.GetExprType(); VarType leftType = new VarType(ICodeConstants.Type_Object, 0, classname); if (rightType.Equals(VarType.Vartype_Object) && !leftType.Equals(rightType)) { buf.Append("((").Append(ExprProcessor.GetCastTypeName(leftType)).Append(")"); if (instance.GetPrecedence() >= FunctionExprent.GetPrecedence(FunctionExprent.Function_Cast )) { res.Enclose("(", ")"); } buf.Append(res).Append(")"); } else if (instance.GetPrecedence() > GetPrecedence()) { buf.Append("(").Append(res).Append(")"); } else { buf.Append(res); } } } } switch (functype) { case Typ_General: { if (VarExprent.Var_Nameless_Enclosure.Equals(buf.ToString())) { buf = new TextBuffer(); } if (buf.Length() > 0) { buf.Append("."); } buf.Append(name); if (invocationTyp == Invoke_Dynamic) { buf.Append("<invokedynamic>"); } buf.Append("("); break; } case Typ_Clinit: { throw new Exception("Explicit invocation of " + ICodeConstants.Clinit_Name); } case Typ_Init: { if (super_qualifier != null) { buf.Append("super("); } else if (isInstanceThis) { buf.Append("this("); } else if (instance != null) { buf.Append(instance.ToJava(indent, tracer)).Append(".<init>("); } else { throw new Exception("Unrecognized invocation of " + ICodeConstants.Init_Name); } break; } } List <VarVersionPair> mask = null; bool isEnum = false; if (functype == Typ_Init) { ClassesProcessor.ClassNode newNode = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(classname); if (newNode != null) { mask = ExprUtil.GetSyntheticParametersMask(newNode, stringDescriptor, lstParameters .Count); isEnum = newNode.classStruct.HasModifier(ICodeConstants.Acc_Enum) && DecompilerContext .GetOption(IFernflowerPreferences.Decompile_Enum); } } BitSet setAmbiguousParameters = GetAmbiguousParameters(); // omit 'new Type[] {}' for the last parameter of a vararg method call if (lstParameters.Count == [email protected] && IsVarArgCall()) { Exprent lastParam = lstParameters[lstParameters.Count - 1]; if (lastParam.type == Exprent_New && lastParam.GetExprType().arrayDim >= 1) { ((NewExprent)lastParam).SetVarArgParam(true); } } bool firstParameter = true; int start = isEnum ? 2 : 0; for (int i = start; i < lstParameters.Count; i++) { if (mask == null || mask[i] == null) { TextBuffer buff = new TextBuffer(); bool ambiguous = setAmbiguousParameters.Get(i); // 'byte' and 'short' literals need an explicit narrowing type cast when used as a parameter ExprProcessor.GetCastedExprent(lstParameters[i], descriptor.@params[i], buff, indent , true, ambiguous, true, true, tracer); // the last "new Object[0]" in the vararg call is not printed if (buff.Length() > 0) { if (!firstParameter) { buf.Append(", "); } buf.Append(buff); } firstParameter = false; } } buf.Append(')'); return(buf); }
// precedence of new public override TextBuffer ToJava(int indent, BytecodeMappingTracer tracer) { TextBuffer buf = new TextBuffer(); if (anonymous) { ClassesProcessor.ClassNode child = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(newType.value); // IDEA-204310 - avoid backtracking later on for lambdas (causes spurious imports) if (!enumConst && (!lambda || DecompilerContext.GetOption(IFernflowerPreferences .Lambda_To_Anonymous_Class))) { string enclosing = null; if (!lambda && constructor != null) { enclosing = GetQualifiedNewInstance(child.anonymousClassType.value, constructor.GetLstParameters (), indent, tracer); if (enclosing != null) { buf.Append(enclosing).Append('.'); } } buf.Append("new "); string typename = ExprProcessor.GetCastTypeName(child.anonymousClassType); if (enclosing != null) { ClassesProcessor.ClassNode anonymousNode = DecompilerContext.GetClassProcessor(). GetMapRootClasses().GetOrNull(child.anonymousClassType.value); if (anonymousNode != null) { typename = anonymousNode.simpleName; } else { typename = Sharpen.Runtime.Substring(typename, typename.LastIndexOf('.') + 1); } } GenericClassDescriptor descriptor = ClassWriter.GetGenericClassDescriptor(child.classStruct ); if (descriptor != null) { if ((descriptor.superinterfaces.Count == 0)) { buf.Append(GenericMain.GetGenericCastTypeName(descriptor.superclass)); } else { if (descriptor.superinterfaces.Count > 1 && !lambda) { DecompilerContext.GetLogger().WriteMessage("Inconsistent anonymous class signature: " + child.classStruct.qualifiedName, IFernflowerLogger.Severity.Warn); } buf.Append(GenericMain.GetGenericCastTypeName(descriptor.superinterfaces[0])); } } else { buf.Append(typename); } } buf.Append('('); if (!lambda && constructor != null) { List <Exprent> parameters = constructor.GetLstParameters(); List <VarVersionPair> mask = child.GetWrapper().GetMethodWrapper(ICodeConstants.Init_Name , constructor.GetStringDescriptor()).synthParameters; if (mask == null) { InvocationExprent superCall = child.superInvocation; mask = ExprUtil.GetSyntheticParametersMask(superCall.GetClassname(), superCall.GetStringDescriptor (), parameters.Count); } int start = enumConst ? 2 : 0; bool firstParam = true; for (int i = start; i < parameters.Count; i++) { if (mask == null || mask[i] == null) { if (!firstParam) { buf.Append(", "); } ExprProcessor.GetCastedExprent(parameters[i], constructor.GetDescriptor().@params [i], buf, indent, true, tracer); firstParam = false; } } } buf.Append(')'); if (enumConst && buf.Length() == 2) { buf.SetLength(0); } if (lambda) { if (!DecompilerContext.GetOption(IFernflowerPreferences.Lambda_To_Anonymous_Class )) { buf.SetLength(0); } // remove the usual 'new <class>()', it will be replaced with lambda style '() ->' Exprent methodObject = constructor == null ? null : constructor.GetInstance(); TextBuffer clsBuf = new TextBuffer(); new ClassWriter().ClassLambdaToJava(child, clsBuf, methodObject, indent, tracer); buf.Append(clsBuf); tracer.IncrementCurrentSourceLine(clsBuf.CountLines()); } else { TextBuffer clsBuf = new TextBuffer(); new ClassWriter().ClassToJava(child, clsBuf, indent, tracer); buf.Append(clsBuf); tracer.IncrementCurrentSourceLine(clsBuf.CountLines()); } } else if (directArrayInit) { VarType leftType = newType.DecreaseArrayDim(); buf.Append('{'); for (int i = 0; i < lstArrayElements.Count; i++) { if (i > 0) { buf.Append(", "); } ExprProcessor.GetCastedExprent(lstArrayElements[i], leftType, buf, indent, false, tracer); } buf.Append('}'); } else if (newType.arrayDim == 0) { if (!enumConst) { string enclosing = null; if (constructor != null) { enclosing = GetQualifiedNewInstance(newType.value, constructor.GetLstParameters() , indent, tracer); if (enclosing != null) { buf.Append(enclosing).Append('.'); } } buf.Append("new "); string typename = ExprProcessor.GetTypeName(newType); if (enclosing != null) { ClassesProcessor.ClassNode newNode = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(newType.value); if (newNode != null) { typename = newNode.simpleName; } else { typename = Sharpen.Runtime.Substring(typename, typename.LastIndexOf('.') + 1); } } buf.Append(typename); } if (constructor != null) { List <Exprent> parameters = constructor.GetLstParameters(); List <VarVersionPair> mask = ExprUtil.GetSyntheticParametersMask(constructor.GetClassname (), constructor.GetStringDescriptor(), parameters.Count); int start = enumConst ? 2 : 0; if (!enumConst || start < parameters.Count) { buf.Append('('); bool firstParam = true; for (int i = start; i < parameters.Count; i++) { if (mask == null || mask[i] == null) { Exprent expr = parameters[i]; VarType leftType = constructor.GetDescriptor().@params[i]; if (i == parameters.Count - 1 && expr.GetExprType() == VarType.Vartype_Null && ProbablySyntheticParameter (leftType.value)) { break; } // skip last parameter of synthetic constructor call if (!firstParam) { buf.Append(", "); } ExprProcessor.GetCastedExprent(expr, leftType, buf, indent, true, false, true, true , tracer); firstParam = false; } } buf.Append(')'); } } } else if (isVarArgParam) { // just print the array elements VarType leftType = newType.DecreaseArrayDim(); for (int i = 0; i < lstArrayElements.Count; i++) { if (i > 0) { buf.Append(", "); } // new String[][]{{"abc"}, {"DEF"}} => new String[]{"abc"}, new String[]{"DEF"} Exprent element = lstArrayElements[i]; if (element.type == Exprent_New) { ((NewExprent)element).SetDirectArrayInit(false); } ExprProcessor.GetCastedExprent(element, leftType, buf, indent, false, tracer); } // if there is just one element of Object[] type it needs to be casted to resolve ambiguity if (lstArrayElements.Count == 1) { VarType elementType = lstArrayElements[0].GetExprType(); if (elementType.type == ICodeConstants.Type_Object && elementType.value.Equals("java/lang/Object" ) && elementType.arrayDim >= 1) { buf.Prepend("(Object)"); } } } else { buf.Append("new ").Append(ExprProcessor.GetTypeName(newType)); if ((lstArrayElements.Count == 0)) { for (int i = 0; i < newType.arrayDim; i++) { buf.Append('['); if (i < lstDims.Count) { buf.Append(lstDims[i].ToJava(indent, tracer)); } buf.Append(']'); } } else { for (int i = 0; i < newType.arrayDim; i++) { buf.Append("[]"); } VarType leftType = newType.DecreaseArrayDim(); buf.Append('{'); for (int i = 0; i < lstArrayElements.Count; i++) { if (i > 0) { buf.Append(", "); } ExprProcessor.GetCastedExprent(lstArrayElements[i], leftType, buf, indent, false, tracer); } buf.Append('}'); } } return(buf); }