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 // Holds AddHandlers stements for events
94 // The emit context for toplevel objects.
98 // Pointers to the default constructor and the default static constructor
100 Constructor default_constructor;
101 Constructor default_static_constructor;
104 // Whether we have seen a static constructor for this class or not
106 bool have_static_constructor = false;
109 // Whether we have at least one non-static field
111 bool have_nonstatic_fields = false;
114 // This one is computed after we can distinguish interfaces
115 // from classes from the arraylist `type_bases'
117 string base_class_name;
119 ArrayList type_bases;
121 // Attributes for this type
122 protected Attributes attributes;
124 // Information in the case we are an attribute type
126 public AttributeTargets Targets = AttributeTargets.All;
127 public bool AllowMultiple = false;
128 public bool Inherited;
130 // The interfaces we implement.
133 // The parent member container and our member cache
134 IMemberContainer parent_container;
135 MemberCache member_cache;
138 // The indexer name for this class
140 public string IndexerName;
142 public TypeContainer (TypeContainer parent, string name, Location l)
143 : base (parent, name, l)
146 types = new ArrayList ();
153 base_class_name = null;
155 //Console.WriteLine ("New class " + name + " inside " + n);
158 public AdditionResult AddConstant (Const constant)
161 string basename = constant.Name;
163 if ((res = IsValid (basename)) != AdditionResult.Success)
166 if (constants == null)
167 constants = new ArrayList ();
169 constants.Add (constant);
170 DefineName (Name + "." + basename, constant);
172 return AdditionResult.Success;
175 public AdditionResult AddEnum (Mono.MonoBASIC.Enum e)
179 if ((res = IsValid (e.Basename)) != AdditionResult.Success)
183 enums = new ArrayList ();
186 DefineName (e.Name, e);
188 return AdditionResult.Success;
191 public AdditionResult AddClass (Class c)
195 if ((res = IsValid (c.Basename)) != AdditionResult.Success)
200 DefineName (c.Name, c);
203 // FIXME: Do we really need to explicitly add an empty default static constructor?
204 // Apparently we don't
205 /* if (c.default_static_constructor == null)
207 bool isModule = c is Mono.MonoBASIC.Module;
208 Constructor dc = new Constructor ("New", Parameters.EmptyReadOnlyParameters, null, c.Location);
209 dc.ModFlags = isModule ? Modifiers.PUBLIC | Modifiers.STATIC : Modifiers.PUBLIC;
210 c.AddConstructor (dc);
213 //--------------------------------------------------------------
215 return AdditionResult.Success;
218 public AdditionResult AddStruct (Struct s)
222 if ((res = IsValid (s.Basename)) != AdditionResult.Success)
225 DefineName (s.Name, s);
228 return AdditionResult.Success;
231 public AdditionResult AddDelegate (Delegate d)
235 if ((res = IsValid (d.Basename)) != AdditionResult.Success)
238 if (delegates == null)
239 delegates = new ArrayList ();
241 DefineName (d.Name, d);
244 return AdditionResult.Success;
247 public AdditionResult AddMethod (Method method)
249 string basename = method.Name;
250 string fullname = Name + "." + basename;
252 Object value = defined_names [fullname];
254 if (value != null && (!(value is Method)))
255 return AdditionResult.NameExists;
257 if (basename == Basename)
258 return AdditionResult.EnclosingClash;
261 methods = new ArrayList ();
263 if (method.Name.IndexOf (".") != -1)
264 methods.Insert (0, method);
266 methods.Add (method);
269 DefineName (fullname, method);
271 return AdditionResult.Success;
274 public AdditionResult AddConstructor (Constructor c)
277 return AdditionResult.NotAConstructor;
279 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
282 have_static_constructor = true;
283 if (default_static_constructor != null){
284 Console.WriteLine ("I have a static constructor already");
285 Console.WriteLine (" " + default_static_constructor);
286 return AdditionResult.MethodExists;
289 default_static_constructor = c;
292 /*if (default_constructor != null)
293 return AdditionResult.MethodExists;*/
294 default_constructor = c;
297 if (instance_constructors == null)
298 instance_constructors = new ArrayList ();
300 instance_constructors.Add (c);
303 return AdditionResult.Success;
306 public AdditionResult AddInterface (Interface iface)
310 if ((res = IsValid (iface.Basename)) != AdditionResult.Success)
313 if (interfaces == null)
314 interfaces = new ArrayList ();
315 interfaces.Add (iface);
316 DefineName (iface.Name, iface);
318 return AdditionResult.Success;
321 public AdditionResult AddField (Field field)
324 string basename = field.Name;
326 if ((res = IsValid (basename)) != AdditionResult.Success)
330 fields = new ArrayList ();
334 if (field.HasInitializer){
335 if ((field.ModFlags & Modifiers.STATIC) != 0) {
336 if (initialized_static_fields == null)
337 initialized_static_fields = new ArrayList ();
339 initialized_static_fields.Add (field);
342 // We have not seen a static constructor,
343 // but we will provide static initialization of fields
345 have_static_constructor = true;
347 if (initialized_fields == null)
348 initialized_fields = new ArrayList ();
350 initialized_fields.Add (field);
354 if ((field.ModFlags & Modifiers.STATIC) == 0)
355 have_nonstatic_fields = true;
357 DefineName (Name + "." + basename, field);
358 return AdditionResult.Success;
361 public AdditionResult AddProperty (Property prop)
364 string basename = prop.Name;
366 if ((res = IsValid (basename)) != AdditionResult.Success)
369 if (properties == null)
370 properties = new ArrayList ();
372 if (prop.Name.IndexOf (".") != -1)
373 properties.Insert (0, prop);
375 properties.Add (prop);
376 DefineName (Name + "." + basename, prop);
378 return AdditionResult.Success;
381 public AdditionResult AddEvent (Event e)
384 string basename = e.Name;
386 if ((res = IsValid (basename)) != AdditionResult.Success)
390 events = new ArrayList ();
393 DefineName (Name + "." + basename, e);
395 return AdditionResult.Success;
398 public AdditionResult AddIndexer (Indexer i)
400 if (indexers == null)
401 indexers = new ArrayList ();
403 if (i.InterfaceType != null)
404 indexers.Insert (0, i);
408 return AdditionResult.Success;
411 public AdditionResult AddOperator (Operator op)
413 if (operators == null)
414 operators = new ArrayList ();
418 return AdditionResult.Success;
421 public AdditionResult AddEventHandler (Statement stmt)
423 if (handlers == null)
424 handlers = new ArrayList ();
427 return AdditionResult.Success;
430 public void RegisterOrder (Interface iface)
432 if (interface_order == null)
433 interface_order = new ArrayList ();
435 interface_order.Add (iface);
438 public ArrayList Types {
444 public ArrayList Methods {
450 public ArrayList Constants {
456 public ArrayList Interfaces {
464 return base_class_name;
468 public ArrayList Bases {
478 public ArrayList Fields {
488 public ArrayList InstanceConstructors {
490 return instance_constructors;
494 public ArrayList Properties {
500 public ArrayList Events {
506 public ArrayList Enums {
512 public ArrayList Indexers {
518 public ArrayList Operators {
524 public ArrayList Delegates {
530 public Attributes OptAttributes {
536 public bool HaveStaticConstructor {
538 return have_static_constructor;
542 public virtual TypeAttributes TypeAttr {
544 return Modifiers.TypeAttr (ModFlags, this);
548 public ArrayList EventHandlers {
555 // Emits the instance field initializers
557 public bool EmitFieldInitializers (EmitContext ec)
560 ILGenerator ig = ec.ig;
561 Expression instance_expr;
564 fields = initialized_static_fields;
565 instance_expr = null;
567 fields = initialized_fields;
568 instance_expr = new This (Location.Null).Resolve (ec);
574 foreach (Field f in fields){
575 Expression e = f.GetInitializerExpression (ec);
579 Location l = f.Location;
580 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
581 fe.InstanceExpression = instance_expr;
582 Expression a = new Assign (fe, e, l);
588 if (a is ExpressionStatement)
589 ((ExpressionStatement) a).EmitStatement (ec);
591 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
599 // Defines the default constructors
601 void DefineDefaultConstructor (bool is_static)
606 c = new Constructor ("New", Parameters.EmptyReadOnlyParameters,
611 mods = Modifiers.STATIC;
615 c.Initializer = new ConstructorBaseInitializer (
616 null, Parameters.EmptyReadOnlyParameters,
621 c.Block = new Block (null);
625 public void ReportStructInitializedInstanceError ()
627 string n = TypeBuilder.FullName;
629 foreach (Field f in initialized_fields){
632 "`" + n + "." + f.Name + "': can not have " +
633 "instance field initializers in structs");
638 /// The pending methods that need to be implemented (interfaces or abstract methods)
640 public PendingImplementation Pending;
643 /// This function computes the Base class and also the
644 /// list of interfaces that the class or struct @c implements.
646 /// The return value is an array (might be null) of
647 /// interfaces implemented (as Types).
649 /// The @parent argument is set to the parent object or null
650 /// if this is `System.Object'.
652 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
654 ArrayList bases = Bases;
663 parent = TypeManager.value_type;
667 if (RootContext.StdLib)
668 parent = TypeManager.object_type;
669 else if (Name != "System.Object")
670 parent = TypeManager.object_type;
673 // If we are compiling our runtime,
674 // and we are defining ValueType, then our
675 // parent is `System.Object'.
677 if (!RootContext.StdLib && Name == "System.ValueType")
678 parent = TypeManager.object_type;
685 // Bases should be null if there are no bases at all
690 Expression name = (Expression) bases [0];
691 name = ResolveTypeExpr (name, false, Location);
698 Type first = name.Type;
704 parent = TypeManager.object_type;
708 if (parent.IsSealed )
709 Report.Error (30299, Location,
710 "Class " + Name + " cannot inherit " +
711 "'NotInheritable' class " + TypeManager.MonoBASIC_Name (parent));
713 if (!AsAccessible (parent, ModFlags))
714 Report.Error (30389, Location,
715 "Inconsistent accessibility: base class `" +
716 TypeManager.MonoBASIC_Name (parent) + "' is less " +
717 "accessible than class `" +
724 Type [] ifaces = new Type [count-start];
726 for (i = start, j = 0; i < count; i++, j++){
727 Expression name = (Expression) bases [i];
728 Expression resolved = ResolveTypeExpr (name, false, Location);
729 bases [i] = resolved;
730 Type t = resolved.Type;
737 if (is_class == false && !t.IsInterface){
738 Report.Error (527, "In Struct `" + Name + "', type `"+
739 name +"' is not an interface");
746 Report.Error (30258, "class `"+ Name +
747 "': a class can not inherit from a struct/enum");
749 /*Report.Error (509, "class `"+ Name +
750 "': Cannot inherit from sealed class `"+
758 Report.Error (30121, Name + ": A class cannot inherit " +
759 "more than one class");
765 for (int x = 0; x < j; x++) {
766 if (t == ifaces [x]) {
767 Report.Error (528, "`" + name + "' is already listed in interface list");
776 return TypeManager.ExpandInterfaces (ifaces);
780 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
782 public override TypeBuilder DefineType ()
788 if (TypeBuilder != null)
801 ec = new EmitContext (this, Mono.MonoBASIC.Location.Null, null, null, ModFlags);
803 if (((ModFlags & Modifiers.ABSTRACT ) != 0) &&
804 ((ModFlags & Modifiers.SEALED) != 0)){
805 Report.Error (31408, Location,
806 "Class declared as 'MustInherit' cannot be declared as 'NotInheritable'");
809 ifaces = GetClassBases (is_class, out parent, out error);
814 if (is_class && parent != null){
815 if (parent == TypeManager.enum_type ||
816 (parent == TypeManager.value_type && RootContext.StdLib) ||
817 parent == TypeManager.delegate_type ||
818 parent == TypeManager.array_type){
820 644, Location, "`" + Name + "' cannot inherit from " +
821 "special class `" + TypeManager.MonoBASIC_Name (parent) + "'");
826 if (!is_class && TypeManager.value_type == null)
827 throw new Exception ();
829 if (is_class && Parent.Parent == null)
\r
831 if ((ModFlags & Modifiers.PRIVATE) != 0)
832 Report.Error (31089, Location,
833 "Only internal classes can be declared as 'Private'");
835 if ((ModFlags & Modifiers.PROTECTED) != 0)
836 Report.Error (31047, Location,
837 "Only internal classes can be declared as 'Protected'");
840 if ((Parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
841 Report.Error (30735, Location,
842 "'Type' inside a 'Module' can not be " +
843 "declared as 'Protected'");
845 if ((Parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
846 Report.Error (30435, Location,
847 "'Type' inside a 'Structure' can not be " +
848 "declared as 'Protected'");
850 TypeAttributes type_attributes = TypeAttr;
852 // if (parent_builder is ModuleBuilder) {
854 ModuleBuilder builder = CodeGen.ModuleBuilder;
855 TypeBuilder = builder.DefineType (
856 Name, type_attributes, parent, ifaces);
859 TypeBuilder builder = Parent.TypeBuilder;
860 TypeBuilder = builder.DefineNestedType (
861 Basename, type_attributes, parent, ifaces);
866 // structure must contain atleast one member variable
867 if(!have_nonstatic_fields){
869 30281, Location, "Structure `" + Name + "' do not " +
870 "contain any member Variable");
872 /*TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
873 FieldAttributes.Private);*/
876 // add interfaces that were not added at type creation (weird API issue)
877 if (!have_nonstatic_fields && (ifaces != null)) {
878 foreach (Type i in ifaces)
879 TypeBuilder.AddInterfaceImplementation (i);
885 // Finish the setup for the EmitContext
887 ec.ContainerType = TypeBuilder;
889 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
891 if ((parent != null) &&
892 (parent == TypeManager.attribute_type ||
893 parent.IsSubclassOf (TypeManager.attribute_type))) {
894 RootContext.RegisterAttribute (this);
895 TypeManager.RegisterAttrType (TypeBuilder, this);
897 RootContext.RegisterOrder (this);
899 if (Interfaces != null) {
900 foreach (Interface iface in Interfaces)
905 foreach (TypeContainer tc in Types)
909 if (Delegates != null) {
910 foreach (Delegate d in Delegates)
915 foreach (Enum en in Enums)
925 /// Defines the MemberCore objects that are in the `list' Arraylist
927 /// The `defined_names' array contains a list of members defined in
930 static ArrayList remove_list = new ArrayList ();
931 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
935 // if one of the overloaded method is having
936 // Shadows or Overloads modifier all other should
937 // have the same modifier
938 Hashtable members = new Hashtable();
940 foreach (MemberCore mc in list)
\r
943 if(members[mc.Name] == null)
945 foreach (MemberCore m in list)
947 if(m.Name == mc.Name)
949 if ((m.ModFlags & Modifiers.SHADOWS) != 0)
951 modval = Modifiers.SHADOWS;
954 else if((m.ModFlags & Modifiers.NEW) != 0)
956 modval = Modifiers.NEW;
960 members.Add(mc.Name, modval);
963 modval = (int)members[mc.Name];
966 if(((modval & Modifiers.SHADOWS) != 0) && ((mc.ModFlags & Modifiers.SHADOWS) == 0))
969 "Function '" + mc.Name + "': must be declared 'Shadows' " +
970 "because another '" + mc.Name + "' declared 'Shadows'");
971 else if(((modval & Modifiers.NEW) != 0) && ((mc.ModFlags & Modifiers.NEW) == 0))
974 "Function '" + mc.Name + "': must be declared 'Overloads' " +
975 "because another '" + mc.Name + "' declared 'Overloads'");
979 remove_list.Clear ();
981 foreach (MemberCore mc in list){
982 if (!mc.Define (this)){
983 remove_list.Add (mc);
987 if (defined_names == null)
990 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
992 if (RootContext.WarningLevel >= 4){
993 if ((mc.ModFlags & Modifiers.NEW) != 0)
994 Warning_KewywordNewNotRequired (mc.Location, mc);
995 if ((mc.ModFlags & Modifiers.SHADOWS) != 0)
996 Warning_KewywordShadowsNotRequired (mc.Location, mc);
1001 MemberInfo match = defined_names [idx];
1003 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
1007 // If we are both methods, let the method resolution emit warnings
1009 if (match is MethodBase && mc is MethodCore)
1012 if (((mc.ModFlags & Modifiers.SHADOWS) == 0) && idx > 0)
1013 Warning_KeywordShadowsRequired (mc.Location, defined_names [idx]);
1017 foreach (object o in remove_list)
1020 remove_list.Clear ();
1024 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
1025 // class is consisten. Either it is `Item' or it is the name defined by all the
1026 // indexers with the `IndexerName' attribute.
1028 // Turns out that the IndexerNameAttribute is applied to each indexer,
1029 // but it is never emitted, instead a DefaultName attribute is attached
1032 void DefineIndexers ()
1034 string class_indexer_name = null;
1036 foreach (Indexer i in Indexers){
1041 name = i.IndexerName;
1043 if (i.InterfaceType != null)
1046 if (class_indexer_name == null){
1047 class_indexer_name = name;
1051 if (name == class_indexer_name)
1055 668, "Two indexers have different names, " +
1056 " you should use the same name for all your indexers");
1058 if (class_indexer_name == null)
1059 class_indexer_name = "Item";
1060 IndexerName = class_indexer_name;
1063 static void Error_KeywordNotAllowed (Location loc)
1065 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1069 /// Populates our TypeBuilder with fields and methods
1071 public override bool DefineMembers (TypeContainer parent)
1073 MemberInfo [] defined_names = null;
1075 if (interface_order != null){
1076 foreach (Interface iface in interface_order)
1077 if ((iface.ModFlags & Modifiers.NEW) == 0)
1078 iface.DefineMembers (this);
1080 Error_KeywordNotAllowed (iface.Location);
1083 if (RootContext.WarningLevel > 1){
1087 // This code throws an exception in the comparer
1088 // I guess the string is not an object?
1090 ptype = TypeBuilder.BaseType;
1092 defined_names = (MemberInfo []) FindMembers (
1093 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1094 BindingFlags.Public | BindingFlags.Instance |
1095 BindingFlags.Static, null, null);
1097 Array.Sort (defined_names, mif_compare);
1101 if (constants != null)
1102 DefineMembers (constants, defined_names);
1105 DefineMembers (fields, defined_names);
1108 if (instance_constructors == null){
1109 if (default_constructor == null)
\r
1110 DefineDefaultConstructor (false);
1113 if (initialized_static_fields != null &&
1114 default_static_constructor == null)
1115 DefineDefaultConstructor (true);
1118 if (this is Struct){
1120 // Structs can not have initialized instance
1123 if (initialized_static_fields != null &&
1124 default_static_constructor == null)
1125 DefineDefaultConstructor (true);
1127 if (initialized_fields != null)
1128 ReportStructInitializedInstanceError ();
1131 Pending = PendingImplementation.GetPendingImplementations (this);
1134 // Constructors are not in the defined_names array
1136 if (instance_constructors != null)
\r
1137 DefineMembers (instance_constructors, null);
1139 if (default_static_constructor != null)
1140 default_static_constructor.Define (this);
1142 if (methods != null)
1143 DefineMembers (methods, defined_names);
1145 if (properties != null)
1146 DefineMembers (properties, defined_names);
1149 DefineMembers (events, defined_names);
1151 if (indexers != null) {
1154 IndexerName = "Item";
1156 if (operators != null){
1157 DefineMembers (operators, null);
1159 CheckPairedOperators ();
1163 DefineMembers (enums, defined_names);
1165 if (delegates != null)
1166 DefineMembers (delegates, defined_names);
1169 if (TypeBuilder.BaseType != null)
1170 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1172 member_cache = new MemberCache (this);
1178 public override bool Define (TypeContainer parent)
1180 if (interface_order != null){
1181 foreach (Interface iface in interface_order)
1182 if ((iface.ModFlags & Modifiers.NEW) == 0)
1183 iface.Define (this);
1190 /// This function is based by a delegate to the FindMembers routine
1192 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1198 /// This filter is used by FindMembers, and we just keep
1199 /// a global for the filter to `AlwaysAccept'
1201 static MemberFilter accepting_filter;
1205 /// A member comparission method based on name only
1207 static IComparer mif_compare;
1209 static TypeContainer ()
1211 accepting_filter = new MemberFilter (AlwaysAccept);
1212 mif_compare = new MemberInfoCompare ();
1216 /// This method returns the members of this type just like Type.FindMembers would
1217 /// Only, we need to use this for types which are _being_ defined because MS'
1218 /// implementation can't take care of that.
1221 // FIXME: return an empty static array instead of null, that cleans up
1222 // some code and is consistent with some coding conventions I just found
1226 // Notice that in various cases we check if our field is non-null,
1227 // something that would normally mean that there was a bug elsewhere.
1229 // The problem happens while we are defining p-invoke methods, as those
1230 // will trigger a FindMembers, but this happens before things are defined
1232 // Since the whole process is a no-op, it is fine to check for null here.
1234 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1235 MemberFilter filter, object criteria)
1237 ArrayList members = new ArrayList ();
1240 if ((bf & BindingFlags.Public) != 0)
1241 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1243 if ((bf & BindingFlags.NonPublic) != 0)
1244 modflags |= Modifiers.PRIVATE;
1246 int static_mask = 0, static_flags = 0;
1247 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1248 case BindingFlags.Static:
1249 static_mask = static_flags = Modifiers.STATIC;
1252 case BindingFlags.Instance:
1253 static_mask = Modifiers.STATIC;
1258 static_mask = static_flags = 0;
1262 Timer.StartTimer (TimerType.TcFindMembers);
1265 filter = accepting_filter;
1267 if ((mt & MemberTypes.Field) != 0) {
1268 if (fields != null) {
1269 foreach (Field f in fields) {
1270 if ((f.ModFlags & modflags) == 0)
1272 if ((f.ModFlags & static_mask) != static_flags)
1275 FieldBuilder fb = f.FieldBuilder;
1276 if (fb != null && filter (fb, criteria) == true)
1281 if (constants != null) {
1282 foreach (Const con in constants) {
1283 if ((con.ModFlags & modflags) == 0)
1285 if ((con.ModFlags & static_mask) != static_flags)
1288 FieldBuilder fb = con.FieldBuilder;
1289 if (fb != null && filter (fb, criteria) == true)
1295 if ((mt & MemberTypes.Method) != 0) {
1296 if (methods != null) {
1297 foreach (Method m in methods) {
1298 if ((m.ModFlags & modflags) == 0)
1300 if ((m.ModFlags & static_mask) != static_flags)
1303 MethodBuilder mb = m.MethodBuilder;
1305 if (mb != null && filter (mb, criteria) == true)
1310 if (operators != null){
1311 foreach (Operator o in operators) {
1312 if ((o.ModFlags & modflags) == 0)
1314 if ((o.ModFlags & static_mask) != static_flags)
1317 MethodBuilder ob = o.OperatorMethodBuilder;
1318 if (ob != null && filter (ob, criteria) == true)
1323 if (properties != null){
1324 foreach (Property p in properties){
1325 if ((p.ModFlags & modflags) == 0)
1327 if ((p.ModFlags & static_mask) != static_flags)
1333 if (b != null && filter (b, criteria) == true)
1337 if (b != null && filter (b, criteria) == true)
1342 if (indexers != null){
1343 foreach (Indexer ix in indexers){
1344 if ((ix.ModFlags & modflags) == 0)
1346 if ((ix.ModFlags & static_mask) != static_flags)
1352 if (b != null && filter (b, criteria) == true)
1356 if (b != null && filter (b, criteria) == true)
1362 if ((mt & MemberTypes.Event) != 0) {
1364 foreach (Event e in events) {
1365 if ((e.ModFlags & modflags) == 0)
1367 if ((e.ModFlags & static_mask) != static_flags)
1370 MemberInfo eb = e.EventBuilder;
1371 if (eb != null && filter (eb, criteria) == true)
1372 members.Add (e.EventBuilder);
1376 if ((mt & MemberTypes.Property) != 0){
1377 if (properties != null)
1378 foreach (Property p in properties) {
1379 if ((p.ModFlags & modflags) == 0)
1381 if ((p.ModFlags & static_mask) != static_flags)
1384 MemberInfo pb = p.PropertyBuilder;
1386 if (pb != null && filter (pb, criteria) == true) {
1387 members.Add (p.PropertyBuilder);
1391 if (indexers != null)
1392 foreach (Indexer ix in indexers) {
1393 if ((ix.ModFlags & modflags) == 0)
1395 if ((ix.ModFlags & static_mask) != static_flags)
1398 MemberInfo ib = ix.PropertyBuilder;
1399 if (ib != null && filter (ib, criteria) == true) {
1400 members.Add (ix.PropertyBuilder);
1405 if ((mt & MemberTypes.NestedType) != 0) {
1407 foreach (TypeContainer t in types) {
1408 if ((t.ModFlags & modflags) == 0)
1411 TypeBuilder tb = t.TypeBuilder;
1412 if (tb != null && (filter (tb, criteria) == true))
1418 foreach (Enum en in enums){
1419 if ((en.ModFlags & modflags) == 0)
1422 TypeBuilder tb = en.TypeBuilder;
1423 if (tb != null && (filter (tb, criteria) == true))
1428 if (delegates != null){
1429 foreach (Delegate d in delegates){
1430 if ((d.ModFlags & modflags) == 0)
1433 TypeBuilder tb = d.TypeBuilder;
1434 if (tb != null && (filter (tb, criteria) == true))
1439 if (interfaces != null){
1440 foreach (Interface iface in interfaces){
1441 if ((iface.ModFlags & modflags) == 0)
1444 TypeBuilder tb = iface.TypeBuilder;
1445 if (tb != null && (filter (tb, criteria) == true))
1451 if ((mt & MemberTypes.Constructor) != 0){
1452 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1453 foreach (Constructor c in instance_constructors){
1454 ConstructorBuilder cb = c.ConstructorBuilder;
1456 if (filter (cb, criteria) == true)
1461 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1462 ConstructorBuilder cb =
1463 default_static_constructor.ConstructorBuilder;
1466 if (filter (cb, criteria) == true)
1472 // Lookup members in parent if requested.
1474 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1475 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1476 members.AddRange (list);
1479 Timer.StopTimer (TimerType.TcFindMembers);
1481 return new MemberList (members);
1484 public override MemberCache MemberCache {
1486 return member_cache;
1490 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1491 MemberFilter filter, object criteria)
1493 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1496 return tc.FindMembers (mt, bf, filter, criteria);
1498 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1502 // FindMethods will look for methods not only in the type `t', but in
1503 // any interfaces implemented by the type.
1505 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1506 MemberFilter filter, object criteria)
1512 /// Emits the values for the constants
1514 public void EmitConstants ()
1516 if (constants != null)
1517 foreach (Const con in constants)
1518 con.EmitConstant (this);
1523 /// Emits the code, this step is performed after all
1524 /// the types, enumerations, constructors
1528 if (instance_constructors != null)
1529 foreach (Constructor c in instance_constructors)
1532 if (default_static_constructor != null)
1533 default_static_constructor.Emit (this);
1535 if (methods != null)
1536 foreach (Method m in methods)
1539 if (operators != null)
1540 foreach (Operator o in operators)
1543 if (properties != null)
1544 foreach (Property p in properties)
1547 if (indexers != null){
1548 foreach (Indexer ix in indexers)
1551 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1552 this, IndexerName, ModFlags, Location);
1553 TypeBuilder.SetCustomAttribute (cb);
1557 foreach (Field f in fields)
1560 if (events != null){
1561 foreach (Event e in Events)
1565 if (Pending != null)
1566 if (Pending.VerifyPendingMethods ())
1569 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1572 // Check for internal or private fields that were never assigned
1574 if (fields != null && RootContext.WarningLevel >= 3) {
1575 foreach (Field f in fields) {
1576 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1581 169, f.Location, "Private field " +
1582 MakeName (f.Name) + " is never used");
1587 // Only report 649 on level 4
1589 if (RootContext.WarningLevel < 4)
1592 if ((f.status & Field.Status.ASSIGNED) != 0)
1597 "Field " + MakeName (f.Name) + " is never assigned " +
1598 " to and will always have its default value");
1602 // if (types != null)
1603 // foreach (TypeContainer tc in types)
1607 public override void CloseType ()
1612 TypeBuilder.CreateType ();
1614 } catch (TypeLoadException){
1616 // This is fine, the code still created the type
1618 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1619 // Console.WriteLine (e.Message);
1621 Console.WriteLine ("In type: " + Name);
1626 foreach (Enum en in Enums)
1629 if (interface_order != null){
1630 foreach (Interface iface in interface_order)
1635 foreach (TypeContainer tc in Types)
1639 foreach (TypeContainer tc in Types)
1640 if (!(tc is Struct))
1644 if (Delegates != null)
1645 foreach (Delegate d in Delegates)
1649 public string MakeName (string n)
1651 return "`" + Name + "." + n + "'";
1654 public void Warning_KeywordShadowsRequired (Location l, MemberInfo mi)
1657 108, l, "The keyword 'Shadows' is required on " +
1658 MakeName (mi.Name) + " because it shadows `" +
1659 mi.ReflectedType.Name + "." + mi.Name + "'");
1662 public void Warning_KewywordShadowsNotRequired (Location l, MemberCore mc)
1665 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1666 "inherited member, the keyword shadows is not required");
1669 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1672 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1673 "inherited member, the keyword new is not required");
1676 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1682 // Performs the validation on a Method's modifiers (properties have
1683 // the same properties).
1685 public bool MethodModifiersValid (int flags, string n, Location loc)
1687 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1688 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1689 const int nv = (Modifiers.SHADOWS | Modifiers.VIRTUAL);
1691 string name = MakeName (n);
1694 // At most one of static, virtual or override
1696 if ((flags & Modifiers.STATIC) != 0){
1697 if ((flags & vao) != 0){
1699 30501, loc, "Shared method " + name + " can not be " +
1700 "declared as Overridable");
1705 if (this is Struct){
1706 if ((flags & va) != 0){
1707 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1712 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.VIRTUAL) != 0)
\r
1716 ": Methods marked as Overrides cannot be made Overridable");
1720 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.SHADOWS) != 0){
1723 ": Methods marked as Overrides cannot be marked as Shadows");
1728 // If the declaration includes the abstract modifier, then the
1729 // declaration does not include static, virtual or extern
1731 if ((flags & Modifiers.ABSTRACT) != 0){
1732 if ((flags & Modifiers.EXTERN) != 0){
1734 180, loc, name + " can not be both abstract and extern");
1738 if ((flags & Modifiers.VIRTUAL) != 0){
1740 503, loc, name + " can not be both abstract and virtual");
1744 if((ModFlags & Modifiers.SEALED) != 0){
1747 "Class declared as 'NotInheritable' " +
1748 "cannot have a 'MustOverride' member");
1751 else if ((ModFlags & Modifiers.ABSTRACT) == 0){
1754 " is declared as 'MustOverride', hence its container " +
1755 "class should be declared as 'MustInherit'");
1761 if ((flags & Modifiers.PRIVATE) != 0){
1762 if ((flags & vao) != 0){
1765 ": Members marked as Overridable or Overrides can not be Private");
1770 if ((flags & Modifiers.SEALED) != 0){
1771 if ((flags & Modifiers.OVERRIDE) == 0){
1774 ": cannot be sealed because it is not an override");
1778 if ((flags & Modifiers.NEW) != 0){
1779 if ((flags & Modifiers.SHADOWS) != 0){
1782 " 'Overloads' and 'Shadows' cannot be combined ");
1790 // Access level of a type.
1793 ProtectedInternal = 1,
1799 // Check whether `flags' denotes a more restricted access than `level'
1800 // and return the new level.
1801 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1803 AccessLevel old_level = level;
1805 if ((flags & Modifiers.INTERNAL) != 0) {
1806 if ((flags & Modifiers.PROTECTED) != 0) {
1807 if ((int) level < (int) AccessLevel.ProtectedInternal)
1808 level = AccessLevel.ProtectedInternal;
1810 if ((int) level < (int) AccessLevel.Internal)
1811 level = AccessLevel.Internal;
1813 } else if ((flags & Modifiers.PROTECTED) != 0) {
1814 if ((int) level < (int) AccessLevel.Protected)
1815 level = AccessLevel.Protected;
1816 } else if ((flags & Modifiers.PRIVATE) != 0)
1817 level = AccessLevel.Private;
1822 // Return the access level for a new member which is defined in the current
1823 // TypeContainer with access modifiers `flags'.
1824 AccessLevel GetAccessLevel (int flags)
1826 if ((flags & Modifiers.PRIVATE) != 0)
1827 return AccessLevel.Private;
1830 if (!IsTopLevel && (Parent != null))
1831 level = Parent.GetAccessLevel (flags);
1833 level = AccessLevel.Public;
1835 return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1838 // Return the access level for type `t', but don't give more access than `flags'.
1839 static AccessLevel GetAccessLevel (Type t, int flags)
1841 if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1842 return AccessLevel.Private;
1845 if (TypeManager.IsBuiltinType (t))
1846 return AccessLevel.Public;
1847 else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1848 level = GetAccessLevel (t.DeclaringType, flags);
1850 level = CheckAccessLevel (AccessLevel.Public, flags);
1853 if (t.IsNestedPublic)
1856 if (t.IsNestedAssembly || t.IsNotPublic) {
1857 if ((int) level < (int) AccessLevel.Internal)
1858 level = AccessLevel.Internal;
1861 if (t.IsNestedFamily) {
1862 if ((int) level < (int) AccessLevel.Protected)
1863 level = AccessLevel.Protected;
1866 if (t.IsNestedFamORAssem) {
1867 if ((int) level < (int) AccessLevel.ProtectedInternal)
1868 level = AccessLevel.ProtectedInternal;
1875 // Returns true if `parent' is as accessible as the flags `flags'
1876 // given for this member.
1878 public bool AsAccessible (Type parent, int flags)
1880 while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1881 parent = parent.GetElementType ();
1883 AccessLevel level = GetAccessLevel (flags);
1884 AccessLevel level2 = GetAccessLevel (parent, flags);
1886 return (int) level >= (int) level2;
1889 Hashtable builder_and_args;
1891 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1893 if (builder_and_args == null)
1894 builder_and_args = new Hashtable ();
1899 /// Performs checks for an explicit interface implementation. First it
1900 /// checks whether the `interface_type' is a base inteface implementation.
1901 /// Then it checks whether `name' exists in the interface type.
1903 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1907 if (ifaces != null){
1908 foreach (Type t in ifaces){
1909 if (t == interface_type){
1917 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1924 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1926 Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1933 string IMemberContainer.Name {
1939 Type IMemberContainer.Type {
1945 IMemberContainer IMemberContainer.Parent {
1947 return parent_container;
1951 MemberCache IMemberContainer.MemberCache {
1953 return member_cache;
1957 bool IMemberContainer.IsInterface {
1963 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1965 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1969 // Operator pair checking
1972 class OperatorEntry {
1974 public Type ret_type;
1975 public Type type1, type2;
1977 public Operator.OpType ot;
1979 public OperatorEntry (int f, Operator o)
1983 ret_type = o.OperatorMethod.GetReturnType ();
1984 Type [] pt = o.OperatorMethod.ParameterTypes;
1988 ot = o.OperatorType;
1991 public override int GetHashCode ()
1993 return ret_type.GetHashCode ();
1996 public override bool Equals (object o)
1998 OperatorEntry other = (OperatorEntry) o;
2000 if (other.ret_type != ret_type)
2002 if (other.type1 != type1)
2004 if (other.type2 != type2)
2011 // Checks that some operators come in pairs:
2016 // They are matched based on the return type and the argument types
2018 void CheckPairedOperators ()
2020 Hashtable pairs = new Hashtable (null, null);
2022 // Register all the operators we care about.
2023 foreach (Operator op in operators){
2026 switch (op.OperatorType){
2027 case Operator.OpType.Equality:
2029 case Operator.OpType.Inequality:
2032 case Operator.OpType.GreaterThan:
2034 case Operator.OpType.LessThan:
2037 case Operator.OpType.GreaterThanOrEqual:
2039 case Operator.OpType.LessThanOrEqual:
2045 OperatorEntry oe = new OperatorEntry (reg, op);
2047 object o = pairs [oe];
2051 oe = (OperatorEntry) o;
2057 // Look for the mistakes.
2059 foreach (DictionaryEntry de in pairs){
2060 OperatorEntry oe = (OperatorEntry) de.Key;
2067 case Operator.OpType.Equality:
2070 case Operator.OpType.Inequality:
2073 case Operator.OpType.GreaterThan:
2076 case Operator.OpType.LessThan:
2079 case Operator.OpType.GreaterThanOrEqual:
2082 case Operator.OpType.LessThanOrEqual:
2086 Report.Error (216, oe.op.Location,
2087 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2094 public class Class : TypeContainer {
2096 // Modifiers allowed in a class declaration
2098 public const int AllowedModifiers =
2101 Modifiers.PROTECTED |
2102 Modifiers.INTERNAL |
2104 Modifiers.ABSTRACT |
2107 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2108 : base (parent, name, l)
2112 if (parent.Parent == null)
2113 accmods = Modifiers.INTERNAL;
2115 accmods = Modifiers.PUBLIC;
2117 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2118 this.attributes = attrs;
2122 // FIXME: How do we deal with the user specifying a different
2125 public override TypeAttributes TypeAttr {
2127 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2132 public class Struct : TypeContainer {
2134 // Modifiers allowed in a struct declaration
2136 public const int AllowedModifiers =
2139 Modifiers.PROTECTED |
2140 Modifiers.INTERNAL |
2144 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2145 : base (parent, name, l)
2149 if (parent.Parent == null)
2150 accmods = Modifiers.INTERNAL;
2152 accmods = Modifiers.PUBLIC;
2154 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2156 this.ModFlags |= Modifiers.SEALED;
2157 this.attributes = attrs;
2162 // FIXME: Allow the user to specify a different set of attributes
2163 // in some cases (Sealed for example is mandatory for a class,
2164 // but what SequentialLayout can be changed
2166 public override TypeAttributes TypeAttr {
2168 return base.TypeAttr |
2169 TypeAttributes.SequentialLayout |
2170 TypeAttributes.Sealed |
2171 TypeAttributes.BeforeFieldInit;
2176 public abstract class MethodCore : MemberBase {
2177 public /* readonly */ Parameters Parameters;
2181 // Parameters, cached for semantic analysis.
2183 protected InternalParameters parameter_info;
2184 protected Type [] parameter_types;
2186 public MethodCore (Expression type, int mod, int allowed_mod, string name,
2187 Attributes attrs, Parameters parameters, Location loc)
2188 : base (type, mod, allowed_mod, name, attrs, loc)
2190 Parameters = parameters;
2194 // Returns the System.Type array for the parameters of this method
2196 public Type [] ParameterTypes {
2198 return parameter_types;
2202 public InternalParameters ParameterInfo
2205 return parameter_info;
2209 public Block Block {
2219 protected virtual bool DoDefineParameters (TypeContainer parent)
2221 // Check if arguments were correct
2222 parameter_types = Parameters.GetParameterInfo (parent);
2223 if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
2226 parameter_info = new InternalParameters (parent, Parameters);
2231 public CallingConventions GetCallingConvention (bool is_class)
2233 CallingConventions cc = 0;
2235 cc = Parameters.GetCallingConvention ();
2238 if ((ModFlags & Modifiers.STATIC) == 0)
2239 cc |= CallingConventions.HasThis;
2241 // FIXME: How is `ExplicitThis' used in C#?
2246 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
2248 LabelParameters (ec, parameters, builder, null);
2251 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder, Parameters p_params)
2254 // Define each type attribute (in/out/ref) and
2255 // the argument names.
2257 Parameter [] p = p_params == null ? Parameters.FixedParameters : p_params.FixedParameters;
2260 MethodBuilder mb = null;
2261 ConstructorBuilder cb = null;
2263 if (builder is MethodBuilder)
2264 mb = (MethodBuilder) builder;
2266 cb = (ConstructorBuilder) builder;
2269 for (i = 0; i < p.Length; i++) {
2270 ParameterBuilder pb;
2273 pb = cb.DefineParameter (
2274 i + 1, p [i].Attributes, p [i].Name);
2276 pb = mb.DefineParameter (
2277 i + 1, p [i].Attributes, p [i].Name);
2279 Attributes attr = p [i].OptAttributes;
2281 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
2285 if (Parameters.ArrayParameter != null){
2286 ParameterBuilder pb;
2287 Parameter array_param = Parameters.ArrayParameter;
2290 pb = cb.DefineParameter (
2291 i + 1, array_param.Attributes,
2294 pb = mb.DefineParameter (
2295 i + 1, array_param.Attributes,
2298 CustomAttributeBuilder a = new CustomAttributeBuilder (
2299 TypeManager.cons_param_array_attribute, new object [0]);
2301 pb.SetCustomAttribute (a);
2306 public class Method : MethodCore {
2307 public MethodBuilder MethodBuilder;
2308 public MethodData MethodData;
2311 /// Modifiers allowed in a class declaration
2313 const int AllowedModifiers =
2316 Modifiers.PROTECTED |
2317 Modifiers.INTERNAL |
2321 Modifiers.NONVIRTUAL |
2322 Modifiers.OVERRIDE |
2323 Modifiers.ABSTRACT |
2329 // return_type can be "null" for VOID values.
2331 public Method (Expression return_type, int mod, string name, Parameters parameters,
2332 Attributes attrs, Location l)
2333 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2338 public Method (Expression return_type, int mod, string name, Parameters parameters,
2339 Attributes attrs, Expression impl_what, Location l)
2340 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2342 Implements = impl_what;
2346 // Returns the `System.Type' for the ReturnType of this
2347 // function. Provides a nice cache. (used between semantic analysis
2348 // and actual code generation
2350 public Type GetReturnType ()
2355 // Whether this is an operator method.
2356 public bool IsOperator;
2358 void DuplicateEntryPoint (MethodInfo b, Location location)
2362 "Program `" + CodeGen.FileName +
2363 "' has more than one entry point defined: `" +
2364 TypeManager.MonoBASIC_Signature(b) + "'");
2367 void Report28 (MethodInfo b)
2369 if (RootContext.WarningLevel < 4)
2374 "`" + TypeManager.MonoBASIC_Signature(b) +
2375 "' has the wrong signature to be an entry point");
2378 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2380 if (b.ReturnType != TypeManager.void_type &&
2381 b.ReturnType != TypeManager.int32_type)
2384 if (pinfo.Count == 0)
2387 if (pinfo.Count > 1)
2390 Type t = pinfo.ParameterType(0);
2392 (t.GetArrayRank() == 1) &&
2393 (t.GetElementType() == TypeManager.string_type) &&
2394 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2401 // Checks our base implementation if any
2403 protected override bool CheckBase (TypeContainer parent)
2405 // Check whether arguments were correct.
2406 if (!DoDefineParameters (parent))
2409 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2413 mi_this = TypeContainer.FindMembers (
2414 parent.TypeBuilder, MemberTypes.Method,
2415 BindingFlags.NonPublic | BindingFlags.Public |
2416 BindingFlags.Static | BindingFlags.Instance |
2417 BindingFlags.DeclaredOnly,
2418 MethodSignature.method_signature_filter, ms);
2420 if (mi_this.Count > 0) {
2421 Report.Error (111, Location, "Class `" + parent.Name + "' " +
2422 "already defines a member called `" + Name + "' " +
2423 "with the same parameter types");
2429 // Verify if the parent has a type with the same name, and then
2430 // check whether we have to create a new slot for it or not.
2432 Type ptype = parent.TypeBuilder.BaseType;
2434 // ptype is only null for System.Object while compiling corlib.
2436 MemberList mi, mi_static, mi_instance;
2438 mi_static = TypeContainer.FindMembers (
2439 ptype, MemberTypes.Method,
2440 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2441 MethodSignature.inheritable_method_signature_filter, ms);
2443 mi_instance = TypeContainer.FindMembers (
2444 ptype, MemberTypes.Method,
2445 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2446 MethodSignature.inheritable_method_signature_filter,
2449 if (mi_instance.Count > 0){
2451 } else if (mi_static.Count > 0)
2456 if (mi != null && mi.Count > 0){
2457 parent_method = (MethodInfo) mi [0];
2458 string name = parent_method.DeclaringType.Name + "." +
2461 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2464 if ((ModFlags & Modifiers.NEW) == 0) {
2465 Type parent_ret = TypeManager.TypeToCoreType (
2466 parent_method.ReturnType);
2468 if (parent_ret != MemberType) {
2470 508, parent.MakeName (Name) + ": cannot " +
2471 "change return type when overriding " +
2472 "inherited member " + name);
2477 /*if ((ModFlags & Modifiers.NEW) != 0)
2478 WarningNotHiding (parent);*/
2480 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2481 Report.Error (30284, Location,
2482 parent.MakeName (Name) +
2483 " : No suitable methods found to override");
2485 if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0)
\r
2487 if ((ModFlags & Modifiers.NONVIRTUAL) != 0)
\r
2489 Report.Error (31088, Location,
2490 parent.MakeName (Name) + " : Cannot " +
2491 "be declared NotOverridable since this method is " +
2492 "not maked as Overrides");
2495 // if a member of module is not inherited from Object class
2496 // can not be declared protected
2497 if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
2498 Report.Error (31066, Location,
2499 "'Sub' or 'Function' inside a 'Module' can not be declared as " +
2500 "'Protected' or 'Protected Friend'");
2503 /* else if ((ModFlags & Modifiers.NEW) != 0)
2504 WarningNotHiding (parent);
2513 public override bool Define (TypeContainer parent)
2515 if (!DoDefine (parent))
2518 if (!CheckBase (parent))
2521 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
2522 Report.Error (31067, Location,
2523 "'Sub' or 'Function' inside a 'Structure' can not be declared as " +
2524 "'Protected' or 'Protected Friend'");
2526 CallingConventions cc = GetCallingConvention (parent is Class);
2528 MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2529 ParameterInfo, cc, OptAttributes,
2530 ModFlags, flags, true);
2532 if (!MethodData.Define (parent))
2535 MethodBuilder = MethodData.MethodBuilder;
2538 // This is used to track the Entry Point,
2540 if (Name.ToUpper() == "MAIN" &&
2541 ((ModFlags & Modifiers.STATIC) != 0) &&
2542 (RootContext.MainClass == null ||
2543 RootContext.MainClass == parent.TypeBuilder.FullName ||
2544 (RootContext.RootNamespace != null &&
2545 RootContext.RootNamespace.Length > 0 &&
2546 (RootContext.RootNamespace + "." + RootContext.MainClass) == parent.TypeBuilder.FullName))) {
2547 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2548 if (RootContext.EntryPoint == null) {
2549 RootContext.EntryPoint = MethodBuilder;
2550 RootContext.EntryPointLocation = Location;
2552 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2553 DuplicateEntryPoint (MethodBuilder, Location);
2556 Report28(MethodBuilder);
2565 public void Emit (TypeContainer parent)
2567 MethodData.Emit (parent, Block, this);
2571 public abstract class ConstructorInitializer {
2572 ArrayList argument_list;
2573 ConstructorInfo parent_constructor;
2574 Parameters parameters;
2576 public bool implicit_initialization;
2578 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2581 this.argument_list = argument_list;
2582 this.parameters = parameters;
2584 this.implicit_initialization = false;
2587 public ArrayList Arguments {
2589 return argument_list;
2593 public ConstructorInfo ParentConstructor
2597 return parent_constructor;
2601 public bool Resolve (EmitContext ec)
2603 Expression parent_constructor_group;
2606 ec.CurrentBlock = new Block (null, true, parameters);
2608 if (argument_list != null){
2609 foreach (Argument a in argument_list){
2610 if (!a.Resolve (ec, loc))
2615 ec.CurrentBlock = null;
2617 if (this is ConstructorBaseInitializer) {
2618 if (ec.ContainerType.BaseType == null)
2621 t = ec.ContainerType.BaseType;
2622 if (ec.ContainerType.IsValueType){
2623 Report.Error (522, loc,
2624 "structs cannot call base class constructors");
2629 t = ec.ContainerType;
2631 parent_constructor_group = Expression.MemberLookup (
2633 MemberTypes.Constructor,
2634 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2637 if (parent_constructor_group == null){
2638 Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
2642 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2643 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2645 if (parent_constructor == null) {
2646 if (this.implicit_initialization)
2647 Report.Error (30148, loc, "Must declare 'MyBase.New' in the constructor " +
\r
2648 "of the class '" + ec.TypeContainer.Name + "' with appropriate arguments, since the base class '" +
\r
2649 t.FullName + "' does not contain a definition of 'New' without any parameter");
2651 Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
2659 public void Emit (EmitContext ec)
2661 if (parent_constructor != null){
2663 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2665 Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2672 public class ConstructorBaseInitializer : ConstructorInitializer {
2673 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2674 base (argument_list, pars, l)
2679 public class ConstructorThisInitializer : ConstructorInitializer {
2680 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2681 base (argument_list, pars, l)
2686 public class Constructor : MethodCore {
2687 public ConstructorBuilder ConstructorBuilder;
2688 public ConstructorInitializer Initializer;
2689 new public Attributes OptAttributes;
2692 // Modifiers allowed for a constructor.
2694 public const int AllowedModifiers =
2696 Modifiers.PROTECTED |
2697 Modifiers.INTERNAL |
2704 // The spec claims that static is not permitted, but
2705 // my very own code has static constructors.
2707 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2708 : base (null, 0, AllowedModifiers, name, null, args, l)
2713 public Constructor (string name, int mod, Parameters args, ConstructorInitializer init, Location l)
2714 : base (null, mod, AllowedModifiers, name, null, args, l)
2720 // Returns true if this is a default constructor
2722 public bool IsDefault ()
2724 if ((ModFlags & Modifiers.STATIC) != 0)
2725 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2726 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2729 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2730 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2731 (Initializer is ConstructorBaseInitializer) &&
2732 (Initializer.Arguments == null);
2736 // Creates the ConstructorBuilder
2738 public override bool Define (TypeContainer parent)
2740 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2741 MethodAttributes.SpecialName);
2743 if (parent.EventHandlers != null) {
2744 ArrayList hdlrs = parent.EventHandlers;
2745 foreach(Statement stmt in hdlrs)
2746 this.Block.AddStatement (stmt);
2750 // Check if arguments were correct.
2751 if (!DoDefineParameters (parent))
2754 if ((ModFlags & Modifiers.STATIC) != 0) {
2755 ca |= MethodAttributes.Static;
2757 if (this.Parameters != Parameters.EmptyReadOnlyParameters)
2760 "Shared constructor can not have parameters");
2762 if ((ModFlags & Modifiers.Accessibility) != 0)
2765 "Shared constructor can not be declared " +
2766 "explicitly as public, private, friend or protected");
2768 if (this.Initializer != null)
2771 "Keywords like MyBase, MyClass, Me are not " +
2772 "valid inside a Shared Constructor");
2775 if (parent is Struct && ParameterTypes.Length == 0) {
2778 "Structs can not contain explicit parameterless " +
2782 ca |= MethodAttributes.HideBySig;
2784 if ((ModFlags & Modifiers.PUBLIC) != 0)
2785 ca |= MethodAttributes.Public;
2786 else if ((ModFlags & Modifiers.PROTECTED) != 0) {
2787 if ((ModFlags & Modifiers.INTERNAL) != 0)
2788 ca |= MethodAttributes.FamORAssem;
2790 ca |= MethodAttributes.Family;
2792 else if ((ModFlags & Modifiers.INTERNAL) != 0)
2793 ca |= MethodAttributes.Assembly;
2794 else if (IsDefault ())
2795 ca |= MethodAttributes.Public;
2797 ca |= MethodAttributes.Private;
2800 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2801 ca, GetCallingConvention (parent is Class), ParameterTypes);
2804 // HACK because System.Reflection.Emit is lame
2806 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2809 "Class `" +parent.Name+ "' already contains a definition with the " +
2810 "same return value and parameter types for constructor `" + Name
2821 public void Emit (TypeContainer parent)
2823 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2824 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2826 if ((ModFlags & Modifiers.STATIC) == 0){
2827 if (parent is Class && Initializer == null) {
2828 Initializer = new ConstructorBaseInitializer (
2829 null, Parameters.EmptyReadOnlyParameters, parent.Location);
2830 Initializer.implicit_initialization = true;
2834 // Spec mandates that Initializers will not have
2838 if (Initializer != null && !Initializer.Resolve (ec))
2840 ec.IsStatic = false;
2843 LabelParameters (ec, ParameterTypes, ConstructorBuilder);
2846 // Classes can have base initializers and instance field initializers.
2848 if (parent is Class){
2849 if ((ModFlags & Modifiers.STATIC) == 0)
2850 parent.EmitFieldInitializers (ec);
2853 if (Initializer != null) {
2854 if (this.ConstructorBuilder.Equals (Initializer.ParentConstructor))
2857 "A constructor can not call itself" );
2859 Initializer.Emit (ec);
2862 if ((ModFlags & Modifiers.STATIC) != 0)
2863 parent.EmitFieldInitializers (ec);
2865 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2867 // If this is a non-static `struct' constructor and doesn't have any
2868 // initializer, it must initialize all of the struct's fields.
2869 if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2870 (Initializer == null))
2871 Block.AddThisVariable (parent, Location);
2873 ec.EmitTopBlock (Block, ParameterInfo, Location);
2877 public class MethodData {
2879 // The return type of this method
2881 public readonly Type ReturnType;
2882 public readonly Type[] ParameterTypes;
2883 public readonly InternalParameters ParameterInfo;
2884 public readonly CallingConventions CallingConventions;
2885 public readonly Attributes OptAttributes;
2886 public readonly Location Location;
2889 // Are we implementing an interface ?
2891 public bool IsImplementing = false;
2896 protected MemberBase member;
2897 protected int modifiers;
2898 protected MethodAttributes flags;
2899 protected bool is_method;
2900 protected string accessor_name;
2901 ArrayList conditionals;
2903 MethodBuilder builder = null;
2904 public MethodBuilder MethodBuilder {
2910 public MethodData (MemberBase member, string name, Type return_type,
2911 Type [] parameter_types, InternalParameters parameters,
2912 CallingConventions cc, Attributes opt_attrs,
2913 int modifiers, MethodAttributes flags, bool is_method)
2915 this.member = member;
2916 this.accessor_name = name;
2917 this.ReturnType = return_type;
2918 this.ParameterTypes = parameter_types;
2919 this.ParameterInfo = parameters;
2920 this.CallingConventions = cc;
2921 this.OptAttributes = opt_attrs;
2922 this.modifiers = modifiers;
2924 this.is_method = is_method;
2925 this.Location = member.Location;
2926 this.conditionals = new ArrayList ();
2932 Attribute dllimport_attribute = null;
2933 string obsolete = null;
2934 bool obsolete_error = false;
2936 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2938 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2941 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2942 if (asec.Attributes == null)
2945 foreach (Attribute a in asec.Attributes) {
2946 if (a.Name == "Conditional") {
2947 if (!ApplyConditionalAttribute (a))
2949 } else if (a.Name == "Obsolete") {
2950 if (!ApplyObsoleteAttribute (a))
2952 } else if (a.Name.IndexOf ("DllImport") != -1) {
2954 a.Type = TypeManager.dllimport_type;
2955 Attribute.Error_AttributeNotValidForElement (a, Location);
2958 if (!ApplyDllImportAttribute (a))
2968 // Applies the `DllImport' attribute to the method.
2970 protected virtual bool ApplyDllImportAttribute (Attribute a)
2972 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2973 if ((modifiers & extern_static) != extern_static) {
2974 Report.Error (601, Location,
2975 "The DllImport attribute must be specified on a method " +
2976 "marked `static' and `extern'.");
2980 flags |= MethodAttributes.PinvokeImpl;
2981 dllimport_attribute = a;
2986 // Applies the `Obsolete' attribute to the method.
2988 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2990 if (obsolete != null) {
2991 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2995 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2996 return obsolete != null;
3000 // Applies the `Conditional' attribute to the method.
3002 protected virtual bool ApplyConditionalAttribute (Attribute a)
3004 // The Conditional attribute is only valid on methods.
3006 Attribute.Error_AttributeNotValidForElement (a, Location);
3010 string condition = a.Conditional_GetConditionName ();
3012 if (condition == null)
3015 if (ReturnType != TypeManager.void_type) {
3016 Report.Error (578, Location,
3017 "Conditional not valid on `" + member.Name + "' " +
3018 "because its return type is not void");
3022 if ((modifiers & Modifiers.OVERRIDE) != 0) {
3023 Report.Error (243, Location,
3024 "Conditional not valid on `" + member.Name + "' " +
3025 "because it is an override method");
3029 if (member.IsExplicitImpl) {
3030 Report.Error (577, Location,
3031 "Conditional not valid on `" + member.Name + "' " +
3032 "because it is an explicit interface implementation");
3036 if (IsImplementing) {
3037 Report.Error (623, Location,
3038 "Conditional not valid on `" + member.Name + "' " +
3039 "because it is an interface method");
3043 conditionals.Add (condition);
3049 // Checks whether this method should be ignored due to its Conditional attributes.
3051 bool ShouldIgnore (Location loc)
3053 // When we're overriding a virtual method, we implicitly inherit the
3054 // Conditional attributes from our parent.
3055 if (member.ParentMethod != null) {
3056 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3057 member.ParentMethod, loc);
3059 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3063 foreach (string condition in conditionals)
3064 if (RootContext.AllDefines [condition] == null)
3071 // Returns the TypeManager.MethodFlags for this method.
3072 // This emits an error 619 / warning 618 if the method is obsolete.
3073 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3075 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3077 TypeManager.MethodFlags flags = 0;
3079 if (obsolete != null) {
3080 if (obsolete_error) {
3081 Report.Error (619, loc, "Method `" + member.Name +
3082 "' is obsolete: `" + obsolete + "'");
3083 return TypeManager.MethodFlags.IsObsoleteError;
3085 Report.Warning (618, loc, "Method `" + member.Name +
3086 "' is obsolete: `" + obsolete + "'");
3088 flags |= TypeManager.MethodFlags.IsObsolete;
3091 if (ShouldIgnore (loc))
3092 flags |= TypeManager.MethodFlags.ShouldIgnore;
3097 public virtual bool Define (TypeContainer parent)
3099 MethodInfo implementing = null;
3100 string method_name, name, prefix;
3102 if (OptAttributes != null)
3103 if (!ApplyAttributes (OptAttributes, is_method))
3106 if (member.IsExplicitImpl)
3107 prefix = member.InterfaceType.FullName + ".";
3111 if (accessor_name != null)
3112 name = accessor_name + "_" + member.ShortName;
3114 name = member.ShortName;
3115 method_name = prefix + name;
3117 if (parent.Pending != null){
3118 if (member is Indexer)
3119 implementing = parent.Pending.IsInterfaceIndexer (
3120 member.InterfaceType, ReturnType, ParameterTypes);
3122 implementing = parent.Pending.IsInterfaceMethod (
3123 member.InterfaceType, name, ReturnType, ParameterTypes);
3125 if (member.InterfaceType != null && implementing == null){
3126 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
3133 // For implicit implementations, make sure we are public, for
3134 // explicit implementations, make sure we are private.
3136 if (implementing != null){
3138 // Setting null inside this block will trigger a more
3139 // verbose error reporting for missing interface implementations
3141 // The "candidate" function has been flagged already
3142 // but it wont get cleared
3144 if (!member.IsExplicitImpl){
3146 // We already catch different accessibility settings
3147 // so we just need to check that we are not private
3149 if ((modifiers & Modifiers.PRIVATE) != 0)
3150 implementing = null;
3153 // Static is not allowed
3155 if ((modifiers & Modifiers.STATIC) != 0)
3156 implementing = null;
3158 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3159 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3160 implementing = null;
3166 // If implementing is still valid, set flags
3168 if (implementing != null){
3170 // When implementing interface methods, set NewSlot.
3172 if (implementing.DeclaringType.IsInterface)
3173 flags |= MethodAttributes.NewSlot;
3176 MethodAttributes.Virtual |
3177 MethodAttributes.HideBySig;
3179 // Get the method name from the explicit interface.
3180 if (member.InterfaceType != null) {
3181 name = implementing.Name;
3182 method_name = prefix + name;
3185 IsImplementing = true;
3189 // Create the MethodBuilder for the method
3191 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3192 if ((modifiers & Modifiers.STATIC) == 0) {
3193 Report.Error (601, Location,
3194 "The DllImport attribute must be specified on " +
3195 "a method marked 'static' and 'extern'.");
3199 EmitContext ec = new EmitContext (
3200 parent, Location, null, ReturnType, modifiers);
3202 builder = dllimport_attribute.DefinePInvokeMethod (
3203 ec, parent.TypeBuilder, method_name, flags,
3204 ReturnType, ParameterTypes);
3206 builder = parent.TypeBuilder.DefineMethod (
3207 method_name, flags, CallingConventions,
3208 ReturnType, ParameterTypes);
3210 if (builder == null)
3213 if (IsImplementing) {
3215 // clear the pending implemntation flag
3217 if (member is Indexer) {
3218 parent.Pending.ImplementIndexer (
3219 member.InterfaceType, builder, ReturnType,
3220 ParameterTypes, true);
3222 parent.Pending.ImplementMethod (
3223 member.InterfaceType, name, ReturnType,
3224 ParameterTypes, member.IsExplicitImpl);
3226 if (member.IsExplicitImpl)
3227 parent.TypeBuilder.DefineMethodOverride (
3228 builder, implementing);
3231 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3232 Report.Error (111, Location,
3233 "Class `" + parent.Name +
3234 "' already contains a definition with the " +
3235 "same return value and parameter types as the " +
3236 "'get' method of property `" + member.Name + "'");
3240 TypeManager.AddMethod (builder, this);
3248 public virtual void Emit (TypeContainer parent, Block block, object kind)
3253 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3254 ig = builder.GetILGenerator ();
3258 ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3260 if (OptAttributes != null)
3261 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
3263 if (member is MethodCore)
3264 ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder);
3267 // abstract or extern methods have no bodies
3269 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3274 // abstract or extern methods have no bodies.
3276 if ((modifiers & Modifiers.ABSTRACT) != 0)
3278 500, Location, "Abstract method `" +
3279 TypeManager.MonoBASIC_Signature (builder) +
3280 "' can not have a body");
3282 if ((modifiers & Modifiers.EXTERN) != 0)
3284 179, Location, "External method `" +
3285 TypeManager.MonoBASIC_Signature (builder) +
3286 "' can not have a body");
3292 // Methods must have a body unless they're extern or abstract
3294 if (block == null) {
3296 501, Location, "Method `" +
3297 TypeManager.MonoBASIC_Signature (builder) +
3298 "' must declare a body since it is not marked " +
3299 "abstract or extern");
3304 // Handle destructors specially
3306 // FIXME: This code generates buggy code
3308 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3309 EmitDestructor (ec, block);
3311 ISymbolWriter sw = CodeGen.SymbolWriter;
3313 if ((sw != null) && !Location.IsNull (Location) &&
3314 !Location.IsNull (block.EndLocation)) {
3315 Location end = block.EndLocation;
3316 MethodToken token = MethodBuilder.GetToken ();
3317 sw.OpenMethod (new SymbolToken (token.Token));
3318 // Avoid error if we don't support debugging for the platform
3320 sw.SetMethodSourceRange (Location.SymbolDocument,
3324 } catch (Exception) {
3327 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3331 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3335 void EmitDestructor (EmitContext ec, Block block)
3337 ILGenerator ig = ec.ig;
3339 Label finish = ig.DefineLabel ();
3340 bool old_in_try = ec.InTry;
3342 ig.BeginExceptionBlock ();
3344 ec.ReturnLabel = finish;
3345 ec.HasReturnLabel = true;
3346 ec.EmitTopBlock (block, null, Location);
3347 ec.InTry = old_in_try;
3349 // ig.MarkLabel (finish);
3350 bool old_in_finally = ec.InFinally;
3351 ec.InFinally = true;
3352 ig.BeginFinallyBlock ();
3354 if (ec.ContainerType.BaseType != null) {
3355 Expression member_lookup = Expression.MemberLookup (
3356 ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
3357 MemberTypes.Method, Expression.AllBindingFlags, Location);
3359 if (member_lookup != null){
3360 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3362 ig.Emit (OpCodes.Ldarg_0);
3363 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3366 ec.InFinally = old_in_finally;
3368 ig.EndExceptionBlock ();
3369 //ig.MarkLabel (ec.ReturnLabel);
3370 ig.Emit (OpCodes.Ret);
3374 abstract public class MemberBase : MemberCore {
3375 public Expression Type;
3376 public readonly Attributes OptAttributes;
3377 public Expression Implements;
3379 protected MethodAttributes flags;
3382 // The "short" name of this property / indexer / event. This is the
3383 // name without the explicit interface.
3385 public string ShortName;
3388 // The type of this property / indexer / event
3390 public Type MemberType;
3393 // If true, this is an explicit interface implementation
3395 public bool IsExplicitImpl = false;
3398 // The name of the interface we are explicitly implementing
3400 public string ExplicitInterfaceName = null;
3403 // If true, the interface type we are explicitly implementing
3405 public Type InterfaceType = null;
3408 // The method we're overriding if this is an override method.
3410 protected MethodInfo parent_method = null;
3411 public MethodInfo ParentMethod {
3413 return parent_method;
3418 // The constructor is only exposed to our children
3420 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3421 Attributes attrs, Location loc)
3425 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PUBLIC, loc);
3426 OptAttributes = attrs;
3429 protected virtual bool CheckBase (TypeContainer parent)
3434 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3438 foreach (Type partype in parameters){
3439 if (partype.IsPointer && !UnsafeOK (parent))
3442 if (parent.AsAccessible (partype, ModFlags))
3445 if (this is Indexer)
3446 Report.Error (55, Location,
3447 "Inconsistent accessibility: parameter type `" +
3448 TypeManager.MonoBASIC_Name (partype) + "' is less " +
3449 "accessible than indexer `" + Name + "'");
3451 Report.Error (51, Location,
3452 "Inconsistent accessibility: parameter type `" +
3453 TypeManager.MonoBASIC_Name (partype) + "' is less " +
3454 "accessible than method `" + Name + "'");
3461 protected virtual bool DoDefine (TypeContainer parent)
3466 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3469 flags = Modifiers.MethodAttr (ModFlags);
3471 // Lookup Type, verify validity
3472 MemberType = parent.ResolveType (Type, false, Location);
3473 if (MemberType == null)
3476 // verify accessibility
3477 if (!parent.AsAccessible (MemberType, ModFlags)) {
3478 if (this is Property)
3479 Report.Error (53, Location,
3480 "Inconsistent accessibility: property type `" +
3481 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3482 "accessible than property `" + Name + "'");
3483 else if (this is Indexer)
3484 Report.Error (54, Location,
3485 "Inconsistent accessibility: indexer return type `" +
3486 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3487 "accessible than indexer `" + Name + "'");
3488 else if (this is Method)
3489 Report.Error (50, Location,
3490 "Inconsistent accessibility: return type `" +
3491 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3492 "accessible than method `" + Name + "'");
3494 Report.Error (52, Location,
3495 "Inconsistent accessibility: field type `" +
3496 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3497 "accessible than field `" + Name + "'");
3501 if (MemberType.IsPointer && !UnsafeOK (parent))
3505 // Check for explicit interface implementation
3507 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
3508 int pos = Name.LastIndexOf (".");
3510 ExplicitInterfaceName = Name.Substring (0, pos);
3511 ShortName = Name.Substring (pos + 1);
3515 if (ExplicitInterfaceName != null) {
3516 InterfaceType = RootContext.LookupType (
3517 parent, ExplicitInterfaceName, false, Location);
3518 if (InterfaceType == null)
3521 // Compute the full name that we need to export.
3522 Name = InterfaceType.FullName + "." + ShortName;
3524 if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
3527 IsExplicitImpl = true;
3529 IsExplicitImpl = false;
3536 // Fields and Events both generate FieldBuilders, we use this to share
3537 // their common bits. This is also used to flag usage of the field
3539 abstract public class FieldBase : MemberBase {
3540 public FieldBuilder FieldBuilder;
3541 public Status status;
3544 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3547 // The constructor is only exposed to our children
3549 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3550 object init, Attributes attrs, Location loc)
3551 : base (type, mod, allowed_mod, name, attrs, loc)
3557 // Whether this field has an initializer.
3559 public bool HasInitializer {
3561 return init != null;
3566 readonly Object init;
3567 Expression init_expr;
3568 bool init_expr_initialized = false;
3571 // Resolves and returns the field initializer.
3573 public Expression GetInitializerExpression (EmitContext ec)
3575 if (init_expr_initialized)
3579 if (init is Expression)
3580 e = (Expression) init;
3582 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3584 ec.IsFieldInitializer = true;
3585 e = e.DoResolve (ec);
3586 ec.IsFieldInitializer = false;
3589 init_expr_initialized = true;
3597 // The Field class is used to represents class/struct fields during parsing.
3599 public class Field : FieldBase {
3601 // Modifiers allowed in a class declaration
3603 const int AllowedModifiers =
3606 Modifiers.PROTECTED |
3607 Modifiers.INTERNAL |
3610 // Modifiers.VOLATILE |
3611 // Modifiers.UNSAFE |
3614 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3615 Attributes attrs, Location loc)
3616 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3620 public override bool Define (TypeContainer parent)
3622 Type t = parent.ResolveType (Type, false, Location);
3627 if (!parent.AsAccessible (t, ModFlags)) {
3628 Report.Error (52, Location,
3629 "Inconsistent accessibility: field type `" +
3630 TypeManager.MonoBASIC_Name (t) + "' is less " +
3631 "accessible than field `" + Name + "'");
3635 if (t.IsPointer && !UnsafeOK (parent))
3638 Type ptype = parent.TypeBuilder.BaseType;
3640 // ptype is only null for System.Object while compiling corlib.
3642 MemberList list = TypeContainer.FindMembers (
3643 ptype, MemberTypes.Field,
3644 BindingFlags.Public |
3645 BindingFlags.Static | BindingFlags.Instance,
3646 System.Type.FilterName, Name);
3648 if (RootContext.WarningLevel > 1){
3649 if ((list.Count > 0) && ((ModFlags & Modifiers.SHADOWS) == 0))
\r
3653 "Variable '" + Name + "' should be declared " +
3654 "Shadows since the base type '" + ptype.Name +
3655 "' has a variable with same name");
3657 ModFlags |= Modifiers.SHADOWS;
3660 if (list.Count == 0)
3661 // if a member of module is not inherited from Object class
3662 // can not be declared protected
3663 if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
3664 Report.Error (30593, Location,
3665 "'Variable' inside a 'Module' can not be " +
3666 "declared as 'Protected'");
3669 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
3670 Report.Error (30435, Location,
3671 "'Variable' inside a 'Structure' can not be " +
3672 "declared as 'Protected'");
3674 if ((ModFlags & Modifiers.VOLATILE) != 0){
3676 if (TypeManager.IsEnumType (t))
3677 t = TypeManager.EnumToUnderlying (t);
3679 if (!((t == TypeManager.bool_type) ||
3680 (t == TypeManager.sbyte_type) ||
3681 (t == TypeManager.byte_type) ||
3682 (t == TypeManager.short_type) ||
3683 (t == TypeManager.ushort_type) ||
3684 (t == TypeManager.int32_type) ||
3685 (t == TypeManager.uint32_type) ||
3686 (t == TypeManager.char_type) ||
3687 (t == TypeManager.float_type))){
3689 677, Location, parent.MakeName (Name) +
3690 " A volatile field can not be of type `" +
3691 TypeManager.MonoBASIC_Name (t) + "'");
3697 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3699 if (parent is Struct &&
3700 ((fa & FieldAttributes.Static) == 0) &&
3701 t == parent.TypeBuilder &&
3702 !TypeManager.IsBuiltinType (t)){
3703 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name +
3704 "' causes a cycle in the structure layout");
3707 FieldBuilder = parent.TypeBuilder.DefineField (
3708 Name, t, Modifiers.FieldAttr (ModFlags));
3710 TypeManager.RegisterFieldBase (FieldBuilder, this);
3714 public void Emit (TypeContainer tc)
3716 EmitContext ec = new EmitContext (tc, Location, null,
3717 FieldBuilder.FieldType, ModFlags);
3719 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
3724 // `set' and `get' accessors are represented with an Accessor.
3726 public class Accessor {
3728 // Null if the accessor is empty, or a Block if not
3731 public Attributes OptAttributes;
3733 public Accessor (Block b, Attributes attrs)
3736 OptAttributes = attrs;
3741 // Properties and Indexers both generate PropertyBuilders, we use this to share
3742 // their common bits.
3744 abstract public class PropertyBase : MethodCore {
3745 public Accessor Get, Set;
3746 public PropertyBuilder PropertyBuilder;
3747 public MethodBuilder GetBuilder, SetBuilder;
3748 public MethodData GetData, SetData;
3750 protected EmitContext ec;
3752 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3753 Parameters parameters, Accessor get_block, Accessor set_block,
3754 Attributes attrs, Location loc)
3755 : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3761 protected override bool DoDefine (TypeContainer parent)
3763 if (!base.DoDefine (parent))
3766 ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3772 // Checks our base implementation if any
3774 protected override bool CheckBase (TypeContainer parent)
3776 // Check whether arguments were correct.
3777 if (!DoDefineParameters (parent))
3784 MethodSignature ms, base_ms;
3785 if (this is Indexer) {
3786 string name, base_name;
3788 report_name = "this";
3789 name = TypeManager.IndexerPropertyName (parent.TypeBuilder);
3790 ms = new MethodSignature (name, null, ParameterTypes);
3791 base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType);
3792 base_ms = new MethodSignature (base_name, null, ParameterTypes);
3795 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
3798 MemberList props_this;
3800 props_this = TypeContainer.FindMembers (
3801 parent.TypeBuilder, MemberTypes.Property,
3802 BindingFlags.NonPublic | BindingFlags.Public |
3803 BindingFlags.Static | BindingFlags.Instance |
3804 BindingFlags.DeclaredOnly,
3805 MethodSignature.method_signature_filter, ms);
3807 if (props_this.Count > 0) {
3808 Report.Error (111, Location, "Class `" + parent.Name + "' " +
3809 "already defines a member called `" + report_name + "' " +
3810 "with the same parameter types");
3815 // Find properties with the same name on the base class
3818 MemberList props_static = TypeContainer.FindMembers (
3819 parent.TypeBuilder.BaseType, MemberTypes.Property,
3820 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3821 MethodSignature.inheritable_property_signature_filter, base_ms);
3823 MemberList props_instance = TypeContainer.FindMembers (
3824 parent.TypeBuilder.BaseType, MemberTypes.Property,
3825 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3826 MethodSignature.inheritable_property_signature_filter,
3830 // Find if we have anything
3832 if (props_static.Count > 0)
3833 props = props_static;
3834 else if (props_instance.Count > 0)
3835 props = props_instance;
3841 // If we have something on the base.
3842 if (props != null && props.Count > 0){
3843 PropertyInfo pi = (PropertyInfo) props [0];
3845 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
3846 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
3848 MethodInfo reference = inherited_get == null ?
3849 inherited_set : inherited_get;
3851 if (reference != null) {
3852 string name = reference.DeclaringType.Name + "." + report_name;
3854 if (!CheckMethodAgainstBase (parent, flags, reference, name))
3858 if (((ModFlags & Modifiers.NEW) == 0) && (pi.PropertyType != MemberType)) {
3859 Report.Error (508, parent.MakeName (Name) + ": cannot " +
3860 "change return type when overriding inherited " +
3861 "member `" + pi.DeclaringType + "." + pi.Name + "'");
3865 /*if ((ModFlags & Modifiers.NEW) != 0)
3866 WarningNotHiding (parent);*/
3868 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3869 if (this is Indexer)
3870 Report.Error (115, Location,
3871 parent.MakeName (Name) +
3872 " no suitable indexers found to override");
3874 Report.Error (30284, Location,
3875 parent.MakeName (Name) +
3876 " no suitable properties found to override");
3880 if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0) {
3881 if ((ModFlags & Modifiers.NONVIRTUAL) != 0) {
3882 Report.Error (31088, Location,
3883 parent.MakeName (Name) + " : Cannot " +
3884 "be declared NotOverridable since this 'Property' does " +
3885 "not 'Overrides' any other 'Property'");
3888 // if a member of module is not inherited from Object class
3889 // can not be declared protected
3890 if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
3891 Report.Error (30503, Location,
3892 "'Property' inside a 'Module' can not be declared as " +
3893 "'Protected' or 'Protected Friend'");
3898 public virtual void Emit (TypeContainer tc)
3901 // The PropertyBuilder can be null for explicit implementations, in that
3902 // case, we do not actually emit the ".property", so there is nowhere to
3903 // put the attribute
3905 if (PropertyBuilder != null)
3906 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3908 if (GetData != null)
3909 GetData.Emit (tc, Get.Block, Get);
3911 if (SetData != null)
3912 SetData.Emit (tc, Set.Block, Set);
3917 public class Property : PropertyBase {
3918 const int AllowedModifiers =
3921 Modifiers.PROTECTED |
3922 Modifiers.INTERNAL |
3926 Modifiers.OVERRIDE |
3927 Modifiers.ABSTRACT |
3931 Modifiers.NONVIRTUAL |
3933 Modifiers.READONLY |
3934 Modifiers.WRITEONLY |
3937 string set_parameter_name;
3938 Parameters get_params;
3939 Parameters set_params;
3941 public Property (Expression type, string name, int mod_flags,
3942 Accessor get_block, Accessor set_block,
3943 Attributes attrs, Location loc, string set_name,
3944 Parameters p_get, Parameters p_set, Expression impl_what)
3945 : base (type, name, mod_flags, AllowedModifiers,
3947 get_block, set_block, attrs, loc)
3949 set_parameter_name = set_name;
3952 Implements = impl_what;
3955 public Property (Expression type, string name, int mod_flags,
3956 Accessor get_block, Accessor set_block,
3957 Attributes attrs, Location loc)
3958 : this (type, name, mod_flags, get_block, set_block, attrs, loc,
3959 "Value", Parameters.EmptyReadOnlyParameters, Parameters.EmptyReadOnlyParameters, null)
3963 public override bool Define (TypeContainer parent)
3965 Type [] g_parameters=null, s_parameters=null;
3966 Parameter [] g_parms, s_parms;
3967 InternalParameters g_ip=null, s_ip=null;
3969 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
3970 Report.Error (30435, Location,
3971 "'Property' inside a 'Structure' can not be declared as " +
3972 "'Protected' or 'Protected Friend'");
3974 if (!DoDefine (parent))
3977 if (!CheckBase (parent))
3980 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3983 if ((ModFlags & Modifiers.WRITEONLY) == 0)
3986 "Property without 'Get' accessor must have a 'WriteOnly' modifier");
3989 if (get_params == Parameters.EmptyReadOnlyParameters)
3991 g_parameters = TypeManager.NoTypes;
3992 g_ip = new InternalParameters (
3993 parent, Parameters.EmptyReadOnlyParameters);
3997 g_parameters = new Type [get_params.FixedParameters.Length];
3998 for (int i = 0; i < get_params.FixedParameters.Length; i ++)
4000 g_parameters[i] = get_params.FixedParameters[i].ParameterType;
4002 g_parms = new Parameter [get_params.FixedParameters.Length];
4003 for (int i = 0; i < get_params.FixedParameters.Length; i ++)
4005 Parameter tp = get_params.FixedParameters[i];
4006 g_parms[i] = new Parameter (tp.TypeName, tp.Name,
4007 Parameter.Modifier.NONE, null);
4009 g_ip = new InternalParameters (
4010 parent, new Parameters (g_parms, null, Location));
4013 GetData = new MethodData (this, "get", MemberType,
4014 g_parameters, g_ip, CallingConventions.Standard,
4015 Get.OptAttributes, ModFlags, flags, false);
4017 if (!GetData.Define (parent))
4020 GetBuilder = GetData.MethodBuilder;
4024 if ((ModFlags & Modifiers.READONLY) == 0)
4027 "Property without 'Set' accessor must have a 'ReadOnly' modifier");
4032 if (set_params == Parameters.EmptyReadOnlyParameters)
4034 s_parameters = new Type [1];
4035 s_parameters [0] = MemberType;
4037 s_parms = new Parameter [1];
4038 s_parms [0] = new Parameter (Type, set_parameter_name,
4039 Parameter.Modifier.NONE, null);
4043 s_parameters = new Type [set_params.FixedParameters.Length];
4044 for (int i = 0; i < set_params.FixedParameters.Length; i ++)
4046 s_parameters[i] = set_params.FixedParameters[i].ParameterType;
4049 s_parms = new Parameter [set_params.FixedParameters.Length];
4050 for (int i = 0; i < set_params.FixedParameters.Length; i ++)
4052 Parameter tp = set_params.FixedParameters[i];
4053 s_parms[i] = new Parameter (tp.TypeName, tp.Name,
4054 Parameter.Modifier.NONE, null);
4058 s_ip = new InternalParameters (
4059 parent, new Parameters (s_parms, null, Location));
4061 SetData = new MethodData (this, "set", TypeManager.void_type,
4062 s_parameters, s_ip, CallingConventions.Standard,
4063 Set.OptAttributes, ModFlags, flags, false);
4065 if (!SetData.Define (parent))
4068 SetBuilder = SetData.MethodBuilder;
4069 SetBuilder.DefineParameter (1, ParameterAttributes.None,
4070 set_parameter_name);
4073 // FIXME - PropertyAttributes.HasDefault ?
4075 PropertyAttributes prop_attr =
4076 PropertyAttributes.RTSpecialName |
4077 PropertyAttributes.SpecialName;
4079 if (!IsExplicitImpl){
4080 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4081 Name, prop_attr, MemberType, null);
4083 PropertyBuilder.SetGetMethod (GetBuilder);
4084 PropertyBuilder.SetSetMethod (SetBuilder);
4087 // HACK for the reasons exposed above
4089 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4092 "Class `" + parent.Name +
4093 "' already contains a definition for the property `" +
4101 public override void Emit (TypeContainer tc)
4105 if (GetData != null)
4107 Parameters = get_params;
4108 GetData.Emit (tc, Get.Block, Get);
4111 if (SetData != null)
4113 Parameters = set_params;
4114 SetData.Emit (tc, Set.Block, Set);
4121 /// Gigantic workaround for lameness in SRE follows :
4122 /// This class derives from EventInfo and attempts to basically
4123 /// wrap around the EventBuilder so that FindMembers can quickly
4124 /// return this in it search for members
4126 public class MyEventBuilder : EventInfo {
4129 // We use this to "point" to our Builder which is
4130 // not really a MemberInfo
4132 EventBuilder MyBuilder;
4135 // We "catch" and wrap these methods
4137 MethodInfo raise, remove, add;
4139 EventAttributes attributes;
4140 Type declaring_type, reflected_type, event_type;
4143 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4145 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4147 // And now store the values in our own fields.
4149 declaring_type = type_builder;
4151 reflected_type = type_builder;
4153 attributes = event_attr;
4155 this.event_type = event_type;
4159 // Methods that you have to override. Note that you only need
4160 // to "implement" the variants that take the argument (those are
4161 // the "abstract" methods, the others (GetAddMethod()) are
4164 public override MethodInfo GetAddMethod (bool nonPublic)
4169 public override MethodInfo GetRemoveMethod (bool nonPublic)
4174 public override MethodInfo GetRaiseMethod (bool nonPublic)
4180 // These methods make "MyEventInfo" look like a Builder
4182 public void SetRaiseMethod (MethodBuilder raiseMethod)
4184 raise = raiseMethod;
4185 MyBuilder.SetRaiseMethod (raiseMethod);
4188 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4190 remove = removeMethod;
4191 MyBuilder.SetRemoveOnMethod (removeMethod);
4194 public void SetAddOnMethod (MethodBuilder addMethod)
4197 MyBuilder.SetAddOnMethod (addMethod);
4200 public void SetCustomAttribute (CustomAttributeBuilder cb)
4202 MyBuilder.SetCustomAttribute (cb);
4205 public override object [] GetCustomAttributes (bool inherit)
4207 // FIXME : There's nothing which can be seemingly done here because
4208 // we have no way of getting at the custom attribute objects of the
4213 public override object [] GetCustomAttributes (Type t, bool inherit)
4215 // FIXME : Same here !
4219 public override bool IsDefined (Type t, bool b)
4224 public override EventAttributes Attributes {
4230 public override string Name {
4236 public override Type DeclaringType {
4238 return declaring_type;
4242 public override Type ReflectedType {
4244 return reflected_type;
4248 public Type EventType {
4255 public class Event : FieldBase {
4256 const int AllowedModifiers =
4259 Modifiers.PROTECTED |
4260 Modifiers.INTERNAL |
4265 Modifiers.OVERRIDE |
4269 public readonly Accessor Add;
4270 public readonly Accessor Remove;
4271 public MyEventBuilder EventBuilder;
4273 MethodBuilder AddBuilder, RemoveBuilder;
4274 MethodData AddData, RemoveData;
4276 public Event (Expression type, string name, Object init, int mod, Accessor add,
4277 Accessor remove, Attributes attrs, Location loc)
4278 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4284 public override bool Define (TypeContainer parent)
4286 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4288 if (!DoDefine (parent))
4291 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4292 Report.Error (31044, Location, "'" + parent.Name + "." + Name +
4293 "' : event must be of a delegate type");
4297 Type [] parameter_types = new Type [1];
4298 parameter_types [0] = MemberType;
4300 Parameter [] parms = new Parameter [1];
4301 parms [0] = new Parameter (Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4302 InternalParameters ip = new InternalParameters (
4303 parent, new Parameters (parms, null, Location));
4305 if (!CheckBase (parent))
4309 // Now define the accessors
4311 AddData = new MethodData (this, "add", TypeManager.void_type,
4312 parameter_types, ip, CallingConventions.Standard,
4313 (Add != null) ? Add.OptAttributes : null,
4314 ModFlags, flags, false);
4316 if (!AddData.Define (parent))
4319 AddBuilder = AddData.MethodBuilder;
4320 AddBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4322 RemoveData = new MethodData (this, "remove", TypeManager.void_type,
4323 parameter_types, ip, CallingConventions.Standard,
4324 (Remove != null) ? Remove.OptAttributes : null,
4325 ModFlags, flags, false);
4327 if (!RemoveData.Define (parent))
4330 RemoveBuilder = RemoveData.MethodBuilder;
4331 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4333 if (!IsExplicitImpl){
4334 EventBuilder = new MyEventBuilder (
4335 parent.TypeBuilder, Name, e_attr, MemberType);
4337 if (Add == null && Remove == null) {
4338 FieldBuilder = parent.TypeBuilder.DefineField (
4340 FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4341 TypeManager.RegisterPrivateFieldOfEvent (
4342 (EventInfo) EventBuilder, FieldBuilder);
4343 TypeManager.RegisterFieldBase (FieldBuilder, this);
4346 EventBuilder.SetAddOnMethod (AddBuilder);
4347 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4349 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4350 Report.Error (111, Location,
4351 "Class `" + parent.Name +
4352 "' already contains a definition for the event `" +
4361 void EmitDefaultMethod (EmitContext ec, bool is_add)
4363 ILGenerator ig = ec.ig;
4364 MethodInfo method = null;
4367 method = TypeManager.delegate_combine_delegate_delegate;
4369 method = TypeManager.delegate_remove_delegate_delegate;
4371 if ((ModFlags & Modifiers.STATIC) != 0) {
4372 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4373 ig.Emit (OpCodes.Ldarg_0);
4374 ig.Emit (OpCodes.Call, method);
4375 ig.Emit (OpCodes.Castclass, MemberType);
4376 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4378 ig.Emit (OpCodes.Ldarg_0);
4379 ig.Emit (OpCodes.Ldarg_0);
4380 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4381 ig.Emit (OpCodes.Ldarg_1);
4382 ig.Emit (OpCodes.Call, method);
4383 ig.Emit (OpCodes.Castclass, MemberType);
4384 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4386 ig.Emit (OpCodes.Ret);
4389 public void Emit (TypeContainer tc)
4393 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4394 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
4397 AddData.Emit (tc, Add.Block, Add);
4399 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4400 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4401 EmitDefaultMethod (ec, true);
4405 RemoveData.Emit (tc, Remove.Block, Remove);
4407 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4408 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4409 EmitDefaultMethod (ec, false);
4416 // FIXME: This does not handle:
4418 // int INTERFACENAME [ args ]
4423 // int this [ args ]
4425 public class Indexer : PropertyBase {
4427 const int AllowedModifiers =
4430 Modifiers.PROTECTED |
4431 Modifiers.INTERNAL |
4435 Modifiers.OVERRIDE |
4440 public string IndexerName;
4441 public string InterfaceIndexerName;
4444 // Are we implementing an interface ?
4446 bool IsImplementing = false;
4448 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4449 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4450 : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4453 ExplicitInterfaceName = int_type;
4456 public override bool Define (TypeContainer parent)
4458 PropertyAttributes prop_attr =
4459 PropertyAttributes.RTSpecialName |
4460 PropertyAttributes.SpecialName;
4462 if (!DoDefine (parent))
4465 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4466 if (IndexerName == null)
4467 IndexerName = "Item";
4468 else if (IsExplicitImpl)
4469 Report.Error (592, Location,
4470 "Attribute 'IndexerName' is not valid on this declaration " +
4471 "type. It is valid on `property' declarations only.");
4473 ShortName = IndexerName;
4474 if (IsExplicitImpl) {
4475 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4476 Name = InterfaceType.FullName + "." + IndexerName;
4478 InterfaceIndexerName = IndexerName;
4482 if (!CheckBase (parent))
4486 InternalParameters ip = new InternalParameters (parent, Parameters);
4488 GetData = new MethodData (this, "get", MemberType,
4489 ParameterTypes, ip, CallingConventions.Standard,
4490 Get.OptAttributes, ModFlags, flags, false);
4492 if (!GetData.Define (parent))
4495 GetBuilder = GetData.MethodBuilder;
4499 int top = ParameterTypes.Length;
4500 Type [] set_pars = new Type [top + 1];
4501 ParameterTypes.CopyTo (set_pars, 0);
4502 set_pars [top] = MemberType;
4504 Parameter [] fixed_parms = Parameters.FixedParameters;
4506 if (fixed_parms == null){
4507 throw new Exception ("We currently do not support only array arguments in an indexer");
4508 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4509 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4511 // Here is the problem: the `value' parameter has
4512 // to come *after* the array parameter in the declaration
4514 // X (object [] x, Type value)
4517 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4518 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4522 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4525 fixed_parms.CopyTo (tmp, 0);
4526 tmp [fixed_parms.Length] = new Parameter (
4527 Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4529 Parameters set_formal_params = new Parameters (tmp, null, Location);
4531 InternalParameters ip = new InternalParameters (parent, set_formal_params);
4533 SetData = new MethodData (this, "set", TypeManager.void_type,
4534 set_pars, ip, CallingConventions.Standard,
4535 Set.OptAttributes, ModFlags, flags, false);
4537 if (!SetData.Define (parent))
4540 SetBuilder = SetData.MethodBuilder;
4544 // Now name the parameters
4546 Parameter [] p = Parameters.FixedParameters;
4550 for (i = 0; i < p.Length; ++i) {
4552 GetBuilder.DefineParameter (
4553 i + 1, p [i].Attributes, p [i].Name);
4556 SetBuilder.DefineParameter (
4557 i + 1, p [i].Attributes, p [i].Name);
4562 SetBuilder.DefineParameter (
4563 i + 1, ParameterAttributes.None, /* was "value" */ this.Name);
4565 if (i != ParameterTypes.Length) {
4566 Parameter array_param = Parameters.ArrayParameter;
4567 SetBuilder.DefineParameter (
4568 i + 1, array_param.Attributes, array_param.Name);
4572 if (GetData != null)
4573 IsImplementing = GetData.IsImplementing;
4574 else if (SetData != null)
4575 IsImplementing = SetData.IsImplementing;
4578 // Define the PropertyBuilder if one of the following conditions are met:
4579 // a) we're not implementing an interface indexer.
4580 // b) the indexer has a different IndexerName and this is no
4581 // explicit interface implementation.
4583 if (!IsExplicitImpl) {
4584 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4585 IndexerName, prop_attr, MemberType, ParameterTypes);
4587 if (GetData != null)
4588 PropertyBuilder.SetGetMethod (GetBuilder);
4590 if (SetData != null)
4591 PropertyBuilder.SetSetMethod (SetBuilder);
4593 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4601 public class Operator : MemberCore {
4603 const int AllowedModifiers =
4609 const int RequiredModifiers =
4613 public enum OpType : byte {
4623 // Unary and Binary operators
4646 // Implicit and Explicit
4651 public readonly OpType OperatorType;
4652 public readonly Expression ReturnType;
4653 public readonly Expression FirstArgType, SecondArgType;
4654 public readonly string FirstArgName, SecondArgName;
4655 public readonly Block Block;
4656 public Attributes OptAttributes;
4657 public MethodBuilder OperatorMethodBuilder;
4659 public string MethodName;
4660 public Method OperatorMethod;
4662 public Operator (OpType type, Expression ret_type, int flags,
4663 Expression arg1type, string arg1name,
4664 Expression arg2type, string arg2name,
4665 Block block, Attributes attrs, Location loc)
4668 OperatorType = type;
4669 ReturnType = ret_type;
4670 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4671 FirstArgType = arg1type;
4672 FirstArgName = arg1name;
4673 SecondArgType = arg2type;
4674 SecondArgName = arg2name;
4676 OptAttributes = attrs;
4679 string Prototype (TypeContainer parent)
4681 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4682 SecondArgType + ")";
4685 public override bool Define (TypeContainer parent)
4688 MethodName = "op_" + OperatorType;
4690 if (SecondArgType != null)
4693 Parameter [] param_list = new Parameter [length];
4695 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4698 "User defined operators `" +
4699 Prototype (parent) +
4700 "' must be declared static and public");
4704 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4705 Parameter.Modifier.NONE, null);
4706 if (SecondArgType != null)
4707 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4708 Parameter.Modifier.NONE, null);
4710 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4711 new Parameters (param_list, null, Location),
4712 OptAttributes, Mono.MonoBASIC.Location.Null);
4714 OperatorMethod.IsOperator = true;
4715 OperatorMethod.Define (parent);
4717 if (OperatorMethod.MethodBuilder == null)
4720 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4722 Type [] param_types = OperatorMethod.ParameterTypes;
4723 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4724 Type return_type = OperatorMethod.GetReturnType ();
4725 Type first_arg_type = param_types [0];
4727 // Rules for conversion operators
4729 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4730 if (first_arg_type == return_type && first_arg_type == declaring_type){
4733 "User-defined conversion cannot take an object of the " +
4734 "enclosing type and convert to an object of the enclosing" +
4739 if (first_arg_type != declaring_type && return_type != declaring_type){
4742 "User-defined conversion must convert to or from the " +
4747 if (first_arg_type == TypeManager.object_type ||
4748 return_type == TypeManager.object_type){
4751 "User-defined conversion cannot convert to or from " +
4756 if (first_arg_type.IsInterface || return_type.IsInterface){
4759 "User-defined conversion cannot convert to or from an " +
4764 if (first_arg_type.IsSubclassOf (return_type) ||
4765 return_type.IsSubclassOf (first_arg_type)){
4768 "User-defined conversion cannot convert between types " +
4769 "that derive from each other");
4772 } else if (SecondArgType == null) {
4773 // Checks for Unary operators
4775 if (first_arg_type != declaring_type){
4778 "The parameter of a unary operator must be the " +
4783 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4784 if (return_type != declaring_type){
4787 "The parameter and return type for ++ and -- " +
4788 "must be the containing type");
4794 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4795 if (return_type != TypeManager.bool_type){
4798 "The return type of operator True or False " +
4805 // Checks for Binary operators
4807 if (first_arg_type != declaring_type &&
4808 param_types [1] != declaring_type){
4811 "One of the parameters of a binary operator must " +
4812 "be the containing type");
4820 public void Emit (TypeContainer parent)
4822 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4823 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4826 // abstract or extern methods have no bodies
4828 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4831 OperatorMethod.Block = Block;
4832 OperatorMethod.Emit (parent);
4835 public static string GetName (OpType ot)
4838 case OpType.LogicalNot:
4840 case OpType.OnesComplement:
4842 case OpType.Increment:
4844 case OpType.Decrement:
4850 case OpType.Addition:
4852 case OpType.Subtraction:
4854 case OpType.UnaryPlus:
4856 case OpType.UnaryNegation:
4858 case OpType.Multiply:
4860 case OpType.Division:
4862 case OpType.Modulus:
4864 case OpType.BitwiseAnd:
4866 case OpType.BitwiseOr:
4868 case OpType.ExclusiveOr:
4870 case OpType.LeftShift:
4872 case OpType.RightShift:
4874 case OpType.Equality:
4876 case OpType.Inequality:
4878 case OpType.GreaterThan:
4880 case OpType.LessThan:
4882 case OpType.GreaterThanOrEqual:
4884 case OpType.LessThanOrEqual:
4886 case OpType.Implicit:
4888 case OpType.Explicit:
4894 public override string ToString ()
4896 Type return_type = OperatorMethod.GetReturnType();
4897 Type [] param_types = OperatorMethod.ParameterTypes;
4899 if (SecondArgType == null)
4900 return String.Format (
4901 "{0} operator {1}({2})",
4902 TypeManager.MonoBASIC_Name (return_type),
4903 GetName (OperatorType),
4906 return String.Format (
4907 "{0} operator {1}({2}, {3})",
4908 TypeManager.MonoBASIC_Name (return_type),
4909 GetName (OperatorType),
4910 param_types [0], param_types [1]);
4915 // This is used to compare method signatures
4917 struct MethodSignature {
4919 public Type RetType;
4920 public Type [] Parameters;
4923 /// This delegate is used to extract methods which have the
4924 /// same signature as the argument
4926 public static MemberFilter method_signature_filter;
4929 /// This delegate is used to extract methods which have the
4930 /// same signature as the argument except for the name
4932 public static MemberFilter method_signature_noname_filter;
4935 /// This delegate is used to extract inheritable methods which
4936 /// have the same signature as the argument. By inheritable,
4937 /// this means that we have permissions to override the method
4938 /// from the current assembly and class
4940 public static MemberFilter inheritable_method_signature_filter;
4943 /// This delegate is used to extract inheritable methods which
4944 /// have the same signature as the argument. By inheritable,
4945 /// this means that we have permissions to override the method
4946 /// from the current assembly and class
4948 public static MemberFilter inheritable_property_signature_filter;
4950 static MethodSignature ()
4952 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4953 method_signature_noname_filter = new MemberFilter (MemberSignatureCompareNoName);
4954 inheritable_method_signature_filter = new MemberFilter (
4955 InheritableMemberSignatureCompare);
4956 inheritable_property_signature_filter = new MemberFilter (
4957 InheritablePropertySignatureCompare);
4960 public MethodSignature (string name, Type ret_type, Type [] parameters)
4965 if (parameters == null)
4966 Parameters = TypeManager.NoTypes;
4968 Parameters = parameters;
4971 public override int GetHashCode ()
4973 return Name.GetHashCode ();
4976 public override bool Equals (Object o)
4978 MethodSignature other = (MethodSignature) o;
4980 if (other.Name != Name)
4983 if (other.RetType != RetType)
4986 if (Parameters == null){
4987 if (other.Parameters == null)
4992 if (other.Parameters == null)
4995 int c = Parameters.Length;
4996 if (other.Parameters.Length != c)
4999 for (int i = 0; i < c; i++)
5000 if (other.Parameters [i] != Parameters [i])
5006 static bool MemberSignatureCompareNoName (MemberInfo m, object filter_criteria)
5008 return MemberSignatureCompare (m, filter_criteria, false);
5011 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
5013 return MemberSignatureCompare (m, filter_criteria, true);
5016 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria, bool use_name)
5018 MethodSignature sig = (MethodSignature) filter_criteria;
5020 if (use_name && (m.Name != sig.Name))
5024 MethodInfo mi = m as MethodInfo;
5025 PropertyInfo pi = m as PropertyInfo;
5028 ReturnType = mi.ReturnType;
5029 else if (pi != null)
5030 ReturnType = pi.PropertyType;
5035 // we use sig.RetType == null to mean `do not check the
5036 // method return value.
5038 if (sig.RetType != null)
5039 if (ReturnType != sig.RetType)
5044 args = TypeManager.GetArgumentTypes (mi);
5046 args = TypeManager.GetArgumentTypes (pi);
5047 Type [] sigp = sig.Parameters;
5049 if (args.Length != sigp.Length)
5052 for (int i = args.Length; i > 0; ){
5054 if (args [i] != sigp [i])
5061 // This filter should be used when we are requesting methods that
5062 // we want to override.
5064 // This makes a number of assumptions, for example
5065 // that the methods being extracted are of a parent
5066 // class (this means we know implicitly that we are
5067 // being called to find out about members by a derived
5070 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
5072 if (MemberSignatureCompare (m, filter_criteria)){
5073 MethodInfo mi = (MethodInfo) m;
5074 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
5076 // If only accessible to the current class.
5077 if (prot == MethodAttributes.Private)
5080 // If only accessible to the defining assembly or
5081 if (prot == MethodAttributes.FamANDAssem ||
5082 prot == MethodAttributes.Assembly){
5083 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
5089 // Anything else (FamOrAssembly and Public) is fine
5096 // This filter should be used when we are requesting properties that
5097 // we want to override.
5099 // This makes a number of assumptions, for example
5100 // that the methods being extracted are of a parent
5101 // class (this means we know implicitly that we are
5102 // being called to find out about members by a derived
5105 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
5107 if (MemberSignatureCompare (m, filter_criteria)){
5108 PropertyInfo pi = (PropertyInfo) m;
5110 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
5111 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
5113 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
5115 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
5117 // If only accessible to the current class.
5118 if (prot == MethodAttributes.Private)
5121 // If only accessible to the defining assembly or
5122 if (prot == MethodAttributes.FamANDAssem ||
5123 prot == MethodAttributes.Assembly){
5124 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
5130 // Anything else (FamOrAssembly and Public) is fine