[mcs] Special case flowanalysis of primitive structs. Fixes #28296
authorMarek Safar <marek.safar@gmail.com>
Thu, 26 Mar 2015 15:57:36 +0000 (16:57 +0100)
committerMarek Safar <marek.safar@gmail.com>
Thu, 26 Mar 2015 15:58:22 +0000 (16:58 +0100)
mcs/mcs/flowanalysis.cs
mcs/mcs/module.cs
mcs/tests/test-616.cs

index da30a3e5b907570cd2453f3c40761e43935c5f29..b9189c1f3d6d8aa31ef785065331a78c969c275b 100644 (file)
@@ -59,10 +59,9 @@ namespace Mono.CSharp
                public TypeInfo[] SubStructInfo;
 
                readonly StructInfo struct_info;
-               private static Dictionary<TypeSpec, TypeInfo> type_hash;
 
                static readonly TypeInfo simple_type = new TypeInfo (1);
-               
+
                static TypeInfo ()
                {
                        Reset ();
@@ -70,7 +69,6 @@ namespace Mono.CSharp
                
                public static void Reset ()
                {
-                       type_hash = new Dictionary<TypeSpec, TypeInfo> ();
                        StructInfo.field_type_hash = new Dictionary<TypeSpec, StructInfo> ();
                }
 
@@ -111,8 +109,17 @@ namespace Mono.CSharp
                                return simple_type;
 
                        TypeInfo info;
-                       if (type_hash.TryGetValue (type, out info))
-                               return info;
+                       Dictionary<TypeSpec, TypeInfo> type_hash;
+                       if (type.BuiltinType > 0) {
+                               // Don't cache built-in types, they are null in most cases except for
+                               // corlib compilation when we need to distinguish between declaration
+                               // and referencing
+                               type_hash = null;
+                       } else {
+                               type_hash = context.Module.TypeInfoCache;
+                               if (type_hash.TryGetValue (type, out info))
+                                       return info;
+                       }
 
                        var struct_info = StructInfo.GetStructInfo (type, context);
                        if (struct_info != null) {
@@ -121,7 +128,9 @@ namespace Mono.CSharp
                                info = simple_type;
                        }
 
-                       type_hash.Add (type, info);
+                       if (type_hash != null)
+                               type_hash.Add (type, info);
+
                        return info;
                }
 
@@ -262,7 +271,7 @@ namespace Mono.CSharp
 
                        public static StructInfo GetStructInfo (TypeSpec type, IMemberContext context)
                        {
-                               if (type.BuiltinType > 0)
+                               if (type.BuiltinType > 0 && type != context.CurrentType)
                                        return null;
 
                                StructInfo info;
index 3a9377c7547bc94531acc0df743eeb868d2e07e7..262f55e7b53f37b34f383ffb509c289294af4411 100644 (file)
@@ -267,6 +267,7 @@ namespace Mono.CSharp
                readonly Dictionary<TypeSpec, ReferenceContainer> reference_types;
                readonly Dictionary<TypeSpec, MethodSpec> attrs_cache;
                readonly Dictionary<TypeSpec, AwaiterDefinition> awaiters;
+               readonly Dictionary<TypeSpec, TypeInfo> type_info_cache;
 
                AssemblyDefinition assembly;
                readonly CompilerContext context;
@@ -302,6 +303,7 @@ namespace Mono.CSharp
                        reference_types = new Dictionary<TypeSpec, ReferenceContainer> ();
                        attrs_cache = new Dictionary<TypeSpec, MethodSpec> ();
                        awaiters = new Dictionary<TypeSpec, AwaiterDefinition> ();
+                       type_info_cache = new Dictionary<TypeSpec, TypeInfo> ();
                }
 
                #region Properties
@@ -425,6 +427,12 @@ namespace Mono.CSharp
                        }
                }
 
+               internal Dictionary<TypeSpec, TypeInfo> TypeInfoCache {
+                       get {
+                               return type_info_cache;
+                       }
+               }
+
                public override string[] ValidAttributeTargets {
                        get {
                                return attribute_targets;
index 6f189e836f26476de172d806ce3ef909ee1bb93a..9994d02ba941e8da2439e056a1e12201af3ef928 100644 (file)
@@ -25,7 +25,6 @@ namespace System
        public struct UInt64 {}
        public struct IntPtr {}
        public struct UIntPtr {}
-       public struct Decimal { }
        public class String { }
        public class Delegate {}
        public class MulticastDelegate {}
@@ -43,6 +42,24 @@ namespace System
                
        public interface IDisposable {}
 
+       public struct Decimal {
+
+               private int flags;
+
+               public Decimal(int[] bits) {
+                       flags = 0;
+                       SetBits(bits);
+               }
+
+               public Decimal (int i)
+               {
+                       flags = 0;
+               }
+
+               private void SetBits(int[] bits) {
+               }
+       }
+
        partial class Type
        {
                public static bool operator == (Type left, Type right)
@@ -54,6 +71,12 @@ namespace System
                {
                        return true;
                }
+
+               void Foo ()
+               {
+                       Decimal d = 0;
+                       var d2 = d;
+               }
        }       
 }
        
@@ -73,4 +96,3 @@ namespace System.Reflection
 {
        public class DefaultMemberAttribute {}
 }
-