X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mcs%2Fmcs%2Fanonymous.cs;h=d27fe806048797af33538b202c262e0e040dff4e;hb=f16a7daaf19d1deec3bb2f799db8d520c7112c84;hp=b20608ea52def25fa65d522c58746fbab1a0e59e;hpb=396d9dbeb1a93665ede08c0e24e3e051e2c3e1de;p=mono.git diff --git a/mcs/mcs/anonymous.cs b/mcs/mcs/anonymous.cs index b20608ea52d..d27fe806048 100644 --- a/mcs/mcs/anonymous.cs +++ b/mcs/mcs/anonymous.cs @@ -343,7 +343,7 @@ namespace Mono.CSharp { } if (hoisted == null) { - hoisted = new HoistedLocalVariable (this, localVariable, GetVariableMangledName (localVariable)); + hoisted = new HoistedLocalVariable (this, localVariable, GetVariableMangledName (ec, localVariable)); localVariable.HoistedVariant = hoisted; if (hoisted_locals == null) @@ -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 { @@ -667,7 +667,7 @@ namespace Mono.CSharp { return f_ind; } - protected virtual string GetVariableMangledName (LocalVariable local_info) + protected virtual string GetVariableMangledName (ResolveContext rc, LocalVariable local_info) { // // No need to mangle anonymous method hoisted variables cause they @@ -1154,7 +1154,8 @@ namespace Mono.CSharp { prev = null; } - var body = CompatibleMethodBody (ec, tic, null, delegate_type); + HashSet 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 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) { @@ -1384,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 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; @@ -1578,6 +1595,15 @@ namespace Mono.CSharp { if (res && errors != ec.Report.Errors) return null; + if (block.IsAsync && block.Original.ParametersBlock.HasCapturedThis && ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.block.IsAsync) { + // + // We'll do ldftn to load the fabricated m_X method but + // because we are inside struct the method can be hoisted + // anywhere in the parent scope + // + ec.CurrentBlock.ParametersBlock.HasReferenceToStoreyForInstanceLambdas = true; + } + return res ? this : null; } @@ -1613,14 +1639,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) @@ -1778,6 +1807,8 @@ namespace Mono.CSharp { parent = storey = sm; } } + } else if (src_block.ParametersBlock.HasReferenceToStoreyForInstanceLambdas) { + src_block.ParametersBlock.StateMachine.AddParentStoreyReference (ec, storey); } modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE; @@ -1917,17 +1948,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;