dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
19.07k stars 4.04k forks source link

ControlFlowAnalysis.EndPointIsReachable appears to be thrown off by a local function #42447

Open louis-z opened 4 years ago

louis-z commented 4 years ago

Version Used: Microsoft.CodeAnalysis.CSharp.Workspaces 2.10.0 (I know it's an old version)

Steps to Reproduce: Analyze control flow on the following if block:

if (value < 0)
{
    Increment(ref value);
    return;
    void Increment(ref int val) => val++;
    value++;
}

Expected Behavior: EndPointIsReachable == false

According to the EndPointIsReachable documentation:

Return true if and only if the end of the last statement in a region is reachable or the region contains no statements.

In this case, the last statement (value++;) is unreachable.

Actual Behavior: EndPointIsReachable == true

Here's the complete code I used to test this behavior:

using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Xunit;

namespace MyCodeAnalysisTests
{
    public sealed class EndPointIsReachableTests
    {
        [Fact]
        public void Test_IfReturns_EndPointIsUnreachable()
        {
            var code = @"
class TestClass
{
    void TestMethod()
    {
        var value = -1;
        if (value < 0)
        {
            Increment(ref value);
            return;
            void Increment(ref int val) => val++;
            value++;
        }
        else
        {
            value--;
        }
    }
}";
            var tree = CSharpSyntaxTree.ParseText(code);

            var compilation = CSharpCompilation.Create("MyCompilation", syntaxTrees: new[] { tree });
            var model = compilation.GetSemanticModel(tree);

            var ifStatement = tree.GetRoot().DescendantNodes().OfType<IfStatementSyntax>().Single();
            var result = model.AnalyzeControlFlow(ifStatement.Statement);

            Assert.True(result.Succeeded);
            Assert.False(result.EndPointIsReachable);
        }
    }
}
mavasani commented 4 years ago

Moving to the compiler team - this is a compiler API

Rekkonnect commented 3 weeks ago

In VS 17.11.5, using the sample code above I'm getting it dimmed and the compiler emits a warning about the code being unreachable at that location, so this must be fixed already I assume

CyrusNajmabadi commented 3 weeks ago

@Rekkonnect What does hte api produce though?