Skip to content

Commit

Permalink
Fix null ref exception in Symbol.CanBeReferencedByName for VB (#71253)
Browse files Browse the repository at this point in the history
Fixes #71115.
  • Loading branch information
AlekseyTs authored Dec 14, 2023
1 parent 01173c5 commit 3560634
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
6 changes: 4 additions & 2 deletions src/Compilers/VisualBasic/Portable/Symbols/Symbol.vb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
178 changes: 178 additions & 0 deletions src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenRefReturnTests.vb
Original file line number Diff line number Diff line change
Expand Up @@ -3593,6 +3593,184 @@ End Module",
verifier.VerifyDiagnostics()
End Sub

<Fact>
<WorkItem("https://github.com/dotnet/roslyn/issues/71115")>
Public Sub With_RegionAnalysisRefIndexer()
Dim comp1 = CreateCSharpCompilation(
"public class C<T>
{
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

<Fact>
<WorkItem("https://github.com/dotnet/roslyn/issues/71115")>
Public Sub With_RegionAnalysisRefProperty()
Dim comp1 = CreateCSharpCompilation(
"public class C<T>
{
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

<Fact>
<WorkItem("https://github.com/dotnet/roslyn/issues/71115")>
Public Sub With_RegionAnalysisRefMethod()
Dim comp1 = CreateCSharpCompilation(
"public class C<T>
{
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

0 comments on commit 3560634

Please sign in to comment.