Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
2f6c1c58
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,发现更多精彩内容 >>
未验证
提交
2f6c1c58
编写于
1月 10, 2018
作者:
C
Charles Stoner
提交者:
GitHub
1月 10, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Avoid using a ref local for array element l-value (#24070)
上级
bb5d3736
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
931 addition
and
99 deletion
+931
-99
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CompoundAssignmentOperator.cs
...LocalRewriter/LocalRewriter_CompoundAssignmentOperator.cs
+27
-21
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenOperators.cs
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenOperators.cs
+1
-1
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTests.cs
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTests.cs
+204
-0
src/Compilers/VisualBasic/Portable/Lowering/UseTwiceRewriter.vb
...mpilers/VisualBasic/Portable/Lowering/UseTwiceRewriter.vb
+15
-6
src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTests.vb
src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTests.vb
+598
-1
src/Compilers/VisualBasic/Test/Semantic/Semantics/CompoundAssignment.vb
...VisualBasic/Test/Semantic/Semantics/CompoundAssignment.vb
+86
-70
未找到文件。
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CompoundAssignmentOperator.cs
浏览文件 @
2f6c1c58
...
...
@@ -507,29 +507,30 @@ private BoundExpression TransformCompoundAssignmentLHS(BoundExpression originalL
break
;
case
BoundKind
.
ArrayAccess
:
if
(
isDynamicAssignment
)
{
// In non-dynamic array[index] op= R we emit:
// T& tmp = &array[index];
// *tmp = *L op R;
// where T is the type of L.
//
// If L is an array access, the assignment is dynamic, the compile-time of the array is dynamic[]
// and the runtime type of the array is not object[] (but e.g. string[]) the pointer approach is broken.
// T is Object in such case and we can't take a read-write pointer of type Object& to an array element of non-object type.
//
// In this case we rewrite the assignment as follows:
//
// E t_array = array;
// I t_index = index; (possibly more indices)
// T value = t_array[t_index];
// t_array[t_index] = value op R;
var
arrayAccess
=
(
BoundArrayAccess
)
originalLHS
;
var
loweredArray
=
VisitExpression
(
arrayAccess
.
Expression
);
var
loweredIndices
=
VisitList
(
arrayAccess
.
Indices
);
return
SpillArrayElementAccess
(
loweredArray
,
loweredIndices
,
stores
,
temps
);
if
(
isDynamicAssignment
||
!
IsInvariantArray
(
arrayAccess
.
Expression
.
Type
))
{
// In non-dynamic, invariant array[index] op= R we emit:
// T& tmp = &array[index];
// *tmp = *L op R;
// where T is the type of L.
//
// If L is an array access, the assignment is dynamic, the compile-time of the array is dynamic[]
// and the runtime type of the array is not object[] (but e.g. string[]) the pointer approach is broken.
// T is Object in such case and we can't take a read-write pointer of type Object& to an array element of non-object type.
//
// In the dynamic case, or when the array may be co-variant, we rewrite the assignment as follows:
//
// E t_array = array;
// I t_index = index; (possibly more indices)
// T value = t_array[t_index];
// t_array[t_index] = value op R;
var
loweredArray
=
VisitExpression
(
arrayAccess
.
Expression
);
var
loweredIndices
=
VisitList
(
arrayAccess
.
Indices
);
return
SpillArrayElementAccess
(
loweredArray
,
loweredIndices
,
stores
,
temps
);
}
}
break
;
...
...
@@ -603,6 +604,11 @@ private BoundExpression TransformCompoundAssignmentLHS(BoundExpression originalL
return
variableTemp
;
}
private
static
bool
IsInvariantArray
(
TypeSymbol
type
)
{
return
(
type
as
ArrayTypeSymbol
)?.
ElementType
.
IsSealed
==
true
;
}
private
BoundExpression
BoxReceiver
(
BoundExpression
rewrittenReceiver
,
NamedTypeSymbol
memberContainingType
)
{
return
MakeConversionNode
(
...
...
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenOperators.cs
浏览文件 @
2f6c1c58
...
...
@@ -4860,7 +4860,7 @@ .locals init (int? V_0)
}
[
Fact
]
public
void
TestCompoundOnA
f
ieldOfGeneric
()
public
void
TestCompoundOnA
F
ieldOfGeneric
()
{
var
source
=
@"
class Program
...
...
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTests.cs
浏览文件 @
2f6c1c58
...
...
@@ -16073,5 +16073,209 @@ public static void Main()
CompileAndVerify
(
comp
,
expectedOutput
:
"SpanOpCalled"
,
verify
:
Verification
.
Fails
);
}
[
Fact
]
public
void
ArrayElementCompoundAssignment_Invariant
()
{
string
source
=
@"class C
{
static void Main()
{
F(new string[] { """" }, ""B"");
}
static void F(string[] a, string s)
{
G(a, s);
System.Console.Write(a[0]);
}
static void G(string[] a, string s)
{
a[0] += s;
}
}"
;
var
verifier
=
CompileAndVerify
(
source
,
expectedOutput
:
"B"
);
verifier
.
VerifyIL
(
"C.G"
,
@"{
// Code size 17 (0x11)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema ""string""
IL_0007: dup
IL_0008: ldind.ref
IL_0009: ldarg.1
IL_000a: call ""string string.Concat(string, string)""
IL_000f: stind.ref
IL_0010: ret
}"
);
}
[
WorkItem
(
547533
,
"https://devdiv.visualstudio.com/DevDiv/_workitems?id=547533"
)]
[
Fact
]
public
void
ArrayElementCompoundAssignment_Covariant
()
{
string
source
=
@"class C
{
static void Main()
{
F(new object[] { """" }, ""A"");
F(new string[] { """" }, ""B"");
}
static void F(object[] a, string s)
{
G(a, s);
System.Console.Write(a[0]);
}
static void G(object[] a, string s)
{
a[0] += s;
}
}"
;
var
verifier
=
CompileAndVerify
(
source
,
expectedOutput
:
"AB"
);
verifier
.
VerifyIL
(
"C.G"
,
@"{
// Code size 15 (0xf)
.maxstack 4
.locals init (object[] V_0)
IL_0000: ldarg.0
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: ldc.i4.0
IL_0004: ldloc.0
IL_0005: ldc.i4.0
IL_0006: ldelem.ref
IL_0007: ldarg.1
IL_0008: call ""string string.Concat(object, object)""
IL_000d: stelem.ref
IL_000e: ret
}"
);
}
[
Fact
]
public
void
ArrayElementCompoundAssignment_ValueType
()
{
string
source
=
@"class C
{
static void Main()
{
F(new int[] { 1 }, 2);
}
static void F(int[] a, int i)
{
G(a, i);
System.Console.Write(a[0]);
}
static void G(int[] a, int i)
{
a[0] += i;
}
}"
;
var
verifier
=
CompileAndVerify
(
source
,
expectedOutput
:
"3"
);
verifier
.
VerifyIL
(
"C.G"
,
@"{
// Code size 13 (0xd)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema ""int""
IL_0007: dup
IL_0008: ldind.i4
IL_0009: ldarg.1
IL_000a: add
IL_000b: stind.i4
IL_000c: ret
}"
);
}
[
WorkItem
(
547533
,
"https://devdiv.visualstudio.com/DevDiv/_workitems?id=547533"
)]
[
Fact
]
public
void
ArrayElementCompoundAssignment_Covariant_NonConstantIndex
()
{
string
source
=
@"class C
{
static void Main()
{
F(new object[] { """" }, ""A"");
F(new string[] { """" }, ""B"");
}
static void F(object[] a, string s)
{
G(a, s);
System.Console.Write(a[0]);
}
static void G(object[] a, string s)
{
a[Index(a)] += s;
}
static int Index(object arg)
{
System.Console.Write(arg.GetType().Name);
return 0;
}
}"
;
var
verifier
=
CompileAndVerify
(
source
,
expectedOutput
:
"Object[]AString[]B"
);
verifier
.
VerifyIL
(
"C.G"
,
@"{
// Code size 22 (0x16)
.maxstack 4
.locals init (object[] V_0,
int V_1)
IL_0000: ldarg.0
IL_0001: stloc.0
IL_0002: ldarg.0
IL_0003: call ""int C.Index(object)""
IL_0008: stloc.1
IL_0009: ldloc.0
IL_000a: ldloc.1
IL_000b: ldloc.0
IL_000c: ldloc.1
IL_000d: ldelem.ref
IL_000e: ldarg.1
IL_000f: call ""string string.Concat(object, object)""
IL_0014: stelem.ref
IL_0015: ret
}"
);
}
[
Fact
]
public
void
ArrayElementIncrement_ValueType
()
{
string
source
=
@"class C
{
static void Main()
{
F(new int[] { 1 });
}
static void F(int[] a)
{
G(a);
System.Console.Write(a[0]);
}
static void G(int[] a)
{
a[0]++;
}
}"
;
var
verifier
=
CompileAndVerify
(
source
,
expectedOutput
:
"2"
);
verifier
.
VerifyIL
(
"C.G"
,
@"{
// Code size 13 (0xd)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema ""int""
IL_0007: dup
IL_0008: ldind.i4
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stind.i4
IL_000c: ret
}"
);
}
}
}
src/Compilers/VisualBasic/Portable/Lowering/UseTwiceRewriter.vb
浏览文件 @
2f6c1c58
...
...
@@ -209,6 +209,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Debug
.
Assert
(
node
.
IsLValue
)
#If DONT_USE_BYREF_LOCALS_FOR_USE_TWICE Then
#
Else
If
IsInvariantArray
(
node
.
Expression
.
Type
)
Then
Return
UseTwiceLValue
(
containingMember
,
node
,
arg
)
End
If
#End If
' Note, as an alternative we could capture reference to the array element in a ByRef temp.
' However, without an introduction of an indirect assignment node, IL-gen is unable to distinguish
' when it should assign indirect or should assign a reference. For now, decided to not introduce
...
...
@@ -232,9 +238,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Debug
.
Assert
(
first
.
IsLValue
AndAlso
second
.
IsLValue
)
Return
New
Result
(
first
,
second
)
#
Else
Return
UseTwiceLValue
(
containingMember
,
node
,
arg
)
#End If
End
Function
Private
Shared
Function
IsInvariantArray
(
type
As
TypeSymbol
)
As
Boolean
Dim
value
=
TryCast
(
type
,
ArrayTypeSymbol
)
?
.
ElementType
.
IsNotInheritable
Return
value
.
GetValueOrDefault
()
End
Function
Private
Shared
Function
UseTwiceLValue
(
containingMember
As
Symbol
,
lvalue
As
BoundExpression
,
temporaries
As
ArrayBuilder
(
Of
SynthesizedLocal
))
As
Result
...
...
@@ -274,8 +283,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' easier to implement.
Dim
receiver
As
Result
=
UseTwiceReceiver
(
containingMember
,
node
.
ReceiverOpt
,
arg
)
Dim
first
=
node
.
Update
(
receiver
.
First
,
fieldSymbol
,
node
.
IsLValue
,
node
.
ConstantsInProgressOpt
,
node
.
Type
)
Dim
second
=
node
.
Update
(
receiver
.
Second
,
fieldSymbol
,
node
.
IsLValue
,
node
.
ConstantsInProgressOpt
,
node
.
Type
)
Dim
first
=
node
.
Update
(
receiver
.
First
,
fieldSymbol
,
node
.
IsLValue
,
suppressVirtualCalls
:
=
False
,
node
.
ConstantsInProgressOpt
,
node
.
Type
)
Dim
second
=
node
.
Update
(
receiver
.
Second
,
fieldSymbol
,
node
.
IsLValue
,
suppressVirtualCalls
:
=
False
,
node
.
ConstantsInProgressOpt
,
node
.
Type
)
Debug
.
Assert
(
first
.
IsLValue
AndAlso
second
.
IsLValue
)
Return
New
Result
(
first
,
second
)
...
...
@@ -496,7 +505,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End
Sub
#If DONT_USE_BYREF_LOCALS_FOR_USE_TWICE Then
Private
Shared
Function
UseTwiceReceiver
(
containingMember
As
Symbol
,
receiverOpt
As
BoundExpression
,
arg
As
ArrayBuilder
(
Of
TempLocalSymbo
l
))
As
Result
Private
Shared
Function
UseTwiceReceiver
(
containingMember
As
Symbol
,
receiverOpt
As
BoundExpression
,
arg
As
ArrayBuilder
(
Of
SynthesizedLoca
l
))
As
Result
If
receiverOpt
Is
Nothing
Then
Return
New
Result
(
Nothing
,
Nothing
)
ElseIf
receiverOpt
.
IsLValue
AndAlso
receiverOpt
.
Type
.
IsReferenceType
Then
...
...
src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTests.vb
浏览文件 @
2f6c1c58
...
...
@@ -12487,7 +12487,7 @@ End Class
<WorkItem(745103, "
http
:
//
vstfdevdiv
:
8080
/
DevDiv2
/
DevDiv
/
_workitems
/
edit
/
745103
")>
<Fact()>
Public Sub TestCompoundOnA
f
ieldOfGeneric()
Public Sub TestCompoundOnA
F
ieldOfGeneric()
CompileAndVerify(
<compilation>
<file name="
a
.
vb
">
...
...
@@ -13837,5 +13837,602 @@ End Module
]]>)
End Sub
<Fact>
Public Sub ArrayElementByReference_Invariant()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New String() {"
b
"})
End Sub
Sub F(a() As String)
G(a)
System.Console.Write(a(0))
End Sub
Sub G(a() As String)
H(a(0))
End Sub
Sub H(ByRef s As String)
s = s.ToUpper()
End Sub
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="
B
").
VerifyIL("
M
.
G
",
<![CDATA[
{
// Code size 13 (0xd)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema "
String
"
IL_0007: call "
Sub
M
.
H
(
ByRef
String
)
"
IL_000c: ret
}
]]>)
End Sub
<Fact, WorkItem(547533, "
https
:
//
devdiv
.
visualstudio
.
com
/
DevDiv
/
_workitems
?
id
=
547533
")>
Public Sub ArrayElementByReference_Covariant()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New Object() {"
a
"})
F(New String() {"
b
"})
End Sub
Sub F(a() As Object)
G(a)
System.Console.Write(a(0))
End Sub
Sub G(a() As Object)
H(a(0))
End Sub
Sub H(ByRef s As String)
s = s.ToUpper()
End Sub
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="
AB
").
VerifyIL("
M
.
G
",
<![CDATA[
{
// Code size 21 (0x15)
.maxstack 3
.locals init (String V_0)
IL_0000: ldarg.0
IL_0001: dup
IL_0002: ldc.i4.0
IL_0003: ldelem.ref
IL_0004: call "
Function
Microsoft
.
VisualBasic
.
CompilerServices
.
Conversions
.
ToString
(
Object
)
As
String
"
IL_0009: stloc.0
IL_000a: ldloca.s V_0
IL_000c: call "
Sub
M
.
H
(
ByRef
String
)
"
IL_0011: ldc.i4.0
IL_0012: ldloc.0
IL_0013: stelem.ref
IL_0014: ret
}
]]>)
End Sub
' Generated code results in ArrayTypeMismatchException,
' matching native compiler.
<Fact, WorkItem(547533, "
https
:
//
devdiv
.
visualstudio
.
com
/
DevDiv
/
_workitems
?
id
=
547533
")>
Public Sub ArrayElementByReferenceBase_Covariant()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New Object() {"
a
"})
F(New String() {"
b
"})
End Sub
Sub F(a() As Object)
Try
G(a)
System.Console.Write(a(0))
Catch e As System.Exception
System.Console.Write(e.GetType().Name)
End Try
End Sub
Sub G(a() As Object)
H(a(0))
End Sub
Sub H(ByRef s As Object)
s = s.ToString().ToUpper()
End Sub
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="
AArrayTypeMismatchException
").
VerifyIL("
M
.
G
",
<![CDATA[
{
// Code size 13 (0xd)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema "
Object
"
IL_0007: call "
Sub
M
.
H
(
ByRef
Object
)
"
IL_000c: ret
}
]]>)
End Sub
<Fact, WorkItem(547533, "
https
:
//
devdiv
.
visualstudio
.
com
/
DevDiv
/
_workitems
?
id
=
547533
")>
Public Sub ArrayElementByReference_TypeParameter()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
Dim a = New String() { "
b
" }
Dim b = New B()
b.F(a)
System.Console.Write(a(0))
End Sub
End Module
MustInherit Class A(Of T)
Friend MustOverride Sub F(Of U As T)(a() As U)
End Class
Class B
Inherits A(Of String)
Friend Overrides Sub F(Of U As String)(a() As U)
G(a(0))
End Sub
Sub G(ByRef s As String)
s = s.ToUpper()
End Sub
End Class
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="
B
").
VerifyIL("
B
.
F
",
<![CDATA[
{
// Code size 42 (0x2a)
.maxstack 3
.locals init (U() V_0,
String V_1)
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: dup
IL_0003: stloc.0
IL_0004: ldc.i4.0
IL_0005: ldelem "
U
"
IL_000a: box "
U
"
IL_000f: castclass "
String
"
IL_0014: stloc.1
IL_0015: ldloca.s V_1
IL_0017: call "
Sub
B
.
G
(
ByRef
String
)
"
IL_001c: ldloc.0
IL_001d: ldc.i4.0
IL_001e: ldloc.1
IL_001f: unbox.any "
U
"
IL_0024: stelem "
U
"
IL_0029: ret
}
]]>)
End Sub
<Fact, WorkItem(547533, "
https
:
//
devdiv
.
visualstudio
.
com
/
DevDiv
/
_workitems
?
id
=
547533
")>
Public Sub ArrayElementByReference_StructConstraint()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
Dim a = New Integer() { 1 }
Dim b = New B()
b.F(a)
System.Console.Write(a(0))
End Sub
End Module
MustInherit Class A(Of T)
Friend MustOverride Sub F(Of U As {T, Structure})(a() As U)
End Class
Class B
Inherits A(Of Integer)
Friend Overrides Sub F(Of U As {Integer, Structure})(a() As U)
G(a(0))
End Sub
Sub G(ByRef i As Integer)
i += 1
End Sub
End Class
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="
2
").
VerifyIL("
B
.
F
",
<![CDATA[
{
// Code size 47 (0x2f)
.maxstack 3
.locals init (U() V_0,
Integer V_1)
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: dup
IL_0003: stloc.0
IL_0004: ldc.i4.0
IL_0005: ldelem "
U
"
IL_000a: box "
U
"
IL_000f: unbox.any "
Integer
"
IL_0014: stloc.1
IL_0015: ldloca.s V_1
IL_0017: call "
Sub
B
.
G
(
ByRef
Integer
)
"
IL_001c: ldloc.0
IL_001d: ldc.i4.0
IL_001e: ldloc.1
IL_001f: box "
Integer
"
IL_0024: unbox.any "
U
"
IL_0029: stelem "
U
"
IL_002e: ret
}
]]>)
End Sub
<Fact>
Public Sub ArrayElementByReference_ValueType()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New Integer() {1})
End Sub
Sub F(a() As Integer)
G(a)
System.Console.Write(a(0))
End Sub
Sub G(a() As Integer)
H(a(0))
End Sub
Sub H(ByRef i As Integer)
i = 2
End Sub
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="
2
").
VerifyIL("
M
.
G
",
<![CDATA[
{
// Code size 13 (0xd)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema "
Integer
"
IL_0007: call "
Sub
M
.
H
(
ByRef
Integer
)
"
IL_000c: ret
}
]]>)
End Sub
<Fact>
Public Sub ArrayElementCompoundAssignment_Invariant()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New String() {
""
}, "
B
")
End Sub
Sub F(a() As String, s As String)
G(a, s)
System.Console.Write(a(0))
End Sub
Sub G(a() As String, s As String)
a(0) += s
End Sub
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="
B
").
VerifyIL("
M
.
G
",
<![CDATA[
{
// Code size 19 (0x13)
.maxstack 3
.locals init (String& V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema "
String
"
IL_0007: dup
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: ldind.ref
IL_000b: ldarg.1
IL_000c: call "
Function
String
.
Concat
(
String
,
String
)
As
String
"
IL_0011: stind.ref
IL_0012: ret
}
]]>)
End Sub
<Fact, WorkItem(547533, "
https
:
//
devdiv
.
visualstudio
.
com
/
DevDiv
/
_workitems
?
id
=
547533
")>
Public Sub ArrayElementCompoundAssignment_Covariant()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New Object() {
""
}, "
A
")
F(New String() {
""
}, "
B
")
End Sub
Sub F(a() As Object, s As String)
G(a, s)
System.Console.Write(a(0))
End Sub
Sub G(a() As Object, s As String)
a(0) += s
End Sub
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="
AB
").
VerifyIL("
M
.
G
",
<![CDATA[
{
// Code size 15 (0xf)
.maxstack 4
.locals init (Object() V_0)
IL_0000: ldarg.0
IL_0001: dup
IL_0002: stloc.0
IL_0003: ldc.i4.0
IL_0004: ldloc.0
IL_0005: ldc.i4.0
IL_0006: ldelem.ref
IL_0007: ldarg.1
IL_0008: call "
Function
Microsoft
.
VisualBasic
.
CompilerServices
.
Operators
.
AddObject
(
Object
,
Object
)
As
Object
"
IL_000d: stelem.ref
IL_000e: ret
}
]]>)
End Sub
<Fact>
Public Sub ArrayElementCompoundAssignment_ValueType()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New Integer() {1}, 2)
End Sub
Sub F(a() As Integer, i As Integer)
G(a, i)
System.Console.Write(a(0))
End Sub
Sub G(a() As Integer, i As Integer)
a(0) += i
End Sub
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="
3
").
VerifyIL("
M
.
G
",
<![CDATA[
{
// Code size 15 (0xf)
.maxstack 3
.locals init (Integer& V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema "
Integer
"
IL_0007: dup
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: ldind.i4
IL_000b: ldarg.1
IL_000c: add.ovf
IL_000d: stind.i4
IL_000e: ret
}
]]>)
End Sub
<Fact, WorkItem(547533, "
https
:
//
devdiv
.
visualstudio
.
com
/
DevDiv
/
_workitems
?
id
=
547533
")>
Public Sub ArrayElementCompoundAssignment_Covariant_NonConstantIndex()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New Object() {
""
}, "
A
")
F(New String() {
""
}, "
B
")
End Sub
Sub F(a() As Object, s As String)
G(a, s)
System.Console.Write(a(0))
End Sub
Sub G(a() As Object, s As String)
a(Index(a)) += s
End Sub
Function Index(arg As Object) As Integer
System.Console.Write(arg.GetType().Name)
Return 0
End Function
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="
Object
[]
AString
[]
B
").
VerifyIL("
M
.
G
",
<![CDATA[
{
// Code size 22 (0x16)
.maxstack 4
.locals init (Object() V_0,
Integer V_1)
IL_0000: ldarg.0
IL_0001: dup
IL_0002: stloc.0
IL_0003: ldarg.0
IL_0004: call "
Function
M
.
Index
(
Object
)
As
Integer
"
IL_0009: dup
IL_000a: stloc.1
IL_000b: ldloc.0
IL_000c: ldloc.1
IL_000d: ldelem.ref
IL_000e: ldarg.1
IL_000f: call "
Function
Microsoft
.
VisualBasic
.
CompilerServices
.
Operators
.
AddObject
(
Object
,
Object
)
As
Object
"
IL_0014: stelem.ref
IL_0015: ret
}
]]>)
End Sub
<Fact>
Public Sub ArrayElementWithBlock_Invariant()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New String() {"
B
"})
End Sub
Sub F(a() As String)
System.Console.Write(G(a))
End Sub
Function G(a() As String) As String
With a(0)
Return .ToString() + .ToLower()
End With
End Function
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="
Bb
").
VerifyIL("
M
.
G
",
<![CDATA[
{
// Code size 22 (0x16)
.maxstack 2
.locals init (String V_0) //$W0
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelem.ref
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: callvirt "
Function
String
.
ToString
()
As
String
"
IL_000a: ldloc.0
IL_000b: callvirt "
Function
String
.
ToLower
()
As
String
"
IL_0010: call "
Function
String
.
Concat
(
String
,
String
)
As
String
"
IL_0015: ret
}
]]>)
End Sub
<Fact>
Public Sub ArrayElementWithBlock_Covariant()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New Object() {"
A
"})
F(New String() {"
B
"})
End Sub
Sub F(a() As Object)
System.Console.Write(G(a))
End Sub
Function G(a() As Object) As String
With a(0)
Return .ToString() + .ToLower()
End With
End Function
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="
AaBb
").
VerifyIL("
M
.
G
",
<![CDATA[
{
// Code size 42 (0x2a)
.maxstack 8
.locals init (Object V_0) //$W0
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelem.ref
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: callvirt "
Function
Object
.
ToString
()
As
String
"
IL_000a: ldloc.0
IL_000b: ldnull
IL_000c: ldstr "
ToLower
"
IL_0011: ldc.i4.0
IL_0012: newarr "
Object
"
IL_0017: ldnull
IL_0018: ldnull
IL_0019: ldnull
IL_001a: call "
Function
Microsoft
.
VisualBasic
.
CompilerServices
.
NewLateBinding
.
LateGet
(
Object
,
System
.
Type
,
String
,
Object
(),
String
(),
System
.
Type
(),
Boolean
())
As
Object
"
IL_001f: call "
Function
Microsoft
.
VisualBasic
.
CompilerServices
.
Operators
.
AddObject
(
Object
,
Object
)
As
Object
"
IL_0024: call "
Function
Microsoft
.
VisualBasic
.
CompilerServices
.
Conversions
.
ToString
(
Object
)
As
String
"
IL_0029: ret
}
]]>)
End Sub
<Fact>
Public Sub ArrayElementWithBlock_ValueType()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New Integer() {1})
End Sub
Sub F(a() As Integer)
System.Console.Write(G(a))
End Sub
Function G(a() As Integer) As String
With a(0)
Return .ToString() + .ToString()
End With
End Function
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="
11
").
VerifyIL("
M
.
G
",
<![CDATA[
{
// Code size 26 (0x1a)
.maxstack 2
.locals init (Integer& V_0) //$W0
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema "
Integer
"
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: call "
Function
Integer
.
ToString
()
As
String
"
IL_000e: ldloc.0
IL_000f: call "
Function
Integer
.
ToString
()
As
String
"
IL_0014: call "
Function
String
.
Concat
(
String
,
String
)
As
String
"
IL_0019: ret
}
]]>)
End Sub
End Class
End Namespace
src/Compilers/VisualBasic/Test/Semantic/Semantics/CompoundAssignment.vb
浏览文件 @
2f6c1c58
...
...
@@ -1465,25 +1465,29 @@ Position set for item 'Goo'
verifier
.
VerifyIL
(
"Program.Shift"
,
<
!
[
CDATA
[
{
//
Code
size
46
(
0
x2e
)
//
Code
size
56
(
0
x38
)
.
maxstack
4
.
locals
init
(
T
&
V_0
)
.
locals
init
(
T
()
V_0
)
IL_0000
:
ldarg
.
0
IL_0001
:
ldc
.
i4
.
0
IL_0002
:
ldelema
"T"
IL_0007
:
dup
IL_0008
:
stloc
.
0
IL_0009
:
ldloc
.
0
IL_000a
:
constrained
.
"
T
"
IL_0010: callvirt "
Function
IMoveable
.
get_Position
()
As
Integer
"
IL_0015: ldarg.0
IL_0016: ldc.i4.0
IL_0017: ldelema "
T
"
IL_001c: call "
Function
Program
.
GetOffset
(
Of
T
)(
ByRef
T
)
As
Integer
"
IL_0021: add.ovf
IL_0022: constrained. "
T
"
IL_0028: callvirt "
Sub
IMoveable
.
set_Position
(
Integer
)
"
IL_002d: ret
IL_0001
:
dup
IL_0002
:
stloc
.
0
IL_0003
:
ldc
.
i4
.
0
IL_0004
:
readonly
.
IL_0006
:
ldelema
"T"
IL_000b
:
ldloc
.
0
IL_000c
:
ldc
.
i4
.
0
IL_000d
:
readonly
.
IL_000f
:
ldelema
"T"
IL_0014
:
constrained
.
"
T
"
IL_001a: callvirt "
Function
IMoveable
.
get_Position
()
As
Integer
"
IL_001f: ldarg.0
IL_0020: ldc.i4.0
IL_0021: ldelema "
T
"
IL_0026: call "
Function
Program
.
GetOffset
(
Of
T
)(
ByRef
T
)
As
Integer
"
IL_002b: add.ovf
IL_002c: constrained. "
T
"
IL_0032: callvirt "
Sub
IMoveable
.
set_Position
(
Integer
)
"
IL_0037: ret
}
]]>)
...
...
@@ -1499,27 +1503,31 @@ Position set for item 'Bar'
verifier.VerifyIL("
Program
.
Shift
",
<![CDATA[
{
// Code size
48 (0x30
)
// Code size
58 (0x3a
)
.maxstack 4
.locals init (T
&
V_0)
.locals init (T
()
V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: ldelema "
T
"
IL_0008: dup
IL_0009: stloc.0
IL_000a: ldloc.0
IL_000b: constrained. "
T
"
IL_0011: callvirt "
Function
IMoveable
.
get_Position
()
As
Integer
"
IL_0016: ldarg.0
IL_0017: ldc.i4.0
IL_0018: ldelema "
T
"
IL_001d: call "
Function
Program
.
GetOffset
(
Of
T
)(
ByRef
T
)
As
Integer
"
IL_0022: add.ovf
IL_0023: constrained. "
T
"
IL_0029: callvirt "
Sub
IMoveable
.
set_Position
(
Integer
)
"
IL_002e: nop
IL_002f: ret
IL_0002: dup
IL_0003: stloc.0
IL_0004: ldc.i4.0
IL_0005: readonly.
IL_0007: ldelema "
T
"
IL_000c: ldloc.0
IL_000d: ldc.i4.0
IL_000e: readonly.
IL_0010: ldelema "
T
"
IL_0015: constrained. "
T
"
IL_001b: callvirt "
Function
IMoveable
.
get_Position
()
As
Integer
"
IL_0020: ldarg.0
IL_0021: ldc.i4.0
IL_0022: ldelema "
T
"
IL_0027: call "
Function
Program
.
GetOffset
(
Of
T
)(
ByRef
T
)
As
Integer
"
IL_002c: add.ovf
IL_002d: constrained. "
T
"
IL_0033: callvirt "
Sub
IMoveable
.
set_Position
(
Integer
)
"
IL_0038: nop
IL_0039: ret
}
]]>)
End Sub
...
...
@@ -2122,25 +2130,29 @@ Position set for item 'Goo'
verifier
.
VerifyIL
(
"Program.Shift"
,
<
!
[
CDATA
[
{
//
Code
size
46
(
0
x2e
)
//
Code
size
56
(
0
x38
)
.
maxstack
4
.
locals
init
(
T
&
V_0
)
.
locals
init
(
T
()
V_0
)
IL_0000
:
ldarg
.
0
IL_0001
:
ldc
.
i4
.
0
IL_0002
:
ldelema
"T"
IL_0007
:
dup
IL_0008
:
stloc
.
0
IL_0009
:
ldloc
.
0
IL_000a
:
constrained
.
"
T
"
IL_0010: callvirt "
Function
IMoveable
.
get_Position
()
As
Integer
"
IL_0015: ldarg.0
IL_0016: ldc.i4.0
IL_0017: ldelema "
T
"
IL_001c: call "
Function
Program
.
GetOffset
(
Of
T
)(
ByRef
T
)
As
Integer
"
IL_0021: add.ovf
IL_0022: constrained. "
T
"
IL_0028: callvirt "
Sub
IMoveable
.
set_Position
(
Integer
)
"
IL_002d: ret
IL_0001
:
dup
IL_0002
:
stloc
.
0
IL_0003
:
ldc
.
i4
.
0
IL_0004
:
readonly
.
IL_0006
:
ldelema
"T"
IL_000b
:
ldloc
.
0
IL_000c
:
ldc
.
i4
.
0
IL_000d
:
readonly
.
IL_000f
:
ldelema
"T"
IL_0014
:
constrained
.
"
T
"
IL_001a: callvirt "
Function
IMoveable
.
get_Position
()
As
Integer
"
IL_001f: ldarg.0
IL_0020: ldc.i4.0
IL_0021: ldelema "
T
"
IL_0026: call "
Function
Program
.
GetOffset
(
Of
T
)(
ByRef
T
)
As
Integer
"
IL_002b: add.ovf
IL_002c: constrained. "
T
"
IL_0032: callvirt "
Sub
IMoveable
.
set_Position
(
Integer
)
"
IL_0037: ret
}
]]>)
...
...
@@ -2156,27 +2168,31 @@ Position set for item 'Bar'
verifier.VerifyIL("
Program
.
Shift
",
<![CDATA[
{
// Code size
48 (0x30
)
// Code size
58 (0x3a
)
.maxstack 4
.locals init (T
&
V_0)
.locals init (T
()
V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: ldelema "
T
"
IL_0008: dup
IL_0009: stloc.0
IL_000a: ldloc.0
IL_000b: constrained. "
T
"
IL_0011: callvirt "
Function
IMoveable
.
get_Position
()
As
Integer
"
IL_0016: ldarg.0
IL_0017: ldc.i4.0
IL_0018: ldelema "
T
"
IL_001d: call "
Function
Program
.
GetOffset
(
Of
T
)(
ByRef
T
)
As
Integer
"
IL_0022: add.ovf
IL_0023: constrained. "
T
"
IL_0029: callvirt "
Sub
IMoveable
.
set_Position
(
Integer
)
"
IL_002e: nop
IL_002f: ret
IL_0002: dup
IL_0003: stloc.0
IL_0004: ldc.i4.0
IL_0005: readonly.
IL_0007: ldelema "
T
"
IL_000c: ldloc.0
IL_000d: ldc.i4.0
IL_000e: readonly.
IL_0010: ldelema "
T
"
IL_0015: constrained. "
T
"
IL_001b: callvirt "
Function
IMoveable
.
get_Position
()
As
Integer
"
IL_0020: ldarg.0
IL_0021: ldc.i4.0
IL_0022: ldelema "
T
"
IL_0027: call "
Function
Program
.
GetOffset
(
Of
T
)(
ByRef
T
)
As
Integer
"
IL_002c: add.ovf
IL_002d: constrained. "
T
"
IL_0033: callvirt "
Sub
IMoveable
.
set_Position
(
Integer
)
"
IL_0038: nop
IL_0039: ret
}
]]>)
End Sub
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录