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)
12 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
14 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
15 // have fixed a remaining problem: not every AddXXXX was adding a
16 // fully qualified name.
18 // Now everyone registers a fully qualified name in the DeclSpace as
19 // being defined instead of the partial name.
21 // Downsides: we are slower than we need to be due to the excess
22 // copies and the names being registered this way.
24 // The reason for this is that we currently depend (on the corlib
25 // bootstrap for instance) that types are fully qualified, because
26 // we dump all the types in the namespace, and we should really have
27 // types inserted into the proper namespace, so we can only store the
28 // basenames in the defined_names array.
33 using System.Collections;
34 using System.Reflection;
35 using System.Reflection.Emit;
36 using System.Runtime.CompilerServices;
38 namespace Mono.CSharp {
41 /// This is the base class for structs and classes.
43 public class TypeContainer : DeclSpace, IMemberContainer {
44 // Holds a list of classes and structures
47 // Holds the list of properties
50 // Holds the list of enumerations
53 // Holds the list of delegates
56 // Holds the list of constructors
57 ArrayList instance_constructors;
59 // Holds the list of fields
62 // Holds a list of fields that have initializers
63 ArrayList initialized_fields;
65 // Holds a list of static fields that have initializers
66 ArrayList initialized_static_fields;
68 // Holds the list of constants
74 // Holds order in which interfaces must be closed
75 ArrayList interface_order;
86 // Holds the operators
89 // The emit context for toplevel objects.
93 // Pointers to the default constructor and the default static constructor
95 Constructor default_constructor;
96 Constructor default_static_constructor;
99 // Whether we have seen a static constructor for this class or not
101 bool have_static_constructor = false;
104 // Whether we have at least one non-static field
106 bool have_nonstatic_fields = false;
109 // This one is computed after we can distinguish interfaces
110 // from classes from the arraylist `type_bases'
112 string base_class_name;
114 ArrayList type_bases;
116 // Attributes for this type
117 protected Attributes attributes;
119 // Information in the case we are an attribute type
121 public AttributeTargets Targets = AttributeTargets.All;
122 public bool AllowMultiple = false;
123 public bool Inherited;
125 // The interfaces we implement.
128 // The parent member container and our member cache
129 IMemberContainer parent_container;
130 MemberCache member_cache;
133 // The indexer name for this class
135 public string IndexerName;
137 public TypeContainer (TypeContainer parent, string name, Location l)
138 : base (parent, name, l)
141 types = new ArrayList ();
148 base_class_name = null;
150 //Console.WriteLine ("New class " + name + " inside " + n);
153 public AdditionResult AddConstant (Const constant)
156 string basename = constant.Name;
157 string fullname = Name + "." + basename;
159 if ((res = IsValid (fullname)) != AdditionResult.Success)
162 if (constants == null)
163 constants = new ArrayList ();
165 constants.Add (constant);
166 DefineName (fullname, constant);
168 return AdditionResult.Success;
171 public AdditionResult AddEnum (Mono.CSharp.Enum e)
175 if ((res = IsValid (e.Basename)) != AdditionResult.Success)
179 enums = new ArrayList ();
182 DefineName (e.Name, e);
184 return AdditionResult.Success;
187 public AdditionResult AddClass (Class c)
191 if ((res = IsValid (c.Basename)) != AdditionResult.Success)
194 DefineName (c.Name, c);
197 return AdditionResult.Success;
200 public AdditionResult AddStruct (Struct s)
204 if ((res = IsValid (s.Basename)) != AdditionResult.Success)
207 DefineName (s.Name, s);
210 return AdditionResult.Success;
213 public AdditionResult AddDelegate (Delegate d)
217 if ((res = IsValid (d.Basename)) != AdditionResult.Success)
220 if (delegates == null)
221 delegates = new ArrayList ();
223 DefineName (d.Name, d);
226 return AdditionResult.Success;
229 public AdditionResult AddMethod (Method method)
231 string basename = method.Name;
232 string fullname = Name + "." + basename;
234 Object value = defined_names [fullname];
236 if (value != null && (!(value is Method)))
237 return AdditionResult.NameExists;
239 if (basename == Basename)
240 return AdditionResult.EnclosingClash;
243 methods = new ArrayList ();
245 if (method.Name.IndexOf (".") != -1)
246 methods.Insert (0, method);
248 methods.Add (method);
251 DefineName (fullname, method);
253 return AdditionResult.Success;
256 public AdditionResult AddConstructor (Constructor c)
258 if (c.Name != Basename)
259 return AdditionResult.NotAConstructor;
261 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
264 have_static_constructor = true;
265 if (default_static_constructor != null){
266 Console.WriteLine ("I have a static constructor already");
267 Console.WriteLine (" " + default_static_constructor);
268 return AdditionResult.MethodExists;
271 default_static_constructor = c;
274 if (default_constructor != null)
275 return AdditionResult.MethodExists;
276 default_constructor = c;
279 if (instance_constructors == null)
280 instance_constructors = new ArrayList ();
282 instance_constructors.Add (c);
285 return AdditionResult.Success;
288 public AdditionResult AddInterface (Interface iface)
292 if ((res = IsValid (iface.Basename)) != AdditionResult.Success)
295 if (interfaces == null)
296 interfaces = new ArrayList ();
297 interfaces.Add (iface);
298 DefineName (iface.Name, iface);
300 return AdditionResult.Success;
303 public AdditionResult AddField (Field field)
306 string basename = field.Name;
307 string fullname = Name + "." + basename;
309 if ((res = IsValid (fullname)) != AdditionResult.Success)
313 fields = new ArrayList ();
317 if (field.HasInitializer){
318 if ((field.ModFlags & Modifiers.STATIC) != 0){
319 if (initialized_static_fields == null)
320 initialized_static_fields = new ArrayList ();
322 initialized_static_fields.Add (field);
325 // We have not seen a static constructor,
326 // but we will provide static initialization of fields
328 have_static_constructor = true;
330 if (initialized_fields == null)
331 initialized_fields = new ArrayList ();
333 initialized_fields.Add (field);
337 if ((field.ModFlags & Modifiers.STATIC) == 0)
338 have_nonstatic_fields = true;
340 DefineName (fullname, field);
341 return AdditionResult.Success;
344 public AdditionResult AddProperty (Property prop)
347 string basename = prop.Name;
348 string fullname = Name + "." + basename;
350 if ((res = IsValid (fullname)) != AdditionResult.Success)
353 if (properties == null)
354 properties = new ArrayList ();
356 if (prop.Name.IndexOf (".") != -1)
357 properties.Insert (0, prop);
359 properties.Add (prop);
360 DefineName (fullname, prop);
362 return AdditionResult.Success;
365 public AdditionResult AddEvent (Event e)
368 string basename = e.Name;
369 string fullname = Name + "." + basename;
371 if ((res = IsValid (fullname)) != AdditionResult.Success)
375 events = new ArrayList ();
378 DefineName (fullname, e);
380 return AdditionResult.Success;
383 public AdditionResult AddIndexer (Indexer i)
385 if (indexers == null)
386 indexers = new ArrayList ();
388 if (i.InterfaceType != null)
389 indexers.Insert (0, i);
393 return AdditionResult.Success;
396 public AdditionResult AddOperator (Operator op)
398 if (operators == null)
399 operators = new ArrayList ();
403 return AdditionResult.Success;
406 public void RegisterOrder (Interface iface)
408 if (interface_order == null)
409 interface_order = new ArrayList ();
411 interface_order.Add (iface);
414 public ArrayList Types {
420 public ArrayList Methods {
426 public ArrayList Constants {
432 public ArrayList Interfaces {
440 return base_class_name;
444 public ArrayList Bases {
454 public ArrayList Fields {
464 public ArrayList InstanceConstructors {
466 return instance_constructors;
470 public ArrayList Properties {
476 public ArrayList Events {
482 public ArrayList Enums {
488 public ArrayList Indexers {
494 public ArrayList Operators {
500 public ArrayList Delegates {
506 public Attributes OptAttributes {
512 public bool HaveStaticConstructor {
514 return have_static_constructor;
518 public virtual TypeAttributes TypeAttr {
520 return Modifiers.TypeAttr (ModFlags, this);
525 // Emits the instance field initializers
527 public bool EmitFieldInitializers (EmitContext ec)
530 ILGenerator ig = ec.ig;
531 Expression instance_expr;
534 fields = initialized_static_fields;
535 instance_expr = null;
537 fields = initialized_fields;
538 instance_expr = new This (Location.Null).Resolve (ec);
544 foreach (Field f in fields){
545 Expression e = f.GetInitializerExpression (ec);
549 Location l = f.Location;
550 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
551 fe.InstanceExpression = instance_expr;
552 Expression a = new Assign (fe, e, l);
558 if (a is ExpressionStatement)
559 ((ExpressionStatement) a).EmitStatement (ec);
561 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
569 // Defines the default constructors
571 void DefineDefaultConstructor (bool is_static)
576 c = new Constructor (Basename, Parameters.EmptyReadOnlyParameters,
577 new ConstructorBaseInitializer (
578 null, Parameters.EmptyReadOnlyParameters,
583 mods = Modifiers.STATIC;
589 c.Block = new Block (null);
593 public void ReportStructInitializedInstanceError ()
595 string n = TypeBuilder.FullName;
597 foreach (Field f in initialized_fields){
600 "`" + n + "." + f.Name + "': can not have " +
601 "instance field initializers in structs");
606 /// The pending methods that need to be implemented (interfaces or abstract methods)
608 public PendingImplementation Pending;
611 /// This function computes the Base class and also the
612 /// list of interfaces that the class or struct @c implements.
614 /// The return value is an array (might be null) of
615 /// interfaces implemented (as Types).
617 /// The @parent argument is set to the parent object or null
618 /// if this is `System.Object'.
620 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
622 ArrayList bases = Bases;
631 parent = TypeManager.value_type;
635 if (RootContext.StdLib)
636 parent = TypeManager.object_type;
637 else if (Name != "System.Object")
638 parent = TypeManager.object_type;
641 // If we are compiling our runtime,
642 // and we are defining ValueType, then our
643 // parent is `System.Object'.
645 if (!RootContext.StdLib && Name == "System.ValueType")
646 parent = TypeManager.object_type;
653 // Bases should be null if there are no bases at all
658 Expression name = (Expression) bases [0];
659 name = ResolveTypeExpr (name, false, Location);
666 Type first = name.Type;
671 } else if (first.IsSealed){
674 if (first.IsValueType)
675 detail = " (a class can not inherit from a struct/enum)";
677 Report.Error (509, "class `"+ Name +
678 "': Cannot inherit from sealed class `"+
679 first + "'" + detail);
683 parent = TypeManager.object_type;
687 if (!AsAccessible (parent, ModFlags))
688 Report.Error (60, Location,
689 "Inconsistent accessibility: base class `" +
690 TypeManager.CSharpName (parent) + "' is less " +
691 "accessible than class `" +
698 Type [] ifaces = new Type [count-start];
700 for (i = start, j = 0; i < count; i++, j++){
701 Expression name = (Expression) bases [i];
702 Expression resolved = ResolveTypeExpr (name, false, Location);
703 if (resolved == null)
706 bases [i] = resolved;
707 Type t = resolved.Type;
714 if (is_class == false && !t.IsInterface){
715 Report.Error (527, "In Struct `" + Name + "', type `"+
716 name +"' is not an interface");
723 Report.Error (527, "In Class `" + Name + "', type `"+
724 name+"' is not an interface");
730 for (int x = 0; x < j; x++) {
731 if (t == ifaces [x]) {
732 Report.Error (528, "`" + name + "' is already listed in interface list");
741 return TypeManager.ExpandInterfaces (ifaces);
745 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
747 public override TypeBuilder DefineType ()
753 if (TypeBuilder != null)
766 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
768 ifaces = GetClassBases (is_class, out parent, out error);
773 if (is_class && parent != null){
774 if (parent == TypeManager.enum_type ||
775 (parent == TypeManager.value_type && RootContext.StdLib) ||
776 parent == TypeManager.delegate_type ||
777 parent == TypeManager.array_type){
779 644, Location, "`" + Name + "' cannot inherit from " +
780 "special class `" + TypeManager.CSharpName (parent) + "'");
785 if (!is_class && TypeManager.value_type == null)
786 throw new Exception ();
788 TypeAttributes type_attributes = TypeAttr;
790 // if (parent_builder is ModuleBuilder) {
792 ModuleBuilder builder = CodeGen.ModuleBuilder;
793 TypeBuilder = builder.DefineType (
794 Name, type_attributes, parent, ifaces);
797 TypeBuilder builder = Parent.TypeBuilder;
798 TypeBuilder = builder.DefineNestedType (
799 Basename, type_attributes, parent, ifaces);
803 // Structs with no fields need to have at least one byte.
804 // The right thing would be to set the PackingSize in a DefineType
805 // but there are no functions that allow interfaces *and* the size to
809 if (!is_class && !have_nonstatic_fields){
810 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
811 FieldAttributes.Private);
812 // add interfaces that were not added at type creation
813 if (ifaces != null) {
814 foreach (Type i in ifaces)
815 TypeBuilder.AddInterfaceImplementation (i);
820 // Finish the setup for the EmitContext
822 ec.ContainerType = TypeBuilder;
824 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
826 if ((parent != null) &&
827 (parent == TypeManager.attribute_type ||
828 parent.IsSubclassOf (TypeManager.attribute_type))) {
829 RootContext.RegisterAttribute (this);
830 TypeManager.RegisterAttrType (TypeBuilder, this);
832 RootContext.RegisterOrder (this);
834 if (Interfaces != null) {
835 foreach (Interface iface in Interfaces)
840 foreach (TypeContainer tc in Types)
844 if (Delegates != null) {
845 foreach (Delegate d in Delegates)
850 foreach (Enum en in Enums)
860 /// Defines the MemberCore objects that are in the `list' Arraylist
862 /// The `defined_names' array contains a list of members defined in
865 static ArrayList remove_list = new ArrayList ();
866 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
870 remove_list.Clear ();
872 foreach (MemberCore mc in list){
873 if (!mc.Define (this)){
874 remove_list.Add (mc);
878 if (defined_names == null)
881 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
883 if (RootContext.WarningLevel >= 4){
884 if ((mc.ModFlags & Modifiers.NEW) != 0)
885 Warning_KewywordNewNotRequired (mc.Location, mc);
890 MemberInfo match = defined_names [idx];
892 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
896 // If we are both methods, let the method resolution emit warnings
898 if (match is MethodBase && mc is MethodCore)
901 if ((mc.ModFlags & Modifiers.NEW) == 0)
902 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
905 foreach (object o in remove_list)
908 remove_list.Clear ();
912 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
913 // class is consisten. Either it is `Item' or it is the name defined by all the
914 // indexers with the `IndexerName' attribute.
916 // Turns out that the IndexerNameAttribute is applied to each indexer,
917 // but it is never emitted, instead a DefaultName attribute is attached
920 void DefineIndexers ()
922 string class_indexer_name = null;
924 foreach (Indexer i in Indexers){
929 name = i.IndexerName;
931 if (i.InterfaceType != null)
934 if (class_indexer_name == null){
935 class_indexer_name = name;
939 if (name == class_indexer_name)
943 668, "Two indexers have different names, " +
944 " you should use the same name for all your indexers");
946 if (class_indexer_name == null)
947 class_indexer_name = "Item";
948 IndexerName = class_indexer_name;
951 static void Error_KeywordNotAllowed (Location loc)
953 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
957 /// Populates our TypeBuilder with fields and methods
959 public override bool DefineMembers (TypeContainer container)
961 MemberInfo [] defined_names = null;
963 if (interface_order != null){
964 foreach (Interface iface in interface_order)
965 if ((iface.ModFlags & Modifiers.NEW) == 0)
966 iface.DefineMembers (this);
968 Error_KeywordNotAllowed (iface.Location);
971 if (RootContext.WarningLevel > 1){
975 // This code throws an exception in the comparer
976 // I guess the string is not an object?
978 ptype = TypeBuilder.BaseType;
980 defined_names = (MemberInfo []) FindMembers (
981 ptype, MemberTypes.All & ~MemberTypes.Constructor,
982 BindingFlags.Public | BindingFlags.Instance |
983 BindingFlags.Static, null, null);
985 Array.Sort (defined_names, mif_compare);
989 if (constants != null)
990 DefineMembers (constants, defined_names);
993 DefineMembers (fields, defined_names);
996 if (instance_constructors == null){
997 if (default_constructor == null)
998 DefineDefaultConstructor (false);
1001 if (initialized_static_fields != null &&
1002 default_static_constructor == null)
1003 DefineDefaultConstructor (true);
1006 if (this is Struct){
1008 // Structs can not have initialized instance
1011 if (initialized_static_fields != null &&
1012 default_static_constructor == null)
1013 DefineDefaultConstructor (true);
1015 if (initialized_fields != null)
1016 ReportStructInitializedInstanceError ();
1019 Pending = PendingImplementation.GetPendingImplementations (this);
1022 // Constructors are not in the defined_names array
1024 if (instance_constructors != null)
1025 DefineMembers (instance_constructors, null);
1027 if (default_static_constructor != null)
1028 default_static_constructor.Define (this);
1030 if (methods != null)
1031 DefineMembers (methods, defined_names);
1033 if (properties != null)
1034 DefineMembers (properties, defined_names);
1037 DefineMembers (events, defined_names);
1039 if (indexers != null) {
1042 IndexerName = "Item";
1044 if (operators != null){
1045 DefineMembers (operators, null);
1047 CheckPairedOperators ();
1051 DefineMembers (enums, defined_names);
1053 if (delegates != null)
1054 DefineMembers (delegates, defined_names);
1057 if (TypeBuilder.BaseType != null)
1058 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1060 member_cache = new MemberCache (this);
1066 public override bool Define (TypeContainer container)
1068 if (interface_order != null){
1069 foreach (Interface iface in interface_order)
1070 if ((iface.ModFlags & Modifiers.NEW) == 0)
1071 iface.Define (this);
1078 /// This function is based by a delegate to the FindMembers routine
1080 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1086 /// This filter is used by FindMembers, and we just keep
1087 /// a global for the filter to `AlwaysAccept'
1089 static MemberFilter accepting_filter;
1093 /// A member comparission method based on name only
1095 static IComparer mif_compare;
1097 static TypeContainer ()
1099 accepting_filter = new MemberFilter (AlwaysAccept);
1100 mif_compare = new MemberInfoCompare ();
1104 /// This method returns the members of this type just like Type.FindMembers would
1105 /// Only, we need to use this for types which are _being_ defined because MS'
1106 /// implementation can't take care of that.
1109 // FIXME: return an empty static array instead of null, that cleans up
1110 // some code and is consistent with some coding conventions I just found
1114 // Notice that in various cases we check if our field is non-null,
1115 // something that would normally mean that there was a bug elsewhere.
1117 // The problem happens while we are defining p-invoke methods, as those
1118 // will trigger a FindMembers, but this happens before things are defined
1120 // Since the whole process is a no-op, it is fine to check for null here.
1122 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1123 MemberFilter filter, object criteria)
1125 ArrayList members = new ArrayList ();
1128 if ((bf & BindingFlags.Public) != 0)
1129 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1131 if ((bf & BindingFlags.NonPublic) != 0)
1132 modflags |= Modifiers.PRIVATE;
1134 int static_mask = 0, static_flags = 0;
1135 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1136 case BindingFlags.Static:
1137 static_mask = static_flags = Modifiers.STATIC;
1140 case BindingFlags.Instance:
1141 static_mask = Modifiers.STATIC;
1146 static_mask = static_flags = 0;
1150 Timer.StartTimer (TimerType.TcFindMembers);
1153 filter = accepting_filter;
1155 if ((mt & MemberTypes.Field) != 0) {
1156 if (fields != null) {
1157 foreach (Field f in fields) {
1158 if ((f.ModFlags & modflags) == 0)
1160 if ((f.ModFlags & static_mask) != static_flags)
1163 FieldBuilder fb = f.FieldBuilder;
1164 if (fb != null && filter (fb, criteria) == true)
1169 if (constants != null) {
1170 foreach (Const con in constants) {
1171 if ((con.ModFlags & modflags) == 0)
1173 if ((con.ModFlags & static_mask) != static_flags)
1176 FieldBuilder fb = con.FieldBuilder;
1177 if (fb != null && filter (fb, criteria) == true)
1183 if ((mt & MemberTypes.Method) != 0) {
1184 if (methods != null) {
1185 foreach (Method m in methods) {
1186 if ((m.ModFlags & modflags) == 0)
1188 if ((m.ModFlags & static_mask) != static_flags)
1191 MethodBuilder mb = m.MethodBuilder;
1193 if (mb != null && filter (mb, criteria) == true)
1198 if (operators != null){
1199 foreach (Operator o in operators) {
1200 if ((o.ModFlags & modflags) == 0)
1202 if ((o.ModFlags & static_mask) != static_flags)
1205 MethodBuilder ob = o.OperatorMethodBuilder;
1206 if (ob != null && filter (ob, criteria) == true)
1211 if (properties != null){
1212 foreach (Property p in properties){
1213 if ((p.ModFlags & modflags) == 0)
1215 if ((p.ModFlags & static_mask) != static_flags)
1221 if (b != null && filter (b, criteria) == true)
1225 if (b != null && filter (b, criteria) == true)
1230 if (indexers != null){
1231 foreach (Indexer ix in indexers){
1232 if ((ix.ModFlags & modflags) == 0)
1234 if ((ix.ModFlags & static_mask) != static_flags)
1240 if (b != null && filter (b, criteria) == true)
1244 if (b != null && filter (b, criteria) == true)
1250 if ((mt & MemberTypes.Event) != 0) {
1252 foreach (Event e in events) {
1253 if ((e.ModFlags & modflags) == 0)
1255 if ((e.ModFlags & static_mask) != static_flags)
1258 MemberInfo eb = e.EventBuilder;
1259 if (eb != null && filter (eb, criteria) == true)
1260 members.Add (e.EventBuilder);
1264 if ((mt & MemberTypes.Property) != 0){
1265 if (properties != null)
1266 foreach (Property p in properties) {
1267 if ((p.ModFlags & modflags) == 0)
1269 if ((p.ModFlags & static_mask) != static_flags)
1272 MemberInfo pb = p.PropertyBuilder;
1273 if (pb != null && filter (pb, criteria) == true) {
1274 members.Add (p.PropertyBuilder);
1278 if (indexers != null)
1279 foreach (Indexer ix in indexers) {
1280 if ((ix.ModFlags & modflags) == 0)
1282 if ((ix.ModFlags & static_mask) != static_flags)
1285 MemberInfo ib = ix.PropertyBuilder;
1286 if (ib != null && filter (ib, criteria) == true) {
1287 members.Add (ix.PropertyBuilder);
1292 if ((mt & MemberTypes.NestedType) != 0) {
1294 foreach (TypeContainer t in types) {
1295 if ((t.ModFlags & modflags) == 0)
1298 TypeBuilder tb = t.TypeBuilder;
1299 if (tb != null && (filter (tb, criteria) == true))
1305 foreach (Enum en in enums){
1306 if ((en.ModFlags & modflags) == 0)
1309 TypeBuilder tb = en.TypeBuilder;
1310 if (tb != null && (filter (tb, criteria) == true))
1315 if (delegates != null){
1316 foreach (Delegate d in delegates){
1317 if ((d.ModFlags & modflags) == 0)
1320 TypeBuilder tb = d.TypeBuilder;
1321 if (tb != null && (filter (tb, criteria) == true))
1326 if (interfaces != null){
1327 foreach (Interface iface in interfaces){
1328 if ((iface.ModFlags & modflags) == 0)
1331 TypeBuilder tb = iface.TypeBuilder;
1332 if (tb != null && (filter (tb, criteria) == true))
1338 if ((mt & MemberTypes.Constructor) != 0){
1339 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1340 foreach (Constructor c in instance_constructors){
1341 ConstructorBuilder cb = c.ConstructorBuilder;
1343 if (filter (cb, criteria) == true)
1348 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1349 ConstructorBuilder cb =
1350 default_static_constructor.ConstructorBuilder;
1353 if (filter (cb, criteria) == true)
1359 // Lookup members in parent if requested.
1361 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1362 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1363 members.AddRange (list);
1366 Timer.StopTimer (TimerType.TcFindMembers);
1368 return new MemberList (members);
1371 public override MemberCache MemberCache {
1373 return member_cache;
1377 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1378 MemberFilter filter, object criteria)
1380 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1383 return tc.FindMembers (mt, bf, filter, criteria);
1385 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1389 // FindMethods will look for methods not only in the type `t', but in
1390 // any interfaces implemented by the type.
1392 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1393 MemberFilter filter, object criteria)
1399 /// Emits the values for the constants
1401 public void EmitConstants ()
1403 if (constants != null)
1404 foreach (Const con in constants)
1405 con.EmitConstant (this);
1410 /// Emits the code, this step is performed after all
1411 /// the types, enumerations, constructors
1415 if (instance_constructors != null)
1416 foreach (Constructor c in instance_constructors)
1419 if (default_static_constructor != null)
1420 default_static_constructor.Emit (this);
1422 if (methods != null)
1423 foreach (Method m in methods)
1426 if (operators != null)
1427 foreach (Operator o in operators)
1430 if (properties != null)
1431 foreach (Property p in properties)
1434 if (indexers != null){
1435 foreach (Indexer ix in indexers)
1438 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1439 this, IndexerName, ModFlags, Location);
1440 TypeBuilder.SetCustomAttribute (cb);
1444 foreach (Field f in fields)
1447 if (events != null){
1448 foreach (Event e in Events)
1452 if (Pending != null)
1453 if (Pending.VerifyPendingMethods ())
1456 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
1459 // Check for internal or private fields that were never assigned
1461 if (RootContext.WarningLevel >= 3) {
1462 if (fields != null){
1463 foreach (Field f in fields) {
1464 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1469 169, f.Location, "Private field " +
1470 MakeName (f.Name) + " is never used");
1475 // Only report 649 on level 4
1477 if (RootContext.WarningLevel < 4)
1480 if ((f.status & Field.Status.ASSIGNED) != 0)
1485 "Field " + MakeName (f.Name) + " is never assigned " +
1486 " to and will always have its default value");
1490 if (events != null){
1491 foreach (Event e in events){
1493 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1498 // if (types != null)
1499 // foreach (TypeContainer tc in types)
1503 public override void CloseType ()
1508 TypeBuilder.CreateType ();
1510 } catch (TypeLoadException){
1512 // This is fine, the code still created the type
1514 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1515 // Console.WriteLine (e.Message);
1517 Console.WriteLine ("In type: " + Name);
1522 foreach (Enum en in Enums)
1525 if (interface_order != null){
1526 foreach (Interface iface in interface_order)
1531 foreach (TypeContainer tc in Types)
1535 foreach (TypeContainer tc in Types)
1536 if (!(tc is Struct))
1540 if (Delegates != null)
1541 foreach (Delegate d in Delegates)
1545 public string MakeName (string n)
1547 return "`" + Name + "." + n + "'";
1550 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1553 108, l, "The keyword new is required on " +
1554 MakeName (mi.Name) + " because it hides `" +
1555 mi.ReflectedType.Name + "." + mi.Name + "'");
1558 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1561 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1562 "inherited member, the keyword new is not required");
1565 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1571 // Performs the validation on a Method's modifiers (properties have
1572 // the same properties).
1574 public bool MethodModifiersValid (int flags, string n, Location loc)
1576 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1577 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1578 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1582 // At most one of static, virtual or override
1584 if ((flags & Modifiers.STATIC) != 0){
1585 if ((flags & vao) != 0){
1587 112, loc, "static method " + MakeName (n) + "can not be marked " +
1588 "as virtual, abstract or override");
1593 if (this is Struct){
1594 if ((flags & va) != 0){
1595 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1600 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1602 113, loc, MakeName (n) +
1603 " marked as override cannot be marked as new or virtual");
1608 // If the declaration includes the abstract modifier, then the
1609 // declaration does not include static, virtual or extern
1611 if ((flags & Modifiers.ABSTRACT) != 0){
1612 if ((flags & Modifiers.EXTERN) != 0){
1614 180, loc, MakeName (n) + " can not be both abstract and extern");
1618 if ((flags & Modifiers.VIRTUAL) != 0){
1620 503, loc, MakeName (n) + " can not be both abstract and virtual");
1624 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1626 513, loc, MakeName (n) +
1627 " is abstract but its container class is not");
1633 if ((flags & Modifiers.PRIVATE) != 0){
1634 if ((flags & vao) != 0){
1636 621, loc, MakeName (n) +
1637 " virtual or abstract members can not be private");
1642 if ((flags & Modifiers.SEALED) != 0){
1643 if ((flags & Modifiers.OVERRIDE) == 0){
1645 238, loc, MakeName (n) +
1646 " cannot be sealed because it is not an override");
1654 // Access level of a type.
1657 ProtectedInternal = 1,
1663 // Check whether `flags' denotes a more restricted access than `level'
1664 // and return the new level.
1665 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1667 AccessLevel old_level = level;
1669 if ((flags & Modifiers.INTERNAL) != 0) {
1670 if ((flags & Modifiers.PROTECTED) != 0) {
1671 if ((int) level < (int) AccessLevel.ProtectedInternal)
1672 level = AccessLevel.ProtectedInternal;
1674 if ((int) level < (int) AccessLevel.Internal)
1675 level = AccessLevel.Internal;
1677 } else if ((flags & Modifiers.PROTECTED) != 0) {
1678 if ((int) level < (int) AccessLevel.Protected)
1679 level = AccessLevel.Protected;
1680 } else if ((flags & Modifiers.PRIVATE) != 0)
1681 level = AccessLevel.Private;
1686 // Return the access level for a new member which is defined in the current
1687 // TypeContainer with access modifiers `flags'.
1688 AccessLevel GetAccessLevel (int flags)
1690 if ((flags & Modifiers.PRIVATE) != 0)
1691 return AccessLevel.Private;
1694 if (!IsTopLevel && (Parent != null))
1695 level = Parent.GetAccessLevel (flags);
1697 level = AccessLevel.Public;
1699 return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1702 // Return the access level for type `t', but don't give more access than `flags'.
1703 static AccessLevel GetAccessLevel (Type t, int flags)
1705 if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1706 return AccessLevel.Private;
1709 if (TypeManager.IsBuiltinType (t))
1710 return AccessLevel.Public;
1711 else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1712 level = GetAccessLevel (t.DeclaringType, flags);
1714 level = CheckAccessLevel (AccessLevel.Public, flags);
1717 if (t.IsNestedPublic)
1720 if (t.IsNestedAssembly || t.IsNotPublic) {
1721 if ((int) level < (int) AccessLevel.Internal)
1722 level = AccessLevel.Internal;
1725 if (t.IsNestedFamily) {
1726 if ((int) level < (int) AccessLevel.Protected)
1727 level = AccessLevel.Protected;
1730 if (t.IsNestedFamORAssem) {
1731 if ((int) level < (int) AccessLevel.ProtectedInternal)
1732 level = AccessLevel.ProtectedInternal;
1739 // Returns true if `parent' is as accessible as the flags `flags'
1740 // given for this member.
1742 public bool AsAccessible (Type parent, int flags)
1744 while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1745 parent = parent.GetElementType ();
1747 AccessLevel level = GetAccessLevel (flags);
1748 AccessLevel level2 = GetAccessLevel (parent, flags);
1750 return (int) level >= (int) level2;
1753 Hashtable builder_and_args;
1755 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1757 if (builder_and_args == null)
1758 builder_and_args = new Hashtable ();
1763 /// Performs checks for an explicit interface implementation. First it
1764 /// checks whether the `interface_type' is a base inteface implementation.
1765 /// Then it checks whether `name' exists in the interface type.
1767 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1771 if (ifaces != null){
1772 foreach (Type t in ifaces){
1773 if (t == interface_type){
1781 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1788 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1790 Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1797 string IMemberContainer.Name {
1803 Type IMemberContainer.Type {
1809 IMemberContainer IMemberContainer.Parent {
1811 return parent_container;
1815 MemberCache IMemberContainer.MemberCache {
1817 return member_cache;
1821 bool IMemberContainer.IsInterface {
1827 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1829 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1833 // Operator pair checking
1836 class OperatorEntry {
1838 public Type ret_type;
1839 public Type type1, type2;
1841 public Operator.OpType ot;
1843 public OperatorEntry (int f, Operator o)
1847 ret_type = o.OperatorMethod.GetReturnType ();
1848 Type [] pt = o.OperatorMethod.ParameterTypes;
1852 ot = o.OperatorType;
1855 public override int GetHashCode ()
1857 return ret_type.GetHashCode ();
1860 public override bool Equals (object o)
1862 OperatorEntry other = (OperatorEntry) o;
1864 if (other.ret_type != ret_type)
1866 if (other.type1 != type1)
1868 if (other.type2 != type2)
1875 // Checks that some operators come in pairs:
1881 // They are matched based on the return type and the argument types
1883 void CheckPairedOperators ()
1885 Hashtable pairs = new Hashtable (null, null);
1886 Operator true_op = null;
1887 Operator false_op = null;
1889 // Register all the operators we care about.
1890 foreach (Operator op in operators){
1893 switch (op.OperatorType){
1894 case Operator.OpType.Equality:
1896 case Operator.OpType.Inequality:
1899 case Operator.OpType.True:
1902 case Operator.OpType.False:
1906 case Operator.OpType.GreaterThan:
1908 case Operator.OpType.LessThan:
1911 case Operator.OpType.GreaterThanOrEqual:
1913 case Operator.OpType.LessThanOrEqual:
1919 OperatorEntry oe = new OperatorEntry (reg, op);
1921 object o = pairs [oe];
1925 oe = (OperatorEntry) o;
1930 if (true_op != null){
1931 if (false_op == null)
1932 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
1933 } else if (false_op != null)
1934 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
1937 // Look for the mistakes.
1939 foreach (DictionaryEntry de in pairs){
1940 OperatorEntry oe = (OperatorEntry) de.Key;
1947 case Operator.OpType.Equality:
1950 case Operator.OpType.Inequality:
1953 case Operator.OpType.GreaterThan:
1956 case Operator.OpType.LessThan:
1959 case Operator.OpType.GreaterThanOrEqual:
1962 case Operator.OpType.LessThanOrEqual:
1966 Report.Error (216, oe.op.Location,
1967 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
1974 public class Class : TypeContainer {
1976 // Modifiers allowed in a class declaration
1978 public const int AllowedModifiers =
1981 Modifiers.PROTECTED |
1982 Modifiers.INTERNAL |
1984 Modifiers.ABSTRACT |
1988 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1989 : base (parent, name, l)
1993 if (parent.Parent == null)
1994 accmods = Modifiers.INTERNAL;
1996 accmods = Modifiers.PRIVATE;
1998 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1999 this.attributes = attrs;
2003 // FIXME: How do we deal with the user specifying a different
2006 public override TypeAttributes TypeAttr {
2008 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2013 public class Struct : TypeContainer {
2015 // Modifiers allowed in a struct declaration
2017 public const int AllowedModifiers =
2020 Modifiers.PROTECTED |
2021 Modifiers.INTERNAL |
2025 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2026 : base (parent, name, l)
2030 if (parent.Parent == null)
2031 accmods = Modifiers.INTERNAL;
2033 accmods = Modifiers.PRIVATE;
2035 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2037 this.ModFlags |= Modifiers.SEALED;
2038 this.attributes = attrs;
2043 // FIXME: Allow the user to specify a different set of attributes
2044 // in some cases (Sealed for example is mandatory for a class,
2045 // but what SequentialLayout can be changed
2047 public override TypeAttributes TypeAttr {
2049 return base.TypeAttr |
2050 TypeAttributes.SequentialLayout |
2051 TypeAttributes.Sealed |
2052 TypeAttributes.BeforeFieldInit;
2057 public abstract class MethodCore : MemberBase {
2058 public readonly Parameters Parameters;
2059 protected Block block;
2062 // Parameters, cached for semantic analysis.
2064 protected InternalParameters parameter_info;
2065 protected Type [] parameter_types;
2067 public MethodCore (Expression type, int mod, int allowed_mod, string name,
2068 Attributes attrs, Parameters parameters, Location loc)
2069 : base (type, mod, allowed_mod, name, attrs, loc)
2071 Parameters = parameters;
2075 // Returns the System.Type array for the parameters of this method
2077 public Type [] ParameterTypes {
2079 return parameter_types;
2083 public InternalParameters ParameterInfo
2086 return parameter_info;
2090 public Block Block {
2100 protected virtual bool DoDefineParameters (TypeContainer container)
2102 // Check if arguments were correct
2103 parameter_types = Parameters.GetParameterInfo (container);
2104 if ((parameter_types == null) || !CheckParameters (container, parameter_types))
2107 parameter_info = new InternalParameters (container, Parameters);
2112 public CallingConventions GetCallingConvention (bool is_class)
2114 CallingConventions cc = 0;
2116 cc = Parameters.GetCallingConvention ();
2119 if ((ModFlags & Modifiers.STATIC) == 0)
2120 cc |= CallingConventions.HasThis;
2122 // FIXME: How is `ExplicitThis' used in C#?
2128 // The method's attributes are passed in because we need to extract
2129 // the "return:" attribute from there to apply on the return type
2131 public void LabelParameters (EmitContext ec, MethodBase builder, Attributes method_attrs)
2134 // Define each type attribute (in/out/ref) and
2135 // the argument names.
2137 Parameter [] p = Parameters.FixedParameters;
2140 MethodBuilder mb = null;
2141 ConstructorBuilder cb = null;
2143 if (builder is MethodBuilder)
2144 mb = (MethodBuilder) builder;
2146 cb = (ConstructorBuilder) builder;
2149 for (i = 0; i < p.Length; i++) {
2150 ParameterBuilder pb;
2151 ParameterAttributes par_attr = p [i].Attributes;
2154 pb = cb.DefineParameter (
2155 i + 1, par_attr, p [i].Name);
2157 pb = mb.DefineParameter (
2158 i + 1, par_attr, p [i].Name);
2160 Attributes attr = p [i].OptAttributes;
2162 Attribute.ApplyAttributes (ec, pb, pb, attr);
2164 if (par_attr == ParameterAttributes.Out){
2165 if (attr.Contains (TypeManager.in_attribute_type))
2166 Report.Error (36, Location, "Can not use [In] attribute on out parameter");
2172 if (Parameters.ArrayParameter != null){
2173 ParameterBuilder pb;
2174 Parameter array_param = Parameters.ArrayParameter;
2177 pb = cb.DefineParameter (
2178 i + 1, array_param.Attributes,
2181 pb = mb.DefineParameter (
2182 i + 1, array_param.Attributes,
2185 CustomAttributeBuilder a = new CustomAttributeBuilder (
2186 TypeManager.cons_param_array_attribute, new object [0]);
2188 pb.SetCustomAttribute (a);
2192 // And now for the return type attribute decoration
2194 ParameterBuilder ret_pb;
2195 Attributes ret_attrs = null;
2197 if (mb == null || method_attrs == null)
2200 foreach (AttributeSection asec in method_attrs.AttributeSections) {
2202 if (asec.Target != "return")
2205 if (ret_attrs == null)
2206 ret_attrs = new Attributes (asec);
2208 ret_attrs.AddAttributeSection (asec);
2211 if (ret_attrs != null) {
2213 ret_pb = mb.DefineParameter (0, ParameterAttributes.None, "");
2214 Attribute.ApplyAttributes (ec, ret_pb, ret_pb, ret_attrs);
2215 } catch (ArgumentOutOfRangeException) {
2218 ".NET SDK 1.0 does not permit to set custom attributes to the return type of a method");
2224 public class Method : MethodCore {
2225 public MethodBuilder MethodBuilder;
2226 public MethodData MethodData;
2229 /// Modifiers allowed in a class declaration
2231 const int AllowedModifiers =
2234 Modifiers.PROTECTED |
2235 Modifiers.INTERNAL |
2240 Modifiers.OVERRIDE |
2241 Modifiers.ABSTRACT |
2246 // return_type can be "null" for VOID values.
2248 public Method (Expression return_type, int mod, string name, Parameters parameters,
2249 Attributes attrs, Location l)
2250 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2254 // Returns the `System.Type' for the ReturnType of this
2255 // function. Provides a nice cache. (used between semantic analysis
2256 // and actual code generation
2258 public Type GetReturnType ()
2263 // Whether this is an operator method.
2264 public bool IsOperator;
2266 void DuplicateEntryPoint (MethodInfo b, Location location)
2270 "Program `" + CodeGen.FileName +
2271 "' has more than one entry point defined: `" +
2272 TypeManager.CSharpSignature(b) + "'");
2275 void Report28 (MethodInfo b)
2277 if (RootContext.WarningLevel < 4)
2282 "`" + TypeManager.CSharpSignature(b) +
2283 "' has the wrong signature to be an entry point");
2286 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2288 if (b.ReturnType != TypeManager.void_type &&
2289 b.ReturnType != TypeManager.int32_type)
2292 if (pinfo.Count == 0)
2295 if (pinfo.Count > 1)
2298 Type t = pinfo.ParameterType(0);
2300 (t.GetArrayRank() == 1) &&
2301 (t.GetElementType() == TypeManager.string_type) &&
2302 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2309 // Checks our base implementation if any
2311 protected override bool CheckBase (TypeContainer container)
2313 // Check whether arguments were correct.
2314 if (!DoDefineParameters (container))
2317 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2319 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2323 mi_this = TypeContainer.FindMembers (
2324 container.TypeBuilder, MemberTypes.Method,
2325 BindingFlags.NonPublic | BindingFlags.Public |
2326 BindingFlags.Static | BindingFlags.Instance |
2327 BindingFlags.DeclaredOnly,
2328 MethodSignature.method_signature_filter, ms);
2330 if (mi_this.Count > 0) {
2331 Report.Error (111, Location, "Class `" + container.Name + "' " +
2332 "already defines a member called `" + Name + "' " +
2333 "with the same parameter types");
2339 // Verify if the parent has a type with the same name, and then
2340 // check whether we have to create a new slot for it or not.
2342 Type ptype = container.TypeBuilder.BaseType;
2344 // ptype is only null for System.Object while compiling corlib.
2346 MemberList mi, mi_static, mi_instance;
2348 mi_instance = TypeContainer.FindMembers (
2349 ptype, MemberTypes.Method,
2350 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2351 MethodSignature.inheritable_method_signature_filter,
2354 if (mi_instance.Count > 0){
2357 mi_static = TypeContainer.FindMembers (
2358 ptype, MemberTypes.Method,
2359 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2360 MethodSignature.inheritable_method_signature_filter, ms);
2362 if (mi_static.Count > 0)
2368 if (mi != null && mi.Count > 0){
2369 parent_method = (MethodInfo) mi [0];
2370 string name = parent_method.DeclaringType.Name + "." +
2373 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
2376 if ((ModFlags & Modifiers.NEW) == 0) {
2377 Type parent_ret = TypeManager.TypeToCoreType (
2378 parent_method.ReturnType);
2380 if (parent_ret != MemberType) {
2382 508, Location, container.MakeName (Name) + ": cannot " +
2383 "change return type when overriding " +
2384 "inherited member " + name);
2389 if ((ModFlags & Modifiers.NEW) != 0)
2390 WarningNotHiding (container);
2392 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2393 Report.Error (115, Location,
2394 container.MakeName (Name) +
2395 " no suitable methods found to override");
2398 } else if ((ModFlags & Modifiers.NEW) != 0)
2399 WarningNotHiding (container);
2407 public override bool Define (TypeContainer container)
2409 if (!DoDefine (container))
2412 if (!CheckBase (container))
2415 CallingConventions cc = GetCallingConvention (container is Class);
2417 MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2418 ParameterInfo, cc, OptAttributes,
2419 ModFlags, flags, true);
2421 if (!MethodData.Define (container))
2424 MethodBuilder = MethodData.MethodBuilder;
2427 // This is used to track the Entry Point,
2429 if (Name == "Main" &&
2430 ((ModFlags & Modifiers.STATIC) != 0) &&
2431 (RootContext.MainClass == null ||
2432 RootContext.MainClass == container.TypeBuilder.FullName)){
2433 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2434 if (RootContext.EntryPoint == null) {
2435 RootContext.EntryPoint = MethodBuilder;
2436 RootContext.EntryPointLocation = Location;
2438 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2439 DuplicateEntryPoint (MethodBuilder, Location);
2442 Report28(MethodBuilder);
2451 public void Emit (TypeContainer container)
2453 MethodData.Emit (container, Block, this);
2458 public abstract class ConstructorInitializer {
2459 ArrayList argument_list;
2460 ConstructorInfo parent_constructor;
2461 Parameters parameters;
2464 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2467 this.argument_list = argument_list;
2468 this.parameters = parameters;
2472 public ArrayList Arguments {
2474 return argument_list;
2478 public bool Resolve (EmitContext ec)
2480 Expression parent_constructor_group;
2483 ec.CurrentBlock = new Block (null, true, parameters);
2485 if (argument_list != null){
2486 foreach (Argument a in argument_list){
2487 if (!a.Resolve (ec, loc))
2492 ec.CurrentBlock = null;
2494 if (this is ConstructorBaseInitializer) {
2495 if (ec.ContainerType.BaseType == null)
2498 t = ec.ContainerType.BaseType;
2499 if (ec.ContainerType.IsValueType) {
2500 Report.Error (522, loc,
2501 "structs cannot call base class constructors");
2505 t = ec.ContainerType;
2507 parent_constructor_group = Expression.MemberLookup (
2508 ec, t, null, t, ".ctor",
2509 MemberTypes.Constructor,
2510 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2513 if (parent_constructor_group == null){
2514 Report.Error (1501, loc,
2515 "Can not find a constructor for this argument list");
2519 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2520 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2522 if (parent_constructor == null){
2523 Report.Error (1501, loc,
2524 "Can not find a constructor for this argument list");
2531 public void Emit (EmitContext ec)
2533 if (parent_constructor != null){
2534 ec.Mark (loc, false);
2536 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2538 Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2543 public class ConstructorBaseInitializer : ConstructorInitializer {
2544 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2545 base (argument_list, pars, l)
2550 public class ConstructorThisInitializer : ConstructorInitializer {
2551 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2552 base (argument_list, pars, l)
2557 public class Constructor : MethodCore {
2558 public ConstructorBuilder ConstructorBuilder;
2559 public ConstructorInitializer Initializer;
2560 new public Attributes OptAttributes;
2563 // Modifiers allowed for a constructor.
2565 public const int AllowedModifiers =
2567 Modifiers.PROTECTED |
2568 Modifiers.INTERNAL |
2575 // The spec claims that static is not permitted, but
2576 // my very own code has static constructors.
2578 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2579 : base (null, 0, AllowedModifiers, name, null, args, l)
2585 // Returns true if this is a default constructor
2587 public bool IsDefault ()
2589 if ((ModFlags & Modifiers.STATIC) != 0)
2590 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2591 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2594 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2595 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2596 (Initializer is ConstructorBaseInitializer) &&
2597 (Initializer.Arguments == null);
2601 // Creates the ConstructorBuilder
2603 public override bool Define (TypeContainer container)
2605 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2606 MethodAttributes.SpecialName);
2608 // Check if arguments were correct.
2609 if (!DoDefineParameters (container))
2612 if ((ModFlags & Modifiers.STATIC) != 0)
2613 ca |= MethodAttributes.Static;
2615 if (container is Struct && ParameterTypes.Length == 0){
2618 "Structs can not contain explicit parameterless " +
2622 ca |= MethodAttributes.HideBySig;
2624 if ((ModFlags & Modifiers.PUBLIC) != 0)
2625 ca |= MethodAttributes.Public;
2626 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2627 if ((ModFlags & Modifiers.INTERNAL) != 0)
2628 ca |= MethodAttributes.FamORAssem;
2630 ca |= MethodAttributes.Family;
2631 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2632 ca |= MethodAttributes.Assembly;
2633 else if (IsDefault ())
2634 ca |= MethodAttributes.Public;
2636 ca |= MethodAttributes.Private;
2639 ConstructorBuilder = container.TypeBuilder.DefineConstructor (
2640 ca, GetCallingConvention (container is Class), ParameterTypes);
2643 // HACK because System.Reflection.Emit is lame
2645 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2648 "Class `" +container.Name+ "' already contains a definition with the " +
2649 "same return value and parameter types for constructor `" + Name
2660 public void Emit (TypeContainer container)
2662 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2663 EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
2666 // extern methods have no bodies
2668 if ((ModFlags & Modifiers.EXTERN) != 0) {
2669 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
2671 179, Location, "External constructor `" +
2672 TypeManager.CSharpSignature (ConstructorBuilder) +
2673 "' can not have a body");
2676 } else if (block == null) {
2678 501, Location, "Constructor `" +
2679 TypeManager.CSharpSignature (ConstructorBuilder) +
2680 "' must declare a body since it is not marked extern");
2684 if ((ModFlags & Modifiers.STATIC) == 0){
2685 if (container is Class && Initializer == null)
2686 Initializer = new ConstructorBaseInitializer (
2687 null, Parameters.EmptyReadOnlyParameters, Location.Null);
2691 // Spec mandates that Initializers will not have
2695 if (Initializer != null && !Initializer.Resolve (ec))
2697 ec.IsStatic = false;
2700 LabelParameters (ec, ConstructorBuilder, OptAttributes);
2702 SymbolWriter sw = CodeGen.SymbolWriter;
2703 bool generate_debugging = false;
2705 if ((sw != null) && (block != null) &&
2706 !Location.IsNull (Location) &&
2707 !Location.IsNull (block.EndLocation)) {
2709 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
2711 generate_debugging = true;
2715 // Classes can have base initializers and instance field initializers.
2717 if (container is Class){
2718 if ((ModFlags & Modifiers.STATIC) == 0)
2719 container.EmitFieldInitializers (ec);
2721 if (Initializer != null)
2722 Initializer.Emit (ec);
2724 if ((ModFlags & Modifiers.STATIC) != 0)
2725 container.EmitFieldInitializers (ec);
2727 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes);
2729 // If this is a non-static `struct' constructor and doesn't have any
2730 // initializer, it must initialize all of the struct's fields.
2731 if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
2732 Block.AddThisVariable (container, Location);
2734 ec.EmitTopBlock (block, ParameterInfo, Location);
2736 if (generate_debugging)
2743 public class MethodData {
2745 // The return type of this method
2747 public readonly Type ReturnType;
2748 public readonly Type[] ParameterTypes;
2749 public readonly InternalParameters ParameterInfo;
2750 public readonly CallingConventions CallingConventions;
2751 public readonly Attributes OptAttributes;
2752 public readonly Location Location;
2755 // Are we implementing an interface ?
2757 public bool IsImplementing = false;
2762 protected MemberBase member;
2763 protected int modifiers;
2764 protected MethodAttributes flags;
2765 protected bool is_method;
2766 protected string accessor_name;
2767 ArrayList conditionals;
2769 MethodBuilder builder = null;
2770 public MethodBuilder MethodBuilder {
2776 public MethodData (MemberBase member, string name, Type return_type,
2777 Type [] parameter_types, InternalParameters parameters,
2778 CallingConventions cc, Attributes opt_attrs,
2779 int modifiers, MethodAttributes flags, bool is_method)
2781 this.member = member;
2782 this.accessor_name = name;
2783 this.ReturnType = return_type;
2784 this.ParameterTypes = parameter_types;
2785 this.ParameterInfo = parameters;
2786 this.CallingConventions = cc;
2787 this.OptAttributes = opt_attrs;
2788 this.modifiers = modifiers;
2790 this.is_method = is_method;
2791 this.Location = member.Location;
2792 this.conditionals = new ArrayList ();
2798 Attribute dllimport_attribute = null;
2799 string obsolete = null;
2800 bool obsolete_error = false;
2802 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2804 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2807 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2808 if (asec.Attributes == null)
2811 foreach (Attribute a in asec.Attributes) {
2812 if (a.Name == "Conditional") {
2813 if (!ApplyConditionalAttribute (a))
2815 } else if (a.Name == "Obsolete") {
2816 if (!ApplyObsoleteAttribute (a))
2818 } else if (a.Name.IndexOf ("DllImport") != -1) {
2820 a.Type = TypeManager.dllimport_type;
2821 Attribute.Error_AttributeNotValidForElement (a, Location);
2824 if (!ApplyDllImportAttribute (a))
2834 // Applies the `DllImport' attribute to the method.
2836 protected virtual bool ApplyDllImportAttribute (Attribute a)
2838 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2839 if ((modifiers & extern_static) != extern_static) {
2840 Report.Error (601, Location,
2841 "The DllImport attribute must be specified on a method " +
2842 "marked `static' and `extern'.");
2846 flags |= MethodAttributes.PinvokeImpl;
2847 dllimport_attribute = a;
2852 // Applies the `Obsolete' attribute to the method.
2854 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2856 if (obsolete != null) {
2857 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2861 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2862 return obsolete != null;
2866 // Applies the `Conditional' attribute to the method.
2868 protected virtual bool ApplyConditionalAttribute (Attribute a)
2870 // The Conditional attribute is only valid on methods.
2872 Attribute.Error_AttributeNotValidForElement (a, Location);
2876 string condition = a.Conditional_GetConditionName ();
2878 if (condition == null)
2881 if (ReturnType != TypeManager.void_type) {
2882 Report.Error (578, Location,
2883 "Conditional not valid on `" + member.Name + "' " +
2884 "because its return type is not void");
2888 if ((modifiers & Modifiers.OVERRIDE) != 0) {
2889 Report.Error (243, Location,
2890 "Conditional not valid on `" + member.Name + "' " +
2891 "because it is an override method");
2895 if (member.IsExplicitImpl) {
2896 Report.Error (577, Location,
2897 "Conditional not valid on `" + member.Name + "' " +
2898 "because it is an explicit interface implementation");
2902 if (IsImplementing) {
2903 Report.Error (623, Location,
2904 "Conditional not valid on `" + member.Name + "' " +
2905 "because it is an interface method");
2909 conditionals.Add (condition);
2915 // Checks whether this method should be ignored due to its Conditional attributes.
2917 bool ShouldIgnore (Location loc)
2919 // When we're overriding a virtual method, we implicitly inherit the
2920 // Conditional attributes from our parent.
2921 if (member.ParentMethod != null) {
2922 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2923 member.ParentMethod, loc);
2925 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2929 foreach (string condition in conditionals)
2930 if (RootContext.AllDefines [condition] == null)
2937 // Returns the TypeManager.MethodFlags for this method.
2938 // This emits an error 619 / warning 618 if the method is obsolete.
2939 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2941 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2943 TypeManager.MethodFlags flags = 0;
2945 if (obsolete != null) {
2946 if (obsolete_error) {
2947 Report.Error (619, loc, "Method `" + member.Name +
2948 "' is obsolete: `" + obsolete + "'");
2949 return TypeManager.MethodFlags.IsObsoleteError;
2951 Report.Warning (618, loc, "Method `" + member.Name +
2952 "' is obsolete: `" + obsolete + "'");
2954 flags |= TypeManager.MethodFlags.IsObsolete;
2957 if (ShouldIgnore (loc))
2958 flags |= TypeManager.MethodFlags.ShouldIgnore;
2963 public virtual bool Define (TypeContainer container)
2965 MethodInfo implementing = null;
2966 string method_name, name, prefix;
2968 if (OptAttributes != null)
2969 if (!ApplyAttributes (OptAttributes, is_method))
2972 if (member.IsExplicitImpl)
2973 prefix = member.InterfaceType.FullName + ".";
2977 if (accessor_name != null)
2978 name = accessor_name + "_" + member.ShortName;
2980 name = member.ShortName;
2981 method_name = prefix + name;
2983 if (container.Pending != null){
2984 if (member is Indexer)
2985 implementing = container.Pending.IsInterfaceIndexer (
2986 member.InterfaceType, ReturnType, ParameterTypes);
2988 implementing = container.Pending.IsInterfaceMethod (
2989 member.InterfaceType, name, ReturnType, ParameterTypes);
2991 if (member.InterfaceType != null && implementing == null){
2992 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
2999 // For implicit implementations, make sure we are public, for
3000 // explicit implementations, make sure we are private.
3002 if (implementing != null){
3004 // Setting null inside this block will trigger a more
3005 // verbose error reporting for missing interface implementations
3007 // The "candidate" function has been flagged already
3008 // but it wont get cleared
3010 if (member.IsExplicitImpl){
3011 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3012 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3013 implementing = null;
3017 // We already catch different accessibility settings
3018 // so we just need to check that we are not private
3020 if ((modifiers & Modifiers.PRIVATE) != 0)
3021 implementing = null;
3025 // Static is not allowed
3027 if ((modifiers & Modifiers.STATIC) != 0){
3028 implementing = null;
3029 Modifiers.Error_InvalidModifier (Location, "static");
3034 // If implementing is still valid, set flags
3036 if (implementing != null){
3038 // When implementing interface methods, set NewSlot.
3040 if (implementing.DeclaringType.IsInterface)
3041 flags |= MethodAttributes.NewSlot;
3044 MethodAttributes.Virtual |
3045 MethodAttributes.HideBySig;
3047 // Get the method name from the explicit interface.
3048 if (member.InterfaceType != null) {
3049 name = implementing.Name;
3050 method_name = prefix + name;
3053 IsImplementing = true;
3057 // Create the MethodBuilder for the method
3059 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3060 if ((modifiers & Modifiers.STATIC) == 0) {
3061 Report.Error (601, Location,
3062 "The DllImport attribute must be specified on " +
3063 "a method marked 'static' and 'extern'.");
3067 EmitContext ec = new EmitContext (
3068 container, Location, null, ReturnType, modifiers);
3070 builder = dllimport_attribute.DefinePInvokeMethod (
3071 ec, container.TypeBuilder, method_name, flags,
3072 ReturnType, ParameterTypes);
3074 builder = container.TypeBuilder.DefineMethod (
3075 method_name, flags, CallingConventions,
3076 ReturnType, ParameterTypes);
3078 if (builder == null)
3081 if (IsImplementing) {
3083 // clear the pending implemntation flag
3085 if (member is Indexer) {
3086 container.Pending.ImplementIndexer (
3087 member.InterfaceType, builder, ReturnType,
3088 ParameterTypes, true);
3090 container.Pending.ImplementMethod (
3091 member.InterfaceType, name, ReturnType,
3092 ParameterTypes, member.IsExplicitImpl);
3094 if (member.IsExplicitImpl)
3095 container.TypeBuilder.DefineMethodOverride (
3096 builder, implementing);
3099 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3100 Report.Error (111, Location,
3101 "Class `" + container.Name +
3102 "' already contains a definition with the " +
3103 "same return value and parameter types as the " +
3104 "'get' method of property `" + member.Name + "'");
3108 TypeManager.AddMethod (builder, this);
3116 public virtual void Emit (TypeContainer container, Block block, object kind)
3121 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3122 ig = builder.GetILGenerator ();
3126 ec = new EmitContext (container, Location, ig, ReturnType, modifiers);
3128 if (OptAttributes != null)
3129 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes);
3131 if (member is MethodCore)
3132 ((MethodCore) member).LabelParameters (ec, MethodBuilder, OptAttributes);
3135 // abstract or extern methods have no bodies
3137 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3138 if (block == null) {
3139 SymbolWriter sw = CodeGen.SymbolWriter;
3141 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0)) {
3142 sw.OpenMethod (container, MethodBuilder, Location, Location);
3150 // abstract or extern methods have no bodies.
3152 if ((modifiers & Modifiers.ABSTRACT) != 0)
3154 500, Location, "Abstract method `" +
3155 TypeManager.CSharpSignature (builder) +
3156 "' can not have a body");
3158 if ((modifiers & Modifiers.EXTERN) != 0)
3160 179, Location, "External method `" +
3161 TypeManager.CSharpSignature (builder) +
3162 "' can not have a body");
3168 // Methods must have a body unless they're extern or abstract
3170 if (block == null) {
3172 501, Location, "Method `" +
3173 TypeManager.CSharpSignature (builder) +
3174 "' must declare a body since it is not marked " +
3175 "abstract or extern");
3180 // Handle destructors specially
3182 // FIXME: This code generates buggy code
3184 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3185 EmitDestructor (ec, block);
3187 SymbolWriter sw = CodeGen.SymbolWriter;
3189 if ((sw != null) && !Location.IsNull (Location) &&
3190 !Location.IsNull (block.EndLocation)) {
3191 sw.OpenMethod (container, MethodBuilder, Location, block.EndLocation);
3193 ec.EmitTopBlock (block, ParameterInfo, Location);
3197 ec.EmitTopBlock (block, ParameterInfo, Location);
3201 void EmitDestructor (EmitContext ec, Block block)
3203 ILGenerator ig = ec.ig;
3205 Label finish = ig.DefineLabel ();
3206 bool old_in_try = ec.InTry;
3208 ig.BeginExceptionBlock ();
3210 ec.ReturnLabel = finish;
3211 ec.HasReturnLabel = true;
3212 ec.EmitTopBlock (block, null, Location);
3213 ec.InTry = old_in_try;
3215 // ig.MarkLabel (finish);
3216 bool old_in_finally = ec.InFinally;
3217 ec.InFinally = true;
3218 ig.BeginFinallyBlock ();
3220 if (ec.ContainerType.BaseType != null) {
3221 Expression member_lookup = Expression.MemberLookup (
3222 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3223 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, Location);
3225 if (member_lookup != null){
3226 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3228 ig.Emit (OpCodes.Ldarg_0);
3229 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3232 ec.InFinally = old_in_finally;
3234 ig.EndExceptionBlock ();
3235 //ig.MarkLabel (ec.ReturnLabel);
3236 ig.Emit (OpCodes.Ret);
3240 abstract public class MemberBase : MemberCore {
3241 public Expression Type;
3242 public readonly Attributes OptAttributes;
3244 protected MethodAttributes flags;
3247 // The "short" name of this property / indexer / event. This is the
3248 // name without the explicit interface.
3250 public string ShortName;
3253 // The type of this property / indexer / event
3255 public Type MemberType;
3258 // If true, this is an explicit interface implementation
3260 public bool IsExplicitImpl = false;
3263 // The name of the interface we are explicitly implementing
3265 public string ExplicitInterfaceName = null;
3268 // If true, the interface type we are explicitly implementing
3270 public Type InterfaceType = null;
3273 // The method we're overriding if this is an override method.
3275 protected MethodInfo parent_method = null;
3276 public MethodInfo ParentMethod {
3278 return parent_method;
3283 // The constructor is only exposed to our children
3285 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3286 Attributes attrs, Location loc)
3290 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
3291 OptAttributes = attrs;
3294 protected virtual bool CheckBase (TypeContainer container)
3299 protected virtual bool CheckParameters (TypeContainer container, Type [] parameters)
3303 foreach (Type partype in parameters){
3304 if (partype.IsPointer){
3305 if (!UnsafeOK (container))
3307 if (!TypeManager.VerifyUnManaged (partype.GetElementType (), Location))
3311 if (container.AsAccessible (partype, ModFlags))
3314 if (this is Indexer)
3315 Report.Error (55, Location,
3316 "Inconsistent accessibility: parameter type `" +
3317 TypeManager.CSharpName (partype) + "' is less " +
3318 "accessible than indexer `" + Name + "'");
3320 Report.Error (51, Location,
3321 "Inconsistent accessibility: parameter type `" +
3322 TypeManager.CSharpName (partype) + "' is less " +
3323 "accessible than method `" + Name + "'");
3330 protected virtual bool DoDefine (TypeContainer container)
3335 if (!container.MethodModifiersValid (ModFlags, Name, Location))
3338 flags = Modifiers.MethodAttr (ModFlags);
3340 // Lookup Type, verify validity
3341 MemberType = container.ResolveType (Type, false, Location);
3342 if (MemberType == null)
3345 if ((container.ModFlags & Modifiers.SEALED) != 0){
3346 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
3347 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
3352 // verify accessibility
3353 if (!container.AsAccessible (MemberType, ModFlags)) {
3354 if (this is Property)
3355 Report.Error (53, Location,
3356 "Inconsistent accessibility: property type `" +
3357 TypeManager.CSharpName (MemberType) + "' is less " +
3358 "accessible than property `" + Name + "'");
3359 else if (this is Indexer)
3360 Report.Error (54, Location,
3361 "Inconsistent accessibility: indexer return type `" +
3362 TypeManager.CSharpName (MemberType) + "' is less " +
3363 "accessible than indexer `" + Name + "'");
3364 else if (this is Method)
3365 Report.Error (50, Location,
3366 "Inconsistent accessibility: return type `" +
3367 TypeManager.CSharpName (MemberType) + "' is less " +
3368 "accessible than method `" + Name + "'");
3370 Report.Error (52, Location,
3371 "Inconsistent accessibility: field type `" +
3372 TypeManager.CSharpName (MemberType) + "' is less " +
3373 "accessible than field `" + Name + "'");
3377 if (MemberType.IsPointer && !UnsafeOK (container))
3381 // Check for explicit interface implementation
3383 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
3384 int pos = Name.LastIndexOf (".");
3386 ExplicitInterfaceName = Name.Substring (0, pos);
3387 ShortName = Name.Substring (pos + 1);
3391 if (ExplicitInterfaceName != null) {
3392 InterfaceType = RootContext.LookupType (
3393 container, ExplicitInterfaceName, false, Location);
3394 if (InterfaceType == null)
3397 // Compute the full name that we need to export.
3398 Name = InterfaceType.FullName + "." + ShortName;
3400 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
3403 IsExplicitImpl = true;
3405 IsExplicitImpl = false;
3412 // Fields and Events both generate FieldBuilders, we use this to share
3413 // their common bits. This is also used to flag usage of the field
3415 abstract public class FieldBase : MemberBase {
3416 public FieldBuilder FieldBuilder;
3417 public Status status;
3420 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3423 // The constructor is only exposed to our children
3425 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3426 object init, Attributes attrs, Location loc)
3427 : base (type, mod, allowed_mod, name, attrs, loc)
3433 // Whether this field has an initializer.
3435 public bool HasInitializer {
3437 return init != null;
3441 protected readonly Object init;
3443 Expression init_expr;
3444 bool init_expr_initialized = false;
3447 // Resolves and returns the field initializer.
3449 public Expression GetInitializerExpression (EmitContext ec)
3451 if (init_expr_initialized)
3455 if (init is Expression)
3456 e = (Expression) init;
3458 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3460 ec.IsFieldInitializer = true;
3461 e = e.DoResolve (ec);
3462 ec.IsFieldInitializer = false;
3465 init_expr_initialized = true;
3472 // The Field class is used to represents class/struct fields during parsing.
3474 public class Field : FieldBase {
3476 // Modifiers allowed in a class declaration
3478 const int AllowedModifiers =
3481 Modifiers.PROTECTED |
3482 Modifiers.INTERNAL |
3485 Modifiers.VOLATILE |
3489 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3490 Attributes attrs, Location loc)
3491 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3495 public override bool Define (TypeContainer container)
3497 Type t = container.ResolveType (Type, false, Location);
3502 if (!container.AsAccessible (t, ModFlags)) {
3503 Report.Error (52, Location,
3504 "Inconsistent accessibility: field type `" +
3505 TypeManager.CSharpName (t) + "' is less " +
3506 "accessible than field `" + Name + "'");
3510 if (RootContext.WarningLevel > 1){
3511 Type ptype = container.TypeBuilder.BaseType;
3513 // ptype is only null for System.Object while compiling corlib.
3515 TypeContainer.FindMembers (
3516 ptype, MemberTypes.Method,
3517 BindingFlags.Public |
3518 BindingFlags.Static | BindingFlags.Instance,
3519 System.Type.FilterName, Name);
3523 if ((ModFlags & Modifiers.VOLATILE) != 0){
3527 if (TypeManager.IsEnumType (vt))
3528 vt = TypeManager.EnumToUnderlying (t);
3530 if (!((vt == TypeManager.bool_type) ||
3531 (vt == TypeManager.sbyte_type) ||
3532 (vt == TypeManager.byte_type) ||
3533 (vt == TypeManager.short_type) ||
3534 (vt == TypeManager.ushort_type) ||
3535 (vt == TypeManager.int32_type) ||
3536 (vt == TypeManager.uint32_type) ||
3537 (vt == TypeManager.char_type) ||
3538 (vt == TypeManager.float_type))){
3540 677, Location, container.MakeName (Name) +
3541 " A volatile field can not be of type `" +
3542 TypeManager.CSharpName (vt) + "'");
3548 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3550 if (container is Struct &&
3551 ((fa & FieldAttributes.Static) == 0) &&
3552 t == container.TypeBuilder &&
3553 !TypeManager.IsBuiltinType (t)){
3554 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name +
3555 "' causes a cycle in the structure layout");
3558 FieldBuilder = container.TypeBuilder.DefineField (
3559 Name, t, Modifiers.FieldAttr (ModFlags));
3561 TypeManager.RegisterFieldBase (FieldBuilder, this);
3565 public void Emit (TypeContainer tc)
3567 EmitContext ec = new EmitContext (tc, Location, null,
3568 FieldBuilder.FieldType, ModFlags);
3570 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes);
3575 // `set' and `get' accessors are represented with an Accessor.
3577 public class Accessor {
3579 // Null if the accessor is empty, or a Block if not
3582 public Attributes OptAttributes;
3584 public Accessor (Block b, Attributes attrs)
3587 OptAttributes = attrs;
3592 // Properties and Indexers both generate PropertyBuilders, we use this to share
3593 // their common bits.
3595 abstract public class PropertyBase : MethodCore {
3596 public Accessor Get, Set;
3597 public PropertyBuilder PropertyBuilder;
3598 public MethodBuilder GetBuilder, SetBuilder;
3599 public MethodData GetData, SetData;
3601 protected EmitContext ec;
3603 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3604 Parameters parameters, Accessor get_block, Accessor set_block,
3605 Attributes attrs, Location loc)
3606 : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3612 protected override bool DoDefine (TypeContainer container)
3614 if (!base.DoDefine (container))
3617 ec = new EmitContext (container, Location, null, MemberType, ModFlags);
3623 // Checks our base implementation if any
3625 protected override bool CheckBase (TypeContainer container)
3627 // Check whether arguments were correct.
3628 if (!DoDefineParameters (container))
3635 MethodSignature ms, base_ms;
3636 if (this is Indexer) {
3637 string name, base_name;
3639 report_name = "this";
3640 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
3641 ms = new MethodSignature (name, null, ParameterTypes);
3642 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
3643 base_ms = new MethodSignature (base_name, null, ParameterTypes);
3646 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
3650 // Verify if the parent has a type with the same name, and then
3651 // check whether we have to create a new slot for it or not.
3653 Type ptype = container.TypeBuilder.BaseType;
3655 // ptype is only null for System.Object while compiling corlib.
3656 if (ptype == null) {
3657 if ((ModFlags & Modifiers.NEW) != 0)
3658 WarningNotHiding (container);
3663 MemberList props_this;
3665 props_this = TypeContainer.FindMembers (
3666 container.TypeBuilder, MemberTypes.Property,
3667 BindingFlags.NonPublic | BindingFlags.Public |
3668 BindingFlags.Static | BindingFlags.Instance |
3669 BindingFlags.DeclaredOnly,
3670 MethodSignature.method_signature_filter, ms);
3672 if (props_this.Count > 0) {
3673 Report.Error (111, Location, "Class `" + container.Name + "' " +
3674 "already defines a member called `" + report_name + "' " +
3675 "with the same parameter types");
3679 MemberList mi_props;
3681 mi_props = TypeContainer.FindMembers (
3682 ptype, MemberTypes.Property,
3683 BindingFlags.NonPublic | BindingFlags.Public |
3684 BindingFlags.Instance | BindingFlags.Static,
3685 MethodSignature.inheritable_method_signature_filter, base_ms);
3687 if (mi_props.Count > 0){
3688 PropertyInfo parent_property = (PropertyInfo) mi_props [0];
3689 string name = parent_property.DeclaringType.Name + "." +
3690 parent_property.Name;
3692 MethodInfo get, set, parent_method;
3693 get = parent_property.GetGetMethod (true);
3694 set = parent_property.GetSetMethod (true);
3697 parent_method = get;
3698 else if (set != null)
3699 parent_method = set;
3701 throw new Exception ("Internal error!");
3703 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
3706 if ((ModFlags & Modifiers.NEW) == 0) {
3707 Type parent_type = TypeManager.TypeToCoreType (
3708 parent_property.PropertyType);
3710 if (parent_type != MemberType) {
3712 508, Location, container.MakeName (Name) + ": cannot " +
3713 "change return type when overriding " +
3714 "inherited member " + name);
3719 if ((ModFlags & Modifiers.NEW) != 0)
3720 WarningNotHiding (container);
3722 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3723 if (this is Indexer)
3724 Report.Error (115, Location,
3725 container.MakeName (Name) +
3726 " no suitable indexers found to override");
3728 Report.Error (115, Location,
3729 container.MakeName (Name) +
3730 " no suitable properties found to override");
3737 public void Emit (TypeContainer tc)
3740 // The PropertyBuilder can be null for explicit implementations, in that
3741 // case, we do not actually emit the ".property", so there is nowhere to
3742 // put the attribute
3744 if (PropertyBuilder != null)
3745 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes);
3747 if (GetData != null) {
3748 GetData.Emit (tc, Get.Block, Get);
3752 if (SetData != null) {
3753 SetData.Emit (tc, Set.Block, Set);
3759 public class Property : PropertyBase {
3760 const int AllowedModifiers =
3763 Modifiers.PROTECTED |
3764 Modifiers.INTERNAL |
3768 Modifiers.OVERRIDE |
3769 Modifiers.ABSTRACT |
3774 public Property (Expression type, string name, int mod_flags,
3775 Accessor get_block, Accessor set_block,
3776 Attributes attrs, Location loc)
3777 : base (type, name, mod_flags, AllowedModifiers,
3778 Parameters.EmptyReadOnlyParameters,
3779 get_block, set_block, attrs, loc)
3783 public override bool Define (TypeContainer container)
3785 if (!DoDefine (container))
3788 if (!CheckBase (container))
3791 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3794 Type [] parameters = TypeManager.NoTypes;
3796 InternalParameters ip = new InternalParameters (
3797 container, Parameters.EmptyReadOnlyParameters);
3799 GetData = new MethodData (this, "get", MemberType,
3800 parameters, ip, CallingConventions.Standard,
3801 Get.OptAttributes, ModFlags, flags, false);
3803 if (!GetData.Define (container))
3806 GetBuilder = GetData.MethodBuilder;
3810 Type [] parameters = new Type [1];
3811 parameters [0] = MemberType;
3813 Parameter [] parms = new Parameter [1];
3814 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3815 InternalParameters ip = new InternalParameters (
3816 container, new Parameters (parms, null, Location));
3818 SetData = new MethodData (this, "set", TypeManager.void_type,
3819 parameters, ip, CallingConventions.Standard,
3820 Set.OptAttributes, ModFlags, flags, false);
3822 if (!SetData.Define (container))
3825 SetBuilder = SetData.MethodBuilder;
3826 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3829 // FIXME - PropertyAttributes.HasDefault ?
3831 PropertyAttributes prop_attr =
3832 PropertyAttributes.RTSpecialName |
3833 PropertyAttributes.SpecialName;
3835 if (!IsExplicitImpl){
3836 PropertyBuilder = container.TypeBuilder.DefineProperty (
3837 Name, prop_attr, MemberType, null);
3840 PropertyBuilder.SetGetMethod (GetBuilder);
3843 PropertyBuilder.SetSetMethod (SetBuilder);
3846 // HACK for the reasons exposed above
3848 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3851 "Class `" + container.Name +
3852 "' already contains a definition for the property `" +
3862 /// Gigantic workaround for lameness in SRE follows :
3863 /// This class derives from EventInfo and attempts to basically
3864 /// wrap around the EventBuilder so that FindMembers can quickly
3865 /// return this in it search for members
3867 public class MyEventBuilder : EventInfo {
3870 // We use this to "point" to our Builder which is
3871 // not really a MemberInfo
3873 EventBuilder MyBuilder;
3876 // We "catch" and wrap these methods
3878 MethodInfo raise, remove, add;
3880 EventAttributes attributes;
3881 Type declaring_type, reflected_type, event_type;
3886 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3888 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3890 // And now store the values in our own fields.
3892 declaring_type = type_builder;
3894 reflected_type = type_builder;
3896 attributes = event_attr;
3899 this.event_type = event_type;
3903 // Methods that you have to override. Note that you only need
3904 // to "implement" the variants that take the argument (those are
3905 // the "abstract" methods, the others (GetAddMethod()) are
3908 public override MethodInfo GetAddMethod (bool nonPublic)
3913 public override MethodInfo GetRemoveMethod (bool nonPublic)
3918 public override MethodInfo GetRaiseMethod (bool nonPublic)
3924 // These methods make "MyEventInfo" look like a Builder
3926 public void SetRaiseMethod (MethodBuilder raiseMethod)
3928 raise = raiseMethod;
3929 MyBuilder.SetRaiseMethod (raiseMethod);
3932 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3934 remove = removeMethod;
3935 MyBuilder.SetRemoveOnMethod (removeMethod);
3938 public void SetAddOnMethod (MethodBuilder addMethod)
3941 MyBuilder.SetAddOnMethod (addMethod);
3944 public void SetCustomAttribute (CustomAttributeBuilder cb)
3946 MyBuilder.SetCustomAttribute (cb);
3949 public override object [] GetCustomAttributes (bool inherit)
3951 // FIXME : There's nothing which can be seemingly done here because
3952 // we have no way of getting at the custom attribute objects of the
3957 public override object [] GetCustomAttributes (Type t, bool inherit)
3959 // FIXME : Same here !
3963 public override bool IsDefined (Type t, bool b)
3968 public override EventAttributes Attributes {
3974 public override string Name {
3980 public override Type DeclaringType {
3982 return declaring_type;
3986 public override Type ReflectedType {
3988 return reflected_type;
3992 public Type EventType {
3998 public void SetUsed ()
4000 if (my_event != null)
4001 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
4005 public class Event : FieldBase {
4006 const int AllowedModifiers =
4009 Modifiers.PROTECTED |
4010 Modifiers.INTERNAL |
4015 Modifiers.OVERRIDE |
4019 public readonly Accessor Add;
4020 public readonly Accessor Remove;
4021 public MyEventBuilder EventBuilder;
4023 MethodBuilder AddBuilder, RemoveBuilder;
4024 MethodData AddData, RemoveData;
4026 public Event (Expression type, string name, Object init, int mod, Accessor add,
4027 Accessor remove, Attributes attrs, Location loc)
4028 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4034 public override bool Define (TypeContainer container)
4036 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4038 if (!DoDefine (container))
4041 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
4042 Report.Error (74, Location, "'" + container.Name + "." + Name +
4043 "': abstract event can not have an initializer");
4047 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4048 Report.Error (66, Location, "'" + container.Name + "." + Name +
4049 "' : event must be of a delegate type");
4053 Type [] parameter_types = new Type [1];
4054 parameter_types [0] = MemberType;
4056 Parameter [] parms = new Parameter [1];
4057 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4058 InternalParameters ip = new InternalParameters (
4059 container, new Parameters (parms, null, Location));
4061 if (!CheckBase (container))
4065 // Now define the accessors
4067 AddData = new MethodData (this, "add", TypeManager.void_type,
4068 parameter_types, ip, CallingConventions.Standard,
4069 (Add != null) ? Add.OptAttributes : null,
4070 ModFlags, flags, false);
4072 if (!AddData.Define (container))
4075 AddBuilder = AddData.MethodBuilder;
4076 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4078 RemoveData = new MethodData (this, "remove", TypeManager.void_type,
4079 parameter_types, ip, CallingConventions.Standard,
4080 (Remove != null) ? Remove.OptAttributes : null,
4081 ModFlags, flags, false);
4083 if (!RemoveData.Define (container))
4086 RemoveBuilder = RemoveData.MethodBuilder;
4087 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4089 if (!IsExplicitImpl){
4090 EventBuilder = new MyEventBuilder (this,
4091 container.TypeBuilder, Name, e_attr, MemberType);
4093 if (Add == null && Remove == null) {
4094 FieldBuilder = container.TypeBuilder.DefineField (
4096 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4097 TypeManager.RegisterPrivateFieldOfEvent (
4098 (EventInfo) EventBuilder, FieldBuilder);
4099 TypeManager.RegisterFieldBase (FieldBuilder, this);
4102 EventBuilder.SetAddOnMethod (AddBuilder);
4103 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4105 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4106 Report.Error (111, Location,
4107 "Class `" + container.Name +
4108 "' already contains a definition for the event `" +
4117 void EmitDefaultMethod (EmitContext ec, bool is_add)
4119 ILGenerator ig = ec.ig;
4120 MethodInfo method = null;
4123 method = TypeManager.delegate_combine_delegate_delegate;
4125 method = TypeManager.delegate_remove_delegate_delegate;
4127 if ((ModFlags & Modifiers.STATIC) != 0) {
4128 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4129 ig.Emit (OpCodes.Ldarg_0);
4130 ig.Emit (OpCodes.Call, method);
4131 ig.Emit (OpCodes.Castclass, MemberType);
4132 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4134 ig.Emit (OpCodes.Ldarg_0);
4135 ig.Emit (OpCodes.Ldarg_0);
4136 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4137 ig.Emit (OpCodes.Ldarg_1);
4138 ig.Emit (OpCodes.Call, method);
4139 ig.Emit (OpCodes.Castclass, MemberType);
4140 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4142 ig.Emit (OpCodes.Ret);
4145 public void Emit (TypeContainer tc)
4149 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4150 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes);
4153 AddData.Emit (tc, Add.Block, Add);
4156 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4157 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4158 EmitDefaultMethod (ec, true);
4161 if (Remove != null) {
4162 RemoveData.Emit (tc, Remove.Block, Remove);
4163 Remove.Block = null;
4165 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4166 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4167 EmitDefaultMethod (ec, false);
4174 // FIXME: This does not handle:
4176 // int INTERFACENAME [ args ]
4181 // int this [ args ]
4183 public class Indexer : PropertyBase {
4185 const int AllowedModifiers =
4188 Modifiers.PROTECTED |
4189 Modifiers.INTERNAL |
4193 Modifiers.OVERRIDE |
4198 public string IndexerName;
4199 public string InterfaceIndexerName;
4202 // Are we implementing an interface ?
4204 bool IsImplementing = false;
4206 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4207 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4208 : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4211 ExplicitInterfaceName = int_type;
4214 public override bool Define (TypeContainer container)
4216 PropertyAttributes prop_attr =
4217 PropertyAttributes.RTSpecialName |
4218 PropertyAttributes.SpecialName;
4220 if (!DoDefine (container))
4223 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4224 if (IndexerName == null)
4225 IndexerName = "Item";
4226 else if (IsExplicitImpl)
4227 Report.Error (592, Location,
4228 "Attribute 'IndexerName' is not valid on this declaration " +
4229 "type. It is valid on `property' declarations only.");
4231 ShortName = IndexerName;
4232 if (IsExplicitImpl) {
4233 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4234 Name = InterfaceType.FullName + "." + IndexerName;
4236 InterfaceIndexerName = IndexerName;
4240 if (!CheckBase (container))
4243 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4245 InternalParameters ip = new InternalParameters (container, Parameters);
4247 GetData = new MethodData (this, "get", MemberType,
4248 ParameterTypes, ip, CallingConventions.Standard,
4249 Get.OptAttributes, ModFlags, flags, false);
4251 if (!GetData.Define (container))
4254 GetBuilder = GetData.MethodBuilder;
4258 int top = ParameterTypes.Length;
4259 Type [] set_pars = new Type [top + 1];
4260 ParameterTypes.CopyTo (set_pars, 0);
4261 set_pars [top] = MemberType;
4263 Parameter [] fixed_parms = Parameters.FixedParameters;
4265 if (fixed_parms == null){
4266 throw new Exception ("We currently do not support only array arguments in an indexer");
4267 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4268 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4270 // Here is the problem: the `value' parameter has
4271 // to come *after* the array parameter in the declaration
4273 // X (object [] x, Type value)
4276 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4277 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4281 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4284 fixed_parms.CopyTo (tmp, 0);
4285 tmp [fixed_parms.Length] = new Parameter (
4286 Type, "value", Parameter.Modifier.NONE, null);
4288 Parameters set_formal_params = new Parameters (tmp, null, Location);
4290 InternalParameters ip = new InternalParameters (container, set_formal_params);
4292 SetData = new MethodData (this, "set", TypeManager.void_type,
4293 set_pars, ip, CallingConventions.Standard,
4294 Set.OptAttributes, ModFlags, flags, false);
4296 if (!SetData.Define (container))
4299 SetBuilder = SetData.MethodBuilder;
4303 // Now name the parameters
4305 Parameter [] p = Parameters.FixedParameters;
4309 for (i = 0; i < p.Length; ++i) {
4311 GetBuilder.DefineParameter (
4312 i + 1, p [i].Attributes, p [i].Name);
4315 SetBuilder.DefineParameter (
4316 i + 1, p [i].Attributes, p [i].Name);
4320 SetBuilder.DefineParameter (
4321 i + 1, ParameterAttributes.None, "value");
4323 if (i != ParameterTypes.Length) {
4324 Parameter array_param = Parameters.ArrayParameter;
4325 SetBuilder.DefineParameter (
4326 i + 1, array_param.Attributes, array_param.Name);
4330 if (GetData != null)
4331 IsImplementing = GetData.IsImplementing;
4332 else if (SetData != null)
4333 IsImplementing = SetData.IsImplementing;
4336 // Define the PropertyBuilder if one of the following conditions are met:
4337 // a) we're not implementing an interface indexer.
4338 // b) the indexer has a different IndexerName and this is no
4339 // explicit interface implementation.
4341 if (!IsExplicitImpl) {
4342 PropertyBuilder = container.TypeBuilder.DefineProperty (
4343 IndexerName, prop_attr, MemberType, ParameterTypes);
4345 if (GetData != null)
4346 PropertyBuilder.SetGetMethod (GetBuilder);
4348 if (SetData != null)
4349 PropertyBuilder.SetSetMethod (SetBuilder);
4351 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4359 public class Operator : MemberCore {
4361 const int AllowedModifiers =
4367 const int RequiredModifiers =
4371 public enum OpType : byte {
4381 // Unary and Binary operators
4404 // Implicit and Explicit
4409 public readonly OpType OperatorType;
4410 public readonly Expression ReturnType;
4411 public readonly Expression FirstArgType, SecondArgType;
4412 public readonly string FirstArgName, SecondArgName;
4414 public Attributes OptAttributes;
4415 public MethodBuilder OperatorMethodBuilder;
4417 public string MethodName;
4418 public Method OperatorMethod;
4420 public Operator (OpType type, Expression ret_type, int flags,
4421 Expression arg1type, string arg1name,
4422 Expression arg2type, string arg2name,
4423 Block block, Attributes attrs, Location loc)
4426 OperatorType = type;
4427 ReturnType = ret_type;
4428 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4429 FirstArgType = arg1type;
4430 FirstArgName = arg1name;
4431 SecondArgType = arg2type;
4432 SecondArgName = arg2name;
4434 OptAttributes = attrs;
4437 string Prototype (TypeContainer container)
4439 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4440 SecondArgType + ")";
4443 public override bool Define (TypeContainer container)
4446 MethodName = "op_" + OperatorType;
4448 if (SecondArgType != null)
4451 Parameter [] param_list = new Parameter [length];
4453 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4456 "User defined operators `" +
4457 Prototype (container) +
4458 "' must be declared static and public");
4462 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4463 Parameter.Modifier.NONE, null);
4464 if (SecondArgType != null)
4465 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4466 Parameter.Modifier.NONE, null);
4468 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4469 new Parameters (param_list, null, Location),
4470 OptAttributes, Mono.CSharp.Location.Null);
4472 OperatorMethod.IsOperator = true;
4473 OperatorMethod.Define (container);
4475 if (OperatorMethod.MethodBuilder == null)
4478 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4480 Type [] param_types = OperatorMethod.ParameterTypes;
4481 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4482 Type return_type = OperatorMethod.GetReturnType ();
4483 Type first_arg_type = param_types [0];
4485 // Rules for conversion operators
4487 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4488 if (first_arg_type == return_type && first_arg_type == declaring_type){
4491 "User-defined conversion cannot take an object of the " +
4492 "enclosing type and convert to an object of the enclosing" +
4497 if (first_arg_type != declaring_type && return_type != declaring_type){
4500 "User-defined conversion must convert to or from the " +
4505 if (first_arg_type == TypeManager.object_type ||
4506 return_type == TypeManager.object_type){
4509 "User-defined conversion cannot convert to or from " +
4514 if (first_arg_type.IsInterface || return_type.IsInterface){
4517 "User-defined conversion cannot convert to or from an " +
4522 if (first_arg_type.IsSubclassOf (return_type) ||
4523 return_type.IsSubclassOf (first_arg_type)){
4526 "User-defined conversion cannot convert between types " +
4527 "that derive from each other");
4530 } else if (SecondArgType == null) {
4531 // Checks for Unary operators
4533 if (first_arg_type != declaring_type){
4536 "The parameter of a unary operator must be the " +
4541 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4542 if (return_type != declaring_type){
4545 "The parameter and return type for ++ and -- " +
4546 "must be the containing type");
4552 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4553 if (return_type != TypeManager.bool_type){
4556 "The return type of operator True or False " +
4563 // Checks for Binary operators
4565 if (first_arg_type != declaring_type &&
4566 param_types [1] != declaring_type){
4569 "One of the parameters of a binary operator must " +
4570 "be the containing type");
4578 public void Emit (TypeContainer container)
4580 EmitContext ec = new EmitContext (container, Location, null, null, ModFlags);
4581 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes);
4584 // abstract or extern methods have no bodies
4586 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4589 OperatorMethod.Block = Block;
4590 OperatorMethod.Emit (container);
4594 public static string GetName (OpType ot)
4597 case OpType.LogicalNot:
4599 case OpType.OnesComplement:
4601 case OpType.Increment:
4603 case OpType.Decrement:
4609 case OpType.Addition:
4611 case OpType.Subtraction:
4613 case OpType.UnaryPlus:
4615 case OpType.UnaryNegation:
4617 case OpType.Multiply:
4619 case OpType.Division:
4621 case OpType.Modulus:
4623 case OpType.BitwiseAnd:
4625 case OpType.BitwiseOr:
4627 case OpType.ExclusiveOr:
4629 case OpType.LeftShift:
4631 case OpType.RightShift:
4633 case OpType.Equality:
4635 case OpType.Inequality:
4637 case OpType.GreaterThan:
4639 case OpType.LessThan:
4641 case OpType.GreaterThanOrEqual:
4643 case OpType.LessThanOrEqual:
4645 case OpType.Implicit:
4647 case OpType.Explicit:
4653 public override string ToString ()
4655 Type return_type = OperatorMethod.GetReturnType();
4656 Type [] param_types = OperatorMethod.ParameterTypes;
4658 if (SecondArgType == null)
4659 return String.Format (
4660 "{0} operator {1}({2})",
4661 TypeManager.CSharpName (return_type),
4662 GetName (OperatorType),
4665 return String.Format (
4666 "{0} operator {1}({2}, {3})",
4667 TypeManager.CSharpName (return_type),
4668 GetName (OperatorType),
4669 param_types [0], param_types [1]);
4674 // This is used to compare method signatures
4676 struct MethodSignature {
4678 public Type RetType;
4679 public Type [] Parameters;
4682 /// This delegate is used to extract methods which have the
4683 /// same signature as the argument
4685 public static MemberFilter method_signature_filter;
4688 /// This delegate is used to extract inheritable methods which
4689 /// have the same signature as the argument. By inheritable,
4690 /// this means that we have permissions to override the method
4691 /// from the current assembly and class
4693 public static MemberFilter inheritable_method_signature_filter;
4695 static MethodSignature ()
4697 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4698 inheritable_method_signature_filter = new MemberFilter (
4699 InheritableMemberSignatureCompare);
4702 public MethodSignature (string name, Type ret_type, Type [] parameters)
4707 if (parameters == null)
4708 Parameters = TypeManager.NoTypes;
4710 Parameters = parameters;
4713 public override string ToString ()
4716 if (Parameters.Length != 0){
4717 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
4718 for (int i = 0; i < Parameters.Length; i++){
4719 sb.Append (Parameters [i]);
4720 if (i+1 < Parameters.Length)
4723 pars = sb.ToString ();
4726 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
4729 public override int GetHashCode ()
4731 return Name.GetHashCode ();
4734 public override bool Equals (Object o)
4736 MethodSignature other = (MethodSignature) o;
4738 if (other.Name != Name)
4741 if (other.RetType != RetType)
4744 if (Parameters == null){
4745 if (other.Parameters == null)
4750 if (other.Parameters == null)
4753 int c = Parameters.Length;
4754 if (other.Parameters.Length != c)
4757 for (int i = 0; i < c; i++)
4758 if (other.Parameters [i] != Parameters [i])
4764 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4766 MethodSignature sig = (MethodSignature) filter_criteria;
4768 if (m.Name != sig.Name)
4772 MethodInfo mi = m as MethodInfo;
4773 PropertyInfo pi = m as PropertyInfo;
4776 ReturnType = mi.ReturnType;
4777 else if (pi != null)
4778 ReturnType = pi.PropertyType;
4783 // we use sig.RetType == null to mean `do not check the
4784 // method return value.
4786 if (sig.RetType != null)
4787 if (ReturnType != sig.RetType)
4792 args = TypeManager.GetArgumentTypes (mi);
4794 args = TypeManager.GetArgumentTypes (pi);
4795 Type [] sigp = sig.Parameters;
4797 if (args.Length != sigp.Length)
4800 for (int i = args.Length; i > 0; ){
4802 if (args [i] != sigp [i])
4809 // This filter should be used when we are requesting methods that
4810 // we want to override.
4812 // This makes a number of assumptions, for example
4813 // that the methods being extracted are of a parent
4814 // class (this means we know implicitly that we are
4815 // being called to find out about members by a derived
4818 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4821 PropertyInfo pi = m as PropertyInfo;
4824 mi = pi.GetGetMethod (true);
4826 mi = pi.GetSetMethod (true);
4828 mi = m as MethodInfo;
4831 Console.WriteLine ("Nothing found");
4834 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4836 // If only accessible to the current class.
4837 if (prot == MethodAttributes.Private)
4840 if (!MemberSignatureCompare (m, filter_criteria))
4843 // If only accessible to the defining assembly or
4844 if (prot == MethodAttributes.FamANDAssem ||
4845 prot == MethodAttributes.Assembly){
4846 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4852 // Anything else (FamOrAssembly and Public) is fine