未验证 提交 5bb48dbd 编写于 作者: C Charles Stoner 提交者: GitHub

Set null state on dereference (#30564)

上级 c20eae14
......@@ -1354,6 +1354,8 @@ public override BoundNode VisitArrayAccess(BoundArrayAccess node)
Debug.Assert(!IsConditionalState);
Debug.Assert(!node.Expression.Type.IsValueType);
// https://github.com/dotnet/roslyn/issues/30598: Mark receiver as not null
// after indices have been visited, and only if the receiver has not changed.
CheckPossibleNullReceiver(node.Expression);
var type = _resultType.TypeSymbol as ArrayTypeSymbol;
......@@ -1943,6 +1945,8 @@ public override BoundNode VisitCall(BoundCall node)
if (receiverOpt != null && method.MethodKind != MethodKind.Constructor)
{
VisitRvalue(receiverOpt);
// https://github.com/dotnet/roslyn/issues/30598: Mark receiver as not null
// after arguments have been visited, and only if the receiver has not changed.
CheckPossibleNullReceiver(receiverOpt);
// Update method based on inferred receiver type: see https://github.com/dotnet/roslyn/issues/29605.
}
......@@ -3303,6 +3307,10 @@ public override BoundNode VisitMethodGroup(BoundMethodGroup node)
if (receiverOpt != null)
{
VisitRvalue(receiverOpt);
// https://github.com/dotnet/roslyn/issues/30563: Should not check receiver here.
// That check should be handled when applying the method group conversion,
// when we have a specific method, to avoid reporting null receiver warnings
// for extension method delegates.
CheckPossibleNullReceiver(receiverOpt);
}
......@@ -3672,6 +3680,8 @@ public override BoundNode VisitIndexerAccess(BoundIndexerAccess node)
{
var receiverOpt = node.ReceiverOpt;
VisitRvalue(receiverOpt);
// https://github.com/dotnet/roslyn/issues/30598: Mark receiver as not null
// after indices have been visited, and only if the receiver has not changed.
CheckPossibleNullReceiver(receiverOpt);
// https://github.com/dotnet/roslyn/issues/29964 Update indexer based on inferred receiver type.
......@@ -3698,6 +3708,8 @@ private void VisitMemberAccess(BoundExpression receiverOpt, Symbol member, bool
if (!member.IsStatic)
{
member = AsMemberOfResultType(member);
// https://github.com/dotnet/roslyn/issues/30598: For l-values, mark receiver as not null
// after RHS has been visited, and only if the receiver has not changed.
CheckPossibleNullReceiver(receiverOpt);
}
......@@ -4206,6 +4218,8 @@ public override BoundNode VisitEventAssignmentOperator(BoundEventAssignmentOpera
var receiverOpt = node.ReceiverOpt;
if (!node.Event.IsStatic)
{
// https://github.com/dotnet/roslyn/issues/30598: Mark receiver as not null
// after arguments have been visited, and only if the receiver has not changed.
CheckPossibleNullReceiver(receiverOpt);
}
VisitRvalue(node.Argument);
......@@ -4294,6 +4308,8 @@ public override BoundNode VisitDynamicIndexerAccess(BoundDynamicIndexerAccess no
{
var receiver = node.ReceiverOpt;
VisitRvalue(receiver);
// https://github.com/dotnet/roslyn/issues/30598: Mark receiver as not null
// after indices have been visited, and only if the receiver has not changed.
CheckPossibleNullReceiver(receiver);
VisitArgumentsEvaluate(node.Arguments, node.ArgumentRefKindsOpt);
......@@ -4309,6 +4325,7 @@ public override BoundNode VisitDynamicIndexerAccess(BoundDynamicIndexerAccess no
private void CheckPossibleNullReceiver(BoundExpression receiverOpt)
{
Debug.Assert(!this.IsConditionalState);
if (receiverOpt != null && this.State.Reachable)
{
#if DEBUG
......@@ -4320,6 +4337,11 @@ private void CheckPossibleNullReceiver(BoundExpression receiverOpt)
!resultType.IsValueType)
{
ReportDiagnostic(ErrorCode.WRN_NullReferenceReceiver, receiverOpt.Syntax);
int slot = MakeSlot(receiverOpt);
if (slot > 0)
{
this.State[slot] = true;
}
}
}
}
......
......@@ -312,7 +312,7 @@ protected override bool ConvertInsufficientExecutionStackExceptionToCancelledByS
/// <summary>
/// A pending branch. These are created for a return, break, continue, goto statement,
/// yield return, yield break, await expression, await foreach/using, and if PreciseAbstractFlowPass.trackExceptions
/// yield return, yield break, await expression, await foreach/using, and if PreciseAbstractFlowPass._trackExceptions
/// is true for other
/// constructs that can cause an exception to be raised such as a throw statement or method
/// invocation.
......
......@@ -25,7 +25,7 @@ internal sealed class CSharpConvertForEachToForCodeRefactoringProvider :
protected override ForEachStatementSyntax GetForEachStatement(TextSpan selection, SyntaxToken token)
{
var foreachStatement = token.Parent.FirstAncestorOrSelf<ForEachStatementSyntax>();
// PROTOTYPE(async-streams): Add tests for this scenario
// https://github.com/dotnet/roslyn/issues/30584: Add tests for this scenario
if (foreachStatement == null || foreachStatement.AwaitKeyword != default)
{
return null;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册