Addressed more PR feedback.

上级 631e421a
...@@ -1462,10 +1462,12 @@ protected override void AfterLeftChildHasBeenVisited(BoundBinaryOperator binary) ...@@ -1462,10 +1462,12 @@ protected override void AfterLeftChildHasBeenVisited(BoundBinaryOperator binary)
if (operandComparedToNull.Type?.IsReferenceType == true) if (operandComparedToNull.Type?.IsReferenceType == true)
{ {
var slotBuilder = ArrayBuilder<int>.GetInstance(); var slotBuilder = ArrayBuilder<int>.GetInstance();
// Set all nested conditional slots. For example in a?.b?.c we'll set a, b, and c
getOperandSlots(operandComparedToNull, slotBuilder); getOperandSlots(operandComparedToNull, slotBuilder);
Normalize(ref this.State);
if (slotBuilder.Count != 0) if (slotBuilder.Count != 0)
{ {
Normalize(ref this.State);
Split(); Split();
ref LocalState state = ref (op == BinaryOperatorKind.Equal) ? ref this.StateWhenFalse : ref this.StateWhenTrue; ref LocalState state = ref (op == BinaryOperatorKind.Equal) ? ref this.StateWhenFalse : ref this.StateWhenTrue;
foreach (int slot in slotBuilder) foreach (int slot in slotBuilder)
...@@ -1536,13 +1538,15 @@ void getOperandSlots(BoundExpression operand, ArrayBuilder<int> slotBuilder) ...@@ -1536,13 +1538,15 @@ void getOperandSlots(BoundExpression operand, ArrayBuilder<int> slotBuilder)
// c.D has been invoked, c must be nonnull or we've thrown a NullRef), revisit whether // c.D has been invoked, c must be nonnull or we've thrown a NullRef), revisit whether
// we need more special handling here // we need more special handling here
// If we're in this case, then all previous BoundCondtionalReceivers must have been handled.
Debug.Assert(_lastConditionalAccessSlot == -1);
slot = MakeSlot(operand); slot = MakeSlot(operand);
if (slot > 0) if (slot > 0)
{ {
// If we got a slot then all previous BoundCondtionalReceivers must have been handled.
Debug.Assert(_lastConditionalAccessSlot == -1);
slotBuilder.Add(slot); slotBuilder.Add(slot);
} }
break; break;
} }
......
...@@ -11756,7 +11756,7 @@ void Test1(C? c1) ...@@ -11756,7 +11756,7 @@ void Test1(C? c1)
} }
else else
{ {
c1._cField.ToString(); // warn c1._cField.ToString(); // warn 1 2
} }
} }
...@@ -11769,7 +11769,7 @@ void Test2() ...@@ -11769,7 +11769,7 @@ void Test2()
} }
else else
{ {
c2._cField.ToString(); // warn x2 c2._cField.ToString(); // warn 3 4
} }
} }
...@@ -11782,11 +11782,11 @@ void Test3(C? c3) ...@@ -11782,11 +11782,11 @@ void Test3(C? c3)
else if (c3?._cField != null) else if (c3?._cField != null)
{ {
c3._cField.ToString(); c3._cField.ToString();
c3._cField._cField.ToString(); // warn c3._cField._cField.ToString(); // warn 5
} }
else else
{ {
c3.ToString(); // warn c3.ToString(); // warn 6
} }
} }
...@@ -11798,7 +11798,7 @@ void Test4(C? c4) ...@@ -11798,7 +11798,7 @@ void Test4(C? c4)
} }
else else
{ {
c4._nonNullCField._cField._nonNullCField._cField.ToString(); // warn x3 c4._nonNullCField._cField._nonNullCField._cField.ToString(); // warn 7 8 9
} }
} }
...@@ -11806,7 +11806,7 @@ void Test5(C? c5) ...@@ -11806,7 +11806,7 @@ void Test5(C? c5)
{ {
if (c5?._cField == null) if (c5?._cField == null)
{ {
c5._cField.ToString(); // warn x2 c5._cField.ToString(); // warn 10 11
} }
else else
{ {
...@@ -11818,7 +11818,7 @@ void Test6(C? c6) ...@@ -11818,7 +11818,7 @@ void Test6(C? c6)
{ {
if (c6?._cField?.GetC() != null) if (c6?._cField?.GetC() != null)
{ {
c6._cField.GetC().ToString(); // warn c6._cField.GetC().ToString(); // warn 12
} }
} }
...@@ -11834,45 +11834,46 @@ void Test7(C? c7) ...@@ -11834,45 +11834,46 @@ void Test7(C? c7)
compilation.VerifyDiagnostics( compilation.VerifyDiagnostics(
// (17,13): warning CS8602: Possible dereference of a null reference. // (17,13): warning CS8602: Possible dereference of a null reference.
// c1._cField.ToString(); // warn // c1._cField.ToString(); // warn 1 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1").WithLocation(17, 13), Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1").WithLocation(17, 13),
// (17,13): warning CS8602: Possible dereference of a null reference. // (17,13): warning CS8602: Possible dereference of a null reference.
// c1._cField.ToString(); // warn // c1._cField.ToString(); // warn 1 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1._cField").WithLocation(17, 13), Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1._cField").WithLocation(17, 13),
// (30,13): warning CS8602: Possible dereference of a null reference. // (30,13): warning CS8602: Possible dereference of a null reference.
// c2._cField.ToString(); // warn x2 // c2._cField.ToString(); // warn 3 4
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2").WithLocation(30, 13), Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2").WithLocation(30, 13),
// (30,13): warning CS8602: Possible dereference of a null reference. // (30,13): warning CS8602: Possible dereference of a null reference.
// c2._cField.ToString(); // warn x2 // c2._cField.ToString(); // warn 3 4
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2._cField").WithLocation(30, 13), Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2._cField").WithLocation(30, 13),
// (43,13): warning CS8602: Possible dereference of a null reference. // (43,13): warning CS8602: Possible dereference of a null reference.
// c3._cField._cField.ToString(); // warn // c3._cField._cField.ToString(); // warn 5
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c3._cField._cField").WithLocation(43, 13), Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c3._cField._cField").WithLocation(43, 13),
// (47,13): warning CS8602: Possible dereference of a null reference. // (47,13): warning CS8602: Possible dereference of a null reference.
// c3.ToString(); // warn // c3.ToString(); // warn 6
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c3").WithLocation(47, 13), Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c3").WithLocation(47, 13),
// (59,13): warning CS8602: Possible dereference of a null reference. // (59,13): warning CS8602: Possible dereference of a null reference.
// c4._nonNullCField._cField._nonNullCField._cField.ToString(); // warn x3 // c4._nonNullCField._cField._nonNullCField._cField.ToString(); // warn 7 8 9
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c4").WithLocation(59, 13), Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c4").WithLocation(59, 13),
// (59,13): warning CS8602: Possible dereference of a null reference. // (59,13): warning CS8602: Possible dereference of a null reference.
// c4._nonNullCField._cField._nonNullCField._cField.ToString(); // warn x3 // c4._nonNullCField._cField._nonNullCField._cField.ToString(); // warn 7 8 9
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c4._nonNullCField._cField").WithLocation(59, 13), Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c4._nonNullCField._cField").WithLocation(59, 13),
// (59,13): warning CS8602: Possible dereference of a null reference. // (59,13): warning CS8602: Possible dereference of a null reference.
// c4._nonNullCField._cField._nonNullCField._cField.ToString(); // warn x3 // c4._nonNullCField._cField._nonNullCField._cField.ToString(); // warn 7 8 9
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c4._nonNullCField._cField._nonNullCField._cField").WithLocation(59, 13), Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c4._nonNullCField._cField._nonNullCField._cField").WithLocation(59, 13),
// (67,13): warning CS8602: Possible dereference of a null reference. // (67,13): warning CS8602: Possible dereference of a null reference.
// c5._cField.ToString(); // warn x2 // c5._cField.ToString(); // warn 10 11
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c5").WithLocation(67, 13), Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c5").WithLocation(67, 13),
// (67,13): warning CS8602: Possible dereference of a null reference. // (67,13): warning CS8602: Possible dereference of a null reference.
// c5._cField.ToString(); // warn x2 // c5._cField.ToString(); // warn 10 11
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c5._cField").WithLocation(67, 13), Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c5._cField").WithLocation(67, 13),
// (79,13): warning CS8602: Possible dereference of a null reference. // (79,13): warning CS8602: Possible dereference of a null reference.
// c6._cField.GetC().ToString(); // warn // c6._cField.GetC().ToString(); // warn 12
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c6._cField.GetC()").WithLocation(79, 13) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c6._cField.GetC()").WithLocation(79, 13)
); );
} }
...@@ -11888,11 +11889,11 @@ void Test(C? c1) ...@@ -11888,11 +11889,11 @@ void Test(C? c1)
if (c1?[0] != null) if (c1?[0] != null)
{ {
c1.ToString(); c1.ToString();
c1[0].ToString(); // warn c1[0].ToString(); // warn 1
} }
else else
{ {
c1.ToString(); // warn c1.ToString(); // warn 2
} }
} }
...@@ -11902,14 +11903,75 @@ void Test(C? c1) ...@@ -11902,14 +11903,75 @@ void Test(C? c1)
compilation.VerifyDiagnostics( compilation.VerifyDiagnostics(
// (9,13): warning CS8602: Possible dereference of a null reference. // (9,13): warning CS8602: Possible dereference of a null reference.
// c1[0].ToString(); // warn // c1[0].ToString(); // warn 1
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1[0]").WithLocation(9, 13), Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1[0]").WithLocation(9, 13),
// (13,13): warning CS8602: Possible dereference of a null reference. // (13,13): warning CS8602: Possible dereference of a null reference.
// c1.ToString(); // warn // c1.ToString(); // warn 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1").WithLocation(13, 13) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1").WithLocation(13, 13)
); );
} }
[Fact]
public void ConditionalBranching_16()
{
var compilation = CreateCompilation(@"
class C
{
void Test<T>(T t)
{
if (t?.ToString() != null)
{
t.ToString();
}
else
{
t.ToString(); // warn
}
}
}", parseOptions: TestOptions.Regular8);
// PROTOTYPE(NullableReferenceTypes): We are currently warning on all unconstrained type parameter invocations
// https://github.com/dotnet/roslyn/issues/28792
compilation.VerifyDiagnostics(
// (6,13): warning CS8602: Possible dereference of a null reference.
// if (t?.ToString() != null)
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(6, 13),
// (8,13): warning CS8602: Possible dereference of a null reference.
// t.ToString();
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(8, 13),
// (12,13): warning CS8602: Possible dereference of a null reference.
// t.ToString(); // warn
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(12, 13)
);
}
[Fact]
public void ConditionalBranching_17()
{
var compilation = CreateCompilation(@"
class C
{
object? Prop { get; }
object? GetObj(bool val) => null;
void Test(C? c1, C? c2)
{
if (c1?.GetObj(c2?.Prop != null) != null)
{
c2.Prop.ToString(); // warn 1 2
}
}
}", parseOptions: TestOptions.Regular8);
compilation.VerifyDiagnostics(
// (10,13): warning CS8602: Possible dereference of a null reference.
// c2.Prop.ToString(); // warn 1 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2").WithLocation(10, 13),
// (10,13): warning CS8602: Possible dereference of a null reference.
// c2.Prop.ToString(); // warn 1 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2.Prop").WithLocation(10, 13)
);
}
[Fact] [Fact]
public void ConditionalOperator_01() public void ConditionalOperator_01()
{ {
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册