protected override Expression DoResolve (ResolveContext rc)
{
- if (rc.HasSet (ResolveContext.Options.FinallyScope)) {
- rc.Report.Error (1984, loc, "The `await' operator cannot be used in the body of a finally clause");
- }
-
if (rc.HasSet (ResolveContext.Options.LockScope)) {
rc.Report.Error (1996, loc,
"The `await' operator cannot be used in the body of a lock statement");
var fe_awaiter = new FieldExpr (awaiter, loc);
fe_awaiter.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc);
- Label skip_continuation = ec.DefineLabel ();
+ Label skip_continuation = ec.DefineLabel ();
using (ec.With (BuilderContext.Options.OmitDebugInfo, true)) {
//
return false;
}
- if (bc.HasSet (ResolveContext.Options.CatchScope)) {
- bc.Report.Error (1985, loc, "The `await' operator cannot be used in the body of a catch clause");
- }
-
if (!base.Resolve (bc))
return false;
get; set;
}
+ public StackFieldExpr HoistedReturnState {
+ get; set;
+ }
+
public override bool IsIterator {
get {
return false;
protected override BlockContext CreateBlockContext (BlockContext bc)
{
var ctx = base.CreateBlockContext (bc);
- var lambda = bc.CurrentAnonymousMethod as LambdaMethod;
- if (lambda != null)
- return_inference = lambda.ReturnTypeInference;
+ var am = bc.CurrentAnonymousMethod as AnonymousMethodBody;
+ if (am != null)
+ return_inference = am.ReturnTypeInference;
ctx.Set (ResolveContext.Options.TryScope);
throw new NotImplementedException ();
}
+ public void EmitCatchBlock (EmitContext ec)
+ {
+ var catch_value = LocalVariable.CreateCompilerGenerated (ec.Module.Compiler.BuiltinTypes.Exception, block, Location);
+
+ ec.BeginCatchBlock (catch_value.Type);
+ catch_value.EmitAssign (ec);
+
+ ec.EmitThis ();
+ ec.EmitInt ((int) IteratorStorey.State.After);
+ ec.Emit (OpCodes.Stfld, storey.PC.Spec);
+
+ ((AsyncTaskStorey) Storey).EmitSetException (ec, new LocalVariableReference (catch_value, Location));
+
+ ec.Emit (OpCodes.Leave, move_next_ok);
+ ec.EndExceptionBlock ();
+
+ }
+
protected override void EmitMoveNextEpilogue (EmitContext ec)
{
var storey = (AsyncTaskStorey) Storey;
MethodSpec builder_factory;
MethodSpec builder_start;
PropertySpec task;
- LocalVariable hoisted_return;
int locals_captured;
Dictionary<TypeSpec, List<Field>> stack_fields;
Dictionary<TypeSpec, List<Field>> awaiter_fields;
#region Properties
- public LocalVariable HoistedReturn {
- get {
- return hoisted_return;
- }
- }
+ public Expression HoistedReturnValue { get; set; }
public TypeSpec ReturnType {
get {
return field;
}
- public Field AddCapturedLocalVariable (TypeSpec type)
+ public Field AddCapturedLocalVariable (TypeSpec type, bool requiresUninitialized = false)
{
if (mutator != null)
type = mutator.Mutate (type);
List<Field> existing_fields = null;
if (stack_fields == null) {
stack_fields = new Dictionary<TypeSpec, List<Field>> ();
- } else if (stack_fields.TryGetValue (type, out existing_fields)) {
+ } else if (stack_fields.TryGetValue (type, out existing_fields) && !requiresUninitialized) {
foreach (var f in existing_fields) {
if (f.IsAvailableForReuse) {
f.IsAvailableForReuse = false;
set_state_machine.Block.AddStatement (new StatementExpression (new Invocation (mg, args)));
if (has_task_return_type) {
- hoisted_return = LocalVariable.CreateCompilerGenerated (bt.TypeArguments[0], StateMachineMethod.Block, Location);
+ HoistedReturnValue = TemporaryVariableReference.Create (bt.TypeArguments [0], StateMachineMethod.Block, Location);
}
return true;
args.Add (new Argument (awaiter, Argument.AType.Ref));
args.Add (new Argument (new CompilerGeneratedThis (CurrentType, Location), Argument.AType.Ref));
using (ec.With (BuilderContext.Options.OmitDebugInfo, true)) {
- mg.EmitCall (ec, args);
+ mg.EmitCall (ec, args, true);
}
}
args.Add (new Argument (exceptionVariable));
using (ec.With (BuilderContext.Options.OmitDebugInfo, true)) {
- mg.EmitCall (ec, args);
+ mg.EmitCall (ec, args, true);
}
}
};
Arguments args;
- if (hoisted_return == null) {
+ if (HoistedReturnValue == null) {
args = new Arguments (0);
} else {
args = new Arguments (1);
- args.Add (new Argument (new LocalVariableReference (hoisted_return, Location)));
+ args.Add (new Argument (HoistedReturnValue));
}
using (ec.With (BuilderContext.Options.OmitDebugInfo, true)) {
- mg.EmitCall (ec, args);
+ mg.EmitCall (ec, args, true);
}
}