2 // class.cs: Class and Struct handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@gnome.org)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
14 using System.Collections;
15 using System.Reflection;
16 using System.Reflection.Emit;
17 using System.Runtime.CompilerServices;
18 using System.Diagnostics.SymbolStore;
20 namespace Mono.CSharp {
23 /// This is the base class for structs and classes.
25 public class TypeContainer : DeclSpace {
26 // Holds a list of classes and structures
29 // Holds the list of properties
32 // Holds the list of enumerations
35 // Holds the list of delegates
38 // Holds the list of constructors
39 ArrayList instance_constructors;
41 // Holds the list of fields
44 // Holds a list of fields that have initializers
45 ArrayList initialized_fields;
47 // Holds a list of static fields that have initializers
48 ArrayList initialized_static_fields;
50 // Holds the list of constants
56 // Holds order in which interfaces must be closed
57 ArrayList interface_order;
68 // Holds the operators
71 // The emit context for toplevel objects.
75 // Pointers to the default constructor and the default static constructor
77 Constructor default_constructor;
78 Constructor default_static_constructor;
81 // Whether we have seen a static constructor for this class or not
83 bool have_static_constructor = false;
86 // Whether we have at least one non-static field
88 bool have_nonstatic_fields = false;
91 // This one is computed after we can distinguish interfaces
92 // from classes from the arraylist `type_bases'
94 string base_class_name;
98 // Attributes for this type
99 protected Attributes attributes;
101 // Information in the case we are an attribute type
103 public AttributeTargets Targets = AttributeTargets.All;
104 public bool AllowMultiple = false;
105 public bool Inherited;
107 // The interfaces we implement.
111 // The indexer name for this class
113 public string IndexerName;
115 public TypeContainer (TypeContainer parent, string name, Location l)
116 : base (parent, name, l)
119 types = new ArrayList ();
126 base_class_name = null;
128 //Console.WriteLine ("New class " + name + " inside " + n);
131 public AdditionResult AddConstant (Const constant)
134 string name = constant.Name;
136 if ((res = IsValid (name)) != AdditionResult.Success)
139 if (constants == null)
140 constants = new ArrayList ();
142 constants.Add (constant);
143 DefineName (name, constant);
145 return AdditionResult.Success;
148 public AdditionResult AddEnum (Mono.CSharp.Enum e)
151 string name = e.Name;
153 if ((res = IsValid (name)) != AdditionResult.Success)
157 enums = new ArrayList ();
160 DefineName (name, e);
162 return AdditionResult.Success;
165 public AdditionResult AddClass (Class c)
168 string name = c.Name;
171 if ((res = IsValid (name)) != AdditionResult.Success)
174 DefineName (name, c);
177 return AdditionResult.Success;
180 public AdditionResult AddStruct (Struct s)
183 string name = s.Name;
185 if ((res = IsValid (name)) != AdditionResult.Success)
188 DefineName (name, s);
191 return AdditionResult.Success;
194 public AdditionResult AddDelegate (Delegate d)
197 string name = d.Name;
199 if ((res = IsValid (name)) != AdditionResult.Success)
202 if (delegates == null)
203 delegates = new ArrayList ();
205 DefineName (name, d);
208 return AdditionResult.Success;
211 public AdditionResult AddMethod (Method method)
213 string name = method.Name;
214 Object value = defined_names [name];
216 if (value != null && (!(value is Method)))
217 return AdditionResult.NameExists;
219 if (name == Basename)
220 return AdditionResult.EnclosingClash;
223 methods = new ArrayList ();
225 if (method.Name.IndexOf (".") != -1)
226 methods.Insert (0, method);
228 methods.Add (method);
231 DefineName (name, method);
233 return AdditionResult.Success;
236 public AdditionResult AddConstructor (Constructor c)
238 if (c.Name != Basename)
239 return AdditionResult.NotAConstructor;
241 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
244 have_static_constructor = true;
245 if (default_static_constructor != null){
246 Console.WriteLine ("I have a static constructor already");
247 Console.WriteLine (" " + default_static_constructor);
248 return AdditionResult.MethodExists;
251 default_static_constructor = c;
254 if (default_constructor != null)
255 return AdditionResult.MethodExists;
256 default_constructor = c;
259 if (instance_constructors == null)
260 instance_constructors = new ArrayList ();
262 instance_constructors.Add (c);
265 return AdditionResult.Success;
268 public AdditionResult AddInterface (Interface iface)
271 string name = iface.Name;
273 if ((res = IsValid (name)) != AdditionResult.Success)
276 if (interfaces == null)
277 interfaces = new ArrayList ();
278 interfaces.Add (iface);
279 DefineName (name, iface);
281 return AdditionResult.Success;
284 public AdditionResult AddField (Field field)
287 string name = field.Name;
289 if ((res = IsValid (name)) != AdditionResult.Success)
293 fields = new ArrayList ();
297 if (field.Initializer != null){
298 if ((field.ModFlags & Modifiers.STATIC) != 0){
299 if (initialized_static_fields == null)
300 initialized_static_fields = new ArrayList ();
302 initialized_static_fields.Add (field);
305 // We have not seen a static constructor,
306 // but we will provide static initialization of fields
308 have_static_constructor = true;
310 if (initialized_fields == null)
311 initialized_fields = new ArrayList ();
313 initialized_fields.Add (field);
317 if ((field.ModFlags & Modifiers.STATIC) == 0)
318 have_nonstatic_fields = true;
320 DefineName (name, field);
321 return AdditionResult.Success;
324 public AdditionResult AddProperty (Property prop)
327 string name = prop.Name;
329 if ((res = IsValid (name)) != AdditionResult.Success)
332 if (properties == null)
333 properties = new ArrayList ();
335 if (prop.Name.IndexOf (".") != -1)
336 properties.Insert (0, prop);
338 properties.Add (prop);
339 DefineName (name, prop);
341 return AdditionResult.Success;
344 public AdditionResult AddEvent (Event e)
347 string name = e.Name;
349 if ((res = IsValid (name)) != AdditionResult.Success)
353 events = new ArrayList ();
356 DefineName (name, e);
358 return AdditionResult.Success;
361 public AdditionResult AddIndexer (Indexer i)
363 if (indexers == null)
364 indexers = new ArrayList ();
366 if (i.InterfaceType != null)
367 indexers.Insert (0, i);
371 return AdditionResult.Success;
374 public AdditionResult AddOperator (Operator op)
376 if (operators == null)
377 operators = new ArrayList ();
381 return AdditionResult.Success;
384 public void RegisterOrder (Interface iface)
386 if (interface_order == null)
387 interface_order = new ArrayList ();
389 interface_order.Add (iface);
392 public ArrayList Types {
398 public ArrayList Methods {
404 public ArrayList Constants {
410 public ArrayList Interfaces {
418 return base_class_name;
422 public ArrayList Bases {
432 public ArrayList Fields {
442 public ArrayList InstanceConstructors {
444 return instance_constructors;
448 public ArrayList Properties {
454 public ArrayList Events {
460 public ArrayList Enums {
466 public ArrayList Indexers {
472 public ArrayList Operators {
478 public ArrayList Delegates {
484 public Attributes OptAttributes {
490 public bool HaveStaticConstructor {
492 return have_static_constructor;
496 public virtual TypeAttributes TypeAttr {
498 return Modifiers.TypeAttr (ModFlags, this);
503 // Emits the instance field initializers
505 public bool EmitFieldInitializers (EmitContext ec)
508 ILGenerator ig = ec.ig;
509 Expression instance_expr;
512 fields = initialized_static_fields;
513 instance_expr = null;
515 fields = initialized_fields;
516 instance_expr = new This (Location.Null).Resolve (ec);
522 foreach (Field f in fields){
523 Object init = f.Initializer;
526 if (init is Expression)
527 e = (Expression) init;
529 e = new ArrayCreation (f.Type, "", (ArrayList)init, f.Location);
532 Location l = f.Location;
533 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
534 fe.InstanceExpression = instance_expr;
535 Expression a = new Assign (fe, e, l);
541 if (a is ExpressionStatement)
542 ((ExpressionStatement) a).EmitStatement (ec);
544 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
552 // Defines the default constructors
554 void DefineDefaultConstructor (bool is_static)
559 c = new Constructor (Basename, Parameters.EmptyReadOnlyParameters,
560 new ConstructorBaseInitializer (null, new Location (-1)),
564 mods = Modifiers.STATIC;
570 c.Block = new Block (null);
574 public void ReportStructInitializedInstanceError ()
576 string n = TypeBuilder.FullName;
578 foreach (Field f in initialized_fields){
581 "`" + n + "." + f.Name + "': can not have " +
582 "instance field initializers in structs");
587 /// The pending methods that need to be implemented (interfaces or abstract methods)
589 public PendingImplementation Pending;
592 /// This function computes the Base class and also the
593 /// list of interfaces that the class or struct @c implements.
595 /// The return value is an array (might be null) of
596 /// interfaces implemented (as Types).
598 /// The @parent argument is set to the parent object or null
599 /// if this is `System.Object'.
601 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
603 ArrayList bases = Bases;
612 parent = TypeManager.value_type;
616 if (RootContext.StdLib)
617 parent = TypeManager.object_type;
618 else if (Name != "System.Object")
619 parent = TypeManager.object_type;
622 // If we are compiling our runtime,
623 // and we are defining ValueType, then our
624 // parent is `System.Object'.
626 if (!RootContext.StdLib && Name == "System.ValueType")
627 parent = TypeManager.object_type;
634 // Bases should be null if there are no bases at all
639 Expression name = (Expression) bases [0];
640 name = ResolveTypeExpr (name, false, Location);
647 Type first = name.Type;
653 parent = TypeManager.object_type;
657 if (!AsAccessible (parent, ModFlags))
658 Report.Error (60, Location,
659 "Inconsistent accessibility: base class `" +
660 TypeManager.CSharpName (parent) + "' is less " +
661 "accessible than class `" +
668 Type [] ifaces = new Type [count-start];
670 for (i = start, j = 0; i < count; i++, j++){
671 Expression name = (Expression) bases [i];
672 Expression resolved = ResolveTypeExpr (name, false, Location);
673 bases [i] = resolved;
674 Type t = resolved.Type;
681 if (is_class == false && !t.IsInterface){
682 Report.Error (527, "In Struct `" + Name + "', type `"+
683 name +"' is not an interface");
692 detail = " (a class can not inherit from a struct/enum)";
694 Report.Error (509, "class `"+ Name +
695 "': Cannot inherit from sealed class `"+
696 bases [i]+"'"+detail);
703 Report.Error (527, "In Class `" + Name + "', type `"+
704 name+"' is not an interface");
710 for (int x = 0; x < j; x++) {
711 if (t == ifaces [x]) {
712 Report.Error (528, "`" + name + "' is already listed in interface list");
721 return TypeManager.ExpandInterfaces (ifaces);
725 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
727 public override TypeBuilder DefineType ()
733 if (TypeBuilder != null)
746 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
748 ifaces = GetClassBases (is_class, out parent, out error);
753 if (is_class && parent != null){
754 if (parent == TypeManager.enum_type ||
755 (parent == TypeManager.value_type && RootContext.StdLib) ||
756 parent == TypeManager.delegate_type ||
757 parent == TypeManager.array_type){
759 644, Location, "`" + Name + "' cannot inherit from " +
760 "special class `" + TypeManager.CSharpName (parent) + "'");
765 if (!is_class && TypeManager.value_type == null)
766 throw new Exception ();
768 TypeAttributes type_attributes = TypeAttr;
770 // if (parent_builder is ModuleBuilder) {
772 ModuleBuilder builder = CodeGen.ModuleBuilder;
775 // Structs with no fields need to have a ".size 1"
779 if (!is_class && !have_nonstatic_fields)
780 TypeBuilder = builder.DefineType (Name,
783 PackingSize.Unspecified, 1);
786 // classes or structs with fields
788 TypeBuilder = builder.DefineType (Name,
793 TypeBuilder builder = Parent.TypeBuilder;
796 // Structs with no fields need to have a ".size 1"
799 if (!is_class && !have_nonstatic_fields)
800 TypeBuilder = builder.DefineNestedType (Basename,
803 PackingSize.Unspecified);
806 // classes or structs with fields
808 TypeBuilder = builder.DefineNestedType (Basename,
815 // add interfaces that were not added at type creation (weird API issue)
816 if (!is_class && !have_nonstatic_fields && (ifaces != null)) {
817 foreach (Type i in ifaces)
818 TypeBuilder.AddInterfaceImplementation (i);
822 // Finish the setup for the EmitContext
824 ec.ContainerType = TypeBuilder;
826 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
828 if ((parent != null) &&
829 (parent == TypeManager.attribute_type ||
830 parent.IsSubclassOf (TypeManager.attribute_type))) {
831 RootContext.RegisterAttribute (this);
832 TypeManager.RegisterAttrType (TypeBuilder, this);
834 RootContext.RegisterOrder (this);
836 if (Interfaces != null) {
837 foreach (Interface iface in Interfaces)
842 foreach (TypeContainer tc in Types)
846 if (Delegates != null) {
847 foreach (Delegate d in Delegates)
852 foreach (Enum en in Enums)
862 /// Defines the MemberCore objects that are in the `list' Arraylist
864 /// The `defined_names' array contains a list of members defined in
867 static ArrayList remove_list = new ArrayList ();
868 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
872 remove_list.Clear ();
874 foreach (MemberCore mc in list){
875 if (!mc.Define (this)){
876 remove_list.Add (mc);
880 if (defined_names == null)
883 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
885 if (RootContext.WarningLevel >= 4){
886 if ((mc.ModFlags & Modifiers.NEW) != 0)
887 Warning_KewywordNewNotRequired (mc.Location, mc);
892 MemberInfo match = defined_names [idx];
894 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
898 // If we are both methods, let the method resolution emit warnings
900 if (match is MethodBase && mc is MethodCore)
903 if ((mc.ModFlags & Modifiers.NEW) == 0)
904 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
907 foreach (object o in remove_list)
910 remove_list.Clear ();
914 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
915 // class is consisten. Either it is `Item' or it is the name defined by all the
916 // indexers with the `IndexerName' attribute.
918 // Turns out that the IndexerNameAttribute is applied to each indexer,
919 // but it is never emitted, instead a DefaultName attribute is attached
922 void DefineIndexers ()
924 string class_indexer_name = null;
926 foreach (Indexer i in Indexers){
931 name = i.IndexerName;
933 if (i.InterfaceType != null)
936 if (class_indexer_name == null){
937 class_indexer_name = name;
941 if (name == class_indexer_name)
945 668, "Two indexers have different names, " +
946 " you should use the same name for all your indexers");
948 if (class_indexer_name == null)
949 class_indexer_name = "Item";
950 IndexerName = class_indexer_name;
953 static void Report1530 (Location loc)
955 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
959 /// Populates our TypeBuilder with fields and methods
961 public override bool Define (TypeContainer parent)
963 MemberInfo [] defined_names = null;
965 if (interface_order != null){
966 foreach (Interface iface in interface_order)
967 if ((iface.ModFlags & Modifiers.NEW) == 0)
970 Report1530 (iface.Location);
973 if (RootContext.WarningLevel > 1){
977 // This code throws an exception in the comparer
978 // I guess the string is not an object?
980 ptype = TypeBuilder.BaseType;
982 defined_names = FindMembers (
983 ptype, MemberTypes.All & ~MemberTypes.Constructor,
984 BindingFlags.Public | BindingFlags.Instance |
985 BindingFlags.Static, null, null);
987 Array.Sort (defined_names, mif_compare);
991 if (constants != null)
992 DefineMembers (constants, defined_names);
995 DefineMembers (fields, defined_names);
998 if (instance_constructors == null){
999 if (default_constructor == null)
1000 DefineDefaultConstructor (false);
1003 if (initialized_static_fields != null &&
1004 default_static_constructor == null)
1005 DefineDefaultConstructor (true);
1008 if (this is Struct){
1010 // Structs can not have initialized instance
1013 if (initialized_static_fields != null &&
1014 default_static_constructor == null)
1015 DefineDefaultConstructor (true);
1017 if (initialized_fields != null)
1018 ReportStructInitializedInstanceError ();
1021 Pending = PendingImplementation.GetPendingImplementations (this);
1024 // Constructors are not in the defined_names array
1026 if (instance_constructors != null)
1027 DefineMembers (instance_constructors, null);
1029 if (default_static_constructor != null)
1030 default_static_constructor.Define (this);
1032 if (methods != null)
1033 DefineMembers (methods, defined_names);
1035 if (properties != null)
1036 DefineMembers (properties, defined_names);
1039 DefineMembers (events, defined_names);
1041 if (indexers != null) {
1044 IndexerName = "Item";
1046 if (operators != null)
1047 DefineMembers (operators, null);
1050 DefineMembers (enums, defined_names);
1052 if (delegates != null)
1053 DefineMembers (delegates, defined_names);
1059 /// This function is based by a delegate to the FindMembers routine
1061 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1067 /// This filter is used by FindMembers, and we just keep
1068 /// a global for the filter to `AlwaysAccept'
1070 static MemberFilter accepting_filter;
1074 /// A member comparission method based on name only
1076 static IComparer mif_compare;
1078 static TypeContainer ()
1080 accepting_filter = new MemberFilter (AlwaysAccept);
1081 mif_compare = new MemberInfoCompare ();
1085 /// This method returns the members of this type just like Type.FindMembers would
1086 /// Only, we need to use this for types which are _being_ defined because MS'
1087 /// implementation can't take care of that.
1090 // FIXME: return an empty static array instead of null, that cleans up
1091 // some code and is consistent with some coding conventions I just found
1095 // Notice that in various cases we check if our field is non-null,
1096 // something that would normally mean that there was a bug elsewhere.
1098 // The problem happens while we are defining p-invoke methods, as those
1099 // will trigger a FindMembers, but this happens before things are defined
1101 // Since the whole process is a no-op, it is fine to check for null here.
1103 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
1104 MemberFilter filter, object criteria)
1106 ArrayList members = new ArrayList ();
1107 bool priv = (bf & BindingFlags.NonPublic) != 0;
1110 filter = accepting_filter;
1112 if ((mt & MemberTypes.Field) != 0) {
1113 if (fields != null) {
1114 foreach (Field f in fields) {
1115 if ((f.ModFlags & Modifiers.PRIVATE) != 0)
1119 FieldBuilder fb = f.FieldBuilder;
1120 if (fb != null && filter (fb, criteria) == true)
1125 if (constants != null) {
1126 foreach (Const con in constants) {
1127 if ((con.ModFlags & Modifiers.PRIVATE) != 0)
1131 FieldBuilder fb = con.FieldBuilder;
1132 if (fb != null && filter (fb, criteria) == true)
1138 if ((mt & MemberTypes.Method) != 0) {
1139 if (methods != null) {
1140 foreach (Method m in methods) {
1141 if ((m.ModFlags & Modifiers.PRIVATE) != 0)
1145 MethodBuilder mb = m.MethodBuilder;
1147 if (mb != null && filter (mb, criteria) == true)
1152 if (operators != null){
1153 foreach (Operator o in operators) {
1154 if ((o.ModFlags & Modifiers.PRIVATE) != 0)
1158 MethodBuilder ob = o.OperatorMethodBuilder;
1159 if (ob != null && filter (ob, criteria) == true)
1164 if (properties != null){
1165 foreach (Property p in properties){
1166 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1173 if (b != null && filter (b, criteria) == true)
1177 if (b != null && filter (b, criteria) == true)
1183 if ((mt & MemberTypes.Event) != 0) {
1185 foreach (Event e in events) {
1186 if ((e.ModFlags & Modifiers.PRIVATE) != 0)
1190 MemberInfo eb = e.EventBuilder;
1191 if (eb != null && filter (eb, criteria) == true)
1192 members.Add (e.EventBuilder);
1196 if ((mt & MemberTypes.Property) != 0){
1197 if (properties != null)
1198 foreach (Property p in properties) {
1199 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1203 MemberInfo pb = p.PropertyBuilder;
1204 if (pb != null && filter (pb, criteria) == true) {
1205 members.Add (p.PropertyBuilder);
1209 if (indexers != null)
1210 foreach (Indexer ix in indexers) {
1211 if ((ix.ModFlags & Modifiers.PRIVATE) != 0)
1215 MemberInfo ib = ix.PropertyBuilder;
1216 if (ib != null && filter (ib, criteria) == true) {
1217 members.Add (ix.PropertyBuilder);
1222 if ((mt & MemberTypes.NestedType) != 0) {
1224 foreach (TypeContainer t in types) {
1225 TypeBuilder tb = t.TypeBuilder;
1227 if (tb != null && (filter (tb, criteria) == true))
1233 foreach (Enum en in enums){
1234 TypeBuilder tb = en.TypeBuilder;
1236 if (tb != null && (filter (tb, criteria) == true))
1241 if (delegates != null){
1242 foreach (Delegate d in delegates){
1243 TypeBuilder tb = d.TypeBuilder;
1245 if (tb != null && (filter (tb, criteria) == true))
1251 if ((mt & MemberTypes.Constructor) != 0){
1252 if (instance_constructors != null){
1253 foreach (Constructor c in instance_constructors){
1254 ConstructorBuilder cb = c.ConstructorBuilder;
1257 if (filter (cb, criteria) == true)
1262 if (default_static_constructor != null){
1263 ConstructorBuilder cb =
1264 default_static_constructor.ConstructorBuilder;
1267 if (filter (cb, criteria) == true)
1273 // Lookup members in parent if requested.
1275 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1278 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1280 members.AddRange (mi);
1283 int count = members.Count;
1285 MemberInfo [] mi = new MemberInfo [count];
1286 members.CopyTo (mi);
1295 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1296 MemberFilter filter, object criteria)
1298 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1301 return tc.FindMembers (mt, bf, filter, criteria);
1303 return t.FindMembers (mt, bf, filter, criteria);
1307 // FindMethods will look for methods not only in the type `t', but in
1308 // any interfaces implemented by the type.
1310 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1311 MemberFilter filter, object criteria)
1317 /// Emits the values for the constants
1319 public void EmitConstants ()
1321 if (constants != null)
1322 foreach (Const con in constants)
1323 con.EmitConstant (this);
1328 /// Emits the code, this step is performed after all
1329 /// the types, enumerations, constructors
1333 if (instance_constructors != null)
1334 foreach (Constructor c in instance_constructors)
1337 if (default_static_constructor != null)
1338 default_static_constructor.Emit (this);
1340 if (methods != null)
1341 foreach (Method m in methods)
1344 if (operators != null)
1345 foreach (Operator o in operators)
1348 if (properties != null)
1349 foreach (Property p in properties)
1352 if (indexers != null){
1353 foreach (Indexer ix in indexers)
1356 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1357 this, IndexerName, ModFlags, Location);
1358 TypeBuilder.SetCustomAttribute (cb);
1362 foreach (Field f in fields)
1365 if (events != null){
1366 foreach (Event e in Events)
1370 if (Pending != null)
1371 if (Pending.VerifyPendingMethods ())
1374 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1377 // Check for internal or private fields that were never assigned
1379 if (fields != null && RootContext.WarningLevel >= 3) {
1380 foreach (Field f in fields) {
1381 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1386 169, f.Location, "Private field " +
1387 MakeName (f.Name) + " is never used");
1392 // Only report 649 on level 4
1394 if (RootContext.WarningLevel < 4)
1397 if ((f.status & Field.Status.ASSIGNED) != 0)
1402 "Field " + MakeName (f.Name) + " is never assigned " +
1403 " to and will always have its default value");
1407 // if (types != null)
1408 // foreach (TypeContainer tc in types)
1412 public override void CloseType ()
1417 TypeBuilder.CreateType ();
1419 } catch (TypeLoadException){
1421 // This is fine, the code still created the type
1423 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1424 // Console.WriteLine (e.Message);
1426 Console.WriteLine ("In type: " + Name);
1431 foreach (Enum en in Enums)
1434 if (interface_order != null){
1435 foreach (Interface iface in interface_order)
1440 foreach (TypeContainer tc in Types)
1444 foreach (TypeContainer tc in Types)
1445 if (!(tc is Struct))
1449 if (Delegates != null)
1450 foreach (Delegate d in Delegates)
1454 public string MakeName (string n)
1456 return "`" + Name + "." + n + "'";
1459 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1462 108, l, "The keyword new is required on " +
1463 MakeName (mi.Name) + " because it hides `" +
1464 mi.ReflectedType.Name + "." + mi.Name + "'");
1467 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1470 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1471 "inherited member, the keyword new is not required");
1474 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1480 // Performs the validation on a Method's modifiers (properties have
1481 // the same properties).
1483 public bool MethodModifiersValid (int flags, string n, Location loc)
1485 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1486 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1487 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1489 string name = MakeName (n);
1492 // At most one of static, virtual or override
1494 if ((flags & Modifiers.STATIC) != 0){
1495 if ((flags & vao) != 0){
1497 112, loc, "static method " + name + "can not be marked " +
1498 "as virtual, abstract or override");
1503 if (this is Struct){
1504 if ((flags & va) != 0){
1505 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1510 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1513 " marked as override cannot be marked as new or virtual");
1518 // If the declaration includes the abstract modifier, then the
1519 // declaration does not include static, virtual or extern
1521 if ((flags & Modifiers.ABSTRACT) != 0){
1522 if ((flags & Modifiers.EXTERN) != 0){
1524 180, loc, name + " can not be both abstract and extern");
1528 if ((flags & Modifiers.VIRTUAL) != 0){
1530 503, loc, name + " can not be both abstract and virtual");
1534 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1537 " is abstract but its container class is not");
1543 if ((flags & Modifiers.PRIVATE) != 0){
1544 if ((flags & vao) != 0){
1547 " virtual or abstract members can not be private");
1552 if ((flags & Modifiers.SEALED) != 0){
1553 if ((flags & Modifiers.OVERRIDE) == 0){
1556 " cannot be sealed because it is not an override");
1564 // Access level of a type.
1567 ProtectedInternal = 1,
1573 // Check whether `flags' denotes a more restricted access than `level'
1574 // and return the new level.
1575 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1577 AccessLevel old_level = level;
1579 if ((flags & Modifiers.INTERNAL) != 0) {
1580 if ((flags & Modifiers.PROTECTED) != 0) {
1581 if ((int) level < (int) AccessLevel.ProtectedInternal)
1582 level = AccessLevel.ProtectedInternal;
1584 if ((int) level < (int) AccessLevel.Internal)
1585 level = AccessLevel.Internal;
1587 } else if ((flags & Modifiers.PROTECTED) != 0) {
1588 if ((int) level < (int) AccessLevel.Protected)
1589 level = AccessLevel.Protected;
1590 } else if ((flags & Modifiers.PRIVATE) != 0)
1591 level = AccessLevel.Private;
1596 // Return the access level for a new member which is defined in the current
1597 // TypeContainer with access modifiers `flags'.
1598 AccessLevel GetAccessLevel (int flags)
1600 if ((flags & Modifiers.PRIVATE) != 0)
1601 return AccessLevel.Private;
1604 if (!IsTopLevel && (Parent != null))
1605 level = Parent.GetAccessLevel (flags);
1607 level = AccessLevel.Public;
1609 return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1612 // Return the access level for type `t', but don't give more access than `flags'.
1613 static AccessLevel GetAccessLevel (Type t, int flags)
1615 if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1616 return AccessLevel.Private;
1619 if (TypeManager.IsBuiltinType (t))
1620 return AccessLevel.Public;
1621 else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1622 level = GetAccessLevel (t.DeclaringType, flags);
1624 level = CheckAccessLevel (AccessLevel.Public, flags);
1627 if (t.IsNestedPublic)
1630 if (t.IsNestedAssembly || t.IsNotPublic) {
1631 if ((int) level < (int) AccessLevel.Internal)
1632 level = AccessLevel.Internal;
1635 if (t.IsNestedFamily) {
1636 if ((int) level < (int) AccessLevel.Protected)
1637 level = AccessLevel.Protected;
1640 if (t.IsNestedFamORAssem) {
1641 if ((int) level < (int) AccessLevel.ProtectedInternal)
1642 level = AccessLevel.ProtectedInternal;
1649 // Returns true if `parent' is as accessible as the flags `flags'
1650 // given for this member.
1652 public bool AsAccessible (Type parent, int flags)
1654 while (parent.HasElementType)
1655 parent = parent.GetElementType ();
1657 AccessLevel level = GetAccessLevel (flags);
1658 AccessLevel level2 = GetAccessLevel (parent, flags);
1660 return (int) level >= (int) level2;
1663 Hashtable builder_and_args;
1665 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1667 if (builder_and_args == null)
1668 builder_and_args = new Hashtable ();
1673 /// Performs checks for an explicit interface implementation. First it
1674 /// checks whether the `interface_type' is a base inteface implementation.
1675 /// Then it checks whether `name' exists in the interface type.
1677 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1681 if (ifaces != null){
1682 foreach (Type t in ifaces){
1683 if (t == interface_type){
1691 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1698 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1700 Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1704 public class Class : TypeContainer {
1706 // Modifiers allowed in a class declaration
1708 public const int AllowedModifiers =
1711 Modifiers.PROTECTED |
1712 Modifiers.INTERNAL |
1714 Modifiers.ABSTRACT |
1718 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1719 : base (parent, name, l)
1723 if (parent.Parent == null)
1724 accmods = Modifiers.INTERNAL;
1726 accmods = Modifiers.PRIVATE;
1728 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1729 this.attributes = attrs;
1733 // FIXME: How do we deal with the user specifying a different
1736 public override TypeAttributes TypeAttr {
1738 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1743 public class Struct : TypeContainer {
1745 // Modifiers allowed in a struct declaration
1747 public const int AllowedModifiers =
1750 Modifiers.PROTECTED |
1751 Modifiers.INTERNAL |
1755 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1756 : base (parent, name, l)
1760 if (parent.Parent == null)
1761 accmods = Modifiers.INTERNAL;
1763 accmods = Modifiers.PRIVATE;
1765 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1767 this.ModFlags |= Modifiers.SEALED;
1768 this.attributes = attrs;
1773 // FIXME: Allow the user to specify a different set of attributes
1774 // in some cases (Sealed for example is mandatory for a class,
1775 // but what SequentialLayout can be changed
1777 public override TypeAttributes TypeAttr {
1779 return base.TypeAttr |
1780 TypeAttributes.SequentialLayout |
1781 TypeAttributes.Sealed |
1782 TypeAttributes.BeforeFieldInit;
1787 public abstract class MethodCore : MemberBase {
1788 public readonly Parameters Parameters;
1792 // Parameters, cached for semantic analysis.
1794 protected InternalParameters parameter_info;
1795 protected Type [] parameter_types;
1797 public MethodCore (Expression type, int mod, int allowed_mod, string name,
1798 Attributes attrs, Parameters parameters, Location loc)
1799 : base (type, mod, allowed_mod, name, attrs, loc)
1801 Parameters = parameters;
1805 // Returns the System.Type array for the parameters of this method
1807 public Type [] ParameterTypes {
1809 return parameter_types;
1813 public InternalParameters ParameterInfo
1816 return parameter_info;
1820 public Block Block {
1830 protected virtual bool DoDefineParameters (TypeContainer parent)
1832 // Check if arguments were correct
1833 parameter_types = Parameters.GetParameterInfo (parent);
1834 if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
1837 parameter_info = new InternalParameters (parent, Parameters);
1842 public CallingConventions GetCallingConvention (bool is_class)
1844 CallingConventions cc = 0;
1846 cc = Parameters.GetCallingConvention ();
1849 if ((ModFlags & Modifiers.STATIC) == 0)
1850 cc |= CallingConventions.HasThis;
1852 // FIXME: How is `ExplicitThis' used in C#?
1857 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
1860 // Define each type attribute (in/out/ref) and
1861 // the argument names.
1863 Parameter [] p = Parameters.FixedParameters;
1866 MethodBuilder mb = null;
1867 ConstructorBuilder cb = null;
1869 if (builder is MethodBuilder)
1870 mb = (MethodBuilder) builder;
1872 cb = (ConstructorBuilder) builder;
1875 for (i = 0; i < p.Length; i++) {
1876 ParameterBuilder pb;
1879 pb = cb.DefineParameter (
1880 i + 1, p [i].Attributes, p [i].Name);
1882 pb = mb.DefineParameter (
1883 i + 1, p [i].Attributes, p [i].Name);
1885 Attributes attr = p [i].OptAttributes;
1887 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
1891 if (Parameters.ArrayParameter != null){
1892 ParameterBuilder pb;
1893 Parameter array_param = Parameters.ArrayParameter;
1896 pb = cb.DefineParameter (
1897 i + 1, array_param.Attributes,
1900 pb = mb.DefineParameter (
1901 i + 1, array_param.Attributes,
1904 CustomAttributeBuilder a = new CustomAttributeBuilder (
1905 TypeManager.cons_param_array_attribute, new object [0]);
1907 pb.SetCustomAttribute (a);
1912 public class Method : MethodCore {
1913 public MethodBuilder MethodBuilder;
1914 public MethodData MethodData;
1917 /// Modifiers allowed in a class declaration
1919 const int AllowedModifiers =
1922 Modifiers.PROTECTED |
1923 Modifiers.INTERNAL |
1928 Modifiers.OVERRIDE |
1929 Modifiers.ABSTRACT |
1934 // return_type can be "null" for VOID values.
1936 public Method (Expression return_type, int mod, string name, Parameters parameters,
1937 Attributes attrs, Location l)
1938 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
1942 // Returns the `System.Type' for the ReturnType of this
1943 // function. Provides a nice cache. (used between semantic analysis
1944 // and actual code generation
1946 public Type GetReturnType (TypeContainer parent)
1951 // Whether this is an operator method.
1952 public bool IsOperator;
1954 void DuplicateEntryPoint (MethodInfo b, Location location)
1958 "Program `" + CodeGen.FileName +
1959 "' has more than one entry point defined: `" +
1960 TypeManager.CSharpSignature(b) + "'");
1963 void Report28 (MethodInfo b)
1965 if (RootContext.WarningLevel < 4)
1970 "`" + TypeManager.CSharpSignature(b) +
1971 "' has the wrong signature to be an entry point");
1974 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
1976 if (b.ReturnType != TypeManager.void_type &&
1977 b.ReturnType != TypeManager.int32_type)
1980 if (pinfo.Count == 0)
1983 if (pinfo.Count > 1)
1986 Type t = pinfo.ParameterType(0);
1988 (t.GetArrayRank() == 1) &&
1989 (t.GetElementType() == TypeManager.string_type) &&
1990 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
1997 // Checks our base implementation if any
1999 protected override bool CheckBase (TypeContainer parent)
2001 // Check whether arguments were correct.
2002 if (!DoDefineParameters (parent))
2005 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2007 MemberInfo [] mi_this;
2009 mi_this = TypeContainer.FindMembers (
2010 parent.TypeBuilder, MemberTypes.Method,
2011 BindingFlags.NonPublic | BindingFlags.Public |
2012 BindingFlags.Static | BindingFlags.Instance |
2013 BindingFlags.DeclaredOnly,
2014 MethodSignature.method_signature_filter, ms);
2016 if (mi_this != null && mi_this.Length > 0) {
2017 Report.Error (111, Location, "Class `" + parent.Name + "' " +
2018 "already defines a member called `" + Name + "' " +
2019 "with the same parameter types");
2025 // Verify if the parent has a type with the same name, and then
2026 // check whether we have to create a new slot for it or not.
2028 Type ptype = parent.TypeBuilder.BaseType;
2030 // ptype is only null for System.Object while compiling corlib.
2032 MemberInfo [] mi, mi_static, mi_instance;
2034 mi_static = TypeContainer.FindMembers (
2035 ptype, MemberTypes.Method,
2036 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2037 MethodSignature.inheritable_method_signature_filter, ms);
2039 mi_instance = TypeContainer.FindMembers (
2040 ptype, MemberTypes.Method,
2041 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2042 MethodSignature.inheritable_method_signature_filter,
2045 if (mi_instance != null && mi_instance.Length > 0){
2047 } else if (mi_static != null && mi_static.Length > 0)
2052 if (mi != null && mi.Length > 0){
2053 parent_method = (MethodInfo) mi [0];
2054 string name = parent_method.DeclaringType.Name + "." +
2057 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2060 if ((ModFlags & Modifiers.NEW) == 0) {
2061 Type parent_ret = TypeManager.TypeToCoreType (
2062 parent_method.ReturnType);
2064 if (parent_ret != MemberType) {
2066 508, parent.MakeName (Name) + ": cannot " +
2067 "change return type when overriding " +
2068 "inherited member " + name);
2073 if ((ModFlags & Modifiers.NEW) != 0)
2074 WarningNotHiding (parent);
2076 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2077 Report.Error (115, Location,
2078 parent.MakeName (Name) +
2079 " no suitable methods found to override");
2082 } else if ((ModFlags & Modifiers.NEW) != 0)
2083 WarningNotHiding (parent);
2091 public override bool Define (TypeContainer parent)
2093 if (!DoDefine (parent))
2096 if (!CheckBase (parent))
2099 CallingConventions cc = GetCallingConvention (parent is Class);
2101 MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2102 ParameterInfo, cc, OptAttributes,
2103 ModFlags, flags, true);
2105 if (!MethodData.Define (parent))
2108 MethodBuilder = MethodData.MethodBuilder;
2111 // This is used to track the Entry Point,
2113 if (Name == "Main" &&
2114 ((ModFlags & Modifiers.STATIC) != 0) &&
2115 (RootContext.MainClass == null ||
2116 RootContext.MainClass == parent.TypeBuilder.FullName)){
2117 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2118 if (RootContext.EntryPoint == null) {
2119 RootContext.EntryPoint = MethodBuilder;
2120 RootContext.EntryPointLocation = Location;
2122 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2123 DuplicateEntryPoint (MethodBuilder, Location);
2126 Report28(MethodBuilder);
2135 public void Emit (TypeContainer parent)
2137 MethodData.Emit (parent, Block, this);
2141 public abstract class ConstructorInitializer {
2142 ArrayList argument_list;
2143 ConstructorInfo parent_constructor;
2146 public ConstructorInitializer (ArrayList argument_list, Location location)
2148 this.argument_list = argument_list;
2149 this.location = location;
2152 public ArrayList Arguments {
2154 return argument_list;
2158 public bool Resolve (EmitContext ec)
2160 Expression parent_constructor_group;
2163 if (argument_list != null){
2164 foreach (Argument a in argument_list){
2165 if (!a.Resolve (ec, location))
2170 if (this is ConstructorBaseInitializer) {
2171 if (ec.ContainerType.BaseType == null)
2174 t = ec.ContainerType.BaseType;
2175 if (ec.ContainerType.IsValueType) {
2176 Report.Error (522, location,
2177 "structs cannot call base class constructors");
2181 t = ec.ContainerType;
2183 parent_constructor_group = Expression.MemberLookup (
2185 MemberTypes.Constructor,
2186 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2189 if (parent_constructor_group == null){
2190 Report.Error (1501, location,
2191 "Can not find a constructor for this argument list");
2195 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2196 (MethodGroupExpr) parent_constructor_group, argument_list, location);
2198 if (parent_constructor == null){
2199 Report.Error (1501, location,
2200 "Can not find a constructor for this argument list");
2207 public void Emit (EmitContext ec)
2209 if (parent_constructor != null)
2210 ec.ig.Emit (OpCodes.Ldarg_0);
2211 if (argument_list != null)
2212 Invocation.EmitArguments (ec, null, argument_list);
2213 if (parent_constructor != null)
2214 ec.ig.Emit (OpCodes.Call, parent_constructor);
2218 public class ConstructorBaseInitializer : ConstructorInitializer {
2219 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2224 public class ConstructorThisInitializer : ConstructorInitializer {
2225 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2230 public class Constructor : MethodCore {
2231 public ConstructorBuilder ConstructorBuilder;
2232 public ConstructorInitializer Initializer;
2233 new public Attributes OptAttributes;
2236 // Modifiers allowed for a constructor.
2238 const int AllowedModifiers =
2240 Modifiers.PROTECTED |
2241 Modifiers.INTERNAL |
2247 // The spec claims that static is not permitted, but
2248 // my very own code has static constructors.
2250 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2251 : base (null, 0, AllowedModifiers, name, null, args, l)
2257 // Returns true if this is a default constructor
2259 public bool IsDefault ()
2261 if ((ModFlags & Modifiers.STATIC) != 0)
2262 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2263 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2266 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2267 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2268 (Initializer is ConstructorBaseInitializer) &&
2269 (Initializer.Arguments == null);
2273 // Creates the ConstructorBuilder
2275 public override bool Define (TypeContainer parent)
2277 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2278 MethodAttributes.SpecialName);
2280 // Check if arguments were correct.
2281 if (!DoDefineParameters (parent))
2284 if ((ModFlags & Modifiers.STATIC) != 0)
2285 ca |= MethodAttributes.Static;
2287 if (parent is Struct && ParameterTypes.Length == 0){
2290 "Structs can not contain explicit parameterless " +
2294 ca |= MethodAttributes.Public | MethodAttributes.HideBySig;
2297 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2298 ca, GetCallingConvention (parent is Class), ParameterTypes);
2301 // HACK because System.Reflection.Emit is lame
2303 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2306 "Class `" +parent.Name+ "' already contains a definition with the " +
2307 "same return value and parameter types for constructor `" + Name
2318 public void Emit (TypeContainer parent)
2320 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2321 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2323 if ((ModFlags & Modifiers.STATIC) == 0){
2324 if (parent is Class && Initializer == null)
2325 Initializer = new ConstructorBaseInitializer (null, parent.Location);
2329 // Spec mandates that Initializers will not have
2333 if (Initializer != null && !Initializer.Resolve (ec))
2335 ec.IsStatic = false;
2338 LabelParameters (ec, ParameterTypes, ConstructorBuilder);
2341 // Classes can have base initializers and instance field initializers.
2343 if (parent is Class){
2344 if ((ModFlags & Modifiers.STATIC) == 0)
2345 parent.EmitFieldInitializers (ec);
2347 if (Initializer != null)
2348 Initializer.Emit (ec);
2350 if ((ModFlags & Modifiers.STATIC) != 0)
2351 parent.EmitFieldInitializers (ec);
2353 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2355 ec.EmitTopBlock (Block, ParameterInfo, Location);
2359 public class MethodData {
2361 // The return type of this method
2363 public readonly Type ReturnType;
2364 public readonly Type[] ParameterTypes;
2365 public readonly InternalParameters ParameterInfo;
2366 public readonly CallingConventions CallingConventions;
2367 public readonly Attributes OptAttributes;
2368 public readonly Location Location;
2371 // Are we implementing an interface ?
2373 public bool IsImplementing = false;
2378 protected MemberBase member;
2379 protected int modifiers;
2380 protected MethodAttributes flags;
2381 protected bool is_method;
2382 protected string accessor_name;
2383 ArrayList conditionals;
2385 MethodBuilder builder = null;
2386 public MethodBuilder MethodBuilder {
2392 public MethodData (MemberBase member, string name, Type return_type,
2393 Type [] parameter_types, InternalParameters parameters,
2394 CallingConventions cc, Attributes opt_attrs,
2395 int modifiers, MethodAttributes flags, bool is_method)
2397 this.member = member;
2398 this.accessor_name = name;
2399 this.ReturnType = return_type;
2400 this.ParameterTypes = parameter_types;
2401 this.ParameterInfo = parameters;
2402 this.CallingConventions = cc;
2403 this.OptAttributes = opt_attrs;
2404 this.modifiers = modifiers;
2406 this.is_method = is_method;
2407 this.Location = member.Location;
2408 this.conditionals = new ArrayList ();
2414 Attribute dllimport_attribute = null;
2415 string obsolete = null;
2416 bool obsolete_error = false;
2418 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2420 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2423 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2424 if (asec.Attributes == null)
2427 foreach (Attribute a in asec.Attributes) {
2428 if (a.Name == "Conditional") {
2429 if (!ApplyConditionalAttribute (a))
2431 } else if (a.Name == "Obsolete") {
2432 if (!ApplyObsoleteAttribute (a))
2434 } else if (a.Name.IndexOf ("DllImport") != -1) {
2436 a.Type = TypeManager.dllimport_type;
2437 Attribute.Error_AttributeNotValidForElement (a, Location);
2440 if (!ApplyDllImportAttribute (a))
2450 // Applies the `DllImport' attribute to the method.
2452 protected virtual bool ApplyDllImportAttribute (Attribute a)
2454 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2455 if ((modifiers & extern_static) != extern_static) {
2456 Report.Error (601, Location,
2457 "The DllImport attribute must be specified on a method " +
2458 "marked `static' and `extern'.");
2462 flags |= MethodAttributes.PinvokeImpl;
2463 dllimport_attribute = a;
2468 // Applies the `Obsolete' attribute to the method.
2470 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2472 if (obsolete != null) {
2473 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2477 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2478 return obsolete != null;
2482 // Applies the `Conditional' attribute to the method.
2484 protected virtual bool ApplyConditionalAttribute (Attribute a)
2486 // The Conditional attribute is only valid on methods.
2488 Attribute.Error_AttributeNotValidForElement (a, Location);
2492 string condition = a.Conditional_GetConditionName ();
2494 if (condition == null)
2497 if (ReturnType != TypeManager.void_type) {
2498 Report.Error (578, Location,
2499 "Conditional not valid on `" + member.Name + "' " +
2500 "because its return type is not void");
2504 if ((modifiers & Modifiers.OVERRIDE) != 0) {
2505 Report.Error (243, Location,
2506 "Conditional not valid on `" + member.Name + "' " +
2507 "because it is an override method");
2511 if (member.IsExplicitImpl) {
2512 Report.Error (577, Location,
2513 "Conditional not valid on `" + member.Name + "' " +
2514 "because it is an explicit interface implementation");
2518 if (IsImplementing) {
2519 Report.Error (623, Location,
2520 "Conditional not valid on `" + member.Name + "' " +
2521 "because it is an interface method");
2525 conditionals.Add (condition);
2531 // Checks whether this method should be ignored due to its Conditional attributes.
2533 bool ShouldIgnore (Location loc)
2535 // When we're overriding a virtual method, we implicitly inherit the
2536 // Conditional attributes from our parent.
2537 if (member.ParentMethod != null) {
2538 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2539 member.ParentMethod, loc);
2541 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2545 foreach (string condition in conditionals)
2546 if (RootContext.AllDefines [condition] == null)
2553 // Returns the TypeManager.MethodFlags for this method.
2554 // This emits an error 619 / warning 618 if the method is obsolete.
2555 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2557 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2559 TypeManager.MethodFlags flags = 0;
2561 if (obsolete != null) {
2562 if (obsolete_error) {
2563 Report.Error (619, loc, "Method `" + member.Name +
2564 "' is obsolete: `" + obsolete + "'");
2565 return TypeManager.MethodFlags.IsObsoleteError;
2567 Report.Warning (618, loc, "Method `" + member.Name +
2568 "' is obsolete: `" + obsolete + "'");
2570 flags |= TypeManager.MethodFlags.IsObsolete;
2573 if (ShouldIgnore (loc))
2574 flags |= TypeManager.MethodFlags.ShouldIgnore;
2579 public virtual bool Define (TypeContainer parent)
2581 MethodInfo implementing = null;
2582 string method_name, name, prefix;
2584 if (OptAttributes != null)
2585 if (!ApplyAttributes (OptAttributes, is_method))
2588 if (member.IsExplicitImpl)
2589 prefix = member.InterfaceType.FullName + ".";
2593 if (accessor_name != null)
2594 name = accessor_name + "_" + member.ShortName;
2596 name = member.ShortName;
2597 method_name = prefix + name;
2599 if (parent.Pending != null){
2600 if (member is Indexer)
2601 implementing = parent.Pending.IsInterfaceIndexer (
2602 member.InterfaceType, ReturnType, ParameterTypes);
2604 implementing = parent.Pending.IsInterfaceMethod (
2605 member.InterfaceType, name, ReturnType, ParameterTypes);
2607 if (member.InterfaceType != null && implementing == null){
2608 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
2615 // For implicit implementations, make sure we are public, for
2616 // explicit implementations, make sure we are private.
2618 if (implementing != null){
2620 // Setting null inside this block will trigger a more
2621 // verbose error reporting for missing interface implementations
2623 // The "candidate" function has been flagged already
2624 // but it wont get cleared
2626 if (!member.IsExplicitImpl){
2628 // We already catch different accessibility settings
2629 // so we just need to check that we are not private
2631 if ((modifiers & Modifiers.PRIVATE) != 0)
2632 implementing = null;
2635 // Static is not allowed
2637 if ((modifiers & Modifiers.STATIC) != 0)
2638 implementing = null;
2640 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
2641 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
2642 implementing = null;
2648 // If implementing is still valid, set flags
2650 if (implementing != null){
2652 // When implementing interface methods, set NewSlot.
2654 if (implementing.DeclaringType.IsInterface)
2655 flags |= MethodAttributes.NewSlot;
2658 MethodAttributes.Virtual |
2659 MethodAttributes.HideBySig;
2661 // Get the method name from the explicit interface.
2662 if (member.InterfaceType != null) {
2663 name = implementing.Name;
2664 method_name = prefix + name;
2667 IsImplementing = true;
2671 // Create the MethodBuilder for the method
2673 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2674 if ((modifiers & Modifiers.STATIC) == 0) {
2675 Report.Error (601, Location,
2676 "The DllImport attribute must be specified on " +
2677 "a method marked 'static' and 'extern'.");
2681 EmitContext ec = new EmitContext (
2682 parent, Location, null, ReturnType, modifiers);
2684 builder = dllimport_attribute.DefinePInvokeMethod (
2685 ec, parent.TypeBuilder, method_name, flags,
2686 ReturnType, ParameterTypes);
2688 builder = parent.TypeBuilder.DefineMethod (
2689 method_name, flags, CallingConventions,
2690 ReturnType, ParameterTypes);
2692 if (builder == null)
2695 if (IsImplementing) {
2697 // clear the pending implemntation flag
2699 if (member is Indexer) {
2700 parent.Pending.ImplementIndexer (
2701 member.InterfaceType, builder, ReturnType,
2702 ParameterTypes, true);
2704 parent.Pending.ImplementMethod (
2705 member.InterfaceType, name, ReturnType,
2706 ParameterTypes, member.IsExplicitImpl);
2708 if (member.IsExplicitImpl)
2709 parent.TypeBuilder.DefineMethodOverride (
2710 builder, implementing);
2713 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
2714 Report.Error (111, Location,
2715 "Class `" + parent.Name +
2716 "' already contains a definition with the " +
2717 "same return value and parameter types as the " +
2718 "'get' method of property `" + member.Name + "'");
2722 TypeManager.AddMethod (builder, this);
2730 public virtual void Emit (TypeContainer parent, Block block, object kind)
2735 if ((flags & MethodAttributes.PinvokeImpl) == 0)
2736 ig = builder.GetILGenerator ();
2740 ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
2742 if (OptAttributes != null)
2743 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
2745 if (member is MethodCore)
2746 ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder);
2749 // abstract or extern methods have no bodies
2751 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
2756 // abstract or extern methods have no bodies.
2758 if ((modifiers & Modifiers.ABSTRACT) != 0)
2760 500, Location, "Abstract method `" +
2761 TypeManager.CSharpSignature (builder) +
2762 "' can not have a body");
2764 if ((modifiers & Modifiers.EXTERN) != 0)
2766 179, Location, "External method `" +
2767 TypeManager.CSharpSignature (builder) +
2768 "' can not have a body");
2774 // Methods must have a body unless they're extern or abstract
2776 if (block == null) {
2778 501, Location, "Method `" +
2779 TypeManager.CSharpSignature (builder) +
2780 "' must declare a body since it is not marked " +
2781 "abstract or extern");
2786 // Handle destructors specially
2788 // FIXME: This code generates buggy code
2790 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
2791 EmitDestructor (ec, block);
2793 ISymbolWriter sw = CodeGen.SymbolWriter;
2795 if ((sw != null) && !Location.IsNull (Location) &&
2796 !Location.IsNull (block.EndLocation)) {
2797 Location end = block.EndLocation;
2798 MethodToken token = MethodBuilder.GetToken ();
2799 sw.OpenMethod (new SymbolToken (token.Token));
2800 sw.SetMethodSourceRange (Location.SymbolDocument,
2805 ec.EmitTopBlock (block, ParameterInfo, Location);
2809 ec.EmitTopBlock (block, ParameterInfo, Location);
2813 void EmitDestructor (EmitContext ec, Block block)
2815 ILGenerator ig = ec.ig;
2817 Label finish = ig.DefineLabel ();
2818 bool old_in_try = ec.InTry;
2820 ig.BeginExceptionBlock ();
2822 ec.ReturnLabel = finish;
2823 ec.HasReturnLabel = true;
2824 ec.EmitTopBlock (block, null, Location);
2825 ec.InTry = old_in_try;
2827 // ig.MarkLabel (finish);
2828 bool old_in_finally = ec.InFinally;
2829 ec.InFinally = true;
2830 ig.BeginFinallyBlock ();
2832 if (ec.ContainerType.BaseType != null) {
2833 Expression member_lookup = Expression.MemberLookup (
2834 ec, ec.ContainerType.BaseType, "Finalize",
2835 MemberTypes.Method, Expression.AllBindingFlags, Location);
2837 if (member_lookup != null){
2838 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
2840 ig.Emit (OpCodes.Ldarg_0);
2841 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
2844 ec.InFinally = old_in_finally;
2846 ig.EndExceptionBlock ();
2847 //ig.MarkLabel (ec.ReturnLabel);
2848 ig.Emit (OpCodes.Ret);
2852 abstract public class MemberBase : MemberCore {
2853 public Expression Type;
2854 public readonly Attributes OptAttributes;
2856 protected MethodAttributes flags;
2859 // The "short" name of this property / indexer / event. This is the
2860 // name without the explicit interface.
2862 public string ShortName;
2865 // The type of this property / indexer / event
2867 public Type MemberType;
2870 // If true, this is an explicit interface implementation
2872 public bool IsExplicitImpl = false;
2875 // The name of the interface we are explicitly implementing
2877 public string ExplicitInterfaceName = null;
2880 // If true, the interface type we are explicitly implementing
2882 public Type InterfaceType = null;
2885 // The method we're overriding if this is an override method.
2887 protected MethodInfo parent_method = null;
2888 public MethodInfo ParentMethod {
2890 return parent_method;
2895 // The constructor is only exposed to our children
2897 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
2898 Attributes attrs, Location loc)
2902 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
2903 OptAttributes = attrs;
2906 protected virtual bool CheckBase (TypeContainer parent)
2911 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
2915 foreach (Type partype in parameters){
2916 if (partype.IsPointer && !UnsafeOK (parent))
2919 if (parent.AsAccessible (partype, ModFlags))
2922 if (this is Indexer)
2923 Report.Error (55, Location,
2924 "Inconsistent accessibility: parameter type `" +
2925 TypeManager.CSharpName (partype) + "' is less " +
2926 "accessible than indexer `" + Name + "'");
2928 Report.Error (51, Location,
2929 "Inconsistent accessibility: parameter type `" +
2930 TypeManager.CSharpName (partype) + "' is less " +
2931 "accessible than method `" + Name + "'");
2938 protected virtual bool DoDefine (TypeContainer parent)
2943 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
2946 flags = Modifiers.MethodAttr (ModFlags);
2948 // Lookup Type, verify validity
2949 MemberType = parent.ResolveType (Type, false, Location);
2950 if (MemberType == null)
2953 // verify accessibility
2954 if (!parent.AsAccessible (MemberType, ModFlags)) {
2955 if (this is Property)
2956 Report.Error (53, Location,
2957 "Inconsistent accessibility: property type `" +
2958 TypeManager.CSharpName (MemberType) + "' is less " +
2959 "accessible than property `" + Name + "'");
2960 else if (this is Indexer)
2961 Report.Error (54, Location,
2962 "Inconsistent accessibility: indexer return type `" +
2963 TypeManager.CSharpName (MemberType) + "' is less " +
2964 "accessible than indexer `" + Name + "'");
2965 else if (this is Method)
2966 Report.Error (50, Location,
2967 "Inconsistent accessibility: return type `" +
2968 TypeManager.CSharpName (MemberType) + "' is less " +
2969 "accessible than method `" + Name + "'");
2971 Report.Error (52, Location,
2972 "Inconsistent accessibility: field type `" +
2973 TypeManager.CSharpName (MemberType) + "' is less " +
2974 "accessible than field `" + Name + "'");
2978 if (MemberType.IsPointer && !UnsafeOK (parent))
2982 // Check for explicit interface implementation
2984 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
2985 int pos = Name.LastIndexOf (".");
2987 ExplicitInterfaceName = Name.Substring (0, pos);
2988 ShortName = Name.Substring (pos + 1);
2992 if (ExplicitInterfaceName != null) {
2993 InterfaceType = RootContext.LookupType (
2994 parent, ExplicitInterfaceName, false, Location);
2995 if (InterfaceType == null)
2998 // Compute the full name that we need to export.
2999 Name = InterfaceType.FullName + "." + ShortName;
3001 if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
3004 IsExplicitImpl = true;
3006 IsExplicitImpl = false;
3013 // Fields and Events both generate FieldBuilders, we use this to share
3014 // their common bits. This is also used to flag usage of the field
3016 abstract public class FieldBase : MemberBase {
3017 public readonly Object Initializer;
3018 public FieldBuilder FieldBuilder;
3019 public Status status;
3022 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3025 // The constructor is only exposed to our children
3027 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3028 object init, Attributes attrs, Location loc)
3029 : base (type, mod, allowed_mod, name, attrs, loc)
3036 // The Field class is used to represents class/struct fields during parsing.
3038 public class Field : FieldBase {
3040 // Modifiers allowed in a class declaration
3042 const int AllowedModifiers =
3045 Modifiers.PROTECTED |
3046 Modifiers.INTERNAL |
3049 Modifiers.VOLATILE |
3053 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3054 Attributes attrs, Location loc)
3055 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3059 public override bool Define (TypeContainer parent)
3061 Type t = parent.ResolveType (Type, false, Location);
3066 if (!parent.AsAccessible (t, ModFlags)) {
3067 Report.Error (52, Location,
3068 "Inconsistent accessibility: field type `" +
3069 TypeManager.CSharpName (t) + "' is less " +
3070 "accessible than field `" + Name + "'");
3074 if (t.IsPointer && !UnsafeOK (parent))
3077 if (RootContext.WarningLevel > 1){
3078 Type ptype = parent.TypeBuilder.BaseType;
3080 // ptype is only null for System.Object while compiling corlib.
3084 mi = TypeContainer.FindMembers (
3085 ptype, MemberTypes.Method,
3086 BindingFlags.Public |
3087 BindingFlags.Static | BindingFlags.Instance,
3088 System.Type.FilterName, Name);
3092 if ((ModFlags & Modifiers.VOLATILE) != 0){
3094 if (TypeManager.IsEnumType (t))
3095 t = TypeManager.EnumToUnderlying (t);
3097 if (!((t == TypeManager.bool_type) ||
3098 (t == TypeManager.sbyte_type) ||
3099 (t == TypeManager.byte_type) ||
3100 (t == TypeManager.short_type) ||
3101 (t == TypeManager.ushort_type) ||
3102 (t == TypeManager.int32_type) ||
3103 (t == TypeManager.uint32_type) ||
3104 (t == TypeManager.char_type) ||
3105 (t == TypeManager.float_type))){
3107 677, Location, parent.MakeName (Name) +
3108 " A volatile field can not be of type `" +
3109 TypeManager.CSharpName (t) + "'");
3115 FieldBuilder = parent.TypeBuilder.DefineField (
3116 Name, t, Modifiers.FieldAttr (ModFlags));
3118 TypeManager.RegisterFieldBase (FieldBuilder, this);
3122 public void Emit (TypeContainer tc)
3124 EmitContext ec = new EmitContext (tc, Location, null,
3125 FieldBuilder.FieldType, ModFlags);
3127 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
3132 // `set' and `get' accessors are represented with an Accessor.
3134 public class Accessor {
3136 // Null if the accessor is empty, or a Block if not
3139 public Attributes OptAttributes;
3141 public Accessor (Block b, Attributes attrs)
3144 OptAttributes = attrs;
3149 // Properties and Indexers both generate PropertyBuilders, we use this to share
3150 // their common bits.
3152 abstract public class PropertyBase : MethodCore {
3153 public Accessor Get, Set;
3154 public PropertyBuilder PropertyBuilder;
3155 public MethodBuilder GetBuilder, SetBuilder;
3156 public MethodData GetData, SetData;
3158 protected EmitContext ec;
3160 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3161 Parameters parameters, Accessor get_block, Accessor set_block,
3162 Attributes attrs, Location loc)
3163 : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3169 protected override bool DoDefine (TypeContainer parent)
3171 if (!base.DoDefine (parent))
3174 ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3180 // Checks our base implementation if any
3182 protected override bool CheckBase (TypeContainer parent)
3184 // Check whether arguments were correct.
3185 if (!DoDefineParameters (parent))
3188 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
3189 MemberInfo [] props_this;
3191 props_this = TypeContainer.FindMembers (
3192 parent.TypeBuilder, MemberTypes.Property,
3193 BindingFlags.NonPublic | BindingFlags.Public |
3194 BindingFlags.Static | BindingFlags.Instance |
3195 BindingFlags.DeclaredOnly,
3196 MethodSignature.method_signature_filter, ms);
3198 if (props_this != null && props_this.Length > 0) {
3199 Report.Error (111, Location, "Class `" + parent.Name + "' " +
3200 "already defines a member called `" + Name + "' " +
3201 "with the same parameter types");
3206 // Find properties with the same name on the base class
3208 MemberInfo [] props;
3209 MemberInfo [] props_static = TypeContainer.FindMembers (
3210 parent.TypeBuilder.BaseType, MemberTypes.Property,
3211 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3212 MethodSignature.inheritable_property_signature_filter, ms);
3214 MemberInfo [] props_instance = TypeContainer.FindMembers (
3215 parent.TypeBuilder.BaseType, MemberTypes.Property,
3216 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3217 MethodSignature.inheritable_property_signature_filter,
3221 // Find if we have anything
3223 if (props_static != null && props_static.Length > 0)
3224 props = props_static;
3225 else if (props_instance != null && props_instance.Length > 0)
3226 props = props_instance;
3231 // If we have something on the base.
3232 if (props != null && props.Length > 0){
3233 PropertyInfo pi = (PropertyInfo) props [0];
3235 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
3236 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
3238 MethodInfo reference = inherited_get == null ?
3239 inherited_set : inherited_get;
3241 if (reference != null) {
3242 string name = reference.DeclaringType.Name + "." + Name;
3244 if (!CheckMethodAgainstBase (parent, flags, reference, name))
3248 if (((ModFlags & Modifiers.NEW) == 0) && (pi.PropertyType != MemberType)) {
3249 Report.Error (508, parent.MakeName (Name) + ": cannot " +
3250 "change return type when overriding inherited " +
3251 "member `" + pi.DeclaringType + "." + pi.Name + "'");
3255 if ((ModFlags & Modifiers.NEW) != 0)
3256 WarningNotHiding (parent);
3258 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3259 if (this is Indexer)
3260 Report.Error (115, Location,
3261 parent.MakeName (Name) +
3262 " no suitable indexers found to override");
3264 Report.Error (115, Location,
3265 parent.MakeName (Name) +
3266 " no suitable properties found to override");
3273 public void Emit (TypeContainer tc)
3276 // The PropertyBuilder can be null for explicit implementations, in that
3277 // case, we do not actually emit the ".property", so there is nowhere to
3278 // put the attribute
3280 if (PropertyBuilder != null)
3281 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3283 if (GetData != null)
3284 GetData.Emit (tc, Get.Block, Get);
3286 if (SetData != null)
3287 SetData.Emit (tc, Set.Block, Set);
3291 public class Property : PropertyBase {
3292 const int AllowedModifiers =
3295 Modifiers.PROTECTED |
3296 Modifiers.INTERNAL |
3300 Modifiers.OVERRIDE |
3301 Modifiers.ABSTRACT |
3306 public Property (Expression type, string name, int mod_flags,
3307 Accessor get_block, Accessor set_block,
3308 Attributes attrs, Location loc)
3309 : base (type, name, mod_flags, AllowedModifiers,
3310 Parameters.EmptyReadOnlyParameters,
3311 get_block, set_block, attrs, loc)
3315 public override bool Define (TypeContainer parent)
3317 if (!DoDefine (parent))
3320 if (!CheckBase (parent))
3323 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3326 Type [] parameters = TypeManager.NoTypes;
3328 InternalParameters ip = new InternalParameters (
3329 parent, Parameters.EmptyReadOnlyParameters);
3331 GetData = new MethodData (this, "get", MemberType,
3332 parameters, ip, CallingConventions.Standard,
3333 Get.OptAttributes, ModFlags, flags, false);
3335 if (!GetData.Define (parent))
3338 GetBuilder = GetData.MethodBuilder;
3342 Type [] parameters = new Type [1];
3343 parameters [0] = MemberType;
3345 Parameter [] parms = new Parameter [1];
3346 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3347 InternalParameters ip = new InternalParameters (
3348 parent, new Parameters (parms, null, Location));
3350 SetData = new MethodData (this, "set", TypeManager.void_type,
3351 parameters, ip, CallingConventions.Standard,
3352 Set.OptAttributes, ModFlags, flags, false);
3354 if (!SetData.Define (parent))
3357 SetBuilder = SetData.MethodBuilder;
3358 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3361 // FIXME - PropertyAttributes.HasDefault ?
3363 PropertyAttributes prop_attr =
3364 PropertyAttributes.RTSpecialName |
3365 PropertyAttributes.SpecialName;
3367 if (!IsExplicitImpl){
3368 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3369 Name, prop_attr, MemberType, null);
3372 PropertyBuilder.SetGetMethod (GetBuilder);
3375 PropertyBuilder.SetSetMethod (SetBuilder);
3378 // HACK for the reasons exposed above
3380 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3383 "Class `" + parent.Name +
3384 "' already contains a definition for the property `" +
3394 /// Gigantic workaround for lameness in SRE follows :
3395 /// This class derives from EventInfo and attempts to basically
3396 /// wrap around the EventBuilder so that FindMembers can quickly
3397 /// return this in it search for members
3399 public class MyEventBuilder : EventInfo {
3402 // We use this to "point" to our Builder which is
3403 // not really a MemberInfo
3405 EventBuilder MyBuilder;
3408 // We "catch" and wrap these methods
3410 MethodInfo raise, remove, add;
3412 EventAttributes attributes;
3413 Type declaring_type, reflected_type, event_type;
3416 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3418 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3420 // And now store the values in our own fields.
3422 declaring_type = type_builder;
3424 reflected_type = type_builder;
3426 attributes = event_attr;
3428 this.event_type = event_type;
3432 // Methods that you have to override. Note that you only need
3433 // to "implement" the variants that take the argument (those are
3434 // the "abstract" methods, the others (GetAddMethod()) are
3437 public override MethodInfo GetAddMethod (bool nonPublic)
3442 public override MethodInfo GetRemoveMethod (bool nonPublic)
3447 public override MethodInfo GetRaiseMethod (bool nonPublic)
3453 // These methods make "MyEventInfo" look like a Builder
3455 public void SetRaiseMethod (MethodBuilder raiseMethod)
3457 raise = raiseMethod;
3458 MyBuilder.SetRaiseMethod (raiseMethod);
3461 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3463 remove = removeMethod;
3464 MyBuilder.SetRemoveOnMethod (removeMethod);
3467 public void SetAddOnMethod (MethodBuilder addMethod)
3470 MyBuilder.SetAddOnMethod (addMethod);
3473 public void SetCustomAttribute (CustomAttributeBuilder cb)
3475 MyBuilder.SetCustomAttribute (cb);
3478 public override object [] GetCustomAttributes (bool inherit)
3480 // FIXME : There's nothing which can be seemingly done here because
3481 // we have no way of getting at the custom attribute objects of the
3486 public override object [] GetCustomAttributes (Type t, bool inherit)
3488 // FIXME : Same here !
3492 public override bool IsDefined (Type t, bool b)
3497 public override EventAttributes Attributes {
3503 public override string Name {
3509 public override Type DeclaringType {
3511 return declaring_type;
3515 public override Type ReflectedType {
3517 return reflected_type;
3521 public Type EventType {
3528 public class Event : FieldBase {
3529 const int AllowedModifiers =
3532 Modifiers.PROTECTED |
3533 Modifiers.INTERNAL |
3538 Modifiers.OVERRIDE |
3542 public readonly Accessor Add;
3543 public readonly Accessor Remove;
3544 public MyEventBuilder EventBuilder;
3546 MethodBuilder AddBuilder, RemoveBuilder;
3547 MethodData AddData, RemoveData;
3549 public Event (Expression type, string name, Object init, int mod, Accessor add,
3550 Accessor remove, Attributes attrs, Location loc)
3551 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
3557 public override bool Define (TypeContainer parent)
3559 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3561 if (!DoDefine (parent))
3564 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
3565 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3566 "' : event must be of a delegate type");
3570 Type [] parameter_types = new Type [1];
3571 parameter_types [0] = MemberType;
3573 Parameter [] parms = new Parameter [1];
3574 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3575 InternalParameters ip = new InternalParameters (
3576 parent, new Parameters (parms, null, Location));
3578 if (!CheckBase (parent))
3582 // Now define the accessors
3584 AddData = new MethodData (this, "add", TypeManager.void_type,
3585 parameter_types, ip, CallingConventions.Standard,
3586 (Add != null) ? Add.OptAttributes : null,
3587 ModFlags, flags, false);
3589 if (!AddData.Define (parent))
3592 AddBuilder = AddData.MethodBuilder;
3593 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3595 RemoveData = new MethodData (this, "remove", TypeManager.void_type,
3596 parameter_types, ip, CallingConventions.Standard,
3597 (Remove != null) ? Remove.OptAttributes : null,
3598 ModFlags, flags, false);
3600 if (!RemoveData.Define (parent))
3603 RemoveBuilder = RemoveData.MethodBuilder;
3604 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3606 if (!IsExplicitImpl){
3607 EventBuilder = new MyEventBuilder (
3608 parent.TypeBuilder, Name, e_attr, MemberType);
3610 if (Add == null && Remove == null) {
3611 FieldBuilder = parent.TypeBuilder.DefineField (
3612 Name, MemberType, FieldAttributes.FamANDAssem);
3613 TypeManager.RegisterPrivateFieldOfEvent (
3614 (EventInfo) EventBuilder, FieldBuilder);
3615 TypeManager.RegisterFieldBase (FieldBuilder, this);
3618 EventBuilder.SetAddOnMethod (AddBuilder);
3619 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3621 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3622 Report.Error (111, Location,
3623 "Class `" + parent.Name +
3624 "' already contains a definition for the event `" +
3633 void EmitDefaultMethod (EmitContext ec, bool is_add)
3635 ILGenerator ig = ec.ig;
3636 MethodInfo method = null;
3639 method = TypeManager.delegate_combine_delegate_delegate;
3641 method = TypeManager.delegate_remove_delegate_delegate;
3643 if ((ModFlags & Modifiers.STATIC) != 0) {
3644 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
3645 ig.Emit (OpCodes.Ldarg_0);
3646 ig.Emit (OpCodes.Call, method);
3647 ig.Emit (OpCodes.Castclass, MemberType);
3648 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
3650 ig.Emit (OpCodes.Ldarg_0);
3651 ig.Emit (OpCodes.Ldarg_0);
3652 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3653 ig.Emit (OpCodes.Ldarg_1);
3654 ig.Emit (OpCodes.Call, method);
3655 ig.Emit (OpCodes.Castclass, MemberType);
3656 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3658 ig.Emit (OpCodes.Ret);
3661 public void Emit (TypeContainer tc)
3665 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
3666 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3669 AddData.Emit (tc, Add.Block, Add);
3671 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
3672 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3673 EmitDefaultMethod (ec, true);
3677 RemoveData.Emit (tc, Remove.Block, Remove);
3679 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
3680 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3681 EmitDefaultMethod (ec, false);
3688 // FIXME: This does not handle:
3690 // int INTERFACENAME [ args ]
3695 // int this [ args ]
3697 public class Indexer : PropertyBase {
3699 const int AllowedModifiers =
3702 Modifiers.PROTECTED |
3703 Modifiers.INTERNAL |
3707 Modifiers.OVERRIDE |
3712 public string IndexerName;
3713 public string InterfaceIndexerName;
3716 // Are we implementing an interface ?
3718 bool IsImplementing = false;
3720 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
3721 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
3722 : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
3725 ExplicitInterfaceName = int_type;
3728 public override bool Define (TypeContainer parent)
3730 PropertyAttributes prop_attr =
3731 PropertyAttributes.RTSpecialName |
3732 PropertyAttributes.SpecialName;
3734 if (!DoDefine (parent))
3737 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
3738 if (IndexerName == null)
3739 IndexerName = "Item";
3740 else if (IsExplicitImpl)
3741 Report.Error (592, Location,
3742 "Attribute 'IndexerName' is not valid on this declaration " +
3743 "type. It is valid on `property' declarations only.");
3745 ShortName = IndexerName;
3746 if (IsExplicitImpl) {
3747 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
3748 Name = InterfaceType.FullName + "." + IndexerName;
3750 InterfaceIndexerName = IndexerName;
3754 if (!CheckBase (parent))
3758 InternalParameters ip = new InternalParameters (parent, Parameters);
3760 GetData = new MethodData (this, "get", MemberType,
3761 ParameterTypes, ip, CallingConventions.Standard,
3762 Get.OptAttributes, ModFlags, flags, false);
3764 if (!GetData.Define (parent))
3767 GetBuilder = GetData.MethodBuilder;
3771 int top = ParameterTypes.Length;
3772 Type [] set_pars = new Type [top + 1];
3773 ParameterTypes.CopyTo (set_pars, 0);
3774 set_pars [top] = MemberType;
3776 Parameter [] fixed_parms = Parameters.FixedParameters;
3778 if (fixed_parms == null){
3779 throw new Exception ("We currently do not support only array arguments in an indexer");
3780 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3781 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3783 // Here is the problem: the `value' parameter has
3784 // to come *after* the array parameter in the declaration
3786 // X (object [] x, Type value)
3789 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3790 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3794 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
3797 fixed_parms.CopyTo (tmp, 0);
3798 tmp [fixed_parms.Length] = new Parameter (
3799 Type, "value", Parameter.Modifier.NONE, null);
3801 Parameters set_formal_params = new Parameters (tmp, null, Location);
3803 InternalParameters ip = new InternalParameters (parent, set_formal_params);
3805 SetData = new MethodData (this, "set", TypeManager.void_type,
3806 set_pars, ip, CallingConventions.Standard,
3807 Set.OptAttributes, ModFlags, flags, false);
3809 if (!SetData.Define (parent))
3812 SetBuilder = SetData.MethodBuilder;
3816 // Now name the parameters
3818 Parameter [] p = Parameters.FixedParameters;
3822 for (i = 0; i < p.Length; ++i) {
3824 GetBuilder.DefineParameter (
3825 i + 1, p [i].Attributes, p [i].Name);
3828 SetBuilder.DefineParameter (
3829 i + 1, p [i].Attributes, p [i].Name);
3833 SetBuilder.DefineParameter (
3834 i + 1, ParameterAttributes.None, "value");
3836 if (i != ParameterTypes.Length) {
3837 Parameter array_param = Parameters.ArrayParameter;
3838 SetBuilder.DefineParameter (
3839 i + 1, array_param.Attributes, array_param.Name);
3843 if (GetData != null)
3844 IsImplementing = GetData.IsImplementing;
3845 else if (SetData != null)
3846 IsImplementing = SetData.IsImplementing;
3849 // Define the PropertyBuilder if one of the following conditions are met:
3850 // a) we're not implementing an interface indexer.
3851 // b) the indexer has a different IndexerName and this is no
3852 // explicit interface implementation.
3854 if (!IsExplicitImpl) {
3855 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3856 IndexerName, prop_attr, MemberType, ParameterTypes);
3858 if (GetData != null)
3859 PropertyBuilder.SetGetMethod (GetBuilder);
3861 if (SetData != null)
3862 PropertyBuilder.SetSetMethod (SetBuilder);
3864 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
3872 public class Operator : MemberCore {
3874 const int AllowedModifiers =
3880 const int RequiredModifiers =
3884 public enum OpType : byte {
3894 // Unary and Binary operators
3917 // Implicit and Explicit
3922 public readonly OpType OperatorType;
3923 public readonly Expression ReturnType;
3924 public readonly Expression FirstArgType, SecondArgType;
3925 public readonly string FirstArgName, SecondArgName;
3926 public readonly Block Block;
3927 public Attributes OptAttributes;
3928 public MethodBuilder OperatorMethodBuilder;
3930 public string MethodName;
3931 public Method OperatorMethod;
3933 public Operator (OpType type, Expression ret_type, int flags,
3934 Expression arg1type, string arg1name,
3935 Expression arg2type, string arg2name,
3936 Block block, Attributes attrs, Location loc)
3939 OperatorType = type;
3940 ReturnType = ret_type;
3941 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
3942 FirstArgType = arg1type;
3943 FirstArgName = arg1name;
3944 SecondArgType = arg2type;
3945 SecondArgName = arg2name;
3947 OptAttributes = attrs;
3950 string Prototype (TypeContainer parent)
3952 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
3953 SecondArgType + ")";
3956 public override bool Define (TypeContainer parent)
3959 MethodName = "op_" + OperatorType;
3961 if (SecondArgType != null)
3964 Parameter [] param_list = new Parameter [length];
3966 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
3969 "User defined operators `" +
3970 Prototype (parent) +
3971 "' must be declared static and public");
3975 param_list[0] = new Parameter (FirstArgType, FirstArgName,
3976 Parameter.Modifier.NONE, null);
3977 if (SecondArgType != null)
3978 param_list[1] = new Parameter (SecondArgType, SecondArgName,
3979 Parameter.Modifier.NONE, null);
3981 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
3982 new Parameters (param_list, null, Location),
3983 OptAttributes, Mono.CSharp.Location.Null);
3985 OperatorMethod.IsOperator = true;
3986 OperatorMethod.Define (parent);
3988 if (OperatorMethod.MethodBuilder == null)
3991 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
3993 Type [] param_types = OperatorMethod.ParameterTypes;
3994 Type declaring_type = OperatorMethodBuilder.DeclaringType;
3995 Type return_type = OperatorMethod.GetReturnType (parent);
3996 Type first_arg_type = param_types [0];
3998 // Rules for conversion operators
4000 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4001 if (first_arg_type == return_type && first_arg_type == declaring_type){
4004 "User-defined conversion cannot take an object of the " +
4005 "enclosing type and convert to an object of the enclosing" +
4010 if (first_arg_type != declaring_type && return_type != declaring_type){
4013 "User-defined conversion must convert to or from the " +
4018 if (first_arg_type == TypeManager.object_type ||
4019 return_type == TypeManager.object_type){
4022 "User-defined conversion cannot convert to or from " +
4027 if (first_arg_type.IsInterface || return_type.IsInterface){
4030 "User-defined conversion cannot convert to or from an " +
4035 if (first_arg_type.IsSubclassOf (return_type) ||
4036 return_type.IsSubclassOf (first_arg_type)){
4039 "User-defined conversion cannot convert between types " +
4040 "that derive from each other");
4043 } else if (SecondArgType == null) {
4044 // Checks for Unary operators
4046 if (first_arg_type != declaring_type){
4049 "The parameter of a unary operator must be the " +
4054 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4055 if (return_type != declaring_type){
4058 "The parameter and return type for ++ and -- " +
4059 "must be the containing type");
4065 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4066 if (return_type != TypeManager.bool_type){
4069 "The return type of operator True or False " +
4076 // Checks for Binary operators
4078 if (first_arg_type != declaring_type &&
4079 param_types [1] != declaring_type){
4082 "One of the parameters of a binary operator must " +
4083 "be the containing type");
4091 public void Emit (TypeContainer parent)
4093 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4094 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4097 // abstract or extern methods have no bodies
4099 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4102 OperatorMethod.Block = Block;
4103 OperatorMethod.Emit (parent);
4108 // This is used to compare method signatures
4110 struct MethodSignature {
4112 public Type RetType;
4113 public Type [] Parameters;
4116 /// This delegate is used to extract methods which have the
4117 /// same signature as the argument
4119 public static MemberFilter method_signature_filter;
4122 /// This delegate is used to extract inheritable methods which
4123 /// have the same signature as the argument. By inheritable,
4124 /// this means that we have permissions to override the method
4125 /// from the current assembly and class
4127 public static MemberFilter inheritable_method_signature_filter;
4130 /// This delegate is used to extract inheritable methods which
4131 /// have the same signature as the argument. By inheritable,
4132 /// this means that we have permissions to override the method
4133 /// from the current assembly and class
4135 public static MemberFilter inheritable_property_signature_filter;
4137 static MethodSignature ()
4139 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4140 inheritable_method_signature_filter = new MemberFilter (
4141 InheritableMemberSignatureCompare);
4142 inheritable_property_signature_filter = new MemberFilter (
4143 InheritablePropertySignatureCompare);
4146 public MethodSignature (string name, Type ret_type, Type [] parameters)
4151 if (parameters == null)
4152 Parameters = TypeManager.NoTypes;
4154 Parameters = parameters;
4157 public override int GetHashCode ()
4159 return Name.GetHashCode ();
4162 public override bool Equals (Object o)
4164 MethodSignature other = (MethodSignature) o;
4166 if (other.Name != Name)
4169 if (other.RetType != RetType)
4172 if (Parameters == null){
4173 if (other.Parameters == null)
4178 if (other.Parameters == null)
4181 int c = Parameters.Length;
4182 if (other.Parameters.Length != c)
4185 for (int i = 0; i < c; i++)
4186 if (other.Parameters [i] != Parameters [i])
4192 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4194 MethodSignature sig = (MethodSignature) filter_criteria;
4196 if (m.Name != sig.Name)
4200 MethodInfo mi = m as MethodInfo;
4201 PropertyInfo pi = m as PropertyInfo;
4204 ReturnType = mi.ReturnType;
4205 else if (pi != null)
4206 ReturnType = pi.PropertyType;
4211 // we use sig.RetType == null to mean `do not check the
4212 // method return value.
4214 if (sig.RetType != null)
4215 if (ReturnType != sig.RetType)
4220 args = TypeManager.GetArgumentTypes (mi);
4222 args = TypeManager.GetArgumentTypes (pi);
4223 Type [] sigp = sig.Parameters;
4225 if (args.Length != sigp.Length)
4228 for (int i = args.Length; i > 0; ){
4230 if (args [i] != sigp [i])
4237 // This filter should be used when we are requesting methods that
4238 // we want to override.
4240 // This makes a number of assumptions, for example
4241 // that the methods being extracted are of a parent
4242 // class (this means we know implicitly that we are
4243 // being called to find out about members by a derived
4246 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4248 if (MemberSignatureCompare (m, filter_criteria)){
4249 MethodInfo mi = (MethodInfo) m;
4250 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4252 // If only accessible to the current class.
4253 if (prot == MethodAttributes.Private)
4256 // If only accessible to the defining assembly or
4257 if (prot == MethodAttributes.FamANDAssem ||
4258 prot == MethodAttributes.Assembly){
4259 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4265 // Anything else (FamOrAssembly and Public) is fine
4272 // This filter should be used when we are requesting properties that
4273 // we want to override.
4275 // This makes a number of assumptions, for example
4276 // that the methods being extracted are of a parent
4277 // class (this means we know implicitly that we are
4278 // being called to find out about members by a derived
4281 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
4283 if (MemberSignatureCompare (m, filter_criteria)){
4284 PropertyInfo pi = (PropertyInfo) m;
4286 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
4287 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
4289 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
4291 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4293 // If only accessible to the current class.
4294 if (prot == MethodAttributes.Private)
4297 // If only accessible to the defining assembly or
4298 if (prot == MethodAttributes.FamANDAssem ||
4299 prot == MethodAttributes.Assembly){
4300 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4306 // Anything else (FamOrAssembly and Public) is fine