public override void Emit (EmitContext ec)
{
var call = new CallEmitter ();
- call.EmitPredefined (ec, oper, arguments);
+ call.EmitPredefined (ec, oper, arguments, loc);
}
public override SLE.Expression MakeExpression (BuilderContext ctx)
return this;
}
- ec.Report.Error (39, loc, "Cannot convert type `{0}' to `{1}' via a built-in conversion",
- etype.GetSignatureForError (), type.GetSignatureForError ());
+ if (etype != InternalType.ErrorType) {
+ ec.Report.Error (39, loc, "Cannot convert type `{0}' to `{1}' via a built-in conversion",
+ etype.GetSignatureForError (), type.GetSignatureForError ());
+ }
return null;
}
if (right_expr.IsNull) {
if ((b.oper & Operator.EqualityMask) != 0) {
- if (!left_expr.Type.IsNullableType && left_expr.Type == left_unwrap)
- return b.CreateLiftedValueTypeResult (rc, left_unwrap);
+ if (!left_expr.Type.IsNullableType && BuiltinTypeSpec.IsPrimitiveType (left_expr.Type))
+ return b.CreateLiftedValueTypeResult (rc, left_expr.Type);
} else if ((b.oper & Operator.BitwiseMask) != 0) {
if (left_unwrap.BuiltinType != BuiltinTypeSpec.Type.Bool)
return Nullable.LiftedNull.CreateFromExpression (rc, b);
}
} else if (left_expr.IsNull) {
if ((b.oper & Operator.EqualityMask) != 0) {
- if (!right_expr.Type.IsNullableType && right_expr.Type == right_unwrap)
- return b.CreateLiftedValueTypeResult (rc, right_unwrap);
+ if (!right_expr.Type.IsNullableType && BuiltinTypeSpec.IsPrimitiveType (right_expr.Type))
+ return b.CreateLiftedValueTypeResult (rc, right_expr.Type);
} else if ((b.oper & Operator.BitwiseMask) != 0) {
if (right_unwrap.BuiltinType != BuiltinTypeSpec.Type.Bool)
return Nullable.LiftedNull.CreateFromExpression (rc, b);
if (l.IsPointer || r.IsPointer)
return ResolveOperatorPointer (rc, l, r);
+ // User operators
+ expr = ResolveUserOperator (rc, left, right);
+ if (expr != null)
+ return expr;
+
+
bool lenum = l.IsEnum;
bool renum = r.IsEnum;
if ((oper & (Operator.ComparisonMask | Operator.BitwiseMask)) != 0) {
return expr;
}
}
-
- // User operators
- expr = ResolveUserOperator (rc, left, right);
- if (expr != null)
- return expr;
}
//
Nullable.NullableInfo.GetEnumUnderlyingType (rc.Module, left.Type) :
EnumSpec.GetUnderlyingType (left.Type);
}
- } else if (IsEnumOrNullableEnum (left.Type)) {
- result_type = left.Type;
} else {
- result_type = right.Type;
+ if (IsEnumOrNullableEnum (left.Type)) {
+ result_type = left.Type;
+ } else {
+ result_type = right.Type;
+ }
+
+ if (expr is Nullable.LiftedBinaryOperator && !result_type.IsNullableType)
+ result_type = rc.Module.PredefinedTypes.Nullable.TypeSpec.MakeGenericType (rc.Module, new[] { result_type });
}
return EmptyCast.Create (expr, result_type);
//
// Now try lifted version of predefined operators
//
- result = ResolveOperatorPredefined (ec, ec.Module.OperatorsBinaryEqualityLifted, no_arg_conv);
- if (result != null)
- return result;
+ if (no_arg_conv && !l.IsNullableType) {
+ //
+ // Optimizes cases which won't match
+ //
+ } else {
+ result = ResolveOperatorPredefined (ec, ec.Module.OperatorsBinaryEqualityLifted, no_arg_conv);
+ if (result != null)
+ return result;
+ }
//
// The == and != operators permit one operand to be a value of a nullable
/// </remarks>
public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
{
+ if (ec.HasSet (BuilderContext.Options.AsyncBody) && right.ContainsEmitWithAwait ()) {
+ left = left.EmitToField (ec);
+
+ if ((oper & Operator.LogicalMask) == 0) {
+ right = right.EmitToField (ec);
+ }
+ }
+
//
// This is more complicated than it looks, but its just to avoid
// duplicated tests: basically, we allow ==, !=, >, <, >= and <=
if (member_expr != null)
member_expr = member_expr.Resolve (ec);
} else {
- member_expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
+ member_expr = expr.Resolve (ec);
}
if (member_expr == null)
}
if (vr != null) {
+ ec.MarkCallEntry (loc);
ec.Emit (OpCodes.Call, method);
return false;
}
}
if (type is TypeParameterSpec)
- return DoEmitTypeParameter (ec);
+ return DoEmitTypeParameter (ec);
+ ec.MarkCallEntry (loc);
ec.Emit (OpCodes.Newobj, method);
return true;
}
e = e.ResolveLValue (rc, right_side);
} else {
- e = e.Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.Type);
+ e = e.Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.Type | ResolveFlags.MethodGroup);
}
return e;
public override void Emit (EmitContext ec)
{
source.Emit (ec);
+ ec.MarkCallEntry (loc);
ec.Emit (OpCodes.Call, method);
}
this.loc = loc;
}
+ public CollectionElementInitializer (Location loc)
+ : base (null, null)
+ {
+ this.loc = loc;
+ }
+
public override Expression CreateExpressionTree (ResolveContext ec)
{
Arguments args = new Arguments (2);