c14a6c388f2d7ead77af118aa26a8f0c12cde2dd
[mono.git] / mcs / class / corlib / Test / System.Reflection.Emit / MethodBuilderTest.cs
1 //
2 // MethodBuilderTest.cs - NUnit Test Cases for the MethodBuilder class
3 //
4 // Zoltan Varga (vargaz@freemail.hu)
5 //
6 // (C) Ximian, Inc.  http://www.ximian.com
7
8 // TODO:
9 //  - implement 'Signature' (what the hell it does???) and test it
10 //  - implement Equals and test it
11
12 using System;
13 using System.Threading;
14 using System.Reflection;
15 using System.Reflection.Emit;
16 using System.Runtime.CompilerServices;
17 using System.Security;
18 using System.Security.Permissions;
19 using System.Runtime.InteropServices;
20
21 using NUnit.Framework;
22
23 namespace MonoTests.System.Reflection.Emit
24 {
25         [TestFixture]
26         public class MethodBuilderTest
27         {
28                 private TypeBuilder genClass;
29                 private ModuleBuilder module;
30
31                 [SetUp]
32                 protected void SetUp ()
33                 {
34                         AssemblyName assemblyName = new AssemblyName ();
35                         assemblyName.Name = "MonoTests.System.Reflection.Emit.MethodBuilderTest";
36
37                         AssemblyBuilder assembly = Thread.GetDomain ().DefineDynamicAssembly (
38                                 assemblyName, AssemblyBuilderAccess.Run);
39                         module = assembly.DefineDynamicModule ("module1");
40                         genClass = module.DefineType (genTypeName (), TypeAttributes.Public);
41                 }
42
43                 static int methodIndexer = 0;
44                 static int typeIndexer = 0;
45
46                 // Return a unique method name
47                 private string genMethodName ()
48                 {
49                         return "m" + (methodIndexer++);
50                 }
51
52                 // Return a unique type name
53                 private string genTypeName ()
54                 {
55                         return "class" + (typeIndexer++);
56                 }
57
58                 [Test]
59                 public void TestAttributes ()
60                 {
61                         MethodBuilder mb = genClass.DefineMethod (
62                                 genMethodName (), MethodAttributes.Public, typeof (void), new Type [0]);
63                         Assert.AreEqual (MethodAttributes.Public, mb.Attributes);
64                 }
65
66                 [Test]
67                 public void TestCallingConvention ()
68                 {
69                         MethodBuilder mb = genClass.DefineMethod (
70                                 genMethodName (), 0, typeof (void), new Type [0]);
71                         Assert.AreEqual (CallingConventions.Standard | CallingConventions.HasThis,
72                                 mb.CallingConvention, "CallingConvetion defaults to Standard+HasThis");
73
74                         MethodBuilder mb3 = genClass.DefineMethod (
75                                 genMethodName (), 0, CallingConventions.VarArgs, typeof (void), new Type [0]);
76                         Assert.AreEqual (CallingConventions.VarArgs | CallingConventions.HasThis,
77                                 mb3.CallingConvention, "CallingConvetion works");
78
79                         MethodBuilder mb4 = genClass.DefineMethod (
80                                 genMethodName (), MethodAttributes.Static, CallingConventions.Standard,
81                                 typeof (void), new Type [0]);
82                         Assert.AreEqual (CallingConventions.Standard, mb4.CallingConvention,
83                                 "Static implies !HasThis");
84                 }
85
86                 [Test]
87                 public void TestDeclaringType ()
88                 {
89                         MethodBuilder mb = genClass.DefineMethod (
90                                 genMethodName (), 0, typeof (void), new Type [0]);
91
92                         Assert.AreEqual (genClass, mb.DeclaringType, "DeclaringType works");
93                 }
94
95                 [Test]
96                 public void TestInitLocals ()
97                 {
98                         MethodBuilder mb = genClass.DefineMethod (
99                                 genMethodName (), 0, typeof (void), new Type [0]);
100
101                         Assert.IsTrue (mb.InitLocals, "#1");
102                         mb.InitLocals = false;
103                         Assert.IsFalse (mb.InitLocals, "#2");
104                 }
105
106                 [Test]
107                 [ExpectedException (typeof (NotSupportedException))]
108                 public void TestMethodHandleIncomplete ()
109                 {
110                         MethodBuilder mb = genClass.DefineMethod (
111                                 genMethodName (), 0, typeof (void), new Type [0]);
112
113                         RuntimeMethodHandle handle = mb.MethodHandle;
114                 }
115
116                 [Test]
117                 [ExpectedException (typeof (NotSupportedException))]
118                 public void TestMethodHandleComplete ()
119                 {
120                         MethodBuilder mb = genClass.DefineMethod (
121                                 genMethodName (), 0, typeof (void), new Type [0]);
122                         mb.CreateMethodBody (new byte [2], 1);
123                         genClass.CreateType ();
124
125                         RuntimeMethodHandle handle = mb.MethodHandle;
126                 }
127
128                 [Test]
129                 public void TestName ()
130                 {
131                         string name = genMethodName ();
132                         MethodBuilder mb = genClass.DefineMethod (
133                                 name, 0, typeof (void), new Type [0]);
134
135                         Assert.AreEqual (name, mb.Name);
136                 }
137
138                 [Test]
139                 public void TestReflectedType ()
140                 {
141                         MethodBuilder mb = genClass.DefineMethod (
142                                 genMethodName (), 0, typeof (void), new Type [0]);
143
144                         Assert.AreEqual (genClass, mb.ReflectedType);
145                 }
146
147                 [Test]
148                 public void TestReturnType ()
149                 {
150                         MethodBuilder mb = genClass.DefineMethod (
151                                 genMethodName (), 0, typeof (Console), new Type [0]);
152                         Assert.AreEqual (typeof (Console), mb.ReturnType, "#1");
153
154                         MethodBuilder mb2 = genClass.DefineMethod (
155                                 genMethodName (), 0, null, new Type [0]);
156                         Assert.IsTrue (mb2.ReturnType == null || mb2.ReturnType == typeof (void), "#2");
157                 }
158
159                 [Test]
160                 public void TestReturnTypeCustomAttributes ()
161                 {
162                         MethodBuilder mb = genClass.DefineMethod (
163                                 genMethodName (), 0, typeof (Console), new Type [0]);
164                         Assert.IsNull (mb.ReturnTypeCustomAttributes);
165                 }
166
167                 /*
168                 public void TestSignature () {
169                         MethodBuilder mb = genClass.DefineMethod (
170                                 "m91", 0, typeof (Console), new Type [1] { typeof (Console) });
171
172                         Console.WriteLine (mb.Signature);
173                 }
174                 */
175
176                 [Test]
177                 public void TestCreateMethodBody ()
178                 {
179                         MethodBuilder mb = genClass.DefineMethod (
180                                 genMethodName (), 0, typeof (void), new Type [0]);
181
182                         // Clear body
183                         mb.CreateMethodBody (null, 999);
184
185                         // Check arguments 1.
186                         try {
187                                 mb.CreateMethodBody (new byte [1], -1);
188                                 Assert.Fail ("#1");
189                         } catch (ArgumentOutOfRangeException) {
190                         }
191
192                         // Check arguments 2.
193                         try {
194                                 mb.CreateMethodBody (new byte [1], 2);
195                                 Assert.Fail ("#2");
196                         } catch (ArgumentOutOfRangeException) {
197                         }
198
199                         mb.CreateMethodBody (new byte [2], 1);
200
201                         // Could only be called once
202                         try {
203                                 mb.CreateMethodBody (new byte [2], 1);
204                                 Assert.Fail ("#3");
205                         } catch (InvalidOperationException) {
206                         }
207
208                         // Can not be called on a created type
209                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
210                         MethodBuilder mb2 = tb.DefineMethod (
211                                 genMethodName (), 0, typeof (void), new Type [0]);
212                         ILGenerator ilgen = mb2.GetILGenerator ();
213                         ilgen.Emit (OpCodes.Ret);
214                         tb.CreateType ();
215
216                         try {
217                                 mb2.CreateMethodBody (new byte [2], 1);
218                                 Assert.Fail ("#4");
219                         } catch (InvalidOperationException) {
220                         }
221                 }
222
223                 [Test]
224                 [ExpectedException (typeof (InvalidOperationException))]
225                 public void TestDefineParameterInvalidIndexComplete ()
226                 {
227                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
228                         MethodBuilder mb = tb.DefineMethod (genMethodName (), 0, typeof (void),
229                                 new Type [2] { typeof(int), typeof(int) });
230                         mb.CreateMethodBody (new byte [2], 1);
231                         tb.CreateType ();
232                         mb.DefineParameter (-5, ParameterAttributes.None, "param1");
233                 }
234
235                 [Test]
236                 [ExpectedException (typeof (InvalidOperationException))]
237                 public void TestDefineParameterValidIndexComplete ()
238                 {
239                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
240                         MethodBuilder mb = tb.DefineMethod (genMethodName (), 0, typeof (void),
241                                 new Type [2] { typeof(int), typeof(int) });
242                         mb.CreateMethodBody (new byte [2], 1);
243                         tb.CreateType ();
244                         mb.DefineParameter (1, ParameterAttributes.None, "param1");
245                 }
246
247                 [Test]
248                 public void TestDefineParameter ()
249                 {
250                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
251                         MethodBuilder mb = tb.DefineMethod (
252                                 genMethodName (), 0, typeof (void),
253                                 new Type [2] { typeof (int), typeof (int) });
254
255                         // index out of range
256
257                         // This fails on mono because the mono version accepts a 0 index
258                         /*
259                         try {
260                                 mb.DefineParameter (0, 0, "param1");
261                                 Fail ();
262                         } catch (ArgumentOutOfRangeException) {
263                         }
264                         */
265
266                         try {
267                                 mb.DefineParameter (3, 0, "param1");
268                                 Assert.Fail ("#1");
269                         } catch (ArgumentOutOfRangeException) {
270                         }
271
272                         // Normal usage
273                         mb.DefineParameter (1, 0, "param1");
274                         mb.DefineParameter (1, 0, "param1");
275                         mb.DefineParameter (2, 0, null);
276
277                         mb.CreateMethodBody (new byte [2], 1);
278                         tb.CreateType ();
279                         try {
280                                 mb.DefineParameter (1, 0, "param1");
281                                 Assert.Fail ("#2");
282                         } catch (InvalidOperationException) {
283                         }
284                 }
285
286                 [Test]
287                 // MS.NET 2.x no longer allows a zero length method body
288                 // to be emitted
289                 [ExpectedException (typeof (InvalidOperationException))]
290                 public void ZeroLengthBodyTest1 ()
291                 {
292                         MethodBuilder mb = genClass.DefineMethod (
293                                 genMethodName (), 0, typeof (void),
294                                 new Type [2] { typeof (int), typeof (int) });
295                         mb.CreateMethodBody (new byte [2], 0);
296                         genClass.CreateType ();
297                 }
298
299                 // A zero length method body can be created
300                 [Test]
301                 public void ZeroLengthBodyTest2 ()
302                 {
303                         MethodBuilder mb = genClass.DefineMethod (
304                                 genMethodName (), 0, typeof (void),
305                                 new Type [2] { typeof (int), typeof (int) });
306                         mb.CreateMethodBody (new byte [2], 0);
307                 }
308
309                 [Test]
310                 public void TestHashCode ()
311                 {
312                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
313                         string methodName = genMethodName ();
314                         MethodBuilder mb = tb.DefineMethod (methodName, 0, typeof (void),
315                                 new Type [2] { typeof(int), typeof(int) });
316                         Assert.AreEqual (methodName.GetHashCode (), mb.GetHashCode ());
317                 }
318
319                 [Test]
320                 public void TestGetBaseDefinition ()
321                 {
322                         MethodBuilder mb = genClass.DefineMethod (
323                                 genMethodName (), 0, typeof (void), new Type [0]);
324                         Assert.AreEqual (mb.GetBaseDefinition (), mb);
325                 }
326
327                 [Test]
328                 public void TestGetILGenerator ()
329                 {
330                         MethodBuilder mb = genClass.DefineMethod (
331                                 genMethodName (), 0, typeof (void), new Type [0]);
332
333                         // The same instance is returned on the second call
334                         ILGenerator ilgen1 = mb.GetILGenerator ();
335                         ILGenerator ilgen2 = mb.GetILGenerator ();
336
337                         Assert.AreEqual (ilgen1, ilgen2, "#1");
338
339                         // Does not work on unmanaged code
340                         MethodBuilder mb2 = genClass.DefineMethod (
341                                 genMethodName (), 0, typeof (void), new Type [0]);
342                         try {
343                                 mb2.SetImplementationFlags (MethodImplAttributes.Unmanaged);
344                                 mb2.GetILGenerator ();
345                                 Assert.Fail ("#2");
346                         } catch (InvalidOperationException) {
347                         }
348                         try {
349                                 mb2.SetImplementationFlags (MethodImplAttributes.Native);
350                                 mb2.GetILGenerator ();
351                                 Assert.Fail ("#3");
352                         } catch (InvalidOperationException) {
353                         }
354                 }
355
356                 [Test]
357                 public void TestMethodImplementationFlags ()
358                 {
359                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
360                         MethodBuilder mb = tb.DefineMethod (
361                                 genMethodName (), 0, typeof (void), new Type [0]);
362
363                         Assert.AreEqual (MethodImplAttributes.Managed | MethodImplAttributes.IL,
364                                 mb.GetMethodImplementationFlags (), "#1");
365
366                         mb.SetImplementationFlags (MethodImplAttributes.OPTIL);
367
368                         Assert.AreEqual (MethodImplAttributes.OPTIL, mb.GetMethodImplementationFlags (), "#2");
369
370                         mb.CreateMethodBody (new byte [2], 1);
371                         mb.SetImplementationFlags (MethodImplAttributes.Managed);
372                         tb.CreateType ();
373                         try {
374                                 mb.SetImplementationFlags (MethodImplAttributes.OPTIL);
375                                 Assert.Fail ("#3");
376                         } catch (InvalidOperationException) {
377                         }
378                 }
379
380                 [Test]
381                 public void TestGetModule ()
382                 {
383                         MethodBuilder mb = genClass.DefineMethod (
384                                 genMethodName (), 0, typeof (void), new Type [0]);
385                         Assert.AreEqual (module, mb.GetModule ());
386                 }
387
388                 [Test]
389                 public void TestGetParameters ()
390                 {
391                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
392                         MethodBuilder mb = tb.DefineMethod (genMethodName (), 0, typeof (void),
393                                 new Type [1] { typeof (void) });
394
395                         /*
396                          * According to the MSDN docs, this method should fail with a
397                          * NotSupportedException. In reality, it throws an 
398                          * InvalidOperationException under MS .NET, and returns the 
399                          * requested data under mono.
400                          */
401                         /*
402                         try {
403                                 mb.GetParameters ();
404                                 Fail ("#161");
405                         } catch (InvalidOperationException ex) {
406                                 Console.WriteLine (ex);
407                         }
408                         */
409                 }
410
411                 [Test]
412                 public void TestGetToken ()
413                 {
414                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
415                         MethodBuilder mb = tb.DefineMethod (
416                                 genMethodName (), 0, typeof (void), new Type [1] { typeof (void) });
417                         mb.GetToken ();
418                 }
419
420                 [Test]
421                 public void TestInvoke ()
422                 {
423                         MethodBuilder mb = genClass.DefineMethod (
424                                 genMethodName (), 0, typeof (void),
425                                 new Type [1] { typeof (int) });
426
427                         try {
428                                 mb.Invoke (null, new object [1] { 42 });
429                                 Assert.Fail ("#1");
430                         } catch (NotSupportedException) {
431                         }
432
433                         try {
434                                 mb.Invoke (null, 0, null, new object [1] { 42 }, null);
435                                 Assert.Fail ("#2");
436                         } catch (NotSupportedException) {
437                         }
438                 }
439
440                 [Test]
441                 [ExpectedException (typeof (NotSupportedException))]
442                 public void TestIsDefined ()
443                 {
444                         MethodBuilder mb = genClass.DefineMethod (
445                                 genMethodName (), 0, typeof (void),
446                                 new Type [1] { typeof (int) });
447                         mb.IsDefined (null, true);
448                 }
449
450                 [Test]
451                 public void TestGetCustomAttributes_Incomplete ()
452                 {
453                         MethodBuilder mb = genClass.DefineMethod (
454                                 genMethodName (), 0, typeof (void),
455                                 new Type [1] { typeof (int) });
456
457                         try {
458                                 mb.GetCustomAttributes (true);
459                                 Assert.Fail ("#1");
460                         } catch (NotSupportedException) {
461                         }
462
463                         try {
464                                 mb.GetCustomAttributes (null, true);
465                                 Assert.Fail ("#2");
466                         } catch (NotSupportedException) {
467                         }
468                 }
469
470                 [Test]
471                 [Category ("NotWorking")]
472                 public void TestGetCustomAttributes_Complete ()
473                 {
474                         MethodBuilder mb = genClass.DefineMethod (
475                                 genMethodName (), 0, typeof (void),
476                                 new Type [1] { typeof (int) });
477                         mb.GetILGenerator ().Emit (OpCodes.Ret);
478                         genClass.CreateType ();
479
480                         try {
481                                 mb.GetCustomAttributes (true);
482                                 Assert.Fail ("#1");
483                         } catch (NotSupportedException) {
484                         }
485
486                         try {
487                                 mb.GetCustomAttributes (null, true);
488                                 Assert.Fail ("#2");
489                         } catch (NotSupportedException) {
490                         }
491                 }
492
493                 [Test]
494                 public void TestSetCustomAttribute ()
495                 {
496                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
497                         string name = genMethodName ();
498                         MethodBuilder mb = tb.DefineMethod (
499                                 name, MethodAttributes.Public, typeof (void),
500                                 new Type [1] { typeof (int) });
501
502                         // Null argument
503                         try {
504                                 mb.SetCustomAttribute (null);
505                                 Assert.Fail ("#1");
506                         } catch (ArgumentNullException) {
507                         }
508
509                         byte [] custAttrData = { 1, 0, 0, 0, 0 };
510                         Type attrType = Type.GetType
511                                 ("System.Reflection.AssemblyKeyNameAttribute");
512                         Type [] paramTypes = new Type [1];
513                         paramTypes [0] = typeof (String);
514                         ConstructorInfo ctorInfo =
515                                 attrType.GetConstructor (paramTypes);
516
517                         mb.SetCustomAttribute (ctorInfo, custAttrData);
518
519                         // Test MethodImplAttribute
520                         mb.SetCustomAttribute (new CustomAttributeBuilder (typeof (MethodImplAttribute).GetConstructor (new Type [1] { typeof (short) }), new object [1] { (short) MethodImplAttributes.Synchronized }));
521                         mb.GetILGenerator ().Emit (OpCodes.Ret);
522
523                         Type t = tb.CreateType ();
524
525                         Assert.AreEqual (t.GetMethod (name).GetMethodImplementationFlags (),
526                                 MethodImplAttributes.Synchronized, "#2");
527
528                         // Null arguments again
529                         try {
530                                 mb.SetCustomAttribute (null, new byte [2]);
531                                 Assert.Fail ("#3");
532                         } catch (ArgumentNullException) {
533                         }
534
535                         try {
536                                 mb.SetCustomAttribute (ctorInfo, null);
537                                 Assert.Fail ("#4");
538                         } catch (ArgumentNullException) {
539                         }
540                 }
541
542                 [Test]
543                 public void SetCustomAttribute_DllImport_DllName_Empty ()
544                 {
545                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
546                         MethodBuilder mb = tb.DefineMethod (genMethodName (),
547                                 MethodAttributes.Public, typeof (void),
548                                 new Type [1] { typeof (int) });
549
550                         ConstructorInfo ctorInfo = typeof (DllImportAttribute).GetConstructor (
551                                 new Type [] { typeof (string) });
552                         try {
553                                 mb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo,
554                                         new object [] { string.Empty }));
555                                 Assert.Fail ("#1");
556                         } catch (ArgumentException ex) {
557                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
558                                 Assert.IsNull (ex.InnerException, "#3");
559                                 Assert.IsNotNull (ex.Message, "#4");
560                                 Assert.IsNull (ex.ParamName, "#5");
561                         }
562                 }
563
564                 [Test]
565                 public void SetCustomAttribute_DllImport_DllName_Null ()
566                 {
567                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
568                         MethodBuilder mb = tb.DefineMethod (genMethodName (),
569                                 MethodAttributes.Public, typeof (void),
570                                 new Type [1] { typeof (int) });
571
572                         ConstructorInfo ctorInfo = typeof (DllImportAttribute).GetConstructor (
573                                 new Type [] { typeof (string) });
574                         try {
575                                 mb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo,
576                                         new object [] { null }));
577                                 Assert.Fail ("#1");
578                         } catch (ArgumentException ex) {
579                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
580                                 Assert.IsNull (ex.InnerException, "#3");
581                                 Assert.IsNotNull (ex.Message, "#4");
582                                 Assert.IsNull (ex.ParamName, "#5");
583                         }
584                 }
585
586                 [Test]
587                 public void SetCustomAttribute_SuppressUnmanagedCodeSecurity ()
588                 {
589                         string mname = genMethodName ();
590
591                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
592                         MethodBuilder mb = tb.DefineMethod (mname, MethodAttributes.Public,
593                                 typeof (void), new Type [] { typeof (int), typeof (string) });
594                         ConstructorInfo attrCtor = typeof (SuppressUnmanagedCodeSecurityAttribute).
595                                 GetConstructor (new Type [0]);
596                         CustomAttributeBuilder caBuilder = new CustomAttributeBuilder (
597                                 attrCtor, new object [0]);
598                         Assert.IsTrue ((mb.Attributes & MethodAttributes.HasSecurity) == 0, "#1");
599                         mb.SetCustomAttribute (caBuilder);
600                         //Assert.IsTrue ((mb.Attributes & MethodAttributes.HasSecurity) == 0, "#2");
601                         mb.GetILGenerator ().Emit (OpCodes.Ret);
602                         Type emittedType = tb.CreateType ();
603                         MethodInfo emittedMethod = emittedType.GetMethod (mname);
604                         Assert.AreEqual (MethodAttributes.HasSecurity, emittedMethod.Attributes & MethodAttributes.HasSecurity, "#3");
605                         //Assert.IsTrue ((mb.Attributes & MethodAttributes.HasSecurity) == 0, "#4");
606                         object [] emittedAttrs = emittedMethod.GetCustomAttributes (typeof (SuppressUnmanagedCodeSecurityAttribute), true);
607                         Assert.AreEqual (1, emittedAttrs.Length, "#5");
608                 }
609
610                 [AttributeUsage (AttributeTargets.Parameter)]
611                 class PrivateAttribute : Attribute
612                 {
613
614                         public PrivateAttribute ()
615                         {
616                         }
617                 }
618
619                 [Test]
620                 public void GetCustomAttributes ()
621                 {
622                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
623                         MethodBuilder mb = tb.DefineMethod ("foo", MethodAttributes.Public,
624                                                                                                 typeof (void),
625                                                                                                 new Type [1] { typeof (int) });
626                         mb.GetILGenerator ().Emit (OpCodes.Ret);
627
628                         Type attrType = typeof (ObsoleteAttribute);
629                         ConstructorInfo ctorInfo =
630                                 attrType.GetConstructor (new Type [] { typeof (String) });
631
632                         mb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo, new object [] { "FOO" }));
633
634                         // Check that attributes not accessible are not returned
635                         mb.SetCustomAttribute (new CustomAttributeBuilder (typeof (PrivateAttribute).GetConstructor (new Type [0]), new object [] { }));
636
637                         Type t = tb.CreateType ();
638
639                         // Try the created type
640                         {
641                                 MethodInfo mi = t.GetMethod ("foo");
642                                 object [] attrs = mi.GetCustomAttributes (true);
643
644                                 Assert.AreEqual (1, attrs.Length, "#A1");
645                                 Assert.IsTrue (attrs [0] is ObsoleteAttribute, "#A2");
646                                 Assert.AreEqual ("FOO", ((ObsoleteAttribute) attrs [0]).Message, "#A3");
647                         }
648
649                         // Try the type builder
650                         {
651                                 MethodInfo mi = tb.GetMethod ("foo");
652                                 object [] attrs = mi.GetCustomAttributes (true);
653
654                                 Assert.AreEqual (1, attrs.Length, "#B1");
655                                 Assert.IsTrue (attrs [0] is ObsoleteAttribute, "#B2");
656                                 Assert.AreEqual ("FOO", ((ObsoleteAttribute) attrs [0]).Message, "#B3");
657                         }
658                 }
659 #if !NET_2_1
660                 [Test]
661                 [ExpectedException (typeof (InvalidOperationException))]
662                 public void TestAddDeclarativeSecurityAlreadyCreated ()
663                 {
664                         MethodBuilder mb = genClass.DefineMethod (
665                                 genMethodName (), MethodAttributes.Public, typeof (void),
666                                 new Type [0]);
667                         ILGenerator ilgen = mb.GetILGenerator ();
668                         ilgen.Emit (OpCodes.Ret);
669                         genClass.CreateType ();
670
671                         PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
672                         mb.AddDeclarativeSecurity (SecurityAction.Demand, set);
673                 }
674
675                 [Test]
676                 [ExpectedException (typeof (ArgumentNullException))]
677                 public void TestAddDeclarativeSecurityNullPermissionSet ()
678                 {
679                         MethodBuilder mb = genClass.DefineMethod (
680                                 genMethodName (), MethodAttributes.Public, typeof (void),
681                                 new Type [0]);
682                         mb.AddDeclarativeSecurity (SecurityAction.Demand, null);
683                 }
684
685                 [Test]
686                 public void TestAddDeclarativeSecurityInvalidAction ()
687                 {
688                         MethodBuilder mb = genClass.DefineMethod (
689                                 genMethodName (), MethodAttributes.Public, typeof (void),
690                                 new Type [0]);
691
692                         SecurityAction [] actions = new SecurityAction [] { 
693                         SecurityAction.RequestMinimum,
694                         SecurityAction.RequestOptional,
695                         SecurityAction.RequestRefuse };
696                         PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
697
698                         foreach (SecurityAction action in actions) {
699                                 try {
700                                         mb.AddDeclarativeSecurity (action, set);
701                                         Assert.Fail ();
702                                 } catch (ArgumentOutOfRangeException) {
703                                 }
704                         }
705                 }
706
707                 [Test]
708                 [ExpectedException (typeof (InvalidOperationException))]
709                 public void TestAddDeclarativeSecurityDuplicateAction ()
710                 {
711                         MethodBuilder mb = genClass.DefineMethod (
712                                 genMethodName (), MethodAttributes.Public, typeof (void),
713                                 new Type [0]);
714                         PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
715                         mb.AddDeclarativeSecurity (SecurityAction.Demand, set);
716                         mb.AddDeclarativeSecurity (SecurityAction.Demand, set);
717                 }
718 #endif
719                 [AttributeUsage (AttributeTargets.Parameter)]
720                 class ParamAttribute : Attribute
721                 {
722
723                         public ParamAttribute ()
724                         {
725                         }
726                 }
727
728                 [Test]
729                 public void TestDynamicParams ()
730                 {
731                         string mname = genMethodName ();
732
733                         MethodBuilder mb = genClass.DefineMethod (
734                                 mname, MethodAttributes.Public, typeof (void),
735                                 new Type [] { typeof (int), typeof (string) });
736                         ParameterBuilder pb = mb.DefineParameter (1, ParameterAttributes.In, "foo");
737                         pb.SetConstant (52);
738                         pb.SetCustomAttribute (new CustomAttributeBuilder (typeof (ParamAttribute).GetConstructors () [0], new object [] { }));
739                         ParameterBuilder pb2 = mb.DefineParameter (2, 0, "bar");
740                         pb2.SetConstant ("foo");
741                         mb.GetILGenerator ().Emit (OpCodes.Ret);
742
743                         Type t = genClass.CreateType ();
744                         MethodInfo m = t.GetMethod (mname);
745                         ParameterInfo [] pi = m.GetParameters ();
746
747                         Assert.AreEqual ("foo", pi [0].Name, "#A1");
748                         Assert.IsTrue (pi [0].IsIn, "#A2");
749                         Assert.AreEqual (52, pi [0].DefaultValue, "#A3");
750                         object [] cattrs = pi [0].GetCustomAttributes (true);
751                         Assert.AreEqual (1, cattrs.Length, "#A4");
752                         Assert.AreEqual (typeof (InAttribute), cattrs [0].GetType (), "#A5");
753
754                         cattrs = pi [1].GetCustomAttributes (true);
755                         Assert.AreEqual ("foo", pi [1].DefaultValue, "#B1");
756                 }
757
758                 [Test]
759                 public void SetCustomAttribute_DllImport1 ()
760                 {
761                         string mname = genMethodName ();
762
763                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
764                         MethodBuilder mb = tb.DefineMethod (
765                                 mname, MethodAttributes.Public, typeof (void), 
766                                 new Type [] { typeof (int), typeof (string) });
767
768                         // Create an attribute with default values
769                         mb.SetCustomAttribute (new CustomAttributeBuilder(typeof(DllImportAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { "kernel32" }));
770
771                         Type t = tb.CreateType ();
772
773                         DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
774
775                         Assert.AreEqual (CallingConvention.Winapi, attr.CallingConvention, "#1");
776                         Assert.AreEqual (mname, attr.EntryPoint, "#2");
777                         Assert.AreEqual ("kernel32", attr.Value, "#3");
778                         Assert.IsFalse (attr.ExactSpelling, "#4");
779                         Assert.IsTrue (attr.PreserveSig, "#5");
780                         Assert.IsFalse (attr.SetLastError, "#6");
781                         Assert.IsFalse (attr.BestFitMapping, "#7");
782                         Assert.IsFalse (attr.ThrowOnUnmappableChar, "#8");
783                 }
784
785                 [Test]
786                 public void SetCustomAttribute_DllImport2 () {
787                         string mname = genMethodName ();
788
789                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
790                         MethodBuilder mb = tb.DefineMethod (
791                                 mname, MethodAttributes.Public, typeof (void), 
792                                 new Type [] { typeof (int), typeof (string) });
793
794                         CustomAttributeBuilder cb = new CustomAttributeBuilder (typeof (DllImportAttribute).GetConstructor (new Type [] {typeof (String)}), new object [] { "foo" }, new FieldInfo [] {typeof (DllImportAttribute).GetField ("EntryPoint"), typeof (DllImportAttribute).GetField ("CallingConvention"), typeof (DllImportAttribute).GetField ("CharSet"), typeof (DllImportAttribute).GetField ("ExactSpelling"), typeof (DllImportAttribute).GetField ("PreserveSig")}, new object [] { "bar", CallingConvention.StdCall, CharSet.Unicode, true, false });
795                         mb.SetCustomAttribute (cb);
796
797                         Type t = tb.CreateType ();
798
799                         DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
800
801                         Assert.AreEqual (CallingConvention.StdCall, attr.CallingConvention, "#1");
802                         Assert.AreEqual (CharSet.Unicode, attr.CharSet, "#2");
803                         Assert.AreEqual ("bar", attr.EntryPoint, "#3");
804                         Assert.AreEqual ("foo", attr.Value, "#4");
805                         Assert.IsTrue (attr.ExactSpelling, "#5");
806                         Assert.IsFalse (attr.PreserveSig, "#6");
807                         Assert.IsFalse (attr.SetLastError, "#7");
808                         Assert.IsFalse (attr.BestFitMapping, "#8");
809                         Assert.IsFalse (attr.ThrowOnUnmappableChar, "#9");
810                 }
811
812                 [Test]
813                 public void SetCustomAttribute_DllImport3 () {
814                         string mname = genMethodName ();
815
816                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
817                         MethodBuilder mb = tb.DefineMethod (
818                                 mname, MethodAttributes.Public, typeof (void), 
819                                 new Type [] { typeof (int), typeof (string) });
820
821                         // Test attributes with three values (on/off/missing)
822                         CustomAttributeBuilder cb = new CustomAttributeBuilder (typeof (DllImportAttribute).GetConstructor (new Type [] {typeof (String)}), new object [] { "foo" }, new FieldInfo [] { typeof (DllImportAttribute).GetField ("BestFitMapping"), typeof (DllImportAttribute).GetField ("ThrowOnUnmappableChar")}, new object [] { false, false });
823                         mb.SetCustomAttribute (cb);
824
825                         Type t = tb.CreateType ();
826
827                         DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
828
829                         Assert.IsFalse (attr.BestFitMapping, "#1");
830                         Assert.IsFalse (attr.ThrowOnUnmappableChar, "#2");
831                 }
832
833                 [Test]
834                 public void SetCustomAttribute_DllImport4 ()
835                 {
836                         string mname = genMethodName ();
837
838                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
839                         MethodBuilder mb = tb.DefineMethod (
840                                 mname, MethodAttributes.Public, typeof (void), 
841                                 new Type [] { typeof (int), typeof (string) });
842
843                         CustomAttributeBuilder cb = new CustomAttributeBuilder (typeof (DllImportAttribute).GetConstructor (new Type [] {typeof (String)}), new object [] { "foo" }, new FieldInfo [] { typeof (DllImportAttribute).GetField ("SetLastError"), typeof (DllImportAttribute).GetField ("BestFitMapping"), typeof (DllImportAttribute).GetField ("ThrowOnUnmappableChar")}, new object [] { true, true, true });
844                         mb.SetCustomAttribute (cb);
845
846                         Type t = tb.CreateType ();
847
848                         DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
849
850                         Assert.IsTrue (attr.SetLastError, "#1");
851                         Assert.IsTrue (attr.BestFitMapping, "#2");
852                         Assert.IsTrue (attr.ThrowOnUnmappableChar, "#3");
853                 }
854
855                 public class GenericFoo <T> {
856                         public static T field;
857                 }
858
859                 [Test]
860                 public void ILGen_GenericTypeParameterBuilder ()
861                 {
862                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
863                         MethodBuilder mb = tb.DefineMethod ("box_int", 
864                                                                                                 MethodAttributes.Public|MethodAttributes.Static, typeof (object), new Type [] { typeof (int) });
865
866                         GenericTypeParameterBuilder[] pars = mb.DefineGenericParameters (new string [] { "foo" });
867
868                         ILGenerator ilgen = mb.GetILGenerator ();
869                         ilgen.Emit (OpCodes.Ldarg_0);
870                         ilgen.Emit (OpCodes.Box, pars [0]);
871                         ilgen.Emit (OpCodes.Ret);
872
873                         Type t = tb.CreateType ();
874                         MethodInfo mi = t.GetMethod ("box_int");
875                         MethodInfo mi2 = mi.MakeGenericMethod (new Type [] { typeof (int) });
876                         Assert.AreEqual (1, mi2.Invoke (null, new object [] { 1 }));
877                 }
878
879                 public void ILGen_InstantiatedGenericType ()
880                 {
881                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
882                         MethodBuilder mb = tb.DefineMethod ("return_type", 
883                                                                                                 MethodAttributes.Public|MethodAttributes.Static, typeof (object), new Type [] { });
884
885                         GenericTypeParameterBuilder[] pars = mb.DefineGenericParameters (new string [] { "foo" });
886
887                         ILGenerator ilgen = mb.GetILGenerator ();
888
889                         Type genericFoo = typeof (GenericFoo<int>).GetGenericTypeDefinition ().MakeGenericType (new Type [] { pars [0] });
890
891                         ilgen.Emit (OpCodes.Ldtoken, genericFoo);
892                         ilgen.Emit (OpCodes.Call, typeof (Type).GetMethod ("GetTypeFromHandle"));
893                         ilgen.Emit (OpCodes.Ret);
894
895                         Type t = tb.CreateType ();
896                         MethodInfo mi = t.GetMethod ("box_int");
897                         MethodInfo mi2 = mi.MakeGenericMethod (new Type [] { typeof (int) });
898                         Assert.AreEqual (typeof (GenericFoo<int>), mi2.Invoke (null, new object [] { 1 }));
899                 }
900
901                 public void ILGen_InstantiatedTypeBuilder ()
902                 {
903                         TypeBuilder genericTb = module.DefineType (genTypeName (), TypeAttributes.Public);
904                         genericTb.DefineGenericParameters (new string [] { "foo" });
905                         Type generatedGenericType = genericTb.CreateType ();
906
907                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
908                         MethodBuilder mb = tb.DefineMethod ("return_type", 
909                                                                                                 MethodAttributes.Public|MethodAttributes.Static, typeof (object), new Type [] { });
910
911                         GenericTypeParameterBuilder[] pars = mb.DefineGenericParameters (new string [] { "foo" });
912
913                         ILGenerator ilgen = mb.GetILGenerator ();
914
915                         ilgen.Emit (OpCodes.Ldtoken, genericTb.MakeGenericType (new Type [] { pars [0] }));
916                         ilgen.Emit (OpCodes.Call, typeof (Type).GetMethod ("GetTypeFromHandle"));
917                         ilgen.Emit (OpCodes.Ret);
918
919                         Type t = tb.CreateType ();
920                         MethodInfo mi = t.GetMethod ("return_type");
921                         MethodInfo mi2 = mi.MakeGenericMethod (new Type [] { typeof (int) });
922                         Assert.AreEqual (generatedGenericType.MakeGenericType (new Type [] { typeof (int) }), mi2.Invoke (null, new object [] { 1 }));
923                 }
924
925                 [Test]
926                 public void Bug354757 ()
927                 {
928                         TypeBuilder gtb = module.DefineType (genTypeName (), TypeAttributes.Public);
929                         gtb.DefineGenericParameters ("T");
930                         MethodBuilder mb = gtb.DefineMethod ("foo", MethodAttributes.Public);
931                         mb.DefineGenericParameters ("S");
932                         Assert.IsTrue (mb.IsGenericMethodDefinition);
933
934                         Type gt = gtb.MakeGenericType (typeof (object));
935                         MethodInfo m = TypeBuilder.GetMethod (gt, mb);
936                         Assert.IsTrue (m.IsGenericMethodDefinition);
937
938                         MethodInfo mopen = m.MakeGenericMethod (m.GetGenericArguments ());
939                         Assert.IsFalse (mopen.IsGenericMethodDefinition);
940                 }
941
942                 [Test]
943                 public void DefineGenericParameters_Names_Empty ()
944                 {
945                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
946                         MethodBuilder mb = tb.DefineMethod ("foo", MethodAttributes.Public);
947
948                         try {
949                                 mb.DefineGenericParameters (new string [0]);
950                                 Assert.Fail ("#1");
951                         } catch (ArgumentException ex) {
952                                 // Value does not fall within the expected range
953                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
954                                 Assert.IsNull (ex.InnerException, "#3");
955                                 Assert.IsNotNull (ex.Message, "#4");
956                                 Assert.IsNull (ex.ParamName, "#5");
957                         }
958                 }
959
960
961
962                 [Test]
963                 public void DefineGenericParameters_Names_Null ()
964                 {
965                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
966                         MethodBuilder mb = tb.DefineMethod ("foo", MethodAttributes.Public);
967
968                         try {
969                                 mb.DefineGenericParameters ((string []) null);
970                                 Assert.Fail ("#A1");
971                         } catch (ArgumentNullException ex) {
972                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#A2");
973                                 Assert.IsNull (ex.InnerException, "#A3");
974                                 Assert.IsNotNull (ex.Message, "#A4");
975                                 Assert.AreEqual ("names", ex.ParamName, "#A5");
976                         }
977
978                         try {
979                                 mb.DefineGenericParameters ("K", null, "V");
980                                 Assert.Fail ("#B1");
981                         } catch (ArgumentNullException ex) {
982                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#B2");
983                                 Assert.IsNull (ex.InnerException, "#B3");
984                                 Assert.IsNotNull (ex.Message, "#B4");
985                                 Assert.AreEqual ("names", ex.ParamName, "#B5");
986                         }
987                 }
988
989
990                 public static int Foo<T> (T a, T b) {
991                         return 99;
992                 }
993
994                 [Test]//bug #591226
995                 public void GenericMethodIsProperlyInflated ()
996                 {
997                         var tb = module.DefineType ("foo");
998                         var met = typeof (MethodBuilderTest).GetMethod ("Foo");
999
1000                         var mb = tb.DefineMethod ("myFunc", MethodAttributes.Public | MethodAttributes.Static, typeof (int), Type.EmptyTypes);
1001                         var garg = mb.DefineGenericParameters ("a") [0];
1002                         mb.SetParameters (garg, garg);
1003
1004                         var ilgen = mb.GetILGenerator ();
1005                         ilgen.Emit (OpCodes.Ldarg_0);
1006                         ilgen.Emit (OpCodes.Ldarg_1);
1007                         ilgen.Emit (OpCodes.Call, met.MakeGenericMethod (garg));
1008                         ilgen.Emit (OpCodes.Ret);
1009
1010                         var res = tb.CreateType ();
1011                         var mm = res.GetMethod ("myFunc").MakeGenericMethod (typeof (int));
1012
1013                         var rt = mm.Invoke (null, new object[] { 10, 20 });
1014                         Assert.AreEqual (99, rt, "#1");
1015                 }
1016
1017             public static void VarargMethod (string headline, __arglist) {
1018                 ArgIterator ai = new ArgIterator (__arglist);
1019         
1020                 Console.Write (headline);
1021                 while (ai.GetRemainingCount () > 0)
1022                     Console.Write (TypedReference.ToObject (ai.GetNextArg ()));
1023                 Console.WriteLine ();
1024             }
1025
1026                 [Test]//bug #626441
1027                 public void CanCallVarargMethods ()
1028                 {
1029                         var tb = module.DefineType ("foo");
1030                         MethodBuilder mb = tb.DefineMethod ("CallVarargMethod", 
1031                                 MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,
1032                                 typeof (void), Type.EmptyTypes);
1033
1034                         ILGenerator il = mb.GetILGenerator ();
1035                         MethodInfo miVarargMethod = typeof (MethodBuilderTest).GetMethod ("VarargMethod");
1036                         
1037                         il.Emit (OpCodes.Ldstr, "Hello world from ");
1038                         il.Emit (OpCodes.Call, typeof(Assembly).GetMethod ("GetExecutingAssembly"));
1039                         il.EmitCall (OpCodes.Call, miVarargMethod, new Type[] { typeof(Assembly) });
1040                         
1041                         il.Emit (OpCodes.Ldstr, "Current time: ");
1042                         il.Emit (OpCodes.Call, typeof(DateTime).GetMethod("get_Now"));
1043                         il.Emit (OpCodes.Ldstr, " (UTC ");
1044                         il.Emit (OpCodes.Call, typeof(DateTime).GetMethod("get_UtcNow"));
1045                         il.Emit (OpCodes.Ldstr, ")");
1046                         il.EmitCall (OpCodes.Call, miVarargMethod, new Type[] { typeof (DateTime), typeof (string), typeof (DateTime), typeof (string) });
1047                         il.Emit (OpCodes.Ret);
1048
1049                         Type type = tb.CreateType ();
1050                         type.GetMethod ("CallVarargMethod").Invoke (null, null);
1051                 }
1052
1053                 public static string GenericMethodWithOneArg<T> (T t)
1054                 {
1055                         return t.ToString ();
1056                 }
1057
1058                 [Test]
1059                 public void ParamerersOfGenericArgumentsAreProperlyEncoded ()
1060                 {
1061                         var type = module.DefineType (
1062                                 "Bar",
1063                                 TypeAttributes.Public
1064                                 | TypeAttributes.Abstract
1065                                 | TypeAttributes.Sealed,
1066                                 typeof (object));
1067
1068                         var foo_method = typeof (MethodBuilderTest).GetMethod ("GenericMethodWithOneArg");
1069
1070                         var method = type.DefineMethod (
1071                                 "ReFoo",
1072                                 MethodAttributes.Static | MethodAttributes.Public,
1073                                 typeof (string),
1074                                 new [] { foo_method.GetGenericArguments () [0] });
1075                         method.DefineGenericParameters ("K");
1076
1077                         var il = method.GetILGenerator ();
1078                         il.Emit (OpCodes.Ldarga, 0);
1079                         il.Emit (OpCodes.Constrained, method.GetGenericArguments () [0]);
1080                         il.Emit (OpCodes.Callvirt, typeof (object).GetMethod ("ToString"));
1081                         il.Emit (OpCodes.Ret);
1082
1083                         type.CreateType ();
1084
1085                         var re_foo_open = module.GetType ("Bar").GetMethod ("ReFoo");
1086
1087                         Assert.AreEqual (re_foo_open.GetGenericArguments ()[0], re_foo_open.GetParameters () [0].ParameterType, "#1");
1088                 }
1089
1090                 [Test] // #628660
1091                 public void CanCallGetMethodBodyOnDynamicImageMethod ()
1092                 {
1093                         var type = module.DefineType (
1094                                 "CanCallGetMethodBodyOnDynamicImageMethod",
1095                                 TypeAttributes.Public,
1096                                 typeof (object));
1097
1098                         var baz = type.DefineMethod ("Foo", MethodAttributes.Public | MethodAttributes.Static, typeof (object), Type.EmptyTypes);
1099
1100                         var il = baz.GetILGenerator ();
1101                         var temp = il.DeclareLocal (typeof (object));
1102                         il.Emit (OpCodes.Ldnull);
1103                         il.Emit (OpCodes.Stloc, temp);
1104                         il.Emit (OpCodes.Ldloc, temp);
1105                         il.Emit (OpCodes.Ret);
1106
1107                         var body = type.CreateType ().GetMethod ("Foo").GetMethodBody ();
1108
1109                         Assert.IsNotNull (body);
1110                         Assert.AreEqual (1, body.LocalVariables.Count);
1111                         Assert.AreEqual (typeof (object), body.LocalVariables [0].LocalType);
1112                 }
1113
1114
1115                 [Test] //#384127
1116                 public void GetGenericArgumentsReturnsNullForNonGenericMethod ()
1117                 {
1118                         var tb = module.DefineType ("Base");
1119         
1120                         var mb = tb.DefineMethod ("foo", MethodAttributes.Public, typeof (void), Type.EmptyTypes);
1121         
1122                         Assert.IsNull (mb.GetGenericArguments ());
1123
1124                 }
1125
1126                 [Test]
1127                 [ExpectedException (typeof (ArgumentException))]
1128                 public void SetConstantIllegalType ()
1129                 {
1130                         var tb = module.DefineType ("Base");
1131         
1132                         var mb = tb.DefineMethod ("foo", MethodAttributes.Public, typeof (void), new Type [] { typeof (decimal) });
1133                         ParameterBuilder pb = mb.DefineParameter (1, ParameterAttributes.In, "foo");
1134                         pb.SetConstant (5m);
1135                 }
1136
1137                 public interface ITest
1138                 {
1139                         T[] Method<T>(T[] value);
1140                 }
1141
1142                 [Test]
1143                 // #7964
1144                 public void ArrayOfGenericParam ()
1145                 {
1146                         var tb = module.DefineType ("Base");
1147
1148             tb.AddInterfaceImplementation (typeof (ITest));
1149
1150             var testMethod = tb.DefineMethod ("Method", MethodAttributes.Public | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis);
1151
1152             var testParameters = Array.ConvertAll (testMethod.DefineGenericParameters("T"), b => (Type)b);
1153
1154             var returnType = testParameters[0].MakeArrayType();
1155
1156             testMethod.SetParameters (testParameters[0].MakeArrayType());
1157             testMethod.SetReturnType (returnType);
1158
1159             var testIl = testMethod.GetILGenerator ();
1160                         testIl.Emit (OpCodes.Ldarg_1);
1161                         testIl.Emit (OpCodes.Castclass, returnType);
1162                         testIl.Emit (OpCodes.Ret);
1163
1164             var t = tb.CreateType ();
1165
1166             var test = (ITest) Activator.CreateInstance (t);
1167
1168                         var o = new int[0];
1169             var returnValue = test.Method (o);
1170
1171                         Assert.AreEqual (o, returnValue);
1172                 }
1173         }
1174 }