Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
404c680e
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,发现更多精彩内容 >>
未验证
提交
404c680e
编写于
11月 05, 2019
作者:
N
Neal Gafter
提交者:
GitHub
11月 05, 2019
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Evaluate tuple elements in a switch control expression in the order written (#39595)
Fixes #39564
上级
f1f2f517
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
192 addition
and
17 deletion
+192
-17
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs
...Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs
+7
-17
src/Compilers/CSharp/Test/Emit/CodeGen/SwitchTests.cs
src/Compilers/CSharp/Test/Emit/CodeGen/SwitchTests.cs
+185
-0
未找到文件。
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs
浏览文件 @
404c680e
...
...
@@ -491,10 +491,8 @@ bool usesOriginalInput(BoundDecisionDagNode node)
out
BoundExpression
savedInputExpression
)
{
int
count
=
loweredInput
.
Arguments
.
Length
;
var
tupleElementEvaluated
=
new
bool
[
count
];
var
rewrittenDag
=
decisionDag
.
Rewrite
(
makeReplacement
);
//
If any remaining input elements remain unevaluated, evaluate them now
//
first evaluate the inputs (in order) into temps
var
originalInput
=
BoundDagTemp
.
ForOriginalInput
(
loweredInput
.
Syntax
,
loweredInput
.
Type
);
var
newArguments
=
ArrayBuilder
<
BoundExpression
>.
GetInstance
(
loweredInput
.
Arguments
.
Length
);
for
(
int
i
=
0
;
i
<
count
;
i
++)
...
...
@@ -504,14 +502,11 @@ bool usesOriginalInput(BoundDecisionDagNode node)
var
expr
=
loweredInput
.
Arguments
[
i
];
var
fieldFetchEvaluation
=
new
BoundDagFieldEvaluation
(
expr
.
Syntax
,
field
,
originalInput
);
var
temp
=
new
BoundDagTemp
(
expr
.
Syntax
,
expr
.
Type
,
fieldFetchEvaluation
);
if
(!
tupleElementEvaluated
[
i
])
{
storeToTemp
(
temp
,
expr
);
}
storeToTemp
(
temp
,
expr
);
newArguments
.
Add
(
_tempAllocator
.
GetTemp
(
temp
));
}
var
rewrittenDag
=
decisionDag
.
Rewrite
(
makeReplacement
);
savedInputExpression
=
loweredInput
.
Update
(
loweredInput
.
Constructor
,
arguments
:
newArguments
.
ToImmutableAndFree
(),
loweredInput
.
ArgumentNamesOpt
,
loweredInput
.
ArgumentRefKindsOpt
,
loweredInput
.
Expanded
,
loweredInput
.
ArgsToParamsOpt
,
loweredInput
.
ConstantValueOpt
,
...
...
@@ -543,18 +538,13 @@ BoundDecisionDagNode makeReplacement(BoundDecisionDagNode node, Func<BoundDecisi
field
.
CorrespondingTupleField
!=
null
&&
field
.
TupleElementIndex
is
int
i
)
{
if
(!
tupleElementEvaluated
[
i
])
{
// Store the value in the right temp
var
temp
=
new
BoundDagTemp
(
eval
.
Syntax
,
field
.
Type
,
eval
);
BoundExpression
expr
=
loweredInput
.
Arguments
[
i
];
storeToTemp
(
temp
,
expr
);
tupleElementEvaluated
[
i
]
=
true
;
}
// The elements of an input tuple were evaluated beforehand, so don't need to be evaluated now.
return
replacement
(
evalNode
.
Next
);
}
// Since we are performing an optimization whose precondition is that the original
// input is not used except to get its elements, we can assert here that the original
// input is not used for anything else.
Debug
.
Assert
(!
evalNode
.
Evaluation
.
Input
.
IsOriginalInput
);
break
;
...
...
src/Compilers/CSharp/Test/Emit/CodeGen/SwitchTests.cs
浏览文件 @
404c680e
...
...
@@ -9409,6 +9409,191 @@ .maxstack 1
);
}
[
Fact
]
[
WorkItem
(
39564
,
"https://github.com/dotnet/roslyn/issues/39564"
)]
public
void
OrderOfEvaluationOfTupleAsSwitchExpressionArgument
()
{
var
source
=
@"using System;
class Program
{
public static void Main(string[] args)
{
using var sr = new System.IO.StringReader(""foo\nbar"");
var r = (sr.ReadLine(), sr.ReadLine()) switch
{
(""foo"", ""bar"") => ""Yep, all good!"",
var (a, b) => $""Wait, what? I got ({a}, {b})!"",
};
Console.WriteLine(r);
}
}
"
;
var
compilation
=
CreateCompilation
(
source
,
options
:
TestOptions
.
DebugExe
)
.
VerifyDiagnostics
();
var
compVerifier
=
CompileAndVerify
(
compilation
,
expectedOutput
:
"Yep, all good!"
);
compVerifier
.
VerifyIL
(
"Program.Main"
,
@" {
// Code size 142 (0x8e)
.maxstack 4
.locals init (System.IO.StringReader V_0, //sr
string V_1, //r
string V_2, //a
string V_3, //b
string V_4)
IL_0000: nop
IL_0001: ldstr ""foo
bar""
IL_0006: newobj ""System.IO.StringReader..ctor(string)""
IL_000b: stloc.0
.try
{
IL_000c: ldloc.0
IL_000d: callvirt ""string System.IO.TextReader.ReadLine()""
IL_0012: stloc.2
IL_0013: ldloc.0
IL_0014: callvirt ""string System.IO.TextReader.ReadLine()""
IL_0019: stloc.3
IL_001a: ldloc.2
IL_001b: brfalse.s IL_0045
IL_001d: ldloc.2
IL_001e: ldstr ""foo""
IL_0023: call ""bool string.op_Equality(string, string)""
IL_0028: brfalse.s IL_0045
IL_002a: ldloc.3
IL_002b: brfalse.s IL_0045
IL_002d: ldloc.3
IL_002e: ldstr ""bar""
IL_0033: call ""bool string.op_Equality(string, string)""
IL_0038: brtrue.s IL_003c
IL_003a: br.s IL_0045
IL_003c: ldstr ""Yep, all good!""
IL_0041: stloc.s V_4
IL_0043: br.s IL_0076
IL_0045: br.s IL_0047
IL_0047: ldc.i4.5
IL_0048: newarr ""string""
IL_004d: dup
IL_004e: ldc.i4.0
IL_004f: ldstr ""Wait, what? I got (""
IL_0054: stelem.ref
IL_0055: dup
IL_0056: ldc.i4.1
IL_0057: ldloc.2
IL_0058: stelem.ref
IL_0059: dup
IL_005a: ldc.i4.2
IL_005b: ldstr "", ""
IL_0060: stelem.ref
IL_0061: dup
IL_0062: ldc.i4.3
IL_0063: ldloc.3
IL_0064: stelem.ref
IL_0065: dup
IL_0066: ldc.i4.4
IL_0067: ldstr "")!""
IL_006c: stelem.ref
IL_006d: call ""string string.Concat(params string[])""
IL_0072: stloc.s V_4
IL_0074: br.s IL_0076
IL_0076: ldloc.s V_4
IL_0078: stloc.1
IL_0079: ldloc.1
IL_007a: call ""void System.Console.WriteLine(string)""
IL_007f: nop
IL_0080: leave.s IL_008d
}
finally
{
IL_0082: ldloc.0
IL_0083: brfalse.s IL_008c
IL_0085: ldloc.0
IL_0086: callvirt ""void System.IDisposable.Dispose()""
IL_008b: nop
IL_008c: endfinally
}
IL_008d: ret
}
"
);
compilation
=
CreateCompilation
(
source
,
options
:
TestOptions
.
ReleaseExe
)
.
VerifyDiagnostics
();
compVerifier
=
CompileAndVerify
(
compilation
,
expectedOutput
:
"Yep, all good!"
);
compVerifier
.
VerifyIL
(
"Program.Main"
,
@" {
// Code size 128 (0x80)
.maxstack 4
.locals init (System.IO.StringReader V_0, //sr
string V_1, //a
string V_2, //b
string V_3)
IL_0000: ldstr ""foo
bar""
IL_0005: newobj ""System.IO.StringReader..ctor(string)""
IL_000a: stloc.0
.try
{
IL_000b: ldloc.0
IL_000c: callvirt ""string System.IO.TextReader.ReadLine()""
IL_0011: stloc.1
IL_0012: ldloc.0
IL_0013: callvirt ""string System.IO.TextReader.ReadLine()""
IL_0018: stloc.2
IL_0019: ldloc.1
IL_001a: brfalse.s IL_0041
IL_001c: ldloc.1
IL_001d: ldstr ""foo""
IL_0022: call ""bool string.op_Equality(string, string)""
IL_0027: brfalse.s IL_0041
IL_0029: ldloc.2
IL_002a: brfalse.s IL_0041
IL_002c: ldloc.2
IL_002d: ldstr ""bar""
IL_0032: call ""bool string.op_Equality(string, string)""
IL_0037: brfalse.s IL_0041
IL_0039: ldstr ""Yep, all good!""
IL_003e: stloc.3
IL_003f: br.s IL_006d
IL_0041: ldc.i4.5
IL_0042: newarr ""string""
IL_0047: dup
IL_0048: ldc.i4.0
IL_0049: ldstr ""Wait, what? I got (""
IL_004e: stelem.ref
IL_004f: dup
IL_0050: ldc.i4.1
IL_0051: ldloc.1
IL_0052: stelem.ref
IL_0053: dup
IL_0054: ldc.i4.2
IL_0055: ldstr "", ""
IL_005a: stelem.ref
IL_005b: dup
IL_005c: ldc.i4.3
IL_005d: ldloc.2
IL_005e: stelem.ref
IL_005f: dup
IL_0060: ldc.i4.4
IL_0061: ldstr "")!""
IL_0066: stelem.ref
IL_0067: call ""string string.Concat(params string[])""
IL_006c: stloc.3
IL_006d: ldloc.3
IL_006e: call ""void System.Console.WriteLine(string)""
IL_0073: leave.s IL_007f
}
finally
{
IL_0075: ldloc.0
IL_0076: brfalse.s IL_007e
IL_0078: ldloc.0
IL_0079: callvirt ""void System.IDisposable.Dispose()""
IL_007e: endfinally
}
IL_007f: ret
}
"
);
}
#
endregion
"regression tests"
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录