3 // class.cs: Class and Struct handlers
5 // Authors: Miguel de Icaza (miguel@gnu.org)
6 // Martin Baulig (martin@gnome.org)
8 // Licensed under the terms of the GNU GPL
10 // (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
13 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
15 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
16 // have fixed a remaining problem: not every AddXXXX was adding a
17 // fully qualified name.
19 // Now everyone registers a fully qualified name in the DeclSpace as
20 // being defined instead of the partial name.
22 // Downsides: we are slower than we need to be due to the excess
23 // copies and the names being registered this way.
25 // The reason for this is that we currently depend (on the corlib
26 // bootstrap for instance) that types are fully qualified, because
27 // we dump all the types in the namespace, and we should really have
28 // types inserted into the proper namespace, so we can only store the
29 // basenames in the defined_names array.
34 using System.Collections;
35 using System.Reflection;
36 using System.Reflection.Emit;
37 using System.Runtime.CompilerServices;
38 using System.Diagnostics.SymbolStore;
40 namespace Mono.MonoBASIC {
43 /// This is the base class for structs and classes.
45 public class TypeContainer : DeclSpace, IMemberContainer {
46 // Holds a list of classes and structures
49 // Holds the list of properties
52 // Holds the list of enumerations
55 // Holds the list of delegates
58 // Holds the list of constructors
59 ArrayList instance_constructors;
61 // Holds the list of fields
64 // Holds a list of fields that have initializers
65 ArrayList initialized_fields;
67 // Holds a list of static fields that have initializers
68 ArrayList initialized_static_fields;
70 // Holds the list of constants
76 // Holds order in which interfaces must be closed
77 ArrayList interface_order;
88 // Holds the operators
91 // The emit context for toplevel objects.
95 // Pointers to the default constructor and the default static constructor
97 Constructor default_constructor;
98 Constructor default_static_constructor;
101 // Whether we have seen a static constructor for this class or not
103 bool have_static_constructor = false;
106 // Whether we have at least one non-static field
108 bool have_nonstatic_fields = false;
111 // This one is computed after we can distinguish interfaces
112 // from classes from the arraylist `type_bases'
114 string base_class_name;
116 ArrayList type_bases;
118 // Attributes for this type
119 protected Attributes attributes;
121 // Information in the case we are an attribute type
123 public AttributeTargets Targets = AttributeTargets.All;
124 public bool AllowMultiple = false;
125 public bool Inherited;
127 // The interfaces we implement.
130 // The parent member container and our member cache
131 IMemberContainer parent_container;
132 MemberCache member_cache;
135 // The indexer name for this class
137 public string IndexerName;
139 public TypeContainer (TypeContainer parent, string name, Location l)
140 : base (parent, name, l)
143 types = new ArrayList ();
150 base_class_name = null;
152 //Console.WriteLine ("New class " + name + " inside " + n);
155 public AdditionResult AddConstant (Const constant)
158 string basename = constant.Name;
160 if ((res = IsValid (basename)) != AdditionResult.Success)
163 if (constants == null)
164 constants = new ArrayList ();
166 constants.Add (constant);
167 DefineName (Name + "." + basename, constant);
169 return AdditionResult.Success;
172 public AdditionResult AddEnum (Mono.MonoBASIC.Enum e)
176 if ((res = IsValid (e.Basename)) != AdditionResult.Success)
180 enums = new ArrayList ();
183 DefineName (e.Name, e);
185 return AdditionResult.Success;
188 public AdditionResult AddClass (Class c)
192 if ((res = IsValid (c.Basename)) != AdditionResult.Success)
197 DefineName (c.Name, c);
200 // FIXME: Do we really need to explicitly add an empty default static constructor?
201 // Apparently we don't
202 /* if (c.default_static_constructor == null)
204 bool isModule = c is Mono.MonoBASIC.Module;
205 Constructor dc = new Constructor ("New", Parameters.EmptyReadOnlyParameters, null, c.Location);
206 dc.ModFlags = isModule ? Modifiers.PUBLIC | Modifiers.STATIC : Modifiers.PUBLIC;
207 c.AddConstructor (dc);
210 //--------------------------------------------------------------
212 return AdditionResult.Success;
215 public AdditionResult AddStruct (Struct s)
219 if ((res = IsValid (s.Basename)) != AdditionResult.Success)
222 DefineName (s.Name, s);
225 return AdditionResult.Success;
228 public AdditionResult AddDelegate (Delegate d)
232 if ((res = IsValid (d.Basename)) != AdditionResult.Success)
235 if (delegates == null)
236 delegates = new ArrayList ();
238 DefineName (d.Name, d);
241 return AdditionResult.Success;
244 public AdditionResult AddMethod (Method method)
246 string basename = method.Name;
247 string fullname = Name + "." + basename;
249 Object value = defined_names [fullname];
251 if (value != null && (!(value is Method)))
252 return AdditionResult.NameExists;
254 if (basename == Basename)
255 return AdditionResult.EnclosingClash;
258 methods = new ArrayList ();
260 if (method.Name.IndexOf (".") != -1)
261 methods.Insert (0, method);
263 methods.Add (method);
266 DefineName (fullname, method);
268 return AdditionResult.Success;
271 public AdditionResult AddConstructor (Constructor c)
274 return AdditionResult.NotAConstructor;
276 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
279 have_static_constructor = true;
280 if (default_static_constructor != null){
281 Console.WriteLine ("I have a static constructor already");
282 Console.WriteLine (" " + default_static_constructor);
283 return AdditionResult.MethodExists;
286 default_static_constructor = c;
289 if (default_constructor != null)
290 return AdditionResult.MethodExists;
291 default_constructor = c;
294 if (instance_constructors == null)
295 instance_constructors = new ArrayList ();
297 instance_constructors.Add (c);
300 return AdditionResult.Success;
303 public AdditionResult AddInterface (Interface iface)
307 if ((res = IsValid (iface.Basename)) != AdditionResult.Success)
310 if (interfaces == null)
311 interfaces = new ArrayList ();
312 interfaces.Add (iface);
313 DefineName (iface.Name, iface);
315 return AdditionResult.Success;
318 public AdditionResult AddField (Field field)
321 string basename = field.Name;
323 if ((res = IsValid (basename)) != AdditionResult.Success)
327 fields = new ArrayList ();
331 if (field.HasInitializer){
332 if ((field.ModFlags & Modifiers.STATIC) != 0) {
333 if (initialized_static_fields == null)
334 initialized_static_fields = new ArrayList ();
336 initialized_static_fields.Add (field);
339 // We have not seen a static constructor,
340 // but we will provide static initialization of fields
342 have_static_constructor = true;
344 if (initialized_fields == null)
345 initialized_fields = new ArrayList ();
347 initialized_fields.Add (field);
351 if ((field.ModFlags & Modifiers.STATIC) == 0)
352 have_nonstatic_fields = true;
354 DefineName (Name + "." + basename, field);
355 return AdditionResult.Success;
358 public AdditionResult AddProperty (Property prop)
361 string basename = prop.Name;
363 if ((res = IsValid (basename)) != AdditionResult.Success)
366 if (properties == null)
367 properties = new ArrayList ();
369 if (prop.Name.IndexOf (".") != -1)
370 properties.Insert (0, prop);
372 properties.Add (prop);
373 DefineName (Name + "." + basename, prop);
375 return AdditionResult.Success;
378 public AdditionResult AddEvent (Event e)
381 string basename = e.Name;
383 if ((res = IsValid (basename)) != AdditionResult.Success)
387 events = new ArrayList ();
390 DefineName (Name + "." + basename, e);
392 return AdditionResult.Success;
395 public AdditionResult AddIndexer (Indexer i)
397 if (indexers == null)
398 indexers = new ArrayList ();
400 if (i.InterfaceType != null)
401 indexers.Insert (0, i);
405 return AdditionResult.Success;
408 public AdditionResult AddOperator (Operator op)
410 if (operators == null)
411 operators = new ArrayList ();
415 return AdditionResult.Success;
418 public void RegisterOrder (Interface iface)
420 if (interface_order == null)
421 interface_order = new ArrayList ();
423 interface_order.Add (iface);
426 public ArrayList Types {
432 public ArrayList Methods {
438 public ArrayList Constants {
444 public ArrayList Interfaces {
452 return base_class_name;
456 public ArrayList Bases {
466 public ArrayList Fields {
476 public ArrayList InstanceConstructors {
478 return instance_constructors;
482 public ArrayList Properties {
488 public ArrayList Events {
494 public ArrayList Enums {
500 public ArrayList Indexers {
506 public ArrayList Operators {
512 public ArrayList Delegates {
518 public Attributes OptAttributes {
524 public bool HaveStaticConstructor {
526 return have_static_constructor;
530 public virtual TypeAttributes TypeAttr {
532 return Modifiers.TypeAttr (ModFlags, this);
537 // Emits the instance field initializers
539 public bool EmitFieldInitializers (EmitContext ec)
542 ILGenerator ig = ec.ig;
543 Expression instance_expr;
546 fields = initialized_static_fields;
547 instance_expr = null;
549 fields = initialized_fields;
550 instance_expr = new This (Location.Null).Resolve (ec);
556 foreach (Field f in fields){
557 Expression e = f.GetInitializerExpression (ec);
561 Location l = f.Location;
562 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
563 fe.InstanceExpression = instance_expr;
564 Expression a = new Assign (fe, e, l);
570 if (a is ExpressionStatement)
571 ((ExpressionStatement) a).EmitStatement (ec);
573 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
581 // Defines the default constructors
583 void DefineDefaultConstructor (bool is_static)
588 c = new Constructor ("New", Parameters.EmptyReadOnlyParameters,
589 new ConstructorBaseInitializer (
590 null, Parameters.EmptyReadOnlyParameters,
595 mods = Modifiers.STATIC;
601 c.Block = new Block (null);
605 public void ReportStructInitializedInstanceError ()
607 string n = TypeBuilder.FullName;
609 foreach (Field f in initialized_fields){
612 "`" + n + "." + f.Name + "': can not have " +
613 "instance field initializers in structs");
618 /// The pending methods that need to be implemented (interfaces or abstract methods)
620 public PendingImplementation Pending;
623 /// This function computes the Base class and also the
624 /// list of interfaces that the class or struct @c implements.
626 /// The return value is an array (might be null) of
627 /// interfaces implemented (as Types).
629 /// The @parent argument is set to the parent object or null
630 /// if this is `System.Object'.
632 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
634 ArrayList bases = Bases;
643 parent = TypeManager.value_type;
647 if (RootContext.StdLib)
648 parent = TypeManager.object_type;
649 else if (Name != "System.Object")
650 parent = TypeManager.object_type;
653 // If we are compiling our runtime,
654 // and we are defining ValueType, then our
655 // parent is `System.Object'.
657 if (!RootContext.StdLib && Name == "System.ValueType")
658 parent = TypeManager.object_type;
665 // Bases should be null if there are no bases at all
670 Expression name = (Expression) bases [0];
671 name = ResolveTypeExpr (name, false, Location);
678 Type first = name.Type;
684 parent = TypeManager.object_type;
688 if (parent.IsSealed )
689 Report.Error (30299, Location,
690 "Class " + Name + " cannot inherit " +
691 "'NotInheritable' class " + TypeManager.MonoBASIC_Name (parent));
693 if (!AsAccessible (parent, ModFlags))
694 Report.Error (30389, Location,
695 "Inconsistent accessibility: base class `" +
696 TypeManager.MonoBASIC_Name (parent) + "' is less " +
697 "accessible than class `" +
704 Type [] ifaces = new Type [count-start];
706 for (i = start, j = 0; i < count; i++, j++){
707 Expression name = (Expression) bases [i];
708 Expression resolved = ResolveTypeExpr (name, false, Location);
709 bases [i] = resolved;
710 Type t = resolved.Type;
717 if (is_class == false && !t.IsInterface){
718 Report.Error (527, "In Struct `" + Name + "', type `"+
719 name +"' is not an interface");
726 Report.Error (30258, "class `"+ Name +
727 "': a class can not inherit from a struct/enum");
729 /*Report.Error (509, "class `"+ Name +
730 "': Cannot inherit from sealed class `"+
738 Report.Error (527, "In Class `" + Name + "', type `"+
739 name+"' is not an interface");
745 for (int x = 0; x < j; x++) {
746 if (t == ifaces [x]) {
747 Report.Error (528, "`" + name + "' is already listed in interface list");
756 return TypeManager.ExpandInterfaces (ifaces);
760 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
762 public override TypeBuilder DefineType ()
768 if (TypeBuilder != null)
781 ec = new EmitContext (this, Mono.MonoBASIC.Location.Null, null, null, ModFlags);
783 if (((ModFlags & Modifiers.ABSTRACT ) != 0) &&
784 ((ModFlags & Modifiers.SEALED) != 0)){
785 Report.Error (31408, Location,
786 "Class declared as 'MustInherit' cannot be declared as 'NotInheritable'");
789 ifaces = GetClassBases (is_class, out parent, out error);
794 if (is_class && parent != null){
795 if (parent == TypeManager.enum_type ||
796 (parent == TypeManager.value_type && RootContext.StdLib) ||
797 parent == TypeManager.delegate_type ||
798 parent == TypeManager.array_type){
800 644, Location, "`" + Name + "' cannot inherit from " +
801 "special class `" + TypeManager.MonoBASIC_Name (parent) + "'");
806 if (!is_class && TypeManager.value_type == null)
807 throw new Exception ();
809 if (is_class && Parent.Parent == null)
\r
811 if ((ModFlags & Modifiers.PRIVATE) != 0)
812 Report.Error (31089, Location,
813 "Only internal classes can be declared as 'Private'");
815 if ((ModFlags & Modifiers.PROTECTED) != 0)
816 Report.Error (31047, Location,
817 "Only internal classes can be declared as 'Protected'");
821 TypeAttributes type_attributes = TypeAttr;
823 // if (parent_builder is ModuleBuilder) {
825 ModuleBuilder builder = CodeGen.ModuleBuilder;
826 TypeBuilder = builder.DefineType (
827 Name, type_attributes, parent, ifaces);
830 TypeBuilder builder = Parent.TypeBuilder;
831 TypeBuilder = builder.DefineNestedType (
832 Basename, type_attributes, parent, ifaces);
836 // Structs with no fields need to have at least one byte.
837 // The right thing would be to set the PackingSize in a DefineType
838 // but there are no functions that allow interfaces *and* the size to
842 if (!is_class && !have_nonstatic_fields){
843 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
844 FieldAttributes.Private);
847 // add interfaces that were not added at type creation (weird API issue)
848 if (!is_class && !have_nonstatic_fields && (ifaces != null)) {
849 foreach (Type i in ifaces)
850 TypeBuilder.AddInterfaceImplementation (i);
854 // Finish the setup for the EmitContext
856 ec.ContainerType = TypeBuilder;
858 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
860 if ((parent != null) &&
861 (parent == TypeManager.attribute_type ||
862 parent.IsSubclassOf (TypeManager.attribute_type))) {
863 RootContext.RegisterAttribute (this);
864 TypeManager.RegisterAttrType (TypeBuilder, this);
866 RootContext.RegisterOrder (this);
868 if (Interfaces != null) {
869 foreach (Interface iface in Interfaces)
874 foreach (TypeContainer tc in Types)
878 if (Delegates != null) {
879 foreach (Delegate d in Delegates)
884 foreach (Enum en in Enums)
894 /// Defines the MemberCore objects that are in the `list' Arraylist
896 /// The `defined_names' array contains a list of members defined in
899 static ArrayList remove_list = new ArrayList ();
900 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
904 // if one of the overloaded method is having
905 // Shadows or Overloads modifier all other should
906 // have the same modifier
907 Hashtable members = new Hashtable();
909 foreach (MemberCore mc in list)
\r
912 if(members[mc.Name] == null)
914 foreach (MemberCore m in list)
916 if(m.Name == mc.Name)
918 if ((m.ModFlags & Modifiers.SHADOWS) != 0)
920 modval = Modifiers.SHADOWS;
923 else if((m.ModFlags & Modifiers.NEW) != 0)
925 modval = Modifiers.NEW;
929 members.Add(mc.Name, modval);
932 modval = (int)members[mc.Name];
935 if(((modval & Modifiers.SHADOWS) != 0) && ((mc.ModFlags & Modifiers.SHADOWS) == 0))
938 "Function '" + mc.Name + "': must be declared 'Shadows' " +
939 "because another '" + mc.Name + "' declared 'Shadows'");
940 else if(((modval & Modifiers.NEW) != 0) && ((mc.ModFlags & Modifiers.NEW) == 0))
943 "Function '" + mc.Name + "': must be declared 'Overloads' " +
944 "because another '" + mc.Name + "' declared 'Overloads'");
948 remove_list.Clear ();
950 foreach (MemberCore mc in list){
951 if (!mc.Define (this)){
952 remove_list.Add (mc);
956 if (defined_names == null)
959 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
961 if (RootContext.WarningLevel >= 4){
962 if ((mc.ModFlags & Modifiers.NEW) != 0)
963 Warning_KewywordNewNotRequired (mc.Location, mc);
964 if ((mc.ModFlags & Modifiers.SHADOWS) != 0)
965 Warning_KewywordShadowsNotRequired (mc.Location, mc);
970 MemberInfo match = defined_names [idx];
972 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
976 // If we are both methods, let the method resolution emit warnings
978 if (match is MethodBase && mc is MethodCore)
981 if (((mc.ModFlags & Modifiers.SHADOWS) == 0) && idx > 0)
982 Warning_KeywordShadowsRequired (mc.Location, defined_names [idx]);
986 foreach (object o in remove_list)
989 remove_list.Clear ();
993 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
994 // class is consisten. Either it is `Item' or it is the name defined by all the
995 // indexers with the `IndexerName' attribute.
997 // Turns out that the IndexerNameAttribute is applied to each indexer,
998 // but it is never emitted, instead a DefaultName attribute is attached
1001 void DefineIndexers ()
1003 string class_indexer_name = null;
1005 foreach (Indexer i in Indexers){
1010 name = i.IndexerName;
1012 if (i.InterfaceType != null)
1015 if (class_indexer_name == null){
1016 class_indexer_name = name;
1020 if (name == class_indexer_name)
1024 668, "Two indexers have different names, " +
1025 " you should use the same name for all your indexers");
1027 if (class_indexer_name == null)
1028 class_indexer_name = "Item";
1029 IndexerName = class_indexer_name;
1032 static void Error_KeywordNotAllowed (Location loc)
1034 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1038 /// Populates our TypeBuilder with fields and methods
1040 public override bool DefineMembers (TypeContainer parent)
1042 MemberInfo [] defined_names = null;
1044 if (interface_order != null){
1045 foreach (Interface iface in interface_order)
1046 if ((iface.ModFlags & Modifiers.NEW) == 0)
1047 iface.DefineMembers (this);
1049 Error_KeywordNotAllowed (iface.Location);
1052 if (RootContext.WarningLevel > 1){
1056 // This code throws an exception in the comparer
1057 // I guess the string is not an object?
1059 ptype = TypeBuilder.BaseType;
1061 defined_names = (MemberInfo []) FindMembers (
1062 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1063 BindingFlags.Public | BindingFlags.Instance |
1064 BindingFlags.Static, null, null);
1066 Array.Sort (defined_names, mif_compare);
1070 if (constants != null)
1071 DefineMembers (constants, defined_names);
1074 DefineMembers (fields, defined_names);
1077 if (instance_constructors == null){
1078 if (default_constructor == null)
\r
1079 DefineDefaultConstructor (false);
1082 if (initialized_static_fields != null &&
1083 default_static_constructor == null)
1084 DefineDefaultConstructor (true);
1087 if (this is Struct){
1089 // Structs can not have initialized instance
1092 if (initialized_static_fields != null &&
1093 default_static_constructor == null)
1094 DefineDefaultConstructor (true);
1096 if (initialized_fields != null)
1097 ReportStructInitializedInstanceError ();
1100 Pending = PendingImplementation.GetPendingImplementations (this);
1103 // Constructors are not in the defined_names array
1105 if (instance_constructors != null)
\r
1106 DefineMembers (instance_constructors, null);
1108 if (default_static_constructor != null)
1109 default_static_constructor.Define (this);
1111 if (methods != null)
1112 DefineMembers (methods, defined_names);
1114 if (properties != null)
1115 DefineMembers (properties, defined_names);
1118 DefineMembers (events, defined_names);
1120 if (indexers != null) {
1123 IndexerName = "Item";
1125 if (operators != null){
1126 DefineMembers (operators, null);
1128 CheckPairedOperators ();
1132 DefineMembers (enums, defined_names);
1134 if (delegates != null)
1135 DefineMembers (delegates, defined_names);
1138 if (TypeBuilder.BaseType != null)
1139 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1141 member_cache = new MemberCache (this);
1147 public override bool Define (TypeContainer parent)
1149 if (interface_order != null){
1150 foreach (Interface iface in interface_order)
1151 if ((iface.ModFlags & Modifiers.NEW) == 0)
1152 iface.Define (this);
1159 /// This function is based by a delegate to the FindMembers routine
1161 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1167 /// This filter is used by FindMembers, and we just keep
1168 /// a global for the filter to `AlwaysAccept'
1170 static MemberFilter accepting_filter;
1174 /// A member comparission method based on name only
1176 static IComparer mif_compare;
1178 static TypeContainer ()
1180 accepting_filter = new MemberFilter (AlwaysAccept);
1181 mif_compare = new MemberInfoCompare ();
1185 /// This method returns the members of this type just like Type.FindMembers would
1186 /// Only, we need to use this for types which are _being_ defined because MS'
1187 /// implementation can't take care of that.
1190 // FIXME: return an empty static array instead of null, that cleans up
1191 // some code and is consistent with some coding conventions I just found
1195 // Notice that in various cases we check if our field is non-null,
1196 // something that would normally mean that there was a bug elsewhere.
1198 // The problem happens while we are defining p-invoke methods, as those
1199 // will trigger a FindMembers, but this happens before things are defined
1201 // Since the whole process is a no-op, it is fine to check for null here.
1203 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1204 MemberFilter filter, object criteria)
1206 ArrayList members = new ArrayList ();
1209 if ((bf & BindingFlags.Public) != 0)
1210 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1212 if ((bf & BindingFlags.NonPublic) != 0)
1213 modflags |= Modifiers.PRIVATE;
1215 int static_mask = 0, static_flags = 0;
1216 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1217 case BindingFlags.Static:
1218 static_mask = static_flags = Modifiers.STATIC;
1221 case BindingFlags.Instance:
1222 static_mask = Modifiers.STATIC;
1227 static_mask = static_flags = 0;
1231 Timer.StartTimer (TimerType.TcFindMembers);
1234 filter = accepting_filter;
1236 if ((mt & MemberTypes.Field) != 0) {
1237 if (fields != null) {
1238 foreach (Field f in fields) {
1239 if ((f.ModFlags & modflags) == 0)
1241 if ((f.ModFlags & static_mask) != static_flags)
1244 FieldBuilder fb = f.FieldBuilder;
1245 if (fb != null && filter (fb, criteria) == true)
1250 if (constants != null) {
1251 foreach (Const con in constants) {
1252 if ((con.ModFlags & modflags) == 0)
1254 if ((con.ModFlags & static_mask) != static_flags)
1257 FieldBuilder fb = con.FieldBuilder;
1258 if (fb != null && filter (fb, criteria) == true)
1264 if ((mt & MemberTypes.Method) != 0) {
1265 if (methods != null) {
1266 foreach (Method m in methods) {
1267 if ((m.ModFlags & modflags) == 0)
1269 if ((m.ModFlags & static_mask) != static_flags)
1272 MethodBuilder mb = m.MethodBuilder;
1274 if (mb != null && filter (mb, criteria) == true)
1279 if (operators != null){
1280 foreach (Operator o in operators) {
1281 if ((o.ModFlags & modflags) == 0)
1283 if ((o.ModFlags & static_mask) != static_flags)
1286 MethodBuilder ob = o.OperatorMethodBuilder;
1287 if (ob != null && filter (ob, criteria) == true)
1292 if (properties != null){
1293 foreach (Property p in properties){
1294 if ((p.ModFlags & modflags) == 0)
1296 if ((p.ModFlags & static_mask) != static_flags)
1302 if (b != null && filter (b, criteria) == true)
1306 if (b != null && filter (b, criteria) == true)
1311 if (indexers != null){
1312 foreach (Indexer ix in indexers){
1313 if ((ix.ModFlags & modflags) == 0)
1315 if ((ix.ModFlags & static_mask) != static_flags)
1321 if (b != null && filter (b, criteria) == true)
1325 if (b != null && filter (b, criteria) == true)
1331 if ((mt & MemberTypes.Event) != 0) {
1333 foreach (Event e in events) {
1334 if ((e.ModFlags & modflags) == 0)
1336 if ((e.ModFlags & static_mask) != static_flags)
1339 MemberInfo eb = e.EventBuilder;
1340 if (eb != null && filter (eb, criteria) == true)
1341 members.Add (e.EventBuilder);
1345 if ((mt & MemberTypes.Property) != 0){
1346 if (properties != null)
1347 foreach (Property p in properties) {
1348 if ((p.ModFlags & modflags) == 0)
1350 if ((p.ModFlags & static_mask) != static_flags)
1353 MemberInfo pb = p.PropertyBuilder;
1354 if (pb != null && filter (pb, criteria) == true) {
1355 members.Add (p.PropertyBuilder);
1359 if (indexers != null)
1360 foreach (Indexer ix in indexers) {
1361 if ((ix.ModFlags & modflags) == 0)
1363 if ((ix.ModFlags & static_mask) != static_flags)
1366 MemberInfo ib = ix.PropertyBuilder;
1367 if (ib != null && filter (ib, criteria) == true) {
1368 members.Add (ix.PropertyBuilder);
1373 if ((mt & MemberTypes.NestedType) != 0) {
1375 foreach (TypeContainer t in types) {
1376 if ((t.ModFlags & modflags) == 0)
1379 TypeBuilder tb = t.TypeBuilder;
1380 if (tb != null && (filter (tb, criteria) == true))
1386 foreach (Enum en in enums){
1387 if ((en.ModFlags & modflags) == 0)
1390 TypeBuilder tb = en.TypeBuilder;
1391 if (tb != null && (filter (tb, criteria) == true))
1396 if (delegates != null){
1397 foreach (Delegate d in delegates){
1398 if ((d.ModFlags & modflags) == 0)
1401 TypeBuilder tb = d.TypeBuilder;
1402 if (tb != null && (filter (tb, criteria) == true))
1407 if (interfaces != null){
1408 foreach (Interface iface in interfaces){
1409 if ((iface.ModFlags & modflags) == 0)
1412 TypeBuilder tb = iface.TypeBuilder;
1413 if (tb != null && (filter (tb, criteria) == true))
1419 if ((mt & MemberTypes.Constructor) != 0){
1420 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1421 foreach (Constructor c in instance_constructors){
1422 ConstructorBuilder cb = c.ConstructorBuilder;
1424 if (filter (cb, criteria) == true)
1429 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1430 ConstructorBuilder cb =
1431 default_static_constructor.ConstructorBuilder;
1434 if (filter (cb, criteria) == true)
1440 // Lookup members in parent if requested.
1442 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1443 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1444 members.AddRange (list);
1447 Timer.StopTimer (TimerType.TcFindMembers);
1449 return new MemberList (members);
1452 public override MemberCache MemberCache {
1454 return member_cache;
1458 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1459 MemberFilter filter, object criteria)
1461 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1464 return tc.FindMembers (mt, bf, filter, criteria);
1466 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1470 // FindMethods will look for methods not only in the type `t', but in
1471 // any interfaces implemented by the type.
1473 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1474 MemberFilter filter, object criteria)
1480 /// Emits the values for the constants
1482 public void EmitConstants ()
1484 if (constants != null)
1485 foreach (Const con in constants)
1486 con.EmitConstant (this);
1491 /// Emits the code, this step is performed after all
1492 /// the types, enumerations, constructors
1496 if (instance_constructors != null)
1497 foreach (Constructor c in instance_constructors)
1500 if (default_static_constructor != null)
1501 default_static_constructor.Emit (this);
1503 if (methods != null)
1504 foreach (Method m in methods)
1507 if (operators != null)
1508 foreach (Operator o in operators)
1511 if (properties != null)
1512 foreach (Property p in properties)
1515 if (indexers != null){
1516 foreach (Indexer ix in indexers)
1519 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1520 this, IndexerName, ModFlags, Location);
1521 TypeBuilder.SetCustomAttribute (cb);
1525 foreach (Field f in fields)
1528 if (events != null){
1529 foreach (Event e in Events)
1533 if (Pending != null)
1534 if (Pending.VerifyPendingMethods ())
1537 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1540 // Check for internal or private fields that were never assigned
1542 if (fields != null && RootContext.WarningLevel >= 3) {
1543 foreach (Field f in fields) {
1544 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1549 169, f.Location, "Private field " +
1550 MakeName (f.Name) + " is never used");
1555 // Only report 649 on level 4
1557 if (RootContext.WarningLevel < 4)
1560 if ((f.status & Field.Status.ASSIGNED) != 0)
1565 "Field " + MakeName (f.Name) + " is never assigned " +
1566 " to and will always have its default value");
1570 // if (types != null)
1571 // foreach (TypeContainer tc in types)
1575 public override void CloseType ()
1580 TypeBuilder.CreateType ();
1582 } catch (TypeLoadException){
1584 // This is fine, the code still created the type
1586 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1587 // Console.WriteLine (e.Message);
1589 Console.WriteLine ("In type: " + Name);
1594 foreach (Enum en in Enums)
1597 if (interface_order != null){
1598 foreach (Interface iface in interface_order)
1603 foreach (TypeContainer tc in Types)
1607 foreach (TypeContainer tc in Types)
1608 if (!(tc is Struct))
1612 if (Delegates != null)
1613 foreach (Delegate d in Delegates)
1617 public string MakeName (string n)
1619 return "`" + Name + "." + n + "'";
1622 public void Warning_KeywordShadowsRequired (Location l, MemberInfo mi)
1625 108, l, "The keyword 'Shadows' is required on " +
1626 MakeName (mi.Name) + " because it shadows `" +
1627 mi.ReflectedType.Name + "." + mi.Name + "'");
1630 public void Warning_KewywordShadowsNotRequired (Location l, MemberCore mc)
1633 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1634 "inherited member, the keyword shadows is not required");
1637 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1640 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1641 "inherited member, the keyword new is not required");
1644 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1650 // Performs the validation on a Method's modifiers (properties have
1651 // the same properties).
1653 public bool MethodModifiersValid (int flags, string n, Location loc)
1655 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1656 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1657 const int nv = (Modifiers.SHADOWS | Modifiers.VIRTUAL);
1659 string name = MakeName (n);
1662 // At most one of static, virtual or override
1664 if ((flags & Modifiers.STATIC) != 0){
1665 if ((flags & vao) != 0){
1667 30501, loc, "Shared method " + name + " can not be " +
1668 "declared as Overridable");
1673 if (this is Struct){
1674 if ((flags & va) != 0){
1675 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1680 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.VIRTUAL) != 0)
\r
1684 ": Methods marked as Overrides cannot be made Overridable");
1688 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.SHADOWS) != 0){
1691 ": Methods marked as Overrides cannot be marked as Shadows");
1696 // If the declaration includes the abstract modifier, then the
1697 // declaration does not include static, virtual or extern
1699 if ((flags & Modifiers.ABSTRACT) != 0){
1700 if ((flags & Modifiers.EXTERN) != 0){
1702 180, loc, name + " can not be both abstract and extern");
1706 if ((flags & Modifiers.VIRTUAL) != 0){
1708 503, loc, name + " can not be both abstract and virtual");
1712 if((ModFlags & Modifiers.SEALED) != 0){
1715 "Class declared as 'NotInheritable' " +
1716 "cannot have a 'MustOverride' member");
1719 else if ((ModFlags & Modifiers.ABSTRACT) == 0){
1722 " is declared as 'MustOverride', hence its container " +
1723 "class should be declared as 'MustInherit'");
1729 if ((flags & Modifiers.PRIVATE) != 0){
1730 if ((flags & vao) != 0){
1733 ": Members marked as Overridable or Overrides can not be Private");
1738 if ((flags & Modifiers.SEALED) != 0){
1739 if ((flags & Modifiers.OVERRIDE) == 0){
1742 ": cannot be sealed because it is not an override");
1746 if ((flags & Modifiers.NEW) != 0){
1747 if ((flags & Modifiers.SHADOWS) != 0){
1750 " 'Overloads' and 'Shadows' cannot be combined ");
1758 // Access level of a type.
1761 ProtectedInternal = 1,
1767 // Check whether `flags' denotes a more restricted access than `level'
1768 // and return the new level.
1769 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1771 AccessLevel old_level = level;
1773 if ((flags & Modifiers.INTERNAL) != 0) {
1774 if ((flags & Modifiers.PROTECTED) != 0) {
1775 if ((int) level < (int) AccessLevel.ProtectedInternal)
1776 level = AccessLevel.ProtectedInternal;
1778 if ((int) level < (int) AccessLevel.Internal)
1779 level = AccessLevel.Internal;
1781 } else if ((flags & Modifiers.PROTECTED) != 0) {
1782 if ((int) level < (int) AccessLevel.Protected)
1783 level = AccessLevel.Protected;
1784 } else if ((flags & Modifiers.PRIVATE) != 0)
1785 level = AccessLevel.Private;
1790 // Return the access level for a new member which is defined in the current
1791 // TypeContainer with access modifiers `flags'.
1792 AccessLevel GetAccessLevel (int flags)
1794 if ((flags & Modifiers.PRIVATE) != 0)
1795 return AccessLevel.Private;
1798 if (!IsTopLevel && (Parent != null))
1799 level = Parent.GetAccessLevel (flags);
1801 level = AccessLevel.Public;
1803 return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1806 // Return the access level for type `t', but don't give more access than `flags'.
1807 static AccessLevel GetAccessLevel (Type t, int flags)
1809 if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1810 return AccessLevel.Private;
1813 if (TypeManager.IsBuiltinType (t))
1814 return AccessLevel.Public;
1815 else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1816 level = GetAccessLevel (t.DeclaringType, flags);
1818 level = CheckAccessLevel (AccessLevel.Public, flags);
1821 if (t.IsNestedPublic)
1824 if (t.IsNestedAssembly || t.IsNotPublic) {
1825 if ((int) level < (int) AccessLevel.Internal)
1826 level = AccessLevel.Internal;
1829 if (t.IsNestedFamily) {
1830 if ((int) level < (int) AccessLevel.Protected)
1831 level = AccessLevel.Protected;
1834 if (t.IsNestedFamORAssem) {
1835 if ((int) level < (int) AccessLevel.ProtectedInternal)
1836 level = AccessLevel.ProtectedInternal;
1843 // Returns true if `parent' is as accessible as the flags `flags'
1844 // given for this member.
1846 public bool AsAccessible (Type parent, int flags)
1848 while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1849 parent = parent.GetElementType ();
1851 AccessLevel level = GetAccessLevel (flags);
1852 AccessLevel level2 = GetAccessLevel (parent, flags);
1854 return (int) level >= (int) level2;
1857 Hashtable builder_and_args;
1859 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1861 if (builder_and_args == null)
1862 builder_and_args = new Hashtable ();
1867 /// Performs checks for an explicit interface implementation. First it
1868 /// checks whether the `interface_type' is a base inteface implementation.
1869 /// Then it checks whether `name' exists in the interface type.
1871 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1875 if (ifaces != null){
1876 foreach (Type t in ifaces){
1877 if (t == interface_type){
1885 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1892 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1894 Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1901 string IMemberContainer.Name {
1907 Type IMemberContainer.Type {
1913 IMemberContainer IMemberContainer.Parent {
1915 return parent_container;
1919 MemberCache IMemberContainer.MemberCache {
1921 return member_cache;
1925 bool IMemberContainer.IsInterface {
1931 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1933 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1937 // Operator pair checking
1940 class OperatorEntry {
1942 public Type ret_type;
1943 public Type type1, type2;
1945 public Operator.OpType ot;
1947 public OperatorEntry (int f, Operator o)
1951 ret_type = o.OperatorMethod.GetReturnType ();
1952 Type [] pt = o.OperatorMethod.ParameterTypes;
1956 ot = o.OperatorType;
1959 public override int GetHashCode ()
1961 return ret_type.GetHashCode ();
1964 public override bool Equals (object o)
1966 OperatorEntry other = (OperatorEntry) o;
1968 if (other.ret_type != ret_type)
1970 if (other.type1 != type1)
1972 if (other.type2 != type2)
1979 // Checks that some operators come in pairs:
1984 // They are matched based on the return type and the argument types
1986 void CheckPairedOperators ()
1988 Hashtable pairs = new Hashtable (null, null);
1990 // Register all the operators we care about.
1991 foreach (Operator op in operators){
1994 switch (op.OperatorType){
1995 case Operator.OpType.Equality:
1997 case Operator.OpType.Inequality:
2000 case Operator.OpType.GreaterThan:
2002 case Operator.OpType.LessThan:
2005 case Operator.OpType.GreaterThanOrEqual:
2007 case Operator.OpType.LessThanOrEqual:
2013 OperatorEntry oe = new OperatorEntry (reg, op);
2015 object o = pairs [oe];
2019 oe = (OperatorEntry) o;
2025 // Look for the mistakes.
2027 foreach (DictionaryEntry de in pairs){
2028 OperatorEntry oe = (OperatorEntry) de.Key;
2035 case Operator.OpType.Equality:
2038 case Operator.OpType.Inequality:
2041 case Operator.OpType.GreaterThan:
2044 case Operator.OpType.LessThan:
2047 case Operator.OpType.GreaterThanOrEqual:
2050 case Operator.OpType.LessThanOrEqual:
2054 Report.Error (216, oe.op.Location,
2055 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2062 public class Class : TypeContainer {
2064 // Modifiers allowed in a class declaration
2066 public const int AllowedModifiers =
2069 Modifiers.PROTECTED |
2070 Modifiers.INTERNAL |
2072 Modifiers.ABSTRACT |
2075 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2076 : base (parent, name, l)
2080 if (parent.Parent == null)
2081 accmods = Modifiers.INTERNAL;
2083 accmods = Modifiers.PUBLIC;
2085 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2086 this.attributes = attrs;
2090 // FIXME: How do we deal with the user specifying a different
2093 public override TypeAttributes TypeAttr {
2095 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2100 public class Struct : TypeContainer {
2102 // Modifiers allowed in a struct declaration
2104 public const int AllowedModifiers =
2107 Modifiers.PROTECTED |
2108 Modifiers.INTERNAL |
2112 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2113 : base (parent, name, l)
2117 if (parent.Parent == null)
2118 accmods = Modifiers.INTERNAL;
2120 accmods = Modifiers.PUBLIC;
2122 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2124 this.ModFlags |= Modifiers.SEALED;
2125 this.attributes = attrs;
2130 // FIXME: Allow the user to specify a different set of attributes
2131 // in some cases (Sealed for example is mandatory for a class,
2132 // but what SequentialLayout can be changed
2134 public override TypeAttributes TypeAttr {
2136 return base.TypeAttr |
2137 TypeAttributes.SequentialLayout |
2138 TypeAttributes.Sealed |
2139 TypeAttributes.BeforeFieldInit;
2144 public abstract class MethodCore : MemberBase {
2145 public /* readonly */ Parameters Parameters;
2149 // Parameters, cached for semantic analysis.
2151 protected InternalParameters parameter_info;
2152 protected Type [] parameter_types;
2154 public MethodCore (Expression type, int mod, int allowed_mod, string name,
2155 Attributes attrs, Parameters parameters, Location loc)
2156 : base (type, mod, allowed_mod, name, attrs, loc)
2158 Parameters = parameters;
2162 // Returns the System.Type array for the parameters of this method
2164 public Type [] ParameterTypes {
2166 return parameter_types;
2170 public InternalParameters ParameterInfo
2173 return parameter_info;
2177 public Block Block {
2187 protected virtual bool DoDefineParameters (TypeContainer parent)
2189 // Check if arguments were correct
2190 parameter_types = Parameters.GetParameterInfo (parent);
2191 if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
2194 parameter_info = new InternalParameters (parent, Parameters);
2199 public CallingConventions GetCallingConvention (bool is_class)
2201 CallingConventions cc = 0;
2203 cc = Parameters.GetCallingConvention ();
2206 if ((ModFlags & Modifiers.STATIC) == 0)
2207 cc |= CallingConventions.HasThis;
2209 // FIXME: How is `ExplicitThis' used in C#?
2214 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
2216 LabelParameters (ec, parameters, builder, null);
2219 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder, Parameters p_params)
2222 // Define each type attribute (in/out/ref) and
2223 // the argument names.
2225 Parameter [] p = p_params == null ? Parameters.FixedParameters : p_params.FixedParameters;
2228 MethodBuilder mb = null;
2229 ConstructorBuilder cb = null;
2231 if (builder is MethodBuilder)
2232 mb = (MethodBuilder) builder;
2234 cb = (ConstructorBuilder) builder;
2237 for (i = 0; i < p.Length; i++) {
2238 ParameterBuilder pb;
2241 pb = cb.DefineParameter (
2242 i + 1, p [i].Attributes, p [i].Name);
2244 pb = mb.DefineParameter (
2245 i + 1, p [i].Attributes, p [i].Name);
2247 Attributes attr = p [i].OptAttributes;
2249 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
2253 if (Parameters.ArrayParameter != null){
2254 ParameterBuilder pb;
2255 Parameter array_param = Parameters.ArrayParameter;
2258 pb = cb.DefineParameter (
2259 i + 1, array_param.Attributes,
2262 pb = mb.DefineParameter (
2263 i + 1, array_param.Attributes,
2266 CustomAttributeBuilder a = new CustomAttributeBuilder (
2267 TypeManager.cons_param_array_attribute, new object [0]);
2269 pb.SetCustomAttribute (a);
2274 public class Method : MethodCore {
2275 public MethodBuilder MethodBuilder;
2276 public MethodData MethodData;
2279 /// Modifiers allowed in a class declaration
2281 const int AllowedModifiers =
2284 Modifiers.PROTECTED |
2285 Modifiers.INTERNAL |
2289 Modifiers.NONVIRTUAL |
2290 Modifiers.OVERRIDE |
2291 Modifiers.ABSTRACT |
2297 // return_type can be "null" for VOID values.
2299 public Method (Expression return_type, int mod, string name, Parameters parameters,
2300 Attributes attrs, Location l)
2301 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2306 public Method (Expression return_type, int mod, string name, Parameters parameters,
2307 Attributes attrs, Expression impl_what, Location l)
2308 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2310 Implements = impl_what;
2314 // Returns the `System.Type' for the ReturnType of this
2315 // function. Provides a nice cache. (used between semantic analysis
2316 // and actual code generation
2318 public Type GetReturnType ()
2323 // Whether this is an operator method.
2324 public bool IsOperator;
2326 void DuplicateEntryPoint (MethodInfo b, Location location)
2330 "Program `" + CodeGen.FileName +
2331 "' has more than one entry point defined: `" +
2332 TypeManager.MonoBASIC_Signature(b) + "'");
2335 void Report28 (MethodInfo b)
2337 if (RootContext.WarningLevel < 4)
2342 "`" + TypeManager.MonoBASIC_Signature(b) +
2343 "' has the wrong signature to be an entry point");
2346 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2348 if (b.ReturnType != TypeManager.void_type &&
2349 b.ReturnType != TypeManager.int32_type)
2352 if (pinfo.Count == 0)
2355 if (pinfo.Count > 1)
2358 Type t = pinfo.ParameterType(0);
2360 (t.GetArrayRank() == 1) &&
2361 (t.GetElementType() == TypeManager.string_type) &&
2362 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2369 // Checks our base implementation if any
2371 protected override bool CheckBase (TypeContainer parent)
2373 // Check whether arguments were correct.
2374 if (!DoDefineParameters (parent))
2377 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2381 mi_this = TypeContainer.FindMembers (
2382 parent.TypeBuilder, MemberTypes.Method,
2383 BindingFlags.NonPublic | BindingFlags.Public |
2384 BindingFlags.Static | BindingFlags.Instance |
2385 BindingFlags.DeclaredOnly,
2386 MethodSignature.method_signature_filter, ms);
2388 if (mi_this.Count > 0) {
2389 Report.Error (111, Location, "Class `" + parent.Name + "' " +
2390 "already defines a member called `" + Name + "' " +
2391 "with the same parameter types");
2397 // Verify if the parent has a type with the same name, and then
2398 // check whether we have to create a new slot for it or not.
2400 Type ptype = parent.TypeBuilder.BaseType;
2402 // ptype is only null for System.Object while compiling corlib.
2404 MemberList mi, mi_static, mi_instance;
2406 mi_static = TypeContainer.FindMembers (
2407 ptype, MemberTypes.Method,
2408 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2409 MethodSignature.inheritable_method_signature_filter, ms);
2411 mi_instance = TypeContainer.FindMembers (
2412 ptype, MemberTypes.Method,
2413 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2414 MethodSignature.inheritable_method_signature_filter,
2417 if (mi_instance.Count > 0){
2419 } else if (mi_static.Count > 0)
2424 if (mi != null && mi.Count > 0){
2425 parent_method = (MethodInfo) mi [0];
2426 string name = parent_method.DeclaringType.Name + "." +
2429 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2432 if ((ModFlags & Modifiers.NEW) == 0) {
2433 Type parent_ret = TypeManager.TypeToCoreType (
2434 parent_method.ReturnType);
2436 if (parent_ret != MemberType) {
2438 508, parent.MakeName (Name) + ": cannot " +
2439 "change return type when overriding " +
2440 "inherited member " + name);
2445 /*if ((ModFlags & Modifiers.NEW) != 0)
2446 WarningNotHiding (parent);*/
2448 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2449 Report.Error (30284, Location,
2450 parent.MakeName (Name) +
2451 " : No suitable methods found to override");
2453 if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0)
\r
2455 if ((ModFlags & Modifiers.NONVIRTUAL) != 0)
\r
2457 Report.Error (31088, Location,
2458 parent.MakeName (Name) + " : Cannot " +
2459 "be declared NotOverridable since this method is " +
2460 "not maked as Overrides");
2464 }/* else if ((ModFlags & Modifiers.NEW) != 0)
2465 WarningNotHiding (parent);
2473 public override bool Define (TypeContainer parent)
2475 if (!DoDefine (parent))
2478 if (!CheckBase (parent))
2481 CallingConventions cc = GetCallingConvention (parent is Class);
2483 MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2484 ParameterInfo, cc, OptAttributes,
2485 ModFlags, flags, true);
2487 if (!MethodData.Define (parent))
2490 MethodBuilder = MethodData.MethodBuilder;
2493 // This is used to track the Entry Point,
2495 if (Name.ToUpper() == "MAIN" &&
2496 ((ModFlags & Modifiers.STATIC) != 0) &&
2497 (RootContext.MainClass == null ||
2498 RootContext.MainClass == parent.TypeBuilder.FullName ||
2499 (RootContext.RootNamespace != null &&
2500 RootContext.RootNamespace.Length > 0 &&
2501 (RootContext.RootNamespace + "." + RootContext.MainClass) == parent.TypeBuilder.FullName))) {
2502 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2503 if (RootContext.EntryPoint == null) {
2504 RootContext.EntryPoint = MethodBuilder;
2505 RootContext.EntryPointLocation = Location;
2507 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2508 DuplicateEntryPoint (MethodBuilder, Location);
2511 Report28(MethodBuilder);
2520 public void Emit (TypeContainer parent)
2522 MethodData.Emit (parent, Block, this);
2526 public abstract class ConstructorInitializer {
2527 ArrayList argument_list;
2528 ConstructorInfo parent_constructor;
2529 Parameters parameters;
2532 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2535 this.argument_list = argument_list;
2536 this.parameters = parameters;
2540 public ArrayList Arguments {
2542 return argument_list;
2546 public bool Resolve (EmitContext ec)
2548 Expression parent_constructor_group;
2551 ec.CurrentBlock = new Block (null, true, parameters);
2553 if (argument_list != null){
2554 foreach (Argument a in argument_list){
2555 if (!a.Resolve (ec, loc))
2560 ec.CurrentBlock = null;
2562 if (this is ConstructorBaseInitializer) {
2563 if (ec.ContainerType.BaseType == null)
2566 t = ec.ContainerType.BaseType;
2567 if (ec.ContainerType.IsValueType) {
2568 Report.Error (522, loc,
2569 "structs cannot call base class constructors");
2573 t = ec.ContainerType;
2575 parent_constructor_group = Expression.MemberLookup (
2577 MemberTypes.Constructor,
2578 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2581 if (parent_constructor_group == null){
2582 string s = String.Format ("'{0}': Can not find a constructor for this argument list", t);
2583 Report.Error (1501, loc, s);
2587 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2588 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2590 if (parent_constructor == null){
2591 string s = String.Format ("'{0}': Can not find a constructor for this argument list", t);
2592 Report.Error (1501, loc, s);
2599 public void Emit (EmitContext ec)
2601 if (parent_constructor != null){
2603 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2605 Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2610 public class ConstructorBaseInitializer : ConstructorInitializer {
2611 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2612 base (argument_list, pars, l)
2617 public class ConstructorThisInitializer : ConstructorInitializer {
2618 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2619 base (argument_list, pars, l)
2624 public class Constructor : MethodCore {
2625 public ConstructorBuilder ConstructorBuilder;
2626 public ConstructorInitializer Initializer;
2627 new public Attributes OptAttributes;
2630 // Modifiers allowed for a constructor.
2632 public const int AllowedModifiers =
2634 Modifiers.PROTECTED |
2635 Modifiers.INTERNAL |
2642 // The spec claims that static is not permitted, but
2643 // my very own code has static constructors.
2645 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2646 : base (null, 0, AllowedModifiers, name, null, args, l)
2652 // Returns true if this is a default constructor
2654 public bool IsDefault ()
2656 if ((ModFlags & Modifiers.STATIC) != 0)
2657 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2658 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2661 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2662 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2663 (Initializer is ConstructorBaseInitializer) &&
2664 (Initializer.Arguments == null);
2668 // Creates the ConstructorBuilder
2670 public override bool Define (TypeContainer parent)
2672 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2673 MethodAttributes.SpecialName);
2675 // Check if arguments were correct.
2676 if (!DoDefineParameters (parent))
2679 if ((ModFlags & Modifiers.STATIC) != 0)
2680 ca |= MethodAttributes.Static;
2682 if (parent is Struct && ParameterTypes.Length == 0){
2685 "Structs can not contain explicit parameterless " +
2689 ca |= MethodAttributes.HideBySig;
2691 if ((ModFlags & Modifiers.PUBLIC) != 0)
2692 ca |= MethodAttributes.Public;
2693 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2694 if ((ModFlags & Modifiers.INTERNAL) != 0)
2695 ca |= MethodAttributes.FamORAssem;
2697 ca |= MethodAttributes.Family;
2698 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2699 ca |= MethodAttributes.Assembly;
2700 else if (IsDefault ())
2701 ca |= MethodAttributes.Public;
2703 ca |= MethodAttributes.Private;
2706 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2707 ca, GetCallingConvention (parent is Class), ParameterTypes);
2710 // HACK because System.Reflection.Emit is lame
2712 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2715 "Class `" +parent.Name+ "' already contains a definition with the " +
2716 "same return value and parameter types for constructor `" + Name
2727 public void Emit (TypeContainer parent)
2729 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2730 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2732 if ((ModFlags & Modifiers.STATIC) == 0){
2733 if (parent is Class && Initializer == null)
2734 Initializer = new ConstructorBaseInitializer (
2735 null, Parameters.EmptyReadOnlyParameters, parent.Location);
2739 // Spec mandates that Initializers will not have
2743 if (Initializer != null && !Initializer.Resolve (ec))
2745 ec.IsStatic = false;
2748 LabelParameters (ec, ParameterTypes, ConstructorBuilder);
2751 // Classes can have base initializers and instance field initializers.
2753 if (parent is Class){
2754 if ((ModFlags & Modifiers.STATIC) == 0)
2755 parent.EmitFieldInitializers (ec);
2757 if (Initializer != null)
2758 Initializer.Emit (ec);
2760 if ((ModFlags & Modifiers.STATIC) != 0)
2761 parent.EmitFieldInitializers (ec);
2763 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2765 // If this is a non-static `struct' constructor and doesn't have any
2766 // initializer, it must initialize all of the struct's fields.
2767 if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2768 (Initializer == null))
2769 Block.AddThisVariable (parent, Location);
2771 ec.EmitTopBlock (Block, ParameterInfo, Location);
2775 public class MethodData {
2777 // The return type of this method
2779 public readonly Type ReturnType;
2780 public readonly Type[] ParameterTypes;
2781 public readonly InternalParameters ParameterInfo;
2782 public readonly CallingConventions CallingConventions;
2783 public readonly Attributes OptAttributes;
2784 public readonly Location Location;
2787 // Are we implementing an interface ?
2789 public bool IsImplementing = false;
2794 protected MemberBase member;
2795 protected int modifiers;
2796 protected MethodAttributes flags;
2797 protected bool is_method;
2798 protected string accessor_name;
2799 ArrayList conditionals;
2801 MethodBuilder builder = null;
2802 public MethodBuilder MethodBuilder {
2808 public MethodData (MemberBase member, string name, Type return_type,
2809 Type [] parameter_types, InternalParameters parameters,
2810 CallingConventions cc, Attributes opt_attrs,
2811 int modifiers, MethodAttributes flags, bool is_method)
2813 this.member = member;
2814 this.accessor_name = name;
2815 this.ReturnType = return_type;
2816 this.ParameterTypes = parameter_types;
2817 this.ParameterInfo = parameters;
2818 this.CallingConventions = cc;
2819 this.OptAttributes = opt_attrs;
2820 this.modifiers = modifiers;
2822 this.is_method = is_method;
2823 this.Location = member.Location;
2824 this.conditionals = new ArrayList ();
2830 Attribute dllimport_attribute = null;
2831 string obsolete = null;
2832 bool obsolete_error = false;
2834 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2836 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2839 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2840 if (asec.Attributes == null)
2843 foreach (Attribute a in asec.Attributes) {
2844 if (a.Name == "Conditional") {
2845 if (!ApplyConditionalAttribute (a))
2847 } else if (a.Name == "Obsolete") {
2848 if (!ApplyObsoleteAttribute (a))
2850 } else if (a.Name.IndexOf ("DllImport") != -1) {
2852 a.Type = TypeManager.dllimport_type;
2853 Attribute.Error_AttributeNotValidForElement (a, Location);
2856 if (!ApplyDllImportAttribute (a))
2866 // Applies the `DllImport' attribute to the method.
2868 protected virtual bool ApplyDllImportAttribute (Attribute a)
2870 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2871 if ((modifiers & extern_static) != extern_static) {
2872 Report.Error (601, Location,
2873 "The DllImport attribute must be specified on a method " +
2874 "marked `static' and `extern'.");
2878 flags |= MethodAttributes.PinvokeImpl;
2879 dllimport_attribute = a;
2884 // Applies the `Obsolete' attribute to the method.
2886 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2888 if (obsolete != null) {
2889 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2893 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2894 return obsolete != null;
2898 // Applies the `Conditional' attribute to the method.
2900 protected virtual bool ApplyConditionalAttribute (Attribute a)
2902 // The Conditional attribute is only valid on methods.
2904 Attribute.Error_AttributeNotValidForElement (a, Location);
2908 string condition = a.Conditional_GetConditionName ();
2910 if (condition == null)
2913 if (ReturnType != TypeManager.void_type) {
2914 Report.Error (578, Location,
2915 "Conditional not valid on `" + member.Name + "' " +
2916 "because its return type is not void");
2920 if ((modifiers & Modifiers.OVERRIDE) != 0) {
2921 Report.Error (243, Location,
2922 "Conditional not valid on `" + member.Name + "' " +
2923 "because it is an override method");
2927 if (member.IsExplicitImpl) {
2928 Report.Error (577, Location,
2929 "Conditional not valid on `" + member.Name + "' " +
2930 "because it is an explicit interface implementation");
2934 if (IsImplementing) {
2935 Report.Error (623, Location,
2936 "Conditional not valid on `" + member.Name + "' " +
2937 "because it is an interface method");
2941 conditionals.Add (condition);
2947 // Checks whether this method should be ignored due to its Conditional attributes.
2949 bool ShouldIgnore (Location loc)
2951 // When we're overriding a virtual method, we implicitly inherit the
2952 // Conditional attributes from our parent.
2953 if (member.ParentMethod != null) {
2954 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2955 member.ParentMethod, loc);
2957 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2961 foreach (string condition in conditionals)
2962 if (RootContext.AllDefines [condition] == null)
2969 // Returns the TypeManager.MethodFlags for this method.
2970 // This emits an error 619 / warning 618 if the method is obsolete.
2971 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2973 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2975 TypeManager.MethodFlags flags = 0;
2977 if (obsolete != null) {
2978 if (obsolete_error) {
2979 Report.Error (619, loc, "Method `" + member.Name +
2980 "' is obsolete: `" + obsolete + "'");
2981 return TypeManager.MethodFlags.IsObsoleteError;
2983 Report.Warning (618, loc, "Method `" + member.Name +
2984 "' is obsolete: `" + obsolete + "'");
2986 flags |= TypeManager.MethodFlags.IsObsolete;
2989 if (ShouldIgnore (loc))
2990 flags |= TypeManager.MethodFlags.ShouldIgnore;
2995 public virtual bool Define (TypeContainer parent)
2997 MethodInfo implementing = null;
2998 string method_name, name, prefix;
3000 if (OptAttributes != null)
3001 if (!ApplyAttributes (OptAttributes, is_method))
3004 if (member.IsExplicitImpl)
3005 prefix = member.InterfaceType.FullName + ".";
3009 if (accessor_name != null)
3010 name = accessor_name + "_" + member.ShortName;
3012 name = member.ShortName;
3013 method_name = prefix + name;
3015 if (parent.Pending != null){
3016 if (member is Indexer)
3017 implementing = parent.Pending.IsInterfaceIndexer (
3018 member.InterfaceType, ReturnType, ParameterTypes);
3020 implementing = parent.Pending.IsInterfaceMethod (
3021 member.InterfaceType, name, ReturnType, ParameterTypes);
3023 if (member.InterfaceType != null && implementing == null){
3024 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
3031 // For implicit implementations, make sure we are public, for
3032 // explicit implementations, make sure we are private.
3034 if (implementing != null){
3036 // Setting null inside this block will trigger a more
3037 // verbose error reporting for missing interface implementations
3039 // The "candidate" function has been flagged already
3040 // but it wont get cleared
3042 if (!member.IsExplicitImpl){
3044 // We already catch different accessibility settings
3045 // so we just need to check that we are not private
3047 if ((modifiers & Modifiers.PRIVATE) != 0)
3048 implementing = null;
3051 // Static is not allowed
3053 if ((modifiers & Modifiers.STATIC) != 0)
3054 implementing = null;
3056 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3057 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3058 implementing = null;
3064 // If implementing is still valid, set flags
3066 if (implementing != null){
3068 // When implementing interface methods, set NewSlot.
3070 if (implementing.DeclaringType.IsInterface)
3071 flags |= MethodAttributes.NewSlot;
3074 MethodAttributes.Virtual |
3075 MethodAttributes.HideBySig;
3077 // Get the method name from the explicit interface.
3078 if (member.InterfaceType != null) {
3079 name = implementing.Name;
3080 method_name = prefix + name;
3083 IsImplementing = true;
3087 // Create the MethodBuilder for the method
3089 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3090 if ((modifiers & Modifiers.STATIC) == 0) {
3091 Report.Error (601, Location,
3092 "The DllImport attribute must be specified on " +
3093 "a method marked 'static' and 'extern'.");
3097 EmitContext ec = new EmitContext (
3098 parent, Location, null, ReturnType, modifiers);
3100 builder = dllimport_attribute.DefinePInvokeMethod (
3101 ec, parent.TypeBuilder, method_name, flags,
3102 ReturnType, ParameterTypes);
3104 builder = parent.TypeBuilder.DefineMethod (
3105 method_name, flags, CallingConventions,
3106 ReturnType, ParameterTypes);
3108 if (builder == null)
3111 if (IsImplementing) {
3113 // clear the pending implemntation flag
3115 if (member is Indexer) {
3116 parent.Pending.ImplementIndexer (
3117 member.InterfaceType, builder, ReturnType,
3118 ParameterTypes, true);
3120 parent.Pending.ImplementMethod (
3121 member.InterfaceType, name, ReturnType,
3122 ParameterTypes, member.IsExplicitImpl);
3124 if (member.IsExplicitImpl)
3125 parent.TypeBuilder.DefineMethodOverride (
3126 builder, implementing);
3129 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3130 Report.Error (111, Location,
3131 "Class `" + parent.Name +
3132 "' already contains a definition with the " +
3133 "same return value and parameter types as the " +
3134 "'get' method of property `" + member.Name + "'");
3138 TypeManager.AddMethod (builder, this);
3146 public virtual void Emit (TypeContainer parent, Block block, object kind)
3151 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3152 ig = builder.GetILGenerator ();
3156 ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3158 if (OptAttributes != null)
3159 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
3161 if (member is MethodCore)
3162 ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder);
3165 // abstract or extern methods have no bodies
3167 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3172 // abstract or extern methods have no bodies.
3174 if ((modifiers & Modifiers.ABSTRACT) != 0)
3176 500, Location, "Abstract method `" +
3177 TypeManager.MonoBASIC_Signature (builder) +
3178 "' can not have a body");
3180 if ((modifiers & Modifiers.EXTERN) != 0)
3182 179, Location, "External method `" +
3183 TypeManager.MonoBASIC_Signature (builder) +
3184 "' can not have a body");
3190 // Methods must have a body unless they're extern or abstract
3192 if (block == null) {
3194 501, Location, "Method `" +
3195 TypeManager.MonoBASIC_Signature (builder) +
3196 "' must declare a body since it is not marked " +
3197 "abstract or extern");
3202 // Handle destructors specially
3204 // FIXME: This code generates buggy code
3206 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3207 EmitDestructor (ec, block);
3209 ISymbolWriter sw = CodeGen.SymbolWriter;
3211 if ((sw != null) && !Location.IsNull (Location) &&
3212 !Location.IsNull (block.EndLocation)) {
3213 Location end = block.EndLocation;
3214 MethodToken token = MethodBuilder.GetToken ();
3215 sw.OpenMethod (new SymbolToken (token.Token));
3216 // Avoid error if we don't support debugging for the platform
3218 sw.SetMethodSourceRange (Location.SymbolDocument,
3222 } catch (Exception) {
3225 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3229 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3233 void EmitDestructor (EmitContext ec, Block block)
3235 ILGenerator ig = ec.ig;
3237 Label finish = ig.DefineLabel ();
3238 bool old_in_try = ec.InTry;
3240 ig.BeginExceptionBlock ();
3242 ec.ReturnLabel = finish;
3243 ec.HasReturnLabel = true;
3244 ec.EmitTopBlock (block, null, Location);
3245 ec.InTry = old_in_try;
3247 // ig.MarkLabel (finish);
3248 bool old_in_finally = ec.InFinally;
3249 ec.InFinally = true;
3250 ig.BeginFinallyBlock ();
3252 if (ec.ContainerType.BaseType != null) {
3253 Expression member_lookup = Expression.MemberLookup (
3254 ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
3255 MemberTypes.Method, Expression.AllBindingFlags, Location);
3257 if (member_lookup != null){
3258 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3260 ig.Emit (OpCodes.Ldarg_0);
3261 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3264 ec.InFinally = old_in_finally;
3266 ig.EndExceptionBlock ();
3267 //ig.MarkLabel (ec.ReturnLabel);
3268 ig.Emit (OpCodes.Ret);
3272 abstract public class MemberBase : MemberCore {
3273 public Expression Type;
3274 public readonly Attributes OptAttributes;
3275 public Expression Implements;
3277 protected MethodAttributes flags;
3280 // The "short" name of this property / indexer / event. This is the
3281 // name without the explicit interface.
3283 public string ShortName;
3286 // The type of this property / indexer / event
3288 public Type MemberType;
3291 // If true, this is an explicit interface implementation
3293 public bool IsExplicitImpl = false;
3296 // The name of the interface we are explicitly implementing
3298 public string ExplicitInterfaceName = null;
3301 // If true, the interface type we are explicitly implementing
3303 public Type InterfaceType = null;
3306 // The method we're overriding if this is an override method.
3308 protected MethodInfo parent_method = null;
3309 public MethodInfo ParentMethod {
3311 return parent_method;
3316 // The constructor is only exposed to our children
3318 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3319 Attributes attrs, Location loc)
3323 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PUBLIC, loc);
3324 OptAttributes = attrs;
3327 protected virtual bool CheckBase (TypeContainer parent)
3332 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3336 foreach (Type partype in parameters){
3337 if (partype.IsPointer && !UnsafeOK (parent))
3340 if (parent.AsAccessible (partype, ModFlags))
3343 if (this is Indexer)
3344 Report.Error (55, Location,
3345 "Inconsistent accessibility: parameter type `" +
3346 TypeManager.MonoBASIC_Name (partype) + "' is less " +
3347 "accessible than indexer `" + Name + "'");
3349 Report.Error (51, Location,
3350 "Inconsistent accessibility: parameter type `" +
3351 TypeManager.MonoBASIC_Name (partype) + "' is less " +
3352 "accessible than method `" + Name + "'");
3359 protected virtual bool DoDefine (TypeContainer parent)
3364 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3367 flags = Modifiers.MethodAttr (ModFlags);
3369 // Lookup Type, verify validity
3370 MemberType = parent.ResolveType (Type, false, Location);
3371 if (MemberType == null)
3374 // verify accessibility
3375 if (!parent.AsAccessible (MemberType, ModFlags)) {
3376 if (this is Property)
3377 Report.Error (53, Location,
3378 "Inconsistent accessibility: property type `" +
3379 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3380 "accessible than property `" + Name + "'");
3381 else if (this is Indexer)
3382 Report.Error (54, Location,
3383 "Inconsistent accessibility: indexer return type `" +
3384 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3385 "accessible than indexer `" + Name + "'");
3386 else if (this is Method)
3387 Report.Error (50, Location,
3388 "Inconsistent accessibility: return type `" +
3389 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3390 "accessible than method `" + Name + "'");
3392 Report.Error (52, Location,
3393 "Inconsistent accessibility: field type `" +
3394 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3395 "accessible than field `" + Name + "'");
3399 if (MemberType.IsPointer && !UnsafeOK (parent))
3403 // Check for explicit interface implementation
3405 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
3406 int pos = Name.LastIndexOf (".");
3408 ExplicitInterfaceName = Name.Substring (0, pos);
3409 ShortName = Name.Substring (pos + 1);
3413 if (ExplicitInterfaceName != null) {
3414 InterfaceType = RootContext.LookupType (
3415 parent, ExplicitInterfaceName, false, Location);
3416 if (InterfaceType == null)
3419 // Compute the full name that we need to export.
3420 Name = InterfaceType.FullName + "." + ShortName;
3422 if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
3425 IsExplicitImpl = true;
3427 IsExplicitImpl = false;
3434 // Fields and Events both generate FieldBuilders, we use this to share
3435 // their common bits. This is also used to flag usage of the field
3437 abstract public class FieldBase : MemberBase {
3438 public FieldBuilder FieldBuilder;
3439 public Status status;
3442 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3445 // The constructor is only exposed to our children
3447 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3448 object init, Attributes attrs, Location loc)
3449 : base (type, mod, allowed_mod, name, attrs, loc)
3455 // Whether this field has an initializer.
3457 public bool HasInitializer {
3459 return init != null;
3464 readonly Object init;
3465 Expression init_expr;
3466 bool init_expr_initialized = false;
3469 // Resolves and returns the field initializer.
3471 public Expression GetInitializerExpression (EmitContext ec)
3473 if (init_expr_initialized)
3477 if (init is Expression)
3478 e = (Expression) init;
3480 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3482 ec.IsFieldInitializer = true;
3483 e = e.DoResolve (ec);
3484 ec.IsFieldInitializer = false;
3487 init_expr_initialized = true;
3495 // The Field class is used to represents class/struct fields during parsing.
3497 public class Field : FieldBase {
3499 // Modifiers allowed in a class declaration
3501 const int AllowedModifiers =
3504 Modifiers.PROTECTED |
3505 Modifiers.INTERNAL |
3508 Modifiers.VOLATILE |
3512 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3513 Attributes attrs, Location loc)
3514 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3518 public override bool Define (TypeContainer parent)
3520 Type t = parent.ResolveType (Type, false, Location);
3525 if (!parent.AsAccessible (t, ModFlags)) {
3526 Report.Error (52, Location,
3527 "Inconsistent accessibility: field type `" +
3528 TypeManager.MonoBASIC_Name (t) + "' is less " +
3529 "accessible than field `" + Name + "'");
3533 if (t.IsPointer && !UnsafeOK (parent))
3536 if (RootContext.WarningLevel > 1){
3537 Type ptype = parent.TypeBuilder.BaseType;
3539 // ptype is only null for System.Object while compiling corlib.
3541 TypeContainer.FindMembers (
3542 ptype, MemberTypes.Method,
3543 BindingFlags.Public |
3544 BindingFlags.Static | BindingFlags.Instance,
3545 System.Type.FilterName, Name);
3549 if ((ModFlags & Modifiers.VOLATILE) != 0){
3551 if (TypeManager.IsEnumType (t))
3552 t = TypeManager.EnumToUnderlying (t);
3554 if (!((t == TypeManager.bool_type) ||
3555 (t == TypeManager.sbyte_type) ||
3556 (t == TypeManager.byte_type) ||
3557 (t == TypeManager.short_type) ||
3558 (t == TypeManager.ushort_type) ||
3559 (t == TypeManager.int32_type) ||
3560 (t == TypeManager.uint32_type) ||
3561 (t == TypeManager.char_type) ||
3562 (t == TypeManager.float_type))){
3564 677, Location, parent.MakeName (Name) +
3565 " A volatile field can not be of type `" +
3566 TypeManager.MonoBASIC_Name (t) + "'");
3572 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3574 if (parent is Struct &&
3575 ((fa & FieldAttributes.Static) == 0) &&
3576 t == parent.TypeBuilder &&
3577 !TypeManager.IsBuiltinType (t)){
3578 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name +
3579 "' causes a cycle in the structure layout");
3582 FieldBuilder = parent.TypeBuilder.DefineField (
3583 Name, t, Modifiers.FieldAttr (ModFlags));
3585 TypeManager.RegisterFieldBase (FieldBuilder, this);
3589 public void Emit (TypeContainer tc)
3591 EmitContext ec = new EmitContext (tc, Location, null,
3592 FieldBuilder.FieldType, ModFlags);
3594 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
3599 // `set' and `get' accessors are represented with an Accessor.
3601 public class Accessor {
3603 // Null if the accessor is empty, or a Block if not
3606 public Attributes OptAttributes;
3608 public Accessor (Block b, Attributes attrs)
3611 OptAttributes = attrs;
3616 // Properties and Indexers both generate PropertyBuilders, we use this to share
3617 // their common bits.
3619 abstract public class PropertyBase : MethodCore {
3620 public Accessor Get, Set;
3621 public PropertyBuilder PropertyBuilder;
3622 public MethodBuilder GetBuilder, SetBuilder;
3623 public MethodData GetData, SetData;
3625 protected EmitContext ec;
3627 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3628 Parameters parameters, Accessor get_block, Accessor set_block,
3629 Attributes attrs, Location loc)
3630 : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3636 protected override bool DoDefine (TypeContainer parent)
3638 if (!base.DoDefine (parent))
3641 ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3647 // Checks our base implementation if any
3649 protected override bool CheckBase (TypeContainer parent)
3651 // Check whether arguments were correct.
3652 if (!DoDefineParameters (parent))
3659 MethodSignature ms, base_ms;
3660 if (this is Indexer) {
3661 string name, base_name;
3663 report_name = "this";
3664 name = TypeManager.IndexerPropertyName (parent.TypeBuilder);
3665 ms = new MethodSignature (name, null, ParameterTypes);
3666 base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType);
3667 base_ms = new MethodSignature (base_name, null, ParameterTypes);
3670 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
3673 MemberList props_this;
3675 props_this = TypeContainer.FindMembers (
3676 parent.TypeBuilder, MemberTypes.Property,
3677 BindingFlags.NonPublic | BindingFlags.Public |
3678 BindingFlags.Static | BindingFlags.Instance |
3679 BindingFlags.DeclaredOnly,
3680 MethodSignature.method_signature_filter, ms);
3682 if (props_this.Count > 0) {
3683 Report.Error (111, Location, "Class `" + parent.Name + "' " +
3684 "already defines a member called `" + report_name + "' " +
3685 "with the same parameter types");
3690 // Find properties with the same name on the base class
3693 MemberList props_static = TypeContainer.FindMembers (
3694 parent.TypeBuilder.BaseType, MemberTypes.Property,
3695 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3696 MethodSignature.inheritable_property_signature_filter, base_ms);
3698 MemberList props_instance = TypeContainer.FindMembers (
3699 parent.TypeBuilder.BaseType, MemberTypes.Property,
3700 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3701 MethodSignature.inheritable_property_signature_filter,
3705 // Find if we have anything
3707 if (props_static.Count > 0)
3708 props = props_static;
3709 else if (props_instance.Count > 0)
3710 props = props_instance;
3716 // If we have something on the base.
3717 if (props != null && props.Count > 0){
3718 PropertyInfo pi = (PropertyInfo) props [0];
3720 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
3721 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
3723 MethodInfo reference = inherited_get == null ?
3724 inherited_set : inherited_get;
3726 if (reference != null) {
3727 string name = reference.DeclaringType.Name + "." + report_name;
3729 if (!CheckMethodAgainstBase (parent, flags, reference, name))
3733 if (((ModFlags & Modifiers.NEW) == 0) && (pi.PropertyType != MemberType)) {
3734 Report.Error (508, parent.MakeName (Name) + ": cannot " +
3735 "change return type when overriding inherited " +
3736 "member `" + pi.DeclaringType + "." + pi.Name + "'");
3740 /*if ((ModFlags & Modifiers.NEW) != 0)
3741 WarningNotHiding (parent);*/
3743 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3744 if (this is Indexer)
3745 Report.Error (115, Location,
3746 parent.MakeName (Name) +
3747 " no suitable indexers found to override");
3749 Report.Error (115, Location,
3750 parent.MakeName (Name) +
3751 " no suitable properties found to override");
3758 public virtual void Emit (TypeContainer tc)
3761 // The PropertyBuilder can be null for explicit implementations, in that
3762 // case, we do not actually emit the ".property", so there is nowhere to
3763 // put the attribute
3765 if (PropertyBuilder != null)
3766 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3768 if (GetData != null)
3769 GetData.Emit (tc, Get.Block, Get);
3771 if (SetData != null)
3772 SetData.Emit (tc, Set.Block, Set);
3777 public class Property : PropertyBase {
3778 const int AllowedModifiers =
3781 Modifiers.PROTECTED |
3782 Modifiers.INTERNAL |
3786 Modifiers.OVERRIDE |
3787 Modifiers.ABSTRACT |
3792 Modifiers.READONLY |
3793 Modifiers.WRITEONLY |
3796 string set_parameter_name;
3797 Parameters get_params;
3798 Parameters set_params;
3800 public Property (Expression type, string name, int mod_flags,
3801 Accessor get_block, Accessor set_block,
3802 Attributes attrs, Location loc, string set_name,
3803 Parameters p_get, Parameters p_set, Expression impl_what)
3804 : base (type, name, mod_flags, AllowedModifiers,
3806 get_block, set_block, attrs, loc)
3808 set_parameter_name = set_name;
3811 Implements = impl_what;
3814 public Property (Expression type, string name, int mod_flags,
3815 Accessor get_block, Accessor set_block,
3816 Attributes attrs, Location loc)
3817 : this (type, name, mod_flags, get_block, set_block, attrs, loc,
3818 "Value", Parameters.EmptyReadOnlyParameters, Parameters.EmptyReadOnlyParameters, null)
3822 public override bool Define (TypeContainer parent)
3824 Type [] g_parameters=null, s_parameters=null;
3825 Parameter [] g_parms, s_parms;
3826 InternalParameters g_ip=null, s_ip=null;
3828 if (!DoDefine (parent))
3831 if (!CheckBase (parent))
3834 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3837 if (get_params == Parameters.EmptyReadOnlyParameters)
3839 g_parameters = TypeManager.NoTypes;
3840 g_ip = new InternalParameters (
3841 parent, Parameters.EmptyReadOnlyParameters);
3845 g_parameters = new Type [get_params.FixedParameters.Length];
3846 for (int i = 0; i < get_params.FixedParameters.Length; i ++)
3848 g_parameters[i] = get_params.FixedParameters[i].ParameterType;
3850 g_parms = new Parameter [get_params.FixedParameters.Length];
3851 for (int i = 0; i < get_params.FixedParameters.Length; i ++)
3853 Parameter tp = get_params.FixedParameters[i];
3854 g_parms[i] = new Parameter (tp.TypeName, tp.Name,
3855 Parameter.Modifier.NONE, null);
3857 g_ip = new InternalParameters (
3858 parent, new Parameters (g_parms, null, Location));
3861 GetData = new MethodData (this, "get", MemberType,
3862 g_parameters, g_ip, CallingConventions.Standard,
3863 Get.OptAttributes, ModFlags, flags, false);
3865 if (!GetData.Define (parent))
3868 GetBuilder = GetData.MethodBuilder;
3872 if (set_params == Parameters.EmptyReadOnlyParameters)
3874 s_parameters = new Type [1];
3875 s_parameters [0] = MemberType;
3877 s_parms = new Parameter [1];
3878 s_parms [0] = new Parameter (Type, /* was "value" */ set_parameter_name,
3879 Parameter.Modifier.NONE, null);
3883 s_parameters = new Type [set_params.FixedParameters.Length];
3884 for (int i = 0; i < set_params.FixedParameters.Length; i ++)
3886 s_parameters[i] = set_params.FixedParameters[i].ParameterType;
3889 s_parms = new Parameter [set_params.FixedParameters.Length];
3890 for (int i = 0; i < set_params.FixedParameters.Length; i ++)
3892 Parameter tp = set_params.FixedParameters[i];
3893 s_parms[i] = new Parameter (tp.TypeName, tp.Name,
3894 Parameter.Modifier.NONE, null);
3898 s_ip = new InternalParameters (
3899 parent, new Parameters (s_parms, null, Location));
3902 SetData = new MethodData (this, "set", TypeManager.void_type,
3903 s_parameters, s_ip, CallingConventions.Standard,
3904 Set.OptAttributes, ModFlags, flags, false);
3906 if (!SetData.Define (parent))
3909 SetBuilder = SetData.MethodBuilder;
3910 SetBuilder.DefineParameter (1, ParameterAttributes.None,
3911 /* was "value" */ set_parameter_name);
3914 // FIXME - PropertyAttributes.HasDefault ?
3916 PropertyAttributes prop_attr =
3917 PropertyAttributes.RTSpecialName |
3918 PropertyAttributes.SpecialName;
3920 if (!IsExplicitImpl){
3921 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3922 Name, prop_attr, MemberType, null);
3925 PropertyBuilder.SetGetMethod (GetBuilder);
3928 PropertyBuilder.SetSetMethod (SetBuilder);
3931 // HACK for the reasons exposed above
3933 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3936 "Class `" + parent.Name +
3937 "' already contains a definition for the property `" +
3945 public override void Emit (TypeContainer tc)
3949 if (GetData != null)
3951 Parameters = get_params;
3952 GetData.Emit (tc, Get.Block, Get);
3955 if (SetData != null)
3957 Parameters = set_params;
3958 SetData.Emit (tc, Set.Block, Set);
3965 /// Gigantic workaround for lameness in SRE follows :
3966 /// This class derives from EventInfo and attempts to basically
3967 /// wrap around the EventBuilder so that FindMembers can quickly
3968 /// return this in it search for members
3970 public class MyEventBuilder : EventInfo {
3973 // We use this to "point" to our Builder which is
3974 // not really a MemberInfo
3976 EventBuilder MyBuilder;
3979 // We "catch" and wrap these methods
3981 MethodInfo raise, remove, add;
3983 EventAttributes attributes;
3984 Type declaring_type, reflected_type, event_type;
3987 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3989 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3991 // And now store the values in our own fields.
3993 declaring_type = type_builder;
3995 reflected_type = type_builder;
3997 attributes = event_attr;
3999 this.event_type = event_type;
4003 // Methods that you have to override. Note that you only need
4004 // to "implement" the variants that take the argument (those are
4005 // the "abstract" methods, the others (GetAddMethod()) are
4008 public override MethodInfo GetAddMethod (bool nonPublic)
4013 public override MethodInfo GetRemoveMethod (bool nonPublic)
4018 public override MethodInfo GetRaiseMethod (bool nonPublic)
4024 // These methods make "MyEventInfo" look like a Builder
4026 public void SetRaiseMethod (MethodBuilder raiseMethod)
4028 raise = raiseMethod;
4029 MyBuilder.SetRaiseMethod (raiseMethod);
4032 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4034 remove = removeMethod;
4035 MyBuilder.SetRemoveOnMethod (removeMethod);
4038 public void SetAddOnMethod (MethodBuilder addMethod)
4041 MyBuilder.SetAddOnMethod (addMethod);
4044 public void SetCustomAttribute (CustomAttributeBuilder cb)
4046 MyBuilder.SetCustomAttribute (cb);
4049 public override object [] GetCustomAttributes (bool inherit)
4051 // FIXME : There's nothing which can be seemingly done here because
4052 // we have no way of getting at the custom attribute objects of the
4057 public override object [] GetCustomAttributes (Type t, bool inherit)
4059 // FIXME : Same here !
4063 public override bool IsDefined (Type t, bool b)
4068 public override EventAttributes Attributes {
4074 public override string Name {
4080 public override Type DeclaringType {
4082 return declaring_type;
4086 public override Type ReflectedType {
4088 return reflected_type;
4092 public Type EventType {
4099 public class Event : FieldBase {
4100 const int AllowedModifiers =
4103 Modifiers.PROTECTED |
4104 Modifiers.INTERNAL |
4109 Modifiers.OVERRIDE |
4113 public readonly Accessor Add;
4114 public readonly Accessor Remove;
4115 public MyEventBuilder EventBuilder;
4117 MethodBuilder AddBuilder, RemoveBuilder;
4118 MethodData AddData, RemoveData;
4120 public Event (Expression type, string name, Object init, int mod, Accessor add,
4121 Accessor remove, Attributes attrs, Location loc)
4122 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4128 public override bool Define (TypeContainer parent)
4130 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4132 if (!DoDefine (parent))
4135 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4136 Report.Error (66, Location, "'" + parent.Name + "." + Name +
4137 "' : event must be of a delegate type");
4141 Type [] parameter_types = new Type [1];
4142 parameter_types [0] = MemberType;
4144 Parameter [] parms = new Parameter [1];
4145 parms [0] = new Parameter (Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4146 InternalParameters ip = new InternalParameters (
4147 parent, new Parameters (parms, null, Location));
4149 if (!CheckBase (parent))
4153 // Now define the accessors
4155 AddData = new MethodData (this, "add", TypeManager.void_type,
4156 parameter_types, ip, CallingConventions.Standard,
4157 (Add != null) ? Add.OptAttributes : null,
4158 ModFlags, flags, false);
4160 if (!AddData.Define (parent))
4163 AddBuilder = AddData.MethodBuilder;
4164 AddBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4166 RemoveData = new MethodData (this, "remove", TypeManager.void_type,
4167 parameter_types, ip, CallingConventions.Standard,
4168 (Remove != null) ? Remove.OptAttributes : null,
4169 ModFlags, flags, false);
4171 if (!RemoveData.Define (parent))
4174 RemoveBuilder = RemoveData.MethodBuilder;
4175 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4177 if (!IsExplicitImpl){
4178 EventBuilder = new MyEventBuilder (
4179 parent.TypeBuilder, Name, e_attr, MemberType);
4181 if (Add == null && Remove == null) {
4182 FieldBuilder = parent.TypeBuilder.DefineField (
4184 FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4185 TypeManager.RegisterPrivateFieldOfEvent (
4186 (EventInfo) EventBuilder, FieldBuilder);
4187 TypeManager.RegisterFieldBase (FieldBuilder, this);
4190 EventBuilder.SetAddOnMethod (AddBuilder);
4191 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4193 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4194 Report.Error (111, Location,
4195 "Class `" + parent.Name +
4196 "' already contains a definition for the event `" +
4205 void EmitDefaultMethod (EmitContext ec, bool is_add)
4207 ILGenerator ig = ec.ig;
4208 MethodInfo method = null;
4211 method = TypeManager.delegate_combine_delegate_delegate;
4213 method = TypeManager.delegate_remove_delegate_delegate;
4215 if ((ModFlags & Modifiers.STATIC) != 0) {
4216 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4217 ig.Emit (OpCodes.Ldarg_0);
4218 ig.Emit (OpCodes.Call, method);
4219 ig.Emit (OpCodes.Castclass, MemberType);
4220 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4222 ig.Emit (OpCodes.Ldarg_0);
4223 ig.Emit (OpCodes.Ldarg_0);
4224 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4225 ig.Emit (OpCodes.Ldarg_1);
4226 ig.Emit (OpCodes.Call, method);
4227 ig.Emit (OpCodes.Castclass, MemberType);
4228 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4230 ig.Emit (OpCodes.Ret);
4233 public void Emit (TypeContainer tc)
4237 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4238 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
4241 AddData.Emit (tc, Add.Block, Add);
4243 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4244 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4245 EmitDefaultMethod (ec, true);
4249 RemoveData.Emit (tc, Remove.Block, Remove);
4251 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4252 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4253 EmitDefaultMethod (ec, false);
4260 // FIXME: This does not handle:
4262 // int INTERFACENAME [ args ]
4267 // int this [ args ]
4269 public class Indexer : PropertyBase {
4271 const int AllowedModifiers =
4274 Modifiers.PROTECTED |
4275 Modifiers.INTERNAL |
4279 Modifiers.OVERRIDE |
4284 public string IndexerName;
4285 public string InterfaceIndexerName;
4288 // Are we implementing an interface ?
4290 bool IsImplementing = false;
4292 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4293 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4294 : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4297 ExplicitInterfaceName = int_type;
4300 public override bool Define (TypeContainer parent)
4302 PropertyAttributes prop_attr =
4303 PropertyAttributes.RTSpecialName |
4304 PropertyAttributes.SpecialName;
4306 if (!DoDefine (parent))
4309 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4310 if (IndexerName == null)
4311 IndexerName = "Item";
4312 else if (IsExplicitImpl)
4313 Report.Error (592, Location,
4314 "Attribute 'IndexerName' is not valid on this declaration " +
4315 "type. It is valid on `property' declarations only.");
4317 ShortName = IndexerName;
4318 if (IsExplicitImpl) {
4319 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4320 Name = InterfaceType.FullName + "." + IndexerName;
4322 InterfaceIndexerName = IndexerName;
4326 if (!CheckBase (parent))
4330 InternalParameters ip = new InternalParameters (parent, Parameters);
4332 GetData = new MethodData (this, "get", MemberType,
4333 ParameterTypes, ip, CallingConventions.Standard,
4334 Get.OptAttributes, ModFlags, flags, false);
4336 if (!GetData.Define (parent))
4339 GetBuilder = GetData.MethodBuilder;
4343 int top = ParameterTypes.Length;
4344 Type [] set_pars = new Type [top + 1];
4345 ParameterTypes.CopyTo (set_pars, 0);
4346 set_pars [top] = MemberType;
4348 Parameter [] fixed_parms = Parameters.FixedParameters;
4350 if (fixed_parms == null){
4351 throw new Exception ("We currently do not support only array arguments in an indexer");
4352 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4353 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4355 // Here is the problem: the `value' parameter has
4356 // to come *after* the array parameter in the declaration
4358 // X (object [] x, Type value)
4361 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4362 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4366 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4369 fixed_parms.CopyTo (tmp, 0);
4370 tmp [fixed_parms.Length] = new Parameter (
4371 Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4373 Parameters set_formal_params = new Parameters (tmp, null, Location);
4375 InternalParameters ip = new InternalParameters (parent, set_formal_params);
4377 SetData = new MethodData (this, "set", TypeManager.void_type,
4378 set_pars, ip, CallingConventions.Standard,
4379 Set.OptAttributes, ModFlags, flags, false);
4381 if (!SetData.Define (parent))
4384 SetBuilder = SetData.MethodBuilder;
4388 // Now name the parameters
4390 Parameter [] p = Parameters.FixedParameters;
4394 for (i = 0; i < p.Length; ++i) {
4396 GetBuilder.DefineParameter (
4397 i + 1, p [i].Attributes, p [i].Name);
4400 SetBuilder.DefineParameter (
4401 i + 1, p [i].Attributes, p [i].Name);
4406 SetBuilder.DefineParameter (
4407 i + 1, ParameterAttributes.None, /* was "value" */ this.Name);
4409 if (i != ParameterTypes.Length) {
4410 Parameter array_param = Parameters.ArrayParameter;
4411 SetBuilder.DefineParameter (
4412 i + 1, array_param.Attributes, array_param.Name);
4416 if (GetData != null)
4417 IsImplementing = GetData.IsImplementing;
4418 else if (SetData != null)
4419 IsImplementing = SetData.IsImplementing;
4422 // Define the PropertyBuilder if one of the following conditions are met:
4423 // a) we're not implementing an interface indexer.
4424 // b) the indexer has a different IndexerName and this is no
4425 // explicit interface implementation.
4427 if (!IsExplicitImpl) {
4428 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4429 IndexerName, prop_attr, MemberType, ParameterTypes);
4431 if (GetData != null)
4432 PropertyBuilder.SetGetMethod (GetBuilder);
4434 if (SetData != null)
4435 PropertyBuilder.SetSetMethod (SetBuilder);
4437 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4445 public class Operator : MemberCore {
4447 const int AllowedModifiers =
4453 const int RequiredModifiers =
4457 public enum OpType : byte {
4467 // Unary and Binary operators
4490 // Implicit and Explicit
4495 public readonly OpType OperatorType;
4496 public readonly Expression ReturnType;
4497 public readonly Expression FirstArgType, SecondArgType;
4498 public readonly string FirstArgName, SecondArgName;
4499 public readonly Block Block;
4500 public Attributes OptAttributes;
4501 public MethodBuilder OperatorMethodBuilder;
4503 public string MethodName;
4504 public Method OperatorMethod;
4506 public Operator (OpType type, Expression ret_type, int flags,
4507 Expression arg1type, string arg1name,
4508 Expression arg2type, string arg2name,
4509 Block block, Attributes attrs, Location loc)
4512 OperatorType = type;
4513 ReturnType = ret_type;
4514 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4515 FirstArgType = arg1type;
4516 FirstArgName = arg1name;
4517 SecondArgType = arg2type;
4518 SecondArgName = arg2name;
4520 OptAttributes = attrs;
4523 string Prototype (TypeContainer parent)
4525 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4526 SecondArgType + ")";
4529 public override bool Define (TypeContainer parent)
4532 MethodName = "op_" + OperatorType;
4534 if (SecondArgType != null)
4537 Parameter [] param_list = new Parameter [length];
4539 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4542 "User defined operators `" +
4543 Prototype (parent) +
4544 "' must be declared static and public");
4548 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4549 Parameter.Modifier.NONE, null);
4550 if (SecondArgType != null)
4551 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4552 Parameter.Modifier.NONE, null);
4554 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4555 new Parameters (param_list, null, Location),
4556 OptAttributes, Mono.MonoBASIC.Location.Null);
4558 OperatorMethod.IsOperator = true;
4559 OperatorMethod.Define (parent);
4561 if (OperatorMethod.MethodBuilder == null)
4564 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4566 Type [] param_types = OperatorMethod.ParameterTypes;
4567 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4568 Type return_type = OperatorMethod.GetReturnType ();
4569 Type first_arg_type = param_types [0];
4571 // Rules for conversion operators
4573 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4574 if (first_arg_type == return_type && first_arg_type == declaring_type){
4577 "User-defined conversion cannot take an object of the " +
4578 "enclosing type and convert to an object of the enclosing" +
4583 if (first_arg_type != declaring_type && return_type != declaring_type){
4586 "User-defined conversion must convert to or from the " +
4591 if (first_arg_type == TypeManager.object_type ||
4592 return_type == TypeManager.object_type){
4595 "User-defined conversion cannot convert to or from " +
4600 if (first_arg_type.IsInterface || return_type.IsInterface){
4603 "User-defined conversion cannot convert to or from an " +
4608 if (first_arg_type.IsSubclassOf (return_type) ||
4609 return_type.IsSubclassOf (first_arg_type)){
4612 "User-defined conversion cannot convert between types " +
4613 "that derive from each other");
4616 } else if (SecondArgType == null) {
4617 // Checks for Unary operators
4619 if (first_arg_type != declaring_type){
4622 "The parameter of a unary operator must be the " +
4627 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4628 if (return_type != declaring_type){
4631 "The parameter and return type for ++ and -- " +
4632 "must be the containing type");
4638 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4639 if (return_type != TypeManager.bool_type){
4642 "The return type of operator True or False " +
4649 // Checks for Binary operators
4651 if (first_arg_type != declaring_type &&
4652 param_types [1] != declaring_type){
4655 "One of the parameters of a binary operator must " +
4656 "be the containing type");
4664 public void Emit (TypeContainer parent)
4666 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4667 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4670 // abstract or extern methods have no bodies
4672 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4675 OperatorMethod.Block = Block;
4676 OperatorMethod.Emit (parent);
4679 public static string GetName (OpType ot)
4682 case OpType.LogicalNot:
4684 case OpType.OnesComplement:
4686 case OpType.Increment:
4688 case OpType.Decrement:
4694 case OpType.Addition:
4696 case OpType.Subtraction:
4698 case OpType.UnaryPlus:
4700 case OpType.UnaryNegation:
4702 case OpType.Multiply:
4704 case OpType.Division:
4706 case OpType.Modulus:
4708 case OpType.BitwiseAnd:
4710 case OpType.BitwiseOr:
4712 case OpType.ExclusiveOr:
4714 case OpType.LeftShift:
4716 case OpType.RightShift:
4718 case OpType.Equality:
4720 case OpType.Inequality:
4722 case OpType.GreaterThan:
4724 case OpType.LessThan:
4726 case OpType.GreaterThanOrEqual:
4728 case OpType.LessThanOrEqual:
4730 case OpType.Implicit:
4732 case OpType.Explicit:
4738 public override string ToString ()
4740 Type return_type = OperatorMethod.GetReturnType();
4741 Type [] param_types = OperatorMethod.ParameterTypes;
4743 if (SecondArgType == null)
4744 return String.Format (
4745 "{0} operator {1}({2})",
4746 TypeManager.MonoBASIC_Name (return_type),
4747 GetName (OperatorType),
4750 return String.Format (
4751 "{0} operator {1}({2}, {3})",
4752 TypeManager.MonoBASIC_Name (return_type),
4753 GetName (OperatorType),
4754 param_types [0], param_types [1]);
4759 // This is used to compare method signatures
4761 struct MethodSignature {
4763 public Type RetType;
4764 public Type [] Parameters;
4767 /// This delegate is used to extract methods which have the
4768 /// same signature as the argument
4770 public static MemberFilter method_signature_filter;
4773 /// This delegate is used to extract methods which have the
4774 /// same signature as the argument except for the name
4776 public static MemberFilter method_signature_noname_filter;
4779 /// This delegate is used to extract inheritable methods which
4780 /// have the same signature as the argument. By inheritable,
4781 /// this means that we have permissions to override the method
4782 /// from the current assembly and class
4784 public static MemberFilter inheritable_method_signature_filter;
4787 /// This delegate is used to extract inheritable methods which
4788 /// have the same signature as the argument. By inheritable,
4789 /// this means that we have permissions to override the method
4790 /// from the current assembly and class
4792 public static MemberFilter inheritable_property_signature_filter;
4794 static MethodSignature ()
4796 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4797 method_signature_noname_filter = new MemberFilter (MemberSignatureCompareNoName);
4798 inheritable_method_signature_filter = new MemberFilter (
4799 InheritableMemberSignatureCompare);
4800 inheritable_property_signature_filter = new MemberFilter (
4801 InheritablePropertySignatureCompare);
4804 public MethodSignature (string name, Type ret_type, Type [] parameters)
4809 if (parameters == null)
4810 Parameters = TypeManager.NoTypes;
4812 Parameters = parameters;
4815 public override int GetHashCode ()
4817 return Name.GetHashCode ();
4820 public override bool Equals (Object o)
4822 MethodSignature other = (MethodSignature) o;
4824 if (other.Name != Name)
4827 if (other.RetType != RetType)
4830 if (Parameters == null){
4831 if (other.Parameters == null)
4836 if (other.Parameters == null)
4839 int c = Parameters.Length;
4840 if (other.Parameters.Length != c)
4843 for (int i = 0; i < c; i++)
4844 if (other.Parameters [i] != Parameters [i])
4850 static bool MemberSignatureCompareNoName (MemberInfo m, object filter_criteria)
4852 return MemberSignatureCompare (m, filter_criteria, false);
4855 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4857 return MemberSignatureCompare (m, filter_criteria, true);
4860 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria, bool use_name)
4862 MethodSignature sig = (MethodSignature) filter_criteria;
4864 if (use_name && (m.Name != sig.Name))
4868 MethodInfo mi = m as MethodInfo;
4869 PropertyInfo pi = m as PropertyInfo;
4872 ReturnType = mi.ReturnType;
4873 else if (pi != null)
4874 ReturnType = pi.PropertyType;
4879 // we use sig.RetType == null to mean `do not check the
4880 // method return value.
4882 if (sig.RetType != null)
4883 if (ReturnType != sig.RetType)
4888 args = TypeManager.GetArgumentTypes (mi);
4890 args = TypeManager.GetArgumentTypes (pi);
4891 Type [] sigp = sig.Parameters;
4893 if (args.Length != sigp.Length)
4896 for (int i = args.Length; i > 0; ){
4898 if (args [i] != sigp [i])
4905 // This filter should be used when we are requesting methods that
4906 // we want to override.
4908 // This makes a number of assumptions, for example
4909 // that the methods being extracted are of a parent
4910 // class (this means we know implicitly that we are
4911 // being called to find out about members by a derived
4914 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4916 if (MemberSignatureCompare (m, filter_criteria)){
4917 MethodInfo mi = (MethodInfo) m;
4918 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4920 // If only accessible to the current class.
4921 if (prot == MethodAttributes.Private)
4924 // If only accessible to the defining assembly or
4925 if (prot == MethodAttributes.FamANDAssem ||
4926 prot == MethodAttributes.Assembly){
4927 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4933 // Anything else (FamOrAssembly and Public) is fine
4940 // This filter should be used when we are requesting properties that
4941 // we want to override.
4943 // This makes a number of assumptions, for example
4944 // that the methods being extracted are of a parent
4945 // class (this means we know implicitly that we are
4946 // being called to find out about members by a derived
4949 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
4951 if (MemberSignatureCompare (m, filter_criteria)){
4952 PropertyInfo pi = (PropertyInfo) m;
4954 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
4955 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
4957 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
4959 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4961 // If only accessible to the current class.
4962 if (prot == MethodAttributes.Private)
4965 // If only accessible to the defining assembly or
4966 if (prot == MethodAttributes.FamANDAssem ||
4967 prot == MethodAttributes.Assembly){
4968 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4974 // Anything else (FamOrAssembly and Public) is fine