[Microsoft.Build.Tasks] Fix a net 2.0 failure.
[mono.git] / mcs / mcs / anonymous.cs
index c9aae70a86bac508f753f1868570b73bc54c392a..b20608ea52def25fa65d522c58746fbab1a0e59e 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);
                }
 
@@ -1321,16 +1321,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 +1353,7 @@ namespace Mono.CSharp {
                        // 
                        type = InternalType.AnonymousMethod;
 
-                       if (!DoResolveParameters (ec))
+                       if (!DoResolveParameters (rc))
                                return null;
 
                        return this;
@@ -1357,9 +1369,12 @@ namespace Mono.CSharp {
                        // nothing, as we only exist to not do anything.
                }
 
-               public static void Error_AddressOfCapturedVar (ResolveContext ec, IVariableReference var, Location loc)
+               public static void Error_AddressOfCapturedVar (ResolveContext rc, IVariableReference var, Location loc)
                {
-                       ec.Report.Error (1686, loc,
+                       if (rc.CurrentAnonymousMethod is AsyncInitializer)
+                               return;
+
+                       rc.Report.Error (1686, loc,
                                "Local variable or parameter `{0}' cannot have their address taken and be used inside an anonymous method, lambda expression or query expression",
                                var.Name);
                }
@@ -1722,6 +1737,8 @@ namespace Mono.CSharp {
 
                        Modifiers modifiers;
                        TypeDefinition parent = null;
+                       TypeParameters hoisted_tparams = null;
+                       ParametersCompiled method_parameters = parameters;
 
                        var src_block = Block.Original.Explicit;
                        if (src_block.HasCapturedVariable || src_block.HasCapturedThis) {
@@ -1753,6 +1770,7 @@ namespace Mono.CSharp {
                                                        // use ldftn on non-boxed instances either to share mutated state
                                                        //
                                                        parent = sm_parent.Parent.PartialContainer;
+                                                       hoisted_tparams = sm_parent.OriginalTypeParameters;
                                                } else if (sm is IteratorStorey) {
                                                        //
                                                        // For iterators we can host everything in one class
@@ -1768,8 +1786,21 @@ namespace Mono.CSharp {
                                        parent = storey = ec.CurrentAnonymousMethod.Storey;
 
                                modifiers = Modifiers.STATIC | Modifiers.PRIVATE;
+
+                               //
+                               // Convert generated method to closed delegate method where unused
+                               // this argument is generated during compilation which speeds up dispatch
+                               // by about 25%
+                               //
+                               // Unused as it breaks compatibility
+                               //
+                               // method_parameters = ParametersCompiled.Prefix (method_parameters,
+                               //      new Parameter (null, null, 0, null, loc), ec.Module.Compiler.BuiltinTypes.Object);
                        }
 
+                       if (storey == null && hoisted_tparams == null)
+                               hoisted_tparams = ec.CurrentTypeParameters;
+
                        if (parent == null)
                                parent = ec.CurrentTypeDefinition.Parent.PartialContainer;
 
@@ -1777,9 +1808,7 @@ namespace Mono.CSharp {
                                "m", null, parent.PartialContainer.CounterAnonymousMethods++);
 
                        MemberName member_name;
-                       if (storey == null && ec.CurrentTypeParameters != null) {
-
-                               var hoisted_tparams = ec.CurrentTypeParameters;
+                       if (hoisted_tparams != null) {
                                var type_params = new TypeParameters (hoisted_tparams.Count);
                                for (int i = 0; i < hoisted_tparams.Count; ++i) {
                                    type_params.Add (hoisted_tparams[i].CreateHoistedCopy (null));
@@ -1792,7 +1821,7 @@ namespace Mono.CSharp {
 
                        return new AnonymousMethodMethod (parent,
                                this, storey, new TypeExpression (ReturnType, Location), modifiers,
-                               member_name, parameters);
+                               member_name, method_parameters);
                }
 
                protected override Expression DoResolve (ResolveContext ec)
@@ -1821,7 +1850,7 @@ namespace Mono.CSharp {
                        }
 
                        bool is_static = (method.ModFlags & Modifiers.STATIC) != 0;
-                       if (is_static && am_cache == null) {
+                       if (is_static && am_cache == null && !ec.IsStaticConstructor) {
                                //
                                // Creates a field cache to store delegate instance if it's not generic
                                //
@@ -1900,8 +1929,17 @@ namespace Mono.CSharp {
 
                                ec.Emit (OpCodes.Ldftn, TypeBuilder.GetMethod (t.GetMetaInfo (), (MethodInfo) delegate_method.GetMetaInfo ()));
                        } else {
-                               if (delegate_method.IsGeneric)
-                                       delegate_method = delegate_method.MakeGenericMethod (ec.MemberContext, method.TypeParameters);
+                               if (delegate_method.IsGeneric) {
+                                       TypeParameterSpec[] tparams;
+                                       var sm = ec.CurrentAnonymousMethod == null ? null : ec.CurrentAnonymousMethod.Storey as StateMachine;
+                                       if (sm != null && sm.OriginalTypeParameters != null) {
+                                               tparams = sm.CurrentTypeParameters.Types;
+                                       } else {
+                                               tparams = method.TypeParameters;
+                                       }
+
+                                       delegate_method = delegate_method.MakeGenericMethod (ec.MemberContext, tparams);
+                               }
 
                                ec.Emit (OpCodes.Ldftn, delegate_method);
                        }
@@ -2162,7 +2200,6 @@ namespace Mono.CSharp {
 
                        equals.Block = equals_block;
                        equals.Define ();
-                       equals.PrepareEmit ();
                        Members.Add (equals);
 
                        //
@@ -2217,7 +2254,6 @@ namespace Mono.CSharp {
                        hashcode_block.AddStatement (new Return (hash_variable, loc));
                        hashcode.Block = hashcode_top;
                        hashcode.Define ();
-                       hashcode.PrepareEmit ();
                        Members.Add (hashcode);
 
                        //
@@ -2228,7 +2264,6 @@ namespace Mono.CSharp {
                        tostring_block.AddStatement (new Return (string_concat, loc));
                        tostring.Block = tostring_block;
                        tostring.Define ();
-                       tostring.PrepareEmit ();
                        Members.Add (tostring);
 
                        return true;