Merge pull request #5313 from lambdageek/corefx-sre-fixup
[mono.git] / mcs / class / corlib / System.Reflection.Emit / ConstructorBuilder.cs
1 //
2 // System.Reflection.Emit.ConstructorBuilder.cs
3 //
4 // Author:
5 //   Paolo Molaro (lupus@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.  http://www.ximian.com
8 //
9
10 //
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 #if !FULL_AOT_RUNTIME
34 using System;
35 using System.Collections.Generic;
36 using System.Reflection;
37 using System.Reflection.Emit;
38 using System.Globalization;
39 using System.Security;
40 using System.Security.Permissions;
41 using System.Runtime.InteropServices;
42 using System.Diagnostics.SymbolStore;
43
44 namespace System.Reflection.Emit {
45
46         [ComVisible (true)]
47         [ComDefaultInterface (typeof (_ConstructorBuilder))]
48         [ClassInterface (ClassInterfaceType.None)]
49         [StructLayout (LayoutKind.Sequential)]
50         public sealed class ConstructorBuilder : ConstructorInfo, _ConstructorBuilder {
51         
52 #pragma warning disable 169, 414
53                 private RuntimeMethodHandle mhandle;
54                 private ILGenerator ilgen;
55                 internal Type[] parameters;
56                 private MethodAttributes attrs;
57                 private MethodImplAttributes iattrs;
58                 private int table_idx;
59                 private CallingConventions call_conv;
60                 private TypeBuilder type;
61                 internal ParameterBuilder[] pinfo;
62                 private CustomAttributeBuilder[] cattrs;
63                 private bool init_locals = true;
64                 private Type[][] paramModReq;
65                 private Type[][] paramModOpt;
66                 private RefEmitPermissionSet[] permissions;
67 #pragma warning restore 169, 414
68
69                 internal ConstructorBuilder (TypeBuilder tb, MethodAttributes attributes, CallingConventions callingConvention, Type[] parameterTypes, Type[][] paramModReq, Type[][] paramModOpt)
70                 {
71                         attrs = attributes | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
72                         call_conv = callingConvention;
73                         if (parameterTypes != null) {
74                                 for (int i = 0; i < parameterTypes.Length; ++i)
75                                         if (parameterTypes [i] == null)
76                                                 throw new ArgumentException ("Elements of the parameterTypes array cannot be null", "parameterTypes");
77
78                                 this.parameters = new Type [parameterTypes.Length];
79                                 System.Array.Copy (parameterTypes, this.parameters, parameterTypes.Length);
80                         }
81                         type = tb;
82                         this.paramModReq = paramModReq;
83                         this.paramModOpt = paramModOpt;
84                         table_idx = get_next_table_index (this, 0x06, true);
85
86                         ((ModuleBuilder) tb.Module).RegisterToken (this, GetToken ().Token);
87                 }
88
89                 [MonoTODO]
90                 public override CallingConventions CallingConvention {
91                         get {
92                                 return call_conv;
93                         }
94                 }
95
96                 public bool InitLocals {
97                         get {
98                                 return init_locals;
99                         }
100                         set {
101                                 init_locals = value;
102                         }
103                 }
104
105                 internal TypeBuilder TypeBuilder {
106                         get {
107                                 return type;
108                         }
109                 }
110                 
111                 public override MethodImplAttributes GetMethodImplementationFlags ()
112                 {
113                         return iattrs;
114                 }
115
116                 public override ParameterInfo[] GetParameters ()
117                 {
118                         if (!type.is_created)
119                                 throw not_created ();
120
121                         return GetParametersInternal ();
122                 }
123
124                 internal override ParameterInfo [] GetParametersInternal ()
125                 {
126                         if (parameters == null)
127                                 return EmptyArray<ParameterInfo>.Value;
128
129                         ParameterInfo [] retval = new ParameterInfo [parameters.Length];
130                         for (int i = 0; i < parameters.Length; i++)
131                                 retval [i] = ParameterInfo.New (pinfo == null ? null
132                                         : pinfo [i + 1], parameters [i], this, i + 1);
133
134                         return retval;
135                 }
136                 
137                 internal override int GetParametersCount ()
138                 {
139                         if (parameters == null)
140                                 return 0;
141                         
142                         return parameters.Length;
143                 }
144
145                 internal override Type GetParameterType (int pos) {
146                         return parameters [pos];
147                 }
148
149                 internal MethodBase RuntimeResolve () {
150                         return type.RuntimeResolve ().GetConstructor (this);
151                 }
152
153                 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
154                 {
155                         throw not_supported ();
156                 }
157
158                 public override object Invoke (BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
159                 {
160                         throw not_supported ();
161                 }
162
163                 public override RuntimeMethodHandle MethodHandle {
164                         get {
165                                 throw not_supported ();
166                         }
167                 }
168
169                 public override MethodAttributes Attributes {
170                         get {
171                                 return attrs;
172                         }
173                 }
174
175                 public override Type ReflectedType {
176                         get {
177                                 return type;
178                         }
179                 }
180
181                 public override Type DeclaringType {
182                         get {
183                                 return type;
184                         }
185                 }
186
187                 [Obsolete]
188                 public Type ReturnType {
189                         get {
190                                 return null;
191                         }
192                 }
193
194                 public override string Name {
195                         get {
196                                 return (attrs & MethodAttributes.Static) != 0 ? ConstructorInfo.TypeConstructorName : ConstructorInfo.ConstructorName;
197                         }
198                 }
199
200                 public string Signature {
201                         get {
202                                 return "constructor signature";
203                         }
204                 }
205
206                 public void AddDeclarativeSecurity (SecurityAction action, PermissionSet pset)
207                 {
208 #if !MOBILE
209                         if (pset == null)
210                                 throw new ArgumentNullException ("pset");
211                         if ((action == SecurityAction.RequestMinimum) ||
212                                 (action == SecurityAction.RequestOptional) ||
213                                 (action == SecurityAction.RequestRefuse))
214                                 throw new ArgumentOutOfRangeException ("action", "Request* values are not permitted");
215
216                         RejectIfCreated ();
217
218                         if (permissions != null) {
219                                 /* Check duplicate actions */
220                                 foreach (RefEmitPermissionSet set in permissions)
221                                         if (set.action == action)
222                                                 throw new InvalidOperationException ("Multiple permission sets specified with the same SecurityAction.");
223
224                                 RefEmitPermissionSet[] new_array = new RefEmitPermissionSet [permissions.Length + 1];
225                                 permissions.CopyTo (new_array, 0);
226                                 permissions = new_array;
227                         }
228                         else
229                                 permissions = new RefEmitPermissionSet [1];
230
231                         permissions [permissions.Length - 1] = new RefEmitPermissionSet (action, pset.ToXml ().ToString ());
232                         attrs |= MethodAttributes.HasSecurity;
233 #endif
234                 }
235
236                 public ParameterBuilder DefineParameter (int iSequence, ParameterAttributes attributes, string strParamName)
237                 {
238                         // The 0th ParameterBuilder does not correspond to an
239                         // actual parameter, but .NETFramework lets you define
240                         // it anyway. It is not useful.
241                         if (iSequence < 0 || iSequence > GetParametersCount ())
242                                 throw new ArgumentOutOfRangeException ("iSequence");
243                         if (type.is_created)
244                                 throw not_after_created ();
245
246                         ParameterBuilder pb = new ParameterBuilder (this, iSequence, attributes, strParamName);
247                         if (pinfo == null)
248                                 pinfo = new ParameterBuilder [parameters.Length + 1];
249                         pinfo [iSequence] = pb;
250                         return pb;
251                 }
252
253                 public override bool IsDefined (Type attributeType, bool inherit)
254                 {
255                         throw not_supported ();
256                 }
257
258                 public override object [] GetCustomAttributes (bool inherit)
259                 {
260                         throw not_supported ();
261                 }
262
263                 public override object [] GetCustomAttributes (Type attributeType, bool inherit)
264                 {
265                         throw not_supported ();
266                 }
267
268                 public ILGenerator GetILGenerator ()
269                 {
270                         return GetILGenerator (64);
271                 }
272
273                 public ILGenerator GetILGenerator (int streamSize)
274                 {
275                         if (ilgen != null)
276                                 return ilgen;
277                         ilgen = new ILGenerator (type.Module, ((ModuleBuilder)type.Module).GetTokenGenerator (), streamSize);
278                         return ilgen;
279                 }
280
281                 public void SetMethodBody (byte[] il, int maxStack, byte[] localSignature,
282                         IEnumerable<ExceptionHandler> exceptionHandlers, IEnumerable<int> tokenFixups)
283                 {
284                         var ilgen = GetILGenerator ();
285                         ilgen.Init (il, maxStack, localSignature, exceptionHandlers, tokenFixups);
286                 }
287
288
289                 public void SetCustomAttribute (CustomAttributeBuilder customBuilder)
290                 {
291                         if (customBuilder == null)
292                                 throw new ArgumentNullException ("customBuilder");
293
294                         string attrname = customBuilder.Ctor.ReflectedType.FullName;
295                         if (attrname == "System.Runtime.CompilerServices.MethodImplAttribute") {
296                                 byte[] data = customBuilder.Data;
297                                 int impla; // the (stupid) ctor takes a short or an int ... 
298                                 impla = (int)data [2];
299                                 impla |= ((int)data [3]) << 8;
300                                 SetImplementationFlags ((MethodImplAttributes)impla);
301                                 return;
302                         }
303                         if (cattrs != null) {
304                                 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
305                                 cattrs.CopyTo (new_array, 0);
306                                 new_array [cattrs.Length] = customBuilder;
307                                 cattrs = new_array;
308                         } else {
309                                 cattrs = new CustomAttributeBuilder [1];
310                                 cattrs [0] = customBuilder;
311                         }
312                 }
313
314                 [ComVisible (true)]
315                 public void SetCustomAttribute (ConstructorInfo con, byte[] binaryAttribute)
316                 {
317                         if (con == null)
318                                 throw new ArgumentNullException ("con");
319                         if (binaryAttribute == null)
320                                 throw new ArgumentNullException ("binaryAttribute");
321
322                         SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
323                 }
324
325                 public void SetImplementationFlags (MethodImplAttributes attributes)
326                 {
327                         if (type.is_created)
328                                 throw not_after_created ();
329
330                         iattrs = attributes;
331                 }
332
333                 public Module GetModule ()
334                 {
335                         return type.Module;
336                 }
337
338                 public MethodToken GetToken ()
339                 {
340                         return new MethodToken (0x06000000 | table_idx);
341                 }
342
343                 [MonoTODO]
344                 public void SetSymCustomAttribute (string name, byte[] data)
345                 {
346                         if (type.is_created)
347                                 throw not_after_created ();
348                 }
349
350                 public override Module Module {
351                         get {
352                                 return GetModule ();
353                         }
354                 }
355
356                 public override string ToString ()
357                 {
358                         return "ConstructorBuilder ['" + type.Name + "']";
359                 }
360
361                 internal void fixup ()
362                 {
363                         if (((attrs & (MethodAttributes.Abstract | MethodAttributes.PinvokeImpl)) == 0) && ((iattrs & (MethodImplAttributes.Runtime | MethodImplAttributes.InternalCall)) == 0)) {
364                         if ((ilgen == null) || (ilgen.ILOffset == 0))
365                                 throw new InvalidOperationException ("Method '" + Name + "' does not have a method body.");
366                         }
367                         if (ilgen != null)
368                                 ilgen.label_fixup (this);
369                 }
370
371                 internal void ResolveUserTypes () {
372                         TypeBuilder.ResolveUserTypes (parameters);
373                         if (paramModReq != null) {
374                                 foreach (var types in paramModReq)
375                                         TypeBuilder.ResolveUserTypes (types);
376                         }
377                         if (paramModOpt != null) {
378                                 foreach (var types in paramModOpt)
379                                         TypeBuilder.ResolveUserTypes (types);
380                         }
381                 }
382
383                 internal void FixupTokens (Dictionary<int, int> token_map, Dictionary<int, MemberInfo> member_map) {
384                         if (ilgen != null)
385                                 ilgen.FixupTokens (token_map, member_map);
386                 }
387                 
388                 internal void GenerateDebugInfo (ISymbolWriter symbolWriter)
389                 {
390                         if (ilgen != null && ilgen.HasDebugInfo) {
391                                 SymbolToken token = new SymbolToken (GetToken().Token);
392                                 symbolWriter.OpenMethod (token);
393                                 symbolWriter.SetSymAttribute (token, "__name", System.Text.Encoding.UTF8.GetBytes (Name));
394                                 ilgen.GenerateDebugInfo (symbolWriter);
395                                 symbolWriter.CloseMethod ();
396                         }
397                 }
398
399                 internal override int get_next_table_index (object obj, int table, bool inc)
400                 {
401                         return type.get_next_table_index (obj, table, inc);
402                 }
403
404                 private void RejectIfCreated ()
405                 {
406                         if (type.is_created)
407                                 throw new InvalidOperationException ("Type definition of the method is complete.");
408                 }
409
410                 private Exception not_supported ()
411                 {
412                         return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
413                 }
414
415                 private Exception not_after_created ()
416                 {
417                         return new InvalidOperationException ("Unable to change after type has been created.");
418                 }
419
420                 private Exception not_created ()
421                 {
422                         return new NotSupportedException ("The type is not yet created.");
423                 }
424
425                 void _ConstructorBuilder.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
426                 {
427                         throw new NotImplementedException ();
428                 }
429
430                 void _ConstructorBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
431                 {
432                         throw new NotImplementedException ();
433                 }
434
435                 void _ConstructorBuilder.GetTypeInfoCount (out uint pcTInfo)
436                 {
437                         throw new NotImplementedException ();
438                 }
439
440                 void _ConstructorBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
441                 {
442                         throw new NotImplementedException ();
443                 }
444         }
445 }
446 #endif