Imported Upstream version 5.8.0.22

Former-commit-id: df344e34b07851d296efb3e6604c8db42b6f7aa3
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-10-19 20:04:20 +00:00
parent 5f4a27cc8a
commit 7d05485754
5020 changed files with 114082 additions and 186061 deletions

View File

@@ -155,7 +155,7 @@
</Type>
</Namespace>
<Namespace Name="System.Collections.Generic">
<Type Name="IEnumerable&lt;&gt;" Dynamic="Required">
<Type Name="IEnumerable&lt;&gt;">
<Method Name="GetEnumerator" Dynamic="Required"/>
</Type>
<Type Name="IEnumerator&lt;&gt;">

View File

@@ -904,7 +904,6 @@ namespace System.Linq.Expressions.Compiler
Label labEnd;
LocalBuilder locFrom = locals.GetLocal(typeFrom);
il.Emit(OpCodes.Stloc, locFrom);
LocalBuilder locTo = locals.GetLocal(typeTo);
// test for null
il.Emit(OpCodes.Ldloca, locFrom);
il.EmitHasValue(typeFrom);
@@ -919,16 +918,16 @@ namespace System.Linq.Expressions.Compiler
// construct result type
ConstructorInfo ci = typeTo.GetConstructor(new Type[] { nnTypeTo });
il.Emit(OpCodes.Newobj, ci);
il.Emit(OpCodes.Stloc, locTo);
labEnd = il.DefineLabel();
il.Emit(OpCodes.Br_S, labEnd);
// if null then create a default one
il.MarkLabel(labIfNull);
LocalBuilder locTo = locals.GetLocal(typeTo);
il.Emit(OpCodes.Ldloca, locTo);
il.Emit(OpCodes.Initobj, typeTo);
il.MarkLabel(labEnd);
il.Emit(OpCodes.Ldloc, locTo);
locals.FreeLocal(locTo);
il.MarkLabel(labEnd);
}
@@ -936,14 +935,10 @@ namespace System.Linq.Expressions.Compiler
{
Debug.Assert(!typeFrom.IsNullableType());
Debug.Assert(typeTo.IsNullableType());
LocalBuilder locTo = locals.GetLocal(typeTo);
Type nnTypeTo = typeTo.GetNonNullableType();
il.EmitConvertToType(typeFrom, nnTypeTo, isChecked, locals);
ConstructorInfo ci = typeTo.GetConstructor(new Type[] { nnTypeTo });
il.Emit(OpCodes.Newobj, ci);
il.Emit(OpCodes.Stloc, locTo);
il.Emit(OpCodes.Ldloc, locTo);
locals.FreeLocal(locTo);
}

View File

@@ -150,43 +150,33 @@ namespace System.Linq.Expressions.Compiler
{
Debug.Assert(!leftType.IsNullableType());
Debug.Assert(!rightType.IsNullableType());
if (op == ExpressionType.Equal || op == ExpressionType.NotEqual)
{
EmitUnliftedEquality(op, leftType);
return;
}
Debug.Assert(leftType.IsPrimitive);
Debug.Assert(leftType.IsPrimitive || (op == ExpressionType.Equal || op == ExpressionType.NotEqual) && (!leftType.IsValueType || leftType.IsEnum));
switch (op)
{
case ExpressionType.NotEqual:
if (leftType.GetTypeCode() == TypeCode.Boolean)
{
goto case ExpressionType.ExclusiveOr;
}
_ilg.Emit(OpCodes.Ceq);
_ilg.Emit(OpCodes.Ldc_I4_0);
goto case ExpressionType.Equal;
case ExpressionType.Equal:
_ilg.Emit(OpCodes.Ceq);
return;
case ExpressionType.Add:
_ilg.Emit(OpCodes.Add);
break;
case ExpressionType.AddChecked:
if (leftType.IsFloatingPoint())
{
_ilg.Emit(OpCodes.Add);
}
else if (leftType.IsUnsigned())
{
_ilg.Emit(OpCodes.Add_Ovf_Un);
}
else
{
_ilg.Emit(OpCodes.Add_Ovf);
}
_ilg.Emit(leftType.IsFloatingPoint() ? OpCodes.Add : (leftType.IsUnsigned() ? OpCodes.Add_Ovf_Un : OpCodes.Add_Ovf));
break;
case ExpressionType.Subtract:
_ilg.Emit(OpCodes.Sub);
break;
case ExpressionType.SubtractChecked:
if (leftType.IsFloatingPoint())
{
_ilg.Emit(OpCodes.Sub);
}
else if (leftType.IsUnsigned())
if (leftType.IsUnsigned())
{
_ilg.Emit(OpCodes.Sub_Ovf_Un);
// Guaranteed to fit within result type: no conversion
@@ -194,25 +184,14 @@ namespace System.Linq.Expressions.Compiler
}
else
{
_ilg.Emit(OpCodes.Sub_Ovf);
_ilg.Emit(leftType.IsFloatingPoint() ? OpCodes.Sub : OpCodes.Sub_Ovf);
}
break;
case ExpressionType.Multiply:
_ilg.Emit(OpCodes.Mul);
break;
case ExpressionType.MultiplyChecked:
if (leftType.IsFloatingPoint())
{
_ilg.Emit(OpCodes.Mul);
}
else if (leftType.IsUnsigned())
{
_ilg.Emit(OpCodes.Mul_Ovf_Un);
}
else
{
_ilg.Emit(OpCodes.Mul_Ovf);
}
_ilg.Emit(leftType.IsFloatingPoint() ? OpCodes.Mul : (leftType.IsUnsigned() ? OpCodes.Mul_Ovf_Un : OpCodes.Mul_Ovf));
break;
case ExpressionType.Divide:
_ilg.Emit(leftType.IsUnsigned() ? OpCodes.Div_Un : OpCodes.Div);
@@ -306,19 +285,6 @@ namespace System.Linq.Expressions.Compiler
}
}
private void EmitUnliftedEquality(ExpressionType op, Type type)
{
Debug.Assert(op == ExpressionType.Equal || op == ExpressionType.NotEqual);
Debug.Assert(type.IsPrimitive || !type.IsValueType || type.IsEnum);
_ilg.Emit(OpCodes.Ceq);
if (op == ExpressionType.NotEqual)
{
_ilg.Emit(OpCodes.Ldc_I4_0);
_ilg.Emit(OpCodes.Ceq);
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
private void EmitLiftedBinaryOp(ExpressionType op, Type leftType, Type rightType, Type resultType, bool liftedToNull)
{

View File

@@ -146,17 +146,20 @@ namespace System.Linq.Expressions.Compiler
// emit call to invoke
_ilg.Emit(OpCodes.Callvirt, b.Conversion.Type.GetInvokeMethod());
}
else if (!TypeUtils.AreEquivalent(b.Type, nnLeftType))
else if (TypeUtils.AreEquivalent(b.Type, b.Left.Type))
{
_ilg.Emit(OpCodes.Ldloca, loc);
_ilg.EmitGetValueOrDefault(b.Left.Type);
_ilg.EmitConvertToType(nnLeftType, b.Type, isChecked: true, locals: this);
_ilg.Emit(OpCodes.Ldloc, loc);
}
else
{
_ilg.Emit(OpCodes.Ldloca, loc);
_ilg.EmitGetValueOrDefault(b.Left.Type);
if (!TypeUtils.AreEquivalent(b.Type, nnLeftType))
{
_ilg.EmitConvertToType(nnLeftType, b.Type, isChecked: true, locals: this);
}
}
FreeLocal(loc);
_ilg.Emit(OpCodes.Br, labEnd);
@@ -273,6 +276,8 @@ namespace System.Linq.Expressions.Compiler
private void EmitMethodAndAlso(BinaryExpression b, CompilationFlags flags)
{
Debug.Assert(b.Method.IsStatic);
Label labEnd = _ilg.DefineLabel();
EmitExpression(b.Left);
_ilg.Emit(OpCodes.Dup);
@@ -281,25 +286,13 @@ namespace System.Linq.Expressions.Compiler
_ilg.Emit(OpCodes.Call, opFalse);
_ilg.Emit(OpCodes.Brtrue, labEnd);
//store the value of the left value before emitting b.Right to empty the evaluation stack
LocalBuilder locLeft = GetLocal(b.Left.Type);
_ilg.Emit(OpCodes.Stloc, locLeft);
EmitExpression(b.Right);
//store the right value to local
LocalBuilder locRight = GetLocal(b.Right.Type);
_ilg.Emit(OpCodes.Stloc, locRight);
Debug.Assert(b.Method.IsStatic);
_ilg.Emit(OpCodes.Ldloc, locLeft);
_ilg.Emit(OpCodes.Ldloc, locRight);
if ((flags & CompilationFlags.EmitAsTailCallMask) == CompilationFlags.EmitAsTail)
{
_ilg.Emit(OpCodes.Tailcall);
}
_ilg.Emit(OpCodes.Call, b.Method);
FreeLocal(locLeft);
FreeLocal(locRight);
_ilg.MarkLabel(labEnd);
}
@@ -319,18 +312,21 @@ namespace System.Linq.Expressions.Compiler
{
BinaryExpression b = (BinaryExpression)expr;
if (b.Method != null && !b.IsLiftedLogical)
if (b.Method != null)
{
EmitMethodAndAlso(b, flags);
if (b.IsLiftedLogical)
{
EmitExpression(b.ReduceUserdefinedLifted());
}
else
{
EmitMethodAndAlso(b, flags);
}
}
else if (b.Left.Type == typeof(bool?))
{
EmitLiftedAndAlso(b);
}
else if (b.IsLiftedLogical)
{
EmitExpression(b.ReduceUserdefinedLifted());
}
else
{
EmitUnliftedAndAlso(b);
@@ -386,33 +382,23 @@ namespace System.Linq.Expressions.Compiler
private void EmitMethodOrElse(BinaryExpression b, CompilationFlags flags)
{
Debug.Assert(b.Method.IsStatic);
Label labEnd = _ilg.DefineLabel();
EmitExpression(b.Left);
_ilg.Emit(OpCodes.Dup);
MethodInfo opTrue = TypeUtils.GetBooleanOperator(b.Method.DeclaringType, "op_True");
Debug.Assert(opTrue != null, "factory should check that the method exists");
_ilg.Emit(OpCodes.Call, opTrue);
_ilg.Emit(OpCodes.Brtrue, labEnd);
//store the value of the left value before emitting b.Right to empty the evaluation stack
LocalBuilder locLeft = GetLocal(b.Left.Type);
_ilg.Emit(OpCodes.Stloc, locLeft);
EmitExpression(b.Right);
//store the right value to local
LocalBuilder locRight = GetLocal(b.Right.Type);
_ilg.Emit(OpCodes.Stloc, locRight);
Debug.Assert(b.Method.IsStatic);
_ilg.Emit(OpCodes.Ldloc, locLeft);
_ilg.Emit(OpCodes.Ldloc, locRight);
if ((flags & CompilationFlags.EmitAsTailCallMask) == CompilationFlags.EmitAsTail)
{
_ilg.Emit(OpCodes.Tailcall);
}
_ilg.Emit(OpCodes.Call, b.Method);
FreeLocal(locLeft);
FreeLocal(locRight);
_ilg.MarkLabel(labEnd);
}
@@ -420,18 +406,21 @@ namespace System.Linq.Expressions.Compiler
{
BinaryExpression b = (BinaryExpression)expr;
if (b.Method != null && !b.IsLiftedLogical)
if (b.Method != null)
{
EmitMethodOrElse(b, flags);
if (b.IsLiftedLogical)
{
EmitExpression(b.ReduceUserdefinedLifted());
}
else
{
EmitMethodOrElse(b, flags);
}
}
else if (b.Left.Type == typeof(bool?))
{
EmitLiftedOrElse(b);
}
else if (b.IsLiftedLogical)
{
EmitExpression(b.ReduceUserdefinedLifted());
}
else
{
EmitUnliftedOrElse(b);
@@ -468,36 +457,36 @@ namespace System.Linq.Expressions.Compiler
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
private void EmitExpressionAndBranch(bool branchValue, Expression node, Label label)
{
Debug.Assert(node.Type == typeof(bool));
CompilationFlags startEmitted = EmitExpressionStart(node);
try
switch (node.NodeType)
{
if (node.Type == typeof(bool))
{
switch (node.NodeType)
{
case ExpressionType.Not:
EmitBranchNot(branchValue, (UnaryExpression)node, label);
return;
case ExpressionType.AndAlso:
case ExpressionType.OrElse:
EmitBranchLogical(branchValue, (BinaryExpression)node, label);
return;
case ExpressionType.Block:
EmitBranchBlock(branchValue, (BlockExpression)node, label);
return;
case ExpressionType.Equal:
case ExpressionType.NotEqual:
EmitBranchComparison(branchValue, (BinaryExpression)node, label);
return;
}
}
EmitExpression(node, CompilationFlags.EmitAsNoTail | CompilationFlags.EmitNoExpressionStart);
EmitBranchOp(branchValue, label);
}
finally
{
EmitExpressionEnd(startEmitted);
case ExpressionType.Not:
EmitBranchNot(branchValue, (UnaryExpression)node, label);
break;
case ExpressionType.AndAlso:
case ExpressionType.OrElse:
EmitBranchLogical(branchValue, (BinaryExpression)node, label);
break;
case ExpressionType.Block:
EmitBranchBlock(branchValue, (BlockExpression)node, label);
break;
case ExpressionType.Equal:
case ExpressionType.NotEqual:
EmitBranchComparison(branchValue, (BinaryExpression)node, label);
break;
default:
EmitExpression(node, CompilationFlags.EmitAsNoTail | CompilationFlags.EmitNoExpressionStart);
EmitBranchOp(branchValue, label);
break;
}
EmitExpressionEnd(startEmitted);
}
private void EmitBranchOp(bool branch, Label label)
@@ -513,6 +502,7 @@ namespace System.Linq.Expressions.Compiler
EmitBranchOp(branch, label);
return;
}
EmitExpressionAndBranch(!branch, node.Operand, label);
}

View File

@@ -72,14 +72,44 @@ namespace System.Linq.Expressions.Compiler
}
else if (node.NodeType == ExpressionType.NegateChecked && node.Operand.Type.IsInteger())
{
EmitExpression(node.Operand);
LocalBuilder loc = GetLocal(node.Operand.Type);
_ilg.Emit(OpCodes.Stloc, loc);
_ilg.EmitPrimitive(0);
_ilg.EmitConvertToType(typeof(int), node.Operand.Type, isChecked: false, locals: this);
_ilg.Emit(OpCodes.Ldloc, loc);
FreeLocal(loc);
EmitBinaryOperator(ExpressionType.SubtractChecked, node.Operand.Type, node.Operand.Type, node.Type, liftedToNull: false);
Type type = node.Type;
Debug.Assert(type == node.Operand.Type);
if (type.IsNullableType())
{
Label nullOrZero = _ilg.DefineLabel();
Label end = _ilg.DefineLabel();
EmitExpression(node.Operand);
LocalBuilder loc = GetLocal(type);
// check for null or zero
_ilg.Emit(OpCodes.Stloc, loc);
_ilg.Emit(OpCodes.Ldloca, loc);
_ilg.EmitGetValueOrDefault(type);
_ilg.Emit(OpCodes.Brfalse_S, nullOrZero);
// calculate 0 - operand
Type nnType = type.GetNonNullableType();
_ilg.EmitDefault(nnType, locals: null); // locals won't be used.
_ilg.Emit(OpCodes.Ldloca, loc);
_ilg.EmitGetValueOrDefault(type);
EmitBinaryOperator(ExpressionType.SubtractChecked, nnType, nnType, nnType, liftedToNull: false);
// construct result
_ilg.Emit(OpCodes.Newobj, type.GetConstructor(new Type[] { nnType }));
_ilg.Emit(OpCodes.Br_S, end);
// if null then push back on stack
_ilg.MarkLabel(nullOrZero);
_ilg.Emit(OpCodes.Ldloc, loc);
FreeLocal(loc);
_ilg.MarkLabel(end);
}
else
{
_ilg.EmitDefault(type, locals: null); // locals won't be used.
EmitExpression(node.Operand);
EmitBinaryOperator(ExpressionType.SubtractChecked, type, type, type, liftedToNull: false);
}
}
else
{

View File

@@ -47,12 +47,10 @@ namespace System.Linq.Expressions.Interpreter
public override int Run(InterpretedFrame frame)
{
int length = ConvertHelper.ToInt32NoNull(frame.Pop());
if (length < 0)
{
// to make behavior aligned with array creation emitted by C# compiler
throw new OverflowException();
}
frame.Push(Array.CreateInstance(_elementType, length));
// To make behavior aligned with array creation emitted by C# compiler if length is less than
// zero we try to use it to create an array, which will throw an OverflowException with the
// correct localized error message.
frame.Push(length < 0 ? new int[length] : Array.CreateInstance(_elementType, length));
return 1;
}
}

View File

@@ -13,7 +13,7 @@ namespace System.Linq.Expressions.Interpreter
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
[ThreadStatic]
public static InterpretedFrame CurrentFrame;
private static InterpretedFrame s_currentFrame;
internal readonly Interpreter Interpreter;
internal InterpretedFrame _parent;
@@ -177,14 +177,14 @@ namespace System.Linq.Expressions.Interpreter
internal InterpretedFrame Enter()
{
InterpretedFrame currentFrame = CurrentFrame;
CurrentFrame = this;
InterpretedFrame currentFrame = s_currentFrame;
s_currentFrame = this;
return _parent = currentFrame;
}
internal void Leave(InterpretedFrame prevFrame)
{
CurrentFrame = prevFrame;
s_currentFrame = prevFrame;
}
#endregion

View File

@@ -79,7 +79,7 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
frame.Push(unchecked(-(float)obj));
frame.Push(-(float)obj);
}
return 1;
}
@@ -96,7 +96,7 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
frame.Push(unchecked(-(double)obj));
frame.Push(-(double)obj);
}
return 1;
}
@@ -120,7 +120,7 @@ namespace System.Linq.Expressions.Interpreter
internal abstract class NegateCheckedInstruction : Instruction
{
private static Instruction s_Int16, s_Int32, s_Int64, s_Single, s_Double;
private static Instruction s_Int16, s_Int32, s_Int64;
public override int ConsumedStack => 1;
public override int ProducedStack => 1;
@@ -179,40 +179,6 @@ namespace System.Linq.Expressions.Interpreter
}
}
private sealed class NegateCheckedSingle : NegateCheckedInstruction
{
public override int Run(InterpretedFrame frame)
{
object obj = frame.Pop();
if (obj == null)
{
frame.Push(null);
}
else
{
frame.Push(checked(-(float)obj));
}
return 1;
}
}
private sealed class NegateCheckedDouble : NegateCheckedInstruction
{
public override int Run(InterpretedFrame frame)
{
object obj = frame.Pop();
if (obj == null)
{
frame.Push(null);
}
else
{
frame.Push(checked(-(double)obj));
}
return 1;
}
}
public static Instruction Create(Type type)
{
Debug.Assert(!type.IsEnum);
@@ -221,10 +187,8 @@ namespace System.Linq.Expressions.Interpreter
case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new NegateCheckedInt16());
case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new NegateCheckedInt32());
case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new NegateCheckedInt64());
case TypeCode.Single: return s_Single ?? (s_Single = new NegateCheckedSingle());
case TypeCode.Double: return s_Double ?? (s_Double = new NegateCheckedDouble());
default:
throw ContractUtils.Unreachable;
return NegateInstruction.Create(type);
}
}
}

View File

@@ -11,7 +11,7 @@ namespace System.Linq.Expressions.Interpreter
{
// Perf: EqualityComparer<T> but is 3/2 to 2 times slower.
private static Instruction s_reference, s_Boolean, s_SByte, s_Int16, s_Char, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64, s_Single, s_Double;
private static Instruction s_BooleanLiftedToNull, s_SByteLiftedToNull, s_Int16LiftedToNull, s_CharLiftedToNull, s_Int32LiftedToNull, s_Int64LiftedToNull, s_ByteLiftedToNull, s_UInt16LiftedToNull, s_UInt32LiftedToNull, s_UInt64LiftedToNull, s_SingleLiftedToNull, s_DoubleLiftedToNull;
private static Instruction s_SByteLiftedToNull, s_Int16LiftedToNull, s_CharLiftedToNull, s_Int32LiftedToNull, s_Int64LiftedToNull, s_ByteLiftedToNull, s_UInt16LiftedToNull, s_UInt32LiftedToNull, s_UInt64LiftedToNull, s_SingleLiftedToNull, s_DoubleLiftedToNull;
public override int ConsumedStack => 2;
public override int ProducedStack => 1;
@@ -292,24 +292,6 @@ namespace System.Linq.Expressions.Interpreter
}
}
private sealed class NotEqualBooleanLiftedToNull : NotEqualInstruction
{
public override int Run(InterpretedFrame frame)
{
object right = frame.Pop();
object left = frame.Pop();
if (left == null || right == null)
{
frame.Push(null);
}
else
{
frame.Push((bool)left != (bool)right);
}
return 1;
}
}
private sealed class NotEqualSByteLiftedToNull : NotEqualInstruction
{
public override int Run(InterpretedFrame frame)
@@ -515,7 +497,7 @@ namespace System.Linq.Expressions.Interpreter
{
switch (type.GetNonNullableType().GetTypeCode())
{
case TypeCode.Boolean: return s_BooleanLiftedToNull ?? (s_BooleanLiftedToNull = new NotEqualBooleanLiftedToNull());
case TypeCode.Boolean: return ExclusiveOrInstruction.Create(type);
case TypeCode.SByte: return s_SByteLiftedToNull ?? (s_SByteLiftedToNull = new NotEqualSByteLiftedToNull());
case TypeCode.Int16: return s_Int16LiftedToNull ?? (s_Int16LiftedToNull = new NotEqualInt16LiftedToNull());
case TypeCode.Char: return s_CharLiftedToNull ?? (s_CharLiftedToNull = new NotEqualCharLiftedToNull());

View File

@@ -93,6 +93,26 @@ namespace System.Linq.Expressions
// Null paramName as there are two paths here with different parameter names at the API
TypeUtils.ValidateType(decType, null);
#if __MonoCS__
if (member is PropertyInfo pi)
{
if (!pi.CanWrite)
{
throw Error.PropertyDoesNotHaveSetter(pi, nameof(member));
}
memberType = pi.PropertyType;
}
else if (member is FieldInfo fi)
{
memberType = fi.FieldType;
}
else
{
throw Error.ArgumentMustBeFieldInfoOrPropertyInfo(nameof(member));
}
#else
switch (member)
{
case PropertyInfo pi:
@@ -111,6 +131,7 @@ namespace System.Linq.Expressions
default:
throw Error.ArgumentMustBeFieldInfoOrPropertyInfo(nameof(member));
}
#endif
}
}
}

View File

@@ -127,6 +127,26 @@ namespace System.Linq.Expressions
// Null paramName as there are several paths here with different parameter names at the API
TypeUtils.ValidateType(decType, null, allowByRef: true, allowPointer: true);
#if __MonoCS__
if (member is PropertyInfo pi)
{
if (!pi.CanRead)
{
throw Error.PropertyDoesNotHaveGetter(pi, nameof(member));
}
memberType = pi.PropertyType;
}
else if (member is FieldInfo fi)
{
memberType = fi.FieldType;
}
else
{
throw Error.ArgumentMustBeFieldInfoOrPropertyInfo(nameof(member));
}
#else
switch (member)
{
case PropertyInfo pi:
@@ -145,6 +165,7 @@ namespace System.Linq.Expressions
default:
throw Error.ArgumentMustBeFieldInfoOrPropertyInfo(nameof(member));
}
#endif
}
private static void ValidateMemberInitArgs(Type type, ReadOnlyCollection<MemberBinding> bindings)

View File

@@ -58,7 +58,7 @@ namespace System.Linq.Expressions.Tests
{
ConstantExpression instance = Expression.Constant(new int[2,3]);
ConstantExpression index = Expression.Constant(2);
Assert.Throws<ArgumentException>(() => Expression.ArrayAccess(instance, index));
AssertExtensions.Throws<ArgumentException>(null, () => Expression.ArrayAccess(instance, index));
}
[Fact]

View File

@@ -1 +1 @@
484a44b822cf81dea641f5fdd78dc6323912be5c
389b6d47b316f20c52847e6c98776e95d6654046

View File

@@ -1616,7 +1616,7 @@ namespace System.Linq.Expressions.Tests
public static void UnreadableArray()
{
Expression array = Expression.Property(null, typeof(Unreadable<int[]>), nameof(Unreadable<int>.WriteOnly));
Assert.Throws<ArgumentException>(() => Expression.ArrayLength(array));
AssertExtensions.Throws<ArgumentException>("array", () => Expression.ArrayLength(array));
}
private static IEnumerable<object[]> TestArrays()

View File

@@ -285,5 +285,50 @@ namespace System.Linq.Expressions.Tests
NewArrayExpression newArrayExpression = Expression.NewArrayBounds(typeof(string), bound0, bound1);
AssertExtensions.Throws<ArgumentNullException>("expressions", () => newArrayExpression.Update(null));
}
[Theory, ClassData(typeof(CompilationTypes))]
public static void SingleNegativeBoundErrorMessage(bool useInterpreter)
{
string localizedMessage = null;
try
{
int[] dummy = new int["".Length - 2];
}
catch (OverflowException oe)
{
localizedMessage = oe.Message;
}
Expression<Func<int[]>> lambda =
Expression.Lambda<Func<int[]>>(Expression.NewArrayBounds(typeof(int), Expression.Constant(-2)));
var func = lambda.Compile(useInterpreter);
OverflowException ex = Assert.Throws<OverflowException>(() => func());
if (!PlatformDetection.IsNetNative) // Exceptions do not always have messages
Assert.Equal(localizedMessage, ex.Message);
}
[Theory, ClassData(typeof(CompilationTypes))]
public static void MultipleNegativeBoundErrorMessage(bool useInterpreter)
{
string localizedMessage = null;
try
{
int[,,] dummy = new int[1, 1, "".Length - 2];
}
catch (OverflowException oe)
{
localizedMessage = oe.Message;
}
Expression<Func<int[,,]>> lambda = Expression.Lambda<Func<int[,,]>>(
Expression.NewArrayBounds(
typeof(int), Expression.Constant(0), Expression.Constant(0), Expression.Constant(-2)));
var func = lambda.Compile(useInterpreter);
OverflowException ex = Assert.Throws<OverflowException>(() => func());
if (!PlatformDetection.IsNetNative) // Exceptions do not always have messages
Assert.Equal(localizedMessage, ex.Message);
}
}
}

View File

@@ -1645,7 +1645,7 @@ namespace System.Linq.Expressions.Tests
[Fact]
public static void VoidType()
{
Assert.Throws<ArgumentException>(() => Expression.NewArrayInit(typeof(void)));
AssertExtensions.Throws<ArgumentException>("type", () => Expression.NewArrayInit(typeof(void)));
}
[Fact]
@@ -1665,7 +1665,7 @@ namespace System.Linq.Expressions.Tests
[Fact]
public static void ByRefType()
{
Assert.Throws<ArgumentException>(() => Expression.NewArrayInit(typeof(int).MakeByRefType()));
AssertExtensions.Throws<ArgumentException>("type", () => Expression.NewArrayInit(typeof(int).MakeByRefType()));
}
[Fact]
@@ -1677,14 +1677,14 @@ namespace System.Linq.Expressions.Tests
[Fact]
public static void GenericType()
{
Assert.Throws<ArgumentException>(() => Expression.NewArrayInit(typeof(List<>)));
AssertExtensions.Throws<ArgumentException>("type", () => Expression.NewArrayInit(typeof(List<>)));
}
[Fact]
public static void TypeContainsGenericParameters()
{
Assert.Throws<ArgumentException>(() => Expression.NewArrayInit(typeof(List<>.Enumerator)));
Assert.Throws<ArgumentException>(() => Expression.NewArrayInit(typeof(List<>).MakeGenericType(typeof(List<>))));
AssertExtensions.Throws<ArgumentException>("type", () => Expression.NewArrayInit(typeof(List<>.Enumerator)));
AssertExtensions.Throws<ArgumentException>("type", () => Expression.NewArrayInit(typeof(List<>).MakeGenericType(typeof(List<>))));
}
[Fact]

View File

@@ -494,5 +494,36 @@ namespace System.Linq.Expressions.Tests
)).Compile(useInterpreter);
Assert.Equal(1, func());
}
#if FEATURE_COMPILE
[Fact]
public static void VerifyIL_NullableIntCoalesceToNullableInt()
{
ParameterExpression x = Expression.Parameter(typeof(int?));
ParameterExpression y = Expression.Parameter(typeof(int?));
Expression<Func<int?, int?, int?>> f =
Expression.Lambda<Func<int?, int?, int?>>(Expression.Coalesce(x, y), x, y);
f.VerifyIL(
@".method valuetype [System.Private.CoreLib]System.Nullable`1<int32> ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure,valuetype [System.Private.CoreLib]System.Nullable`1<int32>,valuetype [System.Private.CoreLib]System.Nullable`1<int32>)
{
.maxstack 2
.locals init (
[0] valuetype [System.Private.CoreLib]System.Nullable`1<int32>
)
IL_0000: ldarg.1
IL_0001: stloc.0
IL_0002: ldloca.s V_0
IL_0004: call instance bool valuetype [System.Private.CoreLib]System.Nullable`1<int32>::get_HasValue()
IL_0009: brfalse IL_0014
IL_000e: ldloc.0
IL_000f: br IL_0015
IL_0014: ldarg.2
IL_0015: ret
}");
}
#endif
}
}

View File

@@ -785,14 +785,14 @@ namespace System.Linq.Expressions.Tests
public static void AndAlsoGlobalMethod()
{
MethodInfo method = GlobalMethod(typeof(int), new[] { typeof(int), typeof(int) });
Assert.Throws<ArgumentException>(() => Expression.AndAlso(Expression.Constant(1), Expression.Constant(2), method));
AssertExtensions.Throws<ArgumentException>(null, () => Expression.AndAlso(Expression.Constant(1), Expression.Constant(2), method));
}
[Fact]
public static void OrElseGlobalMethod()
{
MethodInfo method = GlobalMethod(typeof(int), new [] { typeof(int), typeof(int) });
Assert.Throws<ArgumentException>(() => Expression.OrElse(Expression.Constant(1), Expression.Constant(2), method));
AssertExtensions.Throws<ArgumentException>(null, () => Expression.OrElse(Expression.Constant(1), Expression.Constant(2), method));
}
private static TypeBuilder GetTypeBuilder()

View File

@@ -376,7 +376,7 @@ namespace System.Linq.Expressions.Tests
Assert.Throws<ArgumentNullException>(() => children.CopyTo(null, 0));
Assert.Throws<ArgumentOutOfRangeException>(() => children.CopyTo(copyToTest, -1));
Assert.All(copyToTest, Assert.Null); // assert partial copy didn't happen before exception
Assert.Throws<ArgumentException>(() => children.CopyTo(copyToTest, 2));
AssertExtensions.Throws<ArgumentException>(parCount >= 2 && parCount <= 5 ? null : "destinationArray", () => children.CopyTo(copyToTest, 2));
Assert.All(copyToTest, Assert.Null);
children.CopyTo(copyToTest, 1);
Assert.Equal(copyToTest, exps.Prepend(null));

View File

@@ -169,6 +169,41 @@ namespace System.Linq.Expressions.Tests
Assert.Equal(expected, func());
}
[Theory, PerCompilationType(nameof(ConditionalValues))]
public void InvertedConditionalSelectsCorrectExpression(bool test, object ifTrue, object ifFalse, object expected, bool useInterpreter)
{
Func<object> func = Expression.Lambda<Func<object>>(
Expression.Convert(
Expression.Condition(
Expression.Not(Expression.Constant(test)),
Expression.Constant(ifFalse),
Expression.Constant(ifTrue)
),
typeof(object)
)
).Compile(useInterpreter);
Assert.Equal(expected, func());
}
[Theory, PerCompilationType(nameof(ConditionalValues))]
public void ConditionalWithMethodSelectsCorrectExpression(bool test, object ifTrue, object ifFalse, object expected, bool useInterpreter)
{
Func<object> func = Expression.Lambda<Func<object>>(
Expression.Convert(
Expression.Condition(
Expression.Not(Expression.Constant(test), GetType().GetMethod(nameof(NotNot))),
Expression.Constant(ifTrue),
Expression.Constant(ifFalse)
),
typeof(object)
)
).Compile(useInterpreter);
Assert.Equal(expected, func());
}
[Theory, PerCompilationType(nameof(ConditionalValuesWithTypes))]
public void ConditionalSelectsCorrectExpressionWithType(bool test, object ifTrue, object ifFalse, object expected, Type type, bool useInterpreter)
{
@@ -187,7 +222,7 @@ namespace System.Linq.Expressions.Tests
[Fact]
public void ByRefType()
{
Assert.Throws<ArgumentException>(() => Expression.Condition(
AssertExtensions.Throws<ArgumentException>(null, () => Expression.Condition(
Expression.Constant(true),
Expression.Constant(null),
Expression.Constant(null),
@@ -197,7 +232,7 @@ namespace System.Linq.Expressions.Tests
[Fact]
public void PointerType()
{
Assert.Throws<ArgumentException>(() => Expression.Condition(
AssertExtensions.Throws<ArgumentException>(null, () => Expression.Condition(
Expression.Constant(true),
Expression.Constant(null),
Expression.Constant(null),
@@ -207,7 +242,7 @@ namespace System.Linq.Expressions.Tests
[Fact]
public void GenericType()
{
Assert.Throws<ArgumentException>(() => Expression.Condition(
AssertExtensions.Throws<ArgumentException>(null, () => Expression.Condition(
Expression.Constant(true),
Expression.Constant(null),
Expression.Constant(null),
@@ -217,12 +252,12 @@ namespace System.Linq.Expressions.Tests
[Fact]
public void TypeContainsGenericParameters()
{
Assert.Throws<ArgumentException>(() => Expression.Condition(
AssertExtensions.Throws<ArgumentException>(null, () => Expression.Condition(
Expression.Constant(true),
Expression.Constant(null),
Expression.Constant(null),
typeof(List<>.Enumerator)));
Assert.Throws<ArgumentException>(() => Expression.Condition(
AssertExtensions.Throws<ArgumentException>(null, () => Expression.Condition(
Expression.Constant(true),
Expression.Constant(null),
Expression.Constant(null),
@@ -270,5 +305,7 @@ namespace System.Linq.Expressions.Tests
private class Visitor : ExpressionVisitor
{
}
public static bool NotNot(bool value) => value;
}
}

Some files were not shown because too many files have changed in this diff Show More