if (!stmt.Resolve (bc))
return null;
+ if (rc.HasSet (ResolveContext.Options.FinallyScope) && rc.CurrentAnonymousMethod != null) {
+ var ats = (AsyncTaskStorey)rc.CurrentAnonymousMethod.Storey;
+ ats.HasAwaitInsideFinally = true;
+ }
+
type = stmt.ResultType;
eclass = ExprClass.Variable;
return this;
public bool ProbingMode { get; set; }
- protected override void Error_TypeDoesNotContainDefinition (ResolveContext rc, TypeSpec type, string name)
+ public override void Error_TypeDoesNotContainDefinition (ResolveContext rc, TypeSpec type, string name)
{
Error_OperatorCannotBeApplied (rc, type);
}
var errors_printer = new SessionReportPrinter ();
var old = bc.Report.SetPrinter (errors_printer);
- ama = new Invocation (ama, args).Resolve (bc);
+
+ //
+ // The expression await t is classified the same way as the expression (t).GetAwaiter().GetResult().
+ //
+ ama = new Invocation (new ParenthesizedExpression (ama, Location.Null), args).Resolve (bc);
bc.Report.SetPrinter (old);
if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression (ama.Type)) {
#region Properties
+ public bool HasAwaitInsideFinally { get; set; }
+
public Expression HoistedReturnValue { get; set; }
public TypeSpec ReturnType {
builder = AddCompilerGeneratedField ("$builder", new TypeExpression (bt, Location));
+ Field rfield;
+ if (has_task_return_type && HasAwaitInsideFinally) {
+ //
+ // Special case async block with return value from finally clause. In such case
+ // we rewrite all return expresison stores to stfld to $return. Instead of treating
+ // returns outside of finally and inside of finally differently.
+ //
+ rfield = AddCompilerGeneratedField ("$return", new TypeExpression (bt.TypeArguments [0], Location));
+ } else {
+ rfield = null;
+ }
+
var set_state_machine = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Void, Location),
Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN | Modifiers.PUBLIC,
new MemberName ("SetStateMachine"),
set_state_machine.Block.AddStatement (new StatementExpression (new Invocation (mg, args)));
if (has_task_return_type) {
- HoistedReturnValue = TemporaryVariableReference.Create (bt.TypeArguments [0], StateMachineMethod.Block, Location);
+ if (rfield != null) {
+ HoistedReturnValue = new FieldExpr (rfield, Location) {
+ InstanceExpression = new CompilerGeneratedThis (CurrentType, Location.Null)
+ };
+ } else {
+ HoistedReturnValue = TemporaryVariableReference.Create (bt.TypeArguments [0], StateMachineMethod.Block, Location);
+ }
}
return true;
public StackFieldExpr (Field field)
: base (field, Location.Null)
{
+ AutomaticallyReuse = true;
}
+ public bool AutomaticallyReuse { get; set; }
+
public bool IsAvailableForReuse {
get {
var field = (Field) spec.MemberDefinition;
return field.IsAvailableForReuse;
}
- set {
+ private set {
var field = (Field) spec.MemberDefinition;
field.IsAvailableForReuse = value;
}
{
base.AddressOf (ec, mode);
- if (mode == AddressOp.Load) {
+ if (mode == AddressOp.Load && AutomaticallyReuse) {
IsAvailableForReuse = true;
}
}
{
base.Emit (ec);
- PrepareCleanup (ec);
+ if (AutomaticallyReuse)
+ PrepareCleanup (ec);
}
public void EmitLoad (EmitContext ec)