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