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;
#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;
// Special case hoisted return value (happens in try/finally scenario)
//
if (ec.TryFinallyUnwind != null) {
- if (storey.HoistedReturnValue is VariableReference) {
- storey.HoistedReturnValue = ec.GetTemporaryField (storey.HoistedReturnValue.Type);
- }
-
exit_label = TryFinally.EmitRedirectedReturn (ec, async_body);
}
--- /dev/null
+using System;
+using System.Threading.Tasks;
+
+class X
+{
+ public static int Main ()
+ {
+ if (new X ().Test (false).Result != true)
+ return 1;
+
+ if (new X ().Test (true).Result != true)
+ return 2;
+
+ return 0;
+ }
+
+ public async Task<bool> Test(bool TrueOrFalse)
+ {
+ if (TrueOrFalse)
+ return true;
+
+ try {
+ return true;
+ }
+ finally
+ {
+ await Task.Yield ();
+ }
+ }
+}
\ No newline at end of file
</method>
</type>
</test>
+ <test name="test-async-82.cs">
+ <type name="X">
+ <method name="Int32 Main()" attrs="150">
+ <size>66</size>
+ </method>
+ <method name="System.Threading.Tasks.Task`1[System.Boolean] Test(Boolean)" attrs="134">
+ <size>41</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="X+<Test>c__async0">
+ <method name="Void MoveNext()" attrs="486">
+ <size>269</size>
+ </method>
+ <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">
+ <size>13</size>
+ </method>
+ </type>
+ </test>
<test name="test-cls-00.cs">
<type name="CLSCLass_6">
<method name="Void add_Disposed(Delegate)" attrs="2182">