Merge pull request #2721 from ludovic-henry/fix-mono_ms_ticks
[mono.git] / mcs / mcs / expression.cs
index e8938153c8003b6e4d087caf94dfdcdba32fa412..aadf818066d2ad89b3d82a2b8488256753e09d9c 100644 (file)
@@ -110,7 +110,6 @@ namespace Mono.CSharp
                protected override Expression DoResolve (ResolveContext rc)
                {
                        Expression res = null;
-
                        using (rc.With (ResolveContext.Options.DontSetConditionalAccessReceiver, false)) {
                                res = expr.Resolve (rc);
                        }
@@ -6466,7 +6465,7 @@ namespace Mono.CSharp
                        }
 
                        New n_source = source as New;
-                       if (n_source != null) {
+                       if (n_source != null && n_source.CanEmitOptimizedLocalTarget (ec)) {
                                if (!n_source.Emit (ec, this)) {
                                        if (leave_copy) {
                                                EmitLoad (ec);
@@ -7024,6 +7023,16 @@ namespace Mono.CSharp
                        }
                }
 
+               bool statement_resolve;
+               public override ExpressionStatement ResolveStatement (BlockContext bc)
+               {
+                       statement_resolve = true;
+                       var es = base.ResolveStatement (bc);
+                       statement_resolve = false;
+
+                       return es;
+               }
+
                protected override Expression DoResolve (ResolveContext rc)
                {
                        ResolveConditionalAccessReceiver (rc);
@@ -7112,7 +7121,7 @@ namespace Mono.CSharp
 
                        var method = mg.BestCandidate;
                        type = mg.BestCandidateReturnType;
-                       if (conditional_access_receiver)
+                       if (conditional_access_receiver && !statement_resolve)
                                type = LiftMemberType (ec, type);
 
                        if (arguments == null && method.DeclaringType.BuiltinType == BuiltinTypeSpec.Type.Object && method.Name == Destructor.MetadataName) {
@@ -7174,7 +7183,7 @@ namespace Mono.CSharp
                                                args.Insert (0, new Argument (inst.Resolve (ec), mod));
                                        }
                                } else {        // is SimpleName
-                                       if (ec.IsStatic) {
+                                       if (ec.IsStatic || ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer)) {
                                                args.Insert (0, new Argument (new TypeOf (ec.CurrentType, loc).Resolve (ec), Argument.AType.DynamicTypeName));
                                        } else {
                                                args.Insert (0, new Argument (new This (loc).Resolve (ec)));
@@ -7182,7 +7191,7 @@ namespace Mono.CSharp
                                }
                        }
 
-                       return new DynamicInvocation (expr as ATypeNameExpression, args, loc).Resolve (ec);
+                       return new DynamicInvocation (expr as ATypeNameExpression, args, conditional_access_receiver, loc).Resolve (ec);
                }
 
                protected virtual MethodGroupExpr DoResolveOverload (ResolveContext ec)
@@ -7606,6 +7615,11 @@ namespace Mono.CSharp
                                ec.Emit (OpCodes.Pop);
                }
 
+               public virtual bool CanEmitOptimizedLocalTarget (EmitContext ec)
+               {
+                       return true;
+               }
+
                public override void FlowAnalysis (FlowAnalysisContext fc)
                {
                        if (arguments != null)
@@ -7858,6 +7872,8 @@ namespace Mono.CSharp
                {
                }
 
+               public bool NoEmptyInterpolation { get; set; }
+
                public ComposedTypeSpecifier Rank {
                        get {
                                return this.rank;
@@ -8394,11 +8410,32 @@ namespace Mono.CSharp
 
                public override void Emit (EmitContext ec)
                {
+                       if (!NoEmptyInterpolation && EmitOptimizedEmpty (ec))
+                               return;
+
                        var await_field = EmitToFieldSource (ec);
                        if (await_field != null)
                                await_field.Emit (ec);
                }
 
+               bool EmitOptimizedEmpty (EmitContext ec)
+               {
+                       if (arguments.Count != 1 || dimensions != 1)
+                               return false;
+
+                       var c = arguments [0] as Constant;
+                       if (c == null || !c.IsZeroInteger)
+                               return false;
+
+                       var m = ec.Module.PredefinedMembers.ArrayEmpty.Get ();
+                       if (m == null || ec.CurrentType.MemberDefinition.DeclaringAssembly == m.DeclaringType.MemberDefinition.DeclaringAssembly)
+                               return false;
+
+                       m = m.MakeGenericMethod (ec.MemberContext, array_element_type);
+                       ec.Emit (OpCodes.Call, m);
+                       return true;
+               }
+
                protected sealed override FieldExpr EmitToFieldSource (EmitContext ec)
                {
                        if (first_emit != null) {
@@ -9720,6 +9757,8 @@ namespace Mono.CSharp
                                return retval;
                        }
 
+                       var cma = this as ConditionalMemberAccess;
+
                        MemberExpr me;
                        TypeSpec expr_type = expr.Type;
                        if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
@@ -9729,10 +9768,13 @@ namespace Mono.CSharp
 
                                Arguments args = new Arguments (1);
                                args.Add (new Argument (expr));
+
+                               if (cma != null)
+                                       return new DynamicConditionalMemberBinder (Name, args, loc);
+
                                return new DynamicMemberBinder (Name, args, loc);
                        }
 
-                       var cma = this as ConditionalMemberAccess;
                        if (cma != null) {
                                if (!IsNullPropagatingValid (expr.Type)) {
                                        expr.Error_OperatorCannotBeApplied (rc, loc, "?", expr.Type);
@@ -10863,7 +10905,7 @@ namespace Mono.CSharp
                                args.AddRange (arguments);
 
                                best_candidate = null;
-                               return new DynamicIndexBinder (args, loc);
+                               return new DynamicIndexBinder (args, conditional_access_receiver, ConditionalAccess, loc);
                        }
 
                        //
@@ -11671,7 +11713,6 @@ namespace Mono.CSharp
                                args.Add (new Argument (rc.CurrentInitializerVariable));
                                target = new DynamicMemberBinder (Name, args, loc);
                        } else {
-
                                var member = MemberLookup (rc, false, t, Name, 0, MemberLookupRestrictions.ExactArity, loc);
                                if (member == null) {
                                        member = Expression.MemberLookup (rc, true, t, Name, 0, MemberLookupRestrictions.ExactArity, loc);
@@ -12134,7 +12175,7 @@ namespace Mono.CSharp
 
                public override void Emit (EmitContext ec)
                {
-                       if (method == null && TypeSpec.IsValueType (type) && initializers.Initializers.Count > 1 && ec.HasSet (BuilderContext.Options.AsyncBody) && initializers.ContainsEmitWithAwait ()) {
+                       if (!CanEmitOptimizedLocalTarget (ec)) {
                                var fe = ec.GetTemporaryField (type);
 
                                if (!Emit (ec, fe))
@@ -12222,6 +12263,13 @@ namespace Mono.CSharp
                        return true;
                }
 
+               public override bool CanEmitOptimizedLocalTarget (EmitContext ec)
+               {
+                       return !(method == null && TypeSpec.IsValueType (type) &&
+                                       initializers.Initializers.Count > 1 && ec.HasSet (BuilderContext.Options.AsyncBody) &&
+                                       initializers.ContainsEmitWithAwait ());
+               }
+
                protected override IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp Mode)
                {
                        instance = base.EmitAddressOf (ec, Mode);