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;
638 icount = ifaces.Length;
641 // If we are implementing an abstract class, and we are not
642 // ourselves abstract, and there are abstract methods (C# allows
643 // abstract classes that have no abstract methods), then allocate
646 // We also pre-compute the methods.
648 bool implementing_abstract = (b.IsAbstract && !TypeBuilder.IsAbstract);
649 ArrayList abstract_methods = null;
651 if (implementing_abstract){
652 abstract_methods = GetAbstractMethods (b);
654 if (abstract_methods == null)
655 implementing_abstract = false;
658 int total = icount + (implementing_abstract ? 1 : 0);
662 pending_implementations = new TypeAndMethods [total];
666 foreach (Type t in ifaces){
669 if (t is TypeBuilder){
672 iface = RootContext.TypeManager.LookupInterface (t);
674 mi = iface.GetMethods ();
676 mi = t.GetMethods ();
678 int count = mi.Length;
679 pending_implementations [i].type = t;
680 pending_implementations [i].methods = mi;
681 pending_implementations [i].args = new Type [count][];
682 pending_implementations [i].found = new bool [count];
685 foreach (MethodInfo m in mi){
686 Type [] types = TypeManager.GetArgumentTypes (m);
688 pending_implementations [i].args [j] = types;
695 if (abstract_methods != null){
696 int count = abstract_methods.Count;
697 pending_implementations [i].methods = new MethodInfo [count];
699 abstract_methods.CopyTo (pending_implementations [i].methods, 0);
700 pending_implementations [i].found = new bool [count];
701 pending_implementations [i].args = new Type [count][];
702 pending_implementations [i].type = TypeBuilder;
705 foreach (MemberInfo m in abstract_methods){
706 MethodInfo mi = (MethodInfo) m;
708 Type [] types = TypeManager.GetArgumentTypes (mi);
710 pending_implementations [i].args [j] = types;
716 public static string MakeFQN (string nsn, string name)
718 string prefix = (nsn == "" ? "" : nsn + ".");
720 return prefix + name;
723 Type LookupInterfaceOrClass (object builder, string ns, string name, bool is_class, out bool error)
725 TypeContainer parent;
729 name = MakeFQN (ns, name);
731 t = RootContext.TypeManager.LookupType (name);
736 parent = (Class) RootContext.Tree.Classes [name];
738 parent = (Struct) RootContext.Tree.Structs [name];
742 t = parent.DefineType (builder);
744 Report.Error (146, "Class definition is circular: `"+name+"'");
756 // returns the type for an interface or a class, this will recursively
757 // try to define the types that it depends on.
759 Type GetInterfaceOrClass (object builder, string name, bool is_class)
765 // Attempt to lookup the class on our namespace
767 t = LookupInterfaceOrClass (builder, Namespace.Name, name, is_class, out error);
775 // Attempt to do a direct unqualified lookup
777 t = LookupInterfaceOrClass (builder, "", name, is_class, out error);
785 // Attempt to lookup the class on any of the `using'
789 for (Namespace ns = Namespace; ns != null; ns = ns.Parent){
790 ArrayList using_list = ns.UsingTable;
792 if (using_list == null)
795 foreach (string n in using_list){
796 t = LookupInterfaceOrClass (builder, n, name, is_class, out error);
805 Report.Error (246, "Can not find type `"+name+"'");
810 /// This function computes the Base class and also the
811 /// list of interfaces that the class or struct @c implements.
813 /// The return value is an array (might be null) of
814 /// interfaces implemented (as Types).
816 /// The @parent argument is set to the parent object or null
817 /// if this is `System.Object'.
819 Type [] GetClassBases (object builder, bool is_class, out Type parent, out bool error)
821 ArrayList bases = Bases;
830 parent = TypeManager.value_type;
834 if (RootContext.StdLib)
835 parent = TypeManager.object_type;
836 else if (Name != "System.Object")
837 parent = TypeManager.object_type;
840 // If we are compiling our runtime,
841 // and we are defining ValueType, then our
842 // parent is `System.Object'.
844 if (!RootContext.StdLib && Name == "System.ValueType")
845 parent = TypeManager.object_type;
852 // Bases should be null if there are no bases at all
857 string name = (string) bases [0];
858 Type first = GetInterfaceOrClass (builder, name, is_class);
869 parent = TypeManager.object_type;
876 Type [] ifaces = new Type [count-start];
878 for (i = start, j = 0; i < count; i++, j++){
879 string name = (string) bases [i];
880 Type t = GetInterfaceOrClass (builder, name, is_class);
887 if (is_class == false && !t.IsInterface){
888 Report.Error (527, "In Struct `" + Name + "', type `"+
889 name +"' is not an interface");
898 detail = " (a class can not inherit from a struct)";
900 Report.Error (509, "class `"+ Name +
901 "': Cannot inherit from sealed class `"+
902 bases [i]+"'"+detail);
909 Report.Error (527, "In Class `" + Name + "', type `"+
910 name+"' is not an interface");
923 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
925 public TypeBuilder DefineType (object parent_builder)
932 if (TypeBuilder != null)
945 ifaces = GetClassBases (parent_builder, is_class, out parent, out error);
951 if (parent == TypeManager.enum_type ||
952 (parent == TypeManager.value_type && RootContext.StdLib) ||
953 parent == TypeManager.delegate_type ||
954 parent == TypeManager.array_type){
956 644, Location, "`" + Name + "' cannot inherit from " +
957 "special class `" + TypeManager.CSharpName (parent) + "'");
962 if (parent_builder is ModuleBuilder) {
963 ModuleBuilder builder = (ModuleBuilder) parent_builder;
965 // Structs with no fields need to have a ".size 1"
969 if (!is_class && Fields == null)
970 TypeBuilder = builder.DefineType (Name,
973 PackingSize.Unspecified, 1);
976 // classes or structs with fields
978 TypeBuilder = builder.DefineType (Name,
983 TypeBuilder builder = (System.Reflection.Emit.TypeBuilder) parent_builder;
986 // Structs with no fields need to have a ".size 1"
989 if (!is_class && Fields == null)
990 TypeBuilder = builder.DefineNestedType (Basename,
993 PackingSize.Unspecified);
996 // classes or structs with fields
998 TypeBuilder = builder.DefineNestedType (Basename,
1004 RootContext.TypeManager.AddUserType (Name, TypeBuilder, this);
1005 RootContext.RegisterOrder (this);
1007 if (Types != null) {
1008 foreach (TypeContainer tc in Types)
1009 tc.DefineType (TypeBuilder);
1012 if (Delegates != null) {
1013 foreach (Delegate d in Delegates)
1014 d.DefineDelegate (TypeBuilder);
1017 if (Enums != null) {
1018 foreach (Enum en in Enums)
1019 en.DefineEnum (TypeBuilder);
1028 /// Defines the MemberCore objects that are in the `list' Arraylist
1030 /// The `defined_names' array contains a list of members defined in
1033 static ArrayList remove_list = new ArrayList ();
1034 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
1038 remove_list.Clear ();
1040 foreach (MemberCore mc in list){
1041 if (!mc.Define (this)){
1042 remove_list.Add (mc);
1046 if (defined_names == null)
1049 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
1052 if (RootContext.WarningLevel >= 4){
1053 if ((mc.ModFlags & Modifiers.NEW) != 0)
1054 Report109 (mc.Location, mc);
1059 if (defined_names [idx] is PropertyInfo &&
1060 ((mc.ModFlags & Modifiers.OVERRIDE) != 0)){
1064 #if WANT_TO_VERIFY_SIGNATURES_HERE
1065 if (defined_names [idx] is MethodBase && mc is MethodCore){
1066 MethodBase mb = (MethodBase) defined_names [idx];
1067 MethodCore met = (MethodCore) mc;
1069 if ((mb.IsVirtual || mb.IsAbstract) &&
1070 (mc.ModFlags & Modifiers.OVERRIDE) != 0)
1074 // FIXME: Compare the signatures here. If they differ,
1075 // then: `continue;'
1078 Report108 (mc.Location, defined_names [idx]);
1081 foreach (object o in remove_list)
1084 remove_list.Clear ();
1088 /// Populates our TypeBuilder with fields and methods
1090 public override bool Define (TypeContainer parent)
1092 MemberInfo [] defined_names = null;
1094 if (RootContext.WarningLevel > 1){
1098 // This code throws an exception in the comparer
1099 // I guess the string is not an object?
1101 ptype = TypeBuilder.BaseType;
1103 defined_names = FindMembers (
1104 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1105 BindingFlags.Public | BindingFlags.Instance |
1106 BindingFlags.Static, null, null);
1108 Array.Sort (defined_names, mif_compare);
1112 if (constants != null)
1113 DefineMembers (constants, defined_names);
1116 DefineMembers (fields, defined_names);
1119 if (instance_constructors == null){
1120 if (default_constructor == null)
1121 DefineDefaultConstructor (false);
1124 if (initialized_static_fields != null &&
1125 default_static_constructor == null)
1126 DefineDefaultConstructor (true);
1129 if (this is Struct){
1131 // Structs can not have initialized instance
1134 if (initialized_static_fields != null &&
1135 default_static_constructor == null)
1136 DefineDefaultConstructor (true);
1138 if (initialized_fields != null)
1139 ReportStructInitializedInstanceError ();
1142 RegisterRequiredImplementations ();
1145 // Constructors are not in the defined_names array
1147 if (instance_constructors != null)
1148 DefineMembers (instance_constructors, null);
1150 if (default_static_constructor != null)
1151 default_static_constructor.Define (this);
1153 if (methods != null)
1154 DefineMembers (methods, null);
1156 if (properties != null)
1157 DefineMembers (properties, defined_names);
1160 DefineMembers (events, defined_names);
1162 if (indexers != null) {
1163 foreach (Indexer i in Indexers)
1167 if (operators != null)
1168 DefineMembers (operators, null);
1171 DefineMembers (enums, defined_names);
1173 if (delegates != null)
1174 DefineMembers (delegates, defined_names);
1180 /// Looks up the alias for the name
1182 public string LookupAlias (string name)
1184 if (Namespace != null)
1185 return Namespace.LookupAlias (name);
1191 /// This function is based by a delegate to the FindMembers routine
1193 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1199 /// This filter is used by FindMembers, and we just keep
1200 /// a global for the filter to `AlwaysAccept'
1202 static MemberFilter accepting_filter;
1204 static bool IsVirtualFilter (MemberInfo m, object filterCriteria)
1206 if (!(m is MethodInfo))
1209 return ((MethodInfo) m).IsVirtual;
1213 /// This filter is used by FindMembers, and it is used to
1214 /// extract only virtual/abstract fields
1216 static MemberFilter virtual_method_filter;
1219 /// A member comparission method based on name only
1221 static IComparer mif_compare;
1223 static TypeContainer ()
1225 accepting_filter = new MemberFilter (AlwaysAccept);
1226 virtual_method_filter = new MemberFilter (IsVirtualFilter);
1227 mif_compare = new MemberInfoCompare ();
1231 /// This method returns the members of this type just like Type.FindMembers would
1232 /// Only, we need to use this for types which are _being_ defined because MS'
1233 /// implementation can't take care of that.
1236 // FIXME: return an empty static array instead of null, that cleans up
1237 // some code and is consistent with some coding conventions I just found
1239 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
1240 MemberFilter filter, object criteria)
1242 ArrayList members = new ArrayList ();
1245 filter = accepting_filter;
1247 if ((mt & MemberTypes.Field) != 0) {
1248 if (fields != null) {
1249 foreach (Field f in fields) {
1250 FieldBuilder fb = f.FieldBuilder;
1251 if (filter (fb, criteria) == true)
1256 if (constants != null) {
1257 foreach (Const con in constants) {
1258 FieldBuilder fb = con.FieldBuilder;
1259 if (filter (fb, criteria) == true)
1265 if ((mt & MemberTypes.Method) != 0) {
1266 if (methods != null) {
1267 foreach (Method m in methods) {
1268 MethodBuilder mb = m.MethodBuilder;
1270 // If we are in transit, ignore
1271 // This case arises when we are still defining a PInvoke method
1272 // and we hit FindMembers because of the need to resolve named
1273 // arguments inside of Attribute.DefinePInvokeMethod
1277 if (filter (mb, criteria) == true)
1282 if (operators != null){
1283 foreach (Operator o in operators) {
1284 MethodBuilder ob = o.OperatorMethodBuilder;
1286 if (filter (ob, criteria) == true)
1292 if ((mt & MemberTypes.Event) != 0) {
1294 foreach (Event e in events) {
1295 if (filter (e.EventBuilder, criteria) == true)
1296 members.Add (e.EventBuilder);
1300 if ((mt & MemberTypes.Property) != 0){
1301 if (properties != null)
1302 foreach (Property p in properties) {
1303 if (filter (p.PropertyBuilder, criteria) == true) {
1304 members.Add (p.PropertyBuilder);
1308 if (indexers != null)
1309 foreach (Indexer ix in indexers) {
1310 if (filter (ix.PropertyBuilder, criteria) == true) {
1311 members.Add (ix.PropertyBuilder);
1316 if ((mt & MemberTypes.NestedType) != 0) {
1319 foreach (TypeContainer t in Types)
1320 if (filter (t.TypeBuilder, criteria) == true)
1321 members.Add (t.TypeBuilder);
1324 foreach (Enum en in Enums)
1325 if (filter (en.TypeBuilder, criteria) == true)
1326 members.Add (en.TypeBuilder);
1330 if ((mt & MemberTypes.Constructor) != 0){
1331 if (instance_constructors != null){
1332 foreach (Constructor c in instance_constructors){
1333 ConstructorBuilder cb = c.ConstructorBuilder;
1335 if (filter (cb, criteria) == true)
1340 if (default_static_constructor != null){
1341 ConstructorBuilder cb =
1342 default_static_constructor.ConstructorBuilder;
1344 if (filter (cb, criteria) == true)
1350 // Lookup members in parent if requested.
1352 if ((bf & BindingFlags.DeclaredOnly) == 0){
1355 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1357 members.AddRange (mi);
1360 int count = members.Count;
1362 MemberInfo [] mi = new MemberInfo [count];
1363 members.CopyTo (mi);
1370 public MemberInfo GetFieldFromEvent (EventExpr event_expr)
1372 EventInfo ei = event_expr.EventInfo;
1374 foreach (Event e in events) {
1376 if (e.FieldBuilder == null)
1379 if (Type.FilterName (e.FieldBuilder, ei.Name))
1380 return e.FieldBuilder;
1386 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1387 MemberFilter filter, object criteria)
1389 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1392 return tc.FindMembers (mt, bf, filter, criteria);
1394 return t.FindMembers (mt, bf, filter, criteria);
1398 /// Whether the specified method is an interface method implementation
1402 /// If a method in Type `t' (or null to look in all interfaces
1403 /// and the base abstract class) with name `Name', return type `ret_type' and
1404 /// arguments `args' implements an interface, this method will
1405 /// return the MethodInfo that this method implements.
1407 /// This will remove the method from the list of "pending" methods
1408 /// that are required to be implemented for this class as a side effect.
1411 public MethodInfo IsInterfaceMethod (Type t, string Name, Type ret_type, Type [] args,
1414 if (pending_implementations == null)
1417 foreach (TypeAndMethods tm in pending_implementations){
1418 if (!(t == null || tm.type == t))
1422 foreach (MethodInfo m in tm.methods){
1428 if (Name != m.Name){
1433 if (ret_type != m.ReturnType){
1439 if (tm.args [i] == null || tm.args [i].Length == 0){
1441 tm.methods [i] = null;
1442 tm.found [i] = true;
1449 if (tm.args == null){
1450 Console.WriteLine ("Type: " + tm.type);
1451 Console.WriteLine ("method: " + tm.methods [i]);
1454 if (tm.args [i] == null){
1460 // Check if we have the same parameters
1462 if (tm.args [i].Length != args.Length){
1467 int j, top = args.Length;
1470 for (j = 0; j < top; j++){
1471 if (tm.args [i][j] != args[j]){
1482 tm.methods [i] = null;
1483 tm.found [i] = true;
1487 // If a specific type was requested, we can stop now.
1495 /// Verifies that any pending abstract methods or interface methods
1496 /// were implemented.
1498 bool VerifyPendingMethods ()
1500 int top = pending_implementations.Length;
1501 bool errors = false;
1504 for (i = 0; i < top; i++){
1505 Type type = pending_implementations [i].type;
1508 foreach (MethodInfo mi in pending_implementations [i].methods){
1512 if (type.IsInterface){
1515 if (pending_implementations [i].found [j])
1516 extra = ". (method might be private or static)";
1519 "`" + Name + "' does not implement " +
1520 "interface member `" +
1521 type.FullName + "." + mi.Name + "'" + extra);
1525 "`" + Name + "' does not implement " +
1526 "inherited abstract member `" +
1527 type.FullName + "." + mi.Name + "'");
1537 /// Emits the values for the constants
1539 public void EmitConstants ()
1541 if (constants != null)
1542 foreach (Const con in constants)
1543 con.EmitConstant (this);
1548 /// Emits the code, this step is performed after all
1549 /// the types, enumerations, constructors
1553 if (instance_constructors != null)
1554 foreach (Constructor c in instance_constructors)
1557 if (default_static_constructor != null)
1558 default_static_constructor.Emit (this);
1560 if (methods != null)
1561 foreach (Method m in methods)
1564 if (operators != null)
1565 foreach (Operator o in operators)
1568 if (properties != null)
1569 foreach (Property p in properties)
1572 if (indexers != null) {
1573 foreach (Indexer ix in indexers)
1576 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (this, ModFlags, Location);
1578 TypeBuilder.SetCustomAttribute (cb);
1582 foreach (Field f in fields)
1585 if (events != null){
1586 foreach (Event e in Events)
1590 if (pending_implementations != null)
1591 if (!VerifyPendingMethods ())
1594 EmitContext ec = new EmitContext (
1595 this, Mono.CSharp.Location.Null, null, null,
1598 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1601 // Check for internal or private fields that were never assigned
1603 if (RootContext.WarningLevel >= 3){
1604 foreach (Field f in fields){
1605 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1610 169, f.Location, "Private field " +
1611 MakeName (f.Name) + " is never used");
1616 // Only report 649 on level 4
1618 if (RootContext.WarningLevel < 4)
1621 if ((f.status & Field.Status.ASSIGNED) != 0)
1626 "Field " + MakeName (f.Name) + " is never assigned " +
1627 " to and will always have its default value");
1631 // if (types != null)
1632 // foreach (TypeContainer tc in types)
1636 public override void CloseType ()
1641 TypeBuilder.CreateType ();
1643 } catch (TypeLoadException){
1645 // This is fine, the code still created the type
1647 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1648 // Console.WriteLine (e.Message);
1652 foreach (Enum en in Enums)
1656 foreach (TypeContainer tc in Types)
1660 foreach (TypeContainer tc in Types)
1661 if (!(tc is Struct))
1665 if (Delegates != null)
1666 foreach (Delegate d in Delegates)
1670 public string MakeName (string n)
1672 return "`" + Name + "." + n + "'";
1675 public void Report108 (Location l, MemberInfo mi)
1678 108, l, "The keyword new is required on " +
1679 MakeName (mi.Name) + " because it hides `" +
1680 mi.ReflectedType.Name + "." + mi.Name + "'");
1683 public void Report109 (Location l, MemberCore mc)
1686 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1687 "inherited member, the keyword new is not required");
1690 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1696 // Performs the validation on a Method's modifiers (properties have
1697 // the same properties).
1699 public bool MethodModifiersValid (int flags, string n, Location loc)
1701 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1702 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1704 string name = MakeName (n);
1707 // At most one of static, virtual or override
1709 if ((flags & Modifiers.STATIC) != 0){
1710 if ((flags & vao) != 0){
1712 112, loc, "static method " + name + "can not be marked " +
1713 "as virtual, abstract or override");
1718 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1721 " marked as override cannot be marked as new or virtual");
1726 // If the declaration includes the abstract modifier, then the
1727 // declaration does not include static, virtual or extern
1729 if ((flags & Modifiers.ABSTRACT) != 0){
1730 if ((flags & Modifiers.EXTERN) != 0){
1732 180, loc, name + " can not be both abstract and extern");
1736 if ((flags & Modifiers.VIRTUAL) != 0){
1738 503, loc, name + " can not be both abstract and virtual");
1742 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1745 " is abstract but its container class is not");
1751 if ((flags & Modifiers.PRIVATE) != 0){
1752 if ((flags & vao) != 0){
1755 " virtual or abstract members can not be private");
1760 if ((flags & Modifiers.SEALED) != 0){
1761 if ((flags & Modifiers.OVERRIDE) == 0){
1764 " cannot be sealed because it is not an override");
1773 // Returns true if `type' is as accessible as the flags `flags'
1774 // given for this member
1776 static public bool AsAccessible (Type type, int flags)
1781 Hashtable builder_and_args;
1783 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1785 if (builder_and_args == null)
1786 builder_and_args = new Hashtable ();
1791 public class Class : TypeContainer {
1793 // Modifiers allowed in a class declaration
1795 public const int AllowedModifiers =
1798 Modifiers.PROTECTED |
1799 Modifiers.INTERNAL |
1801 Modifiers.ABSTRACT |
1805 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1806 : base (parent, name, l)
1810 if (parent.Parent == null)
1811 accmods = Modifiers.INTERNAL;
1813 accmods = Modifiers.PRIVATE;
1815 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1816 this.attributes = attrs;
1820 // FIXME: How do we deal with the user specifying a different
1823 public override TypeAttributes TypeAttr {
1825 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1830 public class Struct : TypeContainer {
1832 // Modifiers allowed in a struct declaration
1834 public const int AllowedModifiers =
1837 Modifiers.PROTECTED |
1838 Modifiers.INTERNAL |
1842 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1843 : base (parent, name, l)
1847 if (parent.Parent == null)
1848 accmods = Modifiers.INTERNAL;
1850 accmods = Modifiers.PRIVATE;
1852 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1854 this.ModFlags |= Modifiers.SEALED;
1855 this.attributes = attrs;
1860 // FIXME: Allow the user to specify a different set of attributes
1861 // in some cases (Sealed for example is mandatory for a class,
1862 // but what SequentialLayout can be changed
1864 public override TypeAttributes TypeAttr {
1866 return base.TypeAttr |
1867 TypeAttributes.SequentialLayout |
1868 TypeAttributes.Sealed |
1869 TypeAttributes.BeforeFieldInit;
1874 public abstract class MethodCore : MemberCore {
1875 public readonly Parameters Parameters;
1879 // Parameters, cached for semantic analysis.
1881 InternalParameters parameter_info;
1883 public MethodCore (string name, Parameters parameters, Location l)
1887 Parameters = parameters;
1891 // Returns the System.Type array for the parameters of this method
1893 Type [] parameter_types;
1894 static Type [] no_types = new Type [0];
1895 public Type [] ParameterTypes (TypeContainer parent)
1897 if (Parameters == null)
1900 if (parameter_types == null)
1901 parameter_types = Parameters.GetParameterInfo (parent);
1903 return parameter_types;
1906 public InternalParameters ParameterInfo
1909 return parameter_info;
1913 parameter_info = value;
1917 public Block Block {
1927 public CallingConventions GetCallingConvention (bool is_class)
1929 CallingConventions cc = 0;
1931 cc = Parameters.GetCallingConvention ();
1934 if ((ModFlags & Modifiers.STATIC) == 0)
1935 cc |= CallingConventions.HasThis;
1937 // FIXME: How is `ExplicitThis' used in C#?
1942 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
1945 // Define each type attribute (in/out/ref) and
1946 // the argument names.
1948 Parameter [] p = Parameters.FixedParameters;
1952 MethodBuilder mb = null;
1953 ConstructorBuilder cb = null;
1955 if (builder is MethodBuilder)
1956 mb = (MethodBuilder) builder;
1958 cb = (ConstructorBuilder) builder;
1962 for (i = 0; i < p.Length; i++) {
1963 ParameterBuilder pb;
1966 pb = cb.DefineParameter (
1967 i + 1, p [i].Attributes, p [i].Name);
1969 pb = mb.DefineParameter (
1970 i + 1, p [i].Attributes, p [i].Name);
1972 Attributes attr = p [i].OptAttributes;
1974 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
1977 if (i != parameters.Length) {
1978 ParameterBuilder pb;
1980 Parameter array_param = Parameters.ArrayParameter;
1982 pb = cb.DefineParameter (
1983 i + 1, array_param.Attributes,
1986 pb = mb.DefineParameter (
1987 i + 1, array_param.Attributes,
1990 CustomAttributeBuilder a = new CustomAttributeBuilder (
1991 TypeManager.cons_param_array_attribute, new object [0]);
1993 pb.SetCustomAttribute (a);
1998 public class Method : MethodCore {
1999 public readonly string ReturnType;
2000 public MethodBuilder MethodBuilder;
2001 public readonly Attributes OptAttributes;
2003 MethodAttributes flags;
2006 /// Modifiers allowed in a class declaration
2008 const int AllowedModifiers =
2011 Modifiers.PROTECTED |
2012 Modifiers.INTERNAL |
2017 Modifiers.OVERRIDE |
2018 Modifiers.ABSTRACT |
2023 // return_type can be "null" for VOID values.
2025 public Method (string return_type, int mod, string name, Parameters parameters,
2026 Attributes attrs, Location l)
2027 : base (name, parameters, l)
2029 ReturnType = return_type;
2030 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l);
2031 OptAttributes = attrs;
2034 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
2038 if (! (m is MethodInfo))
2041 MethodSignature sig = (MethodSignature) filter_criteria;
2043 if (m.Name != sig.Name)
2046 mi = (MethodInfo) m;
2048 if (mi.ReturnType != sig.RetType)
2051 Type [] args = TypeManager.GetArgumentTypes (mi);
2052 Type [] sigp = sig.Parameters;
2054 if (args.Length != sigp.Length)
2057 for (int i = args.Length; i > 0; ){
2059 if (args [i] != sigp [i])
2066 /// This delegate is used to extract methods which have the
2067 /// same signature as the argument
2069 static MemberFilter method_signature_filter;
2073 method_signature_filter = new MemberFilter (MemberSignatureCompare);
2078 // Returns the `System.Type' for the ReturnType of this
2079 // function. Provides a nice cache. (used between semantic analysis
2080 // and actual code generation
2082 Type type_return_type;
2084 public Type GetReturnType (TypeContainer parent)
2086 if (type_return_type == null)
2087 type_return_type = RootContext.LookupType (
2088 parent, ReturnType, false, Location);
2090 return type_return_type;
2093 void DuplicatEntryPoint (MethodInfo b)
2097 "Program `" + RootContext.CodeGen.FileName +
2098 "' has more than one entry point defined: `" +
2099 b.DeclaringType.Name + "." + b.Name + "'");
2105 public override bool Define (TypeContainer parent)
2107 Type ret_type = GetReturnType (parent);
2108 Type [] parameters = ParameterTypes (parent);
2110 MethodInfo implementing;
2111 Type iface_type = null;
2112 string iface = "", short_name;
2113 bool explicit_impl = false;
2115 // Check if the return type and arguments were correct
2116 if (ret_type == null || parameters == null)
2119 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
2122 flags = Modifiers.MethodAttr (ModFlags);
2124 // verify accessibility
2126 if (!TypeContainer.AsAccessible (ret_type, ModFlags))
2129 if (ret_type.IsPointer && !UnsafeOK (parent))
2132 foreach (Type partype in parameters){
2133 if (!TypeContainer.AsAccessible (partype, ModFlags))
2135 if (partype.IsPointer && !UnsafeOK (parent))
2143 // Verify if the parent has a type with the same name, and then
2144 // check whether we have to create a new slot for it or not.
2146 Type ptype = parent.TypeBuilder.BaseType;
2148 // ptype is only null for System.Object while compiling corlib.
2150 MethodSignature ms = new MethodSignature (Name, ret_type, parameters);
2151 MemberInfo [] mi, mi_static, mi_instance;
2153 mi_static = TypeContainer.FindMembers (
2154 ptype, MemberTypes.Method,
2155 BindingFlags.Public | BindingFlags.Static, method_signature_filter,
2158 mi_instance = TypeContainer.FindMembers (
2159 ptype, MemberTypes.Method,
2160 BindingFlags.Public | BindingFlags.Instance, method_signature_filter,
2163 if (mi_instance != null && mi_instance.Length > 0){
2165 } else if (mi_static != null && mi_static.Length > 0)
2170 if (mi != null && mi.Length > 0){
2171 if (!CheckMethodAgainstBase (parent, (MethodInfo) mi [0])){
2175 if ((ModFlags & Modifiers.NEW) != 0)
2176 WarningNotHiding (parent);
2178 if ((ModFlags & Modifiers.OVERRIDE) != 0)
2179 Report.Error (115, Location,
2180 parent.MakeName (Name) +
2181 " no suitable methods found to override");
2183 } else if ((ModFlags & Modifiers.NEW) != 0)
2184 WarningNotHiding (parent);
2187 // If we implement an interface, extract the interface name.
2190 if (Name.IndexOf (".") != -1){
2191 int pos = Name.LastIndexOf (".");
2192 iface = Name.Substring (0, pos);
2194 iface_type = RootContext.LookupType (parent, iface, false, Location);
2195 short_name = Name.Substring (pos + 1);
2197 if (iface_type == null)
2200 // Compute the full name that we need to export
2201 Name = iface_type.FullName + "." + short_name;
2202 explicit_impl = true;
2207 // Check if we are an implementation of an interface method or
2210 implementing = parent.IsInterfaceMethod (
2211 iface_type, short_name, ret_type, parameters, false);
2214 // For implicit implementations, make sure we are public, for
2215 // explicit implementations, make sure we are private.
2217 if (implementing != null){
2219 // Setting null inside this block will trigger a more
2220 // verbose error reporting for missing interface implementations
2222 // The "candidate" function has been flagged already
2223 // but it wont get cleared
2225 if (iface_type == null){
2226 if ((ModFlags & Modifiers.PUBLIC) == 0)
2227 implementing = null;
2229 if ((ModFlags & Modifiers.STATIC) != 0)
2230 implementing = null;
2232 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2234 106, Location, "`public' or `abstract' modifiers "+
2235 "are not allowed in explicit interface declarations"
2237 implementing = null;
2243 // If implementing is still valid, set flags
2245 if (implementing != null){
2247 MethodAttributes.Virtual |
2248 MethodAttributes.HideBySig;
2250 // If not abstract, then we can set Final.
2251 if (((flags & MethodAttributes.Abstract) == 0) &&
2252 implementing.DeclaringType.IsInterface)
2253 flags |= MethodAttributes.Final;
2258 parent.IsInterfaceMethod (
2259 iface_type, short_name, ret_type, parameters, true);
2262 Attribute dllimport_attr = null;
2263 if (OptAttributes != null && OptAttributes.AttributeSections != null) {
2264 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2265 if (asec.Attributes == null)
2268 foreach (Attribute a in asec.Attributes)
2269 if (a.Name.IndexOf ("DllImport") != -1) {
2270 flags |= MethodAttributes.PinvokeImpl;
2277 // Finally, define the method
2280 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2281 EmitContext ec = new EmitContext (
2282 parent, Location, null, GetReturnType (parent), ModFlags);
2284 MethodBuilder = dllimport_attr.DefinePInvokeMethod (
2285 ec, parent.TypeBuilder,
2286 Name, flags, ret_type, parameters);
2289 MethodBuilder = parent.TypeBuilder.DefineMethod (
2291 GetCallingConvention (parent is Class),
2292 ret_type, parameters);
2294 if (implementing != null && explicit_impl)
2295 parent.TypeBuilder.DefineMethodOverride (
2296 MethodBuilder, implementing);
2299 if (MethodBuilder == null)
2303 // HACK because System.Reflection.Emit is lame
2305 ParameterInfo = new InternalParameters (parent, Parameters);
2307 if (!TypeManager.RegisterMethod (MethodBuilder, ParameterInfo,
2311 "Class `" + parent.Name + "' already contains a definition with " +
2312 " the same return value and parameter types for method `" +
2318 // This is used to track the Entry Point,
2320 // FIXME: Allow pluggable entry point, check arguments, etc.
2322 if (Name == "Main" &&
2323 ((ModFlags & Modifiers.STATIC) != 0) &&
2324 (RootContext.MainClass == null ||
2325 RootContext.MainClass == parent.TypeBuilder.FullName)){
2326 if (RootContext.EntryPoint != null){
2327 DuplicatEntryPoint (MethodBuilder);
2328 DuplicatEntryPoint (RootContext.EntryPoint);
2330 RootContext.EntryPoint = MethodBuilder;
2333 // FIXME: Verify that the method signature
2334 // is valid for an entry point, and report
2345 public void Emit (TypeContainer parent)
2347 if ((flags & MethodAttributes.PinvokeImpl) != 0)
2350 ILGenerator ig = MethodBuilder.GetILGenerator ();
2351 EmitContext ec = new EmitContext (parent, Location, ig,
2352 GetReturnType (parent), ModFlags);
2354 if (OptAttributes != null)
2355 Attribute.ApplyAttributes (ec, MethodBuilder, this, OptAttributes, Location);
2358 LabelParameters (ec, ParameterTypes (parent), MethodBuilder);
2361 // abstract or extern methods have no bodies
2363 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
2367 // Handle destructors specially
2369 // FIXME: This code generates buggy code
2371 if (Name == "Finalize" && type_return_type == TypeManager.void_type)
2372 EmitDestructor (ec);
2374 ec.EmitTopBlock (Block, Location);
2377 void EmitDestructor (EmitContext ec)
2379 ILGenerator ig = ec.ig;
2381 Label finish = ig.DefineLabel ();
2382 bool old_in_try = ec.InTry;
2383 Expression member_lookup;
2385 ig.BeginExceptionBlock ();
2387 ec.ReturnLabel = finish;
2388 ec.EmitTopBlock (Block, Location);
2389 ec.InTry = old_in_try;
2391 ig.MarkLabel (finish);
2392 bool old_in_finally = ec.InFinally;
2393 ec.InFinally = true;
2394 ig.BeginFinallyBlock ();
2396 member_lookup = Expression.MemberLookup (
2397 ec, ec.TypeContainer.TypeBuilder.BaseType, "Finalize",
2398 MemberTypes.Method, Expression.AllBindingFlags, Location);
2400 if (member_lookup != null){
2401 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
2403 ig.Emit (OpCodes.Ldarg_0);
2404 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
2406 ec.InFinally = old_in_finally;
2408 ig.EndExceptionBlock ();
2409 //ig.MarkLabel (ec.ReturnLabel);
2410 ig.Emit (OpCodes.Ret);
2414 public abstract class ConstructorInitializer {
2415 ArrayList argument_list;
2416 ConstructorInfo parent_constructor;
2419 public ConstructorInitializer (ArrayList argument_list, Location location)
2421 this.argument_list = argument_list;
2422 this.location = location;
2425 public ArrayList Arguments {
2427 return argument_list;
2431 public bool Resolve (EmitContext ec)
2433 Expression parent_constructor_group;
2436 if (argument_list != null){
2437 for (int i = argument_list.Count; i > 0; ){
2440 Argument a = (Argument) argument_list [i];
2441 if (!a.Resolve (ec, location))
2446 if (this is ConstructorBaseInitializer)
2447 t = ec.TypeContainer.TypeBuilder.BaseType;
2449 t = ec.TypeContainer.TypeBuilder;
2451 parent_constructor_group = Expression.MemberLookup (
2453 MemberTypes.Constructor,
2454 BindingFlags.Public | BindingFlags.Instance, location);
2456 if (parent_constructor_group == null){
2457 Console.WriteLine ("Could not find a constructor in our parent");
2461 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2462 (MethodGroupExpr) parent_constructor_group, argument_list, location);
2464 if (parent_constructor == null){
2465 Console.WriteLine ("Could not locate a proper overload function");
2472 public void Emit (EmitContext ec)
2474 ec.ig.Emit (OpCodes.Ldarg_0);
2475 if (argument_list != null)
2476 Invocation.EmitArguments (ec, null, argument_list);
2477 ec.ig.Emit (OpCodes.Call, parent_constructor);
2481 public class ConstructorBaseInitializer : ConstructorInitializer {
2482 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2487 public class ConstructorThisInitializer : ConstructorInitializer {
2488 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2493 public class Constructor : MethodCore {
2494 public ConstructorBuilder ConstructorBuilder;
2495 public ConstructorInitializer Initializer;
2496 public Attributes OptAttributes;
2499 // Modifiers allowed for a constructor.
2501 const int AllowedModifiers =
2503 Modifiers.PROTECTED |
2504 Modifiers.INTERNAL |
2510 // The spec claims that static is not permitted, but
2511 // my very own code has static constructors.
2513 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2514 : base (name, args, l)
2520 // Returns true if this is a default constructor
2522 public bool IsDefault ()
2524 if ((ModFlags & Modifiers.STATIC) != 0)
2525 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2526 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2529 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2530 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2531 (Initializer is ConstructorBaseInitializer) &&
2532 (Initializer.Arguments == null);
2536 // Creates the ConstructorBuilder
2538 public override bool Define (TypeContainer parent)
2540 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2541 MethodAttributes.SpecialName);
2543 Type [] parameters = ParameterTypes (parent);
2545 if ((ModFlags & Modifiers.STATIC) != 0)
2546 ca |= MethodAttributes.Static;
2548 if (parent is Struct && parameters.Length == 0){
2551 "Structs can not contain explicit parameterless " +
2555 ca |= MethodAttributes.Public | MethodAttributes.HideBySig;
2558 foreach (Type partype in parameters)
2559 if (!TypeContainer.AsAccessible (partype, ModFlags))
2562 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2563 ca, GetCallingConvention (parent is Class), parameters);
2566 // HACK because System.Reflection.Emit is lame
2568 ParameterInfo = new InternalParameters (parent, Parameters);
2570 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, parameters)) {
2573 "Class `" +parent.Name+ "' already contains a definition with the " +
2574 "same return value and parameter types for constructor `" + Name
2585 public void Emit (TypeContainer parent)
2587 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2588 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2590 if (parent is Class && ((ModFlags & Modifiers.STATIC) == 0)){
2591 if (Initializer == null)
2592 Initializer = new ConstructorBaseInitializer (null, parent.Location);
2594 if (!Initializer.Resolve (ec)){
2595 Console.WriteLine ("Could not resolve initializer: " + parent.Name);
2599 LabelParameters (ec, ParameterTypes (parent), ConstructorBuilder);
2602 // Classes can have base initializers and instance field initializers.
2604 if (parent is Class){
2605 if ((ModFlags & Modifiers.STATIC) == 0){
2606 Initializer.Emit (ec);
2607 parent.EmitFieldInitializers (ec, false);
2611 if ((ModFlags & Modifiers.STATIC) != 0)
2612 parent.EmitFieldInitializers (ec, true);
2614 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2616 ec.EmitTopBlock (Block, Location);
2620 public class Field : MemberCore {
2621 public readonly string Type;
2622 public readonly Object Initializer;
2623 public readonly Attributes OptAttributes;
2624 public FieldBuilder FieldBuilder;
2625 public Status status;
2628 public enum Status : byte { ASSIGNED = 1, USED = 2 }
2632 // Modifiers allowed in a class declaration
2634 const int AllowedModifiers =
2637 Modifiers.PROTECTED |
2638 Modifiers.INTERNAL |
2641 Modifiers.VOLATILE |
2645 public Field (string type, int mod, string name, Object expr_or_array_init,
2646 Attributes attrs, Location loc)
2650 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, loc);
2651 Initializer = expr_or_array_init;
2652 OptAttributes = attrs;
2655 public override bool Define (TypeContainer parent)
2657 Type t = RootContext.LookupType (parent, Type, false, Location);
2662 if (!TypeContainer.AsAccessible (t, ModFlags))
2665 if (t.IsPointer && !UnsafeOK (parent))
2668 if (RootContext.WarningLevel > 1){
2669 Type ptype = parent.TypeBuilder.BaseType;
2671 // ptype is only null for System.Object while compiling corlib.
2675 mi = TypeContainer.FindMembers (
2676 ptype, MemberTypes.Method,
2677 BindingFlags.Public |
2678 BindingFlags.Static | BindingFlags.Instance,
2679 System.Type.FilterName, Name);
2683 if ((ModFlags & Modifiers.VOLATILE) != 0){
2685 if (TypeManager.IsEnumType (t))
2686 t = TypeManager.EnumToUnderlying (t);
2688 if (!((t == TypeManager.bool_type) ||
2689 (t == TypeManager.sbyte_type) ||
2690 (t == TypeManager.byte_type) ||
2691 (t == TypeManager.short_type) ||
2692 (t == TypeManager.ushort_type) ||
2693 (t == TypeManager.int32_type) ||
2694 (t == TypeManager.uint32_type) ||
2695 (t == TypeManager.char_type) ||
2696 (t == TypeManager.float_type))){
2698 677, Location, parent.MakeName (Name) +
2699 " A volatile field can not be of type `" +
2700 TypeManager.CSharpName (t) + "'");
2706 FieldBuilder = parent.TypeBuilder.DefineField (
2707 Name, t, Modifiers.FieldAttr (ModFlags));
2709 TypeManager.RegisterField (FieldBuilder, this);
2713 public void Emit (TypeContainer tc)
2715 EmitContext ec = new EmitContext (tc, Location, null, FieldBuilder.FieldType, ModFlags);
2717 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
2721 public class Property : MemberCore {
2722 public readonly string Type;
2723 public Block Get, Set;
2724 public PropertyBuilder PropertyBuilder;
2725 public Attributes OptAttributes;
2726 MethodBuilder GetBuilder, SetBuilder;
2729 // The type, once we compute it.
2733 const int AllowedModifiers =
2736 Modifiers.PROTECTED |
2737 Modifiers.INTERNAL |
2741 Modifiers.OVERRIDE |
2742 Modifiers.ABSTRACT |
2746 public Property (string type, string name, int mod_flags, Block get_block, Block set_block,
2747 Attributes attrs, Location loc)
2751 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
2754 OptAttributes = attrs;
2758 // Checks our base implementation if any
2760 bool CheckBase (TypeContainer parent)
2763 // Find properties with the same name on the base class
2765 MemberInfo [] props;
2766 MemberInfo [] props_static = TypeContainer.FindMembers (
2767 parent.TypeBuilder.BaseType,
2768 MemberTypes.All, BindingFlags.Public | BindingFlags.Static,
2769 System.Type.FilterName, Name);
2771 MemberInfo [] props_instance = TypeContainer.FindMembers (
2772 parent.TypeBuilder.BaseType,
2773 MemberTypes.All, BindingFlags.Public | BindingFlags.Instance,
2774 System.Type.FilterName, Name);
2777 // Find if we have anything
2779 if (props_static != null && props_static.Length > 0)
2780 props = props_static;
2781 else if (props_instance != null && props_instance.Length > 0)
2782 props = props_instance;
2787 // If we have something on the base.
2788 if (props != null && props.Length > 0){
2791 // Currently we expect only to get 1 match at most from our
2792 // base class, maybe we can get more than one, investigate
2793 // whether this is possible
2795 if (props.Length > 1)
2796 throw new Exception ("How do we handle this?");
2798 PropertyInfo pi = (PropertyInfo) props [0];
2800 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
2801 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
2803 MethodInfo reference = inherited_get == null ?
2804 inherited_set : inherited_get;
2806 if (!CheckMethodAgainstBase (parent, reference))
2809 if ((ModFlags & Modifiers.NEW) != 0)
2810 WarningNotHiding (parent);
2812 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2813 Report.Error (115, Location,
2814 parent.MakeName (Name) +
2815 " no suitable methods found to override");
2822 bool DefineMethod (TypeContainer parent, Type iface_type, string short_name, bool is_get)
2824 MethodAttributes flags = Modifiers.MethodAttr (ModFlags);
2825 Type [] parameters = null;
2826 MethodInfo implementing;
2830 flags |= MethodAttributes.HideBySig |
2831 MethodAttributes.SpecialName;
2834 fn_type = PropertyType;
2835 name = "get_" + short_name;
2837 name = "set_" + short_name;
2838 parameters = new Type [1];
2839 parameters [0] = PropertyType;
2840 fn_type = TypeManager.void_type;
2843 implementing = parent.IsInterfaceMethod (
2844 iface_type, name, fn_type, parameters, false);
2847 // For implicit implementations, make sure we are public, for
2848 // explicit implementations, make sure we are private.
2850 if (implementing != null){
2852 // Setting null inside this block will trigger a more
2853 // verbose error reporting for missing interface implementations
2855 // The "candidate" function has been flagged already
2856 // but it wont get cleared
2858 if (iface_type == null){
2859 if ((ModFlags & Modifiers.PUBLIC) == 0)
2860 implementing = null;
2861 if ((ModFlags & Modifiers.STATIC) != 0)
2862 implementing = null;
2864 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2866 106, Location, "`public' or `abstract' modifiers "+
2867 "are not allowed in explicit interface declarations"
2869 implementing = null;
2875 // If implementing is still valid, set flags
2877 if (implementing != null){
2879 MethodAttributes.Virtual |
2881 MethodAttributes.HideBySig;
2883 // If an interface implementation, then we can set Final.
2884 if (((flags & MethodAttributes.Abstract) == 0) &&
2885 implementing.DeclaringType.IsInterface)
2886 flags |= MethodAttributes.Final;
2889 // clear the pending flag
2891 parent.IsInterfaceMethod (
2892 iface_type, name, fn_type, parameters, true);
2896 // If this is not an explicit interface implementation,
2897 // clear implementing, as it is only used for explicit
2898 // interface implementation
2900 if (Name.IndexOf (".") == -1)
2901 implementing = null;
2904 GetBuilder = parent.TypeBuilder.DefineMethod (
2905 name, flags, PropertyType, null);
2906 PropertyBuilder.SetGetMethod (GetBuilder);
2908 if (implementing != null)
2909 parent.TypeBuilder.DefineMethodOverride (
2910 GetBuilder, implementing);
2913 // HACK because System.Reflection.Emit is lame
2915 InternalParameters ip = new InternalParameters (
2916 parent, Parameters.GetEmptyReadOnlyParameters ());
2918 if (!TypeManager.RegisterMethod (GetBuilder, ip, null)) {
2919 Report.Error (111, Location,
2920 "Class `" + parent.Name +
2921 "' already contains a definition with the " +
2922 "same return value and parameter types as the " +
2923 "'get' method of property `" + Name + "'");
2927 SetBuilder = parent.TypeBuilder.DefineMethod (
2928 name, flags, null, parameters);
2930 if (implementing != null)
2931 parent.TypeBuilder.DefineMethodOverride (
2932 SetBuilder, implementing);
2934 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
2935 PropertyBuilder.SetSetMethod (SetBuilder);
2938 // HACK because System.Reflection.Emit is lame
2940 Parameter [] parms = new Parameter [1];
2941 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
2942 InternalParameters ip = new InternalParameters (
2943 parent, new Parameters (parms, null, Location));
2945 if (!TypeManager.RegisterMethod (SetBuilder, ip, parameters)) {
2948 "Class `" + parent.Name +
2949 "' already contains a definition with the " +
2950 "same return value and parameter types as the " +
2951 "'set' method of property `" + Name + "'");
2959 public override bool Define (TypeContainer parent)
2961 Type iface_type = null;
2964 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
2967 // Lookup Type, verify validity
2968 PropertyType = RootContext.LookupType (parent, Type, false, Location);
2969 if (PropertyType == null)
2972 // verify accessibility
2973 if (!TypeContainer.AsAccessible (PropertyType, ModFlags))
2976 if (PropertyType.IsPointer && !UnsafeOK (parent))
2979 if (!CheckBase (parent))
2983 // Check for explicit interface implementation
2985 if (Name.IndexOf (".") != -1){
2986 int pos = Name.LastIndexOf (".");
2987 string iface = Name.Substring (0, pos);
2989 iface_type = RootContext.LookupType (parent, iface, false, Location);
2990 if (iface_type == null)
2993 short_name = Name.Substring (pos + 1);
2995 // Compute the full name that we need to export.
2996 Name = iface_type.FullName + "." + short_name;
3000 // FIXME - PropertyAttributes.HasDefault ?
3002 PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
3003 PropertyAttributes.SpecialName;
3005 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3006 Name, prop_attr, PropertyType, null);
3009 if (!DefineMethod (parent, iface_type, short_name, true))
3013 if (!DefineMethod (parent, iface_type, short_name, false))
3017 // HACK for the reasons exposed above
3019 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3022 "Class `" + parent.Name +
3023 "' already contains a definition for the property `" +
3031 public void Emit (TypeContainer tc)
3036 ec = new EmitContext (tc, Location, null, PropertyType, ModFlags);
3037 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3041 // abstract or extern properties have no bodies
3043 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3047 ig = GetBuilder.GetILGenerator ();
3048 ec = new EmitContext (tc, Location, ig, PropertyType, ModFlags);
3050 ec.EmitTopBlock (Get, Location);
3054 ig = SetBuilder.GetILGenerator ();
3055 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3057 ec.EmitTopBlock (Set, Location);
3064 /// Gigantic workaround for lameness in SRE follows :
3065 /// This class derived from EventInfo and attempts to basically
3066 /// wrap around the EventBuilder so that FindMembers can quickly
3067 /// return this in it search for members
3069 public class MyEventBuilder : EventInfo {
3072 // We use this to "point" to our Builder which is
3073 // not really a MemberInfo
3075 EventBuilder MyBuilder;
3078 // We "catch" and wrap these methods
3080 MethodInfo raise, remove, add;
3082 EventAttributes attributes;
3083 Type declaring_type, reflected_type, event_type;
3086 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3088 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3090 // And now store the values in our own fields.
3092 declaring_type = type_builder;
3094 // FIXME : This is supposed to be MyBuilder but since that doesn't
3095 // derive from Type, I have no clue what to do with this.
3096 reflected_type = null;
3098 attributes = event_attr;
3100 this.event_type = event_type;
3104 // Methods that you have to override. Note that you only need
3105 // to "implement" the variants that take the argument (those are
3106 // the "abstract" methods, the others (GetAddMethod()) are
3109 public override MethodInfo GetAddMethod (bool nonPublic)
3114 public override MethodInfo GetRemoveMethod (bool nonPublic)
3119 public override MethodInfo GetRaiseMethod (bool nonPublic)
3125 // These methods make "MyEventInfo" look like a Builder
3127 public void SetRaiseMethod (MethodBuilder raiseMethod)
3129 raise = raiseMethod;
3130 MyBuilder.SetRaiseMethod (raiseMethod);
3133 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3135 remove = removeMethod;
3136 MyBuilder.SetRemoveOnMethod (removeMethod);
3139 public void SetAddOnMethod (MethodBuilder addMethod)
3142 MyBuilder.SetAddOnMethod (addMethod);
3145 public void SetCustomAttribute (CustomAttributeBuilder cb)
3147 MyBuilder.SetCustomAttribute (cb);
3150 public override object [] GetCustomAttributes (bool inherit)
3152 // FIXME : There's nothing which can be seemingly done here because
3153 // we have no way of getting at the custom attribute objects of the
3158 public override object [] GetCustomAttributes (Type t, bool inherit)
3160 // FIXME : Same here !
3164 public override bool IsDefined (Type t, bool b)
3169 public override EventAttributes Attributes {
3175 public override string Name {
3181 public override Type DeclaringType {
3183 return declaring_type;
3187 public override Type ReflectedType {
3189 return reflected_type;
3193 public Type EventType {
3200 public class Event : MemberCore {
3202 const int AllowedModifiers =
3205 Modifiers.PROTECTED |
3206 Modifiers.INTERNAL |
3211 Modifiers.OVERRIDE |
3215 public readonly string Type;
3216 public readonly Object Initializer;
3217 public readonly Block Add;
3218 public readonly Block Remove;
3219 public MyEventBuilder EventBuilder;
3220 public FieldBuilder FieldBuilder;
3221 public Attributes OptAttributes;
3224 MethodBuilder AddBuilder, RemoveBuilder;
3227 public Event (string type, string name, Object init, int flags, Block add_block,
3228 Block rem_block, Attributes attrs, Location loc)
3233 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE, loc);
3236 OptAttributes = attrs;
3239 public override bool Define (TypeContainer parent)
3241 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3244 MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
3245 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3247 EventType = RootContext.LookupType (parent, Type, false, Location);
3248 if (EventType == null)
3251 if (!TypeContainer.AsAccessible (EventType, ModFlags))
3254 if (EventType.IsPointer && !UnsafeOK (parent))
3257 if (!EventType.IsSubclassOf (TypeManager.delegate_type)) {
3258 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3259 "' : event must be of a delegate type");
3263 Type [] parameters = new Type [1];
3264 parameters [0] = EventType;
3266 EventBuilder = new MyEventBuilder (parent.TypeBuilder, Name, e_attr, EventType);
3268 if (Add == null && Remove == null)
3269 FieldBuilder = parent.TypeBuilder.DefineField (Name, EventType, FieldAttributes.Private);
3272 // Now define the accessors
3275 AddBuilder = parent.TypeBuilder.DefineMethod (
3276 "add_" + Name, m_attr, null, parameters);
3277 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3278 EventBuilder.SetAddOnMethod (AddBuilder);
3281 // HACK because System.Reflection.Emit is lame
3283 Parameter [] parms = new Parameter [1];
3284 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3285 InternalParameters ip = new InternalParameters (
3286 parent, new Parameters (parms, null, Location));
3288 if (!TypeManager.RegisterMethod (AddBuilder, ip, parameters)) {
3289 Report.Error (111, Location,
3290 "Class `" + parent.Name + "' already contains a definition with the " +
3291 "same return value and parameter types for the " +
3292 "'add' method of event `" + Name + "'");
3296 RemoveBuilder = parent.TypeBuilder.DefineMethod (
3297 "remove_" + Name, m_attr, null, parameters);
3298 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3299 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3302 // HACK because System.Reflection.Emit is lame
3305 if (!TypeManager.RegisterMethod (RemoveBuilder, ip, parameters)) {
3306 Report.Error (111, Location,
3307 "Class `" + parent.Name + "' already contains a definition with the " +
3308 "same return value and parameter types for the " +
3309 "'remove' method of event `" + Name + "'");
3313 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3314 Report.Error (111, Location,
3315 "Class `" + parent.Name +
3316 "' already contains a definition for the event `" +
3324 void EmitDefaultMethod (EmitContext ec, bool is_add)
3326 ILGenerator ig = ec.ig;
3327 MethodInfo method = null;
3330 method = TypeManager.delegate_combine_delegate_delegate;
3332 method = TypeManager.delegate_remove_delegate_delegate;
3334 ig.Emit (OpCodes.Ldarg_0);
3335 ig.Emit (OpCodes.Ldarg_0);
3336 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3337 ig.Emit (OpCodes.Ldarg_1);
3338 ig.Emit (OpCodes.Call, method);
3339 ig.Emit (OpCodes.Castclass, EventType);
3340 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3341 ig.Emit (OpCodes.Ret);
3344 public void Emit (TypeContainer tc)
3349 ig = AddBuilder.GetILGenerator ();
3350 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3353 ec.EmitTopBlock (Add, Location);
3355 EmitDefaultMethod (ec, true);
3357 ig = RemoveBuilder.GetILGenerator ();
3358 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3361 ec.EmitTopBlock (Remove, Location);
3363 EmitDefaultMethod (ec, false);
3365 ec = new EmitContext (tc, Location, null, EventType, ModFlags);
3366 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3373 // FIXME: This does not handle:
3375 // int INTERFACENAME [ args ]
3379 // int this [ args ]
3381 public class Indexer : MemberCore {
3383 const int AllowedModifiers =
3386 Modifiers.PROTECTED |
3387 Modifiers.INTERNAL |
3391 Modifiers.OVERRIDE |
3395 public readonly string Type;
3396 public readonly string InterfaceType;
3397 public readonly Parameters FormalParameters;
3398 public readonly Block Get;
3399 public readonly Block Set;
3400 public Attributes OptAttributes;
3401 public MethodBuilder GetBuilder;
3402 public MethodBuilder SetBuilder;
3403 public PropertyBuilder PropertyBuilder;
3404 public Type IndexerType;
3406 public Indexer (string type, string int_type, int flags, Parameters parms,
3407 Block get_block, Block set_block, Attributes attrs, Location loc)
3412 InterfaceType = int_type;
3413 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE, loc);
3414 FormalParameters = parms;
3417 OptAttributes = attrs;
3420 void DefineMethod (TypeContainer parent, Type iface_type,
3421 Type ret_type, string name,
3422 Type [] parameters, bool is_get)
3424 MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
3425 MethodInfo implementing;
3427 implementing = parent.IsInterfaceMethod (
3428 iface_type, name, ret_type, parameters, false);
3431 // Setting null inside this block will trigger a more
3432 // verbose error reporting for missing interface implementations
3434 // The "candidate" function has been flagged already
3435 // but it wont get cleared
3437 if (implementing != null){
3438 if (iface_type == null){
3439 if ((ModFlags & Modifiers.PUBLIC) == 0)
3440 implementing = null;
3441 if ((ModFlags & Modifiers.STATIC) != 0)
3442 implementing = null;
3444 if((ModFlags&(Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
3447 "`public' or `abstract' modifiers are not "+
3448 "allowed in explicit interface declarations"
3450 implementing = null;
3454 if (implementing != null){
3456 MethodAttributes.Virtual |
3458 MethodAttributes.HideBySig;
3460 // If an interface implementing, then we can set final.
3461 if (((attr & MethodAttributes.Abstract) == 0) &&
3462 implementing.DeclaringType.IsInterface)
3463 attr |= MethodAttributes.Final;
3466 // clear the pending flag
3468 parent.IsInterfaceMethod (
3469 iface_type, name, ret_type, parameters, true);
3473 // If this is not an explicit interface implementation,
3474 // clear implementing, as it is only used for explicit
3475 // interface implementation
3477 if (Name.IndexOf (".") == -1)
3478 implementing = null;
3482 string meth_name = "get_Item";
3483 if (iface_type != null)
3484 meth_name = iface_type + ".get_Item";
3486 GetBuilder = parent.TypeBuilder.DefineMethod (
3487 meth_name, attr, IndexerType, parameters);
3489 if (implementing != null)
3490 parent.TypeBuilder.DefineMethodOverride (
3491 GetBuilder, implementing);
3494 PropertyBuilder.SetGetMethod (GetBuilder);
3497 string meth_name = "set_Item";
3499 if (iface_type != null)
3500 meth_name = iface_type + ".set_Item";
3502 SetBuilder = parent.TypeBuilder.DefineMethod (
3503 meth_name, attr, null, parameters);
3504 if (implementing != null)
3505 parent.TypeBuilder.DefineMethodOverride (
3506 SetBuilder, implementing);
3508 PropertyBuilder.SetSetMethod (SetBuilder);
3512 public override bool Define (TypeContainer parent)
3514 PropertyAttributes prop_attr =
3515 PropertyAttributes.RTSpecialName |
3516 PropertyAttributes.SpecialName;
3519 IndexerType = RootContext.LookupType (parent, Type, false, Location);
3520 Type [] parameters = FormalParameters.GetParameterInfo (parent);
3522 // Check if the return type and arguments were correct
3523 if (IndexerType == null || parameters == null)
3526 if (!parent.MethodModifiersValid (ModFlags, InterfaceType == null ?
3527 "this" : InterfaceType, Location))
3531 // verify accessibility and unsafe pointers
3533 if (!TypeContainer.AsAccessible (IndexerType, ModFlags))
3536 if (IndexerType.IsPointer && !UnsafeOK (parent))
3539 foreach (Type partype in parameters){
3540 if (!TypeContainer.AsAccessible (partype, ModFlags))
3542 if (partype.IsPointer && !UnsafeOK (parent))
3549 Type iface_type = null;
3551 if (InterfaceType != null){
3552 iface_type = RootContext.LookupType (parent, InterfaceType, false, Location);
3553 if (iface_type == null)
3558 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3559 TypeManager.IndexerPropertyName (parent.TypeBuilder),
3560 prop_attr, IndexerType, parameters);
3563 DefineMethod (parent, iface_type, IndexerType, "get_Item", parameters, true);
3564 InternalParameters pi = new InternalParameters (parent, FormalParameters);
3565 if (!TypeManager.RegisterMethod (GetBuilder, pi, parameters)) {
3566 Report.Error (111, Location,
3567 "Class `" + parent.Name +
3568 "' already contains a definition with the " +
3569 "same return value and parameter types for the " +
3576 int top = parameters.Length;
3577 Type [] set_pars = new Type [top + 1];
3578 parameters.CopyTo (set_pars, 0);
3579 set_pars [top] = IndexerType;
3581 Parameter [] fixed_parms = FormalParameters.FixedParameters;
3583 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
3585 fixed_parms.CopyTo (tmp, 0);
3586 tmp [fixed_parms.Length] = new Parameter (
3587 Type, "value", Parameter.Modifier.NONE, null);
3589 Parameters set_formal_params = new Parameters (tmp, null, Location);
3592 parent, iface_type, TypeManager.void_type,
3593 "set_Item", set_pars, false);
3595 InternalParameters ip = new InternalParameters (parent, set_formal_params);
3597 if (!TypeManager.RegisterMethod (SetBuilder, ip, set_pars)) {
3600 "Class `" + parent.Name + "' already contains a " +
3601 "definition with the " +
3602 "same return value and parameter types for the " +
3609 // Now name the parameters
3611 Parameter [] p = FormalParameters.FixedParameters;
3615 for (i = 0; i < p.Length; ++i) {
3617 GetBuilder.DefineParameter (
3618 i + 1, p [i].Attributes, p [i].Name);
3621 SetBuilder.DefineParameter (
3622 i + 1, p [i].Attributes, p [i].Name);
3626 SetBuilder.DefineParameter (
3627 i + 1, ParameterAttributes.None, "value");
3629 if (i != parameters.Length) {
3630 Parameter array_param = FormalParameters.ArrayParameter;
3631 SetBuilder.DefineParameter (i + 1, array_param.Attributes,
3636 TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
3641 public void Emit (TypeContainer tc)
3646 ec = new EmitContext (tc, Location, null, IndexerType, ModFlags);
3647 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3650 ig = GetBuilder.GetILGenerator ();
3651 ec = new EmitContext (tc, Location, ig, IndexerType, ModFlags);
3653 ec.EmitTopBlock (Get, Location);
3657 ig = SetBuilder.GetILGenerator ();
3658 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3660 ec.EmitTopBlock (Set, Location);
3665 public class Operator : MemberCore {
3667 const int AllowedModifiers =
3672 const int RequiredModifiers =
3676 public enum OpType : byte {
3686 // Unary and Binary operators
3709 // Implicit and Explicit
3714 public readonly OpType OperatorType;
3715 public readonly string ReturnType;
3716 public readonly string FirstArgType;
3717 public readonly string FirstArgName;
3718 public readonly string SecondArgType;
3719 public readonly string SecondArgName;
3720 public readonly Block Block;
3721 public Attributes OptAttributes;
3722 public MethodBuilder OperatorMethodBuilder;
3724 public string MethodName;
3725 public Method OperatorMethod;
3727 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
3728 string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
3731 OperatorType = type;
3732 ReturnType = ret_type;
3733 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
3734 FirstArgType = arg1type;
3735 FirstArgName = arg1name;
3736 SecondArgType = arg2type;
3737 SecondArgName = arg2name;
3739 OptAttributes = attrs;
3742 string Prototype (TypeContainer parent)
3744 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
3745 SecondArgType + ")";
3748 public override bool Define (TypeContainer parent)
3751 MethodName = "op_" + OperatorType;
3753 if (SecondArgType != null)
3756 Parameter [] param_list = new Parameter [length];
3758 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
3761 "User defined operators `" +
3762 Prototype (parent) +
3763 "' must be declared static and public");
3767 param_list[0] = new Parameter (FirstArgType, FirstArgName,
3768 Parameter.Modifier.NONE, null);
3769 if (SecondArgType != null)
3770 param_list[1] = new Parameter (SecondArgType, SecondArgName,
3771 Parameter.Modifier.NONE, null);
3773 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
3774 new Parameters (param_list, null, Location),
3775 OptAttributes, Mono.CSharp.Location.Null);
3777 OperatorMethod.Define (parent);
3779 if (OperatorMethod.MethodBuilder == null)
3782 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
3784 Type [] param_types = OperatorMethod.ParameterTypes (parent);
3785 Type declaring_type = OperatorMethodBuilder.DeclaringType;
3786 Type return_type = OperatorMethod.GetReturnType (parent);
3787 Type first_arg_type = param_types [0];
3789 // Rules for conversion operators
3791 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
3792 if (first_arg_type == return_type && first_arg_type == declaring_type){
3795 "User-defined conversion cannot take an object of the " +
3796 "enclosing type and convert to an object of the enclosing" +
3801 if (first_arg_type != declaring_type && return_type != declaring_type){
3804 "User-defined conversion must convert to or from the " +
3809 if (first_arg_type == TypeManager.object_type ||
3810 return_type == TypeManager.object_type){
3813 "User-defined conversion cannot convert to or from " +
3818 if (first_arg_type.IsInterface || return_type.IsInterface){
3821 "User-defined conversion cannot convert to or from an " +
3826 if (first_arg_type.IsSubclassOf (return_type) ||
3827 return_type.IsSubclassOf (first_arg_type)){
3830 "User-defined conversion cannot convert between types " +
3831 "that derive from each other");
3834 } else if (SecondArgType == null) {
3835 // Checks for Unary operators
3837 if (first_arg_type != declaring_type){
3840 "The parameter of a unary operator must be the " +
3845 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
3846 if (return_type != declaring_type){
3849 "The parameter and return type for ++ and -- " +
3850 "must be the containing type");
3856 if (OperatorType == OpType.True || OperatorType == OpType.False) {
3857 if (return_type != TypeManager.bool_type){
3860 "The return type of operator True or False " +
3867 // Checks for Binary operators
3869 if (first_arg_type != declaring_type &&
3870 param_types [1] != declaring_type){
3873 "One of the parameters of a binary operator must " +
3874 "be the containing type");
3882 public void Emit (TypeContainer parent)
3884 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
3885 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
3887 OperatorMethod.Block = Block;
3888 OperatorMethod.Emit (parent);
3893 // This is used to compare method signatures
3895 struct MethodSignature {
3897 public Type RetType;
3898 public Type [] Parameters;
3900 public MethodSignature (string name, Type ret_type, Type [] parameters)
3904 Parameters = parameters;
3907 public override int GetHashCode ()
3909 return Name.GetHashCode ();
3912 public override bool Equals (Object o)
3914 MethodSignature other = (MethodSignature) o;
3916 if (other.Name != Name)
3919 if (other.RetType != RetType)
3922 if (Parameters == null){
3923 if (other.Parameters == null)
3928 if (other.Parameters == null)
3931 int c = Parameters.Length;
3932 if (other.Parameters.Length != c)
3935 for (int i = 0; i < c; i++)
3936 if (other.Parameters [i] != Parameters [i])