Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C#7.2 produces not verifiable il code when direct accessing field of readonly struct field #26196

Closed
Ralf1108 opened this issue Apr 17, 2018 · 2 comments
Labels
Area-Compilers Resolution-Answered The question has been answered

Comments

@Ralf1108
Copy link

Version Used:
Visual Studio 2017
LanguageVersion: C# 7.2

Steps to Reproduce:

  1. Compile program in DEBUG with 'x1' or 'x2' uncommented:
namespace PeVerifyBug
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }

    public class TestClass
    {
        private readonly TestStruct _readonlyValue = new TestStruct(42);

        public TestStruct Value
        {
            get
            {
                //var x1 = _readonlyValue.X;
                //var x2 = _readonlyValue.XX;
                return default(TestStruct);
            }
        }
    }

    public struct TestStruct
    {
        public readonly float X;

        public TestStruct(float x)
        {
            X = x;
        }

        public float XX => X;
    }
}
  1. Run PE-Verify on the result assembly
    I used the one from "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.1 Tools"
    -> Microsoft (R) .NET Framework PE Verifier. Version 4.0.30319.0

Expected Behavior:
pe verifier should not complain.

Actual Behavior:

  • if 'x1' was uncommented, pe verifier complains about:
    [IL]: Error: [C:\Users\xxxx\source\repos\PeVerifyBug\PeVerifyBug\bin\Debug\PeVerifyBug.exe : PeVerifyBug.TestClass::get_Value][offset 0x00000002] Cannot change initonly field outside its .ctor.
  • if 'x2' was uncommented, pe verifier doesn't complain.

Analyzing the il code

  • 'x1'-version:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldflda valuetype PeVerifyBug.TestStruct PeVerifyBug.TestClass::_readonlyValue
IL_0007: ldfld float32 PeVerifyBug.TestStruct::X
IL_000c: stloc.0
IL_000d: ldloca.s 1
IL_000f: initobj PeVerifyBug.TestStruct
IL_0015: ldloc.1
IL_0016: stloc.2
IL_0017: br.s IL_0019

IL_0019: ldloc.2
IL_001a: ret
  • 'x2'-version:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld valuetype PeVerifyBug.TestStruct PeVerifyBug.TestClass::_readonlyValue
IL_0007: stloc.1
IL_0008: ldloca.s 1
IL_000a: call instance float32 PeVerifyBug.TestStruct::get_XX()
IL_000f: stloc.0
IL_0010: ldloca.s 1
IL_0012: initobj PeVerifyBug.TestStruct
IL_0018: ldloc.1
IL_0019: stloc.2
IL_001a: br.s IL_001c

IL_001c: ldloc.2
IL_001d: ret

Additional information
When using LanguageVersion: C# 7.1 both cases work
so I think this is a compiler bug and not a problem of PE verify.

@jcouv
Copy link
Member

jcouv commented Apr 17, 2018

Relates to #21269 and #22772
The C# compiler sometimes emit unverifiable code (by current PEVerify rules). This can happen when using new features, or when re-compiling existing code with LangVersion >= 7.2. In the latter case, a feature flag can be set in the project to restore the non-optimized behavior (if you prefer that).

@jcouv jcouv added Area-Compilers Resolution-Answered The question has been answered labels Apr 17, 2018
@Ralf1108
Copy link
Author

solved it with introducing property getter instead of directly access the fields. Thanks for clarification!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers Resolution-Answered The question has been answered
Projects
None yet
Development

No branches or pull requests

3 participants