Add clone for error expression. Fixes #13443
[mono.git] / mcs / mcs / expression.cs
index 14776484844ffafb07da563b3be88b150e706349..d02603f90f2f399ae00741ee76ad519ffd692e01 100644 (file)
@@ -80,7 +80,7 @@ namespace Mono.CSharp
                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)
@@ -1662,8 +1662,10 @@ namespace Mono.CSharp
                                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;
                }
@@ -1930,8 +1932,8 @@ namespace Mono.CSharp
 
                                        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);
@@ -1946,8 +1948,8 @@ namespace Mono.CSharp
                                                }
                                        } 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);
@@ -2752,6 +2754,12 @@ namespace Mono.CSharp
                                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) {
@@ -2805,11 +2813,6 @@ namespace Mono.CSharp
                                                        return expr;
                                        }
                                }
-
-                               // User operators
-                               expr = ResolveUserOperator (rc, left, right);
-                               if (expr != null)
-                                       return expr;
                        }
                        
                        //
@@ -3718,10 +3721,15 @@ namespace Mono.CSharp
                                                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);
@@ -3865,9 +3873,15 @@ namespace Mono.CSharp
                                //
                                // 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
@@ -4330,6 +4344,14 @@ namespace Mono.CSharp
                /// </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 <=
@@ -6015,7 +6037,7 @@ namespace Mono.CSharp
                                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)
@@ -6533,14 +6555,16 @@ namespace Mono.CSharp
                                }
 
                                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;
                }
@@ -8598,7 +8622,7 @@ namespace Mono.CSharp
 
                                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;
@@ -10037,6 +10061,7 @@ namespace Mono.CSharp
                public override void Emit (EmitContext ec)
                {
                        source.Emit (ec);
+                       ec.MarkCallEntry (loc);
                        ec.Emit (OpCodes.Call, method);
                }
 
@@ -10553,6 +10578,12 @@ namespace Mono.CSharp
                        this.loc = loc;
                }
 
+               public CollectionElementInitializer (Location loc)
+                       : base (null, null)
+               {
+                       this.loc = loc;
+               }
+
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
                        Arguments args = new Arguments (2);