Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
4faa3b39
R
roslyn
项目概览
lwm1986
/
roslyn
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
roslyn
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
4faa3b39
编写于
12月 07, 2020
作者:
F
Fred Silberberg
提交者:
GitHub
12月 07, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Handle passing a function pointer ref through a ref returning method (#49526)
上级
1afc0cf9
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
345 addition
and
0 deletion
+345
-0
src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs
src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs
+23
-0
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs
.../CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs
+322
-0
未找到文件。
src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs
浏览文件 @
4faa3b39
...
...
@@ -2292,6 +2292,29 @@ internal static bool CheckRefEscape(SyntaxNode node, BoundExpression expr, uint
diagnostics
,
isRefEscape
:
true
);
case
BoundKind
.
FunctionPointerInvocation
:
var
functionPointerInvocation
=
(
BoundFunctionPointerInvocation
)
expr
;
FunctionPointerMethodSymbol
signature
=
functionPointerInvocation
.
FunctionPointer
.
Signature
;
if
(
signature
.
RefKind
==
RefKind
.
None
)
{
break
;
}
return
CheckInvocationEscape
(
functionPointerInvocation
.
Syntax
,
signature
,
functionPointerInvocation
.
InvokedExpression
,
signature
.
Parameters
,
functionPointerInvocation
.
Arguments
,
functionPointerInvocation
.
ArgumentRefKindsOpt
,
argsToParamsOpt
:
default
,
checkingReceiver
,
escapeFrom
,
escapeTo
,
diagnostics
,
isRefEscape
:
true
);
case
BoundKind
.
PropertyAccess
:
var
propertyAccess
=
(
BoundPropertyAccess
)
expr
;
var
propertySymbol
=
propertyAccess
.
PropertySymbol
;
...
...
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs
浏览文件 @
4faa3b39
...
...
@@ -10677,6 +10677,328 @@ .maxstack 4
"
);
}
[
Fact
,
WorkItem
(
49315
,
"https://github.com/dotnet/roslyn/issues/49315"
)]
public
void
ReturnByRefFromRefReturningMethod
()
{
var
verifier
=
CompileAndVerifyFunctionPointers
(
@"
unsafe
{
int i = 1;
ref int iRef = ref ReturnPtrByRef(&ReturnByRef, ref i);
iRef = 2;
System.Console.WriteLine(i);
static ref int ReturnPtrByRef(delegate*<ref int, ref int> ptr, ref int i)
=> ref ptr(ref i);
static ref int ReturnByRef(ref int i) => ref i;
}"
,
expectedOutput
:
"2"
);
verifier
.
VerifyIL
(
"<Program>$.<<Main>$>g__ReturnPtrByRef|0_0(delegate*<ref int, int>, ref int)"
,
@"
{
// Code size 10 (0xa)
.maxstack 2
.locals init (delegate*<ref int, ref int> V_0)
IL_0000: ldarg.0
IL_0001: stloc.0
IL_0002: ldarg.1
IL_0003: ldloc.0
IL_0004: calli ""delegate*<ref int, ref int>""
IL_0009: ret
}
"
);
}
[
Fact
,
WorkItem
(
49315
,
"https://github.com/dotnet/roslyn/issues/49315"
)]
public
void
ReturnByRefFromRefReturningMethod_FunctionPointerDoesNotReturnByRefError
()
{
var
comp
=
CreateCompilationWithFunctionPointers
(
@"
unsafe
{
int i = 1;
ref int iRef = ref ReturnPtrByRef(&ReturnByRef, ref i);
static ref int ReturnPtrByRef(delegate*<ref int, int> ptr, ref int i)
=> ref ptr(ref i);
static int ReturnByRef(ref int i) => i;
}"
,
options
:
TestOptions
.
UnsafeReleaseExe
);
comp
.
VerifyDiagnostics
(
// (8,16): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
// => ref ptr(ref i);
Diagnostic
(
ErrorCode
.
ERR_RefReturnLvalueExpected
,
"ptr(ref i)"
).
WithLocation
(
8
,
16
)
);
}
[
Fact
,
WorkItem
(
49315
,
"https://github.com/dotnet/roslyn/issues/49315"
)]
public
void
ReturnByRefFromRefReturningMethod_NotSafeToEscape
()
{
var
comp
=
CreateCompilationWithSpan
(
@"
using System;
unsafe
{
ref Span<int> spanRef = ref ReturnPtrByRef(&ReturnByRef);
static ref Span<int> ReturnPtrByRef(delegate*<ref Span<int>, ref Span<int>> ptr)
{
Span<int> span = stackalloc int[1];
return ref ptr(ref span);
}
static ref Span<int> ReturnByRef(ref Span<int> i) => ref i;
}"
,
options
:
TestOptions
.
UnsafeReleaseExe
);
comp
.
VerifyDiagnostics
(
// (10,20): error CS8347: Cannot use a result of 'delegate*<ref Span<int>, Span<int>>' in this context because it may expose variables referenced by parameter '' outside of their declaration scope
// return ref ptr(ref span);
Diagnostic
(
ErrorCode
.
ERR_EscapeCall
,
"ptr(ref span)"
).
WithArguments
(
"delegate*<ref System.Span<int>, System.Span<int>>"
,
""
).
WithLocation
(
10
,
20
),
// (10,28): error CS8168: Cannot return local 'span' by reference because it is not a ref local
// return ref ptr(ref span);
Diagnostic
(
ErrorCode
.
ERR_RefReturnLocal
,
"span"
).
WithArguments
(
"span"
).
WithLocation
(
10
,
28
)
);
}
[
Fact
,
WorkItem
(
49315
,
"https://github.com/dotnet/roslyn/issues/49315"
)]
public
void
ReturnByRefFromRefReturningMethod_SafeToEscape
()
{
var
comp
=
CreateCompilationWithSpan
(
@"
using System;
unsafe
{
Span<int> s = stackalloc int[1];
s[0] = 1;
ref Span<int> sRef = ref ReturnPtrByRef(&ReturnByRef, ref s);
sRef[0] = 2;
Console.WriteLine(s[0]);
static ref Span<int> ReturnPtrByRef(delegate*<ref Span<int>, ref Span<int>> ptr, ref Span<int> s)
=> ref ptr(ref s);
static ref Span<int> ReturnByRef(ref Span<int> i) => ref i;
}"
,
options
:
TestOptions
.
UnsafeReleaseExe
);
var
verifier
=
CompileAndVerify
(
comp
,
expectedOutput
:
"2"
,
verify
:
Verification
.
Skipped
);
verifier
.
VerifyIL
(
"<Program>$.<<Main>$>g__ReturnPtrByRef|0_0(delegate*<ref System.Span<int>, System.Span<int>>, ref System.Span<int>)"
,
@"
{
// Code size 10 (0xa)
.maxstack 2
.locals init (delegate*<ref System.Span<int>, ref System.Span<int>> V_0)
IL_0000: ldarg.0
IL_0001: stloc.0
IL_0002: ldarg.1
IL_0003: ldloc.0
IL_0004: calli ""delegate*<ref System.Span<int>, ref System.Span<int>>""
IL_0009: ret
}
"
);
}
[
Fact
,
WorkItem
(
49315
,
"https://github.com/dotnet/roslyn/issues/49315"
)]
public
void
ReturnByRefFromRefReturningMethod_RefReadonlyToRefError
()
{
var
comp
=
CreateCompilationWithFunctionPointers
(
@"
unsafe
{
int i = 1;
ref int iRef = ref ReturnPtrByRef(&ReturnByRef, ref i);
static ref int ReturnPtrByRef(delegate*<ref int, ref readonly int> ptr, ref int i)
=> ref ptr(ref i);
static ref readonly int ReturnByRef(ref int i) => ref i;
}"
,
options
:
TestOptions
.
UnsafeReleaseExe
);
comp
.
VerifyDiagnostics
(
// (8,16): error CS8333: Cannot return method 'delegate*<ref int, int>' by writable reference because it is a readonly variable
// => ref ptr(ref i);
Diagnostic
(
ErrorCode
.
ERR_RefReturnReadonlyNotField
,
"ptr(ref i)"
).
WithArguments
(
"method"
,
"delegate*<ref int, int>"
).
WithLocation
(
8
,
16
)
);
}
[
Fact
,
WorkItem
(
49315
,
"https://github.com/dotnet/roslyn/issues/49315"
)]
public
void
ReturnByRefFromRefReturningMethod_RefToRefReadonly
()
{
var
verifier
=
CompileAndVerifyFunctionPointers
(
@"
unsafe
{
int i = 1;
ref readonly int iRef = ref ReturnPtrByRef(&ReturnByRef, ref i);
i = 2;
System.Console.WriteLine(iRef);
static ref readonly int ReturnPtrByRef(delegate*<ref int, ref int> ptr, ref int i)
=> ref ptr(ref i);
static ref int ReturnByRef(ref int i) => ref i;
}"
,
expectedOutput
:
"2"
);
verifier
.
VerifyIL
(
"<Program>$.<<Main>$>g__ReturnPtrByRef|0_0(delegate*<ref int, int>, ref int)"
,
@"
{
// Code size 10 (0xa)
.maxstack 2
.locals init (delegate*<ref int, ref int> V_0)
IL_0000: ldarg.0
IL_0001: stloc.0
IL_0002: ldarg.1
IL_0003: ldloc.0
IL_0004: calli ""delegate*<ref int, ref int>""
IL_0009: ret
}
"
);
}
[
Fact
,
WorkItem
(
49315
,
"https://github.com/dotnet/roslyn/issues/49315"
)]
public
void
RefAssignment
()
{
var
verifier
=
CompileAndVerifyFunctionPointers
(
@"
unsafe
{
int i = 1;
delegate*<ref int, ref int> ptr = &ReturnByRef;
ref readonly int iRef = ref ptr(ref i);
i = 2;
System.Console.WriteLine(iRef);
static ref int ReturnByRef(ref int i) => ref i;
}"
,
expectedOutput
:
"2"
);
verifier
.
VerifyIL
(
"<top-level-statements-entry-point>"
,
@"
{
// Code size 26 (0x1a)
.maxstack 2
.locals init (int V_0, //i
delegate*<ref int, ref int> V_1)
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldftn ""ref int <Program>$.<<Main>$>g__ReturnByRef|0_0(ref int)""
IL_0008: stloc.1
IL_0009: ldloca.s V_0
IL_000b: ldloc.1
IL_000c: calli ""delegate*<ref int, ref int>""
IL_0011: ldc.i4.2
IL_0012: stloc.0
IL_0013: ldind.i4
IL_0014: call ""void System.Console.WriteLine(int)""
IL_0019: ret
}
"
);
}
[
Fact
,
WorkItem
(
49315
,
"https://github.com/dotnet/roslyn/issues/49315"
)]
public
void
RefAssignmentThroughTernary
()
{
var
verifier
=
CompileAndVerifyFunctionPointers
(
@"
unsafe
{
int i = 1;
int i2 = 3;
delegate*<ref int, ref int> ptr = &ReturnByRef;
ref readonly int iRef = ref false ? ref i2 : ref ptr(ref i);
i = 2;
System.Console.WriteLine(iRef);
static ref int ReturnByRef(ref int i) => ref i;
}"
,
expectedOutput
:
"2"
);
verifier
.
VerifyIL
(
"<top-level-statements-entry-point>"
,
@"
{
// Code size 26 (0x1a)
.maxstack 2
.locals init (int V_0, //i
delegate*<ref int, ref int> V_1)
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldftn ""ref int <Program>$.<<Main>$>g__ReturnByRef|0_0(ref int)""
IL_0008: stloc.1
IL_0009: ldloca.s V_0
IL_000b: ldloc.1
IL_000c: calli ""delegate*<ref int, ref int>""
IL_0011: ldc.i4.2
IL_0012: stloc.0
IL_0013: ldind.i4
IL_0014: call ""void System.Console.WriteLine(int)""
IL_0019: ret
}
"
);
}
[
Fact
,
WorkItem
(
49315
,
"https://github.com/dotnet/roslyn/issues/49315"
)]
public
void
RefReturnThroughTernary
()
{
var
verifier
=
CompileAndVerifyFunctionPointers
(
@"
unsafe
{
int i = 1;
int i2 = 3;
ref int iRef = ref ReturnPtrByRef(&ReturnByRef, ref i, ref i2);
iRef = 2;
System.Console.WriteLine(i);
static ref int ReturnPtrByRef(delegate*<ref int, ref int> ptr, ref int i, ref int i2)
=> ref false ? ref i2 : ref ptr(ref i);
static ref int ReturnByRef(ref int i) => ref i;
}"
,
expectedOutput
:
"2"
);
verifier
.
VerifyIL
(
"<Program>$.<<Main>$>g__ReturnPtrByRef|0_0(delegate*<ref int, int>, ref int, ref int)"
,
@"
{
// Code size 10 (0xa)
.maxstack 2
.locals init (delegate*<ref int, ref int> V_0)
IL_0000: ldarg.0
IL_0001: stloc.0
IL_0002: ldarg.1
IL_0003: ldloc.0
IL_0004: calli ""delegate*<ref int, ref int>""
IL_0009: ret
}
"
);
}
[
Fact
,
WorkItem
(
49315
,
"https://github.com/dotnet/roslyn/issues/49315"
)]
public
void
PassedAsByRefParameter
()
{
var
verifier
=
CompileAndVerifyFunctionPointers
(
@"
unsafe
{
int i = 1;
delegate*<ref int, ref int> ptr = &ReturnByRef;
ref readonly int iRef = ref ptr(ref ptr(ref i));
i = 2;
System.Console.WriteLine(iRef);
static ref int ReturnByRef(ref int i) => ref i;
}"
,
expectedOutput
:
"2"
);
verifier
.
VerifyIL
(
"<top-level-statements-entry-point>"
,
@"
{
// Code size 34 (0x22)
.maxstack 2
.locals init (int V_0, //i
delegate*<ref int, ref int> V_1,
delegate*<ref int, ref int> V_2)
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldftn ""ref int <Program>$.<<Main>$>g__ReturnByRef|0_0(ref int)""
IL_0008: dup
IL_0009: stloc.1
IL_000a: stloc.2
IL_000b: ldloca.s V_0
IL_000d: ldloc.2
IL_000e: calli ""delegate*<ref int, ref int>""
IL_0013: ldloc.1
IL_0014: calli ""delegate*<ref int, ref int>""
IL_0019: ldc.i4.2
IL_001a: stloc.0
IL_001b: ldind.i4
IL_001c: call ""void System.Console.WriteLine(int)""
IL_0021: ret
}
"
);
}
private
static
readonly
Guid
s_guid
=
new
Guid
(
"97F4DBD4-F6D1-4FAD-91B3-1001F92068E5"
);
private
static
readonly
BlobContentId
s_contentId
=
new
BlobContentId
(
s_guid
,
0x04030201
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录