未验证 提交 4a668d2b 编写于 作者: J Jared Parsons 提交者: GitHub

Merge pull request #28118 from OmarTawfik/bugs/28087/ref-array-crash

Ref-assigning to array elements should produce an error
......@@ -370,32 +370,41 @@ internal bool CheckValueKind(SyntaxNode node, BoundExpression expr, BindValueKin
}
break;
// array elements and pointer dereferencing are readwrite variables
case BoundKind.ArrayAccess:
case BoundKind.PointerIndirectionOperator:
// array elements and pointer dereferencing are readwrite variables
return true;
// The undocumented __refvalue(tr, T) expression results in a variable of type T.
case BoundKind.RefValueOperator:
// dynamic expressions are readwrite, and can even be passed by ref (which is implemented via a temp)
case BoundKind.DynamicMemberAccess:
case BoundKind.DynamicIndexerAccess:
{
if (RequiresRefAssignableVariable(valueKind))
{
Error(diagnostics, ErrorCode.ERR_RefLocalOrParamExpected, node);
return false;
}
// These are readwrite variables
return true;
}
case BoundKind.PointerElementAccess:
{
if (RequiresRefAssignableVariable(valueKind))
{
Error(diagnostics, ErrorCode.ERR_RefLocalOrParamExpected, node);
return false;
}
var receiver = ((BoundPointerElementAccess)expr).Expression;
if (receiver is BoundFieldAccess fieldAccess && fieldAccess.FieldSymbol.IsFixed)
{
return CheckValueKind(node, fieldAccess.ReceiverOpt, valueKind, checkingReceiver: true, diagnostics);
}
}
return true;
case BoundKind.RefValueOperator:
// The undocumented __refvalue(tr, T) expression results in a variable of type T.
// it is a readwrite variable.
return true;
case BoundKind.DynamicMemberAccess:
case BoundKind.DynamicIndexerAccess:
// dynamic expressions can be read and written to
// can even be passed by reference (which is implemented via a temp)
return true;
return true;
}
case BoundKind.Parameter:
var parameter = (BoundParameter)expr;
......
......@@ -3836,28 +3836,105 @@ public void M(ref int x)
}
[Fact]
[WorkItem(26978, "https://github.com/dotnet/roslyn/issues/26978")]
public void BindingRefDynamicObjAssignment()
[WorkItem(28087, "https://github.com/dotnet/roslyn/issues/28087")]
public void AssigningRef_ArrayElement()
{
CompileAndVerify(@"
using System;
class C
CreateCompilation(@"
public class C
{
public int P;
public void M(int[] array, ref int value)
{
array[0] = ref value;
}
}").VerifyDiagnostics(
// (6,9): error CS8373: The left-hand side of a ref assignment must be a ref local or parameter.
// array[0] = ref value;
Diagnostic(ErrorCode.ERR_RefLocalOrParamExpected, "array[0]").WithLocation(6, 9));
}
static void Main()
[Fact]
[WorkItem(28087, "https://github.com/dotnet/roslyn/issues/28087")]
public void AssigningRef_PointerIndirectionOperator()
{
CreateCompilation(@"
public unsafe class C
{
public void M(int* ptr, ref int value)
{
dynamic x = new C();
x.P = 5;
Console.WriteLine(x.P);
dynamic y = new C();
y.P = ref x.P;
Console.WriteLine(y.P);
*ptr = ref value;
}
}", options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (6,9): error CS8373: The left-hand side of a ref assignment must be a ref local or parameter.
// *ptr = ref value;
Diagnostic(ErrorCode.ERR_RefLocalOrParamExpected, "*ptr").WithLocation(6, 9));
}
[Fact]
[WorkItem(28087, "https://github.com/dotnet/roslyn/issues/28087")]
public void AssigningRef_PointerElementAccess()
{
CreateCompilation(@"
public unsafe class C
{
public void M(int* ptr, ref int value)
{
ptr[0] = ref value;
}
}", options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (6,9): error CS8373: The left-hand side of a ref assignment must be a ref local or parameter.
// ptr[0] = ref value;
Diagnostic(ErrorCode.ERR_RefLocalOrParamExpected, "ptr[0]").WithLocation(6, 9));
}
[Fact]
[WorkItem(28087, "https://github.com/dotnet/roslyn/issues/28087")]
public void AssigningRef_RefvalueExpression()
{
CreateCompilation(@"
public unsafe class C
{
public void M(int x)
{
__refvalue(__makeref(x), int) = ref x;
}
}", options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (6,9): error CS8373: The left-hand side of a ref assignment must be a ref local or parameter.
// __refvalue(__makeref(x), int) = ref x;
Diagnostic(ErrorCode.ERR_RefLocalOrParamExpected, "__refvalue(__makeref(x), int)").WithLocation(6, 9));
}
[Fact]
[WorkItem(28087, "https://github.com/dotnet/roslyn/issues/28087")]
public void AssigningRef_DynamicIndexerAccess()
{
CreateCompilation(@"
public unsafe class C
{
public void M(dynamic d, ref int value)
{
d[0] = ref value;
}
}", options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (6,9): error CS8373: The left-hand side of a ref assignment must be a ref local or parameter.
// d[0] = ref value;
Diagnostic(ErrorCode.ERR_RefLocalOrParamExpected, "d[0]").WithLocation(6, 9));
}
[Fact]
[WorkItem(28087, "https://github.com/dotnet/roslyn/issues/28087")]
public void AssigningRef_DynamicMemberAccess()
{
CreateCompilation(@"
public unsafe class C
{
public void M(dynamic d, ref int value)
{
d.member = ref value;
}
}", references: new[] { CSharpRef }, expectedOutput: @"
5
5");
}", options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (6,9): error CS8373: The left-hand side of a ref assignment must be a ref local or parameter.
// d.member = ref value;
Diagnostic(ErrorCode.ERR_RefLocalOrParamExpected, "d.member").WithLocation(6, 9));
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册