Clone shared members list before operators merging. Fixes #10967
authorMarek Safar <marek.safar@gmail.com>
Fri, 8 Mar 2013 21:55:23 +0000 (22:55 +0100)
committerMarek Safar <marek.safar@gmail.com>
Fri, 8 Mar 2013 22:46:26 +0000 (23:46 +0100)
mcs/mcs/membercache.cs
mcs/tests/test-866.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_5.xml

index 7209af7dc74c5fcbe93d50e9eb6ec8f3bfceadfd..cad910e01bc896b209a8c150e094a23a5513b660 100644 (file)
@@ -299,6 +299,7 @@ namespace Mono.CSharp {
                        if (member.Kind == MemberKind.Operator) {
                                var dt = member.DeclaringType;
 
+
                                //
                                // Some core types have user operators but they cannot be used like normal
                                // user operators as they are predefined and therefore having different
@@ -908,7 +909,7 @@ namespace Mono.CSharp {
                public static IList<MemberSpec> GetUserOperator (TypeSpec container, Operator.OpType op, bool declaredOnly)
                {
                        IList<MemberSpec> found = null;
-
+                       bool shared_list = true;
                        IList<MemberSpec> applicable;
                        do {
                                var mc = container.MemberCache;
@@ -938,10 +939,13 @@ namespace Mono.CSharp {
                                                                        found = new List<MemberSpec> ();
                                                                        found.Add (applicable[i]);
                                                                } else {
-                                                                       var prev = found as List<MemberSpec>;
-                                                                       if (prev == null) {
+                                                                       List<MemberSpec> prev;
+                                                                       if (shared_list) {
+                                                                               shared_list = false;
                                                                                prev = new List<MemberSpec> (found.Count + 1);
                                                                                prev.AddRange (found);
+                                                                       } else {
+                                                                               prev = (List<MemberSpec>) found;
                                                                        }
 
                                                                        prev.Add (applicable[i]);
@@ -950,12 +954,16 @@ namespace Mono.CSharp {
                                                } else {
                                                        if (found == null) {
                                                                found = applicable;
+                                                               shared_list = true;
                                                        } else {
-                                                               var merged = found as List<MemberSpec>;
-                                                               if (merged == null) {
+                                                               List<MemberSpec> merged;
+                                                               if (shared_list) {
+                                                                       shared_list = false;
                                                                        merged = new List<MemberSpec> (found.Count + applicable.Count);
                                                                        merged.AddRange (found);
                                                                        found = merged;
+                                                               } else {
+                                                                       merged = (List<MemberSpec>) found;
                                                                }
 
                                                                merged.AddRange (applicable);
diff --git a/mcs/tests/test-866.cs b/mcs/tests/test-866.cs
new file mode 100644 (file)
index 0000000..723795e
--- /dev/null
@@ -0,0 +1,30 @@
+class C : B
+{
+       public static bool operator + (C a, short b)
+       {
+               return false;
+       }
+
+       public static bool operator + (C a, long b)
+       {
+               return false;
+       }
+}
+
+class B
+{
+       public static bool operator + (B b, string s)
+       {
+               return false;
+       }
+}
+
+public class Test
+{
+       public static void Main ()
+       {
+               var c = new C ();
+               var a1 = c + "a";
+               var a2 = c + "a";
+       }
+}
\ No newline at end of file
index 36c43c712418bf7446aed496666a07b55f781b3b..ab4aca730e063b1d154cc5c4975792dcdb6a5df7 100644 (file)
       </method>\r
     </type>\r
   </test>\r
+  <test name="test-866.cs">\r
+    <type name="C">\r
+      <method name="Boolean op_Addition(C, Int16)" attrs="2198">\r
+        <size>10</size>\r
+      </method>\r
+      <method name="Boolean op_Addition(C, Int64)" attrs="2198">\r
+        <size>10</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+    <type name="B">\r
+      <method name="Boolean op_Addition(B, System.String)" attrs="2198">\r
+        <size>10</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+    <type name="Test">\r
+      <method name="Void Main()" attrs="150">\r
+        <size>32</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
   <test name="test-87.cs">\r
     <type name="Top">\r
       <method name="Int32 Main()" attrs="150">\r