File: CodeGen\CodeGenStringConcat.vb
Web Access
Project: src\src\Compilers\VisualBasic\Test\Emit\Microsoft.CodeAnalysis.VisualBasic.Emit.UnitTests.vbproj (Microsoft.CodeAnalysis.VisualBasic.Emit.UnitTests)
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.
 
Imports Roslyn.Test.Utilities
 
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests
    Public Class CodeGenStringConcat
        Inherits BasicTestBase
 
        <Fact()>
        Public Sub Concat001()
            CompileAndVerify(
<compilation>
    <file name="a.vb">
        <![CDATA[
Imports System        
Module Module1

    Sub Main()
        Dim a = "qqqq"

        Dim b = a & a & a & a

        Console.WriteLine(b)
    End Sub

End Module
]]>
    </file>
</compilation>,
expectedOutput:="qqqqqqqqqqqqqqqq").
            VerifyIL("Module1.Main",
            <![CDATA[
{
  // Code size       19 (0x13)
  .maxstack  4
  IL_0000:  ldstr      "qqqq"
  IL_0005:  dup
  IL_0006:  dup
  IL_0007:  dup
  IL_0008:  call       "Function String.Concat(String, String, String, String) As String"
  IL_000d:  call       "Sub System.Console.WriteLine(String)"
  IL_0012:  ret
}
]]>)
        End Sub
 
        <Fact()>
        Public Sub ConcatMerge()
            CompileAndVerify(
<compilation>
    <file name="a.vb">
        <![CDATA[
Imports System        
Module Module1

    Sub Main()
        Dim a = "qqqq"

        Dim b = a & "A" & "B" & a

        Console.WriteLine(b)
    End Sub

End Module
]]>
    </file>
</compilation>,
expectedOutput:="qqqqABqqqq").
            VerifyIL("Module1.Main",
            <![CDATA[
{
  // Code size       24 (0x18)
  .maxstack  3
  .locals init (String V_0) //a
  IL_0000:  ldstr      "qqqq"
  IL_0005:  stloc.0
  IL_0006:  ldloc.0
  IL_0007:  ldstr      "AB"
  IL_000c:  ldloc.0
  IL_000d:  call       "Function String.Concat(String, String, String) As String"
  IL_0012:  call       "Sub System.Console.WriteLine(String)"
  IL_0017:  ret
}
]]>)
        End Sub
 
        <Fact()>
        Public Sub ConcatMergeParams()
            CompileAndVerify(
<compilation>
    <file name="a.vb">
        <![CDATA[
Imports System        
Module Module1

    Sub Main()
        Dim a = "qqqq"

        Dim b = (a & a & a & a & a &"A") & ("B" & a)

        Console.WriteLine(b)
    End Sub

End Module
]]>
    </file>
</compilation>,
expectedOutput:="qqqqqqqqqqqqqqqqqqqqABqqqq").
            VerifyIL("Module1.Main",
            <![CDATA[
{
  // Code size       55 (0x37)
  .maxstack  4
  .locals init (String V_0) //a
  IL_0000:  ldstr      "qqqq"
  IL_0005:  stloc.0
  IL_0006:  ldc.i4.7
  IL_0007:  newarr     "String"
  IL_000c:  dup
  IL_000d:  ldc.i4.0
  IL_000e:  ldloc.0
  IL_000f:  stelem.ref
  IL_0010:  dup
  IL_0011:  ldc.i4.1
  IL_0012:  ldloc.0
  IL_0013:  stelem.ref
  IL_0014:  dup
  IL_0015:  ldc.i4.2
  IL_0016:  ldloc.0
  IL_0017:  stelem.ref
  IL_0018:  dup
  IL_0019:  ldc.i4.3
  IL_001a:  ldloc.0
  IL_001b:  stelem.ref
  IL_001c:  dup
  IL_001d:  ldc.i4.4
  IL_001e:  ldloc.0
  IL_001f:  stelem.ref
  IL_0020:  dup
  IL_0021:  ldc.i4.5
  IL_0022:  ldstr      "AB"
  IL_0027:  stelem.ref
  IL_0028:  dup
  IL_0029:  ldc.i4.6
  IL_002a:  ldloc.0
  IL_002b:  stelem.ref
  IL_002c:  call       "Function String.Concat(ParamArray String()) As String"
  IL_0031:  call       "Sub System.Console.WriteLine(String)"
  IL_0036:  ret
}
]]>)
        End Sub
 
        <Fact()>
        Public Sub ConcatWithOtherOptimizations()
            Dim result = CompileAndVerify(
<compilation>
    <file name="a.vb">
        <![CDATA[
Imports System        
Module Module1

    Sub Main()
        Dim expr1 = "hi"
        Dim expr2 = "bye"

        ' expr1 is optimized away 
        ' only expr2 should be lifted!!
        Dim f As Func(Of String) = Function() If("abc" & "def" & Nothing, expr1 & "moo" & "baz") & expr2

        System.Console.WriteLine(f())
    End Sub

End Module
]]>
    </file>
</compilation>,
expectedOutput:="abcdefbye")
 
            ' IMPORTANT!!  only  $VB$Local_expr2  should be initialized,
            '              there should not be such thing as $VB$Local_expr1
            result.VerifyIL("Module1.Main",
            <![CDATA[
{
  // Code size       38 (0x26)
  .maxstack  3
  IL_0000:  newobj     "Sub Module1._Closure$__0-0..ctor()"
  IL_0005:  dup
  IL_0006:  ldstr      "bye"
  IL_000b:  stfld      "Module1._Closure$__0-0.$VB$Local_expr2 As String"
  IL_0010:  ldftn      "Function Module1._Closure$__0-0._Lambda$__0() As String"
  IL_0016:  newobj     "Sub System.Func(Of String)..ctor(Object, System.IntPtr)"
  IL_001b:  callvirt   "Function System.Func(Of String).Invoke() As String"
  IL_0020:  call       "Sub System.Console.WriteLine(String)"
  IL_0025:  ret
}
]]>)
        End Sub
 
        <Fact>
        <WorkItem(679120, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/679120")>
        Public Sub ConcatEmptyArray()
            Dim result = CompileAndVerify(
<compilation>
    <file name="a.vb">
        <![CDATA[
Imports System

Module Program
    Sub Main()
        Console.WriteLine("Start")
        Console.WriteLine(String.Concat({}))
        Console.WriteLine(String.Concat({}) + String.Concat({}))
        Console.WriteLine("A" + String.Concat({}))
        Console.WriteLine(String.Concat({}) + "B")
        Console.WriteLine("End")
    End Sub
End Module
]]>
    </file>
</compilation>,
expectedOutput:=<![CDATA[Start


A
B
End
]]>)
 
            result.VerifyIL("Program.Main", <![CDATA[
{
  // Code size       67 (0x43)
  .maxstack  1
  IL_0000:  ldstr      "Start"
  IL_0005:  call       "Sub System.Console.WriteLine(String)"
  IL_000a:  ldc.i4.0
  IL_000b:  newarr     "String"
  IL_0010:  call       "Function String.Concat(ParamArray String()) As String"
  IL_0015:  call       "Sub System.Console.WriteLine(String)"
  IL_001a:  ldstr      ""
  IL_001f:  call       "Sub System.Console.WriteLine(String)"
  IL_0024:  ldstr      "A"
  IL_0029:  call       "Sub System.Console.WriteLine(String)"
  IL_002e:  ldstr      "B"
  IL_0033:  call       "Sub System.Console.WriteLine(String)"
  IL_0038:  ldstr      "End"
  IL_003d:  call       "Sub System.Console.WriteLine(String)"
  IL_0042:  ret
}
]]>)
        End Sub
 
    End Class
End Namespace