Browse Source

added notnullwhen annotations

pull/3287/head
apmoskevitz 10 months ago
parent
commit
30421e7309
  1. 1
      .editorconfig
  2. 11
      ICSharpCode.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs
  3. 5
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  4. 6
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  5. 8
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  6. 54
      ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs
  7. 3
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs
  8. 3
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  9. 5
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  10. 7
      ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs
  11. 3
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs
  12. 17
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs
  13. 5
      ICSharpCode.Decompiler/DebugInfo/IDebugInfoProvider.cs
  14. 2
      ICSharpCode.Decompiler/DecompilerSettings.cs
  15. 16
      ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs
  16. 13
      ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs
  17. 3
      ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs
  18. 36
      ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs
  19. 1
      ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs
  20. 2
      ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs
  21. 3
      ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs
  22. 2
      ICSharpCode.Decompiler/IL/ILReader.cs
  23. 5
      ICSharpCode.Decompiler/IL/Instructions/DeconstructInstruction.cs
  24. 17
      ICSharpCode.Decompiler/IL/Transforms/DeconstructionTransform.cs
  25. 3
      ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
  26. 6
      ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs
  27. 9
      ICSharpCode.Decompiler/IL/Transforms/DynamicCallSiteTransform.cs
  28. 3
      ICSharpCode.Decompiler/IL/Transforms/DynamicIsEventAssignmentTransform.cs
  29. 5
      ICSharpCode.Decompiler/IL/Transforms/EarlyExpressionTransforms.cs
  30. 7
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
  31. 14
      ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs
  32. 13
      ICSharpCode.Decompiler/IL/Transforms/IndexRangeTransform.cs
  33. 3
      ICSharpCode.Decompiler/IL/Transforms/InterpolatedStringTransform.cs
  34. 3
      ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs
  35. 14
      ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs
  36. 10
      ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs
  37. 63
      ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs
  38. 9
      ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs
  39. 43
      ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs
  40. 36
      ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs
  41. 7
      ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs
  42. 13
      ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs
  43. 19
      ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs
  44. 3
      ICSharpCode.Decompiler/IL/Transforms/TupleTransform.cs
  45. 3
      ICSharpCode.Decompiler/IL/Transforms/UserDefinedLogicTransform.cs
  46. 3
      ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs
  47. 5
      ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
  48. 3
      ICSharpCode.Decompiler/Metadata/ReferenceLoadInfo.cs
  49. 2
      ICSharpCode.Decompiler/TypeSystem/GenericContext.cs
  50. 5
      ICSharpCode.Decompiler/TypeSystem/TaskType.cs
  51. 4
      ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs

1
.editorconfig

@ -152,6 +152,7 @@ dotnet_diagnostic.MEF006.severity = silent @@ -152,6 +152,7 @@ dotnet_diagnostic.MEF006.severity = silent
dotnet_diagnostic.IDE2003.severity = silent
#cleared null error types
dotnet_diagnostic.CS8612.severity = error
dotnet_diagnostic.CS8714.severity = error
dotnet_diagnostic.CS8765.severity = error
dotnet_diagnostic.CS8766.severity = error

11
ICSharpCode.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs

@ -22,15 +22,16 @@ using System.Linq; @@ -22,15 +22,16 @@ using System.Linq;
using System.Reflection.Metadata;
using System.Xml.Linq;
using ICSharpCode.BamlDecompiler.Xaml;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.BamlDecompiler.Xaml;
namespace ICSharpCode.BamlDecompiler.Rewrite
{
using System.Diagnostics.CodeAnalysis;
using ICSharpCode.Decompiler.TypeSystem;
internal class ConnectionIdRewritePass : IRewritePass
@ -249,7 +250,7 @@ namespace ICSharpCode.BamlDecompiler.Rewrite @@ -249,7 +250,7 @@ namespace ICSharpCode.BamlDecompiler.Rewrite
}
}
bool MatchFieldAssignment(ILInstruction inst, out FieldAssignment field)
bool MatchFieldAssignment(ILInstruction inst, [NotNullWhen(true)] out FieldAssignment field)
{
field = null;
if (!inst.MatchStFld(out _, out var fld, out var value) || !value.MatchCastClass(out var arg, out _)
@ -293,7 +294,7 @@ namespace ICSharpCode.BamlDecompiler.Rewrite @@ -293,7 +294,7 @@ namespace ICSharpCode.BamlDecompiler.Rewrite
// callvirt set_Event(ldloc v, ldsfld eventName)
// callvirt set_Handler(ldloc v, newobj RoutedEventHandler..ctor(ldloc this, ldftn eventHandler))
// callvirt Add(callvirt get_Setters(castclass System.Windows.Style(ldloc target)), ldloc v)
bool MatchEventSetterCreation(Block b, ref int pos, out EventRegistration @event)
bool MatchEventSetterCreation(Block b, ref int pos, [NotNullWhen(true)] out EventRegistration? @event)
{
@event = null;
if (!b.FinalInstruction.MatchNop())
@ -362,7 +363,7 @@ namespace ICSharpCode.BamlDecompiler.Rewrite @@ -362,7 +363,7 @@ namespace ICSharpCode.BamlDecompiler.Rewrite
return true;
}
bool MatchSimpleEventRegistration(ILInstruction inst, out EventRegistration @event)
bool MatchSimpleEventRegistration(ILInstruction inst, [NotNullWhen(true)] out EventRegistration? @event)
{
@event = null;
if (!(inst is CallInstruction call) || call.OpCode == OpCode.NewObj)

5
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
@ -406,7 +407,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -406,7 +407,7 @@ namespace ICSharpCode.Decompiler.CSharp
static readonly Regex automaticPropertyBackingFieldRegex = new Regex(@"^<(.*)>k__BackingField$",
RegexOptions.Compiled | RegexOptions.CultureInvariant);
static bool IsAutomaticPropertyBackingField(FieldDefinition field, MetadataReader metadata, out string? propertyName)
static bool IsAutomaticPropertyBackingField(FieldDefinition field, MetadataReader metadata, [NotNullWhen(true)] out string? propertyName)
{
propertyName = null;
var name = metadata.GetString(field.Name);
@ -1917,7 +1918,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1917,7 +1918,7 @@ namespace ICSharpCode.Decompiler.CSharp
return found;
}
bool FindAttribute(EntityDeclaration entityDecl, KnownAttribute attributeType, out Syntax.Attribute? attribute)
bool FindAttribute(EntityDeclaration entityDecl, KnownAttribute attributeType, [NotNullWhen(true)] out Syntax.Attribute? attribute)
{
attribute = null;
foreach (var section in entityDecl.Attributes)

6
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -698,7 +698,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -698,7 +698,7 @@ namespace ICSharpCode.Decompiler.CSharp
);
}
private bool TryGetStringInterpolationTokens(ArgumentList argumentList, out string? format, out List<(TokenKind Kind, int Index, int Alignment, string? Format)>? tokens)
private bool TryGetStringInterpolationTokens(ArgumentList argumentList, [NotNullWhen(true)] out string? format, [NotNullWhen(true)] out List<(TokenKind Kind, int Index, int Alignment, string? Format)>? tokens)
{
tokens = null;
format = null;
@ -1823,7 +1823,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1823,7 +1823,7 @@ namespace ICSharpCode.Decompiler.CSharp
return expr.Expression.WithRR(new MemberResolveResult(null, method));
}
ExpressionWithResolveResult BuildDelegateReference(IMethod method, IMethod invokeMethod, ExpectedTargetDetails expectedTargetDetails, ILInstruction thisArg)
ExpressionWithResolveResult BuildDelegateReference(IMethod method, IMethod? invokeMethod, ExpectedTargetDetails expectedTargetDetails, ILInstruction thisArg)
{
ExpressionBuilder expressionBuilder = this.expressionBuilder;
ExpressionWithResolveResult targetExpression;
@ -1983,7 +1983,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1983,7 +1983,7 @@ namespace ICSharpCode.Decompiler.CSharp
return oce;
}
bool IsUnambiguousMethodReference(ExpectedTargetDetails expectedTargetDetails, IMethod method, ResolveResult target, IReadOnlyList<IType> typeArguments, bool isExtensionMethodReference, out ResolveResult result)
bool IsUnambiguousMethodReference(ExpectedTargetDetails expectedTargetDetails, IMethod method, ResolveResult target, IReadOnlyList<IType> typeArguments, bool isExtensionMethodReference, [NotNullWhen(true)] out ResolveResult result)
{
Log.WriteLine("IsUnambiguousMethodReference: Performing overload resolution for " + method);

8
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -3545,7 +3545,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3545,7 +3545,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
var stloc = block.Instructions.FirstOrDefault() as StLoc;
var final = block.FinalInstruction as LdLoc;
if (stloc == null || final == null || !stloc.Value.MatchNewArr(out IType type))
if (stloc == null || final == null || !stloc.Value.MatchNewArr(out IType? type))
throw new ArgumentException("given Block is invalid!");
if (stloc.Variable != final.Variable || stloc.Variable.Kind != VariableKind.InitializerTarget)
throw new ArgumentException("given Block is invalid!");
@ -3564,11 +3564,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3564,11 +3564,11 @@ namespace ICSharpCode.Decompiler.CSharp
for (int i = 1; i < block.Instructions.Count; i++)
{
if (!block.Instructions[i].MatchStObj(out ILInstruction target, out ILInstruction value, out IType t) || !type.Equals(t))
if (!block.Instructions[i].MatchStObj(out ILInstruction? target, out ILInstruction? value, out IType? t) || !type.Equals(t))
throw new ArgumentException("given Block is invalid!");
if (!target.MatchLdElema(out t, out ILInstruction array) || !type.Equals(t))
if (!target.MatchLdElema(out t, out ILInstruction? array) || !type.Equals(t))
throw new ArgumentException("given Block is invalid!");
if (!array.MatchLdLoc(out ILVariable v) || v != final.Variable)
if (!array.MatchLdLoc(out ILVariable? v) || v != final.Variable)
throw new ArgumentException("given Block is invalid!");
while (container.Count < dimensions)
{

54
ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection.Metadata;
using System.Threading;
@ -39,8 +40,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -39,8 +40,8 @@ namespace ICSharpCode.Decompiler.CSharp
readonly bool isInheritedRecord;
readonly bool isStruct;
readonly bool isSealed;
readonly IMethod primaryCtor;
readonly IType baseClass;
readonly IMethod? primaryCtor;
readonly IType? baseClass;
readonly Dictionary<IField, IProperty> backingFieldToAutoProperty = new Dictionary<IField, IProperty>();
readonly Dictionary<IProperty, IField> autoPropertyToBackingField = new Dictionary<IProperty, IField>();
readonly Dictionary<IParameter, IMember> primaryCtorParameterToAutoPropertyOrBackingField = new Dictionary<IParameter, IMember>();
@ -75,7 +76,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -75,7 +76,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
bool IsAutoProperty(IProperty p, out IField? field)
bool IsAutoProperty(IProperty p, [NotNullWhen(true)] out IField? field)
{
field = null;
if (p.IsStatic)
@ -108,7 +109,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -108,7 +109,7 @@ namespace ICSharpCode.Decompiler.CSharp
return field.Name == $"<{p.Name}>k__BackingField";
}
bool IsAutoGetter(IMethod method, out IField? field)
bool IsAutoGetter(IMethod method, [NotNullWhen(true)] out IField? field)
{
field = null;
var body = DecompileBody(method);
@ -129,7 +130,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -129,7 +130,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
bool IsAutoSetter(IMethod method, out IField? field)
bool IsAutoSetter(IMethod method, [NotNullWhen(true)] out IField? field)
{
field = null;
Debug.Assert(!method.IsStatic);
@ -137,7 +138,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -137,7 +138,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (body == null)
return false;
// this.field = value;
ILInstruction valueInst;
ILInstruction? valueInst;
if (method.IsStatic)
{
if (!body.Instructions[0].MatchStsFld(out field, out valueInst))
@ -158,7 +159,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -158,7 +159,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
IMethod DetectPrimaryConstructor()
IMethod? DetectPrimaryConstructor()
{
if (recordTypeDef.IsRecord)
{
@ -373,7 +374,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -373,7 +374,7 @@ namespace ICSharpCode.Decompiler.CSharp
&& autoPropertyOrBackingFieldToPrimaryCtorParameter.ContainsKey((IProperty)property.Specialize(subst));
}
internal (IProperty prop, IField field) GetPropertyInfoByPrimaryConstructorParameter(IParameter parameter)
internal (IProperty? prop, IField field) GetPropertyInfoByPrimaryConstructorParameter(IParameter parameter)
{
var member = primaryCtorParameterToAutoPropertyOrBackingField[parameter];
if (member is IField field)
@ -450,8 +451,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -450,8 +451,14 @@ namespace ICSharpCode.Decompiler.CSharp
{
if (!(member is IField field))
{
if (!autoPropertyToBackingField.TryGetValue((IProperty)member, out field))
if (!autoPropertyToBackingField.TryGetValue((IProperty)member, out var fieldHolder))
{
continue;
}
else
{
field = fieldHolder;
}
}
if (pos >= body.Instructions.Count)
return false;
@ -516,7 +523,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -516,7 +523,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (!(body.Instructions.Single() is Leave leave))
return false;
// leave IL_0000 (call GetTypeFromHandle(ldtypetoken R))
if (!TransformExpressionTrees.MatchGetTypeFromHandle(leave.Value, out IType ty))
if (!TransformExpressionTrees.MatchGetTypeFromHandle(leave.Value, out IType? ty))
return false;
return IsRecordType(ty);
}
@ -569,7 +576,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -569,7 +576,7 @@ namespace ICSharpCode.Decompiler.CSharp
trueInst = Block.Unwrap(trueInst);
if (!MatchStringBuilderAppend(trueInst, builder, out var val))
return false;
if (!(val.MatchLdStr(out string text) && text == ", "))
if (!(val.MatchLdStr(out string? text) && text == ", "))
return false;
pos++;
@ -601,7 +608,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -601,7 +608,7 @@ namespace ICSharpCode.Decompiler.CSharp
callvirt Append(ldloc builder, ldstr " = ")
callvirt Append(ldloc builder, constrained[System.Int32].callvirt ToString(ldflda B(ldloc this)))
leave IL_0000 (ldc.i4 1) */
if (!MatchStringBuilderAppendConstant(out string text))
if (!MatchStringBuilderAppendConstant(out string? text))
return false;
string expectedText = (needsComma ? ", " : "") + member.Name + " = ";
if (text != expectedText)
@ -672,10 +679,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -672,10 +679,10 @@ namespace ICSharpCode.Decompiler.CSharp
return true;
}
bool MatchStringBuilderAppendConstant(out string? text)
bool MatchStringBuilderAppendConstant([NotNullWhen(true)] out string? text)
{
text = null;
while (MatchStringBuilderAppend(body.Instructions[pos], builder, out var val) && val.MatchLdStr(out string valText))
while (MatchStringBuilderAppend(body.Instructions[pos], builder, out var val) && val.MatchLdStr(out string? valText))
{
text += valText;
pos++;
@ -684,7 +691,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -684,7 +691,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
private bool MatchStringBuilderAppend(ILInstruction inst, ILVariable sb, out ILInstruction? val)
private bool MatchStringBuilderAppend(ILInstruction inst, ILVariable sb, [NotNullWhen(true)] out ILInstruction? val)
{
val = null;
if (!(inst is CallVirt { Method: { Name: "Append", DeclaringType: { Namespace: "System.Text", Name: "StringBuilder" } } } call))
@ -760,7 +767,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -760,7 +767,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
return val != null && val.Length == 1 && call.Arguments[1].MatchLdcI4(val[0]);
}
return call.Arguments[1].MatchLdStr(out string val1) && val1 == val;
return call.Arguments[1].MatchLdStr(out string? val1) && val1 == val;
}
}
@ -912,7 +919,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -912,7 +919,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
private bool MatchGetEqualityContract(ILInstruction inst, out ILInstruction? target)
private bool MatchGetEqualityContract(ILInstruction inst, [NotNullWhen(true)] out ILInstruction? target)
{
target = null;
if (!(inst is CallInstruction { Method: { Name: "get_EqualityContract" } } call))
@ -1099,7 +1106,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1099,7 +1106,7 @@ namespace ICSharpCode.Decompiler.CSharp
return returnInst != null && returnInst.MatchReturn(out var retVal) && retVal.MatchNop();
}
bool MatchMemberAccess(ILInstruction inst, out ILInstruction? target, out IMember? member)
bool MatchMemberAccess(ILInstruction inst, [NotNullWhen(true)] out ILInstruction? target, [NotNullWhen(true)] out IMember? member)
{
target = null;
member = null;
@ -1116,12 +1123,17 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1116,12 +1123,17 @@ namespace ICSharpCode.Decompiler.CSharp
member = property;
return true;
}
else if (inst.MatchLdFld(out target, out IField field))
else if (inst.MatchLdFld(out target, out IField? field))
{
if (backingFieldToAutoProperty.TryGetValue(field, out property))
if (backingFieldToAutoProperty.TryGetValue(field, out var propertyHolder))
{
property = propertyHolder;
member = property;
}
else
{
member = field;
}
return true;
}
else
@ -1130,7 +1142,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1130,7 +1142,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
Block DecompileBody(IMethod method)
Block? DecompileBody(IMethod method)
{
if (method == null || method.MetadataToken.IsNil)
return null;

3
ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.CSharp.Syntax;
@ -1597,7 +1598,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -1597,7 +1598,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
}
public bool IsVariableReferenceWithSameType(ResolveResult rr, string identifier, out TypeResolveResult? trr)
public bool IsVariableReferenceWithSameType(ResolveResult rr, string identifier, [NotNullWhen(true)] out TypeResolveResult? trr)
{
if (!(rr is MemberResolveResult || rr is LocalResolveResult))
{

3
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
@ -875,7 +876,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -875,7 +876,7 @@ namespace ICSharpCode.Decompiler.CSharp
return NormalizeTypeVisitor.TypeErasure.EquivalentTypes(a, b);
}
private bool IsDynamicCastToIEnumerable(Expression expr, out Expression? dynamicExpr)
private bool IsDynamicCastToIEnumerable(Expression expr, [NotNullWhen(true)] out Expression? dynamicExpr)
{
if (!(expr is CastExpression cast))
{

5
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
@ -1081,7 +1082,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1081,7 +1082,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
}
bool IsSpecialConstant(IType expectedType, object constant, out Expression? expression)
bool IsSpecialConstant(IType expectedType, object constant, [NotNullWhen(true)] out Expression? expression)
{
expression = null;
if (!specialConstants.TryGetValue(constant, out var info))
@ -2492,7 +2493,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -2492,7 +2493,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return new NamespaceDeclaration(ns.FullName);
}
AstType GetExplicitInterfaceType(IMember member)
AstType? GetExplicitInterfaceType(IMember member)
{
if (member.IsExplicitInterfaceImplementation)
{

7
ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.CSharp.Syntax;
@ -552,7 +553,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -552,7 +553,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
}
}
bool IsMatchingAssignment(VariableToDeclare v, out AssignmentExpression assignment)
bool IsMatchingAssignment(VariableToDeclare v, [NotNullWhen(true)] out AssignmentExpression? assignment)
{
assignment = v.InsertionPoint.nextNode as AssignmentExpression;
if (assignment == null)
@ -731,7 +732,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -731,7 +732,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
}
}
private bool CanBeDeclaredAsOutVariable(VariableToDeclare v, out DirectionExpression dirExpr)
private bool CanBeDeclaredAsOutVariable(VariableToDeclare v, [NotNullWhen(true)] out DirectionExpression? dirExpr)
{
dirExpr = v.FirstUse.Parent as DirectionExpression;
if (dirExpr == null || dirExpr.FieldDirection != FieldDirection.Out)
@ -740,7 +741,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -740,7 +741,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return false;
if (v.DefaultInitialization != VariableInitKind.None)
return false;
for (AstNode node = v.FirstUse; node != null; node = node.Parent)
for (AstNode? node = v.FirstUse; node != null; node = node.Parent)
{
if (node.Role == Roles.EmbeddedStatement)
{

3
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.CSharp.Syntax;
@ -370,7 +371,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -370,7 +371,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
}
/// <summary>Matches simple lambdas of the form "a => b"</summary>
bool MatchSimpleLambda(Expression expr, out ParameterDeclaration? parameter, out Expression? body)
bool MatchSimpleLambda(Expression expr, [NotNullWhen(true)] out ParameterDeclaration? parameter, [NotNullWhen(true)] out Expression? body)
{
if (expr is LambdaExpression lambda && lambda.Parameters.Count == 1 && lambda.Body is Expression)
{

17
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.CSharp.Syntax;
@ -431,7 +432,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -431,7 +432,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
)
)));
bool MatchLowerBound(int indexNum, out IL.ILVariable? index, IL.ILVariable collection, Statement statement)
bool MatchLowerBound(int indexNum, [NotNullWhen(true)] out IL.ILVariable? index, IL.ILVariable collection, Statement statement)
{
index = null;
var m = variableAssignLowerBoundPattern.Match(statement);
@ -443,7 +444,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -443,7 +444,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return m.Get<IdentifierExpression>("collection").Single().GetILVariable() == collection;
}
bool MatchForeachOnMultiDimArray(IL.ILVariable[] upperBounds, IL.ILVariable collection, Statement firstInitializerStatement, out IdentifierExpression? foreachVariable, out IList<Statement>? statements, out IL.ILVariable[] lowerBounds)
bool MatchForeachOnMultiDimArray(IL.ILVariable[] upperBounds, IL.ILVariable collection, Statement firstInitializerStatement, [NotNullWhen(true)] out IdentifierExpression? foreachVariable, [NotNullWhen(true)] out IList<Statement>? statements, out IL.ILVariable[] lowerBounds)
{
int i = 0;
foreachVariable = null;
@ -451,7 +452,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -451,7 +452,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
lowerBounds = new IL.ILVariable[upperBounds.Length];
Statement stmt = firstInitializerStatement;
Match m = default(Match);
while (i < upperBounds.Length && MatchLowerBound(i, out IL.ILVariable indexVariable, collection, stmt))
while (i < upperBounds.Length && MatchLowerBound(i, out IL.ILVariable? indexVariable, collection, stmt))
{
m = forOnArrayMultiDimPattern.Match(stmt.GetNextStatement());
if (!m.Success)
@ -702,16 +703,16 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -702,16 +703,16 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return base.VisitIdentifier(identifier);
}
internal static bool IsBackingFieldOfAutomaticProperty(IField field, out IProperty? property)
internal static bool IsBackingFieldOfAutomaticProperty(IField field, [NotNullWhen(true)] out IProperty? property)
{
property = null;
if (!NameCouldBeBackingFieldOfAutomaticProperty(field.Name, out string propertyName))
if (!NameCouldBeBackingFieldOfAutomaticProperty(field.Name, out string? propertyName))
return false;
if (!field.IsCompilerGenerated())
return false;
property = field.DeclaringTypeDefinition
property = field.DeclaringTypeDefinition?
.GetProperties(p => p.Name == propertyName, GetMemberOptions.IgnoreInheritedMembers)
.FirstOrDefault();
?.FirstOrDefault();
return property != null;
}
@ -725,7 +726,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -725,7 +726,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
static readonly System.Text.RegularExpressions.Regex automaticPropertyBackingFieldNameRegex
= new System.Text.RegularExpressions.Regex(@"^(<(?<name>.+)>k__BackingField|_(?<name>.+))$");
static bool NameCouldBeBackingFieldOfAutomaticProperty(string name, out string? propertyName)
static bool NameCouldBeBackingFieldOfAutomaticProperty(string name, [NotNullWhen(true)] out string? propertyName)
{
propertyName = null;
var m = automaticPropertyBackingFieldNameRegex.Match(name);

5
ICSharpCode.Decompiler/DebugInfo/IDebugInfoProvider.cs

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Reflection.Metadata;
using System.Text;
@ -28,8 +29,8 @@ namespace ICSharpCode.Decompiler.DebugInfo @@ -28,8 +29,8 @@ namespace ICSharpCode.Decompiler.DebugInfo
string Description { get; }
IList<SequencePoint> GetSequencePoints(MethodDefinitionHandle method);
IList<Variable> GetVariables(MethodDefinitionHandle method);
bool TryGetName(MethodDefinitionHandle method, int index, out string name);
bool TryGetExtraTypeInfo(MethodDefinitionHandle method, int index, out PdbExtraTypeInfo extraTypeInfo);
bool TryGetName(MethodDefinitionHandle method, int index, [NotNullWhen(true)] out string? name);
bool TryGetExtraTypeInfo(MethodDefinitionHandle method, int index, [NotNullWhen(true)] out PdbExtraTypeInfo extraTypeInfo);
string SourceFileName { get; }
}
}

2
ICSharpCode.Decompiler/DecompilerSettings.cs

@ -2173,7 +2173,7 @@ namespace ICSharpCode.Decompiler @@ -2173,7 +2173,7 @@ namespace ICSharpCode.Decompiler
}
}
public event PropertyChangedEventHandler PropertyChanged;
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{

16
ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection.Metadata;
@ -482,7 +483,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -482,7 +483,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// <summary>
/// Matches a (potentially virtual) instance method call.
/// </summary>
static bool MatchCall(ILInstruction inst, string name, out InstructionCollection<ILInstruction>? args)
static bool MatchCall(ILInstruction inst, string name, [NotNullWhen(true)] out InstructionCollection<ILInstruction>? args)
{
if (inst is CallInstruction call && (call.OpCode == OpCode.Call || call.OpCode == OpCode.CallVirt)
&& call.Method.Name == name && !call.Method.IsStatic)
@ -497,7 +498,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -497,7 +498,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// <summary>
/// Matches a store to the state machine.
/// </summary>
static bool MatchStFld(ILInstruction stfld, ILVariable stateMachineVar, out IField field, out ILInstruction value)
static bool MatchStFld(ILInstruction stfld, ILVariable stateMachineVar, [NotNullWhen(true)] out IField? field, [NotNullWhen(true)] out ILInstruction? value)
{
if (!stfld.MatchStFld(out var target, out field, out value))
return false;
@ -869,7 +870,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -869,7 +870,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
return blockContainer.Blocks[setResultReturnBlockIndex];
}
private bool MatchDisposeCombinedTokens(BlockContainer blockContainer, ILInstruction condition, ILInstruction trueInst, ILInstruction falseInst, bool[] blocksAnalyzed, out Block? setResultAndExitBlock)
private bool MatchDisposeCombinedTokens(BlockContainer blockContainer, ILInstruction condition, ILInstruction trueInst, ILInstruction falseInst, bool[] blocksAnalyzed, [NotNullWhen(true)] out Block? setResultAndExitBlock)
{
setResultAndExitBlock = null;
// ...
@ -1423,7 +1424,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -1423,7 +1424,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
}
bool AnalyzeAwaitBlock(Block block, out ILVariable? awaiter, out IField? awaiterField, out int state, out int yieldOffset)
bool AnalyzeAwaitBlock(Block block, [NotNullWhen(true)] out ILVariable? awaiter, [NotNullWhen(true)] out IField? awaiterField, out int state, out int yieldOffset)
{
awaiter = null;
awaiterField = null;
@ -1522,6 +1523,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -1522,6 +1523,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
{
pos--;
}
block.Instructions.RemoveRange(pos, block.Instructions.Count - pos);
return true;
}
@ -1538,7 +1540,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -1538,7 +1540,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
return inst;
}
private bool AnalyzeYieldReturn(Block block, out ILInstruction? yieldValue, out int newState)
private bool AnalyzeYieldReturn(Block block, [NotNullWhen(true)] out ILInstruction? yieldValue, out int newState)
{
yieldValue = default;
newState = default;
@ -1584,7 +1586,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -1584,7 +1586,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
return true;
}
bool MatchCurrentAssignment(ILInstruction inst, out ILInstruction value)
bool MatchCurrentAssignment(ILInstruction inst, [NotNullWhen(true)] out ILInstruction? value)
{
if (!inst.MatchStFld(out var target, out var field, out value))
return false;
@ -1701,7 +1703,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -1701,7 +1703,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
return inst;
}
bool CheckAwaitBlock(Block block, out Block? resumeBlock, out IField? stackField)
bool CheckAwaitBlock(Block block, [NotNullWhen(true)] out Block? resumeBlock, out IField? stackField)
{
// awaitBlock:
// (pre-roslyn: save stack)

13
ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.IL.Transforms;
@ -223,7 +224,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -223,7 +224,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// Analyzes all catch handlers and returns every handler that follows the await catch handler pattern.
/// </summary>
static bool AnalyzeHandlers(InstructionCollection<TryCatchHandler> handlers, out ILVariable? catchHandlerIdentifier,
out List<CatchBlockInfo> transformableCatchBlocks)
[NotNullWhen(true)] out List<CatchBlockInfo> transformableCatchBlocks)
{
transformableCatchBlocks = new List<CatchBlockInfo>();
catchHandlerIdentifier = null;
@ -254,9 +255,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -254,9 +255,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// stloc V_5(ldc.i4 2) - store id of catch block in 'identifierVariable'
/// br IL_0075 - jump out of catch block to the head of the catch-handler jump table
/// </summary>
static bool MatchAwaitCatchHandler(TryCatchHandler handler, out int id, out ILVariable? identifierVariable,
out Block? realEntryPoint, out ILInstruction? nextBlockOrExitContainer,
out ILInstruction? jumpTableEntry, out ILVariable? objectVariable)
static bool MatchAwaitCatchHandler(TryCatchHandler handler, out int id, [NotNullWhen(true)] out ILVariable? identifierVariable,
[NotNullWhen(true)] out Block? realEntryPoint, out ILInstruction? nextBlockOrExitContainer,
[NotNullWhen(true)] out ILInstruction? jumpTableEntry, out ILVariable? objectVariable)
{
id = 0;
identifierVariable = null;
@ -266,7 +267,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -266,7 +267,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
nextBlockOrExitContainer = null;
var exceptionVariable = handler.Variable;
var catchBlock = ((BlockContainer)handler.Body).EntryPoint;
ILInstruction value;
ILInstruction? value;
switch (catchBlock.Instructions.Count)
{
case 3:
@ -326,7 +327,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -326,7 +327,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
return false;
}
bool ParseSwitchJumpTable(int id, SwitchInstruction jumpTable, ILVariable identifierVariable, out Block? realEntryPoint, out ILInstruction? nextBlockOrExitContainer, out ILInstruction? jumpTableEntry)
bool ParseSwitchJumpTable(int id, SwitchInstruction jumpTable, ILVariable identifierVariable, [NotNullWhen(true)] out Block? realEntryPoint, out ILInstruction? nextBlockOrExitContainer, [NotNullWhen(true)] out ILInstruction? jumpTableEntry)
{
realEntryPoint = null;
nextBlockOrExitContainer = null;

3
ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.FlowAnalysis;
@ -610,7 +611,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -610,7 +611,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// Determine if the specified instruction necessarily exits (EndPointUnreachable)
/// and if so return last (or single) exit instruction
/// </summary>
private static bool TryGetExit(ILInstruction inst, out ILInstruction? exitInst)
private static bool TryGetExit(ILInstruction inst, [NotNullWhen(true)] out ILInstruction? exitInst)
{
if (inst is Block block && block.Instructions.Count > 0)
inst = block.Instructions.Last();

36
ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.InteropServices.ComTypes;
@ -241,8 +242,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -241,8 +242,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// stloc V_1(get.pinnable.reference(ldloc mem))
// stloc ptr(conv ref->u (ldloc V_1))
// br targetBlock
private bool IsCustomRefPinPattern(Block block, out ILInstruction? ldlocMem, out CallInstruction? callGPR,
out ILVariable? v, out StLoc? ptrAssign, out Block? targetBlock, out Block? nullBlock, out Block? notNullBlock)
private bool IsCustomRefPinPattern(Block block, [NotNullWhen(true)] out ILInstruction? ldlocMem, [NotNullWhen(true)] out CallInstruction? callGPR,
[NotNullWhen(true)] out ILVariable? v, out StLoc? ptrAssign, [NotNullWhen(true)] out Block? targetBlock, out Block? nullBlock, [NotNullWhen(true)] out Block? notNullBlock)
{
ldlocMem = null;
callGPR = null;
@ -356,7 +357,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -356,7 +357,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// ...
// stloc P(array.to.pointer(V))
// br B_target
bool IsNullSafeArrayToPointerPattern(Block block, out ILVariable? v, out ILVariable? p, out Block? targetBlock)
bool IsNullSafeArrayToPointerPattern(Block block, [NotNullWhen(true)] out ILVariable? v, [NotNullWhen(true)] out ILVariable? p, [NotNullWhen(true)] out Block? targetBlock)
{
v = null;
p = null;
@ -384,7 +385,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -384,7 +385,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
usingPreviousVar = true;
}
}
if (!ifInst.TrueInst.MatchBranch(out Block nullOrEmptyBlock))
if (!ifInst.TrueInst.MatchBranch(out Block? nullOrEmptyBlock))
return false;
if (!ifInst.FalseInst.MatchNop())
return false;
@ -394,7 +395,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -394,7 +395,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
return false;
if (!(p.Kind == VariableKind.PinnedLocal || (usingPreviousVar && v.Kind == VariableKind.PinnedLocal)))
return false;
if (!block.Instructions.Last().MatchBranch(out Block notNullBlock))
if (!block.Instructions.Last().MatchBranch(out Block? notNullBlock))
return false;
if (notNullBlock.Parent != block.Parent)
return false;
@ -409,7 +410,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -409,7 +410,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// }
if (block.Instructions.Count != 2)
return false;
if (!block.Instructions[0].MatchIfInstruction(out ILInstruction condition, out ILInstruction trueInst))
if (!block.Instructions[0].MatchIfInstruction(out var condition, out var trueInst))
return false;
var falseInst = block.Instructions[1];
if (condition is Comp comp && comp.Right.MatchLdcI(0))
@ -495,7 +496,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -495,7 +496,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
return block.Instructions[1].MatchBranch(targetBlock);
}
bool IsNullSafeArrayToPointerNullOrEmptyBlock(Block block, out ILVariable? p, out Block? targetBlock)
bool IsNullSafeArrayToPointerNullOrEmptyBlock(Block block, [NotNullWhen(true)] out ILVariable? p, [NotNullWhen(true)] out Block? targetBlock)
{
p = null;
targetBlock = null;
@ -503,7 +504,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -503,7 +504,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// stloc P(conv i4->u(ldc.i4 0))
// br B_target
// }
ILInstruction value;
ILInstruction? value;
return block.Instructions.Count == 2
&& block.Instructions[0].MatchStLoc(out p, out value)
&& (p.Kind == VariableKind.PinnedLocal || p.Kind == VariableKind.Local)
@ -863,13 +864,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -863,13 +864,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
return slotInfo == Block.InstructionSlot || slotInfo == LdObj.TargetSlot || slotInfo == StObj.TargetSlot;
}
bool IsBranchOnNull(ILInstruction condBranch, ILVariable nativeVar, out Block? targetBlock)
bool IsBranchOnNull(ILInstruction condBranch, ILVariable nativeVar, [NotNullWhen(true)] out Block? targetBlock)
{
targetBlock = null;
// if (comp(ldloc nativeVar == conv i4->i <sign extend>(ldc.i4 0))) br targetBlock
ILInstruction condition, trueInst, left, right;
return condBranch.MatchIfInstruction(out condition, out trueInst)
&& condition.MatchCompEquals(out left, out right)
return condBranch.MatchIfInstruction(out var condition, out var trueInst)
&& condition.MatchCompEquals(out var left, out var right)
&& left.MatchLdLoc(nativeVar) && IsNullOrZero(right)
&& trueInst.MatchBranch(out targetBlock);
}
@ -884,7 +884,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -884,7 +884,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// if (comp(ldloc nativeVar == conv i4->i <sign extend>(ldc.i4 0))) br targetBlock
// br adjustOffsetToStringData
ILVariable newVar;
if (!body.EntryPoint.Instructions[0].MatchStLoc(out ILVariable nativeVar, out ILInstruction initInst))
if (!body.EntryPoint.Instructions[0].MatchStLoc(out var nativeVar, out var initInst))
{
// potentially a special case with legacy csc and an unused pinned variable:
if (pinnedRegion.Variable.AddressCount == 0 && pinnedRegion.Variable.LoadCount == 0)
@ -902,11 +902,11 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -902,11 +902,11 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (nativeVar.Type.GetStackType() != StackType.I)
return;
Block targetBlock;
Block? targetBlock;
Block? adjustOffsetToStringData = null;
if (body.EntryPoint.Instructions.Count == 2)
{
if (!initInst.MatchBinaryNumericInstruction(BinaryNumericOperator.Add, out ILInstruction left, out ILInstruction right))
if (!initInst.MatchBinaryNumericInstruction(BinaryNumericOperator.Add, out var left, out var right))
return;
if (!left.UnwrapConv(ConversionKind.StopGCTracking).MatchLdLoc(pinnedRegion.Variable))
return;
@ -977,13 +977,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -977,13 +977,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
ReplacePinnedVar(pinnedRegion.Variable, newVar, pinnedRegion);
}
bool IsOffsetToStringDataBlock(Block block, ILVariable nativeVar, Block targetBlock)
bool IsOffsetToStringDataBlock(Block block, ILVariable nativeVar, Block? targetBlock)
{
// stloc nativeVar(add(ldloc nativeVar, conv i4->i <sign extend>(call [Accessor System.Runtime.CompilerServices.RuntimeHelpers.get_OffsetToStringData():System.Int32]())))
// br IL_0011
if (block.Instructions.Count != 2)
return false;
ILInstruction value;
ILInstruction? value;
if (nativeVar.IsSingleDefinition && nativeVar.LoadCount == 2)
{
// If there are no loads (except for the two in the string-to-pointer pattern),
@ -1003,7 +1003,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -1003,7 +1003,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
{
return false;
}
if (!value.MatchBinaryNumericInstruction(BinaryNumericOperator.Add, out ILInstruction left, out ILInstruction right))
if (!value.MatchBinaryNumericInstruction(BinaryNumericOperator.Add, out var left, out var right))
return false;
if (!left.MatchLdLoc(nativeVar))
return false;

1
ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs

@ -613,6 +613,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -613,6 +613,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// skip blocks that only branch to another block
entryPoint = targetBlock;
}
return entryPoint == loopHead;
}
#endregion

2
ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs

@ -314,7 +314,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -314,7 +314,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
trueValues = new LongSet(0).Invert();
return true;
}
else if (condition.MatchLogicNot(out ILInstruction arg))
else if (condition.MatchLogicNot(out var arg))
{
// if (logic.not(X)) --> branch for all values where if (X) does not branch
bool res = AnalyzeCondition(arg, out LongSet falseValues);

3
ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection.Metadata;
@ -1426,7 +1427,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -1426,7 +1427,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
context.StepEndGroup(keepIfEmpty: true);
bool IsCallToMonoFinallyMethod(Call call, out IMethod? finallyMethod)
bool IsCallToMonoFinallyMethod(Call call, [NotNullWhen(true)] out IMethod? finallyMethod)
{
finallyMethod = default;
if (call == null)

2
ICSharpCode.Decompiler/IL/ILReader.cs

@ -312,7 +312,7 @@ namespace ICSharpCode.Decompiler.IL @@ -312,7 +312,7 @@ namespace ICSharpCode.Decompiler.IL
}
ILVariable ilVar = new ILVariable(kind, type, index);
if (!UseDebugSymbols || DebugInfo == null || !DebugInfo.TryGetName((MethodDefinitionHandle)method.MetadataToken, index, out string name))
if (!UseDebugSymbols || DebugInfo == null || !DebugInfo.TryGetName((MethodDefinitionHandle)method.MetadataToken, index, out string? name))
{
ilVar.Name = "V_" + index;
ilVar.HasGeneratedName = true;

5
ICSharpCode.Decompiler/IL/Instructions/DeconstructInstruction.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
@ -190,7 +191,7 @@ namespace ICSharpCode.Decompiler.IL @@ -190,7 +191,7 @@ namespace ICSharpCode.Decompiler.IL
output.MarkFoldEnd();
}
internal static bool IsConversionStLoc(ILInstruction inst, out ILVariable variable, out ILVariable? inputVariable)
internal static bool IsConversionStLoc(ILInstruction inst, [NotNullWhen(true)] out ILVariable? variable, [NotNullWhen(true)] out ILVariable? inputVariable)
{
inputVariable = null;
if (!inst.MatchStLoc(out variable, out var value))
@ -210,7 +211,7 @@ namespace ICSharpCode.Decompiler.IL @@ -210,7 +211,7 @@ namespace ICSharpCode.Decompiler.IL
return input.MatchLdLoc(out inputVariable) || input.MatchLdLoca(out inputVariable);
}
internal static bool IsAssignment(ILInstruction inst, ICompilation typeSystem, out IType? expectedType, out ILInstruction? value)
internal static bool IsAssignment(ILInstruction inst, ICompilation typeSystem, [NotNullWhen(true)] out IType? expectedType, [NotNullWhen(true)] out ILInstruction? value)
{
expectedType = null;
value = null;

17
ICSharpCode.Decompiler/IL/Transforms/DeconstructionTransform.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Resources;
@ -35,9 +36,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -35,9 +36,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
StatementTransformContext context;
readonly Dictionary<ILVariable, int> deconstructionResultsLookup = new Dictionary<ILVariable, int>();
ILVariable[] deconstructionResults;
ILVariable tupleVariable;
TupleType tupleType;
ILVariable[]? deconstructionResults;
ILVariable? tupleVariable;
TupleType? tupleType;
/*
stloc tuple(call MakeIntIntTuple(ldloc this))
@ -262,8 +263,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -262,8 +263,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
bool MatchDeconstruction(ILInstruction inst, out IMethod? deconstructMethod,
out ILInstruction? testedOperand)
bool MatchDeconstruction(ILInstruction inst, [NotNullWhen(true)] out IMethod? deconstructMethod,
[NotNullWhen(true)] out ILInstruction? testedOperand)
{
testedOperand = null;
deconstructMethod = null;
@ -328,8 +329,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -328,8 +329,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
bool MatchConversion(ILInstruction inst, out ILInstruction? inputInstruction,
out ILVariable outputVariable, out ConversionInfo info)
bool MatchConversion(ILInstruction inst, [NotNullWhen(true)] out ILInstruction? inputInstruction,
[NotNullWhen(true)] out ILVariable? outputVariable, [NotNullWhen(true)] out ConversionInfo info)
{
info = default;
inputInstruction = null;
@ -433,7 +434,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -433,7 +434,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
bool MatchAssignment(ILInstruction inst, out IType? targetType, out ILInstruction? valueInst, out Action<DeconstructInstruction>? addAssignment)
bool MatchAssignment(ILInstruction inst, out IType? targetType, [NotNullWhen(true)] out ILInstruction? valueInst, [NotNullWhen(true)] out Action<DeconstructInstruction>? addAssignment)
{
targetType = null;
valueInst = null;

3
ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection.Metadata;
@ -80,7 +81,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -80,7 +81,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
internal static bool MatchDelegateConstruction(ILInstruction inst, out IMethod? targetMethod,
out ILInstruction? target, out IType? delegateType, bool allowTransformed = false)
[NotNullWhen(true)] out ILInstruction? target, [NotNullWhen(true)] out IType? delegateType, bool allowTransformed = false)
{
targetMethod = null;
target = null;

6
ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
@ -162,7 +163,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -162,7 +163,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// br falseBlock
/// }
/// </summary>
bool MatchCatchWhenEntryPoint(ILVariable exceptionVar, BlockContainer container, Block entryPoint, out IType? exceptionType, out ILInstruction? exceptionSlot, out Block? whenConditionBlock)
bool MatchCatchWhenEntryPoint(ILVariable exceptionVar, BlockContainer container, Block entryPoint, [NotNullWhen(true)] out IType? exceptionType, [NotNullWhen(true)] out ILInstruction? exceptionSlot, [NotNullWhen(true)] out Block? whenConditionBlock)
{
exceptionType = null;
exceptionSlot = null;
@ -206,6 +207,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -206,6 +207,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (right.MatchLdNull())
{
return branch.MatchBranch(out whenConditionBlock);
}
}
@ -218,7 +220,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -218,7 +220,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// br exitBlock
/// }
/// </summary>
bool MatchFalseBlock(BlockContainer container, Block falseBlock, out ILVariable? returnVar, out Block? exitBlock)
bool MatchFalseBlock(BlockContainer container, Block falseBlock, [NotNullWhen(true)] out ILVariable? returnVar, [NotNullWhen(true)] out Block? exitBlock)
{
returnVar = null;
exitBlock = null;

9
ICSharpCode.Decompiler/IL/Transforms/DynamicCallSiteTransform.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
@ -272,7 +273,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -272,7 +273,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
bool ScanCallSiteInitBlock(Block callSiteInitBlock, IField callSiteCacheField, IType callSiteDelegateType, out CallSiteInfo callSiteInfo, out Block? blockAfterInit)
bool ScanCallSiteInitBlock(Block callSiteInitBlock, IField callSiteCacheField, IType callSiteDelegateType, out CallSiteInfo callSiteInfo, [NotNullWhen(true)] out Block? blockAfterInit)
{
callSiteInfo = default(CallSiteInfo);
blockAfterInit = null;
@ -300,7 +301,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -300,7 +301,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (!binderCall.Arguments[0].MatchLdcI4(out int binderFlagsInteger))
return false;
callSiteInfo.Flags = (CSharpBinderFlags)binderFlagsInteger;
if (!binderCall.Arguments[1].MatchLdStr(out string name))
if (!binderCall.Arguments[1].MatchLdStr(out var name))
return false;
callSiteInfo.MemberName = name;
if (!TransformExpressionTrees.MatchGetTypeFromHandle(binderCall.Arguments[2], out var contextType))
@ -551,7 +552,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -551,7 +552,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!createCall.Arguments[0].MatchLdcI4(out var argumentInfoFlags))
return false;
if (!createCall.Arguments[1].MatchLdStr(out string argumentName))
if (!createCall.Arguments[1].MatchLdStr(out var argumentName))
if (!createCall.Arguments[1].MatchLdNull())
return false;
callSiteInfo.ArgumentInfos[i] = new CSharpArgumentInfo { Flags = (CSharpArgumentInfoFlags)argumentInfoFlags, Name = argumentName, CompileTimeType = compileTimeTypes[i + 1] };
@ -560,7 +561,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -560,7 +561,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
bool MatchCallSiteCacheNullCheck(ILInstruction condition, out IField? callSiteCacheField, out IType? callSiteDelegate, out bool invertBranches)
bool MatchCallSiteCacheNullCheck(ILInstruction condition, [NotNullWhen(true)] out IField? callSiteCacheField, [NotNullWhen(true)] out IType? callSiteDelegate, out bool invertBranches)
{
callSiteCacheField = null;
callSiteDelegate = null;

3
ICSharpCode.Decompiler/IL/Transforms/DynamicIsEventAssignmentTransform.cs

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Diagnostics.CodeAnalysis;
using System.Linq;
namespace ICSharpCode.Decompiler.IL.Transforms
@ -121,7 +122,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -121,7 +122,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// stloc V_2(dynamic.getmember B(target))
/// }
/// </summary>
static bool MatchLhsCacheIfInstruction(ILInstruction ifInst, ILVariable flagVar, out StLoc? cacheStore)
static bool MatchLhsCacheIfInstruction(ILInstruction ifInst, ILVariable flagVar, [NotNullWhen(true)] out StLoc? cacheStore)
{
cacheStore = null;
if (!ifInst.MatchIfInstruction(out var condition, out var trueInst))

5
ICSharpCode.Decompiler/IL/Transforms/EarlyExpressionTransforms.cs

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
@ -175,7 +176,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -175,7 +176,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
protected internal override void VisitNewObj(NewObj inst)
{
if (TransformDecimalCtorToConstant(inst, out LdcDecimal decimalConstant))
if (TransformDecimalCtorToConstant(inst, out var decimalConstant))
{
context.Step("TransformDecimalCtorToConstant", inst);
inst.ReplaceWith(decimalConstant);
@ -185,7 +186,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -185,7 +186,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
base.VisitNewObj(inst);
}
bool TransformDecimalCtorToConstant(NewObj inst, out LdcDecimal? result)
bool TransformDecimalCtorToConstant(NewObj inst, [NotNullWhen(true)] out LdcDecimal? result)
{
IType t = inst.Method.DeclaringType;
result = null;

7
ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
@ -342,7 +343,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -342,7 +343,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// =>
/// ldvirtdelegate System.Delegate TargetMethod(target)
/// </summary>
bool TransformDelegateCtorLdVirtFtnToLdVirtDelegate(NewObj inst, out LdVirtDelegate? ldVirtDelegate)
bool TransformDelegateCtorLdVirtFtnToLdVirtDelegate(NewObj inst, [NotNullWhen(true)] out LdVirtDelegate? ldVirtDelegate)
{
ldVirtDelegate = null;
if (inst.Method.DeclaringType.Kind != TypeKind.Delegate)
@ -379,7 +380,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -379,7 +380,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// final: ldloc I_0
/// }
/// </summary>
bool TransformSpanTCtorContainingStackAlloc(NewObj newObj, out ILInstruction? locallocSpan)
bool TransformSpanTCtorContainingStackAlloc(NewObj newObj, [NotNullWhen(true)] out ILInstruction? locallocSpan)
{
locallocSpan = null;
IType type = newObj.Method.DeclaringType;
@ -428,7 +429,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -428,7 +429,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
bool TransformDecimalFieldToConstant(LdObj inst, out LdcDecimal? result)
bool TransformDecimalFieldToConstant(LdObj inst, [NotNullWhen(true)] out LdcDecimal? result)
{
if (inst.MatchLdsFld(out var field) && field.DeclaringType.IsKnownType(KnownTypeCode.Decimal))
{

14
ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.IL.ControlFlow;
@ -53,7 +54,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -53,7 +54,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
bool MatchWhileLoop(BlockContainer loop, out IfInstruction? condition, out Block loopBody)
bool MatchWhileLoop(BlockContainer loop, [NotNullWhen(true)] out IfInstruction? condition, out Block loopBody)
{
// ConditionDetection favours leave inside if and branch at end of block
// while-loop:
@ -115,7 +116,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -115,7 +116,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
ExpressionTransforms.RunOnSingleStatment(inst, context);
}
}*/
return true;
}
@ -156,7 +156,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -156,7 +156,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// </summary>
bool MatchDoWhileLoop(BlockContainer loop)
{
(List<IfInstruction> conditions, ILInstruction exit, bool swap, bool split, bool unwrap) = AnalyzeDoWhileConditions(loop);
(List<IfInstruction>? conditions, ILInstruction exit, bool swap, bool split, bool unwrap) = AnalyzeDoWhileConditions(loop);
// not a do-while loop, exit.
if (conditions == null || conditions.Count == 0)
return false;
@ -240,7 +240,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -240,7 +240,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
static (List<IfInstruction> conditions, ILInstruction exit, bool swap, bool split, bool unwrap) AnalyzeDoWhileConditions(BlockContainer loop)
static (List<IfInstruction>? conditions, ILInstruction? exit, bool swap, bool split, bool unwrap) AnalyzeDoWhileConditions(BlockContainer loop)
{
// we iterate over all blocks from the bottom, because the entry-point
// should only be considered as condition block, if there are no other blocks.
@ -356,7 +356,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -356,7 +356,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
// early match before block containers have been constructed
internal static bool MatchDoWhileConditionBlock(Block block, out Block target1, out Block? target2)
internal static bool MatchDoWhileConditionBlock(Block block, out Block? target1, out Block? target2)
{
target1 = target2 = null;
if (block.Instructions.Count < 2)
@ -370,7 +370,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -370,7 +370,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
(last.MatchBranch(out target2) || last.MatchReturn(out var _));
}
internal static Block GetIncrementBlock(BlockContainer loop, Block whileLoopBody) =>
internal static Block? GetIncrementBlock(BlockContainer loop, Block whileLoopBody) =>
loop.Blocks.SingleOrDefault(b => b != whileLoopBody
&& b.Instructions.Last().MatchBranch(loop.EntryPoint)
&& b.Instructions.SkipLast(1).All(IsSimpleStatement));
@ -480,7 +480,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -480,7 +480,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// Returns true if the instruction is stloc v(add(ldloc v, arg))
/// or compound.assign(ldloca v, arg)
/// </summary>
public static bool MatchIncrement(ILInstruction inst, out ILVariable variable)
public static bool MatchIncrement(ILInstruction inst, [NotNullWhen(true)] out ILVariable? variable)
{
if (inst.MatchStLoc(out variable, out var value))
{

13
ICSharpCode.Decompiler/IL/Transforms/IndexRangeTransform.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
@ -152,7 +153,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -152,7 +153,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
int startPos = pos;
ILVariable? containerVar = null;
// The container length access may be a separate instruction, or it may be inline with the variable's use
if (MatchContainerLengthStore(block.Instructions[pos], out ILVariable containerLengthVar, ref containerVar))
if (MatchContainerLengthStore(block.Instructions[pos], out var containerLengthVar, ref containerVar))
{
// stloc containerLengthVar(call get_Length/get_Count(ldloc container))
pos++;
@ -465,7 +466,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -465,7 +466,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
private bool MatchIndexImplicitConv(ILInstruction inst, out ILInstruction? offsetInst)
private bool MatchIndexImplicitConv(ILInstruction inst, [NotNullWhen(true)] out ILInstruction? offsetInst)
{
offsetInst = null;
if (!(inst is CallInstruction call))
@ -607,7 +608,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -607,7 +608,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// Matches the instruction:
/// stloc containerLengthVar(call get_Length/get_Count(ldloc containerVar))
/// </summary>
static bool MatchContainerLengthStore(ILInstruction inst, out ILVariable lengthVar, ref ILVariable containerVar)
static bool MatchContainerLengthStore(ILInstruction inst, [NotNullWhen(true)] out ILVariable? lengthVar, ref ILVariable? containerVar)
{
if (!inst.MatchStLoc(out lengthVar, out var init))
return false;
@ -624,7 +625,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -624,7 +625,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// Otherwise, matches the instruction:
/// call get_Length/get_Count(ldloc containerVar)
/// </summary>
static bool MatchContainerLength(ILInstruction init, ILVariable lengthVar, ref ILVariable containerVar)
static bool MatchContainerLength(ILInstruction init, ILVariable? lengthVar, ref ILVariable? containerVar)
{
if (lengthVar != null)
{
@ -658,7 +659,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -658,7 +659,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return MatchContainerVar(call.Arguments[0], ref containerVar);
}
static bool MatchContainerVar(ILInstruction inst, ref ILVariable containerVar)
static bool MatchContainerVar(ILInstruction inst, [NotNullWhen(true)] ref ILVariable? containerVar)
{
if (containerVar != null)
{
@ -745,7 +746,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -745,7 +746,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// Matches an instruction computing a slice length:
/// binary.sub.i4(call GetOffset(endIndexLoad, ldloc length), ldloc startOffset))
/// </summary>
static bool MatchSliceLength(ILInstruction inst, out IndexKind endIndexKind, out ILInstruction? endIndexLoad, ILVariable containerLengthVar, ref ILVariable containerVar, ILVariable startOffsetVar)
static bool MatchSliceLength(ILInstruction inst, out IndexKind endIndexKind, [NotNullWhen(true)] out ILInstruction? endIndexLoad, ILVariable containerLengthVar, ref ILVariable containerVar, ILVariable startOffsetVar)
{
endIndexKind = default;
endIndexLoad = default;

3
ICSharpCode.Decompiler/IL/Transforms/InterpolatedStringTransform.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using ICSharpCode.Decompiler.TypeSystem;
@ -104,7 +105,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -104,7 +105,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
private bool FindToStringAndClear(Block block, int pos, int interpolationStart, int interpolationEnd, ILVariable v, out ILInstruction? insertionPoint)
private bool FindToStringAndClear(Block block, int pos, int interpolationStart, int interpolationEnd, ILVariable v, [NotNullWhen(true)] out ILInstruction? insertionPoint)
{
insertionPoint = null;
if (pos >= block.Instructions.Count)

3
ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
@ -831,7 +832,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -831,7 +832,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// </summary>
static readonly Regex functionNameRegex = new Regex(@"^<(.*)>g__([^\|]*)\|{0,1}\d+(_\d+)?$", RegexOptions.Compiled);
internal static bool ParseLocalFunctionName(string name, out string? callerName, out string? functionName)
internal static bool ParseLocalFunctionName(string name, [NotNullWhen(true)] out string? callerName, [NotNullWhen(true)] out string? functionName)
{
callerName = null;
functionName = null;

14
ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Diagnostics.CodeAnalysis;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.IL.Transforms
@ -331,7 +333,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -331,7 +333,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
bool MatchLockEntryPoint(Block entryPoint, ILVariable flag, out StLoc? obj)
bool MatchLockEntryPoint(Block entryPoint, ILVariable flag, [NotNullWhen(true)] out StLoc? obj)
{
obj = null;
if (entryPoint.Instructions.Count == 0 || entryPoint.IncomingEdgeCount != 1)
@ -341,14 +343,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -341,14 +343,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
bool MatchLockEntryPoint(Block entryPoint, ILVariable flag, out ILVariable? exitVairable, out StLoc? obj)
bool MatchLockEntryPoint(Block entryPoint, ILVariable flag, [NotNullWhen(true)] out ILVariable? exitVariable, [NotNullWhen(true)] out StLoc? obj)
{
// This pattern is commonly seen in yield return state machines emitted by the legacy C# compiler.
obj = null;
exitVairable = null;
exitVariable = null;
if (entryPoint.Instructions.Count < 1 || entryPoint.IncomingEdgeCount != 1)
return false;
if (entryPoint.Instructions[0].MatchStLoc(out exitVairable, out var value) && value is StLoc nestedStloc)
if (entryPoint.Instructions[0].MatchStLoc(out exitVariable, out var value) && value is StLoc nestedStloc)
{
obj = nestedStloc;
if (!MatchCall(entryPoint.Instructions[1] as Call, "Enter", nestedStloc.Variable, flag))
@ -358,7 +360,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -358,7 +360,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
}
bool MatchCall(Call call, string methodName, ILVariable flag, out StLoc? obj)
bool MatchCall(Call? call, string methodName, ILVariable flag, [NotNullWhen(true)] out StLoc? obj)
{
obj = null;
const string ThreadingMonitor = "System.Threading.Monitor";
@ -371,7 +373,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -371,7 +373,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
bool MatchCall(Call call, string methodName, params ILVariable[] variables)
bool MatchCall(Call? call, string methodName, params ILVariable[] variables)
{
const string ThreadingMonitor = "System.Threading.Monitor";
if (call == null || call.Method.Name != methodName || call.Method.DeclaringType.FullName != ThreadingMonitor ||

10
ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
@ -237,7 +238,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -237,7 +238,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
).WithILRange(ifInst));
}
bool IsValidAccessChain(ILVariable testedVar, Mode mode, ILInstruction inst, out ILInstruction? finalLoad)
bool IsValidAccessChain(ILVariable testedVar, Mode mode, ILInstruction inst, [NotNullWhen(true)] out ILInstruction? finalLoad)
{
finalLoad = null;
int chainLength = 0;
@ -475,7 +476,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -475,7 +476,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// stloc resultTemporary(constrained[type].call_instruction(ldloc target, ...))
// br endBlock
private bool MatchStLocResultTemporary(Block block, int pos, IType type, ILVariable target, ILVariable defaultTemporary, ILInstruction fallbackBlock, out ILInstruction? nonNullInst, out ILInstruction? nullInst, out Block? endBlock)
private bool MatchStLocResultTemporary(Block block, int pos, IType type, ILVariable target, ILVariable defaultTemporary, ILInstruction fallbackBlock, [NotNullWhen(true)] out ILInstruction? nonNullInst, [NotNullWhen(true)] out ILInstruction? nullInst, [NotNullWhen(true)] out Block? endBlock)
{
endBlock = null;
nonNullInst = null;
@ -496,7 +497,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -496,7 +497,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
private bool MatchLeaveResult(Block block, int pos, IType type, ILVariable target, ILVariable defaultTemporary, ILInstruction fallbackBlock, out ILInstruction? nonNullInst, out ILInstruction? nullInst)
private bool MatchLeaveResult(Block block, int pos, IType type, ILVariable target, ILVariable defaultTemporary, ILInstruction fallbackBlock, [NotNullWhen(true)] out ILInstruction? nonNullInst, [NotNullWhen(true)] out ILInstruction? nullInst)
{
nonNullInst = null;
nullInst = null;
@ -508,6 +509,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -508,6 +509,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// Analyze Block fallbackBlock
if (!(fallbackBlock is Block b && IsFallbackBlock(b, type, target, defaultTemporary, null, leave.TargetContainer, out nullInst)))
return false;
return true;
}
@ -519,7 +521,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -519,7 +521,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// br endBlock
// }
// }
private bool IsFallbackBlock(Block block, IType type, ILVariable target, ILVariable defaultTemporary, ILVariable resultTemporary, ILInstruction endBlockOrLeaveContainer, out ILInstruction? nullInst)
private bool IsFallbackBlock(Block block, IType type, ILVariable target, ILVariable defaultTemporary, ILVariable? resultTemporary, ILInstruction endBlockOrLeaveContainer, [NotNullWhen(true)] out ILInstruction? nullInst)
{
nullInst = null;
if (!(block.Instructions.Count == 3))

63
ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
@ -371,7 +372,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -371,7 +372,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
compRight.MatchLdNull();
}
private bool MatchThreeValuedLogicConditionPattern(ILInstruction condition, out ILVariable? nullable1, out ILVariable? nullable2)
private bool MatchThreeValuedLogicConditionPattern(ILInstruction condition, [NotNullWhen(true)] out ILVariable? nullable1, [NotNullWhen(true)] out ILVariable? nullable2)
{
// Try to match: nullable1.GetValueOrDefault() || (!nullable2.GetValueOrDefault() && !nullable1.HasValue)
nullable1 = null;
@ -518,7 +519,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -518,7 +519,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
#endregion
#region Lift...Comparison
ILInstruction LiftCSharpEqualityComparison(CompOrDecimal valueComp, ComparisonKind newComparisonKind, ILInstruction hasValueTest)
ILInstruction? LiftCSharpEqualityComparison(CompOrDecimal valueComp, ComparisonKind newComparisonKind, ILInstruction hasValueTest)
{
Debug.Assert(newComparisonKind.IsEqualityOrInequality());
bool hasValueTestNegated = false;
@ -535,9 +536,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -535,9 +536,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// Comparing two nullables: HasValue comparison must be the same operator as the Value comparison
if ((hasValueTestNegated ? hasValueComp.Kind.Negate() : hasValueComp.Kind) != newComparisonKind)
return null;
if (!MatchHasValueCall(hasValueComp.Left, out ILVariable leftVar))
if (!MatchHasValueCall(hasValueComp.Left, out ILVariable? leftVar))
return null;
if (!MatchHasValueCall(hasValueComp.Right, out ILVariable rightVar))
if (!MatchHasValueCall(hasValueComp.Right, out ILVariable? rightVar))
return null;
nullableVars = new List<ILVariable> { leftVar };
var (left, leftBits) = DoLift(valueComp.Left);
@ -551,7 +552,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -551,7 +552,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return valueComp.MakeLifted(newComparisonKind, left, right);
}
}
else if (newComparisonKind == ComparisonKind.Equality && !hasValueTestNegated && MatchHasValueCall(hasValueTest, out ILVariable v))
else if (newComparisonKind == ComparisonKind.Equality && !hasValueTestNegated && MatchHasValueCall(hasValueTest, out ILVariable? v))
{
// Comparing nullable with non-nullable -> we can fall back to the normal comparison code.
nullableVars = new List<ILVariable> { v };
@ -578,7 +579,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -578,7 +579,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// This means unlike LiftNormal(), we cannot rely on the input instruction not being evaluated if
/// a variable is <c>null</c>.
/// </summary>
ILInstruction LiftCSharpComparison(CompOrDecimal comp, ComparisonKind newComparisonKind)
ILInstruction? LiftCSharpComparison(CompOrDecimal comp, ComparisonKind newComparisonKind)
{
if (comp.IsLifted)
{
@ -614,7 +615,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -614,7 +615,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return null;
}
ILInstruction LiftCSharpUserEqualityComparison(CompOrDecimal hasValueComp, ComparisonKind newComparisonKind, ILInstruction nestedIfInst)
ILInstruction? LiftCSharpUserEqualityComparison(CompOrDecimal hasValueComp, ComparisonKind newComparisonKind, ILInstruction nestedIfInst)
{
// User-defined equality operator:
// if (comp(call get_HasValue(ldloca nullable1) == call get_HasValue(ldloca nullable2)))
@ -635,13 +636,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -635,13 +636,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// ldc.i4 0
if (hasValueComp.IsLifted)
return null;
if (!MatchHasValueCall(hasValueComp.Left, out ILVariable nullable1))
if (!MatchHasValueCall(hasValueComp.Left, out ILVariable? nullable1))
return null;
if (!MatchHasValueCall(hasValueComp.Right, out ILVariable nullable2))
if (!MatchHasValueCall(hasValueComp.Right, out ILVariable? nullable2))
return null;
if (!nestedIfInst.MatchIfInstructionPositiveCondition(out var condition, out var trueInst, out var falseInst))
return null;
if (!MatchHasValueCall(condition, out ILVariable nullable))
if (!MatchHasValueCall(condition, out ILVariable? nullable))
return null;
if (nullable != nullable1 && nullable != nullable2)
return null;
@ -687,7 +688,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -687,7 +688,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return null;
}
ILInstruction LiftCSharpUserComparison(ILInstruction trueInst, ILInstruction falseInst)
ILInstruction? LiftCSharpUserComparison(ILInstruction trueInst, ILInstruction falseInst)
{
// (v1 != null && ... && vn != null) ? trueInst : falseInst
bool trueInstNegated = false;
@ -745,13 +746,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -745,13 +746,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// where the v1,...,vn are the <c>this.nullableVars</c>.
/// If lifting fails, returns <c>null</c>.
/// </summary>
ILInstruction LiftNormal(ILInstruction trueInst, ILInstruction falseInst)
ILInstruction? LiftNormal(ILInstruction trueInst, ILInstruction falseInst)
{
if (trueInst.MatchIfInstructionPositiveCondition(out var nestedCondition, out var nestedTrue, out var nestedFalse))
{
// Sometimes Roslyn generates pointless conditions like:
// if (nullable.HasValue && (!nullable.HasValue || nullable.GetValueOrDefault() == b))
if (MatchHasValueCall(nestedCondition, out ILVariable v) && nullableVars.Contains(v))
if (MatchHasValueCall(nestedCondition, out ILVariable? v) && nullableVars.Contains(v))
{
trueInst = nestedTrue;
}
@ -851,9 +852,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -851,9 +852,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// If any relevant variable is null, the new instruction is guaranteed to evaluate to <c>null</c>
/// without having any other effect.
/// </summary>
(ILInstruction, BitSet) DoLift(ILInstruction inst)
(ILInstruction?, BitSet?) DoLift(ILInstruction inst)
{
if (MatchGetValueOrDefault(inst, out ILVariable inputVar))
if (MatchGetValueOrDefault(inst, out ILVariable? inputVar))
{
// n.GetValueOrDefault() lifted => n.
BitSet foundIndices = new BitSet(nullableVars.Count);
@ -916,7 +917,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -916,7 +917,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
else if (inst is Comp comp && !comp.IsLifted && comp.Kind == ComparisonKind.Equality
&& MatchGetValueOrDefault(comp.Left, out ILVariable v) && nullableVars.Contains(v)
&& MatchGetValueOrDefault(comp.Left, out ILVariable? v) && nullableVars.Contains(v)
&& NullableType.GetUnderlyingType(v.Type).IsKnownType(KnownTypeCode.Boolean)
&& comp.Right.MatchLdcI4(0)
)
@ -934,8 +935,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -934,8 +935,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var liftedOperator = CSharp.Resolver.CSharpOperators.LiftUserDefinedOperator(call.Method);
if (liftedOperator == null || !NullableType.IsNullable(liftedOperator.ReturnType))
return (null, null);
ILInstruction[] newArgs;
BitSet newBits;
ILInstruction?[] newArgs;
BitSet? newBits;
if (call.Arguments.Count == 1)
{
var (arg, bits) = DoLift(call.Arguments[0]);
@ -969,7 +970,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -969,7 +970,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return (null, null);
}
(ILInstruction, ILInstruction, BitSet) DoLiftBinary(ILInstruction lhs, ILInstruction rhs, IType leftExpectedType, IType rightExpectedType)
(ILInstruction?, ILInstruction?, BitSet?) DoLiftBinary(ILInstruction lhs, ILInstruction rhs, IType leftExpectedType, IType rightExpectedType)
{
var (left, leftBits) = DoLift(lhs);
var (right, rightBits) = DoLift(rhs);
@ -1018,7 +1019,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1018,7 +1019,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// <summary>
/// Matches 'call get_HasValue(arg)'
/// </summary>
internal static bool MatchHasValueCall(ILInstruction inst, out ILInstruction? arg)
internal static bool MatchHasValueCall(ILInstruction inst, [NotNullWhen(true)] out ILInstruction? arg)
{
arg = null;
if (!(inst is Call call))
@ -1036,9 +1037,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1036,9 +1037,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// <summary>
/// Matches 'call get_HasValue(ldloca v)'
/// </summary>
internal static bool MatchHasValueCall(ILInstruction inst, out ILVariable? v)
internal static bool MatchHasValueCall(ILInstruction inst, [NotNullWhen(true)] out ILVariable? v)
{
if (MatchHasValueCall(inst, out ILInstruction arg))
if (MatchHasValueCall(inst, out ILInstruction? arg))
{
return arg.MatchLdLoca(out v);
}
@ -1051,7 +1052,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1051,7 +1052,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// </summary>
internal static bool MatchHasValueCall(ILInstruction inst, ILVariable v)
{
return MatchHasValueCall(inst, out ILVariable v2) && v == v2;
return MatchHasValueCall(inst, out ILVariable? v2) && v == v2;
}
/// <summary>
@ -1065,7 +1066,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1065,7 +1066,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// <summary>
/// Matches 'newobj Nullable{underlyingType}.ctor(arg)'
/// </summary>
internal static bool MatchNullableCtor(ILInstruction inst, out IType? underlyingType, out ILInstruction? arg)
internal static bool MatchNullableCtor(ILInstruction inst, [NotNullWhen(true)] out IType? underlyingType, [NotNullWhen(true)] out ILInstruction? arg)
{
underlyingType = null;
arg = null;
@ -1083,7 +1084,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1083,7 +1084,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// <summary>
/// Matches 'call Nullable{T}.GetValueOrDefault(arg)'
/// </summary>
internal static bool MatchGetValueOrDefault(ILInstruction inst, out ILInstruction? arg)
internal static bool MatchGetValueOrDefault(ILInstruction inst, [NotNullWhen(true)] out ILInstruction? arg)
{
arg = null;
if (!(inst is Call call))
@ -1099,7 +1100,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1099,7 +1100,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// <summary>
/// Matches 'call nullableValue.GetValueOrDefault(fallback)'
/// </summary>
internal static bool MatchGetValueOrDefault(ILInstruction inst, out ILInstruction? nullableValue, out ILInstruction? fallback)
internal static bool MatchGetValueOrDefault(ILInstruction inst, [NotNullWhen(true)] out ILInstruction? nullableValue, [NotNullWhen(true)] out ILInstruction? fallback)
{
nullableValue = null;
fallback = null;
@ -1117,10 +1118,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1117,10 +1118,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// <summary>
/// Matches 'call Nullable{T}.GetValueOrDefault(ldloca v)'
/// </summary>
internal static bool MatchGetValueOrDefault(ILInstruction inst, out ILVariable? v)
internal static bool MatchGetValueOrDefault(ILInstruction inst, [NotNullWhen(true)] out ILVariable? v)
{
v = null;
return MatchGetValueOrDefault(inst, out ILInstruction arg)
return MatchGetValueOrDefault(inst, out ILInstruction? arg)
&& arg.MatchLdLoca(out v);
}
@ -1129,13 +1130,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1129,13 +1130,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// </summary>
internal static bool MatchGetValueOrDefault(ILInstruction inst, ILVariable v)
{
return MatchGetValueOrDefault(inst, out ILVariable v2) && v == v2;
return MatchGetValueOrDefault(inst, out ILVariable? v2) && v == v2;
}
static bool MatchNull(ILInstruction inst, out IType? underlyingType)
static bool MatchNull(ILInstruction inst, [NotNullWhen(true)] out IType? underlyingType)
{
underlyingType = null;
if (inst.MatchDefaultValue(out IType type))
if (inst.MatchDefaultValue(out var type))
{
underlyingType = NullableType.GetUnderlyingType(type);
return NullableType.IsNullable(type);

9
ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.IL.ControlFlow;
@ -77,7 +78,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -77,7 +78,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// <summary>
/// Matches legacy C# switch on nullable.
/// </summary>
bool MatchSwitchOnNullable(InstructionCollection<ILInstruction> instructions, int i, out SwitchInstruction? newSwitch)
bool MatchSwitchOnNullable(InstructionCollection<ILInstruction> instructions, int i, [NotNullWhen(true)] out SwitchInstruction? newSwitch)
{
newSwitch = null;
// match first block:
@ -133,7 +134,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -133,7 +134,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// <summary>
/// Matches Roslyn C# switch on nullable.
/// </summary>
bool MatchRoslynSwitchOnNullable(InstructionCollection<ILInstruction> instructions, int i, out SwitchInstruction? newSwitch)
bool MatchRoslynSwitchOnNullable(InstructionCollection<ILInstruction> instructions, int i, [NotNullWhen(true)] out SwitchInstruction? newSwitch)
{
newSwitch = null;
// match first block:
@ -143,7 +144,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -143,7 +144,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!instructions[i + 1].MatchBranch(out var switchBlock) || !trueInst.MatchBranch(out var nullCaseBlock))
return false;
if (!condition.MatchLogicNot(out var getHasValue) || !NullableLiftingTransform.MatchHasValueCall(getHasValue, out ILInstruction target) || !SemanticHelper.IsPure(target.Flags))
if (!condition.MatchLogicNot(out var getHasValue) || !NullableLiftingTransform.MatchHasValueCall(getHasValue, out ILInstruction? target) || !SemanticHelper.IsPure(target.Flags))
return false;
// match second block: switchBlock
// note: I have seen cases where switchVar is inlined into the switch.
@ -165,7 +166,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -165,7 +166,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!switchVar.IsSingleDefinition || switchVar.LoadCount != 1)
return false;
if (!(NullableLiftingTransform.MatchGetValueOrDefault(getValueOrDefault, out ILInstruction target2) && target2.Match(target).Success))
if (!(NullableLiftingTransform.MatchGetValueOrDefault(getValueOrDefault, out ILInstruction? target2) && target2.Match(target).Success))
return false;
if (!(switchBlock.Instructions[1] is SwitchInstruction si))
return false;

43
ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.IL.ControlFlow;
@ -473,7 +474,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -473,7 +474,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
bool IsIsInternedCall(Call call, out ILInstruction? argument)
bool IsIsInternedCall(Call call, [NotNullWhen(true)] out ILInstruction? argument)
{
if (call != null
&& call.Method.DeclaringType.IsKnownType(KnownTypeCode.String)
@ -503,7 +504,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -503,7 +504,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// The <paramref name="switchVariable"/> is updated if the value gets copied to a different variable.
/// See comments below for more info.
/// </summary>
ILInstruction MatchCaseBlock(Block currentBlock, ILVariable switchVariable, out string? value, out bool emptyStringEqualsNull, out ILInstruction? caseBlockOrLeave)
ILInstruction? MatchCaseBlock(Block currentBlock, ILVariable switchVariable, out string? value, out bool emptyStringEqualsNull, out ILInstruction? caseBlockOrLeave)
{
value = null;
caseBlockOrLeave = null;
@ -534,12 +535,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -534,12 +535,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
return null;
}
if (nextBlockBranch.MatchBranch(out Block nextBlock))
if (nextBlockBranch.MatchBranch(out Block? nextBlock))
{
// success
return nextBlock;
}
else if (nextBlockBranch.MatchLeave(out BlockContainer blockContainer))
else if (nextBlockBranch.MatchLeave(out BlockContainer? blockContainer))
{
// success
return blockContainer;
@ -740,7 +741,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -740,7 +741,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
bool AddNullSection(List<SwitchSection> sections, List<(string Value, int Index)> stringValues, Block nullValueCaseBlock)
bool AddNullSection(List<SwitchSection> sections, List<(string? Value, int Index)> stringValues, Block nullValueCaseBlock)
{
var label = new LongSet(stringValues.Max(item => item.Index) + 1);
var possibleConflicts = sections.Where(sec => sec.Labels.Overlaps(label)).ToArray();
@ -760,7 +761,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -760,7 +761,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// <summary>
/// Matches 'volatile.ldobj dictionaryType(ldsflda dictField)'
/// </summary>
bool MatchDictionaryFieldLoad(ILInstruction inst, Func<IType, bool> typeMatcher, out IField? dictField, out IType? dictionaryType)
bool MatchDictionaryFieldLoad(ILInstruction inst, Func<IType, bool> typeMatcher, [NotNullWhen(true)] out IField? dictField, [NotNullWhen(true)] out IType? dictionaryType)
{
dictField = null;
dictionaryType = null;
@ -773,7 +774,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -773,7 +774,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// <summary>
/// Matches and extracts values from Add-call sequences.
/// </summary>
bool ExtractStringValuesFromInitBlock(Block block, out List<(string, int)>? values, out Block? blockAfterInit, IType dictionaryType, IField dictionaryField, bool isHashtablePattern)
bool ExtractStringValuesFromInitBlock(Block block, [NotNullWhen(true)] out List<(string?, int)>? values, [NotNullWhen(true)] out Block? blockAfterInit, IType dictionaryType, IField dictionaryField, bool isHashtablePattern)
{
values = null;
blockAfterInit = null;
@ -797,7 +798,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -797,7 +798,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (!newObj.Arguments[0].MatchLdcI4(out valuesLength))
return false;
}
values = new List<(string, int)>(valuesLength);
values = new List<(string?, int)>(valuesLength);
int i = 0;
while (MatchAddCall(dictionaryType, block.Instructions[i + 1], dictVar, out var index, out var value))
{
@ -822,7 +823,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -822,7 +823,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// -or-
/// call Add(ldloc dictVar, ldstr value, box System.Int32(ldc.i4 index))
/// </summary>
bool MatchAddCall(IType dictionaryType, ILInstruction inst, ILVariable dictVar, out int index, out string? value)
bool MatchAddCall(IType dictionaryType, ILInstruction inst, ILVariable dictVar, out int index, [NotNullWhen(true)] out string? value)
{
value = null;
index = -1;
@ -941,7 +942,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -941,7 +942,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
bool FindHashtableInitBlock(Block entryPoint, out List<(string, int)>? stringValues, out IField? dictField, out Block? blockAfterThisInitBlock, out ILInstruction? thisSwitchInitJumpInst, out ILInstruction? nextSwitchInitJumpInst)
bool FindHashtableInitBlock(Block entryPoint, out List<(string?, int)>? stringValues, out IField? dictField, out Block? blockAfterThisInitBlock, out ILInstruction? thisSwitchInitJumpInst, out ILInstruction? nextSwitchInitJumpInst)
{
stringValues = null;
dictField = null;
@ -1310,7 +1311,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1310,7 +1311,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
bool MatchSwitchOnCharBlock(Block block, int length, ILVariable switchValueVar, out List<(string StringValue, ILInstruction BodyOrLeave)>? results)
bool MatchSwitchOnCharBlock(Block block, int length, ILVariable switchValueVar, [NotNullWhen(true)] out List<(string StringValue, ILInstruction BodyOrLeave)>? results)
{
results = null;
if (block.IncomingEdgeCount != 1)
@ -1399,12 +1400,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1399,12 +1400,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return results?.Count > 0;
}
bool MatchSwitchOnLengthBlock(ref ILVariable switchValueVar, Block switchOnLengthBlock, int startOffset, out List<(LongSet Length, Block TargetBlock)>? blocks)
bool MatchSwitchOnLengthBlock(ref ILVariable switchValueVar, Block switchOnLengthBlock, int startOffset, [NotNullWhen(true)] out List<(LongSet Length, Block TargetBlock)>? blocks)
{
blocks = null;
SwitchInstruction? @switch;
ILInstruction getLengthCall;
ILVariable lengthVar;
ILInstruction? getLengthCall;
ILVariable? lengthVar;
switch (switchOnLengthBlock.Instructions.Count - startOffset)
{
case 1:
@ -1506,7 +1507,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1506,7 +1507,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// br newDefaultBlock
/// }
/// </summary>
private bool IsNullCheckInDefaultBlock(ref Block exitOrDefaultBlock, ILVariable switchVar, out Block? nullValueCaseBlock)
private bool IsNullCheckInDefaultBlock(ref Block exitOrDefaultBlock, ILVariable switchVar, [NotNullWhen(true)] out Block? nullValueCaseBlock)
{
nullValueCaseBlock = null;
if (exitOrDefaultBlock == null)
@ -1532,7 +1533,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1532,7 +1533,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// if (call op_Equality(ldloc switchValueVar, stringValue)) br body
/// br exit
/// </summary>
bool MatchRoslynCaseBlockHead(Block target, ILVariable switchValueVar, out ILInstruction? bodyOrLeave, out Block? defaultOrExitBlock, out string? stringValue, out bool emptyStringEqualsNull)
bool MatchRoslynCaseBlockHead(Block target, ILVariable switchValueVar, [NotNullWhen(true)] out ILInstruction? bodyOrLeave, [NotNullWhen(true)] out Block? defaultOrExitBlock, [NotNullWhen(true)] out string? stringValue, out bool emptyStringEqualsNull)
{
bodyOrLeave = null;
defaultOrExitBlock = null;
@ -1592,7 +1593,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1592,7 +1593,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// br exit
/// }
/// </summary>
bool MatchRoslynEmptyStringCaseBlockHead(Block target, ILVariable switchValueVar, out ILInstruction? bodyOrLeave, out Block? defaultOrExitBlock)
bool MatchRoslynEmptyStringCaseBlockHead(Block target, ILVariable switchValueVar, [NotNullWhen(true)] out ILInstruction? bodyOrLeave, [NotNullWhen(true)] out Block? defaultOrExitBlock)
{
bodyOrLeave = null;
defaultOrExitBlock = null;
@ -1602,7 +1603,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1602,7 +1603,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!nullComparisonCondition.MatchCompEqualsNull(out var arg) || !arg.MatchLdLoc(switchValueVar))
return false;
if (!target.Instructions[1].MatchBranch(out Block lengthCheckBlock))
if (!target.Instructions[1].MatchBranch(out Block? lengthCheckBlock))
return false;
if (lengthCheckBlock.Instructions.Count != 2 || lengthCheckBlock.IncomingEdgeCount != 1)
return false;
@ -1660,7 +1661,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1660,7 +1661,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// - or -
/// 'stloc(targetVar, call ComputeReadOnlySpanHash(ldloc switchValue))'
/// </summary>
internal static bool MatchComputeStringOrReadOnlySpanHashCall(ILInstruction inst, ILVariable targetVar, out LdLoc? switchValue)
internal static bool MatchComputeStringOrReadOnlySpanHashCall(ILInstruction inst, ILVariable targetVar, [NotNullWhen(true)] out LdLoc? switchValue)
{
switchValue = null;
if (!inst.MatchStLoc(targetVar, out var value))
@ -1682,7 +1683,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1682,7 +1683,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// or 'comp(ldloc(variable) == ldnull)'
/// or 'call SequenceEqual(ldloc variable, call AsSpan(ldstr stringValue))'
/// </summary>
bool MatchStringEqualityComparison(ILInstruction condition, ILVariable variable, out string stringValue, out bool isVBCompareString)
bool MatchStringEqualityComparison(ILInstruction condition, ILVariable variable, out string? stringValue, out bool isVBCompareString)
{
return MatchStringEqualityComparison(condition, out var v, out stringValue, out isVBCompareString) && v == variable;
}
@ -1692,7 +1693,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1692,7 +1693,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// or 'comp(ldloc(variable) == ldnull)'
/// or 'call SequenceEqual(ldloc variable, call AsSpan(ldstr stringValue))'
/// </summary>
bool MatchStringEqualityComparison(ILInstruction condition, out ILVariable? variable, out string? stringValue, out bool isVBCompareString)
bool MatchStringEqualityComparison(ILInstruction condition, [NotNullWhen(true)] out ILVariable? variable, out string? stringValue, out bool isVBCompareString)
{
stringValue = null;
variable = null;

36
ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
@ -114,7 +115,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -114,7 +115,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
}
internal static bool TransformSpanTArrayInitialization(NewObj inst, StatementTransformContext context, out ILInstruction? replacement)
internal static bool TransformSpanTArrayInitialization(NewObj inst, StatementTransformContext context, [NotNullWhen(true)] out ILInstruction? replacement)
{
replacement = null;
if (!context.Settings.ArrayInitializers)
@ -143,7 +144,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -143,7 +144,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
}
private static unsafe bool DecodeUTF8String(BlobReader blob, int size, out string? text)
private static unsafe bool DecodeUTF8String(BlobReader blob, int size, [NotNullWhen(true)] out string? text)
{
if (size > blob.RemainingBytes)
{
@ -166,7 +167,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -166,7 +167,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return MemoryExtensions.SequenceEqual(bytes, new ReadOnlySpan<byte>(blob.CurrentPointer, size));
}
static bool MatchSpanTCtorWithPointerAndSize(NewObj newObj, StatementTransformContext context, out IType? elementType, out FieldDefinition field, out int size)
static bool MatchSpanTCtorWithPointerAndSize(NewObj newObj, StatementTransformContext context, [NotNullWhen(true)] out IType? elementType, [NotNullWhen(true)] out FieldDefinition field, out int size)
{
field = default;
size = default;
@ -288,7 +289,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -288,7 +289,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
bool HandleCpblkInitializer(Block block, int pos, ILVariable v, long length, out BlobReader blob, out IType? elementType)
bool HandleCpblkInitializer(Block block, int pos, ILVariable v, long length, [NotNullWhen(true)] out BlobReader blob, [NotNullWhen(true)] out IType? elementType)
{
blob = default;
elementType = null;
@ -334,7 +335,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -334,7 +335,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
bool MatchGetStaticFieldAddress(ILInstruction input, out IField field)
bool MatchGetStaticFieldAddress(ILInstruction input, [NotNullWhen(true)] out IField? field)
{
if (input.MatchLdsFlda(out field))
return true;
@ -359,7 +360,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -359,7 +360,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
static bool IsRuntimeHelpers(IType type) => type is { Name: "RuntimeHelpers", Namespace: "System.Runtime.CompilerServices" };
unsafe bool HandleSequentialLocAllocInitializer(Block block, int pos, ILVariable store, ILInstruction locAllocInstruction, out IType? elementType, out StObj[]? values, out int instructionsToRemove)
unsafe bool HandleSequentialLocAllocInitializer(Block block, int pos, ILVariable store, ILInstruction locAllocInstruction, [NotNullWhen(true)] out IType? elementType, [NotNullWhen(true)] out StObj[]? values, out int instructionsToRemove)
{
int elementCount = 0;
long minExpectedOffset = 0;
@ -399,7 +400,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -399,7 +400,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
for (int i = pos; i < block.Instructions.Count; i++)
{
// match the basic stobj pattern
if (!block.Instructions[i].MatchStObj(out ILInstruction target, out var value, out var currentType)
if (!block.Instructions[i].MatchStObj(out ILInstruction? target, out var value, out var currentType)
|| value.Descendants.OfType<IInstructionWithVariableOperand>().Any(inst => inst.Variable == store))
break;
// first
@ -462,7 +463,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -462,7 +463,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
elementType = ((PointerType)finalStore.Variable.Type).ElementType;
}
instructionsToRemove += elementCount;
return elementCount <= values.Length;
}
@ -498,7 +498,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -498,7 +498,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// <summary>
/// Handle simple case where RuntimeHelpers.InitializeArray is not used.
/// </summary>
internal static bool HandleSimpleArrayInitializer(ILFunction function, Block block, int pos, ILVariable store, int[] arrayLength, out (ILInstruction[] Indices, ILInstruction Value)[]? values, out int instructionsToRemove)
internal static bool HandleSimpleArrayInitializer(ILFunction function, Block block, int pos, ILVariable store, int[] arrayLength, [NotNullWhen(true)] out (ILInstruction[] Indices, ILInstruction? Value)[]? values, out int instructionsToRemove)
{
instructionsToRemove = 0;
int elementCount = 0;
@ -508,11 +508,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -508,11 +508,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// To prevent excessive allocations, use min(|block|, arraySize) als initial capacity.
// This should prevent list-resizing as well as out-of-memory errors.
values = null;
var valuesList = new List<(ILInstruction[] Indices, ILInstruction Value)>(Math.Min(block.Instructions.Count, length));
var valuesList = new List<(ILInstruction[] Indices, ILInstruction? Value)>(Math.Min(block.Instructions.Count, length));
int[] nextMinimumIndex = new int[arrayLength.Length];
ILInstruction[] CalculateNextIndices(InstructionCollection<ILInstruction> indices, out bool exactMatch)
ILInstruction[]? CalculateNextIndices(InstructionCollection<ILInstruction>? indices, out bool exactMatch)
{
var nextIndices = new ILInstruction[arrayLength.Length];
exactMatch = true;
@ -565,7 +565,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -565,7 +565,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
InstructionCollection<ILInstruction> indices;
// stobj elementType(ldelema elementType(ldloc store, indices), value)
if (block.Instructions[i].MatchStObj(out ILInstruction target, out ILInstruction value, out IType type))
if (block.Instructions[i].MatchStObj(out var target, out var value, out var type))
{
if (!(target is LdElema ldelem && ldelem.Array.MatchLdLoc(store)))
break;
@ -620,7 +620,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -620,7 +620,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
if (i < block.Instructions.Count)
{
if (block.Instructions[i].MatchStObj(out ILInstruction target, out ILInstruction value, out IType type))
if (block.Instructions[i].MatchStObj(out var target, out var value, out var type))
{
// An element of the array is modified directly after the initializer:
// Abort transform, so that partial initializers are not constructed.
@ -671,7 +671,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -671,7 +671,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
// 1. Instruction: (optional) temporary copy of store
bool hasTemporaryCopy = block.Instructions[pos].MatchStLoc(out var temp, out var storeLoad) && storeLoad.MatchLdLoc(store);
ILInstruction initializer;
ILInstruction? initializer;
if (hasTemporaryCopy)
{
if (!MatchJaggedArrayStore(block, pos + 1, temp, i, out initializer, out _))
@ -703,7 +703,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -703,7 +703,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
bool MatchJaggedArrayStore(Block block, int pos, ILVariable store, int index, out ILInstruction? initializer, out IType? type)
bool MatchJaggedArrayStore(Block block, int pos, ILVariable store, int index, [NotNullWhen(true)] out ILInstruction? initializer, [NotNullWhen(true)] out IType? type)
{
initializer = null;
type = null;
@ -751,7 +751,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -751,7 +751,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return block;
}
static bool MatchNewArr(ILInstruction instruction, out IType? arrayType, out int[]? length)
static bool MatchNewArr(ILInstruction instruction, [NotNullWhen(true)] out IType? arrayType, [NotNullWhen(true)] out int[]? length)
{
length = null;
arrayType = null;
@ -769,7 +769,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -769,7 +769,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
bool MatchInitializeArrayCall(ILInstruction instruction, out ILInstruction? array, out FieldDefinition field)
bool MatchInitializeArrayCall(ILInstruction instruction, [NotNullWhen(true)] out ILInstruction? array, [NotNullWhen(true)] out FieldDefinition field)
{
array = null;
field = default;
@ -789,7 +789,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -789,7 +789,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
bool HandleRuntimeHelpersInitializeArray(Block body, int pos, ILVariable array, IType arrayType, int[] arrayLength, out ILInstruction[]? values, out int foundPos)
bool HandleRuntimeHelpersInitializeArray(Block body, int pos, ILVariable array, IType arrayType, int[] arrayLength, [NotNullWhen(true)] out ILInstruction[]? values, out int foundPos)
{
if (MatchInitializeArrayCall(body.Instructions[pos], out var arrayInst, out var field) && arrayInst.MatchLdLoc(array))
{

7
ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
@ -677,8 +678,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -677,8 +678,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
///
/// Every IsCompoundStore() call should be followed by an IsMatchingCompoundLoad() call.
/// </remarks>
static bool IsCompoundStore(ILInstruction inst, out IType? storeType,
out ILInstruction? value, ICompilation compilation)
static bool IsCompoundStore(ILInstruction inst, [NotNullWhen(true)] out IType? storeType,
[NotNullWhen(true)] out ILInstruction? value, ICompilation compilation)
{
value = null;
storeType = null;
@ -1025,7 +1026,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1025,7 +1026,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
static bool IsSameMember(IMember a, IMember b)
static bool IsSameMember(IMember? a, IMember? b)
{
if (a == null || b == null)
return false;

13
ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection.Metadata;
@ -588,7 +589,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -588,7 +589,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
internal static bool IsClosure(ILTransformContext context, ILVariable variable, out ITypeDefinition? closureType, out ILInstruction? initializer)
internal static bool IsClosure(ILTransformContext context, ILVariable variable, [NotNullWhen(true)] out ITypeDefinition? closureType, [NotNullWhen(true)] out ILInstruction? initializer)
{
closureType = null;
initializer = null;
@ -610,7 +611,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -610,7 +611,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
}
static bool IsClosureInit(ILTransformContext context, StLoc inst, out ITypeDefinition? closureType)
static bool IsClosureInit(ILTransformContext context, StLoc inst, [NotNullWhen(true)] out ITypeDefinition? closureType)
{
if (inst.Value is NewObj newObj)
{
@ -840,18 +841,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -840,18 +841,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms
EarlyExpressionTransforms.LdObjToLdLoc(inst, context);
}
private bool IsDisplayClassLoad(ILInstruction target, out ILVariable variable)
private bool IsDisplayClassLoad(ILInstruction target, [NotNullWhen(true)] out ILVariable? variable)
{
// We cannot use MatchLdLocRef here because local functions use ref parameters
if (!target.MatchLdLoc(out variable) && !target.MatchLdLoca(out variable))
return false;
if (displayClassCopyMap.TryGetValue(variable, out ILVariable other))
if (displayClassCopyMap.TryGetValue(variable, out ILVariable? other))
variable = other;
return true;
}
private bool IsDisplayClassFieldAccess(ILInstruction inst,
out ILVariable? displayClassVar, out DisplayClass? displayClass, out IField? field)
[NotNullWhen(true)] out ILVariable? displayClassVar, [NotNullWhen(true)] out DisplayClass? displayClass, [NotNullWhen(true)] out IField? field)
{
displayClass = null;
displayClassVar = null;
@ -867,7 +868,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -867,7 +868,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
base.VisitLdFlda(inst);
// Get display class info
if (!IsDisplayClassFieldAccess(inst, out _, out DisplayClass displayClass, out IField field))
if (!IsDisplayClassFieldAccess(inst, out _, out DisplayClass? displayClass, out IField? field))
return;
var keyField = (IField)field.MemberDefinition;
var v = displayClass.VariablesToDeclare[keyField];

19
ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.CSharp.Resolver;
@ -63,7 +64,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -63,7 +64,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
}
bool MatchParameterVariableAssignment(ILInstruction expr, out ILVariable parameterReferenceVar, out IType? type, out string? name)
bool MatchParameterVariableAssignment(ILInstruction expr, [NotNullWhen(true)] out ILVariable? parameterReferenceVar, [NotNullWhen(true)] out IType? type, [NotNullWhen(true)] out string? name)
{
// stloc(v, call(Expression::Parameter, call(Type::GetTypeFromHandle, ldtoken(...)), ldstr(...)))
type = null;
@ -1124,7 +1125,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1124,7 +1125,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return (BuildInitializer, arrayType);
}
bool MatchNew(CallInstruction invocation, out IMethod? ctor)
bool MatchNew(CallInstruction invocation, [NotNullWhen(true)] out IMethod? ctor)
{
ctor = null;
if (invocation.Method.Name != "New")
@ -1413,7 +1414,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1413,7 +1414,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return variable.Type.FullName == "System.Linq.Expressions.ParameterExpression";
}
bool MatchConstantCall(ILInstruction inst, out ILInstruction? value, out IType? type)
bool MatchConstantCall(ILInstruction inst, [NotNullWhen(true)] out ILInstruction? value, [NotNullWhen(true)] out IType? type)
{
value = null;
type = null;
@ -1436,7 +1437,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1436,7 +1437,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
}
internal static bool MatchGetTypeFromHandle(ILInstruction inst, out IType? type)
internal static bool MatchGetTypeFromHandle(ILInstruction inst, [NotNullWhen(true)] out IType? type)
{
type = null;
return inst is CallInstruction getTypeCall
@ -1445,7 +1446,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1445,7 +1446,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
&& getTypeCall.Arguments[0].MatchLdTypeToken(out type);
}
bool MatchGetMethodFromHandle(ILInstruction inst, out IMember? member)
bool MatchGetMethodFromHandle(ILInstruction inst, [NotNullWhen(true)] out IMember? member)
{
member = null;
//castclass System.Reflection.MethodInfo(call GetMethodFromHandle(ldmembertoken op_Addition))
@ -1458,7 +1459,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1458,7 +1459,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return MatchFromHandleParameterList(call, out member);
}
bool MatchGetConstructorFromHandle(ILInstruction inst, out IMember? member)
bool MatchGetConstructorFromHandle(ILInstruction inst, [NotNullWhen(true)] out IMember? member)
{
member = null;
//castclass System.Reflection.ConstructorInfo(call GetMethodFromHandle(ldmembertoken op_Addition))
@ -1471,7 +1472,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1471,7 +1472,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return MatchFromHandleParameterList(call, out member);
}
bool MatchGetFieldFromHandle(ILInstruction inst, out IMember? member)
bool MatchGetFieldFromHandle(ILInstruction inst, [NotNullWhen(true)] out IMember? member)
{
member = null;
if (!(inst is CallInstruction call && call.Method.FullName == "System.Reflection.FieldInfo.GetFieldFromHandle"))
@ -1479,7 +1480,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1479,7 +1480,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return MatchFromHandleParameterList(call, out member);
}
static bool MatchFromHandleParameterList(CallInstruction call, out IMember? member)
static bool MatchFromHandleParameterList(CallInstruction call, [NotNullWhen(true)] out IMember? member)
{
member = null;
switch (call.Arguments.Count)
@ -1500,7 +1501,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1500,7 +1501,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
bool MatchArgumentList(ILInstruction inst, out IList<ILInstruction>? arguments)
bool MatchArgumentList(ILInstruction inst, [NotNullWhen(true)] out IList<ILInstruction>? arguments)
{
arguments = null;
if (!(inst is Block block && block.Kind == BlockKind.ArrayInitializer))

3
ICSharpCode.Decompiler/IL/Transforms/TupleTransform.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using ICSharpCode.Decompiler.TypeSystem;
@ -59,7 +60,7 @@ namespace ICSharpCode.Decompiler.IL @@ -59,7 +60,7 @@ namespace ICSharpCode.Decompiler.IL
/// Matches 'newobj TupleType(...)'.
/// Takes care of flattening long tuples.
/// </summary>
public static bool MatchTupleConstruction(NewObj? newobj, out ILInstruction[]? arguments)
public static bool MatchTupleConstruction(NewObj? newobj, [NotNullWhen(true)] out ILInstruction[]? arguments)
{
arguments = null;
if (newobj == null)

3
ICSharpCode.Decompiler/IL/Transforms/UserDefinedLogicTransform.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
@ -116,7 +117,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -116,7 +117,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
}
static bool MatchCondition(ILInstruction condition, out ILVariable? v, out string? name)
static bool MatchCondition(ILInstruction condition, [NotNullWhen(true)] out ILVariable? v, [NotNullWhen(true)] out string? name)
{
v = null;
name = null;

3
ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
@ -488,7 +489,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -488,7 +489,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
bool CheckAsyncResourceType(IType type, out string? disposeMethodFullName)
bool CheckAsyncResourceType(IType type, [NotNullWhen(true)] out string? disposeMethodFullName)
{
disposeMethodFullName = null;
IType t = NullableType.GetUnderlyingType(type);

5
ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
@ -73,7 +74,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -73,7 +74,7 @@ namespace ICSharpCode.Decompiler.Metadata
$"PublicKeyToken={publicKey}";
}
public static bool TryGetFullAssemblyName(this MetadataReader reader, out string? assemblyName)
public static bool TryGetFullAssemblyName(this MetadataReader reader, [NotNullWhen(true)] out string? assemblyName)
{
try
{
@ -124,7 +125,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -124,7 +125,7 @@ namespace ICSharpCode.Decompiler.Metadata
return builder.ToString();
}
public static bool TryGetFullAssemblyName(this SRM.AssemblyReference reference, MetadataReader reader, out string? assemblyName)
public static bool TryGetFullAssemblyName(this SRM.AssemblyReference reference, MetadataReader reader, [NotNullWhen(true)] out string? assemblyName)
{
try
{

3
ICSharpCode.Decompiler/Metadata/ReferenceLoadInfo.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
namespace ICSharpCode.Decompiler.Metadata
@ -58,7 +59,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -58,7 +59,7 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
public bool TryGetInfo(string fullName, out UnresolvedAssemblyNameReference info)
public bool TryGetInfo(string fullName, [NotNullWhen(true)] out UnresolvedAssemblyNameReference? info)
{
lock (loadedAssemblyReferences)
{

2
ICSharpCode.Decompiler/TypeSystem/GenericContext.cs

@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
this.MethodTypeParameters = null;
}
public GenericContext(IReadOnlyList<ITypeParameter> classTypeParameters, IReadOnlyList<ITypeParameter> methodTypeParameters)
public GenericContext(IReadOnlyList<ITypeParameter>? classTypeParameters, IReadOnlyList<ITypeParameter>? methodTypeParameters)
{
this.ClassTypeParameters = classTypeParameters;
this.MethodTypeParameters = methodTypeParameters;

5
ICSharpCode.Decompiler/TypeSystem/TaskType.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Diagnostics.CodeAnalysis;
namespace ICSharpCode.Decompiler.TypeSystem
{
@ -59,10 +60,10 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -59,10 +60,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// <summary>
/// Gets whether the specified type is a Task-like type.
/// </summary>
public static bool IsCustomTask(IType type, out IType? builderType)
public static bool IsCustomTask(IType type, [NotNullWhen(true)] out IType? builderType)
{
builderType = null;
ITypeDefinition def = type.GetDefinition();
ITypeDefinition? def = type.GetDefinition();
if (def != null)
{
if (def.TypeParameterCount > 1)

4
ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs

@ -23,6 +23,8 @@ using ICSharpCode.ILSpy.TreeNodes; @@ -23,6 +23,8 @@ using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
{
using System.Diagnostics.CodeAnalysis;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpyX.Analyzers;
@ -68,7 +70,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes @@ -68,7 +70,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
}
}
bool TryFindBackingField(IEvent analyzedEvent, out IField backingField)
bool TryFindBackingField(IEvent analyzedEvent, [NotNullWhen(true)] out IField? backingField)
{
backingField = null;
foreach (var field in analyzedEvent.DeclaringTypeDefinition.GetFields(options: GetMemberOptions.IgnoreInheritedMembers))

Loading…
Cancel
Save