Search

Compiler produces wrong IL code for managed c++ (only release compile) VS2010 SP1 by Amberg

Closed
as Fixed Help for as Fixed

3
0
Sign in
to vote
Type: Bug
ID: 746946
Opened: 6/6/2012 5:10:55 AM
Access Restriction: Public
0
Workaround(s)
1
User(s) can reproduce this bug
The following managed c++ code generates wrong IL code. This leads to an Access violation.

public ref class Test
{
public:
    int CompilerBugMethod()
    {
        int nTickCount = 0;
        Object^ obj = gcnew Object();
        if(System::Environment::TickCount > 50)
        {
            nTickCount = System::Environment::TickCount;
        }
        String^ strObjToString = obj->ToString();
        return nTickCount;
    }
};

int main(array<System::String ^> ^args)
{
    Test^ test = gcnew Test();
    test->CompilerBugMethod();
    return 0;
}

---> IL Code:

.method public hidebysig
    instance int32 CompilerBugMethod () cil managed
{
    // Method begins at RVA 0x1000
    // Code size 28 (0x1c)
    .maxstack 4

    IL_0000: ldc.i4.0
    IL_0001: newobj instance void [mscorlib]System.Object::.ctor()
    IL_0006: call int32 [mscorlib]System.Environment::get_TickCount()
    IL_000b: ldc.i4.s 50
    IL_000d: ble.s IL_0015

    IL_000f: pop
    IL_0010: call int32 [mscorlib]System.Environment::get_TickCount()

    IL_0015: callvirt instance string [mscorlib]System.Object::ToString()
    IL_001a: pop
    IL_001b: ret
} // end of method Test::CompilerBugMethod

Details (expand)

Visual Studio/Team Foundation Server/.NET Framework Tooling Version

.NET Framework 4

Steps to reproduce

Compile and run this code in a default managed cpp project:

#include "stdafx.h"

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace GenericToolsCs;

public ref class Test
{
public:
    int CompilerBugMethod()
    {
        int nTickCount = 0;
        Object^ obj = gcnew Object();
        if(System::Environment::TickCount > 50)
        {
            nTickCount = System::Environment::TickCount;
        }
        String^ strObjToString = obj->ToString();
        return nTickCount;
    }
};

int main(array<System::String ^> ^args)
{
    Test^ test = gcnew Test();
    test->CompilerBugMethod();
    return 0;
}

Product Language

English

Operating System

Windows 7

Operating System Language

English

Actual results

Decompiled IL with ILSpy:

public int CompilerBugMethod()
{
    int arg_1B_0 = 0;
    object arg_15_0 = new object();
    if (Environment.TickCount > 50)
    {
        arg_15_0 = Environment.TickCount;
    }
    arg_15_0.ToString();
    return arg_1B_0;
}

Expected results

public int CompilerBugMethod()
{
    int nTickCount = 0;
    object obj = new object();
    if (Environment.TickCount > 50)
    {
        nTickCount = Environment.TickCount;
    }
    string strObjToString = obj.ToString();
    return nTickCount;
}
File Attachments
0 attachments
Sign in to post a comment.
Posted by Microsoft on 6/14/2012 at 3:20 PM
The workaround is to turn off optimization for the impacted functions by using "#pragma optimize("", off)".

Unfortunately there is no easy way to tell whether the problem would occur from source code, as the problem occurred after inlining and optimiztaion, at which point, the generated intermediate representation of the code can look much different than what is in source code.
Posted by Microsoft on 6/14/2012 at 2:46 PM
Sorry I should have pasted the disassembly code from release build:

.method public hidebysig instance int32 CompilerBugMethod() cil managed
{
// Code size     30 (0x1e)
.maxstack 3
.locals ([0] int32 nTickCount)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: newobj     instance void [mscorlib]System.Object::.ctor()
IL_0007: call     int32 [mscorlib]System.Environment::get_TickCount()
IL_000c: ldc.i4.s 50
IL_000e: ble.s     IL_0016
IL_0010: call     int32 [mscorlib]System.Environment::get_TickCount()
IL_0015: stloc.0
IL_0016: callvirt instance string [mscorlib]System.Object::ToString()
IL_001b: pop
IL_001c: ldloc.0
IL_001d: ret
} // end of method Test::CompilerBugMethod
Posted by Patrick Grawehr on 6/11/2012 at 12:34 AM
Is there a workaround or a specific way to identify possible occurences of this problem in the source? The code that generates the problem is not realy complex, so there could be several functions in the code that are affected by this.
Posted by Microsoft on 6/8/2012 at 11:03 AM
Thanks for your report.

The problem has already been fixed. Using VS 2012 RC compiler, we got these ILs from debug build:

.method public hidebysig instance int32 CompilerBugMethod() cil managed
{
// Code size     38 (0x26)
.maxstack 2
.locals (int32 V_0,
         object V_1,
         int32 V_2,
         string V_3)
IL_0000: ldnull
IL_0001: stloc.1
IL_0002: ldnull
IL_0003: stloc.3
IL_0004: ldc.i4.0
IL_0005: stloc.0
IL_0006: newobj     instance void [mscorlib]System.Object::.ctor()
IL_000b: stloc.1
IL_000c: call     int32 [mscorlib]System.Environment::get_TickCount()
IL_0011: ldc.i4.s 50
IL_0013: ble.s     IL_001b
IL_0015: call     int32 [mscorlib]System.Environment::get_TickCount()
IL_001a: stloc.0
IL_001b: ldloc.1
IL_001c: callvirt instance string [mscorlib]System.Object::ToString()
IL_0021: stloc.3
IL_0022: ldloc.0
IL_0023: stloc.2
IL_0024: ldloc.2
IL_0025: ret
} // end of method Test::CompilerBugMethod
Posted by Microsoft on 6/6/2012 at 9:42 PM
Thanks for your feedback.

We are rerouting this issue to the appropriate group within the Visual Studio Product Team for triage and resolution. These specialized experts will follow-up with your issue.
Posted by MS-Moderator01 on 6/6/2012 at 6:52 AM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)
Sign in to post a workaround.