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,
593 mods = Modifiers.STATIC;
597 c.Initializer = new ConstructorBaseInitializer (
598 null, Parameters.EmptyReadOnlyParameters,
603 c.Block = new Block (null);
607 public void ReportStructInitializedInstanceError ()
609 string n = TypeBuilder.FullName;
611 foreach (Field f in initialized_fields){
614 "`" + n + "." + f.Name + "': can not have " +
615 "instance field initializers in structs");
620 /// The pending methods that need to be implemented (interfaces or abstract methods)
622 public PendingImplementation Pending;
625 /// This function computes the Base class and also the
626 /// list of interfaces that the class or struct @c implements.
628 /// The return value is an array (might be null) of
629 /// interfaces implemented (as Types).
631 /// The @parent argument is set to the parent object or null
632 /// if this is `System.Object'.
634 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
636 ArrayList bases = Bases;
645 parent = TypeManager.value_type;
649 if (RootContext.StdLib)
650 parent = TypeManager.object_type;
651 else if (Name != "System.Object")
652 parent = TypeManager.object_type;
655 // If we are compiling our runtime,
656 // and we are defining ValueType, then our
657 // parent is `System.Object'.
659 if (!RootContext.StdLib && Name == "System.ValueType")
660 parent = TypeManager.object_type;
667 // Bases should be null if there are no bases at all
672 Expression name = (Expression) bases [0];
673 name = ResolveTypeExpr (name, false, Location);
680 Type first = name.Type;
686 parent = TypeManager.object_type;
690 if (parent.IsSealed )
691 Report.Error (30299, Location,
692 "Class " + Name + " cannot inherit " +
693 "'NotInheritable' class " + TypeManager.MonoBASIC_Name (parent));
695 if (!AsAccessible (parent, ModFlags))
696 Report.Error (30389, Location,
697 "Inconsistent accessibility: base class `" +
698 TypeManager.MonoBASIC_Name (parent) + "' is less " +
699 "accessible than class `" +
706 Type [] ifaces = new Type [count-start];
708 for (i = start, j = 0; i < count; i++, j++){
709 Expression name = (Expression) bases [i];
710 Expression resolved = ResolveTypeExpr (name, false, Location);
711 bases [i] = resolved;
712 Type t = resolved.Type;
719 if (is_class == false && !t.IsInterface){
720 Report.Error (527, "In Struct `" + Name + "', type `"+
721 name +"' is not an interface");
728 Report.Error (30258, "class `"+ Name +
729 "': a class can not inherit from a struct/enum");
731 /*Report.Error (509, "class `"+ Name +
732 "': Cannot inherit from sealed class `"+
740 Report.Error (30121, Name + ": A class cannot inherit " +
741 "more than one class");
747 for (int x = 0; x < j; x++) {
748 if (t == ifaces [x]) {
749 Report.Error (528, "`" + name + "' is already listed in interface list");
758 return TypeManager.ExpandInterfaces (ifaces);
762 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
764 public override TypeBuilder DefineType ()
770 if (TypeBuilder != null)
783 ec = new EmitContext (this, Mono.MonoBASIC.Location.Null, null, null, ModFlags);
785 if (((ModFlags & Modifiers.ABSTRACT ) != 0) &&
786 ((ModFlags & Modifiers.SEALED) != 0)){
787 Report.Error (31408, Location,
788 "Class declared as 'MustInherit' cannot be declared as 'NotInheritable'");
791 ifaces = GetClassBases (is_class, out parent, out error);
796 if (is_class && parent != null){
797 if (parent == TypeManager.enum_type ||
798 (parent == TypeManager.value_type && RootContext.StdLib) ||
799 parent == TypeManager.delegate_type ||
800 parent == TypeManager.array_type){
802 644, Location, "`" + Name + "' cannot inherit from " +
803 "special class `" + TypeManager.MonoBASIC_Name (parent) + "'");
808 if (!is_class && TypeManager.value_type == null)
809 throw new Exception ();
811 if (is_class && Parent.Parent == null)
\r
813 if ((ModFlags & Modifiers.PRIVATE) != 0)
814 Report.Error (31089, Location,
815 "Only internal classes can be declared as 'Private'");
817 if ((ModFlags & Modifiers.PROTECTED) != 0)
818 Report.Error (31047, Location,
819 "Only internal classes can be declared as 'Protected'");
822 if ((Parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
823 Report.Error (30735, Location,
824 "'Type' inside a 'Module' can not be " +
825 "declared as 'Protected'");
827 if ((Parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
828 Report.Error (30435, Location,
829 "'Type' inside a 'Structure' can not be " +
830 "declared as 'Protected'");
832 TypeAttributes type_attributes = TypeAttr;
834 // if (parent_builder is ModuleBuilder) {
836 ModuleBuilder builder = CodeGen.ModuleBuilder;
837 TypeBuilder = builder.DefineType (
838 Name, type_attributes, parent, ifaces);
841 TypeBuilder builder = Parent.TypeBuilder;
842 TypeBuilder = builder.DefineNestedType (
843 Basename, type_attributes, parent, ifaces);
848 // structure must contain atleast one member variable
849 if(!have_nonstatic_fields){
851 30281, Location, "Structure `" + Name + "' do not " +
852 "contain any member Variable");
854 /*TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
855 FieldAttributes.Private);*/
858 // add interfaces that were not added at type creation (weird API issue)
859 if (!have_nonstatic_fields && (ifaces != null)) {
860 foreach (Type i in ifaces)
861 TypeBuilder.AddInterfaceImplementation (i);
867 // Finish the setup for the EmitContext
869 ec.ContainerType = TypeBuilder;
871 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
873 if ((parent != null) &&
874 (parent == TypeManager.attribute_type ||
875 parent.IsSubclassOf (TypeManager.attribute_type))) {
876 RootContext.RegisterAttribute (this);
877 TypeManager.RegisterAttrType (TypeBuilder, this);
879 RootContext.RegisterOrder (this);
881 if (Interfaces != null) {
882 foreach (Interface iface in Interfaces)
887 foreach (TypeContainer tc in Types)
891 if (Delegates != null) {
892 foreach (Delegate d in Delegates)
897 foreach (Enum en in Enums)
907 /// Defines the MemberCore objects that are in the `list' Arraylist
909 /// The `defined_names' array contains a list of members defined in
912 static ArrayList remove_list = new ArrayList ();
913 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
917 // if one of the overloaded method is having
918 // Shadows or Overloads modifier all other should
919 // have the same modifier
920 Hashtable members = new Hashtable();
922 foreach (MemberCore mc in list)
\r
925 if(members[mc.Name] == null)
927 foreach (MemberCore m in list)
929 if(m.Name == mc.Name)
931 if ((m.ModFlags & Modifiers.SHADOWS) != 0)
933 modval = Modifiers.SHADOWS;
936 else if((m.ModFlags & Modifiers.NEW) != 0)
938 modval = Modifiers.NEW;
942 members.Add(mc.Name, modval);
945 modval = (int)members[mc.Name];
948 if(((modval & Modifiers.SHADOWS) != 0) && ((mc.ModFlags & Modifiers.SHADOWS) == 0))
951 "Function '" + mc.Name + "': must be declared 'Shadows' " +
952 "because another '" + mc.Name + "' declared 'Shadows'");
953 else if(((modval & Modifiers.NEW) != 0) && ((mc.ModFlags & Modifiers.NEW) == 0))
956 "Function '" + mc.Name + "': must be declared 'Overloads' " +
957 "because another '" + mc.Name + "' declared 'Overloads'");
961 remove_list.Clear ();
963 foreach (MemberCore mc in list){
964 if (!mc.Define (this)){
965 remove_list.Add (mc);
969 if (defined_names == null)
972 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
974 if (RootContext.WarningLevel >= 4){
975 if ((mc.ModFlags & Modifiers.NEW) != 0)
976 Warning_KewywordNewNotRequired (mc.Location, mc);
977 if ((mc.ModFlags & Modifiers.SHADOWS) != 0)
978 Warning_KewywordShadowsNotRequired (mc.Location, mc);
983 MemberInfo match = defined_names [idx];
985 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
989 // If we are both methods, let the method resolution emit warnings
991 if (match is MethodBase && mc is MethodCore)
994 if (((mc.ModFlags & Modifiers.SHADOWS) == 0) && idx > 0)
995 Warning_KeywordShadowsRequired (mc.Location, defined_names [idx]);
999 foreach (object o in remove_list)
1002 remove_list.Clear ();
1006 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
1007 // class is consisten. Either it is `Item' or it is the name defined by all the
1008 // indexers with the `IndexerName' attribute.
1010 // Turns out that the IndexerNameAttribute is applied to each indexer,
1011 // but it is never emitted, instead a DefaultName attribute is attached
1014 void DefineIndexers ()
1016 string class_indexer_name = null;
1018 foreach (Indexer i in Indexers){
1023 name = i.IndexerName;
1025 if (i.InterfaceType != null)
1028 if (class_indexer_name == null){
1029 class_indexer_name = name;
1033 if (name == class_indexer_name)
1037 668, "Two indexers have different names, " +
1038 " you should use the same name for all your indexers");
1040 if (class_indexer_name == null)
1041 class_indexer_name = "Item";
1042 IndexerName = class_indexer_name;
1045 static void Error_KeywordNotAllowed (Location loc)
1047 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1051 /// Populates our TypeBuilder with fields and methods
1053 public override bool DefineMembers (TypeContainer parent)
1055 MemberInfo [] defined_names = null;
1057 if (interface_order != null){
1058 foreach (Interface iface in interface_order)
1059 if ((iface.ModFlags & Modifiers.NEW) == 0)
1060 iface.DefineMembers (this);
1062 Error_KeywordNotAllowed (iface.Location);
1065 if (RootContext.WarningLevel > 1){
1069 // This code throws an exception in the comparer
1070 // I guess the string is not an object?
1072 ptype = TypeBuilder.BaseType;
1074 defined_names = (MemberInfo []) FindMembers (
1075 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1076 BindingFlags.Public | BindingFlags.Instance |
1077 BindingFlags.Static, null, null);
1079 Array.Sort (defined_names, mif_compare);
1083 if (constants != null)
1084 DefineMembers (constants, defined_names);
1087 DefineMembers (fields, defined_names);
1090 if (instance_constructors == null){
1091 if (default_constructor == null)
\r
1092 DefineDefaultConstructor (false);
1095 if (initialized_static_fields != null &&
1096 default_static_constructor == null)
1097 DefineDefaultConstructor (true);
1100 if (this is Struct){
1102 // Structs can not have initialized instance
1105 if (initialized_static_fields != null &&
1106 default_static_constructor == null)
1107 DefineDefaultConstructor (true);
1109 if (initialized_fields != null)
1110 ReportStructInitializedInstanceError ();
1113 Pending = PendingImplementation.GetPendingImplementations (this);
1116 // Constructors are not in the defined_names array
1118 if (instance_constructors != null)
\r
1119 DefineMembers (instance_constructors, null);
1121 if (default_static_constructor != null)
1122 default_static_constructor.Define (this);
1124 if (methods != null)
1125 DefineMembers (methods, defined_names);
1127 if (properties != null)
1128 DefineMembers (properties, defined_names);
1131 DefineMembers (events, defined_names);
1133 if (indexers != null) {
1136 IndexerName = "Item";
1138 if (operators != null){
1139 DefineMembers (operators, null);
1141 CheckPairedOperators ();
1145 DefineMembers (enums, defined_names);
1147 if (delegates != null)
1148 DefineMembers (delegates, defined_names);
1151 if (TypeBuilder.BaseType != null)
1152 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1154 member_cache = new MemberCache (this);
1160 public override bool Define (TypeContainer parent)
1162 if (interface_order != null){
1163 foreach (Interface iface in interface_order)
1164 if ((iface.ModFlags & Modifiers.NEW) == 0)
1165 iface.Define (this);
1172 /// This function is based by a delegate to the FindMembers routine
1174 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1180 /// This filter is used by FindMembers, and we just keep
1181 /// a global for the filter to `AlwaysAccept'
1183 static MemberFilter accepting_filter;
1187 /// A member comparission method based on name only
1189 static IComparer mif_compare;
1191 static TypeContainer ()
1193 accepting_filter = new MemberFilter (AlwaysAccept);
1194 mif_compare = new MemberInfoCompare ();
1198 /// This method returns the members of this type just like Type.FindMembers would
1199 /// Only, we need to use this for types which are _being_ defined because MS'
1200 /// implementation can't take care of that.
1203 // FIXME: return an empty static array instead of null, that cleans up
1204 // some code and is consistent with some coding conventions I just found
1208 // Notice that in various cases we check if our field is non-null,
1209 // something that would normally mean that there was a bug elsewhere.
1211 // The problem happens while we are defining p-invoke methods, as those
1212 // will trigger a FindMembers, but this happens before things are defined
1214 // Since the whole process is a no-op, it is fine to check for null here.
1216 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1217 MemberFilter filter, object criteria)
1219 ArrayList members = new ArrayList ();
1222 if ((bf & BindingFlags.Public) != 0)
1223 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1225 if ((bf & BindingFlags.NonPublic) != 0)
1226 modflags |= Modifiers.PRIVATE;
1228 int static_mask = 0, static_flags = 0;
1229 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1230 case BindingFlags.Static:
1231 static_mask = static_flags = Modifiers.STATIC;
1234 case BindingFlags.Instance:
1235 static_mask = Modifiers.STATIC;
1240 static_mask = static_flags = 0;
1244 Timer.StartTimer (TimerType.TcFindMembers);
1247 filter = accepting_filter;
1249 if ((mt & MemberTypes.Field) != 0) {
1250 if (fields != null) {
1251 foreach (Field f in fields) {
1252 if ((f.ModFlags & modflags) == 0)
1254 if ((f.ModFlags & static_mask) != static_flags)
1257 FieldBuilder fb = f.FieldBuilder;
1258 if (fb != null && filter (fb, criteria) == true)
1263 if (constants != null) {
1264 foreach (Const con in constants) {
1265 if ((con.ModFlags & modflags) == 0)
1267 if ((con.ModFlags & static_mask) != static_flags)
1270 FieldBuilder fb = con.FieldBuilder;
1271 if (fb != null && filter (fb, criteria) == true)
1277 if ((mt & MemberTypes.Method) != 0) {
1278 if (methods != null) {
1279 foreach (Method m in methods) {
1280 if ((m.ModFlags & modflags) == 0)
1282 if ((m.ModFlags & static_mask) != static_flags)
1285 MethodBuilder mb = m.MethodBuilder;
1287 if (mb != null && filter (mb, criteria) == true)
1292 if (operators != null){
1293 foreach (Operator o in operators) {
1294 if ((o.ModFlags & modflags) == 0)
1296 if ((o.ModFlags & static_mask) != static_flags)
1299 MethodBuilder ob = o.OperatorMethodBuilder;
1300 if (ob != null && filter (ob, criteria) == true)
1305 if (properties != null){
1306 foreach (Property p in properties){
1307 if ((p.ModFlags & modflags) == 0)
1309 if ((p.ModFlags & static_mask) != static_flags)
1315 if (b != null && filter (b, criteria) == true)
1319 if (b != null && filter (b, criteria) == true)
1324 if (indexers != null){
1325 foreach (Indexer ix in indexers){
1326 if ((ix.ModFlags & modflags) == 0)
1328 if ((ix.ModFlags & static_mask) != static_flags)
1334 if (b != null && filter (b, criteria) == true)
1338 if (b != null && filter (b, criteria) == true)
1344 if ((mt & MemberTypes.Event) != 0) {
1346 foreach (Event e in events) {
1347 if ((e.ModFlags & modflags) == 0)
1349 if ((e.ModFlags & static_mask) != static_flags)
1352 MemberInfo eb = e.EventBuilder;
1353 if (eb != null && filter (eb, criteria) == true)
1354 members.Add (e.EventBuilder);
1358 if ((mt & MemberTypes.Property) != 0){
1359 if (properties != null)
1360 foreach (Property p in properties) {
1361 if ((p.ModFlags & modflags) == 0)
1363 if ((p.ModFlags & static_mask) != static_flags)
1366 MemberInfo pb = p.PropertyBuilder;
1368 if (pb != null && filter (pb, criteria) == true) {
1369 members.Add (p.PropertyBuilder);
1373 if (indexers != null)
1374 foreach (Indexer ix in indexers) {
1375 if ((ix.ModFlags & modflags) == 0)
1377 if ((ix.ModFlags & static_mask) != static_flags)
1380 MemberInfo ib = ix.PropertyBuilder;
1381 if (ib != null && filter (ib, criteria) == true) {
1382 members.Add (ix.PropertyBuilder);
1387 if ((mt & MemberTypes.NestedType) != 0) {
1389 foreach (TypeContainer t in types) {
1390 if ((t.ModFlags & modflags) == 0)
1393 TypeBuilder tb = t.TypeBuilder;
1394 if (tb != null && (filter (tb, criteria) == true))
1400 foreach (Enum en in enums){
1401 if ((en.ModFlags & modflags) == 0)
1404 TypeBuilder tb = en.TypeBuilder;
1405 if (tb != null && (filter (tb, criteria) == true))
1410 if (delegates != null){
1411 foreach (Delegate d in delegates){
1412 if ((d.ModFlags & modflags) == 0)
1415 TypeBuilder tb = d.TypeBuilder;
1416 if (tb != null && (filter (tb, criteria) == true))
1421 if (interfaces != null){
1422 foreach (Interface iface in interfaces){
1423 if ((iface.ModFlags & modflags) == 0)
1426 TypeBuilder tb = iface.TypeBuilder;
1427 if (tb != null && (filter (tb, criteria) == true))
1433 if ((mt & MemberTypes.Constructor) != 0){
1434 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1435 foreach (Constructor c in instance_constructors){
1436 ConstructorBuilder cb = c.ConstructorBuilder;
1438 if (filter (cb, criteria) == true)
1443 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1444 ConstructorBuilder cb =
1445 default_static_constructor.ConstructorBuilder;
1448 if (filter (cb, criteria) == true)
1454 // Lookup members in parent if requested.
1456 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1457 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1458 members.AddRange (list);
1461 Timer.StopTimer (TimerType.TcFindMembers);
1463 return new MemberList (members);
1466 public override MemberCache MemberCache {
1468 return member_cache;
1472 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1473 MemberFilter filter, object criteria)
1475 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1478 return tc.FindMembers (mt, bf, filter, criteria);
1480 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1484 // FindMethods will look for methods not only in the type `t', but in
1485 // any interfaces implemented by the type.
1487 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1488 MemberFilter filter, object criteria)
1494 /// Emits the values for the constants
1496 public void EmitConstants ()
1498 if (constants != null)
1499 foreach (Const con in constants)
1500 con.EmitConstant (this);
1505 /// Emits the code, this step is performed after all
1506 /// the types, enumerations, constructors
1510 if (instance_constructors != null)
1511 foreach (Constructor c in instance_constructors)
1514 if (default_static_constructor != null)
1515 default_static_constructor.Emit (this);
1517 if (methods != null)
1518 foreach (Method m in methods)
1521 if (operators != null)
1522 foreach (Operator o in operators)
1525 if (properties != null)
1526 foreach (Property p in properties)
1529 if (indexers != null){
1530 foreach (Indexer ix in indexers)
1533 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1534 this, IndexerName, ModFlags, Location);
1535 TypeBuilder.SetCustomAttribute (cb);
1539 foreach (Field f in fields)
1542 if (events != null){
1543 foreach (Event e in Events)
1547 if (Pending != null)
1548 if (Pending.VerifyPendingMethods ())
1551 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1554 // Check for internal or private fields that were never assigned
1556 if (fields != null && RootContext.WarningLevel >= 3) {
1557 foreach (Field f in fields) {
1558 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1563 169, f.Location, "Private field " +
1564 MakeName (f.Name) + " is never used");
1569 // Only report 649 on level 4
1571 if (RootContext.WarningLevel < 4)
1574 if ((f.status & Field.Status.ASSIGNED) != 0)
1579 "Field " + MakeName (f.Name) + " is never assigned " +
1580 " to and will always have its default value");
1584 // if (types != null)
1585 // foreach (TypeContainer tc in types)
1589 public override void CloseType ()
1594 TypeBuilder.CreateType ();
1596 } catch (TypeLoadException){
1598 // This is fine, the code still created the type
1600 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1601 // Console.WriteLine (e.Message);
1603 Console.WriteLine ("In type: " + Name);
1608 foreach (Enum en in Enums)
1611 if (interface_order != null){
1612 foreach (Interface iface in interface_order)
1617 foreach (TypeContainer tc in Types)
1621 foreach (TypeContainer tc in Types)
1622 if (!(tc is Struct))
1626 if (Delegates != null)
1627 foreach (Delegate d in Delegates)
1631 public string MakeName (string n)
1633 return "`" + Name + "." + n + "'";
1636 public void Warning_KeywordShadowsRequired (Location l, MemberInfo mi)
1639 108, l, "The keyword 'Shadows' is required on " +
1640 MakeName (mi.Name) + " because it shadows `" +
1641 mi.ReflectedType.Name + "." + mi.Name + "'");
1644 public void Warning_KewywordShadowsNotRequired (Location l, MemberCore mc)
1647 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1648 "inherited member, the keyword shadows is not required");
1651 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1654 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1655 "inherited member, the keyword new is not required");
1658 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1664 // Performs the validation on a Method's modifiers (properties have
1665 // the same properties).
1667 public bool MethodModifiersValid (int flags, string n, Location loc)
1669 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1670 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1671 const int nv = (Modifiers.SHADOWS | Modifiers.VIRTUAL);
1673 string name = MakeName (n);
1676 // At most one of static, virtual or override
1678 if ((flags & Modifiers.STATIC) != 0){
1679 if ((flags & vao) != 0){
1681 30501, loc, "Shared method " + name + " can not be " +
1682 "declared as Overridable");
1687 if (this is Struct){
1688 if ((flags & va) != 0){
1689 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1694 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.VIRTUAL) != 0)
\r
1698 ": Methods marked as Overrides cannot be made Overridable");
1702 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.SHADOWS) != 0){
1705 ": Methods marked as Overrides cannot be marked as Shadows");
1710 // If the declaration includes the abstract modifier, then the
1711 // declaration does not include static, virtual or extern
1713 if ((flags & Modifiers.ABSTRACT) != 0){
1714 if ((flags & Modifiers.EXTERN) != 0){
1716 180, loc, name + " can not be both abstract and extern");
1720 if ((flags & Modifiers.VIRTUAL) != 0){
1722 503, loc, name + " can not be both abstract and virtual");
1726 if((ModFlags & Modifiers.SEALED) != 0){
1729 "Class declared as 'NotInheritable' " +
1730 "cannot have a 'MustOverride' member");
1733 else if ((ModFlags & Modifiers.ABSTRACT) == 0){
1736 " is declared as 'MustOverride', hence its container " +
1737 "class should be declared as 'MustInherit'");
1743 if ((flags & Modifiers.PRIVATE) != 0){
1744 if ((flags & vao) != 0){
1747 ": Members marked as Overridable or Overrides can not be Private");
1752 if ((flags & Modifiers.SEALED) != 0){
1753 if ((flags & Modifiers.OVERRIDE) == 0){
1756 ": cannot be sealed because it is not an override");
1760 if ((flags & Modifiers.NEW) != 0){
1761 if ((flags & Modifiers.SHADOWS) != 0){
1764 " 'Overloads' and 'Shadows' cannot be combined ");
1772 // Access level of a type.
1775 ProtectedInternal = 1,
1781 // Check whether `flags' denotes a more restricted access than `level'
1782 // and return the new level.
1783 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1785 AccessLevel old_level = level;
1787 if ((flags & Modifiers.INTERNAL) != 0) {
1788 if ((flags & Modifiers.PROTECTED) != 0) {
1789 if ((int) level < (int) AccessLevel.ProtectedInternal)
1790 level = AccessLevel.ProtectedInternal;
1792 if ((int) level < (int) AccessLevel.Internal)
1793 level = AccessLevel.Internal;
1795 } else if ((flags & Modifiers.PROTECTED) != 0) {
1796 if ((int) level < (int) AccessLevel.Protected)
1797 level = AccessLevel.Protected;
1798 } else if ((flags & Modifiers.PRIVATE) != 0)
1799 level = AccessLevel.Private;
1804 // Return the access level for a new member which is defined in the current
1805 // TypeContainer with access modifiers `flags'.
1806 AccessLevel GetAccessLevel (int flags)
1808 if ((flags & Modifiers.PRIVATE) != 0)
1809 return AccessLevel.Private;
1812 if (!IsTopLevel && (Parent != null))
1813 level = Parent.GetAccessLevel (flags);
1815 level = AccessLevel.Public;
1817 return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1820 // Return the access level for type `t', but don't give more access than `flags'.
1821 static AccessLevel GetAccessLevel (Type t, int flags)
1823 if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1824 return AccessLevel.Private;
1827 if (TypeManager.IsBuiltinType (t))
1828 return AccessLevel.Public;
1829 else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1830 level = GetAccessLevel (t.DeclaringType, flags);
1832 level = CheckAccessLevel (AccessLevel.Public, flags);
1835 if (t.IsNestedPublic)
1838 if (t.IsNestedAssembly || t.IsNotPublic) {
1839 if ((int) level < (int) AccessLevel.Internal)
1840 level = AccessLevel.Internal;
1843 if (t.IsNestedFamily) {
1844 if ((int) level < (int) AccessLevel.Protected)
1845 level = AccessLevel.Protected;
1848 if (t.IsNestedFamORAssem) {
1849 if ((int) level < (int) AccessLevel.ProtectedInternal)
1850 level = AccessLevel.ProtectedInternal;
1857 // Returns true if `parent' is as accessible as the flags `flags'
1858 // given for this member.
1860 public bool AsAccessible (Type parent, int flags)
1862 while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1863 parent = parent.GetElementType ();
1865 AccessLevel level = GetAccessLevel (flags);
1866 AccessLevel level2 = GetAccessLevel (parent, flags);
1868 return (int) level >= (int) level2;
1871 Hashtable builder_and_args;
1873 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1875 if (builder_and_args == null)
1876 builder_and_args = new Hashtable ();
1881 /// Performs checks for an explicit interface implementation. First it
1882 /// checks whether the `interface_type' is a base inteface implementation.
1883 /// Then it checks whether `name' exists in the interface type.
1885 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1889 if (ifaces != null){
1890 foreach (Type t in ifaces){
1891 if (t == interface_type){
1899 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1906 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1908 Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1915 string IMemberContainer.Name {
1921 Type IMemberContainer.Type {
1927 IMemberContainer IMemberContainer.Parent {
1929 return parent_container;
1933 MemberCache IMemberContainer.MemberCache {
1935 return member_cache;
1939 bool IMemberContainer.IsInterface {
1945 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1947 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1951 // Operator pair checking
1954 class OperatorEntry {
1956 public Type ret_type;
1957 public Type type1, type2;
1959 public Operator.OpType ot;
1961 public OperatorEntry (int f, Operator o)
1965 ret_type = o.OperatorMethod.GetReturnType ();
1966 Type [] pt = o.OperatorMethod.ParameterTypes;
1970 ot = o.OperatorType;
1973 public override int GetHashCode ()
1975 return ret_type.GetHashCode ();
1978 public override bool Equals (object o)
1980 OperatorEntry other = (OperatorEntry) o;
1982 if (other.ret_type != ret_type)
1984 if (other.type1 != type1)
1986 if (other.type2 != type2)
1993 // Checks that some operators come in pairs:
1998 // They are matched based on the return type and the argument types
2000 void CheckPairedOperators ()
2002 Hashtable pairs = new Hashtable (null, null);
2004 // Register all the operators we care about.
2005 foreach (Operator op in operators){
2008 switch (op.OperatorType){
2009 case Operator.OpType.Equality:
2011 case Operator.OpType.Inequality:
2014 case Operator.OpType.GreaterThan:
2016 case Operator.OpType.LessThan:
2019 case Operator.OpType.GreaterThanOrEqual:
2021 case Operator.OpType.LessThanOrEqual:
2027 OperatorEntry oe = new OperatorEntry (reg, op);
2029 object o = pairs [oe];
2033 oe = (OperatorEntry) o;
2039 // Look for the mistakes.
2041 foreach (DictionaryEntry de in pairs){
2042 OperatorEntry oe = (OperatorEntry) de.Key;
2049 case Operator.OpType.Equality:
2052 case Operator.OpType.Inequality:
2055 case Operator.OpType.GreaterThan:
2058 case Operator.OpType.LessThan:
2061 case Operator.OpType.GreaterThanOrEqual:
2064 case Operator.OpType.LessThanOrEqual:
2068 Report.Error (216, oe.op.Location,
2069 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2076 public class Class : TypeContainer {
2078 // Modifiers allowed in a class declaration
2080 public const int AllowedModifiers =
2083 Modifiers.PROTECTED |
2084 Modifiers.INTERNAL |
2086 Modifiers.ABSTRACT |
2089 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2090 : base (parent, name, l)
2094 if (parent.Parent == null)
2095 accmods = Modifiers.INTERNAL;
2097 accmods = Modifiers.PUBLIC;
2099 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2100 this.attributes = attrs;
2104 // FIXME: How do we deal with the user specifying a different
2107 public override TypeAttributes TypeAttr {
2109 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2114 public class Struct : TypeContainer {
2116 // Modifiers allowed in a struct declaration
2118 public const int AllowedModifiers =
2121 Modifiers.PROTECTED |
2122 Modifiers.INTERNAL |
2126 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2127 : base (parent, name, l)
2131 if (parent.Parent == null)
2132 accmods = Modifiers.INTERNAL;
2134 accmods = Modifiers.PUBLIC;
2136 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2138 this.ModFlags |= Modifiers.SEALED;
2139 this.attributes = attrs;
2144 // FIXME: Allow the user to specify a different set of attributes
2145 // in some cases (Sealed for example is mandatory for a class,
2146 // but what SequentialLayout can be changed
2148 public override TypeAttributes TypeAttr {
2150 return base.TypeAttr |
2151 TypeAttributes.SequentialLayout |
2152 TypeAttributes.Sealed |
2153 TypeAttributes.BeforeFieldInit;
2158 public abstract class MethodCore : MemberBase {
2159 public /* readonly */ Parameters Parameters;
2163 // Parameters, cached for semantic analysis.
2165 protected InternalParameters parameter_info;
2166 protected Type [] parameter_types;
2168 public MethodCore (Expression type, int mod, int allowed_mod, string name,
2169 Attributes attrs, Parameters parameters, Location loc)
2170 : base (type, mod, allowed_mod, name, attrs, loc)
2172 Parameters = parameters;
2176 // Returns the System.Type array for the parameters of this method
2178 public Type [] ParameterTypes {
2180 return parameter_types;
2184 public InternalParameters ParameterInfo
2187 return parameter_info;
2191 public Block Block {
2201 protected virtual bool DoDefineParameters (TypeContainer parent)
2203 // Check if arguments were correct
2204 parameter_types = Parameters.GetParameterInfo (parent);
2205 if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
2208 parameter_info = new InternalParameters (parent, Parameters);
2213 public CallingConventions GetCallingConvention (bool is_class)
2215 CallingConventions cc = 0;
2217 cc = Parameters.GetCallingConvention ();
2220 if ((ModFlags & Modifiers.STATIC) == 0)
2221 cc |= CallingConventions.HasThis;
2223 // FIXME: How is `ExplicitThis' used in C#?
2228 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
2230 LabelParameters (ec, parameters, builder, null);
2233 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder, Parameters p_params)
2236 // Define each type attribute (in/out/ref) and
2237 // the argument names.
2239 Parameter [] p = p_params == null ? Parameters.FixedParameters : p_params.FixedParameters;
2242 MethodBuilder mb = null;
2243 ConstructorBuilder cb = null;
2245 if (builder is MethodBuilder)
2246 mb = (MethodBuilder) builder;
2248 cb = (ConstructorBuilder) builder;
2251 for (i = 0; i < p.Length; i++) {
2252 ParameterBuilder pb;
2255 pb = cb.DefineParameter (
2256 i + 1, p [i].Attributes, p [i].Name);
2258 pb = mb.DefineParameter (
2259 i + 1, p [i].Attributes, p [i].Name);
2261 Attributes attr = p [i].OptAttributes;
2263 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
2267 if (Parameters.ArrayParameter != null){
2268 ParameterBuilder pb;
2269 Parameter array_param = Parameters.ArrayParameter;
2272 pb = cb.DefineParameter (
2273 i + 1, array_param.Attributes,
2276 pb = mb.DefineParameter (
2277 i + 1, array_param.Attributes,
2280 CustomAttributeBuilder a = new CustomAttributeBuilder (
2281 TypeManager.cons_param_array_attribute, new object [0]);
2283 pb.SetCustomAttribute (a);
2288 public class Method : MethodCore {
2289 public MethodBuilder MethodBuilder;
2290 public MethodData MethodData;
2293 /// Modifiers allowed in a class declaration
2295 const int AllowedModifiers =
2298 Modifiers.PROTECTED |
2299 Modifiers.INTERNAL |
2303 Modifiers.NONVIRTUAL |
2304 Modifiers.OVERRIDE |
2305 Modifiers.ABSTRACT |
2311 // return_type can be "null" for VOID values.
2313 public Method (Expression return_type, int mod, string name, Parameters parameters,
2314 Attributes attrs, Location l)
2315 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2320 public Method (Expression return_type, int mod, string name, Parameters parameters,
2321 Attributes attrs, Expression impl_what, Location l)
2322 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2324 Implements = impl_what;
2328 // Returns the `System.Type' for the ReturnType of this
2329 // function. Provides a nice cache. (used between semantic analysis
2330 // and actual code generation
2332 public Type GetReturnType ()
2337 // Whether this is an operator method.
2338 public bool IsOperator;
2340 void DuplicateEntryPoint (MethodInfo b, Location location)
2344 "Program `" + CodeGen.FileName +
2345 "' has more than one entry point defined: `" +
2346 TypeManager.MonoBASIC_Signature(b) + "'");
2349 void Report28 (MethodInfo b)
2351 if (RootContext.WarningLevel < 4)
2356 "`" + TypeManager.MonoBASIC_Signature(b) +
2357 "' has the wrong signature to be an entry point");
2360 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2362 if (b.ReturnType != TypeManager.void_type &&
2363 b.ReturnType != TypeManager.int32_type)
2366 if (pinfo.Count == 0)
2369 if (pinfo.Count > 1)
2372 Type t = pinfo.ParameterType(0);
2374 (t.GetArrayRank() == 1) &&
2375 (t.GetElementType() == TypeManager.string_type) &&
2376 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2383 // Checks our base implementation if any
2385 protected override bool CheckBase (TypeContainer parent)
2387 // Check whether arguments were correct.
2388 if (!DoDefineParameters (parent))
2391 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2395 mi_this = TypeContainer.FindMembers (
2396 parent.TypeBuilder, MemberTypes.Method,
2397 BindingFlags.NonPublic | BindingFlags.Public |
2398 BindingFlags.Static | BindingFlags.Instance |
2399 BindingFlags.DeclaredOnly,
2400 MethodSignature.method_signature_filter, ms);
2402 if (mi_this.Count > 0) {
2403 Report.Error (111, Location, "Class `" + parent.Name + "' " +
2404 "already defines a member called `" + Name + "' " +
2405 "with the same parameter types");
2411 // Verify if the parent has a type with the same name, and then
2412 // check whether we have to create a new slot for it or not.
2414 Type ptype = parent.TypeBuilder.BaseType;
2416 // ptype is only null for System.Object while compiling corlib.
2418 MemberList mi, mi_static, mi_instance;
2420 mi_static = TypeContainer.FindMembers (
2421 ptype, MemberTypes.Method,
2422 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2423 MethodSignature.inheritable_method_signature_filter, ms);
2425 mi_instance = TypeContainer.FindMembers (
2426 ptype, MemberTypes.Method,
2427 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2428 MethodSignature.inheritable_method_signature_filter,
2431 if (mi_instance.Count > 0){
2433 } else if (mi_static.Count > 0)
2438 if (mi != null && mi.Count > 0){
2439 parent_method = (MethodInfo) mi [0];
2440 string name = parent_method.DeclaringType.Name + "." +
2443 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2446 if ((ModFlags & Modifiers.NEW) == 0) {
2447 Type parent_ret = TypeManager.TypeToCoreType (
2448 parent_method.ReturnType);
2450 if (parent_ret != MemberType) {
2452 508, parent.MakeName (Name) + ": cannot " +
2453 "change return type when overriding " +
2454 "inherited member " + name);
2459 /*if ((ModFlags & Modifiers.NEW) != 0)
2460 WarningNotHiding (parent);*/
2462 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2463 Report.Error (30284, Location,
2464 parent.MakeName (Name) +
2465 " : No suitable methods found to override");
2467 if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0)
\r
2469 if ((ModFlags & Modifiers.NONVIRTUAL) != 0)
\r
2471 Report.Error (31088, Location,
2472 parent.MakeName (Name) + " : Cannot " +
2473 "be declared NotOverridable since this method is " +
2474 "not maked as Overrides");
2477 // if a member of module is not inherited from Object class
2478 // can not be declared protected
2479 if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
2480 Report.Error (31066, Location,
2481 "'Sub' or 'Function' inside a 'Module' can not be declared as " +
2482 "'Protected' or 'Protected Friend'");
2485 /* else if ((ModFlags & Modifiers.NEW) != 0)
2486 WarningNotHiding (parent);
2495 public override bool Define (TypeContainer parent)
2497 if (!DoDefine (parent))
2500 if (!CheckBase (parent))
2503 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
2504 Report.Error (31067, Location,
2505 "'Sub' or 'Function' inside a 'Structure' can not be declared as " +
2506 "'Protected' or 'Protected Friend'");
2508 CallingConventions cc = GetCallingConvention (parent is Class);
2510 MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2511 ParameterInfo, cc, OptAttributes,
2512 ModFlags, flags, true);
2514 if (!MethodData.Define (parent))
2517 MethodBuilder = MethodData.MethodBuilder;
2520 // This is used to track the Entry Point,
2522 if (Name.ToUpper() == "MAIN" &&
2523 ((ModFlags & Modifiers.STATIC) != 0) &&
2524 (RootContext.MainClass == null ||
2525 RootContext.MainClass == parent.TypeBuilder.FullName ||
2526 (RootContext.RootNamespace != null &&
2527 RootContext.RootNamespace.Length > 0 &&
2528 (RootContext.RootNamespace + "." + RootContext.MainClass) == parent.TypeBuilder.FullName))) {
2529 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2530 if (RootContext.EntryPoint == null) {
2531 RootContext.EntryPoint = MethodBuilder;
2532 RootContext.EntryPointLocation = Location;
2534 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2535 DuplicateEntryPoint (MethodBuilder, Location);
2538 Report28(MethodBuilder);
2547 public void Emit (TypeContainer parent)
2549 MethodData.Emit (parent, Block, this);
2553 public abstract class ConstructorInitializer {
2554 ArrayList argument_list;
2555 ConstructorInfo parent_constructor;
2556 Parameters parameters;
2558 public bool implicit_initialization;
2560 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2563 this.argument_list = argument_list;
2564 this.parameters = parameters;
2566 this.implicit_initialization = false;
2569 public ArrayList Arguments {
2571 return argument_list;
2575 public ConstructorInfo ParentConstructor
2579 return parent_constructor;
2583 public bool Resolve (EmitContext ec)
2585 Expression parent_constructor_group;
2588 ec.CurrentBlock = new Block (null, true, parameters);
2590 if (argument_list != null){
2591 foreach (Argument a in argument_list){
2592 if (!a.Resolve (ec, loc))
2597 ec.CurrentBlock = null;
2599 if (this is ConstructorBaseInitializer) {
2600 if (ec.ContainerType.BaseType == null)
2603 t = ec.ContainerType.BaseType;
2604 if (ec.ContainerType.IsValueType){
2605 Report.Error (522, loc,
2606 "structs cannot call base class constructors");
2611 t = ec.ContainerType;
2613 parent_constructor_group = Expression.MemberLookup (
2615 MemberTypes.Constructor,
2616 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2619 if (parent_constructor_group == null){
2620 Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
2624 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2625 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2627 if (parent_constructor == null) {
2628 if (this.implicit_initialization)
2629 Report.Error (30148, loc, "Must declare 'MyBase.New' in the constructor " +
\r
2630 "of the class '" + ec.TypeContainer.Name + "' with appropriate arguments, since the base class '" +
\r
2631 t.FullName + "' does not contain a definition of 'New' without any parameter");
2633 Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
2641 public void Emit (EmitContext ec)
2643 if (parent_constructor != null){
2645 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2647 Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2654 public class ConstructorBaseInitializer : ConstructorInitializer {
2655 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2656 base (argument_list, pars, l)
2661 public class ConstructorThisInitializer : ConstructorInitializer {
2662 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2663 base (argument_list, pars, l)
2668 public class Constructor : MethodCore {
2669 public ConstructorBuilder ConstructorBuilder;
2670 public ConstructorInitializer Initializer;
2671 new public Attributes OptAttributes;
2674 // Modifiers allowed for a constructor.
2676 public const int AllowedModifiers =
2678 Modifiers.PROTECTED |
2679 Modifiers.INTERNAL |
2686 // The spec claims that static is not permitted, but
2687 // my very own code has static constructors.
2689 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2690 : base (null, 0, AllowedModifiers, name, null, args, l)
2696 // Returns true if this is a default constructor
2698 public bool IsDefault ()
2700 if ((ModFlags & Modifiers.STATIC) != 0)
2701 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2702 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2705 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2706 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2707 (Initializer is ConstructorBaseInitializer) &&
2708 (Initializer.Arguments == null);
2712 // Creates the ConstructorBuilder
2714 public override bool Define (TypeContainer parent)
2716 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2717 MethodAttributes.SpecialName);
2719 // Check if arguments were correct.
2720 if (!DoDefineParameters (parent))
2723 if ((ModFlags & Modifiers.STATIC) != 0) {
2724 ca |= MethodAttributes.Static;
2726 if (this.Parameters != Parameters.EmptyReadOnlyParameters)
2729 "Shared constructor can not have parameters");
2731 if ((ModFlags & Modifiers.Accessibility) != 0)
2734 "Shared constructor can not be declared " +
2735 "explicitly as public, private, friend or protected");
2737 if (this.Initializer != null)
2740 "Keywords like MyBase, MyClass, Me are not " +
2741 "valid inside a Shared Constructor");
2744 if (parent is Struct && ParameterTypes.Length == 0) {
2747 "Structs can not contain explicit parameterless " +
2751 ca |= MethodAttributes.HideBySig;
2753 if ((ModFlags & Modifiers.PUBLIC) != 0)
2754 ca |= MethodAttributes.Public;
2755 else if ((ModFlags & Modifiers.PROTECTED) != 0) {
2756 if ((ModFlags & Modifiers.INTERNAL) != 0)
2757 ca |= MethodAttributes.FamORAssem;
2759 ca |= MethodAttributes.Family;
2761 else if ((ModFlags & Modifiers.INTERNAL) != 0)
2762 ca |= MethodAttributes.Assembly;
2763 else if (IsDefault ())
2764 ca |= MethodAttributes.Public;
2766 ca |= MethodAttributes.Private;
2769 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2770 ca, GetCallingConvention (parent is Class), ParameterTypes);
2773 // HACK because System.Reflection.Emit is lame
2775 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2778 "Class `" +parent.Name+ "' already contains a definition with the " +
2779 "same return value and parameter types for constructor `" + Name
2790 public void Emit (TypeContainer parent)
2792 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2793 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2795 if ((ModFlags & Modifiers.STATIC) == 0){
2796 if (parent is Class && Initializer == null) {
2797 Initializer = new ConstructorBaseInitializer (
2798 null, Parameters.EmptyReadOnlyParameters, parent.Location);
2799 Initializer.implicit_initialization = true;
2803 // Spec mandates that Initializers will not have
2807 if (Initializer != null && !Initializer.Resolve (ec))
2809 ec.IsStatic = false;
2812 LabelParameters (ec, ParameterTypes, ConstructorBuilder);
2815 // Classes can have base initializers and instance field initializers.
2817 if (parent is Class){
2818 if ((ModFlags & Modifiers.STATIC) == 0)
2819 parent.EmitFieldInitializers (ec);
2822 if (Initializer != null) {
2823 if (this.ConstructorBuilder.Equals (Initializer.ParentConstructor))
2826 "A constructor can not call itself" );
2828 Initializer.Emit (ec);
2831 if ((ModFlags & Modifiers.STATIC) != 0)
2832 parent.EmitFieldInitializers (ec);
2834 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2836 // If this is a non-static `struct' constructor and doesn't have any
2837 // initializer, it must initialize all of the struct's fields.
2838 if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2839 (Initializer == null))
2840 Block.AddThisVariable (parent, Location);
2842 ec.EmitTopBlock (Block, ParameterInfo, Location);
2846 public class MethodData {
2848 // The return type of this method
2850 public readonly Type ReturnType;
2851 public readonly Type[] ParameterTypes;
2852 public readonly InternalParameters ParameterInfo;
2853 public readonly CallingConventions CallingConventions;
2854 public readonly Attributes OptAttributes;
2855 public readonly Location Location;
2858 // Are we implementing an interface ?
2860 public bool IsImplementing = false;
2865 protected MemberBase member;
2866 protected int modifiers;
2867 protected MethodAttributes flags;
2868 protected bool is_method;
2869 protected string accessor_name;
2870 ArrayList conditionals;
2872 MethodBuilder builder = null;
2873 public MethodBuilder MethodBuilder {
2879 public MethodData (MemberBase member, string name, Type return_type,
2880 Type [] parameter_types, InternalParameters parameters,
2881 CallingConventions cc, Attributes opt_attrs,
2882 int modifiers, MethodAttributes flags, bool is_method)
2884 this.member = member;
2885 this.accessor_name = name;
2886 this.ReturnType = return_type;
2887 this.ParameterTypes = parameter_types;
2888 this.ParameterInfo = parameters;
2889 this.CallingConventions = cc;
2890 this.OptAttributes = opt_attrs;
2891 this.modifiers = modifiers;
2893 this.is_method = is_method;
2894 this.Location = member.Location;
2895 this.conditionals = new ArrayList ();
2901 Attribute dllimport_attribute = null;
2902 string obsolete = null;
2903 bool obsolete_error = false;
2905 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2907 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2910 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2911 if (asec.Attributes == null)
2914 foreach (Attribute a in asec.Attributes) {
2915 if (a.Name == "Conditional") {
2916 if (!ApplyConditionalAttribute (a))
2918 } else if (a.Name == "Obsolete") {
2919 if (!ApplyObsoleteAttribute (a))
2921 } else if (a.Name.IndexOf ("DllImport") != -1) {
2923 a.Type = TypeManager.dllimport_type;
2924 Attribute.Error_AttributeNotValidForElement (a, Location);
2927 if (!ApplyDllImportAttribute (a))
2937 // Applies the `DllImport' attribute to the method.
2939 protected virtual bool ApplyDllImportAttribute (Attribute a)
2941 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2942 if ((modifiers & extern_static) != extern_static) {
2943 Report.Error (601, Location,
2944 "The DllImport attribute must be specified on a method " +
2945 "marked `static' and `extern'.");
2949 flags |= MethodAttributes.PinvokeImpl;
2950 dllimport_attribute = a;
2955 // Applies the `Obsolete' attribute to the method.
2957 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2959 if (obsolete != null) {
2960 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2964 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2965 return obsolete != null;
2969 // Applies the `Conditional' attribute to the method.
2971 protected virtual bool ApplyConditionalAttribute (Attribute a)
2973 // The Conditional attribute is only valid on methods.
2975 Attribute.Error_AttributeNotValidForElement (a, Location);
2979 string condition = a.Conditional_GetConditionName ();
2981 if (condition == null)
2984 if (ReturnType != TypeManager.void_type) {
2985 Report.Error (578, Location,
2986 "Conditional not valid on `" + member.Name + "' " +
2987 "because its return type is not void");
2991 if ((modifiers & Modifiers.OVERRIDE) != 0) {
2992 Report.Error (243, Location,
2993 "Conditional not valid on `" + member.Name + "' " +
2994 "because it is an override method");
2998 if (member.IsExplicitImpl) {
2999 Report.Error (577, Location,
3000 "Conditional not valid on `" + member.Name + "' " +
3001 "because it is an explicit interface implementation");
3005 if (IsImplementing) {
3006 Report.Error (623, Location,
3007 "Conditional not valid on `" + member.Name + "' " +
3008 "because it is an interface method");
3012 conditionals.Add (condition);
3018 // Checks whether this method should be ignored due to its Conditional attributes.
3020 bool ShouldIgnore (Location loc)
3022 // When we're overriding a virtual method, we implicitly inherit the
3023 // Conditional attributes from our parent.
3024 if (member.ParentMethod != null) {
3025 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3026 member.ParentMethod, loc);
3028 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3032 foreach (string condition in conditionals)
3033 if (RootContext.AllDefines [condition] == null)
3040 // Returns the TypeManager.MethodFlags for this method.
3041 // This emits an error 619 / warning 618 if the method is obsolete.
3042 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3044 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3046 TypeManager.MethodFlags flags = 0;
3048 if (obsolete != null) {
3049 if (obsolete_error) {
3050 Report.Error (619, loc, "Method `" + member.Name +
3051 "' is obsolete: `" + obsolete + "'");
3052 return TypeManager.MethodFlags.IsObsoleteError;
3054 Report.Warning (618, loc, "Method `" + member.Name +
3055 "' is obsolete: `" + obsolete + "'");
3057 flags |= TypeManager.MethodFlags.IsObsolete;
3060 if (ShouldIgnore (loc))
3061 flags |= TypeManager.MethodFlags.ShouldIgnore;
3066 public virtual bool Define (TypeContainer parent)
3068 MethodInfo implementing = null;
3069 string method_name, name, prefix;
3071 if (OptAttributes != null)
3072 if (!ApplyAttributes (OptAttributes, is_method))
3075 if (member.IsExplicitImpl)
3076 prefix = member.InterfaceType.FullName + ".";
3080 if (accessor_name != null)
3081 name = accessor_name + "_" + member.ShortName;
3083 name = member.ShortName;
3084 method_name = prefix + name;
3086 if (parent.Pending != null){
3087 if (member is Indexer)
3088 implementing = parent.Pending.IsInterfaceIndexer (
3089 member.InterfaceType, ReturnType, ParameterTypes);
3091 implementing = parent.Pending.IsInterfaceMethod (
3092 member.InterfaceType, name, ReturnType, ParameterTypes);
3094 if (member.InterfaceType != null && implementing == null){
3095 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
3102 // For implicit implementations, make sure we are public, for
3103 // explicit implementations, make sure we are private.
3105 if (implementing != null){
3107 // Setting null inside this block will trigger a more
3108 // verbose error reporting for missing interface implementations
3110 // The "candidate" function has been flagged already
3111 // but it wont get cleared
3113 if (!member.IsExplicitImpl){
3115 // We already catch different accessibility settings
3116 // so we just need to check that we are not private
3118 if ((modifiers & Modifiers.PRIVATE) != 0)
3119 implementing = null;
3122 // Static is not allowed
3124 if ((modifiers & Modifiers.STATIC) != 0)
3125 implementing = null;
3127 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3128 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3129 implementing = null;
3135 // If implementing is still valid, set flags
3137 if (implementing != null){
3139 // When implementing interface methods, set NewSlot.
3141 if (implementing.DeclaringType.IsInterface)
3142 flags |= MethodAttributes.NewSlot;
3145 MethodAttributes.Virtual |
3146 MethodAttributes.HideBySig;
3148 // Get the method name from the explicit interface.
3149 if (member.InterfaceType != null) {
3150 name = implementing.Name;
3151 method_name = prefix + name;
3154 IsImplementing = true;
3158 // Create the MethodBuilder for the method
3160 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3161 if ((modifiers & Modifiers.STATIC) == 0) {
3162 Report.Error (601, Location,
3163 "The DllImport attribute must be specified on " +
3164 "a method marked 'static' and 'extern'.");
3168 EmitContext ec = new EmitContext (
3169 parent, Location, null, ReturnType, modifiers);
3171 builder = dllimport_attribute.DefinePInvokeMethod (
3172 ec, parent.TypeBuilder, method_name, flags,
3173 ReturnType, ParameterTypes);
3175 builder = parent.TypeBuilder.DefineMethod (
3176 method_name, flags, CallingConventions,
3177 ReturnType, ParameterTypes);
3179 if (builder == null)
3182 if (IsImplementing) {
3184 // clear the pending implemntation flag
3186 if (member is Indexer) {
3187 parent.Pending.ImplementIndexer (
3188 member.InterfaceType, builder, ReturnType,
3189 ParameterTypes, true);
3191 parent.Pending.ImplementMethod (
3192 member.InterfaceType, name, ReturnType,
3193 ParameterTypes, member.IsExplicitImpl);
3195 if (member.IsExplicitImpl)
3196 parent.TypeBuilder.DefineMethodOverride (
3197 builder, implementing);
3200 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3201 Report.Error (111, Location,
3202 "Class `" + parent.Name +
3203 "' already contains a definition with the " +
3204 "same return value and parameter types as the " +
3205 "'get' method of property `" + member.Name + "'");
3209 TypeManager.AddMethod (builder, this);
3217 public virtual void Emit (TypeContainer parent, Block block, object kind)
3222 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3223 ig = builder.GetILGenerator ();
3227 ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3229 if (OptAttributes != null)
3230 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
3232 if (member is MethodCore)
3233 ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder);
3236 // abstract or extern methods have no bodies
3238 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3243 // abstract or extern methods have no bodies.
3245 if ((modifiers & Modifiers.ABSTRACT) != 0)
3247 500, Location, "Abstract method `" +
3248 TypeManager.MonoBASIC_Signature (builder) +
3249 "' can not have a body");
3251 if ((modifiers & Modifiers.EXTERN) != 0)
3253 179, Location, "External method `" +
3254 TypeManager.MonoBASIC_Signature (builder) +
3255 "' can not have a body");
3261 // Methods must have a body unless they're extern or abstract
3263 if (block == null) {
3265 501, Location, "Method `" +
3266 TypeManager.MonoBASIC_Signature (builder) +
3267 "' must declare a body since it is not marked " +
3268 "abstract or extern");
3273 // Handle destructors specially
3275 // FIXME: This code generates buggy code
3277 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3278 EmitDestructor (ec, block);
3280 ISymbolWriter sw = CodeGen.SymbolWriter;
3282 if ((sw != null) && !Location.IsNull (Location) &&
3283 !Location.IsNull (block.EndLocation)) {
3284 Location end = block.EndLocation;
3285 MethodToken token = MethodBuilder.GetToken ();
3286 sw.OpenMethod (new SymbolToken (token.Token));
3287 // Avoid error if we don't support debugging for the platform
3289 sw.SetMethodSourceRange (Location.SymbolDocument,
3293 } catch (Exception) {
3296 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3300 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3304 void EmitDestructor (EmitContext ec, Block block)
3306 ILGenerator ig = ec.ig;
3308 Label finish = ig.DefineLabel ();
3309 bool old_in_try = ec.InTry;
3311 ig.BeginExceptionBlock ();
3313 ec.ReturnLabel = finish;
3314 ec.HasReturnLabel = true;
3315 ec.EmitTopBlock (block, null, Location);
3316 ec.InTry = old_in_try;
3318 // ig.MarkLabel (finish);
3319 bool old_in_finally = ec.InFinally;
3320 ec.InFinally = true;
3321 ig.BeginFinallyBlock ();
3323 if (ec.ContainerType.BaseType != null) {
3324 Expression member_lookup = Expression.MemberLookup (
3325 ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
3326 MemberTypes.Method, Expression.AllBindingFlags, Location);
3328 if (member_lookup != null){
3329 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3331 ig.Emit (OpCodes.Ldarg_0);
3332 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3335 ec.InFinally = old_in_finally;
3337 ig.EndExceptionBlock ();
3338 //ig.MarkLabel (ec.ReturnLabel);
3339 ig.Emit (OpCodes.Ret);
3343 abstract public class MemberBase : MemberCore {
3344 public Expression Type;
3345 public readonly Attributes OptAttributes;
3346 public Expression Implements;
3348 protected MethodAttributes flags;
3351 // The "short" name of this property / indexer / event. This is the
3352 // name without the explicit interface.
3354 public string ShortName;
3357 // The type of this property / indexer / event
3359 public Type MemberType;
3362 // If true, this is an explicit interface implementation
3364 public bool IsExplicitImpl = false;
3367 // The name of the interface we are explicitly implementing
3369 public string ExplicitInterfaceName = null;
3372 // If true, the interface type we are explicitly implementing
3374 public Type InterfaceType = null;
3377 // The method we're overriding if this is an override method.
3379 protected MethodInfo parent_method = null;
3380 public MethodInfo ParentMethod {
3382 return parent_method;
3387 // The constructor is only exposed to our children
3389 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3390 Attributes attrs, Location loc)
3394 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PUBLIC, loc);
3395 OptAttributes = attrs;
3398 protected virtual bool CheckBase (TypeContainer parent)
3403 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3407 foreach (Type partype in parameters){
3408 if (partype.IsPointer && !UnsafeOK (parent))
3411 if (parent.AsAccessible (partype, ModFlags))
3414 if (this is Indexer)
3415 Report.Error (55, Location,
3416 "Inconsistent accessibility: parameter type `" +
3417 TypeManager.MonoBASIC_Name (partype) + "' is less " +
3418 "accessible than indexer `" + Name + "'");
3420 Report.Error (51, Location,
3421 "Inconsistent accessibility: parameter type `" +
3422 TypeManager.MonoBASIC_Name (partype) + "' is less " +
3423 "accessible than method `" + Name + "'");
3430 protected virtual bool DoDefine (TypeContainer parent)
3435 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3438 flags = Modifiers.MethodAttr (ModFlags);
3440 // Lookup Type, verify validity
3441 MemberType = parent.ResolveType (Type, false, Location);
3442 if (MemberType == null)
3445 // verify accessibility
3446 if (!parent.AsAccessible (MemberType, ModFlags)) {
3447 if (this is Property)
3448 Report.Error (53, Location,
3449 "Inconsistent accessibility: property type `" +
3450 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3451 "accessible than property `" + Name + "'");
3452 else if (this is Indexer)
3453 Report.Error (54, Location,
3454 "Inconsistent accessibility: indexer return type `" +
3455 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3456 "accessible than indexer `" + Name + "'");
3457 else if (this is Method)
3458 Report.Error (50, Location,
3459 "Inconsistent accessibility: return type `" +
3460 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3461 "accessible than method `" + Name + "'");
3463 Report.Error (52, Location,
3464 "Inconsistent accessibility: field type `" +
3465 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3466 "accessible than field `" + Name + "'");
3470 if (MemberType.IsPointer && !UnsafeOK (parent))
3474 // Check for explicit interface implementation
3476 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
3477 int pos = Name.LastIndexOf (".");
3479 ExplicitInterfaceName = Name.Substring (0, pos);
3480 ShortName = Name.Substring (pos + 1);
3484 if (ExplicitInterfaceName != null) {
3485 InterfaceType = RootContext.LookupType (
3486 parent, ExplicitInterfaceName, false, Location);
3487 if (InterfaceType == null)
3490 // Compute the full name that we need to export.
3491 Name = InterfaceType.FullName + "." + ShortName;
3493 if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
3496 IsExplicitImpl = true;
3498 IsExplicitImpl = false;
3505 // Fields and Events both generate FieldBuilders, we use this to share
3506 // their common bits. This is also used to flag usage of the field
3508 abstract public class FieldBase : MemberBase {
3509 public FieldBuilder FieldBuilder;
3510 public Status status;
3513 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3516 // The constructor is only exposed to our children
3518 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3519 object init, Attributes attrs, Location loc)
3520 : base (type, mod, allowed_mod, name, attrs, loc)
3526 // Whether this field has an initializer.
3528 public bool HasInitializer {
3530 return init != null;
3535 readonly Object init;
3536 Expression init_expr;
3537 bool init_expr_initialized = false;
3540 // Resolves and returns the field initializer.
3542 public Expression GetInitializerExpression (EmitContext ec)
3544 if (init_expr_initialized)
3548 if (init is Expression)
3549 e = (Expression) init;
3551 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3553 ec.IsFieldInitializer = true;
3554 e = e.DoResolve (ec);
3555 ec.IsFieldInitializer = false;
3558 init_expr_initialized = true;
3566 // The Field class is used to represents class/struct fields during parsing.
3568 public class Field : FieldBase {
3570 // Modifiers allowed in a class declaration
3572 const int AllowedModifiers =
3575 Modifiers.PROTECTED |
3576 Modifiers.INTERNAL |
3579 // Modifiers.VOLATILE |
3580 // Modifiers.UNSAFE |
3583 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3584 Attributes attrs, Location loc)
3585 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3589 public override bool Define (TypeContainer parent)
3591 Type t = parent.ResolveType (Type, false, Location);
3596 if (!parent.AsAccessible (t, ModFlags)) {
3597 Report.Error (52, Location,
3598 "Inconsistent accessibility: field type `" +
3599 TypeManager.MonoBASIC_Name (t) + "' is less " +
3600 "accessible than field `" + Name + "'");
3604 if (t.IsPointer && !UnsafeOK (parent))
3607 Type ptype = parent.TypeBuilder.BaseType;
3609 // ptype is only null for System.Object while compiling corlib.
3611 MemberList list = TypeContainer.FindMembers (
3612 ptype, MemberTypes.Field,
3613 BindingFlags.Public |
3614 BindingFlags.Static | BindingFlags.Instance,
3615 System.Type.FilterName, Name);
3617 if (RootContext.WarningLevel > 1){
3618 if ((list.Count > 0) && ((ModFlags & Modifiers.SHADOWS) == 0))
\r
3622 "Variable '" + Name + "' should be declared " +
3623 "Shadows since the base type '" + ptype.Name +
3624 "' has a variable with same name");
3626 ModFlags |= Modifiers.SHADOWS;
3629 if (list.Count == 0)
3630 // if a member of module is not inherited from Object class
3631 // can not be declared protected
3632 if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
3633 Report.Error (30593, Location,
3634 "'Variable' inside a 'Module' can not be " +
3635 "declared as 'Protected'");
3638 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
3639 Report.Error (30435, Location,
3640 "'Variable' inside a 'Structure' can not be " +
3641 "declared as 'Protected'");
3643 if ((ModFlags & Modifiers.VOLATILE) != 0){
3645 if (TypeManager.IsEnumType (t))
3646 t = TypeManager.EnumToUnderlying (t);
3648 if (!((t == TypeManager.bool_type) ||
3649 (t == TypeManager.sbyte_type) ||
3650 (t == TypeManager.byte_type) ||
3651 (t == TypeManager.short_type) ||
3652 (t == TypeManager.ushort_type) ||
3653 (t == TypeManager.int32_type) ||
3654 (t == TypeManager.uint32_type) ||
3655 (t == TypeManager.char_type) ||
3656 (t == TypeManager.float_type))){
3658 677, Location, parent.MakeName (Name) +
3659 " A volatile field can not be of type `" +
3660 TypeManager.MonoBASIC_Name (t) + "'");
3666 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3668 if (parent is Struct &&
3669 ((fa & FieldAttributes.Static) == 0) &&
3670 t == parent.TypeBuilder &&
3671 !TypeManager.IsBuiltinType (t)){
3672 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name +
3673 "' causes a cycle in the structure layout");
3676 FieldBuilder = parent.TypeBuilder.DefineField (
3677 Name, t, Modifiers.FieldAttr (ModFlags));
3679 TypeManager.RegisterFieldBase (FieldBuilder, this);
3683 public void Emit (TypeContainer tc)
3685 EmitContext ec = new EmitContext (tc, Location, null,
3686 FieldBuilder.FieldType, ModFlags);
3688 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
3693 // `set' and `get' accessors are represented with an Accessor.
3695 public class Accessor {
3697 // Null if the accessor is empty, or a Block if not
3700 public Attributes OptAttributes;
3702 public Accessor (Block b, Attributes attrs)
3705 OptAttributes = attrs;
3710 // Properties and Indexers both generate PropertyBuilders, we use this to share
3711 // their common bits.
3713 abstract public class PropertyBase : MethodCore {
3714 public Accessor Get, Set;
3715 public PropertyBuilder PropertyBuilder;
3716 public MethodBuilder GetBuilder, SetBuilder;
3717 public MethodData GetData, SetData;
3719 protected EmitContext ec;
3721 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3722 Parameters parameters, Accessor get_block, Accessor set_block,
3723 Attributes attrs, Location loc)
3724 : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3730 protected override bool DoDefine (TypeContainer parent)
3732 if (!base.DoDefine (parent))
3735 ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3741 // Checks our base implementation if any
3743 protected override bool CheckBase (TypeContainer parent)
3745 // Check whether arguments were correct.
3746 if (!DoDefineParameters (parent))
3753 MethodSignature ms, base_ms;
3754 if (this is Indexer) {
3755 string name, base_name;
3757 report_name = "this";
3758 name = TypeManager.IndexerPropertyName (parent.TypeBuilder);
3759 ms = new MethodSignature (name, null, ParameterTypes);
3760 base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType);
3761 base_ms = new MethodSignature (base_name, null, ParameterTypes);
3764 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
3767 MemberList props_this;
3769 props_this = TypeContainer.FindMembers (
3770 parent.TypeBuilder, MemberTypes.Property,
3771 BindingFlags.NonPublic | BindingFlags.Public |
3772 BindingFlags.Static | BindingFlags.Instance |
3773 BindingFlags.DeclaredOnly,
3774 MethodSignature.method_signature_filter, ms);
3776 if (props_this.Count > 0) {
3777 Report.Error (111, Location, "Class `" + parent.Name + "' " +
3778 "already defines a member called `" + report_name + "' " +
3779 "with the same parameter types");
3784 // Find properties with the same name on the base class
3787 MemberList props_static = TypeContainer.FindMembers (
3788 parent.TypeBuilder.BaseType, MemberTypes.Property,
3789 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3790 MethodSignature.inheritable_property_signature_filter, base_ms);
3792 MemberList props_instance = TypeContainer.FindMembers (
3793 parent.TypeBuilder.BaseType, MemberTypes.Property,
3794 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3795 MethodSignature.inheritable_property_signature_filter,
3799 // Find if we have anything
3801 if (props_static.Count > 0)
3802 props = props_static;
3803 else if (props_instance.Count > 0)
3804 props = props_instance;
3810 // If we have something on the base.
3811 if (props != null && props.Count > 0){
3812 PropertyInfo pi = (PropertyInfo) props [0];
3814 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
3815 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
3817 MethodInfo reference = inherited_get == null ?
3818 inherited_set : inherited_get;
3820 if (reference != null) {
3821 string name = reference.DeclaringType.Name + "." + report_name;
3823 if (!CheckMethodAgainstBase (parent, flags, reference, name))
3827 if (((ModFlags & Modifiers.NEW) == 0) && (pi.PropertyType != MemberType)) {
3828 Report.Error (508, parent.MakeName (Name) + ": cannot " +
3829 "change return type when overriding inherited " +
3830 "member `" + pi.DeclaringType + "." + pi.Name + "'");
3834 /*if ((ModFlags & Modifiers.NEW) != 0)
3835 WarningNotHiding (parent);*/
3837 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3838 if (this is Indexer)
3839 Report.Error (115, Location,
3840 parent.MakeName (Name) +
3841 " no suitable indexers found to override");
3843 Report.Error (30284, Location,
3844 parent.MakeName (Name) +
3845 " no suitable properties found to override");
3852 public virtual void Emit (TypeContainer tc)
3855 // The PropertyBuilder can be null for explicit implementations, in that
3856 // case, we do not actually emit the ".property", so there is nowhere to
3857 // put the attribute
3859 if (PropertyBuilder != null)
3860 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3862 if (GetData != null)
3863 GetData.Emit (tc, Get.Block, Get);
3865 if (SetData != null)
3866 SetData.Emit (tc, Set.Block, Set);
3871 public class Property : PropertyBase {
3872 const int AllowedModifiers =
3875 Modifiers.PROTECTED |
3876 Modifiers.INTERNAL |
3880 Modifiers.OVERRIDE |
3881 Modifiers.ABSTRACT |
3886 Modifiers.READONLY |
3887 Modifiers.WRITEONLY |
3890 string set_parameter_name;
3891 Parameters get_params;
3892 Parameters set_params;
3894 public Property (Expression type, string name, int mod_flags,
3895 Accessor get_block, Accessor set_block,
3896 Attributes attrs, Location loc, string set_name,
3897 Parameters p_get, Parameters p_set, Expression impl_what)
3898 : base (type, name, mod_flags, AllowedModifiers,
3900 get_block, set_block, attrs, loc)
3902 set_parameter_name = set_name;
3905 Implements = impl_what;
3908 public Property (Expression type, string name, int mod_flags,
3909 Accessor get_block, Accessor set_block,
3910 Attributes attrs, Location loc)
3911 : this (type, name, mod_flags, get_block, set_block, attrs, loc,
3912 "Value", Parameters.EmptyReadOnlyParameters, Parameters.EmptyReadOnlyParameters, null)
3916 public override bool Define (TypeContainer parent)
3918 Type [] g_parameters=null, s_parameters=null;
3919 Parameter [] g_parms, s_parms;
3920 InternalParameters g_ip=null, s_ip=null;
3922 if (!DoDefine (parent))
3925 if (!CheckBase (parent))
3928 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3931 if ((ModFlags & Modifiers.WRITEONLY) == 0)
3934 "Property without 'Get' accessor must have a 'WriteOnly' modifier");
3937 if (get_params == Parameters.EmptyReadOnlyParameters)
3939 g_parameters = TypeManager.NoTypes;
3940 g_ip = new InternalParameters (
3941 parent, Parameters.EmptyReadOnlyParameters);
3945 g_parameters = new Type [get_params.FixedParameters.Length];
3946 for (int i = 0; i < get_params.FixedParameters.Length; i ++)
3948 g_parameters[i] = get_params.FixedParameters[i].ParameterType;
3950 g_parms = new Parameter [get_params.FixedParameters.Length];
3951 for (int i = 0; i < get_params.FixedParameters.Length; i ++)
3953 Parameter tp = get_params.FixedParameters[i];
3954 g_parms[i] = new Parameter (tp.TypeName, tp.Name,
3955 Parameter.Modifier.NONE, null);
3957 g_ip = new InternalParameters (
3958 parent, new Parameters (g_parms, null, Location));
3961 GetData = new MethodData (this, "get", MemberType,
3962 g_parameters, g_ip, CallingConventions.Standard,
3963 Get.OptAttributes, ModFlags, flags, false);
3965 if (!GetData.Define (parent))
3968 GetBuilder = GetData.MethodBuilder;
3972 if ((ModFlags & Modifiers.READONLY) == 0)
3975 "Property without 'Set' accessor must have a 'ReadOnly' modifier");
3980 if (set_params == Parameters.EmptyReadOnlyParameters)
3982 s_parameters = new Type [1];
3983 s_parameters [0] = MemberType;
3985 s_parms = new Parameter [1];
3986 s_parms [0] = new Parameter (Type, set_parameter_name,
3987 Parameter.Modifier.NONE, null);
3991 s_parameters = new Type [set_params.FixedParameters.Length];
3992 for (int i = 0; i < set_params.FixedParameters.Length; i ++)
3994 s_parameters[i] = set_params.FixedParameters[i].ParameterType;
3997 s_parms = new Parameter [set_params.FixedParameters.Length];
3998 for (int i = 0; i < set_params.FixedParameters.Length; i ++)
4000 Parameter tp = set_params.FixedParameters[i];
4001 s_parms[i] = new Parameter (tp.TypeName, tp.Name,
4002 Parameter.Modifier.NONE, null);
4006 s_ip = new InternalParameters (
4007 parent, new Parameters (s_parms, null, Location));
4009 SetData = new MethodData (this, "set", TypeManager.void_type,
4010 s_parameters, s_ip, CallingConventions.Standard,
4011 Set.OptAttributes, ModFlags, flags, false);
4013 if (!SetData.Define (parent))
4016 SetBuilder = SetData.MethodBuilder;
4017 SetBuilder.DefineParameter (1, ParameterAttributes.None,
4018 set_parameter_name);
4021 // FIXME - PropertyAttributes.HasDefault ?
4023 PropertyAttributes prop_attr =
4024 PropertyAttributes.RTSpecialName |
4025 PropertyAttributes.SpecialName;
4027 if (!IsExplicitImpl){
4028 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4029 Name, prop_attr, MemberType, null);
4031 PropertyBuilder.SetGetMethod (GetBuilder);
4032 PropertyBuilder.SetSetMethod (SetBuilder);
4035 // HACK for the reasons exposed above
4037 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4040 "Class `" + parent.Name +
4041 "' already contains a definition for the property `" +
4049 public override void Emit (TypeContainer tc)
4053 if (GetData != null)
4055 Parameters = get_params;
4056 GetData.Emit (tc, Get.Block, Get);
4059 if (SetData != null)
4061 Parameters = set_params;
4062 SetData.Emit (tc, Set.Block, Set);
4069 /// Gigantic workaround for lameness in SRE follows :
4070 /// This class derives from EventInfo and attempts to basically
4071 /// wrap around the EventBuilder so that FindMembers can quickly
4072 /// return this in it search for members
4074 public class MyEventBuilder : EventInfo {
4077 // We use this to "point" to our Builder which is
4078 // not really a MemberInfo
4080 EventBuilder MyBuilder;
4083 // We "catch" and wrap these methods
4085 MethodInfo raise, remove, add;
4087 EventAttributes attributes;
4088 Type declaring_type, reflected_type, event_type;
4091 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4093 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4095 // And now store the values in our own fields.
4097 declaring_type = type_builder;
4099 reflected_type = type_builder;
4101 attributes = event_attr;
4103 this.event_type = event_type;
4107 // Methods that you have to override. Note that you only need
4108 // to "implement" the variants that take the argument (those are
4109 // the "abstract" methods, the others (GetAddMethod()) are
4112 public override MethodInfo GetAddMethod (bool nonPublic)
4117 public override MethodInfo GetRemoveMethod (bool nonPublic)
4122 public override MethodInfo GetRaiseMethod (bool nonPublic)
4128 // These methods make "MyEventInfo" look like a Builder
4130 public void SetRaiseMethod (MethodBuilder raiseMethod)
4132 raise = raiseMethod;
4133 MyBuilder.SetRaiseMethod (raiseMethod);
4136 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4138 remove = removeMethod;
4139 MyBuilder.SetRemoveOnMethod (removeMethod);
4142 public void SetAddOnMethod (MethodBuilder addMethod)
4145 MyBuilder.SetAddOnMethod (addMethod);
4148 public void SetCustomAttribute (CustomAttributeBuilder cb)
4150 MyBuilder.SetCustomAttribute (cb);
4153 public override object [] GetCustomAttributes (bool inherit)
4155 // FIXME : There's nothing which can be seemingly done here because
4156 // we have no way of getting at the custom attribute objects of the
4161 public override object [] GetCustomAttributes (Type t, bool inherit)
4163 // FIXME : Same here !
4167 public override bool IsDefined (Type t, bool b)
4172 public override EventAttributes Attributes {
4178 public override string Name {
4184 public override Type DeclaringType {
4186 return declaring_type;
4190 public override Type ReflectedType {
4192 return reflected_type;
4196 public Type EventType {
4203 public class Event : FieldBase {
4204 const int AllowedModifiers =
4207 Modifiers.PROTECTED |
4208 Modifiers.INTERNAL |
4213 Modifiers.OVERRIDE |
4217 public readonly Accessor Add;
4218 public readonly Accessor Remove;
4219 public MyEventBuilder EventBuilder;
4221 MethodBuilder AddBuilder, RemoveBuilder;
4222 MethodData AddData, RemoveData;
4224 public Event (Expression type, string name, Object init, int mod, Accessor add,
4225 Accessor remove, Attributes attrs, Location loc)
4226 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4232 public override bool Define (TypeContainer parent)
4234 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4236 if (!DoDefine (parent))
4239 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4240 Report.Error (66, Location, "'" + parent.Name + "." + Name +
4241 "' : event must be of a delegate type");
4245 Type [] parameter_types = new Type [1];
4246 parameter_types [0] = MemberType;
4248 Parameter [] parms = new Parameter [1];
4249 parms [0] = new Parameter (Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4250 InternalParameters ip = new InternalParameters (
4251 parent, new Parameters (parms, null, Location));
4253 if (!CheckBase (parent))
4257 // Now define the accessors
4259 AddData = new MethodData (this, "add", TypeManager.void_type,
4260 parameter_types, ip, CallingConventions.Standard,
4261 (Add != null) ? Add.OptAttributes : null,
4262 ModFlags, flags, false);
4264 if (!AddData.Define (parent))
4267 AddBuilder = AddData.MethodBuilder;
4268 AddBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4270 RemoveData = new MethodData (this, "remove", TypeManager.void_type,
4271 parameter_types, ip, CallingConventions.Standard,
4272 (Remove != null) ? Remove.OptAttributes : null,
4273 ModFlags, flags, false);
4275 if (!RemoveData.Define (parent))
4278 RemoveBuilder = RemoveData.MethodBuilder;
4279 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4281 if (!IsExplicitImpl){
4282 EventBuilder = new MyEventBuilder (
4283 parent.TypeBuilder, Name, e_attr, MemberType);
4285 if (Add == null && Remove == null) {
4286 FieldBuilder = parent.TypeBuilder.DefineField (
4288 FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4289 TypeManager.RegisterPrivateFieldOfEvent (
4290 (EventInfo) EventBuilder, FieldBuilder);
4291 TypeManager.RegisterFieldBase (FieldBuilder, this);
4294 EventBuilder.SetAddOnMethod (AddBuilder);
4295 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4297 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4298 Report.Error (111, Location,
4299 "Class `" + parent.Name +
4300 "' already contains a definition for the event `" +
4309 void EmitDefaultMethod (EmitContext ec, bool is_add)
4311 ILGenerator ig = ec.ig;
4312 MethodInfo method = null;
4315 method = TypeManager.delegate_combine_delegate_delegate;
4317 method = TypeManager.delegate_remove_delegate_delegate;
4319 if ((ModFlags & Modifiers.STATIC) != 0) {
4320 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4321 ig.Emit (OpCodes.Ldarg_0);
4322 ig.Emit (OpCodes.Call, method);
4323 ig.Emit (OpCodes.Castclass, MemberType);
4324 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4326 ig.Emit (OpCodes.Ldarg_0);
4327 ig.Emit (OpCodes.Ldarg_0);
4328 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4329 ig.Emit (OpCodes.Ldarg_1);
4330 ig.Emit (OpCodes.Call, method);
4331 ig.Emit (OpCodes.Castclass, MemberType);
4332 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4334 ig.Emit (OpCodes.Ret);
4337 public void Emit (TypeContainer tc)
4341 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4342 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
4345 AddData.Emit (tc, Add.Block, Add);
4347 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4348 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4349 EmitDefaultMethod (ec, true);
4353 RemoveData.Emit (tc, Remove.Block, Remove);
4355 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4356 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4357 EmitDefaultMethod (ec, false);
4364 // FIXME: This does not handle:
4366 // int INTERFACENAME [ args ]
4371 // int this [ args ]
4373 public class Indexer : PropertyBase {
4375 const int AllowedModifiers =
4378 Modifiers.PROTECTED |
4379 Modifiers.INTERNAL |
4383 Modifiers.OVERRIDE |
4388 public string IndexerName;
4389 public string InterfaceIndexerName;
4392 // Are we implementing an interface ?
4394 bool IsImplementing = false;
4396 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4397 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4398 : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4401 ExplicitInterfaceName = int_type;
4404 public override bool Define (TypeContainer parent)
4406 PropertyAttributes prop_attr =
4407 PropertyAttributes.RTSpecialName |
4408 PropertyAttributes.SpecialName;
4410 if (!DoDefine (parent))
4413 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4414 if (IndexerName == null)
4415 IndexerName = "Item";
4416 else if (IsExplicitImpl)
4417 Report.Error (592, Location,
4418 "Attribute 'IndexerName' is not valid on this declaration " +
4419 "type. It is valid on `property' declarations only.");
4421 ShortName = IndexerName;
4422 if (IsExplicitImpl) {
4423 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4424 Name = InterfaceType.FullName + "." + IndexerName;
4426 InterfaceIndexerName = IndexerName;
4430 if (!CheckBase (parent))
4434 InternalParameters ip = new InternalParameters (parent, Parameters);
4436 GetData = new MethodData (this, "get", MemberType,
4437 ParameterTypes, ip, CallingConventions.Standard,
4438 Get.OptAttributes, ModFlags, flags, false);
4440 if (!GetData.Define (parent))
4443 GetBuilder = GetData.MethodBuilder;
4447 int top = ParameterTypes.Length;
4448 Type [] set_pars = new Type [top + 1];
4449 ParameterTypes.CopyTo (set_pars, 0);
4450 set_pars [top] = MemberType;
4452 Parameter [] fixed_parms = Parameters.FixedParameters;
4454 if (fixed_parms == null){
4455 throw new Exception ("We currently do not support only array arguments in an indexer");
4456 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4457 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4459 // Here is the problem: the `value' parameter has
4460 // to come *after* the array parameter in the declaration
4462 // X (object [] x, Type value)
4465 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4466 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4470 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4473 fixed_parms.CopyTo (tmp, 0);
4474 tmp [fixed_parms.Length] = new Parameter (
4475 Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4477 Parameters set_formal_params = new Parameters (tmp, null, Location);
4479 InternalParameters ip = new InternalParameters (parent, set_formal_params);
4481 SetData = new MethodData (this, "set", TypeManager.void_type,
4482 set_pars, ip, CallingConventions.Standard,
4483 Set.OptAttributes, ModFlags, flags, false);
4485 if (!SetData.Define (parent))
4488 SetBuilder = SetData.MethodBuilder;
4492 // Now name the parameters
4494 Parameter [] p = Parameters.FixedParameters;
4498 for (i = 0; i < p.Length; ++i) {
4500 GetBuilder.DefineParameter (
4501 i + 1, p [i].Attributes, p [i].Name);
4504 SetBuilder.DefineParameter (
4505 i + 1, p [i].Attributes, p [i].Name);
4510 SetBuilder.DefineParameter (
4511 i + 1, ParameterAttributes.None, /* was "value" */ this.Name);
4513 if (i != ParameterTypes.Length) {
4514 Parameter array_param = Parameters.ArrayParameter;
4515 SetBuilder.DefineParameter (
4516 i + 1, array_param.Attributes, array_param.Name);
4520 if (GetData != null)
4521 IsImplementing = GetData.IsImplementing;
4522 else if (SetData != null)
4523 IsImplementing = SetData.IsImplementing;
4526 // Define the PropertyBuilder if one of the following conditions are met:
4527 // a) we're not implementing an interface indexer.
4528 // b) the indexer has a different IndexerName and this is no
4529 // explicit interface implementation.
4531 if (!IsExplicitImpl) {
4532 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4533 IndexerName, prop_attr, MemberType, ParameterTypes);
4535 if (GetData != null)
4536 PropertyBuilder.SetGetMethod (GetBuilder);
4538 if (SetData != null)
4539 PropertyBuilder.SetSetMethod (SetBuilder);
4541 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4549 public class Operator : MemberCore {
4551 const int AllowedModifiers =
4557 const int RequiredModifiers =
4561 public enum OpType : byte {
4571 // Unary and Binary operators
4594 // Implicit and Explicit
4599 public readonly OpType OperatorType;
4600 public readonly Expression ReturnType;
4601 public readonly Expression FirstArgType, SecondArgType;
4602 public readonly string FirstArgName, SecondArgName;
4603 public readonly Block Block;
4604 public Attributes OptAttributes;
4605 public MethodBuilder OperatorMethodBuilder;
4607 public string MethodName;
4608 public Method OperatorMethod;
4610 public Operator (OpType type, Expression ret_type, int flags,
4611 Expression arg1type, string arg1name,
4612 Expression arg2type, string arg2name,
4613 Block block, Attributes attrs, Location loc)
4616 OperatorType = type;
4617 ReturnType = ret_type;
4618 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4619 FirstArgType = arg1type;
4620 FirstArgName = arg1name;
4621 SecondArgType = arg2type;
4622 SecondArgName = arg2name;
4624 OptAttributes = attrs;
4627 string Prototype (TypeContainer parent)
4629 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4630 SecondArgType + ")";
4633 public override bool Define (TypeContainer parent)
4636 MethodName = "op_" + OperatorType;
4638 if (SecondArgType != null)
4641 Parameter [] param_list = new Parameter [length];
4643 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4646 "User defined operators `" +
4647 Prototype (parent) +
4648 "' must be declared static and public");
4652 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4653 Parameter.Modifier.NONE, null);
4654 if (SecondArgType != null)
4655 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4656 Parameter.Modifier.NONE, null);
4658 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4659 new Parameters (param_list, null, Location),
4660 OptAttributes, Mono.MonoBASIC.Location.Null);
4662 OperatorMethod.IsOperator = true;
4663 OperatorMethod.Define (parent);
4665 if (OperatorMethod.MethodBuilder == null)
4668 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4670 Type [] param_types = OperatorMethod.ParameterTypes;
4671 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4672 Type return_type = OperatorMethod.GetReturnType ();
4673 Type first_arg_type = param_types [0];
4675 // Rules for conversion operators
4677 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4678 if (first_arg_type == return_type && first_arg_type == declaring_type){
4681 "User-defined conversion cannot take an object of the " +
4682 "enclosing type and convert to an object of the enclosing" +
4687 if (first_arg_type != declaring_type && return_type != declaring_type){
4690 "User-defined conversion must convert to or from the " +
4695 if (first_arg_type == TypeManager.object_type ||
4696 return_type == TypeManager.object_type){
4699 "User-defined conversion cannot convert to or from " +
4704 if (first_arg_type.IsInterface || return_type.IsInterface){
4707 "User-defined conversion cannot convert to or from an " +
4712 if (first_arg_type.IsSubclassOf (return_type) ||
4713 return_type.IsSubclassOf (first_arg_type)){
4716 "User-defined conversion cannot convert between types " +
4717 "that derive from each other");
4720 } else if (SecondArgType == null) {
4721 // Checks for Unary operators
4723 if (first_arg_type != declaring_type){
4726 "The parameter of a unary operator must be the " +
4731 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4732 if (return_type != declaring_type){
4735 "The parameter and return type for ++ and -- " +
4736 "must be the containing type");
4742 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4743 if (return_type != TypeManager.bool_type){
4746 "The return type of operator True or False " +
4753 // Checks for Binary operators
4755 if (first_arg_type != declaring_type &&
4756 param_types [1] != declaring_type){
4759 "One of the parameters of a binary operator must " +
4760 "be the containing type");
4768 public void Emit (TypeContainer parent)
4770 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4771 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4774 // abstract or extern methods have no bodies
4776 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4779 OperatorMethod.Block = Block;
4780 OperatorMethod.Emit (parent);
4783 public static string GetName (OpType ot)
4786 case OpType.LogicalNot:
4788 case OpType.OnesComplement:
4790 case OpType.Increment:
4792 case OpType.Decrement:
4798 case OpType.Addition:
4800 case OpType.Subtraction:
4802 case OpType.UnaryPlus:
4804 case OpType.UnaryNegation:
4806 case OpType.Multiply:
4808 case OpType.Division:
4810 case OpType.Modulus:
4812 case OpType.BitwiseAnd:
4814 case OpType.BitwiseOr:
4816 case OpType.ExclusiveOr:
4818 case OpType.LeftShift:
4820 case OpType.RightShift:
4822 case OpType.Equality:
4824 case OpType.Inequality:
4826 case OpType.GreaterThan:
4828 case OpType.LessThan:
4830 case OpType.GreaterThanOrEqual:
4832 case OpType.LessThanOrEqual:
4834 case OpType.Implicit:
4836 case OpType.Explicit:
4842 public override string ToString ()
4844 Type return_type = OperatorMethod.GetReturnType();
4845 Type [] param_types = OperatorMethod.ParameterTypes;
4847 if (SecondArgType == null)
4848 return String.Format (
4849 "{0} operator {1}({2})",
4850 TypeManager.MonoBASIC_Name (return_type),
4851 GetName (OperatorType),
4854 return String.Format (
4855 "{0} operator {1}({2}, {3})",
4856 TypeManager.MonoBASIC_Name (return_type),
4857 GetName (OperatorType),
4858 param_types [0], param_types [1]);
4863 // This is used to compare method signatures
4865 struct MethodSignature {
4867 public Type RetType;
4868 public Type [] Parameters;
4871 /// This delegate is used to extract methods which have the
4872 /// same signature as the argument
4874 public static MemberFilter method_signature_filter;
4877 /// This delegate is used to extract methods which have the
4878 /// same signature as the argument except for the name
4880 public static MemberFilter method_signature_noname_filter;
4883 /// This delegate is used to extract inheritable methods which
4884 /// have the same signature as the argument. By inheritable,
4885 /// this means that we have permissions to override the method
4886 /// from the current assembly and class
4888 public static MemberFilter inheritable_method_signature_filter;
4891 /// This delegate is used to extract inheritable methods which
4892 /// have the same signature as the argument. By inheritable,
4893 /// this means that we have permissions to override the method
4894 /// from the current assembly and class
4896 public static MemberFilter inheritable_property_signature_filter;
4898 static MethodSignature ()
4900 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4901 method_signature_noname_filter = new MemberFilter (MemberSignatureCompareNoName);
4902 inheritable_method_signature_filter = new MemberFilter (
4903 InheritableMemberSignatureCompare);
4904 inheritable_property_signature_filter = new MemberFilter (
4905 InheritablePropertySignatureCompare);
4908 public MethodSignature (string name, Type ret_type, Type [] parameters)
4913 if (parameters == null)
4914 Parameters = TypeManager.NoTypes;
4916 Parameters = parameters;
4919 public override int GetHashCode ()
4921 return Name.GetHashCode ();
4924 public override bool Equals (Object o)
4926 MethodSignature other = (MethodSignature) o;
4928 if (other.Name != Name)
4931 if (other.RetType != RetType)
4934 if (Parameters == null){
4935 if (other.Parameters == null)
4940 if (other.Parameters == null)
4943 int c = Parameters.Length;
4944 if (other.Parameters.Length != c)
4947 for (int i = 0; i < c; i++)
4948 if (other.Parameters [i] != Parameters [i])
4954 static bool MemberSignatureCompareNoName (MemberInfo m, object filter_criteria)
4956 return MemberSignatureCompare (m, filter_criteria, false);
4959 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4961 return MemberSignatureCompare (m, filter_criteria, true);
4964 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria, bool use_name)
4966 MethodSignature sig = (MethodSignature) filter_criteria;
4968 if (use_name && (m.Name != sig.Name))
4972 MethodInfo mi = m as MethodInfo;
4973 PropertyInfo pi = m as PropertyInfo;
4976 ReturnType = mi.ReturnType;
4977 else if (pi != null)
4978 ReturnType = pi.PropertyType;
4983 // we use sig.RetType == null to mean `do not check the
4984 // method return value.
4986 if (sig.RetType != null)
4987 if (ReturnType != sig.RetType)
4992 args = TypeManager.GetArgumentTypes (mi);
4994 args = TypeManager.GetArgumentTypes (pi);
4995 Type [] sigp = sig.Parameters;
4997 if (args.Length != sigp.Length)
5000 for (int i = args.Length; i > 0; ){
5002 if (args [i] != sigp [i])
5009 // This filter should be used when we are requesting methods that
5010 // we want to override.
5012 // This makes a number of assumptions, for example
5013 // that the methods being extracted are of a parent
5014 // class (this means we know implicitly that we are
5015 // being called to find out about members by a derived
5018 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
5020 if (MemberSignatureCompare (m, filter_criteria)){
5021 MethodInfo mi = (MethodInfo) m;
5022 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
5024 // If only accessible to the current class.
5025 if (prot == MethodAttributes.Private)
5028 // If only accessible to the defining assembly or
5029 if (prot == MethodAttributes.FamANDAssem ||
5030 prot == MethodAttributes.Assembly){
5031 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
5037 // Anything else (FamOrAssembly and Public) is fine
5044 // This filter should be used when we are requesting properties that
5045 // we want to override.
5047 // This makes a number of assumptions, for example
5048 // that the methods being extracted are of a parent
5049 // class (this means we know implicitly that we are
5050 // being called to find out about members by a derived
5053 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
5055 if (MemberSignatureCompare (m, filter_criteria)){
5056 PropertyInfo pi = (PropertyInfo) m;
5058 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
5059 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
5061 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
5063 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
5065 // If only accessible to the current class.
5066 if (prot == MethodAttributes.Private)
5069 // If only accessible to the defining assembly or
5070 if (prot == MethodAttributes.FamANDAssem ||
5071 prot == MethodAttributes.Assembly){
5072 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
5078 // Anything else (FamOrAssembly and Public) is fine