dlr bug
[mcs.git] / ilasm / codegen / TypeDef.cs
blob0f2525c5de0fed66eb9255e1664b6443b06f356e
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 //
11 using System;
12 using System.Collections;
13 using System.Security;
15 namespace Mono.ILASM {
17 public class TypeDef : ICustomAttrTarget, IDeclSecurityTarget, IComparable {
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 method_list;
31 private ArrayList customattr_list;
32 private DeclSecurity decl_sec;
33 private ArrayList event_list;
34 private ArrayList property_list;
35 private GenericParameters gen_params;
36 private ArrayList override_list;
37 private ArrayList override_long_list;
38 private TypeDef outer;
40 private EventDef current_event;
41 private PropertyDef current_property;
43 private int size;
44 private int pack;
46 private bool is_value_class;
47 private bool is_enum_class;
49 private Location location;
51 public TypeDef (PEAPI.TypeAttr attr, string name_space, string name,
52 BaseClassRef parent, ArrayList impl_list, Location location, GenericParameters gen_params, TypeDef outer)
54 this.attr = attr;
55 this.parent = parent;
56 this.impl_list = impl_list;
57 this.gen_params = gen_params;
58 this.outer = outer;
59 this.location = location;
61 field_table = new Hashtable ();
62 field_list = new ArrayList ();
64 method_table = new Hashtable ();
65 method_list = new ArrayList ();
67 size = -1;
68 pack = -1;
70 is_defined = false;
71 is_intransit = false;
73 is_value_class = false;
74 is_enum_class = false;
76 ResolveGenParams ();
78 int lastdot = name.LastIndexOf ('.');
79 /* Namespace . name split should not be done for nested classes */
80 if (lastdot >= 0 && outer == null) {
81 if (name_space == null || name_space == "")
82 this.name_space = name.Substring (0, lastdot);
83 else
84 this.name_space = name_space + "." + name.Substring (0, lastdot);
85 this.name = name.Substring (lastdot + 1);
86 } else {
87 this.name_space = name_space;
88 this.name = name;
91 //Fixup attributes
92 if (IsInterface)
93 this.attr |= PEAPI.TypeAttr.Abstract;
96 public string Name {
97 get { return name; }
100 public string FullName {
101 get { return MakeFullName (); }
104 public string NestedFullName {
105 get { return (outer == null ? FullName : (outer.NestedFullName + "/" + FullName)); }
108 public TypeDef OuterType {
109 get { return outer; }
112 public PEAPI.ClassDef PeapiType {
113 get { return classdef; }
116 public PEAPI.ClassDef ClassDef {
117 get { return classdef; }
120 public bool IsGenericType {
121 get { return (gen_params == null); }
124 public bool IsDefined {
125 get { return is_defined; }
128 public EventDef CurrentEvent {
129 get { return current_event; }
132 public PropertyDef CurrentProperty {
133 get { return current_property; }
136 public bool IsInterface {
137 get { return (attr & PEAPI.TypeAttr.Interface) != 0; }
140 public bool IsAbstract {
141 get { return (attr & PEAPI.TypeAttr.Abstract) != 0; }
144 public GenericParameters TypeParameters {
145 get { return gen_params; }
148 public DeclSecurity DeclSecurity {
149 get {
150 if (decl_sec == null)
151 decl_sec = new DeclSecurity ();
152 return decl_sec;
156 public void AddOverride (MethodDef body, BaseTypeRef parent, string name)
158 if (override_list == null)
159 override_list = new ArrayList ();
160 override_list.Add (new DictionaryEntry (body,
161 new DictionaryEntry (parent, name)));
164 public void AddOverride (string sig, BaseMethodRef decl)
166 if (override_long_list == null)
167 override_long_list = new ArrayList ();
168 override_long_list.Add (new DictionaryEntry (sig,
169 decl));
172 public void MakeValueClass ()
174 is_value_class = true;
177 public void MakeEnumClass ()
179 is_enum_class = true;
182 public void SetSize (int size)
184 this.size = size;
187 public void SetPack (int pack)
189 this.pack = pack;
192 public void AddFieldDef (FieldDef fielddef)
194 if (IsInterface && !fielddef.IsStatic) {
195 Report.Warning ("Non-static field in interface, set to such");
196 fielddef.Attributes |= PEAPI.FieldAttr.Static;
199 DictionaryEntry entry = new DictionaryEntry (fielddef.Name, fielddef.Type.FullName);
200 if (field_table [entry] != null)
201 Report.Error ("Duplicate field declaration: " + fielddef.Type.FullName + " " + fielddef.Name);
202 field_table.Add (entry, fielddef);
203 field_list.Add (fielddef);
206 public void AddMethodDef (MethodDef methoddef)
208 if (IsInterface && !methoddef.IsStatic && (!methoddef.IsVirtual || !methoddef.IsAbstract)) {
209 Report.Warning (methoddef.StartLocation, "Non-virtual or non-abstract instance method in interface, set to such");
210 methoddef.Attributes |= PEAPI.MethAttr.Abstract | PEAPI.MethAttr.Virtual;
213 if (method_table [methoddef.Signature] != null)
214 Report.Error (methoddef.StartLocation, "Duplicate method declaration: " + methoddef.Signature);
216 method_table.Add (methoddef.Signature, methoddef);
217 method_list.Add (methoddef);
220 public void BeginEventDef (EventDef event_def)
222 if (current_event != null)
223 Report.Error ("An event definition was not closed.");
225 current_event = event_def;
228 public void EndEventDef ()
230 if (event_list == null)
231 event_list = new ArrayList ();
233 event_list.Add (current_event);
234 current_event = null;
237 public void BeginPropertyDef (PropertyDef property_def)
239 if (current_property != null)
240 Report.Error ("A property definition was not closed.");
242 current_property = property_def;
245 public void EndPropertyDef ()
247 if (property_list == null)
248 property_list = new ArrayList ();
250 property_list.Add (current_property);
251 current_property = null;
254 public void AddCustomAttribute (CustomAttr customattr)
256 if (customattr_list == null)
257 customattr_list = new ArrayList ();
259 customattr_list.Add (customattr);
262 public GenericParameter GetGenericParam (string id)
264 if (gen_params == null)
265 return null;
267 return gen_params.GetGenericParam (id);
270 public GenericParameter GetGenericParam (int index)
272 if (gen_params == null || index < 0 || index >= gen_params.Count)
273 return null;
275 return gen_params [index];
278 public int GetGenericParamNum (string id)
280 if (gen_params == null)
281 return -1;
283 return gen_params.GetGenericParamNum (id);
286 /* Resolve any GenParams in constraints, parent & impl_list */
287 private void ResolveGenParams ()
289 if (gen_params == null)
290 return;
292 gen_params.ResolveConstraints (gen_params, null);
294 BaseGenericTypeRef gtr = parent as BaseGenericTypeRef;
295 if (gtr != null)
296 gtr.Resolve (gen_params, null);
298 if (impl_list == null)
299 return;
301 foreach (BaseClassRef impl in impl_list) {
302 gtr = impl as BaseGenericTypeRef;
303 if (gtr != null)
304 gtr.Resolve (gen_params, null);
308 private bool IsValueType (string ns, string name)
310 return (ns == "System" && name == "ValueType");
313 private bool IsEnumType (string ns, string name)
315 return (ns == "System" && name == "Enum");
318 public void Define (CodeGen code_gen)
320 if (is_defined)
321 return;
323 if (is_intransit) {
324 // Circular definition
325 Report.Error ("Circular definition of class: " + FullName);
328 if (outer != null) {
329 PEAPI.TypeAttr vis = attr & PEAPI.TypeAttr.VisibilityMask;
331 if (vis == PEAPI.TypeAttr.Private || vis == PEAPI.TypeAttr.Public) {
332 /* Nested class, but attr not set accordingly. */
333 Report.Warning (location, String.Format ("Nested class '{0}' has non-nested visibility, set to such.", NestedFullName));
334 attr = attr ^ vis;
335 attr |= (vis == PEAPI.TypeAttr.Public ? PEAPI.TypeAttr.NestedPublic : PEAPI.TypeAttr.NestedPrivate);
339 if (parent != null) {
340 is_intransit = true;
341 parent.Resolve (code_gen);
343 is_intransit = false;
344 if (parent.PeapiClass == null) {
345 Report.Error ("this type can not be a base type: "
346 + parent);
349 if (IsValueType (parent.PeapiClass.nameSpace, parent.PeapiClass.name))
350 is_value_class = true;
351 else if (IsEnumType (parent.PeapiClass.nameSpace, parent.PeapiClass.name))
352 is_enum_class = true;
354 if (!IsValueType (name_space, name) && !IsEnumType (name_space, name) &&
355 is_value_class && (attr & PEAPI.TypeAttr.Sealed) == 0) {
357 Report.Warning (location, "Non-sealed value class, made sealed.");
358 attr |= PEAPI.TypeAttr.Sealed;
361 if (outer != null) {
362 if (!outer.IsDefined)
363 outer.Define (code_gen);
364 classdef = outer.PeapiType.AddNestedClass (attr,
365 name_space, name, parent.PeapiClass);
366 } else {
367 if (is_value_class || is_enum_class) {
368 // Should probably confirm that the parent is System.ValueType
369 classdef = code_gen.PEFile.AddValueClass (attr,
370 name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
371 } else {
372 classdef = code_gen.PEFile.AddClass (attr,
373 name_space, name, parent.PeapiClass);
376 } else {
377 if (outer != null) {
378 if (!outer.IsDefined)
379 outer.Define (code_gen);
380 classdef = outer.PeapiType.AddNestedClass (attr,
381 name_space, name);
382 } else {
383 if (is_value_class || is_enum_class) {
384 classdef = code_gen.PEFile.AddValueClass (attr,
385 name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
386 } else {
387 classdef = code_gen.PEFile.AddClass (attr,
388 name_space, name);
391 if (FullName == "System.Object")
392 classdef.SpecialNoSuper ();
395 is_defined = true;
397 if (size != -1 || pack != -1)
398 classdef.AddLayoutInfo ( (pack == -1) ? 1 : pack, (size == -1) ? 0 : size);
400 if (impl_list != null) {
401 foreach (BaseClassRef impl in impl_list) {
402 impl.Resolve (code_gen);
403 classdef.AddImplementedInterface (impl.PeapiClass);
407 if (gen_params != null)
408 gen_params.Resolve (code_gen, classdef);
410 is_intransit = false;
412 code_gen.AddToDefineContentsList (this);
415 public void DefineContents (CodeGen code_gen)
417 ArrayList fielddef_list = new ArrayList ();
418 foreach (FieldDef fielddef in field_list) {
419 fielddef.Define (code_gen, classdef);
420 fielddef_list.Add (fielddef.PeapiFieldDef);
423 classdef.SetFieldOrder (fielddef_list);
425 foreach (MethodDef methoddef in method_list) {
426 methoddef.Define (code_gen);
429 if (event_list != null) {
430 foreach (EventDef eventdef in event_list) {
431 eventdef.Define (code_gen, classdef);
435 if (property_list != null) {
436 foreach (PropertyDef propdef in property_list) {
437 propdef.Define (code_gen, classdef);
442 if (customattr_list != null) {
443 foreach (CustomAttr customattr in customattr_list) {
444 customattr.AddTo (code_gen, classdef);
445 if (customattr.IsSuppressUnmanaged (code_gen))
446 classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
450 /// Add declarative security to this class
451 if (decl_sec != null) {
452 decl_sec.AddTo (code_gen, classdef);
453 classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
456 if (override_list != null) {
457 foreach (DictionaryEntry entry in override_list) {
458 MethodDef body = (MethodDef) entry.Key;
459 DictionaryEntry decl = (DictionaryEntry) entry.Value;
460 BaseTypeRef parent_type = (BaseTypeRef) decl.Key;
461 parent_type.Resolve (code_gen);
462 string over_name = (string) decl.Value;
463 BaseMethodRef over_meth = parent_type.GetMethodRef (body.RetType,
464 body.CallConv, over_name, body.ParamTypeList (), body.GenParamCount);
465 over_meth.Resolve (code_gen);
466 classdef.AddMethodOverride (over_meth.PeapiMethod,
467 body.PeapiMethodDef);
471 if (override_long_list != null) {
472 foreach (DictionaryEntry entry in override_long_list) {
473 string sig = (string) entry.Key;
474 BaseMethodRef decl = (BaseMethodRef) entry.Value;
475 MethodDef body = (MethodDef) method_table[sig];
476 decl.Resolve (code_gen);
477 classdef.AddMethodOverride (decl.PeapiMethod,
478 body.PeapiMethodDef);
483 public PEAPI.Method ResolveMethod (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
484 string name, BaseTypeRef [] param, int gen_param_count, CodeGen code_gen)
486 string signature = MethodDef.CreateSignature (ret_type, call_conv, name, param, gen_param_count, false);
487 MethodDef methoddef = (MethodDef) method_table[signature];
489 if (methoddef != null)
490 return methoddef.Resolve (code_gen, classdef);
491 return ResolveAsMethodRef (ret_type, call_conv, name, param, gen_param_count, code_gen);
494 public PEAPI.Method ResolveVarargMethod (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
495 string name, BaseTypeRef [] param, int gen_param_count, PEAPI.Type [] opt, CodeGen code_gen)
497 // Only MethodDef sig required to lookup in the method_table
498 string signature = MethodDef.CreateSignature (ret_type, call_conv, name, param, 0, false);
499 MethodDef methoddef = (MethodDef) method_table[signature];
500 if (methoddef != null) {
501 methoddef.Resolve (code_gen, classdef);
502 return methoddef.GetVarargSig (
503 opt,
504 MethodDef.CreateSignature (ret_type, call_conv, name, param, 0, true));
507 return ResolveAsMethodRef (ret_type, call_conv, name, param, gen_param_count, code_gen);
510 private PEAPI.Method ResolveAsMethodRef (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
511 string name, BaseTypeRef [] param, int gen_param_count, CodeGen code_gen)
513 ExternTypeRef type_ref = code_gen.ThisModule.GetTypeRef (FullName, false);
514 ExternMethodRef methodref = (ExternMethodRef) type_ref.GetMethodRef (ret_type, call_conv, name, param, gen_param_count);
515 methodref.Resolve (code_gen);
517 return methodref.PeapiMethod;
520 public PEAPI.Field ResolveField (string name, BaseTypeRef ret_type, CodeGen code_gen)
522 FieldDef fielddef = (FieldDef) field_table[new DictionaryEntry (name, ret_type.FullName)];
523 if (fielddef !=null)
524 return fielddef.Resolve (code_gen, classdef);
526 ExternTypeRef type_ref = code_gen.ThisModule.GetTypeRef (FullName, false);
527 IFieldRef fieldref = type_ref.GetFieldRef (ret_type, name);
528 fieldref.Resolve (code_gen);
530 return fieldref.PeapiField;
533 private string MakeFullName ()
535 if (name_space == null || name_space == String.Empty)
536 return name;
538 return name_space + "." + name;
541 public int CompareTo (object obj)
543 TypeDef type_def = (TypeDef) obj;
545 return FullName.CompareTo (type_def.FullName);