Browse Source

Fix #2140: ILSpy 6.2p1 no longer respects "use discards" setting

pull/2145/head
Siegfried Pammer 5 years ago
parent
commit
04f9603768
  1. 35
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Discards.cs
  2. 2
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs
  3. 2
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs
  4. 4
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/OutVariables.cs
  5. 2
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ThrowExpressions.cs
  6. 8
      ICSharpCode.Decompiler/CSharp/Annotations.cs
  7. 98
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  8. 23
      ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs
  9. 2
      ICSharpCode.Decompiler/Semantics/OutVarResolveResult.cs

35
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Discards.cs

@ -14,6 +14,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
value = 0; value = 0;
} }
public void GetOutOverloaded(out int value)
{
value = 0;
}
public void GetOutOverloaded(out string value)
{
value = "Hello World";
}
public void MakeValue(Func<object, string, int> func) public void MakeValue(Func<object, string, int> func)
{ {
@ -28,16 +38,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
} }
// out _ is currently not supported: the test cases below are not useful public void ParameterHiddenByLocal(@_ _)
//public void ParameterHiddenByLocal(@_ _) {
//{ GetOut(out var _);
// GetOut(out int value); }
//}
//public void DiscardedOutVsLambdaParameter() public void DiscardedOutVsLambdaParameter()
//{ {
// GetOut(out int value); GetOut(out var _);
// MakeValue((@_ _) => 5); MakeValue((@_ _) => 5);
//} }
public void ExplicitlyTypedDiscard()
{
GetOutOverloaded(out string _);
GetOutOverloaded(out int _);
}
} }
} }

2
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs

@ -82,7 +82,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private static void RefCallSiteTests() private static void RefCallSiteTests()
{ {
#if CS70 #if CS70
CallWithOut(out dynamic d); CallWithOut(out var d);
CallWithIn(in d); CallWithIn(in d);
#else #else
dynamic d; dynamic d;

2
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs

@ -1040,7 +1040,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
await Task.Delay(100); await Task.Delay(100);
#if CS70 #if CS70
if (string.IsNullOrEmpty(str) && int.TryParse(str, out int id)) if (string.IsNullOrEmpty(str) && int.TryParse(str, out var id))
{ {
#else #else
int id; int id;

4
ICSharpCode.Decompiler.Tests/TestCases/Pretty/OutVariables.cs

@ -25,7 +25,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
public static void OutVarInShortCircuit(Dictionary<int, string> d) public static void OutVarInShortCircuit(Dictionary<int, string> d)
{ {
if (d.Count > 2 && d.TryGetValue(42, out string value)) if (d.Count > 2 && d.TryGetValue(42, out var value))
{ {
Console.WriteLine(value); Console.WriteLine(value);
} }
@ -35,7 +35,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
// Note: needs reasoning about "definitely assigned if true" // Note: needs reasoning about "definitely assigned if true"
// to ensure that the value is initialized when the delegate is declared. // to ensure that the value is initialized when the delegate is declared.
if (d.Count > 2 && d.TryGetValue(42, out string value)) if (d.Count > 2 && d.TryGetValue(42, out var value))
{ {
return delegate { return delegate {
Console.WriteLine(value); Console.WriteLine(value);

2
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ThrowExpressions.cs

@ -32,7 +32,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private static int? GetIntOrNull(string v) private static int? GetIntOrNull(string v)
{ {
if (int.TryParse(v, out int result)) if (int.TryParse(v, out var result))
{ {
return result; return result;
} }

8
ICSharpCode.Decompiler/CSharp/Annotations.cs

@ -345,4 +345,12 @@ namespace ICSharpCode.Decompiler.CSharp
this.EqualsLambda = equals; this.EqualsLambda = equals;
} }
} }
/// <summary>
/// Annotates an out DirectionExpression if the out variable can be declared implicitly typed.
/// </summary>
public class UseImplicitlyTypedOutAnnotation
{
public static readonly UseImplicitlyTypedOutAnnotation Instance = new UseImplicitlyTypedOutAnnotation();
}
} }

98
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -52,6 +52,7 @@ namespace ICSharpCode.Decompiler.CSharp
public IReadOnlyList<int> ArgumentToParameterMap; public IReadOnlyList<int> ArgumentToParameterMap;
public bool AddNamesToPrimitiveValues; public bool AddNamesToPrimitiveValues;
public bool UseImplicitlyTypedOut;
public bool IsExpandedForm; public bool IsExpandedForm;
public int Length => Arguments.Length; public int Length => Arguments.Length;
@ -62,9 +63,33 @@ namespace ICSharpCode.Decompiler.CSharp
return FirstOptionalArgumentIndex; return FirstOptionalArgumentIndex;
} }
public IEnumerable<ResolveResult> GetArgumentResolveResults(int skipCount = 0) public IList<ResolveResult> GetArgumentResolveResults(int skipCount = 0)
{ {
return Arguments.Skip(skipCount).Take(GetActualArgumentCount()).Select(a => a.ResolveResult); var expectedParameters = ExpectedParameters;
var useImplicitlyTypedOut = UseImplicitlyTypedOut;
return Arguments
.SelectWithIndex(GetResolveResult)
.Skip(skipCount)
.Take(GetActualArgumentCount())
.ToArray();
ResolveResult GetResolveResult(int index, TranslatedExpression expression)
{
var param = expectedParameters[index];
if (useImplicitlyTypedOut && param.IsOut)
return OutVarResolveResult.Instance;
return expression.ResolveResult;
}
}
public IList<ResolveResult> GetArgumentResolveResultsDirect(int skipCount = 0)
{
return Arguments
.Skip(skipCount)
.Take(GetActualArgumentCount())
.Select(a => a.ResolveResult)
.ToArray();
} }
public IEnumerable<Expression> GetArgumentExpressions(int skipCount = 0) public IEnumerable<Expression> GetArgumentExpressions(int skipCount = 0)
@ -87,9 +112,10 @@ namespace ICSharpCode.Decompiler.CSharp
} }
} }
int argumentCount = GetActualArgumentCount(); int argumentCount = GetActualArgumentCount();
var useImplicitlyTypedOut = UseImplicitlyTypedOut;
if (ArgumentNames == null) if (ArgumentNames == null)
{ {
return Arguments.Skip(skipCount).Take(argumentCount).Select(arg => arg.Expression); return Arguments.Skip(skipCount).Take(argumentCount).Select(arg => AddAnnotations(arg.Expression));
} }
else else
{ {
@ -97,11 +123,23 @@ namespace ICSharpCode.Decompiler.CSharp
return Arguments.Take(argumentCount).Zip(ArgumentNames.Take(argumentCount), return Arguments.Take(argumentCount).Zip(ArgumentNames.Take(argumentCount),
(arg, name) => { (arg, name) => {
if (name == null) if (name == null)
return arg.Expression; return AddAnnotations(arg.Expression);
else else
return new NamedArgumentExpression(name, arg); return new NamedArgumentExpression(name, AddAnnotations(arg.Expression));
}); });
} }
Expression AddAnnotations(Expression expression)
{
if (!useImplicitlyTypedOut)
return expression;
if (expression.GetResolveResult() is ByReferenceResolveResult brrr
&& brrr.IsOut)
{
expression.AddAnnotation(UseImplicitlyTypedOutAnnotation.Instance);
}
return expression;
}
} }
public bool CanInferAnonymousTypePropertyNamesFromArguments() public bool CanInferAnonymousTypePropertyNamesFromArguments()
@ -255,13 +293,14 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
return new InvocationExpression(target, argumentList.GetArgumentExpressions()) return new InvocationExpression(target, argumentList.GetArgumentExpressions())
.WithRR(new CSharpInvocationResolveResult(target.ResolveResult, method, .WithRR(new CSharpInvocationResolveResult(target.ResolveResult, method,
argumentList.GetArgumentResolveResults().ToList(), isExpandedForm: argumentList.IsExpandedForm)); argumentList.GetArgumentResolveResults(), isExpandedForm: argumentList.IsExpandedForm));
} }
if (method is VarArgInstanceMethod) if (method is VarArgInstanceMethod)
{ {
argumentList.FirstOptionalArgumentIndex = -1; argumentList.FirstOptionalArgumentIndex = -1;
argumentList.AddNamesToPrimitiveValues = false; argumentList.AddNamesToPrimitiveValues = false;
argumentList.UseImplicitlyTypedOut = false;
int regularParameterCount = ((VarArgInstanceMethod)method).RegularParameterCount; int regularParameterCount = ((VarArgInstanceMethod)method).RegularParameterCount;
var argListArg = new UndocumentedExpression(); var argListArg = new UndocumentedExpression();
argListArg.UndocumentedExpressionType = UndocumentedExpressionType.ArgList; argListArg.UndocumentedExpressionType = UndocumentedExpressionType.ArgList;
@ -293,7 +332,7 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
return new InvocationExpression(target, argumentList.GetArgumentExpressions()) return new InvocationExpression(target, argumentList.GetArgumentExpressions())
.WithRR(new CSharpInvocationResolveResult(target.ResolveResult, method, .WithRR(new CSharpInvocationResolveResult(target.ResolveResult, method,
argumentList.GetArgumentResolveResults().ToList(), isExpandedForm: argumentList.IsExpandedForm, isDelegateInvocation: true)); argumentList.GetArgumentResolveResults(), isExpandedForm: argumentList.IsExpandedForm, isDelegateInvocation: true));
} }
if (settings.StringInterpolation && IsInterpolatedStringCreation(method, argumentList) && if (settings.StringInterpolation && IsInterpolatedStringCreation(method, argumentList) &&
@ -340,7 +379,7 @@ namespace ICSharpCode.Decompiler.CSharp
} }
var formattableStringType = expressionBuilder.compilation.FindType(KnownTypeCode.FormattableString); var formattableStringType = expressionBuilder.compilation.FindType(KnownTypeCode.FormattableString);
var isrr = new InterpolatedStringResolveResult(expressionBuilder.compilation.FindType(KnownTypeCode.String), var isrr = new InterpolatedStringResolveResult(expressionBuilder.compilation.FindType(KnownTypeCode.String),
format, argumentList.GetArgumentResolveResults().Skip(1).ToArray()); format, argumentList.GetArgumentResolveResults(1).ToArray());
var expr = new InterpolatedStringExpression(); var expr = new InterpolatedStringExpression();
expr.Content.AddRange(content); expr.Content.AddRange(content);
if (method.Name == "Format") if (method.Name == "Format")
@ -363,7 +402,7 @@ namespace ICSharpCode.Decompiler.CSharp
argumentList.CheckNoNamedOrOptionalArguments(); argumentList.CheckNoNamedOrOptionalArguments();
return HandleDelegateEqualityComparison(method, argumentList.Arguments) return HandleDelegateEqualityComparison(method, argumentList.Arguments)
.WithRR(new CSharpInvocationResolveResult(target.ResolveResult, method, .WithRR(new CSharpInvocationResolveResult(target.ResolveResult, method,
argumentList.GetArgumentResolveResults().ToList(), isExpandedForm: argumentList.IsExpandedForm)); argumentList.GetArgumentResolveResults(), isExpandedForm: argumentList.IsExpandedForm));
} }
if (method.IsOperator && method.Name == "op_Implicit" && argumentList.Length == 1) if (method.IsOperator && method.Name == "op_Implicit" && argumentList.Length == 1)
@ -420,7 +459,7 @@ namespace ICSharpCode.Decompiler.CSharp
typeArgumentList.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); typeArgumentList.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType));
return new InvocationExpression(targetExpr, argumentList.GetArgumentExpressions()) return new InvocationExpression(targetExpr, argumentList.GetArgumentExpressions())
.WithRR(new CSharpInvocationResolveResult(target.ResolveResult, foundMethod, .WithRR(new CSharpInvocationResolveResult(target.ResolveResult, foundMethod,
argumentList.GetArgumentResolveResults().ToList(), isExpandedForm: argumentList.IsExpandedForm)); argumentList.GetArgumentResolveResultsDirect(), isExpandedForm: argumentList.IsExpandedForm));
} }
/// <summary> /// <summary>
@ -457,6 +496,7 @@ namespace ICSharpCode.Decompiler.CSharp
firstParamIndex: 0, args, null); firstParamIndex: 0, args, null);
argumentList.ArgumentNames = null; argumentList.ArgumentNames = null;
argumentList.AddNamesToPrimitiveValues = false; argumentList.AddNamesToPrimitiveValues = false;
argumentList.UseImplicitlyTypedOut = false;
var transform = GetRequiredTransformationsForCall(expectedTargetDetails, method, ref unused, var transform = GetRequiredTransformationsForCall(expectedTargetDetails, method, ref unused,
ref argumentList, CallTransformation.None, out _); ref argumentList, CallTransformation.None, out _);
Debug.Assert(transform == CallTransformation.None || transform == CallTransformation.NoOptionalArgumentAllowed); Debug.Assert(transform == CallTransformation.None || transform == CallTransformation.NoOptionalArgumentAllowed);
@ -755,6 +795,7 @@ namespace ICSharpCode.Decompiler.CSharp
list.IsExpandedForm = isExpandedForm; list.IsExpandedForm = isExpandedForm;
list.IsPrimitiveValue = isPrimitiveValue; list.IsPrimitiveValue = isPrimitiveValue;
list.FirstOptionalArgumentIndex = firstOptionalArgumentIndex; list.FirstOptionalArgumentIndex = firstOptionalArgumentIndex;
list.UseImplicitlyTypedOut = true;
list.AddNamesToPrimitiveValues = expressionBuilder.settings.NamedArguments && expressionBuilder.settings.NonTrailingNamedArguments; list.AddNamesToPrimitiveValues = expressionBuilder.settings.NamedArguments && expressionBuilder.settings.NonTrailingNamedArguments;
return list; return list;
} }
@ -787,7 +828,8 @@ namespace ICSharpCode.Decompiler.CSharp
} }
} }
if (IsUnambiguousCall(expectedTargetDetails, method, targetResolveResult, Empty<IType>.Array, if (IsUnambiguousCall(expectedTargetDetails, method, targetResolveResult, Empty<IType>.Array,
expandedArguments, argumentNames: null, firstOptionalArgumentIndex: -1, out _, expandedArguments.SelectArray(a => a.ResolveResult), argumentNames: null,
firstOptionalArgumentIndex: -1, out _,
out var bestCandidateIsExpandedForm) == OverloadResolutionErrors.None && bestCandidateIsExpandedForm) out var bestCandidateIsExpandedForm) == OverloadResolutionErrors.None && bestCandidateIsExpandedForm)
{ {
expectedParameters = expandedParameters; expectedParameters = expandedParameters;
@ -917,7 +959,7 @@ namespace ICSharpCode.Decompiler.CSharp
bool argumentsCasted = false; bool argumentsCasted = false;
OverloadResolutionErrors errors; OverloadResolutionErrors errors;
while ((errors = IsUnambiguousCall(expectedTargetDetails, method, targetResolveResult, typeArguments, while ((errors = IsUnambiguousCall(expectedTargetDetails, method, targetResolveResult, typeArguments,
argumentList.Arguments, argumentList.ArgumentNames, argumentList.FirstOptionalArgumentIndex, out foundMethod, argumentList.GetArgumentResolveResults().ToArray(), argumentList.ArgumentNames, argumentList.FirstOptionalArgumentIndex, out foundMethod,
out var bestCandidateIsExpandedForm)) != OverloadResolutionErrors.None || bestCandidateIsExpandedForm != argumentList.IsExpandedForm) out var bestCandidateIsExpandedForm)) != OverloadResolutionErrors.None || bestCandidateIsExpandedForm != argumentList.IsExpandedForm)
{ {
switch (errors) switch (errors)
@ -958,6 +1000,7 @@ namespace ICSharpCode.Decompiler.CSharp
appliedRequireTypeArgumentsShortcut = false; appliedRequireTypeArgumentsShortcut = false;
} }
argumentsCasted = true; argumentsCasted = true;
argumentList.UseImplicitlyTypedOut = false;
CastArguments(argumentList.Arguments, argumentList.ExpectedParameters); CastArguments(argumentList.Arguments, argumentList.ExpectedParameters);
} }
else if ((allowedTransforms & CallTransformation.RequireTarget) != 0 && !requireTarget) else if ((allowedTransforms & CallTransformation.RequireTarget) != 0 && !requireTarget)
@ -1116,27 +1159,32 @@ namespace ICSharpCode.Decompiler.CSharp
} }
OverloadResolutionErrors IsUnambiguousCall(ExpectedTargetDetails expectedTargetDetails, IMethod method, OverloadResolutionErrors IsUnambiguousCall(ExpectedTargetDetails expectedTargetDetails, IMethod method,
ResolveResult target, IType[] typeArguments, IList<TranslatedExpression> arguments, ResolveResult target, IType[] typeArguments, ResolveResult[] arguments,
string[] argumentNames, int firstOptionalArgumentIndex, string[] argumentNames, int firstOptionalArgumentIndex,
out IParameterizedMember foundMember, out bool bestCandidateIsExpandedForm) out IParameterizedMember foundMember, out bool bestCandidateIsExpandedForm)
{ {
foundMember = null; foundMember = null;
bestCandidateIsExpandedForm = false; bestCandidateIsExpandedForm = false;
var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentModule); var currentTypeDefinition = resolver.CurrentTypeDefinition;
var lookup = new MemberLookup(currentTypeDefinition, currentTypeDefinition.ParentModule);
Log.WriteLine("IsUnambiguousCall: Performing overload resolution for " + method); Log.WriteLine("IsUnambiguousCall: Performing overload resolution for " + method);
Log.WriteCollection(" Arguments: ", arguments.Select(a => a.ResolveResult)); Log.WriteCollection(" Arguments: ", arguments);
argumentNames = firstOptionalArgumentIndex < 0 || argumentNames == null
? argumentNames
: argumentNames.Take(firstOptionalArgumentIndex).ToArray();
var or = new OverloadResolution(resolver.Compilation, var or = new OverloadResolution(resolver.Compilation,
firstOptionalArgumentIndex < 0 ? arguments.SelectArray(a => a.ResolveResult) : arguments.Take(firstOptionalArgumentIndex).Select(a => a.ResolveResult).ToArray(), arguments, argumentNames, typeArguments,
argumentNames: firstOptionalArgumentIndex < 0 || argumentNames == null ? argumentNames : argumentNames.Take(firstOptionalArgumentIndex).ToArray(),
typeArguments: typeArguments,
conversions: expressionBuilder.resolver.conversions); conversions: expressionBuilder.resolver.conversions);
if (expectedTargetDetails.CallOpCode == OpCode.NewObj) if (expectedTargetDetails.CallOpCode == OpCode.NewObj)
{ {
foreach (IMethod ctor in method.DeclaringType.GetConstructors()) foreach (IMethod ctor in method.DeclaringType.GetConstructors())
{ {
if (lookup.IsAccessible(ctor, allowProtectedAccess: resolver.CurrentTypeDefinition == method.DeclaringTypeDefinition)) bool allowProtectedAccess =
resolver.CurrentTypeDefinition == method.DeclaringTypeDefinition;
if (lookup.IsAccessible(ctor, allowProtectedAccess))
{ {
or.AddCandidate(ctor); or.AddCandidate(ctor);
} }
@ -1145,12 +1193,12 @@ namespace ICSharpCode.Decompiler.CSharp
else if (method.IsOperator) else if (method.IsOperator)
{ {
IEnumerable<IParameterizedMember> operatorCandidates; IEnumerable<IParameterizedMember> operatorCandidates;
if (arguments.Count == 1) if (arguments.Length == 1)
{ {
IType argType = NullableType.GetUnderlyingType(arguments[0].Type); IType argType = NullableType.GetUnderlyingType(arguments[0].Type);
operatorCandidates = resolver.GetUserDefinedOperatorCandidates(argType, method.Name); operatorCandidates = resolver.GetUserDefinedOperatorCandidates(argType, method.Name);
} }
else if (arguments.Count == 2) else if (arguments.Length == 2)
{ {
IType lhsType = NullableType.GetUnderlyingType(arguments[0].Type); IType lhsType = NullableType.GetUnderlyingType(arguments[0].Type);
IType rhsType = NullableType.GetUnderlyingType(arguments[1].Type); IType rhsType = NullableType.GetUnderlyingType(arguments[1].Type);
@ -1170,7 +1218,8 @@ namespace ICSharpCode.Decompiler.CSharp
} }
else if (target == null) else if (target == null)
{ {
var result = resolver.ResolveSimpleName(method.Name, typeArguments, isInvocationTarget: true) as MethodGroupResolveResult; var result = resolver.ResolveSimpleName(method.Name, typeArguments, isInvocationTarget: true)
as MethodGroupResolveResult;
if (result == null) if (result == null)
return OverloadResolutionErrors.AmbiguousMatch; return OverloadResolutionErrors.AmbiguousMatch;
or.AddMethodLists(result.MethodsGroupedByDeclaringType.ToArray()); or.AddMethodLists(result.MethodsGroupedByDeclaringType.ToArray());
@ -1386,13 +1435,14 @@ namespace ICSharpCode.Decompiler.CSharp
} }
} }
return atce.WithRR(new CSharpInvocationResolveResult( return atce.WithRR(new CSharpInvocationResolveResult(
target, method, argumentList.GetArgumentResolveResults().ToList(), target, method, argumentList.GetArgumentResolveResults(),
isExpandedForm: argumentList.IsExpandedForm, argumentToParameterMap: argumentList.ArgumentToParameterMap isExpandedForm: argumentList.IsExpandedForm, argumentToParameterMap: argumentList.ArgumentToParameterMap
)); ));
} }
else else
{ {
while (IsUnambiguousCall(expectedTargetDetails, method, null, Empty<IType>.Array, argumentList.Arguments, while (IsUnambiguousCall(expectedTargetDetails, method, null, Empty<IType>.Array,
argumentList.GetArgumentResolveResults().ToArray(),
argumentList.ArgumentNames, argumentList.FirstOptionalArgumentIndex, out _, argumentList.ArgumentNames, argumentList.FirstOptionalArgumentIndex, out _,
out var bestCandidateIsExpandedForm) != OverloadResolutionErrors.None || bestCandidateIsExpandedForm != argumentList.IsExpandedForm) out var bestCandidateIsExpandedForm) != OverloadResolutionErrors.None || bestCandidateIsExpandedForm != argumentList.IsExpandedForm)
{ {

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

@ -580,17 +580,36 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} }
else if (CanBeDeclaredAsOutVariable(v, out var dirExpr)) else if (CanBeDeclaredAsOutVariable(v, out var dirExpr))
{ {
// 'T v; SomeCall(out v);' can be combined to 'SomeCall(out var v);' // 'T v; SomeCall(out v);' can be combined to 'SomeCall(out T v);'
AstType type; AstType type;
if (context.Settings.AnonymousTypes && v.Type.ContainsAnonymousType()) if (context.Settings.AnonymousTypes && v.Type.ContainsAnonymousType())
{ {
type = new SimpleType("var"); type = new SimpleType("var");
} }
else if (dirExpr.Annotation<UseImplicitlyTypedOutAnnotation>() != null)
{
type = new SimpleType("var");
}
else else
{ {
type = context.TypeSystemAstBuilder.ConvertType(v.Type); type = context.TypeSystemAstBuilder.ConvertType(v.Type);
} }
var ovd = new OutVarDeclarationExpression(type, v.Name); string name;
// Variable is not used and discards are allowed, we can simplify this to 'out T _'.
// TODO: if no variable named _ is declared and var is used instead of T, use out _.
// Note: ExpressionBuilder.HidesVariableWithName produces inaccurate results, because it
// does not take lambdas and local functions into account, that are defined in the same
// scope as v.
if (context.Settings.Discards && v.ILVariable.LoadCount == 0
&& v.ILVariable.StoreCount == 0 && v.ILVariable.AddressCount == 1)
{
name = "_";
}
else
{
name = v.Name;
}
var ovd = new OutVarDeclarationExpression(type, name);
ovd.Variable.AddAnnotation(new ILVariableResolveResult(ilVariable)); ovd.Variable.AddAnnotation(new ILVariableResolveResult(ilVariable));
ovd.CopyAnnotationsFrom(dirExpr); ovd.CopyAnnotationsFrom(dirExpr);
replacements.Add((dirExpr, ovd)); replacements.Add((dirExpr, ovd));

2
ICSharpCode.Decompiler/Semantics/OutVarResolveResult.cs

@ -26,6 +26,8 @@ namespace ICSharpCode.Decompiler.Semantics
/// </summary> /// </summary>
class OutVarResolveResult : ResolveResult class OutVarResolveResult : ResolveResult
{ {
public static readonly OutVarResolveResult Instance = new OutVarResolveResult();
public OutVarResolveResult() : base(SpecialType.NoType) { } public OutVarResolveResult() : base(SpecialType.NoType) { }
} }
} }

Loading…
Cancel
Save