Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
d8ef80e3
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,发现更多精彩内容 >>
未验证
提交
d8ef80e3
编写于
2月 11, 2020
作者:
Y
Yair Halberstadt
提交者:
GitHub
2月 11, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fix invalid IL for unconstrained conditional access. (#40878)
上级
4e88ffa6
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
479 addition
and
455 deletion
+479
-455
src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
+39
-26
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenConditionalOperatorTests.cs
...harp/Test/Emit/CodeGen/CodeGenConditionalOperatorTests.cs
+129
-102
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenShortCircuitOperatorTests.cs
...arp/Test/Emit/CodeGen/CodeGenShortCircuitOperatorTests.cs
+23
-38
src/Compilers/CSharp/Test/WinRT/AnonymousTypesSymbolTests.cs
src/Compilers/CSharp/Test/WinRT/AnonymousTypesSymbolTests.cs
+94
-142
src/Compilers/VisualBasic/Portable/CodeGen/EmitExpression.vb
src/Compilers/VisualBasic/Portable/CodeGen/EmitExpression.vb
+36
-25
src/Compilers/VisualBasic/Test/Semantic/Semantics/ConditionalAccessTests.vb
...alBasic/Test/Semantic/Semantics/ConditionalAccessTests.vb
+158
-122
未找到文件。
src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
浏览文件 @
d8ef80e3
...
...
@@ -407,32 +407,45 @@ private void EmitLoweredConditionalAccessExpression(BoundLoweredConditionalAcces
// if T happens to be a value type, it could be a target of mutating calls.
receiverTemp
=
EmitReceiverRef
(
receiver
,
AddressKind
.
Constrained
);
// unconstrained case needs to handle case where T is actually a struct.
// such values are never nulls
// 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)
// {
// goto whenNotNull
// }
// else
// {
// temp = receiverRef
// receiverRef = ref temp
// }
EmitDefaultValue
(
receiverType
,
true
,
receiver
.
Syntax
);
EmitBox
(
receiverType
,
receiver
.
Syntax
);
_builder
.
EmitBranch
(
ILOpCode
.
Brtrue
,
whenNotNullLabel
);
EmitLoadIndirect
(
receiverType
,
receiver
.
Syntax
);
cloneTemp
=
AllocateTemp
(
receiverType
,
receiver
.
Syntax
);
_builder
.
EmitLocalStore
(
cloneTemp
);
_builder
.
EmitLocalAddress
(
cloneTemp
);
_builder
.
EmitLocalLoad
(
cloneTemp
);
EmitBox
(
receiver
.
Type
,
receiver
.
Syntax
);
// here we have loaded a ref to a temp and its boxed value { &T, O }
if
(
receiverTemp
is
null
)
{
// unconstrained case needs to handle case where T is actually a struct.
// such values are never nulls
// 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)
// {
// goto whenNotNull
// }
// else
// {
// temp = receiverRef
// receiverRef = ref temp
// }
EmitDefaultValue
(
receiverType
,
true
,
receiver
.
Syntax
);
EmitBox
(
receiverType
,
receiver
.
Syntax
);
_builder
.
EmitBranch
(
ILOpCode
.
Brtrue
,
whenNotNullLabel
);
EmitLoadIndirect
(
receiverType
,
receiver
.
Syntax
);
cloneTemp
=
AllocateTemp
(
receiverType
,
receiver
.
Syntax
);
_builder
.
EmitLocalStore
(
cloneTemp
);
_builder
.
EmitLocalAddress
(
cloneTemp
);
_builder
.
EmitLocalLoad
(
cloneTemp
);
EmitBox
(
receiverType
,
receiver
.
Syntax
);
// 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.
// We currently have an address on the stack. Duplicate it, and load the value of the address.
_builder
.
EmitOpCode
(
ILOpCode
.
Dup
);
EmitLoadIndirect
(
receiverType
,
receiver
.
Syntax
);
EmitBox
(
receiverType
,
receiver
.
Syntax
);
}
}
else
{
...
...
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenConditionalOperatorTests.cs
浏览文件 @
d8ef80e3
...
...
@@ -2893,36 +2893,28 @@ public static void Main()
verify
.
VerifyIL
(
"C<T>.Print()"
,
@"
{
// Code size
78 (0x4e
)
// Code size
59 (0x3b
)
.maxstack 2
.locals init (T V_0,
T V_1)
.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: ldloca.s V_1
IL_000b: initobj ""T""
IL_0011: ldloc.1
IL_0012: box ""T""
IL_0017: brtrue.s IL_002d
IL_0019: ldobj ""T""
IL_001e: stloc.1
IL_001f: ldloca.s V_1
IL_0021: ldloc.1
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 ""string object.ToString()""
IL_0038: call ""void System.Console.WriteLine(string)""
IL_003d: ldarg.0
IL_003e: ldfld ""T C<T>.t""
IL_0043: box ""T""
IL_0048: call ""void System.Console.WriteLine(object)""
IL_004d: ret
IL_0009: dup
IL_000a: ldobj ""T""
IL_000f: box ""T""
IL_0014: brtrue.s IL_001a
IL_0016: pop
IL_0017: ldnull
IL_0018: br.s IL_0025
IL_001a: constrained. ""T""
IL_0020: callvirt ""string object.ToString()""
IL_0025: call ""void System.Console.WriteLine(string)""
IL_002a: ldarg.0
IL_002b: ldfld ""T C<T>.t""
IL_0030: box ""T""
IL_0035: call ""void System.Console.WriteLine(object)""
IL_003a: ret
}"
);
}
...
...
@@ -3036,33 +3028,26 @@ public static void Main()
verify
.
VerifyIL
(
"C<T>.Print()"
,
@"
{
// Code size
62 (0x3e
)
// Code size
43 (0x2b
)
.maxstack 2
.locals init (T V_0,
T V_1)
.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: ldloca.s V_1
IL_000b: initobj ""T""
IL_0011: ldloc.1
IL_0012: box ""T""
IL_0017: brtrue.s IL_002d
IL_0019: ldobj ""T""
IL_001e: stloc.1
IL_001f: ldloca.s V_1
IL_0021: ldloc.1
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 ""string object.ToString()""
IL_0038: call ""void System.Console.WriteLine(string)""
IL_003d: ret
IL_0009: dup
IL_000a: ldobj ""T""
IL_000f: box ""T""
IL_0014: brtrue.s IL_001a
IL_0016: pop
IL_0017: ldnull
IL_0018: br.s IL_0025
IL_001a: constrained. ""T""
IL_0020: callvirt ""string object.ToString()""
IL_0025: call ""void System.Console.WriteLine(string)""
IL_002a: ret
}"
);
}
[
Fact
,
WorkItem
(
40690
,
"https://github.com/dotnet/roslyn/issues/40690"
)]
...
...
@@ -3070,83 +3055,125 @@ public void ConditionalAccess_GenericExtension_ValueTuple()
{
var
source
=
@"
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace bug
public static class Extension
{
public static class Extension
public static string GetValue(this object value) => value?.ToString();
}
public class Class<T>
{
public (long, T) Data { get; }
public Class((long, T) data)
{
public static String GetValue(this object value) => value?.ToString()
;
Data = data
;
}
public partial class BGen<__T__>
internal string Value
{
public (Int64, __T__) Data { get; }
public BGen((Int64, __T__) data)
get
{
this.Data = data;
var q2 = Data.Item2?.GetValue();
return q2;
}
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(new Class<string>((0, ""abc"")).Value);
Console.WriteLine(new Class<string>((0, null)).Value);
Console.WriteLine(new Class<int>((0, 0)).Value);
Console.WriteLine(new Class<int?>((0, 0)).Value);
Console.WriteLine(new Class<int?>((0, null)).Value);
}
}"
;
var
verifier
=
CompileAndVerify
(
source
,
expectedOutput
:
@"abc
internal String Value
0
0
"
);
verifier
.
VerifyIL
(
"Class<T>.Value.get"
,
@"
{
// Code size 46 (0x2e)
.maxstack 2
.locals init (System.ValueTuple<long, T> V_0)
IL_0000: ldarg.0
IL_0001: call ""System.ValueTuple<long, T> Class<T>.Data.get""
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0009: ldflda ""T System.ValueTuple<long, T>.Item2""
IL_000e: dup
IL_000f: ldobj ""T""
IL_0014: box ""T""
IL_0019: brtrue.s IL_001e
IL_001b: pop
IL_001c: ldnull
IL_001d: ret
IL_001e: ldobj ""T""
IL_0023: box ""T""
IL_0028: call ""string Extension.GetValue(object)""
IL_002d: ret
}"
);
}
[
Fact
,
WorkItem
(
40690
,
"https://github.com/dotnet/roslyn/issues/40690"
)]
public
void
ConditionalAccess_InstanceMethod_ValueTuple
()
{
get
{
/// This works fine:
//var i2 = Data.Item2;
//var q2 = i2?.GetValue();
var
source
=
@"
using System;
// This causes the AccessViolation:
var q2 = Data.Item2?.GetValue();
return q2;
}
}
public class Class<T>
{
public (long, T) Data { get; }
public Class((long, T) data)
{
Data = data;
}
class Program
internal string Value
{
static void Main(string[] args)
get
{
var i = new BGen<string>((0, ""abc""));
var r = i.Value;
Console.Write(r);
var q2 = Data.Item2?.ToString();
return q2;
}
}
}
"
;
var
verifier
=
CompileAndVerify
(
source
,
expectedOutput
:
"abc"
);
verifier
.
VerifyIL
(
"bug.BGen<__T__>.Value.get"
,
@"
class Program
{
static void Main(string[] args)
{
Console.WriteLine(new Class<string>((0, ""abc"")).Value);
Console.WriteLine(new Class<string>((0, null)).Value);
Console.WriteLine(new Class<int>((0, 0)).Value);
Console.WriteLine(new Class<int?>((0, 0)).Value);
Console.WriteLine(new Class<int?>((0, null)).Value);
}
}"
;
var
verifier
=
CompileAndVerify
(
source
,
expectedOutput
:
@"abc
0
0
"
);
verifier
.
VerifyIL
(
"Class<T>.Value.get"
,
@"
{
// Code size
65 (0x41
)
// Code size
42 (0x2a
)
.maxstack 2
.locals init (System.ValueTuple<long, __T__> V_0,
__T__ V_1)
.locals init (System.ValueTuple<long, T> V_0)
IL_0000: ldarg.0
IL_0001: call ""System.ValueTuple<long,
__T__> bug.BGen<__T__
>.Data.get""
IL_0001: call ""System.ValueTuple<long,
T> Class<T
>.Data.get""
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0009: ldflda ""__T__ System.ValueTuple<long, __T__>.Item2""
IL_000e: ldloca.s V_1
IL_0010: initobj ""__T__""
IL_0016: ldloc.1
IL_0017: box ""__T__""
IL_001c: brtrue.s IL_0031
IL_001e: ldobj ""__T__""
IL_0023: stloc.1
IL_0024: ldloca.s V_1
IL_0026: ldloc.1
IL_0027: box ""__T__""
IL_002c: brtrue.s IL_0031
IL_002e: pop
IL_002f: ldnull
IL_0030: ret
IL_0031: ldobj ""__T__""
IL_0036: box ""__T__""
IL_003b: call ""string bug.Extension.GetValue(object)""
IL_0040: ret
IL_0009: ldflda ""T System.ValueTuple<long, T>.Item2""
IL_000e: dup
IL_000f: ldobj ""T""
IL_0014: box ""T""
IL_0019: brtrue.s IL_001e
IL_001b: pop
IL_001c: ldnull
IL_001d: ret
IL_001e: constrained. ""T""
IL_0024: callvirt ""string object.ToString()""
IL_0029: ret
}"
);
}
}
...
...
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenShortCircuitOperatorTests.cs
浏览文件 @
d8ef80e3
...
...
@@ -2463,49 +2463,34 @@ static void Main(string[] args)
False"
);
comp
.
VerifyIL
(
"Program.Test<T>(System.Func<T>)"
,
@"
{
// Code size
110 (0x6e
)
// Code size
72 (0x48
)
.maxstack 2
.locals init (T V_0,
T V_1)
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: callvirt ""T System.Func<T>.Invoke()""
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0009: ldloca.s V_1
IL_000b: initobj ""T""
IL_0011: ldloc.1
IL_0012: box ""T""
IL_0017: brtrue.s IL_002c
IL_0019: ldobj ""T""
IL_001e: stloc.1
IL_001f: ldloca.s V_1
IL_0021: ldloc.1
IL_0022: box ""T""
IL_0027: brtrue.s IL_002c
IL_0029: pop
IL_002a: br.s IL_0037
IL_002c: constrained. ""T""
IL_0032: callvirt ""void System.IDisposable.Dispose()""
IL_0037: ldarg.0
IL_0038: callvirt ""T System.Func<T>.Invoke()""
IL_003d: stloc.0
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
IL_0009: dup
IL_000a: ldobj ""T""
IL_000f: box ""T""
IL_0014: brtrue.s IL_0019
IL_0016: pop
IL_0017: br.s IL_0024
IL_0019: constrained. ""T""
IL_001f: callvirt ""void System.IDisposable.Dispose()""
IL_0024: ldarg.0
IL_0025: callvirt ""T System.Func<T>.Invoke()""
IL_002a: stloc.0
IL_002b: ldloca.s V_0
IL_002d: dup
IL_002e: ldobj ""T""
IL_0033: box ""T""
IL_0038: brtrue.s IL_003c
IL_003a: pop
IL_003b: ret
IL_003c: constrained. ""T""
IL_0042: callvirt ""void System.IDisposable.Dispose()""
IL_0047: ret
}
"
);
}
...
...
src/Compilers/CSharp/Test/WinRT/AnonymousTypesSymbolTests.cs
浏览文件 @
d8ef80e3
...
...
@@ -426,14 +426,11 @@ .maxstack 3
).
VerifyIL
(
"<>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.ToString"
,
@"{
// Code size 1
99 (0xc7
)
// Code size 1
38 (0x8a
)
.maxstack 7
.locals init (<Length>j__TPar V_0,
<Length>j__TPar V_1,
<at1>j__TPar V_2,
<at1>j__TPar V_3,
<C>j__TPar V_4,
<C>j__TPar V_5)
<at1>j__TPar V_1,
<C>j__TPar V_2)
IL_0000: ldnull
IL_0001: ldstr ""{{ Length = {0}, at1 = {1}, C = {2} }}""
IL_0006: ldc.i4.3
...
...
@@ -444,71 +441,50 @@ .maxstack 7
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_0015: ldloca.s V_0
IL_0017: ldloca.s V_1
IL_0019: initobj ""<Length>j__TPar""
IL_001f: ldloc.1
IL_0020: box ""<Length>j__TPar""
IL_0025: brtrue.s IL_003b
IL_0027: ldobj ""<Length>j__TPar""
IL_002c: stloc.1
IL_002d: ldloca.s V_1
IL_002f: ldloc.1
IL_0030: box ""<Length>j__TPar""
IL_0035: brtrue.s IL_003b
IL_0037: pop
IL_0038: ldnull
IL_0039: br.s IL_0046
IL_003b: constrained. ""<Length>j__TPar""
IL_0041: callvirt ""string object.ToString()""
IL_0046: stelem.ref
IL_0047: dup
IL_0048: ldc.i4.1
IL_0049: ldarg.0
IL_004a: ldfld ""<at1>j__TPar <>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.<at1>i__Field""
IL_004f: stloc.2
IL_0050: ldloca.s V_2
IL_0052: ldloca.s V_3
IL_0054: initobj ""<at1>j__TPar""
IL_005a: ldloc.3
IL_005b: box ""<at1>j__TPar""
IL_0060: brtrue.s IL_0076
IL_0062: ldobj ""<at1>j__TPar""
IL_0067: stloc.3
IL_0068: ldloca.s V_3
IL_006a: ldloc.3
IL_006b: box ""<at1>j__TPar""
IL_0070: brtrue.s IL_0076
IL_0072: pop
IL_0073: ldnull
IL_0074: br.s IL_0081
IL_0076: constrained. ""<at1>j__TPar""
IL_007c: callvirt ""string object.ToString()""
IL_0081: stelem.ref
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
IL_0017: dup
IL_0018: ldobj ""<Length>j__TPar""
IL_001d: box ""<Length>j__TPar""
IL_0022: brtrue.s IL_0028
IL_0024: pop
IL_0025: ldnull
IL_0026: br.s IL_0033
IL_0028: constrained. ""<Length>j__TPar""
IL_002e: callvirt ""string object.ToString()""
IL_0033: stelem.ref
IL_0034: dup
IL_0035: ldc.i4.1
IL_0036: ldarg.0
IL_0037: ldfld ""<at1>j__TPar <>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.<at1>i__Field""
IL_003c: stloc.1
IL_003d: ldloca.s V_1
IL_003f: dup
IL_0040: ldobj ""<at1>j__TPar""
IL_0045: box ""<at1>j__TPar""
IL_004a: brtrue.s IL_0050
IL_004c: pop
IL_004d: ldnull
IL_004e: br.s IL_005b
IL_0050: constrained. ""<at1>j__TPar""
IL_0056: callvirt ""string object.ToString()""
IL_005b: stelem.ref
IL_005c: dup
IL_005d: ldc.i4.2
IL_005e: ldarg.0
IL_005f: ldfld ""<C>j__TPar <>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.<C>i__Field""
IL_0064: stloc.2
IL_0065: ldloca.s V_2
IL_0067: dup
IL_0068: ldobj ""<C>j__TPar""
IL_006d: box ""<C>j__TPar""
IL_0072: brtrue.s IL_0078
IL_0074: pop
IL_0075: ldnull
IL_0076: br.s IL_0083
IL_0078: constrained. ""<C>j__TPar""
IL_007e: callvirt ""string object.ToString()""
IL_0083: stelem.ref
IL_0084: call ""string string.Format(System.IFormatProvider, string, params object[])""
IL_0089: ret
}"
);
}
...
...
@@ -875,14 +851,11 @@ .maxstack 3
).
VerifyIL
(
"<>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.ToString"
,
@"{
// Code size 1
99 (0xc7
)
// Code size 1
38 (0x8a
)
.maxstack 7
.locals init (<ToString>j__TPar V_0,
<ToString>j__TPar V_1,
<Equals>j__TPar V_2,
<Equals>j__TPar V_3,
<GetHashCode>j__TPar V_4,
<GetHashCode>j__TPar V_5)
<Equals>j__TPar V_1,
<GetHashCode>j__TPar V_2)
IL_0000: ldnull
IL_0001: ldstr ""{{ ToString = {0}, Equals = {1}, GetHashCode = {2} }}""
IL_0006: ldc.i4.3
...
...
@@ -893,71 +866,50 @@ .maxstack 7
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_0015: ldloca.s V_0
IL_0017: ldloca.s V_1
IL_0019: initobj ""<ToString>j__TPar""
IL_001f: ldloc.1
IL_0020: box ""<ToString>j__TPar""
IL_0025: brtrue.s IL_003b
IL_0027: ldobj ""<ToString>j__TPar""
IL_002c: stloc.1
IL_002d: ldloca.s V_1
IL_002f: ldloc.1
IL_0030: box ""<ToString>j__TPar""
IL_0035: brtrue.s IL_003b
IL_0037: pop
IL_0038: ldnull
IL_0039: br.s IL_0046
IL_003b: constrained. ""<ToString>j__TPar""
IL_0041: callvirt ""string object.ToString()""
IL_0046: stelem.ref
IL_0047: dup
IL_0048: ldc.i4.1
IL_0049: ldarg.0
IL_004a: ldfld ""<Equals>j__TPar <>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.<Equals>i__Field""
IL_004f: stloc.2
IL_0050: ldloca.s V_2
IL_0052: ldloca.s V_3
IL_0054: initobj ""<Equals>j__TPar""
IL_005a: ldloc.3
IL_005b: box ""<Equals>j__TPar""
IL_0060: brtrue.s IL_0076
IL_0062: ldobj ""<Equals>j__TPar""
IL_0067: stloc.3
IL_0068: ldloca.s V_3
IL_006a: ldloc.3
IL_006b: box ""<Equals>j__TPar""
IL_0070: brtrue.s IL_0076
IL_0072: pop
IL_0073: ldnull
IL_0074: br.s IL_0081
IL_0076: constrained. ""<Equals>j__TPar""
IL_007c: callvirt ""string object.ToString()""
IL_0081: stelem.ref
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
IL_0017: dup
IL_0018: ldobj ""<ToString>j__TPar""
IL_001d: box ""<ToString>j__TPar""
IL_0022: brtrue.s IL_0028
IL_0024: pop
IL_0025: ldnull
IL_0026: br.s IL_0033
IL_0028: constrained. ""<ToString>j__TPar""
IL_002e: callvirt ""string object.ToString()""
IL_0033: stelem.ref
IL_0034: dup
IL_0035: ldc.i4.1
IL_0036: ldarg.0
IL_0037: ldfld ""<Equals>j__TPar <>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.<Equals>i__Field""
IL_003c: stloc.1
IL_003d: ldloca.s V_1
IL_003f: dup
IL_0040: ldobj ""<Equals>j__TPar""
IL_0045: box ""<Equals>j__TPar""
IL_004a: brtrue.s IL_0050
IL_004c: pop
IL_004d: ldnull
IL_004e: br.s IL_005b
IL_0050: constrained. ""<Equals>j__TPar""
IL_0056: callvirt ""string object.ToString()""
IL_005b: stelem.ref
IL_005c: dup
IL_005d: ldc.i4.2
IL_005e: ldarg.0
IL_005f: ldfld ""<GetHashCode>j__TPar <>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.<GetHashCode>i__Field""
IL_0064: stloc.2
IL_0065: ldloca.s V_2
IL_0067: dup
IL_0068: ldobj ""<GetHashCode>j__TPar""
IL_006d: box ""<GetHashCode>j__TPar""
IL_0072: brtrue.s IL_0078
IL_0074: pop
IL_0075: ldnull
IL_0076: br.s IL_0083
IL_0078: constrained. ""<GetHashCode>j__TPar""
IL_007e: callvirt ""string object.ToString()""
IL_0083: stelem.ref
IL_0084: call ""string string.Format(System.IFormatProvider, string, params object[])""
IL_0089: ret
}"
).
VerifyIL
(
"<>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.ToString.get"
,
...
...
src/Compilers/VisualBasic/Portable/CodeGen/EmitExpression.vb
浏览文件 @
d8ef80e3
...
...
@@ -290,35 +290,45 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen
Dim
nullCheckOnCopy
=
conditional
.
CaptureReceiver
OrElse
(
receiverType
.
IsReferenceType
AndAlso
receiverType
.
TypeKind
=
TypeKind
.
TypeParameter
)
If
nullCheckOnCopy
Then
EmitReceiverRef
(
receiver
,
isAccessConstrained
:
=
Not
receiverType
.
IsReferenceType
,
addressKind
:
=
AddressKind
.
ReadOnly
)
receiverTemp
=
EmitReceiverRef
(
receiver
,
isAccessConstrained
:
=
Not
receiverType
.
IsReferenceType
,
addressKind
:
=
AddressKind
.
ReadOnly
)
If
Not
receiverType
.
IsReferenceType
Then
' unconstrained case needs to handle case where T Is actually a struct.
' such values are never nulls
' 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)
' {
' goto whenNotNull
' }
' else
' {
' temp = receiverRef
' receiverRef = ref temp
' }
EmitInitObj
(
receiverType
,
True
,
receiver
.
Syntax
)
EmitBox
(
receiverType
,
receiver
.
Syntax
)
_builder
.
EmitBranch
(
ILOpCode
.
Brtrue
,
whenNotNullLabel
)
EmitLoadIndirect
(
receiverType
,
receiver
.
Syntax
)
If
receiverTemp
Is
Nothing
Then
' unconstrained case needs to handle case where T Is actually a struct.
' such values are never nulls
' 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)
' {
' goto whenNotNull
' }
' else
' {
' temp = receiverRef
' receiverRef = ref temp
' }
EmitInitObj
(
receiverType
,
True
,
receiver
.
Syntax
)
EmitBox
(
receiverType
,
receiver
.
Syntax
)
_builder
.
EmitBranch
(
ILOpCode
.
Brtrue
,
whenNotNullLabel
)
EmitLoadIndirect
(
receiverType
,
receiver
.
Syntax
)
temp
=
AllocateTemp
(
receiverType
,
receiver
.
Syntax
)
_builder
.
EmitLocalStore
(
temp
)
_builder
.
EmitLocalAddress
(
temp
)
_builder
.
EmitLocalLoad
(
temp
)
EmitBox
(
receiverType
,
receiver
.
Syntax
)
temp
=
AllocateTemp
(
receiverType
,
receiver
.
Syntax
)
_builder
.
EmitLocalStore
(
temp
)
_builder
.
EmitLocalAddress
(
temp
)
_builder
.
EmitLocalLoad
(
temp
)
EmitBox
(
receiver
.
Type
,
receiver
.
Syntax
)
' 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.
' here we have loaded a ref to a temp And its boxed value { &T, O }
' We currently have an adress on the stack. Duplicate it, and load the value of the address.
_builder
.
EmitOpCode
(
ILOpCode
.
Dup
)
EmitLoadIndirect
(
receiverType
,
receiver
.
Syntax
)
EmitBox
(
receiverType
,
receiver
.
Syntax
)
End
If
Else
_builder
.
EmitOpCode
(
ILOpCode
.
Dup
)
' here we have loaded two copies of a reference { O, O }
...
...
@@ -362,6 +372,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen
_builder
.
MarkLabel
(
whenNotNullLabel
)
If
Not
nullCheckOnCopy
Then
Debug
.
Assert
(
receiverTemp
Is
Nothing
)
receiverTemp
=
EmitReceiverRef
(
receiver
,
isAccessConstrained
:
=
Not
receiverType
.
IsReferenceType
,
addressKind
:
=
AddressKind
.
ReadOnly
)
Debug
.
Assert
(
receiverTemp
Is
Nothing
OrElse
receiver
.
IsDefaultValue
())
End
If
...
...
src/Compilers/VisualBasic/Test/Semantic/Semantics/ConditionalAccessTests.vb
浏览文件 @
d8ef80e3
...
...
@@ -615,32 +615,24 @@ Null
verifier.VerifyIL("
Module1
.
Test8
",
<![CDATA[
{
// Code size
62 (0x3e
)
// Code size
43 (0x2b
)
.maxstack 2
.locals init (T V_0,
T V_1)
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: call "
Function
Module1
.
GetT
(
Of
T
)(
T
)
As
T
"
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0009: ldloca.s V_1
IL_000b: initobj "
T
"
IL_0011: ldloc.1
IL_0012: box "
T
"
IL_0017: brtrue.s IL_002d
IL_0019: ldobj "
T
"
IL_001e: stloc.1
IL_001f: ldloca.s V_1
IL_0021: ldloc.1
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
IL_0009: dup
IL_000a: ldobj "
T
"
IL_000f: box "
T
"
IL_0014: brtrue.s IL_001a
IL_0016: pop
IL_0017: ldnull
IL_0018: br.s IL_0025
IL_001a: constrained. "
T
"
IL_0020: callvirt "
Function
I1
.
get_P2
()
As
String
"
IL_0025: call "
Sub
Module1
.
Do
(
Of
String
)(
String
)
"
IL_002a: ret
}
]]>)
...
...
@@ -3554,30 +3546,22 @@ Ext4 C1
verifier.VerifyIL("
Module1
.
Test1_6
",
<![CDATA[
{
// Code size
54 (0x36
)
// Code size
35 (0x23
)
.maxstack 2
.locals init (T V_0,
T V_1)
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: call "
Function
Module1
.
GetT
(
Of
T
)(
T
)
As
T
"
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0009: ldloca.s V_1
IL_000b: initobj "
T
"
IL_0011: ldloc.1
IL_0012: box "
T
"
IL_0017: brtrue.s IL_002b
IL_0019: ldobj "
T
"
IL_001e: stloc.1
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
IL_0009: dup
IL_000a: ldobj "
T
"
IL_000f: box "
T
"
IL_0014: brtrue.s IL_0018
IL_0016: pop
IL_0017: ret
IL_0018: ldobj "
T
"
IL_001d: call "
Sub
Module1
.
Ext1
(
Of
T
)(
T
)
"
IL_0022: ret
}
]]>)
...
...
@@ -5449,36 +5433,28 @@ hello")
c.VerifyIL("C
(
Of
T
).
Print
()
",
<![CDATA[
{
// Code size
78 (0x4e
)
// Code size
59 (0x3b
)
.maxstack 2
.locals init (T V_0,
T V_1)
.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: ldloca.s V_1
IL_000b: initobj "
T
"
IL_0011: ldloc.1
IL_0012: box "
T
"
IL_0017: brtrue.s IL_002d
IL_0019: ldobj "
T
"
IL_001e: stloc.1
IL_001f: ldloca.s V_1
IL_0021: ldloc.1
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
Object
.
ToString
()
As
String
"
IL_0038: call "
Sub
System
.
Console
.
WriteLine
(
String
)
"
IL_003d: ldarg.0
IL_003e: ldfld "C
(
Of
T
).
field
As
T
"
IL_0043: box "
T
"
IL_0048: call "
Sub
System
.
Console
.
WriteLine
(
Object
)
"
IL_004d: ret
IL_0009: dup
IL_000a: ldobj "
T
"
IL_000f: box "
T
"
IL_0014: brtrue.s IL_001a
IL_0016: pop
IL_0017: ldnull
IL_0018: br.s IL_0025
IL_001a: constrained. "
T
"
IL_0020: callvirt "
Function
Object
.
ToString
()
As
String
"
IL_0025: call "
Sub
System
.
Console
.
WriteLine
(
String
)
"
IL_002a: ldarg.0
IL_002b: ldfld "C
(
Of
T
).
field
As
T
"
IL_0030: box "
T
"
IL_0035: call "
Sub
System
.
Console
.
WriteLine
(
Object
)
"
IL_003a: ret
}
]]>)
End Sub
...
...
@@ -5607,32 +5583,24 @@ hello
c.VerifyIL("C
(
Of
T
).
Print
()
",
<![CDATA[
{
// Code size
62 (0x3e
)
// Code size
43 (0x2b
)
.maxstack 2
.locals init (T V_0,
T V_1)
.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: ldloca.s V_1
IL_000b: initobj "
T
"
IL_0011: ldloc.1
IL_0012: box "
T
"
IL_0017: brtrue.s IL_002d
IL_0019: ldobj "
T
"
IL_001e: stloc.1
IL_001f: ldloca.s V_1
IL_0021: ldloc.1
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
Object
.
ToString
()
As
String
"
IL_0038: call "
Sub
System
.
Console
.
WriteLine
(
String
)
"
IL_003d: ret
IL_0009: dup
IL_000a: ldobj "
T
"
IL_000f: box "
T
"
IL_0014: brtrue.s IL_001a
IL_0016: pop
IL_0017: ldnull
IL_0018: br.s IL_0025
IL_001a: constrained. "
T
"
IL_0020: callvirt "
Function
Object
.
ToString
()
As
String
"
IL_0025: call "
Sub
System
.
Console
.
WriteLine
(
String
)
"
IL_002a: ret
}
]]>)
End Sub
...
...
@@ -10215,10 +10183,9 @@ False
CompileAndVerify(compilationDef, options:=TestOptions.ReleaseExe, expectedOutput:=expectedOutput)
End Sub
<Fact()>
<WorkItem(40690, "
https
:
//
github
.
com
/
dotnet
/
roslyn
/
issues
/
40690
")>
Public Sub ConditionalAccess_GenericExtension_ValueTuple
Public Sub ConditionalAccess_GenericExtension_ValueTuple
()
Dim compilationDef =
<compilation>
<file name="
a
.
vb
">
...
...
@@ -10232,10 +10199,10 @@ Public Module Extensions
End Function
End Module
Public Class
BGen(Of __T__
)
Public ReadOnly Property Data As (Integer,
__T__
)
Public Class
C(Of T
)
Public ReadOnly Property Data As (Integer,
T
)
Public Sub New(data As (Integer,
__T__
))
Public Sub New(data As (Integer,
T
))
Me.Data = data
End Sub
...
...
@@ -10245,57 +10212,126 @@ Public Class BGen(Of __T__)
End Get
End Property
End Class
Public Class Main
Public Shared Sub Main()
Console.WriteLine(New C(Of String)((0, "
abc
")).Value)
Console.WriteLine(New C(Of String)((0, Nothing)).Value)
Console.WriteLine(New C(Of Integer)((0, 0)).Value)
Console.WriteLine(New C(Of Integer?)((0, 0)).Value)
Console.WriteLine(New C(Of Integer?)((0, Nothing)).Value)
End Sub
End Class
</file>
</compilation>
Dim valueTupleRefs As MetadataReference() = New MetadataReference() {ValueTupleRef, SystemRuntimeFacadeRef}
Dim expectedOutput = "
abc
0
0
"
Dim verifier = CompileAndVerify(
CreateCompilationWithMscorlib45AndVBRuntime(compilationDef, options:=TestOptions.DebugExe, references:=valueTupleRefs),
expectedOutput:=expectedOutput)
verifier.VerifyIL("C
(
Of
T
).
get_Value
()
", "
{
//
Code
size
52
(
0
x34
)
.
maxstack
2
.
locals
init
(
String
V_0
,
//
Value
System
.
ValueTuple
(
Of
Integer
,
T
)
V_1
)
IL_0000
:
nop
IL_0001
:
ldarg
.
0
IL_0002
:
call
""
Function
C
(
Of
T
).
get_Data
()
As
(
Integer
,
T
)
""
IL_0007
:
stloc
.
1
IL_0008
:
ldloca
.
s
V_1
IL_000a
:
ldflda
""
System
.
ValueTuple
(
Of
Integer
,
T
).
Item2
As
T
""
IL_000f
:
dup
IL_0010
:
ldobj
""
T
""
IL_0015
:
box
""
T
""
IL_001a
:
brtrue
.
s
IL_0020
IL_001c
:
pop
IL_001d
:
ldnull
IL_001e
:
br
.
s
IL_002f
IL_0020
:
ldobj
""
T
""
IL_0025
:
box
""
T
""
IL_002a
:
call
""
Function
Extensions
.
GetValue
(
Object
)
As
String
""
IL_002f
:
stloc
.
0
IL_0030
:
br
.
s
IL_0032
IL_0032
:
ldloc
.
0
IL_0033
:
ret
}
")
End Sub
<Fact()>
<WorkItem(40690, "
https
:
//
github
.
com
/
dotnet
/
roslyn
/
issues
/
40690
")>
Public Sub ConditionalAccess_InstanceMethod_ValueTuple()
Dim compilationDef =
<compilation>
<file name="
a
.
vb
">
Imports System
Imports System.Runtime.CompilerServices
Public Class C(Of T)
Public ReadOnly Property Data As (Integer, T)
Public Sub New(data As (Integer, T))
Me.Data = data
End Sub
Public ReadOnly Property Value As String
Get
Return Data.Item2?.ToString()
End Get
End Property
End Class
Public Class Main
Public Shared Sub Main()
Dim i = New BGen(Of String)((0, "
abc
"))
Dim r = i.Value
Console.Write(r)
Console.WriteLine(New C(Of String)((0, "
abc
")).Value)
Console.WriteLine(New C(Of String)((0, Nothing)).Value)
Console.WriteLine(New C(Of Integer)((0, 0)).Value)
Console.WriteLine(New C(Of Integer?)((0, 0)).Value)
Console.WriteLine(New C(Of Integer?)((0, Nothing)).Value)
End Sub
End Class
</file>
</compilation>
Dim valueTupleRefs As MetadataReference() = New MetadataReference() {ValueTupleRef, SystemRuntimeFacadeRef}
Dim expectedOutput = "
abc
"
Dim expectedOutput = "
abc
0
0
"
Dim verifier = CompileAndVerify(
CreateCompilationWithMscorlib45AndVBRuntime(compilationDef, options:=TestOptions.DebugExe, references:=valueTupleRefs),
expectedOutput:=expectedOutput)
verifier.VerifyIL("
BGen
(
Of
__T__
).
get_Value
()
", "
verifier.VerifyIL("
C
(
Of
T
).
get_Value
()
", "
{
//
Code
size
71
(
0
x47
)
//
Code
size
48
(
0
x30
)
.
maxstack
2
.
locals
init
(
String
V_0
,
//
Value
System
.
ValueTuple
(
Of
Integer
,
__T__
)
V_1
,
__T__
V_2
)
System
.
ValueTuple
(
Of
Integer
,
T
)
V_1
)
IL_0000
:
nop
IL_0001
:
ldarg
.
0
IL_0002
:
call
""
Function
BGen
(
Of
__T__
).
get_Data
()
As
(
Integer
,
__T__
)
""
IL_0002
:
call
""
Function
C
(
Of
T
).
get_Data
()
As
(
Integer
,
T
)
""
IL_0007
:
stloc
.
1
IL_0008
:
ldloca
.
s
V_1
IL_000a
:
ldflda
""
System
.
ValueTuple
(
Of
Integer
,
__T__
).
Item2
As
__T__
""
IL_000f
:
ldloca
.
s
V_2
IL_0011
:
initobj
""
__T__
""
IL_0017
:
ldloc
.
2
IL_0018
:
box
""
__T__
""
IL_001d
:
brtrue
.
s
IL_0033
IL_001f
:
ldobj
""
__T__
""
IL_0024
:
stloc
.
2
IL_0025
:
ldloca
.
s
V_2
IL_0027
:
ldloc
.
2
IL_0028
:
box
""
__T__
""
IL_002d
:
brtrue
.
s
IL_0033
IL_002f
:
pop
IL_0030
:
ldnull
IL_0031
:
br
.
s
IL_0042
IL_0033
:
ldobj
""
__T__
""
IL_0038
:
box
""
__T__
""
IL_003d
:
call
""
Function
Extensions
.
GetValue
(
Object
)
As
String
""
IL_0042
:
stloc
.
0
IL_0043
:
br
.
s
IL_0045
IL_0045
:
ldloc
.
0
IL_0046
:
ret
IL_000a
:
ldflda
""
System
.
ValueTuple
(
Of
Integer
,
T
).
Item2
As
T
""
IL_000f
:
dup
IL_0010
:
ldobj
""
T
""
IL_0015
:
box
""
T
""
IL_001a
:
brtrue
.
s
IL_0020
IL_001c
:
pop
IL_001d
:
ldnull
IL_001e
:
br
.
s
IL_002b
IL_0020
:
constrained
.
""
T
""
IL_0026
:
callvirt
""
Function
Object
.
ToString
()
As
String
""
IL_002b
:
stloc
.
0
IL_002c
:
br
.
s
IL_002e
IL_002e
:
ldloc
.
0
IL_002f
:
ret
}
")
End Sub
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录