I was playing around with the C# compiler on TryRoslyn recently, and I came across a strange problem where an inequality check was getting converted into a greater-than one. Here is the repro 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 that gets 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's the link to the repro. Why does Roslyn do this; is it a bug?
Some observations I've made after playing around with the code for a while:
This only happens with the last boolean expression in the condition. For example if you add another ||
statement, it will only happen with the last call to Foo()
.
It also only happens with 0, specifically; if you substitute it for 1
, or some other number, it won't happen.
NET Compiler Platform (Roslyn) Analyzers inspect your C# or Visual Basic code for style, quality, maintainability, design, and other issues. This inspection or analysis happens during design time in all open files. Analyzers are divided into the following groups: Code style analyzers are built into Visual Studio.
One advantage that Roslyn has is when your application needs a scripting interface. With Roslyn, you can directly compile the script as C# source code with same programming possibilities as the source of the application and directly use it. do you mean after compiling, the script is converted to C# source code?
Roslyn, the . NET Compiler Platform, empowers the C# compiler on . NET Core and allows developers to leverage the rich code analysis APIs to perform code generation, analysis and compilation.
A Source Generator is a . NET Standard 2.0 assembly that is loaded by the compiler along with any analyzers. It's usable in environments where . NET Standard components can be loaded and run.
The decompiled code is wrong; this is a bug in the decompiler, not the compiler. The generated IL is correct. Read the IL very carefully. Do you see why the greater-than comparison is correct and the decompilation is wrong?
As for why this codegen only happens for the right hand side of the operator, that I do not recall. If you want to go spelunking in the code generator it is here:
https://github.com/dotnet/roslyn/blob/master/src/Compilers/CSharp/Portable/CodeGen/EmitOperators.cs
You want method EmitIsNonNullOrZero
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With