diff --git a/src/Compilers/VisualBasic/Portable/Analysis/FlowAnalysis/DataFlowPass.vb b/src/Compilers/VisualBasic/Portable/Analysis/FlowAnalysis/DataFlowPass.vb index 59997714be17e..6438b888d7d88 100644 --- a/src/Compilers/VisualBasic/Portable/Analysis/FlowAnalysis/DataFlowPass.vb +++ b/src/Compilers/VisualBasic/Portable/Analysis/FlowAnalysis/DataFlowPass.vb @@ -1022,6 +1022,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Case BoundKind.Local Dim local As LocalSymbol = DirectCast(node, BoundLocal).LocalSymbol + + If local.IsCompilerGenerated AndAlso Not Me.ProcessCompilerGeneratedLocals Then + ' For consistency with Assign behavior, which does not process compiler generated temporary locals. + Return True + End If + If local.DeclarationKind <> LocalDeclarationKind.AmbiguousLocals Then unassignedSlot = VariableSlot(local) diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Symbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Symbol.vb index 4b57e06fd523d..cac4cfd3bedd2 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Symbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Symbol.vb @@ -589,8 +589,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Public ReadOnly Property CanBeReferencedByName As Boolean Get Select Case Me.Kind - Case SymbolKind.Local, - SymbolKind.Label, + Case SymbolKind.Local + Return If(Me.Name?.Length, 0) > 0 + + Case SymbolKind.Label, SymbolKind.Alias ' Can't be imported, but might have syntax errors in which case we use an empty name: Return Me.Name.Length > 0 diff --git a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenRefReturnTests.vb b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenRefReturnTests.vb index 237f366ee1cf6..38f7db79e94ac 100644 --- a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenRefReturnTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenRefReturnTests.vb @@ -3593,6 +3593,184 @@ End Module", verifier.VerifyDiagnostics() End Sub + + + Public Sub With_RegionAnalysisRefIndexer() + Dim comp1 = CreateCSharpCompilation( +"public class C +{ + private T _p; + public ref T this[int i] + { + get { return ref _p; } + } +}") + comp1.VerifyDiagnostics() + Dim comp2 = CreateVisualBasicCompilation( + Nothing, +" +Public Class LocalDeclConversionError + Private Structure SomeStruct + Dim SomeField As Integer + Dim Text As String + End Structure + + Dim lst As New C(Of SomeStruct) + + Sub S() + Dim s As String + + With lst(0) + .SomeField = 5 + s = .Text + End With + End Sub +End Class +", + referencedCompilations:={comp1}, + compilationOptions:=TestOptions.DebugDll) + + comp2.AssertTheseEmitDiagnostics() + + Dim tree = comp2.SyntaxTrees(0) + Dim model = comp2.GetSemanticModel(tree) + Dim syntax = tree.GetRoot().DescendantNodes().OfType(Of Syntax.MethodBlockBaseSyntax).Single() + + Dim methodFlow = model.AnalyzeDataFlow(syntax.Statements.First(), syntax.Statements.Last()) + Assert.True(methodFlow.Succeeded) + Assert.Equal("[Me]", GetSymbolNamesJoined(methodFlow.ReadInside)) + Assert.Equal("[s]", GetSymbolNamesJoined(methodFlow.AlwaysAssigned)) + Assert.Equal(Nothing, GetSymbolNamesJoined(methodFlow.Captured)) + Assert.Equal("[Me]", GetSymbolNamesJoined(methodFlow.DataFlowsIn)) + Assert.Equal(Nothing, GetSymbolNamesJoined(methodFlow.DataFlowsOut)) + Assert.Equal("[Me]", GetSymbolNamesJoined(methodFlow.DefinitelyAssignedOnEntry)) + Assert.Equal("[Me], [s]", GetSymbolNamesJoined(methodFlow.DefinitelyAssignedOnExit)) + Assert.Equal(Nothing, GetSymbolNamesJoined(methodFlow.ReadOutside)) + Assert.Equal("[s]", GetSymbolNamesJoined(methodFlow.VariablesDeclared)) + Assert.Equal("[s]", GetSymbolNamesJoined(methodFlow.WrittenInside)) + Assert.Equal("[Me]", GetSymbolNamesJoined(methodFlow.WrittenOutside)) + End Sub + + + + Public Sub With_RegionAnalysisRefProperty() + Dim comp1 = CreateCSharpCompilation( +"public class C +{ + private T _p; + public ref T P + { + get { return ref _p; } + } +}") + comp1.VerifyDiagnostics() + Dim comp2 = CreateVisualBasicCompilation( + Nothing, +" +Public Class LocalDeclConversionError + Private Structure SomeStruct + Dim SomeField As Integer + Dim Text As String + End Structure + + Dim lst As New C(Of SomeStruct) + + Sub S() + Dim s As String + + With lst.P + .SomeField = 5 + s = .Text + End With + End Sub +End Class +", + referencedCompilations:={comp1}, + compilationOptions:=TestOptions.DebugDll) + + comp2.AssertTheseEmitDiagnostics() + + Dim tree = comp2.SyntaxTrees(0) + Dim model = comp2.GetSemanticModel(tree) + Dim syntax = tree.GetRoot().DescendantNodes().OfType(Of Syntax.MethodBlockBaseSyntax).Single() + + Dim methodFlow = model.AnalyzeDataFlow(syntax.Statements.First(), syntax.Statements.Last()) + Assert.True(methodFlow.Succeeded) + Assert.Equal("[Me]", GetSymbolNamesJoined(methodFlow.ReadInside)) + Assert.Equal("[s]", GetSymbolNamesJoined(methodFlow.AlwaysAssigned)) + Assert.Equal(Nothing, GetSymbolNamesJoined(methodFlow.Captured)) + Assert.Equal("[Me]", GetSymbolNamesJoined(methodFlow.DataFlowsIn)) + Assert.Equal(Nothing, GetSymbolNamesJoined(methodFlow.DataFlowsOut)) + Assert.Equal("[Me]", GetSymbolNamesJoined(methodFlow.DefinitelyAssignedOnEntry)) + Assert.Equal("[Me], [s]", GetSymbolNamesJoined(methodFlow.DefinitelyAssignedOnExit)) + Assert.Equal(Nothing, GetSymbolNamesJoined(methodFlow.ReadOutside)) + Assert.Equal("[s]", GetSymbolNamesJoined(methodFlow.VariablesDeclared)) + Assert.Equal("[s]", GetSymbolNamesJoined(methodFlow.WrittenInside)) + Assert.Equal("[Me]", GetSymbolNamesJoined(methodFlow.WrittenOutside)) + End Sub + + + + Public Sub With_RegionAnalysisRefMethod() + Dim comp1 = CreateCSharpCompilation( +"public class C +{ + private T _p; + public ref T GetP() + { + return ref _p; + } +}") + comp1.VerifyDiagnostics() + Dim comp2 = CreateVisualBasicCompilation( + Nothing, +" +Public Class LocalDeclConversionError + Private Structure SomeStruct + Dim SomeField As Integer + Dim Text As String + End Structure + + Dim lst As New C(Of SomeStruct) + + Sub S() + Dim s As String + + With lst.GetP() + .SomeField = 5 + s = .Text + End With + End Sub +End Class +", + referencedCompilations:={comp1}, + compilationOptions:=TestOptions.DebugDll) + + comp2.AssertTheseEmitDiagnostics() + + Dim tree = comp2.SyntaxTrees(0) + Dim model = comp2.GetSemanticModel(tree) + Dim syntax = tree.GetRoot().DescendantNodes().OfType(Of Syntax.MethodBlockBaseSyntax).Single() + + Dim methodFlow = model.AnalyzeDataFlow(syntax.Statements.First(), syntax.Statements.Last()) + Assert.True(methodFlow.Succeeded) + Assert.Equal("[Me]", GetSymbolNamesJoined(methodFlow.ReadInside)) + Assert.Equal("[s]", GetSymbolNamesJoined(methodFlow.AlwaysAssigned)) + Assert.Equal(Nothing, GetSymbolNamesJoined(methodFlow.Captured)) + Assert.Equal("[Me]", GetSymbolNamesJoined(methodFlow.DataFlowsIn)) + Assert.Equal(Nothing, GetSymbolNamesJoined(methodFlow.DataFlowsOut)) + Assert.Equal("[Me]", GetSymbolNamesJoined(methodFlow.DefinitelyAssignedOnEntry)) + Assert.Equal("[Me], [s]", GetSymbolNamesJoined(methodFlow.DefinitelyAssignedOnExit)) + Assert.Equal(Nothing, GetSymbolNamesJoined(methodFlow.ReadOutside)) + Assert.Equal("[s]", GetSymbolNamesJoined(methodFlow.VariablesDeclared)) + Assert.Equal("[s]", GetSymbolNamesJoined(methodFlow.WrittenInside)) + Assert.Equal("[Me]", GetSymbolNamesJoined(methodFlow.WrittenOutside)) + End Sub + + Protected Shared Function GetSymbolNamesJoined(Of T As ISymbol)(symbols As IEnumerable(Of T)) As String + Return If(Not symbols.IsEmpty(), String.Join(", ", symbols.Select(Function(symbol) "[" + symbol.Name + "]")), Nothing) + End Function + End Class End Namespace