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, 2002 Ximian, Inc (http://www.ximian.com)
13 using System.Collections;
14 using System.Reflection;
15 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
70 // The emit context for toplevel objects.
74 // Pointers to the default constructor and the default static constructor
76 Constructor default_constructor;
77 Constructor default_static_constructor;
80 // Whether we have seen a static constructor for this class or not
82 bool have_static_constructor = false;
85 // Whether we have at least one non-static field
87 bool have_nonstatic_fields = false;
90 // This one is computed after we can distinguish interfaces
91 // from classes from the arraylist `type_bases'
93 string base_class_name;
97 // Attributes for this type
98 protected Attributes attributes;
100 // Information in the case we are an attribute type
102 public AttributeTargets Targets = AttributeTargets.All;
103 public bool AllowMultiple = false;
104 public bool Inherited;
106 // The interfaces we implement.
110 // The indexer name for this class
112 public string IndexerName;
114 public TypeContainer (TypeContainer parent, string name, Location l)
115 : base (parent, name, l)
118 types = new ArrayList ();
125 base_class_name = null;
127 //Console.WriteLine ("New class " + name + " inside " + n);
130 public AdditionResult AddConstant (Const constant)
133 string name = constant.Name;
135 if ((res = IsValid (name)) != AdditionResult.Success)
138 if (constants == null)
139 constants = new ArrayList ();
141 constants.Add (constant);
142 DefineName (name, constant);
144 return AdditionResult.Success;
147 public AdditionResult AddEnum (Mono.CSharp.Enum e)
150 string name = e.Name;
152 if ((res = IsValid (name)) != AdditionResult.Success)
156 enums = new ArrayList ();
159 DefineName (name, e);
161 return AdditionResult.Success;
164 public AdditionResult AddClass (Class c)
167 string name = c.Name;
170 if ((res = IsValid (name)) != AdditionResult.Success)
173 DefineName (name, c);
176 return AdditionResult.Success;
179 public AdditionResult AddStruct (Struct s)
182 string name = s.Name;
184 if ((res = IsValid (name)) != AdditionResult.Success)
187 DefineName (name, s);
190 return AdditionResult.Success;
193 public AdditionResult AddDelegate (Delegate d)
196 string name = d.Name;
198 if ((res = IsValid (name)) != AdditionResult.Success)
201 if (delegates == null)
202 delegates = new ArrayList ();
204 DefineName (name, d);
207 return AdditionResult.Success;
210 public AdditionResult AddMethod (Method method)
212 string name = method.Name;
213 Object value = defined_names [name];
215 if (value != null && (!(value is Method)))
216 return AdditionResult.NameExists;
219 methods = new ArrayList ();
221 if (method.Name.IndexOf (".") != -1)
222 methods.Insert (0, method);
224 methods.Add (method);
227 DefineName (name, method);
229 return AdditionResult.Success;
232 public AdditionResult AddConstructor (Constructor c)
234 if (c.Name != Basename)
235 return AdditionResult.NotAConstructor;
237 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
240 have_static_constructor = true;
241 if (default_static_constructor != null){
242 Console.WriteLine ("I have a static constructor already");
243 Console.WriteLine (" " + default_static_constructor);
244 return AdditionResult.MethodExists;
247 default_static_constructor = c;
250 if (default_constructor != null)
251 return AdditionResult.MethodExists;
252 default_constructor = c;
255 if (instance_constructors == null)
256 instance_constructors = new ArrayList ();
258 instance_constructors.Add (c);
261 return AdditionResult.Success;
264 public AdditionResult AddInterface (Interface iface)
267 string name = iface.Name;
269 if ((res = IsValid (name)) != AdditionResult.Success)
272 if (interfaces == null)
273 interfaces = new ArrayList ();
274 interfaces.Add (iface);
275 DefineName (name, iface);
277 return AdditionResult.Success;
280 public AdditionResult AddField (Field field)
283 string name = field.Name;
285 if ((res = IsValid (name)) != AdditionResult.Success)
289 fields = new ArrayList ();
293 if (field.Initializer != null){
294 if ((field.ModFlags & Modifiers.STATIC) != 0){
295 if (initialized_static_fields == null)
296 initialized_static_fields = new ArrayList ();
298 initialized_static_fields.Add (field);
301 // We have not seen a static constructor,
302 // but we will provide static initialization of fields
304 have_static_constructor = true;
306 if (initialized_fields == null)
307 initialized_fields = new ArrayList ();
309 initialized_fields.Add (field);
313 if ((field.ModFlags & Modifiers.STATIC) == 0)
314 have_nonstatic_fields = true;
316 DefineName (name, field);
317 return AdditionResult.Success;
320 public AdditionResult AddProperty (Property prop)
323 string name = prop.Name;
325 if ((res = IsValid (name)) != AdditionResult.Success)
328 if (properties == null)
329 properties = new ArrayList ();
331 if (prop.Name.IndexOf (".") != -1)
332 properties.Insert (0, prop);
334 properties.Add (prop);
335 DefineName (name, prop);
337 return AdditionResult.Success;
340 public AdditionResult AddEvent (Event e)
343 string name = e.Name;
345 if ((res = IsValid (name)) != AdditionResult.Success)
349 events = new ArrayList ();
352 DefineName (name, e);
354 return AdditionResult.Success;
357 public AdditionResult AddIndexer (Indexer i)
359 if (indexers == null)
360 indexers = new ArrayList ();
362 if (i.InterfaceType != null)
363 indexers.Insert (0, i);
367 return AdditionResult.Success;
370 public AdditionResult AddOperator (Operator op)
372 if (operators == null)
373 operators = new ArrayList ();
377 return AdditionResult.Success;
380 public void RegisterOrder (Interface iface)
382 if (interface_order == null)
383 interface_order = new ArrayList ();
385 interface_order.Add (iface);
388 public ArrayList Types {
394 public ArrayList Methods {
400 public ArrayList Constants {
406 public ArrayList Interfaces {
414 return base_class_name;
418 public ArrayList Bases {
428 public ArrayList Fields {
438 public ArrayList InstanceConstructors {
440 return instance_constructors;
444 public ArrayList Properties {
450 public ArrayList Events {
456 public ArrayList Enums {
462 public ArrayList Indexers {
468 public ArrayList Operators {
474 public ArrayList Delegates {
480 public Attributes OptAttributes {
486 public bool HaveStaticConstructor {
488 return have_static_constructor;
492 public virtual TypeAttributes TypeAttr {
494 return Modifiers.TypeAttr (ModFlags, this);
499 // Emits the instance field initializers
501 public bool EmitFieldInitializers (EmitContext ec)
504 ILGenerator ig = ec.ig;
505 Expression instance_expr;
508 fields = initialized_static_fields;
509 instance_expr = null;
511 fields = initialized_fields;
512 instance_expr = new This (Location.Null).Resolve (ec);
518 foreach (Field f in fields){
519 Object init = f.Initializer;
522 if (init is Expression)
523 e = (Expression) init;
525 string base_type = f.Type.Substring (0, f.Type.IndexOf ("["));
526 string rank = f.Type.Substring (f.Type.IndexOf ("["));
527 e = new ArrayCreation (base_type, rank, (ArrayList)init, f.Location);
530 Location l = f.Location;
531 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
532 fe.InstanceExpression = instance_expr;
533 Expression a = new Assign (fe, e, l);
539 if (a is ExpressionStatement)
540 ((ExpressionStatement) a).EmitStatement (ec);
542 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
550 // Defines the default constructors
552 void DefineDefaultConstructor (bool is_static)
557 c = new Constructor (Basename, Parameters.GetEmptyReadOnlyParameters (),
558 new ConstructorBaseInitializer (null, new Location (-1)),
562 mods = Modifiers.STATIC;
568 c.Block = new Block (null);
572 public void ReportStructInitializedInstanceError ()
574 string n = TypeBuilder.FullName;
576 foreach (Field f in initialized_fields){
579 "`" + n + "." + f.Name + "': can not have " +
580 "instance field initializers in structs");
585 /// The pending methods that need to be implemented (interfaces or abstract methods)
587 public PendingImplementation Pending;
590 /// This function computes the Base class and also the
591 /// list of interfaces that the class or struct @c implements.
593 /// The return value is an array (might be null) of
594 /// interfaces implemented (as Types).
596 /// The @parent argument is set to the parent object or null
597 /// if this is `System.Object'.
599 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
601 ArrayList bases = Bases;
610 parent = TypeManager.value_type;
614 if (RootContext.StdLib)
615 parent = TypeManager.object_type;
616 else if (Name != "System.Object")
617 parent = TypeManager.object_type;
620 // If we are compiling our runtime,
621 // and we are defining ValueType, then our
622 // parent is `System.Object'.
624 if (!RootContext.StdLib && Name == "System.ValueType")
625 parent = TypeManager.object_type;
632 // Bases should be null if there are no bases at all
637 string name = (string) bases [0];
638 Type first = FindType (name);
649 parent = TypeManager.object_type;
657 Type [] ifaces = new Type [count-start];
659 for (i = start, j = 0; i < count; i++, j++){
660 string name = (string) bases [i];
661 Type t = FindType (name);
668 if (is_class == false && !t.IsInterface){
669 Report.Error (527, "In Struct `" + Name + "', type `"+
670 name +"' is not an interface");
679 detail = " (a class can not inherit from a struct/enum)";
681 Report.Error (509, "class `"+ Name +
682 "': Cannot inherit from sealed class `"+
683 bases [i]+"'"+detail);
690 Report.Error (527, "In Class `" + Name + "', type `"+
691 name+"' is not an interface");
697 for (int x = 0; x < j; x++) {
698 if (t == ifaces [x]) {
699 Report.Error (528, "`" + name + "' is already listed in interface list");
708 return TypeManager.ExpandInterfaces (ifaces);
712 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
714 public override TypeBuilder DefineType ()
720 if (TypeBuilder != null)
733 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
735 ifaces = GetClassBases (is_class, out parent, out error);
740 if (is_class && parent != null){
741 if (parent == TypeManager.enum_type ||
742 (parent == TypeManager.value_type && RootContext.StdLib) ||
743 parent == TypeManager.delegate_type ||
744 parent == TypeManager.array_type){
746 644, Location, "`" + Name + "' cannot inherit from " +
747 "special class `" + TypeManager.CSharpName (parent) + "'");
752 if (!is_class && TypeManager.value_type == null)
753 throw new Exception ();
755 TypeAttributes type_attributes = TypeAttr;
757 // if (parent_builder is ModuleBuilder) {
759 ModuleBuilder builder = CodeGen.ModuleBuilder;
762 // Structs with no fields need to have a ".size 1"
766 if (!is_class && !have_nonstatic_fields)
767 TypeBuilder = builder.DefineType (Name,
770 PackingSize.Unspecified, 1);
773 // classes or structs with fields
775 TypeBuilder = builder.DefineType (Name,
780 TypeBuilder builder = Parent.TypeBuilder;
783 // Structs with no fields need to have a ".size 1"
786 if (!is_class && !have_nonstatic_fields)
787 TypeBuilder = builder.DefineNestedType (Basename,
790 PackingSize.Unspecified);
793 // classes or structs with fields
795 TypeBuilder = builder.DefineNestedType (Basename,
802 // add interfaces that were not added at type creation (weird API issue)
803 if (!is_class && !have_nonstatic_fields && (ifaces != null)) {
804 foreach (Type i in ifaces)
805 TypeBuilder.AddInterfaceImplementation (i);
809 // Finish the setup for the EmitContext
811 ec.ContainerType = TypeBuilder;
813 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
815 if ((parent != null) &&
816 (parent == TypeManager.attribute_type ||
817 parent.IsSubclassOf (TypeManager.attribute_type))) {
818 RootContext.RegisterAttribute (this);
819 TypeManager.RegisterAttrType (TypeBuilder, this);
821 RootContext.RegisterOrder (this);
823 if (Interfaces != null) {
824 foreach (Interface iface in Interfaces)
829 foreach (TypeContainer tc in Types)
833 if (Delegates != null) {
834 foreach (Delegate d in Delegates)
839 foreach (Enum en in Enums)
849 /// Defines the MemberCore objects that are in the `list' Arraylist
851 /// The `defined_names' array contains a list of members defined in
854 static ArrayList remove_list = new ArrayList ();
855 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
859 remove_list.Clear ();
861 foreach (MemberCore mc in list){
862 if (!mc.Define (this)){
863 remove_list.Add (mc);
867 if (defined_names == null)
870 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
872 if (RootContext.WarningLevel >= 4){
873 if ((mc.ModFlags & Modifiers.NEW) != 0)
874 Warning_KewywordNewNotRequired (mc.Location, mc);
879 MemberInfo match = defined_names [idx];
881 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
885 // If we are both methods, let the method resolution emit warnings
887 if (match is MethodBase && mc is MethodCore)
890 if ((mc.ModFlags & Modifiers.NEW) == 0)
891 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
894 foreach (object o in remove_list)
897 remove_list.Clear ();
901 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
902 // class is consisten. Either it is `Item' or it is the name defined by all the
903 // indexers with the `IndexerName' attribute.
905 // Turns out that the IndexerNameAttribute is applied to each indexer,
906 // but it is never emitted, instead a DefaultName attribute is attached
909 void DefineIndexers ()
911 string class_indexer_name = null;
913 foreach (Indexer i in Indexers){
918 name = i.IndexerName;
919 if (class_indexer_name == null){
920 class_indexer_name = name;
924 if (name == class_indexer_name)
928 668, "Two indexers have different names, " +
929 " you should use the same name for all your indexers");
931 if (class_indexer_name == null)
932 class_indexer_name = "Item";
933 IndexerName = class_indexer_name;
937 /// Populates our TypeBuilder with fields and methods
939 public override bool Define (TypeContainer parent)
941 MemberInfo [] defined_names = null;
943 if (RootContext.WarningLevel > 1){
947 // This code throws an exception in the comparer
948 // I guess the string is not an object?
950 ptype = TypeBuilder.BaseType;
952 defined_names = FindMembers (
953 ptype, MemberTypes.All & ~MemberTypes.Constructor,
954 BindingFlags.Public | BindingFlags.Instance |
955 BindingFlags.Static, null, null);
957 Array.Sort (defined_names, mif_compare);
961 if (constants != null)
962 DefineMembers (constants, defined_names);
965 DefineMembers (fields, defined_names);
968 if (instance_constructors == null){
969 if (default_constructor == null)
970 DefineDefaultConstructor (false);
973 if (initialized_static_fields != null &&
974 default_static_constructor == null)
975 DefineDefaultConstructor (true);
980 // Structs can not have initialized instance
983 if (initialized_static_fields != null &&
984 default_static_constructor == null)
985 DefineDefaultConstructor (true);
987 if (initialized_fields != null)
988 ReportStructInitializedInstanceError ();
991 Pending = PendingImplementation.GetPendingImplementations (this);
994 // Constructors are not in the defined_names array
996 if (instance_constructors != null)
997 DefineMembers (instance_constructors, null);
999 if (default_static_constructor != null)
1000 default_static_constructor.Define (this);
1002 if (methods != null)
1003 DefineMembers (methods, defined_names);
1005 if (properties != null)
1006 DefineMembers (properties, defined_names);
1009 DefineMembers (events, defined_names);
1011 if (indexers != null) {
1014 IndexerName = "Item";
1016 if (operators != null)
1017 DefineMembers (operators, null);
1020 DefineMembers (enums, defined_names);
1022 if (delegates != null)
1023 DefineMembers (delegates, defined_names);
1029 /// Looks up the alias for the name
1031 public string LookupAlias (string name)
1033 if (Namespace != null)
1034 return Namespace.LookupAlias (name);
1040 /// This function is based by a delegate to the FindMembers routine
1042 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1048 /// This filter is used by FindMembers, and we just keep
1049 /// a global for the filter to `AlwaysAccept'
1051 static MemberFilter accepting_filter;
1055 /// A member comparission method based on name only
1057 static IComparer mif_compare;
1059 static TypeContainer ()
1061 accepting_filter = new MemberFilter (AlwaysAccept);
1062 mif_compare = new MemberInfoCompare ();
1066 /// This method returns the members of this type just like Type.FindMembers would
1067 /// Only, we need to use this for types which are _being_ defined because MS'
1068 /// implementation can't take care of that.
1071 // FIXME: return an empty static array instead of null, that cleans up
1072 // some code and is consistent with some coding conventions I just found
1076 // Notice that in various cases we check if our field is non-null,
1077 // something that would normally mean that there was a bug elsewhere.
1079 // The problem happens while we are defining p-invoke methods, as those
1080 // will trigger a FindMembers, but this happens before things are defined
1082 // Since the whole process is a no-op, it is fine to check for null here.
1084 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
1085 MemberFilter filter, object criteria)
1087 ArrayList members = new ArrayList ();
1088 bool priv = (bf & BindingFlags.NonPublic) != 0;
1091 filter = accepting_filter;
1093 if ((mt & MemberTypes.Field) != 0) {
1094 if (fields != null) {
1095 foreach (Field f in fields) {
1096 if ((f.ModFlags & Modifiers.PRIVATE) != 0)
1100 FieldBuilder fb = f.FieldBuilder;
1101 if (fb != null && filter (fb, criteria) == true)
1106 if (constants != null) {
1107 foreach (Const con in constants) {
1108 if ((con.ModFlags & Modifiers.PRIVATE) != 0)
1112 FieldBuilder fb = con.FieldBuilder;
1113 if (fb != null && filter (fb, criteria) == true)
1119 if ((mt & MemberTypes.Method) != 0) {
1120 if (methods != null) {
1121 foreach (Method m in methods) {
1122 if ((m.ModFlags & Modifiers.PRIVATE) != 0)
1126 MethodBuilder mb = m.MethodBuilder;
1128 if (mb != null && filter (mb, criteria) == true)
1133 if (operators != null){
1134 foreach (Operator o in operators) {
1135 if ((o.ModFlags & Modifiers.PRIVATE) != 0)
1139 MethodBuilder ob = o.OperatorMethodBuilder;
1140 if (ob != null && filter (ob, criteria) == true)
1145 if (properties != null){
1146 foreach (Property p in properties){
1147 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1154 if (b != null && filter (b, criteria) == true)
1158 if (b != null && filter (b, criteria) == true)
1164 if ((mt & MemberTypes.Event) != 0) {
1166 foreach (Event e in events) {
1167 if ((e.ModFlags & Modifiers.PRIVATE) != 0)
1171 MemberInfo eb = e.EventBuilder;
1172 if (eb != null && filter (eb, criteria) == true)
1173 members.Add (e.EventBuilder);
1177 if ((mt & MemberTypes.Property) != 0){
1178 if (properties != null)
1179 foreach (Property p in properties) {
1180 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1184 MemberInfo pb = p.PropertyBuilder;
1185 if (pb != null && filter (pb, criteria) == true) {
1186 members.Add (p.PropertyBuilder);
1190 if (indexers != null)
1191 foreach (Indexer ix in indexers) {
1192 if ((ix.ModFlags & Modifiers.PRIVATE) != 0)
1196 MemberInfo ib = ix.PropertyBuilder;
1197 if (ib != null && filter (ib, criteria) == true) {
1198 members.Add (ix.PropertyBuilder);
1203 if ((mt & MemberTypes.NestedType) != 0) {
1206 foreach (TypeContainer t in Types)
1207 if (filter (t.TypeBuilder, criteria) == true)
1208 members.Add (t.TypeBuilder);
1211 foreach (Enum en in Enums)
1212 if (filter (en.TypeBuilder, criteria) == true)
1213 members.Add (en.TypeBuilder);
1216 if ((mt & MemberTypes.Constructor) != 0){
1217 if (instance_constructors != null){
1218 foreach (Constructor c in instance_constructors){
1219 ConstructorBuilder cb = c.ConstructorBuilder;
1222 if (filter (cb, criteria) == true)
1227 if (default_static_constructor != null){
1228 ConstructorBuilder cb =
1229 default_static_constructor.ConstructorBuilder;
1231 if (filter (cb, criteria) == true)
1237 // Lookup members in parent if requested.
1239 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1242 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1244 members.AddRange (mi);
1247 int count = members.Count;
1249 MemberInfo [] mi = new MemberInfo [count];
1250 members.CopyTo (mi);
1259 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1260 MemberFilter filter, object criteria)
1262 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1265 return tc.FindMembers (mt, bf, filter, criteria);
1267 return t.FindMembers (mt, bf, filter, criteria);
1271 // FindMethods will look for methods not only in the type `t', but in
1272 // any interfaces implemented by the type.
1274 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1275 MemberFilter filter, object criteria)
1281 /// Emits the values for the constants
1283 public void EmitConstants ()
1285 if (constants != null)
1286 foreach (Const con in constants)
1287 con.EmitConstant (this);
1292 /// Emits the code, this step is performed after all
1293 /// the types, enumerations, constructors
1297 if (instance_constructors != null)
1298 foreach (Constructor c in instance_constructors)
1301 if (default_static_constructor != null)
1302 default_static_constructor.Emit (this);
1304 if (methods != null)
1305 foreach (Method m in methods)
1308 if (operators != null)
1309 foreach (Operator o in operators)
1312 if (properties != null)
1313 foreach (Property p in properties)
1316 if (indexers != null){
1317 foreach (Indexer ix in indexers)
1320 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1321 this, IndexerName, ModFlags, Location);
1322 TypeBuilder.SetCustomAttribute (cb);
1326 foreach (Field f in fields)
1329 if (events != null){
1330 foreach (Event e in Events)
1334 if (Pending != null)
1335 if (Pending.VerifyPendingMethods ())
1338 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1341 // Check for internal or private fields that were never assigned
1343 if (fields != null && RootContext.WarningLevel >= 3) {
1344 foreach (Field f in fields) {
1345 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1350 169, f.Location, "Private field " +
1351 MakeName (f.Name) + " is never used");
1356 // Only report 649 on level 4
1358 if (RootContext.WarningLevel < 4)
1361 if ((f.status & Field.Status.ASSIGNED) != 0)
1366 "Field " + MakeName (f.Name) + " is never assigned " +
1367 " to and will always have its default value");
1371 // if (types != null)
1372 // foreach (TypeContainer tc in types)
1376 public override void CloseType ()
1381 TypeBuilder.CreateType ();
1383 } catch (TypeLoadException){
1385 // This is fine, the code still created the type
1387 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1388 // Console.WriteLine (e.Message);
1390 Console.WriteLine ("In type: " + Name);
1395 foreach (Enum en in Enums)
1398 if (interface_order != null){
1399 foreach (Interface iface in interface_order)
1404 foreach (TypeContainer tc in Types)
1408 foreach (TypeContainer tc in Types)
1409 if (!(tc is Struct))
1413 if (Delegates != null)
1414 foreach (Delegate d in Delegates)
1418 public string MakeName (string n)
1420 return "`" + Name + "." + n + "'";
1423 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1426 108, l, "The keyword new is required on " +
1427 MakeName (mi.Name) + " because it hides `" +
1428 mi.ReflectedType.Name + "." + mi.Name + "'");
1431 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1434 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1435 "inherited member, the keyword new is not required");
1438 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1444 // Performs the validation on a Method's modifiers (properties have
1445 // the same properties).
1447 public bool MethodModifiersValid (int flags, string n, Location loc)
1449 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1450 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1451 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1453 string name = MakeName (n);
1456 // At most one of static, virtual or override
1458 if ((flags & Modifiers.STATIC) != 0){
1459 if ((flags & vao) != 0){
1461 112, loc, "static method " + name + "can not be marked " +
1462 "as virtual, abstract or override");
1467 if (this is Struct){
1468 if ((flags & va) != 0){
1469 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1474 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1477 " marked as override cannot be marked as new or virtual");
1482 // If the declaration includes the abstract modifier, then the
1483 // declaration does not include static, virtual or extern
1485 if ((flags & Modifiers.ABSTRACT) != 0){
1486 if ((flags & Modifiers.EXTERN) != 0){
1488 180, loc, name + " can not be both abstract and extern");
1492 if ((flags & Modifiers.VIRTUAL) != 0){
1494 503, loc, name + " can not be both abstract and virtual");
1498 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1501 " is abstract but its container class is not");
1507 if ((flags & Modifiers.PRIVATE) != 0){
1508 if ((flags & vao) != 0){
1511 " virtual or abstract members can not be private");
1516 if ((flags & Modifiers.SEALED) != 0){
1517 if ((flags & Modifiers.OVERRIDE) == 0){
1520 " cannot be sealed because it is not an override");
1529 // Returns true if `type' is as accessible as the flags `flags'
1530 // given for this member
1532 static public bool AsAccessible (Type type, int flags)
1537 Hashtable builder_and_args;
1539 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1541 if (builder_and_args == null)
1542 builder_and_args = new Hashtable ();
1547 /// Performs checks for an explicit interface implementation. First it
1548 /// checks whether the `interface_type' is a base inteface implementation.
1549 /// Then it checks whether `name' exists in the interface type.
1551 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1555 if (ifaces != null){
1556 foreach (Type t in ifaces){
1557 if (t == interface_type){
1565 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1572 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1574 Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1578 public class Class : TypeContainer {
1580 // Modifiers allowed in a class declaration
1582 public const int AllowedModifiers =
1585 Modifiers.PROTECTED |
1586 Modifiers.INTERNAL |
1588 Modifiers.ABSTRACT |
1592 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1593 : base (parent, name, l)
1597 if (parent.Parent == null)
1598 accmods = Modifiers.INTERNAL;
1600 accmods = Modifiers.PRIVATE;
1602 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1603 this.attributes = attrs;
1607 // FIXME: How do we deal with the user specifying a different
1610 public override TypeAttributes TypeAttr {
1612 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1617 public class Struct : TypeContainer {
1619 // Modifiers allowed in a struct declaration
1621 public const int AllowedModifiers =
1624 Modifiers.PROTECTED |
1625 Modifiers.INTERNAL |
1629 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1630 : base (parent, name, l)
1634 if (parent.Parent == null)
1635 accmods = Modifiers.INTERNAL;
1637 accmods = Modifiers.PRIVATE;
1639 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1641 this.ModFlags |= Modifiers.SEALED;
1642 this.attributes = attrs;
1647 // FIXME: Allow the user to specify a different set of attributes
1648 // in some cases (Sealed for example is mandatory for a class,
1649 // but what SequentialLayout can be changed
1651 public override TypeAttributes TypeAttr {
1653 return base.TypeAttr |
1654 TypeAttributes.SequentialLayout |
1655 TypeAttributes.Sealed |
1656 TypeAttributes.BeforeFieldInit;
1661 public abstract class MethodCore : MemberCore {
1662 public readonly Parameters Parameters;
1666 // Parameters, cached for semantic analysis.
1668 InternalParameters parameter_info;
1670 public MethodCore (string name, Parameters parameters, Location l)
1674 Parameters = parameters;
1678 // Returns the System.Type array for the parameters of this method
1680 Type [] parameter_types;
1681 public Type [] ParameterTypes (TypeContainer parent)
1683 if (Parameters == null)
1684 return TypeManager.NoTypes;
1686 if (parameter_types == null)
1687 parameter_types = Parameters.GetParameterInfo (parent);
1689 return parameter_types;
1692 public InternalParameters ParameterInfo
1695 return parameter_info;
1699 parameter_info = value;
1703 public Block Block {
1713 public CallingConventions GetCallingConvention (bool is_class)
1715 CallingConventions cc = 0;
1717 cc = Parameters.GetCallingConvention ();
1720 if ((ModFlags & Modifiers.STATIC) == 0)
1721 cc |= CallingConventions.HasThis;
1723 // FIXME: How is `ExplicitThis' used in C#?
1728 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
1731 // Define each type attribute (in/out/ref) and
1732 // the argument names.
1734 Parameter [] p = Parameters.FixedParameters;
1737 MethodBuilder mb = null;
1738 ConstructorBuilder cb = null;
1740 if (builder is MethodBuilder)
1741 mb = (MethodBuilder) builder;
1743 cb = (ConstructorBuilder) builder;
1746 for (i = 0; i < p.Length; i++) {
1747 ParameterBuilder pb;
1750 pb = cb.DefineParameter (
1751 i + 1, p [i].Attributes, p [i].Name);
1753 pb = mb.DefineParameter (
1754 i + 1, p [i].Attributes, p [i].Name);
1756 Attributes attr = p [i].OptAttributes;
1758 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
1762 if (Parameters.ArrayParameter != null){
1763 ParameterBuilder pb;
1764 Parameter array_param = Parameters.ArrayParameter;
1767 pb = cb.DefineParameter (
1768 i + 1, array_param.Attributes,
1771 pb = mb.DefineParameter (
1772 i + 1, array_param.Attributes,
1775 CustomAttributeBuilder a = new CustomAttributeBuilder (
1776 TypeManager.cons_param_array_attribute, new object [0]);
1778 pb.SetCustomAttribute (a);
1783 public class Method : MethodCore {
1784 public readonly string ReturnType;
1785 public MethodBuilder MethodBuilder;
1786 public readonly Attributes OptAttributes;
1788 MethodAttributes flags;
1791 /// Modifiers allowed in a class declaration
1793 const int AllowedModifiers =
1796 Modifiers.PROTECTED |
1797 Modifiers.INTERNAL |
1802 Modifiers.OVERRIDE |
1803 Modifiers.ABSTRACT |
1808 // return_type can be "null" for VOID values.
1810 public Method (string return_type, int mod, string name, Parameters parameters,
1811 Attributes attrs, Location l)
1812 : base (name, parameters, l)
1814 ReturnType = return_type;
1815 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l);
1816 OptAttributes = attrs;
1820 // Returns the `System.Type' for the ReturnType of this
1821 // function. Provides a nice cache. (used between semantic analysis
1822 // and actual code generation
1824 Type type_return_type;
1826 public Type GetReturnType (TypeContainer parent)
1828 if (type_return_type == null)
1829 type_return_type = RootContext.LookupType (
1830 parent, ReturnType, false, Location);
1832 return type_return_type;
1835 void DuplicateEntryPoint (MethodInfo b, Location location)
1839 "Program `" + CodeGen.FileName +
1840 "' has more than one entry point defined: `" +
1841 TypeManager.CSharpSignature(b) + "'");
1844 void Report28 (MethodInfo b)
1846 if (RootContext.WarningLevel < 4)
1851 "`" + TypeManager.CSharpSignature(b) +
1852 "' has the wrong signature to be an entry point");
1855 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
1857 if (b.ReturnType != TypeManager.void_type &&
1858 b.ReturnType != TypeManager.int32_type)
1861 if (pinfo.Count == 0)
1864 if (pinfo.Count > 1)
1867 Type t = pinfo.ParameterType(0);
1869 (t.GetArrayRank() == 1) &&
1870 (t.GetElementType() == TypeManager.string_type) &&
1871 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
1880 public override bool Define (TypeContainer parent)
1882 Type ret_type = GetReturnType (parent);
1883 Type [] parameters = ParameterTypes (parent);
1885 MethodInfo implementing = null;
1886 Type iface_type = null;
1887 string iface = "", short_name;
1888 bool explicit_impl = false;
1890 // Check if the return type and arguments were correct
1891 if (ret_type == null || parameters == null)
1894 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
1897 flags = Modifiers.MethodAttr (ModFlags);
1900 // verify accessibility
1902 if (!TypeContainer.AsAccessible (ret_type, ModFlags))
1905 if (ret_type.IsPointer && !UnsafeOK (parent))
1908 foreach (Type partype in parameters){
1909 if (!TypeContainer.AsAccessible (partype, ModFlags))
1911 if (partype.IsPointer && !UnsafeOK (parent))
1919 // Verify if the parent has a type with the same name, and then
1920 // check whether we have to create a new slot for it or not.
1922 Type ptype = parent.TypeBuilder.BaseType;
1924 // ptype is only null for System.Object while compiling corlib.
1926 MethodSignature ms = new MethodSignature (Name, null, parameters);
1927 MemberInfo [] mi, mi_static, mi_instance;
1929 mi_static = TypeContainer.FindMembers (
1930 ptype, MemberTypes.Method,
1931 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
1932 MethodSignature.inheritable_method_signature_filter, ms);
1934 mi_instance = TypeContainer.FindMembers (
1935 ptype, MemberTypes.Method,
1936 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
1937 MethodSignature.inheritable_method_signature_filter,
1940 if (mi_instance != null && mi_instance.Length > 0){
1942 } else if (mi_static != null && mi_static.Length > 0)
1947 if (mi != null && mi.Length > 0){
1948 if (!CheckMethodAgainstBase (parent, flags, (MethodInfo) mi [0])){
1952 if ((ModFlags & Modifiers.NEW) != 0)
1953 WarningNotHiding (parent);
1955 if ((ModFlags & Modifiers.OVERRIDE) != 0){
1956 Report.Error (115, Location,
1957 parent.MakeName (Name) +
1958 " no suitable methods found to override");
1961 } else if ((ModFlags & Modifiers.NEW) != 0)
1962 WarningNotHiding (parent);
1965 // If we implement an interface, extract the interface name.
1967 if (Name.IndexOf (".") != -1){
1968 int pos = Name.LastIndexOf (".");
1969 iface = Name.Substring (0, pos);
1971 iface_type = RootContext.LookupType (parent, iface, false, Location);
1972 short_name = Name.Substring (pos + 1);
1974 if (iface_type == null)
1977 // Compute the full name that we need to export
1978 Name = iface_type.FullName + "." + short_name;
1980 if (!parent.VerifyImplements (iface_type, short_name, Name, Location))
1983 explicit_impl = true;
1988 // Check if we are an implementation of an interface method or
1991 if (parent.Pending != null){
1992 implementing = parent.Pending.IsInterfaceMethod (
1993 iface_type, short_name, ret_type, parameters);
1995 if (iface_type != null && implementing == null){
1996 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (Location, short_name);
2002 // For implicit implementations, make sure we are public, for
2003 // explicit implementations, make sure we are private.
2005 if (implementing != null){
2007 // Setting null inside this block will trigger a more
2008 // verbose error reporting for missing interface implementations
2010 // The "candidate" function has been flagged already
2011 // but it wont get cleared
2013 if (iface_type == null){
2015 // We already catch different accessibility settings
2016 // so we just need to check that we are not private
2018 if ((ModFlags & Modifiers.PRIVATE) != 0)
2019 implementing = null;
2022 // Static is not allowed
2024 if ((ModFlags & Modifiers.STATIC) != 0)
2025 implementing = null;
2027 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
2028 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
2029 implementing = null;
2035 // If implementing is still valid, set flags
2037 if (implementing != null){
2038 // Console.WriteLine ("Implementing for:" + (iface_type != null ? iface_type.FullName : "<null>") + " " + short_name);
2040 if (implementing.DeclaringType.IsInterface)
2041 flags |= MethodAttributes.NewSlot;
2044 MethodAttributes.Virtual |
2045 MethodAttributes.HideBySig;
2048 // clear the pending implementation flag
2050 parent.Pending.ImplementMethod (
2051 iface_type, short_name, ret_type, parameters, explicit_impl);
2054 Attribute dllimport_attr = null;
2055 if (OptAttributes != null && OptAttributes.AttributeSections != null) {
2056 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2057 if (asec.Attributes == null)
2060 foreach (Attribute a in asec.Attributes)
2061 if (a.Name.IndexOf ("DllImport") != -1) {
2062 flags |= MethodAttributes.PinvokeImpl;
2069 // Finally, define the method
2072 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2074 if ((ModFlags & Modifiers.STATIC) == 0) {
2075 Report.Error (601, Location, "The DllImport attribute must be specified on " +
2076 "a method marked 'static' and 'extern'.");
2080 EmitContext ec = new EmitContext (
2081 parent, Location, null, GetReturnType (parent), ModFlags);
2083 MethodBuilder = dllimport_attr.DefinePInvokeMethod (
2084 ec, parent.TypeBuilder,
2085 Name, flags, ret_type, parameters);
2087 MethodBuilder = parent.TypeBuilder.DefineMethod (
2089 GetCallingConvention (parent is Class),
2090 ret_type, parameters);
2092 if (implementing != null && explicit_impl)
2093 parent.TypeBuilder.DefineMethodOverride (
2094 MethodBuilder, implementing);
2097 if (MethodBuilder == null)
2101 // HACK because System.Reflection.Emit is lame
2103 ParameterInfo = new InternalParameters (parent, Parameters);
2105 if (!TypeManager.RegisterMethod (MethodBuilder, ParameterInfo,
2109 "Class `" + parent.Name + "' already contains a definition with " +
2110 " the same return value and parameter types for method `" +
2116 // This is used to track the Entry Point,
2118 if (Name == "Main" &&
2119 ((ModFlags & Modifiers.STATIC) != 0) &&
2120 (RootContext.MainClass == null ||
2121 RootContext.MainClass == parent.TypeBuilder.FullName)){
2122 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2123 if (RootContext.EntryPoint == null) {
2124 RootContext.EntryPoint = MethodBuilder;
2125 RootContext.EntryPointLocation = Location;
2127 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2128 DuplicateEntryPoint (MethodBuilder, Location);
2131 Report28(MethodBuilder);
2140 public void Emit (TypeContainer parent)
2145 if ((flags & MethodAttributes.PinvokeImpl) == 0)
2146 ig = MethodBuilder.GetILGenerator ();
2150 ec = new EmitContext (parent, Location, ig, GetReturnType (parent), ModFlags);
2152 if (OptAttributes != null)
2153 Attribute.ApplyAttributes (ec, MethodBuilder, this, OptAttributes, Location);
2156 LabelParameters (ec, ParameterTypes (parent), MethodBuilder);
2159 // abstract or extern methods have no bodies
2161 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
2163 if ((ModFlags & Modifiers.ABSTRACT) != 0){
2165 500, "Abstract method `" +
2166 TypeManager.CSharpSignature (MethodBuilder) +
2167 "' can not have a body");
2174 // Handle destructors specially
2176 // FIXME: This code generates buggy code
2178 if (Name == "Finalize" && type_return_type == TypeManager.void_type)
2179 EmitDestructor (ec);
2181 ISymbolWriter sw = CodeGen.SymbolWriter;
2183 if ((sw != null) && (!Location.IsNull (Location))) {
2184 MethodToken token = MethodBuilder.GetToken ();
2185 sw.OpenMethod (new SymbolToken (token.Token));
2186 sw.SetMethodSourceRange (Location.SymbolDocument,
2188 Block.EndLocation.SymbolDocument,
2189 Block.EndLocation.Row, 0);
2191 ec.EmitTopBlock (Block, Location);
2195 ec.EmitTopBlock (Block, Location);
2199 void EmitDestructor (EmitContext ec)
2201 ILGenerator ig = ec.ig;
2203 Label finish = ig.DefineLabel ();
2204 bool old_in_try = ec.InTry;
2206 ig.BeginExceptionBlock ();
2208 ec.ReturnLabel = finish;
2209 ec.EmitTopBlock (Block, Location);
2210 ec.InTry = old_in_try;
2212 ig.MarkLabel (finish);
2213 bool old_in_finally = ec.InFinally;
2214 ec.InFinally = true;
2215 ig.BeginFinallyBlock ();
2217 if (ec.ContainerType.BaseType != null) {
2218 Expression member_lookup = Expression.MemberLookup (
2219 ec, ec.ContainerType.BaseType, "Finalize",
2220 MemberTypes.Method, Expression.AllBindingFlags, Location);
2222 if (member_lookup != null){
2223 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
2225 ig.Emit (OpCodes.Ldarg_0);
2226 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
2229 ec.InFinally = old_in_finally;
2231 ig.EndExceptionBlock ();
2232 //ig.MarkLabel (ec.ReturnLabel);
2233 ig.Emit (OpCodes.Ret);
2237 public abstract class ConstructorInitializer {
2238 ArrayList argument_list;
2239 ConstructorInfo parent_constructor;
2242 public ConstructorInitializer (ArrayList argument_list, Location location)
2244 this.argument_list = argument_list;
2245 this.location = location;
2248 public ArrayList Arguments {
2250 return argument_list;
2254 public bool Resolve (EmitContext ec)
2256 Expression parent_constructor_group;
2259 if (argument_list != null){
2260 foreach (Argument a in argument_list){
2261 if (!a.Resolve (ec, location))
2266 if (this is ConstructorBaseInitializer) {
2267 if (ec.ContainerType.BaseType == null)
2270 t = ec.ContainerType.BaseType;
2271 if (ec.ContainerType.IsValueType) {
2272 Report.Error (522, location,
2273 "structs cannot call base class constructors");
2277 t = ec.ContainerType;
2279 parent_constructor_group = Expression.MemberLookup (
2281 MemberTypes.Constructor,
2282 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2285 if (parent_constructor_group == null){
2286 Report.Error (1501, location,
2287 "Can not find a constructor for this argument list");
2291 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2292 (MethodGroupExpr) parent_constructor_group, argument_list, location);
2294 if (parent_constructor == null){
2295 Report.Error (1501, location,
2296 "Can not find a constructor for this argument list");
2303 public void Emit (EmitContext ec)
2305 if (parent_constructor != null)
2306 ec.ig.Emit (OpCodes.Ldarg_0);
2307 if (argument_list != null)
2308 Invocation.EmitArguments (ec, null, argument_list);
2309 if (parent_constructor != null)
2310 ec.ig.Emit (OpCodes.Call, parent_constructor);
2314 public class ConstructorBaseInitializer : ConstructorInitializer {
2315 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2320 public class ConstructorThisInitializer : ConstructorInitializer {
2321 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2326 public class Constructor : MethodCore {
2327 public ConstructorBuilder ConstructorBuilder;
2328 public ConstructorInitializer Initializer;
2329 public Attributes OptAttributes;
2332 // Modifiers allowed for a constructor.
2334 const int AllowedModifiers =
2336 Modifiers.PROTECTED |
2337 Modifiers.INTERNAL |
2343 // The spec claims that static is not permitted, but
2344 // my very own code has static constructors.
2346 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2347 : base (name, args, l)
2353 // Returns true if this is a default constructor
2355 public bool IsDefault ()
2357 if ((ModFlags & Modifiers.STATIC) != 0)
2358 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2359 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2362 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2363 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2364 (Initializer is ConstructorBaseInitializer) &&
2365 (Initializer.Arguments == null);
2369 // Creates the ConstructorBuilder
2371 public override bool Define (TypeContainer parent)
2373 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2374 MethodAttributes.SpecialName);
2376 Type [] parameters = ParameterTypes (parent);
2378 if (parameters == null)
2381 if ((ModFlags & Modifiers.STATIC) != 0)
2382 ca |= MethodAttributes.Static;
2384 if (parent is Struct && parameters.Length == 0){
2387 "Structs can not contain explicit parameterless " +
2391 ca |= MethodAttributes.Public | MethodAttributes.HideBySig;
2394 foreach (Type partype in parameters)
2395 if (!TypeContainer.AsAccessible (partype, ModFlags))
2398 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2399 ca, GetCallingConvention (parent is Class), parameters);
2402 // HACK because System.Reflection.Emit is lame
2404 ParameterInfo = new InternalParameters (parent, Parameters);
2406 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, parameters)) {
2409 "Class `" +parent.Name+ "' already contains a definition with the " +
2410 "same return value and parameter types for constructor `" + Name
2421 public void Emit (TypeContainer parent)
2423 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2424 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2426 if ((ModFlags & Modifiers.STATIC) == 0){
2427 if (parent is Class && Initializer == null)
2428 Initializer = new ConstructorBaseInitializer (null, parent.Location);
2432 // Spec mandates that Initializers will not have
2436 if (Initializer != null && !Initializer.Resolve (ec))
2438 ec.IsStatic = false;
2441 LabelParameters (ec, ParameterTypes (parent), ConstructorBuilder);
2444 // Classes can have base initializers and instance field initializers.
2446 if (parent is Class){
2447 if ((ModFlags & Modifiers.STATIC) == 0)
2448 parent.EmitFieldInitializers (ec);
2450 if (Initializer != null)
2451 Initializer.Emit (ec);
2453 if ((ModFlags & Modifiers.STATIC) != 0)
2454 parent.EmitFieldInitializers (ec);
2456 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2458 ec.EmitTopBlock (Block, Location);
2463 // Fields and Events both generate FieldBuilders, we use this to share
2464 // their common bits. This is also used to flag usage of the field
2466 abstract public class FieldBase : MemberCore {
2467 public readonly string Type;
2468 public readonly Object Initializer;
2469 public readonly Attributes OptAttributes;
2470 public FieldBuilder FieldBuilder;
2471 public Status status;
2474 public enum Status : byte { ASSIGNED = 1, USED = 2 }
2477 // The constructor is only exposed to our children
2479 protected FieldBase (string type, int mod, int allowed_mod, string name,
2480 object init, Attributes attrs, Location loc)
2484 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
2486 OptAttributes = attrs;
2491 // The Field class is used to represents class/struct fields during parsing.
2493 public class Field : FieldBase {
2495 // Modifiers allowed in a class declaration
2497 const int AllowedModifiers =
2500 Modifiers.PROTECTED |
2501 Modifiers.INTERNAL |
2504 Modifiers.VOLATILE |
2508 public Field (string type, int mod, string name, Object expr_or_array_init,
2509 Attributes attrs, Location loc)
2510 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
2514 public override bool Define (TypeContainer parent)
2516 Type t = RootContext.LookupType (parent, Type, false, Location);
2521 if (!TypeContainer.AsAccessible (t, ModFlags))
2524 if (t.IsPointer && !UnsafeOK (parent))
2527 if (RootContext.WarningLevel > 1){
2528 Type ptype = parent.TypeBuilder.BaseType;
2530 // ptype is only null for System.Object while compiling corlib.
2534 mi = TypeContainer.FindMembers (
2535 ptype, MemberTypes.Method,
2536 BindingFlags.Public |
2537 BindingFlags.Static | BindingFlags.Instance,
2538 System.Type.FilterName, Name);
2542 if ((ModFlags & Modifiers.VOLATILE) != 0){
2544 if (TypeManager.IsEnumType (t))
2545 t = TypeManager.EnumToUnderlying (t);
2547 if (!((t == TypeManager.bool_type) ||
2548 (t == TypeManager.sbyte_type) ||
2549 (t == TypeManager.byte_type) ||
2550 (t == TypeManager.short_type) ||
2551 (t == TypeManager.ushort_type) ||
2552 (t == TypeManager.int32_type) ||
2553 (t == TypeManager.uint32_type) ||
2554 (t == TypeManager.char_type) ||
2555 (t == TypeManager.float_type))){
2557 677, Location, parent.MakeName (Name) +
2558 " A volatile field can not be of type `" +
2559 TypeManager.CSharpName (t) + "'");
2565 FieldBuilder = parent.TypeBuilder.DefineField (
2566 Name, t, Modifiers.FieldAttr (ModFlags));
2568 TypeManager.RegisterFieldBase (FieldBuilder, this);
2572 public void Emit (TypeContainer tc)
2574 EmitContext ec = new EmitContext (tc, Location, null,
2575 FieldBuilder.FieldType, ModFlags);
2577 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
2582 // `set' and `get' accessors are represented with an Accessor.
2584 public class Accessor {
2586 // Null if the accessor is empty, or a Block if not
2589 public Attributes OptAttributes;
2591 public Accessor (Block b, Attributes attrs)
2594 OptAttributes = attrs;
2598 public class Property : MemberCore {
2599 public readonly string Type;
2600 public Accessor Get, Set;
2601 public PropertyBuilder PropertyBuilder;
2602 public Attributes OptAttributes;
2603 public MethodBuilder GetBuilder, SetBuilder;
2606 // The type, once we compute it.
2612 // If true, the interface type we are explicitly implementing
2614 Type explicit_iface_type = null;
2616 const int AllowedModifiers =
2619 Modifiers.PROTECTED |
2620 Modifiers.INTERNAL |
2624 Modifiers.OVERRIDE |
2625 Modifiers.ABSTRACT |
2630 public Property (string type, string name, int mod_flags,
2631 Accessor get_block, Accessor set_block,
2632 Attributes attrs, Location loc)
2636 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
2639 OptAttributes = attrs;
2643 // Checks our base implementation if any
2645 bool CheckBase (MethodAttributes flags, TypeContainer parent)
2648 // Find properties with the same name on the base class
2651 MemberInfo [] props;
2652 MemberInfo [] props_static = TypeManager.MemberLookup (
2654 parent.TypeBuilder.BaseType,
2655 MemberTypes.Property, BindingFlags.Public | BindingFlags.Static,
2658 MemberInfo [] props_instance = TypeManager.MemberLookup (
2660 parent.TypeBuilder.BaseType,
2661 MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance,
2665 // Find if we have anything
2667 if (props_static != null && props_static.Length > 0)
2668 props = props_static;
2669 else if (props_instance != null && props_instance.Length > 0)
2670 props = props_instance;
2675 // If we have something on the base.
2676 if (props != null && props.Length > 0){
2677 if (props.Length > 1)
2678 throw new Exception ("Should not happen");
2680 PropertyInfo pi = (PropertyInfo) props [0];
2682 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
2683 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
2685 MethodInfo reference = inherited_get == null ?
2686 inherited_set : inherited_get;
2688 if (reference != null)
2689 if (!CheckMethodAgainstBase (parent, flags, reference))
2693 if ((ModFlags & Modifiers.NEW) != 0)
2694 WarningNotHiding (parent);
2696 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2697 Report.Error (115, Location,
2698 parent.MakeName (Name) +
2699 " no suitable properties found to override");
2706 bool DefineMethod (TypeContainer parent, string short_name,
2707 MethodAttributes flags, bool is_get, ref bool is_implementing)
2709 Type [] parameters = TypeManager.NoTypes;
2710 MethodInfo implementing = null;
2712 string name, prefix;
2715 prefix = explicit_iface_type.FullName + ".";
2720 fn_type = PropertyType;
2721 name = "get_" + short_name;
2723 name = "set_" + short_name;
2724 parameters = new Type [1];
2725 parameters [0] = PropertyType;
2726 fn_type = TypeManager.void_type;
2729 if (parent.Pending != null){
2730 implementing = parent.Pending.IsInterfaceMethod (
2731 explicit_iface_type, name, fn_type, parameters);
2733 if (explicit_iface_type != null && implementing == null){
2734 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (Location, name);
2740 // For implicit implementations, make sure we are public, for
2741 // explicit implementations, make sure we are private.
2743 if (implementing != null){
2745 // Setting null inside this block will trigger a more
2746 // verbose error reporting for missing interface implementations
2748 // The "candidate" function has been flagged already
2749 // but it wont get cleared
2751 if (explicit_iface_type == null){
2753 // We already catch different accessibility settings
2754 // so we just need to check that we are not private
2756 if ((ModFlags & Modifiers.PRIVATE) != 0)
2757 implementing = null;
2760 // Static is not allowed
2762 if ((ModFlags & Modifiers.STATIC) != 0)
2763 implementing = null;
2765 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
2766 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
2767 implementing = null;
2773 // If implementing is still valid, set flags
2775 if (implementing != null){
2777 // When implementing interface methods, set NewSlot.
2779 if (implementing.DeclaringType.IsInterface)
2780 flags |= MethodAttributes.NewSlot;
2783 MethodAttributes.Virtual |
2784 MethodAttributes.HideBySig;
2787 // clear the pending implemntation flag
2789 parent.Pending.ImplementMethod (
2790 explicit_iface_type, name, fn_type, parameters, explicit_impl);
2792 is_implementing = true;
2796 // If this is not an explicit interface implementation,
2797 // clear implementing, as it is only used for explicit
2798 // interface implementation
2800 if (Name.IndexOf (".") == -1)
2801 implementing = null;
2804 GetBuilder = parent.TypeBuilder.DefineMethod (
2805 prefix + name, flags, PropertyType, null);
2807 if (implementing != null)
2808 parent.TypeBuilder.DefineMethodOverride (
2809 GetBuilder, implementing);
2812 // HACK because System.Reflection.Emit is lame
2814 InternalParameters ip = new InternalParameters (
2815 parent, Parameters.GetEmptyReadOnlyParameters ());
2817 if (!TypeManager.RegisterMethod (GetBuilder, ip, null)) {
2818 Report.Error (111, Location,
2819 "Class `" + parent.Name +
2820 "' already contains a definition with the " +
2821 "same return value and parameter types as the " +
2822 "'get' method of property `" + Name + "'");
2826 SetBuilder = parent.TypeBuilder.DefineMethod (
2827 prefix + name, flags, null, parameters);
2829 if (implementing != null)
2830 parent.TypeBuilder.DefineMethodOverride (
2831 SetBuilder, implementing);
2833 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
2836 // HACK because System.Reflection.Emit is lame
2838 Parameter [] parms = new Parameter [1];
2839 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
2840 InternalParameters ip = new InternalParameters (
2841 parent, new Parameters (parms, null, Location));
2843 if (!TypeManager.RegisterMethod (SetBuilder, ip, parameters)) {
2846 "Class `" + parent.Name +
2847 "' already contains a definition with the " +
2848 "same return value and parameter types as the " +
2849 "'set' method of property `" + Name + "'");
2857 public override bool Define (TypeContainer parent)
2861 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
2864 MethodAttributes flags = Modifiers.MethodAttr (ModFlags);
2866 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
2868 // Lookup Type, verify validity
2869 PropertyType = RootContext.LookupType (parent, Type, false, Location);
2870 if (PropertyType == null)
2873 // verify accessibility
2874 if (!TypeContainer.AsAccessible (PropertyType, ModFlags))
2877 if (PropertyType.IsPointer && !UnsafeOK (parent))
2880 if (!CheckBase (flags, parent))
2884 // Check for explicit interface implementation
2886 if (Name.IndexOf (".") != -1){
2887 int pos = Name.LastIndexOf (".");
2888 string iface = Name.Substring (0, pos);
2890 explicit_iface_type = RootContext.LookupType (parent, iface, false, Location);
2891 if (explicit_iface_type == null)
2894 short_name = Name.Substring (pos + 1);
2896 // Compute the full name that we need to export.
2897 Name = explicit_iface_type.FullName + "." + short_name;
2899 if (!parent.VerifyImplements (explicit_iface_type, short_name, Name, Location))
2902 explicit_impl = true;
2904 explicit_impl = false;
2908 bool is_implementing = false;
2910 if (!DefineMethod (parent, short_name, flags, true, ref is_implementing))
2914 if (!DefineMethod (parent, short_name, flags, false, ref is_implementing))
2917 // FIXME - PropertyAttributes.HasDefault ?
2919 PropertyAttributes prop_attr =
2920 PropertyAttributes.RTSpecialName |
2921 PropertyAttributes.SpecialName;
2923 if (!explicit_impl){
2924 PropertyBuilder = parent.TypeBuilder.DefineProperty (
2925 Name, prop_attr, PropertyType, null);
2928 PropertyBuilder.SetGetMethod (GetBuilder);
2931 PropertyBuilder.SetSetMethod (SetBuilder);
2934 // HACK for the reasons exposed above
2936 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
2939 "Class `" + parent.Name +
2940 "' already contains a definition for the property `" +
2948 public void Emit (TypeContainer tc)
2953 ec = new EmitContext (tc, Location, null, PropertyType, ModFlags);
2956 // The PropertyBuilder can be null for explicit implementations, in that
2957 // case, we do not actually emit the ".property", so there is nowhere to
2958 // put the attribute
2960 if (PropertyBuilder != null)
2961 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
2963 Attribute.ApplyAttributes (ec, GetBuilder, Get, Get.OptAttributes, Location);
2965 Attribute.ApplyAttributes (ec, SetBuilder, Set, Set.OptAttributes, Location);
2968 // abstract or extern properties have no bodies
2970 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
2974 ig = GetBuilder.GetILGenerator ();
2975 ec = new EmitContext (tc, Location, ig, PropertyType, ModFlags);
2977 ec.EmitTopBlock (Get.Block, Location);
2981 ig = SetBuilder.GetILGenerator ();
2982 ec = new EmitContext (tc, Location, ig, null, ModFlags);
2984 ec.EmitTopBlock (Set.Block, Location);
2991 /// Gigantic workaround for lameness in SRE follows :
2992 /// This class derives from EventInfo and attempts to basically
2993 /// wrap around the EventBuilder so that FindMembers can quickly
2994 /// return this in it search for members
2996 public class MyEventBuilder : EventInfo {
2999 // We use this to "point" to our Builder which is
3000 // not really a MemberInfo
3002 EventBuilder MyBuilder;
3005 // We "catch" and wrap these methods
3007 MethodInfo raise, remove, add;
3009 EventAttributes attributes;
3010 Type declaring_type, reflected_type, event_type;
3013 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3015 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3017 // And now store the values in our own fields.
3019 declaring_type = type_builder;
3021 reflected_type = type_builder;
3023 attributes = event_attr;
3025 this.event_type = event_type;
3029 // Methods that you have to override. Note that you only need
3030 // to "implement" the variants that take the argument (those are
3031 // the "abstract" methods, the others (GetAddMethod()) are
3034 public override MethodInfo GetAddMethod (bool nonPublic)
3039 public override MethodInfo GetRemoveMethod (bool nonPublic)
3044 public override MethodInfo GetRaiseMethod (bool nonPublic)
3050 // These methods make "MyEventInfo" look like a Builder
3052 public void SetRaiseMethod (MethodBuilder raiseMethod)
3054 raise = raiseMethod;
3055 MyBuilder.SetRaiseMethod (raiseMethod);
3058 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3060 remove = removeMethod;
3061 MyBuilder.SetRemoveOnMethod (removeMethod);
3064 public void SetAddOnMethod (MethodBuilder addMethod)
3067 MyBuilder.SetAddOnMethod (addMethod);
3070 public void SetCustomAttribute (CustomAttributeBuilder cb)
3072 MyBuilder.SetCustomAttribute (cb);
3075 public override object [] GetCustomAttributes (bool inherit)
3077 // FIXME : There's nothing which can be seemingly done here because
3078 // we have no way of getting at the custom attribute objects of the
3083 public override object [] GetCustomAttributes (Type t, bool inherit)
3085 // FIXME : Same here !
3089 public override bool IsDefined (Type t, bool b)
3094 public override EventAttributes Attributes {
3100 public override string Name {
3106 public override Type DeclaringType {
3108 return declaring_type;
3112 public override Type ReflectedType {
3114 return reflected_type;
3118 public Type EventType {
3125 public class Event : FieldBase {
3126 const int AllowedModifiers =
3129 Modifiers.PROTECTED |
3130 Modifiers.INTERNAL |
3135 Modifiers.OVERRIDE |
3139 public readonly Accessor Add;
3140 public readonly Accessor Remove;
3141 public MyEventBuilder EventBuilder;
3144 MethodBuilder AddBuilder, RemoveBuilder;
3146 public Event (string type, string name, Object init, int mod, Accessor add,
3147 Accessor remove, Attributes attrs, Location loc)
3148 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
3154 public override bool Define (TypeContainer parent)
3156 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3159 MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
3160 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3162 EventType = RootContext.LookupType (parent, Type, false, Location);
3163 if (EventType == null)
3166 if (!TypeContainer.AsAccessible (EventType, ModFlags))
3169 if (EventType.IsPointer && !UnsafeOK (parent))
3172 if (!EventType.IsSubclassOf (TypeManager.delegate_type)) {
3173 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3174 "' : event must be of a delegate type");
3178 Type [] parameters = new Type [1];
3179 parameters [0] = EventType;
3181 EventBuilder = new MyEventBuilder (parent.TypeBuilder, Name, e_attr, EventType);
3183 if (Add == null && Remove == null) {
3184 FieldBuilder = parent.TypeBuilder.DefineField (
3185 Name, EventType, FieldAttributes.FamANDAssem);
3186 TypeManager.RegisterPrivateFieldOfEvent ((EventInfo) EventBuilder, FieldBuilder);
3187 TypeManager.RegisterFieldBase (FieldBuilder, this);
3191 // Now define the accessors
3193 string add_name = "add_" + Name;
3195 AddBuilder = parent.TypeBuilder.DefineMethod (
3196 add_name, m_attr, null, parameters);
3197 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3198 EventBuilder.SetAddOnMethod (AddBuilder);
3199 if (parent.Pending != null)
3200 parent.Pending.ImplementMethod (null, add_name, null, parameters, false);
3203 // HACK because System.Reflection.Emit is lame
3205 Parameter [] parms = new Parameter [1];
3206 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3207 InternalParameters ip = new InternalParameters (
3208 parent, new Parameters (parms, null, Location));
3210 if (!TypeManager.RegisterMethod (AddBuilder, ip, parameters)) {
3211 Report.Error (111, Location,
3212 "Class `" + parent.Name + "' already contains a definition with the " +
3213 "same return value and parameter types for the " +
3214 "'add' method of event `" + Name + "'");
3218 string remove_name = "remove_" + Name;
3219 RemoveBuilder = parent.TypeBuilder.DefineMethod (
3220 remove_name, m_attr, null, parameters);
3221 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3222 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3225 // This looks like dead code
3227 //if (parent.Pending != null)
3228 // parent.Pending.IsInterfaceMethod (null, remove_name, null, parameters, false);
3231 // HACK because System.Reflection.Emit is lame
3234 if (!TypeManager.RegisterMethod (RemoveBuilder, ip, parameters)) {
3235 Report.Error (111, Location,
3236 "Class `" + parent.Name + "' already contains a definition with the " +
3237 "same return value and parameter types for the " +
3238 "'remove' method of event `" + Name + "'");
3242 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3243 Report.Error (111, Location,
3244 "Class `" + parent.Name +
3245 "' already contains a definition for the event `" +
3253 void EmitDefaultMethod (EmitContext ec, bool is_add)
3255 ILGenerator ig = ec.ig;
3256 MethodInfo method = null;
3259 method = TypeManager.delegate_combine_delegate_delegate;
3261 method = TypeManager.delegate_remove_delegate_delegate;
3263 ig.Emit (OpCodes.Ldarg_0);
3264 ig.Emit (OpCodes.Ldarg_0);
3265 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3266 ig.Emit (OpCodes.Ldarg_1);
3267 ig.Emit (OpCodes.Call, method);
3268 ig.Emit (OpCodes.Castclass, EventType);
3269 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3270 ig.Emit (OpCodes.Ret);
3273 public void Emit (TypeContainer tc)
3278 ig = AddBuilder.GetILGenerator ();
3279 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3282 Attribute.ApplyAttributes (ec, AddBuilder, Add, Add.OptAttributes, Location);
3283 ec.EmitTopBlock (Add.Block, Location);
3285 EmitDefaultMethod (ec, true);
3287 ig = RemoveBuilder.GetILGenerator ();
3288 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3290 if (Remove != null) {
3291 Attribute.ApplyAttributes (ec, RemoveBuilder, Remove, Remove.OptAttributes, Location);
3292 ec.EmitTopBlock (Remove.Block, Location);
3294 EmitDefaultMethod (ec, false);
3296 ec = new EmitContext (tc, Location, null, EventType, ModFlags);
3297 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3304 // FIXME: This does not handle:
3306 // int INTERFACENAME [ args ]
3311 // int this [ args ]
3313 public class Indexer : MemberCore {
3315 const int AllowedModifiers =
3318 Modifiers.PROTECTED |
3319 Modifiers.INTERNAL |
3323 Modifiers.OVERRIDE |
3328 public readonly string Type;
3329 public readonly string InterfaceType;
3330 public readonly Parameters FormalParameters;
3331 public readonly Accessor Get, Set;
3332 public Attributes OptAttributes;
3333 public MethodBuilder GetBuilder;
3334 public MethodBuilder SetBuilder;
3335 public PropertyBuilder PropertyBuilder;
3336 public Type IndexerType;
3337 public string IndexerName;
3341 public Indexer (string type, string int_type, int flags, Parameters parms,
3342 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
3347 InterfaceType = int_type;
3348 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE, loc);
3349 FormalParameters = parms;
3352 OptAttributes = attrs;
3355 bool DefineMethod (TypeContainer parent, Type explicit_iface_type,
3356 Type ret_type, string name,
3357 Type [] parameters, MethodAttributes attr, bool is_get)
3359 MethodInfo implementing = null;
3360 bool is_implementation;
3362 if (parent.Pending != null){
3363 implementing = parent.Pending.IsInterfaceMethod (
3364 explicit_iface_type, name, ret_type, parameters);
3366 if (explicit_iface_type != null && implementing == null){
3367 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (Location, "this");
3372 is_implementation = implementing != null;
3375 // Setting null inside this block will trigger a more
3376 // verbose error reporting for missing interface implementations
3378 // The "candidate" function has been flagged already
3379 // but it wont get cleared
3381 if (implementing != null){
3382 if (explicit_iface_type == null){
3384 // We already catch different accessibility settings
3385 // so we just need to check that we are not private
3387 if ((ModFlags & Modifiers.PRIVATE) != 0)
3388 implementing = null;
3391 // Static is not allowed
3393 if ((ModFlags & Modifiers.STATIC) != 0)
3394 implementing = null;
3396 if((ModFlags&(Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3397 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3398 implementing = null;
3402 if (implementing != null){
3404 // When implementing interface methods, set NewSlot.
3406 if (implementing.DeclaringType.IsInterface)
3407 attr |= MethodAttributes.NewSlot;
3410 MethodAttributes.Virtual |
3411 MethodAttributes.HideBySig;
3414 // clear the pending implementing flag
3416 parent.Pending.ImplementMethod (
3417 explicit_iface_type, name, ret_type, parameters, true);
3421 // If this is not an explicit interface implementation,
3422 // clear implementing, as it is only used for explicit
3423 // interface implementation
3425 if (InterfaceType == null)
3426 implementing = null;
3429 if (explicit_iface_type == null)
3432 prefix = explicit_iface_type.FullName + ".";
3435 string meth_name = prefix + "get_" + IndexerName;
3437 GetBuilder = parent.TypeBuilder.DefineMethod (
3438 meth_name, attr, IndexerType, parameters);
3440 if (implementing != null)
3441 parent.TypeBuilder.DefineMethodOverride (
3442 GetBuilder, implementing);
3444 string meth_name = prefix + "set_" + IndexerName;
3446 SetBuilder = parent.TypeBuilder.DefineMethod (
3447 meth_name, attr, null, parameters);
3448 if (implementing != null)
3449 parent.TypeBuilder.DefineMethodOverride (
3450 SetBuilder, implementing);
3453 return is_implementation;
3456 public override bool Define (TypeContainer parent)
3458 PropertyAttributes prop_attr =
3459 PropertyAttributes.RTSpecialName |
3460 PropertyAttributes.SpecialName;
3463 IndexerType = RootContext.LookupType (parent, Type, false, Location);
3464 Type [] parameters = FormalParameters.GetParameterInfo (parent);
3466 // Check if the return type and arguments were correct
3467 if (IndexerType == null || parameters == null)
3470 if (!parent.MethodModifiersValid (ModFlags, InterfaceType == null ?
3471 "this" : InterfaceType, Location))
3475 // verify accessibility and unsafe pointers
3477 if (!TypeContainer.AsAccessible (IndexerType, ModFlags))
3480 if (IndexerType.IsPointer && !UnsafeOK (parent))
3483 foreach (Type partype in parameters){
3484 if (!TypeContainer.AsAccessible (partype, ModFlags))
3486 if (partype.IsPointer && !UnsafeOK (parent))
3493 Type explicit_iface_type = null;
3495 if (InterfaceType != null){
3496 explicit_iface_type = RootContext.LookupType (parent, InterfaceType, false, Location);
3497 if (explicit_iface_type == null)
3500 if (!parent.VerifyImplements (explicit_iface_type, "this", "this", Location))
3504 ec = new EmitContext (parent, Location, null, IndexerType, ModFlags);
3506 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
3507 if (IndexerName == null)
3508 IndexerName = "Item";
3510 MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
3512 bool is_implementing = false;
3515 is_implementing = DefineMethod (
3516 parent, explicit_iface_type, IndexerType, "get_" + IndexerName,
3517 parameters, attr, true);
3518 InternalParameters pi = new InternalParameters (parent, FormalParameters);
3519 if (!TypeManager.RegisterMethod (GetBuilder, pi, parameters)) {
3520 Report.Error (111, Location,
3521 "Class `" + parent.Name +
3522 "' already contains a definition with the " +
3523 "same return value and parameter types for the " +
3530 int top = parameters.Length;
3531 Type [] set_pars = new Type [top + 1];
3532 parameters.CopyTo (set_pars, 0);
3533 set_pars [top] = IndexerType;
3535 Parameter [] fixed_parms = FormalParameters.FixedParameters;
3537 if (fixed_parms == null){
3538 throw new Exception ("We currently do not support only array arguments in an indexer");
3539 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3540 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3542 // Here is the problem: the `value' parameter has
3543 // to come *after* the array parameter in the declaration
3545 // X (object [] x, Type value)
3548 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3549 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3553 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
3556 fixed_parms.CopyTo (tmp, 0);
3557 tmp [fixed_parms.Length] = new Parameter (
3558 Type, "value", Parameter.Modifier.NONE, null);
3560 Parameters set_formal_params = new Parameters (tmp, null, Location);
3562 is_implementing = DefineMethod (
3563 parent, explicit_iface_type, TypeManager.void_type,
3564 "set_" + IndexerName, set_pars, attr, false);
3566 InternalParameters ip = new InternalParameters (parent, set_formal_params);
3568 if (!TypeManager.RegisterMethod (SetBuilder, ip, set_pars)) {
3571 "Class `" + parent.Name + "' already contains a " +
3572 "definition with the " +
3573 "same return value and parameter types for the " +
3580 // Now name the parameters
3582 Parameter [] p = FormalParameters.FixedParameters;
3586 for (i = 0; i < p.Length; ++i) {
3588 GetBuilder.DefineParameter (
3589 i + 1, p [i].Attributes, p [i].Name);
3592 SetBuilder.DefineParameter (
3593 i + 1, p [i].Attributes, p [i].Name);
3597 SetBuilder.DefineParameter (
3598 i + 1, ParameterAttributes.None, "value");
3600 if (i != parameters.Length) {
3601 Parameter array_param = FormalParameters.ArrayParameter;
3602 SetBuilder.DefineParameter (i + 1, array_param.Attributes,
3609 // Only define the PropertyBuilder if we are not implementing
3610 // an interface property.
3612 if (!is_implementing){
3613 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3614 IndexerName, prop_attr, IndexerType, parameters);
3616 if (GetBuilder != null)
3617 PropertyBuilder.SetGetMethod (GetBuilder);
3619 if (SetBuilder != null)
3620 PropertyBuilder.SetSetMethod (SetBuilder);
3622 TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
3628 public void Emit (TypeContainer tc)
3633 // The PropertyBuilder can be null for explicit implementations, in that
3634 // case, we do not actually emit the ".property", so there is nowhere to
3635 // put the attribute
3637 if (PropertyBuilder != null)
3638 Attribute.ApplyAttributes (
3639 ec, PropertyBuilder, this, OptAttributes, Location);
3641 Attribute.ApplyAttributes (ec, GetBuilder, Get, Get.OptAttributes, Location);
3643 Attribute.ApplyAttributes (ec, SetBuilder, Set, Set.OptAttributes, Location);
3645 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3649 ig = GetBuilder.GetILGenerator ();
3650 ec = new EmitContext (tc, Location, ig, IndexerType, ModFlags);
3652 ec.EmitTopBlock (Get.Block, Location);
3656 ig = SetBuilder.GetILGenerator ();
3657 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3659 ec.EmitTopBlock (Set.Block, Location);
3664 public class Operator : MemberCore {
3666 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);
3888 // abstract or extern methods have no bodies
3890 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3893 OperatorMethod.Block = Block;
3894 OperatorMethod.Emit (parent);
3899 // This is used to compare method signatures
3901 struct MethodSignature {
3903 public Type RetType;
3904 public Type [] Parameters;
3907 /// This delegate is used to extract methods which have the
3908 /// same signature as the argument
3910 public static MemberFilter method_signature_filter;
3913 /// This delegate is used to extract inheritable methods which
3914 /// have the same signature as the argument. By inheritable,
3915 /// this means that we have permissions to override the method
3916 /// from the current assembly and class
3918 public static MemberFilter inheritable_method_signature_filter;
3920 static MethodSignature ()
3922 method_signature_filter = new MemberFilter (MemberSignatureCompare);
3923 inheritable_method_signature_filter = new MemberFilter (
3924 InheritableMemberSignatureCompare);
3927 public MethodSignature (string name, Type ret_type, Type [] parameters)
3932 if (parameters == null)
3933 Parameters = TypeManager.NoTypes;
3935 Parameters = parameters;
3938 public override int GetHashCode ()
3940 return Name.GetHashCode ();
3943 public override bool Equals (Object o)
3945 MethodSignature other = (MethodSignature) o;
3947 if (other.Name != Name)
3950 if (other.RetType != RetType)
3953 if (Parameters == null){
3954 if (other.Parameters == null)
3959 if (other.Parameters == null)
3962 int c = Parameters.Length;
3963 if (other.Parameters.Length != c)
3966 for (int i = 0; i < c; i++)
3967 if (other.Parameters [i] != Parameters [i])
3973 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
3977 if (! (m is MethodInfo))
3980 MethodSignature sig = (MethodSignature) filter_criteria;
3982 if (m.Name != sig.Name)
3985 mi = (MethodInfo) m;
3988 // we use sig.RetType == null to mean `do not check the
3989 // method return value.
3991 if (sig.RetType != null)
3992 if (mi.ReturnType != sig.RetType)
3995 Type [] args = TypeManager.GetArgumentTypes (mi);
3996 Type [] sigp = sig.Parameters;
3998 if (args.Length != sigp.Length)
4001 for (int i = args.Length; i > 0; ){
4003 if (args [i] != sigp [i])
4010 // This filter should be used when we are requesting methods that
4011 // we want to override.
4013 // This makes a number of assumptions, for example
4014 // that the methods being extracted are of a parent
4015 // class (this means we know implicitly that we are
4016 // being called to find out about members by a derived
4019 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4021 if (MemberSignatureCompare (m, filter_criteria)){
4022 MethodInfo mi = (MethodInfo) m;
4023 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4025 // If only accessible to the current class.
4026 if (prot == MethodAttributes.Private)
4029 // If only accessible to the defining assembly or
4030 if (prot == MethodAttributes.FamANDAssem ||
4031 prot == MethodAttributes.Assembly){
4032 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4038 // Anything else (FamOrAssembly and Public) is fine