2 // class.cs: Class and Struct handlers
4 // Author: Miguel de Icaza (miguel@gnu.org)
6 // Licensed under the terms of the GNU GPL
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
12 using System.Collections;
13 using System.Reflection;
14 using System.Reflection.Emit;
16 using System.Runtime.CompilerServices;
18 namespace Mono.CSharp {
21 /// This is the base class for structs and classes.
23 public class TypeContainer : DeclSpace {
24 // Holds a list of classes and structures
27 // Holds the list of properties
30 // Holds the list of enumerations
33 // Holds the list of delegates
36 // Holds the list of constructors
37 ArrayList instance_constructors;
39 // Holds the list of fields
42 // Holds a list of fields that have initializers
43 ArrayList initialized_fields;
45 // Holds a list of static fields that have initializers
46 ArrayList initialized_static_fields;
48 // Holds the list of constants
63 // Holds the operators
67 // Pointers to the default constructor and the default static constructor
69 Constructor default_constructor;
70 Constructor default_static_constructor;
73 // Whether we have seen a static constructor for this class or not
75 bool have_static_constructor = false;
78 // This one is computed after we can distinguish interfaces
79 // from classes from the arraylist `type_bases'
81 string base_class_name;
85 // Attributes for this type
86 protected Attributes attributes;
88 // Information in the case we are an attribute type
90 public AttributeTargets Targets;
91 public bool AllowMultiple;
92 public bool Inherited;
95 public TypeContainer (TypeContainer parent, string name, Location l)
96 : base (parent, name, l)
99 types = new ArrayList ();
106 base_class_name = null;
108 //Console.WriteLine ("New class " + name + " inside " + n);
111 public AdditionResult AddConstant (Const constant)
114 string name = constant.Name;
116 if ((res = IsValid (name)) != AdditionResult.Success)
119 if (constants == null)
120 constants = new ArrayList ();
122 constants.Add (constant);
123 DefineName (name, constant);
125 return AdditionResult.Success;
128 public AdditionResult AddEnum (Mono.CSharp.Enum e)
131 string name = e.Name;
133 if ((res = IsValid (name)) != AdditionResult.Success)
137 enums = new ArrayList ();
140 DefineName (name, e);
142 return AdditionResult.Success;
145 public AdditionResult AddClass (Class c)
148 string name = c.Name;
151 if ((res = IsValid (name)) != AdditionResult.Success)
154 DefineName (name, c);
157 return AdditionResult.Success;
160 public AdditionResult AddStruct (Struct s)
163 string name = s.Name;
165 if ((res = IsValid (name)) != AdditionResult.Success)
168 DefineName (name, s);
171 return AdditionResult.Success;
174 public AdditionResult AddDelegate (Delegate d)
177 string name = d.Name;
179 if ((res = IsValid (name)) != AdditionResult.Success)
182 if (delegates == null)
183 delegates = new ArrayList ();
185 DefineName (name, d);
188 return AdditionResult.Success;
191 public AdditionResult AddMethod (Method method)
193 string name = method.Name;
194 Object value = defined_names [name];
196 if (value != null && (!(value is Method)))
197 return AdditionResult.NameExists;
200 methods = new ArrayList ();
202 methods.Add (method);
204 DefineName (name, method);
206 return AdditionResult.Success;
209 public AdditionResult AddConstructor (Constructor c)
211 if (c.Name != Basename)
212 return AdditionResult.NotAConstructor;
214 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
217 have_static_constructor = true;
218 if (default_static_constructor != null){
219 Console.WriteLine ("I have a static constructor already");
220 Console.WriteLine (" " + default_static_constructor);
221 return AdditionResult.MethodExists;
224 default_static_constructor = c;
227 if (default_constructor != null)
228 return AdditionResult.MethodExists;
229 default_constructor = c;
232 if (instance_constructors == null)
233 instance_constructors = new ArrayList ();
235 instance_constructors.Add (c);
238 return AdditionResult.Success;
241 public AdditionResult AddInterface (Interface iface)
244 string name = iface.Name;
246 if ((res = IsValid (name)) != AdditionResult.Success)
249 if (interfaces == null)
250 interfaces = new ArrayList ();
251 interfaces.Add (iface);
252 DefineName (name, iface);
254 return AdditionResult.Success;
257 public AdditionResult AddField (Field field)
260 string name = field.Name;
262 if ((res = IsValid (name)) != AdditionResult.Success)
266 fields = new ArrayList ();
270 if (field.Initializer != null){
271 if ((field.ModFlags & Modifiers.STATIC) != 0){
272 if (initialized_static_fields == null)
273 initialized_static_fields = new ArrayList ();
275 initialized_static_fields.Add (field);
278 // We have not seen a static constructor,
279 // but we will provide static initialization of fields
281 have_static_constructor = true;
283 if (initialized_fields == null)
284 initialized_fields = new ArrayList ();
286 initialized_fields.Add (field);
290 DefineName (name, field);
291 return AdditionResult.Success;
294 public AdditionResult AddProperty (Property prop)
297 string name = prop.Name;
299 if ((res = IsValid (name)) != AdditionResult.Success)
302 if (properties == null)
303 properties = new ArrayList ();
305 properties.Add (prop);
306 DefineName (name, prop);
308 return AdditionResult.Success;
311 public AdditionResult AddEvent (Event e)
314 string name = e.Name;
316 if ((res = IsValid (name)) != AdditionResult.Success)
320 events = new ArrayList ();
323 DefineName (name, e);
325 return AdditionResult.Success;
328 public AdditionResult AddIndexer (Indexer i)
330 if (indexers == null)
331 indexers = new ArrayList ();
335 return AdditionResult.Success;
338 public AdditionResult AddOperator (Operator op)
340 if (operators == null)
341 operators = new ArrayList ();
345 return AdditionResult.Success;
348 public ArrayList Types {
354 public ArrayList Methods {
360 public ArrayList Constants {
366 public ArrayList Interfaces {
374 return base_class_name;
378 public ArrayList Bases {
388 public ArrayList Fields {
394 public ArrayList InstanceConstructors {
396 return instance_constructors;
400 public ArrayList Properties {
406 public ArrayList Events {
412 public ArrayList Enums {
418 public ArrayList Indexers {
424 public ArrayList Operators {
430 public ArrayList Delegates {
436 public Attributes OptAttributes {
443 // root_types contains all the types. All TopLevel types
444 // hence have a parent that points to `root_types', that is
445 // why there is a non-obvious test down here.
447 public bool IsTopLevel {
450 if (Parent.Parent == null)
457 public bool HaveStaticConstructor {
459 return have_static_constructor;
463 public virtual TypeAttributes TypeAttr {
465 return Modifiers.TypeAttr (ModFlags, this);
470 // Emits the instance field initializers
472 public bool EmitFieldInitializers (EmitContext ec, bool is_static)
475 ILGenerator ig = ec.ig;
478 fields = initialized_static_fields;
480 fields = initialized_fields;
485 foreach (Field f in fields){
486 Object init = f.Initializer;
489 if (init is Expression)
490 e = (Expression) init;
492 string base_type = f.Type.Substring (0, f.Type.IndexOf ("["));
493 string rank = f.Type.Substring (f.Type.IndexOf ("["));
494 e = new ArrayCreation (base_type, rank, (ArrayList) init, f.Location);
502 ig.Emit (OpCodes.Ldarg_0);
507 ig.Emit (OpCodes.Stsfld, f.FieldBuilder);
509 ig.Emit (OpCodes.Stfld, f.FieldBuilder);
517 // Defines the default constructors
519 void DefineDefaultConstructor (bool is_static)
524 c = new Constructor (Basename, Parameters.GetEmptyReadOnlyParameters (),
525 new ConstructorBaseInitializer (null, new Location (-1)),
529 mods = Modifiers.STATIC;
535 c.Block = new Block (null);
539 public void ReportStructInitializedInstanceError ()
541 string n = TypeBuilder.FullName;
543 foreach (Field f in initialized_fields){
546 "`" + n + "." + f.Name + "': can not have " +
547 "instance field initializers in structs");
551 struct TypeAndMethods {
553 public MethodInfo [] methods;
555 // Far from ideal, but we want to avoid creating a copy
557 public Type [][] args;
560 // This flag on the method says `We found a match, but
561 // because it was private, we could not use the match
563 public bool [] found;
567 // This array keeps track of the pending implementations
569 TypeAndMethods [] pending_implementations;
572 // Returns a list of the abstract methods that are exposed by all of our
573 // parents that we must implement. Notice that this `flattens' the
574 // method search space, and takes into account overrides.
576 ArrayList GetAbstractMethods (Type t)
578 ArrayList list = null;
579 bool searching = true;
580 Type current_type = t;
586 current_type, MemberTypes.Method,
587 BindingFlags.Public | BindingFlags.Instance |
588 BindingFlags.DeclaredOnly,
589 virtual_method_filter, null);
591 if (current_type == TypeManager.object_type)
594 current_type = current_type.BaseType;
595 if (!current_type.IsAbstract)
602 int count = mi.Length;
606 if (count == 1 && !(mi [0] is MethodBase))
609 list = Expression.CopyNewMethods (list, mi);
615 for (int i = 0; i < list.Count; i++){
616 while (list.Count > i && !((MethodInfo) list [i]).IsAbstract)
627 // Registers the required method implementations for this class
629 // Register method implementations are either abstract methods
630 // flagged as such on the base class or interface methods
632 public void RegisterRequiredImplementations ()
634 Type [] ifaces = TypeBuilder.GetInterfaces ();
635 Type b = TypeBuilder.BaseType;
640 Type x = TypeBuilder;
643 Type [] iff = x.GetInterfaces ();
644 Console.WriteLine ("Type: " + x.Name);
646 foreach (Type tt in iff){
647 Console.WriteLine (" Iface: " + tt.Name);
653 icount = ifaces.Length;
656 // If we are implementing an abstract class, and we are not
657 // ourselves abstract, and there are abstract methods (C# allows
658 // abstract classes that have no abstract methods), then allocate
661 // We also pre-compute the methods.
663 bool implementing_abstract = (b.IsAbstract && !TypeBuilder.IsAbstract);
664 ArrayList abstract_methods = null;
666 if (implementing_abstract){
667 abstract_methods = GetAbstractMethods (b);
669 if (abstract_methods == null)
670 implementing_abstract = false;
673 int total = icount + (implementing_abstract ? 1 : 0);
677 pending_implementations = new TypeAndMethods [total];
681 foreach (Type t in ifaces){
684 if (t is TypeBuilder){
687 iface = RootContext.TypeManager.LookupInterface (t);
689 mi = iface.GetMethods ();
691 mi = t.GetMethods ();
693 int count = mi.Length;
694 pending_implementations [i].type = t;
695 pending_implementations [i].methods = mi;
696 pending_implementations [i].args = new Type [count][];
697 pending_implementations [i].found = new bool [count];
700 foreach (MethodInfo m in mi){
701 Type [] types = TypeManager.GetArgumentTypes (m);
703 pending_implementations [i].args [j] = types;
710 if (abstract_methods != null){
711 int count = abstract_methods.Count;
712 pending_implementations [i].methods = new MethodInfo [count];
714 abstract_methods.CopyTo (pending_implementations [i].methods, 0);
715 pending_implementations [i].found = new bool [count];
716 pending_implementations [i].args = new Type [count][];
717 pending_implementations [i].type = TypeBuilder;
720 foreach (MemberInfo m in abstract_methods){
721 MethodInfo mi = (MethodInfo) m;
723 Type [] types = TypeManager.GetArgumentTypes (mi);
725 pending_implementations [i].args [j] = types;
731 public static string MakeFQN (string nsn, string name)
733 string prefix = (nsn == "" ? "" : nsn + ".");
735 return prefix + name;
738 Type LookupInterfaceOrClass (object builder, string ns, string name, bool is_class, out bool error)
740 TypeContainer parent;
744 name = MakeFQN (ns, name);
746 t = RootContext.TypeManager.LookupType (name);
751 parent = (Class) RootContext.Tree.Classes [name];
753 parent = (Struct) RootContext.Tree.Structs [name];
755 if (parent == null) {
758 if (RootContext.Tree.Enums != null)
759 en = (Enum) RootContext.Tree.Enums [name];
762 t = en.DefineEnum (builder);
770 t = parent.DefineType (builder);
772 Report.Error (146, "Class definition is circular: `"+name+"'");
784 // returns the type for an interface or a class, this will recursively
785 // try to define the types that it depends on.
787 Type GetInterfaceOrClass (object builder, string name, bool is_class)
793 // Attempt to lookup the class on our namespace and all it's implicit parents
795 for (string ns = Namespace.Name; ns != null; ns = RootContext.ImplicitParent (ns)) {
797 t = LookupInterfaceOrClass (builder, ns, name, is_class, out error);
806 // Attempt to do a direct unqualified lookup
808 t = LookupInterfaceOrClass (builder, "", name, is_class, out error);
816 // Attempt to lookup the class on any of the `using'
820 for (Namespace ns = Namespace; ns != null; ns = ns.Parent){
822 t = LookupInterfaceOrClass (builder, ns.Name, name, is_class, out error);
830 // Now check the using clause list
832 ArrayList using_list = ns.UsingTable;
834 if (using_list == null)
837 foreach (string n in using_list){
838 t = LookupInterfaceOrClass (builder, n, name, is_class, out error);
848 Report.Error (246, Location, "Can not find type `"+name+"'");
853 /// This function computes the Base class and also the
854 /// list of interfaces that the class or struct @c implements.
856 /// The return value is an array (might be null) of
857 /// interfaces implemented (as Types).
859 /// The @parent argument is set to the parent object or null
860 /// if this is `System.Object'.
862 Type [] GetClassBases (object builder, bool is_class, out Type parent, out bool error)
864 ArrayList bases = Bases;
873 parent = TypeManager.value_type;
877 if (RootContext.StdLib)
878 parent = TypeManager.object_type;
879 else if (Name != "System.Object")
880 parent = TypeManager.object_type;
883 // If we are compiling our runtime,
884 // and we are defining ValueType, then our
885 // parent is `System.Object'.
887 if (!RootContext.StdLib && Name == "System.ValueType")
888 parent = TypeManager.object_type;
895 // Bases should be null if there are no bases at all
900 string name = (string) bases [0];
901 Type first = GetInterfaceOrClass (builder, name, is_class);
912 parent = TypeManager.object_type;
919 Type [] ifaces = new Type [count-start];
921 for (i = start, j = 0; i < count; i++, j++){
922 string name = (string) bases [i];
923 Type t = GetInterfaceOrClass (builder, name, is_class);
930 if (is_class == false && !t.IsInterface){
931 Report.Error (527, "In Struct `" + Name + "', type `"+
932 name +"' is not an interface");
941 detail = " (a class can not inherit from a struct/enum)";
943 Report.Error (509, "class `"+ Name +
944 "': Cannot inherit from sealed class `"+
945 bases [i]+"'"+detail);
952 Report.Error (527, "In Class `" + Name + "', type `"+
953 name+"' is not an interface");
966 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
968 public TypeBuilder DefineType (object parent_builder)
975 if (TypeBuilder != null)
988 ifaces = GetClassBases (parent_builder, is_class, out parent, out error);
994 if (parent == TypeManager.enum_type ||
995 (parent == TypeManager.value_type && RootContext.StdLib) ||
996 parent == TypeManager.delegate_type ||
997 parent == TypeManager.array_type){
999 644, Location, "`" + Name + "' cannot inherit from " +
1000 "special class `" + TypeManager.CSharpName (parent) + "'");
1005 if (parent_builder is ModuleBuilder) {
1006 ModuleBuilder builder = (ModuleBuilder) parent_builder;
1008 // Structs with no fields need to have a ".size 1"
1012 if (!is_class && Fields == null)
1013 TypeBuilder = builder.DefineType (Name,
1016 PackingSize.Unspecified, 1);
1019 // classes or structs with fields
1021 TypeBuilder = builder.DefineType (Name,
1026 TypeBuilder builder = (System.Reflection.Emit.TypeBuilder) parent_builder;
1029 // Structs with no fields need to have a ".size 1"
1032 if (!is_class && Fields == null)
1033 TypeBuilder = builder.DefineNestedType (Basename,
1036 PackingSize.Unspecified);
1039 // classes or structs with fields
1041 TypeBuilder = builder.DefineNestedType (Basename,
1047 RootContext.TypeManager.AddUserType (Name, TypeBuilder, this);
1048 RootContext.RegisterOrder (this);
1050 if (Types != null) {
1051 foreach (TypeContainer tc in Types)
1052 tc.DefineType (TypeBuilder);
1055 if (Delegates != null) {
1056 foreach (Delegate d in Delegates)
1057 d.DefineDelegate (TypeBuilder);
1060 if (Enums != null) {
1061 foreach (Enum en in Enums)
1062 en.DefineEnum (TypeBuilder);
1071 /// Defines the MemberCore objects that are in the `list' Arraylist
1073 /// The `defined_names' array contains a list of members defined in
1076 static ArrayList remove_list = new ArrayList ();
1077 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
1081 remove_list.Clear ();
1083 foreach (MemberCore mc in list){
1084 if (!mc.Define (this)){
1085 remove_list.Add (mc);
1089 if (defined_names == null)
1092 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
1095 if (RootContext.WarningLevel >= 4){
1096 if ((mc.ModFlags & Modifiers.NEW) != 0)
1097 Report109 (mc.Location, mc);
1102 if (defined_names [idx] is PropertyInfo &&
1103 ((mc.ModFlags & Modifiers.OVERRIDE) != 0)){
1107 #if WANT_TO_VERIFY_SIGNATURES_HERE
1108 if (defined_names [idx] is MethodBase && mc is MethodCore){
1109 MethodBase mb = (MethodBase) defined_names [idx];
1110 MethodCore met = (MethodCore) mc;
1112 if ((mb.IsVirtual || mb.IsAbstract) &&
1113 (mc.ModFlags & Modifiers.OVERRIDE) != 0)
1117 // FIXME: Compare the signatures here. If they differ,
1118 // then: `continue;'
1121 if ((mc.ModFlags & Modifiers.NEW) == 0)
1122 Report108 (mc.Location, defined_names [idx]);
1125 foreach (object o in remove_list)
1128 remove_list.Clear ();
1132 /// Populates our TypeBuilder with fields and methods
1134 public override bool Define (TypeContainer parent)
1136 MemberInfo [] defined_names = null;
1138 if (RootContext.WarningLevel > 1){
1142 // This code throws an exception in the comparer
1143 // I guess the string is not an object?
1145 ptype = TypeBuilder.BaseType;
1147 defined_names = FindMembers (
1148 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1149 BindingFlags.Public | BindingFlags.Instance |
1150 BindingFlags.Static, null, null);
1152 Array.Sort (defined_names, mif_compare);
1156 if (constants != null)
1157 DefineMembers (constants, defined_names);
1160 DefineMembers (fields, defined_names);
1163 if (instance_constructors == null){
1164 if (default_constructor == null)
1165 DefineDefaultConstructor (false);
1168 if (initialized_static_fields != null &&
1169 default_static_constructor == null)
1170 DefineDefaultConstructor (true);
1173 if (this is Struct){
1175 // Structs can not have initialized instance
1178 if (initialized_static_fields != null &&
1179 default_static_constructor == null)
1180 DefineDefaultConstructor (true);
1182 if (initialized_fields != null)
1183 ReportStructInitializedInstanceError ();
1186 RegisterRequiredImplementations ();
1189 // Constructors are not in the defined_names array
1191 if (instance_constructors != null)
1192 DefineMembers (instance_constructors, null);
1194 if (default_static_constructor != null)
1195 default_static_constructor.Define (this);
1197 if (methods != null)
1198 DefineMembers (methods, null);
1200 if (properties != null)
1201 DefineMembers (properties, defined_names);
1204 DefineMembers (events, defined_names);
1206 if (indexers != null) {
1207 foreach (Indexer i in Indexers)
1211 if (operators != null)
1212 DefineMembers (operators, null);
1215 DefineMembers (enums, defined_names);
1217 if (delegates != null)
1218 DefineMembers (delegates, defined_names);
1224 /// Looks up the alias for the name
1226 public string LookupAlias (string name)
1228 if (Namespace != null)
1229 return Namespace.LookupAlias (name);
1235 /// This function is based by a delegate to the FindMembers routine
1237 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1243 /// This filter is used by FindMembers, and we just keep
1244 /// a global for the filter to `AlwaysAccept'
1246 static MemberFilter accepting_filter;
1248 static bool IsVirtualFilter (MemberInfo m, object filterCriteria)
1250 if (!(m is MethodInfo))
1253 return ((MethodInfo) m).IsVirtual;
1257 /// This filter is used by FindMembers, and it is used to
1258 /// extract only virtual/abstract fields
1260 static MemberFilter virtual_method_filter;
1263 /// A member comparission method based on name only
1265 static IComparer mif_compare;
1267 static TypeContainer ()
1269 accepting_filter = new MemberFilter (AlwaysAccept);
1270 virtual_method_filter = new MemberFilter (IsVirtualFilter);
1271 mif_compare = new MemberInfoCompare ();
1275 /// This method returns the members of this type just like Type.FindMembers would
1276 /// Only, we need to use this for types which are _being_ defined because MS'
1277 /// implementation can't take care of that.
1280 // FIXME: return an empty static array instead of null, that cleans up
1281 // some code and is consistent with some coding conventions I just found
1283 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
1284 MemberFilter filter, object criteria)
1286 ArrayList members = new ArrayList ();
1289 filter = accepting_filter;
1291 if ((mt & MemberTypes.Field) != 0) {
1292 if (fields != null) {
1293 foreach (Field f in fields) {
1294 FieldBuilder fb = f.FieldBuilder;
1295 if (filter (fb, criteria) == true)
1300 if (constants != null) {
1301 foreach (Const con in constants) {
1302 FieldBuilder fb = con.FieldBuilder;
1303 if (filter (fb, criteria) == true)
1309 if ((mt & MemberTypes.Method) != 0) {
1310 if (methods != null) {
1311 foreach (Method m in methods) {
1312 MethodBuilder mb = m.MethodBuilder;
1314 // If we are in transit, ignore
1315 // This case arises when we are still defining a PInvoke method
1316 // and we hit FindMembers because of the need to resolve named
1317 // arguments inside of Attribute.DefinePInvokeMethod
1321 if (filter (mb, criteria) == true)
1326 if (operators != null){
1327 foreach (Operator o in operators) {
1328 MethodBuilder ob = o.OperatorMethodBuilder;
1330 if (filter (ob, criteria) == true)
1335 if (properties != null){
1336 foreach (Property p in properties){
1340 if (b != null && filter (b, criteria) == true)
1344 if (b != null && filter (b, criteria) == true)
1350 if ((mt & MemberTypes.Event) != 0) {
1352 foreach (Event e in events) {
1353 if (filter (e.EventBuilder, criteria) == true)
1354 members.Add (e.EventBuilder);
1358 if ((mt & MemberTypes.Property) != 0){
1359 if (properties != null)
1360 foreach (Property p in properties) {
1361 if (filter (p.PropertyBuilder, criteria) == true) {
1362 members.Add (p.PropertyBuilder);
1366 if (indexers != null)
1367 foreach (Indexer ix in indexers) {
1368 if (filter (ix.PropertyBuilder, criteria) == true) {
1369 members.Add (ix.PropertyBuilder);
1374 if ((mt & MemberTypes.NestedType) != 0) {
1377 foreach (TypeContainer t in Types)
1378 if (filter (t.TypeBuilder, criteria) == true)
1379 members.Add (t.TypeBuilder);
1382 foreach (Enum en in Enums)
1383 if (filter (en.TypeBuilder, criteria) == true)
1384 members.Add (en.TypeBuilder);
1388 if ((mt & MemberTypes.Constructor) != 0){
1389 if (instance_constructors != null){
1390 foreach (Constructor c in instance_constructors){
1391 ConstructorBuilder cb = c.ConstructorBuilder;
1393 if (filter (cb, criteria) == true)
1398 if (default_static_constructor != null){
1399 ConstructorBuilder cb =
1400 default_static_constructor.ConstructorBuilder;
1402 if (filter (cb, criteria) == true)
1408 // Lookup members in parent if requested.
1410 if ((bf & BindingFlags.DeclaredOnly) == 0){
1413 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1415 members.AddRange (mi);
1418 int count = members.Count;
1420 MemberInfo [] mi = new MemberInfo [count];
1421 members.CopyTo (mi);
1428 public MemberInfo GetFieldFromEvent (EventExpr event_expr)
1430 EventInfo ei = event_expr.EventInfo;
1432 foreach (Event e in events) {
1434 if (e.FieldBuilder == null)
1437 if (Type.FilterName (e.FieldBuilder, ei.Name))
1438 return e.FieldBuilder;
1444 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1445 MemberFilter filter, object criteria)
1447 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1450 return tc.FindMembers (mt, bf, filter, criteria);
1452 return t.FindMembers (mt, bf, filter, criteria);
1456 // FindMethods will look for methods not only in the type `t', but in
1457 // any interfaces implemented by the type.
1459 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1460 MemberFilter filter, object criteria)
1466 /// Whether the specified method is an interface method implementation
1470 /// If a method in Type `t' (or null to look in all interfaces
1471 /// and the base abstract class) with name `Name', return type `ret_type' and
1472 /// arguments `args' implements an interface, this method will
1473 /// return the MethodInfo that this method implements.
1475 /// This will remove the method from the list of "pending" methods
1476 /// that are required to be implemented for this class as a side effect.
1479 public MethodInfo IsInterfaceMethod (Type t, string Name, Type ret_type, Type [] args,
1482 int arg_len = args.Length;
1484 if (pending_implementations == null)
1487 foreach (TypeAndMethods tm in pending_implementations){
1488 if (!(t == null || tm.type == t))
1492 foreach (MethodInfo m in tm.methods){
1498 if (Name != m.Name){
1503 if (ret_type != m.ReturnType){
1504 if (!((ret_type == null && m.ReturnType == TypeManager.void_type) ||
1505 (m.ReturnType == null && ret_type == TypeManager.void_type)))
1513 // Check if we have the same parameters
1515 if (tm.args [i].Length != arg_len){
1520 int j, top = args.Length;
1523 for (j = 0; j < top; j++){
1524 if (tm.args [i][j] != args[j]){
1535 tm.methods [i] = null;
1536 tm.found [i] = true;
1540 // If a specific type was requested, we can stop now.
1548 /// C# allows this kind of scenarios:
1549 /// interface I { void M (); }
1550 /// class X { public void M (); }
1551 /// class Y : X, I { }
1553 /// For that case, we create an explicit implementation function
1556 void DefineProxy (Type iface, MethodInfo parent_method, MethodInfo iface_method,
1559 MethodBuilder proxy;
1561 string proxy_name = iface.Name + "." + iface_method.Name;
1563 proxy = TypeBuilder.DefineMethod (
1565 MethodAttributes.HideBySig |
1566 MethodAttributes.NewSlot |
1567 MethodAttributes.Virtual,
1568 CallingConventions.Standard | CallingConventions.HasThis,
1569 parent_method.ReturnType, args);
1571 int top = args.Length;
1572 ILGenerator ig = proxy.GetILGenerator ();
1574 ig.Emit (OpCodes.Ldarg_0);
1575 for (int i = 0; i < top; i++){
1578 ig.Emit (OpCodes.Ldarg_1); break;
1580 ig.Emit (OpCodes.Ldarg_2); break;
1582 ig.Emit (OpCodes.Ldarg_3); break;
1584 ig.Emit (OpCodes.Ldarg, i - 1); break;
1587 ig.Emit (OpCodes.Call, parent_method);
1588 ig.Emit (OpCodes.Ret);
1590 TypeBuilder.DefineMethodOverride (proxy, iface_method);
1594 /// This function tells whether one of our parent classes implements
1595 /// the given method (which turns out, it is valid to have an interface
1596 /// implementation in a parent
1598 bool ParentImplements (Type iface_type, MethodInfo mi)
1602 Type [] args = TypeManager.GetArgumentTypes (mi);
1603 ms = new MethodSignature (mi.Name, mi.ReturnType, args);
1604 MemberInfo [] list = FindMembers (
1605 TypeBuilder.BaseType, MemberTypes.Method | MemberTypes.Property,
1606 BindingFlags.Public | BindingFlags.Instance,
1607 MethodSignature.method_signature_filter, ms);
1609 if (list == null || list.Length == 0)
1612 DefineProxy (iface_type, (MethodInfo) list [0], mi, args);
1617 /// Verifies that any pending abstract methods or interface methods
1618 /// were implemented.
1620 bool VerifyPendingMethods ()
1622 int top = pending_implementations.Length;
1623 bool errors = false;
1626 for (i = 0; i < top; i++){
1627 Type type = pending_implementations [i].type;
1630 foreach (MethodInfo mi in pending_implementations [i].methods){
1634 if (type.IsInterface){
1635 if (ParentImplements (type, mi))
1640 if (pending_implementations [i].found [j])
1641 extra = ". (method might be private or static)";
1644 "`" + Name + "' does not implement " +
1645 "interface member `" +
1646 type.FullName + "." + mi.Name + "'" + extra);
1650 "`" + Name + "' does not implement " +
1651 "inherited abstract member `" +
1652 type.FullName + "." + mi.Name + "'");
1662 /// Emits the values for the constants
1664 public void EmitConstants ()
1666 if (constants != null)
1667 foreach (Const con in constants)
1668 con.EmitConstant (this);
1673 /// Emits the code, this step is performed after all
1674 /// the types, enumerations, constructors
1678 if (instance_constructors != null)
1679 foreach (Constructor c in instance_constructors)
1682 if (default_static_constructor != null)
1683 default_static_constructor.Emit (this);
1685 if (methods != null)
1686 foreach (Method m in methods)
1689 if (operators != null)
1690 foreach (Operator o in operators)
1693 if (properties != null)
1694 foreach (Property p in properties)
1697 if (indexers != null) {
1698 foreach (Indexer ix in indexers)
1701 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (this, ModFlags, Location);
1703 TypeBuilder.SetCustomAttribute (cb);
1707 foreach (Field f in fields)
1710 if (events != null){
1711 foreach (Event e in Events)
1715 if (pending_implementations != null)
1716 if (!VerifyPendingMethods ())
1719 EmitContext ec = new EmitContext (
1720 this, Mono.CSharp.Location.Null, null, null,
1723 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1726 // Check for internal or private fields that were never assigned
1728 if (RootContext.WarningLevel >= 3){
1729 foreach (Field f in fields){
1730 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1735 169, f.Location, "Private field " +
1736 MakeName (f.Name) + " is never used");
1741 // Only report 649 on level 4
1743 if (RootContext.WarningLevel < 4)
1746 if ((f.status & Field.Status.ASSIGNED) != 0)
1751 "Field " + MakeName (f.Name) + " is never assigned " +
1752 " to and will always have its default value");
1756 // if (types != null)
1757 // foreach (TypeContainer tc in types)
1761 public override void CloseType ()
1766 TypeBuilder.CreateType ();
1768 } catch (TypeLoadException){
1770 // This is fine, the code still created the type
1772 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1773 // Console.WriteLine (e.Message);
1777 foreach (Enum en in Enums)
1781 foreach (TypeContainer tc in Types)
1785 foreach (TypeContainer tc in Types)
1786 if (!(tc is Struct))
1790 if (Delegates != null)
1791 foreach (Delegate d in Delegates)
1795 public string MakeName (string n)
1797 return "`" + Name + "." + n + "'";
1800 public void Report108 (Location l, MemberInfo mi)
1803 108, l, "The keyword new is required on " +
1804 MakeName (mi.Name) + " because it hides `" +
1805 mi.ReflectedType.Name + "." + mi.Name + "'");
1808 public void Report109 (Location l, MemberCore mc)
1811 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1812 "inherited member, the keyword new is not required");
1815 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1821 // Performs the validation on a Method's modifiers (properties have
1822 // the same properties).
1824 public bool MethodModifiersValid (int flags, string n, Location loc)
1826 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1827 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1829 string name = MakeName (n);
1832 // At most one of static, virtual or override
1834 if ((flags & Modifiers.STATIC) != 0){
1835 if ((flags & vao) != 0){
1837 112, loc, "static method " + name + "can not be marked " +
1838 "as virtual, abstract or override");
1843 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1846 " marked as override cannot be marked as new or virtual");
1851 // If the declaration includes the abstract modifier, then the
1852 // declaration does not include static, virtual or extern
1854 if ((flags & Modifiers.ABSTRACT) != 0){
1855 if ((flags & Modifiers.EXTERN) != 0){
1857 180, loc, name + " can not be both abstract and extern");
1861 if ((flags & Modifiers.VIRTUAL) != 0){
1863 503, loc, name + " can not be both abstract and virtual");
1867 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1870 " is abstract but its container class is not");
1876 if ((flags & Modifiers.PRIVATE) != 0){
1877 if ((flags & vao) != 0){
1880 " virtual or abstract members can not be private");
1885 if ((flags & Modifiers.SEALED) != 0){
1886 if ((flags & Modifiers.OVERRIDE) == 0){
1889 " cannot be sealed because it is not an override");
1898 // Returns true if `type' is as accessible as the flags `flags'
1899 // given for this member
1901 static public bool AsAccessible (Type type, int flags)
1906 Hashtable builder_and_args;
1908 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1910 if (builder_and_args == null)
1911 builder_and_args = new Hashtable ();
1916 public class Class : TypeContainer {
1918 // Modifiers allowed in a class declaration
1920 public const int AllowedModifiers =
1923 Modifiers.PROTECTED |
1924 Modifiers.INTERNAL |
1926 Modifiers.ABSTRACT |
1930 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1931 : base (parent, name, l)
1935 if (parent.Parent == null)
1936 accmods = Modifiers.INTERNAL;
1938 accmods = Modifiers.PRIVATE;
1940 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1941 this.attributes = attrs;
1945 // FIXME: How do we deal with the user specifying a different
1948 public override TypeAttributes TypeAttr {
1950 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1955 public class Struct : TypeContainer {
1957 // Modifiers allowed in a struct declaration
1959 public const int AllowedModifiers =
1962 Modifiers.PROTECTED |
1963 Modifiers.INTERNAL |
1967 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1968 : base (parent, name, l)
1972 if (parent.Parent == null)
1973 accmods = Modifiers.INTERNAL;
1975 accmods = Modifiers.PRIVATE;
1977 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1979 this.ModFlags |= Modifiers.SEALED;
1980 this.attributes = attrs;
1985 // FIXME: Allow the user to specify a different set of attributes
1986 // in some cases (Sealed for example is mandatory for a class,
1987 // but what SequentialLayout can be changed
1989 public override TypeAttributes TypeAttr {
1991 return base.TypeAttr |
1992 TypeAttributes.SequentialLayout |
1993 TypeAttributes.Sealed |
1994 TypeAttributes.BeforeFieldInit;
1999 public abstract class MethodCore : MemberCore {
2000 public readonly Parameters Parameters;
2004 // Parameters, cached for semantic analysis.
2006 InternalParameters parameter_info;
2008 public MethodCore (string name, Parameters parameters, Location l)
2012 Parameters = parameters;
2016 // Returns the System.Type array for the parameters of this method
2018 Type [] parameter_types;
2019 public Type [] ParameterTypes (TypeContainer parent)
2021 if (Parameters == null)
2022 return TypeManager.NoTypes;
2024 if (parameter_types == null)
2025 parameter_types = Parameters.GetParameterInfo (parent);
2027 return parameter_types;
2030 public InternalParameters ParameterInfo
2033 return parameter_info;
2037 parameter_info = value;
2041 public Block Block {
2051 public CallingConventions GetCallingConvention (bool is_class)
2053 CallingConventions cc = 0;
2055 cc = Parameters.GetCallingConvention ();
2058 if ((ModFlags & Modifiers.STATIC) == 0)
2059 cc |= CallingConventions.HasThis;
2061 // FIXME: How is `ExplicitThis' used in C#?
2066 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
2069 // Define each type attribute (in/out/ref) and
2070 // the argument names.
2072 Parameter [] p = Parameters.FixedParameters;
2076 MethodBuilder mb = null;
2077 ConstructorBuilder cb = null;
2079 if (builder is MethodBuilder)
2080 mb = (MethodBuilder) builder;
2082 cb = (ConstructorBuilder) builder;
2086 for (i = 0; i < p.Length; i++) {
2087 ParameterBuilder pb;
2090 pb = cb.DefineParameter (
2091 i + 1, p [i].Attributes, p [i].Name);
2093 pb = mb.DefineParameter (
2094 i + 1, p [i].Attributes, p [i].Name);
2096 Attributes attr = p [i].OptAttributes;
2098 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
2101 if (i != parameters.Length) {
2102 ParameterBuilder pb;
2104 Parameter array_param = Parameters.ArrayParameter;
2106 pb = cb.DefineParameter (
2107 i + 1, array_param.Attributes,
2110 pb = mb.DefineParameter (
2111 i + 1, array_param.Attributes,
2114 CustomAttributeBuilder a = new CustomAttributeBuilder (
2115 TypeManager.cons_param_array_attribute, new object [0]);
2117 pb.SetCustomAttribute (a);
2122 public class Method : MethodCore {
2123 public readonly string ReturnType;
2124 public MethodBuilder MethodBuilder;
2125 public readonly Attributes OptAttributes;
2127 MethodAttributes flags;
2130 /// Modifiers allowed in a class declaration
2132 const int AllowedModifiers =
2135 Modifiers.PROTECTED |
2136 Modifiers.INTERNAL |
2141 Modifiers.OVERRIDE |
2142 Modifiers.ABSTRACT |
2147 // return_type can be "null" for VOID values.
2149 public Method (string return_type, int mod, string name, Parameters parameters,
2150 Attributes attrs, Location l)
2151 : base (name, parameters, l)
2153 ReturnType = return_type;
2154 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l);
2155 OptAttributes = attrs;
2159 // Returns the `System.Type' for the ReturnType of this
2160 // function. Provides a nice cache. (used between semantic analysis
2161 // and actual code generation
2163 Type type_return_type;
2165 public Type GetReturnType (TypeContainer parent)
2167 if (type_return_type == null)
2168 type_return_type = RootContext.LookupType (
2169 parent, ReturnType, false, Location);
2171 return type_return_type;
2174 void DuplicatEntryPoint (MethodInfo b)
2178 "Program `" + RootContext.CodeGen.FileName +
2179 "' has more than one entry point defined: `" +
2180 b.DeclaringType.Name + "." + b.Name + "'");
2186 public override bool Define (TypeContainer parent)
2188 Type ret_type = GetReturnType (parent);
2189 Type [] parameters = ParameterTypes (parent);
2191 MethodInfo implementing;
2192 Type iface_type = null;
2193 string iface = "", short_name;
2194 bool explicit_impl = false;
2196 // Check if the return type and arguments were correct
2197 if (ret_type == null || parameters == null)
2200 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
2203 flags = Modifiers.MethodAttr (ModFlags);
2206 // verify accessibility
2208 if (!TypeContainer.AsAccessible (ret_type, ModFlags))
2211 if (ret_type.IsPointer && !UnsafeOK (parent))
2214 foreach (Type partype in parameters){
2215 if (!TypeContainer.AsAccessible (partype, ModFlags))
2217 if (partype.IsPointer && !UnsafeOK (parent))
2225 // Verify if the parent has a type with the same name, and then
2226 // check whether we have to create a new slot for it or not.
2228 Type ptype = parent.TypeBuilder.BaseType;
2230 // ptype is only null for System.Object while compiling corlib.
2232 MethodSignature ms = new MethodSignature (Name, ret_type, parameters);
2233 MemberInfo [] mi, mi_static, mi_instance;
2235 mi_static = TypeContainer.FindMembers (
2236 ptype, MemberTypes.Method,
2237 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2238 MethodSignature.inheritable_method_signature_filter, ms);
2240 mi_instance = TypeContainer.FindMembers (
2241 ptype, MemberTypes.Method,
2242 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2243 MethodSignature.inheritable_method_signature_filter,
2246 if (mi_instance != null && mi_instance.Length > 0){
2248 } else if (mi_static != null && mi_static.Length > 0)
2253 if (mi != null && mi.Length > 0){
2254 if (!CheckMethodAgainstBase (parent, (MethodInfo) mi [0])){
2258 if ((ModFlags & Modifiers.NEW) != 0)
2259 WarningNotHiding (parent);
2261 if ((ModFlags & Modifiers.OVERRIDE) != 0)
2262 Report.Error (115, Location,
2263 parent.MakeName (Name) +
2264 " no suitable methods found to override");
2266 } else if ((ModFlags & Modifiers.NEW) != 0)
2267 WarningNotHiding (parent);
2270 // If we implement an interface, extract the interface name.
2273 if (Name.IndexOf (".") != -1){
2274 int pos = Name.LastIndexOf (".");
2275 iface = Name.Substring (0, pos);
2277 iface_type = RootContext.LookupType (parent, iface, false, Location);
2278 short_name = Name.Substring (pos + 1);
2280 if (iface_type == null)
2283 // Compute the full name that we need to export
2284 Name = iface_type.FullName + "." + short_name;
2285 explicit_impl = true;
2290 // Check if we are an implementation of an interface method or
2293 implementing = parent.IsInterfaceMethod (
2294 iface_type, short_name, ret_type, parameters, false);
2297 // For implicit implementations, make sure we are public, for
2298 // explicit implementations, make sure we are private.
2300 if (implementing != null){
2302 // Setting null inside this block will trigger a more
2303 // verbose error reporting for missing interface implementations
2305 // The "candidate" function has been flagged already
2306 // but it wont get cleared
2308 if (iface_type == null){
2309 if ((ModFlags & Modifiers.PUBLIC) == 0)
2310 implementing = null;
2312 if ((ModFlags & Modifiers.STATIC) != 0)
2313 implementing = null;
2315 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2317 106, Location, "`public' or `abstract' modifiers "+
2318 "are not allowed in explicit interface declarations"
2320 implementing = null;
2326 // If implementing is still valid, set flags
2328 if (implementing != null){
2329 if (implementing.DeclaringType.IsInterface)
2330 flags |= MethodAttributes.NewSlot;
2333 MethodAttributes.Virtual |
2334 MethodAttributes.HideBySig;
2336 // If not abstract, then we can set Final.
2337 if (((flags & MethodAttributes.Abstract) == 0) &&
2338 implementing.DeclaringType.IsInterface)
2339 flags |= MethodAttributes.Final;
2344 parent.IsInterfaceMethod (
2345 iface_type, short_name, ret_type, parameters, true);
2348 Attribute dllimport_attr = null;
2349 if (OptAttributes != null && OptAttributes.AttributeSections != null) {
2350 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2351 if (asec.Attributes == null)
2354 foreach (Attribute a in asec.Attributes)
2355 if (a.Name.IndexOf ("DllImport") != -1) {
2356 flags |= MethodAttributes.PinvokeImpl;
2363 // Finally, define the method
2366 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2367 EmitContext ec = new EmitContext (
2368 parent, Location, null, GetReturnType (parent), ModFlags);
2370 MethodBuilder = dllimport_attr.DefinePInvokeMethod (
2371 ec, parent.TypeBuilder,
2372 Name, flags, ret_type, parameters);
2375 MethodBuilder = parent.TypeBuilder.DefineMethod (
2377 GetCallingConvention (parent is Class),
2378 ret_type, parameters);
2380 if (implementing != null && explicit_impl)
2381 parent.TypeBuilder.DefineMethodOverride (
2382 MethodBuilder, implementing);
2385 if (MethodBuilder == null)
2389 // HACK because System.Reflection.Emit is lame
2391 ParameterInfo = new InternalParameters (parent, Parameters);
2393 if (!TypeManager.RegisterMethod (MethodBuilder, ParameterInfo,
2397 "Class `" + parent.Name + "' already contains a definition with " +
2398 " the same return value and parameter types for method `" +
2404 // This is used to track the Entry Point,
2406 // FIXME: Allow pluggable entry point, check arguments, etc.
2408 if (Name == "Main" &&
2409 ((ModFlags & Modifiers.STATIC) != 0) &&
2410 (RootContext.MainClass == null ||
2411 RootContext.MainClass == parent.TypeBuilder.FullName)){
2412 if (RootContext.EntryPoint != null){
2413 DuplicatEntryPoint (MethodBuilder);
2414 DuplicatEntryPoint (RootContext.EntryPoint);
2416 RootContext.EntryPoint = MethodBuilder;
2419 // FIXME: Verify that the method signature
2420 // is valid for an entry point, and report
2431 public void Emit (TypeContainer parent)
2436 if ((flags & MethodAttributes.PinvokeImpl) == 0)
2437 ig = MethodBuilder.GetILGenerator ();
2441 ec = new EmitContext (parent, Location, ig, GetReturnType (parent), ModFlags);
2443 if (OptAttributes != null)
2444 Attribute.ApplyAttributes (ec, MethodBuilder, this, OptAttributes, Location);
2447 LabelParameters (ec, ParameterTypes (parent), MethodBuilder);
2450 // abstract or extern methods have no bodies
2452 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
2456 // Handle destructors specially
2458 // FIXME: This code generates buggy code
2460 if (Name == "Finalize" && type_return_type == TypeManager.void_type)
2461 EmitDestructor (ec);
2463 ec.EmitTopBlock (Block, Location);
2466 void EmitDestructor (EmitContext ec)
2468 ILGenerator ig = ec.ig;
2470 Label finish = ig.DefineLabel ();
2471 bool old_in_try = ec.InTry;
2472 Expression member_lookup;
2474 ig.BeginExceptionBlock ();
2476 ec.ReturnLabel = finish;
2477 ec.EmitTopBlock (Block, Location);
2478 ec.InTry = old_in_try;
2480 ig.MarkLabel (finish);
2481 bool old_in_finally = ec.InFinally;
2482 ec.InFinally = true;
2483 ig.BeginFinallyBlock ();
2485 member_lookup = Expression.MemberLookup (
2486 ec, ec.TypeContainer.TypeBuilder.BaseType, "Finalize",
2487 MemberTypes.Method, Expression.AllBindingFlags, Location);
2489 if (member_lookup != null){
2490 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
2492 ig.Emit (OpCodes.Ldarg_0);
2493 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
2495 ec.InFinally = old_in_finally;
2497 ig.EndExceptionBlock ();
2498 //ig.MarkLabel (ec.ReturnLabel);
2499 ig.Emit (OpCodes.Ret);
2503 public abstract class ConstructorInitializer {
2504 ArrayList argument_list;
2505 ConstructorInfo parent_constructor;
2508 public ConstructorInitializer (ArrayList argument_list, Location location)
2510 this.argument_list = argument_list;
2511 this.location = location;
2514 public ArrayList Arguments {
2516 return argument_list;
2520 public bool Resolve (EmitContext ec)
2522 Expression parent_constructor_group;
2525 if (argument_list != null){
2526 for (int i = argument_list.Count; i > 0; ){
2529 Argument a = (Argument) argument_list [i];
2530 if (!a.Resolve (ec, location))
2535 if (this is ConstructorBaseInitializer)
2536 t = ec.TypeContainer.TypeBuilder.BaseType;
2538 t = ec.TypeContainer.TypeBuilder;
2540 parent_constructor_group = Expression.MemberLookup (
2542 MemberTypes.Constructor,
2543 BindingFlags.Public | BindingFlags.Instance, location);
2545 if (parent_constructor_group == null){
2546 Console.WriteLine ("Could not find a constructor in our parent");
2550 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2551 (MethodGroupExpr) parent_constructor_group, argument_list, location);
2553 if (parent_constructor == null){
2554 Console.WriteLine ("Could not locate a proper overload function");
2561 public void Emit (EmitContext ec)
2563 ec.ig.Emit (OpCodes.Ldarg_0);
2564 if (argument_list != null)
2565 Invocation.EmitArguments (ec, null, argument_list);
2566 ec.ig.Emit (OpCodes.Call, parent_constructor);
2570 public class ConstructorBaseInitializer : ConstructorInitializer {
2571 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2576 public class ConstructorThisInitializer : ConstructorInitializer {
2577 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2582 public class Constructor : MethodCore {
2583 public ConstructorBuilder ConstructorBuilder;
2584 public ConstructorInitializer Initializer;
2585 public Attributes OptAttributes;
2588 // Modifiers allowed for a constructor.
2590 const int AllowedModifiers =
2592 Modifiers.PROTECTED |
2593 Modifiers.INTERNAL |
2599 // The spec claims that static is not permitted, but
2600 // my very own code has static constructors.
2602 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2603 : base (name, args, l)
2609 // Returns true if this is a default constructor
2611 public bool IsDefault ()
2613 if ((ModFlags & Modifiers.STATIC) != 0)
2614 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2615 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2618 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2619 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2620 (Initializer is ConstructorBaseInitializer) &&
2621 (Initializer.Arguments == null);
2625 // Creates the ConstructorBuilder
2627 public override bool Define (TypeContainer parent)
2629 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2630 MethodAttributes.SpecialName);
2632 Type [] parameters = ParameterTypes (parent);
2634 if ((ModFlags & Modifiers.STATIC) != 0)
2635 ca |= MethodAttributes.Static;
2637 if (parent is Struct && parameters.Length == 0){
2640 "Structs can not contain explicit parameterless " +
2644 ca |= MethodAttributes.Public | MethodAttributes.HideBySig;
2647 foreach (Type partype in parameters)
2648 if (!TypeContainer.AsAccessible (partype, ModFlags))
2651 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2652 ca, GetCallingConvention (parent is Class), parameters);
2655 // HACK because System.Reflection.Emit is lame
2657 ParameterInfo = new InternalParameters (parent, Parameters);
2659 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, parameters)) {
2662 "Class `" +parent.Name+ "' already contains a definition with the " +
2663 "same return value and parameter types for constructor `" + Name
2674 public void Emit (TypeContainer parent)
2676 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2677 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2679 if (parent is Class && ((ModFlags & Modifiers.STATIC) == 0)){
2680 if (Initializer == null)
2681 Initializer = new ConstructorBaseInitializer (null, parent.Location);
2683 if (!Initializer.Resolve (ec)){
2684 Console.WriteLine ("Could not resolve initializer: " + parent.Name);
2688 LabelParameters (ec, ParameterTypes (parent), ConstructorBuilder);
2691 // Classes can have base initializers and instance field initializers.
2693 if (parent is Class){
2694 if ((ModFlags & Modifiers.STATIC) == 0){
2695 Initializer.Emit (ec);
2696 parent.EmitFieldInitializers (ec, false);
2700 if ((ModFlags & Modifiers.STATIC) != 0)
2701 parent.EmitFieldInitializers (ec, true);
2703 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2705 ec.EmitTopBlock (Block, Location);
2709 public class Field : MemberCore {
2710 public readonly string Type;
2711 public readonly Object Initializer;
2712 public readonly Attributes OptAttributes;
2713 public FieldBuilder FieldBuilder;
2714 public Status status;
2717 public enum Status : byte { ASSIGNED = 1, USED = 2 }
2721 // Modifiers allowed in a class declaration
2723 const int AllowedModifiers =
2726 Modifiers.PROTECTED |
2727 Modifiers.INTERNAL |
2730 Modifiers.VOLATILE |
2734 public Field (string type, int mod, string name, Object expr_or_array_init,
2735 Attributes attrs, Location loc)
2739 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, loc);
2740 Initializer = expr_or_array_init;
2741 OptAttributes = attrs;
2744 public override bool Define (TypeContainer parent)
2746 Type t = RootContext.LookupType (parent, Type, false, Location);
2751 if (!TypeContainer.AsAccessible (t, ModFlags))
2754 if (t.IsPointer && !UnsafeOK (parent))
2757 if (RootContext.WarningLevel > 1){
2758 Type ptype = parent.TypeBuilder.BaseType;
2760 // ptype is only null for System.Object while compiling corlib.
2764 mi = TypeContainer.FindMembers (
2765 ptype, MemberTypes.Method,
2766 BindingFlags.Public |
2767 BindingFlags.Static | BindingFlags.Instance,
2768 System.Type.FilterName, Name);
2772 if ((ModFlags & Modifiers.VOLATILE) != 0){
2774 if (TypeManager.IsEnumType (t))
2775 t = TypeManager.EnumToUnderlying (t);
2777 if (!((t == TypeManager.bool_type) ||
2778 (t == TypeManager.sbyte_type) ||
2779 (t == TypeManager.byte_type) ||
2780 (t == TypeManager.short_type) ||
2781 (t == TypeManager.ushort_type) ||
2782 (t == TypeManager.int32_type) ||
2783 (t == TypeManager.uint32_type) ||
2784 (t == TypeManager.char_type) ||
2785 (t == TypeManager.float_type))){
2787 677, Location, parent.MakeName (Name) +
2788 " A volatile field can not be of type `" +
2789 TypeManager.CSharpName (t) + "'");
2795 FieldBuilder = parent.TypeBuilder.DefineField (
2796 Name, t, Modifiers.FieldAttr (ModFlags));
2798 TypeManager.RegisterField (FieldBuilder, this);
2802 public void Emit (TypeContainer tc)
2804 EmitContext ec = new EmitContext (tc, Location, null,
2805 FieldBuilder.FieldType, ModFlags);
2807 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
2811 public class Property : MemberCore {
2812 public readonly string Type;
2813 public Block Get, Set;
2814 public PropertyBuilder PropertyBuilder;
2815 public Attributes OptAttributes;
2816 public MethodBuilder GetBuilder, SetBuilder;
2819 // The type, once we compute it.
2823 const int AllowedModifiers =
2826 Modifiers.PROTECTED |
2827 Modifiers.INTERNAL |
2831 Modifiers.OVERRIDE |
2832 Modifiers.ABSTRACT |
2836 public Property (string type, string name, int mod_flags, Block get_block, Block set_block,
2837 Attributes attrs, Location loc)
2841 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
2844 OptAttributes = attrs;
2848 // Checks our base implementation if any
2850 bool CheckBase (TypeContainer parent)
2853 // Find properties with the same name on the base class
2855 MemberInfo [] props;
2856 MemberInfo [] props_static = TypeContainer.FindMembers (
2857 parent.TypeBuilder.BaseType,
2858 MemberTypes.All, BindingFlags.Public | BindingFlags.Static,
2859 System.Type.FilterName, Name);
2861 MemberInfo [] props_instance = TypeContainer.FindMembers (
2862 parent.TypeBuilder.BaseType,
2863 MemberTypes.All, BindingFlags.Public | BindingFlags.Instance,
2864 System.Type.FilterName, Name);
2867 // Find if we have anything
2869 if (props_static != null && props_static.Length > 0)
2870 props = props_static;
2871 else if (props_instance != null && props_instance.Length > 0)
2872 props = props_instance;
2877 // If we have something on the base.
2878 if (props != null && props.Length > 0){
2881 // Currently we expect only to get 1 match at most from our
2882 // base class, maybe we can get more than one, investigate
2883 // whether this is possible
2885 if (props.Length > 1)
2886 throw new Exception ("How do we handle this?");
2888 PropertyInfo pi = (PropertyInfo) props [0];
2890 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
2891 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
2893 MethodInfo reference = inherited_get == null ?
2894 inherited_set : inherited_get;
2896 if (!CheckMethodAgainstBase (parent, reference))
2899 if ((ModFlags & Modifiers.NEW) != 0)
2900 WarningNotHiding (parent);
2902 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2903 Report.Error (115, Location,
2904 parent.MakeName (Name) +
2905 " no suitable methods found to override");
2912 bool DefineMethod (TypeContainer parent, Type iface_type, string short_name, bool is_get)
2914 MethodAttributes flags = Modifiers.MethodAttr (ModFlags);
2915 Type [] parameters = TypeManager.NoTypes;
2916 MethodInfo implementing;
2920 flags |= MethodAttributes.HideBySig |
2921 MethodAttributes.SpecialName;
2924 fn_type = PropertyType;
2925 name = "get_" + short_name;
2927 name = "set_" + short_name;
2928 parameters = new Type [1];
2929 parameters [0] = PropertyType;
2930 fn_type = TypeManager.void_type;
2933 implementing = parent.IsInterfaceMethod (
2934 iface_type, name, fn_type, parameters, false);
2937 // For implicit implementations, make sure we are public, for
2938 // explicit implementations, make sure we are private.
2940 if (implementing != null){
2942 // Setting null inside this block will trigger a more
2943 // verbose error reporting for missing interface implementations
2945 // The "candidate" function has been flagged already
2946 // but it wont get cleared
2948 if (iface_type == null){
2949 if ((ModFlags & Modifiers.PUBLIC) == 0)
2950 implementing = null;
2951 if ((ModFlags & Modifiers.STATIC) != 0)
2952 implementing = null;
2954 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2956 106, Location, "`public' or `abstract' modifiers "+
2957 "are not allowed in explicit interface declarations"
2959 implementing = null;
2965 // If implementing is still valid, set flags
2967 if (implementing != null){
2969 // When implementing interface methods, set NewSlot.
2971 if (implementing.DeclaringType.IsInterface)
2972 flags |= MethodAttributes.NewSlot;
2975 MethodAttributes.Virtual |
2976 MethodAttributes.HideBySig;
2978 // If an interface implementation, then we can set Final.
2979 if (((flags & MethodAttributes.Abstract) == 0) &&
2980 implementing.DeclaringType.IsInterface)
2981 flags |= MethodAttributes.Final;
2984 // clear the pending flag
2986 parent.IsInterfaceMethod (
2987 iface_type, name, fn_type, parameters, true);
2991 // If this is not an explicit interface implementation,
2992 // clear implementing, as it is only used for explicit
2993 // interface implementation
2995 if (Name.IndexOf (".") == -1)
2996 implementing = null;
2999 GetBuilder = parent.TypeBuilder.DefineMethod (
3000 name, flags, PropertyType, null);
3001 PropertyBuilder.SetGetMethod (GetBuilder);
3003 if (implementing != null)
3004 parent.TypeBuilder.DefineMethodOverride (
3005 GetBuilder, implementing);
3008 // HACK because System.Reflection.Emit is lame
3010 InternalParameters ip = new InternalParameters (
3011 parent, Parameters.GetEmptyReadOnlyParameters ());
3013 if (!TypeManager.RegisterMethod (GetBuilder, ip, null)) {
3014 Report.Error (111, Location,
3015 "Class `" + parent.Name +
3016 "' already contains a definition with the " +
3017 "same return value and parameter types as the " +
3018 "'get' method of property `" + Name + "'");
3022 SetBuilder = parent.TypeBuilder.DefineMethod (
3023 name, flags, null, parameters);
3025 if (implementing != null)
3026 parent.TypeBuilder.DefineMethodOverride (
3027 SetBuilder, implementing);
3029 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3030 PropertyBuilder.SetSetMethod (SetBuilder);
3033 // HACK because System.Reflection.Emit is lame
3035 Parameter [] parms = new Parameter [1];
3036 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3037 InternalParameters ip = new InternalParameters (
3038 parent, new Parameters (parms, null, Location));
3040 if (!TypeManager.RegisterMethod (SetBuilder, ip, parameters)) {
3043 "Class `" + parent.Name +
3044 "' already contains a definition with the " +
3045 "same return value and parameter types as the " +
3046 "'set' method of property `" + Name + "'");
3054 public override bool Define (TypeContainer parent)
3056 Type iface_type = null;
3059 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3062 // Lookup Type, verify validity
3063 PropertyType = RootContext.LookupType (parent, Type, false, Location);
3064 if (PropertyType == null)
3067 // verify accessibility
3068 if (!TypeContainer.AsAccessible (PropertyType, ModFlags))
3071 if (PropertyType.IsPointer && !UnsafeOK (parent))
3074 if (!CheckBase (parent))
3078 // Check for explicit interface implementation
3080 if (Name.IndexOf (".") != -1){
3081 int pos = Name.LastIndexOf (".");
3082 string iface = Name.Substring (0, pos);
3084 iface_type = RootContext.LookupType (parent, iface, false, Location);
3085 if (iface_type == null)
3088 short_name = Name.Substring (pos + 1);
3090 // Compute the full name that we need to export.
3091 Name = iface_type.FullName + "." + short_name;
3095 // FIXME - PropertyAttributes.HasDefault ?
3097 PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
3098 PropertyAttributes.SpecialName;
3100 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3101 Name, prop_attr, PropertyType, null);
3104 if (!DefineMethod (parent, iface_type, short_name, true))
3108 if (!DefineMethod (parent, iface_type, short_name, false))
3112 // HACK for the reasons exposed above
3114 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3117 "Class `" + parent.Name +
3118 "' already contains a definition for the property `" +
3126 public void Emit (TypeContainer tc)
3131 ec = new EmitContext (tc, Location, null, PropertyType, ModFlags);
3132 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3136 // abstract or extern properties have no bodies
3138 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3142 ig = GetBuilder.GetILGenerator ();
3143 ec = new EmitContext (tc, Location, ig, PropertyType, ModFlags);
3145 ec.EmitTopBlock (Get, Location);
3149 ig = SetBuilder.GetILGenerator ();
3150 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3152 ec.EmitTopBlock (Set, Location);
3159 /// Gigantic workaround for lameness in SRE follows :
3160 /// This class derives from EventInfo and attempts to basically
3161 /// wrap around the EventBuilder so that FindMembers can quickly
3162 /// return this in it search for members
3164 public class MyEventBuilder : EventInfo {
3167 // We use this to "point" to our Builder which is
3168 // not really a MemberInfo
3170 EventBuilder MyBuilder;
3173 // We "catch" and wrap these methods
3175 MethodInfo raise, remove, add;
3177 EventAttributes attributes;
3178 Type declaring_type, reflected_type, event_type;
3181 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3183 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3185 // And now store the values in our own fields.
3187 declaring_type = type_builder;
3189 // FIXME : This is supposed to be MyBuilder but since that doesn't
3190 // derive from Type, I have no clue what to do with this.
3191 reflected_type = null;
3193 attributes = event_attr;
3195 this.event_type = event_type;
3199 // Methods that you have to override. Note that you only need
3200 // to "implement" the variants that take the argument (those are
3201 // the "abstract" methods, the others (GetAddMethod()) are
3204 public override MethodInfo GetAddMethod (bool nonPublic)
3209 public override MethodInfo GetRemoveMethod (bool nonPublic)
3214 public override MethodInfo GetRaiseMethod (bool nonPublic)
3220 // These methods make "MyEventInfo" look like a Builder
3222 public void SetRaiseMethod (MethodBuilder raiseMethod)
3224 raise = raiseMethod;
3225 MyBuilder.SetRaiseMethod (raiseMethod);
3228 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3230 remove = removeMethod;
3231 MyBuilder.SetRemoveOnMethod (removeMethod);
3234 public void SetAddOnMethod (MethodBuilder addMethod)
3237 MyBuilder.SetAddOnMethod (addMethod);
3240 public void SetCustomAttribute (CustomAttributeBuilder cb)
3242 MyBuilder.SetCustomAttribute (cb);
3245 public override object [] GetCustomAttributes (bool inherit)
3247 // FIXME : There's nothing which can be seemingly done here because
3248 // we have no way of getting at the custom attribute objects of the
3253 public override object [] GetCustomAttributes (Type t, bool inherit)
3255 // FIXME : Same here !
3259 public override bool IsDefined (Type t, bool b)
3264 public override EventAttributes Attributes {
3270 public override string Name {
3276 public override Type DeclaringType {
3278 return declaring_type;
3282 public override Type ReflectedType {
3284 return reflected_type;
3288 public Type EventType {
3295 public class Event : MemberCore {
3297 const int AllowedModifiers =
3300 Modifiers.PROTECTED |
3301 Modifiers.INTERNAL |
3306 Modifiers.OVERRIDE |
3310 public readonly string Type;
3311 public readonly Object Initializer;
3312 public readonly Block Add;
3313 public readonly Block Remove;
3314 public MyEventBuilder EventBuilder;
3315 public FieldBuilder FieldBuilder;
3316 public Attributes OptAttributes;
3319 MethodBuilder AddBuilder, RemoveBuilder;
3322 public Event (string type, string name, Object init, int flags, Block add_block,
3323 Block rem_block, Attributes attrs, Location loc)
3328 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE, loc);
3331 OptAttributes = attrs;
3334 public override bool Define (TypeContainer parent)
3336 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3339 MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
3340 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3342 EventType = RootContext.LookupType (parent, Type, false, Location);
3343 if (EventType == null)
3346 if (!TypeContainer.AsAccessible (EventType, ModFlags))
3349 if (EventType.IsPointer && !UnsafeOK (parent))
3352 if (!EventType.IsSubclassOf (TypeManager.delegate_type)) {
3353 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3354 "' : event must be of a delegate type");
3358 Type [] parameters = new Type [1];
3359 parameters [0] = EventType;
3361 EventBuilder = new MyEventBuilder (parent.TypeBuilder, Name, e_attr, EventType);
3363 if (Add == null && Remove == null)
3364 FieldBuilder = parent.TypeBuilder.DefineField (Name, EventType, FieldAttributes.Private);
3367 // Now define the accessors
3370 AddBuilder = parent.TypeBuilder.DefineMethod (
3371 "add_" + Name, m_attr, null, parameters);
3372 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3373 EventBuilder.SetAddOnMethod (AddBuilder);
3376 // HACK because System.Reflection.Emit is lame
3378 Parameter [] parms = new Parameter [1];
3379 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3380 InternalParameters ip = new InternalParameters (
3381 parent, new Parameters (parms, null, Location));
3383 if (!TypeManager.RegisterMethod (AddBuilder, ip, parameters)) {
3384 Report.Error (111, Location,
3385 "Class `" + parent.Name + "' already contains a definition with the " +
3386 "same return value and parameter types for the " +
3387 "'add' method of event `" + Name + "'");
3391 RemoveBuilder = parent.TypeBuilder.DefineMethod (
3392 "remove_" + Name, m_attr, null, parameters);
3393 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3394 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3397 // HACK because System.Reflection.Emit is lame
3400 if (!TypeManager.RegisterMethod (RemoveBuilder, ip, parameters)) {
3401 Report.Error (111, Location,
3402 "Class `" + parent.Name + "' already contains a definition with the " +
3403 "same return value and parameter types for the " +
3404 "'remove' method of event `" + Name + "'");
3408 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3409 Report.Error (111, Location,
3410 "Class `" + parent.Name +
3411 "' already contains a definition for the event `" +
3419 void EmitDefaultMethod (EmitContext ec, bool is_add)
3421 ILGenerator ig = ec.ig;
3422 MethodInfo method = null;
3425 method = TypeManager.delegate_combine_delegate_delegate;
3427 method = TypeManager.delegate_remove_delegate_delegate;
3429 ig.Emit (OpCodes.Ldarg_0);
3430 ig.Emit (OpCodes.Ldarg_0);
3431 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3432 ig.Emit (OpCodes.Ldarg_1);
3433 ig.Emit (OpCodes.Call, method);
3434 ig.Emit (OpCodes.Castclass, EventType);
3435 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3436 ig.Emit (OpCodes.Ret);
3439 public void Emit (TypeContainer tc)
3444 ig = AddBuilder.GetILGenerator ();
3445 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3448 ec.EmitTopBlock (Add, Location);
3450 EmitDefaultMethod (ec, true);
3452 ig = RemoveBuilder.GetILGenerator ();
3453 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3456 ec.EmitTopBlock (Remove, Location);
3458 EmitDefaultMethod (ec, false);
3460 ec = new EmitContext (tc, Location, null, EventType, ModFlags);
3461 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3468 // FIXME: This does not handle:
3470 // int INTERFACENAME [ args ]
3474 // int this [ args ]
3476 public class Indexer : MemberCore {
3478 const int AllowedModifiers =
3481 Modifiers.PROTECTED |
3482 Modifiers.INTERNAL |
3486 Modifiers.OVERRIDE |
3490 public readonly string Type;
3491 public readonly string InterfaceType;
3492 public readonly Parameters FormalParameters;
3493 public readonly Block Get;
3494 public readonly Block Set;
3495 public Attributes OptAttributes;
3496 public MethodBuilder GetBuilder;
3497 public MethodBuilder SetBuilder;
3498 public PropertyBuilder PropertyBuilder;
3499 public Type IndexerType;
3501 public Indexer (string type, string int_type, int flags, Parameters parms,
3502 Block get_block, Block set_block, Attributes attrs, Location loc)
3507 InterfaceType = int_type;
3508 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE, loc);
3509 FormalParameters = parms;
3512 OptAttributes = attrs;
3515 void DefineMethod (TypeContainer parent, Type iface_type,
3516 Type ret_type, string name,
3517 Type [] parameters, bool is_get)
3519 MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
3520 MethodInfo implementing;
3522 implementing = parent.IsInterfaceMethod (
3523 iface_type, name, ret_type, parameters, false);
3526 // Setting null inside this block will trigger a more
3527 // verbose error reporting for missing interface implementations
3529 // The "candidate" function has been flagged already
3530 // but it wont get cleared
3532 if (implementing != null){
3533 if (iface_type == null){
3534 if ((ModFlags & Modifiers.PUBLIC) == 0)
3535 implementing = null;
3536 if ((ModFlags & Modifiers.STATIC) != 0)
3537 implementing = null;
3539 if((ModFlags&(Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
3542 "`public' or `abstract' modifiers are not "+
3543 "allowed in explicit interface declarations"
3545 implementing = null;
3549 if (implementing != null){
3551 // When implementing interface methods, set NewSlot.
3553 if (implementing.DeclaringType.IsInterface)
3554 attr |= MethodAttributes.NewSlot;
3557 MethodAttributes.Virtual |
3558 MethodAttributes.HideBySig;
3560 // If an interface implementing, then we can set final.
3561 if (((attr & MethodAttributes.Abstract) == 0) &&
3562 implementing.DeclaringType.IsInterface)
3563 attr |= MethodAttributes.Final;
3566 // clear the pending flag
3568 parent.IsInterfaceMethod (
3569 iface_type, name, ret_type, parameters, true);
3573 // If this is not an explicit interface implementation,
3574 // clear implementing, as it is only used for explicit
3575 // interface implementation
3577 if (Name.IndexOf (".") == -1)
3578 implementing = null;
3582 string meth_name = "get_Item";
3583 if (iface_type != null)
3584 meth_name = iface_type + ".get_Item";
3586 GetBuilder = parent.TypeBuilder.DefineMethod (
3587 meth_name, attr, IndexerType, parameters);
3589 if (implementing != null)
3590 parent.TypeBuilder.DefineMethodOverride (
3591 GetBuilder, implementing);
3594 PropertyBuilder.SetGetMethod (GetBuilder);
3597 string meth_name = "set_Item";
3599 if (iface_type != null)
3600 meth_name = iface_type + ".set_Item";
3602 SetBuilder = parent.TypeBuilder.DefineMethod (
3603 meth_name, attr, null, parameters);
3604 if (implementing != null)
3605 parent.TypeBuilder.DefineMethodOverride (
3606 SetBuilder, implementing);
3608 PropertyBuilder.SetSetMethod (SetBuilder);
3612 public override bool Define (TypeContainer parent)
3614 PropertyAttributes prop_attr =
3615 PropertyAttributes.RTSpecialName |
3616 PropertyAttributes.SpecialName;
3619 IndexerType = RootContext.LookupType (parent, Type, false, Location);
3620 Type [] parameters = FormalParameters.GetParameterInfo (parent);
3622 // Check if the return type and arguments were correct
3623 if (IndexerType == null || parameters == null)
3626 if (!parent.MethodModifiersValid (ModFlags, InterfaceType == null ?
3627 "this" : InterfaceType, Location))
3631 // verify accessibility and unsafe pointers
3633 if (!TypeContainer.AsAccessible (IndexerType, ModFlags))
3636 if (IndexerType.IsPointer && !UnsafeOK (parent))
3639 foreach (Type partype in parameters){
3640 if (!TypeContainer.AsAccessible (partype, ModFlags))
3642 if (partype.IsPointer && !UnsafeOK (parent))
3649 Type iface_type = null;
3651 if (InterfaceType != null){
3652 iface_type = RootContext.LookupType (parent, InterfaceType, false, Location);
3653 if (iface_type == null)
3658 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3659 TypeManager.IndexerPropertyName (parent.TypeBuilder),
3660 prop_attr, IndexerType, parameters);
3663 DefineMethod (parent, iface_type, IndexerType, "get_Item", parameters, true);
3664 InternalParameters pi = new InternalParameters (parent, FormalParameters);
3665 if (!TypeManager.RegisterMethod (GetBuilder, pi, parameters)) {
3666 Report.Error (111, Location,
3667 "Class `" + parent.Name +
3668 "' already contains a definition with the " +
3669 "same return value and parameter types for the " +
3676 int top = parameters.Length;
3677 Type [] set_pars = new Type [top + 1];
3678 parameters.CopyTo (set_pars, 0);
3679 set_pars [top] = IndexerType;
3681 Parameter [] fixed_parms = FormalParameters.FixedParameters;
3683 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
3685 fixed_parms.CopyTo (tmp, 0);
3686 tmp [fixed_parms.Length] = new Parameter (
3687 Type, "value", Parameter.Modifier.NONE, null);
3689 Parameters set_formal_params = new Parameters (tmp, null, Location);
3692 parent, iface_type, TypeManager.void_type,
3693 "set_Item", set_pars, false);
3695 InternalParameters ip = new InternalParameters (parent, set_formal_params);
3697 if (!TypeManager.RegisterMethod (SetBuilder, ip, set_pars)) {
3700 "Class `" + parent.Name + "' already contains a " +
3701 "definition with the " +
3702 "same return value and parameter types for the " +
3709 // Now name the parameters
3711 Parameter [] p = FormalParameters.FixedParameters;
3715 for (i = 0; i < p.Length; ++i) {
3717 GetBuilder.DefineParameter (
3718 i + 1, p [i].Attributes, p [i].Name);
3721 SetBuilder.DefineParameter (
3722 i + 1, p [i].Attributes, p [i].Name);
3726 SetBuilder.DefineParameter (
3727 i + 1, ParameterAttributes.None, "value");
3729 if (i != parameters.Length) {
3730 Parameter array_param = FormalParameters.ArrayParameter;
3731 SetBuilder.DefineParameter (i + 1, array_param.Attributes,
3736 TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
3741 public void Emit (TypeContainer tc)
3746 ec = new EmitContext (tc, Location, null, IndexerType, ModFlags);
3747 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3750 ig = GetBuilder.GetILGenerator ();
3751 ec = new EmitContext (tc, Location, ig, IndexerType, ModFlags);
3753 ec.EmitTopBlock (Get, Location);
3757 ig = SetBuilder.GetILGenerator ();
3758 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3760 ec.EmitTopBlock (Set, Location);
3765 public class Operator : MemberCore {
3767 const int AllowedModifiers =
3773 const int RequiredModifiers =
3777 public enum OpType : byte {
3787 // Unary and Binary operators
3810 // Implicit and Explicit
3815 public readonly OpType OperatorType;
3816 public readonly string ReturnType;
3817 public readonly string FirstArgType;
3818 public readonly string FirstArgName;
3819 public readonly string SecondArgType;
3820 public readonly string SecondArgName;
3821 public readonly Block Block;
3822 public Attributes OptAttributes;
3823 public MethodBuilder OperatorMethodBuilder;
3825 public string MethodName;
3826 public Method OperatorMethod;
3828 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
3829 string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
3832 OperatorType = type;
3833 ReturnType = ret_type;
3834 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
3835 FirstArgType = arg1type;
3836 FirstArgName = arg1name;
3837 SecondArgType = arg2type;
3838 SecondArgName = arg2name;
3840 OptAttributes = attrs;
3843 string Prototype (TypeContainer parent)
3845 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
3846 SecondArgType + ")";
3849 public override bool Define (TypeContainer parent)
3852 MethodName = "op_" + OperatorType;
3854 if (SecondArgType != null)
3857 Parameter [] param_list = new Parameter [length];
3859 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
3862 "User defined operators `" +
3863 Prototype (parent) +
3864 "' must be declared static and public");
3868 param_list[0] = new Parameter (FirstArgType, FirstArgName,
3869 Parameter.Modifier.NONE, null);
3870 if (SecondArgType != null)
3871 param_list[1] = new Parameter (SecondArgType, SecondArgName,
3872 Parameter.Modifier.NONE, null);
3874 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
3875 new Parameters (param_list, null, Location),
3876 OptAttributes, Mono.CSharp.Location.Null);
3878 OperatorMethod.Define (parent);
3880 if (OperatorMethod.MethodBuilder == null)
3883 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
3885 Type [] param_types = OperatorMethod.ParameterTypes (parent);
3886 Type declaring_type = OperatorMethodBuilder.DeclaringType;
3887 Type return_type = OperatorMethod.GetReturnType (parent);
3888 Type first_arg_type = param_types [0];
3890 // Rules for conversion operators
3892 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
3893 if (first_arg_type == return_type && first_arg_type == declaring_type){
3896 "User-defined conversion cannot take an object of the " +
3897 "enclosing type and convert to an object of the enclosing" +
3902 if (first_arg_type != declaring_type && return_type != declaring_type){
3905 "User-defined conversion must convert to or from the " +
3910 if (first_arg_type == TypeManager.object_type ||
3911 return_type == TypeManager.object_type){
3914 "User-defined conversion cannot convert to or from " +
3919 if (first_arg_type.IsInterface || return_type.IsInterface){
3922 "User-defined conversion cannot convert to or from an " +
3927 if (first_arg_type.IsSubclassOf (return_type) ||
3928 return_type.IsSubclassOf (first_arg_type)){
3931 "User-defined conversion cannot convert between types " +
3932 "that derive from each other");
3935 } else if (SecondArgType == null) {
3936 // Checks for Unary operators
3938 if (first_arg_type != declaring_type){
3941 "The parameter of a unary operator must be the " +
3946 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
3947 if (return_type != declaring_type){
3950 "The parameter and return type for ++ and -- " +
3951 "must be the containing type");
3957 if (OperatorType == OpType.True || OperatorType == OpType.False) {
3958 if (return_type != TypeManager.bool_type){
3961 "The return type of operator True or False " +
3968 // Checks for Binary operators
3970 if (first_arg_type != declaring_type &&
3971 param_types [1] != declaring_type){
3974 "One of the parameters of a binary operator must " +
3975 "be the containing type");
3983 public void Emit (TypeContainer parent)
3985 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
3986 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
3989 // abstract or extern methods have no bodies
3991 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3994 OperatorMethod.Block = Block;
3995 OperatorMethod.Emit (parent);
4000 // This is used to compare method signatures
4002 struct MethodSignature {
4004 public Type RetType;
4005 public Type [] Parameters;
4008 /// This delegate is used to extract methods which have the
4009 /// same signature as the argument
4011 public static MemberFilter method_signature_filter;
4014 /// This delegate is used to extract inheritable methods which
4015 /// have the same signature as the argument. By inheritable,
4016 /// this means that we have permissions to override the method
4017 /// from the current assembly and class
4019 public static MemberFilter inheritable_method_signature_filter;
4021 static MethodSignature ()
4023 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4024 inheritable_method_signature_filter = new MemberFilter (
4025 InheritableMemberSignatureCompare);
4028 public MethodSignature (string name, Type ret_type, Type [] parameters)
4033 if (parameters == null)
4034 Parameters = TypeManager.NoTypes;
4036 Parameters = parameters;
4039 public override int GetHashCode ()
4041 return Name.GetHashCode ();
4044 public override bool Equals (Object o)
4046 MethodSignature other = (MethodSignature) o;
4048 if (other.Name != Name)
4051 if (other.RetType != RetType)
4054 if (Parameters == null){
4055 if (other.Parameters == null)
4060 if (other.Parameters == null)
4063 int c = Parameters.Length;
4064 if (other.Parameters.Length != c)
4067 for (int i = 0; i < c; i++)
4068 if (other.Parameters [i] != Parameters [i])
4074 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4078 if (! (m is MethodInfo))
4081 MethodSignature sig = (MethodSignature) filter_criteria;
4083 if (m.Name != sig.Name)
4086 mi = (MethodInfo) m;
4088 if (mi.ReturnType != sig.RetType)
4091 Type [] args = TypeManager.GetArgumentTypes (mi);
4092 Type [] sigp = sig.Parameters;
4094 if (args.Length != sigp.Length)
4097 for (int i = args.Length; i > 0; ){
4099 if (args [i] != sigp [i])
4106 // This filter should be used when we are requesting methods that
4107 // we want to override.
4109 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4111 if (MemberSignatureCompare (m, filter_criteria)){
4112 MethodInfo mi = (MethodInfo) m;
4113 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4115 // If only accessible to the current class.
4116 if (prot == MethodAttributes.Private)
4119 // If only accessible to the defining assembly or
4120 if (prot == MethodAttributes.FamANDAssem ||
4121 prot == MethodAttributes.Assembly){
4122 if (m is MethodBuilder)
4128 // Anything else (FamOrAssembly and Public) is fine