Browse Source

Support unary operators on native integers.

pull/2063/head
Daniel Grunwald 5 years ago
parent
commit
dc3dd193c8
  1. 7
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs
  2. 17
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  3. 12
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs

7
ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs

@ -102,6 +102,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -102,6 +102,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine((nuint)i < u);
}
public void Unary()
{
Console.WriteLine(~i);
Console.WriteLine(~u);
Console.WriteLine(-i);
}
public object[] Boxing()
{
return new object[10] {

17
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -567,7 +567,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -567,7 +567,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (argUType.GetStackType().GetSize() < inst.UnderlyingResultType.GetSize()
|| argUType.Kind == TypeKind.Enum && argUType.IsSmallIntegerType()
|| argUType.GetStackType() == StackType.I
|| (argUType.GetStackType() == StackType.I && !argUType.IsCSharpNativeIntegerType())
|| argUType.IsKnownType(KnownTypeCode.Boolean)
|| argUType.IsKnownType(KnownTypeCode.Char))
{
@ -576,13 +576,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -576,13 +576,11 @@ namespace ICSharpCode.Decompiler.CSharp
// Same if the argument is an enum based on a small integer type
// (those don't undergo numeric promotion in C# the way non-enum small integer types do).
// Same if the type is one that does not support ~ (IntPtr, bool and char).
StackType targetStackType = inst.UnderlyingResultType;
if (targetStackType == StackType.I) {
// IntPtr doesn't support operator ~.
// Note that it's OK to use a type that's larger than necessary.
targetStackType = StackType.I8;
Sign sign = context.TypeHint.GetSign();
if (sign == Sign.None) {
sign = argUType.GetSign();
}
IType targetType = compilation.FindType(targetStackType.ToKnownTypeCode(argUType.GetSign()));
IType targetType = FindArithmeticType(inst.UnderlyingResultType, sign);
if (inst.IsLifted) {
targetType = NullableType.Create(compilation, targetType);
}
@ -1261,11 +1259,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1261,11 +1259,12 @@ namespace ICSharpCode.Decompiler.CSharp
if (op == BinaryOperatorType.Subtract && inst.Left.MatchLdcI(0)) {
IType rightUType = NullableType.GetUnderlyingType(right.Type);
if (rightUType.IsKnownType(KnownTypeCode.Int32) || rightUType.IsKnownType(KnownTypeCode.Int64) || rightUType.IsCSharpSmallIntegerType()) {
if (rightUType.IsKnownType(KnownTypeCode.Int32) || rightUType.IsKnownType(KnownTypeCode.Int64)
|| rightUType.IsCSharpSmallIntegerType() || rightUType.IsCSharpNativeIntegerType()) {
// unary minus is supported on signed int and long, and on the small integer types (since they promote to int)
var uoe = new UnaryOperatorExpression(UnaryOperatorType.Minus, right.Expression);
uoe.AddAnnotation(inst.CheckForOverflow ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation);
var resultType = rightUType.IsKnownType(KnownTypeCode.Int64) ? rightUType : compilation.FindType(KnownTypeCode.Int32);
var resultType = FindArithmeticType(inst.RightInputType, Sign.Signed);
if (inst.IsLifted)
resultType = NullableType.Create(compilation, resultType);
return uoe.WithILInstruction(inst).WithRR(new OperatorResolveResult(

12
ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs

@ -449,14 +449,20 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -449,14 +449,20 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
// C# 4.0 spec: §7.6.9 Postfix increment and decrement operators
// C# 4.0 spec: §7.7.5 Prefix increment and decrement operators
TypeCode code = ReflectionHelper.GetTypeCode(type);
if ((code >= TypeCode.Char && code <= TypeCode.Decimal) || type.Kind == TypeKind.Enum || type.Kind == TypeKind.Pointer)
if ((code >= TypeCode.Char && code <= TypeCode.Decimal) || type.Kind == TypeKind.Enum || type.Kind == TypeKind.Pointer || type.IsCSharpNativeIntegerType())
return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable);
else
return new ErrorResolveResult(expression.Type);
case UnaryOperatorType.Plus:
if (type.IsCSharpNativeIntegerType()) {
return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable);
}
methodGroup = operators.UnaryPlusOperators;
break;
case UnaryOperatorType.Minus:
if (type.IsCSharpNativeIntegerType()) {
return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable);
}
methodGroup = CheckForOverflow ? operators.CheckedUnaryMinusOperators : operators.UncheckedUnaryMinusOperators;
break;
case UnaryOperatorType.Not:
@ -472,7 +478,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -472,7 +478,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
rr = WithCheckForOverflow(false).ResolveCast(type, rr);
if (rr.IsCompileTimeConstant)
return rr;
}
}
return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable);
} else if (type.IsCSharpNativeIntegerType()) {
return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable);
} else {
methodGroup = operators.BitwiseComplementOperators;

Loading…
Cancel
Save