Why does Roslyn generate> comparison instead of a = 1 here?

I recently played with the C # compiler on TryRoslyn, and I ran into a strange problem when checking for inequality turned into more than one. Here is the replay code:

using System; public class C { public void M() { if (Foo() != 0 || Foo() != 0) { Console.WriteLine("Hi!"); } } private int Foo() => 0; } 

and here is the code generated by the decompiler:

 using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Security; using System.Security.Permissions; [assembly: AssemblyVersion("0.0.0.0")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [module: UnverifiableCode] public class C { public void M() { bool flag = this.Foo() != 0 || this.Foo() > 0; // this should be an != check if (flag) { Console.WriteLine("Hi!"); } } private int Foo() { return 0; } } 

Here is a link to play. Why is Roslyn doing this; this is mistake?

Some observations that I made after playing with the code for a while:

  • This only happens with the last boolean expression in the condition. For example, if you add another operator || , this will happen only with the last call to Foo() .

  • This also happens with only 0; if you replace it with 1 or some other number, this will not happen.

+7
c # roslyn
source share
1 answer

The decompiled code is invalid; this is a bug in the decompiler, not in the compiler. The generated IL is correct. Read IL very carefully . You see why the comparison is more than the comparison and the decompilation is wrong?

As for why this codegen only happens for the right side of the operator, which I don't remember. If you want to go to the code generator, it is here:

https://github.com/dotnet/roslyn/blob/master/src/Compilers/CSharp/Portable/CodeGen/EmitOperators.cs

You need the EmitIsNonNullOrZero method.

+11
source share

All Articles