File: Semantics\BindingAsyncTests.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Semantic\Microsoft.CodeAnalysis.CSharp.Semantic.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Semantic.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics
{
    public class BindingAsyncTests : CompilingTestBase
    {
        [Fact]
        public void AsyncMethod()
        {
            var source = @"
using System.Threading.Tasks;
class C
{
    async void M(Task t)
    {
        await t;
    }
}";
            var compilation = CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
            var method = (SourceMemberMethodSymbol)compilation.GlobalNamespace.GetTypeMembers("C").Single().GetMembers("M").Single();
            Assert.True(method.IsAsync);
        }
 
        [Fact]
        public void AsyncLambdas()
        {
            var source = @"
using System;
using System.Threading.Tasks;
class C
{
    public static void Main()
    {
        Action<Task> f1 = async (Task t) => { await t; };
        Action<Task> f2 = async t => { await t; };
        Action<Task> f3 = async (t) => { await t; };
    }
}";
            var tree = SyntaxFactory.ParseSyntaxTree(source);
            var compilation = CreateCompilationWithMscorlib461(new SyntaxTree[] { tree }).VerifyDiagnostics();
 
            var model = compilation.GetSemanticModel(tree);
 
            var simple = tree.GetCompilationUnitRoot().DescendantNodes().OfType<SimpleLambdaExpressionSyntax>().Single();
            Assert.True(((IMethodSymbol)model.GetSymbolInfo(simple).Symbol).IsAsync);
 
            var parens = tree.GetCompilationUnitRoot().DescendantNodes().OfType<ParenthesizedLambdaExpressionSyntax>();
            Assert.True(parens.Count() == 2, "Expect exactly two parenthesized lambda expressions in the syntax tree.");
            foreach (var paren in parens)
            {
                Assert.True(((IMethodSymbol)model.GetSymbolInfo(paren).Symbol).IsAsync);
            }
        }
 
        [Fact]
        public void AsyncDelegates()
        {
            var source = @"
using System;
using System.Threading.Tasks;
class C
{
    public static void Main()
    {
        Action<Task> f4 = async delegate(Task t) { await t; };
    }
}";
            var tree = SyntaxFactory.ParseSyntaxTree(source);
            var compilation = CreateCompilationWithMscorlib461(new SyntaxTree[] { tree }).VerifyDiagnostics();
 
            var model = compilation.GetSemanticModel(tree);
 
            var del = tree.GetCompilationUnitRoot().DescendantNodes().OfType<AnonymousMethodExpressionSyntax>().Single();
            Assert.True(((IMethodSymbol)model.GetSymbolInfo(del).Symbol).IsAsync);
        }
 
        [Fact]
        public void BadAsyncConstructor()
        {
            var source = @"
class C {
    async public C() { }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "C").WithArguments("async"));
        }
 
        [Fact]
        public void BadAsyncDestructor()
        {
            var source = @"
class C
{
    async extern ~C();
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "C").WithArguments("async"),
                Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "C").WithArguments("C.~C()"));
        }
 
        [Fact]
        public void BadAsyncEvent()
        {
            var source = @"
public delegate void MyDelegate();
 
class C
{
    public C() {
        MyEvent.Invoke();
    }
 
    async event MyDelegate MyEvent;
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "MyEvent").WithArguments("async"));
        }
 
        [Fact]
        public void BadAsyncField()
        {
            var source = @"
class C
{
    public C(int i)
    {
        this.i = i;
    }
 
    async int i;
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "i").WithArguments("async"));
        }
 
        [Fact]
        public void BadAsyncClass()
        {
            var source = @"
public async class C
{
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "C").WithArguments("async"));
        }
 
        [Fact]
        public void BadAsyncStruct()
        {
            var source = @"
internal async struct S
{
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "S").WithArguments("async"));
        }
 
        [Fact]
        public void BadAsyncInterface()
        {
            var source = @"
internal async interface I
{
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "I").WithArguments("async"));
        }
 
        [Fact]
        public void BadAsyncDelegate()
        {
            var source = @"
public async delegate void MyDelegate();
";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "MyDelegate").WithArguments("async"));
        }
 
        [Fact]
        public void BadAsyncProperty()
        {
            var source = @"
public async delegate void MyDelegate();
";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "MyDelegate").WithArguments("async"));
        }
 
        [Fact]
        public void BadAsyncPropertyAccessor()
        {
            var source = @"
public async delegate void MyDelegate();
";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "MyDelegate").WithArguments("async"));
        }
 
        [Fact]
        public void TaskRetNoObjectRequired()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class C
{
    static void InferTask(Func<Task> x) { }
 
    static void InferTaskOrTaskT(Func<Task> x) { }
    static void InferTaskOrTaskT(Func<Task<int>> x) { }
 
    static async Task F1()
    {
        return await Task.Factory.StartNew(() => 1);
    }
 
    static void Main()
    {
        Func<Task> F2 = async () => { await Task.Factory.StartNew(() => { }); return 1; };
        InferTask(async () => { return await Task.Factory.StartNew(() => 1); });
        InferTaskOrTaskT(async () => { return await Task.Factory.StartNew(() => 1); });
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
    // (14,9): error CS1997: Since 'C.F1()' is an async method that returns 'System.Threading.Tasks.Task', a return keyword must not be followed by an object expression
    //         return await Task.Factory.StartNew(() => 1);
    Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequired, "return").WithArguments("C.F1()", "System.Threading.Tasks.Task").WithLocation(14, 9),
    // (19,79): error CS8030: Async lambda expression converted to a 'System.Threading.Tasks.Task' returning delegate cannot return a value
    //         Func<Task> F2 = async () => { await Task.Factory.StartNew(() => { }); return 1; };
    Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequiredLambda, "return").WithArguments("System.Threading.Tasks.Task").WithLocation(19, 79),
    // (20,33): error CS8030: Async lambda expression converted to a 'System.Threading.Tasks.Task' returning delegate cannot return a value
    //         InferTask(async () => { return await Task.Factory.StartNew(() => 1); });
    Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequiredLambda, "return").WithArguments("System.Threading.Tasks.Task").WithLocation(20, 33)
    );
        }
 
        [Fact]
        public void BadAsyncReturn()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class MyTask : Task
{
    public MyTask(Action a) : base(a) { }
}
 
class C
{
    async int F1()
    {
        await Task.Factory.StartNew(() => { });
    }
 
    async MyTask F2()
    {
        await Task.Factory.StartNew(() => { });
    }
 
    async T F3<T>()
    {
        await Task.Factory.StartNew(() => { });
    }
 
    async T F4<T>() where T : Task
    {
        await Task.Factory.StartNew(() => { });
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (17,18): error CS1983: The return type of an async method must be void, Task or Task<T>
                //     async MyTask F2()
                Diagnostic(ErrorCode.ERR_BadAsyncReturn, "F2"),
                // (22,13): error CS1983: The return type of an async method must be void, Task or Task<T>
                //     async T F3<T>()
                Diagnostic(ErrorCode.ERR_BadAsyncReturn, "F3"),
                // (27,13): error CS1983: The return type of an async method must be void, Task or Task<T>
                //     async T F4<T>() where T : Task
                Diagnostic(ErrorCode.ERR_BadAsyncReturn, "F4"),
                // (12,15): error CS1983: The return type of an async method must be void, Task or Task<T>
                //     async int F1()
                Diagnostic(ErrorCode.ERR_BadAsyncReturn, "F1"),
                // (12,15): error CS0161: 'C.F1()': not all code paths return a value
                //     async int F1()
                Diagnostic(ErrorCode.ERR_ReturnExpected, "F1").WithArguments("C.F1()"),
                // (17,18): error CS0161: 'C.F2()': not all code paths return a value
                //     async MyTask F2()
                Diagnostic(ErrorCode.ERR_ReturnExpected, "F2").WithArguments("C.F2()"),
                // (22,13): error CS0161: 'C.F3<T>()': not all code paths return a value
                //     async T F3<T>()
                Diagnostic(ErrorCode.ERR_ReturnExpected, "F3").WithArguments("C.F3<T>()"),
                // (27,13): error CS0161: 'C.F4<T>()': not all code paths return a value
                //     async T F4<T>() where T : Task
                Diagnostic(ErrorCode.ERR_ReturnExpected, "F4").WithArguments("C.F4<T>()"));
        }
 
        [Fact]
        public void CantConvAsyncAnonFuncReturns()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class C
{
    static void Main()
    {
        Func<int> f1 = async () => await Task.Factory.StartNew(() => 1);
        Func<int> f2 = async () => { return await Task.Factory.StartNew(() => 1); };
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (9,33): error CS4010: Cannot convert async lambda expression to delegate type 'Func<int>'. An async lambda expression may return void, Task or Task<T>, none of which are convertible to 'Func<int>'.
                //         Func<int> f1 = async () => await Task.Factory.StartNew(() => 1);
                Diagnostic(ErrorCode.ERR_CantConvAsyncAnonFuncReturns, "=>").WithArguments("lambda expression", "System.Func<int>").WithLocation(9, 33),
                // (10,33): error CS4010: Cannot convert async lambda expression to delegate type 'Func<int>'. An async lambda expression may return void, Task or Task<T>, none of which are convertible to 'Func<int>'.
                //         Func<int> f2 = async () => { return await Task.Factory.StartNew(() => 1); };
                Diagnostic(ErrorCode.ERR_CantConvAsyncAnonFuncReturns, "=>").WithArguments("lambda expression", "System.Func<int>").WithLocation(10, 33)
                );
        }
 
        [Fact]
        public void BadAsyncReturnExpression()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class C
{
    static void InferTask_T(Func<Task<int>> x) { }
 
    static void Main()
    {
        Func<Task<int>> f1 = async () => await Task.Factory.StartNew(() => new Task<int>(null));
        Func<Task<int>> f2 = async () => { return await Task.Factory.StartNew(() => new Task<int>(null)); };
 
        InferTask_T(async () => await Task.Factory.StartNew(() => new Task<int>(() => 1)));
        InferTask_T(async () => { return await Task.Factory.StartNew(() => new Task<int>(() => 1)); });
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (11,42): error CS4016: Since this is an async method, the return expression must be of type 'int' rather than 'Task<int>'
                //         Func<Task<int>> f1 = async () => await Task.Factory.StartNew(() => new Task<int>(null));
                Diagnostic(ErrorCode.ERR_BadAsyncReturnExpression, "await Task.Factory.StartNew(() => new Task<int>(null))").WithArguments("int", "System.Threading.Tasks.Task<int>").WithLocation(11, 42),
                // (12,51): error CS4016: Since this is an async method, the return expression must be of type 'int' rather than 'Task<int>'
                //         Func<Task<int>> f2 = async () => { return await Task.Factory.StartNew(() => new Task<int>(null)); };
                Diagnostic(ErrorCode.ERR_BadAsyncReturnExpression, "await Task.Factory.StartNew(() => new Task<int>(null))").WithArguments("int", "System.Threading.Tasks.Task<int>").WithLocation(12, 51),
                // (14,33): error CS4016: Since this is an async method, the return expression must be of type 'int' rather than 'Task<int>'
                //         InferTask_T(async () => await Task.Factory.StartNew(() => new Task<int>(() => 1)));
                Diagnostic(ErrorCode.ERR_BadAsyncReturnExpression, "await Task.Factory.StartNew(() => new Task<int>(() => 1))").WithArguments("int", "System.Threading.Tasks.Task<int>").WithLocation(14, 33),
                // (15,42): error CS4016: Since this is an async method, the return expression must be of type 'int' rather than 'Task<int>'
                //         InferTask_T(async () => { return await Task.Factory.StartNew(() => new Task<int>(() => 1)); });
                Diagnostic(ErrorCode.ERR_BadAsyncReturnExpression, "await Task.Factory.StartNew(() => new Task<int>(() => 1))").WithArguments("int", "System.Threading.Tasks.Task<int>").WithLocation(15, 42));
        }
 
        [Fact]
        public void BadAsyncReturnExpression_ValueTask()
        {
            var source = @"
using System.Threading.Tasks;
 
static async ValueTask<int> M() {
    await Task.Yield();
    return new ValueTask<int>();
}
await M();
";
            CreateCompilationWithTasksExtensions(source).VerifyDiagnostics(
                // (6,12): error CS4016: Since this is an async method, the return expression must be of type 'int' rather than 'ValueTask<int>'
                //     return new ValueTask<int>();
                Diagnostic(ErrorCode.ERR_BadAsyncReturnExpression, "new ValueTask<int>()").WithArguments("int", "System.Threading.Tasks.ValueTask<int>").WithLocation(6, 12)
            );
        }
 
        [Fact]
        public void AsyncCantReturnVoid()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class C
{
    static void InferVoid(Action x) { }
    static void InferTask_T<T>(Func<Task<T>> x) { }
    static void Infer_T<T>(Func<T> x) { }
 
    static void Main()
    {
        InferVoid(async () => { return await Task.Factory.StartNew(() => { }); });
        InferTask_T(async () => { return await Task.Factory.StartNew(() => { }); });
        Infer_T(async () => { return await Task.Factory.StartNew(() => { }); });
    }
}";
            CreateCompilationWithMscorlib461(source, new MetadataReference[] { LinqAssemblyRef, SystemRef }).VerifyDiagnostics(
    // (13,33): error CS8029: Anonymous function converted to a void returning delegate cannot return a value
    //         InferVoid(async () => { return await Task.Factory.StartNew(() => { }); });
    Diagnostic(ErrorCode.ERR_RetNoObjectRequiredLambda, "return").WithLocation(13, 33),
    // (14,42): error CS4029: Cannot return an expression of type 'void'
    //         InferTask_T(async () => { return await Task.Factory.StartNew(() => { }); });
    Diagnostic(ErrorCode.ERR_CantReturnVoid, "await Task.Factory.StartNew(() => { })").WithLocation(14, 42),
    // (15,38): error CS4029: Cannot return an expression of type 'void'
    //         Infer_T(async () => { return await Task.Factory.StartNew(() => { }); });
    Diagnostic(ErrorCode.ERR_CantReturnVoid, "await Task.Factory.StartNew(() => { })").WithLocation(15, 38)
    );
        }
 
        [Fact]
        public void InferAsyncReturn()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class C
{
    static void InferVoid(Action x) { }
 
    static void InferTask(Func<Task> x) { }
 
    static void InferTask_T<T>(Func<Task<T>> x) { }
 
    static void Main()
    {
        InferVoid(async () => { await Task.Factory.StartNew(() => { }); });
 
        InferTask(async () => { await Task.Factory.StartNew(() => { return; }); });
 
        InferTask_T(async () => { return await Task.Factory.StartNew(() => 1); });
    }
}";
            CreateCompilationWithMscorlib461(source, new MetadataReference[] { LinqAssemblyRef, SystemRef }).VerifyDiagnostics();
        }
 
        [Fact]
        public void BadInferAsyncReturn_T()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class C
{
    static void Infer<T>(Func<bool, T> x) { }
 
    static void Main()
    {
        Infer(async (x) =>
        {
            await Task.Factory.StartNew(() => { });
            if (x)
            {
                return 1;
            }
            else
            {
                return;
            }
        });
    }
}";
            CreateCompilationWithMscorlib461(source, new MetadataReference[] { LinqAssemblyRef, SystemRef }).VerifyDiagnostics(
                // (19,17): error CS0126: An object of a type convertible to 'int' is required
                //                 return;
                Diagnostic(ErrorCode.ERR_RetObjectRequired, "return").WithArguments("int"));
        }
 
        [Fact]
        public void BadInferAsyncReturnVoid()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class C
{
    static void Infer(Action<bool> x) { }
 
    static void Main()
    {
        Infer(async (x) =>
        {
            await Task.Factory.StartNew(() => { });
            if (x)
            {
                return 1;
            }
            else
            {
                return;
            }
        });
    }
}";
            CreateCompilationWithMscorlib461(source, new MetadataReference[] { LinqAssemblyRef, SystemRef }).VerifyDiagnostics(
    // (16,17): error CS8029: Anonymous function converted to a void returning delegate cannot return a value
    //                 return 1;
    Diagnostic(ErrorCode.ERR_RetNoObjectRequiredLambda, "return").WithLocation(16, 17)
    );
        }
 
        [Fact]
        public void BadInferAsyncReturnTask()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class C
{
    static void Infer(Func<bool, Task> x) { }
 
    static void Main()
    {
        Infer(async (x) =>
        {
            await Task.Factory.StartNew(() => { });
            if (x)
            {
                return 1;
            }
            else
            {
                return;
            }
        });
    }
}";
            CreateCompilationWithMscorlib461(source, new MetadataReference[] { LinqAssemblyRef, SystemRef }).VerifyDiagnostics(
    // (16,17): error CS8030: Async lambda expression converted to a 'System.Threading.Tasks.Task' returning delegate cannot return a value
    //                 return 1;
    Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequiredLambda, "return").WithArguments("System.Threading.Tasks.Task").WithLocation(16, 17)
    );
        }
 
        [Fact]
        public void BadInferAsyncReturnTask_T()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class C
{
    static void Infer<T>(Func<bool, Task<T>> x) { }
 
    static void Main()
    {
        Infer(async (x) =>
        {
            await Task.Factory.StartNew(() => { });
            if (x)
            {
                return 1;
            }
            else
            {
                return;
            }
        });
    }
}";
            CreateCompilationWithMscorlib461(source, new MetadataReference[] { LinqAssemblyRef, SystemRef }).VerifyDiagnostics(
                // (19,17): error CS0126: An object of a type convertible to 'int' is required
                //                 return;
                Diagnostic(ErrorCode.ERR_RetObjectRequired, "return").WithArguments("int"));
        }
 
        [Fact]
        public void TaskReturningAsyncWithoutReturn()
        {
            var source = @"
using System.Threading.Tasks;
 
class C
{
    async static Task F()
    {
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (6,23): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     async static Task F()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "F"));
        }
 
        [Fact]
        public void TestAsyncReturnsNullableT()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class C
{
    async static Task<int?> F()
    {
        await Task.Factory.StartNew(() => { });
        return null;
    }
 
    static void Main()
    {
        Func<Task<int?>> f1 = async () => await Task.Factory.StartNew<int?>(() => { return null; });
        Func<Task<int?>> f2 = async () => { return await Task.Factory.StartNew<int?>(() => { return null; }); };
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
        }
 
        [Fact]
        public void VarargsAsync()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    async static Task M1(__arglist)
    {
        await Task.Factory.StartNew(() => { });
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (6,23): error CS4006: __arglist is not allowed in the parameter list of async methods
                //     async static Task M1(__arglist)
                Diagnostic(ErrorCode.ERR_VarargsAsync, "M1"));
        }
 
        [Fact]
        public void VarargsAsyncGeneric()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    async static Task M1<T>(__arglist)
    {
        await Task.Factory.StartNew(() => { });
        return;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (6,23): error CS0224: A method with vararg cannot be generic, be in a generic type, or have a params parameter
                //     async static Task M1<T>(__arglist)
                Diagnostic(ErrorCode.ERR_BadVarargs, "M1"));
        }
 
        [Fact]
        public void VarargsAsyncInGenericClass()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    async static Task M1<T>(__arglist)
    {
        await Task.Factory.StartNew(() => { });
        return;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (6,23): error CS0224: A method with vararg cannot be generic, be in a generic type, or have a params parameter
                //     async static Task M1<T>(__arglist)
                Diagnostic(ErrorCode.ERR_BadVarargs, "M1"));
        }
 
        [Fact]
        public void UnsafeAsyncArgType()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    unsafe async static Task M1(int* i) { }
}";
            CreateCompilationWithMscorlib461(source, null, TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
                // (6,38): error CS4005: Async methods cannot have pointer type parameters
                //     unsafe async static Task M1(int* i)
                Diagnostic(ErrorCode.ERR_UnsafeAsyncArgType, "i"),
                // (6,30): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     unsafe async static Task M1(ref int* i)
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "M1"));
        }
 
        [Fact]
        public void UnsafeAsyncArgType_FunctionPointer()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    unsafe async static Task M1(delegate*<void> i) { }
}";
            CreateCompilationWithMscorlib461(source, null, TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
                // (6,49): error CS4005: Async methods cannot have pointer type parameters
                //     unsafe async static Task M1(delegate*<void> i) { }
                Diagnostic(ErrorCode.ERR_UnsafeAsyncArgType, "i").WithLocation(6, 49),
                // (6,30): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     unsafe async static Task M1(delegate*<void> i) { }
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "M1").WithLocation(6, 30)
                );
        }
 
        [Fact]
        public void UnsafeAsyncArgType_PointerArray()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    unsafe async static Task M1(int*[] i) { await Task.Yield(); } // 1
    unsafe async static Task M2(delegate*<void>[] i) { await Task.Yield(); } // 2
    async static Task M3(int*[] i) { await Task.Yield(); } // 3
    async static Task M4(delegate*<void>[] i) { await Task.Yield(); } // 4
}";
            CreateCompilationWithMscorlib461(source, null, TestOptions.UnsafeReleaseDll)
                .VerifyDiagnostics(
                    // (6,45): error CS4004: Cannot await in an unsafe context
                    //     unsafe async static Task M1(int*[] i) { await Task.Yield(); } // 1
                    Diagnostic(ErrorCode.ERR_AwaitInUnsafeContext, "await Task.Yield()").WithLocation(6, 45),
                    // (7,56): error CS4004: Cannot await in an unsafe context
                    //     unsafe async static Task M2(delegate*<void>[] i) { await Task.Yield(); } // 2
                    Diagnostic(ErrorCode.ERR_AwaitInUnsafeContext, "await Task.Yield()").WithLocation(7, 56),
                    // (8,26): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                    //     async static Task M3(int*[] i) { await Task.Yield(); } // 3
                    Diagnostic(ErrorCode.ERR_UnsafeNeeded, "int*").WithLocation(8, 26),
                    // (9,26): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                    //     async static Task M4(delegate*<void>[] i) { await Task.Yield(); } // 4
                    Diagnostic(ErrorCode.ERR_UnsafeNeeded, "delegate*").WithLocation(9, 26)
                    );
        }
 
        [Fact]
        public void Ref_and_UnsafeAsyncArgType()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    unsafe async static Task M1(ref int* i) { }
}";
            CreateCompilationWithMscorlib461(source, null, TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
                // (6,42): error CS1988: Async methods cannot have ref, in or out parameters
                //     unsafe async static Task M1(ref int* i)
                Diagnostic(ErrorCode.ERR_BadAsyncArgType, "i"),
                // (6,30): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     unsafe async static Task M1(ref int* i)
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "M1"));
        }
 
        [Fact]
        public void RefAsyncArgType()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    async static Task M1(ref int i)
    {
        await Task.Factory.StartNew(() => { });
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (6,42): error CS1988: Async methods cannot have ref, in or out parameters
                //     unsafe async static Task M1(ref int* i) { }
                Diagnostic(ErrorCode.ERR_BadAsyncArgType, "i"));
        }
 
        [Fact]
        public void OutAsyncArgType()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    async static Task M1(out int i)
    {
        await Task.Factory.StartNew(() => { });
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (6,34): error CS1988: Async methods cannot have ref, in or out parameters
                //     async static Task M1(out int i) { }
                Diagnostic(ErrorCode.ERR_BadAsyncArgType, "i"));
        }
 
        [Fact]
        public void InAsyncArgType()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    async static Task M1(in int i)
    {
        await Task.Factory.StartNew(() => { });
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (6,33): error CS1988: Async methods cannot have ref, in or out parameters
                //     async static Task M1(in int i)
                Diagnostic(ErrorCode.ERR_BadAsyncArgType, "i").WithLocation(6, 33)
                );
        }
 
        [Fact]
        public void BadAwaitWithoutAsync()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class MyAttribute : Attribute {
    public MyAttribute(int i) { }
}
 
[MyAttribute(await C.t)]
class C
{
    public static Task<int> t = new Task<int>(() => 1);
 
    int i = await t;
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (9,14): error CS1992: The 'await' operator can only be used when contained within a method or lambda expression marked with the 'async' modifier
                // [MyAttribute(await C.t)]
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsync, "await C.t"),
                // (14,13): error CS1992: The 'await' operator can only be used when contained within a method or lambda expression marked with the 'async' modifier
                //     int i = await t;
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsync, "await t"));
        }
 
        [Fact]
        public void BadAwaitWithoutAsync_AnonMeth_Lambda()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class C
{
    public static void Main()
    {
        Action f1 = delegate() { await Task.Factory.StartNew(() => { }); };
        Action f2 = () => await Task.Factory.StartNew(() => { });
        Action f3 = () => { await Task.Factory.StartNew(() => { }); };
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (9,34): error CS4034: The 'await' operator can only be used within an async anonymous method. Consider marking this anonymous method with the 'async' modifier.
                //         Action f1 = delegate() { await Task.Factory.StartNew(() => { }); };
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncLambda, "await Task.Factory.StartNew(() => { })").WithArguments("anonymous method"),
                // (10,27): error CS4034: The 'await' operator can only be used within an async lambda expression. Consider marking this lambda expression with the 'async' modifier.
                //         Action f2 = () => await Task.Factory.StartNew(() => { });
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncLambda, "await Task.Factory.StartNew(() => { })").WithArguments("lambda expression"),
                // (11,29): error CS4034: The 'await' operator can only be used within an async lambda expression. Consider marking this lambda expression with the 'async' modifier.
                //         Action f3 = () => { await Task.Factory.StartNew(() => { }); };
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncLambda, "await Task.Factory.StartNew(() => { })").WithArguments("lambda expression"));
        }
 
        [Fact]
        public void IDS_BadAwaitWithoutAsyncMethod_VoidMethod()
        {
            var source = @"
using System.Threading.Tasks;
 
class C
{
    public static void F()
    {
        await Task.Factory.StartNew(() => { });
    }
 
    public static int G()
    {
        return await Task.Factory.StartNew(() => 1);
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (8,9): error CS4033: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.
                //         await Task.Factory.StartNew(() => { });
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutVoidAsyncMethod, "await Task.Factory.StartNew(() => { })"),
                // (13,16): error CS4033: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task<int>'.
                //         return await Task.Factory.StartNew(() => 1);
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await Task.Factory.StartNew(() => 1)").WithArguments("int"));
        }
 
        [Fact]
        public void IDS_BadAwaitAsDefaultParam()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    static Task t = new Task(null);
 
    class @await { }
 
    static int Goo(int[] arr = await t)
    {
        return arr.Length;
    }
 
    static int Main()
    {
        return 1;
    }
}";
 
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (10,32): error CS4032: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task<int>'.
                //     static int Goo(int[] arr = await t)
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await t").WithArguments("int").WithLocation(10, 32)
                );
        }
 
        [Fact]
        public void BadAwaitInFinally()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    async static Task M1() {
        try
        {
        }
        catch
        {
            try
            {
            }
            catch
            {
            }
            finally
            {
                await Task.Factory.StartNew(() => { });
            }
        }
        finally
        {
            try
            {
            }
            catch
            {
                await Task.Factory.StartNew(() => { });
            }
            finally
            {
            }
        }
    }
}";
            CreateCompilationWithMscorlib461(source, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp5)).VerifyDiagnostics(
                // (20,17): error CS1984: Cannot await in the body of a finally clause
                //                 await Task.Factory.StartNew(() => { });
                Diagnostic(ErrorCode.ERR_BadAwaitInFinally, "await Task.Factory.StartNew(() => { })").WithLocation(20, 17),
                // (30,17): error CS1984: Cannot await in the body of a finally clause
                //                 await Task.Factory.StartNew(() => { });
                Diagnostic(ErrorCode.ERR_BadAwaitInFinally, "await Task.Factory.StartNew(() => { })").WithLocation(30, 17)
                );
            CreateCompilationWithMscorlib461(source, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6)).VerifyDiagnostics();
        }
 
        [Fact]
        public void BadAwaitInCatch()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    async static Task M1() {
        try
        {
        }
        catch
        {
            await Task.Factory.StartNew(() => { });
        }
        finally
        {
        }
    }
}";
            CreateCompilationWithMscorlib461(source, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp5)).VerifyDiagnostics(
                // (12,13): error CS1985: Cannot await in a catch clause
                //             await Task.Factory.StartNew(() => { });
                Diagnostic(ErrorCode.ERR_BadAwaitInCatch, "await Task.Factory.StartNew(() => { })").WithLocation(12, 13)
                );
            CreateCompilationWithMscorlib461(source, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6)).VerifyDiagnostics();
        }
 
        [Fact]
        public void BadAwaitInCatchFilter()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    async static Task M1()
    {
        try
        {
        }
        catch when (await Task.Factory.StartNew(() => false))
        {
        }
        finally
        {
        }
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (11,19): error CS7094: Cannot await in the filter expression of a catch clause
                //         catch when (await Task.Factory.StartNew(() => false))
                Diagnostic(ErrorCode.ERR_BadAwaitInCatchFilter, "await Task.Factory.StartNew(() => false)").WithLocation(11, 21)
                );
        }
 
        [Fact]
        public void BadAwaitInLock()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    async static Task M1() {
 
        lock (new object())
        {
            await Task.Factory.StartNew(() => { });
 
            try
            {
            }
            catch
            {
                await Task.Factory.StartNew(() => { });
            }
            finally
            {
                await Task.Factory.StartNew(() => { });
            }
        }
 
        try
        {
        }
        catch
        {
            lock (new object())
            {
                await Task.Factory.StartNew(() => { });
            }
        }
        finally
        {
            lock (new object())
            {
                await Task.Factory.StartNew(() => { });
            }
        }
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (10,13): error CS1996: Cannot await in the body of a lock statement
                //             await Task.Factory.StartNew(() => { });
                Diagnostic(ErrorCode.ERR_BadAwaitInLock, "await Task.Factory.StartNew(() => { })"),
                // (17,17): error CS1996: Cannot await in the body of a lock statement
                //                 await Task.Factory.StartNew(() => { });
                Diagnostic(ErrorCode.ERR_BadAwaitInLock, "await Task.Factory.StartNew(() => { })"),
                // (21,17): error CS1996: Cannot await in the body of a lock statement
                //                 await Task.Factory.StartNew(() => { });
                Diagnostic(ErrorCode.ERR_BadAwaitInLock, "await Task.Factory.StartNew(() => { })"),
                // (32,17): error CS1996: Cannot await in the body of a lock statement
                //                 await Task.Factory.StartNew(() => { });
                Diagnostic(ErrorCode.ERR_BadAwaitInLock, "await Task.Factory.StartNew(() => { })"),
                // (39,17): error CS1996: Cannot await in the body of a lock statement
                //                 await Task.Factory.StartNew(() => { });
                Diagnostic(ErrorCode.ERR_BadAwaitInLock, "await Task.Factory.StartNew(() => { })"));
        }
 
        [Fact]
        public void BadAwaitInLock2()
        {
            var source = @"
using System.Threading.Tasks;
 
class Program
{
    async void Test()
    {
        lock(await M()) // fine, not in body of lock
            lock (await M()) // error, in body of outer lock
            {
                await M(); // error, in body of inner lock
            }
    }
 
    async Task<object> M()
    {
        return await M();
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (9,19): error CS1996: Cannot await in the body of a lock statement
                //             lock (await M()) // error, in body of outer lock
                Diagnostic(ErrorCode.ERR_BadAwaitInLock, "await M()"),
                // (11,17): error CS1996: Cannot await in the body of a lock statement
                //                 await M(); // error, in body of inner lock
                Diagnostic(ErrorCode.ERR_BadAwaitInLock, "await M()"));
        }
 
        [Fact]
        public void AwaitingInLockExpressionsIsActuallyOK()
        {
            var source = @"
using System.Threading.Tasks;
 
class Driver
{
    public static async void F()
    {
        object o = new object();
        lock(await Task.Factory.StartNew(() => o))
        {
 
        }
    }
 
    static void Main() { }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
        }
 
        [WorkItem(611150, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/611150")]
        [Fact]
        public void AwaitInLambdaInLock()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    static void Main()
    {
        lock (new object())
        {
            Task.Run(async () => { await Task.Factory.StartNew(() => { }); });
            Task.Run(async () => await Task.Factory.StartNew(() => { }));
            Task.Run(async delegate () { await Task.Factory.StartNew(() => { }); });
        }
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
        }
 
        [Fact]
        public void BadAwaitInUnsafeContext()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    unsafe async static Task M1() {
        await Task.Factory.StartNew(() => { });  // not OK
    }
 
    async static Task M2()
    {
        await Task.Factory.StartNew(() => { }); // OK
 
        unsafe
        {
            await Task.Factory.StartNew(() => { }); // not OK
        }
    }
}";
            CreateCompilationWithMscorlib461(source, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
                // (7,9): error CS4004: Cannot await in an unsafe context
                //         await Task.Factory.StartNew(() => { });  // not OK
                Diagnostic(ErrorCode.ERR_AwaitInUnsafeContext, "await Task.Factory.StartNew(() => { })"),
                // (16,13): error CS4004: Cannot await in an unsafe context
                //             await Task.Factory.StartNew(() => { }); // not OK
                Diagnostic(ErrorCode.ERR_AwaitInUnsafeContext, "await Task.Factory.StartNew(() => { })"));
        }
 
        [Fact]
        public void BadAwaitWithoutAsyncInBadContext()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    static Task M2()
    {
        await Task.Factory.StartNew(() => { });
 
        unsafe
        {
            await Task.Factory.StartNew(() => { });
        }
 
        try
        {
        }
        catch
        {
            await Task.Factory.StartNew(() => { });
        }
        finally
        {
            await Task.Factory.StartNew(() => { });
        }
    }
}";
            CreateCompilationWithMscorlib461(source, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
                // (8,9): error CS4032: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task<System.Threading.Tasks.Task>'.
                //         await Task.Factory.StartNew(() => { });
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await Task.Factory.StartNew(() => { })").WithArguments("System.Threading.Tasks.Task").WithLocation(8, 9),
                // (12,13): error CS4032: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task<System.Threading.Tasks.Task>'.
                //             await Task.Factory.StartNew(() => { });
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await Task.Factory.StartNew(() => { })").WithArguments("System.Threading.Tasks.Task").WithLocation(12, 13),
                // (12,13): error CS4004: Cannot await in an unsafe context
                //             await Task.Factory.StartNew(() => { });
                Diagnostic(ErrorCode.ERR_AwaitInUnsafeContext, "await Task.Factory.StartNew(() => { })").WithLocation(12, 13),
                // (20,13): error CS4032: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task<System.Threading.Tasks.Task>'.
                //             await Task.Factory.StartNew(() => { });
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await Task.Factory.StartNew(() => { })").WithArguments("System.Threading.Tasks.Task").WithLocation(20, 13),
                // (24,13): error CS4032: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task<System.Threading.Tasks.Task>'.
                //             await Task.Factory.StartNew(() => { });
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await Task.Factory.StartNew(() => { })").WithArguments("System.Threading.Tasks.Task").WithLocation(24, 13),
                // (6,17): error CS0161: 'Test.M2()': not all code paths return a value
                //     static Task M2()
                Diagnostic(ErrorCode.ERR_ReturnExpected, "M2").WithArguments("Test.M2()").WithLocation(6, 17));
        }
 
        [Fact]
        public void AsyncExplicitInterfaceImplementation()
        {
            var source = @"
using System.Threading.Tasks;
 
interface IInterface
{
    void F();
}
 
class C : IInterface
{
    async void IInterface.F()
    {
        await Task.Factory.StartNew(() => { });
    }
 
    static void Main()
    {
 
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
        }
 
        [Fact]
        public void AsyncInterfaceMember()
        {
            var source = @"
interface IInterface
{
    async void F();
}";
            CreateCompilationWithMscorlib461(source, parseOptions: TestOptions.Regular7).VerifyDiagnostics(
                // (4,16): error CS8503: The modifier 'async' is not valid for this item in C# 7. Please use language version 'preview' or greater.
                //     async void F(); 
                Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F").WithArguments("async", "7.0", "8.0").WithLocation(4, 16),
                // (4,16): error CS1994: The 'async' modifier can only be used in methods that have a body.
                //     async void F(); 
                Diagnostic(ErrorCode.ERR_BadAsyncLacksBody, "F").WithLocation(4, 16)
                );
        }
 
        [Fact]
        public void AwaitInQuery_FirstCollectionExpressionOfInitialFrom()
        {
            var source = @"
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
 
class Test
{
    async static Task<List<int>> F1()
    {
        return await Task.Factory.StartNew(() => new List<int>() { 1, 2, 3 });
    }
 
    async static void F2()
    {
        await Task.Factory.StartNew(() => { });
 
        var ls = new List<int>() {1, 2, 3};
 
        var xs = from l in await F1() where l > 1 select l;
    }
}";
            CreateCompilationWithMscorlib461(source, new MetadataReference[] { SystemRef, LinqAssemblyRef }).VerifyDiagnostics();
        }
 
        [Fact]
        public void AwaitInQuery_CollectionExpressionOfJoin()
        {
            var source = @"
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
 
class Test
{
    async static Task<List<int>> F1()
    {
        return await Task.Factory.StartNew(() => new List<int>() { 1, 2, 3 });
    }
 
    async static void F2()
    {
        await Task.Factory.StartNew(() => { });
 
        var ls = new List<int>() {1, 2, 3};
 
        var xs = from l in ls
                 join l2 in await F1() on l equals l2
                 where l > 1 select l;
    }
}";
            CreateCompilationWithMscorlib461(source, new MetadataReference[] { SystemRef, LinqAssemblyRef }).VerifyDiagnostics();
        }
 
        [Fact]
        public void BadAwaitInQuery_QueryBody()
        {
            var source = @"
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
 
class Test
{
    async static Task<List<int>> F1()
    {
        return await Task.Factory.StartNew(() => new List<int>() { 1, 2, 3 });
    }
 
    async static void F2()
    {
        await Task.Factory.StartNew(() => { });
 
        var ls = new List<int>() {1, 2, 3};
 
        var xs = from l in ls
                 where l > 1 select await F1();
    }
}";
            CreateCompilationWithMscorlib461(source, new MetadataReference[] { SystemRef, LinqAssemblyRef }).VerifyDiagnostics(
                // (20,37): error CS1995: The 'await' operator may only be used in a query expression within the first collection expression of the initial 'from' clause or within the collection expression of a 'join' clause
                //                  where l > 1 select await F1();
                Diagnostic(ErrorCode.ERR_BadAwaitInQuery, "await F1()"));
        }
 
        [Fact]
        public void BadAwaitInQuery_FirstCollectionExpressionOfInitialFrom_InsideQueryBody()
        {
            var source = @"
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
 
class Test
{
    async static Task<List<int>> F1()
    {
        return await Task.Factory.StartNew(() => new List<int>() { 1, 2, 3 });
    }
 
    async static void F2()
    {
        await Task.Factory.StartNew(() => { });
 
        var ls = new List<int>() { 1, 2, 3 };
 
        var xs = from l in ls
                 where l > 1
                 select (from l2 in await F1() where l2 > 1 select l2);
    }
}";
            CreateCompilationWithMscorlib461(source, new MetadataReference[] { SystemRef, LinqAssemblyRef }).VerifyDiagnostics(
                // (21,37): error CS1995: The 'await' operator may only be used in a query expression within the first collection expression of the initial 'from' clause or within the collection expression of a 'join' clause
                //                  select (from l2 in await F1() where l2 > 1 select l2);
                Diagnostic(ErrorCode.ERR_BadAwaitInQuery, "await F1()"));
        }
 
        [Fact]
        public void BadAwaitInQuery_CollectionExpressionOfJoin_InsideQueryBody()
        {
            var source = @"
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
 
class Test
{
    async static Task<List<int>> F1()
    {
        return await Task.Factory.StartNew(() => new List<int>() { 1, 2, 3 });
    }
 
    async static void F2()
    {
        await Task.Factory.StartNew(() => { });
 
        var ls = new List<int>() { 1, 2, 3 };
 
        var xs = from l in ls
                 where l > 1
                 select (from l2 in ls
                         join l3 in await F1() on l2 equals l3
                         where l2 > 1
                         select l2);
    }
}";
            CreateCompilationWithMscorlib461(source, new MetadataReference[] { SystemRef, LinqAssemblyRef }).VerifyDiagnostics(
                // (22,37): error CS1995: The 'await' operator may only be used in a query expression within the first collection expression of the initial 'from' clause or within the collection expression of a 'join' clause
                //                          join l3 in await F1() on l2 equals l3
                Diagnostic(ErrorCode.ERR_BadAwaitInQuery, "await F1()"));
        }
 
        [Fact]
        public void BadAwaitWithoutAsyncInUnsafeQuery()
        {
            var source = @"
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
 
class Test
{
    async static Task<List<int>> F1()
    {
        return await Task.Factory.StartNew(() => new List<int>() { 1, 2, 3 });
    }
 
    static void F2()
    {
        var ls = new List<int>() { 1, 2, 3 };
 
        unsafe
        {
            var xs = from l in ls
                     where l > 1
                     select (from l2 in ls
                             join l3 in await F1() on l2 equals l3
                             where l2 > 1
                             select l2);
        }
    }
}";
            var c = CreateCompilationWithMscorlib461(
                source,
                new MetadataReference[] { SystemRef, LinqAssemblyRef },
                TestOptions.UnsafeReleaseDll);
 
            c.VerifyDiagnostics(
                // (22,41): error CS4004: Cannot await in an unsafe context
                //                              join l3 in await F1() on l2 equals l3
                Diagnostic(ErrorCode.ERR_AwaitInUnsafeContext, "await F1()"),
                // (22,41): error CS1995: The 'await' operator may only be used in a query expression within the first collection expression of the initial 'from' clause or within the collection expression of a 'join' clause
                //                              join l3 in await F1() on l2 equals l3
                Diagnostic(ErrorCode.ERR_BadAwaitInQuery, "await F1()"));
        }
 
        [Fact]
        public void BadAwaitWithoutAsyncInQuery()
        {
            var source = @"
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
 
class Test
{
    async static Task<List<int>> F1()
    {
        return await Task.Factory.StartNew(() => new List<int>() { 1, 2, 3 });
    }
 
    static void F2()
    {
        var ls = new List<int>() { 1, 2, 3 };
 
        var xs = from l in ls
                    where l > 1
                    select (from l2 in ls
                            join l3 in await F1() on l2 equals l3
                            where l2 > 1
                            select l2);
    }
}";
            CreateCompilationWithMscorlib461(
                source,
                new MetadataReference[] { SystemRef, LinqAssemblyRef },
                TestOptions.ReleaseDll).VerifyDiagnostics(
 
                // (22,41): error CS1995: The 'await' operator may only be used in a query expression within the first collection expression of the initial 'from' clause or within the collection expression of a 'join' clause
                //                              join l3 in await F1() on l2 equals l3
                Diagnostic(ErrorCode.ERR_BadAwaitInQuery, "await F1()"));
        }
 
        [Fact]
        public void BadAwaitWithoutAsyncInLegalQueryRegion()
        {
            var source = @"
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
 
class Test
{
    async static Task<List<int>> F1()
    {
        return await Task.Factory.StartNew(() => new List<int>() { 1, 2, 3 });
    }
 
    static void F2()
    {
        var ls = new List<int>() { 1, 2, 3 };
 
        var xs = from l in await F1()
                    where l > 1
                    select l;
    }
}";
            CreateCompilationWithMscorlib461(source, new MetadataReference[] { SystemRef, LinqAssemblyRef }).VerifyDiagnostics(
                // (17,28): error CS4033: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.
                //         var xs = from l in await F1()
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutVoidAsyncMethod, "await F1()"));
        }
 
        [Fact]
        public void AsyncLacksAwaits()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    async static Task M()
    {
    }
 
    static void Main()
    {
        Action f1 = async () => new Action(() => { })();
        Action f2 = async () => { };
        Func<Task<int>> f3 = async () => { return 1; };
        Action f4 = async delegate () { };
        Func<Task<int>> f5 = async delegate () { return 1; };
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (7,23): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     async static Task M()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "M").WithLocation(7, 23),
                // (13,30): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //         Action f1 = async () => new Action(() => { })();
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "=>").WithLocation(13, 30),
                // (14,30): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //         Action f2 = async () => { };
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "=>").WithLocation(14, 30),
                // (15,39): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //         Func<Task<int>> f3 = async () => { return 1; };
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "=>").WithLocation(15, 39),
                // (16,27): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //         Action f4 = async delegate () { };
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "delegate").WithLocation(16, 27),
                // (17,36): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //         Func<Task<int>> f5 = async delegate () { return 1; };
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "delegate").WithLocation(17, 36));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    public static async Task F1()
    {
        await Task.Factory.StartNew(() => 1);
    }
 
    public static async Task<int> F2(bool truth)
    {
        for (F1(); truth; F1()) ;
 
        for (F1(), F1(); truth; F1(), F1()) ;
 
        return await Task.Factory.StartNew(() => 1);
    }
 
    static void Main()
    {
        F2(false);
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         for (F1(); truth; F1()) ;
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "F1()"),
                // (13,27): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         for (F1(); truth; F1()) ;
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "F1()"),
                // (15,14): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         for (F1(), F1(); truth; F1(), F1()) ;
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "F1()"),
                // (15,20): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         for (F1(), F1(); truth; F1(), F1()) ;
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "F1()"),
                // (15,33): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         for (F1(), F1(); truth; F1(), F1()) ;
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "F1()"),
                // (15,39): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         for (F1(), F1(); truth; F1(), F1()) ;
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "F1()"),
                // (22,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         F2(false);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "F2(false)"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait01()
        {
            // invoke a method that returns an awaitable type in an async method
            var source = @"
using System.Threading.Tasks;
class Test
{
    public async void Meth()
    {
        await Task.Delay(10);
        Goo();
    }
 
    public async Task<int> Goo()
    {
        await Task.Delay(10);
        return 1;
    }
 
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (16,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Goo();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait02()
        {
            // invoke a method that returns an awaitable type in an async method
 
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    public async Task Meth()
    {
        Goo();
        foreach (var x in new int[] { 1, 2 })
        {
            Goo();
        }
 
        while (await Goo())
        {
            Goo();
        }
    }
 
    public async Task<dynamic> Goo()
    {
        return 1;
    }
 
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }).VerifyDiagnostics(
                // (19,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Goo();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"),
                // (22,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             Goo();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"),
                // (27,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             Goo();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"),
                // (31,32): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     public async Task<dynamic> Goo()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Goo"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait03()
        {
            // invoke a method that returns an awaitable type in an async method
            var source = @"
using System.Threading.Tasks;
 
public delegate Task<decimal?> Bar();
class Test
{
    static async Task<object> Meth()
    {
        Goo();
 
        Bar bar = Goo;
        bar();
 
        return (object)"""";
    }
 
    static async Task<decimal?> Goo()
    {
        return null;
    }
 
    static Task Meth2()
    {
        Goo();
 
        Bar bar = Goo;
        bar();
        return Task.Run(async () => { await Task.Delay(10); });
    }
 
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (21,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Goo();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"),
                // (24,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         bar();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "bar()"),
                // (19,31): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     static async Task<object> Meth()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Meth"),
                // (29,33): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     static async Task<decimal?> Goo()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Goo"),
                // (36,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Goo();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait04()
        {
            // invoke a method that returns an awaitable type in an async method
            var source = @"
using System.Threading.Tasks;
 
class C1{}
 
static class Extension
{
    public static Task<C1> MethExt(this int i)
    {
        return Task.Run(async () => new C1());
    }
}
 
class Test
{
    static async Task<T> Meth<T>(T t)
    {
        int i = 0;
        i.MethExt();
        Goo(1);
        return t;
    }
 
    static Task<T> Goo<T>(T t)
    {
        return Task.Run(async () => { return t; });
    }
 
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (19,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         i.MethExt();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.MethExt()").WithLocation(19, 9),
                // (20,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Goo(1);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo(1)").WithLocation(20, 9),
                // (16,26): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     static async Task<T> Meth<T>(T t)
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Meth").WithLocation(16, 26),
                // (26,34): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //         return Task.Run(async () => { return t; });
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "=>").WithLocation(26, 34),
                // (10,34): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //         return Task.Run(async () => new C1());
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "=>").WithLocation(10, 34));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait05()
        {
            // invoke a method that returns an awaitable type in an async method
            var source = @"
using System;
using System.Threading.Tasks;
class Test
{
    static async Task<dynamic> Meth1()
    {
        throw new EntryPointNotFoundException();
        Goo();
        return """";
    }
 
    static async Task<decimal?> Meth2()
    {
        Goo();
        throw new DuplicateWaitObjectException();
        return null;
    }
 
    static async Task<decimal?> Goo()
    {
        return null;
    }
 
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }).VerifyDiagnostics(
                // (20,32): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     static async Task<dynamic> Meth1()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Meth1"),
                // (23,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Goo();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"),
                // (23,9): warning CS0162: Unreachable code detected
                //         Goo();
                Diagnostic(ErrorCode.WRN_UnreachableCode, "Goo"),
                // (27,33): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     static async Task<decimal?> Meth2()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Meth2"),
                // (29,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Goo();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"),
                // (31,9): warning CS0162: Unreachable code detected
                //         return null;
                Diagnostic(ErrorCode.WRN_UnreachableCode, "return"),
                // (34,33): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     static async Task<decimal?> Goo()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Goo"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait05_b()
        {
            // invoke a method that returns an awaitable type in an async method
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    static async Task<dynamic> Meth1()
    {
        return """";
        Goo();
    }
 
    static int Meth2()
    {
        return 2;
        Goo();
    }
 
    static async Task<double?> Goo()
    {
        return null;
    }
 
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }).VerifyDiagnostics(
                // (22,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Goo();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"),
                // (19,32): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     static async Task<dynamic> Meth1()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Meth1"),
                // (22,9): warning CS0162: Unreachable code detected
                //         Goo();
                Diagnostic(ErrorCode.WRN_UnreachableCode, "Goo"),
                // (28,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Goo();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"),
                // (28,9): warning CS0162: Unreachable code detected
                //         Goo();
                Diagnostic(ErrorCode.WRN_UnreachableCode, "Goo"),
                // (31,32): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     static async Task<double?> Goo()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Goo"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait06()
        {
            // invoke a method that returns an awaitable type in an async method
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<T> Meth<T>(T t)
    {
        await Task.Delay(10);
        return t;
    }
 
    static async Task<T> Goo<T>(T t)
    {
        Func<Task<int>> f = async () =>
        {
            await Task.Delay(10);
            Meth(1);
            return 2;
        };
        f();
 
        Func<Task<Func<Task<int>>>> ff = async delegate()
            {
                Meth((dynamic)5.1);
                await Task.Delay(10);
                return (Func<Task<int>>)(async () =>
                    {
                        Meth("""");
                        await Task.Delay(10);
                        return 3;
                    });
            };
 
        ff();
 
        (await ff())();
 
        return t;
    }
 
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (30,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             Meth(1);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(1)"),
                // (33,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         f();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "f()"),
                // (41,25): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //                         Meth("");
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, @"Meth("""")"),
                // (47,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         ff();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "ff()"),
                // (49,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         (await ff())();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "(await ff())()"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait07()
        {
            // invoke a method that returns an awaitable type in an async method
            var source = @"
using System;
using System.Threading;
using System.Threading.Tasks;
struct MyDisp : IDisposable
{
    public static int DisposeCalledCount;
    public void Dispose()
    {
        DisposeCalledCount++;
        TestCase.DisposeCalled++;
    }
 
    public MyDisp(int Count = 0)
    {
        DisposeCalledCount = 0;
    }
}
 
class TestCase
{
    private int tests;
    public static int DisposeCalled;
 
    public async Task Meth(MyDisp x)
    {
        await Task.Delay(10);
    }
 
    public async void Run()
    {
        this.tests = 0;
        TestCase.DisposeCalled = 0;
 
        //using statement inside async void sub
        tests++;
        using (var x = new MyDisp())
        {
            Meth(x);
        }
        if (MyDisp.DisposeCalledCount == TestCase.DisposeCalled)
            Driver.Count++;
 
        //using statement inside Task returning lambda
        this.tests++;
        Func<Task> f = async () =>
        {
            await Task.Delay(10);
            using (var x = new MyDisp())
            {
                Meth(x);
            }
        };
        f();
        await f();
        if (MyDisp.DisposeCalledCount == TestCase.DisposeCalled)
            Driver.Count++;
 
        //using statement inside Task<decimal> returning lambda
        this.tests++;
        Func<Task<decimal>> g = async () =>
        {
            await Task.Delay(10);
            Meth(new MyDisp());
            using (var x = new MyDisp())
            {
                Task.Run(async () =>
                {
                    new Action<MyDisp>((y) => { })(x);
                    await Task.Delay(10);
                });
            }
            return 1;
        };
 
        var t = await g();
        if (MyDisp.DisposeCalledCount == TestCase.DisposeCalled && t == 1)
            Driver.Count++;
 
        Driver.Result = Driver.Count - this.tests;
        //When test complete, set the flag.
        Driver.CompletedSignal.Set();
    }
}
 
class Driver
{
    public static int Result = -1;
    public static int Count = 0;
    public static AutoResetEvent CompletedSignal = new AutoResetEvent(false);
    static int Main()
    {
        var t = new TestCase();
        t.Run();
 
        CompletedSignal.WaitOne();
        // 0 - success
        // 1 - failed (test completed)
        // -1 - failed (test incomplete - deadlock, etc)
        return Driver.Result;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (55,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             Meth(x);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(x)"),
                // (67,17): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //                 Meth(x);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(x)"),
                // (70,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         f();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "f()"),
                // (80,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             Meth(new MyDisp());
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(new MyDisp())"),
                // (83,17): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //                 Task.Run(async () =>
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, @"Task.Run(async () =>
                {
                    new Action<MyDisp>((y) => { })(x);
                    await Task.Delay(10);
                })"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait08()
        {
            // invoke a method that returns an awaitable type in an async method
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<T> Meth<T>(T t)
    {
        await Task.Delay(10);
        return t;
    }
 
    static async Task Goo()
    {
        try
        {
            Meth(1);
        }
        catch (Exception)
        {
            Meth("""");
        }
        finally
        {
            Meth((decimal?)2);
        }
    }
 
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (28,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             Meth(1);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(1)"),
                // (32,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             Meth("");
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, @"Meth("""")"),
                // (36,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             Meth((decimal?)2);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth((decimal?)2)"),
                // (24,23): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     static async Task Goo()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Goo"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait09()
        {
            // invoke a method that returns an awaitable type in an async method
            var source = @"
using System;
using System.Threading.Tasks;
 
static class Extension
{
    public static async Task Meth<T>(this int i, T t)
    {
        await Task.Delay(10);
    }
}
 
class Test
{
    static async Task<T> Goo<T>(T t)
    {
        var i = 0;
        Func<Task> f = async delegate()
        {
            await Task.Delay(10);
            i.Meth(1);
        };
 
        Func<Task<Func<Task<int>>>> ff = async () =>
        {
            f();
            await Task.Delay(10);
            return (Func<Task<int>>)(async delegate()
            {
                i.Meth("""");
                await Task.Delay(10);
                return 3;
            });
        };
 
        ff();
 
        (await ff())();
 
        return t;
    }
 
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (33,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             i.Meth(1);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.Meth(1)"),
                // (38,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             f();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "f()"),
                // (42,17): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //                 i.Meth("");
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, @"i.Meth("""")"),
                // (48,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         ff();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "ff()"),
                // (50,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         (await ff())();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "(await ff())()"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait10()
        {
            // invoke a method that returns an awaitable type in an async method
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    async Task<T> Meth<T>(T t)
    {
        await Task.Delay(10);
        return t;
    }
 
    private Task field;
    public Task Prop
    {
        get
        {
            Meth(1);
            return @field;
        }
        set
        {
            Bar();
            Meth("""");
            @field = value;
        }
    }
 
    public async Task Goo()
    {
        await Bar();
        Bar(); //the callee return type is dynamic, it will not give warning
        Meth((decimal?)null);
    }
 
    public dynamic Bar()
    {
        return Task.Run<int>(async () => { await Task.Delay(10); return 2; });
    }
 
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }).VerifyDiagnostics(
                // (30,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             Meth(1);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(1)"),
                // (36,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             Meth("");
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, @"Meth("""")"),
                // (45,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Meth((decimal?)null);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth((decimal?)null)"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait11()
        {
            // invoke a method that returns an awaitable type in an async method
            var source = @"
using System.Threading.Tasks;
 
partial class Test
{
    partial void Bar();
    public async Task<T> Meth<T>(params T[] t)
    {
        await Task.Delay(10);
        return t[0];
    }
}
 
partial class Test
{
    async partial void Bar()
    {
        await Task.Delay(10);
        Meth("""", null);
    }
 
    async public Task Goo()
    {
        Bar();
        Meth(Task.Run(async () => 1), Meth(1));
    }
 
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (19,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Meth("", null);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, @"Meth("""", null)").WithLocation(19, 9),
                // (25,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Meth(Task.Run(async () => 1), Meth(1));
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(Task.Run(async () => 1), Meth(1))").WithLocation(25, 9),
                // (25,32): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //         Meth(Task.Run(async () => 1), Meth(1));
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "=>").WithLocation(25, 32),
                // (22,23): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     async public Task Goo()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Goo").WithLocation(22, 23));
        }
 
        [WorkItem(611150, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/611150")]
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait12()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    static async Task<T> Meth<T>(T t)
    {
        await Task.Delay(10);
        return t;
    }
 
    static async Task Goo()
    {
        checked
        {
            Meth(await Meth(int.MaxValue) + 1);
        }
        unchecked
        {
            Meth(long.MinValue - 1);
        }
 
        var str = """";
        lock (str)
        {
            Meth((int?)null);
        }
 
        lock (Meth(""""))
        {
            Task.Run(async () => { await Task.Delay(10); return """"; });
        }
    }
 
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (16,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             Meth(await Meth(int.MaxValue) + 1);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(await Meth(int.MaxValue) + 1)"),
                // (20,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             Meth(long.MinValue - 1);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(long.MinValue - 1)"),
                // (26,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             Meth((int?)null);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth((int?)null)"));
        }
 
        [WorkItem(611150, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/611150")]
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait12_breaking()
        {
            // The native compiler gives a warning on the un-awaited async invocation. However, awaiting inside the lock
            // would escalate the warning to an error. Roslyn does not give a warning.
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    static async Task Goo()
    {
        await Task.Factory.StartNew(() => { });
        lock (new object())
        {
            Task.Run(async () => { await Task.Delay(10); return """"; });
        }
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait13()
        {
            // invoke a method that returns an awaitable type in an async method
            //      1. the callee is a property/indexer that returns Task/Task<T>
            //      2. invoke the method in the constructor
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    public Task Prop
    {
        get { return Task.Run(async () => { await Task.Delay(10); }); }
    }
 
    public Task<int> this[dynamic index]
    {
        get
        {
            return Task.Run<int>(async () => { await Task.Delay(10); return index; });
        }
    }
 
    public async Task<T> Meth<T>(T t)
    {
        await Task.Delay(10);
        return t;
    }
 
    public Test()
    {
        Meth(1); //warning CS4014
    }
 
    public async Task Goo()
    {
        var test = new Test();
        test.Prop; //error CS0201
        test[1]; //error CS0201
    }
 
    static int Main()
    {
        return 0;
    }
}";
 
            CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }).VerifyDiagnostics(
                // (41,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Meth(1); //warning CS4014
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(1)"),
                // (47,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
                //         test.Prop; //error CS0201
                Diagnostic(ErrorCode.ERR_IllegalStatement, "test.Prop"),
                // (48,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
                //         test[1]; //error CS0201
                Diagnostic(ErrorCode.ERR_IllegalStatement, "test[1]"),
                // (44,23): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     public async Task Goo()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Goo"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait14()
        {
            // invoke a method that returns an awaitable type in async/non-async method
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    static async Task<T> Meth<T>(T t)
    {
        await Task.Delay(10);
        return t;
    }
 
    static async Task Goo()
    {
        for (Meth(""""); await Meth(false); Meth((float?)null))
        {
            Meth(1);
        }
    }
 
    static Task<int> Bar()
    {
        for (Meth(5m); ; Meth(""""))
        {
            Meth((string)null);
        }
    }
 
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (27,14): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         for (Meth(""); await Meth(false); Meth((float?)null))
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, @"Meth("""")"),
                // (27,43): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         for (Meth(""); await Meth(false); Meth((float?)null))
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth((float?)null)"),
                // (29,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             Meth(1);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(1)"),
                // (35,14): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         for (Meth(5m); ; Meth(""))
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(5m)"),
                // (35,26): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         for (Meth(5m); ; Meth(""))
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, @"Meth("""")"),
                // (37,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             Meth((string)null);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth((string)null)"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait15()
        {
            // invoke a method that returns an awaitable type in async/non-async method
            var source = @"
using System.Threading.Tasks;
 
public class TestB
{
    public async Task<T> Meth<T>(T t = default(T))
    {
        await Task.Delay(10);
        return t;
    }
 
    public async Task Meth2()
    {
        await Task.Delay(10);
    }
}
 
public class Test
{
    public async Task Goo()
    {
        var testB = new TestB();
        for (testB.Meth2(); await testB.Meth(false); testB.Meth((float?)null))
        {
            testB.Meth(1);
        }
    }
 
    public void Bar()
    {
        //if the awaitable method was compiled into a library, the warning will not give
        var testB = new TestB();
        testB.Meth<decimal>();
        testB.Meth2();
    }
 
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (33,14): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         for (testB.Meth2(); await testB.Meth(false); testB.Meth((float?)null))
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "testB.Meth2()"),
                // (33,54): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         for (testB.Meth2(); await testB.Meth(false); testB.Meth((float?)null))
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "testB.Meth((float?)null)"),
                // (35,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             testB.Meth(1);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "testB.Meth(1)"),
                // (43,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         testB.Meth<decimal>();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "testB.Meth<decimal>()"),
                // (44,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         testB.Meth2();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "testB.Meth2()"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait16()
        {
            // invoke a method that returns an awaitable type in a non-async method
            var source = @"
using System.Threading.Tasks;
class Test
{
    public void Meth()
    {
        Goo();
    }
 
    public async Task<int> Goo()
    {
        await Task.Delay(10);
        return 1;
    }
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (15,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Goo();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait17()
        {
            // invoke a method that returns an awaitable type in a non-async method
            var source = @"
using System;
using System.Threading.Tasks;
 
static class Extension
{
    public static async Task<int> ExMeth(this string str)
    {
        await Task.Delay(10);
        return str.Length;
    }
}
class Test:IDisposable
{
    public void Dispose() { }
    static int Main()
    {
        using (Test test = new Test())
        {
            string s=""abc"";
             s.ExMeth();
        }
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (29,14): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //              s.ExMeth();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "s.ExMeth()"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait18()
        {
            // invoke a method that returns an awaitable type in a non-async method
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    public delegate T Del<T>(T item);
    public T Meth<T>(T t)
    {
        Goo();
        Del<int> del = x =>
            {
                Goo();
                return 1;
            };
        return t;
    }
 
 
    static async Task<Task> Goo()
    {
        await Task.Delay(10);
        return new Task(() => { Task.Delay(10); });
    }
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (18,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Goo();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"),
                // (21,17): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //                 Goo();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait19()
        {
            // invoke a method that returns an awaitable type in a non-async method
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    public delegate T Del<T>();
    public T Meth<T>(T t)
    {
        Goo();
        Del<Task<string>> del =async delegate()
        {
            await Task.Delay(10);
            Goo();
            Del<int> del2 = () =>
                {
                    Goo();
                    return 1;
                };
            return """";
        };
        del();
        return t;
    }
 
 
    public Task Goo()
    {
        return Task.Run(async() =>
            {
                await Task.Delay(10);
            });
    }
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (21,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             Goo();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait20()
        {
            // invoke a method that returns an awaitable type in a non-async method
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test { }
class Testcase
{
    static Test test = null;
    public void Meth()
    {
        Goo();
        Func<Task<Test>> fun = () =>
            {
                return Goo();
            };
    }
 
    public Task<Test> Goo()
    {
        return Task.Run<Test>( () =>
            {
                if (test == null)
                    test = new Test();
                return test;
            }
            );
    }
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait21()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    delegate Task<dynamic> Del(dynamic d = null);
    public void Meth()
    {
        Del del = async x =>
            {
                await Task.Delay(10);
                return 1;
            };
        del();
        Func<int,Task<Func<dynamic>>> func =async y =>
            {
                await Task.Delay(10);
                del(y);
                return (delegate() { return 1; });
            };
        func(1);
    }
 
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }).VerifyDiagnostics(
                // (27,17): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //                 del(y);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "del(y)"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait22()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    public void Meth()
    {
        Func<Task<string>> Goo = async () =>
            {
                await Task.Delay(10);
                return """";
            };
        Goo();
        Task.Run(() =>
            {
                Goo();
                Func<Task<Task>> fun = async () =>
                    {
                        await Task.Delay(10);
                        return Task.Run(() =>
                            {
                                Goo();
                            });
                    };
            });
    }
 
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait23()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    delegate Task<string> Del();
    delegate void Del2();
    public void Meth()
    {
        Del del = async delegate()
        {
            await Task.Delay(10);
            return """";
        };
        del();
        Del2 del2 = delegate()
        {
            del();
            Del del3 = async () =>
                {
                    await Task.Delay(10);
                    Del2 del4 = delegate()
                    {
                        del();
                    };
                    return """";
                };
            del3();
 
        };
    }
 
    static int Main()
    {
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait24()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
static class Extension
{
    public static Task<int> ExMeth(this int i)
    {
        Func<Task<int>> Goo = async () =>
            {
                await Task.Delay(10);
                return ++i;
            };
        return (Task<int>) Goo();
    }
}
class Test
{
    public static int amount=0;
    static int Main()
    {
        lock (amount.ExMeth())
        {
            amount.ExMeth();
        }
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait25()
        {
            var source = @"
using System.Threading.Tasks;
 
class Test
{
    public async Task<int> Meth()
    {
        await Task.Delay(10);
        return int.MaxValue;
    }
    public Task<int> Goo()
    {
        int i = int.MaxValue;
        return Task.Run(async () => { return i; });
    }
    static int Main()
    {
        Test test = new Test();
        checked
        {
            test.Meth();
            test.Goo();
        }
        unchecked
        {
            test.Meth();
            test.Goo();
        }
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (14,34): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //         return Task.Run(async () => { return i; });
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "=>").WithLocation(14, 34),
                // (21,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             test.Meth();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "test.Meth()").WithLocation(21, 13),
                // (26,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             test.Meth();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "test.Meth()").WithLocation(26, 13));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait26()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Testcase
{
    ~Testcase()
    {
        Goo();
        Goo2();
    }
    public async Task<string> Goo()
    {
        await Task.Delay(10);
        return ""Goo"";
    }
    public Task Goo2()
    {
        return Task.Run(() => { });
    }
}
class Test
{
    static int Main()
    {
        Object obj = new Testcase();
        obj = null;
 
        GC.Collect();
        GC.WaitForPendingFinalizers();
        return 0;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (17,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Goo();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_ForgetAwait27()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test : IDisposable
{
    public async Task Goo()
    {
        await Task.Delay(10);
    }
    public void Dispose()
    {
        Goo();
    }
    static int Main()
    {
        using (Test test = new Test())
        {
            test.Goo();
        }
        return 0;
    }
}
";
 
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (22,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Goo();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"),
                // (28,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //             test.Goo();
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "test.Goo()"));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_Script()
        {
            var source =
@"using System.Threading.Tasks;
Task.FromResult(1);
Task.FromResult(2);";
            var compilation = CreateCompilationWithMscorlib461(source, parseOptions: TestOptions.Script);
            compilation.VerifyDiagnostics(
                // (2,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // Task.FromResult(1);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Task.FromResult(1)").WithLocation(2, 1),
                // (3,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // Task.FromResult(2);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Task.FromResult(2)").WithLocation(3, 1));
        }
 
        [Fact]
        public void UnobservedAwaitableExpression_Submission()
        {
            var source0 =
@"using System.Threading.Tasks;
Task.FromResult(1);
Task.FromResult(2)";
            var submission = CSharpCompilation.CreateScriptCompilation(
                "s0.dll",
                syntaxTree: SyntaxFactory.ParseSyntaxTree(source0, options: TestOptions.Script),
                references: new[] { MscorlibRef_v4_0_30316_17626 });
            submission.VerifyDiagnostics(
                // (2,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // Task.FromResult(1);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Task.FromResult(1)").WithLocation(2, 1),
                // (3,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // Task.FromResult(2);
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Task.FromResult(2)").WithLocation(3, 1));
        }
 
        [Fact]
        public void BadAsyncMethodWithNoStatementBody()
        {
            var source = @"
using System.Threading.Tasks;
 
static class Test
{
    static async Task M1();
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (6,23): error CS1994: The 'async' modifier can only be used in methods that have a body
                //     static async Task M1();
                Diagnostic(ErrorCode.ERR_BadAsyncLacksBody, "M1"));
        }
 
        [Fact]
        public void BadAsyncMethodWithVarargsAndNoStatementBody()
        {
            var source = @"
using System.Threading.Tasks;
 
static class Test
{
    static async Task M1(__arglist);
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (6,23): error CS1994: The 'async' modifier can only be used in methods that have a body
                //     static async Task M1(__arglist);
                Diagnostic(ErrorCode.ERR_BadAsyncLacksBody, "M1"));
        }
 
        [Fact]
        public void BadSpecialByRefParameter()
        {
            var source = @"
using System.Threading.Tasks;
using System;
 
class Test
{
    async Task M1(TypedReference tr)
    {
        await Task.Factory.StartNew(() => { });
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (7,34): error CS4012: Parameters of type 'System.TypedReference' cannot be declared in async methods or async lambda expressions
                //     async Task M1(TypedReference tr)
                Diagnostic(ErrorCode.ERR_BadSpecialByRefParameter, "tr").WithArguments("System.TypedReference"));
        }
 
        [Fact]
        public void BadSpecialByRefLocal()
        {
            var source = @"
using System.Threading.Tasks;
using System;
 
class Test
{
    async Task M1()
    {
        TypedReference tr;
        await Task.Factory.StartNew(() => { });
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyEmitDiagnostics(
                // (9,24): warning CS0168: The variable 'tr' is declared but never used
                //         TypedReference tr;
                Diagnostic(ErrorCode.WRN_UnreferencedVar, "tr").WithArguments("tr"));
        }
 
        [Fact]
        public void BadSpecialByRefVarDeclLocal()
        {
            var source = @"
using System.Threading.Tasks;
using System;
 
class Test
{
    async Task M1(bool truth)
    {
        var tr = new TypedReference(); // 1
        await Task.Factory.StartNew(() => { });
    }
 
    async Task M2(bool truth)
    {
        var tr = new TypedReference();
        await Task.Factory.StartNew(() => { });
        var tr2 = tr; // 2
    }
 
    async Task M3()
    {
        var tr = new TypedReference();
        await Task.Factory.StartNew(() => { });
        tr = default;
        var tr2 = tr;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyEmitDiagnostics(
                // (9,13): warning CS0219: The variable 'tr' is assigned but its value is never used
                //         var tr = new TypedReference(); // 1
                Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "tr").WithArguments("tr").WithLocation(9, 13),
                // (17,19): error CS4007: Instance of type 'System.TypedReference' cannot be preserved across 'await' or 'yield' boundary.
                //         var tr2 = tr; // 2
                Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "tr").WithArguments("System.TypedReference").WithLocation(17, 19));
        }
 
        [Fact]
        public void BadFixedSpecialByRefLocal()
        {
            var source = @"
using System;
 
public class MyClass
{
    unsafe async public static void F()
    {
        fixed (TypedReference tr) { }
    }
}";
            CreateCompilationWithMscorlib461(source, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
                // (8,31): error CS0209: The type of a local declared in a fixed statement must be a pointer type
                //         fixed (TypedReference tr) { }
                Diagnostic(ErrorCode.ERR_BadFixedInitType, "tr"),
                // (8,31): error CS0210: You must provide an initializer in a fixed or using statement declaration
                //         fixed (TypedReference tr) { }
                Diagnostic(ErrorCode.ERR_FixedMustInit, "tr"),
                // (6,37): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     unsafe async public static void F()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "F"));
        }
 
        [Fact]
        public void AsyncInSecurityCriticalClass()
        {
            var source = @"
using System.Security;
using System.Threading.Tasks;
 
[SecurityCritical]
public class C
{
    public async void M()
    {
        await Task.Factory.StartNew(() => { });
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (8,23): error CS4031: Async methods are not allowed in an Interface, Class, or Structure which has the 'SecurityCritical' or 'SecuritySafeCritical' attribute.
                //     public async void M()
                Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsyncInClassOrStruct, "M"));
        }
 
        [Fact]
        public void AsyncInSecuritySafeCriticalClass()
        {
            var source = @"
using System.Security;
using System.Threading.Tasks;
 
[SecuritySafeCritical]
public class C
{
    public async void M()
    {
        await Task.Factory.StartNew(() => { });
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (8,23): error CS4031: Async methods are not allowed in an Interface, Class, or Structure which has the 'SecurityCritical' or 'SecuritySafeCritical' attribute.
                //     public async void M()
                Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsyncInClassOrStruct, "M"));
        }
 
        [Fact]
        public void AsyncInSecuritySafeCriticalAndSecurityCriticalClass()
        {
            var source = @"
using System.Security;
using System.Threading.Tasks;
 
[SecurityCritical]
[SecuritySafeCritical]
public class C
{
    public async void M()
    {
        await Task.Factory.StartNew(() => { });
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (9,23): error CS4031: Async methods are not allowed in an Interface, Class, or Structure which has the 'SecurityCritical' or 'SecuritySafeCritical' attribute.
                //     public async void M()
                Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsyncInClassOrStruct, "M"));
        }
 
        [Fact]
        public void AsyncInDoublyNestedSecuritySafeCriticalAndSecurityCriticalClasses()
        {
            var source = @"
using System.Security;
using System.Threading.Tasks;
 
[SecurityCritical]
[SecuritySafeCritical]
public class C
{
    [SecuritySafeCritical]
    public class D
    {
        public async void M()
        {
            await Task.Factory.StartNew(() => { });
        }
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (12,27): error CS4031: Async methods are not allowed in an Interface, Class, or Structure which has the 'SecurityCritical' or 'SecuritySafeCritical' attribute.
                //         public async void M()
                Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsyncInClassOrStruct, "M"));
        }
 
        [Fact]
        public void SecurityCriticalOnAsync()
        {
            var source = @"
using System.Security;
using System.Threading.Tasks;
 
public class D
{
    [SecurityCritical]
    public async void M()
    {
        await Task.Factory.StartNew(() => { });
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (7,6): error CS4030: Security attribute 'SecurityCritical' cannot be applied to an Async method.
                //     [SecurityCritical]
                Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsync, "SecurityCritical").WithArguments("SecurityCritical"));
        }
 
        [Fact]
        public void SecuritySafeCriticalOnAsync()
        {
            var source = @"
using System.Security;
using System.Threading.Tasks;
 
public class D
{
    [SecuritySafeCritical]
    public async void M()
    {
        await Task.Factory.StartNew(() => { });
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (7,6): error CS4030: Security attribute 'SecuritySafeCritical' cannot be applied to an Async method.
                //     [SecuritySafeCritical]
                Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsync, "SecuritySafeCritical").WithArguments("SecuritySafeCritical"));
        }
 
        [Fact]
        public void SecuritySafeCriticalAndSecurityCriticalOnAsync()
        {
            var source = @"
using System.Security;
using System.Threading.Tasks;
 
public class D
{
    [SecurityCritical]
    [SecuritySafeCritical]
    public async void M()
    {
        await Task.Factory.StartNew(() => { });
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (7,6): error CS4030: Security attribute 'SecurityCritical' cannot be applied to an Async method.
                //     [SecurityCritical]
                Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsync, "SecurityCritical").WithArguments("SecurityCritical"),
                // (8,6): error CS4030: Security attribute 'SecuritySafeCritical' cannot be applied to an Async method.
                //     [SecuritySafeCritical]
                Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsync, "SecuritySafeCritical").WithArguments("SecuritySafeCritical"));
        }
 
        [Fact, WorkItem(547077, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547077")]
        public void Repro_17880()
        {
            var source = @"
class Program
{
    async void Meth()
    {
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (4,16): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     async void Meth()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Meth"));
        }
 
        [Fact, WorkItem(547079, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547079")]
        public void Repro_17883()
        {
            var source = @"
abstract class Base
{
    public async abstract void M1();
}
 
class Test
{
    public static int Main()
    {
        return 1;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (4,32): error CS1994: The 'async' modifier can only be used in methods that have a body.
                //     public async abstract void M1();
                Diagnostic(ErrorCode.ERR_BadAsyncLacksBody, "M1"));
        }
 
        [Fact, WorkItem(547081, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547081")]
        public void Repro_17885_CSharp_71()
        {
            var source = @"
using System.Threading.Tasks;
class Test
{
    async public static Task Main()
    {
    }
}";
            CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_1)).VerifyDiagnostics(
                // (5,30): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     async public static Task Main()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Main").WithLocation(5, 30));
        }
 
        [Fact, WorkItem(547081, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547081")]
        public void Repro_17885_CSharp7()
        {
            var source = @"
using System.Threading.Tasks;
class Test
{
    async public static Task Main()
    {
    }
}";
            var comp = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7));
            comp.VerifyDiagnostics(
                // (5,30): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     async public static Task Main()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Main").WithLocation(5, 30),
                // (5,25): error CS8107: Feature 'async main' is not available in C# 7.0. Please use language version 7.1 or greater.
                //     async public static Task Main()
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "Task").WithArguments("async main", "7.1").WithLocation(5, 25),
                // error CS5001: Program does not contain a static 'Main' method suitable for an entry point
                Diagnostic(ErrorCode.ERR_NoEntryPoint).WithLocation(1, 1)
                );
        }
 
        [Fact, WorkItem(547088, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547088")]
        public void Repro_17914()
        {
            var source = @"
class Driver
{
    static int Main()
    {
        return 1;
    }
 
    public async void Goo(ref int x)
    { }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (9,35): error CS1988: Async methods cannot have ref, in or out parameters
                //     public async void Goo(ref int x)
                Diagnostic(ErrorCode.ERR_BadAsyncArgType, "x"),
                // (9,23): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     public async void Goo(ref int x)
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Goo"));
        }
 
        [Fact]
        public void BadAsync_MethodImpl_Synchronized()
        {
            var source = @"
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
 
public class C
{
    [MethodImpl(MethodImplOptions.Synchronized)]
    async Task<int> F1()
    {
        return await Task.Factory.StartNew(() => 1);
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (9,21): error CS4015: 'MethodImplOptions.Synchronized' cannot be applied to an Async method.
                //     async Task<int> F1()
                Diagnostic(ErrorCode.ERR_SynchronizedAsyncMethod, "F1"));
        }
 
        [Fact, WorkItem(66530, "https://github.com/dotnet/roslyn/issues/66530")]
        public void BadAsync_MethodImpl_Synchronized_Lambda()
        {
            var source = @"
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
 
public class C
{
    void M()
    {
        var a = [MethodImpl(MethodImplOptions.Synchronized)] async Task<int> () =>
            {
                await Task.Yield();
                return 42;
            };
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (9,81): error CS4015: 'MethodImplOptions.Synchronized' cannot be applied to an async method
                //         var a = [MethodImpl(MethodImplOptions.Synchronized)] async Task<int> () =>
                Diagnostic(ErrorCode.ERR_SynchronizedAsyncMethod, "=>").WithLocation(9, 81));
        }
 
        [Fact]
        public void BadAsync_MethodImpl_Synchronized_LocalFunction()
        {
            var source = @"
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
 
public class C
{
    void M()
    {
        [MethodImpl(MethodImplOptions.Synchronized)]
        async Task<int> local()
        {
            return await Task.Factory.StartNew(() => 1);
        }
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (10,25): error CS4015: 'MethodImplOptions.Synchronized' cannot be applied to an async method
                //         async Task<int> local()
                Diagnostic(ErrorCode.ERR_SynchronizedAsyncMethod, "local").WithLocation(10, 25),
                // (10,25): warning CS8321: The local function 'local' is declared but never used
                //         async Task<int> local()
                Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local").WithArguments("local").WithLocation(10, 25));
        }
 
        [Fact]
        public void Async_MethodImplSynchronized_BadReturn_SecurityCritical()
        {
            var source = @"
using System.Runtime.CompilerServices;
using System.Security;
using System.Threading.Tasks;
 
[SecurityCritical]
public class C
{
    [MethodImpl(MethodImplOptions.Synchronized)]
    async int F1()
    {
        return await Task.Factory.StartNew(() => 1);
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (10,15): error CS1983: The return type of an async method must be void, Task or Task<T>
                //     async int F1()
                Diagnostic(ErrorCode.ERR_BadAsyncReturn, "F1"),
                // (10,15): error CS4031: Async methods are not allowed in an Interface, Class, or Structure which has the 'SecurityCritical' or 'SecuritySafeCritical' attribute.
                //     async int F1()
                Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsyncInClassOrStruct, "F1"),
                // (10,15): error CS4015: 'MethodImplOptions.Synchronized' cannot be applied to an Async method.
                //     async int F1()
                Diagnostic(ErrorCode.ERR_SynchronizedAsyncMethod, "F1"));
        }
 
        [Fact]
        [WorkItem(552382, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/552382")]
        public void GetAwaiterIsExtension()
        {
            var source =
@"using System;
using A;
 
namespace A
{
    public class IAS<T>
    {
    }
    public class Awaiter<T> : System.Runtime.CompilerServices.INotifyCompletion
    {
        public bool IsCompleted { get { return true; } }
        public T GetResult() { return default(T); }
        public void OnCompleted(Action continuation) { }
    }
    public static class IAS_Extensions
    {
        public static Awaiter<T> GetAwaiter<T>(this IAS<T> self) { return null; }
    }
}
 
namespace B
{
    public class Program
    {
        static async void M(IAS<int> i)
        {
            int i1 = await i;
            int i2 = i.GetAwaiter().GetResult();
        }
        public static void Main(string[] args)
        {
        }
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
        }
 
        [Fact]
        [WorkItem(576311, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/576311")]
        public void BadDelegateTypeForAsync()
        {
            var source =
@"using System;
class C
{
    static void Main()
    {
        Func<int> x = async delegate { throw null; };
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (6,29): error CS4010: Cannot convert async anonymous method to delegate type 'Func<int>'. An async anonymous method may return void, Task or Task<T>, none of which are convertible to 'Func<int>'.
                //         Func<int> x = async delegate { throw null; };
                Diagnostic(ErrorCode.ERR_CantConvAsyncAnonFuncReturns, "delegate").WithArguments("anonymous method", "System.Func<int>"),
                // (6,29): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //         Func<int> x = async delegate { throw null; };
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "delegate").WithLocation(6, 29));
        }
 
        [WorkItem(588706, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/588706")]
        [Fact]
        public void AsyncAsLambdaParameter()
        {
            var source =
@"using System;
using System.Threading.Tasks;
 
class C
{
    async void Goo()
    {
        Action<int> x = (await) => { }; // should be a syntax error
        await Task.Delay(1);
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (8,26): error CS4003: 'await' cannot be used as an identifier within an async method or lambda expression
                //         Action<int> x = (await) => { }; // should be a syntax error
                Diagnostic(ErrorCode.ERR_BadAwaitAsIdentifier, "await").WithLocation(8, 26)
                );
        }
 
        [Fact]
        [WorkItem(629368, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/629368")]
        public void GetAwaiterFieldUsedLikeMethod()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
 
public class C
{
    public Func<TaskAwaiter<int>> GetAwaiter;
 
    public async Task<int> F(C x)
    {
        return await x;
    }
}
";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (12,17): error CS0118: 'GetAwaiter' is a field but is used like a method
                Diagnostic(ErrorCode.ERR_BadSKknown, "await x").WithArguments("GetAwaiter", "field", "method"));
        }
 
        [Fact]
        [WorkItem(629368, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/629368")]
        public void GetAwaiterPropertyUsedLikeMethod()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
 
public class C
{
    public Func<TaskAwaiter<int>> GetAwaiter { get; set; }
 
    public async Task<int> F(C x)
    {
        return await x;
    }
}
";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (12,16): error CS0118: 'GetAwaiter' is a property but is used like a method
                Diagnostic(ErrorCode.ERR_BadSKknown, "await x").WithArguments("GetAwaiter", "property", "method"));
        }
 
        [Fact]
        [WorkItem(628619, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/628619")]
        public void ReturnExpressionNotConvertible()
        {
            string source = @"
using System.Threading.Tasks;
 
class Program
{
    static async Task<T> Goo<T>()
    {
        await Task.Delay(1);
        return 1;
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (9,16): error CS0029: Cannot implicitly convert type 'int' to 'T'
                //         return 1;
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "T")
                );
        }
 
        [Fact]
        [WorkItem(632824, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/632824")]
        public void RefParameterOnAsyncLambda()
        {
            string source = @"
using System;
using System.Threading.Tasks;
 
delegate Task D(ref int x);
 
class C
{
    static void Main()
    {
        D d = async delegate(ref int i)
        {
            await Task.Delay(500);
            Console.WriteLine(i++);
        };
 
        int x = 5;
        d(ref x).Wait();
        Console.WriteLine(x);
    }
}";
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (11,38): error CS1988: Async methods cannot have ref, in or out parameters
                //         D d = async delegate(ref int i)
                Diagnostic(ErrorCode.ERR_BadAsyncArgType, "i")
                );
        }
 
        [Fact]
        [WorkItem(858059, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/858059")]
        public void UnawaitedVersusLambda()
        {
            string source =
@"using System;
using System.Threading.Tasks;
 
public class Program
{
    public static void Main(string[] args)
    {
    }
 
    void X()
    {
        Action x1 = () => XAsync(); // warn
        Action y1 = () => YAsync(); // ok
        Action x2 = async () => XAsync(); // warn
        Action y2 = async () => YAsync(); // warn
 
        XAsync(); // warn
        YAsync(); // ok
    }
    async Task XAsync()
    {
        await Task.Delay(1);
    }
    Task YAsync()
    {
        return Task.Delay(1);
    }
}";
            // The rules for when we give a warning may seem quirky, but we aim to precisely replicate
            // the diagnostics produced by the native compiler.
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (12,27): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Action x1 = () => XAsync(); // warn
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "XAsync()"),
                // (14,33): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Action x2 = async () => XAsync(); // warn
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "XAsync()"),
                // (15,33): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Action y2 = async () => YAsync(); // warn
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "YAsync()"),
                // (17,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         XAsync(); // warn
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "XAsync()"),
                // (14,30): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //         Action x2 = async () => XAsync(); // warn
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "=>").WithLocation(14, 30),
                // (15,30): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //         Action y2 = async () => YAsync(); // warn
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "=>").WithLocation(15, 30));
        }
 
        [Fact()]
        public void DelegateTypeWithNoInvokeMethod()
        {
            // Delegate type with no Invoke method.
            var ilSource =
@".class public auto ansi sealed D`1<T>
       extends [mscorlib]System.MulticastDelegate
{
  .method public hidebysig specialname rtspecialname
          instance void  .ctor(object 'object',
                               native int 'method') runtime managed
  {
  }
}";
            var source =
@"using System;
using System.Threading.Tasks;
class C
{
    static void F(D<Task> d) { }
    static void F<T>(D<Task<T>> d) { }
    static void F(Func<Task> f) { }
    static void F<T>(Func<Task<T>> f) { }
    static void M()
    {
#pragma warning disable CS1998
        F(async () => { });
        F(async () => { return 3; });
#pragma warning restore CS1998
    }
}";
            var reference = CompileIL(ilSource);
            var compilation = CreateCompilationWithMscorlib461(source, references: new[] { reference });
            compilation.VerifyEmitDiagnostics();
        }
 
        [Theory, CombinatorialData, WorkItem(64964, "https://github.com/dotnet/roslyn/issues/64964")]
        public void UnobservedAwaitableExpression_AsyncTopLevelStatement(bool voidReturn)
        {
            var src = $$"""
using System;
using System.Threading.Tasks;
 
await Task.Yield();
 
C c = new C();
c.M(); // 1
c.MAsync(); // 2
Action a1 = () => c.M();
Action a2 = async () => { await Task.Yield(); c.M(); }; // 3
Action a3 = () => c.MAsync(); // 4
Action a4 = async () => { await Task.Yield(); c.MAsync(); }; // 5
 
I i = new C();
i.M(); // 6
i.MAsync(); // 7
Action a5 = () => i.M();
Action a6 = async () => { await Task.Yield(); i.M(); }; // 8
Action a7 = () => i.MAsync();
Action a8 = async () => { await Task.Yield(); i.MAsync(); }; // 9
 
{{(voidReturn ? "" : "return 42;")}}
 
public class D
{
    public async Task M2()
    {
        await Task.Yield();
 
        C c = new C();
        c.M(); // 10
        c.MAsync(); // 11
        Action a1 = () => c.M();
        Action a2 = async () => { await Task.Yield(); c.M(); }; // 12
        Action a3 = () => c.MAsync(); // 13
        Action a4 = async () => { await Task.Yield(); c.MAsync(); }; // 14
 
        I i = new C();
        i.M(); // 15
        i.MAsync(); // 16
        Action a5 = () => i.M();
        Action a6 = async () => { await Task.Yield(); i.M(); }; // 17
        Action a7 = () => i.MAsync();
        Action a8 = async () => { await Task.Yield(); i.MAsync(); }; // 18
    }
}
 
public interface I
{
    Task M();
    Task MAsync();
}
 
public class C : I
{
    public Task M() => throw null;
    public async Task MAsync() => await Task.Yield();
}
""";
            var comp = CreateCompilation(src);
            comp.VerifyDiagnostics(
                // (7,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // c.M(); // 1
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.M()").WithLocation(7, 1),
                // (8,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // c.MAsync(); // 2
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(8, 1),
                // (10,47): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // Action a2 = async () => { await Task.Yield(); c.M(); }; // 3
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.M()").WithLocation(10, 47),
                // (11,19): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // Action a3 = () => c.MAsync(); // 4
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(11, 19),
                // (12,47): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // Action a4 = async () => { await Task.Yield(); c.MAsync(); }; // 5
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(12, 47),
                // (15,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // i.M(); // 6
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.M()").WithLocation(15, 1),
                // (16,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // i.MAsync(); // 7
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.MAsync()").WithLocation(16, 1),
                // (18,47): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // Action a6 = async () => { await Task.Yield(); i.M(); }; // 8
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.M()").WithLocation(18, 47),
                // (20,47): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // Action a8 = async () => { await Task.Yield(); i.MAsync(); }; // 9
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.MAsync()").WithLocation(20, 47),
                // (31,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         c.M(); // 10
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.M()").WithLocation(31, 9),
                // (32,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         c.MAsync(); // 11
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(32, 9),
                // (34,55): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Action a2 = async () => { await Task.Yield(); c.M(); }; // 12
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.M()").WithLocation(34, 55),
                // (35,27): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Action a3 = () => c.MAsync(); // 13
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(35, 27),
                // (36,55): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Action a4 = async () => { await Task.Yield(); c.MAsync(); }; // 14
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(36, 55),
                // (39,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         i.M(); // 15
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.M()").WithLocation(39, 9),
                // (40,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         i.MAsync(); // 16
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.MAsync()").WithLocation(40, 9),
                // (42,55): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Action a6 = async () => { await Task.Yield(); i.M(); }; // 17
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.M()").WithLocation(42, 55),
                // (44,55): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //         Action a8 = async () => { await Task.Yield(); i.MAsync(); }; // 18
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.MAsync()").WithLocation(44, 55)
                );
 
            var entryPoint = SynthesizedSimpleProgramEntryPointSymbol.GetSimpleProgramEntryPoint(comp);
            Assert.Equal(voidReturn ? "System.Threading.Tasks.Task" : "System.Threading.Tasks.Task<System.Int32>", entryPoint.ReturnType.ToTestDisplayString());
        }
 
        [Theory, CombinatorialData, WorkItem(64964, "https://github.com/dotnet/roslyn/issues/64964")]
        public void UnobservedAwaitableExpression_NonAsyncTopLevelStatements_Task(bool voidReturn)
        {
            var src = $$"""
using System;
using System.Threading.Tasks;
 
C c = new C();
c.M(); // 1
c.MAsync(); // 2
Action a1 = () => c.M();
Action a2 = () => c.MAsync(); // 3
 
I i = new C();
i.M(); // 4
i.MAsync(); // 5
Action a3 = () => i.M();
Action a4 = () => i.MAsync();
 
object o = null;
lock(o)
{
    c.M();
    c.MAsync(); // 6
}
 
{{(voidReturn ? "" : "return 42;")}}
 
public interface I
{
    Task M();
    Task MAsync();
}
 
public class C : I
{
    public Task M() => throw null;
    public async Task MAsync() => await Task.Yield();
}
""";
            var comp = CreateCompilation(src);
            comp.VerifyDiagnostics(
                // (5,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // c.M(); // 1
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.M()").WithLocation(5, 1),
                // (6,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // c.MAsync(); // 2
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(6, 1),
                // (8,19): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // Action a2 = () => c.MAsync(); // 3
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(8, 19),
                // (11,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // i.M(); // 4
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.M()").WithLocation(11, 1),
                // (12,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // i.MAsync(); // 5
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.MAsync()").WithLocation(12, 1),
                // (20,5): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                //     c.MAsync(); // 6
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(20, 5)
                );
 
            var entryPoint = SynthesizedSimpleProgramEntryPointSymbol.GetSimpleProgramEntryPoint(comp);
            Assert.Equal(voidReturn ? "System.Void" : "System.Int32", entryPoint.ReturnType.ToTestDisplayString());
        }
 
        [Theory, CombinatorialData, WorkItem(64964, "https://github.com/dotnet/roslyn/issues/64964")]
        public void UnobservedAwaitableExpression_NonAsyncTopLevelStatements_TaskT(bool voidReturn)
        {
            var src = $$"""
using System;
using System.Threading.Tasks;
 
C c = new C();
c.M(); // 1
c.MAsync(); // 2
Action a1 = () => c.M();
Action a2 = () => c.MAsync(); // 3
 
I i = new C();
i.M(); // 4
i.MAsync(); // 5
Action a3 = () => i.M();
Action a4 = () => i.MAsync(); // 6
 
{{(voidReturn ? "" : "return 42;")}}
 
public interface I
{
    Task<int> M();
    Task<int> MAsync();
}
 
public class C : I
{
    public Task<int> M() => throw null;
    public async Task<int> MAsync() { await Task.Yield(); throw null; }
}
""";
            var comp = CreateCompilation(src);
            comp.VerifyDiagnostics(
                // (5,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // c.M(); // 1
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.M()").WithLocation(5, 1),
                // (6,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // c.MAsync(); // 2
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(6, 1),
                // (8,19): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // Action a2 = () => c.MAsync(); // 3
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(8, 19),
                // (11,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // i.M(); // 4
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.M()").WithLocation(11, 1),
                // (12,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
                // i.MAsync(); // 5
                Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.MAsync()").WithLocation(12, 1)
                );
 
            var entryPoint = SynthesizedSimpleProgramEntryPointSymbol.GetSimpleProgramEntryPoint(comp);
            Assert.Equal(voidReturn ? "System.Void" : "System.Int32", entryPoint.ReturnType.ToTestDisplayString());
        }
    }
}