Browse Source

Merge branch 'master' of https://github.com/icsharpcode/ILSpy into local-functions

pull/1586/head
Siegfried Pammer 7 years ago
parent
commit
8af609e7df
  1. 1
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  2. 6
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  3. 9
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/TrickyTypes.cs
  4. 16
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs
  5. 11
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs
  6. 134
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UserDefinedConversions.cs
  7. 14
      ICSharpCode.Decompiler/CSharp/Annotations.cs
  8. 11
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  9. 2
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs
  10. 13
      ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs
  11. 23
      ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs
  12. 11
      ICSharpCode.Decompiler/IL/ILReader.cs
  13. 149
      ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs
  14. 22
      ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs
  15. 1
      ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs
  16. 9
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
  17. 2
      ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs
  18. 12
      ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs
  19. 8
      ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs
  20. 2
      ILSpy-tests
  21. 1
      ILSpy.AddIn/ILSpy.AddIn.csproj
  22. 4
      ILSpy/Options/DecompilerSettingsPanel.xaml.cs

1
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -89,6 +89,7 @@ @@ -89,6 +89,7 @@
<Compile Include="TestCases\ILPretty\Issue1323.cs" />
<Compile Include="TestCases\Pretty\CustomAttributes2.cs" />
<Compile Include="TestCases\Pretty\EnumTests.cs" />
<Compile Include="TestCases\Pretty\UserDefinedConversions.cs" />
<None Include="TestCases\ILPretty\Unsafe.il" />
<None Include="TestCases\Pretty\NullableRefTypes.cs" />
<Compile Include="TestCases\Pretty\TypeMemberTests.cs" />

6
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -425,6 +425,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -425,6 +425,12 @@ namespace ICSharpCode.Decompiler.Tests
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void UserDefinedConversions([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void Discards([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
{

9
ICSharpCode.Decompiler.Tests/TestCases/Correctness/TrickyTypes.cs

@ -26,6 +26,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -26,6 +26,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{
InterestingConstants();
TruncatedComp();
StringConcat();
}
static void Print<T>(T val)
@ -92,5 +93,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -92,5 +93,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Print(val1 <= val2);
Print((int)val1 <= val2);
}
static void StringConcat()
{
// Some string.Concat()-cases that cannot be replaced using operator+
Print(string.Concat("String concat:"));
Print(string.Concat(1, 2));
Print(string.Concat(1, 2, "str"));
}
}
}

16
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs

@ -159,6 +159,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -159,6 +159,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
}
public static Predicate<T> And<T>(this Predicate<T> filter1, Predicate<T> filter2)
{
if (filter1 == null) {
return filter2;
}
if (filter2 == null) {
return filter1;
}
return (T m) => filter1(m) && filter2(m);
}
public static Action<string> ExtensionMethodUnbound()
{
return Test;
@ -174,6 +185,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -174,6 +185,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return ((string)null).Test;
}
public static Predicate<int> NoExtensionMethodOnLambda()
{
return And((int x) => x >= 0, (int x) => x <= 100);
}
public static object StaticMethod()
{
return new Func<Action>(ExtensionMethodBound);

11
ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs

@ -32,11 +32,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -32,11 +32,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
get;
set;
}
public static int StaticProperty {
get;
set;
}
public bool BoolProperty {
get;
set;
}
public void SimpleInlineWithLocals()
{
int index;
@ -136,5 +142,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -136,5 +142,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
return InstanceProperty = GetIndex();
}
public bool BoolPropertyTest(object x)
{
return BoolProperty = (x != null);
}
}
}

134
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UserDefinedConversions.cs

@ -0,0 +1,134 @@ @@ -0,0 +1,134 @@
// Copyright (c) 2019 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
internal class T01Issue1574
{
private struct A
{
private bool val;
public static implicit operator bool(A a)
{
return a.val;
}
}
private struct C
{
private int val;
public static implicit operator C(bool b)
{
return default(C);
}
}
private C ChainedConversion()
{
return (bool)default(A);
}
public void Call_Overloaded()
{
Overloaded((bool)default(A));
}
private void Overloaded(A a)
{
}
private void Overloaded(bool a)
{
}
}
internal class T02BothDirectAndChainedConversionPossible
{
private struct A
{
private bool val;
public static implicit operator bool(A a)
{
return a.val;
}
}
private struct C
{
private int val;
public static implicit operator C(bool b)
{
return default(C);
}
public static implicit operator C(A a)
{
return default(C);
}
public static bool operator ==(C a, C b)
{
return true;
}
public static bool operator !=(C a, C b)
{
return false;
}
}
private C DirectConvert(A a)
{
return a;
}
private C IndirectConvert(A a)
{
return (bool)a;
}
private C? LiftedDirectConvert(A? a)
{
return a;
}
private C? LiftedIndirectConvert(A? a)
{
return (bool?)a;
}
private bool Compare(A a, C c)
{
return a == c;
}
private void LiftedCompare(A? a, C? c)
{
UseBool(a == c);
UseBool(a == default(C));
UseBool(c == default(A));
}
private void UseBool(bool b)
{
}
}
}

14
ICSharpCode.Decompiler/CSharp/Annotations.cs

@ -240,4 +240,18 @@ namespace ICSharpCode.Decompiler.CSharp @@ -240,4 +240,18 @@ namespace ICSharpCode.Decompiler.CSharp
this.Leave = leave;
}
}
/// <summary>
/// Annotates an expression when an implicit user-defined conversion was omitted.
/// </summary>
public class ImplicitConversionAnnotation
{
public readonly ConversionResolveResult ConversionResolveResult;
public IType TargetType => ConversionResolveResult.Type;
public ImplicitConversionAnnotation(ConversionResolveResult conversionResolveResult)
{
this.ConversionResolveResult = conversionResolveResult;
}
}
}

11
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -360,7 +360,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -360,7 +360,7 @@ namespace ICSharpCode.Decompiler.CSharp
// settings.AlwaysCastTargetsOfExplicitInterfaceImplementationCalls == true is used in Windows Forms' InitializeComponent methods.
if (method.IsExplicitInterfaceImplementation && (target.Expression is ThisReferenceExpression || settings.AlwaysCastTargetsOfExplicitInterfaceImplementationCalls)) {
var interfaceMember = method.ExplicitlyImplementedInterfaceMembers.First();
var castExpression = new CastExpression(expressionBuilder.ConvertType(interfaceMember.DeclaringType), target.Expression);
var castExpression = new CastExpression(expressionBuilder.ConvertType(interfaceMember.DeclaringType), target.Expression.Detach());
methodName = interfaceMember.Name;
targetExpr = new MemberReferenceExpression(castExpression, methodName);
typeArgumentList = ((MemberReferenceExpression)targetExpr).TypeArguments;
@ -1008,11 +1008,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1008,11 +1008,14 @@ namespace ICSharpCode.Decompiler.CSharp
} else if (method.IsOperator) {
IEnumerable<IParameterizedMember> operatorCandidates;
if (arguments.Count == 1) {
operatorCandidates = resolver.GetUserDefinedOperatorCandidates(arguments[0].Type, method.Name);
IType argType = NullableType.GetUnderlyingType(arguments[0].Type);
operatorCandidates = resolver.GetUserDefinedOperatorCandidates(argType, method.Name);
} else if (arguments.Count == 2) {
IType lhsType = NullableType.GetUnderlyingType(arguments[0].Type);
IType rhsType = NullableType.GetUnderlyingType(arguments[1].Type);
var hashSet = new HashSet<IParameterizedMember>();
hashSet.UnionWith(resolver.GetUserDefinedOperatorCandidates(arguments[0].Type, method.Name));
hashSet.UnionWith(resolver.GetUserDefinedOperatorCandidates(arguments[1].Type, method.Name));
hashSet.UnionWith(resolver.GetUserDefinedOperatorCandidates(lhsType, method.Name));
hashSet.UnionWith(resolver.GetUserDefinedOperatorCandidates(rhsType, method.Name));
operatorCandidates = hashSet;
} else {
operatorCandidates = EmptyList<IParameterizedMember>.Instance;

2
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs

@ -162,6 +162,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -162,6 +162,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
public static bool CanTransformToExtensionMethodCall(CSharpResolver resolver, IMethod method,
IReadOnlyList<IType> typeArguments, ResolveResult target, ResolveResult[] arguments, string[] argumentNames)
{
if (target is LambdaResolveResult)
return false;
var rr = resolver.ResolveMemberAccess(target, method.Name, typeArguments, NameLookupMode.InvocationTarget) as MethodGroupResolveResult;
if (rr == null)
return false;

13
ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs

@ -154,16 +154,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -154,16 +154,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (arguments.Length < 2)
return false;
bool valid = false;
foreach (var argument in arguments) {
if (argument is NamedArgumentExpression)
return false;
if (argument.GetResolveResult().Type.IsKnownType(KnownTypeCode.String))
valid = true;
}
return valid;
return !arguments.Any(arg => arg is NamedArgumentExpression) &&
(arguments[0].GetResolveResult().Type.IsKnownType(KnownTypeCode.String) ||
arguments[1].GetResolveResult().Type.IsKnownType(KnownTypeCode.String));
}
static BinaryOperatorType? GetBinaryOperatorTypeFromMetadataName(string name)

23
ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

@ -191,7 +191,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -191,7 +191,11 @@ namespace ICSharpCode.Decompiler.CSharp
conversion.Input.Type,
type, targetType
)) {
return this.UnwrapChild(cast.Expression);
var result = this.UnwrapChild(cast.Expression);
if (conversion.Conversion.IsUserDefined) {
result.Expression.AddAnnotation(new ImplicitConversionAnnotation(conversion));
}
return result;
} else if (Expression is ObjectCreateExpression oce && conversion.Conversion.IsMethodGroupConversion
&& oce.Arguments.Count == 1 && expressionBuilder.settings.UseImplicitMethodGroupConversion) {
return this.UnwrapChild(oce.Arguments.Single());
@ -211,6 +215,18 @@ namespace ICSharpCode.Decompiler.CSharp @@ -211,6 +215,18 @@ namespace ICSharpCode.Decompiler.CSharp
if (targetType.Kind == TypeKind.Unknown || targetType.Kind == TypeKind.Void || targetType.Kind == TypeKind.None) {
return this; // don't attempt to insert cast to '?' or 'void' as these are not valid.
}
var convAnnotation = this.Expression.Annotation<ImplicitConversionAnnotation>();
if (convAnnotation != null) {
// If an implicit user-defined conversion was stripped from this expression;
// it needs to be re-introduced before we can apply other casts to this expression.
// This happens when the CallBuilder discovers that the conversion is necessary in
// order to choose the correct overload.
this.Expression.RemoveAnnotations<ImplicitConversionAnnotation>();
return new CastExpression(expressionBuilder.ConvertType(convAnnotation.TargetType), Expression)
.WithoutILInstruction()
.WithRR(convAnnotation.ConversionResolveResult)
.ConvertTo(targetType, expressionBuilder, checkForOverflow, allowImplicitConversion);
}
if (Expression is TupleExpression tupleExpr && targetType is TupleType targetTupleType
&& tupleExpr.Elements.Count == targetTupleType.ElementTypes.Length)
{
@ -231,8 +247,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -231,8 +247,9 @@ namespace ICSharpCode.Decompiler.CSharp
}
var compilation = expressionBuilder.compilation;
var conversions = Resolver.CSharpConversions.Get(compilation);
if (ResolveResult is ConversionResolveResult conv && Expression is CastExpression cast2 &&
CastCanBeMadeImplicit(conversions, conv.Conversion, conv.Input.Type, type, targetType))
if (ResolveResult is ConversionResolveResult conv && Expression is CastExpression cast2
&& !conv.Conversion.IsUserDefined
&& CastCanBeMadeImplicit(conversions, conv.Conversion, conv.Input.Type, type, targetType))
{
var unwrapped = this.UnwrapChild(cast2.Expression);
if (allowImplicitConversion)

11
ICSharpCode.Decompiler/IL/ILReader.cs

@ -1401,12 +1401,17 @@ namespace ICSharpCode.Decompiler.IL @@ -1401,12 +1401,17 @@ namespace ICSharpCode.Decompiler.IL
var signatureHandle = (StandaloneSignatureHandle)ReadAndDecodeMetadataToken();
var signature = module.DecodeMethodSignature(signatureHandle, genericContext);
var functionPointer = Pop(StackType.I);
Debug.Assert(!signature.Header.IsInstance);
var arguments = new ILInstruction[signature.ParameterTypes.Length];
int firstArgument = signature.Header.IsInstance ? 1 : 0;
var arguments = new ILInstruction[firstArgument + signature.ParameterTypes.Length];
for (int i = signature.ParameterTypes.Length - 1; i >= 0; i--) {
arguments[i] = Pop(signature.ParameterTypes[i].GetStackType());
arguments[firstArgument + i] = Pop(signature.ParameterTypes[i].GetStackType());
}
if (firstArgument == 1) {
arguments[0] = Pop();
}
var call = new CallIndirect(
signature.Header.IsInstance,
signature.Header.HasExplicitThis,
signature.Header.CallingConvention,
signature.ReturnType,
signature.ParameterTypes,

149
ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs

@ -133,14 +133,7 @@ namespace ICSharpCode.Decompiler.IL @@ -133,14 +133,7 @@ namespace ICSharpCode.Decompiler.IL
case HandleKind.MethodDefinition: {
var md = metadata.GetMethodDefinition((MethodDefinitionHandle)entity);
methodSignature = md.DecodeSignature(new DisassemblerSignatureProvider(module, output), new Metadata.GenericContext((MethodDefinitionHandle)entity, module));
if (methodSignature.Header.HasExplicitThis) {
output.Write("instance explicit ");
} else if (methodSignature.Header.IsInstance) {
output.Write("instance ");
}
if (methodSignature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
output.Write("vararg ");
}
WriteSignatureHeader(output, methodSignature);
methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
var declaringType = md.GetDeclaringType();
@ -189,13 +182,7 @@ namespace ICSharpCode.Decompiler.IL @@ -189,13 +182,7 @@ namespace ICSharpCode.Decompiler.IL
}
output.Write('>');
}
output.Write("(");
for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) {
if (i > 0)
output.Write(", ");
methodSignature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters);
}
output.Write(")");
WriteParameterList(output, methodSignature);
break;
}
case HandleKind.MemberReference:
@ -204,28 +191,13 @@ namespace ICSharpCode.Decompiler.IL @@ -204,28 +191,13 @@ namespace ICSharpCode.Decompiler.IL
switch (mr.GetKind()) {
case MemberReferenceKind.Method:
methodSignature = mr.DecodeMethodSignature(new DisassemblerSignatureProvider(module, output), genericContext);
if (methodSignature.Header.HasExplicitThis) {
output.Write("instance explicit ");
} else if (methodSignature.Header.IsInstance) {
output.Write("instance ");
}
if (methodSignature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
output.Write("vararg ");
}
WriteSignatureHeader(output, methodSignature);
methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
WriteParent(output, module, metadata, mr.Parent, genericContext, syntax);
output.Write("::");
output.WriteReference(module, entity, DisassemblerHelpers.Escape(memberName));
output.Write("(");
for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) {
if (i > 0)
output.Write(", ");
if (i == methodSignature.RequiredParameterCount)
output.Write("..., ");
methodSignature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters);
}
output.Write(")");
WriteParameterList(output, methodSignature);
break;
case MemberReferenceKind.Field:
var fieldSignature = mr.DecodeFieldSignature(new DisassemblerSignatureProvider(module, output), genericContext);
@ -245,14 +217,7 @@ namespace ICSharpCode.Decompiler.IL @@ -245,14 +217,7 @@ namespace ICSharpCode.Decompiler.IL
var methodDefinition = metadata.GetMethodDefinition((MethodDefinitionHandle)ms.Method);
var methodName = metadata.GetString(methodDefinition.Name);
methodSignature = methodDefinition.DecodeSignature(new DisassemblerSignatureProvider(module, output), genericContext);
if (methodSignature.Header.HasExplicitThis) {
output.Write("instance explicit ");
} else if (methodSignature.Header.IsInstance) {
output.Write("instance ");
}
if (methodSignature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
output.Write("vararg ");
}
WriteSignatureHeader(output, methodSignature);
methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
var declaringType = methodDefinition.GetDeclaringType();
@ -266,52 +231,21 @@ namespace ICSharpCode.Decompiler.IL @@ -266,52 +231,21 @@ namespace ICSharpCode.Decompiler.IL
} else {
output.Write(DisassemblerHelpers.Escape(methodName));
}
output.Write('<');
for (int i = 0; i < substitution.Length; i++) {
if (i > 0)
output.Write(", ");
substitution[i](syntax);
}
output.Write('>');
output.Write("(");
for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) {
if (i > 0)
output.Write(", ");
methodSignature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters);
}
output.Write(")");
WriteTypeParameterList(output, syntax, substitution);
WriteParameterList(output, methodSignature);
break;
case HandleKind.MemberReference:
var memberReference = metadata.GetMemberReference((MemberReferenceHandle)ms.Method);
memberName = metadata.GetString(memberReference.Name);
methodSignature = memberReference.DecodeMethodSignature(new DisassemblerSignatureProvider(module, output), genericContext);
if (methodSignature.Header.HasExplicitThis) {
output.Write("instance explicit ");
} else if (methodSignature.Header.IsInstance) {
output.Write("instance ");
}
if (methodSignature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
output.Write("vararg ");
}
WriteSignatureHeader(output, methodSignature);
methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
WriteParent(output, module, metadata, memberReference.Parent, genericContext, syntax);
output.Write("::");
output.Write(DisassemblerHelpers.Escape(memberName));
output.Write('<');
for (int i = 0; i < substitution.Length; i++) {
if (i > 0)
output.Write(", ");
substitution[i](syntax);
}
output.Write('>');
output.Write("(");
for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) {
if (i > 0)
output.Write(", ");
methodSignature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters);
}
output.Write(")");
WriteTypeParameterList(output, syntax, substitution);
WriteParameterList(output, methodSignature);
break;
}
break;
@ -319,15 +253,10 @@ namespace ICSharpCode.Decompiler.IL @@ -319,15 +253,10 @@ namespace ICSharpCode.Decompiler.IL
var standaloneSig = metadata.GetStandaloneSignature((StandaloneSignatureHandle)entity);
switch (standaloneSig.GetKind()) {
case StandaloneSignatureKind.Method:
var methodSig = standaloneSig.DecodeMethodSignature(new DisassemblerSignatureProvider(module, output), genericContext);
methodSig.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write('(');
for (int i = 0; i < methodSig.ParameterTypes.Length; i++) {
if (i > 0)
output.Write(", ");
methodSig.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters);
}
output.Write(')');
methodSignature = standaloneSig.DecodeMethodSignature(new DisassemblerSignatureProvider(module, output), genericContext);
WriteSignatureHeader(output, methodSignature);
methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
WriteParameterList(output, methodSignature);
break;
case StandaloneSignatureKind.LocalVariables:
default:
@ -341,6 +270,56 @@ namespace ICSharpCode.Decompiler.IL @@ -341,6 +270,56 @@ namespace ICSharpCode.Decompiler.IL
}
}
static void WriteTypeParameterList(ITextOutput output, ILNameSyntax syntax, System.Collections.Immutable.ImmutableArray<Action<ILNameSyntax>> substitution)
{
output.Write('<');
for (int i = 0; i < substitution.Length; i++) {
if (i > 0)
output.Write(", ");
substitution[i](syntax);
}
output.Write('>');
}
static void WriteParameterList(ITextOutput output, MethodSignature<Action<ILNameSyntax>> methodSignature)
{
output.Write("(");
for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) {
if (i > 0)
output.Write(", ");
if (i == methodSignature.RequiredParameterCount)
output.Write("..., ");
methodSignature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters);
}
output.Write(")");
}
static void WriteSignatureHeader(ITextOutput output, MethodSignature<Action<ILNameSyntax>> methodSignature)
{
if (methodSignature.Header.HasExplicitThis) {
output.Write("instance explicit ");
} else if (methodSignature.Header.IsInstance) {
output.Write("instance ");
}
switch (methodSignature.Header.CallingConvention) {
case SignatureCallingConvention.CDecl:
output.Write("unmanaged cdecl ");
break;
case SignatureCallingConvention.StdCall:
output.Write("unmanaged stdcall ");
break;
case SignatureCallingConvention.ThisCall:
output.Write("unmanaged thiscall ");
break;
case SignatureCallingConvention.FastCall:
output.Write("unmanaged fastcall ");
break;
case SignatureCallingConvention.VarArgs:
output.Write("vararg ");
break;
}
}
static void WriteParent(ITextOutput output, PEFile module, MetadataReader metadata, EntityHandle parentHandle, Metadata.GenericContext genericContext, ILNameSyntax syntax)
{
switch (parentHandle.Kind) {

22
ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs

@ -32,7 +32,8 @@ namespace ICSharpCode.Decompiler.IL @@ -32,7 +32,8 @@ namespace ICSharpCode.Decompiler.IL
public readonly InstructionCollection<ILInstruction> Arguments;
ILInstruction functionPointer;
public bool IsInstance { get; }
public bool HasExplicitThis { get; }
public System.Reflection.Metadata.SignatureCallingConvention CallingConvention { get; }
public IType ReturnType { get; }
public ImmutableArray<IType> ParameterTypes { get; }
@ -61,9 +62,11 @@ namespace ICSharpCode.Decompiler.IL @@ -61,9 +62,11 @@ namespace ICSharpCode.Decompiler.IL
functionPointer.ChildIndex = Arguments.Count;
}
public CallIndirect(System.Reflection.Metadata.SignatureCallingConvention callingConvention, IType returnType, ImmutableArray<IType> parameterTypes,
public CallIndirect(bool isInstance, bool hasExplicitThis, System.Reflection.Metadata.SignatureCallingConvention callingConvention, IType returnType, ImmutableArray<IType> parameterTypes,
IEnumerable<ILInstruction> arguments, ILInstruction functionPointer) : base(OpCode.CallIndirect)
{
this.IsInstance = isInstance;
this.HasExplicitThis = hasExplicitThis;
this.CallingConvention = callingConvention;
this.ReturnType = returnType ?? throw new ArgumentNullException("returnType");
this.ParameterTypes = parameterTypes.ToImmutableArray();
@ -74,7 +77,7 @@ namespace ICSharpCode.Decompiler.IL @@ -74,7 +77,7 @@ namespace ICSharpCode.Decompiler.IL
public override ILInstruction Clone()
{
return new CallIndirect(CallingConvention, ReturnType, ParameterTypes,
return new CallIndirect(IsInstance, HasExplicitThis, CallingConvention, ReturnType, ParameterTypes,
this.Arguments.Select(inst => inst.Clone()), functionPointer.Clone()
).WithILRange(this);
}
@ -84,7 +87,7 @@ namespace ICSharpCode.Decompiler.IL @@ -84,7 +87,7 @@ namespace ICSharpCode.Decompiler.IL
internal override void CheckInvariant(ILPhase phase)
{
base.CheckInvariant(phase);
Debug.Assert(Arguments.Count == ParameterTypes.Length);
Debug.Assert(Arguments.Count == ParameterTypes.Length + (IsInstance ? 1 : 0));
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
@ -94,7 +97,12 @@ namespace ICSharpCode.Decompiler.IL @@ -94,7 +97,12 @@ namespace ICSharpCode.Decompiler.IL
ReturnType.WriteTo(output);
output.Write('(');
bool first = true;
foreach (var (inst, type) in Arguments.Zip(ParameterTypes, (a,b) => (a,b))) {
int firstArgument = IsInstance ? 1 : 0;
if (firstArgument == 1) {
Arguments[0].WriteTo(output, options);
first = false;
}
foreach (var (inst, type) in Arguments.Skip(firstArgument).Zip(ParameterTypes, (a,b) => (a,b))) {
if (first)
first = false;
else
@ -155,6 +163,10 @@ namespace ICSharpCode.Decompiler.IL @@ -155,6 +163,10 @@ namespace ICSharpCode.Decompiler.IL
bool EqualSignature(CallIndirect other)
{
if (IsInstance != other.IsInstance)
return false;
if (HasExplicitThis != other.HasExplicitThis)
return false;
if (CallingConvention != other.CallingConvention)
return false;
if (ParameterTypes.Length != other.ParameterTypes.Length)

1
ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs

@ -97,6 +97,7 @@ namespace ICSharpCode.Decompiler.IL @@ -97,6 +97,7 @@ namespace ICSharpCode.Decompiler.IL
this.AddILRange(binary);
Debug.Assert(compoundAssignmentType == CompoundAssignmentType.EvaluatesToNewValue || (Operator == BinaryNumericOperator.Add || Operator == BinaryNumericOperator.Sub));
Debug.Assert(IsValidCompoundAssignmentTarget(Target));
Debug.Assert(this.ResultType == (IsLifted ? StackType.O : UnderlyingResultType));
}
/// <summary>

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

@ -64,8 +64,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -64,8 +64,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
protected internal override void VisitBlock(Block block)
{
// Don't visit child blocks; since this is a block transform
// we know those were already handled previously.
if (block.Kind == BlockKind.ControlFlow) {
// Don't visit child control flow blocks;
// since this is a block transform
// we know those were already handled previously.
return;
}
base.VisitBlock(block);
}
protected internal override void VisitComp(Comp inst)

2
ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs

@ -216,6 +216,8 @@ namespace ICSharpCode.Decompiler.IL @@ -216,6 +216,8 @@ namespace ICSharpCode.Decompiler.IL
var defaultSection = switchInst.Sections.MaxBy(s => s.Labels.Count());
if (!defaultSection.Body.MatchBranch(out var defaultBlock) || defaultBlock.IncomingEdgeCount != 1)
return false;
if (defaultBlock.Parent != switchContainer)
return false;
// tally stats for heuristic from each case block
int maxStatements = 0, maxDepth = 0;

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

@ -478,9 +478,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -478,9 +478,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// Try to determine the real type of the object we're modifying:
storeType = stobj.Target.InferType(compilation);
if (storeType is ByReferenceType refType) {
storeType = refType.ElementType;
if (TypeUtils.IsCompatibleTypeForMemoryAccess(refType.ElementType, stobj.Type)) {
storeType = refType.ElementType;
} else {
storeType = stobj.Type;
}
} else if (storeType is PointerType pointerType) {
storeType = pointerType.ElementType;
if (TypeUtils.IsCompatibleTypeForMemoryAccess(pointerType.ElementType, stobj.Type)) {
storeType = pointerType.ElementType;
} else {
storeType = stobj.Type;
}
} else {
storeType = stobj.Type;
}

8
ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs

@ -141,8 +141,12 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -141,8 +141,12 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (name == null) {
return null;
}
return ReflectionHelper.ParseReflectionName(name)
.Resolve(module != null ? new SimpleTypeResolveContext(module) : new SimpleTypeResolveContext(compilation));
try {
return ReflectionHelper.ParseReflectionName(name)
.Resolve(module != null ? new SimpleTypeResolveContext(module) : new SimpleTypeResolveContext(compilation));
} catch (ReflectionNameParseException ex) {
throw new BadImageFormatException($"Invalid type name: \"{name}\": {ex.Message}");
}
}
public IType GetTypeFromSpecification(SRM.MetadataReader reader, GenericContext genericContext, SRM.TypeSpecificationHandle handle, byte rawTypeKind)

2
ILSpy-tests

@ -1 +1 @@ @@ -1 +1 @@
Subproject commit 28f74a2a8f4050fe455a982dbd361a981841a9bd
Subproject commit 4d29b27bd7262790efe52edfcb9c100bb62a0382

1
ILSpy.AddIn/ILSpy.AddIn.csproj

@ -51,6 +51,7 @@ @@ -51,6 +51,7 @@
<PackageReference Include="Microsoft.VisualStudio.ComponentModelHost" Version="15.6.27413" />
<PackageReference Include="Microsoft.VisualStudio.Editor" Version="15.6.27740" />
<PackageReference Include="Microsoft.VisualStudio.LanguageServices" Version="2.4.0" />
<PackageReference Include="Microsoft.VisualStudio.SDK.Analyzers" Version="16.0.29" />
<PackageReference Include="Microsoft.VisualStudio.Shell.15.0" Version="15.6.27413" />
<PackageReference Include="Microsoft.VisualStudio.Shell.Interop.14.0.DesignTime" Version="14.3.26929" />
<PackageReference Include="Microsoft.VisualStudio.Text.UI" Version="15.6.27740" />

4
ILSpy/Options/DecompilerSettingsPanel.xaml.cs

@ -54,7 +54,9 @@ namespace ICSharpCode.ILSpy.Options @@ -54,7 +54,9 @@ namespace ICSharpCode.ILSpy.Options
var properties = typeof(Decompiler.DecompilerSettings).GetProperties()
.Where(p => p.GetCustomAttribute<BrowsableAttribute>()?.Browsable != false);
foreach (var p in properties) {
p.SetValue(newSettings, (bool?)e.Attribute(p.Name) ?? true);
var value = (bool?)e.Attribute(p.Name);
if (value.HasValue)
p.SetValue(newSettings, value.Value);
}
return newSettings;
}

Loading…
Cancel
Save