Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
c99ad715
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,发现更多精彩内容 >>
提交
c99ad715
编写于
1月 09, 2020
作者:
R
Rikki Gibson
提交者:
GitHub
1月 09, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Revert "Improve the code gen for a conditional access on a readonly unconstrained field (#35979)"
This reverts commit
6b22ff18
.
上级
77728dcc
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
271 addition
and
795 deletion
+271
-795
src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
+26
-37
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenConditionalOperatorTests.cs
...harp/Test/Emit/CodeGen/CodeGenConditionalOperatorTests.cs
+0
-282
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenShortCircuitOperatorTests.cs
...arp/Test/Emit/CodeGen/CodeGenShortCircuitOperatorTests.cs
+38
-21
src/Compilers/CSharp/Test/WinRT/AnonymousTypesSymbolTests.cs
src/Compilers/CSharp/Test/WinRT/AnonymousTypesSymbolTests.cs
+142
-88
src/Compilers/VisualBasic/Portable/CodeGen/EmitExpression.vb
src/Compilers/VisualBasic/Portable/CodeGen/EmitExpression.vb
+25
-34
src/Compilers/VisualBasic/Test/Semantic/Semantics/ConditionalAccessTests.vb
...alBasic/Test/Semantic/Semantics/ConditionalAccessTests.vb
+40
-333
未找到文件。
src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
浏览文件 @
c99ad715
...
@@ -405,43 +405,32 @@ private void EmitLoweredConditionalAccessExpression(BoundLoweredConditionalAcces
...
@@ -405,43 +405,32 @@ private void EmitLoweredConditionalAccessExpression(BoundLoweredConditionalAcces
// if T happens to be a value type, it could be a target of mutating calls.
// if T happens to be a value type, it could be a target of mutating calls.
receiverTemp
=
EmitReceiverRef
(
receiver
,
AddressKind
.
Constrained
);
receiverTemp
=
EmitReceiverRef
(
receiver
,
AddressKind
.
Constrained
);
if
(
receiverTemp
is
null
)
// unconstrained case needs to handle case where T is actually a struct.
{
// such values are never nulls
// unconstrained case needs to handle case where T is actually a struct.
// we will emit a check for such case, but the check is really a JIT-time
// such values are never nulls
// constant since JIT will know if T is a struct or not.
// we will emit a check for such case, but the check is really a JIT-time
// constant since JIT will know if T is a struct or not.
// if ((object)default(T) != null)
// {
// if ((object)default(T) != null)
// goto whenNotNull
// {
// }
// goto whenNotNull
// else
// }
// {
// else
// temp = receiverRef
// {
// receiverRef = ref temp
// temp = receiverRef
// }
// receiverRef = ref temp
EmitDefaultValue
(
receiverType
,
true
,
receiver
.
Syntax
);
// }
EmitBox
(
receiverType
,
receiver
.
Syntax
);
EmitDefaultValue
(
receiverType
,
true
,
receiver
.
Syntax
);
_builder
.
EmitBranch
(
ILOpCode
.
Brtrue
,
whenNotNullLabel
);
EmitBox
(
receiverType
,
receiver
.
Syntax
);
EmitLoadIndirect
(
receiverType
,
receiver
.
Syntax
);
_builder
.
EmitBranch
(
ILOpCode
.
Brtrue
,
whenNotNullLabel
);
EmitLoadIndirect
(
receiverType
,
receiver
.
Syntax
);
cloneTemp
=
AllocateTemp
(
receiverType
,
receiver
.
Syntax
);
_builder
.
EmitLocalStore
(
cloneTemp
);
cloneTemp
=
AllocateTemp
(
receiverType
,
receiver
.
Syntax
);
_builder
.
EmitLocalAddress
(
cloneTemp
);
_builder
.
EmitLocalStore
(
cloneTemp
);
_builder
.
EmitLocalLoad
(
cloneTemp
);
_builder
.
EmitLocalAddress
(
cloneTemp
);
EmitBox
(
receiver
.
Type
,
receiver
.
Syntax
);
_builder
.
EmitLocalLoad
(
cloneTemp
);
EmitBox
(
receiverType
,
receiver
.
Syntax
);
// here we have loaded a ref to a temp and its boxed value { &T, O }
// here we have loaded a ref to a temp and its boxed value { &T, O }
}
else
{
// we are calling the expression on a copy of the target anyway,
// so even if T is a struct, we don't need to make sure we call the expression on the original target.
_builder
.
EmitLocalLoad
(
receiverTemp
);
EmitBox
(
receiverType
,
receiver
.
Syntax
);
}
}
}
else
else
{
{
...
...
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenConditionalOperatorTests.cs
浏览文件 @
c99ad715
...
@@ -2763,287 +2763,5 @@ .maxstack 1
...
@@ -2763,287 +2763,5 @@ .maxstack 1
IL_0064: ret
IL_0064: ret
}"
);
}"
);
}
}
[
Fact
]
[
WorkItem
(
3519
,
"https://github.com/dotnet/roslyn/issues/35319"
)]
public
void
ConditionalAccessUnconstrainedTField
()
{
var
source
=
@"using System;
public class C<T>
{
public C(T t) => this.t = t;
public C(){}
private T t;
public void Print()
{
Console.WriteLine(t?.ToString());
Console.WriteLine(t);
}
}
public struct S
{
int a;
public override string ToString() => a++.ToString();
}
public static class Program
{
public static void Main()
{
new C<S>().Print();
new C<S?>().Print();
new C<S?>(new S()).Print();
new C<string>(""hello"").Print();
new C<string>().Print();
}
}"
;
var
verify
=
CompileAndVerify
(
source
,
expectedOutput
:
@"0
1
0
0
hello
hello"
);
verify
.
VerifyIL
(
"C<T>.Print()"
,
@"
{
// Code size 75 (0x4b)
.maxstack 2
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: ldflda ""T C<T>.t""
IL_0006: ldloca.s V_0
IL_0008: initobj ""T""
IL_000e: ldloc.0
IL_000f: box ""T""
IL_0014: brtrue.s IL_002a
IL_0016: ldobj ""T""
IL_001b: stloc.0
IL_001c: ldloca.s V_0
IL_001e: ldloc.0
IL_001f: box ""T""
IL_0024: brtrue.s IL_002a
IL_0026: pop
IL_0027: ldnull
IL_0028: br.s IL_0035
IL_002a: constrained. ""T""
IL_0030: callvirt ""string object.ToString()""
IL_0035: call ""void System.Console.WriteLine(string)""
IL_003a: ldarg.0
IL_003b: ldfld ""T C<T>.t""
IL_0040: box ""T""
IL_0045: call ""void System.Console.WriteLine(object)""
IL_004a: ret
}"
);
}
[
Fact
]
[
WorkItem
(
3519
,
"https://github.com/dotnet/roslyn/issues/35319"
)]
public
void
ConditionalAccessReadonlyUnconstrainedTField
()
{
var
source
=
@"using System;
public class C<T>
{
public C(T t) => this.t = t;
public C(){}
readonly T t;
public void Print()
{
Console.WriteLine(t?.ToString());
Console.WriteLine(t);
}
}
public struct S
{
int a;
public override string ToString() => a++.ToString();
}
public static class Program
{
public static void Main()
{
new C<S>().Print();
new C<S?>().Print();
new C<S?>(new S()).Print();
new C<string>(""hello"").Print();
new C<string>().Print();
}
}
"
;
var
verify
=
CompileAndVerify
(
source
,
expectedOutput
:
@"0
0
0
0
hello
hello"
);
verify
.
VerifyIL
(
"C<T>.Print()"
,
@"
{
// Code size 54 (0x36)
.maxstack 2
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: ldfld ""T C<T>.t""
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0009: ldloc.0
IL_000a: box ""T""
IL_000f: brtrue.s IL_0015
IL_0011: pop
IL_0012: ldnull
IL_0013: br.s IL_0020
IL_0015: constrained. ""T""
IL_001b: callvirt ""string object.ToString()""
IL_0020: call ""void System.Console.WriteLine(string)""
IL_0025: ldarg.0
IL_0026: ldfld ""T C<T>.t""
IL_002b: box ""T""
IL_0030: call ""void System.Console.WriteLine(object)""
IL_0035: ret
}"
);
}
[
Fact
]
[
WorkItem
(
3519
,
"https://github.com/dotnet/roslyn/issues/35319"
)]
public
void
ConditionalAccessUnconstrainedTLocal
()
{
var
source
=
@"using System;
public class C<T>
{
public C(T t) => this.t = t;
public C(){}
private T t;
public void Print()
{
var temp = t;
Console.WriteLine(temp?.ToString());
Console.WriteLine(temp);
}
}
public struct S
{
int a;
public override string ToString() => a++.ToString();
}
public static class Program
{
public static void Main()
{
new C<S>().Print();
new C<S?>().Print();
new C<S?>(new S()).Print();
new C<string>(""hello"").Print();
new C<string>().Print();
}
}"
;
var
verify
=
CompileAndVerify
(
source
,
expectedOutput
:
@"0
1
0
1
hello
hello"
);
verify
.
VerifyIL
(
"C<T>.Print()"
,
@"
{
// Code size 48 (0x30)
.maxstack 1
.locals init (T V_0) //temp
IL_0000: ldarg.0
IL_0001: ldfld ""T C<T>.t""
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: box ""T""
IL_000d: brtrue.s IL_0012
IL_000f: ldnull
IL_0010: br.s IL_001f
IL_0012: ldloca.s V_0
IL_0014: constrained. ""T""
IL_001a: callvirt ""string object.ToString()""
IL_001f: call ""void System.Console.WriteLine(string)""
IL_0024: ldloc.0
IL_0025: box ""T""
IL_002a: call ""void System.Console.WriteLine(object)""
IL_002f: ret
}"
);
}
[
Fact
]
[
WorkItem
(
3519
,
"https://github.com/dotnet/roslyn/issues/35319"
)]
public
void
ConditionalAccessUnconstrainedTTemp
()
{
var
source
=
@"using System;
public class C<T>
{
public C(T t) => this.t = t;
public C(){}
T t;
T M() => t;
public void Print() => Console.WriteLine(M()?.ToString());
}
public static class Program
{
public static void Main()
{
new C<int>().Print();
new C<int?>().Print();
new C<int?>(0).Print();
new C<string>(""hello"").Print();
new C<string>().Print();
}
}
"
;
var
verify
=
CompileAndVerify
(
source
,
expectedOutput
:
@"0
0
hello
"
);
verify
.
VerifyIL
(
"C<T>.Print()"
,
@"
{
// Code size 38 (0x26)
.maxstack 2
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: call ""T C<T>.M()""
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0009: ldloc.0
IL_000a: box ""T""
IL_000f: brtrue.s IL_0015
IL_0011: pop
IL_0012: ldnull
IL_0013: br.s IL_0020
IL_0015: constrained. ""T""
IL_001b: callvirt ""string object.ToString()""
IL_0020: call ""void System.Console.WriteLine(string)""
IL_0025: ret
}"
);
}
}
}
}
}
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenShortCircuitOperatorTests.cs
浏览文件 @
c99ad715
...
@@ -2461,32 +2461,49 @@ static void Main(string[] args)
...
@@ -2461,32 +2461,49 @@ static void Main(string[] args)
False"
);
False"
);
comp
.
VerifyIL
(
"Program.Test<T>(System.Func<T>)"
,
@"
comp
.
VerifyIL
(
"Program.Test<T>(System.Func<T>)"
,
@"
{
{
// Code size
62 (0x3
e)
// Code size
110 (0x6
e)
.maxstack 2
.maxstack 2
.locals init (T V_0)
.locals init (T V_0,
T V_1)
IL_0000: ldarg.0
IL_0000: ldarg.0
IL_0001: callvirt ""T System.Func<T>.Invoke()""
IL_0001: callvirt ""T System.Func<T>.Invoke()""
IL_0006: stloc.0
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0007: ldloca.s V_0
IL_0009: ldloc.0
IL_0009: ldloca.s V_1
IL_000a: box ""T""
IL_000b: initobj ""T""
IL_000f: brtrue.s IL_0014
IL_0011: ldloc.1
IL_0011: pop
IL_0012: box ""T""
IL_0012: br.s IL_001f
IL_0017: brtrue.s IL_002c
IL_0014: constrained. ""T""
IL_0019: ldobj ""T""
IL_001a: callvirt ""void System.IDisposable.Dispose()""
IL_001e: stloc.1
IL_001f: ldarg.0
IL_001f: ldloca.s V_1
IL_0020: callvirt ""T System.Func<T>.Invoke()""
IL_0021: ldloc.1
IL_0025: stloc.0
IL_0022: box ""T""
IL_0026: ldloca.s V_0
IL_0027: brtrue.s IL_002c
IL_0028: ldloc.0
IL_0029: pop
IL_0029: box ""T""
IL_002a: br.s IL_0037
IL_002e: brtrue.s IL_0032
IL_002c: constrained. ""T""
IL_0030: pop
IL_0032: callvirt ""void System.IDisposable.Dispose()""
IL_0031: ret
IL_0037: ldarg.0
IL_0032: constrained. ""T""
IL_0038: callvirt ""T System.Func<T>.Invoke()""
IL_0038: callvirt ""void System.IDisposable.Dispose()""
IL_003d: stloc.0
IL_003d: ret
IL_003e: ldloca.s V_0
IL_0040: ldloca.s V_1
IL_0042: initobj ""T""
IL_0048: ldloc.1
IL_0049: box ""T""
IL_004e: brtrue.s IL_0062
IL_0050: ldobj ""T""
IL_0055: stloc.1
IL_0056: ldloca.s V_1
IL_0058: ldloc.1
IL_0059: box ""T""
IL_005e: brtrue.s IL_0062
IL_0060: pop
IL_0061: ret
IL_0062: constrained. ""T""
IL_0068: callvirt ""void System.IDisposable.Dispose()""
IL_006d: ret
}
}
"
);
"
);
}
}
...
...
src/Compilers/CSharp/Test/WinRT/AnonymousTypesSymbolTests.cs
浏览文件 @
c99ad715
...
@@ -424,11 +424,14 @@ .maxstack 3
...
@@ -424,11 +424,14 @@ .maxstack 3
).
VerifyIL
(
).
VerifyIL
(
"<>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.ToString"
,
"<>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.ToString"
,
@"{
@"{
// Code size 1
23 (0x7b
)
// Code size 1
99 (0xc7
)
.maxstack 7
.maxstack 7
.locals init (<Length>j__TPar V_0,
.locals init (<Length>j__TPar V_0,
<at1>j__TPar V_1,
<Length>j__TPar V_1,
<C>j__TPar V_2)
<at1>j__TPar V_2,
<at1>j__TPar V_3,
<C>j__TPar V_4,
<C>j__TPar V_5)
IL_0000: ldnull
IL_0000: ldnull
IL_0001: ldstr ""{{ Length = {0}, at1 = {1}, C = {2} }}""
IL_0001: ldstr ""{{ Length = {0}, at1 = {1}, C = {2} }}""
IL_0006: ldc.i4.3
IL_0006: ldc.i4.3
...
@@ -439,47 +442,71 @@ .maxstack 7
...
@@ -439,47 +442,71 @@ .maxstack 7
IL_000f: ldfld ""<Length>j__TPar <>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.<Length>i__Field""
IL_000f: ldfld ""<Length>j__TPar <>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.<Length>i__Field""
IL_0014: stloc.0
IL_0014: stloc.0
IL_0015: ldloca.s V_0
IL_0015: ldloca.s V_0
IL_0017: ldloc.0
IL_0017: ldloca.s V_1
IL_0018: box ""<Length>j__TPar""
IL_0019: initobj ""<Length>j__TPar""
IL_001d: brtrue.s IL_0023
IL_001f: ldloc.1
IL_001f: pop
IL_0020: box ""<Length>j__TPar""
IL_0020: ldnull
IL_0025: brtrue.s IL_003b
IL_0021: br.s IL_002e
IL_0027: ldobj ""<Length>j__TPar""
IL_0023: constrained. ""<Length>j__TPar""
IL_002c: stloc.1
IL_0029: callvirt ""string object.ToString()""
IL_002d: ldloca.s V_1
IL_002e: stelem.ref
IL_002f: ldloc.1
IL_002f: dup
IL_0030: box ""<Length>j__TPar""
IL_0030: ldc.i4.1
IL_0035: brtrue.s IL_003b
IL_0031: ldarg.0
IL_0037: pop
IL_0032: ldfld ""<at1>j__TPar <>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.<at1>i__Field""
IL_0038: ldnull
IL_0037: stloc.1
IL_0039: br.s IL_0046
IL_0038: ldloca.s V_1
IL_003b: constrained. ""<Length>j__TPar""
IL_003a: ldloc.1
IL_0041: callvirt ""string object.ToString()""
IL_003b: box ""<at1>j__TPar""
IL_0046: stelem.ref
IL_0040: brtrue.s IL_0046
IL_0047: dup
IL_0042: pop
IL_0048: ldc.i4.1
IL_0043: ldnull
IL_0049: ldarg.0
IL_0044: br.s IL_0051
IL_004a: ldfld ""<at1>j__TPar <>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.<at1>i__Field""
IL_0046: constrained. ""<at1>j__TPar""
IL_004f: stloc.2
IL_004c: callvirt ""string object.ToString()""
IL_0050: ldloca.s V_2
IL_0051: stelem.ref
IL_0052: ldloca.s V_3
IL_0052: dup
IL_0054: initobj ""<at1>j__TPar""
IL_0053: ldc.i4.2
IL_005a: ldloc.3
IL_0054: ldarg.0
IL_005b: box ""<at1>j__TPar""
IL_0055: ldfld ""<C>j__TPar <>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.<C>i__Field""
IL_0060: brtrue.s IL_0076
IL_005a: stloc.2
IL_0062: ldobj ""<at1>j__TPar""
IL_005b: ldloca.s V_2
IL_0067: stloc.3
IL_005d: ldloc.2
IL_0068: ldloca.s V_3
IL_005e: box ""<C>j__TPar""
IL_006a: ldloc.3
IL_0063: brtrue.s IL_0069
IL_006b: box ""<at1>j__TPar""
IL_0065: pop
IL_0070: brtrue.s IL_0076
IL_0066: ldnull
IL_0072: pop
IL_0067: br.s IL_0074
IL_0073: ldnull
IL_0069: constrained. ""<C>j__TPar""
IL_0074: br.s IL_0081
IL_006f: callvirt ""string object.ToString()""
IL_0076: constrained. ""<at1>j__TPar""
IL_0074: stelem.ref
IL_007c: callvirt ""string object.ToString()""
IL_0075: call ""string string.Format(System.IFormatProvider, string, params object[])""
IL_0081: stelem.ref
IL_007a: ret
IL_0082: dup
IL_0083: ldc.i4.2
IL_0084: ldarg.0
IL_0085: ldfld ""<C>j__TPar <>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.<C>i__Field""
IL_008a: stloc.s V_4
IL_008c: ldloca.s V_4
IL_008e: ldloca.s V_5
IL_0090: initobj ""<C>j__TPar""
IL_0096: ldloc.s V_5
IL_0098: box ""<C>j__TPar""
IL_009d: brtrue.s IL_00b5
IL_009f: ldobj ""<C>j__TPar""
IL_00a4: stloc.s V_5
IL_00a6: ldloca.s V_5
IL_00a8: ldloc.s V_5
IL_00aa: box ""<C>j__TPar""
IL_00af: brtrue.s IL_00b5
IL_00b1: pop
IL_00b2: ldnull
IL_00b3: br.s IL_00c0
IL_00b5: constrained. ""<C>j__TPar""
IL_00bb: callvirt ""string object.ToString()""
IL_00c0: stelem.ref
IL_00c1: call ""string string.Format(System.IFormatProvider, string, params object[])""
IL_00c6: ret
}"
}"
);
);
}
}
...
@@ -846,11 +873,14 @@ .maxstack 3
...
@@ -846,11 +873,14 @@ .maxstack 3
).
VerifyIL
(
).
VerifyIL
(
"<>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.ToString"
,
"<>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.ToString"
,
@"{
@"{
// Code size 1
23 (0x7b
)
// Code size 1
99 (0xc7
)
.maxstack 7
.maxstack 7
.locals init (<ToString>j__TPar V_0,
.locals init (<ToString>j__TPar V_0,
<Equals>j__TPar V_1,
<ToString>j__TPar V_1,
<GetHashCode>j__TPar V_2)
<Equals>j__TPar V_2,
<Equals>j__TPar V_3,
<GetHashCode>j__TPar V_4,
<GetHashCode>j__TPar V_5)
IL_0000: ldnull
IL_0000: ldnull
IL_0001: ldstr ""{{ ToString = {0}, Equals = {1}, GetHashCode = {2} }}""
IL_0001: ldstr ""{{ ToString = {0}, Equals = {1}, GetHashCode = {2} }}""
IL_0006: ldc.i4.3
IL_0006: ldc.i4.3
...
@@ -861,47 +891,71 @@ .maxstack 7
...
@@ -861,47 +891,71 @@ .maxstack 7
IL_000f: ldfld ""<ToString>j__TPar <>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.<ToString>i__Field""
IL_000f: ldfld ""<ToString>j__TPar <>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.<ToString>i__Field""
IL_0014: stloc.0
IL_0014: stloc.0
IL_0015: ldloca.s V_0
IL_0015: ldloca.s V_0
IL_0017: ldloc.0
IL_0017: ldloca.s V_1
IL_0018: box ""<ToString>j__TPar""
IL_0019: initobj ""<ToString>j__TPar""
IL_001d: brtrue.s IL_0023
IL_001f: ldloc.1
IL_001f: pop
IL_0020: box ""<ToString>j__TPar""
IL_0020: ldnull
IL_0025: brtrue.s IL_003b
IL_0021: br.s IL_002e
IL_0027: ldobj ""<ToString>j__TPar""
IL_0023: constrained. ""<ToString>j__TPar""
IL_002c: stloc.1
IL_0029: callvirt ""string object.ToString()""
IL_002d: ldloca.s V_1
IL_002e: stelem.ref
IL_002f: ldloc.1
IL_002f: dup
IL_0030: box ""<ToString>j__TPar""
IL_0030: ldc.i4.1
IL_0035: brtrue.s IL_003b
IL_0031: ldarg.0
IL_0037: pop
IL_0032: ldfld ""<Equals>j__TPar <>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.<Equals>i__Field""
IL_0038: ldnull
IL_0037: stloc.1
IL_0039: br.s IL_0046
IL_0038: ldloca.s V_1
IL_003b: constrained. ""<ToString>j__TPar""
IL_003a: ldloc.1
IL_0041: callvirt ""string object.ToString()""
IL_003b: box ""<Equals>j__TPar""
IL_0046: stelem.ref
IL_0040: brtrue.s IL_0046
IL_0047: dup
IL_0042: pop
IL_0048: ldc.i4.1
IL_0043: ldnull
IL_0049: ldarg.0
IL_0044: br.s IL_0051
IL_004a: ldfld ""<Equals>j__TPar <>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.<Equals>i__Field""
IL_0046: constrained. ""<Equals>j__TPar""
IL_004f: stloc.2
IL_004c: callvirt ""string object.ToString()""
IL_0050: ldloca.s V_2
IL_0051: stelem.ref
IL_0052: ldloca.s V_3
IL_0052: dup
IL_0054: initobj ""<Equals>j__TPar""
IL_0053: ldc.i4.2
IL_005a: ldloc.3
IL_0054: ldarg.0
IL_005b: box ""<Equals>j__TPar""
IL_0055: ldfld ""<GetHashCode>j__TPar <>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.<GetHashCode>i__Field""
IL_0060: brtrue.s IL_0076
IL_005a: stloc.2
IL_0062: ldobj ""<Equals>j__TPar""
IL_005b: ldloca.s V_2
IL_0067: stloc.3
IL_005d: ldloc.2
IL_0068: ldloca.s V_3
IL_005e: box ""<GetHashCode>j__TPar""
IL_006a: ldloc.3
IL_0063: brtrue.s IL_0069
IL_006b: box ""<Equals>j__TPar""
IL_0065: pop
IL_0070: brtrue.s IL_0076
IL_0066: ldnull
IL_0072: pop
IL_0067: br.s IL_0074
IL_0073: ldnull
IL_0069: constrained. ""<GetHashCode>j__TPar""
IL_0074: br.s IL_0081
IL_006f: callvirt ""string object.ToString()""
IL_0076: constrained. ""<Equals>j__TPar""
IL_0074: stelem.ref
IL_007c: callvirt ""string object.ToString()""
IL_0075: call ""string string.Format(System.IFormatProvider, string, params object[])""
IL_0081: stelem.ref
IL_007a: ret
IL_0082: dup
IL_0083: ldc.i4.2
IL_0084: ldarg.0
IL_0085: ldfld ""<GetHashCode>j__TPar <>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.<GetHashCode>i__Field""
IL_008a: stloc.s V_4
IL_008c: ldloca.s V_4
IL_008e: ldloca.s V_5
IL_0090: initobj ""<GetHashCode>j__TPar""
IL_0096: ldloc.s V_5
IL_0098: box ""<GetHashCode>j__TPar""
IL_009d: brtrue.s IL_00b5
IL_009f: ldobj ""<GetHashCode>j__TPar""
IL_00a4: stloc.s V_5
IL_00a6: ldloca.s V_5
IL_00a8: ldloc.s V_5
IL_00aa: box ""<GetHashCode>j__TPar""
IL_00af: brtrue.s IL_00b5
IL_00b1: pop
IL_00b2: ldnull
IL_00b3: br.s IL_00c0
IL_00b5: constrained. ""<GetHashCode>j__TPar""
IL_00bb: callvirt ""string object.ToString()""
IL_00c0: stelem.ref
IL_00c1: call ""string string.Format(System.IFormatProvider, string, params object[])""
IL_00c6: ret
}"
}"
).
VerifyIL
(
).
VerifyIL
(
"<>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.ToString.get"
,
"<>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.ToString.get"
,
...
...
src/Compilers/VisualBasic/Portable/CodeGen/EmitExpression.vb
浏览文件 @
c99ad715
...
@@ -288,43 +288,35 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen
...
@@ -288,43 +288,35 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen
Dim
nullCheckOnCopy
=
conditional
.
CaptureReceiver
OrElse
(
receiverType
.
IsReferenceType
AndAlso
receiverType
.
TypeKind
=
TypeKind
.
TypeParameter
)
Dim
nullCheckOnCopy
=
conditional
.
CaptureReceiver
OrElse
(
receiverType
.
IsReferenceType
AndAlso
receiverType
.
TypeKind
=
TypeKind
.
TypeParameter
)
If
nullCheckOnCopy
Then
If
nullCheckOnCopy
Then
receiverTemp
=
EmitReceiverRef
(
receiver
,
isAccessConstrained
:
=
Not
receiverType
.
IsReferenceType
,
addressKind
:
=
AddressKind
.
ReadOnly
)
EmitReceiverRef
(
receiver
,
isAccessConstrained
:
=
Not
receiverType
.
IsReferenceType
,
addressKind
:
=
AddressKind
.
ReadOnly
)
If
Not
receiverType
.
IsReferenceType
Then
If
Not
receiverType
.
IsReferenceType
Then
If
receiverTemp
Is
Nothing
Then
' unconstrained case needs to handle case where T Is actually a struct.
' unconstrained case needs to handle case where T Is actually a struct.
' such values are never nulls
' such values are never nulls
' we will emit a check for such case, but the check Is really a JIT-time
' we will emit a check for such case, but the check Is really a JIT-time
' constant since JIT will know if T Is a struct Or Not.
' constant since JIT will know if T Is a struct Or Not.
'
'
' if ((object)default(T) != null)
' if ((object)default(T) != null)
' {
' {
' goto whenNotNull
' goto whenNotNull
' }
' }
' else
' else
' {
' {
' temp = receiverRef
' temp = receiverRef
' receiverRef = ref temp
' receiverRef = ref temp
' }
' }
EmitInitObj
(
receiverType
,
True
,
receiver
.
Syntax
)
EmitInitObj
(
receiverType
,
True
,
receiver
.
Syntax
)
EmitBox
(
receiverType
,
receiver
.
Syntax
)
EmitBox
(
receiverType
,
receiver
.
Syntax
)
_builder
.
EmitBranch
(
ILOpCode
.
Brtrue
,
whenNotNullLabel
)
_builder
.
EmitBranch
(
ILOpCode
.
Brtrue
,
whenNotNullLabel
)
EmitLoadIndirect
(
receiverType
,
receiver
.
Syntax
)
EmitLoadIndirect
(
receiverType
,
receiver
.
Syntax
)
temp
=
AllocateTemp
(
receiverType
,
receiver
.
Syntax
)
_builder
.
EmitLocalStore
(
temp
)
_builder
.
EmitLocalAddress
(
temp
)
_builder
.
EmitLocalLoad
(
temp
)
EmitBox
(
receiverType
,
receiver
.
Syntax
)
' here we have loaded a ref to a temp And its boxed value { &T, O }
temp
=
AllocateTemp
(
receiverType
,
receiver
.
Syntax
)
Else
_builder
.
EmitLocalStore
(
temp
)
' we are calling the expression on a copy of the target anyway,
_builder
.
EmitLocalAddress
(
temp
)
' so even if T is a struct, we don't need to make sure we call the expression on the original target.
_builder
.
EmitLocalLoad
(
temp
)
EmitBox
(
receiver
.
Type
,
receiver
.
Syntax
)
_builder
.
EmitLocalLoad
(
receiverTemp
)
' here we have loaded a ref to a temp And its boxed value { &T, O }
EmitBox
(
receiverType
,
receiver
.
Syntax
)
End
If
Else
Else
_builder
.
EmitOpCode
(
ILOpCode
.
Dup
)
_builder
.
EmitOpCode
(
ILOpCode
.
Dup
)
' here we have loaded two copies of a reference { O, O }
' here we have loaded two copies of a reference { O, O }
...
@@ -368,7 +360,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen
...
@@ -368,7 +360,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen
_builder
.
MarkLabel
(
whenNotNullLabel
)
_builder
.
MarkLabel
(
whenNotNullLabel
)
If
Not
nullCheckOnCopy
Then
If
Not
nullCheckOnCopy
Then
Debug
.
Assert
(
receiverTemp
Is
Nothing
)
receiverTemp
=
EmitReceiverRef
(
receiver
,
isAccessConstrained
:
=
Not
receiverType
.
IsReferenceType
,
addressKind
:
=
AddressKind
.
ReadOnly
)
receiverTemp
=
EmitReceiverRef
(
receiver
,
isAccessConstrained
:
=
Not
receiverType
.
IsReferenceType
,
addressKind
:
=
AddressKind
.
ReadOnly
)
Debug
.
Assert
(
receiverTemp
Is
Nothing
OrElse
receiver
.
IsDefaultValue
())
Debug
.
Assert
(
receiverTemp
Is
Nothing
OrElse
receiver
.
IsDefaultValue
())
End
If
End
If
...
...
src/Compilers/VisualBasic/Test/Semantic/Semantics/ConditionalAccessTests.vb
浏览文件 @
c99ad715
...
@@ -613,23 +613,32 @@ Null
...
@@ -613,23 +613,32 @@ Null
verifier.VerifyIL("
Module1
.
Test8
",
verifier.VerifyIL("
Module1
.
Test8
",
<![CDATA[
<![CDATA[
{
{
// Code size
38 (0x26
)
// Code size
62 (0x3e
)
.maxstack 2
.maxstack 2
.locals init (T V_0)
.locals init (T V_0,
T V_1)
IL_0000: ldarg.0
IL_0000: ldarg.0
IL_0001: call "
Function
Module1
.
GetT
(
Of
T
)(
T
)
As
T
"
IL_0001: call "
Function
Module1
.
GetT
(
Of
T
)(
T
)
As
T
"
IL_0006: stloc.0
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0007: ldloca.s V_0
IL_0009: ldloc.0
IL_0009: ldloca.s V_1
IL_000a: box "
T
"
IL_000b: initobj "
T
"
IL_000f: brtrue.s IL_0015
IL_0011: ldloc.1
IL_0011: pop
IL_0012: box "
T
"
IL_0012: ldnull
IL_0017: brtrue.s IL_002d
IL_0013: br.s IL_0020
IL_0019: ldobj "
T
"
IL_0015: constrained. "
T
"
IL_001e: stloc.1
IL_001b: callvirt "
Function
I1
.
get_P2
()
As
String
"
IL_001f: ldloca.s V_1
IL_0020: call "
Sub
Module1
.
Do
(
Of
String
)(
String
)
"
IL_0021: ldloc.1
IL_0025: ret
IL_0022: box "
T
"
IL_0027: brtrue.s IL_002d
IL_0029: pop
IL_002a: ldnull
IL_002b: br.s IL_0038
IL_002d: constrained. "
T
"
IL_0033: callvirt "
Function
I1
.
get_P2
()
As
String
"
IL_0038: call "
Sub
Module1
.
Do
(
Of
String
)(
String
)
"
IL_003d: ret
}
}
]]>)
]]>)
...
@@ -3543,21 +3552,30 @@ Ext4 C1
...
@@ -3543,21 +3552,30 @@ Ext4 C1
verifier.VerifyIL("
Module1
.
Test1_6
",
verifier.VerifyIL("
Module1
.
Test1_6
",
<![CDATA[
<![CDATA[
{
{
// Code size
30 (0x1e
)
// Code size
54 (0x36
)
.maxstack 2
.maxstack 2
.locals init (T V_0)
.locals init (T V_0,
T V_1)
IL_0000: ldarg.0
IL_0000: ldarg.0
IL_0001: call "
Function
Module1
.
GetT
(
Of
T
)(
T
)
As
T
"
IL_0001: call "
Function
Module1
.
GetT
(
Of
T
)(
T
)
As
T
"
IL_0006: stloc.0
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0007: ldloca.s V_0
IL_0009: ldloc.0
IL_0009: ldloca.s V_1
IL_000a: box "
T
"
IL_000b: initobj "
T
"
IL_000f: brtrue.s IL_0013
IL_0011: ldloc.1
IL_0011: pop
IL_0012: box "
T
"
IL_0012: ret
IL_0017: brtrue.s IL_002b
IL_0013: ldobj "
T
"
IL_0019: ldobj "
T
"
IL_0018: call "
Sub
Module1
.
Ext1
(
Of
T
)(
T
)
"
IL_001e: stloc.1
IL_001d: ret
IL_001f: ldloca.s V_1
IL_0021: ldloc.1
IL_0022: box "
T
"
IL_0027: brtrue.s IL_002b
IL_0029: pop
IL_002a: ret
IL_002b: ldobj "
T
"
IL_0030: call "
Sub
Module1
.
Ext1
(
Of
T
)(
T
)
"
IL_0035: ret
}
}
]]>)
]]>)
...
@@ -5288,317 +5306,6 @@ C1
...
@@ -5288,317 +5306,6 @@ C1
]]>)
]]>)
End Sub
End Sub
<Fact>
<WorkItem(3519, "
https
:
//
github
.
com
/
dotnet
/
roslyn
/
issues
/
35319
")>
Public Sub CodeGen_ConditionalAccessUnconstrainedTField()
Dim c = CompileAndVerify(
<compilation>
<file name="
a
.
vb
">
Imports System
Public Class C(Of T)
Public Sub New(t As T)
field = t
End Sub
Public Sub New()
End Sub
Private field As T
Public Sub Print()
Console.WriteLine(field?.ToString())
Console.WriteLine(field)
End Sub
End Class
Public Structure S
Private a As Integer
Public Overrides Function ToString() As String
Dim result = a.ToString()
a = a + 1
Return result
End Function
End Structure
Module Program
Sub Main()
Call New C(Of S)().Print()
Call New C(Of S?)().Print()
Call New C(Of S?)(New S()).Print()
Call New C(Of String)("
hello
").Print()
Call New C(Of String)().Print()
End Sub
End Module
</file>
</compilation>, expectedOutput:="
0
1
0
0
hello
hello
")
c.VerifyIL("C
(
Of
T
).
Print
()
",
<![CDATA[
{
// Code size 75 (0x4b)
.maxstack 2
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: ldflda "C
(
Of
T
).
field
As
T
"
IL_0006: ldloca.s V_0
IL_0008: initobj "
T
"
IL_000e: ldloc.0
IL_000f: box "
T
"
IL_0014: brtrue.s IL_002a
IL_0016: ldobj "
T
"
IL_001b: stloc.0
IL_001c: ldloca.s V_0
IL_001e: ldloc.0
IL_001f: box "
T
"
IL_0024: brtrue.s IL_002a
IL_0026: pop
IL_0027: ldnull
IL_0028: br.s IL_0035
IL_002a: constrained. "
T
"
IL_0030: callvirt "
Function
Object
.
ToString
()
As
String
"
IL_0035: call "
Sub
System
.
Console
.
WriteLine
(
String
)
"
IL_003a: ldarg.0
IL_003b: ldfld "C
(
Of
T
).
field
As
T
"
IL_0040: box "
T
"
IL_0045: call "
Sub
System
.
Console
.
WriteLine
(
Object
)
"
IL_004a: ret
}
]]>)
End Sub
<Fact>
<WorkItem(3519, "
https
:
//
github
.
com
/
dotnet
/
roslyn
/
issues
/
35319
")>
Public Sub CodeGen_ConditionalAccessReadonlyUnconstrainedTField()
Dim c = CompileAndVerify(
<compilation>
<file name="
a
.
vb
">
Imports System
Public Class C(Of T)
Public Sub New(ByVal t As T)
field = t
End Sub
Public Sub New()
End Sub
ReadOnly field As T
Public Sub Print()
Console.WriteLine(field?.ToString())
Console.WriteLine(field)
End Sub
End Class
Public Structure S
Private a As Integer
Public Overrides Function ToString() As String
Return Math.Min(System.Threading.Interlocked.Increment(a), a - 1).ToString()
End Function
End Structure
Module Program
Sub Main()
Call New C(Of S)().Print()
Call New C(Of S?)().Print()
Call New C(Of S?)(New S()).Print()
Call New C(Of String)("
hello
").Print()
Call New C(Of String)().Print()
End Sub
End Module
</file>
</compilation>, expectedOutput:="
0
0
0
0
hello
hello
")
c.VerifyIL("C
(
Of
T
).
Print
()
",
<![CDATA[
{
// Code size 54 (0x36)
.maxstack 2
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: ldfld "C
(
Of
T
).
field
As
T
"
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0009: ldloc.0
IL_000a: box "
T
"
IL_000f: brtrue.s IL_0015
IL_0011: pop
IL_0012: ldnull
IL_0013: br.s IL_0020
IL_0015: constrained. "
T
"
IL_001b: callvirt "
Function
Object
.
ToString
()
As
String
"
IL_0020: call "
Sub
System
.
Console
.
WriteLine
(
String
)
"
IL_0025: ldarg.0
IL_0026: ldfld "C
(
Of
T
).
field
As
T
"
IL_002b: box "
T
"
IL_0030: call "
Sub
System
.
Console
.
WriteLine
(
Object
)
"
IL_0035: ret
}
]]>)
End Sub
<Fact>
<WorkItem(3519, "
https
:
//
github
.
com
/
dotnet
/
roslyn
/
issues
/
35319
")>
Public Sub CodeGen_ConditionalAccessUnconstrainedTLocal()
Dim c = CompileAndVerify(
<compilation>
<file name="
a
.
vb
">
Imports System
Public Class C(Of T)
Public Sub New(ByVal t As T)
field = t
End Sub
Public Sub New()
End Sub
Private field As T
Public Sub Print()
Dim temp = field
Console.WriteLine(temp?.ToString())
Console.WriteLine(temp)
End Sub
End Class
Public Structure S
Private a As Integer
Public Overrides Function ToString() As String
Return Math.Min(System.Threading.Interlocked.Increment(a), a - 1).ToString()
End Function
End Structure
Module Program
Sub Main()
Call New C(Of S)().Print()
Call New C(Of S?)().Print()
Call New C(Of S?)(New S()).Print()
Call New C(Of String)("
hello
").Print()
Call New C(Of String)().Print()
End Sub
End Module
</file>
</compilation>, expectedOutput:="
0
1
0
1
hello
hello
")
c.VerifyIL("C
(
Of
T
).
Print
()
",
<![CDATA[
{
// Code size 48 (0x30)
.maxstack 1
.locals init (T V_0) //temp
IL_0000: ldarg.0
IL_0001: ldfld "C
(
Of
T
).
field
As
T
"
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: box "
T
"
IL_000d: brtrue.s IL_0012
IL_000f: ldnull
IL_0010: br.s IL_001f
IL_0012: ldloca.s V_0
IL_0014: constrained. "
T
"
IL_001a: callvirt "
Function
Object
.
ToString
()
As
String
"
IL_001f: call "
Sub
System
.
Console
.
WriteLine
(
String
)
"
IL_0024: ldloc.0
IL_0025: box "
T
"
IL_002a: call "
Sub
System
.
Console
.
WriteLine
(
Object
)
"
IL_002f: ret
}
]]>)
End Sub
<Fact>
<WorkItem(3519, "
https
:
//
github
.
com
/
dotnet
/
roslyn
/
issues
/
35319
")>
Public Sub CodeGen_ConditionalAccessUnconstrainedTTemp()
Dim c = CompileAndVerify(
<compilation>
<file name="
a
.
vb
">
Imports System
Public Class C(Of T)
Public Sub New(ByVal t As T)
field = t
End Sub
Public Sub New()
End Sub
Private field As T
Private Function M() As T
Return field
End Function
Public Sub Print()
Console.WriteLine(M()?.ToString())
End Sub
End Class
Module Program
Sub Main()
Call New C(Of Integer)().Print()
Call New C(Of Integer?)().Print()
Call New C(Of Integer?)(0).Print()
Call New C(Of String)("
hello
").Print()
Call New C(Of String)().Print()
End Sub
End Module
</file>
</compilation>, expectedOutput:="
0
0
hello
")
c.VerifyIL("C
(
Of
T
).
Print
()
",
<![CDATA[
{
// Code size 38 (0x26)
.maxstack 2
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: call "
Function
C
(
Of
T
).
M
()
As
T
"
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0009: ldloc.0
IL_000a: box "
T
"
IL_000f: brtrue.s IL_0015
IL_0011: pop
IL_0012: ldnull
IL_0013: br.s IL_0020
IL_0015: constrained. "
T
"
IL_001b: callvirt "
Function
Object
.
ToString
()
As
String
"
IL_0020: call "
Sub
System
.
Console
.
WriteLine
(
String
)
"
IL_0025: ret
}
]]>)
End Sub
<Fact()>
<Fact()>
Public Sub InlineNullableIsTrue_01()
Public Sub InlineNullableIsTrue_01()
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录