Browse Source

Fix #304 Search for enum underlying type is incorrect

pull/320/merge
Daniel Grunwald 14 years ago
parent
commit
549d2c4dca
  1. 4
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 38
      ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

4
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -318,7 +318,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -318,7 +318,7 @@ namespace ICSharpCode.Decompiler.Ast
long expectedEnumMemberValue = 0;
bool forcePrintingInitializers = IsFlagsEnum(typeDef);
foreach (FieldDefinition field in typeDef.Fields) {
if (field.IsRuntimeSpecialName) {
if (!field.IsStatic) {
// the value__ field
if (field.FieldType != typeDef.Module.TypeSystem.Int32) {
astType.AddChild(ConvertType(field.FieldType), TypeDeclaration.BaseTypeRole);
@ -1518,7 +1518,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -1518,7 +1518,7 @@ namespace ICSharpCode.Decompiler.Ast
foreach (FieldDefinition field in enumDefinition.Fields) {
if (field.IsStatic && object.Equals(CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false), val))
return ConvertType(type).Member(field.Name).WithAnnotation(field);
else if (!field.IsStatic && field.IsRuntimeSpecialName)
else if (!field.IsStatic)
enumBaseTypeCode = TypeAnalysis.GetTypeCode(field.FieldType); // use primitive type of the enum
}
if (IsFlagsEnum(enumDefinition)) {

38
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -1046,18 +1046,28 @@ namespace ICSharpCode.Decompiler.ILAst @@ -1046,18 +1046,28 @@ namespace ICSharpCode.Decompiler.ILAst
/// </summary>
public const int NativeInt = 33; // treat native int as between int32 and int64
public static int GetInformationAmount(TypeReference type)
/// <summary>
/// Gets the underlying type, if the specified type is an enum.
/// Otherwise, returns null.
/// </summary>
public static TypeReference GetEnumUnderlyingType(TypeReference enumType)
{
if (type == null)
return 0;
if (type.IsValueType && !IsArrayPointerOrReference(type)) {
// unfortunately we cannot rely on enumType.IsValueType here - it's not set when the instruction operand is a typeref (as opposed to a typespec)
if (enumType != null && !IsArrayPointerOrReference(enumType)) {
// value type might be an enum
TypeDefinition typeDef = type.Resolve() as TypeDefinition;
TypeDefinition typeDef = enumType.Resolve() as TypeDefinition;
if (typeDef != null && typeDef.IsEnum) {
TypeReference underlyingType = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType;
return GetInformationAmount(underlyingType);
return typeDef.Fields.Single(f => !f.IsStatic).FieldType;
}
}
return null;
}
public static int GetInformationAmount(TypeReference type)
{
type = GetEnumUnderlyingType(type) ?? type;
if (type == null)
return 0;
switch (type.MetadataType) {
case MetadataType.Void:
return 0;
@ -1109,14 +1119,9 @@ namespace ICSharpCode.Decompiler.ILAst @@ -1109,14 +1119,9 @@ namespace ICSharpCode.Decompiler.ILAst
static bool? IsSigned(TypeReference type)
{
if (type == null || IsArrayPointerOrReference(type))
type = GetEnumUnderlyingType(type) ?? type;
if (type == null)
return null;
// unfortunately we cannot rely on type.IsValueType here - it's not set when the instruction operand is a typeref (as opposed to a typespec)
TypeDefinition typeDef = type.Resolve() as TypeDefinition;
if (typeDef != null && typeDef.IsEnum) {
TypeReference underlyingType = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType;
return IsSigned(underlyingType);
}
switch (type.MetadataType) {
case MetadataType.SByte:
case MetadataType.Int16:
@ -1138,10 +1143,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -1138,10 +1143,7 @@ namespace ICSharpCode.Decompiler.ILAst
static bool OperandFitsInType(TypeReference type, int num)
{
TypeDefinition typeDef = type.Resolve() as TypeDefinition;
if (typeDef != null && typeDef.IsEnum) {
type = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType;
}
type = GetEnumUnderlyingType(type) ?? type;
switch (type.MetadataType) {
case MetadataType.SByte:
return sbyte.MinValue <= num && num <= sbyte.MaxValue;

Loading…
Cancel
Save