Merge pull request #2463 from ludovic-henry/monoerror-mono_object_new_pinned
[mono.git] / mcs / mcs / anonymous.cs
index 6c6acacf683dac66fbd883661c13883bd60cb83e..16ce9dfee86c62e203c26c497ee00f957bebc071 100644 (file)
@@ -352,7 +352,7 @@ namespace Mono.CSharp {
                                hoisted_locals.Add (hoisted);
                        }
 
-                       if (ec.CurrentBlock.Explicit != localVariable.Block.Explicit && !(hoisted.Storey is StateMachine))
+                       if (ec.CurrentBlock.Explicit != localVariable.Block.Explicit && !(hoisted.Storey is StateMachine) && hoisted.Storey != null)
                                hoisted.Storey.AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit);
                }
 
@@ -526,7 +526,7 @@ namespace Mono.CSharp {
                                fexpr.EmitAssign (ec, source, false, false);
                                Instance = fexpr;
                        } else {
-                               var local = TemporaryVariableReference.Create (source.Type, block, Location);
+                               var local = TemporaryVariableReference.Create (source.Type, block, Location, writeToSymbolFile: true);
                                if (source.Type.IsStruct) {
                                        local.LocalInfo.CreateBuilder (ec);
                                } else {
@@ -1154,7 +1154,8 @@ namespace Mono.CSharp {
                                        prev = null;
                                }
 
-                               var body = CompatibleMethodBody (ec, tic, null, delegate_type);
+                               HashSet<LocalVariable> undeclaredVariables = null;
+                               var body = CompatibleMethodBody (ec, tic, null, delegate_type, ref undeclaredVariables);
                                if (body != null) {
                                        am = body.Compatible (ec, body);
                                } else {
@@ -1164,6 +1165,10 @@ namespace Mono.CSharp {
                                if (TypeInferenceReportPrinter != null) {
                                        ec.Report.SetPrinter (prev);
                                }
+
+                               if (undeclaredVariables != null) {
+                                       body.Block.TopBlock.SetUndeclaredVariables (undeclaredVariables);
+                               }
                        }
 
                        if (am == null)
@@ -1188,6 +1193,9 @@ namespace Mono.CSharp {
                        if (compatibles.TryGetValue (type, out am))
                                return am;
 
+                       if (type == InternalType.ErrorType)
+                               return null;
+
                        TypeSpec delegate_type = CompatibleChecks (ec, type);
                        if (delegate_type == null)
                                return null;
@@ -1206,8 +1214,8 @@ namespace Mono.CSharp {
                        // we satisfy the rule by setting the return type on the EmitContext
                        // to be the delegate type return type.
                        //
-
-                       var body = CompatibleMethodBody (ec, null, return_type, delegate_type);
+                       HashSet<LocalVariable> undeclaredVariables = null;
+                       var body = CompatibleMethodBody (ec, null, return_type, delegate_type, ref undeclaredVariables);
                        if (body == null)
                                return null;
 
@@ -1265,6 +1273,15 @@ namespace Mono.CSharp {
                                throw;
                        } catch (Exception e) {
                                throw new InternalErrorException (e, loc);
+                       } finally {
+                               //
+                               // LocalVariable is not stateless and it's not easy to clone because it's
+                               // cached in toplevel block. Unsetting any initialized variables should
+                               // be enough
+                               //
+                               if (undeclaredVariables != null) {
+                                       body.Block.TopBlock.SetUndeclaredVariables (undeclaredVariables);
+                               }
                        }
 
                        if (!ec.IsInProbingMode && !etree_conversion) {
@@ -1321,16 +1338,28 @@ namespace Mono.CSharp {
                        return Parameters;
                }
 
-               protected override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext rc)
                {
-                       if (ec.HasSet (ResolveContext.Options.ConstantScope)) {
-                               ec.Report.Error (1706, loc, "Anonymous methods and lambda expressions cannot be used in the current context");
+                       if (rc.HasSet (ResolveContext.Options.ConstantScope)) {
+                               rc.Report.Error (1706, loc, "Anonymous methods and lambda expressions cannot be used in the current context");
                                return null;
                        }
 
                        //
-                       // Set class type, set type
+                       // Update top-level block generated duting parsing with actual top-level block
                        //
+                       if (rc.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer) && rc.CurrentMemberDefinition.Parent.PartialContainer.PrimaryConstructorParameters != null) {
+                               var tb = rc.ConstructorBlock.ParametersBlock.TopBlock;
+                               if (Block.TopBlock != tb) {
+                                       Block b = Block;
+                                       while (b.Parent != Block.TopBlock && b != Block.TopBlock)
+                                               b = b.Parent;
+
+                                       b.Parent = tb;
+                                       tb.IncludeBlock (Block, Block.TopBlock);
+                                       b.ParametersBlock.TopBlock = tb;
+                               }
+                       }
 
                        eclass = ExprClass.Value;
 
@@ -1341,7 +1370,7 @@ namespace Mono.CSharp {
                        // 
                        type = InternalType.AnonymousMethod;
 
-                       if (!DoResolveParameters (ec))
+                       if (!DoResolveParameters (rc))
                                return null;
 
                        return this;
@@ -1372,13 +1401,13 @@ namespace Mono.CSharp {
                        return ExprClassName;
                }
 
-               AnonymousMethodBody CompatibleMethodBody (ResolveContext ec, TypeInferenceContext tic, TypeSpec return_type, TypeSpec delegate_type)
+               AnonymousMethodBody CompatibleMethodBody (ResolveContext ec, TypeInferenceContext tic, TypeSpec return_type, TypeSpec delegate_type, ref HashSet<LocalVariable> undeclaredVariables)
                {
                        ParametersCompiled p = ResolveParameters (ec, tic, delegate_type);
                        if (p == null)
                                return null;
 
-                       ParametersBlock b = ec.IsInProbingMode ? (ParametersBlock) Block.PerformClone () : Block;
+                       ParametersBlock b = ec.IsInProbingMode ? (ParametersBlock) Block.PerformClone (ref undeclaredVariables) : Block;
 
                        if (b.IsAsync) {
                                var rt = return_type;
@@ -1601,14 +1630,17 @@ namespace Mono.CSharp {
                        fc.ParametersBlock = Block;
                        var da_ontrue = fc.DefiniteAssignmentOnTrue;
                        var da_onfalse = fc.DefiniteAssignmentOnFalse;
+                       var prev_tf = fc.TryFinally;
 
                        fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = null;
+                       fc.TryFinally = null;
                        block.FlowAnalysis (fc);
 
                        fc.ParametersBlock = prev_pb;
                        fc.DefiniteAssignment = das;
                        fc.DefiniteAssignmentOnTrue = da_ontrue;
                        fc.DefiniteAssignmentOnFalse = da_onfalse;
+                       fc.TryFinally = prev_tf;
                }
 
                public override void MarkReachable (Reachability rc)
@@ -1780,11 +1812,9 @@ namespace Mono.CSharp {
                                // this argument is generated during compilation which speeds up dispatch
                                // by about 25%
                                //
-
-                               //
-                               // Disabled for now due to JIT bug
+                               // Unused as it breaks compatibility
                                //
-                               //method_parameters = ParametersCompiled.Prefix (method_parameters,
+                               // method_parameters = ParametersCompiled.Prefix (method_parameters,
                                //      new Parameter (null, null, 0, null, loc), ec.Module.Compiler.BuiltinTypes.Object);
                        }
 
@@ -1907,17 +1937,16 @@ namespace Mono.CSharp {
 
                        var delegate_method = method.Spec;
                        if (storey != null && storey.MemberName.IsGeneric) {
-                               TypeSpec t = storey.Instance.Type;
-
                                //
                                // Mutate anonymous method instance type if we are in nested
                                // hoisted generic anonymous method storey
                                //
                                if (ec.IsAnonymousStoreyMutateRequired) {
-                                       t = storey.Mutator.Mutate (t);
+                                       ec.Emit (OpCodes.Ldftn, delegate_method);
+                               } else {
+                                       TypeSpec t = storey.Instance.Type;
+                                       ec.Emit (OpCodes.Ldftn, TypeBuilder.GetMethod (t.GetMetaInfo (), (MethodInfo) delegate_method.GetMetaInfo ()));
                                }
-
-                               ec.Emit (OpCodes.Ldftn, TypeBuilder.GetMethod (t.GetMetaInfo (), (MethodInfo) delegate_method.GetMetaInfo ()));
                        } else {
                                if (delegate_method.IsGeneric) {
                                        TypeParameterSpec[] tparams;