From 0e9a16334566534326105057a46baf50b0f2a1bf Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 23 Mar 2018 22:40:18 +0100 Subject: [PATCH] Improve on #1085 by setting UnknownType.IsReferenceType in more cases. --- ICSharpCode.Decompiler/IL/ILReader.cs | 12 +++--- .../TypeSystem/DecompilerTypeSystem.cs | 39 ++++++++++++------- .../TypeSystem/IDecompilerTypeSystem.cs | 2 +- .../SpecializingDecompilerTypeSystem.cs | 4 +- 4 files changed, 33 insertions(+), 24 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs index 16c997fa3..b191b142b 100644 --- a/ICSharpCode.Decompiler/IL/ILReader.cs +++ b/ICSharpCode.Decompiler/IL/ILReader.cs @@ -78,7 +78,7 @@ namespace ICSharpCode.Decompiler.IL this.currentStack = ImmutableStack.Empty; this.unionFind = new UnionFind(); this.stackMismatchPairs = new List<(ILVariable, ILVariable)>(); - this.methodReturnStackType = typeSystem.Resolve(body.Method.ReturnType).GetStackType(); + this.methodReturnStackType = typeSystem.Resolve(body.Method.ReturnType, isFromSignature: true).GetStackType(); InitParameterVariables(); this.localVariables = body.Variables.SelectArray(CreateILVariable); if (body.InitLocals) { @@ -130,7 +130,7 @@ namespace ICSharpCode.Decompiler.IL ILVariable CreateILVariable(Cil.VariableDefinition v) { VariableKind kind = IsPinned(v.VariableType) ? VariableKind.PinnedLocal : VariableKind.Local; - ILVariable ilVar = new ILVariable(kind, typeSystem.Resolve(v.VariableType), v.Index); + ILVariable ilVar = new ILVariable(kind, typeSystem.Resolve(v.VariableType, isFromSignature: true), v.Index); if (!UseDebugSymbols || debugInfo == null || !debugInfo.TryGetName(v, out string name)) { ilVar.Name = "V_" + v.Index; ilVar.HasGeneratedName = true; @@ -164,10 +164,10 @@ namespace ICSharpCode.Decompiler.IL parameterType = new ByReferenceType(parameterType); } } else { - parameterType = typeSystem.Resolve(p.ParameterType); + parameterType = typeSystem.Resolve(p.ParameterType, isFromSignature: true); } } else { - parameterType = typeSystem.Resolve(p.ParameterType); + parameterType = typeSystem.Resolve(p.ParameterType, isFromSignature: true); } Debug.Assert(!parameterType.IsUnbound()); if (parameterType.IsUnbound()) { @@ -1283,12 +1283,12 @@ namespace ICSharpCode.Decompiler.IL var parameterTypes = new IType[signature.Parameters.Count]; var arguments = new ILInstruction[parameterTypes.Length]; for (int i = signature.Parameters.Count - 1; i >= 0; i--) { - parameterTypes[i] = typeSystem.Resolve(signature.Parameters[i].ParameterType); + parameterTypes[i] = typeSystem.Resolve(signature.Parameters[i].ParameterType, isFromSignature: true); arguments[i] = Pop(parameterTypes[i].GetStackType()); } var call = new CallIndirect( signature.CallingConvention, - typeSystem.Resolve(signature.ReturnType), + typeSystem.Resolve(signature.ReturnType, isFromSignature: true), parameterTypes.ToImmutableArray(), arguments, functionPointer diff --git a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs index 83500b753..a52e4f64e 100644 --- a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs @@ -136,7 +136,7 @@ namespace ICSharpCode.Decompiler.TypeSystem } #region Resolve Type - public IType Resolve(TypeReference typeReference) + public IType Resolve(TypeReference typeReference, bool isFromSignature = false) { if (typeReference == null) return SpecialType.UnknownType; @@ -144,15 +144,22 @@ namespace ICSharpCode.Decompiler.TypeSystem // But PinnedType can be nested within modopt, so we'll also skip those. while (typeReference is OptionalModifierType || typeReference is RequiredModifierType) { typeReference = ((TypeSpecification)typeReference).ElementType; + isFromSignature = true; } if (typeReference is SentinelType || typeReference is PinnedType) { typeReference = ((TypeSpecification)typeReference).ElementType; + isFromSignature = true; } ITypeReference typeRef; lock (typeReferenceCecilLoader) - typeRef = typeReferenceCecilLoader.ReadTypeReference(typeReference); + typeRef = typeReferenceCecilLoader.ReadTypeReference(typeReference, isFromSignature: isFromSignature); return typeRef.Resolve(context); } + + IType ResolveInSignature(TypeReference typeReference) + { + return Resolve(typeReference, isFromSignature: true); + } #endregion #region Resolve Field @@ -166,7 +173,7 @@ namespace ICSharpCode.Decompiler.TypeSystem field = FindNonGenericField(fieldReference); if (fieldReference.DeclaringType.IsGenericInstance) { var git = (GenericInstanceType)fieldReference.DeclaringType; - var typeArguments = git.GenericArguments.SelectArray(Resolve); + var typeArguments = git.GenericArguments.SelectArray(ResolveInSignature); field = (IField)field.Specialize(new TypeParameterSubstitution(typeArguments, null)); } fieldLookupCache.Add(fieldReference, field); @@ -226,18 +233,18 @@ namespace ICSharpCode.Decompiler.TypeSystem if (methodReference.CallingConvention == MethodCallingConvention.VarArg) { method = new VarArgInstanceMethod( method, - methodReference.Parameters.SkipWhile(p => !p.ParameterType.IsSentinel).Select(p => Resolve(p.ParameterType)) + methodReference.Parameters.SkipWhile(p => !p.ParameterType.IsSentinel).Select(p => ResolveInSignature(p.ParameterType)) ); } else if (methodReference.IsGenericInstance || methodReference.DeclaringType.IsGenericInstance) { IReadOnlyList classTypeArguments = null; IReadOnlyList methodTypeArguments = null; if (methodReference.IsGenericInstance) { var gim = ((GenericInstanceMethod)methodReference); - methodTypeArguments = gim.GenericArguments.SelectArray(Resolve); + methodTypeArguments = gim.GenericArguments.SelectArray(ResolveInSignature); } if (methodReference.DeclaringType.IsGenericInstance) { var git = (GenericInstanceType)methodReference.DeclaringType; - classTypeArguments = git.GenericArguments.SelectArray(Resolve); + classTypeArguments = git.GenericArguments.SelectArray(ResolveInSignature); } method = method.Specialize(new TypeParameterSubstitution(classTypeArguments, methodTypeArguments)); } @@ -261,21 +268,23 @@ namespace ICSharpCode.Decompiler.TypeSystem methods = typeDef.GetMethods(m => m.Name == methodReference.Name, GetMemberOptions.IgnoreInheritedMembers) .Concat(typeDef.GetAccessors(m => m.Name == methodReference.Name, GetMemberOptions.IgnoreInheritedMembers)); } - foreach (var method in methods) { - if (GetCecil(method) == methodReference) - return method; + if (methodReference.MetadataToken.TokenType == TokenType.Method) { + foreach (var method in methods) { + if (method.MetadataToken == methodReference.MetadataToken) + return method; + } } IType[] parameterTypes; if (methodReference.CallingConvention == MethodCallingConvention.VarArg) { parameterTypes = methodReference.Parameters .TakeWhile(p => !p.ParameterType.IsSentinel) - .Select(p => Resolve(p.ParameterType)) + .Select(p => ResolveInSignature(p.ParameterType)) .Concat(new[] { SpecialType.ArgList }) .ToArray(); } else { - parameterTypes = methodReference.Parameters.SelectArray(p => Resolve(p.ParameterType)); + parameterTypes = methodReference.Parameters.SelectArray(p => ResolveInSignature(p.ParameterType)); } - var returnType = Resolve(methodReference.ReturnType); + var returnType = ResolveInSignature(methodReference.ReturnType); foreach (var method in methods) { if (method.TypeParameters.Count != methodReference.GenericParameters.Count) continue; @@ -362,7 +371,7 @@ namespace ICSharpCode.Decompiler.TypeSystem property = FindNonGenericProperty(propertyReference); if (propertyReference.DeclaringType.IsGenericInstance) { var git = (GenericInstanceType)propertyReference.DeclaringType; - var typeArguments = git.GenericArguments.SelectArray(Resolve); + var typeArguments = git.GenericArguments.SelectArray(ResolveInSignature); property = (IProperty)property.Specialize(new TypeParameterSubstitution(typeArguments, null)); } propertyLookupCache.Add(propertyReference, property); @@ -376,7 +385,7 @@ namespace ICSharpCode.Decompiler.TypeSystem ITypeDefinition typeDef = Resolve(propertyReference.DeclaringType).GetDefinition(); if (typeDef == null) return null; - var parameterTypes = propertyReference.Parameters.SelectArray(p => Resolve(p.ParameterType)); + var parameterTypes = propertyReference.Parameters.SelectArray(p => ResolveInSignature(p.ParameterType)); var returnType = Resolve(propertyReference.PropertyType); foreach (IProperty property in typeDef.Properties) { if (property.Name == propertyReference.Name @@ -399,7 +408,7 @@ namespace ICSharpCode.Decompiler.TypeSystem ev = FindNonGenericEvent(eventReference); if (eventReference.DeclaringType.IsGenericInstance) { var git = (GenericInstanceType)eventReference.DeclaringType; - var typeArguments = git.GenericArguments.SelectArray(Resolve); + var typeArguments = git.GenericArguments.SelectArray(ResolveInSignature); ev = (IEvent)ev.Specialize(new TypeParameterSubstitution(typeArguments, null)); } eventLookupCache.Add(eventReference, ev); diff --git a/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs index b0d5009fc..5788afd28 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs @@ -30,7 +30,7 @@ namespace ICSharpCode.Decompiler.TypeSystem TypeDefinition GetCecil(ITypeDefinition typeDefinition); MemberReference GetCecil(IMember member); - IType Resolve(TypeReference typeReference); + IType Resolve(TypeReference typeReference, bool isFromSignature = false); IField Resolve(FieldReference fieldReference); IMethod Resolve(MethodReference methodReference); diff --git a/ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs index 970cb8c66..537fa0f98 100644 --- a/ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs @@ -51,9 +51,9 @@ namespace ICSharpCode.Decompiler.TypeSystem get { return substitution; } } - public IType Resolve(Mono.Cecil.TypeReference typeReference) + public IType Resolve(Mono.Cecil.TypeReference typeReference, bool isFromSignature) { - return context.Resolve(typeReference).AcceptVisitor(substitution); + return context.Resolve(typeReference, isFromSignature).AcceptVisitor(substitution); } public IField Resolve(Mono.Cecil.FieldReference fieldReference)