Fix definitive assignment for imported structs. Fixes #629547
authorMarek Safar <marek.safar@gmail.com>
Wed, 7 Sep 2011 14:15:41 +0000 (15:15 +0100)
committerMarek Safar <marek.safar@gmail.com>
Wed, 7 Sep 2011 15:38:44 +0000 (16:38 +0100)
15 files changed:
mcs/errors/CS0165-19-lib.cs [new file with mode: 0644]
mcs/errors/Makefile
mcs/errors/cs0165-19.cs [new file with mode: 0644]
mcs/errors/cs0165-20.cs [new file with mode: 0644]
mcs/errors/cs0177-8.cs
mcs/errors/known-issues-net_4_0
mcs/mcs/ecore.cs
mcs/mcs/field.cs
mcs/mcs/flowanalysis.cs
mcs/mcs/import.cs
mcs/mcs/membercache.cs
mcs/tests/gtest-linq-22.cs
mcs/tests/test-827-lib.cs [new file with mode: 0644]
mcs/tests/test-827.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_0.xml

diff --git a/mcs/errors/CS0165-19-lib.cs b/mcs/errors/CS0165-19-lib.cs
new file mode 100644 (file)
index 0000000..bc0c0f6
--- /dev/null
@@ -0,0 +1,8 @@
+public struct S
+{
+       int private_value;
+       
+       public void Test ()
+       {
+       }
+}
\ No newline at end of file
index 875dabb8da9365b3840016ba55a8651858009bd2..c6082104d09cc706269abbfc5cfb3ae6755b82b4 100644 (file)
@@ -22,7 +22,7 @@ DISTFILES = \
 
 TEST_SUPPORT_FILES = \
        CS0012-lib.dll CS0012-2-lib.dll CS0012-3-lib.dll CS0012-4-lib.dll CS0012-5-lib.dll CS0012-6-lib.dll CS0012-9-lib.dll CS0012-10-lib.dll CS0012-11-lib.dll CS0012-12-lib.dll CS0012-13-lib.dll CS0029-26-lib.dll \
-       CS0103-2-lib.dll CS0118-2-lib.dll CS0122-10-lib.dll CS0122-14-lib.dll CS0122-15-lib.dll CS0122-19-lib.dll CS0122-35-lib.dll CS0122-36-lib.dll CS0143-lib.dll CS0144-3-lib.dll \
+       CS0103-2-lib.dll CS0118-2-lib.dll CS0122-10-lib.dll CS0122-14-lib.dll CS0122-15-lib.dll CS0122-19-lib.dll CS0122-35-lib.dll CS0122-36-lib.dll CS0143-lib.dll CS0144-3-lib.dll CS0165-19-lib.dll \
        CS0205-3-lib.dll CS0229-3-lib.dll CS0229-4-lib.dll CS0266-25-lib.dll \
        CS0315-2-lib.dll \
        CS0433-lib.dll CS0433-2-lib.dll \
diff --git a/mcs/errors/cs0165-19.cs b/mcs/errors/cs0165-19.cs
new file mode 100644 (file)
index 0000000..3a9e7ef
--- /dev/null
@@ -0,0 +1,12 @@
+// CS0165: Use of unassigned local variable `s'
+// Line: 10
+// Compiler options: -r:CS0165-19-lib.dll
+
+class Program
+{
+       static void Main ()
+       {
+               S s;
+               s.Test ();
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs0165-20.cs b/mcs/errors/cs0165-20.cs
new file mode 100644 (file)
index 0000000..0b52c6a
--- /dev/null
@@ -0,0 +1,20 @@
+// CS0165: Use of unassigned local variable `s'
+// Line: 9
+
+class Program
+{
+       static void Main ()
+       {
+               S s;
+               s.Test ();
+       }
+}
+
+struct S
+{
+       string pp;
+       
+       public void Test ()
+       {
+       }
+}
\ No newline at end of file
index 0a117adbc67c064f99b5efcc3e6d0e0ce8aa3980..c94b15a4699fdcf468e2e2c48c8441e1fa0df8d9 100644 (file)
@@ -1,13 +1,9 @@
 // CS0177: The out parameter `parameterModifiers' must be assigned to before control leaves the current method
-// Line: 17
+// Line: 13
 
 using System;
 using System.Reflection;
 
-/// <summary>
-/// MS does not report CS0177 for structs:
-/// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304489
-/// </summary>
 class Program
 {
        bool GetArgsForCall (object [] originalArgs, out ParameterModifier parameterModifiers)
index 6a59a40cbe5e5d219fffe5ca3881711fbf92bdf6..9cffc8e1742e816fa832698c5423bab33a69b690 100644 (file)
@@ -22,7 +22,6 @@ cs0165-15.cs NO ERROR # Bug 593369
 # all the following are from bug #628673
 cs1979.cs
 cs0168-2.cs
-cs0177-8.cs NO ERROR
 cs0647-14.cs NO ERROR
 cs1612-6.cs NO ERROR
 cs3006-7.cs NO ERROR
index 128fad6cbeecf6ac13d9667693ceb3f126625fa2..8756a951ff65df9d0225609a61352f5877263546 100644 (file)
@@ -669,6 +669,9 @@ namespace Mono.CSharp {
                                        if ((member.Modifiers & Modifiers.OVERRIDE) != 0 && member.Kind != MemberKind.Event)
                                                continue;
 
+                                       if ((member.Modifiers & Modifiers.BACKING_FIELD) != 0)
+                                               continue;
+
                                        if ((arity > 0 || (restrictions & MemberLookupRestrictions.ExactArity) != 0) && member.Arity != arity)
                                                continue;
 
index f10f62fa281fc04c75b3c5f5d81ce29c842b7316..4fd5390d2fdbdadfc7576fc74887d1dc95bae731 100644 (file)
@@ -611,8 +611,11 @@ namespace Mono.CSharp
 
                        spec = new FieldSpec (Parent.Definition, this, MemberType, FieldBuilder, ModFlags);
 
-                       // Don't cache inaccessible fields
-                       if ((ModFlags & Modifiers.BACKING_FIELD) == 0) {
+                       //
+                       // Don't cache inaccessible fields except for struct where we
+                       // need them for definitive assignment checks
+                       //
+                       if ((ModFlags & Modifiers.BACKING_FIELD) == 0 || Parent.Kind == MemberKind.Struct) {
                                Parent.MemberCache.AddMember (spec);
                        }
 
@@ -633,10 +636,6 @@ namespace Mono.CSharp
                                }
                        }
 
-/*
-                       if ((ModFlags & (Modifiers.STATIC | Modifiers.READONLY | Modifiers.COMPILER_GENERATED)) == Modifiers.STATIC)
-                               Console.WriteLine ("{0}: {1}", Location.ToString (), GetSignatureForError ());
-*/
                        return true;
                }
 
index dcd76df59a0edf753b9c9bd5ccd4c68b03d92b4a..17e3dc51965f415125cb641c94975fb656fae064 100644 (file)
@@ -1215,22 +1215,19 @@ namespace Mono.CSharp
                                              Type, Offset, Length, TotalLength);
                }
 
-               class StructInfo {
+               class StructInfo
+               {
                        public readonly TypeSpec Type;
-                       public readonly FieldSpec[] Fields;
+                       readonly List<FieldSpec> fields;
                        public readonly TypeInfo[] StructFields;
-                       public readonly int Count;
-                       public readonly int CountPublic;
-                       public readonly int CountNonPublic;
                        public readonly int Length;
                        public readonly int TotalLength;
-                       public readonly bool HasStructFields;
 
                        public static Dictionary<TypeSpec, StructInfo> field_type_hash;
                        private Dictionary<string, TypeInfo> struct_field_hash;
                        private Dictionary<string, int> field_hash;
 
-                       protected bool InTransit = false;
+                       protected bool InTransit;
 
                        // Private constructor.  To save memory usage, we only need to create one instance
                        // of this class per struct type.
@@ -1240,52 +1237,18 @@ namespace Mono.CSharp
 
                                field_type_hash.Add (type, this);
 
-                               TypeContainer tc = type.MemberDefinition as TypeContainer;
-
-                               var public_fields = new List<FieldSpec> ();
-                               var non_public_fields = new List<FieldSpec> ();
-
-                               if (tc != null) {
-                                       var fields = tc.Fields;
-
-                                       if (fields != null) {
-                                               foreach (FieldBase field in fields) {
-                                                       if ((field.ModFlags & Modifiers.STATIC) != 0)
-                                                               continue;
-
-                                                       //
-                                                       // Fixed size buffers are not subject to definite assignment checking
-                                                       //
-                                                       if (field is FixedField)
-                                                               continue;
-
-                                                       if ((field.ModFlags & Modifiers.PUBLIC) != 0)
-                                                               public_fields.Add (field.Spec);
-                                                       else
-                                                               non_public_fields.Add (field.Spec);
-                                               }
-                                       }
-                               }
-
-                               CountPublic = public_fields.Count;
-                               CountNonPublic = non_public_fields.Count;
-                               Count = CountPublic + CountNonPublic;
-
-                               Fields = new FieldSpec[Count];
-                               public_fields.CopyTo (Fields, 0);
-                               non_public_fields.CopyTo (Fields, CountPublic);
+                               fields = MemberCache.GetAllFieldsForDefiniteAssignment (type);
 
                                struct_field_hash = new Dictionary<string, TypeInfo> ();
-                               field_hash = new Dictionary<string, int> ();
+                               field_hash = new Dictionary<string, int> (fields.Count);
 
-                               Length = 0;
-                               StructFields = new TypeInfo [Count];
-                               StructInfo[] sinfo = new StructInfo [Count];
+                               StructFields = new TypeInfo[fields.Count];
+                               StructInfo[] sinfo = new StructInfo[fields.Count];
 
                                InTransit = true;
 
-                               for (int i = 0; i < Count; i++) {
-                                       var field = Fields [i];
+                               for (int i = 0; i < fields.Count; i++) {
+                                       var field = fields [i];
 
                                        sinfo [i] = GetStructInfo (field.MemberType);
                                        if (sinfo [i] == null)
@@ -1299,21 +1262,32 @@ namespace Mono.CSharp
                                InTransit = false;
 
                                TotalLength = Length + 1;
-                               for (int i = 0; i < Count; i++) {
-                                       var field = Fields [i];
+                               for (int i = 0; i < fields.Count; i++) {
+                                       var field = fields [i];
 
                                        if (sinfo [i] == null)
                                                continue;
 
                                        field_hash.Add (field.Name, TotalLength);
 
-                                       HasStructFields = true;
                                        StructFields [i] = new TypeInfo (sinfo [i], TotalLength);
                                        struct_field_hash.Add (field.Name, StructFields [i]);
                                        TotalLength += sinfo [i].TotalLength;
                                }
                        }
 
+                       public int Count {
+                               get {
+                                       return fields.Count;
+                               }
+                       }
+
+                       public List<FieldSpec> Fields {
+                               get {
+                                       return fields;
+                               }
+                       }
+
                        public int this [string name] {
                                get {
                                        int val;
index 595a6193e60a8d60a412e5f342a7c104c31c0889..76d2392afa8f6c180eb4740cae8e8e9aea7f3f79 100644 (file)
@@ -169,7 +169,8 @@ namespace Mono.CSharp
                                        break;
                                default:
                                        // Ignore private fields (even for error reporting) to not require extra dependencies
-                                       if (IgnorePrivateMembers || HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace))
+                                       if ((IgnorePrivateMembers && !declaringType.IsStruct) ||
+                                               HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace))
                                                return null;
 
                                        mod = Modifiers.PRIVATE;
index a01100c25f69ffe8098f03027742bdbcc7c19fe9..61b51dd7ef04569153e41da2fe773fdafb083a66 100644 (file)
@@ -684,6 +684,44 @@ namespace Mono.CSharp {
                        throw new NotImplementedException (member.GetType ().ToString ());
                }
 
+               public static List<FieldSpec> GetAllFieldsForDefiniteAssignment (TypeSpec container)
+               {
+                       List<FieldSpec> fields = null;
+                       foreach (var entry in container.MemberCache.member_hash) {
+                               foreach (var name_entry in entry.Value) {
+                                       if (name_entry.Kind != MemberKind.Field)
+                                               continue;
+
+                                       if ((name_entry.Modifiers & Modifiers.STATIC) != 0)
+                                               continue;
+
+                                       //
+                                       // Fixed size buffers are not subject to definite assignment checking
+                                       //
+                                       if (name_entry is FixedFieldSpec || name_entry is ConstSpec)
+                                               continue;
+
+                                       var fs = (FieldSpec) name_entry;
+
+                                       //
+                                       // LAMESPEC: Very bizzare hack, definitive assignment is not done
+                                       // for imported non-public reference fields except array. No idea what the
+                                       // actual csc rule is
+                                       //
+                                       if (!fs.IsPublic && container.MemberDefinition.IsImported && (!fs.MemberType.IsArray && TypeSpec.IsReferenceType (fs.MemberType)))
+                                               continue;
+
+                                       if (fields == null)
+                                               fields = new List<FieldSpec> ();
+
+                                       fields.Add (fs);
+                                       break;
+                               }
+                       }
+
+                       return fields ?? new List<FieldSpec> (0);
+               }
+
                public static IList<MemberSpec> GetCompletitionMembers (IMemberContext ctx, TypeSpec container, string name)
                {
                        var matches = new List<MemberSpec> ();
index 05a9fb081f90de3ac1501373b550a4913a2615c4..d6d3a0de443803644ac7d4d0be246548be4d5696 100644 (file)
@@ -7,7 +7,7 @@ namespace Test
        {
                public static void Main ()
                {
-                       DateTime junk;
+                       DateTime junk = DateTime.Today;
                        var results = from item in "abcd"
                                                  let parsed = DateTime.TryParse ("today", out junk)
                                                  select parsed ? junk : DateTime.Now;
diff --git a/mcs/tests/test-827-lib.cs b/mcs/tests/test-827-lib.cs
new file mode 100644 (file)
index 0000000..facb2e9
--- /dev/null
@@ -0,0 +1,10 @@
+// Compiler options: -t:library
+
+public struct S
+{
+       string s;
+       
+       public void Test ()
+       {
+       }
+}
diff --git a/mcs/tests/test-827.cs b/mcs/tests/test-827.cs
new file mode 100644 (file)
index 0000000..faf6a57
--- /dev/null
@@ -0,0 +1,12 @@
+// Compiler options: -r:test-827-lib.dll
+
+// Only to check we are compatible with broken csc definite assignment implementation
+
+class Program
+{
+       static void Main ()
+       {
+               S s;
+               s.Test ();
+       }
+}
index 1da8d87f527d67a177c27d2053021b5915da891f..358ad88006d6c13a9fdc59a9c1db3524640f2c96 100644 (file)
   <test name="gtest-linq-22.cs">
     <type name="Test.MainClass">
       <method name="Void Main()">
-        <size>47</size>
+        <size>58</size>
       </method>
       <method name="Void .ctor()">
         <size>7</size>
       </method>
     </type>
   </test>
+  <test name="test-827.cs">
+    <type name="Program">
+      <method name="Void Main()">
+        <size>8</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="test-83.cs">
     <type name="PersonArrivedArgs">
       <method name="Void .ctor(String)">