(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / mbas / class.cs
blobf0a91d2da18c39e4fa5e9f78e9d2776573d5f383
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 // Information in the case we are an attribute type
121 AttributeUsageAttribute attribute_usage = new AttributeUsageAttribute (AttributeTargets.All);
123 public AttributeUsageAttribute AttributeUsage {
124 get {
125 return attribute_usage;
128 set {
129 attribute_usage = value;
133 // The interfaces we implement.
134 Type [] ifaces;
136 // The parent member container and our member cache
137 IMemberContainer parent_container;
138 MemberCache member_cache;
141 // The indexer name for this class
143 public string IndexerName;
145 public TypeContainer (TypeContainer parent, string name, Attributes attrs, Location l)
146 : base (parent, name, attrs, l)
148 string n;
149 types = new ArrayList ();
151 if (parent == null)
152 n = "";
153 else
154 n = parent.Name;
156 base_class_name = null;
158 //Console.WriteLine ("New class " + name + " inside " + n);
161 public override AttributeTargets AttributeTargets {
162 get {
163 throw new NotSupportedException ();
167 public AdditionResult AddConstant (Const constant)
169 AdditionResult res;
170 string basename = constant.Name;
172 if ((res = IsValid (basename)) != AdditionResult.Success)
173 return res;
175 if (constants == null)
176 constants = new ArrayList ();
178 constants.Add (constant);
179 DefineName (Name + "." + basename, constant);
181 return AdditionResult.Success;
184 public AdditionResult AddEnum (Mono.MonoBASIC.Enum e)
186 AdditionResult res;
188 if ((res = IsValid (e.Basename)) != AdditionResult.Success)
189 return res;
191 if (enums == null)
192 enums = new ArrayList ();
194 enums.Add (e);
195 DefineName (e.Name, e);
197 return AdditionResult.Success;
200 public AdditionResult AddClass (Class c)
202 AdditionResult res;
204 if ((res = IsValid (c.Basename)) != AdditionResult.Success)
205 return res;
209 DefineName (c.Name, c);
210 types.Add (c);
212 // FIXME: Do we really need to explicitly add an empty default static constructor?
213 // Apparently we don't
214 /* if (c.default_static_constructor == null)
216 bool isModule = c is Mono.MonoBASIC.Module;
217 Constructor dc = new Constructor ("New", Parameters.EmptyReadOnlyParameters, null, c.Location);
218 dc.ModFlags = isModule ? Modifiers.PUBLIC | Modifiers.STATIC : Modifiers.PUBLIC;
219 c.AddConstructor (dc);
222 //--------------------------------------------------------------
224 return AdditionResult.Success;
227 public AdditionResult AddStruct (Struct s)
229 AdditionResult res;
231 if ((res = IsValid (s.Basename)) != AdditionResult.Success)
232 return res;
234 DefineName (s.Name, s);
235 types.Add (s);
237 return AdditionResult.Success;
240 public AdditionResult AddDelegate (Delegate d)
242 AdditionResult res;
244 if ((res = IsValid (d.Basename)) != AdditionResult.Success)
245 return res;
247 if (delegates == null)
248 delegates = new ArrayList ();
250 DefineName (d.Name, d);
251 delegates.Add (d);
253 return AdditionResult.Success;
256 public AdditionResult AddMethod (Method method)
258 string basename = method.Name;
259 string fullname = Name + "." + basename;
261 Object value = defined_names [fullname];
263 if (value != null && (!(value is Method)))
264 return AdditionResult.NameExists;
266 if (basename == Basename)
267 return AdditionResult.EnclosingClash;
269 if (methods == null)
270 methods = new ArrayList ();
272 if (method.Name.IndexOf (".") != -1)
273 methods.Insert (0, method);
274 else
275 methods.Add (method);
277 if (value == null)
278 DefineName (fullname, method);
280 return AdditionResult.Success;
283 public AdditionResult AddConstructor (Constructor c)
285 if (c.Name != "New")
286 return AdditionResult.NotAConstructor;
288 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
290 if (is_static){
291 have_static_constructor = true;
292 if (default_static_constructor != null){
293 Console.WriteLine ("I have a static constructor already");
294 Console.WriteLine (" " + default_static_constructor);
295 return AdditionResult.MethodExists;
298 default_static_constructor = c;
299 } else {
300 if (c.IsDefault ()){
301 /*if (default_constructor != null)
302 return AdditionResult.MethodExists;*/
303 default_constructor = c;
306 if (instance_constructors == null)
307 instance_constructors = new ArrayList ();
309 instance_constructors.Add (c);
312 return AdditionResult.Success;
315 public AdditionResult AddInterface (Interface iface)
317 AdditionResult res;
319 if ((res = IsValid (iface.Basename)) != AdditionResult.Success)
320 return res;
322 if (interfaces == null)
323 interfaces = new ArrayList ();
324 interfaces.Add (iface);
325 DefineName (iface.Name, iface);
327 return AdditionResult.Success;
330 public AdditionResult AddField (Field field)
332 AdditionResult res;
333 string basename = field.Name;
335 if ((res = IsValid (basename)) != AdditionResult.Success)
336 return res;
338 if (fields == null)
339 fields = new ArrayList ();
341 fields.Add (field);
343 if (field.HasInitializer){
344 if ((field.ModFlags & Modifiers.STATIC) != 0) {
345 if (initialized_static_fields == null)
346 initialized_static_fields = new ArrayList ();
348 initialized_static_fields.Add (field);
351 // We have not seen a static constructor,
352 // but we will provide static initialization of fields
354 have_static_constructor = true;
355 } else {
356 if (initialized_fields == null)
357 initialized_fields = new ArrayList ();
359 initialized_fields.Add (field);
363 if ((field.ModFlags & Modifiers.STATIC) == 0)
364 have_nonstatic_fields = true;
366 DefineName (Name + "." + basename, field);
367 return AdditionResult.Success;
370 public AdditionResult AddProperty (Property prop)
372 AdditionResult res;
373 string basename = prop.Name;
375 if ((res = IsValid (basename)) != AdditionResult.Success)
376 return res;
378 if (properties == null)
379 properties = new ArrayList ();
381 if (prop.Name.IndexOf (".") != -1)
382 properties.Insert (0, prop);
383 else
384 properties.Add (prop);
385 DefineName (Name + "." + basename, prop);
387 return AdditionResult.Success;
390 public AdditionResult AddEvent (Event e)
392 AdditionResult res;
393 string basename = e.Name;
395 if ((res = IsValid (basename)) != AdditionResult.Success)
396 return res;
398 if (events == null)
399 events = new ArrayList ();
401 events.Add (e);
402 DefineName (Name + "." + basename, e);
404 return AdditionResult.Success;
408 public AdditionResult AddIndexer (Indexer i)
410 if (indexers == null)
411 indexers = new ArrayList ();
413 if (i.InterfaceType != null)
414 indexers.Insert (0, i);
415 else
416 indexers.Add (i);
418 return AdditionResult.Success;
422 public AdditionResult AddEventHandler (Statement stmt)
424 if (handlers == null)
425 handlers = new ArrayList ();
427 handlers.Add (stmt);
428 return AdditionResult.Success;
431 public void RegisterOrder (Interface iface)
433 if (interface_order == null)
434 interface_order = new ArrayList ();
436 interface_order.Add (iface);
439 public ArrayList Types {
440 get {
441 return types;
445 public ArrayList Methods {
446 get {
447 return methods;
451 public ArrayList Constants {
452 get {
453 return constants;
457 public ArrayList Interfaces {
458 get {
459 return interfaces;
463 public string Base {
464 get {
465 return base_class_name;
469 public ArrayList Bases {
470 get {
471 return type_bases;
474 set {
475 type_bases = value;
479 public ArrayList Fields {
480 get {
481 return fields;
484 set {
485 fields = value;
489 public ArrayList InstanceConstructors {
490 get {
491 return instance_constructors;
495 public ArrayList Properties {
496 get {
497 return properties;
501 public ArrayList Events {
502 get {
503 return events;
507 public ArrayList Enums {
508 get {
509 return enums;
514 public ArrayList Indexers {
515 get {
516 return indexers;
521 public ArrayList Delegates {
522 get {
523 return delegates;
527 public bool HaveStaticConstructor {
528 get {
529 return have_static_constructor;
533 public virtual TypeAttributes TypeAttr {
534 get {
535 return Modifiers.TypeAttr (ModFlags, this);
539 public ArrayList EventHandlers {
540 get {
541 return handlers;
546 // Emits the instance field initializers
548 public bool EmitFieldInitializers (EmitContext ec)
550 ArrayList fields;
551 ILGenerator ig = ec.ig;
552 Expression instance_expr;
554 if (ec.IsStatic){
555 fields = initialized_static_fields;
556 instance_expr = null;
557 } else {
558 fields = initialized_fields;
559 instance_expr = new This (Location.Null).Resolve (ec);
562 if (fields == null)
563 return true;
565 foreach (Field f in fields){
566 Expression e = f.GetInitializerExpression (ec);
567 if (e == null)
568 return false;
570 Location l = f.Location;
571 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
572 fe.InstanceExpression = instance_expr;
573 Expression a = new Assign (fe, e, l);
575 a = a.Resolve (ec);
576 if (a == null)
577 return false;
579 if (a is ExpressionStatement)
580 ((ExpressionStatement) a).EmitStatement (ec);
581 else {
582 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
586 return true;
590 // Defines the default constructors
592 void DefineDefaultConstructor (bool is_static)
594 Constructor c;
595 int mods = 0;
597 c = new Constructor ("New", Parameters.EmptyReadOnlyParameters,
598 null,
599 Location.Null);
601 if (is_static) {
602 mods = Modifiers.STATIC;
603 c.ModFlags = mods;
605 else
606 c.Initializer = new ConstructorBaseInitializer (
607 null, Parameters.EmptyReadOnlyParameters,
608 Location.Null);
610 AddConstructor (c);
612 c.Block = new Block (null);
616 public void ReportStructInitializedInstanceError ()
618 string n = TypeBuilder.FullName;
620 foreach (Field f in initialized_fields){
621 Report.Error (
622 31049, Location,
623 "`" + n + "." + f.Name + "': can not have " +
624 "instance field initializers in structs");
628 /// <remarks>
629 /// The pending methods that need to be implemented (interfaces or abstract methods)
630 /// </remarks>
631 public PendingImplementation Pending;
633 /// <summary>
634 /// This function computes the Base class and also the
635 /// list of interfaces that the class or struct @c implements.
636 ///
637 /// The return value is an array (might be null) of
638 /// interfaces implemented (as Types).
639 ///
640 /// The @parent argument is set to the parent object or null
641 /// if this is `System.Object'.
642 /// </summary>
643 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
645 ArrayList bases = Bases;
646 int count;
647 int start, j, i;
649 error = false;
651 if (is_class)
652 parent = null;
653 else
654 parent = TypeManager.value_type;
656 if (bases == null){
657 if (is_class){
658 if (RootContext.StdLib)
659 parent = TypeManager.object_type;
660 else if (Name != "System.Object")
661 parent = TypeManager.object_type;
662 } else {
664 // If we are compiling our runtime,
665 // and we are defining ValueType, then our
666 // parent is `System.Object'.
668 if (!RootContext.StdLib && Name == "System.ValueType")
669 parent = TypeManager.object_type;
672 return null;
676 // Bases should be null if there are no bases at all
678 count = bases.Count;
680 if (is_class && (!(this is Interface))){
681 Expression name = (Expression) bases [0];
682 name = ResolveTypeExpr (name, false, Location);
684 if (name == null){
685 error = true;
686 return null;
689 Type first = name.Type;
691 if (first.IsClass){
692 parent = first;
693 start = 1;
694 } else {
695 parent = TypeManager.object_type;
696 start = 0;
699 if (parent.IsSealed )
700 Report.Error (30299, Location,
701 "Class " + Name + " cannot inherit " +
702 "'NotInheritable' class " + TypeManager.MonoBASIC_Name (parent));
704 if (!AsAccessible (parent, ModFlags))
705 Report.Error (30389, Location,
706 "Inconsistent accessibility: base class `" +
707 TypeManager.MonoBASIC_Name (parent) + "' is less " +
708 "accessible than class `" +
709 Name + "'");
711 } else {
712 start = 0;
715 Type [] ifaces = new Type [count-start];
717 for (i = start, j = 0; i < count; i++, j++){
718 Expression name = (Expression) bases [i];
719 Expression resolved = ResolveTypeExpr (name, false, Location);
720 bases [i] = resolved;
721 Type t = resolved.Type;
722 if (t == null){
723 error = true;
724 return null;
727 if (is_class == false && !t.IsInterface){
728 Report.Error (527, "In Struct `" + Name + "', type `"+
729 name +"' is not an interface");
730 error = true;
731 return null;
734 if (t.IsSealed) {
735 if (t.IsValueType)
736 Report.Error (30258, "class `"+ Name +
737 "': a class can not inherit from a struct/enum");
739 /*Report.Error (509, "class `"+ Name +
740 "': Cannot inherit from sealed class `"+
741 bases [i]);*/
742 error = true;
743 return null;
746 if (t.IsClass) {
747 if (parent != null){
748 Report.Error (30121, Name + ": A class cannot inherit " +
749 "more than one class");
750 error = true;
751 return null;
755 for (int x = 0; x < j; x++) {
756 if (t == ifaces [x]) {
757 Report.Error (528, "`" + name + "' is already listed in interface list");
758 error = true;
759 return null;
763 ifaces [j] = t;
766 return ifaces;
770 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
772 public override TypeBuilder DefineType ()
774 Type parent;
775 bool error;
776 bool is_class;
778 if (TypeBuilder != null)
779 return TypeBuilder;
781 if (InTransit)
782 return null;
784 InTransit = true;
786 if (this is Class)
787 is_class = true;
788 else
789 is_class = false;
791 ec = new EmitContext (this, Mono.MonoBASIC.Location.Null, null, null, ModFlags);
793 if (((ModFlags & Modifiers.ABSTRACT ) != 0) &&
794 ((ModFlags & Modifiers.SEALED) != 0)){
795 Report.Error (31408, Location,
796 "Class declared as 'MustInherit' cannot be declared as 'NotInheritable'");
799 ifaces = GetClassBases (is_class, out parent, out error);
800 if (error)
801 return null;
803 if (this is Interface)
804 parent = null;
806 if (is_class && parent != null){
807 if (parent == TypeManager.enum_type ||
808 (parent == TypeManager.value_type && RootContext.StdLib) ||
809 parent == TypeManager.delegate_type ||
810 parent == TypeManager.array_type){
811 Report.Error (
812 644, Location, "`" + Name + "' cannot inherit from " +
813 "special class `" + TypeManager.MonoBASIC_Name (parent) + "'");
814 return null;
818 if (!is_class && TypeManager.value_type == null)
819 throw new Exception ();
821 if (is_class && Parent.Parent == null && (!(this is Interface)))
823 if ((ModFlags & Modifiers.PRIVATE) != 0)
824 Report.Error (31089, Location,
825 "Only internal classes can be declared as 'Private'");
827 if ((ModFlags & Modifiers.PROTECTED) != 0)
828 Report.Error (31047, Location,
829 "Only internal classes can be declared as 'Protected'");
832 if ((Parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
833 Report.Error (30735, Location,
834 "'Type' inside a 'Module' can not be " +
835 "declared as 'Protected'");
837 if ((Parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
838 Report.Error (30435, Location,
839 "'Type' inside a 'Structure' can not be " +
840 "declared as 'Protected'");
842 TypeAttributes type_attributes = TypeAttr;
844 // if (parent_builder is ModuleBuilder) {
845 if (IsTopLevel){
846 ModuleBuilder builder = CodeGen.ModuleBuilder;
847 TypeBuilder = builder.DefineType (
848 Name, type_attributes, parent, ifaces);
850 } else {
851 TypeBuilder builder = Parent.TypeBuilder;
852 TypeBuilder = builder.DefineNestedType (
853 Basename, type_attributes, parent, ifaces);
856 if (!is_class)
858 // structure must contain atleast one member variable
859 if(!have_nonstatic_fields){
860 Report.Error (
861 30281, Location, "Structure `" + Name + "' do not " +
862 "contain any member Variable");
864 /*TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
865 FieldAttributes.Private);*/
868 // add interfaces that were not added at type creation (weird API issue)
869 if (!have_nonstatic_fields && (ifaces != null)) {
870 foreach (Type i in ifaces)
871 TypeBuilder.AddInterfaceImplementation (i);
877 // Finish the setup for the EmitContext
879 ec.ContainerType = TypeBuilder;
881 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
883 if ((parent != null) &&
884 (parent == TypeManager.attribute_type ||
885 parent.IsSubclassOf (TypeManager.attribute_type))) {
886 RootContext.RegisterAttribute (this);
887 } else
888 RootContext.RegisterOrder (this);
890 if (Interfaces != null) {
891 foreach (Interface iface in Interfaces)
892 iface.DefineType ();
895 if (Types != null) {
896 foreach (TypeContainer tc in Types)
897 tc.DefineType ();
900 if (Delegates != null) {
901 foreach (Delegate d in Delegates)
902 d.DefineType ();
905 if (Enums != null) {
906 foreach (Enum en in Enums)
907 en.DefineType ();
910 InTransit = false;
911 return TypeBuilder;
915 /// <summary>
916 /// Defines the MemberCore objects that are in the `list' Arraylist
918 /// The `defined_names' array contains a list of members defined in
919 /// a base class
920 /// </summary>
921 static ArrayList remove_list = new ArrayList ();
922 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
924 int idx;
926 // if one of the overloaded method is having
927 // Shadows or Overloads modifier all other should
928 // have the same modifier
929 Hashtable members = new Hashtable();
930 int modval;
931 foreach (MemberCore mc in list)
933 modval = 0;
934 if(members[mc.Name] == null)
936 foreach (MemberCore m in list)
938 if(m.Name == mc.Name)
940 if ((m.ModFlags & Modifiers.SHADOWS) != 0)
942 modval = Modifiers.SHADOWS;
943 break;
945 else if((m.ModFlags & Modifiers.NEW) != 0)
947 modval = Modifiers.NEW;
951 members.Add(mc.Name, modval);
954 modval = (int)members[mc.Name];
955 if(modval != 0)
957 if(((modval & Modifiers.SHADOWS) != 0) && ((mc.ModFlags & Modifiers.SHADOWS) == 0))
958 Report.Error (
959 30695, mc.Location,
960 "Function '" + mc.Name + "': must be declared 'Shadows' " +
961 "because another '" + mc.Name + "' declared 'Shadows'");
962 else if(((modval & Modifiers.NEW) != 0) && ((mc.ModFlags & Modifiers.NEW) == 0))
963 Report.Error (
964 31409, mc.Location,
965 "Function '" + mc.Name + "': must be declared 'Overloads' " +
966 "because another '" + mc.Name + "' declared 'Overloads'");
969 members.Clear ();
970 remove_list.Clear ();
972 foreach (MemberCore mc in list){
973 if (!mc.Define (this)){
974 remove_list.Add (mc);
975 continue;
978 if (defined_names == null)
979 continue;
981 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
982 if (idx < 0){
983 if (RootContext.WarningLevel >= 4){
984 if ((mc.ModFlags & Modifiers.NEW) != 0)
985 Warning_KewywordNewNotRequired (mc.Location, mc);
986 if ((mc.ModFlags & Modifiers.SHADOWS) != 0)
987 Warning_KewywordShadowsNotRequired (mc.Location, mc);
989 continue;
992 MemberInfo match = defined_names [idx];
994 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
995 continue;
998 // If we are both methods, let the method resolution emit warnings
1000 if (match is MethodBase && mc is MethodCore)
1001 continue;
1003 if (((mc.ModFlags & Modifiers.SHADOWS) == 0) && idx > 0)
1004 Warning_KeywordShadowsRequired (mc.Location, defined_names [idx]);
1008 foreach (object o in remove_list)
1009 list.Remove (o);
1011 remove_list.Clear ();
1015 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
1016 // class is consisten. Either it is `Item' or it is the name defined by all the
1017 // indexers with the `IndexerName' attribute.
1019 // Turns out that the IndexerNameAttribute is applied to each indexer,
1020 // but it is never emitted, instead a DefaultName attribute is attached
1021 // to the class.
1023 void DefineIndexers ()
1025 string class_indexer_name = null;
1028 foreach (Indexer i in Indexers){
1029 string name;
1031 i.Define (this);
1033 name = i.IndexerName;
1035 if (i.InterfaceType != null)
1036 continue;
1038 if (class_indexer_name == null){
1039 class_indexer_name = name;
1040 continue;
1043 if (name == class_indexer_name)
1044 continue;
1046 Report.Error (
1047 668, "Two indexers have different names, " +
1048 " you should use the same name for all your indexers");
1052 if (class_indexer_name == null)
1053 class_indexer_name = "Item";
1054 IndexerName = class_indexer_name;
1057 static void Error_KeywordNotAllowed (Location loc)
1059 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1062 /// <summary>
1063 /// Populates our TypeBuilder with fields and methods
1064 /// </summary>
1065 public override bool DefineMembers (TypeContainer parent)
1067 MemberInfo [] defined_names = null;
1069 if (interface_order != null){
1070 foreach (Interface iface in interface_order)
1071 if ((iface.ModFlags & Modifiers.NEW) == 0)
1072 iface.DefineMembers (this);
1073 else
1074 Error_KeywordNotAllowed (iface.Location);
1077 if (RootContext.WarningLevel > 1){
1078 Type ptype;
1081 // This code throws an exception in the comparer
1082 // I guess the string is not an object?
1084 ptype = TypeBuilder.BaseType;
1085 if (ptype != null){
1086 defined_names = (MemberInfo []) FindMembers (
1087 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1088 BindingFlags.Public | BindingFlags.Instance |
1089 BindingFlags.Static, null, null);
1091 Array.Sort (defined_names, mif_compare);
1095 if (constants != null)
1096 DefineMembers (constants, defined_names);
1098 if (fields != null)
1099 DefineMembers (fields, defined_names);
1101 if (this is Class && (!(this is Interface))){
1102 if (instance_constructors == null){
1103 if (default_constructor == null)
1104 DefineDefaultConstructor (false);
1107 if (initialized_static_fields != null &&
1108 default_static_constructor == null)
1109 DefineDefaultConstructor (true);
1112 if (this is Struct){
1114 // Structs can not have initialized instance
1115 // fields
1117 if (initialized_static_fields != null &&
1118 default_static_constructor == null)
1119 DefineDefaultConstructor (true);
1121 if (initialized_fields != null)
1122 ReportStructInitializedInstanceError ();
1125 if (!(this is Interface))
1126 Pending = PendingImplementation.GetPendingImplementations (this);
1128 // Constructors are not in the defined_names array
1130 if (instance_constructors != null)
1131 DefineMembers (instance_constructors, null);
1133 if (default_static_constructor != null)
1134 default_static_constructor.Define (this);
1136 if (methods != null)
1137 DefineMembers (methods, defined_names);
1139 if (properties != null)
1140 DefineMembers (properties, defined_names);
1142 if (events != null)
1143 DefineMembers (events, defined_names);
1146 if (indexers != null) {
1147 DefineIndexers ();
1148 } else
1150 IndexerName = "Item";
1152 if (enums != null)
1153 DefineMembers (enums, defined_names);
1155 if (delegates != null)
1156 DefineMembers (delegates, defined_names);
1158 #if CACHE
1159 if (TypeBuilder.BaseType != null)
1160 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1162 member_cache = new MemberCache (this);
1163 #endif
1165 return true;
1168 public override bool Define (TypeContainer parent)
1170 if (interface_order != null){
1171 foreach (Interface iface in interface_order)
1172 if ((iface.ModFlags & Modifiers.NEW) == 0)
1173 iface.Define (this);
1176 return true;
1179 /// <summary>
1180 /// This function is based by a delegate to the FindMembers routine
1181 /// </summary>
1182 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1184 return true;
1187 /// <summary>
1188 /// This filter is used by FindMembers, and we just keep
1189 /// a global for the filter to `AlwaysAccept'
1190 /// </summary>
1191 static MemberFilter accepting_filter;
1194 /// <summary>
1195 /// A member comparission method based on name only
1196 /// </summary>
1197 static IComparer mif_compare;
1199 static TypeContainer ()
1201 accepting_filter = new MemberFilter (AlwaysAccept);
1202 mif_compare = new MemberInfoCompare ();
1205 /// <summary>
1206 /// This method returns the members of this type just like Type.FindMembers would
1207 /// Only, we need to use this for types which are _being_ defined because MS'
1208 /// implementation can't take care of that.
1209 /// </summary>
1211 // FIXME: return an empty static array instead of null, that cleans up
1212 // some code and is consistent with some coding conventions I just found
1213 // out existed ;-)
1216 // Notice that in various cases we check if our field is non-null,
1217 // something that would normally mean that there was a bug elsewhere.
1219 // The problem happens while we are defining p-invoke methods, as those
1220 // will trigger a FindMembers, but this happens before things are defined
1222 // Since the whole process is a no-op, it is fine to check for null here.
1224 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1225 MemberFilter filter, object criteria)
1227 ArrayList members = new ArrayList ();
1229 int modflags = 0;
1230 if ((bf & BindingFlags.Public) != 0)
1231 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1232 Modifiers.INTERNAL;
1233 if ((bf & BindingFlags.NonPublic) != 0)
1234 modflags |= Modifiers.PRIVATE;
1236 int static_mask = 0, static_flags = 0;
1237 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1238 case BindingFlags.Static:
1239 static_mask = static_flags = Modifiers.STATIC;
1240 break;
1242 case BindingFlags.Instance:
1243 static_mask = Modifiers.STATIC;
1244 static_flags = 0;
1245 break;
1247 default:
1248 static_mask = static_flags = 0;
1249 break;
1252 Timer.StartTimer (TimerType.TcFindMembers);
1254 if (filter == null)
1255 filter = accepting_filter;
1257 if ((mt & MemberTypes.Field) != 0) {
1258 if (fields != null) {
1259 foreach (Field f in fields) {
1260 if ((f.ModFlags & modflags) == 0)
1261 continue;
1262 if ((f.ModFlags & static_mask) != static_flags)
1263 continue;
1265 FieldBuilder fb = f.FieldBuilder;
1266 if (fb != null && filter (fb, criteria) == true)
1267 members.Add (fb);
1271 if (constants != null) {
1272 foreach (Const con in constants) {
1273 if ((con.ModFlags & modflags) == 0)
1274 continue;
1275 if ((con.ModFlags & static_mask) != static_flags)
1276 continue;
1278 FieldBuilder fb = con.FieldBuilder;
1279 if (fb != null && filter (fb, criteria) == true)
1280 members.Add (fb);
1285 if ((mt & MemberTypes.Method) != 0) {
1286 if (methods != null) {
1287 foreach (Method m in methods) {
1288 if ((m.ModFlags & modflags) == 0)
1289 continue;
1290 if ((m.ModFlags & static_mask) != static_flags)
1291 continue;
1293 MethodBuilder mb = m.MethodBuilder;
1295 if (mb != null && filter (mb, criteria) == true)
1296 members.Add (mb);
1300 if (properties != null){
1301 foreach (Property p in properties){
1302 if ((p.ModFlags & modflags) == 0)
1303 continue;
1304 if ((p.ModFlags & static_mask) != static_flags)
1305 continue;
1307 MethodBuilder b;
1309 b = p.GetBuilder;
1310 if (b != null && filter (b, criteria) == true)
1311 members.Add (b);
1313 b = p.SetBuilder;
1314 if (b != null && filter (b, criteria) == true)
1315 members.Add (b);
1320 if (indexers != null){
1321 foreach (Indexer ix in indexers){
1322 if ((ix.ModFlags & modflags) == 0)
1323 continue;
1324 if ((ix.ModFlags & static_mask) != static_flags)
1325 continue;
1327 MethodBuilder b;
1329 b = ix.GetBuilder;
1330 if (b != null && filter (b, criteria) == true)
1331 members.Add (b);
1333 b = ix.SetBuilder;
1334 if (b != null && filter (b, criteria) == true)
1335 members.Add (b);
1341 if ((mt & MemberTypes.Event) != 0) {
1342 if (events != null)
1343 foreach (Event e in events) {
1344 if ((e.ModFlags & modflags) == 0)
1345 continue;
1346 if ((e.ModFlags & static_mask) != static_flags)
1347 continue;
1349 MemberInfo eb = e.EventBuilder;
1350 if (eb != null && filter (eb, criteria) == true)
1351 members.Add (e.EventBuilder);
1355 if ((mt & MemberTypes.Property) != 0){
1356 if (properties != null)
1357 foreach (Property p in properties) {
1358 if ((p.ModFlags & modflags) == 0)
1359 continue;
1360 if ((p.ModFlags & static_mask) != static_flags)
1361 continue;
1363 MemberInfo pb = p.PropertyBuilder;
1365 if (pb != null && filter (pb, criteria) == true)
1366 members.Add (p.PropertyBuilder);
1370 if (indexers != null)
1371 foreach (Indexer ix in indexers) {
1372 if ((ix.ModFlags & modflags) == 0)
1373 continue;
1374 if ((ix.ModFlags & static_mask) != static_flags)
1375 continue;
1377 MemberInfo ib = ix.PropertyBuilder;
1378 if (ib != null && filter (ib, criteria) == true) {
1379 members.Add (ix.PropertyBuilder);
1385 if ((mt & MemberTypes.NestedType) != 0) {
1386 if (types != null){
1387 foreach (TypeContainer t in types) {
1388 if ((t.ModFlags & modflags) == 0)
1389 continue;
1391 TypeBuilder tb = t.TypeBuilder;
1392 if (tb != null && (filter (tb, criteria) == true))
1393 members.Add (tb);
1397 if (enums != null){
1398 foreach (Enum en in enums){
1399 if ((en.ModFlags & modflags) == 0)
1400 continue;
1402 TypeBuilder tb = en.TypeBuilder;
1403 if (tb != null && (filter (tb, criteria) == true))
1404 members.Add (tb);
1408 if (delegates != null){
1409 foreach (Delegate d in delegates){
1410 if ((d.ModFlags & modflags) == 0)
1411 continue;
1413 TypeBuilder tb = d.TypeBuilder;
1414 if (tb != null && (filter (tb, criteria) == true))
1415 members.Add (tb);
1419 if (interfaces != null){
1420 foreach (Interface iface in interfaces){
1421 if ((iface.ModFlags & modflags) == 0)
1422 continue;
1424 TypeBuilder tb = iface.TypeBuilder;
1425 if (tb != null && (filter (tb, criteria) == true))
1426 members.Add (tb);
1431 if ((mt & MemberTypes.Constructor) != 0){
1432 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1433 foreach (Constructor c in instance_constructors){
1434 if ((c.ModFlags & modflags) == 0)
1435 continue;
1437 ConstructorBuilder cb = c.ConstructorBuilder;
1438 if (cb != null)
1439 if (filter (cb, criteria) == true)
1440 members.Add (cb);
1444 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null) &&
1445 ((default_static_constructor.ModFlags & modflags) != 0)){
1446 ConstructorBuilder cb =
1447 default_static_constructor.ConstructorBuilder;
1449 if (cb != null)
1450 if (filter (cb, criteria) == true)
1451 members.Add (cb);
1456 // Lookup members in parent if requested.
1458 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1459 if ((mt & ~MemberTypes.Constructor) != 0) {
1460 MemberList list = FindMembers (TypeBuilder.BaseType, mt & ~MemberTypes.Constructor, bf, filter, criteria);
1461 members.AddRange (list);
1465 Timer.StopTimer (TimerType.TcFindMembers);
1467 return new MemberList (members);
1470 public override MemberCache MemberCache {
1471 get {
1472 return member_cache;
1476 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1477 MemberFilter filter, object criteria)
1479 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1481 if (tc != null)
1482 return tc.FindMembers (mt, bf, filter, criteria);
1483 else
1484 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1488 // FindMethods will look for methods not only in the type `t', but in
1489 // any interfaces implemented by the type.
1491 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1492 MemberFilter filter, object criteria)
1494 return null;
1497 /// <summary>
1498 /// Emits the values for the constants
1499 /// </summary>
1500 public void EmitConstants ()
1502 if (constants != null)
1503 foreach (Const con in constants)
1504 con.EmitConstant (this);
1505 return;
1508 /// <summary>
1509 /// Emits the code, this step is performed after all
1510 /// the types, enumerations, constructors
1511 /// </summary>
1512 public void Emit ()
1514 if (instance_constructors != null)
1515 foreach (Constructor c in instance_constructors)
1516 c.Emit (this);
1518 if (default_static_constructor != null)
1519 default_static_constructor.Emit (this);
1521 if (methods != null)
1522 foreach (Method m in methods)
1523 m.Emit (this);
1525 if (properties != null)
1526 foreach (Property p in properties)
1527 p.Emit (this);
1530 if (indexers != null){
1531 foreach (Indexer ix in indexers)
1532 ix.Emit (this);
1534 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1535 this, IndexerName, ModFlags, Location);
1536 TypeBuilder.SetCustomAttribute (cb);
1540 if (fields != null)
1541 foreach (Field f in fields)
1542 f.Emit (this);
1544 if (events != null){
1545 foreach (Event e in Events)
1546 e.Emit (this);
1549 if (Pending != null)
1550 if (Pending.VerifyPendingMethods ())
1551 return;
1553 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1556 // Check for internal or private fields that were never assigned
1558 if (fields != null && RootContext.WarningLevel >= 3) {
1559 foreach (Field f in fields) {
1560 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1561 continue;
1563 if (f.status == 0){
1564 Report.Warning (
1565 169, f.Location, "Private field " +
1566 MakeName (f.Name) + " is never used");
1567 continue;
1571 // Only report 649 on level 4
1573 if (RootContext.WarningLevel < 4)
1574 continue;
1576 if ((f.status & Field.Status.ASSIGNED) != 0)
1577 continue;
1579 Report.Warning (
1580 649, f.Location,
1581 "Field " + MakeName (f.Name) + " is never assigned " +
1582 " to and will always have its default value");
1586 // if (types != null)
1587 // foreach (TypeContainer tc in types)
1588 // tc.Emit ();
1591 public override void CloseType ()
1593 try {
1594 if (!Created){
1595 Created = true;
1596 TypeBuilder.CreateType ();
1598 } catch (TypeLoadException){
1600 // This is fine, the code still created the type
1602 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1603 // Console.WriteLine (e.Message);
1604 } catch {
1605 Console.WriteLine ("In type: " + Name);
1606 throw;
1609 if (Enums != null)
1610 foreach (Enum en in Enums)
1611 en.CloseType ();
1613 if (interface_order != null){
1614 foreach (Interface iface in interface_order)
1615 iface.CloseType ();
1618 if (Types != null){
1619 foreach (TypeContainer tc in Types)
1620 if (tc is Struct)
1621 tc.CloseType ();
1623 foreach (TypeContainer tc in Types)
1624 if (!(tc is Struct))
1625 tc.CloseType ();
1628 if (Delegates != null)
1629 foreach (Delegate d in Delegates)
1630 d.CloseType ();
1633 public string MakeName (string n)
1635 return "`" + Name + "." + n + "'";
1638 public void Warning_KeywordShadowsRequired (Location l, MemberInfo mi)
1640 Report.Warning (
1641 108, l, "The keyword 'Shadows' is required on " +
1642 MakeName (mi.Name) + " because it shadows `" +
1643 mi.ReflectedType.Name + "." + mi.Name + "'");
1646 public void Warning_KewywordShadowsNotRequired (Location l, MemberCore mc)
1648 Report.Warning (
1649 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1650 "inherited member, the keyword shadows is not required");
1653 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1655 Report.Warning (
1656 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1657 "inherited member, the keyword new is not required");
1660 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1662 return 0;
1666 // Performs the validation on a Method's modifiers (properties have
1667 // the same properties).
1669 public bool MethodModifiersValid (int flags, string n, Location loc)
1671 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1672 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1673 const int nv = (Modifiers.SHADOWS | Modifiers.VIRTUAL);
1674 bool ok = true;
1675 string name = MakeName (n);
1678 // At most one of static, virtual or override
1680 if ((flags & Modifiers.STATIC) != 0){
1681 if ((flags & vao) != 0){
1682 Report.Error (
1683 30501, loc, "Shared method " + name + " can not be " +
1684 "declared as Overridable");
1685 ok = false;
1689 if (this is Struct){
1690 if ((flags & va) != 0){
1691 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1692 ok = false;
1696 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.VIRTUAL) != 0)
1698 Report.Error (
1699 30730, loc, name +
1700 ": Methods marked as Overrides cannot be made Overridable");
1701 ok = false;
1704 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.SHADOWS) != 0){
1705 Report.Error (
1706 31408, loc, name +
1707 ": Methods marked as Overrides cannot be marked as Shadows");
1708 ok = false;
1712 // If the declaration includes the abstract modifier, then the
1713 // declaration does not include static, virtual or extern
1715 if ((flags & Modifiers.ABSTRACT) != 0){
1716 if ((flags & Modifiers.EXTERN) != 0){
1717 Report.Error (
1718 180, loc, name + " can not be both abstract and extern");
1719 ok = false;
1722 if ((flags & Modifiers.VIRTUAL) != 0){
1723 Report.Error (
1724 503, loc, name + " can not be both abstract and virtual");
1725 ok = false;
1728 if((ModFlags & Modifiers.SEALED) != 0){
1729 Report.Error (
1730 30607, loc,
1731 "Class declared as 'NotInheritable' " +
1732 "cannot have a 'MustOverride' member");
1733 ok = false;
1735 else if ((ModFlags & Modifiers.ABSTRACT) == 0){
1736 Report.Error (
1737 31411, loc, name +
1738 " is declared as 'MustOverride', hence its container " +
1739 "class should be declared as 'MustInherit'");
1740 ok = false;
1745 if ((flags & Modifiers.PRIVATE) != 0){
1746 if ((flags & vao) != 0){
1747 Report.Error (
1748 31408, loc, name +
1749 ": Members marked as Overridable or Overrides can not be Private");
1750 ok = false;
1754 if ((flags & Modifiers.SEALED) != 0){
1755 if ((flags & Modifiers.OVERRIDE) == 0){
1756 Report.Error (
1757 238, loc, name +
1758 ": cannot be sealed because it is not an override");
1759 ok = false;
1762 if ((flags & Modifiers.NEW) != 0){
1763 if ((flags & Modifiers.SHADOWS) != 0){
1764 Report.Error (
1765 31408, loc,
1766 " 'Overloads' and 'Shadows' cannot be combined ");
1767 ok = false;
1771 return ok;
1774 // Access level of a type.
1775 enum AccessLevel {
1776 Public = 0,
1777 ProtectedInternal = 1,
1778 Internal = 2,
1779 Protected = 3,
1780 Private = 4
1783 // Check whether `flags' denotes a more restricted access than `level'
1784 // and return the new level.
1785 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1787 AccessLevel old_level = level;
1789 if ((flags & Modifiers.INTERNAL) != 0) {
1790 if ((flags & Modifiers.PROTECTED) != 0) {
1791 if ((int) level < (int) AccessLevel.ProtectedInternal)
1792 level = AccessLevel.ProtectedInternal;
1793 } else {
1794 if ((int) level < (int) AccessLevel.Internal)
1795 level = AccessLevel.Internal;
1797 } else if ((flags & Modifiers.PROTECTED) != 0) {
1798 if ((int) level < (int) AccessLevel.Protected)
1799 level = AccessLevel.Protected;
1800 } else if ((flags & Modifiers.PRIVATE) != 0)
1801 level = AccessLevel.Private;
1803 return level;
1806 // Return the access level for a new member which is defined in the current
1807 // TypeContainer with access modifiers `flags'.
1808 AccessLevel GetAccessLevel (int flags)
1810 if ((flags & Modifiers.PRIVATE) != 0)
1811 return AccessLevel.Private;
1813 AccessLevel level;
1814 if (!IsTopLevel && (Parent != null))
1815 level = Parent.GetAccessLevel (flags);
1816 else
1817 level = AccessLevel.Public;
1819 return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1822 // Return the access level for type `t', but don't give more access than `flags'.
1823 static AccessLevel GetAccessLevel (Type t, int flags)
1825 if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1826 return AccessLevel.Private;
1828 AccessLevel level;
1829 if (TypeManager.IsBuiltinType (t))
1830 return AccessLevel.Public;
1831 else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1832 level = GetAccessLevel (t.DeclaringType, flags);
1833 else {
1834 level = CheckAccessLevel (AccessLevel.Public, flags);
1837 if (t.IsNestedPublic)
1838 return level;
1840 if (t.IsNestedAssembly || t.IsNotPublic) {
1841 if ((int) level < (int) AccessLevel.Internal)
1842 level = AccessLevel.Internal;
1845 if (t.IsNestedFamily) {
1846 if ((int) level < (int) AccessLevel.Protected)
1847 level = AccessLevel.Protected;
1850 if (t.IsNestedFamORAssem) {
1851 if ((int) level < (int) AccessLevel.ProtectedInternal)
1852 level = AccessLevel.ProtectedInternal;
1855 return level;
1859 // Returns true if `parent' is as accessible as the flags `flags'
1860 // given for this member.
1862 public bool AsAccessible (Type parent, int flags)
1864 while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1865 parent = parent.GetElementType ();
1867 AccessLevel level = GetAccessLevel (flags);
1868 AccessLevel level2 = GetAccessLevel (parent, flags);
1870 return (int) level >= (int) level2;
1873 Hashtable builder_and_args;
1875 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1877 if (builder_and_args == null)
1878 builder_and_args = new Hashtable ();
1879 return true;
1882 /// <summary>
1883 /// Performs checks for an explicit interface implementation. First it
1884 /// checks whether the `interface_type' is a base inteface implementation.
1885 /// Then it checks whether `name' exists in the interface type.
1886 /// </summary>
1887 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1889 bool found = false;
1891 if (ifaces != null){
1892 foreach (Type t in ifaces){
1893 if (t == interface_type){
1894 found = true;
1895 break;
1900 if (!found){
1901 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1902 return false;
1905 return true;
1908 public static void Error_NotInterfaceMember (Location loc, string member_name, string iface_name)
1910 Report.Error (30401, loc, "'" + member_name + "' is not a member of the interface '" + iface_name + "'");
1914 // IMemberContainer
1917 string IMemberContainer.Name {
1918 get {
1919 return Name;
1923 Type IMemberContainer.Type {
1924 get {
1925 return TypeBuilder;
1929 IMemberContainer IMemberContainer.Parent {
1930 get {
1931 return parent_container;
1935 MemberCache IMemberContainer.MemberCache {
1936 get {
1937 return member_cache;
1941 bool IMemberContainer.IsInterface {
1942 get {
1943 return this is Interface;
1947 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1949 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1954 public class Class : TypeContainer {
1955 // <summary>
1956 // Modifiers allowed in a class declaration
1957 // </summary>
1958 public const int AllowedModifiers =
1959 Modifiers.NEW |
1960 Modifiers.PUBLIC |
1961 Modifiers.PROTECTED |
1962 Modifiers.INTERNAL |
1963 Modifiers.PRIVATE |
1964 Modifiers.ABSTRACT |
1965 Modifiers.SEALED ;
1967 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1968 : base (parent, name, attrs, l)
1970 int accmods;
1972 if (parent.Parent == null)
1973 accmods = Modifiers.INTERNAL;
1974 else
1975 accmods = Modifiers.PUBLIC;
1977 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1980 public override AttributeTargets AttributeTargets {
1981 get {
1982 return AttributeTargets.Class;
1987 // FIXME: How do we deal with the user specifying a different
1988 // layout?
1990 public override TypeAttributes TypeAttr {
1991 get {
1992 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1997 public class Struct : TypeContainer {
1998 // <summary>
1999 // Modifiers allowed in a struct declaration
2000 // </summary>
2001 public const int AllowedModifiers =
2002 Modifiers.NEW |
2003 Modifiers.PUBLIC |
2004 Modifiers.PROTECTED |
2005 Modifiers.INTERNAL |
2006 Modifiers.UNSAFE |
2007 Modifiers.PRIVATE;
2009 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2010 : base (parent, name, attrs, l)
2012 int accmods;
2014 if (parent.Parent == null)
2015 accmods = Modifiers.INTERNAL;
2016 else
2017 accmods = Modifiers.PUBLIC;
2019 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2021 this.ModFlags |= Modifiers.SEALED;
2024 public override AttributeTargets AttributeTargets {
2025 get {
2026 return AttributeTargets.Struct;
2031 // FIXME: Allow the user to specify a different set of attributes
2032 // in some cases (Sealed for example is mandatory for a class,
2033 // but what SequentialLayout can be changed
2035 public override TypeAttributes TypeAttr {
2036 get {
2037 return base.TypeAttr |
2038 TypeAttributes.SequentialLayout |
2039 TypeAttributes.Sealed |
2040 TypeAttributes.BeforeFieldInit;
2045 public abstract class MethodCore : MemberBase {
2046 public /* readonly */ Parameters Parameters;
2047 Block block;
2050 // Parameters, cached for semantic analysis.
2052 protected InternalParameters parameter_info;
2053 protected Type [] parameter_types;
2055 // Whether this is an operator
2056 public bool IsOperator;
2058 public MethodCore (Expression type, int mod, int allowed_mod, string name,
2059 Attributes attrs, Parameters parameters, Location loc)
2060 : base (type, mod, allowed_mod, name, attrs, loc)
2062 Parameters = parameters;
2066 // Returns the System.Type array for the parameters of this method
2068 public Type [] ParameterTypes {
2069 get {
2070 return parameter_types;
2074 public InternalParameters ParameterInfo
2076 get {
2077 return parameter_info;
2081 public Block Block {
2082 get {
2083 return block;
2086 set {
2087 block = value;
2091 protected virtual bool DoDefineParameters (TypeContainer parent)
2093 // Check if arguments were correct
2094 parameter_types = Parameters.GetParameterInfo (parent);
2095 if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
2096 return false;
2098 parameter_info = new InternalParameters (parent, Parameters);
2100 return true;
2103 public CallingConventions GetCallingConvention (bool is_class)
2105 CallingConventions cc = 0;
2107 cc = Parameters.GetCallingConvention ();
2109 if (is_class)
2110 if ((ModFlags & Modifiers.STATIC) == 0)
2111 cc |= CallingConventions.HasThis;
2113 // FIXME: How is `ExplicitThis' used in C#?
2115 return cc;
2118 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
2120 LabelParameters (ec, parameters, builder, null);
2123 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder, Parameters p_params)
2126 // Define each type attribute (in/out/ref) and
2127 // the argument names.
2129 Parameter [] p = p_params == null ? Parameters.FixedParameters : p_params.FixedParameters;
2130 int i = 0;
2132 MethodBuilder mb = null;
2133 ConstructorBuilder cb = null;
2135 if (builder is MethodBuilder)
2136 mb = (MethodBuilder) builder;
2137 else
2138 cb = (ConstructorBuilder) builder;
2140 if (p != null){
2141 for (i = 0; i < p.Length; i++) {
2142 ParameterBuilder pb;
2144 if (mb == null)
2145 pb = cb.DefineParameter (
2146 i + 1, p [i].Attributes, p [i].Name);
2147 else
2148 pb = mb.DefineParameter (
2149 i + 1, p [i].Attributes, p [i].Name);
2151 if (p [i].ParameterInitializer != null) {
2152 if (p [i].ParameterInitializer is MemberAccess) {
2153 MemberAccess ma = p [i].ParameterInitializer as MemberAccess;
2155 Expression const_ex = ma.Resolve(ec);
2156 if (const_ex is EnumConstant)
2157 pb.SetConstant (((EnumConstant) const_ex).Child.GetValue());
2158 else
2159 Report.Error(-1,
2160 "Internal error - Non supported argument type in optional parameter");
2162 else
2163 pb.SetConstant (((Constant) p [i].ParameterInitializer).GetValue());
2166 Attributes attr = p [i].OptAttributes;
2167 if (attr != null)
2168 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
2172 if (Parameters.ArrayParameter != null){
2173 ParameterBuilder pb;
2174 Parameter array_param = Parameters.ArrayParameter;
2176 if (mb == null)
2177 pb = cb.DefineParameter (
2178 i + 1, array_param.Attributes,
2179 array_param.Name);
2180 else
2181 pb = mb.DefineParameter (
2182 i + 1, array_param.Attributes,
2183 array_param.Name);
2185 CustomAttributeBuilder a = new CustomAttributeBuilder (
2186 TypeManager.cons_param_array_attribute, new object [0]);
2188 pb.SetCustomAttribute (a);
2193 public class Method : MethodCore {
2194 public MethodBuilder MethodBuilder;
2195 public MethodData MethodData;
2197 /// <summary>
2198 /// Modifiers allowed in a class declaration
2199 /// </summary>
2200 const int AllowedModifiers =
2201 Modifiers.NEW |
2202 Modifiers.PUBLIC |
2203 Modifiers.PROTECTED |
2204 Modifiers.INTERNAL |
2205 Modifiers.PRIVATE |
2206 Modifiers.STATIC |
2207 Modifiers.VIRTUAL |
2208 Modifiers.NONVIRTUAL |
2209 Modifiers.OVERRIDE |
2210 Modifiers.ABSTRACT |
2211 Modifiers.UNSAFE |
2212 Modifiers.EXTERN|
2213 Modifiers.SHADOWS;
2216 // return_type can be "null" for VOID values.
2218 public Method (Expression return_type, int mod, string name, Parameters parameters,
2219 Attributes attrs, Location l)
2220 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2222 Implements = null;
2225 public Method (Expression return_type, int mod, string name, Parameters parameters,
2226 Attributes attrs, ArrayList impl_what, Location l)
2227 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2229 Implements = impl_what;
2232 public override AttributeTargets AttributeTargets {
2233 get {
2234 return AttributeTargets.Method;
2239 // Returns the `System.Type' for the ReturnType of this
2240 // function. Provides a nice cache. (used between semantic analysis
2241 // and actual code generation
2243 public Type GetReturnType ()
2245 return MemberType;
2248 void DuplicateEntryPoint (MethodInfo b, Location location)
2250 Report.Error (
2251 30738, location,
2252 "Program `" + CodeGen.FileName +
2253 "' has more than one entry point defined: `" +
2254 TypeManager.MonoBASIC_Signature(b) + "'");
2257 void Report28 (MethodInfo b)
2259 if (RootContext.WarningLevel < 4)
2260 return;
2262 Report.Warning (
2263 28, Location,
2264 "`" + TypeManager.MonoBASIC_Signature(b) +
2265 "' has the wrong signature to be an entry point");
2268 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2270 if (b.ReturnType != TypeManager.void_type &&
2271 b.ReturnType != TypeManager.int32_type)
2272 return false;
2274 if (pinfo.Count == 0)
2275 return true;
2277 if (pinfo.Count > 1)
2278 return false;
2280 Type t = pinfo.ParameterType(0);
2281 if (t.IsArray &&
2282 (t.GetArrayRank() == 1) &&
2283 (t.GetElementType() == TypeManager.string_type) &&
2284 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2285 return true;
2286 else
2287 return false;
2291 // Checks our base implementation if any
2293 protected override bool CheckBase (TypeContainer parent)
2295 // Check whether arguments were correct.
2296 if (!DoDefineParameters (parent))
2297 return false;
2299 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2300 if (!IsOperator) {
2301 MemberList mi_this;
2303 mi_this = TypeContainer.FindMembers (
2304 parent.TypeBuilder, MemberTypes.Method,
2305 BindingFlags.NonPublic | BindingFlags.Public |
2306 BindingFlags.Static | BindingFlags.Instance |
2307 BindingFlags.DeclaredOnly,
2308 MethodSignature.method_signature_filter, ms);
2310 if (mi_this.Count > 0) {
2311 Report.Error (111, Location, "Class `" + parent.Name + "' " +
2312 "already defines a member called `" + Name + "' " +
2313 "with the same parameter types");
2314 return false;
2319 // Verify if the parent has a type with the same name, and then
2320 // check whether we have to create a new slot for it or not.
2322 Type ptype = parent.TypeBuilder.BaseType;
2324 // ptype is only null for System.Object while compiling corlib.
2325 if (ptype != null){
2326 MemberList mi, mi_static, mi_instance;
2328 mi_static = TypeContainer.FindMembers (
2329 ptype, MemberTypes.Method,
2330 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2331 MethodSignature.inheritable_method_signature_filter, ms);
2333 mi_instance = TypeContainer.FindMembers (
2334 ptype, MemberTypes.Method,
2335 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2336 MethodSignature.inheritable_method_signature_filter,
2337 ms);
2339 if (mi_instance.Count > 0){
2340 mi = mi_instance;
2341 } else if (mi_static.Count > 0)
2342 mi = mi_static;
2343 else
2344 mi = null;
2346 if (mi != null && mi.Count > 0){
2347 parent_method = (MethodInfo) mi [0];
2348 string name = parent_method.DeclaringType.Name + "." +
2349 parent_method.Name;
2351 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2352 return false;
2354 if ((ModFlags & Modifiers.NEW) == 0) {
2355 Type parent_ret = TypeManager.TypeToCoreType (
2356 parent_method.ReturnType);
2358 if (parent_ret != MemberType) {
2359 Report.Error (
2360 508, parent.MakeName (Name) + ": cannot " +
2361 "change return type when overriding " +
2362 "inherited member " + name);
2363 return false;
2366 } else {
2367 /*if ((ModFlags & Modifiers.NEW) != 0)
2368 WarningNotHiding (parent);*/
2370 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2371 Report.Error (30284, Location,
2372 parent.MakeName (Name) +
2373 " : No suitable methods found to override");
2375 if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0)
2377 if ((ModFlags & Modifiers.NONVIRTUAL) != 0)
2379 Report.Error (31088, Location,
2380 parent.MakeName (Name) + " : Cannot " +
2381 "be declared NotOverridable since this method is " +
2382 "not maked as Overrides");
2385 // if a member of module is not inherited from Object class
2386 // can not be declared protected
2387 if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
2388 Report.Error (31066, Location,
2389 "'Sub' or 'Function' inside a 'Module' can not be declared as " +
2390 "'Protected' or 'Protected Friend'");
2393 /* else if ((ModFlags & Modifiers.NEW) != 0)
2394 WarningNotHiding (parent);
2397 return true;
2401 // Creates the type
2403 public override bool Define (TypeContainer parent)
2405 if (!DoDefine (parent))
2406 return false;
2408 if (!CheckBase (parent))
2409 return false;
2411 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
2412 Report.Error (31067, Location,
2413 "'Sub' or 'Function' inside a 'Structure' can not be declared as " +
2414 "'Protected' or 'Protected Friend'");
2416 CallingConventions cc = GetCallingConvention (parent is Class);
2418 MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2419 ParameterInfo, cc, OptAttributes,
2420 ModFlags, flags, true);
2422 if (!MethodData.Define (parent))
2423 return false;
2425 MethodBuilder = MethodData.MethodBuilder;
2428 // This is used to track the Entry Point,
2430 if (Name.ToUpper() == "MAIN" &&
2431 ((ModFlags & Modifiers.STATIC) != 0) &&
2432 (RootContext.MainClass == null ||
2433 RootContext.MainClass == parent.TypeBuilder.FullName ||
2434 (RootContext.RootNamespace != null &&
2435 RootContext.RootNamespace.Length > 0 &&
2436 (RootContext.RootNamespace + "." + RootContext.MainClass) == parent.TypeBuilder.FullName))) {
2437 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2438 if (RootContext.EntryPoint == null) {
2439 RootContext.EntryPoint = MethodBuilder;
2440 RootContext.EntryPointLocation = Location;
2441 } else {
2442 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2443 DuplicateEntryPoint (MethodBuilder, Location);
2445 } else
2446 Report28(MethodBuilder);
2449 return true;
2453 // Emits the code
2455 public void Emit (TypeContainer parent)
2457 MethodData.Emit (parent, Block, this);
2461 public abstract class ConstructorInitializer {
2462 ArrayList argument_list;
2463 ConstructorInfo parent_constructor;
2464 Parameters parameters;
2465 Location loc;
2466 public bool implicit_initialization;
2468 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2469 Location loc)
2471 this.argument_list = argument_list;
2472 this.parameters = parameters;
2473 this.loc = loc;
2474 this.implicit_initialization = false;
2477 public ArrayList Arguments {
2478 get {
2479 return argument_list;
2483 public ConstructorInfo ParentConstructor
2487 return parent_constructor;
2491 public bool Resolve (EmitContext ec)
2493 Expression parent_constructor_group;
2494 Type t;
2496 ec.CurrentBlock = new Block (null, true, parameters);
2498 if (argument_list != null){
2499 foreach (Argument a in argument_list){
2500 if (!a.Resolve (ec, loc))
2501 return false;
2505 ec.CurrentBlock = null;
2507 if (this is ConstructorBaseInitializer) {
2508 if (ec.ContainerType.BaseType == null)
2509 return true;
2511 t = ec.ContainerType.BaseType;
2512 if (ec.ContainerType.IsValueType){
2513 Report.Error (522, loc,
2514 "structs cannot call base class constructors");
2515 return false;
2518 else
2519 t = ec.ContainerType;
2521 parent_constructor_group = Expression.MemberLookup (
2522 ec, t, t, ".ctor",
2523 MemberTypes.Constructor,
2524 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2525 loc);
2527 if (parent_constructor_group == null){
2528 Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
2529 return false;
2532 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2533 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2535 if (parent_constructor == null) {
2536 if (this.implicit_initialization)
2537 Report.Error (30148, loc, "Must declare 'MyBase.New' in the constructor " +
2538 "of the class '" + ec.TypeContainer.Name + "' with appropriate arguments, since the base class '" +
2539 t.FullName + "' does not contain a definition of 'New' without any parameter");
2540 else
2541 Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
2543 return false;
2546 return true;
2549 public void Emit (EmitContext ec)
2551 if (parent_constructor != null){
2552 if (ec.IsStatic)
2553 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2554 else
2555 Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2562 public class ConstructorBaseInitializer : ConstructorInitializer {
2563 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2564 base (argument_list, pars, l)
2569 public class ConstructorThisInitializer : ConstructorInitializer {
2570 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2571 base (argument_list, pars, l)
2576 public class Constructor : MethodCore {
2577 public ConstructorBuilder ConstructorBuilder;
2578 public ConstructorInitializer Initializer;
2580 // <summary>
2581 // Modifiers allowed for a constructor.
2582 // </summary>
2583 public const int AllowedModifiers =
2584 Modifiers.PUBLIC |
2585 Modifiers.PROTECTED |
2586 Modifiers.INTERNAL |
2587 Modifiers.STATIC |
2588 Modifiers.UNSAFE |
2589 Modifiers.EXTERN |
2590 Modifiers.PRIVATE;
2593 // The spec claims that static is not permitted, but
2594 // my very own code has static constructors.
2596 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2597 : base (null, 0, AllowedModifiers, name, null, args, l)
2599 Initializer = init;
2602 public Constructor (string name, int mod, Parameters args, ConstructorInitializer init, Location l)
2603 : base (null, mod, AllowedModifiers, name, null, args, l)
2605 Initializer = init;
2608 public override AttributeTargets AttributeTargets {
2609 get {
2610 return AttributeTargets.Constructor;
2615 // Returns true if this is a default constructor
2617 public bool IsDefault ()
2619 if ((ModFlags & Modifiers.STATIC) != 0)
2620 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2621 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2623 else
2624 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2625 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2626 (Initializer is ConstructorBaseInitializer) &&
2627 (Initializer.Arguments == null);
2631 // Creates the ConstructorBuilder
2633 public override bool Define (TypeContainer parent)
2635 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2636 MethodAttributes.SpecialName);
2638 if (parent.EventHandlers != null) {
2639 ArrayList hdlrs = parent.EventHandlers;
2640 foreach(Statement stmt in hdlrs)
2641 this.Block.AddStatement (stmt);
2645 // Check if arguments were correct.
2646 if (!DoDefineParameters (parent))
2647 return false;
2649 if ((ModFlags & Modifiers.STATIC) != 0) {
2650 ca |= MethodAttributes.Static;
2652 if (this.Parameters != Parameters.EmptyReadOnlyParameters)
2653 Report.Error (
2654 30479, Location,
2655 "Shared constructor can not have parameters");
2657 if ((ModFlags & Modifiers.Accessibility) != 0)
2658 Report.Error (
2659 30480, Location,
2660 "Shared constructor can not be declared " +
2661 "explicitly as public, private, friend or protected");
2663 if (this.Initializer != null)
2664 Report.Error (
2665 30043, Location,
2666 "Keywords like MyBase, MyClass, Me are not " +
2667 "valid inside a Shared Constructor");
2669 else {
2670 if (parent is Struct && ParameterTypes.Length == 0) {
2671 Report.Error (
2672 30629, Location,
2673 "Structs can not contain explicit parameterless " +
2674 "constructors");
2675 return false;
2677 ca |= MethodAttributes.HideBySig;
2679 if ((ModFlags & Modifiers.PUBLIC) != 0)
2680 ca |= MethodAttributes.Public;
2681 else if ((ModFlags & Modifiers.PROTECTED) != 0) {
2682 if ((ModFlags & Modifiers.INTERNAL) != 0)
2683 ca |= MethodAttributes.FamORAssem;
2684 else
2685 ca |= MethodAttributes.Family;
2687 else if ((ModFlags & Modifiers.INTERNAL) != 0)
2688 ca |= MethodAttributes.Assembly;
2689 else if (IsDefault ())
2690 ca |= MethodAttributes.Public;
2691 else
2692 ca |= MethodAttributes.Private;
2695 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2696 ca, GetCallingConvention (parent is Class), ParameterTypes);
2699 // HACK because System.Reflection.Emit is lame
2701 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2702 Report.Error (
2703 111, Location,
2704 "Class `" +parent.Name+ "' already contains a definition with the " +
2705 "same return value and parameter types for constructor `" + Name
2706 + "'");
2707 return false;
2710 return true;
2714 // Emits the code
2716 public void Emit (TypeContainer parent)
2718 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2719 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2721 if ((ModFlags & Modifiers.STATIC) == 0){
2722 if (parent is Class && Initializer == null) {
2723 Initializer = new ConstructorBaseInitializer (
2724 null, Parameters.EmptyReadOnlyParameters, parent.Location);
2725 Initializer.implicit_initialization = true;
2729 // Spec mandates that Initializers will not have
2730 // `this' access
2732 ec.IsStatic = true;
2733 if (Initializer != null && !Initializer.Resolve (ec))
2734 return;
2735 ec.IsStatic = false;
2738 LabelParameters (ec, ParameterTypes, ConstructorBuilder);
2741 // Classes can have base initializers and instance field initializers.
2743 if (parent is Class){
2744 if ((ModFlags & Modifiers.STATIC) == 0)
2745 parent.EmitFieldInitializers (ec);
2748 if (Initializer != null) {
2749 if (this.ConstructorBuilder.Equals (Initializer.ParentConstructor))
2750 Report.Error (
2751 30297, Location,
2752 "A constructor can not call itself" );
2754 Initializer.Emit (ec);
2757 if ((ModFlags & Modifiers.STATIC) != 0)
2758 parent.EmitFieldInitializers (ec);
2760 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2762 // If this is a non-static `struct' constructor and doesn't have any
2763 // initializer, it must initialize all of the struct's fields.
2764 if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2765 (Initializer == null))
2766 Block.AddThisVariable (parent, Location);
2768 ec.EmitTopBlock (Block, ParameterInfo, Location);
2772 public class MethodData {
2774 // The return type of this method
2776 public readonly Type ReturnType;
2777 public readonly Type[] ParameterTypes;
2778 public readonly InternalParameters ParameterInfo;
2779 public readonly CallingConventions CallingConventions;
2780 public readonly Attributes OptAttributes;
2781 public readonly Location Location;
2784 // Are we implementing an interface ?
2786 public bool IsImplementing = false;
2789 // Protected data.
2791 protected MemberBase member;
2792 protected int modifiers;
2793 protected MethodAttributes flags;
2794 protected bool is_method;
2795 protected string accessor_name;
2796 ArrayList conditionals;
2798 MethodBuilder builder = null;
2799 public MethodBuilder MethodBuilder {
2800 get {
2801 return builder;
2805 public MethodData (MemberBase member, string name, Type return_type,
2806 Type [] parameter_types, InternalParameters parameters,
2807 CallingConventions cc, Attributes opt_attrs,
2808 int modifiers, MethodAttributes flags, bool is_method)
2810 this.member = member;
2811 this.accessor_name = name;
2812 this.ReturnType = return_type;
2813 this.ParameterTypes = parameter_types;
2814 this.ParameterInfo = parameters;
2815 this.CallingConventions = cc;
2816 this.OptAttributes = opt_attrs;
2817 this.modifiers = modifiers;
2818 this.flags = flags;
2819 this.is_method = is_method;
2820 this.Location = member.Location;
2821 this.conditionals = new ArrayList ();
2825 // Attributes.
2827 Attribute dllimport_attribute = null;
2828 string obsolete = null;
2829 bool obsolete_error = false;
2831 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2833 if ((opt_attrs == null) || (opt_attrs.Attrs == null))
2834 return true;
2836 foreach (Attribute a in opt_attrs.Attrs) {
2837 if (a.Name == "Conditional") {
2838 if (!ApplyConditionalAttribute (a))
2839 return false;
2840 } else if (a.Name == "Obsolete") {
2841 if (!ApplyObsoleteAttribute (a))
2842 return false;
2843 } else if (a.Name.IndexOf ("DllImport") != -1) {
2844 if (!is_method) {
2845 a.Type = TypeManager.dllimport_type;
2846 Attribute.Error_AttributeNotValidForElement (a, Location);
2847 return false;
2849 if (!ApplyDllImportAttribute (a))
2850 return false;
2854 return true;
2858 // Applies the `DllImport' attribute to the method.
2860 protected virtual bool ApplyDllImportAttribute (Attribute a)
2862 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2863 if ((modifiers & extern_static) != extern_static) {
2864 Report.Error (601, Location,
2865 "The DllImport attribute must be specified on a method " +
2866 "marked `static' and `extern'.");
2867 return false;
2870 flags |= MethodAttributes.PinvokeImpl;
2871 dllimport_attribute = a;
2872 return true;
2876 // Applies the `Obsolete' attribute to the method.
2878 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2880 if (obsolete != null) {
2881 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2882 return false;
2885 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2886 return obsolete != null;
2890 // Applies the `Conditional' attribute to the method.
2892 protected virtual bool ApplyConditionalAttribute (Attribute a)
2894 // The Conditional attribute is only valid on methods.
2895 if (!is_method) {
2896 Attribute.Error_AttributeNotValidForElement (a, Location);
2897 return false;
2900 string condition = a.Conditional_GetConditionName ();
2902 if (condition == null)
2903 return false;
2905 if (ReturnType != TypeManager.void_type) {
2906 Report.Error (578, Location,
2907 "Conditional not valid on `" + member.Name + "' " +
2908 "because its return type is not void");
2909 return false;
2912 if ((modifiers & Modifiers.OVERRIDE) != 0) {
2913 Report.Error (243, Location,
2914 "Conditional not valid on `" + member.Name + "' " +
2915 "because it is an override method");
2916 return false;
2919 if (member.IsExplicitImpl) {
2920 Report.Error (577, Location,
2921 "Conditional not valid on `" + member.Name + "' " +
2922 "because it is an explicit interface implementation");
2923 return false;
2926 if (IsImplementing) {
2927 Report.Error (623, Location,
2928 "Conditional not valid on `" + member.Name + "' " +
2929 "because it is an interface method");
2930 return false;
2933 conditionals.Add (condition);
2935 return true;
2939 // Checks whether this method should be ignored due to its Conditional attributes.
2941 bool ShouldIgnore (Location loc)
2943 // When we're overriding a virtual method, we implicitly inherit the
2944 // Conditional attributes from our parent.
2945 if (member.ParentMethod != null) {
2946 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2947 member.ParentMethod, loc);
2949 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2950 return true;
2953 foreach (string condition in conditionals)
2954 if (RootContext.AllDefines [condition] == null)
2955 return true;
2957 return false;
2961 // Returns the TypeManager.MethodFlags for this method.
2962 // This emits an error 619 / warning 618 if the method is obsolete.
2963 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2965 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2967 TypeManager.MethodFlags flags = 0;
2969 if (obsolete != null) {
2970 if (obsolete_error) {
2971 Report.Error (619, loc, "Method `" + member.Name +
2972 "' is obsolete: `" + obsolete + "'");
2973 return TypeManager.MethodFlags.IsObsoleteError;
2974 } else
2975 Report.Warning (618, loc, "Method `" + member.Name +
2976 "' is obsolete: `" + obsolete + "'");
2978 flags |= TypeManager.MethodFlags.IsObsolete;
2981 if (ShouldIgnore (loc))
2982 flags |= TypeManager.MethodFlags.ShouldIgnore;
2984 return flags;
2988 // Search all the interface bases recursively for unimplemented methods
2990 bool SearchBasesForAbstractMethods (
2991 TypeContainer parent, Type iface_type,
2992 string method_name, ref ArrayList implementing_list,
2993 ref ArrayList implementing_iface)
2995 MethodInfo implementing = null;
2996 bool IsImplementing = false;
2997 Type current_iface_type = iface_type;
3000 if (member is Indexer)
3001 implementing = parent.Pending.IsAbstractIndexer (
3002 current_iface_type , ReturnType, ParameterTypes);
3003 else
3005 implementing = parent.Pending.IsAbstractMethod (
3006 current_iface_type, method_name, ReturnType, ParameterTypes);
3008 if (implementing != null) {
3009 if (!implementing_list.Contains (implementing)) {
3010 implementing_list.Add (implementing);
3011 implementing_iface.Add(current_iface_type);
3013 IsImplementing = true;
3014 } else {
3015 Type[] current_iface_types = current_iface_type.GetInterfaces();
3016 if (current_iface_types.Length == 0)
3017 return false;
3019 foreach (Type curr_iface_type in current_iface_types) {
3020 IsImplementing = SearchBasesForAbstractMethods (
3021 parent, curr_iface_type, method_name,
3022 ref implementing_list, ref implementing_iface);
3024 if (IsImplementing)
3025 break;
3029 return IsImplementing;
3032 public virtual bool Define (TypeContainer parent)
3034 MethodInfo implementing = null;
3035 ArrayList implementing_list = null;
3036 ArrayList implementing_iface = null;
3037 string method_name, name, prefix, impl_method_name;
3038 int pos = -1;
3040 if (OptAttributes != null)
3041 if (!ApplyAttributes (OptAttributes, is_method))
3042 return false;
3044 if (accessor_name != null)
3045 name = accessor_name + "_" + member.ShortName;
3046 else
3047 name = member.ShortName;
3049 method_name = name;
3050 impl_method_name = name;
3052 if ((member.ModFlags & Modifiers.OVERRIDE) != 0) {
3053 if (parent.Pending == null)
3054 implementing = null;
3056 else if (member is Indexer)
3057 implementing = parent.Pending.IsAbstractIndexer (
3058 (Type) parent.TypeBuilder.BaseType,
3059 ReturnType, ParameterTypes);
3061 else
3062 implementing = parent.Pending.IsAbstractMethod (
3063 (Type) parent.TypeBuilder.BaseType, name,
3064 ReturnType, ParameterTypes);
3066 if (implementing != null)
3067 IsImplementing = true;
3070 if (member.Implements != null) {
3071 implementing_list = new ArrayList();
3072 implementing_iface = new ArrayList();
3074 foreach (Expression Impl in member.Implements) {
3075 name = Impl.ToString();
3076 prefix = name.Substring(0, name.LastIndexOf("."));
3077 name = name.Substring(name.LastIndexOf(".") + 1);
3079 if (accessor_name != null)
3080 impl_method_name = accessor_name + "_" + name;
3081 else
3082 impl_method_name = name;
3084 Type current_iface_type = (Type) member.InterfaceTypes[++pos];
3085 IsImplementing = SearchBasesForAbstractMethods (
3086 parent, current_iface_type, impl_method_name,
3087 ref implementing_list, ref implementing_iface);
3089 if (IsImplementing == false) {
3090 TypeContainer.Error_NotInterfaceMember (
3091 Location, name, prefix);
3092 return false;
3098 // For implicit implementations, make sure we are public, for
3099 // explicit implementations, make sure we are private.
3101 //if (IsImplementing){
3103 // Setting null inside this block will trigger a more
3104 // verbose error reporting for missing interface implementations
3106 // The "candidate" function has been flagged already
3107 // but it wont get cleared
3109 /* if (!member.IsExplicitImpl){
3111 // We already catch different accessibility settings
3112 // so we just need to check that we are not private
3114 if ((modifiers & Modifiers.PRIVATE) != 0)
3115 implementing = null;
3118 // Static is not allowed
3120 if ((modifiers & Modifiers.STATIC) != 0)
3121 implementing = null;
3122 } else {
3123 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3124 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3125 implementing = null;
3131 // If implementing is still valid, set flags
3133 if (IsImplementing){
3135 // When implementing interface methods, set NewSlot.
3137 if (implementing_list != null && implementing_list.Count != 0)
3138 flags |= MethodAttributes.NewSlot;
3140 flags |=
3141 MethodAttributes.Virtual |
3142 MethodAttributes.HideBySig;
3146 // Create the MethodBuilder for the method
3148 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3149 if ((modifiers & Modifiers.STATIC) == 0) {
3150 Report.Error (601, Location,
3151 "The DllImport attribute must be specified on " +
3152 "a method marked 'static' and 'extern'.");
3153 return false;
3156 EmitContext ec = new EmitContext (
3157 parent, Location, null, ReturnType, modifiers);
3159 builder = dllimport_attribute.DefinePInvokeMethod (
3160 ec, parent.TypeBuilder, method_name, flags,
3161 ReturnType, ParameterTypes);
3162 } else
3163 builder = parent.TypeBuilder.DefineMethod (
3164 method_name, flags, CallingConventions,
3165 ReturnType, ParameterTypes);
3167 if (builder == null)
3168 return false;
3170 if (IsImplementing) {
3172 // implement abstract methods from abstract classes
3174 if ((member.ModFlags & Modifiers.OVERRIDE) != 0) {
3176 if (member is Indexer)
3177 parent.Pending.ImplementIndexer (
3178 (Type) parent.TypeBuilder.BaseType,
3179 builder, ReturnType,
3180 ParameterTypes, true);
3181 else
3183 parent.Pending.ImplementMethod (
3184 (Type) parent.TypeBuilder.BaseType,
3185 name, ReturnType,
3186 ParameterTypes, member.IsExplicitImpl);
3190 // implement abstract methods of interfaces
3192 if (member.Implements != null) {
3193 pos = 0;
3194 foreach (MethodInfo Impl in implementing_list) {
3197 if (member is Indexer)
3198 parent.Pending.ImplementIndexer (
3199 (Type) implementing_iface[pos++],
3200 builder, ReturnType,
3201 ParameterTypes, true);
3202 else
3204 parent.Pending.ImplementMethod (
3205 (Type) implementing_iface[pos++],
3206 Impl.Name, ReturnType,
3207 ParameterTypes, member.IsExplicitImpl);
3209 parent.TypeBuilder.DefineMethodOverride (
3210 builder, Impl);
3216 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3217 Report.Error (111, Location,
3218 "Class `" + parent.Name +
3219 "' already contains a definition with the " +
3220 "same return value and parameter types as the " +
3221 "'get' method of property `" + member.Name + "'");
3222 return false;
3225 TypeManager.AddMethod (builder, this);
3226 return true;
3230 // Emits the code
3232 public virtual void Emit (TypeContainer parent, Block block, object kind)
3234 ILGenerator ig;
3235 EmitContext ec;
3237 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3238 ig = builder.GetILGenerator ();
3239 else
3240 ig = null;
3242 ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3244 if (OptAttributes != null)
3245 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
3247 if (member is MethodCore)
3248 ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder);
3251 // abstract or extern methods have no bodies
3253 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3254 if (block == null)
3255 return;
3258 // abstract or extern methods have no bodies.
3260 if ((modifiers & Modifiers.ABSTRACT) != 0)
3261 Report.Error (
3262 500, Location, "Abstract method `" +
3263 TypeManager.MonoBASIC_Signature (builder) +
3264 "' can not have a body");
3266 if ((modifiers & Modifiers.EXTERN) != 0)
3267 Report.Error (
3268 179, Location, "External method `" +
3269 TypeManager.MonoBASIC_Signature (builder) +
3270 "' can not have a body");
3272 return;
3276 // Methods must have a body unless they're extern or abstract
3278 if (block == null) {
3279 Report.Error (
3280 501, Location, "Method `" +
3281 TypeManager.MonoBASIC_Signature (builder) +
3282 "' must declare a body since it is not marked " +
3283 "abstract or extern");
3284 return;
3288 // Handle destructors specially
3290 // FIXME: This code generates buggy code
3292 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3293 EmitDestructor (ec, block);
3294 else {
3295 ISymbolWriter sw = CodeGen.SymbolWriter;
3297 if ((sw != null) && !Location.IsNull (Location) &&
3298 !Location.IsNull (block.EndLocation)) {
3299 Location end = block.EndLocation;
3300 MethodToken token = MethodBuilder.GetToken ();
3301 sw.OpenMethod (new SymbolToken (token.Token));
3302 // Avoid error if we don't support debugging for the platform
3303 try {
3304 sw.SetMethodSourceRange (Location.SymbolDocument,
3305 Location.Row, 0,
3306 end.SymbolDocument,
3307 end.Row, 0);
3308 } catch (Exception) {
3311 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3313 sw.CloseMethod ();
3314 } else
3315 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3319 void EmitDestructor (EmitContext ec, Block block)
3321 ILGenerator ig = ec.ig;
3323 Label finish = ig.DefineLabel ();
3324 bool old_in_try = ec.InTry;
3326 ig.BeginExceptionBlock ();
3327 ec.InTry = true;
3328 ec.ReturnLabel = finish;
3329 ec.HasReturnLabel = true;
3330 ec.EmitTopBlock (block, null, Location);
3331 ec.InTry = old_in_try;
3333 // ig.MarkLabel (finish);
3334 bool old_in_finally = ec.InFinally;
3335 ec.InFinally = true;
3336 ig.BeginFinallyBlock ();
3338 if (ec.ContainerType.BaseType != null) {
3339 Expression member_lookup = Expression.MemberLookup (
3340 ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
3341 MemberTypes.Method, Expression.AllBindingFlags, Location);
3343 if (member_lookup != null){
3344 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3346 ig.Emit (OpCodes.Ldarg_0);
3347 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3350 ec.InFinally = old_in_finally;
3352 ig.EndExceptionBlock ();
3353 //ig.MarkLabel (ec.ReturnLabel);
3354 ig.Emit (OpCodes.Ret);
3358 abstract public class MemberBase : MemberCore {
3359 public Expression Type;
3360 public ArrayList Implements;
3362 protected MethodAttributes flags;
3365 // The "short" name of this property / indexer / event. This is the
3366 // name without the explicit interface.
3368 public string ShortName;
3371 // The type of this property / indexer / event
3373 public Type MemberType;
3376 // If true, this is an explicit interface implementation
3378 public bool IsExplicitImpl = false;
3381 // The name of the interface we are explicitly implementing
3383 public string ExplicitInterfaceName = null;
3386 // If true, the interface type we are explicitly implementing
3388 public Type InterfaceType = null;
3389 public ArrayList InterfaceTypes = null;
3392 // The method we're overriding if this is an override method.
3394 protected MethodInfo parent_method = null;
3395 public MethodInfo ParentMethod {
3396 get {
3397 return parent_method;
3402 // The constructor is only exposed to our children
3404 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3405 Attributes attrs, Location loc)
3406 : base (name, attrs, loc)
3408 Type = type;
3409 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PUBLIC, loc);
3412 protected virtual bool CheckBase (TypeContainer parent)
3414 return true;
3417 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3419 bool error = false;
3421 foreach (Type partype in parameters){
3422 if (partype.IsPointer && !UnsafeOK (parent))
3423 error = true;
3425 if (parent.AsAccessible (partype, ModFlags))
3426 continue;
3429 if (this is Indexer)
3430 Report.Error (55, Location,
3431 "Inconsistent accessibility: parameter type `" +
3432 TypeManager.MonoBASIC_Name (partype) + "' is less " +
3433 "accessible than indexer `" + Name + "'");
3434 else
3436 Report.Error (51, Location,
3437 "Inconsistent accessibility: parameter type `" +
3438 TypeManager.MonoBASIC_Name (partype) + "' is less " +
3439 "accessible than method `" + Name + "'");
3440 error = true;
3443 return !error;
3446 protected virtual bool DoDefine (TypeContainer parent)
3448 if (Name == null)
3449 Name = "this";
3451 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3452 return false;
3454 flags = Modifiers.MethodAttr (ModFlags);
3456 // Lookup Type, verify validity
3457 MemberType = parent.ResolveType (Type, false, Location);
3458 if (MemberType == null)
3459 return false;
3461 // check for whether the Interface is implemented by the class
3462 if (Implements != null) {
3463 InterfaceTypes = new ArrayList ();
3464 foreach (Expression Impls in Implements) {
3465 string iname = Impls.ToString();
3466 iname = iname.Substring(0, iname.LastIndexOf("."));
3467 bool iface_found = false;
3469 InterfaceType = RootContext.LookupType (
3470 parent, iname, false, Location);
3471 if (InterfaceType == null)
3472 return false;
3474 InterfaceTypes.Add (InterfaceType);
3475 Type[] tbases = parent.TypeBuilder.GetInterfaces();
3477 if (tbases.Length != 0) {
3478 ArrayList bases = new ArrayList();
3479 TypeManager.ExpandAllInterfaces (tbases, ref bases);
3481 foreach (Type tbase in bases) {
3482 string bname = tbase.Name;
3483 if (bname.LastIndexOf(".") != -1)
3484 bname = bname.Substring(bname.LastIndexOf("."));
3486 if (bname == iname) {
3487 iface_found = true;
3488 break;
3493 if (!iface_found) {
3494 Report.Error (31035, Location,
3495 "Class '" + parent.Name + "' doesn't implement interface '" + iname + "'");
3496 return false;
3501 // verify accessibility
3502 if (!parent.AsAccessible (MemberType, ModFlags)) {
3503 if (this is Property)
3504 Report.Error (53, Location,
3505 "Inconsistent accessibility: property type `" +
3506 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3507 "accessible than property `" + Name + "'");
3509 else if (this is Indexer)
3510 Report.Error (54, Location,
3511 "Inconsistent accessibility: indexer return type `" +
3512 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3513 "accessible than indexer `" + Name + "'");
3515 else if (this is Method)
3516 Report.Error (50, Location,
3517 "Inconsistent accessibility: return type `" +
3518 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3519 "accessible than method `" + Name + "'");
3520 else
3521 Report.Error (52, Location,
3522 "Inconsistent accessibility: field type `" +
3523 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3524 "accessible than field `" + Name + "'");
3525 return false;
3528 if (MemberType.IsPointer && !UnsafeOK (parent))
3529 return false;
3532 // Check for explicit interface implementation
3534 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)) {
3535 int pos = Name.LastIndexOf (".");
3537 ExplicitInterfaceName = Name.Substring (0, pos);
3538 ShortName = Name.Substring (pos + 1);
3539 } else
3540 ShortName = Name;
3542 return true;
3547 // Fields and Events both generate FieldBuilders, we use this to share
3548 // their common bits. This is also used to flag usage of the field
3550 abstract public class FieldBase : MemberBase {
3551 public FieldBuilder FieldBuilder;
3552 public Status status;
3554 [Flags]
3555 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3558 // The constructor is only exposed to our children
3560 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3561 object init, Attributes attrs, Location loc)
3562 : base (type, mod, allowed_mod, name, attrs, loc)
3564 this.init = init;
3567 public override AttributeTargets AttributeTargets {
3568 get {
3569 return AttributeTargets.Field;
3575 // Whether this field has an initializer.
3577 public bool HasInitializer {
3578 get {
3579 return init != null;
3583 // Private.
3584 readonly Object init;
3585 Expression init_expr;
3586 bool init_expr_initialized = false;
3589 // Resolves and returns the field initializer.
3591 public Expression GetInitializerExpression (EmitContext ec)
3593 if (init_expr_initialized)
3594 return init_expr;
3596 Expression e;
3597 if (init is Expression)
3598 e = (Expression) init;
3599 else
3600 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3602 ec.IsFieldInitializer = true;
3603 e = e.DoResolve (ec);
3604 ec.IsFieldInitializer = false;
3606 init_expr = e;
3607 init_expr_initialized = true;
3609 return init_expr;
3615 // The Field class is used to represents class/struct fields during parsing.
3617 public class Field : FieldBase {
3618 // <summary>
3619 // Modifiers allowed in a class declaration
3620 // </summary>
3621 const int AllowedModifiers =
3622 Modifiers.SHADOWS |
3623 Modifiers.PUBLIC |
3624 Modifiers.PROTECTED |
3625 Modifiers.INTERNAL |
3626 Modifiers.PRIVATE |
3627 Modifiers.STATIC |
3628 // Modifiers.VOLATILE |
3629 // Modifiers.UNSAFE |
3630 Modifiers.READONLY;
3632 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3633 Attributes attrs, Location loc)
3634 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3638 public override AttributeTargets AttributeTargets {
3639 get {
3640 return AttributeTargets.Field;
3644 public override bool Define (TypeContainer parent)
3646 Type t = parent.ResolveType (Type, false, Location);
3648 if (t == null)
3649 return false;
3651 if (!parent.AsAccessible (t, ModFlags)) {
3652 Report.Error (52, Location,
3653 "Inconsistent accessibility: field type `" +
3654 TypeManager.MonoBASIC_Name (t) + "' is less " +
3655 "accessible than field `" + Name + "'");
3656 return false;
3659 if (t.IsPointer && !UnsafeOK (parent))
3660 return false;
3662 Type ptype = parent.TypeBuilder.BaseType;
3664 // ptype is only null for System.Object while compiling corlib.
3665 if (ptype != null){
3666 MemberList list = TypeContainer.FindMembers (
3667 ptype, MemberTypes.Field,
3668 BindingFlags.Public |
3669 BindingFlags.Static | BindingFlags.Instance,
3670 System.Type.FilterName, Name);
3672 if (RootContext.WarningLevel > 1){
3673 if ((list.Count > 0) && ((ModFlags & Modifiers.SHADOWS) == 0))
3675 Report.Warning (
3676 40004, 2, Location,
3677 "Variable '" + Name + "' should be declared " +
3678 "Shadows since the base type '" + ptype.Name +
3679 "' has a variable with same name");
3681 ModFlags |= Modifiers.SHADOWS;
3684 if (list.Count == 0)
3685 // if a member of module is not inherited from Object class
3686 // can not be declared protected
3687 if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
3688 Report.Error (30593, Location,
3689 "'Variable' inside a 'Module' can not be " +
3690 "declared as 'Protected'");
3693 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
3694 Report.Error (30435, Location,
3695 "'Variable' inside a 'Structure' can not be " +
3696 "declared as 'Protected'");
3698 if ((ModFlags & Modifiers.VOLATILE) != 0){
3699 if (!t.IsClass){
3700 if (TypeManager.IsEnumType (t))
3701 t = TypeManager.EnumToUnderlying (t);
3703 if (!((t == TypeManager.bool_type) ||
3704 (t == TypeManager.sbyte_type) ||
3705 (t == TypeManager.byte_type) ||
3706 (t == TypeManager.short_type) ||
3707 (t == TypeManager.ushort_type) ||
3708 (t == TypeManager.int32_type) ||
3709 (t == TypeManager.uint32_type) ||
3710 (t == TypeManager.char_type) ||
3711 (t == TypeManager.float_type))){
3712 Report.Error (
3713 677, Location, parent.MakeName (Name) +
3714 " A volatile field can not be of type `" +
3715 TypeManager.MonoBASIC_Name (t) + "'");
3716 return false;
3721 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3723 if (parent is Struct &&
3724 ((fa & FieldAttributes.Static) == 0) &&
3725 t == parent.TypeBuilder &&
3726 !TypeManager.IsBuiltinType (t)){
3727 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name +
3728 "' causes a cycle in the structure layout");
3729 return false;
3731 FieldBuilder = parent.TypeBuilder.DefineField (
3732 Name, t, Modifiers.FieldAttr (ModFlags));
3734 TypeManager.RegisterFieldBase (FieldBuilder, this);
3735 return true;
3738 public void Emit (TypeContainer tc)
3740 EmitContext ec = new EmitContext (tc, Location, null,
3741 FieldBuilder.FieldType, ModFlags);
3743 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
3748 // `set' and `get' accessors are represented with an Accessor.
3750 public class Accessor {
3752 // Null if the accessor is empty, or a Block if not
3754 public Block Block;
3755 public Attributes OptAttributes;
3757 public Accessor (Block b, Attributes attrs)
3759 Block = b;
3760 OptAttributes = attrs;
3764 public class Property : MethodCore {
3765 public Accessor Get, Set;
3766 public PropertyBuilder PropertyBuilder;
3767 public MethodBuilder GetBuilder, SetBuilder;
3768 public MethodData GetData, SetData;
3770 protected EmitContext ec;
3772 public override AttributeTargets AttributeTargets {
3773 get {
3774 return AttributeTargets.Property;
3778 protected override bool DoDefine (TypeContainer parent)
3780 if (!base.DoDefine (parent))
3781 return false;
3783 ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3785 return true;
3789 // Checks our base implementation if any
3791 protected override bool CheckBase (TypeContainer container)
3793 base.CheckBase (container);
3795 // Check whether arguments were correct.
3796 if (!DoDefineParameters (container))
3797 return false;
3799 if (IsExplicitImpl)
3800 return true;
3802 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
3803 if (!IsOperator)
3805 MemberList mi_this;
3807 mi_this = TypeContainer.FindMembers (
3808 container.TypeBuilder, MemberTypes.Property,
3809 BindingFlags.NonPublic | BindingFlags.Public |
3810 BindingFlags.Static | BindingFlags.Instance |
3811 BindingFlags.DeclaredOnly,
3812 MethodSignature.method_signature_filter, ms);
3814 if (mi_this.Count > 0) {
3815 Report.Error (111, Location, "Class `" + container.Name + "' " +
3816 "already defines a member called `" + Name + "' " +
3817 "with the same parameter types");
3818 return false;
3822 if (container is Interface)
3823 return true;
3825 Type retval = null;
3826 if ((ModFlags & Modifiers.READONLY) != 0)
3827 retval = MemberType;
3829 string report_name;
3830 MethodSignature base_ms;
3833 if (this is Indexer) {
3834 string name, base_name;
3836 report_name = "this";
3837 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
3838 ms = new MethodSignature (name, null, ParameterTypes);
3839 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
3840 base_ms = new MethodSignature (base_name, retval, ParameterTypes);
3841 } else */ {
3842 report_name = Name;
3843 ms = base_ms = new MethodSignature (Name, retval, ParameterTypes);
3847 // Verify if the parent has a type with the same name, and then
3848 // check whether we have to create a new slot for it or not.
3850 Type ptype = container.TypeBuilder.BaseType;
3852 MemberInfo parent_member = null;
3853 MemberList mi, mi_static, mi_instance;
3856 // Find properties with the same name on the base class
3858 mi_static = TypeContainer.FindMembers (
3859 ptype, MemberTypes.Property,
3860 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3861 MethodSignature.inheritable_property_signature_filter, base_ms);
3863 mi_instance = TypeContainer.FindMembers (
3864 ptype, MemberTypes.Property,
3865 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3866 MethodSignature.inheritable_property_signature_filter,
3867 base_ms);
3870 if (mi_instance.Count > 0)
3871 mi = mi_instance;
3872 else if (mi_static.Count > 0)
3873 mi = mi_static;
3874 else
3875 mi = null;
3877 if (mi != null && mi.Count > 0)
3878 parent_member = (PropertyInfo) mi [0];
3880 if (parent_member is PropertyInfo) {
3881 PropertyInfo parent_property = (PropertyInfo)parent_member;
3883 string name = parent_property.DeclaringType.Name + "." +
3884 parent_property.Name;
3886 MethodInfo get, set, parent_method;
3887 get = parent_property.GetGetMethod (true);
3888 set = parent_property.GetSetMethod (true);
3890 if (get != null)
3891 parent_method = get;
3892 else if (set != null)
3893 parent_method = set;
3894 else
3895 throw new Exception ("Internal error!");
3897 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
3898 return false;
3900 if ((ModFlags & Modifiers.NEW) == 0) {
3901 Type parent_type = TypeManager.TypeToCoreType (
3902 parent_property.PropertyType);
3904 if (parent_type != MemberType) {
3905 Report.Error (
3906 508, Location, container.MakeName (Name) + ": cannot " +
3907 "change return type when overriding " +
3908 "inherited member " + name);
3909 return false;
3912 } else if (parent_member == null) {
3913 /*if ((ModFlags & Modifiers.NEW) != 0)
3914 WarningNotHiding (container);
3916 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3919 if (this is Indexer)
3920 Report.Error (115, Location,
3921 container.MakeName (Name) +
3922 " no suitable indexers found to override");
3923 else
3925 Report.Error (115, Location,
3926 container.MakeName (Name) +
3927 " no suitable properties found to override");
3928 return false;
3931 if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0) {
3932 if ((ModFlags & Modifiers.NONVIRTUAL) != 0) {
3933 Report.Error (31088, Location,
3934 container.MakeName (Name) + " : Cannot " +
3935 "be declared NotOverridable since this method is " +
3936 "not maked as Overrides");
3939 // if a member of module is not inherited from Object class
3940 // can not be declared protected
3941 if ((container is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
3942 Report.Error (31066, Location,
3943 "'Property' inside a 'Module' can not be declared as " +
3944 "'Protected' or 'Protected Friend'");
3946 return true;
3950 const int AllowedModifiers =
3951 Modifiers.NEW |
3952 Modifiers.PUBLIC |
3953 Modifiers.PROTECTED |
3954 Modifiers.INTERNAL |
3955 Modifiers.PRIVATE |
3956 Modifiers.STATIC |
3957 Modifiers.SEALED |
3958 Modifiers.OVERRIDE |
3959 Modifiers.ABSTRACT |
3960 Modifiers.UNSAFE |
3961 Modifiers.EXTERN |
3962 Modifiers.VIRTUAL |
3963 Modifiers.NONVIRTUAL |
3964 Modifiers.DEFAULT |
3965 Modifiers.READONLY |
3966 Modifiers.WRITEONLY |
3967 Modifiers.SHADOWS;
3969 string set_parameter_name;
3970 Parameters get_params;
3971 Parameters set_params;
3973 public Property (Expression type, string name, int mod_flags,
3974 Accessor get_block, Accessor set_block,
3975 Attributes attrs, Location loc, string set_name,
3976 Parameters p_get, Parameters p_set, ArrayList impl_what)
3977 : base (type, mod_flags, AllowedModifiers, name, attrs, p_set, loc)
3980 Get = get_block;
3981 get_params = p_get;
3983 Set = set_block;
3984 set_params = p_set;
3985 set_parameter_name = set_name;
3987 Implements = impl_what;
3990 public Property (Expression type, string name, int mod_flags,
3991 Accessor get_block, Accessor set_block,
3992 Attributes attrs, Location loc)
3993 : this (type, name, mod_flags, get_block, set_block, attrs, loc,
3994 "Value", Parameters.EmptyReadOnlyParameters, Parameters.EmptyReadOnlyParameters, null)
3998 public override bool Define (TypeContainer parent)
4000 Type [] g_parameters=null, s_parameters=null;
4001 Parameter [] g_parms, s_parms;
4002 InternalParameters g_ip=null, s_ip=null;
4004 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
4005 Report.Error (30435, Location,
4006 "'Property' inside a 'Structure' can not be declared as " +
4007 "'Protected' or 'Protected Friend'");
4009 if (!DoDefine (parent))
4010 return false;
4012 if (!CheckBase (parent))
4013 return false;
4015 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4017 if (Get == null) {
4018 if ((ModFlags & Modifiers.WRITEONLY) == 0)
4019 Report.Error (
4020 30124, Location,
4021 "Property without 'Get' accessor must have a 'WriteOnly' modifier");
4023 else {
4024 if (get_params == Parameters.EmptyReadOnlyParameters) {
4025 g_parameters = TypeManager.NoTypes;
4026 g_ip = new InternalParameters (
4027 parent, Parameters.EmptyReadOnlyParameters);
4028 } else {
4029 g_parameters = new Type [get_params.FixedParameters.Length];
4030 for (int i = 0; i < get_params.FixedParameters.Length; i ++) {
4031 g_parameters[i] = get_params.FixedParameters[i].ParameterType;
4033 g_parms = new Parameter [get_params.FixedParameters.Length];
4034 for (int i = 0; i < get_params.FixedParameters.Length; i ++) {
4035 Parameter tp = get_params.FixedParameters[i];
4036 g_parms[i] = new Parameter (tp.TypeName, tp.Name,
4037 Parameter.Modifier.NONE, null);
4039 g_ip = new InternalParameters (
4040 parent, new Parameters (g_parms, null, Location));
4043 GetData = new MethodData (this, "get", MemberType,
4044 g_parameters, g_ip, CallingConventions.Standard,
4045 Get.OptAttributes, ModFlags, flags, false);
4047 if (!GetData.Define (parent))
4048 return false;
4050 GetBuilder = GetData.MethodBuilder;
4053 if (Set == null) {
4054 if ((ModFlags & Modifiers.READONLY) == 0)
4055 Report.Error (
4056 30124, Location,
4057 "Property without 'Set' accessor must have a 'ReadOnly' modifier");
4060 else
4062 if (set_params == Parameters.EmptyReadOnlyParameters)
4064 s_parameters = new Type [1];
4065 s_parameters [0] = MemberType;
4067 s_parms = new Parameter [1];
4068 s_parms [0] = new Parameter (Type, set_parameter_name,
4069 Parameter.Modifier.NONE, null);
4070 } else {
4071 s_parameters = new Type [set_params.FixedParameters.Length];
4072 for (int i = 0; i < set_params.FixedParameters.Length; i ++) {
4073 s_parameters[i] = set_params.FixedParameters[i].ParameterType;
4076 s_parms = new Parameter [set_params.FixedParameters.Length];
4077 for (int i = 0; i < set_params.FixedParameters.Length; i ++) {
4078 Parameter tp = set_params.FixedParameters[i];
4079 s_parms[i] = new Parameter (tp.TypeName, tp.Name,
4080 Parameter.Modifier.NONE, null);
4084 s_ip = new InternalParameters (
4085 parent, new Parameters (s_parms, null, Location));
4087 SetData = new MethodData (this, "set", TypeManager.void_type,
4088 s_parameters, s_ip, CallingConventions.Standard,
4089 Set.OptAttributes, ModFlags, flags, false);
4091 if (!SetData.Define (parent))
4092 return false;
4094 SetBuilder = SetData.MethodBuilder;
4095 SetBuilder.DefineParameter (1, ParameterAttributes.None,
4096 set_parameter_name);
4099 // FIXME - PropertyAttributes.HasDefault ?
4101 PropertyAttributes prop_attr =
4102 PropertyAttributes.RTSpecialName |
4103 PropertyAttributes.SpecialName;
4105 if (!IsExplicitImpl){
4106 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4107 Name, prop_attr, MemberType, null);
4109 PropertyBuilder.SetGetMethod (GetBuilder);
4110 PropertyBuilder.SetSetMethod (SetBuilder);
4113 // HACK for the reasons exposed above
4115 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4116 Report.Error (
4117 111, Location,
4118 "Class `" + parent.Name +
4119 "' already contains a definition for the property `" +
4120 Name + "'");
4121 return false;
4124 return true;
4127 public void Emit (TypeContainer tc)
4130 // The PropertyBuilder can be null for explicit implementations, in that
4131 // case, we do not actually emit the ".property", so there is nowhere to
4132 // put the attribute
4135 if (PropertyBuilder != null)
4136 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
4138 if (GetData != null)
4140 Parameters = get_params;
4141 GetData.Emit (tc, Get.Block, Get);
4144 if (SetData != null)
4146 Parameters = set_params;
4147 SetData.Emit (tc, Set.Block, Set);
4153 /// </summary>
4154 /// Gigantic workaround for lameness in SRE follows :
4155 /// This class derives from EventInfo and attempts to basically
4156 /// wrap around the EventBuilder so that FindMembers can quickly
4157 /// return this in it search for members
4158 /// </summary>
4159 public class MyEventBuilder : EventInfo {
4162 // We use this to "point" to our Builder which is
4163 // not really a MemberInfo
4165 EventBuilder MyBuilder;
4168 // We "catch" and wrap these methods
4170 MethodInfo raise, remove, add;
4172 EventAttributes attributes;
4173 Type declaring_type, reflected_type, event_type;
4174 string name;
4176 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4178 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4180 // And now store the values in our own fields.
4182 declaring_type = type_builder;
4184 reflected_type = type_builder;
4186 attributes = event_attr;
4187 this.name = name;
4188 this.event_type = event_type;
4192 // Methods that you have to override. Note that you only need
4193 // to "implement" the variants that take the argument (those are
4194 // the "abstract" methods, the others (GetAddMethod()) are
4195 // regular.
4197 public override MethodInfo GetAddMethod (bool nonPublic)
4199 return add;
4202 public override MethodInfo GetRemoveMethod (bool nonPublic)
4204 return remove;
4207 public override MethodInfo GetRaiseMethod (bool nonPublic)
4209 return raise;
4213 // These methods make "MyEventInfo" look like a Builder
4215 public void SetRaiseMethod (MethodBuilder raiseMethod)
4217 raise = raiseMethod;
4218 MyBuilder.SetRaiseMethod (raiseMethod);
4221 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4223 remove = removeMethod;
4224 MyBuilder.SetRemoveOnMethod (removeMethod);
4227 public void SetAddOnMethod (MethodBuilder addMethod)
4229 add = addMethod;
4230 MyBuilder.SetAddOnMethod (addMethod);
4233 public void SetCustomAttribute (CustomAttributeBuilder cb)
4235 MyBuilder.SetCustomAttribute (cb);
4238 public override object [] GetCustomAttributes (bool inherit)
4240 // FIXME : There's nothing which can be seemingly done here because
4241 // we have no way of getting at the custom attribute objects of the
4242 // EventBuilder !
4243 return null;
4246 public override object [] GetCustomAttributes (Type t, bool inherit)
4248 // FIXME : Same here !
4249 return null;
4252 public override bool IsDefined (Type t, bool b)
4254 return true;
4257 public override EventAttributes Attributes {
4258 get {
4259 return attributes;
4263 public override string Name {
4264 get {
4265 return name;
4269 public override Type DeclaringType {
4270 get {
4271 return declaring_type;
4275 public override Type ReflectedType {
4276 get {
4277 return reflected_type;
4281 public Type EventType {
4282 get {
4283 return event_type;
4288 public class Event : FieldBase {
4289 const int AllowedModifiers =
4290 Modifiers.NEW |
4291 Modifiers.PUBLIC |
4292 Modifiers.PROTECTED |
4293 Modifiers.INTERNAL |
4294 Modifiers.PRIVATE |
4295 Modifiers.STATIC |
4296 Modifiers.VIRTUAL |
4297 Modifiers.SEALED |
4298 Modifiers.OVERRIDE |
4299 Modifiers.UNSAFE |
4300 Modifiers.ABSTRACT;
4302 public readonly Accessor Add;
4303 public readonly Accessor Remove;
4304 public MyEventBuilder EventBuilder;
4306 MethodBuilder AddBuilder, RemoveBuilder;
4307 MethodData AddData, RemoveData;
4309 public Event (Expression type, string name, Object init, int mod, Accessor add,
4310 Accessor remove, Attributes attrs, Location loc)
4311 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4313 Add = add;
4314 Remove = remove;
4315 Implements = null;
4318 public Event (Expression type, string name, Object init, int mod, Accessor add,
4319 Accessor remove, Attributes attrs, ArrayList impl_what, Location loc)
4320 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4322 Add = add;
4323 Remove = remove;
4324 Implements = impl_what;
4327 public override AttributeTargets AttributeTargets {
4328 get {
4329 return AttributeTargets.Event;
4333 public override bool Define (TypeContainer parent)
4335 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4337 if (!DoDefine (parent))
4338 return false;
4340 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4341 Report.Error (31044, Location, "'" + parent.Name + "." + Name +
4342 "' : event must be of a delegate type");
4343 return false;
4346 Type [] parameter_types = new Type [1];
4347 parameter_types [0] = MemberType;
4349 Parameter [] parms = new Parameter [1];
4350 parms [0] = new Parameter (Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4351 InternalParameters ip = new InternalParameters (
4352 parent, new Parameters (parms, null, Location));
4354 if (!CheckBase (parent))
4355 return false;
4358 // Now define the accessors
4360 AddData = new MethodData (this, "add", TypeManager.void_type,
4361 parameter_types, ip, CallingConventions.Standard,
4362 (Add != null) ? Add.OptAttributes : null,
4363 ModFlags, flags, false);
4365 if (!AddData.Define (parent))
4366 return false;
4368 AddBuilder = AddData.MethodBuilder;
4369 AddBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4371 RemoveData = new MethodData (this, "remove", TypeManager.void_type,
4372 parameter_types, ip, CallingConventions.Standard,
4373 (Remove != null) ? Remove.OptAttributes : null,
4374 ModFlags, flags, false);
4376 if (!RemoveData.Define (parent))
4377 return false;
4379 RemoveBuilder = RemoveData.MethodBuilder;
4380 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4382 if (!IsExplicitImpl){
4383 EventBuilder = new MyEventBuilder (
4384 parent.TypeBuilder, Name, e_attr, MemberType);
4386 if (Add == null && Remove == null) {
4387 FieldBuilder = parent.TypeBuilder.DefineField (
4388 Name, MemberType,
4389 FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4390 TypeManager.RegisterPrivateFieldOfEvent (
4391 (EventInfo) EventBuilder, FieldBuilder);
4392 TypeManager.RegisterFieldBase (FieldBuilder, this);
4395 EventBuilder.SetAddOnMethod (AddBuilder);
4396 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4398 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4399 Report.Error (111, Location,
4400 "Class `" + parent.Name +
4401 "' already contains a definition for the event `" +
4402 Name + "'");
4403 return false;
4407 return true;
4410 void EmitDefaultMethod (EmitContext ec, bool is_add)
4412 ILGenerator ig = ec.ig;
4413 MethodInfo method = null;
4415 if (is_add)
4416 method = TypeManager.delegate_combine_delegate_delegate;
4417 else
4418 method = TypeManager.delegate_remove_delegate_delegate;
4420 if ((ModFlags & Modifiers.STATIC) != 0) {
4421 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4422 ig.Emit (OpCodes.Ldarg_0);
4423 ig.Emit (OpCodes.Call, method);
4424 ig.Emit (OpCodes.Castclass, MemberType);
4425 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4426 } else {
4427 ig.Emit (OpCodes.Ldarg_0);
4428 ig.Emit (OpCodes.Ldarg_0);
4429 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4430 ig.Emit (OpCodes.Ldarg_1);
4431 ig.Emit (OpCodes.Call, method);
4432 ig.Emit (OpCodes.Castclass, MemberType);
4433 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4435 ig.Emit (OpCodes.Ret);
4438 public void Emit (TypeContainer tc)
4440 EmitContext ec;
4442 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4443 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
4445 if (Add != null)
4446 AddData.Emit (tc, Add.Block, Add);
4447 else {
4448 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4449 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4450 EmitDefaultMethod (ec, true);
4453 if (Remove != null)
4454 RemoveData.Emit (tc, Remove.Block, Remove);
4455 else {
4456 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4457 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4458 EmitDefaultMethod (ec, false);
4465 // FIXME: This does not handle:
4467 // int INTERFACENAME [ args ]
4468 // Does not
4470 // Only:
4472 // int this [ args ]
4476 public class Indexer : PropertyBase {
4478 const int AllowedModifiers =
4479 Modifiers.NEW |
4480 Modifiers.PUBLIC |
4481 Modifiers.PROTECTED |
4482 Modifiers.INTERNAL |
4483 Modifiers.PRIVATE |
4484 Modifiers.VIRTUAL |
4485 Modifiers.SEALED |
4486 Modifiers.OVERRIDE |
4487 Modifiers.UNSAFE |
4488 Modifiers.EXTERN |
4489 Modifiers.ABSTRACT;
4491 public string IndexerName;
4492 public string InterfaceIndexerName;
4495 // Are we implementing an interface ?
4497 bool IsImplementing = false;
4499 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4500 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4501 : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4502 attrs, loc)
4504 ExplicitInterfaceName = int_type;
4507 public override bool Define (TypeContainer parent)
4509 PropertyAttributes prop_attr =
4510 PropertyAttributes.RTSpecialName |
4511 PropertyAttributes.SpecialName;
4513 if (!DoDefine (parent))
4514 return false;
4516 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4517 if (IndexerName == null)
4518 IndexerName = "Item";
4519 else if (IsExplicitImpl)
4520 Report.Error (592, Location,
4521 "Attribute 'IndexerName' is not valid on this declaration " +
4522 "type. It is valid on `property' declarations only.");
4524 ShortName = IndexerName;
4525 if (IsExplicitImpl) {
4526 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4527 Name = InterfaceType.FullName + "." + IndexerName;
4528 } else {
4529 InterfaceIndexerName = IndexerName;
4530 Name = ShortName;
4533 if (!CheckBase (parent))
4534 return false;
4536 if (Get != null){
4537 InternalParameters ip = new InternalParameters (parent, Parameters);
4539 GetData = new MethodData (this, "get", MemberType,
4540 ParameterTypes, ip, CallingConventions.Standard,
4541 Get.OptAttributes, ModFlags, flags, false);
4543 if (!GetData.Define (parent))
4544 return false;
4546 GetBuilder = GetData.MethodBuilder;
4549 if (Set != null){
4550 int top = ParameterTypes.Length;
4551 Type [] set_pars = new Type [top + 1];
4552 ParameterTypes.CopyTo (set_pars, 0);
4553 set_pars [top] = MemberType;
4555 Parameter [] fixed_parms = Parameters.FixedParameters;
4557 if (fixed_parms == null){
4558 throw new Exception ("We currently do not support only array arguments in an indexer");
4559 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4560 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4562 // Here is the problem: the `value' parameter has
4563 // to come *after* the array parameter in the declaration
4564 // like this:
4565 // X (object [] x, Type value)
4566 // .param [0]
4568 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4569 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4573 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4576 fixed_parms.CopyTo (tmp, 0);
4577 tmp [fixed_parms.Length] = new Parameter (
4578 Type, this.Name, Parameter.Modifier.NONE, null);
4580 Parameters set_formal_params = new Parameters (tmp, null, Location);
4582 InternalParameters ip = new InternalParameters (parent, set_formal_params);
4584 SetData = new MethodData (this, "set", TypeManager.void_type,
4585 set_pars, ip, CallingConventions.Standard,
4586 Set.OptAttributes, ModFlags, flags, false);
4588 if (!SetData.Define (parent))
4589 return false;
4591 SetBuilder = SetData.MethodBuilder;
4595 // Now name the parameters
4597 Parameter [] p = Parameters.FixedParameters;
4598 if (p != null) {
4599 int i;
4601 for (i = 0; i < p.Length; ++i) {
4602 if (Get != null)
4603 GetBuilder.DefineParameter (
4604 i + 1, p [i].Attributes, p [i].Name);
4606 if (Set != null)
4607 SetBuilder.DefineParameter (
4608 i + 1, p [i].Attributes, p [i].Name);
4612 if (Set != null)
4613 SetBuilder.DefineParameter (
4614 i + 1, ParameterAttributes.None, this.Name);
4616 if (i != ParameterTypes.Length) {
4617 Parameter array_param = Parameters.ArrayParameter;
4618 SetBuilder.DefineParameter (
4619 i + 1, array_param.Attributes, array_param.Name);
4623 if (GetData != null)
4624 IsImplementing = GetData.IsImplementing;
4625 else if (SetData != null)
4626 IsImplementing = SetData.IsImplementing;
4629 // Define the PropertyBuilder if one of the following conditions are met:
4630 // a) we're not implementing an interface indexer.
4631 // b) the indexer has a different IndexerName and this is no
4632 // explicit interface implementation.
4634 if (!IsExplicitImpl) {
4635 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4636 IndexerName, prop_attr, MemberType, ParameterTypes);
4638 if (GetData != null)
4639 PropertyBuilder.SetGetMethod (GetBuilder);
4641 if (SetData != null)
4642 PropertyBuilder.SetSetMethod (SetBuilder);
4644 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4645 ParameterTypes);
4648 return true;
4653 struct MethodSignature {
4654 public string Name;
4655 public Type RetType;
4656 public Type [] Parameters;
4658 /// <summary>
4659 /// This delegate is used to extract methods which have the
4660 /// same signature as the argument
4661 /// </summary>
4662 public static MemberFilter method_signature_filter;
4664 /// <summary>
4665 /// This delegate is used to extract methods which have the
4666 /// same signature as the argument except for the name
4667 /// </summary>
4668 public static MemberFilter method_signature_noname_filter;
4670 /// <summary>
4671 /// This delegate is used to extract inheritable methods which
4672 /// have the same signature as the argument. By inheritable,
4673 /// this means that we have permissions to override the method
4674 /// from the current assembly and class
4675 /// </summary>
4676 public static MemberFilter inheritable_method_signature_filter;
4678 /// <summary>
4679 /// This delegate is used to extract inheritable methods which
4680 /// have the same signature as the argument. By inheritable,
4681 /// this means that we have permissions to override the method
4682 /// from the current assembly and class
4683 /// </summary>
4684 public static MemberFilter inheritable_property_signature_filter;
4686 static MethodSignature ()
4688 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4689 method_signature_noname_filter = new MemberFilter (MemberSignatureCompareNoName);
4690 inheritable_method_signature_filter = new MemberFilter (
4691 InheritableMemberSignatureCompare);
4692 inheritable_property_signature_filter = new MemberFilter (
4693 InheritablePropertySignatureCompare);
4696 public MethodSignature (string name, Type ret_type, Type [] parameters)
4698 Name = name;
4699 RetType = ret_type;
4701 if (parameters == null)
4702 Parameters = TypeManager.NoTypes;
4703 else
4704 Parameters = parameters;
4707 public override int GetHashCode ()
4709 return Name.GetHashCode ();
4712 public override bool Equals (Object o)
4714 MethodSignature other = (MethodSignature) o;
4716 if (other.Name != Name)
4717 return false;
4719 if (other.RetType != RetType)
4720 return false;
4722 if (Parameters == null){
4723 if (other.Parameters == null)
4724 return true;
4725 return false;
4728 if (other.Parameters == null)
4729 return false;
4731 int c = Parameters.Length;
4732 if (other.Parameters.Length != c)
4733 return false;
4735 for (int i = 0; i < c; i++)
4736 if (other.Parameters [i] != Parameters [i])
4737 return false;
4739 return true;
4742 static bool MemberSignatureCompareNoName (MemberInfo m, object filter_criteria)
4744 return MemberSignatureCompare (m, filter_criteria, false);
4747 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4749 return MemberSignatureCompare (m, filter_criteria, true);
4752 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria, bool use_name)
4754 MethodSignature sig = (MethodSignature) filter_criteria;
4756 if (use_name && (m.Name != sig.Name))
4757 return false;
4759 Type ReturnType;
4760 MethodInfo mi = m as MethodInfo;
4761 PropertyInfo pi = m as PropertyInfo;
4763 if (mi != null)
4764 ReturnType = mi.ReturnType;
4765 else if (pi != null)
4766 ReturnType = pi.PropertyType;
4767 else
4768 return false;
4771 // we use sig.RetType == null to mean `do not check the
4772 // method return value.
4774 if (sig.RetType != null)
4775 if (ReturnType != sig.RetType)
4776 return false;
4778 Type [] args;
4779 if (mi != null)
4780 args = TypeManager.GetArgumentTypes (mi);
4781 else
4782 args = TypeManager.GetArgumentTypes (pi);
4784 Type [] sigp = sig.Parameters;
4786 if (args.Length != sigp.Length)
4787 return false;
4789 for (int i = args.Length; i > 0; ){
4790 i--;
4791 if (args [i] != sigp [i])
4792 return false;
4794 return true;
4798 // This filter should be used when we are requesting methods that
4799 // we want to override.
4801 // This makes a number of assumptions, for example
4802 // that the methods being extracted are of a parent
4803 // class (this means we know implicitly that we are
4804 // being called to find out about members by a derived
4805 // class).
4807 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4809 if (MemberSignatureCompare (m, filter_criteria)){
4810 MethodInfo mi = (MethodInfo) m;
4811 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4813 // If only accessible to the current class.
4814 if (prot == MethodAttributes.Private)
4815 return false;
4817 // If only accessible to the defining assembly or
4818 if (prot == MethodAttributes.FamANDAssem ||
4819 prot == MethodAttributes.Assembly){
4820 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4821 return true;
4822 else
4823 return false;
4826 // Anything else (FamOrAssembly and Public) is fine
4827 return true;
4829 return false;
4833 // This filter should be used when we are requesting properties that
4834 // we want to override.
4836 // This makes a number of assumptions, for example
4837 // that the methods being extracted are of a parent
4838 // class (this means we know implicitly that we are
4839 // being called to find out about members by a derived
4840 // class).
4842 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
4844 if (MemberSignatureCompare (m, filter_criteria)){
4845 PropertyInfo pi = (PropertyInfo) m;
4847 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
4848 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
4850 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
4852 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4854 // If only accessible to the current class.
4855 if (prot == MethodAttributes.Private)
4856 return false;
4858 // If only accessible to the defining assembly or
4859 if (prot == MethodAttributes.FamANDAssem ||
4860 prot == MethodAttributes.Assembly){
4861 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4862 return true;
4863 else
4864 return false;
4867 // Anything else (FamOrAssembly and Public) is fine
4868 return true;
4870 return false;