Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit d1eba76

Browse files
committed
Merge pull request #3754 from bartdesmet/Issue-3750
Fixing expression interpreter for NegateChecked overflow behavior
2 parents eff8394 + 663b0d9 commit d1eba76

File tree

4 files changed

+824
-91
lines changed

4 files changed

+824
-91
lines changed

src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/TypeOperations.cs

Lines changed: 18 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ public override int Run(InterpretedFrame frame)
308308

309309
internal abstract class NegateInstruction : Instruction
310310
{
311-
private static Instruction s_int16,s_int32,s_int64,s_UInt16,s_UInt32,s_single,s_double;
311+
private static Instruction s_int16, s_int32, s_int64, s_single, s_double;
312312

313313
public override int ConsumedStack { get { return 1; } }
314314
public override int ProducedStack { get { return 1; } }
@@ -348,7 +348,7 @@ public override int Run(InterpretedFrame frame)
348348
}
349349
else
350350
{
351-
frame.Push((Int16)unchecked(-(Int16)obj));
351+
frame.Push(unchecked((Int16)(-(Int16)obj)));
352352
}
353353
return +1;
354354
}
@@ -365,41 +365,7 @@ public override int Run(InterpretedFrame frame)
365365
}
366366
else
367367
{
368-
frame.Push((Int64)unchecked(-(Int64)obj));
369-
}
370-
return +1;
371-
}
372-
}
373-
374-
internal sealed class NegateUInt16 : NegateInstruction
375-
{
376-
public override int Run(InterpretedFrame frame)
377-
{
378-
object obj = frame.Pop();
379-
if (obj == null)
380-
{
381-
frame.Push(null);
382-
}
383-
else
384-
{
385-
frame.Push((Int16)unchecked(-(UInt16)obj));
386-
}
387-
return +1;
388-
}
389-
}
390-
391-
internal sealed class NegateUInt32 : NegateInstruction
392-
{
393-
public override int Run(InterpretedFrame frame)
394-
{
395-
object obj = frame.Pop();
396-
if (obj == null)
397-
{
398-
frame.Push(null);
399-
}
400-
else
401-
{
402-
frame.Push((Int32)unchecked(-(UInt32)obj));
368+
frame.Push(unchecked((Int64)(-(Int64)obj)));
403369
}
404370
return +1;
405371
}
@@ -416,7 +382,7 @@ public override int Run(InterpretedFrame frame)
416382
}
417383
else
418384
{
419-
frame.Push((Single)unchecked(-(Single)obj));
385+
frame.Push(unchecked((Single)(-(Single)obj)));
420386
}
421387
return +1;
422388
}
@@ -433,7 +399,7 @@ public override int Run(InterpretedFrame frame)
433399
}
434400
else
435401
{
436-
frame.Push((Double)unchecked(-(Double)obj));
402+
frame.Push(unchecked((Double)(-(Double)obj)));
437403
}
438404
return +1;
439405
}
@@ -447,8 +413,6 @@ public static Instruction Create(Type type)
447413
case TypeCode.Int16: return s_int16 ?? (s_int16 = new NegateInt16());
448414
case TypeCode.Int32: return s_int32 ?? (s_int32 = new NegateInt32());
449415
case TypeCode.Int64: return s_int64 ?? (s_int64 = new NegateInt64());
450-
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new NegateUInt16());
451-
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new NegateUInt32());
452416
case TypeCode.Single: return s_single ?? (s_single = new NegateSingle());
453417
case TypeCode.Double: return s_double ?? (s_double = new NegateDouble());
454418

@@ -465,7 +429,7 @@ public override string ToString()
465429

466430
internal abstract class NegateCheckedInstruction : Instruction
467431
{
468-
private static Instruction s_int16,s_int32,s_int64,s_UInt16,s_UInt32,s_single,s_double;
432+
private static Instruction s_int16, s_int32, s_int64, s_single, s_double;
469433

470434
public override int ConsumedStack { get { return 1; } }
471435
public override int ProducedStack { get { return 1; } }
@@ -505,7 +469,7 @@ public override int Run(InterpretedFrame frame)
505469
}
506470
else
507471
{
508-
frame.Push((Int16)checked(-(Int16)obj));
472+
frame.Push(checked((Int16)(-(Int16)obj)));
509473
}
510474
return +1;
511475
}
@@ -522,46 +486,11 @@ public override int Run(InterpretedFrame frame)
522486
}
523487
else
524488
{
525-
frame.Push((Int64)checked(-(Int64)obj));
489+
frame.Push(checked((Int64)(-(Int64)obj)));
526490
}
527491
return +1;
528492
}
529493
}
530-
531-
internal sealed class NegateCheckedUInt16 : NegateCheckedInstruction
532-
{
533-
public override int Run(InterpretedFrame frame)
534-
{
535-
object obj = frame.Pop();
536-
if (obj == null)
537-
{
538-
frame.Push(null);
539-
}
540-
else
541-
{
542-
frame.Push((Int16)checked(-(UInt16)obj));
543-
}
544-
return +1;
545-
}
546-
}
547-
548-
internal sealed class NegateCheckedUInt32 : NegateCheckedInstruction
549-
{
550-
public override int Run(InterpretedFrame frame)
551-
{
552-
object obj = frame.Pop();
553-
if (obj == null)
554-
{
555-
frame.Push(null);
556-
}
557-
else
558-
{
559-
frame.Push((Int32)checked(-(UInt32)obj));
560-
}
561-
return +1;
562-
}
563-
}
564-
565494
internal sealed class NegateCheckedSingle : NegateCheckedInstruction
566495
{
567496
public override int Run(InterpretedFrame frame)
@@ -573,7 +502,7 @@ public override int Run(InterpretedFrame frame)
573502
}
574503
else
575504
{
576-
frame.Push((Single)checked(-(Single)obj));
505+
frame.Push(checked((Single)(-(Single)obj)));
577506
}
578507
return +1;
579508
}
@@ -590,7 +519,7 @@ public override int Run(InterpretedFrame frame)
590519
}
591520
else
592521
{
593-
frame.Push((Double)checked(-(Double)obj));
522+
frame.Push(checked((Double)(-(Double)obj)));
594523
}
595524
return +1;
596525
}
@@ -604,8 +533,6 @@ public static Instruction Create(Type type)
604533
case TypeCode.Int16: return s_int16 ?? (s_int16 = new NegateCheckedInt16());
605534
case TypeCode.Int32: return s_int32 ?? (s_int32 = new NegateCheckedInt32());
606535
case TypeCode.Int64: return s_int64 ?? (s_int64 = new NegateCheckedInt64());
607-
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new NegateCheckedUInt16());
608-
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new NegateCheckedUInt32());
609536
case TypeCode.Single: return s_single ?? (s_single = new NegateCheckedSingle());
610537
case TypeCode.Double: return s_double ?? (s_double = new NegateCheckedDouble());
611538
default:
@@ -796,7 +723,7 @@ public override string ToString()
796723

797724
internal abstract class IncrementInstruction : Instruction
798725
{
799-
private static Instruction s_int16,s_int32,s_int64,s_UInt16,s_UInt32,s_single,s_double;
726+
private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_single, s_double;
800727

801728
public override int ConsumedStack { get { return 1; } }
802729
public override int ProducedStack { get { return 1; } }
@@ -953,7 +880,7 @@ public override string ToString()
953880

954881
internal abstract class DecrementInstruction : Instruction
955882
{
956-
private static Instruction s_int16,s_int32,s_int64,s_UInt16,s_UInt32,s_single,s_double;
883+
private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_single, s_double;
957884

958885
public override int ConsumedStack { get { return 1; } }
959886
public override int ProducedStack { get { return 1; } }
@@ -1111,7 +1038,7 @@ public override string ToString()
11111038

11121039
internal abstract class LeftShiftInstruction : Instruction
11131040
{
1114-
private static Instruction s_SByte,s_int16,s_int32,s_int64,s_byte,s_UInt16,s_UInt32,s_UInt64;
1041+
private static Instruction s_SByte, s_int16, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64;
11151042

11161043
public override int ConsumedStack { get { return 2; } }
11171044
public override int ProducedStack { get { return 1; } }
@@ -1296,7 +1223,7 @@ public override string ToString()
12961223

12971224
internal abstract class RightShiftInstruction : Instruction
12981225
{
1299-
private static Instruction s_SByte,s_int16,s_int32,s_int64,s_byte,s_UInt16,s_UInt32,s_UInt64;
1226+
private static Instruction s_SByte, s_int16, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64;
13001227

13011228
public override int ConsumedStack { get { return 2; } }
13021229
public override int ProducedStack { get { return 1; } }
@@ -1481,7 +1408,7 @@ public override string ToString()
14811408

14821409
internal abstract class ExclusiveOrInstruction : Instruction
14831410
{
1484-
private static Instruction s_SByte,s_int16,s_int32,s_int64,s_byte,s_UInt16,s_UInt32,s_UInt64,s_bool;
1411+
private static Instruction s_SByte, s_int16, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64, s_bool;
14851412

14861413
public override int ConsumedStack { get { return 2; } }
14871414
public override int ProducedStack { get { return 1; } }
@@ -1672,7 +1599,7 @@ public override string ToString()
16721599

16731600
internal abstract class OrInstruction : Instruction
16741601
{
1675-
private static Instruction s_SByte,s_int16,s_int32,s_int64,s_byte,s_UInt16,s_UInt32,s_UInt64,s_bool;
1602+
private static Instruction s_SByte, s_int16, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64, s_bool;
16761603

16771604
public override int ConsumedStack { get { return 2; } }
16781605
public override int ProducedStack { get { return 1; } }
@@ -1870,7 +1797,7 @@ public override string ToString()
18701797

18711798
internal abstract class AndInstruction : Instruction
18721799
{
1873-
private static Instruction s_SByte,s_int16,s_int32,s_int64,s_byte,s_UInt16,s_UInt32,s_UInt64,s_bool;
1800+
private static Instruction s_SByte, s_int16, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64, s_bool;
18741801

18751802
public override int ConsumedStack { get { return 2; } }
18761803
public override int ProducedStack { get { return 1; } }
@@ -2233,7 +2160,7 @@ public static Instruction CreateGetValue()
22332160

22342161
internal abstract class CastInstruction : Instruction
22352162
{
2236-
private static CastInstruction s_boolean,s_byte,s_char,s_dateTime,s_decimal,s_double,s_int16,s_int32,s_int64, s_SByte,s_single,s_string,s_UInt16,s_UInt32,s_UInt64;
2163+
private static CastInstruction s_boolean, s_byte, s_char, s_dateTime, s_decimal, s_double, s_int16, s_int32, s_int64, s_SByte, s_single, s_string, s_UInt16, s_UInt32, s_UInt64;
22372164

22382165
public override int ConsumedStack { get { return 1; } }
22392166
public override int ProducedStack { get { return 1; } }

src/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,9 @@
133133
<Compile Include="Ternary\TernaryNullableTests.cs" />
134134
<Compile Include="Ternary\TernaryTests.cs" />
135135
<Compile Include="Unary\UnaryArithmeticNegateNullableOneOffTests.cs" />
136+
<Compile Include="Unary\UnaryArithmeticNegateCheckedNullableTests.cs" />
136137
<Compile Include="Unary\UnaryArithmeticNegateNullableTests.cs" />
138+
<Compile Include="Unary\UnaryArithmeticNegateCheckedTests.cs" />
137139
<Compile Include="Unary\UnaryArithmeticNegateTests.cs" />
138140
<Compile Include="Unary\UnaryBitwiseNotNullableTests.cs" />
139141
<Compile Include="Unary\UnaryBitwiseNotTests.cs" />

0 commit comments

Comments
 (0)