Implement support for imported properties with parameters. Fixes #8398
authorMarek Safar <marek.safar@gmail.com>
Sun, 18 Nov 2012 18:40:04 +0000 (19:40 +0100)
committerMarek Safar <marek.safar@gmail.com>
Sun, 18 Nov 2012 18:41:12 +0000 (19:41 +0100)
12 files changed:
mcs/mcs/ecore.cs
mcs/mcs/generic.cs
mcs/mcs/import.cs
mcs/mcs/typespec.cs
mcs/tests/Makefile
mcs/tests/property-il.il [deleted file]
mcs/tests/property-main.cs [deleted file]
mcs/tests/test-858-lib.il [new file with mode: 0644]
mcs/tests/test-858.cs [new file with mode: 0644]
mcs/tests/test-859-lib.il [new file with mode: 0644]
mcs/tests/test-859.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_5.xml

index 745e422494678b938bf67da570c425b3bb797f79..9766c853853a09e8e6e4165bea70ad56dcf4358e 100644 (file)
@@ -4398,34 +4398,8 @@ namespace Mono.CSharp {
                                        // if the type matches
                                        //
                                        Expression e = fp.DefaultValue;
-                                       if (!(e is Constant) || e.Type != ptypes [i]) {
-                                               //
-                                               // LAMESPEC: No idea what the exact rules are for System.Reflection.Missing.Value instead of null
-                                               //
-                                               var ptype = ptypes [i];
-                                               if (e == EmptyExpression.MissingValue && ptype.BuiltinType == BuiltinTypeSpec.Type.Object || ptype.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
-                                                       e = new MemberAccess (new MemberAccess (new MemberAccess (
-                                                               new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Reflection", loc), "Missing", loc), "Value", loc);
-                                               } else if (e is Constant) {
-                                                       //
-                                                       // Handles int to int? conversions
-                                                       //
-                                                       e = Convert.ImplicitConversionStandard (ec, e, ptype, loc);
-                                                       
-                                                       //
-                                                       // When constant type paramter contains type argument
-                                                       //
-                                                       // Foo (T[] arg = null)
-                                                       //
-                                                       if (e == null) {
-                                                               e = new DefaultValueExpression (new TypeExpression (ptype, loc), loc);
-                                                       }
-                                               } else {
-                                                       e = new DefaultValueExpression (new TypeExpression (ptype, loc), loc);
-                                               }
-                                       
-
-                                               e = e.Resolve (ec);
+                                       if (e != null) {
+                                               e = ResolveDefaultValueArgument (ec, ptypes[i], e, loc);
                                        }
 
                                        if ((fp.ModFlags & Parameter.Modifier.CallerMask) != 0) {
@@ -4518,6 +4492,39 @@ namespace Mono.CSharp {
                        return 0;
                }
 
+               public static Expression ResolveDefaultValueArgument (ResolveContext ec, TypeSpec ptype, Expression e, Location loc)
+               {
+                       if (e is Constant && e.Type == ptype)
+                               return e;
+
+                       //
+                       // LAMESPEC: No idea what the exact rules are for System.Reflection.Missing.Value instead of null
+                       //
+                       if (e == EmptyExpression.MissingValue && ptype.BuiltinType == BuiltinTypeSpec.Type.Object || ptype.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
+                               e = new MemberAccess (new MemberAccess (new MemberAccess (
+                                       new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Reflection", loc), "Missing", loc), "Value", loc);
+                       } else if (e is Constant) {
+                               //
+                               // Handles int to int? conversions
+                               //
+                               e = Convert.ImplicitConversionStandard (ec, e, ptype, loc);
+
+                               //
+                               // When constant type paramter contains type argument
+                               //
+                               // Foo (T[] arg = null)
+                               //
+                               if (e == null) {
+                                       e = new DefaultValueExpression (new TypeExpression (ptype, loc), loc);
+                               }
+                       } else {
+                               e = new DefaultValueExpression (new TypeExpression (ptype, loc), loc);
+                       }
+
+
+                       return e.Resolve (ec);
+               }
+
                //
                // Tests argument compatibility with the parameter
                // The possible return values are
@@ -5808,6 +5815,8 @@ namespace Mono.CSharp {
        //
        sealed class PropertyExpr : PropertyOrIndexerExpr<PropertySpec>
        {
+               Arguments arguments;
+
                public PropertyExpr (PropertySpec spec, Location l)
                        : base (l)
                {
@@ -5819,9 +5828,10 @@ namespace Mono.CSharp {
 
                protected override Arguments Arguments {
                        get {
-                               return null;
+                               return arguments;
                        }
                        set {
+                               arguments = value;
                        }
                }
 
@@ -5978,7 +5988,7 @@ namespace Mono.CSharp {
                                        }
                                }
                        } else {
-                               args = new Arguments (1);
+                               args = arguments == null ? new Arguments (1) : arguments;
 
                                if (leave_copy) {
                                        source.Emit (ec);
@@ -6028,6 +6038,22 @@ namespace Mono.CSharp {
                        }
 
                        DoBestMemberChecks (rc, best_candidate);
+
+                       // Handling of com-imported properties with any number of default property parameters
+                       if (best_candidate.HasGet && !best_candidate.Get.Parameters.IsEmpty) {
+                               var p = best_candidate.Get.Parameters;
+                               arguments = new Arguments (p.Count);
+                               for (int i = 0; i < p.Count; ++i) {
+                                       arguments.Add (new Argument (OverloadResolver.ResolveDefaultValueArgument (rc, p.Types [i], p.FixedParameters [i].DefaultValue, loc)));
+                               }
+                       } else if (best_candidate.HasSet && best_candidate.Set.Parameters.Count > 1) {
+                               var p = best_candidate.Set.Parameters;
+                               arguments = new Arguments (p.Count - 1);
+                               for (int i = 0; i < p.Count - 1; ++i) {
+                                       arguments.Add (new Argument (OverloadResolver.ResolveDefaultValueArgument (rc, p.Types [i], p.FixedParameters [i].DefaultValue, loc)));
+                               }
+                       }
+
                        return this;
                }
 
index f7ecdfcf9e12872d32b8a8c512650fcce4f224c2..7b0a39407758f66e8e6ddcf1025d7df9e6ef0a5b 100644 (file)
@@ -416,6 +416,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               bool ITypeDefinition.IsComImport {
+                       get {
+                               return false;
+                       }
+               }
+
                bool ITypeDefinition.IsPartial {
                        get {
                                return false;
index 4880b3fa021ba4fc1c38ca0236e57bba410e524a..c40ee528eace1746d2fccdce79b0738ef5ca1656 100644 (file)
@@ -6,7 +6,7 @@
 // Dual licensed under the terms of the MIT X11 or GNU GPL
 //
 // Copyright 2009-2011 Novell, Inc
-// Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+// Copyright 2011-2012 Xamarin, Inc (http://www.xamarin.com)
 //
 
 using System;
@@ -620,26 +620,38 @@ namespace Mono.CSharp
 
                        PropertySpec spec = null;
                        if (!param.IsEmpty) {
-                               var index_name = declaringType.MemberDefinition.GetAttributeDefaultMember ();
-                               if (index_name == null) {
-                                       is_valid_property = false;
-                               } else {
-                                       if (get != null) {
-                                               if (get.IsStatic)
-                                                       is_valid_property = false;
-                                               if (get.Name.IndexOf (index_name, StringComparison.Ordinal) != 4)
+                               //
+                               // Enables support for properties with parameters (must have default value) of COM-imported types
+                               //
+                               if (declaringType.MemberDefinition.IsComImport && param.FixedParameters[0].HasDefaultValue) {
+                                       for (int i = 0; i < param.FixedParameters.Length; ++i) {
+                                               if (!param.FixedParameters[i].HasDefaultValue) {
                                                        is_valid_property = false;
+                                                       break;
+                                               }
                                        }
-                                       if (set != null) {
-                                               if (set.IsStatic)
-                                                       is_valid_property = false;
-                                               if (set.Name.IndexOf (index_name, StringComparison.Ordinal) != 4)
-                                                       is_valid_property = false;
+                               } else {
+                                       var index_name = declaringType.MemberDefinition.GetAttributeDefaultMember ();
+                                       if (index_name == null) {
+                                               is_valid_property = false;
+                                       } else {
+                                               if (get != null) {
+                                                       if (get.IsStatic)
+                                                               is_valid_property = false;
+                                                       if (get.Name.IndexOf (index_name, StringComparison.Ordinal) != 4)
+                                                               is_valid_property = false;
+                                               }
+                                               if (set != null) {
+                                                       if (set.IsStatic)
+                                                               is_valid_property = false;
+                                                       if (set.Name.IndexOf (index_name, StringComparison.Ordinal) != 4)
+                                                               is_valid_property = false;
+                                               }
                                        }
-                               }
 
-                               if (is_valid_property)
-                                       spec = new IndexerSpec (declaringType, new ImportedParameterMemberDefinition (pi, type, param, this), type, param, pi, mod);
+                                       if (is_valid_property)
+                                               spec = new IndexerSpec (declaringType, new ImportedParameterMemberDefinition (pi, type, param, this), type, param, pi, mod);
+                               }
                        }
 
                        if (spec == null)
@@ -1780,6 +1792,13 @@ namespace Mono.CSharp
                        }
                }
 
+               bool ITypeDefinition.IsComImport {
+                       get {
+                               return ((MetaType) provider).IsImport;
+                       }
+               }
+
+
                bool ITypeDefinition.IsPartial {
                        get {
                                return false;
@@ -2125,6 +2144,12 @@ namespace Mono.CSharp
                        }
                }
 
+               bool ITypeDefinition.IsComImport {
+                       get {
+                               return false;
+                       }
+               }
+
                bool ITypeDefinition.IsPartial {
                        get {
                                return false;
index 108c5cb7c252d96b5e42d465518a8a5c97e31883..7f10c157e140f171add15dc45301a986a19dc03e 100644 (file)
@@ -1354,6 +1354,7 @@ namespace Mono.CSharp
                IAssemblyDefinition DeclaringAssembly { get; }
                string Namespace { get; }
                bool IsPartial { get; }
+               bool IsComImport { get; }
                int TypeParametersCount { get; }
                TypeParameterSpec[] TypeParameters { get; }
 
@@ -1401,6 +1402,12 @@ namespace Mono.CSharp
                        }
                }
 
+               bool ITypeDefinition.IsComImport {
+                       get {
+                               return false;
+                       }
+               }
+
                bool IMemberDefinition.IsImported {
                        get {
                                return false;
@@ -1525,6 +1532,12 @@ namespace Mono.CSharp
 
                public TypeSpec Element { get; private set; }
 
+               bool ITypeDefinition.IsComImport {
+                       get {
+                               return false;
+                       }
+               }
+
                bool ITypeDefinition.IsPartial {
                        get {
                                return false;
index 2f967c8a0d2c9f769e8b43e209fbabc75f95a491..3be0a849855c00391d62ff3bee01b49d5021c089 100644 (file)
@@ -91,9 +91,5 @@ csproj-local:
        $(ILASM) /dll /out:$@ $<
 
 setup:
-       $(ILASM) /dll property-il.il
-       $(CSCOMPILE) /r:property-il.dll property-main.cs /out:property-main.exe
-       $(TEST_RUNTIME) property-main.exe
-
        $(CSCOMPILE) -t:library dlls/test-679-2/test-679-lib-2.cs
        $(CSCOMPILE) -t:library dlls/test-679-1/test-679-lib.cs -r:dlls/test-679-2/test-679-lib-2.dll
diff --git a/mcs/tests/property-il.il b/mcs/tests/property-il.il
deleted file mode 100644 (file)
index 7115547..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-.assembly extern mscorlib
-{
-  .ver 1:0:5000:0
-}
-.assembly 'property-il'
-{
-  .hash algorithm 0x00008004
-  .ver  0:0:0:0
-}
-.module 'property-il.dll' // GUID = {CACC88BA-6ED4-45E0-8E59-C3ABEBA9753A}
-
-
-  .class public auto ansi beforefieldinit 'Foo'
-       extends [mscorlib]System.Object
-  {
-
-    // method line 1
-    .method public hidebysig  specialname  rtspecialname 
-           instance default void .ctor ()  cil managed 
-    {
-        // Method begins at RVA 0x20ec
-       // Code size 7 (0x7)
-       .maxstack 8
-       IL_0000:  ldarg.0 
-       IL_0001:  call instance void valuetype [mscorlib]'System.Object'::.ctor()
-       IL_0006:  ret 
-    } // end of method Foo::instance default void .ctor () 
-
-    // method line 2
-    .method public virtual  hidebysig  newslot  specialname 
-           instance default string 'Monkey_Jump' ()  cil managed 
-    {
-        // Method begins at RVA 0x20f4
-       // Code size 6 (0x6)
-       .maxstack 8
-       IL_0000:  ldstr "foo"
-       IL_0005:  ret 
-    } // end of method Foo::instance default string 'Monkey_Jump' () 
-
-       .property specialname rtspecialname string Message ()
-       {
-               .get instance default string 'Foo'::'Monkey_Jump' () 
-       }
-  } // end of type Foo
-
-  .class public auto ansi beforefieldinit 'Bar'
-       extends Foo
-  {
-
-    // method line 3
-    .method public hidebysig  specialname  rtspecialname 
-           instance default void .ctor ()  cil managed 
-    {
-        // Method begins at RVA 0x20fb
-       // Code size 7 (0x7)
-       .maxstack 8
-       IL_0000:  ldarg.0 
-       IL_0001:  call instance void class 'Foo'::.ctor()
-       IL_0006:  ret 
-    } // end of method Bar::instance default void .ctor () 
-
-    // method line 4
-    .method public virtual  hidebysig  specialname 
-           instance default string 'Boston' ()  cil managed 
-    {
-        // Method begins at RVA 0x2103
-       // Code size 6 (0x6)
-       .maxstack 8
-       IL_0000:  ldstr "bar"
-       IL_0005:  ret 
-    } // end of method Bar::instance default string 'Boston' () 
-
-       .property specialname rtspecialname string Message ()
-       {
-               .get instance default string 'Bar'::'Boston' () 
-       }
-  } // end of type Bar
-  
-.class public auto ansi beforefieldinit C
-       extends [mscorlib]System.Object
-{
-  .method public hidebysig specialname instance int32 
-          get_Value() cil managed
-  {
-    .maxstack  1
-    .locals init (int32 V_0)
-    IL_0000:  ldc.i4.3
-    IL_0001:  stloc.0
-    IL_0002:  br.s       IL_0004
-
-    IL_0004:  ldloc.0
-    IL_0005:  ret
-  }
-
-  .method public hidebysig specialname instance void 
-          add_Arg(bool arg) cil managed
-  {
-    .maxstack  0
-    IL_0000:  ret
-  }
-
-  .method public hidebysig specialname rtspecialname 
-          instance void  .ctor() cil managed
-  {
-    .maxstack  1
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
-    IL_0006:  ret
-  }
-
-}
-  
diff --git a/mcs/tests/property-main.cs b/mcs/tests/property-main.cs
deleted file mode 100644 (file)
index a6cd8a0..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-using System;
-
-class X
-{
-       static int Main ()
-       {
-               Bar bar = new Bar ();
-               if (bar.Message != "bar")
-                       return 1;
-
-               Foo foo = new Foo ();
-               if (foo.Message != "foo")
-                       return 2;
-
-                C c = new C ();
-                c.get_Value ();
-                c.add_Arg (false);                
-                
-               Console.WriteLine ("Test ok");
-               return 0;
-       }
-}
diff --git a/mcs/tests/test-858-lib.il b/mcs/tests/test-858-lib.il
new file mode 100644 (file)
index 0000000..20cd244
--- /dev/null
@@ -0,0 +1,93 @@
+.assembly extern mscorlib
+{
+}
+
+.assembly 'test-858-lib'
+{
+  .hash algorithm 0x00008004
+  .ver  0:0:0:0
+}
+
+.module 'test-858-lib.dll'
+
+.class public auto ansi beforefieldinit 'Foo'
+       extends [mscorlib]System.Object
+  {
+
+    .method public hidebysig  specialname  rtspecialname 
+           instance default void .ctor ()  cil managed 
+    {
+      ldarg.0 
+      call instance void valuetype [mscorlib]'System.Object'::.ctor()
+      ret 
+    }
+
+    .method public virtual  hidebysig  newslot  specialname 
+           instance default string 'Monkey_Jump' ()  cil managed 
+    {
+      ldstr "foo"
+      ret 
+    }
+
+       .property specialname rtspecialname string Message ()
+       {
+               .get instance default string 'Foo'::'Monkey_Jump' () 
+       }
+}
+
+.class public auto ansi beforefieldinit 'Bar'
+       extends Foo
+  {
+    .method public hidebysig  specialname  rtspecialname 
+           instance default void .ctor ()  cil managed 
+    {
+      ldarg.0 
+      call instance void class 'Foo'::.ctor()
+      ret 
+    }
+
+    .method public virtual  hidebysig  specialname 
+           instance default string 'Boston' ()  cil managed 
+    {
+      ldstr "bar"
+      ret 
+    }
+
+    .property specialname rtspecialname string Message ()
+    {
+                 .get instance default string 'Bar'::'Boston' () 
+    }
+}
+
+.class public auto ansi beforefieldinit C
+       extends [mscorlib]System.Object
+{
+  .method public hidebysig specialname instance int32 
+          get_Value() cil managed
+  {
+    .locals init (int32 V_0)
+    IL_0000:  ldc.i4.3
+    IL_0001:  stloc.0
+    IL_0002:  br.s       IL_0004
+
+    IL_0004:  ldloc.0
+    IL_0005:  ret
+  }
+
+  .method public hidebysig specialname instance void 
+          add_Arg(bool arg) cil managed
+  {
+    ret
+  }
+
+  .method public hidebysig specialname rtspecialname 
+          instance void  .ctor() cil managed
+  {
+    ldarg.0
+    call       instance void [mscorlib]System.Object::.ctor()
+    ret
+  }
+}
+
+
+
diff --git a/mcs/tests/test-858.cs b/mcs/tests/test-858.cs
new file mode 100644 (file)
index 0000000..778ea68
--- /dev/null
@@ -0,0 +1,24 @@
+// Compiler options: -r:test-858-lib.dll
+
+using System;
+
+class X
+{
+       static int Main ()
+       {
+               Bar bar = new Bar ();
+               if (bar.Message != "bar")
+                       return 1;
+
+               Foo foo = new Foo ();
+               if (foo.Message != "foo")
+                       return 2;
+
+               C c = new C ();
+               c.get_Value ();
+               c.add_Arg (false);
+        
+               Console.WriteLine ("Test ok");
+               return 0;
+       }
+}
diff --git a/mcs/tests/test-859-lib.il b/mcs/tests/test-859-lib.il
new file mode 100644 (file)
index 0000000..94922ba
--- /dev/null
@@ -0,0 +1,39 @@
+.assembly extern mscorlib
+{
+}
+
+.assembly 'test-859-lib'
+{
+  .hash algorithm 0x00008004
+  .ver  0:0:0:0
+}
+
+.module 'test-859-lib.dll'
+
+// Import flag enables more magic
+
+.class interface public auto ansi import C
+{
+  .method public hidebysig newslot specialname virtual abstract
+          instance object 
+          get_Value([opt] object a) runtime managed preservesig internalcall
+  {
+  }
+
+  .property object Value(object)
+  {
+    .get instance object C::get_Value(object)
+  }
+
+  .method public hidebysig newslot specialname virtual abstract
+          instance void 
+          set_Value2([opt] object a, [opt] object b) runtime managed preservesig internalcall
+  {
+  }
+
+  .property object Value2(object)
+  {
+    .set instance void C::set_Value2(object, object)
+  }
+
+}
diff --git a/mcs/tests/test-859.cs b/mcs/tests/test-859.cs
new file mode 100644 (file)
index 0000000..1737b9c
--- /dev/null
@@ -0,0 +1,24 @@
+// Compiler options: -r:test-859-lib.dll
+
+using System;
+
+class X
+{
+       void Test_PropertyOptionalParameters (C c)
+       {
+               // need to just run verifier on the method
+               if (c == null)
+                       return;
+
+               Console.WriteLine (c.Value);
+               c.Value2 = 1;
+       }
+
+       static int Main ()
+       {
+               var x = new X ();
+               x.Test_PropertyOptionalParameters (null);
+
+               return 0;
+       }
+}
index cc0f40db31685ea1ba2b7ba9ae250a27308d0e87..955ea2fae2609d3371c12713c4ab84b954991e27 100644 (file)
       </method>\r
     </type>\r
   </test>\r
-  <test name="test-146.cs">\r
-    <type name="Test">\r
-      <method name="Int32 Main()" attrs="150">\r
-        <size>352</size>\r
-      </method>\r
-      <method name="Void .ctor()" attrs="6278">\r
-        <size>7</size>\r
-      </method>\r
-    </type>\r
-  </test>\r
   <test name="test-147.cs">\r
     <type name="X">\r
       <method name="X Foo()" attrs="150">\r
       </method>\r
     </type>\r
   </test>\r
+  <test name="test-858.cs">\r
+    <type name="X">\r
+      <method name="Int32 Main()" attrs="145">\r
+        <size>108</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
+  <test name="test-859.cs">\r
+    <type name="X">\r
+      <method name="Void Test_PropertyOptionalParameters(C)" attrs="129">\r
+        <size>46</size>\r
+      </method>\r
+      <method name="Int32 Main()" attrs="145">\r
+        <size>23</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
   <test name="test-86.cs">\r
     <type name="T.T">\r
       <method name="Int32 method1(System.Type, Int32)" attrs="145">\r
       </method>\r
     </type>\r
   </test>\r
-</tests>\r
+</tests>
\ No newline at end of file