* DeclSecurity.cs (IDeclSecurityTarget): Remove AddPermission &
[mono.git] / mcs / ilasm / codegen / TypeDef.cs
1 //
2 // Mono.ILASM.TypeDef
3 //
4 // Author(s):
5 //  Jackson Harper (Jackson@LatitudeGeo.com)
6 //
7 // (C) 2003 Jackson Harper, All rights reserved
8 //
9
10
11 using System;
12 using System.Collections;
13 using System.Security;
14
15 namespace Mono.ILASM {
16
17         public class TypeDef : ICustomAttrTarget, IDeclSecurityTarget, IComparable {
18
19                 private PEAPI.TypeAttr attr;
20                 private string name_space;
21                 private string name;
22                 private bool is_defined;
23                 private bool is_intransit;
24                 private BaseClassRef parent;
25                 private ArrayList impl_list;
26                 private PEAPI.ClassDef classdef;
27                 private Hashtable field_table;
28                 private ArrayList field_list;
29                 private Hashtable method_table;
30                 private ArrayList customattr_list;
31                 private DeclSecurity decl_sec;
32                 private ArrayList event_list;
33                 private ArrayList property_list;
34                 private GenericParameters gen_params;
35                 private ArrayList override_list;
36                 private ArrayList override_long_list;
37                 private TypeDef outer;
38
39                 private EventDef current_event;
40                 private PropertyDef current_property;
41
42                 private int size;
43                 private int pack;
44
45                 private bool is_value_class;
46                 private bool is_enum_class;
47
48                 public TypeDef (PEAPI.TypeAttr attr, string name_space, string name,
49                                 BaseClassRef parent, ArrayList impl_list, Location location, GenericParameters gen_params, TypeDef outer)
50                 {
51                         this.attr = attr;
52                         this.parent = parent;
53                         this.impl_list = impl_list;
54                         this.gen_params = gen_params;
55                         this.outer = outer;
56
57                         field_table = new Hashtable ();
58                         field_list = new ArrayList ();
59
60                         method_table = new Hashtable ();
61
62                         size = -1;
63                         pack = -1;
64
65                         is_defined = false;
66                         is_intransit = false;
67
68                         is_value_class = false;
69                         is_enum_class = false;
70
71                         ResolveGenParams ();
72
73                         int lastdot = name.LastIndexOf ('.');
74                         /* Namespace . name split should not be done for nested classes */
75                         if (lastdot >= 0 && outer == null) {
76                                 if (name_space == null || name_space == "")
77                                         this.name_space = name.Substring (0, lastdot);
78                                 else
79                                         this.name_space = name_space + "." + name.Substring (0, lastdot);
80                                 this.name = name.Substring (lastdot + 1);
81                         } else {
82                                 this.name_space = name_space;
83                                 this.name = name;
84                         }
85                 }
86
87                 public string Name {
88                         get { return name; }
89                 }
90
91                 public string FullName {
92                         get { return MakeFullName (); }
93                 }
94
95                 public string NestedFullName {
96                         get { return (outer == null ? FullName : (outer.NestedFullName + "/" + FullName)); }
97                 }
98
99                 public TypeDef OuterType {
100                         get { return outer; }
101                 }
102
103                 public PEAPI.ClassDef PeapiType {
104                         get { return classdef; }
105                 }
106
107                 public PEAPI.ClassDef ClassDef {
108                         get { return classdef; }
109                 }
110
111                 public bool IsGenericType {
112                         get { return (gen_params == null); }
113                 }
114
115                 public bool IsDefined {
116                         get { return is_defined; }
117                 }
118
119                 public EventDef CurrentEvent {
120                         get { return current_event; }
121                 }
122
123                 public PropertyDef CurrentProperty {
124                         get { return current_property; }
125                 }
126
127                 public bool IsInterface {
128                         get { return (attr & PEAPI.TypeAttr.Interface) != 0; }
129                 }
130
131                 public GenericParameters TypeParameters {
132                         get { return gen_params; }
133                 }
134
135                 public DeclSecurity DeclSecurity {
136                         get {
137                                 if (decl_sec == null)
138                                         decl_sec = new DeclSecurity ();
139                                 return decl_sec;
140                         }
141                 }
142
143                 public void AddOverride (MethodDef body, BaseTypeRef parent, string name)
144                 {
145                         if (override_list == null)
146                                 override_list = new ArrayList ();
147                         override_list.Add (new DictionaryEntry (body,
148                                            new DictionaryEntry (parent, name)));
149                 }
150
151                 public void AddOverride (string sig, BaseMethodRef decl)
152                 {
153                         if (override_long_list == null)
154                                 override_long_list = new ArrayList ();
155                         override_long_list.Add (new DictionaryEntry (sig,
156                                                                 decl));
157                 }
158
159                 public void MakeValueClass ()
160                 {
161                         is_value_class = true;
162                 }
163
164                 public void MakeEnumClass ()
165                 {
166                         is_enum_class = true;
167                 }
168
169                 public void SetSize (int size)
170                 {
171                         this.size = size;
172                 }
173
174                 public void SetPack (int pack)
175                 {
176                         this.pack = pack;
177                 }
178
179                 public void AddFieldDef (FieldDef fielddef)
180                 {
181                         if (IsInterface && !fielddef.IsStatic) {
182                                 Console.WriteLine ("warning -- Non-static field in interface, set to such");
183                                 fielddef.Attributes |= PEAPI.FieldAttr.Static;
184                         }
185
186                         DictionaryEntry entry = new DictionaryEntry (fielddef.Name, fielddef.Type.FullName);
187                         if (field_table [entry] != null)
188                                 Report.Error ("Duplicate field declaration: " + fielddef.Type.FullName + " " + fielddef.Name);
189                         field_table.Add (entry, fielddef);
190                         field_list.Add (fielddef);
191                 }
192
193                 public void AddMethodDef (MethodDef methoddef)
194                 {
195                         if (IsInterface && !(methoddef.IsVirtual || methoddef.IsAbstract)) {
196                                 Console.WriteLine ("warning -- Non-virtual, non-abstract instance method in interface, set to such");
197                                 methoddef.Attributes |= PEAPI.MethAttr.Abstract | PEAPI.MethAttr.Virtual;
198                         }
199
200                         if (method_table [methoddef.Signature] != null)
201                                 Report.Error ("Duplicate method declaration: " + methoddef.Signature);
202
203                         method_table.Add (methoddef.Signature, methoddef);
204                 }
205
206                 public void BeginEventDef (EventDef event_def)
207                 {
208                         if (current_event != null)
209                                 Report.Error ("An event definition was not closed.");
210
211                         current_event = event_def;
212                 }
213
214                 public void EndEventDef ()
215                 {
216                         if (event_list == null)
217                                 event_list = new ArrayList ();
218
219                         event_list.Add (current_event);
220                         current_event = null;
221                 }
222
223                 public void BeginPropertyDef (PropertyDef property_def)
224                 {
225                         if (current_property != null)
226                                 Report.Error ("A property definition was not closed.");
227
228                         current_property = property_def;
229                 }
230
231                 public void EndPropertyDef ()
232                 {
233                         if (property_list == null)
234                                 property_list = new ArrayList ();
235
236                         property_list.Add (current_property);
237                         current_property = null;
238                 }
239
240                 public void AddCustomAttribute (CustomAttr customattr)
241                 {
242                         if (customattr_list == null)
243                                 customattr_list = new ArrayList ();
244
245                         customattr_list.Add (customattr);
246                 }
247
248                 public GenericParameter GetGenericParam (string id)
249                 {
250                         if (gen_params == null)
251                                 return null;
252                         
253                         return gen_params.GetGenericParam (id);
254                 }
255
256                 public GenericParameter GetGenericParam (int index)
257                 {
258                         if (gen_params == null || index < 0 || index >= gen_params.Count)
259                                 return null;
260                         
261                         return gen_params [index];
262                 }
263
264                 public int GetGenericParamNum (string id)
265                 {
266                         if (gen_params == null)
267                                 return -1;
268                         
269                         return gen_params.GetGenericParamNum (id);
270                 }
271
272                 /* Resolve any GenParams in constraints, parent & impl_list */
273                 private void ResolveGenParams ()
274                 {
275                         if (gen_params == null)
276                                 return;
277
278                         gen_params.ResolveConstraints (gen_params, null);
279
280                         BaseGenericTypeRef gtr = parent as BaseGenericTypeRef;
281                         if (gtr != null)
282                                 gtr.Resolve (gen_params, null);
283                         
284                         if (impl_list == null)
285                                 return;
286                                 
287                         foreach (BaseClassRef impl in impl_list) {
288                                 gtr = impl as BaseGenericTypeRef;
289                                 if (gtr != null)
290                                         gtr.Resolve (gen_params, null);
291                         }
292                 }
293
294                 public void Define (CodeGen code_gen)
295                 {
296                         if (is_defined)
297                                 return;
298
299                         if (is_intransit) {
300                                 // Circular definition
301                                 Report.Error ("Circular definition of class: " + FullName);
302                         }
303
304                         if (outer != null) {
305                                 PEAPI.TypeAttr vis = attr & PEAPI.TypeAttr.VisibilityMask;
306
307                                 if (vis == PEAPI.TypeAttr.Private || vis == PEAPI.TypeAttr.Public) {
308                                         /* Nested class, but attr not set accordingly. */
309                                         //FIXME: 'report' warning here
310                                         Console.WriteLine ("Warning -- Nested class '{0}' has non-nested visibility, set to such.", NestedFullName);
311                                         attr = attr ^ vis;
312                                         attr |= (vis == PEAPI.TypeAttr.Public ? PEAPI.TypeAttr.NestedPublic : PEAPI.TypeAttr.NestedPrivate);
313                                 }               
314                         }
315                         
316                         if (parent != null) {
317                                 is_intransit = true;
318                                 parent.Resolve (code_gen);
319
320                                 is_intransit = false;
321                                 if (parent.PeapiClass == null) {
322                                         Report.Error ("this type can not be a base type: "
323                                                         + parent);
324                                 }
325
326                                 if (parent.PeapiClass.nameSpace != null && 
327                                         parent.PeapiClass.nameSpace.CompareTo ("System") == 0) {
328                                         
329                                         if (parent.PeapiClass.name.CompareTo ("ValueType") == 0)
330                                                 is_value_class = true;
331                                         else
332                                         if (parent.PeapiClass.name.CompareTo ("Enum") == 0 )
333                                                 is_enum_class = true;          
334                                 } 
335
336                                 if (is_value_class && (attr & PEAPI.TypeAttr.Sealed) == 0) {
337                                         Console.WriteLine ("Warning -- Non-sealed value class, made sealed.");
338                                         attr |= PEAPI.TypeAttr.Sealed;
339                                 }
340
341                                 if (outer != null) {
342                                         if (!outer.IsDefined)
343                                                 outer.Define (code_gen);
344                                         classdef = outer.PeapiType.AddNestedClass (attr,
345                                                         name_space, name, parent.PeapiClass);
346                                 } else {
347                                         if (is_value_class || is_enum_class) {
348                                                 // Should probably confirm that the parent is System.ValueType
349                                                 classdef = code_gen.PEFile.AddValueClass (attr,
350                                                         name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
351                                         } else {
352                                                 classdef = code_gen.PEFile.AddClass (attr,
353                                                         name_space, name, parent.PeapiClass);
354                                         }
355                                 }
356                         } else {
357                                 if (outer != null) {
358                                         if (!outer.IsDefined)
359                                                 outer.Define (code_gen);
360                                         classdef = outer.PeapiType.AddNestedClass (attr,
361                                                 name_space, name);
362                                 } else {
363                                         if (is_value_class || is_enum_class) {
364                                                 classdef = code_gen.PEFile.AddValueClass (attr,
365                                                         name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
366                                         } else {
367                                                 classdef = code_gen.PEFile.AddClass (attr,
368                                                         name_space, name);
369                                         }
370                                 }
371                                 if (FullName == "System.Object")
372                                         classdef.SpecialNoSuper ();
373                         }
374
375                         is_defined = true;
376
377                         if (size != -1 || pack != -1)
378                                 classdef.AddLayoutInfo ( (pack == -1) ? 1 : pack, (size == -1) ? 0 : size);
379
380                         if (impl_list != null) {
381                                 foreach (BaseClassRef impl in impl_list) {
382                                         impl.Resolve (code_gen);
383                                         classdef.AddImplementedInterface (impl.PeapiClass);
384                                 }
385                         }
386
387                         if (gen_params != null)
388                                 gen_params.Resolve (code_gen, classdef);
389
390                         is_intransit = false;
391
392                         code_gen.AddToDefineContentsList (this);
393                 }
394
395                 public void DefineContents (CodeGen code_gen)
396                 {
397                         ArrayList fielddef_list = new ArrayList ();
398                         foreach (FieldDef fielddef in field_list) {
399                                 fielddef.Define (code_gen, classdef);
400                                 fielddef_list.Add (fielddef.PeapiFieldDef);
401                         }
402
403                         classdef.SetFieldOrder (fielddef_list);
404
405                         foreach (MethodDef methoddef in method_table.Values) {
406                                 methoddef.Define (code_gen);
407                         }
408
409                         if (event_list != null) {
410                                 foreach (EventDef eventdef in event_list) {
411                                         eventdef.Define (code_gen, classdef);
412                                 }
413                         }
414
415                         if (property_list != null) {
416                                 foreach (PropertyDef propdef in property_list) {
417                                         propdef.Define (code_gen, classdef);
418                                 }
419
420                         }
421
422                         if (customattr_list != null) {
423                                 foreach (CustomAttr customattr in customattr_list) {
424                                         customattr.AddTo (code_gen, classdef);
425                                         if (customattr.IsSuppressUnmanaged (code_gen))
426                                                 classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
427                                 }
428                         }
429                         
430                         /// Add declarative security to this class
431                         if (decl_sec != null) {
432                                 decl_sec.AddTo (code_gen, classdef);
433                                 classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
434                         }       
435
436                         if (override_list != null) {
437                                 foreach (DictionaryEntry entry in override_list) {
438                                         MethodDef body = (MethodDef) entry.Key;
439                                         DictionaryEntry decl = (DictionaryEntry) entry.Value;
440                                         BaseTypeRef parent_type = (BaseTypeRef) decl.Key;
441                                         parent_type.Resolve (code_gen);
442                                         string over_name = (string) decl.Value;
443                                         BaseMethodRef over_meth = parent_type.GetMethodRef (body.RetType,
444                                                         body.CallConv, over_name, body.ParamTypeList (), body.GenParamCount);
445                                         over_meth.Resolve (code_gen);
446                                         classdef.AddMethodOverride (over_meth.PeapiMethod,
447                                                         body.PeapiMethodDef);
448                                 }
449                         }
450
451                         if (override_long_list != null) {
452                                 foreach (DictionaryEntry entry in override_long_list) {
453                                         string sig = (string) entry.Key;
454                                         BaseMethodRef decl = (BaseMethodRef) entry.Value;
455                                         MethodDef body = (MethodDef) method_table[sig];
456                                         decl.Resolve (code_gen);
457                                         classdef.AddMethodOverride (decl.PeapiMethod,
458                                                         body.PeapiMethodDef);
459                                 }
460                         }
461                 }
462
463                 public PEAPI.Method ResolveMethod (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
464                         string name, BaseTypeRef [] param, int gen_param_count, CodeGen code_gen)
465                 {
466                         string signature = MethodDef.CreateSignature (ret_type, name, param, gen_param_count);
467                         MethodDef methoddef = (MethodDef) method_table[signature];
468
469                         if (methoddef != null)
470                                 return methoddef.Resolve (code_gen, classdef);
471                         return ResolveAsMethodRef (ret_type, call_conv, name, param, gen_param_count, code_gen);
472                 }
473
474                 public PEAPI.Method ResolveVarargMethod (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
475                         string name, BaseTypeRef [] param, int gen_param_count, PEAPI.Type [] opt, CodeGen code_gen)
476                 {
477                         string signature = MethodDef.CreateVarargSignature (ret_type, name, param);
478                         MethodDef methoddef = (MethodDef) method_table[signature];
479
480                         if (methoddef != null) {
481                                 methoddef.Resolve (code_gen, classdef);
482                                 return methoddef.GetVarargSig (opt);
483                         }
484                         
485                         return ResolveAsMethodRef (ret_type, call_conv, name, param, gen_param_count, code_gen);
486                 }
487
488                 private PEAPI.Method ResolveAsMethodRef (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
489                         string name, BaseTypeRef [] param, int gen_param_count, CodeGen code_gen)
490                 {
491                         ExternTypeRef type_ref = code_gen.ThisModule.GetTypeRef (FullName, false);
492                         ExternMethodRef methodref = (ExternMethodRef) type_ref.GetMethodRef (ret_type, call_conv, name, param, gen_param_count);
493                         methodref.Resolve (code_gen);
494
495                         return methodref.PeapiMethod;
496                 }
497
498                 public PEAPI.Field ResolveField (string name, BaseTypeRef ret_type, CodeGen code_gen)
499                 {
500                         FieldDef fielddef = (FieldDef) field_table[new DictionaryEntry (name, ret_type.FullName)];
501                         if (fielddef !=null)
502                                 return fielddef.Resolve (code_gen, classdef);
503
504                         ExternTypeRef type_ref = code_gen.ThisModule.GetTypeRef (FullName, false);
505                         IFieldRef fieldref = type_ref.GetFieldRef (ret_type, name);
506                         fieldref.Resolve (code_gen);
507
508                         return fieldref.PeapiField;
509                 }
510
511                 private string MakeFullName ()
512                 {
513                         if (name_space == null || name_space == String.Empty)
514                                 return name;
515
516                         return name_space + "." + name;
517                 }
518
519                 public int CompareTo (object obj)
520                 {
521                         TypeDef type_def = (TypeDef) obj; 
522
523                         return FullName.CompareTo (type_def.FullName);
524                 }
525         }
526
527 }
528