Browse Source

Fix #1796: Use hexadecimal literals with bitwise operators.

pull/2153/head
Siegfried Pammer 5 years ago
parent
commit
9afbcba79a
  1. 209
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstantsTests.cs
  2. 19
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs
  3. 81
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

209
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstantsTests.cs

@ -6,7 +6,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -6,7 +6,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public ulong Issue1308(ulong u = 8uL)
{
Test((u & uint.MaxValue) != 0);
Test((u & 0xFFFFFFFFu) != 0);
return 18446744069414584320uL;
}
@ -50,5 +50,212 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -50,5 +50,212 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Test(decimal.MinValue);
Test(decimal.MaxValue);
}
public void BitwiseAndWithConstantUInt64(ulong a)
{
ExpectUInt64(a & 7);
ExpectUInt64(a & 0x7FFFFFFF);
ExpectUInt64(a & 0xFFFFFFFFu);
ExpectUInt64(a & 0x7FFFFFFFFFFFFFFFuL);
ExpectUInt64(a & 0xFFFFFFFFFFFFFFFFuL);
}
public void BitwiseAndWithConstantInt64(long a)
{
ExpectInt64(a & 7);
ExpectInt64(a & 0x7FFFFFFF);
ExpectInt64(a & 0xFFFFFFFFu);
ExpectInt64(a & 0x7FFFFFFFFFFFFFFFL);
}
public void BitwiseAndWithConstantUInt32(uint a)
{
ExpectUInt32(a & 7u);
ExpectUInt32(a & 0x7FFFFFFFu);
ExpectUInt32(a & 0xFFFFFFFFu);
}
public void BitwiseAndWithConstantInt32(int a)
{
ExpectInt32(a & 7);
ExpectInt32(a & 0x7FFFFFFF);
}
public void BitwiseAndWithConstantUInt16(ushort a)
{
ExpectUInt16((ushort)(a & 7u));
ExpectUInt16((ushort)(a & 0x7FFFu));
ExpectUInt16((ushort)(a & 0xFFFFu));
}
public void BitwiseAndWithConstantInt16(short a)
{
ExpectInt16((short)(a & 7));
ExpectInt16((short)(a & 0x7FFF));
}
public void BitwiseAndWithConstantUInt8(byte a)
{
ExpectUInt8((byte)(a & 7u));
ExpectUInt8((byte)(a & 0x7Fu));
ExpectUInt8((byte)(a & 0xFFu));
}
public void BitwiseAndWithConstantInt8(sbyte a)
{
ExpectInt8((sbyte)(a & 7));
ExpectInt8((sbyte)(a & 0x7F));
}
public void BitwiseOrWithConstantUInt64(ulong a)
{
ExpectUInt64(a | 7);
ExpectUInt64(a | 0x7FFFFFFF);
ExpectUInt64(a | 0xFFFFFFFFu);
ExpectUInt64(a | 0x7FFFFFFFFFFFFFFFuL);
ExpectUInt64(a | 0xFFFFFFFFFFFFFFFFuL);
}
public void BitwiseOrWithConstantInt64(long a)
{
ExpectInt64(a | 7);
ExpectInt64(a | 0x7FFFFFFF);
ExpectInt64(a | 0xFFFFFFFFu);
ExpectInt64(a | 0x7FFFFFFFFFFFFFFFL);
}
public void BitwiseOrWithConstantUInt32(uint a)
{
ExpectUInt32(a | 7u);
ExpectUInt32(a | 0x7FFFFFFFu);
ExpectUInt32(a | 0xFFFFFFFFu);
}
public void BitwiseOrWithConstantInt32(int a)
{
ExpectInt32(a | 7);
ExpectInt32(a | 0x7FFFFFFF);
}
public void BitwiseOrWithConstantUInt16(ushort a)
{
ExpectUInt16((ushort)(a | 7u));
ExpectUInt16((ushort)(a | 0x7FFFu));
ExpectUInt16((ushort)(a | 0xFFFFu));
}
public void BitwiseOrWithConstantInt16(short a)
{
ExpectInt16((short)(a | 7));
ExpectInt16((short)(a | 0x7FFF));
}
public void BitwiseOrWithConstantUInt8(byte a)
{
ExpectUInt8((byte)(a | 7u));
ExpectUInt8((byte)(a | 0x7Fu));
ExpectUInt8((byte)(a | 0xFFu));
}
public void BitwiseOrWithConstantInt8(sbyte a)
{
ExpectInt8((sbyte)(a | 7));
ExpectInt8((sbyte)(a | 0x7F));
}
public void BitwiseXorWithConstantUInt64(ulong a)
{
ExpectUInt64(a ^ 7);
ExpectUInt64(a ^ 0x7FFFFFFF);
ExpectUInt64(a ^ 0xFFFFFFFFu);
ExpectUInt64(a ^ 0x7FFFFFFFFFFFFFFFuL);
ExpectUInt64(a ^ 0xFFFFFFFFFFFFFFFFuL);
}
public void BitwiseXorWithConstantInt64(long a)
{
ExpectInt64(a ^ 7);
ExpectInt64(a ^ 0x7FFFFFFF);
ExpectInt64(a ^ 0xFFFFFFFFu);
ExpectInt64(a ^ 0x7FFFFFFFFFFFFFFFL);
}
public void BitwiseXorWithConstantUInt32(uint a)
{
ExpectUInt32(a ^ 7u);
ExpectUInt32(a ^ 0x7FFFFFFFu);
ExpectUInt32(a ^ 0xFFFFFFFFu);
}
public void BitwiseXorWithConstantInt32(int a)
{
ExpectInt32(a ^ 7);
ExpectInt32(a ^ 0x7FFFFFFF);
}
public void BitwiseXorWithConstantUInt16(ushort a)
{
ExpectUInt16((ushort)(a ^ 7u));
ExpectUInt16((ushort)(a ^ 0x7FFFu));
ExpectUInt16((ushort)(a ^ 0xFFFFu));
}
public void BitwiseXorWithConstantInt16(short a)
{
ExpectInt16((short)(a ^ 7));
ExpectInt16((short)(a ^ 0x7FFF));
}
public void BitwiseXorWithConstantUInt8(byte a)
{
ExpectUInt8((byte)(a ^ 7u));
ExpectUInt8((byte)(a ^ 0x7Fu));
ExpectUInt8((byte)(a ^ 0xFFu));
}
public void BitwiseXorWithConstantInt8(sbyte a)
{
ExpectInt8((sbyte)(a ^ 7));
ExpectInt8((sbyte)(a ^ 0x7F));
}
private void ExpectUInt64(ulong _)
{
}
private void ExpectInt64(long _)
{
}
private void ExpectUInt32(uint _)
{
}
private void ExpectInt32(int _)
{
}
private void ExpectUInt16(ushort _)
{
}
private void ExpectInt16(short _)
{
}
private void ExpectUInt8(byte _)
{
}
private void ExpectInt8(sbyte _)
{
}
}
}

19
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs

@ -28,6 +28,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -28,6 +28,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
private byte[] byteArray;
private ulong uint64Field;
public int Issue1796a {
get {
return (int)(uint64Field & 0x7FFFFFFF);
}
set {
uint64Field = ((uint64Field & 0xFFFFFFFF80000000uL) | (ulong)value);
}
}
public ushort Issue1796b {
get {
return (ushort)((uint64Field & 0xFFFF000000000000uL) >> 48);
}
set {
uint64Field = ((uint64Field & 0xFFFFFFFFFFFFuL) | ((ulong)value << 48));
}
}
public byte SubtractFrom256(byte b)
{

81
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -133,6 +133,20 @@ namespace ICSharpCode.Decompiler.CSharp @@ -133,6 +133,20 @@ namespace ICSharpCode.Decompiler.CSharp
return new ExpressionWithResolveResult(expr, exprRR);
}
public ExpressionWithResolveResult ConvertConstantValue(ResolveResult rr,
bool allowImplicitConversion = false, bool displayAsHex = false)
{
astBuilder.PrintIntegralValuesAsHex = displayAsHex;
try
{
return ConvertConstantValue(rr, allowImplicitConversion);
}
finally
{
astBuilder.PrintIntegralValuesAsHex = false;
}
}
public TranslatedExpression Translate(ILInstruction inst, IType typeHint = null)
{
Debug.Assert(inst != null);
@ -503,16 +517,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -503,16 +517,11 @@ namespace ICSharpCode.Decompiler.CSharp
);
}
rr = AdjustConstantToType(rr, context.TypeHint);
astBuilder.PrintIntegralValuesAsHex = ShouldDisplayAsHex(inst.Value, inst.Parent);
try
{
return ConvertConstantValue(rr, allowImplicitConversion: true)
.WithILInstruction(inst);
}
finally
{
astBuilder.PrintIntegralValuesAsHex = false;
}
return ConvertConstantValue(
rr,
allowImplicitConversion: true,
ShouldDisplayAsHex(inst.Value, rr.Type, inst.Parent)
).WithILInstruction(inst);
}
protected internal override TranslatedExpression VisitLdcI8(LdcI8 inst, TranslationContext context)
@ -533,23 +542,20 @@ namespace ICSharpCode.Decompiler.CSharp @@ -533,23 +542,20 @@ namespace ICSharpCode.Decompiler.CSharp
);
}
rr = AdjustConstantToType(rr, context.TypeHint);
astBuilder.PrintIntegralValuesAsHex = ShouldDisplayAsHex(inst.Value, inst.Parent);
try
{
return ConvertConstantValue(rr, allowImplicitConversion: true)
.WithILInstruction(inst);
}
finally
{
astBuilder.PrintIntegralValuesAsHex = false;
}
return ConvertConstantValue(
rr,
allowImplicitConversion: true,
ShouldDisplayAsHex(inst.Value, rr.Type, inst.Parent)
).WithILInstruction(inst);
}
private bool ShouldDisplayAsHex(long value, ILInstruction parent)
private bool ShouldDisplayAsHex(long value, IType type, ILInstruction parent)
{
if (parent is Conv conv)
parent = conv.Parent;
if (value <= 9)
if (value >= 0 && value <= 9)
return false;
if (value < 0 && type.GetSign() == Sign.Signed)
return false;
switch (parent)
{
@ -1419,8 +1425,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1419,8 +1425,8 @@ namespace ICSharpCode.Decompiler.CSharp
TranslatedExpression HandleBinaryNumeric(BinaryNumericInstruction inst, BinaryOperatorType op, TranslationContext context)
{
var resolverWithOverflowCheck = resolver.WithCheckForOverflow(inst.CheckForOverflow);
var left = Translate(inst.Left);
var right = Translate(inst.Right);
var left = Translate(inst.Left, op.IsBitwise() ? context.TypeHint : null);
var right = Translate(inst.Right, op.IsBitwise() ? context.TypeHint : null);
if (left.Type.Kind == TypeKind.ByReference || right.Type.Kind == TypeKind.ByReference)
{
@ -1488,12 +1494,39 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1488,12 +1494,39 @@ namespace ICSharpCode.Decompiler.CSharp
{
// If the sign doesn't matter, try to use the same sign as expected by the context
sign = context.TypeHint.GetSign();
if (sign == Sign.None)
{
sign = op.IsBitwise() ? Sign.Unsigned : Sign.Signed;
}
}
IType targetType = FindArithmeticType(inst.UnderlyingResultType, sign);
left = left.ConvertTo(NullableType.IsNullable(left.Type) ? NullableType.Create(compilation, targetType) : targetType, this);
right = right.ConvertTo(NullableType.IsNullable(right.Type) ? NullableType.Create(compilation, targetType) : targetType, this);
rr = resolverWithOverflowCheck.ResolveBinaryOperator(op, left.ResolveResult, right.ResolveResult);
}
if (op.IsBitwise())
{
if (left.ResolveResult.ConstantValue != null)
{
long value = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, left.ResolveResult.ConstantValue, checkForOverflow: false);
left = ConvertConstantValue(
left.ResolveResult,
allowImplicitConversion: false,
ShouldDisplayAsHex(value, left.Type, inst)
).WithILInstruction(left.ILInstructions);
}
if (right.ResolveResult.ConstantValue != null)
{
long value = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, right.ResolveResult.ConstantValue, checkForOverflow: false);
right = ConvertConstantValue(
right.ResolveResult,
allowImplicitConversion: false,
ShouldDisplayAsHex(value, right.Type, inst)
).WithILInstruction(right.ILInstructions);
}
}
var resultExpr = new BinaryOperatorExpression(left.Expression, op, right.Expression)
.WithILInstruction(inst)
.WithRR(rr);

Loading…
Cancel
Save