From 3f256a7c9e3058c58d3b45d1abeb3fd85bb71434 Mon Sep 17 00:00:00 2001 From: Omar Tawfik Date: Tue, 6 Mar 2018 00:13:57 +0200 Subject: [PATCH] Support PointerElementAccess in value escape rules (#24909) --- .../Portable/Binder/Binder.ValueChecks.cs | 15 +++++- .../Semantic/Semantics/RefEscapingTests.cs | 51 +++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs index e499285c84a..f71d73a8a76 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs @@ -2185,6 +2185,11 @@ internal static uint GetValEscape(BoundExpression expr, uint scopeOfTheContainin // just say it does not escape anywhere, so that we do not get false errors. return scopeOfTheContainingExpression; + case BoundKind.PointerElementAccess: + case BoundKind.PointerIndirectionOperator: + // Unsafe code will always be allowed to escape. + return Binder.ExternalScope; + default: throw ExceptionUtilities.UnexpectedValue($"{expr.Kind} expression of {expr.Type} type"); } @@ -2492,13 +2497,19 @@ internal static bool CheckValEscape(SyntaxNode node, BoundExpression expr, uint var colElement = (BoundCollectionElementInitializer)expr; return CheckValEscape(colElement.Arguments, escapeFrom, escapeTo, diagnostics); + case BoundKind.PointerElementAccess: + var accessedExpression = ((BoundPointerElementAccess)expr).Expression; + return CheckValEscape(accessedExpression.Syntax, accessedExpression, escapeFrom, escapeTo, checkingReceiver, diagnostics); + + case BoundKind.PointerIndirectionOperator: + var operandExpression = ((BoundPointerIndirectionOperator)expr).Operand; + return CheckValEscape(operandExpression.Syntax, operandExpression, escapeFrom, escapeTo, checkingReceiver, diagnostics); + default: throw ExceptionUtilities.UnexpectedValue($"{expr.Kind} expression of {expr.Type} type"); #region "cannot produce ref-like values" // case BoundKind.ThrowExpression: -// case BoundKind.PointerIndirectionOperator: -// case BoundKind.PointerElementAccess: // case BoundKind.ArgListOperator: // case BoundKind.ArgList: // case BoundKind.RefTypeOperator: diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs index 065d96e616b..55c95f2dc96 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs @@ -3201,5 +3201,56 @@ public class C "; CreateCompilationWithMscorlibAndSpan(text).VerifyDiagnostics(); } + + [Fact] + [WorkItem(24776, "https://github.com/dotnet/roslyn/issues/24776")] + public void PointerElementAccess_RefStructPointer() + { + CreateCompilation(@" +public ref struct TestStruct +{ + public void M() { } +} +public class C +{ + public static unsafe void Test(TestStruct[] ar) + { + fixed (TestStruct* p = ar) + { + for (int i = 0; i < ar.Length; i++) + { + p[i].M(); + } + } + } +}", options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( + // (8,36): error CS0611: Array elements cannot be of type 'TestStruct' + // public static unsafe void Test(TestStruct[] ar) + Diagnostic(ErrorCode.ERR_ArrayElementCantBeRefAny, "TestStruct").WithArguments("TestStruct").WithLocation(8, 36)); + } + + [Fact] + [WorkItem(24776, "https://github.com/dotnet/roslyn/issues/24776")] + public void PointerIndirectionOperator_RefStructPointer() + { + CreateCompilation(@" +public ref struct TestStruct +{ + public void M() { } +} +public class C +{ + public static unsafe void Test(TestStruct[] ar) + { + fixed (TestStruct* p = ar) + { + var x = *p; + } + } +}", options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( + // (8,36): error CS0611: Array elements cannot be of type 'TestStruct' + // public static unsafe void Test(TestStruct[] ar) + Diagnostic(ErrorCode.ERR_ArrayElementCantBeRefAny, "TestStruct").WithArguments("TestStruct").WithLocation(8, 36)); + } } } -- GitLab