2004-11-07 Ben Maurer <bmaurer@ximian.com>
[mono-project.git] / mcs / mbas / class.cs
blob90ebe3fe21ccbb654d34ce8c93d1dfaa54970213
2 //
3 // class.cs: Class and Struct handlers
4 //
5 // Authors: Miguel de Icaza (miguel@gnu.org)
6 // Martin Baulig (martin@gnome.org)
7 // Anirban Bhattacharjee (banirban@novell.com)
8 //
9 // Licensed under the terms of the GNU GPL
11 // (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
14 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
16 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
17 // have fixed a remaining problem: not every AddXXXX was adding a
18 // fully qualified name.
20 // Now everyone registers a fully qualified name in the DeclSpace as
21 // being defined instead of the partial name.
23 // Downsides: we are slower than we need to be due to the excess
24 // copies and the names being registered this way.
26 // The reason for this is that we currently depend (on the corlib
27 // bootstrap for instance) that types are fully qualified, because
28 // we dump all the types in the namespace, and we should really have
29 // types inserted into the proper namespace, so we can only store the
30 // basenames in the defined_names array.
33 #define CACHE
34 using System;
35 using System.Collections;
36 using System.Reflection;
37 using System.Reflection.Emit;
38 using System.Runtime.CompilerServices;
39 using System.Diagnostics.SymbolStore;
41 namespace Mono.MonoBASIC {
43 /// <summary>
44 /// This is the base class for structs and classes.
45 /// </summary>
46 public class TypeContainer : DeclSpace, IMemberContainer {
47 // Holds a list of classes and structures
48 ArrayList types;
50 // Holds the list of properties
51 ArrayList properties;
53 // Holds the list of enumerations
54 ArrayList enums;
56 // Holds the list of delegates
57 ArrayList delegates;
59 // Holds the list of constructors
60 ArrayList instance_constructors;
62 // Holds the list of fields
63 ArrayList fields;
65 // Holds a list of fields that have initializers
66 ArrayList initialized_fields;
68 // Holds a list of static fields that have initializers
69 ArrayList initialized_static_fields;
71 // Holds the list of constants
72 ArrayList constants;
74 // Holds the list of
75 ArrayList interfaces;
77 // Holds order in which interfaces must be closed
78 ArrayList interface_order;
80 // Holds the methods.
81 ArrayList methods;
83 // Holds the events
84 ArrayList events;
86 // Holds the indexers
87 ArrayList indexers;
89 // Holds AddHandlers stements for events
90 ArrayList handlers;
92 // The emit context for toplevel objects.
93 EmitContext ec;
96 // Pointers to the default constructor and the default static constructor
98 Constructor default_constructor;
99 Constructor default_static_constructor;
102 // Whether we have seen a static constructor for this class or not
104 bool have_static_constructor = false;
107 // Whether we have at least one non-static field
109 bool have_nonstatic_fields = false;
112 // This one is computed after we can distinguish interfaces
113 // from classes from the arraylist `type_bases'
115 string base_class_name;
117 ArrayList type_bases;
119 // Attributes for this type
120 protected Attributes attributes;
122 // Information in the case we are an attribute type
124 AttributeUsageAttribute attribute_usage = new AttributeUsageAttribute (AttributeTargets.All);
126 public AttributeUsageAttribute AttributeUsage {
127 get {
128 return attribute_usage;
131 set {
132 attribute_usage = value;
136 // The interfaces we implement.
137 Type [] ifaces;
139 // The parent member container and our member cache
140 IMemberContainer parent_container;
141 MemberCache member_cache;
144 // The indexer name for this class
146 public string IndexerName;
148 public TypeContainer (TypeContainer parent, string name, Location l)
149 : base (parent, name, l)
151 string n;
152 types = new ArrayList ();
154 if (parent == null)
155 n = "";
156 else
157 n = parent.Name;
159 base_class_name = null;
161 //Console.WriteLine ("New class " + name + " inside " + n);
164 public AdditionResult AddConstant (Const constant)
166 AdditionResult res;
167 string basename = constant.Name;
169 if ((res = IsValid (basename)) != AdditionResult.Success)
170 return res;
172 if (constants == null)
173 constants = new ArrayList ();
175 constants.Add (constant);
176 DefineName (Name + "." + basename, constant);
178 return AdditionResult.Success;
181 public AdditionResult AddEnum (Mono.MonoBASIC.Enum e)
183 AdditionResult res;
185 if ((res = IsValid (e.Basename)) != AdditionResult.Success)
186 return res;
188 if (enums == null)
189 enums = new ArrayList ();
191 enums.Add (e);
192 DefineName (e.Name, e);
194 return AdditionResult.Success;
197 public AdditionResult AddClass (Class c)
199 AdditionResult res;
201 if ((res = IsValid (c.Basename)) != AdditionResult.Success)
202 return res;
206 DefineName (c.Name, c);
207 types.Add (c);
209 // FIXME: Do we really need to explicitly add an empty default static constructor?
210 // Apparently we don't
211 /* if (c.default_static_constructor == null)
213 bool isModule = c is Mono.MonoBASIC.Module;
214 Constructor dc = new Constructor ("New", Parameters.EmptyReadOnlyParameters, null, c.Location);
215 dc.ModFlags = isModule ? Modifiers.PUBLIC | Modifiers.STATIC : Modifiers.PUBLIC;
216 c.AddConstructor (dc);
219 //--------------------------------------------------------------
221 return AdditionResult.Success;
224 public AdditionResult AddStruct (Struct s)
226 AdditionResult res;
228 if ((res = IsValid (s.Basename)) != AdditionResult.Success)
229 return res;
231 DefineName (s.Name, s);
232 types.Add (s);
234 return AdditionResult.Success;
237 public AdditionResult AddDelegate (Delegate d)
239 AdditionResult res;
241 if ((res = IsValid (d.Basename)) != AdditionResult.Success)
242 return res;
244 if (delegates == null)
245 delegates = new ArrayList ();
247 DefineName (d.Name, d);
248 delegates.Add (d);
250 return AdditionResult.Success;
253 public AdditionResult AddMethod (Method method)
255 string basename = method.Name;
256 string fullname = Name + "." + basename;
258 Object value = defined_names [fullname];
260 if (value != null && (!(value is Method)))
261 return AdditionResult.NameExists;
263 if (basename == Basename)
264 return AdditionResult.EnclosingClash;
266 if (methods == null)
267 methods = new ArrayList ();
269 if (method.Name.IndexOf (".") != -1)
270 methods.Insert (0, method);
271 else
272 methods.Add (method);
274 if (value == null)
275 DefineName (fullname, method);
277 return AdditionResult.Success;
280 public AdditionResult AddConstructor (Constructor c)
282 if (c.Name != "New")
283 return AdditionResult.NotAConstructor;
285 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
287 if (is_static){
288 have_static_constructor = true;
289 if (default_static_constructor != null){
290 Console.WriteLine ("I have a static constructor already");
291 Console.WriteLine (" " + default_static_constructor);
292 return AdditionResult.MethodExists;
295 default_static_constructor = c;
296 } else {
297 if (c.IsDefault ()){
298 /*if (default_constructor != null)
299 return AdditionResult.MethodExists;*/
300 default_constructor = c;
303 if (instance_constructors == null)
304 instance_constructors = new ArrayList ();
306 instance_constructors.Add (c);
309 return AdditionResult.Success;
312 public AdditionResult AddInterface (Interface iface)
314 AdditionResult res;
316 if ((res = IsValid (iface.Basename)) != AdditionResult.Success)
317 return res;
319 if (interfaces == null)
320 interfaces = new ArrayList ();
321 interfaces.Add (iface);
322 DefineName (iface.Name, iface);
324 return AdditionResult.Success;
327 public AdditionResult AddField (Field field)
329 AdditionResult res;
330 string basename = field.Name;
332 if ((res = IsValid (basename)) != AdditionResult.Success)
333 return res;
335 if (fields == null)
336 fields = new ArrayList ();
338 fields.Add (field);
340 if (field.HasInitializer){
341 if ((field.ModFlags & Modifiers.STATIC) != 0) {
342 if (initialized_static_fields == null)
343 initialized_static_fields = new ArrayList ();
345 initialized_static_fields.Add (field);
348 // We have not seen a static constructor,
349 // but we will provide static initialization of fields
351 have_static_constructor = true;
352 } else {
353 if (initialized_fields == null)
354 initialized_fields = new ArrayList ();
356 initialized_fields.Add (field);
360 if ((field.ModFlags & Modifiers.STATIC) == 0)
361 have_nonstatic_fields = true;
363 DefineName (Name + "." + basename, field);
364 return AdditionResult.Success;
367 public AdditionResult AddProperty (Property prop)
369 AdditionResult res;
370 string basename = prop.Name;
372 if ((res = IsValid (basename)) != AdditionResult.Success)
373 return res;
375 if (properties == null)
376 properties = new ArrayList ();
378 if (prop.Name.IndexOf (".") != -1)
379 properties.Insert (0, prop);
380 else
381 properties.Add (prop);
382 DefineName (Name + "." + basename, prop);
384 return AdditionResult.Success;
387 public AdditionResult AddEvent (Event e)
389 AdditionResult res;
390 string basename = e.Name;
392 if ((res = IsValid (basename)) != AdditionResult.Success)
393 return res;
395 if (events == null)
396 events = new ArrayList ();
398 events.Add (e);
399 DefineName (Name + "." + basename, e);
401 return AdditionResult.Success;
404 public AdditionResult AddIndexer (Indexer i)
406 if (indexers == null)
407 indexers = new ArrayList ();
409 if (i.InterfaceType != null)
410 indexers.Insert (0, i);
411 else
412 indexers.Add (i);
414 return AdditionResult.Success;
417 public AdditionResult AddEventHandler (Statement stmt)
419 if (handlers == null)
420 handlers = new ArrayList ();
422 handlers.Add (stmt);
423 return AdditionResult.Success;
426 public void RegisterOrder (Interface iface)
428 if (interface_order == null)
429 interface_order = new ArrayList ();
431 interface_order.Add (iface);
434 public ArrayList Types {
435 get {
436 return types;
440 public ArrayList Methods {
441 get {
442 return methods;
446 public ArrayList Constants {
447 get {
448 return constants;
452 public ArrayList Interfaces {
453 get {
454 return interfaces;
458 public string Base {
459 get {
460 return base_class_name;
464 public ArrayList Bases {
465 get {
466 return type_bases;
469 set {
470 type_bases = value;
474 public ArrayList Fields {
475 get {
476 return fields;
479 set {
480 fields = value;
484 public ArrayList InstanceConstructors {
485 get {
486 return instance_constructors;
490 public ArrayList Properties {
491 get {
492 return properties;
496 public ArrayList Events {
497 get {
498 return events;
502 public ArrayList Enums {
503 get {
504 return enums;
508 public ArrayList Indexers {
509 get {
510 return indexers;
514 public ArrayList Delegates {
515 get {
516 return delegates;
520 public Attributes OptAttributes {
521 get {
522 return attributes;
526 public bool HaveStaticConstructor {
527 get {
528 return have_static_constructor;
532 public virtual TypeAttributes TypeAttr {
533 get {
534 return Modifiers.TypeAttr (ModFlags, this);
538 public ArrayList EventHandlers {
539 get {
540 return handlers;
545 // Emits the instance field initializers
547 public bool EmitFieldInitializers (EmitContext ec)
549 ArrayList fields;
550 ILGenerator ig = ec.ig;
551 Expression instance_expr;
553 if (ec.IsStatic){
554 fields = initialized_static_fields;
555 instance_expr = null;
556 } else {
557 fields = initialized_fields;
558 instance_expr = new This (Location.Null).Resolve (ec);
561 if (fields == null)
562 return true;
564 foreach (Field f in fields){
565 Expression e = f.GetInitializerExpression (ec);
566 if (e == null)
567 return false;
569 Location l = f.Location;
570 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
571 fe.InstanceExpression = instance_expr;
572 Expression a = new Assign (fe, e, l);
574 a = a.Resolve (ec);
575 if (a == null)
576 return false;
578 if (a is ExpressionStatement)
579 ((ExpressionStatement) a).EmitStatement (ec);
580 else {
581 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
585 return true;
589 // Defines the default constructors
591 void DefineDefaultConstructor (bool is_static)
593 Constructor c;
594 int mods = 0;
596 c = new Constructor ("New", Parameters.EmptyReadOnlyParameters,
597 null,
598 Location.Null);
600 if (is_static) {
601 mods = Modifiers.STATIC;
602 c.ModFlags = mods;
604 else
605 c.Initializer = new ConstructorBaseInitializer (
606 null, Parameters.EmptyReadOnlyParameters,
607 Location.Null);
609 AddConstructor (c);
611 c.Block = new Block (null);
615 public void ReportStructInitializedInstanceError ()
617 string n = TypeBuilder.FullName;
619 foreach (Field f in initialized_fields){
620 Report.Error (
621 31049, Location,
622 "`" + n + "." + f.Name + "': can not have " +
623 "instance field initializers in structs");
627 /// <remarks>
628 /// The pending methods that need to be implemented (interfaces or abstract methods)
629 /// </remarks>
630 public PendingImplementation Pending;
632 /// <summary>
633 /// This function computes the Base class and also the
634 /// list of interfaces that the class or struct @c implements.
635 ///
636 /// The return value is an array (might be null) of
637 /// interfaces implemented (as Types).
638 ///
639 /// The @parent argument is set to the parent object or null
640 /// if this is `System.Object'.
641 /// </summary>
642 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
644 ArrayList bases = Bases;
645 int count;
646 int start, j, i;
648 error = false;
650 if (is_class)
651 parent = null;
652 else
653 parent = TypeManager.value_type;
655 if (bases == null){
656 if (is_class){
657 if (RootContext.StdLib)
658 parent = TypeManager.object_type;
659 else if (Name != "System.Object")
660 parent = TypeManager.object_type;
661 } else {
663 // If we are compiling our runtime,
664 // and we are defining ValueType, then our
665 // parent is `System.Object'.
667 if (!RootContext.StdLib && Name == "System.ValueType")
668 parent = TypeManager.object_type;
671 return null;
675 // Bases should be null if there are no bases at all
677 count = bases.Count;
679 if (is_class && (!(this is Interface))){
680 Expression name = (Expression) bases [0];
681 name = ResolveTypeExpr (name, false, Location);
683 if (name == null){
684 error = true;
685 return null;
688 Type first = name.Type;
690 if (first.IsClass){
691 parent = first;
692 start = 1;
693 } else {
694 parent = TypeManager.object_type;
695 start = 0;
698 if (parent.IsSealed )
699 Report.Error (30299, Location,
700 "Class " + Name + " cannot inherit " +
701 "'NotInheritable' class " + TypeManager.MonoBASIC_Name (parent));
703 if (!AsAccessible (parent, ModFlags))
704 Report.Error (30389, Location,
705 "Inconsistent accessibility: base class `" +
706 TypeManager.MonoBASIC_Name (parent) + "' is less " +
707 "accessible than class `" +
708 Name + "'");
710 } else {
711 start = 0;
714 Type [] ifaces = new Type [count-start];
716 for (i = start, j = 0; i < count; i++, j++){
717 Expression name = (Expression) bases [i];
718 Expression resolved = ResolveTypeExpr (name, false, Location);
719 bases [i] = resolved;
720 Type t = resolved.Type;
721 if (t == null){
722 error = true;
723 return null;
726 if (is_class == false && !t.IsInterface){
727 Report.Error (527, "In Struct `" + Name + "', type `"+
728 name +"' is not an interface");
729 error = true;
730 return null;
733 if (t.IsSealed) {
734 if (t.IsValueType)
735 Report.Error (30258, "class `"+ Name +
736 "': a class can not inherit from a struct/enum");
738 /*Report.Error (509, "class `"+ Name +
739 "': Cannot inherit from sealed class `"+
740 bases [i]);*/
741 error = true;
742 return null;
745 if (t.IsClass) {
746 if (parent != null){
747 Report.Error (30121, Name + ": A class cannot inherit " +
748 "more than one class");
749 error = true;
750 return null;
754 for (int x = 0; x < j; x++) {
755 if (t == ifaces [x]) {
756 Report.Error (528, "`" + name + "' is already listed in interface list");
757 error = true;
758 return null;
762 ifaces [j] = t;
765 return ifaces;
769 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
771 public override TypeBuilder DefineType ()
773 Type parent;
774 bool error;
775 bool is_class;
777 if (TypeBuilder != null)
778 return TypeBuilder;
780 if (InTransit)
781 return null;
783 InTransit = true;
785 if (this is Class)
786 is_class = true;
787 else
788 is_class = false;
790 ec = new EmitContext (this, Mono.MonoBASIC.Location.Null, null, null, ModFlags);
792 if (((ModFlags & Modifiers.ABSTRACT ) != 0) &&
793 ((ModFlags & Modifiers.SEALED) != 0)){
794 Report.Error (31408, Location,
795 "Class declared as 'MustInherit' cannot be declared as 'NotInheritable'");
798 ifaces = GetClassBases (is_class, out parent, out error);
799 if (error)
800 return null;
802 if (this is Interface)
803 parent = null;
805 if (is_class && parent != null){
806 if (parent == TypeManager.enum_type ||
807 (parent == TypeManager.value_type && RootContext.StdLib) ||
808 parent == TypeManager.delegate_type ||
809 parent == TypeManager.array_type){
810 Report.Error (
811 644, Location, "`" + Name + "' cannot inherit from " +
812 "special class `" + TypeManager.MonoBASIC_Name (parent) + "'");
813 return null;
817 if (!is_class && TypeManager.value_type == null)
818 throw new Exception ();
820 if (is_class && Parent.Parent == null && (!(this is Interface)))
822 if ((ModFlags & Modifiers.PRIVATE) != 0)
823 Report.Error (31089, Location,
824 "Only internal classes can be declared as 'Private'");
826 if ((ModFlags & Modifiers.PROTECTED) != 0)
827 Report.Error (31047, Location,
828 "Only internal classes can be declared as 'Protected'");
831 if ((Parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
832 Report.Error (30735, Location,
833 "'Type' inside a 'Module' can not be " +
834 "declared as 'Protected'");
836 if ((Parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
837 Report.Error (30435, Location,
838 "'Type' inside a 'Structure' can not be " +
839 "declared as 'Protected'");
841 TypeAttributes type_attributes = TypeAttr;
843 // if (parent_builder is ModuleBuilder) {
844 if (IsTopLevel){
845 ModuleBuilder builder = CodeGen.ModuleBuilder;
846 TypeBuilder = builder.DefineType (
847 Name, type_attributes, parent, ifaces);
849 } else {
850 TypeBuilder builder = Parent.TypeBuilder;
851 TypeBuilder = builder.DefineNestedType (
852 Basename, type_attributes, parent, ifaces);
855 if (!is_class)
857 // structure must contain atleast one member variable
858 if(!have_nonstatic_fields){
859 Report.Error (
860 30281, Location, "Structure `" + Name + "' do not " +
861 "contain any member Variable");
863 /*TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
864 FieldAttributes.Private);*/
867 // add interfaces that were not added at type creation (weird API issue)
868 if (!have_nonstatic_fields && (ifaces != null)) {
869 foreach (Type i in ifaces)
870 TypeBuilder.AddInterfaceImplementation (i);
876 // Finish the setup for the EmitContext
878 ec.ContainerType = TypeBuilder;
880 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
882 if ((parent != null) &&
883 (parent == TypeManager.attribute_type ||
884 parent.IsSubclassOf (TypeManager.attribute_type))) {
885 RootContext.RegisterAttribute (this);
886 } else
887 RootContext.RegisterOrder (this);
889 if (Interfaces != null) {
890 foreach (Interface iface in Interfaces)
891 iface.DefineType ();
894 if (Types != null) {
895 foreach (TypeContainer tc in Types)
896 tc.DefineType ();
899 if (Delegates != null) {
900 foreach (Delegate d in Delegates)
901 d.DefineType ();
904 if (Enums != null) {
905 foreach (Enum en in Enums)
906 en.DefineType ();
909 InTransit = false;
910 return TypeBuilder;
914 /// <summary>
915 /// Defines the MemberCore objects that are in the `list' Arraylist
917 /// The `defined_names' array contains a list of members defined in
918 /// a base class
919 /// </summary>
920 static ArrayList remove_list = new ArrayList ();
921 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
923 int idx;
925 // if one of the overloaded method is having
926 // Shadows or Overloads modifier all other should
927 // have the same modifier
928 Hashtable members = new Hashtable();
929 int modval;
930 foreach (MemberCore mc in list)
932 modval = 0;
933 if(members[mc.Name] == null)
935 foreach (MemberCore m in list)
937 if(m.Name == mc.Name)
939 if ((m.ModFlags & Modifiers.SHADOWS) != 0)
941 modval = Modifiers.SHADOWS;
942 break;
944 else if((m.ModFlags & Modifiers.NEW) != 0)
946 modval = Modifiers.NEW;
950 members.Add(mc.Name, modval);
953 modval = (int)members[mc.Name];
954 if(modval != 0)
956 if(((modval & Modifiers.SHADOWS) != 0) && ((mc.ModFlags & Modifiers.SHADOWS) == 0))
957 Report.Error (
958 30695, mc.Location,
959 "Function '" + mc.Name + "': must be declared 'Shadows' " +
960 "because another '" + mc.Name + "' declared 'Shadows'");
961 else if(((modval & Modifiers.NEW) != 0) && ((mc.ModFlags & Modifiers.NEW) == 0))
962 Report.Error (
963 31409, mc.Location,
964 "Function '" + mc.Name + "': must be declared 'Overloads' " +
965 "because another '" + mc.Name + "' declared 'Overloads'");
968 members.Clear ();
969 remove_list.Clear ();
971 foreach (MemberCore mc in list){
972 if (!mc.Define (this)){
973 remove_list.Add (mc);
974 continue;
977 if (defined_names == null)
978 continue;
980 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
981 if (idx < 0){
982 if (RootContext.WarningLevel >= 4){
983 if ((mc.ModFlags & Modifiers.NEW) != 0)
984 Warning_KewywordNewNotRequired (mc.Location, mc);
985 if ((mc.ModFlags & Modifiers.SHADOWS) != 0)
986 Warning_KewywordShadowsNotRequired (mc.Location, mc);
988 continue;
991 MemberInfo match = defined_names [idx];
993 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
994 continue;
997 // If we are both methods, let the method resolution emit warnings
999 if (match is MethodBase && mc is MethodCore)
1000 continue;
1002 if (((mc.ModFlags & Modifiers.SHADOWS) == 0) && idx > 0)
1003 Warning_KeywordShadowsRequired (mc.Location, defined_names [idx]);
1007 foreach (object o in remove_list)
1008 list.Remove (o);
1010 remove_list.Clear ();
1014 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
1015 // class is consisten. Either it is `Item' or it is the name defined by all the
1016 // indexers with the `IndexerName' attribute.
1018 // Turns out that the IndexerNameAttribute is applied to each indexer,
1019 // but it is never emitted, instead a DefaultName attribute is attached
1020 // to the class.
1022 void DefineIndexers ()
1024 string class_indexer_name = null;
1026 foreach (Indexer i in Indexers){
1027 string name;
1029 i.Define (this);
1031 name = i.IndexerName;
1033 if (i.InterfaceType != null)
1034 continue;
1036 if (class_indexer_name == null){
1037 class_indexer_name = name;
1038 continue;
1041 if (name == class_indexer_name)
1042 continue;
1044 Report.Error (
1045 668, "Two indexers have different names, " +
1046 " you should use the same name for all your indexers");
1048 if (class_indexer_name == null)
1049 class_indexer_name = "Item";
1050 IndexerName = class_indexer_name;
1053 static void Error_KeywordNotAllowed (Location loc)
1055 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1058 /// <summary>
1059 /// Populates our TypeBuilder with fields and methods
1060 /// </summary>
1061 public override bool DefineMembers (TypeContainer parent)
1063 MemberInfo [] defined_names = null;
1065 if (interface_order != null){
1066 foreach (Interface iface in interface_order)
1067 if ((iface.ModFlags & Modifiers.NEW) == 0)
1068 iface.DefineMembers (this);
1069 else
1070 Error_KeywordNotAllowed (iface.Location);
1073 if (RootContext.WarningLevel > 1){
1074 Type ptype;
1077 // This code throws an exception in the comparer
1078 // I guess the string is not an object?
1080 ptype = TypeBuilder.BaseType;
1081 if (ptype != null){
1082 defined_names = (MemberInfo []) FindMembers (
1083 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1084 BindingFlags.Public | BindingFlags.Instance |
1085 BindingFlags.Static, null, null);
1087 Array.Sort (defined_names, mif_compare);
1091 if (constants != null)
1092 DefineMembers (constants, defined_names);
1094 if (fields != null)
1095 DefineMembers (fields, defined_names);
1097 if (this is Class && (!(this is Interface))){
1098 if (instance_constructors == null){
1099 if (default_constructor == null)
1100 DefineDefaultConstructor (false);
1103 if (initialized_static_fields != null &&
1104 default_static_constructor == null)
1105 DefineDefaultConstructor (true);
1108 if (this is Struct){
1110 // Structs can not have initialized instance
1111 // fields
1113 if (initialized_static_fields != null &&
1114 default_static_constructor == null)
1115 DefineDefaultConstructor (true);
1117 if (initialized_fields != null)
1118 ReportStructInitializedInstanceError ();
1121 if (!(this is Interface))
1122 Pending = PendingImplementation.GetPendingImplementations (this);
1124 // Constructors are not in the defined_names array
1126 if (instance_constructors != null)
1127 DefineMembers (instance_constructors, null);
1129 if (default_static_constructor != null)
1130 default_static_constructor.Define (this);
1132 if (methods != null)
1133 DefineMembers (methods, defined_names);
1135 if (properties != null)
1136 DefineMembers (properties, defined_names);
1138 if (events != null)
1139 DefineMembers (events, defined_names);
1141 if (indexers != null) {
1142 DefineIndexers ();
1143 } else
1144 IndexerName = "Item";
1146 if (enums != null)
1147 DefineMembers (enums, defined_names);
1149 if (delegates != null)
1150 DefineMembers (delegates, defined_names);
1152 #if CACHE
1153 if (TypeBuilder.BaseType != null)
1154 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1156 member_cache = new MemberCache (this);
1157 #endif
1159 return true;
1162 public override bool Define (TypeContainer parent)
1164 if (interface_order != null){
1165 foreach (Interface iface in interface_order)
1166 if ((iface.ModFlags & Modifiers.NEW) == 0)
1167 iface.Define (this);
1170 return true;
1173 /// <summary>
1174 /// This function is based by a delegate to the FindMembers routine
1175 /// </summary>
1176 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1178 return true;
1181 /// <summary>
1182 /// This filter is used by FindMembers, and we just keep
1183 /// a global for the filter to `AlwaysAccept'
1184 /// </summary>
1185 static MemberFilter accepting_filter;
1188 /// <summary>
1189 /// A member comparission method based on name only
1190 /// </summary>
1191 static IComparer mif_compare;
1193 static TypeContainer ()
1195 accepting_filter = new MemberFilter (AlwaysAccept);
1196 mif_compare = new MemberInfoCompare ();
1199 /// <summary>
1200 /// This method returns the members of this type just like Type.FindMembers would
1201 /// Only, we need to use this for types which are _being_ defined because MS'
1202 /// implementation can't take care of that.
1203 /// </summary>
1205 // FIXME: return an empty static array instead of null, that cleans up
1206 // some code and is consistent with some coding conventions I just found
1207 // out existed ;-)
1210 // Notice that in various cases we check if our field is non-null,
1211 // something that would normally mean that there was a bug elsewhere.
1213 // The problem happens while we are defining p-invoke methods, as those
1214 // will trigger a FindMembers, but this happens before things are defined
1216 // Since the whole process is a no-op, it is fine to check for null here.
1218 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1219 MemberFilter filter, object criteria)
1221 ArrayList members = new ArrayList ();
1223 int modflags = 0;
1224 if ((bf & BindingFlags.Public) != 0)
1225 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1226 Modifiers.INTERNAL;
1227 if ((bf & BindingFlags.NonPublic) != 0)
1228 modflags |= Modifiers.PRIVATE;
1230 int static_mask = 0, static_flags = 0;
1231 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1232 case BindingFlags.Static:
1233 static_mask = static_flags = Modifiers.STATIC;
1234 break;
1236 case BindingFlags.Instance:
1237 static_mask = Modifiers.STATIC;
1238 static_flags = 0;
1239 break;
1241 default:
1242 static_mask = static_flags = 0;
1243 break;
1246 Timer.StartTimer (TimerType.TcFindMembers);
1248 if (filter == null)
1249 filter = accepting_filter;
1251 if ((mt & MemberTypes.Field) != 0) {
1252 if (fields != null) {
1253 foreach (Field f in fields) {
1254 if ((f.ModFlags & modflags) == 0)
1255 continue;
1256 if ((f.ModFlags & static_mask) != static_flags)
1257 continue;
1259 FieldBuilder fb = f.FieldBuilder;
1260 if (fb != null && filter (fb, criteria) == true)
1261 members.Add (fb);
1265 if (constants != null) {
1266 foreach (Const con in constants) {
1267 if ((con.ModFlags & modflags) == 0)
1268 continue;
1269 if ((con.ModFlags & static_mask) != static_flags)
1270 continue;
1272 FieldBuilder fb = con.FieldBuilder;
1273 if (fb != null && filter (fb, criteria) == true)
1274 members.Add (fb);
1279 if ((mt & MemberTypes.Method) != 0) {
1280 if (methods != null) {
1281 foreach (Method m in methods) {
1282 if ((m.ModFlags & modflags) == 0)
1283 continue;
1284 if ((m.ModFlags & static_mask) != static_flags)
1285 continue;
1287 MethodBuilder mb = m.MethodBuilder;
1289 if (mb != null && filter (mb, criteria) == true)
1290 members.Add (mb);
1294 if (properties != null){
1295 foreach (Property p in properties){
1296 if ((p.ModFlags & modflags) == 0)
1297 continue;
1298 if ((p.ModFlags & static_mask) != static_flags)
1299 continue;
1301 MethodBuilder b;
1303 b = p.GetBuilder;
1304 if (b != null && filter (b, criteria) == true)
1305 members.Add (b);
1307 b = p.SetBuilder;
1308 if (b != null && filter (b, criteria) == true)
1309 members.Add (b);
1313 if (indexers != null){
1314 foreach (Indexer ix in indexers){
1315 if ((ix.ModFlags & modflags) == 0)
1316 continue;
1317 if ((ix.ModFlags & static_mask) != static_flags)
1318 continue;
1320 MethodBuilder b;
1322 b = ix.GetBuilder;
1323 if (b != null && filter (b, criteria) == true)
1324 members.Add (b);
1326 b = ix.SetBuilder;
1327 if (b != null && filter (b, criteria) == true)
1328 members.Add (b);
1333 if ((mt & MemberTypes.Event) != 0) {
1334 if (events != null)
1335 foreach (Event e in events) {
1336 if ((e.ModFlags & modflags) == 0)
1337 continue;
1338 if ((e.ModFlags & static_mask) != static_flags)
1339 continue;
1341 MemberInfo eb = e.EventBuilder;
1342 if (eb != null && filter (eb, criteria) == true)
1343 members.Add (e.EventBuilder);
1347 if ((mt & MemberTypes.Property) != 0){
1348 if (properties != null)
1349 foreach (Property p in properties) {
1350 if ((p.ModFlags & modflags) == 0)
1351 continue;
1352 if ((p.ModFlags & static_mask) != static_flags)
1353 continue;
1355 MemberInfo pb = p.PropertyBuilder;
1357 if (pb != null && filter (pb, criteria) == true)
1358 members.Add (p.PropertyBuilder);
1361 if (indexers != null)
1362 foreach (Indexer ix in indexers) {
1363 if ((ix.ModFlags & modflags) == 0)
1364 continue;
1365 if ((ix.ModFlags & static_mask) != static_flags)
1366 continue;
1368 MemberInfo ib = ix.PropertyBuilder;
1369 if (ib != null && filter (ib, criteria) == true) {
1370 members.Add (ix.PropertyBuilder);
1375 if ((mt & MemberTypes.NestedType) != 0) {
1376 if (types != null){
1377 foreach (TypeContainer t in types) {
1378 if ((t.ModFlags & modflags) == 0)
1379 continue;
1381 TypeBuilder tb = t.TypeBuilder;
1382 if (tb != null && (filter (tb, criteria) == true))
1383 members.Add (tb);
1387 if (enums != null){
1388 foreach (Enum en in enums){
1389 if ((en.ModFlags & modflags) == 0)
1390 continue;
1392 TypeBuilder tb = en.TypeBuilder;
1393 if (tb != null && (filter (tb, criteria) == true))
1394 members.Add (tb);
1398 if (delegates != null){
1399 foreach (Delegate d in delegates){
1400 if ((d.ModFlags & modflags) == 0)
1401 continue;
1403 TypeBuilder tb = d.TypeBuilder;
1404 if (tb != null && (filter (tb, criteria) == true))
1405 members.Add (tb);
1409 if (interfaces != null){
1410 foreach (Interface iface in interfaces){
1411 if ((iface.ModFlags & modflags) == 0)
1412 continue;
1414 TypeBuilder tb = iface.TypeBuilder;
1415 if (tb != null && (filter (tb, criteria) == true))
1416 members.Add (tb);
1421 if ((mt & MemberTypes.Constructor) != 0){
1422 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1423 foreach (Constructor c in instance_constructors){
1424 if ((c.ModFlags & modflags) == 0)
1425 continue;
1427 ConstructorBuilder cb = c.ConstructorBuilder;
1428 if (cb != null)
1429 if (filter (cb, criteria) == true)
1430 members.Add (cb);
1434 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null) &&
1435 ((default_static_constructor.ModFlags & modflags) != 0)){
1436 ConstructorBuilder cb =
1437 default_static_constructor.ConstructorBuilder;
1439 if (cb != null)
1440 if (filter (cb, criteria) == true)
1441 members.Add (cb);
1446 // Lookup members in parent if requested.
1448 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1449 if ((mt & ~MemberTypes.Constructor) != 0) {
1450 MemberList list = FindMembers (TypeBuilder.BaseType, mt & ~MemberTypes.Constructor, bf, filter, criteria);
1451 members.AddRange (list);
1455 Timer.StopTimer (TimerType.TcFindMembers);
1457 return new MemberList (members);
1460 public override MemberCache MemberCache {
1461 get {
1462 return member_cache;
1466 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1467 MemberFilter filter, object criteria)
1469 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1471 if (tc != null)
1472 return tc.FindMembers (mt, bf, filter, criteria);
1473 else
1474 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1478 // FindMethods will look for methods not only in the type `t', but in
1479 // any interfaces implemented by the type.
1481 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1482 MemberFilter filter, object criteria)
1484 return null;
1487 /// <summary>
1488 /// Emits the values for the constants
1489 /// </summary>
1490 public void EmitConstants ()
1492 if (constants != null)
1493 foreach (Const con in constants)
1494 con.EmitConstant (this);
1495 return;
1498 /// <summary>
1499 /// Emits the code, this step is performed after all
1500 /// the types, enumerations, constructors
1501 /// </summary>
1502 public void Emit ()
1504 if (instance_constructors != null)
1505 foreach (Constructor c in instance_constructors)
1506 c.Emit (this);
1508 if (default_static_constructor != null)
1509 default_static_constructor.Emit (this);
1511 if (methods != null)
1512 foreach (Method m in methods)
1513 m.Emit (this);
1515 if (properties != null)
1516 foreach (Property p in properties)
1517 p.Emit (this);
1519 if (indexers != null){
1520 foreach (Indexer ix in indexers)
1521 ix.Emit (this);
1523 /*CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1524 this, IndexerName, ModFlags, Location);
1525 TypeBuilder.SetCustomAttribute (cb);*/
1528 if (fields != null)
1529 foreach (Field f in fields)
1530 f.Emit (this);
1532 if (events != null){
1533 foreach (Event e in Events)
1534 e.Emit (this);
1537 if (Pending != null)
1538 if (Pending.VerifyPendingMethods ())
1539 return;
1541 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1544 // Check for internal or private fields that were never assigned
1546 if (fields != null && RootContext.WarningLevel >= 3) {
1547 foreach (Field f in fields) {
1548 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1549 continue;
1551 if (f.status == 0){
1552 Report.Warning (
1553 169, f.Location, "Private field " +
1554 MakeName (f.Name) + " is never used");
1555 continue;
1559 // Only report 649 on level 4
1561 if (RootContext.WarningLevel < 4)
1562 continue;
1564 if ((f.status & Field.Status.ASSIGNED) != 0)
1565 continue;
1567 Report.Warning (
1568 649, f.Location,
1569 "Field " + MakeName (f.Name) + " is never assigned " +
1570 " to and will always have its default value");
1574 // if (types != null)
1575 // foreach (TypeContainer tc in types)
1576 // tc.Emit ();
1579 public override void CloseType ()
1581 try {
1582 if (!Created){
1583 Created = true;
1584 TypeBuilder.CreateType ();
1586 } catch (TypeLoadException){
1588 // This is fine, the code still created the type
1590 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1591 // Console.WriteLine (e.Message);
1592 } catch {
1593 Console.WriteLine ("In type: " + Name);
1594 throw;
1597 if (Enums != null)
1598 foreach (Enum en in Enums)
1599 en.CloseType ();
1601 if (interface_order != null){
1602 foreach (Interface iface in interface_order)
1603 iface.CloseType ();
1606 if (Types != null){
1607 foreach (TypeContainer tc in Types)
1608 if (tc is Struct)
1609 tc.CloseType ();
1611 foreach (TypeContainer tc in Types)
1612 if (!(tc is Struct))
1613 tc.CloseType ();
1616 if (Delegates != null)
1617 foreach (Delegate d in Delegates)
1618 d.CloseType ();
1621 public string MakeName (string n)
1623 return "`" + Name + "." + n + "'";
1626 public void Warning_KeywordShadowsRequired (Location l, MemberInfo mi)
1628 Report.Warning (
1629 108, l, "The keyword 'Shadows' is required on " +
1630 MakeName (mi.Name) + " because it shadows `" +
1631 mi.ReflectedType.Name + "." + mi.Name + "'");
1634 public void Warning_KewywordShadowsNotRequired (Location l, MemberCore mc)
1636 Report.Warning (
1637 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1638 "inherited member, the keyword shadows is not required");
1641 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1643 Report.Warning (
1644 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1645 "inherited member, the keyword new is not required");
1648 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1650 return 0;
1654 // Performs the validation on a Method's modifiers (properties have
1655 // the same properties).
1657 public bool MethodModifiersValid (int flags, string n, Location loc)
1659 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1660 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1661 const int nv = (Modifiers.SHADOWS | Modifiers.VIRTUAL);
1662 bool ok = true;
1663 string name = MakeName (n);
1666 // At most one of static, virtual or override
1668 if ((flags & Modifiers.STATIC) != 0){
1669 if ((flags & vao) != 0){
1670 Report.Error (
1671 30501, loc, "Shared method " + name + " can not be " +
1672 "declared as Overridable");
1673 ok = false;
1677 if (this is Struct){
1678 if ((flags & va) != 0){
1679 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1680 ok = false;
1684 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.VIRTUAL) != 0)
1686 Report.Error (
1687 30730, loc, name +
1688 ": Methods marked as Overrides cannot be made Overridable");
1689 ok = false;
1692 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.SHADOWS) != 0){
1693 Report.Error (
1694 31408, loc, name +
1695 ": Methods marked as Overrides cannot be marked as Shadows");
1696 ok = false;
1700 // If the declaration includes the abstract modifier, then the
1701 // declaration does not include static, virtual or extern
1703 if ((flags & Modifiers.ABSTRACT) != 0){
1704 if ((flags & Modifiers.EXTERN) != 0){
1705 Report.Error (
1706 180, loc, name + " can not be both abstract and extern");
1707 ok = false;
1710 if ((flags & Modifiers.VIRTUAL) != 0){
1711 Report.Error (
1712 503, loc, name + " can not be both abstract and virtual");
1713 ok = false;
1716 if((ModFlags & Modifiers.SEALED) != 0){
1717 Report.Error (
1718 30607, loc,
1719 "Class declared as 'NotInheritable' " +
1720 "cannot have a 'MustOverride' member");
1721 ok = false;
1723 else if ((ModFlags & Modifiers.ABSTRACT) == 0){
1724 Report.Error (
1725 31411, loc, name +
1726 " is declared as 'MustOverride', hence its container " +
1727 "class should be declared as 'MustInherit'");
1728 ok = false;
1733 if ((flags & Modifiers.PRIVATE) != 0){
1734 if ((flags & vao) != 0){
1735 Report.Error (
1736 31408, loc, name +
1737 ": Members marked as Overridable or Overrides can not be Private");
1738 ok = false;
1742 if ((flags & Modifiers.SEALED) != 0){
1743 if ((flags & Modifiers.OVERRIDE) == 0){
1744 Report.Error (
1745 238, loc, name +
1746 ": cannot be sealed because it is not an override");
1747 ok = false;
1750 if ((flags & Modifiers.NEW) != 0){
1751 if ((flags & Modifiers.SHADOWS) != 0){
1752 Report.Error (
1753 31408, loc,
1754 " 'Overloads' and 'Shadows' cannot be combined ");
1755 ok = false;
1759 return ok;
1762 // Access level of a type.
1763 enum AccessLevel {
1764 Public = 0,
1765 ProtectedInternal = 1,
1766 Internal = 2,
1767 Protected = 3,
1768 Private = 4
1771 // Check whether `flags' denotes a more restricted access than `level'
1772 // and return the new level.
1773 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1775 AccessLevel old_level = level;
1777 if ((flags & Modifiers.INTERNAL) != 0) {
1778 if ((flags & Modifiers.PROTECTED) != 0) {
1779 if ((int) level < (int) AccessLevel.ProtectedInternal)
1780 level = AccessLevel.ProtectedInternal;
1781 } else {
1782 if ((int) level < (int) AccessLevel.Internal)
1783 level = AccessLevel.Internal;
1785 } else if ((flags & Modifiers.PROTECTED) != 0) {
1786 if ((int) level < (int) AccessLevel.Protected)
1787 level = AccessLevel.Protected;
1788 } else if ((flags & Modifiers.PRIVATE) != 0)
1789 level = AccessLevel.Private;
1791 return level;
1794 // Return the access level for a new member which is defined in the current
1795 // TypeContainer with access modifiers `flags'.
1796 AccessLevel GetAccessLevel (int flags)
1798 if ((flags & Modifiers.PRIVATE) != 0)
1799 return AccessLevel.Private;
1801 AccessLevel level;
1802 if (!IsTopLevel && (Parent != null))
1803 level = Parent.GetAccessLevel (flags);
1804 else
1805 level = AccessLevel.Public;
1807 return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1810 // Return the access level for type `t', but don't give more access than `flags'.
1811 static AccessLevel GetAccessLevel (Type t, int flags)
1813 if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1814 return AccessLevel.Private;
1816 AccessLevel level;
1817 if (TypeManager.IsBuiltinType (t))
1818 return AccessLevel.Public;
1819 else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1820 level = GetAccessLevel (t.DeclaringType, flags);
1821 else {
1822 level = CheckAccessLevel (AccessLevel.Public, flags);
1825 if (t.IsNestedPublic)
1826 return level;
1828 if (t.IsNestedAssembly || t.IsNotPublic) {
1829 if ((int) level < (int) AccessLevel.Internal)
1830 level = AccessLevel.Internal;
1833 if (t.IsNestedFamily) {
1834 if ((int) level < (int) AccessLevel.Protected)
1835 level = AccessLevel.Protected;
1838 if (t.IsNestedFamORAssem) {
1839 if ((int) level < (int) AccessLevel.ProtectedInternal)
1840 level = AccessLevel.ProtectedInternal;
1843 return level;
1847 // Returns true if `parent' is as accessible as the flags `flags'
1848 // given for this member.
1850 public bool AsAccessible (Type parent, int flags)
1852 while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1853 parent = parent.GetElementType ();
1855 AccessLevel level = GetAccessLevel (flags);
1856 AccessLevel level2 = GetAccessLevel (parent, flags);
1858 return (int) level >= (int) level2;
1861 Hashtable builder_and_args;
1863 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1865 if (builder_and_args == null)
1866 builder_and_args = new Hashtable ();
1867 return true;
1870 /// <summary>
1871 /// Performs checks for an explicit interface implementation. First it
1872 /// checks whether the `interface_type' is a base inteface implementation.
1873 /// Then it checks whether `name' exists in the interface type.
1874 /// </summary>
1875 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1877 bool found = false;
1879 if (ifaces != null){
1880 foreach (Type t in ifaces){
1881 if (t == interface_type){
1882 found = true;
1883 break;
1888 if (!found){
1889 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1890 return false;
1893 return true;
1896 public static void Error_NotInterfaceMember (Location loc, string member_name, string iface_name)
1898 Report.Error (30401, loc, "'" + member_name + "' is not a member of the interface '" + iface_name + "'");
1902 // IMemberContainer
1905 string IMemberContainer.Name {
1906 get {
1907 return Name;
1911 Type IMemberContainer.Type {
1912 get {
1913 return TypeBuilder;
1917 IMemberContainer IMemberContainer.Parent {
1918 get {
1919 return parent_container;
1923 MemberCache IMemberContainer.MemberCache {
1924 get {
1925 return member_cache;
1929 bool IMemberContainer.IsInterface {
1930 get {
1931 return this is Interface;
1935 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1937 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1942 public class Class : TypeContainer {
1943 // <summary>
1944 // Modifiers allowed in a class declaration
1945 // </summary>
1946 public const int AllowedModifiers =
1947 Modifiers.NEW |
1948 Modifiers.PUBLIC |
1949 Modifiers.PROTECTED |
1950 Modifiers.INTERNAL |
1951 Modifiers.PRIVATE |
1952 Modifiers.ABSTRACT |
1953 Modifiers.SEALED ;
1955 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1956 : base (parent, name, l)
1958 int accmods;
1960 if (parent.Parent == null)
1961 accmods = Modifiers.INTERNAL;
1962 else
1963 accmods = Modifiers.PUBLIC;
1965 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1966 this.attributes = attrs;
1970 // FIXME: How do we deal with the user specifying a different
1971 // layout?
1973 public override TypeAttributes TypeAttr {
1974 get {
1975 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1980 public class Struct : TypeContainer {
1981 // <summary>
1982 // Modifiers allowed in a struct declaration
1983 // </summary>
1984 public const int AllowedModifiers =
1985 Modifiers.NEW |
1986 Modifiers.PUBLIC |
1987 Modifiers.PROTECTED |
1988 Modifiers.INTERNAL |
1989 Modifiers.UNSAFE |
1990 Modifiers.PRIVATE;
1992 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1993 : base (parent, name, l)
1995 int accmods;
1997 if (parent.Parent == null)
1998 accmods = Modifiers.INTERNAL;
1999 else
2000 accmods = Modifiers.PUBLIC;
2002 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2004 this.ModFlags |= Modifiers.SEALED;
2005 this.attributes = attrs;
2010 // FIXME: Allow the user to specify a different set of attributes
2011 // in some cases (Sealed for example is mandatory for a class,
2012 // but what SequentialLayout can be changed
2014 public override TypeAttributes TypeAttr {
2015 get {
2016 return base.TypeAttr |
2017 TypeAttributes.SequentialLayout |
2018 TypeAttributes.Sealed |
2019 TypeAttributes.BeforeFieldInit;
2024 public abstract class MethodCore : MemberBase {
2025 public /* readonly */ Parameters Parameters;
2026 Block block;
2029 // Parameters, cached for semantic analysis.
2031 protected InternalParameters parameter_info;
2032 protected Type [] parameter_types;
2034 // Whether this is an operator
2035 public bool IsOperator;
2037 public MethodCore (Expression type, int mod, int allowed_mod, string name,
2038 Attributes attrs, Parameters parameters, Location loc)
2039 : base (type, mod, allowed_mod, name, attrs, loc)
2041 Parameters = parameters;
2045 // Returns the System.Type array for the parameters of this method
2047 public Type [] ParameterTypes {
2048 get {
2049 return parameter_types;
2053 public InternalParameters ParameterInfo
2055 get {
2056 return parameter_info;
2060 public Block Block {
2061 get {
2062 return block;
2065 set {
2066 block = value;
2070 protected virtual bool DoDefineParameters (TypeContainer parent)
2072 // Check if arguments were correct
2073 parameter_types = Parameters.GetParameterInfo (parent);
2074 if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
2075 return false;
2077 parameter_info = new InternalParameters (parent, Parameters);
2079 return true;
2082 public CallingConventions GetCallingConvention (bool is_class)
2084 CallingConventions cc = 0;
2086 cc = Parameters.GetCallingConvention ();
2088 if (is_class)
2089 if ((ModFlags & Modifiers.STATIC) == 0)
2090 cc |= CallingConventions.HasThis;
2092 // FIXME: How is `ExplicitThis' used in C#?
2094 return cc;
2097 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
2099 LabelParameters (ec, parameters, builder, null);
2102 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder, Parameters p_params)
2105 // Define each type attribute (in/out/ref) and
2106 // the argument names.
2108 Parameter [] p = p_params == null ? Parameters.FixedParameters : p_params.FixedParameters;
2109 int i = 0;
2111 MethodBuilder mb = null;
2112 ConstructorBuilder cb = null;
2114 if (builder is MethodBuilder)
2115 mb = (MethodBuilder) builder;
2116 else
2117 cb = (ConstructorBuilder) builder;
2119 if (p != null){
2120 for (i = 0; i < p.Length; i++) {
2121 ParameterBuilder pb;
2123 if (mb == null)
2124 pb = cb.DefineParameter (
2125 i + 1, p [i].Attributes, p [i].Name);
2126 else
2127 pb = mb.DefineParameter (
2128 i + 1, p [i].Attributes, p [i].Name);
2130 if (p [i].ParameterInitializer != null) {
2131 if (p [i].ParameterInitializer is MemberAccess) {
2132 MemberAccess ma = p [i].ParameterInitializer as MemberAccess;
2134 Expression const_ex = ma.Resolve(ec);
2135 if (const_ex is EnumConstant)
2136 pb.SetConstant (((EnumConstant) const_ex).Child.GetValue());
2137 else
2138 Report.Error(-1,
2139 "Internal error - Non supported argument type in optional parameter");
2141 else
2142 pb.SetConstant (((Constant) p [i].ParameterInitializer).GetValue());
2145 Attributes attr = p [i].OptAttributes;
2146 if (attr != null)
2147 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
2151 if (Parameters.ArrayParameter != null){
2152 ParameterBuilder pb;
2153 Parameter array_param = Parameters.ArrayParameter;
2155 if (mb == null)
2156 pb = cb.DefineParameter (
2157 i + 1, array_param.Attributes,
2158 array_param.Name);
2159 else
2160 pb = mb.DefineParameter (
2161 i + 1, array_param.Attributes,
2162 array_param.Name);
2164 CustomAttributeBuilder a = new CustomAttributeBuilder (
2165 TypeManager.cons_param_array_attribute, new object [0]);
2167 pb.SetCustomAttribute (a);
2172 public class Method : MethodCore {
2173 public MethodBuilder MethodBuilder;
2174 public MethodData MethodData;
2176 /// <summary>
2177 /// Modifiers allowed in a class declaration
2178 /// </summary>
2179 const int AllowedModifiers =
2180 Modifiers.NEW |
2181 Modifiers.PUBLIC |
2182 Modifiers.PROTECTED |
2183 Modifiers.INTERNAL |
2184 Modifiers.PRIVATE |
2185 Modifiers.STATIC |
2186 Modifiers.VIRTUAL |
2187 Modifiers.NONVIRTUAL |
2188 Modifiers.OVERRIDE |
2189 Modifiers.ABSTRACT |
2190 Modifiers.UNSAFE |
2191 Modifiers.EXTERN|
2192 Modifiers.SHADOWS;
2195 // return_type can be "null" for VOID values.
2197 public Method (Expression return_type, int mod, string name, Parameters parameters,
2198 Attributes attrs, Location l)
2199 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2201 Implements = null;
2204 public Method (Expression return_type, int mod, string name, Parameters parameters,
2205 Attributes attrs, ArrayList impl_what, Location l)
2206 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2208 Implements = impl_what;
2212 // Returns the `System.Type' for the ReturnType of this
2213 // function. Provides a nice cache. (used between semantic analysis
2214 // and actual code generation
2216 public Type GetReturnType ()
2218 return MemberType;
2221 void DuplicateEntryPoint (MethodInfo b, Location location)
2223 Report.Error (
2224 30738, location,
2225 "Program `" + CodeGen.FileName +
2226 "' has more than one entry point defined: `" +
2227 TypeManager.MonoBASIC_Signature(b) + "'");
2230 void Report28 (MethodInfo b)
2232 if (RootContext.WarningLevel < 4)
2233 return;
2235 Report.Warning (
2236 28, Location,
2237 "`" + TypeManager.MonoBASIC_Signature(b) +
2238 "' has the wrong signature to be an entry point");
2241 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2243 if (b.ReturnType != TypeManager.void_type &&
2244 b.ReturnType != TypeManager.int32_type)
2245 return false;
2247 if (pinfo.Count == 0)
2248 return true;
2250 if (pinfo.Count > 1)
2251 return false;
2253 Type t = pinfo.ParameterType(0);
2254 if (t.IsArray &&
2255 (t.GetArrayRank() == 1) &&
2256 (t.GetElementType() == TypeManager.string_type) &&
2257 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2258 return true;
2259 else
2260 return false;
2264 // Checks our base implementation if any
2266 protected override bool CheckBase (TypeContainer parent)
2268 // Check whether arguments were correct.
2269 if (!DoDefineParameters (parent))
2270 return false;
2272 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2273 if (!IsOperator) {
2274 MemberList mi_this;
2276 mi_this = TypeContainer.FindMembers (
2277 parent.TypeBuilder, MemberTypes.Method,
2278 BindingFlags.NonPublic | BindingFlags.Public |
2279 BindingFlags.Static | BindingFlags.Instance |
2280 BindingFlags.DeclaredOnly,
2281 MethodSignature.method_signature_filter, ms);
2283 if (mi_this.Count > 0) {
2284 Report.Error (111, Location, "Class `" + parent.Name + "' " +
2285 "already defines a member called `" + Name + "' " +
2286 "with the same parameter types");
2287 return false;
2292 // Verify if the parent has a type with the same name, and then
2293 // check whether we have to create a new slot for it or not.
2295 Type ptype = parent.TypeBuilder.BaseType;
2297 // ptype is only null for System.Object while compiling corlib.
2298 if (ptype != null){
2299 MemberList mi, mi_static, mi_instance;
2301 mi_static = TypeContainer.FindMembers (
2302 ptype, MemberTypes.Method,
2303 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2304 MethodSignature.inheritable_method_signature_filter, ms);
2306 mi_instance = TypeContainer.FindMembers (
2307 ptype, MemberTypes.Method,
2308 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2309 MethodSignature.inheritable_method_signature_filter,
2310 ms);
2312 if (mi_instance.Count > 0){
2313 mi = mi_instance;
2314 } else if (mi_static.Count > 0)
2315 mi = mi_static;
2316 else
2317 mi = null;
2319 if (mi != null && mi.Count > 0){
2320 parent_method = (MethodInfo) mi [0];
2321 string name = parent_method.DeclaringType.Name + "." +
2322 parent_method.Name;
2324 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2325 return false;
2327 if ((ModFlags & Modifiers.NEW) == 0) {
2328 Type parent_ret = TypeManager.TypeToCoreType (
2329 parent_method.ReturnType);
2331 if (parent_ret != MemberType) {
2332 Report.Error (
2333 508, parent.MakeName (Name) + ": cannot " +
2334 "change return type when overriding " +
2335 "inherited member " + name);
2336 return false;
2339 } else {
2340 /*if ((ModFlags & Modifiers.NEW) != 0)
2341 WarningNotHiding (parent);*/
2343 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2344 Report.Error (30284, Location,
2345 parent.MakeName (Name) +
2346 " : No suitable methods found to override");
2348 if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0)
2350 if ((ModFlags & Modifiers.NONVIRTUAL) != 0)
2352 Report.Error (31088, Location,
2353 parent.MakeName (Name) + " : Cannot " +
2354 "be declared NotOverridable since this method is " +
2355 "not maked as Overrides");
2358 // if a member of module is not inherited from Object class
2359 // can not be declared protected
2360 if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
2361 Report.Error (31066, Location,
2362 "'Sub' or 'Function' inside a 'Module' can not be declared as " +
2363 "'Protected' or 'Protected Friend'");
2366 /* else if ((ModFlags & Modifiers.NEW) != 0)
2367 WarningNotHiding (parent);
2370 return true;
2374 // Creates the type
2376 public override bool Define (TypeContainer parent)
2378 if (!DoDefine (parent))
2379 return false;
2381 if (!CheckBase (parent))
2382 return false;
2384 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
2385 Report.Error (31067, Location,
2386 "'Sub' or 'Function' inside a 'Structure' can not be declared as " +
2387 "'Protected' or 'Protected Friend'");
2389 CallingConventions cc = GetCallingConvention (parent is Class);
2391 MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2392 ParameterInfo, cc, OptAttributes,
2393 ModFlags, flags, true);
2395 if (!MethodData.Define (parent))
2396 return false;
2398 MethodBuilder = MethodData.MethodBuilder;
2401 // This is used to track the Entry Point,
2403 if (Name.ToUpper() == "MAIN" &&
2404 ((ModFlags & Modifiers.STATIC) != 0) &&
2405 (RootContext.MainClass == null ||
2406 RootContext.MainClass == parent.TypeBuilder.FullName ||
2407 (RootContext.RootNamespace != null &&
2408 RootContext.RootNamespace.Length > 0 &&
2409 (RootContext.RootNamespace + "." + RootContext.MainClass) == parent.TypeBuilder.FullName))) {
2410 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2411 if (RootContext.EntryPoint == null) {
2412 RootContext.EntryPoint = MethodBuilder;
2413 RootContext.EntryPointLocation = Location;
2414 } else {
2415 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2416 DuplicateEntryPoint (MethodBuilder, Location);
2418 } else
2419 Report28(MethodBuilder);
2422 return true;
2426 // Emits the code
2428 public void Emit (TypeContainer parent)
2430 MethodData.Emit (parent, Block, this);
2434 public abstract class ConstructorInitializer {
2435 ArrayList argument_list;
2436 ConstructorInfo parent_constructor;
2437 Parameters parameters;
2438 Location loc;
2439 public bool implicit_initialization;
2441 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2442 Location loc)
2444 this.argument_list = argument_list;
2445 this.parameters = parameters;
2446 this.loc = loc;
2447 this.implicit_initialization = false;
2450 public ArrayList Arguments {
2451 get {
2452 return argument_list;
2456 public ConstructorInfo ParentConstructor
2460 return parent_constructor;
2464 public bool Resolve (EmitContext ec)
2466 Expression parent_constructor_group;
2467 Type t;
2469 ec.CurrentBlock = new Block (null, true, parameters);
2471 if (argument_list != null){
2472 foreach (Argument a in argument_list){
2473 if (!a.Resolve (ec, loc))
2474 return false;
2478 ec.CurrentBlock = null;
2480 if (this is ConstructorBaseInitializer) {
2481 if (ec.ContainerType.BaseType == null)
2482 return true;
2484 t = ec.ContainerType.BaseType;
2485 if (ec.ContainerType.IsValueType){
2486 Report.Error (522, loc,
2487 "structs cannot call base class constructors");
2488 return false;
2491 else
2492 t = ec.ContainerType;
2494 parent_constructor_group = Expression.MemberLookup (
2495 ec, t, t, ".ctor",
2496 MemberTypes.Constructor,
2497 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2498 loc);
2500 if (parent_constructor_group == null){
2501 Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
2502 return false;
2505 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2506 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2508 if (parent_constructor == null) {
2509 if (this.implicit_initialization)
2510 Report.Error (30148, loc, "Must declare 'MyBase.New' in the constructor " +
2511 "of the class '" + ec.TypeContainer.Name + "' with appropriate arguments, since the base class '" +
2512 t.FullName + "' does not contain a definition of 'New' without any parameter");
2513 else
2514 Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
2516 return false;
2519 return true;
2522 public void Emit (EmitContext ec)
2524 if (parent_constructor != null){
2525 if (ec.IsStatic)
2526 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2527 else
2528 Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2535 public class ConstructorBaseInitializer : ConstructorInitializer {
2536 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2537 base (argument_list, pars, l)
2542 public class ConstructorThisInitializer : ConstructorInitializer {
2543 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2544 base (argument_list, pars, l)
2549 public class Constructor : MethodCore {
2550 public ConstructorBuilder ConstructorBuilder;
2551 public ConstructorInitializer Initializer;
2552 new public Attributes OptAttributes;
2554 // <summary>
2555 // Modifiers allowed for a constructor.
2556 // </summary>
2557 public const int AllowedModifiers =
2558 Modifiers.PUBLIC |
2559 Modifiers.PROTECTED |
2560 Modifiers.INTERNAL |
2561 Modifiers.STATIC |
2562 Modifiers.UNSAFE |
2563 Modifiers.EXTERN |
2564 Modifiers.PRIVATE;
2567 // The spec claims that static is not permitted, but
2568 // my very own code has static constructors.
2570 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2571 : base (null, 0, AllowedModifiers, name, null, args, l)
2573 Initializer = init;
2576 public Constructor (string name, int mod, Parameters args, ConstructorInitializer init, Location l)
2577 : base (null, mod, AllowedModifiers, name, null, args, l)
2579 Initializer = init;
2583 // Returns true if this is a default constructor
2585 public bool IsDefault ()
2587 if ((ModFlags & Modifiers.STATIC) != 0)
2588 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2589 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2591 else
2592 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2593 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2594 (Initializer is ConstructorBaseInitializer) &&
2595 (Initializer.Arguments == null);
2599 // Creates the ConstructorBuilder
2601 public override bool Define (TypeContainer parent)
2603 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2604 MethodAttributes.SpecialName);
2606 if (parent.EventHandlers != null) {
2607 ArrayList hdlrs = parent.EventHandlers;
2608 foreach(Statement stmt in hdlrs)
2609 this.Block.AddStatement (stmt);
2613 // Check if arguments were correct.
2614 if (!DoDefineParameters (parent))
2615 return false;
2617 if ((ModFlags & Modifiers.STATIC) != 0) {
2618 ca |= MethodAttributes.Static;
2620 if (this.Parameters != Parameters.EmptyReadOnlyParameters)
2621 Report.Error (
2622 30479, Location,
2623 "Shared constructor can not have parameters");
2625 if ((ModFlags & Modifiers.Accessibility) != 0)
2626 Report.Error (
2627 30480, Location,
2628 "Shared constructor can not be declared " +
2629 "explicitly as public, private, friend or protected");
2631 if (this.Initializer != null)
2632 Report.Error (
2633 30043, Location,
2634 "Keywords like MyBase, MyClass, Me are not " +
2635 "valid inside a Shared Constructor");
2637 else {
2638 if (parent is Struct && ParameterTypes.Length == 0) {
2639 Report.Error (
2640 30629, Location,
2641 "Structs can not contain explicit parameterless " +
2642 "constructors");
2643 return false;
2645 ca |= MethodAttributes.HideBySig;
2647 if ((ModFlags & Modifiers.PUBLIC) != 0)
2648 ca |= MethodAttributes.Public;
2649 else if ((ModFlags & Modifiers.PROTECTED) != 0) {
2650 if ((ModFlags & Modifiers.INTERNAL) != 0)
2651 ca |= MethodAttributes.FamORAssem;
2652 else
2653 ca |= MethodAttributes.Family;
2655 else if ((ModFlags & Modifiers.INTERNAL) != 0)
2656 ca |= MethodAttributes.Assembly;
2657 else if (IsDefault ())
2658 ca |= MethodAttributes.Public;
2659 else
2660 ca |= MethodAttributes.Private;
2663 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2664 ca, GetCallingConvention (parent is Class), ParameterTypes);
2667 // HACK because System.Reflection.Emit is lame
2669 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2670 Report.Error (
2671 111, Location,
2672 "Class `" +parent.Name+ "' already contains a definition with the " +
2673 "same return value and parameter types for constructor `" + Name
2674 + "'");
2675 return false;
2678 return true;
2682 // Emits the code
2684 public void Emit (TypeContainer parent)
2686 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2687 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2689 if ((ModFlags & Modifiers.STATIC) == 0){
2690 if (parent is Class && Initializer == null) {
2691 Initializer = new ConstructorBaseInitializer (
2692 null, Parameters.EmptyReadOnlyParameters, parent.Location);
2693 Initializer.implicit_initialization = true;
2697 // Spec mandates that Initializers will not have
2698 // `this' access
2700 ec.IsStatic = true;
2701 if (Initializer != null && !Initializer.Resolve (ec))
2702 return;
2703 ec.IsStatic = false;
2706 LabelParameters (ec, ParameterTypes, ConstructorBuilder);
2709 // Classes can have base initializers and instance field initializers.
2711 if (parent is Class){
2712 if ((ModFlags & Modifiers.STATIC) == 0)
2713 parent.EmitFieldInitializers (ec);
2716 if (Initializer != null) {
2717 if (this.ConstructorBuilder.Equals (Initializer.ParentConstructor))
2718 Report.Error (
2719 30297, Location,
2720 "A constructor can not call itself" );
2722 Initializer.Emit (ec);
2725 if ((ModFlags & Modifiers.STATIC) != 0)
2726 parent.EmitFieldInitializers (ec);
2728 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2730 // If this is a non-static `struct' constructor and doesn't have any
2731 // initializer, it must initialize all of the struct's fields.
2732 if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2733 (Initializer == null))
2734 Block.AddThisVariable (parent, Location);
2736 ec.EmitTopBlock (Block, ParameterInfo, Location);
2740 public class MethodData {
2742 // The return type of this method
2744 public readonly Type ReturnType;
2745 public readonly Type[] ParameterTypes;
2746 public readonly InternalParameters ParameterInfo;
2747 public readonly CallingConventions CallingConventions;
2748 public readonly Attributes OptAttributes;
2749 public readonly Location Location;
2752 // Are we implementing an interface ?
2754 public bool IsImplementing = false;
2757 // Protected data.
2759 protected MemberBase member;
2760 protected int modifiers;
2761 protected MethodAttributes flags;
2762 protected bool is_method;
2763 protected string accessor_name;
2764 ArrayList conditionals;
2766 MethodBuilder builder = null;
2767 public MethodBuilder MethodBuilder {
2768 get {
2769 return builder;
2773 public MethodData (MemberBase member, string name, Type return_type,
2774 Type [] parameter_types, InternalParameters parameters,
2775 CallingConventions cc, Attributes opt_attrs,
2776 int modifiers, MethodAttributes flags, bool is_method)
2778 this.member = member;
2779 this.accessor_name = name;
2780 this.ReturnType = return_type;
2781 this.ParameterTypes = parameter_types;
2782 this.ParameterInfo = parameters;
2783 this.CallingConventions = cc;
2784 this.OptAttributes = opt_attrs;
2785 this.modifiers = modifiers;
2786 this.flags = flags;
2787 this.is_method = is_method;
2788 this.Location = member.Location;
2789 this.conditionals = new ArrayList ();
2793 // Attributes.
2795 Attribute dllimport_attribute = null;
2796 string obsolete = null;
2797 bool obsolete_error = false;
2799 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2801 if ((opt_attrs == null) || (opt_attrs.Attrs == null))
2802 return true;
2804 foreach (Attribute a in opt_attrs.Attrs) {
2805 if (a.Name == "Conditional") {
2806 if (!ApplyConditionalAttribute (a))
2807 return false;
2808 } else if (a.Name == "Obsolete") {
2809 if (!ApplyObsoleteAttribute (a))
2810 return false;
2811 } else if (a.Name.IndexOf ("DllImport") != -1) {
2812 if (!is_method) {
2813 a.Type = TypeManager.dllimport_type;
2814 Attribute.Error_AttributeNotValidForElement (a, Location);
2815 return false;
2817 if (!ApplyDllImportAttribute (a))
2818 return false;
2822 return true;
2826 // Applies the `DllImport' attribute to the method.
2828 protected virtual bool ApplyDllImportAttribute (Attribute a)
2830 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2831 if ((modifiers & extern_static) != extern_static) {
2832 Report.Error (601, Location,
2833 "The DllImport attribute must be specified on a method " +
2834 "marked `static' and `extern'.");
2835 return false;
2838 flags |= MethodAttributes.PinvokeImpl;
2839 dllimport_attribute = a;
2840 return true;
2844 // Applies the `Obsolete' attribute to the method.
2846 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2848 if (obsolete != null) {
2849 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2850 return false;
2853 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2854 return obsolete != null;
2858 // Applies the `Conditional' attribute to the method.
2860 protected virtual bool ApplyConditionalAttribute (Attribute a)
2862 // The Conditional attribute is only valid on methods.
2863 if (!is_method) {
2864 Attribute.Error_AttributeNotValidForElement (a, Location);
2865 return false;
2868 string condition = a.Conditional_GetConditionName ();
2870 if (condition == null)
2871 return false;
2873 if (ReturnType != TypeManager.void_type) {
2874 Report.Error (578, Location,
2875 "Conditional not valid on `" + member.Name + "' " +
2876 "because its return type is not void");
2877 return false;
2880 if ((modifiers & Modifiers.OVERRIDE) != 0) {
2881 Report.Error (243, Location,
2882 "Conditional not valid on `" + member.Name + "' " +
2883 "because it is an override method");
2884 return false;
2887 if (member.IsExplicitImpl) {
2888 Report.Error (577, Location,
2889 "Conditional not valid on `" + member.Name + "' " +
2890 "because it is an explicit interface implementation");
2891 return false;
2894 if (IsImplementing) {
2895 Report.Error (623, Location,
2896 "Conditional not valid on `" + member.Name + "' " +
2897 "because it is an interface method");
2898 return false;
2901 conditionals.Add (condition);
2903 return true;
2907 // Checks whether this method should be ignored due to its Conditional attributes.
2909 bool ShouldIgnore (Location loc)
2911 // When we're overriding a virtual method, we implicitly inherit the
2912 // Conditional attributes from our parent.
2913 if (member.ParentMethod != null) {
2914 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2915 member.ParentMethod, loc);
2917 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2918 return true;
2921 foreach (string condition in conditionals)
2922 if (RootContext.AllDefines [condition] == null)
2923 return true;
2925 return false;
2929 // Returns the TypeManager.MethodFlags for this method.
2930 // This emits an error 619 / warning 618 if the method is obsolete.
2931 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2933 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2935 TypeManager.MethodFlags flags = 0;
2937 if (obsolete != null) {
2938 if (obsolete_error) {
2939 Report.Error (619, loc, "Method `" + member.Name +
2940 "' is obsolete: `" + obsolete + "'");
2941 return TypeManager.MethodFlags.IsObsoleteError;
2942 } else
2943 Report.Warning (618, loc, "Method `" + member.Name +
2944 "' is obsolete: `" + obsolete + "'");
2946 flags |= TypeManager.MethodFlags.IsObsolete;
2949 if (ShouldIgnore (loc))
2950 flags |= TypeManager.MethodFlags.ShouldIgnore;
2952 return flags;
2956 // Search all the interface bases recursively for unimplemented methods
2958 bool SearchBasesForAbstractMethods (
2959 TypeContainer parent, Type iface_type,
2960 string method_name, ref ArrayList implementing_list,
2961 ref ArrayList implementing_iface)
2963 MethodInfo implementing = null;
2964 bool IsImplementing = false;
2965 Type current_iface_type = iface_type;
2967 if (member is Indexer)
2968 implementing = parent.Pending.IsAbstractIndexer (
2969 current_iface_type , ReturnType, ParameterTypes);
2970 else
2971 implementing = parent.Pending.IsAbstractMethod (
2972 current_iface_type, method_name, ReturnType, ParameterTypes);
2974 if (implementing != null) {
2975 if (!implementing_list.Contains (implementing)) {
2976 implementing_list.Add (implementing);
2977 implementing_iface.Add(current_iface_type);
2979 IsImplementing = true;
2980 } else {
2981 Type[] current_iface_types = current_iface_type.GetInterfaces();
2982 if (current_iface_types.Length == 0)
2983 return false;
2985 foreach (Type curr_iface_type in current_iface_types) {
2986 IsImplementing = SearchBasesForAbstractMethods (
2987 parent, curr_iface_type, method_name,
2988 ref implementing_list, ref implementing_iface);
2990 if (IsImplementing)
2991 break;
2995 return IsImplementing;
2998 public virtual bool Define (TypeContainer parent)
3000 MethodInfo implementing = null;
3001 ArrayList implementing_list = null;
3002 ArrayList implementing_iface = null;
3003 string method_name, name, prefix, impl_method_name;
3004 int pos = -1;
3006 if (OptAttributes != null)
3007 if (!ApplyAttributes (OptAttributes, is_method))
3008 return false;
3010 if (accessor_name != null)
3011 name = accessor_name + "_" + member.ShortName;
3012 else
3013 name = member.ShortName;
3015 method_name = name;
3016 impl_method_name = name;
3018 if ((member.ModFlags & Modifiers.OVERRIDE) != 0) {
3019 if (parent.Pending == null)
3020 implementing = null;
3021 else if (member is Indexer)
3022 implementing = parent.Pending.IsAbstractIndexer (
3023 (Type) parent.TypeBuilder.BaseType,
3024 ReturnType, ParameterTypes);
3025 else
3026 implementing = parent.Pending.IsAbstractMethod (
3027 (Type) parent.TypeBuilder.BaseType, name,
3028 ReturnType, ParameterTypes);
3030 if (implementing != null)
3031 IsImplementing = true;
3034 if (member.Implements != null) {
3035 implementing_list = new ArrayList();
3036 implementing_iface = new ArrayList();
3038 foreach (Expression Impl in member.Implements) {
3039 name = Impl.ToString();
3040 prefix = name.Substring(0, name.LastIndexOf("."));
3041 name = name.Substring(name.LastIndexOf(".") + 1);
3043 if (accessor_name != null)
3044 impl_method_name = accessor_name + "_" + name;
3045 else
3046 impl_method_name = name;
3048 Type current_iface_type = (Type) member.InterfaceTypes[++pos];
3049 IsImplementing = SearchBasesForAbstractMethods (
3050 parent, current_iface_type, impl_method_name,
3051 ref implementing_list, ref implementing_iface);
3053 if (IsImplementing == false) {
3054 TypeContainer.Error_NotInterfaceMember (
3055 Location, name, prefix);
3056 return false;
3062 // For implicit implementations, make sure we are public, for
3063 // explicit implementations, make sure we are private.
3065 //if (IsImplementing){
3067 // Setting null inside this block will trigger a more
3068 // verbose error reporting for missing interface implementations
3070 // The "candidate" function has been flagged already
3071 // but it wont get cleared
3073 /* if (!member.IsExplicitImpl){
3075 // We already catch different accessibility settings
3076 // so we just need to check that we are not private
3078 if ((modifiers & Modifiers.PRIVATE) != 0)
3079 implementing = null;
3082 // Static is not allowed
3084 if ((modifiers & Modifiers.STATIC) != 0)
3085 implementing = null;
3086 } else {
3087 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3088 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3089 implementing = null;
3095 // If implementing is still valid, set flags
3097 if (IsImplementing){
3099 // When implementing interface methods, set NewSlot.
3101 if (implementing_list != null && implementing_list.Count != 0)
3102 flags |= MethodAttributes.NewSlot;
3104 flags |=
3105 MethodAttributes.Virtual |
3106 MethodAttributes.HideBySig;
3110 // Create the MethodBuilder for the method
3112 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3113 if ((modifiers & Modifiers.STATIC) == 0) {
3114 Report.Error (601, Location,
3115 "The DllImport attribute must be specified on " +
3116 "a method marked 'static' and 'extern'.");
3117 return false;
3120 EmitContext ec = new EmitContext (
3121 parent, Location, null, ReturnType, modifiers);
3123 builder = dllimport_attribute.DefinePInvokeMethod (
3124 ec, parent.TypeBuilder, method_name, flags,
3125 ReturnType, ParameterTypes);
3126 } else
3127 builder = parent.TypeBuilder.DefineMethod (
3128 method_name, flags, CallingConventions,
3129 ReturnType, ParameterTypes);
3131 if (builder == null)
3132 return false;
3134 if (IsImplementing) {
3136 // implement abstract methods from abstract classes
3138 if ((member.ModFlags & Modifiers.OVERRIDE) != 0) {
3139 if (member is Indexer)
3140 parent.Pending.ImplementIndexer (
3141 (Type) parent.TypeBuilder.BaseType,
3142 builder, ReturnType,
3143 ParameterTypes, true);
3144 else
3145 parent.Pending.ImplementMethod (
3146 (Type) parent.TypeBuilder.BaseType,
3147 name, ReturnType,
3148 ParameterTypes, member.IsExplicitImpl);
3152 // implement abstract methods of interfaces
3154 if (member.Implements != null) {
3155 pos = 0;
3156 foreach (MethodInfo Impl in implementing_list) {
3157 if (member is Indexer)
3158 parent.Pending.ImplementIndexer (
3159 (Type) implementing_iface[pos++],
3160 builder, ReturnType,
3161 ParameterTypes, true);
3162 else
3163 parent.Pending.ImplementMethod (
3164 (Type) implementing_iface[pos++],
3165 Impl.Name, ReturnType,
3166 ParameterTypes, member.IsExplicitImpl);
3168 parent.TypeBuilder.DefineMethodOverride (
3169 builder, Impl);
3175 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3176 Report.Error (111, Location,
3177 "Class `" + parent.Name +
3178 "' already contains a definition with the " +
3179 "same return value and parameter types as the " +
3180 "'get' method of property `" + member.Name + "'");
3181 return false;
3184 TypeManager.AddMethod (builder, this);
3185 return true;
3189 // Emits the code
3191 public virtual void Emit (TypeContainer parent, Block block, object kind)
3193 ILGenerator ig;
3194 EmitContext ec;
3196 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3197 ig = builder.GetILGenerator ();
3198 else
3199 ig = null;
3201 ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3203 if (OptAttributes != null)
3204 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
3206 if (member is MethodCore)
3207 ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder);
3210 // abstract or extern methods have no bodies
3212 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3213 if (block == null)
3214 return;
3217 // abstract or extern methods have no bodies.
3219 if ((modifiers & Modifiers.ABSTRACT) != 0)
3220 Report.Error (
3221 500, Location, "Abstract method `" +
3222 TypeManager.MonoBASIC_Signature (builder) +
3223 "' can not have a body");
3225 if ((modifiers & Modifiers.EXTERN) != 0)
3226 Report.Error (
3227 179, Location, "External method `" +
3228 TypeManager.MonoBASIC_Signature (builder) +
3229 "' can not have a body");
3231 return;
3235 // Methods must have a body unless they're extern or abstract
3237 if (block == null) {
3238 Report.Error (
3239 501, Location, "Method `" +
3240 TypeManager.MonoBASIC_Signature (builder) +
3241 "' must declare a body since it is not marked " +
3242 "abstract or extern");
3243 return;
3247 // Handle destructors specially
3249 // FIXME: This code generates buggy code
3251 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3252 EmitDestructor (ec, block);
3253 else {
3254 ISymbolWriter sw = CodeGen.SymbolWriter;
3256 if ((sw != null) && !Location.IsNull (Location) &&
3257 !Location.IsNull (block.EndLocation)) {
3258 Location end = block.EndLocation;
3259 MethodToken token = MethodBuilder.GetToken ();
3260 sw.OpenMethod (new SymbolToken (token.Token));
3261 // Avoid error if we don't support debugging for the platform
3262 try {
3263 sw.SetMethodSourceRange (Location.SymbolDocument,
3264 Location.Row, 0,
3265 end.SymbolDocument,
3266 end.Row, 0);
3267 } catch (Exception) {
3270 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3272 sw.CloseMethod ();
3273 } else
3274 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3278 void EmitDestructor (EmitContext ec, Block block)
3280 ILGenerator ig = ec.ig;
3282 Label finish = ig.DefineLabel ();
3283 bool old_in_try = ec.InTry;
3285 ig.BeginExceptionBlock ();
3286 ec.InTry = true;
3287 ec.ReturnLabel = finish;
3288 ec.HasReturnLabel = true;
3289 ec.EmitTopBlock (block, null, Location);
3290 ec.InTry = old_in_try;
3292 // ig.MarkLabel (finish);
3293 bool old_in_finally = ec.InFinally;
3294 ec.InFinally = true;
3295 ig.BeginFinallyBlock ();
3297 if (ec.ContainerType.BaseType != null) {
3298 Expression member_lookup = Expression.MemberLookup (
3299 ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
3300 MemberTypes.Method, Expression.AllBindingFlags, Location);
3302 if (member_lookup != null){
3303 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3305 ig.Emit (OpCodes.Ldarg_0);
3306 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3309 ec.InFinally = old_in_finally;
3311 ig.EndExceptionBlock ();
3312 //ig.MarkLabel (ec.ReturnLabel);
3313 ig.Emit (OpCodes.Ret);
3317 abstract public class MemberBase : MemberCore {
3318 public Expression Type;
3319 public readonly Attributes OptAttributes;
3320 public ArrayList Implements;
3322 protected MethodAttributes flags;
3325 // The "short" name of this property / indexer / event. This is the
3326 // name without the explicit interface.
3328 public string ShortName;
3331 // The type of this property / indexer / event
3333 public Type MemberType;
3336 // If true, this is an explicit interface implementation
3338 public bool IsExplicitImpl = false;
3341 // The name of the interface we are explicitly implementing
3343 public string ExplicitInterfaceName = null;
3346 // If true, the interface type we are explicitly implementing
3348 public Type InterfaceType = null;
3349 public ArrayList InterfaceTypes = null;
3352 // The method we're overriding if this is an override method.
3354 protected MethodInfo parent_method = null;
3355 public MethodInfo ParentMethod {
3356 get {
3357 return parent_method;
3362 // The constructor is only exposed to our children
3364 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3365 Attributes attrs, Location loc)
3366 : base (name, loc)
3368 Type = type;
3369 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PUBLIC, loc);
3370 OptAttributes = attrs;
3373 protected virtual bool CheckBase (TypeContainer parent)
3375 return true;
3378 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3380 bool error = false;
3382 foreach (Type partype in parameters){
3383 if (partype.IsPointer && !UnsafeOK (parent))
3384 error = true;
3386 if (parent.AsAccessible (partype, ModFlags))
3387 continue;
3389 if (this is Indexer)
3390 Report.Error (55, Location,
3391 "Inconsistent accessibility: parameter type `" +
3392 TypeManager.MonoBASIC_Name (partype) + "' is less " +
3393 "accessible than indexer `" + Name + "'");
3394 else
3395 Report.Error (51, Location,
3396 "Inconsistent accessibility: parameter type `" +
3397 TypeManager.MonoBASIC_Name (partype) + "' is less " +
3398 "accessible than method `" + Name + "'");
3399 error = true;
3402 return !error;
3405 protected virtual bool DoDefine (TypeContainer parent)
3407 if (Name == null)
3408 Name = "this";
3410 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3411 return false;
3413 flags = Modifiers.MethodAttr (ModFlags);
3415 // Lookup Type, verify validity
3416 MemberType = parent.ResolveType (Type, false, Location);
3417 if (MemberType == null)
3418 return false;
3420 // check for whether the Interface is implemented by the class
3421 if (Implements != null) {
3422 InterfaceTypes = new ArrayList ();
3423 foreach (Expression Impls in Implements) {
3424 string iname = Impls.ToString();
3425 iname = iname.Substring(0, iname.LastIndexOf("."));
3426 bool iface_found = false;
3428 InterfaceType = RootContext.LookupType (
3429 parent, iname, false, Location);
3430 if (InterfaceType == null)
3431 return false;
3433 InterfaceTypes.Add (InterfaceType);
3434 Type[] tbases = parent.TypeBuilder.GetInterfaces();
3436 if (tbases.Length != 0) {
3437 ArrayList bases = new ArrayList();
3438 TypeManager.ExpandAllInterfaces (tbases, ref bases);
3440 foreach (Type tbase in bases) {
3441 string bname = tbase.Name;
3442 if (bname.LastIndexOf(".") != -1)
3443 bname = bname.Substring(bname.LastIndexOf("."));
3445 if (bname == iname) {
3446 iface_found = true;
3447 break;
3452 if (!iface_found) {
3453 Report.Error (31035, Location,
3454 "Class '" + parent.Name + "' doesn't implement interface '" + iname + "'");
3455 return false;
3460 // verify accessibility
3461 if (!parent.AsAccessible (MemberType, ModFlags)) {
3462 if (this is Property)
3463 Report.Error (53, Location,
3464 "Inconsistent accessibility: property type `" +
3465 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3466 "accessible than property `" + Name + "'");
3467 else if (this is Indexer)
3468 Report.Error (54, Location,
3469 "Inconsistent accessibility: indexer return type `" +
3470 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3471 "accessible than indexer `" + Name + "'");
3472 else if (this is Method)
3473 Report.Error (50, Location,
3474 "Inconsistent accessibility: return type `" +
3475 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3476 "accessible than method `" + Name + "'");
3477 else
3478 Report.Error (52, Location,
3479 "Inconsistent accessibility: field type `" +
3480 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3481 "accessible than field `" + Name + "'");
3482 return false;
3485 if (MemberType.IsPointer && !UnsafeOK (parent))
3486 return false;
3489 // Check for explicit interface implementation
3491 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)) {
3492 int pos = Name.LastIndexOf (".");
3494 ExplicitInterfaceName = Name.Substring (0, pos);
3495 ShortName = Name.Substring (pos + 1);
3496 } else
3497 ShortName = Name;
3499 return true;
3504 // Fields and Events both generate FieldBuilders, we use this to share
3505 // their common bits. This is also used to flag usage of the field
3507 abstract public class FieldBase : MemberBase {
3508 public FieldBuilder FieldBuilder;
3509 public Status status;
3511 [Flags]
3512 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3515 // The constructor is only exposed to our children
3517 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3518 object init, Attributes attrs, Location loc)
3519 : base (type, mod, allowed_mod, name, attrs, loc)
3521 this.init = init;
3525 // Whether this field has an initializer.
3527 public bool HasInitializer {
3528 get {
3529 return init != null;
3533 // Private.
3534 readonly Object init;
3535 Expression init_expr;
3536 bool init_expr_initialized = false;
3539 // Resolves and returns the field initializer.
3541 public Expression GetInitializerExpression (EmitContext ec)
3543 if (init_expr_initialized)
3544 return init_expr;
3546 Expression e;
3547 if (init is Expression)
3548 e = (Expression) init;
3549 else
3550 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3552 ec.IsFieldInitializer = true;
3553 e = e.DoResolve (ec);
3554 ec.IsFieldInitializer = false;
3556 init_expr = e;
3557 init_expr_initialized = true;
3559 return init_expr;
3565 // The Field class is used to represents class/struct fields during parsing.
3567 public class Field : FieldBase {
3568 // <summary>
3569 // Modifiers allowed in a class declaration
3570 // </summary>
3571 const int AllowedModifiers =
3572 Modifiers.SHADOWS |
3573 Modifiers.PUBLIC |
3574 Modifiers.PROTECTED |
3575 Modifiers.INTERNAL |
3576 Modifiers.PRIVATE |
3577 Modifiers.STATIC |
3578 // Modifiers.VOLATILE |
3579 // Modifiers.UNSAFE |
3580 Modifiers.READONLY;
3582 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3583 Attributes attrs, Location loc)
3584 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3588 public override bool Define (TypeContainer parent)
3590 Type t = parent.ResolveType (Type, false, Location);
3592 if (t == null)
3593 return false;
3595 if (!parent.AsAccessible (t, ModFlags)) {
3596 Report.Error (52, Location,
3597 "Inconsistent accessibility: field type `" +
3598 TypeManager.MonoBASIC_Name (t) + "' is less " +
3599 "accessible than field `" + Name + "'");
3600 return false;
3603 if (t.IsPointer && !UnsafeOK (parent))
3604 return false;
3606 Type ptype = parent.TypeBuilder.BaseType;
3608 // ptype is only null for System.Object while compiling corlib.
3609 if (ptype != null){
3610 MemberList list = TypeContainer.FindMembers (
3611 ptype, MemberTypes.Field,
3612 BindingFlags.Public |
3613 BindingFlags.Static | BindingFlags.Instance,
3614 System.Type.FilterName, Name);
3616 if (RootContext.WarningLevel > 1){
3617 if ((list.Count > 0) && ((ModFlags & Modifiers.SHADOWS) == 0))
3619 Report.Warning (
3620 40004, 2, Location,
3621 "Variable '" + Name + "' should be declared " +
3622 "Shadows since the base type '" + ptype.Name +
3623 "' has a variable with same name");
3625 ModFlags |= Modifiers.SHADOWS;
3628 if (list.Count == 0)
3629 // if a member of module is not inherited from Object class
3630 // can not be declared protected
3631 if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
3632 Report.Error (30593, Location,
3633 "'Variable' inside a 'Module' can not be " +
3634 "declared as 'Protected'");
3637 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
3638 Report.Error (30435, Location,
3639 "'Variable' inside a 'Structure' can not be " +
3640 "declared as 'Protected'");
3642 if ((ModFlags & Modifiers.VOLATILE) != 0){
3643 if (!t.IsClass){
3644 if (TypeManager.IsEnumType (t))
3645 t = TypeManager.EnumToUnderlying (t);
3647 if (!((t == TypeManager.bool_type) ||
3648 (t == TypeManager.sbyte_type) ||
3649 (t == TypeManager.byte_type) ||
3650 (t == TypeManager.short_type) ||
3651 (t == TypeManager.ushort_type) ||
3652 (t == TypeManager.int32_type) ||
3653 (t == TypeManager.uint32_type) ||
3654 (t == TypeManager.char_type) ||
3655 (t == TypeManager.float_type))){
3656 Report.Error (
3657 677, Location, parent.MakeName (Name) +
3658 " A volatile field can not be of type `" +
3659 TypeManager.MonoBASIC_Name (t) + "'");
3660 return false;
3665 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3667 if (parent is Struct &&
3668 ((fa & FieldAttributes.Static) == 0) &&
3669 t == parent.TypeBuilder &&
3670 !TypeManager.IsBuiltinType (t)){
3671 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name +
3672 "' causes a cycle in the structure layout");
3673 return false;
3675 FieldBuilder = parent.TypeBuilder.DefineField (
3676 Name, t, Modifiers.FieldAttr (ModFlags));
3678 TypeManager.RegisterFieldBase (FieldBuilder, this);
3679 return true;
3682 public void Emit (TypeContainer tc)
3684 EmitContext ec = new EmitContext (tc, Location, null,
3685 FieldBuilder.FieldType, ModFlags);
3687 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
3692 // `set' and `get' accessors are represented with an Accessor.
3694 public class Accessor {
3696 // Null if the accessor is empty, or a Block if not
3698 public Block Block;
3699 public Attributes OptAttributes;
3701 public Accessor (Block b, Attributes attrs)
3703 Block = b;
3704 OptAttributes = attrs;
3709 // Properties and Indexers both generate PropertyBuilders, we use this to share
3710 // their common bits.
3712 abstract public class PropertyBase : MethodCore {
3713 public Accessor Get, Set;
3714 public PropertyBuilder PropertyBuilder;
3715 public MethodBuilder GetBuilder, SetBuilder;
3716 public MethodData GetData, SetData;
3718 protected EmitContext ec;
3720 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3721 Parameters parameters, Accessor get_block, Accessor set_block,
3722 Attributes attrs, Location loc)
3723 : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3725 Get = get_block;
3726 Set = set_block;
3729 protected override bool DoDefine (TypeContainer parent)
3731 if (!base.DoDefine (parent))
3732 return false;
3734 ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3736 return true;
3740 // Checks our base implementation if any
3742 protected override bool CheckBase (TypeContainer container)
3744 base.CheckBase (container);
3746 // Check whether arguments were correct.
3747 if (!DoDefineParameters (container))
3748 return false;
3750 if (IsExplicitImpl)
3751 return true;
3753 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
3754 if (!IsOperator)
3756 MemberList mi_this;
3758 mi_this = TypeContainer.FindMembers (
3759 container.TypeBuilder, MemberTypes.Property,
3760 BindingFlags.NonPublic | BindingFlags.Public |
3761 BindingFlags.Static | BindingFlags.Instance |
3762 BindingFlags.DeclaredOnly,
3763 MethodSignature.method_signature_filter, ms);
3765 if (mi_this.Count > 0) {
3766 Report.Error (111, Location, "Class `" + container.Name + "' " +
3767 "already defines a member called `" + Name + "' " +
3768 "with the same parameter types");
3769 return false;
3773 if (container is Interface)
3774 return true;
3776 Type retval = null;
3777 if ((ModFlags & Modifiers.READONLY) != 0)
3778 retval = MemberType;
3780 string report_name;
3781 MethodSignature base_ms;
3782 if (this is Indexer) {
3783 string name, base_name;
3785 report_name = "this";
3786 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
3787 ms = new MethodSignature (name, null, ParameterTypes);
3788 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
3789 base_ms = new MethodSignature (base_name, retval, ParameterTypes);
3790 } else {
3791 report_name = Name;
3792 ms = base_ms = new MethodSignature (Name, retval, ParameterTypes);
3796 // Verify if the parent has a type with the same name, and then
3797 // check whether we have to create a new slot for it or not.
3799 Type ptype = container.TypeBuilder.BaseType;
3801 MemberInfo parent_member = null;
3802 MemberList mi, mi_static, mi_instance;
3805 // Find properties with the same name on the base class
3807 mi_static = TypeContainer.FindMembers (
3808 ptype, MemberTypes.Property,
3809 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3810 MethodSignature.inheritable_property_signature_filter, base_ms);
3812 mi_instance = TypeContainer.FindMembers (
3813 ptype, MemberTypes.Property,
3814 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3815 MethodSignature.inheritable_property_signature_filter,
3816 base_ms);
3819 if (mi_instance.Count > 0)
3820 mi = mi_instance;
3821 else if (mi_static.Count > 0)
3822 mi = mi_static;
3823 else
3824 mi = null;
3826 if (mi != null && mi.Count > 0)
3827 parent_member = (PropertyInfo) mi [0];
3829 if (parent_member is PropertyInfo) {
3830 PropertyInfo parent_property = (PropertyInfo)parent_member;
3832 string name = parent_property.DeclaringType.Name + "." +
3833 parent_property.Name;
3835 MethodInfo get, set, parent_method;
3836 get = parent_property.GetGetMethod (true);
3837 set = parent_property.GetSetMethod (true);
3839 if (get != null)
3840 parent_method = get;
3841 else if (set != null)
3842 parent_method = set;
3843 else
3844 throw new Exception ("Internal error!");
3846 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
3847 return false;
3849 if ((ModFlags & Modifiers.NEW) == 0) {
3850 Type parent_type = TypeManager.TypeToCoreType (
3851 parent_property.PropertyType);
3853 if (parent_type != MemberType) {
3854 Report.Error (
3855 508, Location, container.MakeName (Name) + ": cannot " +
3856 "change return type when overriding " +
3857 "inherited member " + name);
3858 return false;
3861 } else if (parent_member == null) {
3862 /*if ((ModFlags & Modifiers.NEW) != 0)
3863 WarningNotHiding (container);
3865 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3866 if (this is Indexer)
3867 Report.Error (115, Location,
3868 container.MakeName (Name) +
3869 " no suitable indexers found to override");
3870 else
3871 Report.Error (115, Location,
3872 container.MakeName (Name) +
3873 " no suitable properties found to override");
3874 return false;
3877 if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0) {
3878 if ((ModFlags & Modifiers.NONVIRTUAL) != 0) {
3879 Report.Error (31088, Location,
3880 container.MakeName (Name) + " : Cannot " +
3881 "be declared NotOverridable since this method is " +
3882 "not maked as Overrides");
3885 // if a member of module is not inherited from Object class
3886 // can not be declared protected
3887 if ((container is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
3888 Report.Error (31066, Location,
3889 "'Property' inside a 'Module' can not be declared as " +
3890 "'Protected' or 'Protected Friend'");
3892 return true;
3895 public virtual void Emit (TypeContainer tc)
3898 // The PropertyBuilder can be null for explicit implementations, in that
3899 // case, we do not actually emit the ".property", so there is nowhere to
3900 // put the attribute
3902 if (PropertyBuilder != null)
3903 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3905 if (GetData != null)
3906 GetData.Emit (tc, Get.Block, Get);
3908 if (SetData != null)
3909 SetData.Emit (tc, Set.Block, Set);
3914 public class Property : PropertyBase {
3915 const int AllowedModifiers =
3916 Modifiers.NEW |
3917 Modifiers.PUBLIC |
3918 Modifiers.PROTECTED |
3919 Modifiers.INTERNAL |
3920 Modifiers.PRIVATE |
3921 Modifiers.STATIC |
3922 Modifiers.SEALED |
3923 Modifiers.OVERRIDE |
3924 Modifiers.ABSTRACT |
3925 Modifiers.UNSAFE |
3926 Modifiers.EXTERN |
3927 Modifiers.VIRTUAL |
3928 Modifiers.NONVIRTUAL |
3929 Modifiers.DEFAULT |
3930 Modifiers.READONLY |
3931 Modifiers.WRITEONLY |
3932 Modifiers.SHADOWS;
3934 string set_parameter_name;
3935 Parameters get_params;
3936 Parameters set_params;
3938 public Property (Expression type, string name, int mod_flags,
3939 Accessor get_block, Accessor set_block,
3940 Attributes attrs, Location loc, string set_name,
3941 Parameters p_get, Parameters p_set, ArrayList impl_what)
3942 : base (type, name, mod_flags, AllowedModifiers,
3943 p_set,
3944 get_block, set_block, attrs, loc)
3946 set_parameter_name = set_name;
3947 get_params = p_get;
3948 set_params = p_set;
3949 Implements = impl_what;
3952 public Property (Expression type, string name, int mod_flags,
3953 Accessor get_block, Accessor set_block,
3954 Attributes attrs, Location loc)
3955 : this (type, name, mod_flags, get_block, set_block, attrs, loc,
3956 "Value", Parameters.EmptyReadOnlyParameters, Parameters.EmptyReadOnlyParameters, null)
3960 public override bool Define (TypeContainer parent)
3962 Type [] g_parameters=null, s_parameters=null;
3963 Parameter [] g_parms, s_parms;
3964 InternalParameters g_ip=null, s_ip=null;
3966 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
3967 Report.Error (30435, Location,
3968 "'Property' inside a 'Structure' can not be declared as " +
3969 "'Protected' or 'Protected Friend'");
3971 if (!DoDefine (parent))
3972 return false;
3974 if (!CheckBase (parent))
3975 return false;
3977 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3979 if (Get == null) {
3980 if ((ModFlags & Modifiers.WRITEONLY) == 0)
3981 Report.Error (
3982 30124, Location,
3983 "Property without 'Get' accessor must have a 'WriteOnly' modifier");
3985 else {
3986 if (get_params == Parameters.EmptyReadOnlyParameters) {
3987 g_parameters = TypeManager.NoTypes;
3988 g_ip = new InternalParameters (
3989 parent, Parameters.EmptyReadOnlyParameters);
3990 } else {
3991 g_parameters = new Type [get_params.FixedParameters.Length];
3992 for (int i = 0; i < get_params.FixedParameters.Length; i ++) {
3993 g_parameters[i] = get_params.FixedParameters[i].ParameterType;
3995 g_parms = new Parameter [get_params.FixedParameters.Length];
3996 for (int i = 0; i < get_params.FixedParameters.Length; i ++) {
3997 Parameter tp = get_params.FixedParameters[i];
3998 g_parms[i] = new Parameter (tp.TypeName, tp.Name,
3999 Parameter.Modifier.NONE, null);
4001 g_ip = new InternalParameters (
4002 parent, new Parameters (g_parms, null, Location));
4005 GetData = new MethodData (this, "get", MemberType,
4006 g_parameters, g_ip, CallingConventions.Standard,
4007 Get.OptAttributes, ModFlags, flags, false);
4009 if (!GetData.Define (parent))
4010 return false;
4012 GetBuilder = GetData.MethodBuilder;
4015 if (Set == null) {
4016 if ((ModFlags & Modifiers.READONLY) == 0)
4017 Report.Error (
4018 30124, Location,
4019 "Property without 'Set' accessor must have a 'ReadOnly' modifier");
4022 else
4024 if (set_params == Parameters.EmptyReadOnlyParameters)
4026 s_parameters = new Type [1];
4027 s_parameters [0] = MemberType;
4029 s_parms = new Parameter [1];
4030 s_parms [0] = new Parameter (Type, set_parameter_name,
4031 Parameter.Modifier.NONE, null);
4032 } else {
4033 s_parameters = new Type [set_params.FixedParameters.Length];
4034 for (int i = 0; i < set_params.FixedParameters.Length; i ++) {
4035 s_parameters[i] = set_params.FixedParameters[i].ParameterType;
4038 s_parms = new Parameter [set_params.FixedParameters.Length];
4039 for (int i = 0; i < set_params.FixedParameters.Length; i ++) {
4040 Parameter tp = set_params.FixedParameters[i];
4041 s_parms[i] = new Parameter (tp.TypeName, tp.Name,
4042 Parameter.Modifier.NONE, null);
4046 s_ip = new InternalParameters (
4047 parent, new Parameters (s_parms, null, Location));
4049 SetData = new MethodData (this, "set", TypeManager.void_type,
4050 s_parameters, s_ip, CallingConventions.Standard,
4051 Set.OptAttributes, ModFlags, flags, false);
4053 if (!SetData.Define (parent))
4054 return false;
4056 SetBuilder = SetData.MethodBuilder;
4057 SetBuilder.DefineParameter (1, ParameterAttributes.None,
4058 set_parameter_name);
4061 // FIXME - PropertyAttributes.HasDefault ?
4063 PropertyAttributes prop_attr =
4064 PropertyAttributes.RTSpecialName |
4065 PropertyAttributes.SpecialName;
4067 if (!IsExplicitImpl){
4068 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4069 Name, prop_attr, MemberType, null);
4071 PropertyBuilder.SetGetMethod (GetBuilder);
4072 PropertyBuilder.SetSetMethod (SetBuilder);
4075 // HACK for the reasons exposed above
4077 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4078 Report.Error (
4079 111, Location,
4080 "Class `" + parent.Name +
4081 "' already contains a definition for the property `" +
4082 Name + "'");
4083 return false;
4086 return true;
4089 public override void Emit (TypeContainer tc)
4091 base.Emit (tc);
4093 if (GetData != null)
4095 Parameters = get_params;
4096 GetData.Emit (tc, Get.Block, Get);
4099 if (SetData != null)
4101 Parameters = set_params;
4102 SetData.Emit (tc, Set.Block, Set);
4108 /// </summary>
4109 /// Gigantic workaround for lameness in SRE follows :
4110 /// This class derives from EventInfo and attempts to basically
4111 /// wrap around the EventBuilder so that FindMembers can quickly
4112 /// return this in it search for members
4113 /// </summary>
4114 public class MyEventBuilder : EventInfo {
4117 // We use this to "point" to our Builder which is
4118 // not really a MemberInfo
4120 EventBuilder MyBuilder;
4123 // We "catch" and wrap these methods
4125 MethodInfo raise, remove, add;
4127 EventAttributes attributes;
4128 Type declaring_type, reflected_type, event_type;
4129 string name;
4131 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4133 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4135 // And now store the values in our own fields.
4137 declaring_type = type_builder;
4139 reflected_type = type_builder;
4141 attributes = event_attr;
4142 this.name = name;
4143 this.event_type = event_type;
4147 // Methods that you have to override. Note that you only need
4148 // to "implement" the variants that take the argument (those are
4149 // the "abstract" methods, the others (GetAddMethod()) are
4150 // regular.
4152 public override MethodInfo GetAddMethod (bool nonPublic)
4154 return add;
4157 public override MethodInfo GetRemoveMethod (bool nonPublic)
4159 return remove;
4162 public override MethodInfo GetRaiseMethod (bool nonPublic)
4164 return raise;
4168 // These methods make "MyEventInfo" look like a Builder
4170 public void SetRaiseMethod (MethodBuilder raiseMethod)
4172 raise = raiseMethod;
4173 MyBuilder.SetRaiseMethod (raiseMethod);
4176 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4178 remove = removeMethod;
4179 MyBuilder.SetRemoveOnMethod (removeMethod);
4182 public void SetAddOnMethod (MethodBuilder addMethod)
4184 add = addMethod;
4185 MyBuilder.SetAddOnMethod (addMethod);
4188 public void SetCustomAttribute (CustomAttributeBuilder cb)
4190 MyBuilder.SetCustomAttribute (cb);
4193 public override object [] GetCustomAttributes (bool inherit)
4195 // FIXME : There's nothing which can be seemingly done here because
4196 // we have no way of getting at the custom attribute objects of the
4197 // EventBuilder !
4198 return null;
4201 public override object [] GetCustomAttributes (Type t, bool inherit)
4203 // FIXME : Same here !
4204 return null;
4207 public override bool IsDefined (Type t, bool b)
4209 return true;
4212 public override EventAttributes Attributes {
4213 get {
4214 return attributes;
4218 public override string Name {
4219 get {
4220 return name;
4224 public override Type DeclaringType {
4225 get {
4226 return declaring_type;
4230 public override Type ReflectedType {
4231 get {
4232 return reflected_type;
4236 public Type EventType {
4237 get {
4238 return event_type;
4243 public class Event : FieldBase {
4244 const int AllowedModifiers =
4245 Modifiers.NEW |
4246 Modifiers.PUBLIC |
4247 Modifiers.PROTECTED |
4248 Modifiers.INTERNAL |
4249 Modifiers.PRIVATE |
4250 Modifiers.STATIC |
4251 Modifiers.VIRTUAL |
4252 Modifiers.SEALED |
4253 Modifiers.OVERRIDE |
4254 Modifiers.UNSAFE |
4255 Modifiers.ABSTRACT;
4257 public readonly Accessor Add;
4258 public readonly Accessor Remove;
4259 public MyEventBuilder EventBuilder;
4261 MethodBuilder AddBuilder, RemoveBuilder;
4262 MethodData AddData, RemoveData;
4264 public Event (Expression type, string name, Object init, int mod, Accessor add,
4265 Accessor remove, Attributes attrs, Location loc)
4266 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4268 Add = add;
4269 Remove = remove;
4270 Implements = null;
4273 public Event (Expression type, string name, Object init, int mod, Accessor add,
4274 Accessor remove, Attributes attrs, ArrayList impl_what, Location loc)
4275 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4277 Add = add;
4278 Remove = remove;
4279 Implements = impl_what;
4283 public override bool Define (TypeContainer parent)
4285 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4287 if (!DoDefine (parent))
4288 return false;
4290 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4291 Report.Error (31044, Location, "'" + parent.Name + "." + Name +
4292 "' : event must be of a delegate type");
4293 return false;
4296 Type [] parameter_types = new Type [1];
4297 parameter_types [0] = MemberType;
4299 Parameter [] parms = new Parameter [1];
4300 parms [0] = new Parameter (Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4301 InternalParameters ip = new InternalParameters (
4302 parent, new Parameters (parms, null, Location));
4304 if (!CheckBase (parent))
4305 return false;
4308 // Now define the accessors
4310 AddData = new MethodData (this, "add", TypeManager.void_type,
4311 parameter_types, ip, CallingConventions.Standard,
4312 (Add != null) ? Add.OptAttributes : null,
4313 ModFlags, flags, false);
4315 if (!AddData.Define (parent))
4316 return false;
4318 AddBuilder = AddData.MethodBuilder;
4319 AddBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4321 RemoveData = new MethodData (this, "remove", TypeManager.void_type,
4322 parameter_types, ip, CallingConventions.Standard,
4323 (Remove != null) ? Remove.OptAttributes : null,
4324 ModFlags, flags, false);
4326 if (!RemoveData.Define (parent))
4327 return false;
4329 RemoveBuilder = RemoveData.MethodBuilder;
4330 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4332 if (!IsExplicitImpl){
4333 EventBuilder = new MyEventBuilder (
4334 parent.TypeBuilder, Name, e_attr, MemberType);
4336 if (Add == null && Remove == null) {
4337 FieldBuilder = parent.TypeBuilder.DefineField (
4338 Name, MemberType,
4339 FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4340 TypeManager.RegisterPrivateFieldOfEvent (
4341 (EventInfo) EventBuilder, FieldBuilder);
4342 TypeManager.RegisterFieldBase (FieldBuilder, this);
4345 EventBuilder.SetAddOnMethod (AddBuilder);
4346 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4348 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4349 Report.Error (111, Location,
4350 "Class `" + parent.Name +
4351 "' already contains a definition for the event `" +
4352 Name + "'");
4353 return false;
4357 return true;
4360 void EmitDefaultMethod (EmitContext ec, bool is_add)
4362 ILGenerator ig = ec.ig;
4363 MethodInfo method = null;
4365 if (is_add)
4366 method = TypeManager.delegate_combine_delegate_delegate;
4367 else
4368 method = TypeManager.delegate_remove_delegate_delegate;
4370 if ((ModFlags & Modifiers.STATIC) != 0) {
4371 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4372 ig.Emit (OpCodes.Ldarg_0);
4373 ig.Emit (OpCodes.Call, method);
4374 ig.Emit (OpCodes.Castclass, MemberType);
4375 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4376 } else {
4377 ig.Emit (OpCodes.Ldarg_0);
4378 ig.Emit (OpCodes.Ldarg_0);
4379 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4380 ig.Emit (OpCodes.Ldarg_1);
4381 ig.Emit (OpCodes.Call, method);
4382 ig.Emit (OpCodes.Castclass, MemberType);
4383 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4385 ig.Emit (OpCodes.Ret);
4388 public void Emit (TypeContainer tc)
4390 EmitContext ec;
4392 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4393 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
4395 if (Add != null)
4396 AddData.Emit (tc, Add.Block, Add);
4397 else {
4398 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4399 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4400 EmitDefaultMethod (ec, true);
4403 if (Remove != null)
4404 RemoveData.Emit (tc, Remove.Block, Remove);
4405 else {
4406 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4407 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4408 EmitDefaultMethod (ec, false);
4415 // FIXME: This does not handle:
4417 // int INTERFACENAME [ args ]
4418 // Does not
4420 // Only:
4422 // int this [ args ]
4424 public class Indexer : PropertyBase {
4426 const int AllowedModifiers =
4427 Modifiers.NEW |
4428 Modifiers.PUBLIC |
4429 Modifiers.PROTECTED |
4430 Modifiers.INTERNAL |
4431 Modifiers.PRIVATE |
4432 Modifiers.VIRTUAL |
4433 Modifiers.SEALED |
4434 Modifiers.OVERRIDE |
4435 Modifiers.UNSAFE |
4436 Modifiers.EXTERN |
4437 Modifiers.ABSTRACT;
4439 public string IndexerName;
4440 public string InterfaceIndexerName;
4443 // Are we implementing an interface ?
4445 bool IsImplementing = false;
4447 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4448 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4449 : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4450 attrs, loc)
4452 ExplicitInterfaceName = int_type;
4455 public override bool Define (TypeContainer parent)
4457 PropertyAttributes prop_attr =
4458 PropertyAttributes.RTSpecialName |
4459 PropertyAttributes.SpecialName;
4461 if (!DoDefine (parent))
4462 return false;
4464 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4465 if (IndexerName == null)
4466 IndexerName = "Item";
4467 else if (IsExplicitImpl)
4468 Report.Error (592, Location,
4469 "Attribute 'IndexerName' is not valid on this declaration " +
4470 "type. It is valid on `property' declarations only.");
4472 ShortName = IndexerName;
4473 if (IsExplicitImpl) {
4474 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4475 Name = InterfaceType.FullName + "." + IndexerName;
4476 } else {
4477 InterfaceIndexerName = IndexerName;
4478 Name = ShortName;
4481 if (!CheckBase (parent))
4482 return false;
4484 if (Get != null){
4485 InternalParameters ip = new InternalParameters (parent, Parameters);
4487 GetData = new MethodData (this, "get", MemberType,
4488 ParameterTypes, ip, CallingConventions.Standard,
4489 Get.OptAttributes, ModFlags, flags, false);
4491 if (!GetData.Define (parent))
4492 return false;
4494 GetBuilder = GetData.MethodBuilder;
4497 if (Set != null){
4498 int top = ParameterTypes.Length;
4499 Type [] set_pars = new Type [top + 1];
4500 ParameterTypes.CopyTo (set_pars, 0);
4501 set_pars [top] = MemberType;
4503 Parameter [] fixed_parms = Parameters.FixedParameters;
4505 if (fixed_parms == null){
4506 throw new Exception ("We currently do not support only array arguments in an indexer");
4507 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4508 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4510 // Here is the problem: the `value' parameter has
4511 // to come *after* the array parameter in the declaration
4512 // like this:
4513 // X (object [] x, Type value)
4514 // .param [0]
4516 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4517 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4521 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4524 fixed_parms.CopyTo (tmp, 0);
4525 tmp [fixed_parms.Length] = new Parameter (
4526 Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4528 Parameters set_formal_params = new Parameters (tmp, null, Location);
4530 InternalParameters ip = new InternalParameters (parent, set_formal_params);
4532 SetData = new MethodData (this, "set", TypeManager.void_type,
4533 set_pars, ip, CallingConventions.Standard,
4534 Set.OptAttributes, ModFlags, flags, false);
4536 if (!SetData.Define (parent))
4537 return false;
4539 SetBuilder = SetData.MethodBuilder;
4543 // Now name the parameters
4545 Parameter [] p = Parameters.FixedParameters;
4546 if (p != null) {
4547 int i;
4549 for (i = 0; i < p.Length; ++i) {
4550 if (Get != null)
4551 GetBuilder.DefineParameter (
4552 i + 1, p [i].Attributes, p [i].Name);
4554 if (Set != null)
4555 SetBuilder.DefineParameter (
4556 i + 1, p [i].Attributes, p [i].Name);
4560 if (Set != null)
4561 SetBuilder.DefineParameter (
4562 i + 1, ParameterAttributes.None, /* was "value" */ this.Name);
4564 if (i != ParameterTypes.Length) {
4565 Parameter array_param = Parameters.ArrayParameter;
4566 SetBuilder.DefineParameter (
4567 i + 1, array_param.Attributes, array_param.Name);
4571 if (GetData != null)
4572 IsImplementing = GetData.IsImplementing;
4573 else if (SetData != null)
4574 IsImplementing = SetData.IsImplementing;
4577 // Define the PropertyBuilder if one of the following conditions are met:
4578 // a) we're not implementing an interface indexer.
4579 // b) the indexer has a different IndexerName and this is no
4580 // explicit interface implementation.
4582 if (!IsExplicitImpl) {
4583 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4584 IndexerName, prop_attr, MemberType, ParameterTypes);
4586 if (GetData != null)
4587 PropertyBuilder.SetGetMethod (GetBuilder);
4589 if (SetData != null)
4590 PropertyBuilder.SetSetMethod (SetBuilder);
4592 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4593 ParameterTypes);
4596 return true;
4600 struct MethodSignature {
4601 public string Name;
4602 public Type RetType;
4603 public Type [] Parameters;
4605 /// <summary>
4606 /// This delegate is used to extract methods which have the
4607 /// same signature as the argument
4608 /// </summary>
4609 public static MemberFilter method_signature_filter;
4611 /// <summary>
4612 /// This delegate is used to extract methods which have the
4613 /// same signature as the argument except for the name
4614 /// </summary>
4615 public static MemberFilter method_signature_noname_filter;
4617 /// <summary>
4618 /// This delegate is used to extract inheritable methods which
4619 /// have the same signature as the argument. By inheritable,
4620 /// this means that we have permissions to override the method
4621 /// from the current assembly and class
4622 /// </summary>
4623 public static MemberFilter inheritable_method_signature_filter;
4625 /// <summary>
4626 /// This delegate is used to extract inheritable methods which
4627 /// have the same signature as the argument. By inheritable,
4628 /// this means that we have permissions to override the method
4629 /// from the current assembly and class
4630 /// </summary>
4631 public static MemberFilter inheritable_property_signature_filter;
4633 static MethodSignature ()
4635 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4636 method_signature_noname_filter = new MemberFilter (MemberSignatureCompareNoName);
4637 inheritable_method_signature_filter = new MemberFilter (
4638 InheritableMemberSignatureCompare);
4639 inheritable_property_signature_filter = new MemberFilter (
4640 InheritablePropertySignatureCompare);
4643 public MethodSignature (string name, Type ret_type, Type [] parameters)
4645 Name = name;
4646 RetType = ret_type;
4648 if (parameters == null)
4649 Parameters = TypeManager.NoTypes;
4650 else
4651 Parameters = parameters;
4654 public override int GetHashCode ()
4656 return Name.GetHashCode ();
4659 public override bool Equals (Object o)
4661 MethodSignature other = (MethodSignature) o;
4663 if (other.Name != Name)
4664 return false;
4666 if (other.RetType != RetType)
4667 return false;
4669 if (Parameters == null){
4670 if (other.Parameters == null)
4671 return true;
4672 return false;
4675 if (other.Parameters == null)
4676 return false;
4678 int c = Parameters.Length;
4679 if (other.Parameters.Length != c)
4680 return false;
4682 for (int i = 0; i < c; i++)
4683 if (other.Parameters [i] != Parameters [i])
4684 return false;
4686 return true;
4689 static bool MemberSignatureCompareNoName (MemberInfo m, object filter_criteria)
4691 return MemberSignatureCompare (m, filter_criteria, false);
4694 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4696 return MemberSignatureCompare (m, filter_criteria, true);
4699 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria, bool use_name)
4701 MethodSignature sig = (MethodSignature) filter_criteria;
4703 if (use_name && (m.Name != sig.Name))
4704 return false;
4706 Type ReturnType;
4707 MethodInfo mi = m as MethodInfo;
4708 PropertyInfo pi = m as PropertyInfo;
4710 if (mi != null)
4711 ReturnType = mi.ReturnType;
4712 else if (pi != null)
4713 ReturnType = pi.PropertyType;
4714 else
4715 return false;
4718 // we use sig.RetType == null to mean `do not check the
4719 // method return value.
4721 if (sig.RetType != null)
4722 if (ReturnType != sig.RetType)
4723 return false;
4725 Type [] args;
4726 if (mi != null)
4727 args = TypeManager.GetArgumentTypes (mi);
4728 else
4729 args = TypeManager.GetArgumentTypes (pi);
4731 Type [] sigp = sig.Parameters;
4733 if (args.Length != sigp.Length)
4734 return false;
4736 for (int i = args.Length; i > 0; ){
4737 i--;
4738 if (args [i] != sigp [i])
4739 return false;
4741 return true;
4745 // This filter should be used when we are requesting methods that
4746 // we want to override.
4748 // This makes a number of assumptions, for example
4749 // that the methods being extracted are of a parent
4750 // class (this means we know implicitly that we are
4751 // being called to find out about members by a derived
4752 // class).
4754 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4756 if (MemberSignatureCompare (m, filter_criteria)){
4757 MethodInfo mi = (MethodInfo) m;
4758 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4760 // If only accessible to the current class.
4761 if (prot == MethodAttributes.Private)
4762 return false;
4764 // If only accessible to the defining assembly or
4765 if (prot == MethodAttributes.FamANDAssem ||
4766 prot == MethodAttributes.Assembly){
4767 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4768 return true;
4769 else
4770 return false;
4773 // Anything else (FamOrAssembly and Public) is fine
4774 return true;
4776 return false;
4780 // This filter should be used when we are requesting properties that
4781 // we want to override.
4783 // This makes a number of assumptions, for example
4784 // that the methods being extracted are of a parent
4785 // class (this means we know implicitly that we are
4786 // being called to find out about members by a derived
4787 // class).
4789 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
4791 if (MemberSignatureCompare (m, filter_criteria)){
4792 PropertyInfo pi = (PropertyInfo) m;
4794 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
4795 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
4797 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
4799 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4801 // If only accessible to the current class.
4802 if (prot == MethodAttributes.Private)
4803 return false;
4805 // If only accessible to the defining assembly or
4806 if (prot == MethodAttributes.FamANDAssem ||
4807 prot == MethodAttributes.Assembly){
4808 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4809 return true;
4810 else
4811 return false;
4814 // Anything else (FamOrAssembly and Public) is fine
4815 return true;
4817 return false;