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;
17 using System.Diagnostics.SymbolStore;
19 namespace Mono.CSharp {
22 /// This is the base class for structs and classes.
24 public class TypeContainer : DeclSpace {
25 // Holds a list of classes and structures
28 // Holds the list of properties
31 // Holds the list of enumerations
34 // Holds the list of delegates
37 // Holds the list of constructors
38 ArrayList instance_constructors;
40 // Holds the list of fields
43 // Holds a list of fields that have initializers
44 ArrayList initialized_fields;
46 // Holds a list of static fields that have initializers
47 ArrayList initialized_static_fields;
49 // Holds the list of constants
55 // Holds order in which interfaces must be closed
56 ArrayList interface_order;
67 // Holds the operators
71 // Pointers to the default constructor and the default static constructor
73 Constructor default_constructor;
74 Constructor default_static_constructor;
77 // Whether we have seen a static constructor for this class or not
79 bool have_static_constructor = false;
82 // This one is computed after we can distinguish interfaces
83 // from classes from the arraylist `type_bases'
85 string base_class_name;
89 // Attributes for this type
90 protected Attributes attributes;
92 // Information in the case we are an attribute type
94 public AttributeTargets Targets;
95 public bool AllowMultiple;
96 public bool Inherited;
99 public TypeContainer (TypeContainer parent, string name, Location l)
100 : base (parent, name, l)
103 types = new ArrayList ();
110 base_class_name = null;
112 //Console.WriteLine ("New class " + name + " inside " + n);
115 public AdditionResult AddConstant (Const constant)
118 string name = constant.Name;
120 if ((res = IsValid (name)) != AdditionResult.Success)
123 if (constants == null)
124 constants = new ArrayList ();
126 constants.Add (constant);
127 DefineName (name, constant);
129 return AdditionResult.Success;
132 public AdditionResult AddEnum (Mono.CSharp.Enum e)
135 string name = e.Name;
137 if ((res = IsValid (name)) != AdditionResult.Success)
141 enums = new ArrayList ();
144 DefineName (name, e);
146 return AdditionResult.Success;
149 public AdditionResult AddClass (Class c)
152 string name = c.Name;
155 if ((res = IsValid (name)) != AdditionResult.Success)
158 DefineName (name, c);
161 return AdditionResult.Success;
164 public AdditionResult AddStruct (Struct s)
167 string name = s.Name;
169 if ((res = IsValid (name)) != AdditionResult.Success)
172 DefineName (name, s);
175 return AdditionResult.Success;
178 public AdditionResult AddDelegate (Delegate d)
181 string name = d.Name;
183 if ((res = IsValid (name)) != AdditionResult.Success)
186 if (delegates == null)
187 delegates = new ArrayList ();
189 DefineName (name, d);
192 return AdditionResult.Success;
195 public AdditionResult AddMethod (Method method)
197 string name = method.Name;
198 Object value = defined_names [name];
200 if (value != null && (!(value is Method)))
201 return AdditionResult.NameExists;
204 methods = new ArrayList ();
206 methods.Add (method);
208 DefineName (name, method);
210 return AdditionResult.Success;
213 public AdditionResult AddConstructor (Constructor c)
215 if (c.Name != Basename)
216 return AdditionResult.NotAConstructor;
218 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
221 have_static_constructor = true;
222 if (default_static_constructor != null){
223 Console.WriteLine ("I have a static constructor already");
224 Console.WriteLine (" " + default_static_constructor);
225 return AdditionResult.MethodExists;
228 default_static_constructor = c;
231 if (default_constructor != null)
232 return AdditionResult.MethodExists;
233 default_constructor = c;
236 if (instance_constructors == null)
237 instance_constructors = new ArrayList ();
239 instance_constructors.Add (c);
242 return AdditionResult.Success;
245 public AdditionResult AddInterface (Interface iface)
248 string name = iface.Name;
250 if ((res = IsValid (name)) != AdditionResult.Success)
253 if (interfaces == null)
254 interfaces = new ArrayList ();
255 interfaces.Add (iface);
256 DefineName (name, iface);
258 return AdditionResult.Success;
261 public AdditionResult AddField (Field field)
264 string name = field.Name;
266 if ((res = IsValid (name)) != AdditionResult.Success)
270 fields = new ArrayList ();
274 if (field.Initializer != null){
275 if ((field.ModFlags & Modifiers.STATIC) != 0){
276 if (initialized_static_fields == null)
277 initialized_static_fields = new ArrayList ();
279 initialized_static_fields.Add (field);
282 // We have not seen a static constructor,
283 // but we will provide static initialization of fields
285 have_static_constructor = true;
287 if (initialized_fields == null)
288 initialized_fields = new ArrayList ();
290 initialized_fields.Add (field);
294 DefineName (name, field);
295 return AdditionResult.Success;
298 public AdditionResult AddProperty (Property prop)
301 string name = prop.Name;
303 if ((res = IsValid (name)) != AdditionResult.Success)
306 if (properties == null)
307 properties = new ArrayList ();
309 properties.Add (prop);
310 DefineName (name, prop);
312 return AdditionResult.Success;
315 public AdditionResult AddEvent (Event e)
318 string name = e.Name;
320 if ((res = IsValid (name)) != AdditionResult.Success)
324 events = new ArrayList ();
327 DefineName (name, e);
329 return AdditionResult.Success;
332 public AdditionResult AddIndexer (Indexer i)
334 if (indexers == null)
335 indexers = new ArrayList ();
339 return AdditionResult.Success;
342 public AdditionResult AddOperator (Operator op)
344 if (operators == null)
345 operators = new ArrayList ();
349 return AdditionResult.Success;
352 public void RegisterOrder (Interface iface)
354 if (interface_order == null)
355 interface_order = new ArrayList ();
357 interface_order.Add (iface);
360 public ArrayList Types {
366 public ArrayList Methods {
372 public ArrayList Constants {
378 public ArrayList Interfaces {
386 return base_class_name;
390 public ArrayList Bases {
400 public ArrayList Fields {
406 public ArrayList InstanceConstructors {
408 return instance_constructors;
412 public ArrayList Properties {
418 public ArrayList Events {
424 public ArrayList Enums {
430 public ArrayList Indexers {
436 public ArrayList Operators {
442 public ArrayList Delegates {
448 public Attributes OptAttributes {
454 public bool HaveStaticConstructor {
456 return have_static_constructor;
460 public virtual TypeAttributes TypeAttr {
462 return Modifiers.TypeAttr (ModFlags, this);
467 // Emits the instance field initializers
469 public bool EmitFieldInitializers (EmitContext ec)
472 ILGenerator ig = ec.ig;
473 Expression instance_expr;
476 fields = initialized_static_fields;
477 instance_expr = null;
479 fields = initialized_fields;
480 instance_expr = new This (Location.Null).Resolve (ec);
486 foreach (Field f in fields){
487 Object init = f.Initializer;
490 if (init is Expression)
491 e = (Expression) init;
493 string base_type = f.Type.Substring (0, f.Type.IndexOf ("["));
494 string rank = f.Type.Substring (f.Type.IndexOf ("["));
495 e = new ArrayCreation (base_type, rank, (ArrayList)init, f.Location);
498 Location l = f.Location;
499 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
500 fe.InstanceExpression = instance_expr;
501 Assign a = new Assign (fe, e, l);
503 a = (Assign) a.Resolve (ec);
507 a.EmitStatement (ec);
514 // Defines the default constructors
516 void DefineDefaultConstructor (bool is_static)
521 c = new Constructor (Basename, Parameters.GetEmptyReadOnlyParameters (),
522 new ConstructorBaseInitializer (null, new Location (-1)),
526 mods = Modifiers.STATIC;
532 c.Block = new Block (null);
536 public void ReportStructInitializedInstanceError ()
538 string n = TypeBuilder.FullName;
540 foreach (Field f in initialized_fields){
543 "`" + n + "." + f.Name + "': can not have " +
544 "instance field initializers in structs");
548 struct TypeAndMethods {
550 public MethodInfo [] methods;
552 // Far from ideal, but we want to avoid creating a copy
554 public Type [][] args;
557 // This flag on the method says `We found a match, but
558 // because it was private, we could not use the match
560 public bool [] found;
564 // This array keeps track of the pending implementations
566 TypeAndMethods [] pending_implementations;
569 // Returns a list of the abstract methods that are exposed by all of our
570 // parents that we must implement. Notice that this `flattens' the
571 // method search space, and takes into account overrides.
573 ArrayList GetAbstractMethods (Type t)
575 ArrayList list = null;
576 bool searching = true;
577 Type current_type = t;
583 current_type, MemberTypes.Method,
584 BindingFlags.Public | BindingFlags.Instance |
585 BindingFlags.DeclaredOnly,
586 virtual_method_filter, null);
588 if (current_type == TypeManager.object_type)
591 current_type = current_type.BaseType;
592 if (!current_type.IsAbstract)
599 int count = mi.Length;
603 if (count == 1 && !(mi [0] is MethodBase))
606 list = Expression.CopyNewMethods (list, mi);
612 for (int i = 0; i < list.Count; i++){
613 while (list.Count > i && !((MethodInfo) list [i]).IsAbstract)
624 // Registers the required method implementations for this class
626 // Register method implementations are either abstract methods
627 // flagged as such on the base class or interface methods
629 public void RegisterRequiredImplementations ()
631 Type [] ifaces = TypeBuilder.GetInterfaces ();
632 Type b = TypeBuilder.BaseType;
637 Type x = TypeBuilder;
640 Type [] iff = x.GetInterfaces ();
641 Console.WriteLine ("Type: " + x.Name);
643 foreach (Type tt in iff){
644 Console.WriteLine (" Iface: " + tt.Name);
651 icount = ifaces.Length;
654 // If we are implementing an abstract class, and we are not
655 // ourselves abstract, and there are abstract methods (C# allows
656 // abstract classes that have no abstract methods), then allocate
659 // We also pre-compute the methods.
661 bool implementing_abstract = (b.IsAbstract && !TypeBuilder.IsAbstract);
662 ArrayList abstract_methods = null;
664 if (implementing_abstract){
665 abstract_methods = GetAbstractMethods (b);
667 if (abstract_methods == null)
668 implementing_abstract = false;
671 int total = icount + (implementing_abstract ? 1 : 0);
675 pending_implementations = new TypeAndMethods [total];
679 foreach (Type t in ifaces){
682 if (t is TypeBuilder){
685 iface = TypeManager.LookupInterface (t);
687 mi = iface.GetMethods ();
689 mi = t.GetMethods ();
691 int count = mi.Length;
692 pending_implementations [i].type = t;
693 pending_implementations [i].methods = mi;
694 pending_implementations [i].args = new Type [count][];
695 pending_implementations [i].found = new bool [count];
698 foreach (MethodInfo m in mi){
699 Type [] types = TypeManager.GetArgumentTypes (m);
701 pending_implementations [i].args [j] = types;
708 if (abstract_methods != null){
709 int count = abstract_methods.Count;
710 pending_implementations [i].methods = new MethodInfo [count];
712 abstract_methods.CopyTo (pending_implementations [i].methods, 0);
713 pending_implementations [i].found = new bool [count];
714 pending_implementations [i].args = new Type [count][];
715 pending_implementations [i].type = TypeBuilder;
718 foreach (MemberInfo m in abstract_methods){
719 MethodInfo mi = (MethodInfo) m;
721 Type [] types = TypeManager.GetArgumentTypes (mi);
723 pending_implementations [i].args [j] = types;
730 /// This function computes the Base class and also the
731 /// list of interfaces that the class or struct @c implements.
733 /// The return value is an array (might be null) of
734 /// interfaces implemented (as Types).
736 /// The @parent argument is set to the parent object or null
737 /// if this is `System.Object'.
739 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
741 ArrayList bases = Bases;
750 parent = TypeManager.value_type;
754 if (RootContext.StdLib)
755 parent = TypeManager.object_type;
756 else if (Name != "System.Object")
757 parent = TypeManager.object_type;
760 // If we are compiling our runtime,
761 // and we are defining ValueType, then our
762 // parent is `System.Object'.
764 if (!RootContext.StdLib && Name == "System.ValueType")
765 parent = TypeManager.object_type;
772 // Bases should be null if there are no bases at all
777 string name = (string) bases [0];
778 Type first = FindType (name);
789 parent = TypeManager.object_type;
797 Type [] ifaces = new Type [count-start];
799 for (i = start, j = 0; i < count; i++, j++){
800 string name = (string) bases [i];
801 Type t = FindType (name);
808 if (is_class == false && !t.IsInterface){
809 Report.Error (527, "In Struct `" + Name + "', type `"+
810 name +"' is not an interface");
819 detail = " (a class can not inherit from a struct/enum)";
821 Report.Error (509, "class `"+ Name +
822 "': Cannot inherit from sealed class `"+
823 bases [i]+"'"+detail);
830 Report.Error (527, "In Class `" + Name + "', type `"+
831 name+"' is not an interface");
844 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
846 public override TypeBuilder DefineType ()
853 if (TypeBuilder != null)
866 ifaces = GetClassBases (is_class, out parent, out error);
871 if (is_class && parent != null){
872 if (parent == TypeManager.enum_type ||
873 (parent == TypeManager.value_type && RootContext.StdLib) ||
874 parent == TypeManager.delegate_type ||
875 parent == TypeManager.array_type){
877 644, Location, "`" + Name + "' cannot inherit from " +
878 "special class `" + TypeManager.CSharpName (parent) + "'");
883 // if (parent_builder is ModuleBuilder) {
885 ModuleBuilder builder = CodeGen.ModuleBuilder;
888 // Structs with no fields need to have a ".size 1"
892 if (!is_class && Fields == null)
893 TypeBuilder = builder.DefineType (Name,
896 PackingSize.Unspecified, 1);
899 // classes or structs with fields
901 TypeBuilder = builder.DefineType (Name,
906 TypeBuilder builder = Parent.TypeBuilder;
909 // Structs with no fields need to have a ".size 1"
912 if (!is_class && Fields == null)
913 TypeBuilder = builder.DefineNestedType (Basename,
916 PackingSize.Unspecified);
919 // classes or structs with fields
921 TypeBuilder = builder.DefineNestedType (Basename,
928 TypeManager.AddUserType (Name, TypeBuilder, this);
930 if (parent == TypeManager.attribute_type)
931 RootContext.RegisterAttribute (this);
933 RootContext.RegisterOrder (this);
935 if (Interfaces != null) {
936 foreach (Interface iface in Interfaces)
941 foreach (TypeContainer tc in Types)
945 if (Delegates != null) {
946 foreach (Delegate d in Delegates)
951 foreach (Enum en in Enums)
961 /// Defines the MemberCore objects that are in the `list' Arraylist
963 /// The `defined_names' array contains a list of members defined in
966 static ArrayList remove_list = new ArrayList ();
967 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
971 remove_list.Clear ();
973 foreach (MemberCore mc in list){
974 if (!mc.Define (this)){
975 remove_list.Add (mc);
979 if (defined_names == null)
982 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
985 if (RootContext.WarningLevel >= 4){
986 if ((mc.ModFlags & Modifiers.NEW) != 0)
987 Report109 (mc.Location, mc);
992 if (defined_names [idx] is PropertyInfo &&
993 ((mc.ModFlags & Modifiers.OVERRIDE) != 0)){
997 #if WANT_TO_VERIFY_SIGNATURES_HERE
998 if (defined_names [idx] is MethodBase && mc is MethodCore){
999 MethodBase mb = (MethodBase) defined_names [idx];
1000 MethodCore met = (MethodCore) mc;
1002 if ((mb.IsVirtual || mb.IsAbstract) &&
1003 (mc.ModFlags & Modifiers.OVERRIDE) != 0)
1007 // FIXME: Compare the signatures here. If they differ,
1008 // then: `continue;'
1011 if ((mc.ModFlags & Modifiers.NEW) == 0)
1012 Report108 (mc.Location, defined_names [idx]);
1015 foreach (object o in remove_list)
1018 remove_list.Clear ();
1022 /// Populates our TypeBuilder with fields and methods
1024 public override bool Define (TypeContainer parent)
1026 MemberInfo [] defined_names = null;
1028 if (RootContext.WarningLevel > 1){
1032 // This code throws an exception in the comparer
1033 // I guess the string is not an object?
1035 ptype = TypeBuilder.BaseType;
1037 defined_names = FindMembers (
1038 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1039 BindingFlags.Public | BindingFlags.Instance |
1040 BindingFlags.Static, null, null);
1042 Array.Sort (defined_names, mif_compare);
1046 if (constants != null)
1047 DefineMembers (constants, defined_names);
1050 DefineMembers (fields, defined_names);
1053 if (instance_constructors == null){
1054 if (default_constructor == null)
1055 DefineDefaultConstructor (false);
1058 if (initialized_static_fields != null &&
1059 default_static_constructor == null)
1060 DefineDefaultConstructor (true);
1063 if (this is Struct){
1065 // Structs can not have initialized instance
1068 if (initialized_static_fields != null &&
1069 default_static_constructor == null)
1070 DefineDefaultConstructor (true);
1072 if (initialized_fields != null)
1073 ReportStructInitializedInstanceError ();
1076 RegisterRequiredImplementations ();
1079 // Constructors are not in the defined_names array
1081 if (instance_constructors != null)
1082 DefineMembers (instance_constructors, null);
1084 if (default_static_constructor != null)
1085 default_static_constructor.Define (this);
1087 if (methods != null)
1088 DefineMembers (methods, null);
1090 if (properties != null)
1091 DefineMembers (properties, defined_names);
1094 DefineMembers (events, defined_names);
1096 if (indexers != null) {
1097 foreach (Indexer i in Indexers)
1101 if (operators != null)
1102 DefineMembers (operators, null);
1105 DefineMembers (enums, defined_names);
1107 if (delegates != null)
1108 DefineMembers (delegates, defined_names);
1114 /// Looks up the alias for the name
1116 public string LookupAlias (string name)
1118 if (Namespace != null)
1119 return Namespace.LookupAlias (name);
1125 /// This function is based by a delegate to the FindMembers routine
1127 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1133 /// This filter is used by FindMembers, and we just keep
1134 /// a global for the filter to `AlwaysAccept'
1136 static MemberFilter accepting_filter;
1138 static bool IsVirtualFilter (MemberInfo m, object filterCriteria)
1140 if (!(m is MethodInfo))
1143 return ((MethodInfo) m).IsVirtual;
1147 /// This filter is used by FindMembers, and it is used to
1148 /// extract only virtual/abstract fields
1150 static MemberFilter virtual_method_filter;
1153 /// A member comparission method based on name only
1155 static IComparer mif_compare;
1157 static TypeContainer ()
1159 accepting_filter = new MemberFilter (AlwaysAccept);
1160 virtual_method_filter = new MemberFilter (IsVirtualFilter);
1161 mif_compare = new MemberInfoCompare ();
1165 /// This method returns the members of this type just like Type.FindMembers would
1166 /// Only, we need to use this for types which are _being_ defined because MS'
1167 /// implementation can't take care of that.
1170 // FIXME: return an empty static array instead of null, that cleans up
1171 // some code and is consistent with some coding conventions I just found
1175 // Notice that in various cases we check if our field is non-null,
1176 // something that would normally mean that there was a bug elsewhere.
1178 // The problem happens while we are defining p-invoke methods, as those
1179 // will trigger a FindMembers, but this happens before things are defined
1181 // Since the whole process is a no-op, it is fine to check for null here.
1183 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
1184 MemberFilter filter, object criteria)
1186 ArrayList members = new ArrayList ();
1187 bool priv = (bf & BindingFlags.NonPublic) != 0;
1191 filter = accepting_filter;
1193 if ((mt & MemberTypes.Field) != 0) {
1194 if (fields != null) {
1195 foreach (Field f in fields) {
1196 if ((f.ModFlags & Modifiers.PRIVATE) != 0)
1200 FieldBuilder fb = f.FieldBuilder;
1201 if (fb != null && filter (fb, criteria) == true)
1206 if (constants != null) {
1207 foreach (Const con in constants) {
1208 if ((con.ModFlags & Modifiers.PRIVATE) != 0)
1212 FieldBuilder fb = con.FieldBuilder;
1213 if (fb != null && filter (fb, criteria) == true)
1219 if ((mt & MemberTypes.Method) != 0) {
1220 if (methods != null) {
1221 foreach (Method m in methods) {
1222 if ((m.ModFlags & Modifiers.PRIVATE) != 0)
1226 MethodBuilder mb = m.MethodBuilder;
1228 if (mb != null && filter (mb, criteria) == true)
1233 if (operators != null){
1234 foreach (Operator o in operators) {
1235 if ((o.ModFlags & Modifiers.PRIVATE) != 0)
1239 MethodBuilder ob = o.OperatorMethodBuilder;
1240 if (ob != null && filter (ob, criteria) == true)
1245 if (properties != null){
1246 foreach (Property p in properties){
1247 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1254 if (b != null && filter (b, criteria) == true)
1258 if (b != null && filter (b, criteria) == true)
1264 if ((mt & MemberTypes.Event) != 0) {
1266 foreach (Event e in events) {
1267 if ((e.ModFlags & Modifiers.PRIVATE) != 0)
1271 MemberInfo eb = e.EventBuilder;
1272 if (eb != null && filter (eb, criteria) == true)
1273 members.Add (e.EventBuilder);
1277 if ((mt & MemberTypes.Property) != 0){
1278 if (properties != null)
1279 foreach (Property p in properties) {
1280 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1284 MemberInfo pb = p.PropertyBuilder;
1285 if (pb != null && filter (pb, criteria) == true) {
1286 members.Add (p.PropertyBuilder);
1290 if (indexers != null)
1291 foreach (Indexer ix in indexers) {
1292 if ((ix.ModFlags & Modifiers.PRIVATE) != 0)
1296 MemberInfo ib = ix.PropertyBuilder;
1297 if (ib != null && filter (ib, criteria) == true) {
1298 members.Add (ix.PropertyBuilder);
1303 if ((mt & MemberTypes.NestedType) != 0) {
1306 foreach (TypeContainer t in Types)
1307 if (filter (t.TypeBuilder, criteria) == true)
1308 members.Add (t.TypeBuilder);
1311 foreach (Enum en in Enums)
1312 if (filter (en.TypeBuilder, criteria) == true)
1313 members.Add (en.TypeBuilder);
1317 if ((mt & MemberTypes.Constructor) != 0){
1318 if (instance_constructors != null){
1319 foreach (Constructor c in instance_constructors){
1320 ConstructorBuilder cb = c.ConstructorBuilder;
1322 if (filter (cb, criteria) == true)
1327 if (default_static_constructor != null){
1328 ConstructorBuilder cb =
1329 default_static_constructor.ConstructorBuilder;
1331 if (filter (cb, criteria) == true)
1337 // Lookup members in parent if requested.
1339 if ((bf & BindingFlags.DeclaredOnly) == 0){
1342 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1344 members.AddRange (mi);
1347 int count = members.Count;
1349 MemberInfo [] mi = new MemberInfo [count];
1350 members.CopyTo (mi);
1357 public MemberInfo GetFieldFromEvent (EventExpr event_expr)
1359 EventInfo ei = event_expr.EventInfo;
1361 foreach (Event e in events) {
1363 if (e.FieldBuilder == null)
1366 if (Type.FilterName (e.FieldBuilder, ei.Name))
1367 return e.FieldBuilder;
1373 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1374 MemberFilter filter, object criteria)
1376 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1379 return tc.FindMembers (mt, bf, filter, criteria);
1381 return t.FindMembers (mt, bf, filter, criteria);
1385 // FindMethods will look for methods not only in the type `t', but in
1386 // any interfaces implemented by the type.
1388 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1389 MemberFilter filter, object criteria)
1395 /// Whether the specified method is an interface method implementation
1399 /// If a method in Type `t' (or null to look in all interfaces
1400 /// and the base abstract class) with name `Name', return type `ret_type' and
1401 /// arguments `args' implements an interface, this method will
1402 /// return the MethodInfo that this method implements.
1404 /// This will remove the method from the list of "pending" methods
1405 /// that are required to be implemented for this class as a side effect.
1408 public MethodInfo IsInterfaceMethod (Type t, string Name, Type ret_type, Type [] args,
1411 int arg_len = args.Length;
1413 if (pending_implementations == null)
1416 foreach (TypeAndMethods tm in pending_implementations){
1417 if (!(t == null || tm.type == t))
1421 foreach (MethodInfo m in tm.methods){
1427 if (Name != m.Name){
1432 if (ret_type != m.ReturnType){
1433 if (!((ret_type == null && m.ReturnType == TypeManager.void_type) ||
1434 (m.ReturnType == null && ret_type == TypeManager.void_type)))
1442 // Check if we have the same parameters
1444 if (tm.args [i].Length != arg_len){
1449 int j, top = args.Length;
1452 for (j = 0; j < top; j++){
1453 if (tm.args [i][j] != args[j]){
1464 tm.methods [i] = null;
1465 tm.found [i] = true;
1469 // If a specific type was requested, we can stop now.
1477 /// C# allows this kind of scenarios:
1478 /// interface I { void M (); }
1479 /// class X { public void M (); }
1480 /// class Y : X, I { }
1482 /// For that case, we create an explicit implementation function
1485 void DefineProxy (Type iface, MethodInfo parent_method, MethodInfo iface_method,
1488 MethodBuilder proxy;
1490 string proxy_name = iface.Name + "." + iface_method.Name;
1492 proxy = TypeBuilder.DefineMethod (
1494 MethodAttributes.HideBySig |
1495 MethodAttributes.NewSlot |
1496 MethodAttributes.Virtual,
1497 CallingConventions.Standard | CallingConventions.HasThis,
1498 parent_method.ReturnType, args);
1500 int top = args.Length;
1501 ILGenerator ig = proxy.GetILGenerator ();
1503 ig.Emit (OpCodes.Ldarg_0);
1504 for (int i = 0; i < top; i++){
1507 ig.Emit (OpCodes.Ldarg_1); break;
1509 ig.Emit (OpCodes.Ldarg_2); break;
1511 ig.Emit (OpCodes.Ldarg_3); break;
1513 ig.Emit (OpCodes.Ldarg, i - 1); break;
1516 ig.Emit (OpCodes.Call, parent_method);
1517 ig.Emit (OpCodes.Ret);
1519 TypeBuilder.DefineMethodOverride (proxy, iface_method);
1523 /// This function tells whether one of our parent classes implements
1524 /// the given method (which turns out, it is valid to have an interface
1525 /// implementation in a parent
1527 bool ParentImplements (Type iface_type, MethodInfo mi)
1531 Type [] args = TypeManager.GetArgumentTypes (mi);
1532 ms = new MethodSignature (mi.Name, mi.ReturnType, args);
1533 MemberInfo [] list = FindMembers (
1534 TypeBuilder.BaseType, MemberTypes.Method | MemberTypes.Property,
1535 BindingFlags.Public | BindingFlags.Instance,
1536 MethodSignature.method_signature_filter, ms);
1538 if (list == null || list.Length == 0)
1541 DefineProxy (iface_type, (MethodInfo) list [0], mi, args);
1546 /// Verifies that any pending abstract methods or interface methods
1547 /// were implemented.
1549 bool VerifyPendingMethods ()
1551 int top = pending_implementations.Length;
1552 bool errors = false;
1555 for (i = 0; i < top; i++){
1556 Type type = pending_implementations [i].type;
1559 foreach (MethodInfo mi in pending_implementations [i].methods){
1563 if (type.IsInterface){
1564 if (ParentImplements (type, mi))
1569 if (pending_implementations [i].found [j])
1570 extra = ". (method might be private or static)";
1573 "`" + Name + "' does not implement " +
1574 "interface member `" +
1575 type.FullName + "." + mi.Name + "'" + extra);
1579 "`" + Name + "' does not implement " +
1580 "inherited abstract member `" +
1581 type.FullName + "." + mi.Name + "'");
1591 /// Emits the values for the constants
1593 public void EmitConstants ()
1595 if (constants != null)
1596 foreach (Const con in constants)
1597 con.EmitConstant (this);
1602 /// Emits the code, this step is performed after all
1603 /// the types, enumerations, constructors
1607 if (instance_constructors != null)
1608 foreach (Constructor c in instance_constructors)
1611 if (default_static_constructor != null)
1612 default_static_constructor.Emit (this);
1614 if (methods != null)
1615 foreach (Method m in methods)
1618 if (operators != null)
1619 foreach (Operator o in operators)
1622 if (properties != null)
1623 foreach (Property p in properties)
1626 if (indexers != null) {
1627 foreach (Indexer ix in indexers)
1630 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (this, ModFlags, Location);
1632 TypeBuilder.SetCustomAttribute (cb);
1636 foreach (Field f in fields)
1639 if (events != null){
1640 foreach (Event e in Events)
1644 if (pending_implementations != null)
1645 if (!VerifyPendingMethods ())
1648 EmitContext ec = new EmitContext (
1649 this, Mono.CSharp.Location.Null, null, null,
1652 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1655 // Check for internal or private fields that were never assigned
1657 if (RootContext.WarningLevel >= 3){
1658 foreach (Field f in fields){
1659 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1664 169, f.Location, "Private field " +
1665 MakeName (f.Name) + " is never used");
1670 // Only report 649 on level 4
1672 if (RootContext.WarningLevel < 4)
1675 if ((f.status & Field.Status.ASSIGNED) != 0)
1680 "Field " + MakeName (f.Name) + " is never assigned " +
1681 " to and will always have its default value");
1685 // if (types != null)
1686 // foreach (TypeContainer tc in types)
1690 public override void CloseType ()
1695 TypeBuilder.CreateType ();
1697 } catch (TypeLoadException){
1699 // This is fine, the code still created the type
1701 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1702 // Console.WriteLine (e.Message);
1706 foreach (Enum en in Enums)
1709 if (interface_order != null){
1710 foreach (Interface iface in interface_order)
1715 foreach (TypeContainer tc in Types)
1719 foreach (TypeContainer tc in Types)
1720 if (!(tc is Struct))
1724 if (Delegates != null)
1725 foreach (Delegate d in Delegates)
1729 public string MakeName (string n)
1731 return "`" + Name + "." + n + "'";
1734 public void Report108 (Location l, MemberInfo mi)
1737 108, l, "The keyword new is required on " +
1738 MakeName (mi.Name) + " because it hides `" +
1739 mi.ReflectedType.Name + "." + mi.Name + "'");
1742 public void Report109 (Location l, MemberCore mc)
1745 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1746 "inherited member, the keyword new is not required");
1749 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1755 // Performs the validation on a Method's modifiers (properties have
1756 // the same properties).
1758 public bool MethodModifiersValid (int flags, string n, Location loc)
1760 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1761 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1763 string name = MakeName (n);
1766 // At most one of static, virtual or override
1768 if ((flags & Modifiers.STATIC) != 0){
1769 if ((flags & vao) != 0){
1771 112, loc, "static method " + name + "can not be marked " +
1772 "as virtual, abstract or override");
1777 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1780 " marked as override cannot be marked as new or virtual");
1785 // If the declaration includes the abstract modifier, then the
1786 // declaration does not include static, virtual or extern
1788 if ((flags & Modifiers.ABSTRACT) != 0){
1789 if ((flags & Modifiers.EXTERN) != 0){
1791 180, loc, name + " can not be both abstract and extern");
1795 if ((flags & Modifiers.VIRTUAL) != 0){
1797 503, loc, name + " can not be both abstract and virtual");
1801 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1804 " is abstract but its container class is not");
1810 if ((flags & Modifiers.PRIVATE) != 0){
1811 if ((flags & vao) != 0){
1814 " virtual or abstract members can not be private");
1819 if ((flags & Modifiers.SEALED) != 0){
1820 if ((flags & Modifiers.OVERRIDE) == 0){
1823 " cannot be sealed because it is not an override");
1832 // Returns true if `type' is as accessible as the flags `flags'
1833 // given for this member
1835 static public bool AsAccessible (Type type, int flags)
1840 Hashtable builder_and_args;
1842 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1844 if (builder_and_args == null)
1845 builder_and_args = new Hashtable ();
1850 public class Class : TypeContainer {
1852 // Modifiers allowed in a class declaration
1854 public const int AllowedModifiers =
1857 Modifiers.PROTECTED |
1858 Modifiers.INTERNAL |
1860 Modifiers.ABSTRACT |
1864 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1865 : base (parent, name, l)
1869 if (parent.Parent == null)
1870 accmods = Modifiers.INTERNAL;
1872 accmods = Modifiers.PRIVATE;
1874 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1875 this.attributes = attrs;
1879 // FIXME: How do we deal with the user specifying a different
1882 public override TypeAttributes TypeAttr {
1884 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1889 public class Struct : TypeContainer {
1891 // Modifiers allowed in a struct declaration
1893 public const int AllowedModifiers =
1896 Modifiers.PROTECTED |
1897 Modifiers.INTERNAL |
1901 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1902 : base (parent, name, l)
1906 if (parent.Parent == null)
1907 accmods = Modifiers.INTERNAL;
1909 accmods = Modifiers.PRIVATE;
1911 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1913 this.ModFlags |= Modifiers.SEALED;
1914 this.attributes = attrs;
1919 // FIXME: Allow the user to specify a different set of attributes
1920 // in some cases (Sealed for example is mandatory for a class,
1921 // but what SequentialLayout can be changed
1923 public override TypeAttributes TypeAttr {
1925 return base.TypeAttr |
1926 TypeAttributes.SequentialLayout |
1927 TypeAttributes.Sealed |
1928 TypeAttributes.BeforeFieldInit;
1933 public abstract class MethodCore : MemberCore {
1934 public readonly Parameters Parameters;
1938 // Parameters, cached for semantic analysis.
1940 InternalParameters parameter_info;
1942 public MethodCore (string name, Parameters parameters, Location l)
1946 Parameters = parameters;
1950 // Returns the System.Type array for the parameters of this method
1952 Type [] parameter_types;
1953 public Type [] ParameterTypes (TypeContainer parent)
1955 if (Parameters == null)
1956 return TypeManager.NoTypes;
1958 if (parameter_types == null)
1959 parameter_types = Parameters.GetParameterInfo (parent);
1961 return parameter_types;
1964 public InternalParameters ParameterInfo
1967 return parameter_info;
1971 parameter_info = value;
1975 public Block Block {
1985 public CallingConventions GetCallingConvention (bool is_class)
1987 CallingConventions cc = 0;
1989 cc = Parameters.GetCallingConvention ();
1992 if ((ModFlags & Modifiers.STATIC) == 0)
1993 cc |= CallingConventions.HasThis;
1995 // FIXME: How is `ExplicitThis' used in C#?
2000 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
2003 // Define each type attribute (in/out/ref) and
2004 // the argument names.
2006 Parameter [] p = Parameters.FixedParameters;
2009 MethodBuilder mb = null;
2010 ConstructorBuilder cb = null;
2012 if (builder is MethodBuilder)
2013 mb = (MethodBuilder) builder;
2015 cb = (ConstructorBuilder) builder;
2018 for (i = 0; i < p.Length; i++) {
2019 ParameterBuilder pb;
2022 pb = cb.DefineParameter (
2023 i + 1, p [i].Attributes, p [i].Name);
2025 pb = mb.DefineParameter (
2026 i + 1, p [i].Attributes, p [i].Name);
2028 Attributes attr = p [i].OptAttributes;
2030 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
2034 if (Parameters.ArrayParameter != null){
2035 ParameterBuilder pb;
2036 Parameter array_param = Parameters.ArrayParameter;
2039 pb = cb.DefineParameter (
2040 i + 1, array_param.Attributes,
2043 pb = mb.DefineParameter (
2044 i + 1, array_param.Attributes,
2047 CustomAttributeBuilder a = new CustomAttributeBuilder (
2048 TypeManager.cons_param_array_attribute, new object [0]);
2050 pb.SetCustomAttribute (a);
2055 public class Method : MethodCore {
2056 public readonly string ReturnType;
2057 public MethodBuilder MethodBuilder;
2058 public readonly Attributes OptAttributes;
2060 MethodAttributes flags;
2063 /// Modifiers allowed in a class declaration
2065 const int AllowedModifiers =
2068 Modifiers.PROTECTED |
2069 Modifiers.INTERNAL |
2074 Modifiers.OVERRIDE |
2075 Modifiers.ABSTRACT |
2080 // return_type can be "null" for VOID values.
2082 public Method (string return_type, int mod, string name, Parameters parameters,
2083 Attributes attrs, Location l)
2084 : base (name, parameters, l)
2086 ReturnType = return_type;
2087 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l);
2088 OptAttributes = attrs;
2092 // Returns the `System.Type' for the ReturnType of this
2093 // function. Provides a nice cache. (used between semantic analysis
2094 // and actual code generation
2096 Type type_return_type;
2098 public Type GetReturnType (TypeContainer parent)
2100 if (type_return_type == null)
2101 type_return_type = RootContext.LookupType (
2102 parent, ReturnType, false, Location);
2104 return type_return_type;
2107 void DuplicatEntryPoint (MethodInfo b)
2111 "Program `" + CodeGen.FileName +
2112 "' has more than one entry point defined: `" +
2113 b.DeclaringType.Name + "." + b.Name + "'");
2119 public override bool Define (TypeContainer parent)
2121 Type ret_type = GetReturnType (parent);
2122 Type [] parameters = ParameterTypes (parent);
2124 MethodInfo implementing;
2125 Type iface_type = null;
2126 string iface = "", short_name;
2127 bool explicit_impl = false;
2129 // Check if the return type and arguments were correct
2130 if (ret_type == null || parameters == null)
2133 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
2136 flags = Modifiers.MethodAttr (ModFlags);
2139 // verify accessibility
2141 if (!TypeContainer.AsAccessible (ret_type, ModFlags))
2144 if (ret_type.IsPointer && !UnsafeOK (parent))
2147 foreach (Type partype in parameters){
2148 if (!TypeContainer.AsAccessible (partype, ModFlags))
2150 if (partype.IsPointer && !UnsafeOK (parent))
2158 // Verify if the parent has a type with the same name, and then
2159 // check whether we have to create a new slot for it or not.
2161 Type ptype = parent.TypeBuilder.BaseType;
2163 // ptype is only null for System.Object while compiling corlib.
2165 MethodSignature ms = new MethodSignature (Name, ret_type, parameters);
2166 MemberInfo [] mi, mi_static, mi_instance;
2168 mi_static = TypeContainer.FindMembers (
2169 ptype, MemberTypes.Method,
2170 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2171 MethodSignature.inheritable_method_signature_filter, ms);
2173 mi_instance = TypeContainer.FindMembers (
2174 ptype, MemberTypes.Method,
2175 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2176 MethodSignature.inheritable_method_signature_filter,
2179 if (mi_instance != null && mi_instance.Length > 0){
2181 } else if (mi_static != null && mi_static.Length > 0)
2186 if (mi != null && mi.Length > 0){
2187 if (!CheckMethodAgainstBase (parent, flags, (MethodInfo) mi [0])){
2191 if ((ModFlags & Modifiers.NEW) != 0)
2192 WarningNotHiding (parent);
2194 if ((ModFlags & Modifiers.OVERRIDE) != 0)
2195 Report.Error (115, Location,
2196 parent.MakeName (Name) +
2197 " no suitable methods found to override");
2199 } else if ((ModFlags & Modifiers.NEW) != 0)
2200 WarningNotHiding (parent);
2203 // If we implement an interface, extract the interface name.
2206 if (Name.IndexOf (".") != -1){
2207 int pos = Name.LastIndexOf (".");
2208 iface = Name.Substring (0, pos);
2210 iface_type = RootContext.LookupType (parent, iface, false, Location);
2211 short_name = Name.Substring (pos + 1);
2213 if (iface_type == null)
2216 // Compute the full name that we need to export
2217 Name = iface_type.FullName + "." + short_name;
2218 explicit_impl = true;
2223 // Check if we are an implementation of an interface method or
2226 implementing = parent.IsInterfaceMethod (
2227 iface_type, short_name, ret_type, parameters, false);
2230 // For implicit implementations, make sure we are public, for
2231 // explicit implementations, make sure we are private.
2233 if (implementing != null){
2235 // Setting null inside this block will trigger a more
2236 // verbose error reporting for missing interface implementations
2238 // The "candidate" function has been flagged already
2239 // but it wont get cleared
2241 if (iface_type == null){
2243 // We already catch different accessibility settings
2244 // so we just need to check that we are not private
2246 if ((ModFlags & Modifiers.PRIVATE) != 0)
2247 implementing = null;
2250 // Static is not allowed
2252 if ((ModFlags & Modifiers.STATIC) != 0)
2253 implementing = null;
2255 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2257 106, Location, "`public' or `abstract' modifiers "+
2258 "are not allowed in explicit interface declarations"
2260 implementing = null;
2266 // If implementing is still valid, set flags
2268 if (implementing != null){
2269 if (implementing.DeclaringType.IsInterface)
2270 flags |= MethodAttributes.NewSlot;
2273 MethodAttributes.Virtual |
2274 MethodAttributes.HideBySig;
2279 parent.IsInterfaceMethod (
2280 iface_type, short_name, ret_type, parameters, true);
2283 Attribute dllimport_attr = null;
2284 if (OptAttributes != null && OptAttributes.AttributeSections != null) {
2285 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2286 if (asec.Attributes == null)
2289 foreach (Attribute a in asec.Attributes)
2290 if (a.Name.IndexOf ("DllImport") != -1) {
2291 flags |= MethodAttributes.PinvokeImpl;
2298 // Finally, define the method
2301 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2303 if ((ModFlags & Modifiers.STATIC) == 0) {
2304 Report.Error (601, Location, "The DllImport attribute must be specified on " +
2305 "a method marked 'static' and 'extern'.");
2309 EmitContext ec = new EmitContext (
2310 parent, Location, null, GetReturnType (parent), ModFlags);
2312 MethodBuilder = dllimport_attr.DefinePInvokeMethod (
2313 ec, parent.TypeBuilder,
2314 Name, flags, ret_type, parameters);
2317 MethodBuilder = parent.TypeBuilder.DefineMethod (
2319 GetCallingConvention (parent is Class),
2320 ret_type, parameters);
2322 if (implementing != null && explicit_impl)
2323 parent.TypeBuilder.DefineMethodOverride (
2324 MethodBuilder, implementing);
2327 if (MethodBuilder == null)
2331 // HACK because System.Reflection.Emit is lame
2333 ParameterInfo = new InternalParameters (parent, Parameters);
2335 if (!TypeManager.RegisterMethod (MethodBuilder, ParameterInfo,
2339 "Class `" + parent.Name + "' already contains a definition with " +
2340 " the same return value and parameter types for method `" +
2346 // This is used to track the Entry Point,
2348 // FIXME: Allow pluggable entry point, check arguments, etc.
2350 if (Name == "Main" &&
2351 ((ModFlags & Modifiers.STATIC) != 0) &&
2352 (RootContext.MainClass == null ||
2353 RootContext.MainClass == parent.TypeBuilder.FullName)){
2354 if (RootContext.EntryPoint != null){
2355 DuplicatEntryPoint (MethodBuilder);
2356 DuplicatEntryPoint (RootContext.EntryPoint);
2358 RootContext.EntryPoint = MethodBuilder;
2361 // FIXME: Verify that the method signature
2362 // is valid for an entry point, and report
2373 public void Emit (TypeContainer parent)
2378 if ((flags & MethodAttributes.PinvokeImpl) == 0)
2379 ig = MethodBuilder.GetILGenerator ();
2383 ec = new EmitContext (parent, Location, ig, GetReturnType (parent), ModFlags);
2385 if (OptAttributes != null)
2386 Attribute.ApplyAttributes (ec, MethodBuilder, this, OptAttributes, Location);
2389 LabelParameters (ec, ParameterTypes (parent), MethodBuilder);
2392 // abstract or extern methods have no bodies
2394 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
2398 // Handle destructors specially
2400 // FIXME: This code generates buggy code
2402 if (Name == "Finalize" && type_return_type == TypeManager.void_type)
2403 EmitDestructor (ec);
2405 ISymbolWriter sw = CodeGen.SymbolWriter;
2407 if ((sw != null) && (!Location.IsNull (Location))) {
2408 MethodToken token = MethodBuilder.GetToken ();
2409 sw.OpenMethod (new SymbolToken (token.Token));
2410 sw.SetMethodSourceRange (Location.SymbolDocument,
2412 Block.EndLocation.SymbolDocument,
2413 Block.EndLocation.Row, 0);
2415 ec.EmitTopBlock (Block, Location);
2419 ec.EmitTopBlock (Block, Location);
2423 void EmitDestructor (EmitContext ec)
2425 ILGenerator ig = ec.ig;
2427 Label finish = ig.DefineLabel ();
2428 bool old_in_try = ec.InTry;
2429 Expression member_lookup;
2431 ig.BeginExceptionBlock ();
2433 ec.ReturnLabel = finish;
2434 ec.EmitTopBlock (Block, Location);
2435 ec.InTry = old_in_try;
2437 ig.MarkLabel (finish);
2438 bool old_in_finally = ec.InFinally;
2439 ec.InFinally = true;
2440 ig.BeginFinallyBlock ();
2442 member_lookup = Expression.MemberLookup (
2443 ec, ec.ContainerType.BaseType, "Finalize",
2444 MemberTypes.Method, Expression.AllBindingFlags, Location);
2446 if (member_lookup != null){
2447 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
2449 ig.Emit (OpCodes.Ldarg_0);
2450 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
2452 ec.InFinally = old_in_finally;
2454 ig.EndExceptionBlock ();
2455 //ig.MarkLabel (ec.ReturnLabel);
2456 ig.Emit (OpCodes.Ret);
2460 public abstract class ConstructorInitializer {
2461 ArrayList argument_list;
2462 ConstructorInfo parent_constructor;
2465 public ConstructorInitializer (ArrayList argument_list, Location location)
2467 this.argument_list = argument_list;
2468 this.location = location;
2471 public ArrayList Arguments {
2473 return argument_list;
2477 public bool Resolve (EmitContext ec)
2479 Expression parent_constructor_group;
2482 if (argument_list != null){
2483 for (int i = argument_list.Count; i > 0; ){
2486 Argument a = (Argument) argument_list [i];
2487 if (!a.Resolve (ec, location))
2492 if (this is ConstructorBaseInitializer)
2493 t = ec.ContainerType.BaseType;
2495 t = ec.ContainerType;
2497 parent_constructor_group = Expression.MemberLookup (
2499 MemberTypes.Constructor,
2500 BindingFlags.Public | BindingFlags.Instance, location);
2502 if (parent_constructor_group == null){
2503 Console.WriteLine ("Could not find a constructor in our parent");
2507 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2508 (MethodGroupExpr) parent_constructor_group, argument_list, location);
2510 if (parent_constructor == null){
2511 Console.WriteLine ("Could not locate a proper overload function");
2518 public void Emit (EmitContext ec)
2520 ec.ig.Emit (OpCodes.Ldarg_0);
2521 if (argument_list != null)
2522 Invocation.EmitArguments (ec, null, argument_list);
2523 ec.ig.Emit (OpCodes.Call, parent_constructor);
2527 public class ConstructorBaseInitializer : ConstructorInitializer {
2528 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2533 public class ConstructorThisInitializer : ConstructorInitializer {
2534 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2539 public class Constructor : MethodCore {
2540 public ConstructorBuilder ConstructorBuilder;
2541 public ConstructorInitializer Initializer;
2542 public Attributes OptAttributes;
2545 // Modifiers allowed for a constructor.
2547 const int AllowedModifiers =
2549 Modifiers.PROTECTED |
2550 Modifiers.INTERNAL |
2556 // The spec claims that static is not permitted, but
2557 // my very own code has static constructors.
2559 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2560 : base (name, args, l)
2566 // Returns true if this is a default constructor
2568 public bool IsDefault ()
2570 if ((ModFlags & Modifiers.STATIC) != 0)
2571 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2572 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2575 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2576 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2577 (Initializer is ConstructorBaseInitializer) &&
2578 (Initializer.Arguments == null);
2582 // Creates the ConstructorBuilder
2584 public override bool Define (TypeContainer parent)
2586 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2587 MethodAttributes.SpecialName);
2589 Type [] parameters = ParameterTypes (parent);
2591 if ((ModFlags & Modifiers.STATIC) != 0)
2592 ca |= MethodAttributes.Static;
2594 if (parent is Struct && parameters.Length == 0){
2597 "Structs can not contain explicit parameterless " +
2601 ca |= MethodAttributes.Public | MethodAttributes.HideBySig;
2604 foreach (Type partype in parameters)
2605 if (!TypeContainer.AsAccessible (partype, ModFlags))
2608 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2609 ca, GetCallingConvention (parent is Class), parameters);
2612 // HACK because System.Reflection.Emit is lame
2614 ParameterInfo = new InternalParameters (parent, Parameters);
2616 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, parameters)) {
2619 "Class `" +parent.Name+ "' already contains a definition with the " +
2620 "same return value and parameter types for constructor `" + Name
2631 public void Emit (TypeContainer parent)
2633 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2634 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2636 if (parent is Class && ((ModFlags & Modifiers.STATIC) == 0)){
2637 if (Initializer == null)
2638 Initializer = new ConstructorBaseInitializer (null, parent.Location);
2640 if (!Initializer.Resolve (ec)){
2641 Console.WriteLine ("Could not resolve initializer: " + parent.Name);
2645 LabelParameters (ec, ParameterTypes (parent), ConstructorBuilder);
2648 // Classes can have base initializers and instance field initializers.
2650 if (parent is Class){
2651 if ((ModFlags & Modifiers.STATIC) == 0){
2652 parent.EmitFieldInitializers (ec);
2653 Initializer.Emit (ec);
2657 if ((ModFlags & Modifiers.STATIC) != 0)
2658 parent.EmitFieldInitializers (ec);
2660 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2662 ec.EmitTopBlock (Block, Location);
2666 public class Field : MemberCore {
2667 public readonly string Type;
2668 public readonly Object Initializer;
2669 public readonly Attributes OptAttributes;
2670 public FieldBuilder FieldBuilder;
2671 public Status status;
2674 public enum Status : byte { ASSIGNED = 1, USED = 2 }
2678 // Modifiers allowed in a class declaration
2680 const int AllowedModifiers =
2683 Modifiers.PROTECTED |
2684 Modifiers.INTERNAL |
2687 Modifiers.VOLATILE |
2691 public Field (string type, int mod, string name, Object expr_or_array_init,
2692 Attributes attrs, Location loc)
2696 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, loc);
2697 Initializer = expr_or_array_init;
2698 OptAttributes = attrs;
2701 public override bool Define (TypeContainer parent)
2703 Type t = RootContext.LookupType (parent, Type, false, Location);
2708 if (!TypeContainer.AsAccessible (t, ModFlags))
2711 if (t.IsPointer && !UnsafeOK (parent))
2714 if (RootContext.WarningLevel > 1){
2715 Type ptype = parent.TypeBuilder.BaseType;
2717 // ptype is only null for System.Object while compiling corlib.
2721 mi = TypeContainer.FindMembers (
2722 ptype, MemberTypes.Method,
2723 BindingFlags.Public |
2724 BindingFlags.Static | BindingFlags.Instance,
2725 System.Type.FilterName, Name);
2729 if ((ModFlags & Modifiers.VOLATILE) != 0){
2731 if (TypeManager.IsEnumType (t))
2732 t = TypeManager.EnumToUnderlying (t);
2734 if (!((t == TypeManager.bool_type) ||
2735 (t == TypeManager.sbyte_type) ||
2736 (t == TypeManager.byte_type) ||
2737 (t == TypeManager.short_type) ||
2738 (t == TypeManager.ushort_type) ||
2739 (t == TypeManager.int32_type) ||
2740 (t == TypeManager.uint32_type) ||
2741 (t == TypeManager.char_type) ||
2742 (t == TypeManager.float_type))){
2744 677, Location, parent.MakeName (Name) +
2745 " A volatile field can not be of type `" +
2746 TypeManager.CSharpName (t) + "'");
2752 FieldBuilder = parent.TypeBuilder.DefineField (
2753 Name, t, Modifiers.FieldAttr (ModFlags));
2755 TypeManager.RegisterField (FieldBuilder, this);
2759 public void Emit (TypeContainer tc)
2761 EmitContext ec = new EmitContext (tc, Location, null,
2762 FieldBuilder.FieldType, ModFlags);
2764 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
2768 public class Property : MemberCore {
2769 public readonly string Type;
2770 public Block Get, Set;
2771 public PropertyBuilder PropertyBuilder;
2772 public Attributes OptAttributes;
2773 public MethodBuilder GetBuilder, SetBuilder;
2776 // The type, once we compute it.
2780 const int AllowedModifiers =
2783 Modifiers.PROTECTED |
2784 Modifiers.INTERNAL |
2788 Modifiers.OVERRIDE |
2789 Modifiers.ABSTRACT |
2793 public Property (string type, string name, int mod_flags, Block get_block, Block set_block,
2794 Attributes attrs, Location loc)
2798 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
2801 OptAttributes = attrs;
2805 // Checks our base implementation if any
2807 bool CheckBase (MethodAttributes flags, TypeContainer parent)
2810 // Find properties with the same name on the base class
2812 MemberInfo [] props;
2813 MemberInfo [] props_static = TypeContainer.FindMembers (
2814 parent.TypeBuilder.BaseType,
2815 MemberTypes.All, BindingFlags.Public | BindingFlags.Static,
2816 System.Type.FilterName, Name);
2818 MemberInfo [] props_instance = TypeContainer.FindMembers (
2819 parent.TypeBuilder.BaseType,
2820 MemberTypes.All, BindingFlags.Public | BindingFlags.Instance,
2821 System.Type.FilterName, Name);
2824 // Find if we have anything
2826 if (props_static != null && props_static.Length > 0)
2827 props = props_static;
2828 else if (props_instance != null && props_instance.Length > 0)
2829 props = props_instance;
2834 // If we have something on the base.
2835 if (props != null && props.Length > 0){
2838 // Currently we expect only to get 1 match at most from our
2839 // base class, maybe we can get more than one, investigate
2840 // whether this is possible
2842 if (props.Length > 1)
2843 throw new Exception ("How do we handle this?");
2845 PropertyInfo pi = (PropertyInfo) props [0];
2847 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
2848 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
2850 MethodInfo reference = inherited_get == null ?
2851 inherited_set : inherited_get;
2853 if (reference != null)
2854 if (!CheckMethodAgainstBase (parent, flags, reference))
2858 if ((ModFlags & Modifiers.NEW) != 0)
2859 WarningNotHiding (parent);
2861 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2862 Report.Error (115, Location,
2863 parent.MakeName (Name) +
2864 " no suitable methods found to override");
2871 bool DefineMethod (TypeContainer parent, Type iface_type, string short_name,
2872 MethodAttributes flags, bool is_get)
2874 Type [] parameters = TypeManager.NoTypes;
2875 MethodInfo implementing;
2880 fn_type = PropertyType;
2881 name = "get_" + short_name;
2883 name = "set_" + short_name;
2884 parameters = new Type [1];
2885 parameters [0] = PropertyType;
2886 fn_type = TypeManager.void_type;
2889 implementing = parent.IsInterfaceMethod (
2890 iface_type, name, fn_type, parameters, false);
2893 // For implicit implementations, make sure we are public, for
2894 // explicit implementations, make sure we are private.
2896 if (implementing != null){
2898 // Setting null inside this block will trigger a more
2899 // verbose error reporting for missing interface implementations
2901 // The "candidate" function has been flagged already
2902 // but it wont get cleared
2904 if (iface_type == null){
2906 // We already catch different accessibility settings
2907 // so we just need to check that we are not private
2909 if ((ModFlags & Modifiers.PRIVATE) != 0)
2910 implementing = null;
2913 // Static is not allowed
2915 if ((ModFlags & Modifiers.STATIC) != 0)
2916 implementing = null;
2918 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2920 106, Location, "`public' or `abstract' modifiers "+
2921 "are not allowed in explicit interface declarations"
2923 implementing = null;
2929 // If implementing is still valid, set flags
2931 if (implementing != null){
2933 // When implementing interface methods, set NewSlot.
2935 if (implementing.DeclaringType.IsInterface)
2936 flags |= MethodAttributes.NewSlot;
2939 MethodAttributes.Virtual |
2940 MethodAttributes.HideBySig;
2943 // clear the pending flag
2945 parent.IsInterfaceMethod (
2946 iface_type, name, fn_type, parameters, true);
2950 // If this is not an explicit interface implementation,
2951 // clear implementing, as it is only used for explicit
2952 // interface implementation
2954 if (Name.IndexOf (".") == -1)
2955 implementing = null;
2958 GetBuilder = parent.TypeBuilder.DefineMethod (
2959 name, flags, PropertyType, null);
2960 PropertyBuilder.SetGetMethod (GetBuilder);
2962 if (implementing != null)
2963 parent.TypeBuilder.DefineMethodOverride (
2964 GetBuilder, implementing);
2967 // HACK because System.Reflection.Emit is lame
2969 InternalParameters ip = new InternalParameters (
2970 parent, Parameters.GetEmptyReadOnlyParameters ());
2972 if (!TypeManager.RegisterMethod (GetBuilder, ip, null)) {
2973 Report.Error (111, Location,
2974 "Class `" + parent.Name +
2975 "' already contains a definition with the " +
2976 "same return value and parameter types as the " +
2977 "'get' method of property `" + Name + "'");
2981 SetBuilder = parent.TypeBuilder.DefineMethod (
2982 name, flags, null, parameters);
2984 if (implementing != null)
2985 parent.TypeBuilder.DefineMethodOverride (
2986 SetBuilder, implementing);
2988 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
2989 PropertyBuilder.SetSetMethod (SetBuilder);
2992 // HACK because System.Reflection.Emit is lame
2994 Parameter [] parms = new Parameter [1];
2995 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
2996 InternalParameters ip = new InternalParameters (
2997 parent, new Parameters (parms, null, Location));
2999 if (!TypeManager.RegisterMethod (SetBuilder, ip, parameters)) {
3002 "Class `" + parent.Name +
3003 "' already contains a definition with the " +
3004 "same return value and parameter types as the " +
3005 "'set' method of property `" + Name + "'");
3013 public override bool Define (TypeContainer parent)
3015 Type iface_type = null;
3018 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3021 MethodAttributes flags = Modifiers.MethodAttr (ModFlags);
3023 flags |= MethodAttributes.HideBySig |
3024 MethodAttributes.SpecialName;
3026 // Lookup Type, verify validity
3027 PropertyType = RootContext.LookupType (parent, Type, false, Location);
3028 if (PropertyType == null)
3031 // verify accessibility
3032 if (!TypeContainer.AsAccessible (PropertyType, ModFlags))
3035 if (PropertyType.IsPointer && !UnsafeOK (parent))
3038 if (!CheckBase (flags, parent))
3042 // Check for explicit interface implementation
3044 if (Name.IndexOf (".") != -1){
3045 int pos = Name.LastIndexOf (".");
3046 string iface = Name.Substring (0, pos);
3048 iface_type = RootContext.LookupType (parent, iface, false, Location);
3049 if (iface_type == null)
3052 short_name = Name.Substring (pos + 1);
3054 // Compute the full name that we need to export.
3055 Name = iface_type.FullName + "." + short_name;
3059 // FIXME - PropertyAttributes.HasDefault ?
3061 PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
3062 PropertyAttributes.SpecialName;
3064 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3065 Name, prop_attr, PropertyType, null);
3068 if (!DefineMethod (parent, iface_type, short_name, flags, true))
3072 if (!DefineMethod (parent, iface_type, short_name, flags, false))
3076 // HACK for the reasons exposed above
3078 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3081 "Class `" + parent.Name +
3082 "' already contains a definition for the property `" +
3090 public void Emit (TypeContainer tc)
3095 ec = new EmitContext (tc, Location, null, PropertyType, ModFlags);
3096 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3100 // abstract or extern properties have no bodies
3102 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3106 ig = GetBuilder.GetILGenerator ();
3107 ec = new EmitContext (tc, Location, ig, PropertyType, ModFlags);
3109 ec.EmitTopBlock (Get, Location);
3113 ig = SetBuilder.GetILGenerator ();
3114 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3116 ec.EmitTopBlock (Set, Location);
3123 /// Gigantic workaround for lameness in SRE follows :
3124 /// This class derives from EventInfo and attempts to basically
3125 /// wrap around the EventBuilder so that FindMembers can quickly
3126 /// return this in it search for members
3128 public class MyEventBuilder : EventInfo {
3131 // We use this to "point" to our Builder which is
3132 // not really a MemberInfo
3134 EventBuilder MyBuilder;
3137 // We "catch" and wrap these methods
3139 MethodInfo raise, remove, add;
3141 EventAttributes attributes;
3142 Type declaring_type, reflected_type, event_type;
3145 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3147 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3149 // And now store the values in our own fields.
3151 declaring_type = type_builder;
3153 // FIXME : This is supposed to be MyBuilder but since that doesn't
3154 // derive from Type, I have no clue what to do with this.
3155 reflected_type = null;
3157 attributes = event_attr;
3159 this.event_type = event_type;
3163 // Methods that you have to override. Note that you only need
3164 // to "implement" the variants that take the argument (those are
3165 // the "abstract" methods, the others (GetAddMethod()) are
3168 public override MethodInfo GetAddMethod (bool nonPublic)
3173 public override MethodInfo GetRemoveMethod (bool nonPublic)
3178 public override MethodInfo GetRaiseMethod (bool nonPublic)
3184 // These methods make "MyEventInfo" look like a Builder
3186 public void SetRaiseMethod (MethodBuilder raiseMethod)
3188 raise = raiseMethod;
3189 MyBuilder.SetRaiseMethod (raiseMethod);
3192 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3194 remove = removeMethod;
3195 MyBuilder.SetRemoveOnMethod (removeMethod);
3198 public void SetAddOnMethod (MethodBuilder addMethod)
3201 MyBuilder.SetAddOnMethod (addMethod);
3204 public void SetCustomAttribute (CustomAttributeBuilder cb)
3206 MyBuilder.SetCustomAttribute (cb);
3209 public override object [] GetCustomAttributes (bool inherit)
3211 // FIXME : There's nothing which can be seemingly done here because
3212 // we have no way of getting at the custom attribute objects of the
3217 public override object [] GetCustomAttributes (Type t, bool inherit)
3219 // FIXME : Same here !
3223 public override bool IsDefined (Type t, bool b)
3228 public override EventAttributes Attributes {
3234 public override string Name {
3240 public override Type DeclaringType {
3242 return declaring_type;
3246 public override Type ReflectedType {
3248 return reflected_type;
3252 public Type EventType {
3259 public class Event : MemberCore {
3261 const int AllowedModifiers =
3264 Modifiers.PROTECTED |
3265 Modifiers.INTERNAL |
3270 Modifiers.OVERRIDE |
3274 public readonly string Type;
3275 public readonly Object Initializer;
3276 public readonly Block Add;
3277 public readonly Block Remove;
3278 public MyEventBuilder EventBuilder;
3279 public FieldBuilder FieldBuilder;
3280 public Attributes OptAttributes;
3283 MethodBuilder AddBuilder, RemoveBuilder;
3286 public Event (string type, string name, Object init, int flags, Block add_block,
3287 Block rem_block, Attributes attrs, Location loc)
3292 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE, loc);
3295 OptAttributes = attrs;
3298 public override bool Define (TypeContainer parent)
3300 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3303 MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
3304 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3306 EventType = RootContext.LookupType (parent, Type, false, Location);
3307 if (EventType == null)
3310 if (!TypeContainer.AsAccessible (EventType, ModFlags))
3313 if (EventType.IsPointer && !UnsafeOK (parent))
3316 if (!EventType.IsSubclassOf (TypeManager.delegate_type)) {
3317 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3318 "' : event must be of a delegate type");
3322 Type [] parameters = new Type [1];
3323 parameters [0] = EventType;
3325 EventBuilder = new MyEventBuilder (parent.TypeBuilder, Name, e_attr, EventType);
3327 if (Add == null && Remove == null)
3328 FieldBuilder = parent.TypeBuilder.DefineField (Name, EventType, FieldAttributes.Private);
3331 // Now define the accessors
3334 AddBuilder = parent.TypeBuilder.DefineMethod (
3335 "add_" + Name, m_attr, null, parameters);
3336 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3337 EventBuilder.SetAddOnMethod (AddBuilder);
3340 // HACK because System.Reflection.Emit is lame
3342 Parameter [] parms = new Parameter [1];
3343 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3344 InternalParameters ip = new InternalParameters (
3345 parent, new Parameters (parms, null, Location));
3347 if (!TypeManager.RegisterMethod (AddBuilder, ip, parameters)) {
3348 Report.Error (111, Location,
3349 "Class `" + parent.Name + "' already contains a definition with the " +
3350 "same return value and parameter types for the " +
3351 "'add' method of event `" + Name + "'");
3355 RemoveBuilder = parent.TypeBuilder.DefineMethod (
3356 "remove_" + Name, m_attr, null, parameters);
3357 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3358 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3361 // HACK because System.Reflection.Emit is lame
3364 if (!TypeManager.RegisterMethod (RemoveBuilder, ip, parameters)) {
3365 Report.Error (111, Location,
3366 "Class `" + parent.Name + "' already contains a definition with the " +
3367 "same return value and parameter types for the " +
3368 "'remove' method of event `" + Name + "'");
3372 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3373 Report.Error (111, Location,
3374 "Class `" + parent.Name +
3375 "' already contains a definition for the event `" +
3383 void EmitDefaultMethod (EmitContext ec, bool is_add)
3385 ILGenerator ig = ec.ig;
3386 MethodInfo method = null;
3389 method = TypeManager.delegate_combine_delegate_delegate;
3391 method = TypeManager.delegate_remove_delegate_delegate;
3393 ig.Emit (OpCodes.Ldarg_0);
3394 ig.Emit (OpCodes.Ldarg_0);
3395 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3396 ig.Emit (OpCodes.Ldarg_1);
3397 ig.Emit (OpCodes.Call, method);
3398 ig.Emit (OpCodes.Castclass, EventType);
3399 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3400 ig.Emit (OpCodes.Ret);
3403 public void Emit (TypeContainer tc)
3408 ig = AddBuilder.GetILGenerator ();
3409 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3412 ec.EmitTopBlock (Add, Location);
3414 EmitDefaultMethod (ec, true);
3416 ig = RemoveBuilder.GetILGenerator ();
3417 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3420 ec.EmitTopBlock (Remove, Location);
3422 EmitDefaultMethod (ec, false);
3424 ec = new EmitContext (tc, Location, null, EventType, ModFlags);
3425 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3432 // FIXME: This does not handle:
3434 // int INTERFACENAME [ args ]
3438 // int this [ args ]
3440 public class Indexer : MemberCore {
3442 const int AllowedModifiers =
3445 Modifiers.PROTECTED |
3446 Modifiers.INTERNAL |
3450 Modifiers.OVERRIDE |
3454 public readonly string Type;
3455 public readonly string InterfaceType;
3456 public readonly Parameters FormalParameters;
3457 public readonly Block Get;
3458 public readonly Block Set;
3459 public Attributes OptAttributes;
3460 public MethodBuilder GetBuilder;
3461 public MethodBuilder SetBuilder;
3462 public PropertyBuilder PropertyBuilder;
3463 public Type IndexerType;
3465 public Indexer (string type, string int_type, int flags, Parameters parms,
3466 Block get_block, Block set_block, Attributes attrs, Location loc)
3471 InterfaceType = int_type;
3472 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE, loc);
3473 FormalParameters = parms;
3476 OptAttributes = attrs;
3479 void DefineMethod (TypeContainer parent, Type iface_type,
3480 Type ret_type, string name,
3481 Type [] parameters, MethodAttributes attr, bool is_get)
3483 MethodInfo implementing;
3485 implementing = parent.IsInterfaceMethod (
3486 iface_type, name, ret_type, parameters, false);
3489 // Setting null inside this block will trigger a more
3490 // verbose error reporting for missing interface implementations
3492 // The "candidate" function has been flagged already
3493 // but it wont get cleared
3495 if (implementing != null){
3496 if (iface_type == null){
3498 // We already catch different accessibility settings
3499 // so we just need to check that we are not private
3501 if ((ModFlags & Modifiers.PRIVATE) != 0)
3502 implementing = null;
3505 // Static is not allowed
3507 if ((ModFlags & Modifiers.STATIC) != 0)
3508 implementing = null;
3510 if((ModFlags&(Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
3513 "`public' or `abstract' modifiers are not "+
3514 "allowed in explicit interface declarations"
3516 implementing = null;
3520 if (implementing != null){
3522 // When implementing interface methods, set NewSlot.
3524 if (implementing.DeclaringType.IsInterface)
3525 attr |= MethodAttributes.NewSlot;
3528 MethodAttributes.Virtual |
3529 MethodAttributes.HideBySig;
3532 // clear the pending flag
3534 parent.IsInterfaceMethod (
3535 iface_type, name, ret_type, parameters, true);
3539 // If this is not an explicit interface implementation,
3540 // clear implementing, as it is only used for explicit
3541 // interface implementation
3543 if (Name.IndexOf (".") == -1)
3544 implementing = null;
3548 string meth_name = "get_Item";
3549 if (iface_type != null)
3550 meth_name = iface_type + ".get_Item";
3552 GetBuilder = parent.TypeBuilder.DefineMethod (
3553 meth_name, attr, IndexerType, parameters);
3555 if (implementing != null)
3556 parent.TypeBuilder.DefineMethodOverride (
3557 GetBuilder, implementing);
3560 PropertyBuilder.SetGetMethod (GetBuilder);
3563 string meth_name = "set_Item";
3565 if (iface_type != null)
3566 meth_name = iface_type + ".set_Item";
3568 SetBuilder = parent.TypeBuilder.DefineMethod (
3569 meth_name, attr, null, parameters);
3570 if (implementing != null)
3571 parent.TypeBuilder.DefineMethodOverride (
3572 SetBuilder, implementing);
3574 PropertyBuilder.SetSetMethod (SetBuilder);
3578 public override bool Define (TypeContainer parent)
3580 PropertyAttributes prop_attr =
3581 PropertyAttributes.RTSpecialName |
3582 PropertyAttributes.SpecialName;
3585 IndexerType = RootContext.LookupType (parent, Type, false, Location);
3586 Type [] parameters = FormalParameters.GetParameterInfo (parent);
3588 // Check if the return type and arguments were correct
3589 if (IndexerType == null || parameters == null)
3592 if (!parent.MethodModifiersValid (ModFlags, InterfaceType == null ?
3593 "this" : InterfaceType, Location))
3597 // verify accessibility and unsafe pointers
3599 if (!TypeContainer.AsAccessible (IndexerType, ModFlags))
3602 if (IndexerType.IsPointer && !UnsafeOK (parent))
3605 foreach (Type partype in parameters){
3606 if (!TypeContainer.AsAccessible (partype, ModFlags))
3608 if (partype.IsPointer && !UnsafeOK (parent))
3615 Type iface_type = null;
3617 if (InterfaceType != null){
3618 iface_type = RootContext.LookupType (parent, InterfaceType, false, Location);
3619 if (iface_type == null)
3624 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3625 TypeManager.IndexerPropertyName (parent.TypeBuilder),
3626 prop_attr, IndexerType, parameters);
3628 MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
3631 DefineMethod (parent, iface_type, IndexerType, "get_Item",
3632 parameters, attr, true);
3633 InternalParameters pi = new InternalParameters (parent, FormalParameters);
3634 if (!TypeManager.RegisterMethod (GetBuilder, pi, parameters)) {
3635 Report.Error (111, Location,
3636 "Class `" + parent.Name +
3637 "' already contains a definition with the " +
3638 "same return value and parameter types for the " +
3645 int top = parameters.Length;
3646 Type [] set_pars = new Type [top + 1];
3647 parameters.CopyTo (set_pars, 0);
3648 set_pars [top] = IndexerType;
3650 Parameter [] fixed_parms = FormalParameters.FixedParameters;
3652 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
3654 fixed_parms.CopyTo (tmp, 0);
3655 tmp [fixed_parms.Length] = new Parameter (
3656 Type, "value", Parameter.Modifier.NONE, null);
3658 Parameters set_formal_params = new Parameters (tmp, null, Location);
3661 parent, iface_type, TypeManager.void_type,
3662 "set_Item", set_pars, attr, false);
3664 InternalParameters ip = new InternalParameters (parent, set_formal_params);
3666 if (!TypeManager.RegisterMethod (SetBuilder, ip, set_pars)) {
3669 "Class `" + parent.Name + "' already contains a " +
3670 "definition with the " +
3671 "same return value and parameter types for the " +
3678 // Now name the parameters
3680 Parameter [] p = FormalParameters.FixedParameters;
3684 for (i = 0; i < p.Length; ++i) {
3686 GetBuilder.DefineParameter (
3687 i + 1, p [i].Attributes, p [i].Name);
3690 SetBuilder.DefineParameter (
3691 i + 1, p [i].Attributes, p [i].Name);
3695 SetBuilder.DefineParameter (
3696 i + 1, ParameterAttributes.None, "value");
3698 if (i != parameters.Length) {
3699 Parameter array_param = FormalParameters.ArrayParameter;
3700 SetBuilder.DefineParameter (i + 1, array_param.Attributes,
3705 TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
3710 public void Emit (TypeContainer tc)
3715 ec = new EmitContext (tc, Location, null, IndexerType, ModFlags);
3716 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3719 ig = GetBuilder.GetILGenerator ();
3720 ec = new EmitContext (tc, Location, ig, IndexerType, ModFlags);
3722 ec.EmitTopBlock (Get, Location);
3726 ig = SetBuilder.GetILGenerator ();
3727 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3729 ec.EmitTopBlock (Set, Location);
3734 public class Operator : MemberCore {
3736 const int AllowedModifiers =
3742 const int RequiredModifiers =
3746 public enum OpType : byte {
3756 // Unary and Binary operators
3779 // Implicit and Explicit
3784 public readonly OpType OperatorType;
3785 public readonly string ReturnType;
3786 public readonly string FirstArgType;
3787 public readonly string FirstArgName;
3788 public readonly string SecondArgType;
3789 public readonly string SecondArgName;
3790 public readonly Block Block;
3791 public Attributes OptAttributes;
3792 public MethodBuilder OperatorMethodBuilder;
3794 public string MethodName;
3795 public Method OperatorMethod;
3797 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
3798 string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
3801 OperatorType = type;
3802 ReturnType = ret_type;
3803 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
3804 FirstArgType = arg1type;
3805 FirstArgName = arg1name;
3806 SecondArgType = arg2type;
3807 SecondArgName = arg2name;
3809 OptAttributes = attrs;
3812 string Prototype (TypeContainer parent)
3814 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
3815 SecondArgType + ")";
3818 public override bool Define (TypeContainer parent)
3821 MethodName = "op_" + OperatorType;
3823 if (SecondArgType != null)
3826 Parameter [] param_list = new Parameter [length];
3828 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
3831 "User defined operators `" +
3832 Prototype (parent) +
3833 "' must be declared static and public");
3837 param_list[0] = new Parameter (FirstArgType, FirstArgName,
3838 Parameter.Modifier.NONE, null);
3839 if (SecondArgType != null)
3840 param_list[1] = new Parameter (SecondArgType, SecondArgName,
3841 Parameter.Modifier.NONE, null);
3843 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
3844 new Parameters (param_list, null, Location),
3845 OptAttributes, Mono.CSharp.Location.Null);
3847 OperatorMethod.Define (parent);
3849 if (OperatorMethod.MethodBuilder == null)
3852 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
3854 Type [] param_types = OperatorMethod.ParameterTypes (parent);
3855 Type declaring_type = OperatorMethodBuilder.DeclaringType;
3856 Type return_type = OperatorMethod.GetReturnType (parent);
3857 Type first_arg_type = param_types [0];
3859 // Rules for conversion operators
3861 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
3862 if (first_arg_type == return_type && first_arg_type == declaring_type){
3865 "User-defined conversion cannot take an object of the " +
3866 "enclosing type and convert to an object of the enclosing" +
3871 if (first_arg_type != declaring_type && return_type != declaring_type){
3874 "User-defined conversion must convert to or from the " +
3879 if (first_arg_type == TypeManager.object_type ||
3880 return_type == TypeManager.object_type){
3883 "User-defined conversion cannot convert to or from " +
3888 if (first_arg_type.IsInterface || return_type.IsInterface){
3891 "User-defined conversion cannot convert to or from an " +
3896 if (first_arg_type.IsSubclassOf (return_type) ||
3897 return_type.IsSubclassOf (first_arg_type)){
3900 "User-defined conversion cannot convert between types " +
3901 "that derive from each other");
3904 } else if (SecondArgType == null) {
3905 // Checks for Unary operators
3907 if (first_arg_type != declaring_type){
3910 "The parameter of a unary operator must be the " +
3915 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
3916 if (return_type != declaring_type){
3919 "The parameter and return type for ++ and -- " +
3920 "must be the containing type");
3926 if (OperatorType == OpType.True || OperatorType == OpType.False) {
3927 if (return_type != TypeManager.bool_type){
3930 "The return type of operator True or False " +
3937 // Checks for Binary operators
3939 if (first_arg_type != declaring_type &&
3940 param_types [1] != declaring_type){
3943 "One of the parameters of a binary operator must " +
3944 "be the containing type");
3952 public void Emit (TypeContainer parent)
3954 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
3955 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
3958 // abstract or extern methods have no bodies
3960 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3963 OperatorMethod.Block = Block;
3964 OperatorMethod.Emit (parent);
3969 // This is used to compare method signatures
3971 struct MethodSignature {
3973 public Type RetType;
3974 public Type [] Parameters;
3977 /// This delegate is used to extract methods which have the
3978 /// same signature as the argument
3980 public static MemberFilter method_signature_filter;
3983 /// This delegate is used to extract inheritable methods which
3984 /// have the same signature as the argument. By inheritable,
3985 /// this means that we have permissions to override the method
3986 /// from the current assembly and class
3988 public static MemberFilter inheritable_method_signature_filter;
3990 static MethodSignature ()
3992 method_signature_filter = new MemberFilter (MemberSignatureCompare);
3993 inheritable_method_signature_filter = new MemberFilter (
3994 InheritableMemberSignatureCompare);
3997 public MethodSignature (string name, Type ret_type, Type [] parameters)
4002 if (parameters == null)
4003 Parameters = TypeManager.NoTypes;
4005 Parameters = parameters;
4008 public override int GetHashCode ()
4010 return Name.GetHashCode ();
4013 public override bool Equals (Object o)
4015 MethodSignature other = (MethodSignature) o;
4017 if (other.Name != Name)
4020 if (other.RetType != RetType)
4023 if (Parameters == null){
4024 if (other.Parameters == null)
4029 if (other.Parameters == null)
4032 int c = Parameters.Length;
4033 if (other.Parameters.Length != c)
4036 for (int i = 0; i < c; i++)
4037 if (other.Parameters [i] != Parameters [i])
4043 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4047 if (! (m is MethodInfo))
4050 MethodSignature sig = (MethodSignature) filter_criteria;
4052 if (m.Name != sig.Name)
4055 mi = (MethodInfo) m;
4057 if (mi.ReturnType != sig.RetType)
4060 Type [] args = TypeManager.GetArgumentTypes (mi);
4061 Type [] sigp = sig.Parameters;
4063 if (args.Length != sigp.Length)
4066 for (int i = args.Length; i > 0; ){
4068 if (args [i] != sigp [i])
4075 // This filter should be used when we are requesting methods that
4076 // we want to override.
4078 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4080 if (MemberSignatureCompare (m, filter_criteria)){
4081 MethodInfo mi = (MethodInfo) m;
4082 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4084 // If only accessible to the current class.
4085 if (prot == MethodAttributes.Private)
4088 // If only accessible to the defining assembly or
4089 if (prot == MethodAttributes.FamANDAssem ||
4090 prot == MethodAttributes.Assembly){
4091 if (m is MethodBuilder)
4097 // Anything else (FamOrAssembly and Public) is fine