Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
82c5af62
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,发现更多精彩内容 >>
未验证
提交
82c5af62
编写于
9月 11, 2020
作者:
M
msftbot[bot]
提交者:
GitHub
9月 11, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #47608 from dotnet/merges/release/dev16.8-to-master
Merge release/dev16.8 to master
上级
ed9c6976
bb891054
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
191 addition
and
33 deletion
+191
-33
src/Compilers/CSharp/Portable/Lowering/SpillSequenceSpiller.cs
...ompilers/CSharp/Portable/Lowering/SpillSequenceSpiller.cs
+37
-33
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncSpillTests.cs
...pilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncSpillTests.cs
+97
-0
src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenAsyncTests.vb
...pilers/VisualBasic/Test/Emit/CodeGen/CodeGenAsyncTests.vb
+57
-0
未找到文件。
src/Compilers/CSharp/Portable/Lowering/SpillSequenceSpiller.cs
浏览文件 @
82c5af62
...
...
@@ -734,42 +734,46 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node)
BoundExpression
fieldWithSpilledReceiver
(
BoundFieldAccess
field
,
ref
BoundSpillSequenceBuilder
leftBuilder
,
bool
isAssignmentTarget
)
{
BoundExpression
receiver
;
var
generateDummyFieldAccess
=
false
;
if
(
field
.
FieldSymbol
.
ContainingType
.
IsReferenceType
)
if
(
!
field
.
FieldSymbol
.
IsStatic
)
{
// a reference type can always live across await so Spill using leftBuilder
receiver
=
Spill
(
leftBuilder
,
VisitExpression
(
ref
leftBuilder
,
field
.
ReceiverOpt
));
// dummy field access to trigger NRE
// a.b = c will trigger a NRE if a is null on assignment,
// but a.b.c = d will trigger a NRE if a is null before evaluating d
// so check whether we assign to the field directly
generateDummyFieldAccess
=
!
isAssignmentTarget
;
}
else
if
(
field
.
ReceiverOpt
is
BoundArrayAccess
arrayAccess
)
{
// an arrayAccess returns a ref so can only be called after the await, but spill expression and indices
var
expression
=
VisitExpression
(
ref
leftBuilder
,
arrayAccess
.
Expression
);
expression
=
Spill
(
leftBuilder
,
expression
,
RefKind
.
None
);
var
indices
=
this
.
VisitExpressionList
(
ref
leftBuilder
,
arrayAccess
.
Indices
,
forceSpill
:
true
);
receiver
=
arrayAccess
.
Update
(
expression
,
indices
,
arrayAccess
.
Type
);
// dummy array access to trigger IndexOutRangeException or NRE
// we only need this if the array access is a receiver since
// a[0] = b triggers a NRE/IORE on assignment
// but a[0].b = c triggers an NRE/IORE before evaluating c
Spill
(
leftBuilder
,
receiver
,
sideEffectsOnly
:
true
);
}
else
if
(
field
.
ReceiverOpt
is
BoundFieldAccess
receiverField
)
{
receiver
=
fieldWithSpilledReceiver
(
receiverField
,
ref
leftBuilder
,
isAssignmentTarget
:
false
);
}
else
{
receiver
=
Spill
(
leftBuilder
,
VisitExpression
(
ref
leftBuilder
,
field
.
ReceiverOpt
),
RefKind
.
Ref
);
}
Debug
.
Assert
(
field
.
ReceiverOpt
is
object
);
BoundExpression
receiver
;
if
(
field
.
FieldSymbol
.
ContainingType
.
IsReferenceType
)
{
// a reference type can always live across await so Spill using leftBuilder
receiver
=
Spill
(
leftBuilder
,
VisitExpression
(
ref
leftBuilder
,
field
.
ReceiverOpt
));
// dummy field access to trigger NRE
// a.b = c will trigger a NRE if a is null on assignment,
// but a.b.c = d will trigger a NRE if a is null before evaluating d
// so check whether we assign to the field directly
generateDummyFieldAccess
=
!
isAssignmentTarget
;
}
else
if
(
field
.
ReceiverOpt
is
BoundArrayAccess
arrayAccess
)
{
// an arrayAccess returns a ref so can only be called after the await, but spill expression and indices
var
expression
=
VisitExpression
(
ref
leftBuilder
,
arrayAccess
.
Expression
);
expression
=
Spill
(
leftBuilder
,
expression
,
RefKind
.
None
);
var
indices
=
this
.
VisitExpressionList
(
ref
leftBuilder
,
arrayAccess
.
Indices
,
forceSpill
:
true
);
receiver
=
arrayAccess
.
Update
(
expression
,
indices
,
arrayAccess
.
Type
);
// dummy array access to trigger IndexOutRangeException or NRE
// we only need this if the array access is a receiver since
// a[0] = b triggers a NRE/IORE on assignment
// but a[0].b = c triggers an NRE/IORE before evaluating c
Spill
(
leftBuilder
,
receiver
,
sideEffectsOnly
:
true
);
}
else
if
(
field
.
ReceiverOpt
is
BoundFieldAccess
receiverField
)
{
receiver
=
fieldWithSpilledReceiver
(
receiverField
,
ref
leftBuilder
,
isAssignmentTarget
:
false
);
}
else
{
receiver
=
Spill
(
leftBuilder
,
VisitExpression
(
ref
leftBuilder
,
field
.
ReceiverOpt
),
RefKind
.
Ref
);
}
field
=
field
.
Update
(
receiver
,
field
.
FieldSymbol
,
field
.
ConstantValueOpt
,
field
.
ResultKind
,
field
.
Type
);
field
=
field
.
Update
(
receiver
,
field
.
FieldSymbol
,
field
.
ConstantValueOpt
,
field
.
ResultKind
,
field
.
Type
);
}
if
(
generateDummyFieldAccess
)
{
...
...
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncSpillTests.cs
浏览文件 @
82c5af62
...
...
@@ -6319,5 +6319,102 @@ .maxstack 3
IL_009e: ret
}"
);
}
[
Fact
,
WorkItem
(
47191
,
"https://github.com/dotnet/roslyn/issues/47191"
)]
public
void
AssignStaticStructField
()
{
var
source
=
@"
using System;
using System.Threading.Tasks;
public struct S1
{
public int Field;
}
public class C
{
public static S1 s1;
static async Task M(Task<int> t)
{
s1.Field = await t;
}
static async Task Main()
{
await M(Task.FromResult(1));
Console.Write(s1.Field);
}
}"
;
var
verifier
=
CompileAndVerify
(
source
,
expectedOutput
:
"1"
);
verifier
.
VerifyDiagnostics
();
}
[
Fact
,
WorkItem
(
47191
,
"https://github.com/dotnet/roslyn/issues/47191"
)]
public
void
AssignStaticStructField_ViaUsingStatic
()
{
var
source
=
@"
using System;
using System.Threading.Tasks;
using static C;
public struct S1
{
public int Field;
}
public class C
{
public static S1 s1;
}
public class Program
{
static async Task M(Task<int> t)
{
s1.Field = await t;
}
static async Task Main()
{
await M(Task.FromResult(1));
Console.Write(s1.Field);
}
}
"
;
var
verifier
=
CompileAndVerify
(
source
,
expectedOutput
:
"1"
);
verifier
.
VerifyDiagnostics
();
}
[
Fact
,
WorkItem
(
47191
,
"https://github.com/dotnet/roslyn/issues/47191"
)]
public
void
AssignInstanceStructField
()
{
var
source
=
@"
using System;
using System.Threading.Tasks;
public struct S1
{
public int Field;
}
public class C
{
public S1 s1;
async Task M(Task<int> t)
{
s1.Field = await t;
}
static async Task Main()
{
var c = new C();
await c.M(Task.FromResult(1));
Console.Write(c.s1.Field);
}
}"
;
var
verifier
=
CompileAndVerify
(
source
,
expectedOutput
:
"1"
);
verifier
.
VerifyDiagnostics
();
}
}
}
src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenAsyncTests.vb
浏览文件 @
82c5af62
...
...
@@ -11441,6 +11441,63 @@ After Invoke").VerifyIL("Program.VB$StateMachine_0_Invoke.MoveNext", "
IL_00d1
:
ret
}
")
End Sub
<Fact>
<WorkItem(47191, "
https
:
//
github
.
com
/
dotnet
/
roslyn
/
issues
/
47191
")>
Public Sub AssignModuleStructureField()
Dim source = "
Imports
System
Imports
System.Threading.Tasks
Public
Structure
S1
Public
Field
As
Integer
End
Structure
Module
Program
Dim
s1
As
S1
Async
Function
M1
(
t
As
Task
(
Of
Integer
))
As
Task
s1
.
Field
=
Await
t
End
Function
Sub
Main
()
M1
(
Task
.
FromResult
(
1
)).
Wait
()
Console
.
Write
(
s1
.
Field
)
End
Sub
End
Module
"
Dim compilation = CreateCompilation(source, options:=TestOptions.ReleaseExe)
CompileAndVerify(compilation, expectedOutput:="
1
")
End Sub
<Fact>
<WorkItem(47191, "
https
:
//
github
.
com
/
dotnet
/
roslyn
/
issues
/
47191
")>
Public Sub AssignInstanceStructureField()
Dim source = "
Imports
System
Imports
System.Threading.Tasks
Public
Structure
S1
Public
Field
As
Integer
End
Structure
Class
C
Dim
s1
As
S1
Async
Function
M1
(
t
As
Task
(
Of
Integer
))
As
Task
s1
.
Field
=
Await
t
End
Function
Shared
Sub
Main
()
Dim
c
=
New
C
()
c
.
M1
(
Task
.
FromResult
(
1
)).
Wait
()
Console
.
Write
(
c
.
s1
.
Field
)
End
Sub
End
Class
"
Dim compilation = CreateCompilation(source, options:=TestOptions.ReleaseExe)
CompileAndVerify(compilation, expectedOutput:="
1
")
End Sub
End Class
End Namespace
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录