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))
2491 ec.CurrentBlock = null;
2493 if (this is ConstructorBaseInitializer) {
2494 if (ec.ContainerType.BaseType == null)
2497 t = ec.ContainerType.BaseType;
2498 if (ec.ContainerType.IsValueType) {
2499 Report.Error (522, loc,
2500 "structs cannot call base class constructors");
2504 t = ec.ContainerType;
2506 parent_constructor_group = Expression.MemberLookup (
2507 ec, t, null, t, ".ctor",
2508 MemberTypes.Constructor,
2509 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2512 if (parent_constructor_group == null){
2513 Report.Error (1501, loc,
2514 "Can not find a constructor for this argument list");
2518 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2519 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2521 if (parent_constructor == null){
2522 Report.Error (1501, loc,
2523 "Can not find a constructor for this argument list");
2530 public void Emit (EmitContext ec)
2532 if (parent_constructor != null){
2533 ec.Mark (loc, false);
2535 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2537 Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2542 public class ConstructorBaseInitializer : ConstructorInitializer {
2543 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2544 base (argument_list, pars, l)
2549 public class ConstructorThisInitializer : ConstructorInitializer {
2550 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2551 base (argument_list, pars, l)
2556 public class Constructor : MethodCore {
2557 public ConstructorBuilder ConstructorBuilder;
2558 public ConstructorInitializer Initializer;
2559 new public Attributes OptAttributes;
2562 // Modifiers allowed for a constructor.
2564 public const int AllowedModifiers =
2566 Modifiers.PROTECTED |
2567 Modifiers.INTERNAL |
2574 // The spec claims that static is not permitted, but
2575 // my very own code has static constructors.
2577 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2578 : base (null, 0, AllowedModifiers, name, null, args, l)
2584 // Returns true if this is a default constructor
2586 public bool IsDefault ()
2588 if ((ModFlags & Modifiers.STATIC) != 0)
2589 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2590 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2593 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2594 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2595 (Initializer is ConstructorBaseInitializer) &&
2596 (Initializer.Arguments == null);
2600 // Creates the ConstructorBuilder
2602 public override bool Define (TypeContainer container)
2604 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2605 MethodAttributes.SpecialName);
2607 // Check if arguments were correct.
2608 if (!DoDefineParameters (container))
2611 if ((ModFlags & Modifiers.STATIC) != 0)
2612 ca |= MethodAttributes.Static;
2614 if (container is Struct && ParameterTypes.Length == 0){
2617 "Structs can not contain explicit parameterless " +
2621 ca |= MethodAttributes.HideBySig;
2623 if ((ModFlags & Modifiers.PUBLIC) != 0)
2624 ca |= MethodAttributes.Public;
2625 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2626 if ((ModFlags & Modifiers.INTERNAL) != 0)
2627 ca |= MethodAttributes.FamORAssem;
2629 ca |= MethodAttributes.Family;
2630 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2631 ca |= MethodAttributes.Assembly;
2632 else if (IsDefault ())
2633 ca |= MethodAttributes.Public;
2635 ca |= MethodAttributes.Private;
2638 ConstructorBuilder = container.TypeBuilder.DefineConstructor (
2639 ca, GetCallingConvention (container is Class), ParameterTypes);
2642 // HACK because System.Reflection.Emit is lame
2644 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2647 "Class `" +container.Name+ "' already contains a definition with the " +
2648 "same return value and parameter types for constructor `" + Name
2659 public void Emit (TypeContainer container)
2661 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2662 EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
2665 // extern methods have no bodies
2667 if ((ModFlags & Modifiers.EXTERN) != 0) {
2668 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
2670 179, Location, "External constructor `" +
2671 TypeManager.CSharpSignature (ConstructorBuilder) +
2672 "' can not have a body");
2675 } else if (block == null) {
2677 501, Location, "Constructor `" +
2678 TypeManager.CSharpSignature (ConstructorBuilder) +
2679 "' must declare a body since it is not marked extern");
2683 if ((ModFlags & Modifiers.STATIC) == 0){
2684 if (container is Class && Initializer == null)
2685 Initializer = new ConstructorBaseInitializer (
2686 null, Parameters.EmptyReadOnlyParameters, Location);
2690 // Spec mandates that Initializers will not have
2694 if (Initializer != null && !Initializer.Resolve (ec))
2696 ec.IsStatic = false;
2699 LabelParameters (ec, ConstructorBuilder, OptAttributes);
2701 SymbolWriter sw = CodeGen.SymbolWriter;
2702 bool generate_debugging = false;
2704 if ((sw != null) && (block != null) &&
2705 !Location.IsNull (Location) &&
2706 !Location.IsNull (block.EndLocation)) {
2708 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
2710 generate_debugging = true;
2714 // Classes can have base initializers and instance field initializers.
2716 if (container is Class){
2717 if ((ModFlags & Modifiers.STATIC) == 0)
2718 container.EmitFieldInitializers (ec);
2720 if (Initializer != null)
2721 Initializer.Emit (ec);
2723 if ((ModFlags & Modifiers.STATIC) != 0)
2724 container.EmitFieldInitializers (ec);
2726 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes);
2728 // If this is a non-static `struct' constructor and doesn't have any
2729 // initializer, it must initialize all of the struct's fields.
2730 if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
2731 Block.AddThisVariable (container, Location);
2733 ec.EmitTopBlock (block, ParameterInfo, Location);
2735 if (generate_debugging)
2742 public class MethodData {
2744 // The return type of this method
2746 public readonly Type ReturnType;
2747 public readonly Type[] ParameterTypes;
2748 public readonly InternalParameters ParameterInfo;
2749 public readonly CallingConventions CallingConventions;
2750 public readonly Attributes OptAttributes;
2751 public readonly Location Location;
2754 // Are we implementing an interface ?
2756 public bool IsImplementing = false;
2761 protected MemberBase member;
2762 protected int modifiers;
2763 protected MethodAttributes flags;
2764 protected bool is_method;
2765 protected string accessor_name;
2766 ArrayList conditionals;
2768 MethodBuilder builder = null;
2769 public MethodBuilder MethodBuilder {
2775 public MethodData (MemberBase member, string name, Type return_type,
2776 Type [] parameter_types, InternalParameters parameters,
2777 CallingConventions cc, Attributes opt_attrs,
2778 int modifiers, MethodAttributes flags, bool is_method)
2780 this.member = member;
2781 this.accessor_name = name;
2782 this.ReturnType = return_type;
2783 this.ParameterTypes = parameter_types;
2784 this.ParameterInfo = parameters;
2785 this.CallingConventions = cc;
2786 this.OptAttributes = opt_attrs;
2787 this.modifiers = modifiers;
2789 this.is_method = is_method;
2790 this.Location = member.Location;
2791 this.conditionals = new ArrayList ();
2797 Attribute dllimport_attribute = null;
2798 string obsolete = null;
2799 bool obsolete_error = false;
2801 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2803 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2806 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2807 if (asec.Attributes == null)
2810 foreach (Attribute a in asec.Attributes) {
2811 if (a.Name == "Conditional") {
2812 if (!ApplyConditionalAttribute (a))
2814 } else if (a.Name == "Obsolete") {
2815 if (!ApplyObsoleteAttribute (a))
2817 } else if (a.Name.IndexOf ("DllImport") != -1) {
2819 a.Type = TypeManager.dllimport_type;
2820 Attribute.Error_AttributeNotValidForElement (a, Location);
2823 if (!ApplyDllImportAttribute (a))
2833 // Applies the `DllImport' attribute to the method.
2835 protected virtual bool ApplyDllImportAttribute (Attribute a)
2837 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2838 if ((modifiers & extern_static) != extern_static) {
2839 Report.Error (601, Location,
2840 "The DllImport attribute must be specified on a method " +
2841 "marked `static' and `extern'.");
2845 flags |= MethodAttributes.PinvokeImpl;
2846 dllimport_attribute = a;
2851 // Applies the `Obsolete' attribute to the method.
2853 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2855 if (obsolete != null) {
2856 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2860 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2861 return obsolete != null;
2865 // Applies the `Conditional' attribute to the method.
2867 protected virtual bool ApplyConditionalAttribute (Attribute a)
2869 // The Conditional attribute is only valid on methods.
2871 Attribute.Error_AttributeNotValidForElement (a, Location);
2875 string condition = a.Conditional_GetConditionName ();
2877 if (condition == null)
2880 if (ReturnType != TypeManager.void_type) {
2881 Report.Error (578, Location,
2882 "Conditional not valid on `" + member.Name + "' " +
2883 "because its return type is not void");
2887 if ((modifiers & Modifiers.OVERRIDE) != 0) {
2888 Report.Error (243, Location,
2889 "Conditional not valid on `" + member.Name + "' " +
2890 "because it is an override method");
2894 if (member.IsExplicitImpl) {
2895 Report.Error (577, Location,
2896 "Conditional not valid on `" + member.Name + "' " +
2897 "because it is an explicit interface implementation");
2901 if (IsImplementing) {
2902 Report.Error (623, Location,
2903 "Conditional not valid on `" + member.Name + "' " +
2904 "because it is an interface method");
2908 conditionals.Add (condition);
2914 // Checks whether this method should be ignored due to its Conditional attributes.
2916 bool ShouldIgnore (Location loc)
2918 // When we're overriding a virtual method, we implicitly inherit the
2919 // Conditional attributes from our parent.
2920 if (member.ParentMethod != null) {
2921 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2922 member.ParentMethod, loc);
2924 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2928 foreach (string condition in conditionals)
2929 if (RootContext.AllDefines [condition] == null)
2936 // Returns the TypeManager.MethodFlags for this method.
2937 // This emits an error 619 / warning 618 if the method is obsolete.
2938 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2940 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2942 TypeManager.MethodFlags flags = 0;
2944 if (obsolete != null) {
2945 if (obsolete_error) {
2946 Report.Error (619, loc, "Method `" + member.Name +
2947 "' is obsolete: `" + obsolete + "'");
2948 return TypeManager.MethodFlags.IsObsoleteError;
2950 Report.Warning (618, loc, "Method `" + member.Name +
2951 "' is obsolete: `" + obsolete + "'");
2953 flags |= TypeManager.MethodFlags.IsObsolete;
2956 if (ShouldIgnore (loc))
2957 flags |= TypeManager.MethodFlags.ShouldIgnore;
2962 public virtual bool Define (TypeContainer container)
2964 MethodInfo implementing = null;
2965 string method_name, name, prefix;
2967 if (OptAttributes != null)
2968 if (!ApplyAttributes (OptAttributes, is_method))
2971 if (member.IsExplicitImpl)
2972 prefix = member.InterfaceType.FullName + ".";
2976 if (accessor_name != null)
2977 name = accessor_name + "_" + member.ShortName;
2979 name = member.ShortName;
2980 method_name = prefix + name;
2982 if (container.Pending != null){
2983 if (member is Indexer)
2984 implementing = container.Pending.IsInterfaceIndexer (
2985 member.InterfaceType, ReturnType, ParameterTypes);
2987 implementing = container.Pending.IsInterfaceMethod (
2988 member.InterfaceType, name, ReturnType, ParameterTypes);
2990 if (member.InterfaceType != null && implementing == null){
2991 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
2998 // For implicit implementations, make sure we are public, for
2999 // explicit implementations, make sure we are private.
3001 if (implementing != null){
3003 // Setting null inside this block will trigger a more
3004 // verbose error reporting for missing interface implementations
3006 // The "candidate" function has been flagged already
3007 // but it wont get cleared
3009 if (member.IsExplicitImpl){
3010 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3011 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3012 implementing = null;
3016 // We already catch different accessibility settings
3017 // so we just need to check that we are not private
3019 if ((modifiers & Modifiers.PRIVATE) != 0)
3020 implementing = null;
3024 // Static is not allowed
3026 if ((modifiers & Modifiers.STATIC) != 0){
3027 implementing = null;
3028 Modifiers.Error_InvalidModifier (Location, "static");
3033 // If implementing is still valid, set flags
3035 if (implementing != null){
3037 // When implementing interface methods, set NewSlot.
3039 if (implementing.DeclaringType.IsInterface)
3040 flags |= MethodAttributes.NewSlot;
3043 MethodAttributes.Virtual |
3044 MethodAttributes.HideBySig;
3046 // Get the method name from the explicit interface.
3047 if (member.InterfaceType != null) {
3048 name = implementing.Name;
3049 method_name = prefix + name;
3052 IsImplementing = true;
3056 // Create the MethodBuilder for the method
3058 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3059 if ((modifiers & Modifiers.STATIC) == 0) {
3060 Report.Error (601, Location,
3061 "The DllImport attribute must be specified on " +
3062 "a method marked 'static' and 'extern'.");
3066 EmitContext ec = new EmitContext (
3067 container, Location, null, ReturnType, modifiers);
3069 builder = dllimport_attribute.DefinePInvokeMethod (
3070 ec, container.TypeBuilder, method_name, flags,
3071 ReturnType, ParameterTypes);
3073 builder = container.TypeBuilder.DefineMethod (
3074 method_name, flags, CallingConventions,
3075 ReturnType, ParameterTypes);
3077 if (builder == null)
3080 if (IsImplementing) {
3082 // clear the pending implemntation flag
3084 if (member is Indexer) {
3085 container.Pending.ImplementIndexer (
3086 member.InterfaceType, builder, ReturnType,
3087 ParameterTypes, true);
3089 container.Pending.ImplementMethod (
3090 member.InterfaceType, name, ReturnType,
3091 ParameterTypes, member.IsExplicitImpl);
3093 if (member.IsExplicitImpl)
3094 container.TypeBuilder.DefineMethodOverride (
3095 builder, implementing);
3098 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3099 Report.Error (111, Location,
3100 "Class `" + container.Name +
3101 "' already contains a definition with the " +
3102 "same return value and parameter types as the " +
3103 "'get' method of property `" + member.Name + "'");
3107 TypeManager.AddMethod (builder, this);
3115 public virtual void Emit (TypeContainer container, Block block, object kind)
3120 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3121 ig = builder.GetILGenerator ();
3125 ec = new EmitContext (container, Location, ig, ReturnType, modifiers);
3127 if (OptAttributes != null)
3128 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes);
3130 if (member is MethodCore)
3131 ((MethodCore) member).LabelParameters (ec, MethodBuilder, OptAttributes);
3134 // abstract or extern methods have no bodies
3136 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3137 if (block == null) {
3138 SymbolWriter sw = CodeGen.SymbolWriter;
3140 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0)) {
3141 sw.OpenMethod (container, MethodBuilder, Location, Location);
3149 // abstract or extern methods have no bodies.
3151 if ((modifiers & Modifiers.ABSTRACT) != 0)
3153 500, Location, "Abstract method `" +
3154 TypeManager.CSharpSignature (builder) +
3155 "' can not have a body");
3157 if ((modifiers & Modifiers.EXTERN) != 0)
3159 179, Location, "External method `" +
3160 TypeManager.CSharpSignature (builder) +
3161 "' can not have a body");
3167 // Methods must have a body unless they're extern or abstract
3169 if (block == null) {
3171 501, Location, "Method `" +
3172 TypeManager.CSharpSignature (builder) +
3173 "' must declare a body since it is not marked " +
3174 "abstract or extern");
3179 // Handle destructors specially
3181 // FIXME: This code generates buggy code
3183 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3184 EmitDestructor (ec, block);
3186 SymbolWriter sw = CodeGen.SymbolWriter;
3188 if ((sw != null) && !Location.IsNull (Location) &&
3189 !Location.IsNull (block.EndLocation)) {
3190 sw.OpenMethod (container, MethodBuilder, Location, block.EndLocation);
3192 ec.EmitTopBlock (block, ParameterInfo, Location);
3196 ec.EmitTopBlock (block, ParameterInfo, Location);
3200 void EmitDestructor (EmitContext ec, Block block)
3202 ILGenerator ig = ec.ig;
3204 Label finish = ig.DefineLabel ();
3205 bool old_in_try = ec.InTry;
3207 ig.BeginExceptionBlock ();
3209 ec.ReturnLabel = finish;
3210 ec.HasReturnLabel = true;
3211 ec.EmitTopBlock (block, null, Location);
3212 ec.InTry = old_in_try;
3214 // ig.MarkLabel (finish);
3215 bool old_in_finally = ec.InFinally;
3216 ec.InFinally = true;
3217 ig.BeginFinallyBlock ();
3219 if (ec.ContainerType.BaseType != null) {
3220 Expression member_lookup = Expression.MemberLookup (
3221 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3222 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, Location);
3224 if (member_lookup != null){
3225 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3227 ig.Emit (OpCodes.Ldarg_0);
3228 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3231 ec.InFinally = old_in_finally;
3233 ig.EndExceptionBlock ();
3234 //ig.MarkLabel (ec.ReturnLabel);
3235 ig.Emit (OpCodes.Ret);
3239 abstract public class MemberBase : MemberCore {
3240 public Expression Type;
3241 public readonly Attributes OptAttributes;
3243 protected MethodAttributes flags;
3246 // The "short" name of this property / indexer / event. This is the
3247 // name without the explicit interface.
3249 public string ShortName;
3252 // The type of this property / indexer / event
3254 public Type MemberType;
3257 // If true, this is an explicit interface implementation
3259 public bool IsExplicitImpl = false;
3262 // The name of the interface we are explicitly implementing
3264 public string ExplicitInterfaceName = null;
3267 // If true, the interface type we are explicitly implementing
3269 public Type InterfaceType = null;
3272 // The method we're overriding if this is an override method.
3274 protected MethodInfo parent_method = null;
3275 public MethodInfo ParentMethod {
3277 return parent_method;
3282 // The constructor is only exposed to our children
3284 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3285 Attributes attrs, Location loc)
3289 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
3290 OptAttributes = attrs;
3293 protected virtual bool CheckBase (TypeContainer container)
3298 protected virtual bool CheckParameters (TypeContainer container, Type [] parameters)
3302 foreach (Type partype in parameters){
3303 if (partype.IsPointer){
3304 if (!UnsafeOK (container))
3306 if (!TypeManager.VerifyUnManaged (partype.GetElementType (), Location))
3310 if (container.AsAccessible (partype, ModFlags))
3313 if (this is Indexer)
3314 Report.Error (55, Location,
3315 "Inconsistent accessibility: parameter type `" +
3316 TypeManager.CSharpName (partype) + "' is less " +
3317 "accessible than indexer `" + Name + "'");
3319 Report.Error (51, Location,
3320 "Inconsistent accessibility: parameter type `" +
3321 TypeManager.CSharpName (partype) + "' is less " +
3322 "accessible than method `" + Name + "'");
3329 protected virtual bool DoDefine (TypeContainer container)
3334 if (!container.MethodModifiersValid (ModFlags, Name, Location))
3337 flags = Modifiers.MethodAttr (ModFlags);
3339 // Lookup Type, verify validity
3340 MemberType = container.ResolveType (Type, false, Location);
3341 if (MemberType == null)
3344 if ((container.ModFlags & Modifiers.SEALED) != 0){
3345 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
3346 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
3351 // verify accessibility
3352 if (!container.AsAccessible (MemberType, ModFlags)) {
3353 if (this is Property)
3354 Report.Error (53, Location,
3355 "Inconsistent accessibility: property type `" +
3356 TypeManager.CSharpName (MemberType) + "' is less " +
3357 "accessible than property `" + Name + "'");
3358 else if (this is Indexer)
3359 Report.Error (54, Location,
3360 "Inconsistent accessibility: indexer return type `" +
3361 TypeManager.CSharpName (MemberType) + "' is less " +
3362 "accessible than indexer `" + Name + "'");
3363 else if (this is Method)
3364 Report.Error (50, Location,
3365 "Inconsistent accessibility: return type `" +
3366 TypeManager.CSharpName (MemberType) + "' is less " +
3367 "accessible than method `" + Name + "'");
3369 Report.Error (52, Location,
3370 "Inconsistent accessibility: field type `" +
3371 TypeManager.CSharpName (MemberType) + "' is less " +
3372 "accessible than field `" + Name + "'");
3376 if (MemberType.IsPointer && !UnsafeOK (container))
3380 // Check for explicit interface implementation
3382 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
3383 int pos = Name.LastIndexOf (".");
3385 ExplicitInterfaceName = Name.Substring (0, pos);
3386 ShortName = Name.Substring (pos + 1);
3390 if (ExplicitInterfaceName != null) {
3391 InterfaceType = RootContext.LookupType (
3392 container, ExplicitInterfaceName, false, Location);
3393 if (InterfaceType == null)
3396 // Compute the full name that we need to export.
3397 Name = InterfaceType.FullName + "." + ShortName;
3399 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
3402 IsExplicitImpl = true;
3404 IsExplicitImpl = false;
3411 // Fields and Events both generate FieldBuilders, we use this to share
3412 // their common bits. This is also used to flag usage of the field
3414 abstract public class FieldBase : MemberBase {
3415 public FieldBuilder FieldBuilder;
3416 public Status status;
3419 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3422 // The constructor is only exposed to our children
3424 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3425 object init, Attributes attrs, Location loc)
3426 : base (type, mod, allowed_mod, name, attrs, loc)
3432 // Whether this field has an initializer.
3434 public bool HasInitializer {
3436 return init != null;
3440 protected readonly Object init;
3442 Expression init_expr;
3443 bool init_expr_initialized = false;
3446 // Resolves and returns the field initializer.
3448 public Expression GetInitializerExpression (EmitContext ec)
3450 if (init_expr_initialized)
3454 if (init is Expression)
3455 e = (Expression) init;
3457 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3459 ec.IsFieldInitializer = true;
3460 e = e.DoResolve (ec);
3461 ec.IsFieldInitializer = false;
3464 init_expr_initialized = true;
3471 // The Field class is used to represents class/struct fields during parsing.
3473 public class Field : FieldBase {
3475 // Modifiers allowed in a class declaration
3477 const int AllowedModifiers =
3480 Modifiers.PROTECTED |
3481 Modifiers.INTERNAL |
3484 Modifiers.VOLATILE |
3488 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3489 Attributes attrs, Location loc)
3490 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3494 public override bool Define (TypeContainer container)
3496 Type t = container.ResolveType (Type, false, Location);
3501 if (!container.AsAccessible (t, ModFlags)) {
3502 Report.Error (52, Location,
3503 "Inconsistent accessibility: field type `" +
3504 TypeManager.CSharpName (t) + "' is less " +
3505 "accessible than field `" + Name + "'");
3509 if (RootContext.WarningLevel > 1){
3510 Type ptype = container.TypeBuilder.BaseType;
3512 // ptype is only null for System.Object while compiling corlib.
3514 TypeContainer.FindMembers (
3515 ptype, MemberTypes.Method,
3516 BindingFlags.Public |
3517 BindingFlags.Static | BindingFlags.Instance,
3518 System.Type.FilterName, Name);
3522 if ((ModFlags & Modifiers.VOLATILE) != 0){
3526 if (TypeManager.IsEnumType (vt))
3527 vt = TypeManager.EnumToUnderlying (t);
3529 if (!((vt == TypeManager.bool_type) ||
3530 (vt == TypeManager.sbyte_type) ||
3531 (vt == TypeManager.byte_type) ||
3532 (vt == TypeManager.short_type) ||
3533 (vt == TypeManager.ushort_type) ||
3534 (vt == TypeManager.int32_type) ||
3535 (vt == TypeManager.uint32_type) ||
3536 (vt == TypeManager.char_type) ||
3537 (vt == TypeManager.float_type))){
3539 677, Location, container.MakeName (Name) +
3540 " A volatile field can not be of type `" +
3541 TypeManager.CSharpName (vt) + "'");
3547 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3549 if (container is Struct &&
3550 ((fa & FieldAttributes.Static) == 0) &&
3551 t == container.TypeBuilder &&
3552 !TypeManager.IsBuiltinType (t)){
3553 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name +
3554 "' causes a cycle in the structure layout");
3557 FieldBuilder = container.TypeBuilder.DefineField (
3558 Name, t, Modifiers.FieldAttr (ModFlags));
3560 TypeManager.RegisterFieldBase (FieldBuilder, this);
3564 public void Emit (TypeContainer tc)
3566 EmitContext ec = new EmitContext (tc, Location, null,
3567 FieldBuilder.FieldType, ModFlags);
3569 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes);
3574 // `set' and `get' accessors are represented with an Accessor.
3576 public class Accessor {
3578 // Null if the accessor is empty, or a Block if not
3581 public Attributes OptAttributes;
3583 public Accessor (Block b, Attributes attrs)
3586 OptAttributes = attrs;
3591 // Properties and Indexers both generate PropertyBuilders, we use this to share
3592 // their common bits.
3594 abstract public class PropertyBase : MethodCore {
3595 public Accessor Get, Set;
3596 public PropertyBuilder PropertyBuilder;
3597 public MethodBuilder GetBuilder, SetBuilder;
3598 public MethodData GetData, SetData;
3600 protected EmitContext ec;
3602 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3603 Parameters parameters, Accessor get_block, Accessor set_block,
3604 Attributes attrs, Location loc)
3605 : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3611 protected override bool DoDefine (TypeContainer container)
3613 if (!base.DoDefine (container))
3616 ec = new EmitContext (container, Location, null, MemberType, ModFlags);
3622 // Checks our base implementation if any
3624 protected override bool CheckBase (TypeContainer container)
3626 // Check whether arguments were correct.
3627 if (!DoDefineParameters (container))
3634 MethodSignature ms, base_ms;
3635 if (this is Indexer) {
3636 string name, base_name;
3638 report_name = "this";
3639 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
3640 ms = new MethodSignature (name, null, ParameterTypes);
3641 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
3642 base_ms = new MethodSignature (base_name, null, ParameterTypes);
3645 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
3649 // Verify if the parent has a type with the same name, and then
3650 // check whether we have to create a new slot for it or not.
3652 Type ptype = container.TypeBuilder.BaseType;
3654 // ptype is only null for System.Object while compiling corlib.
3655 if (ptype == null) {
3656 if ((ModFlags & Modifiers.NEW) != 0)
3657 WarningNotHiding (container);
3662 MemberList props_this;
3664 props_this = TypeContainer.FindMembers (
3665 container.TypeBuilder, MemberTypes.Property,
3666 BindingFlags.NonPublic | BindingFlags.Public |
3667 BindingFlags.Static | BindingFlags.Instance |
3668 BindingFlags.DeclaredOnly,
3669 MethodSignature.method_signature_filter, ms);
3671 if (props_this.Count > 0) {
3672 Report.Error (111, Location, "Class `" + container.Name + "' " +
3673 "already defines a member called `" + report_name + "' " +
3674 "with the same parameter types");
3678 MemberList mi_props;
3680 mi_props = TypeContainer.FindMembers (
3681 ptype, MemberTypes.Property,
3682 BindingFlags.NonPublic | BindingFlags.Public |
3683 BindingFlags.Instance | BindingFlags.Static,
3684 MethodSignature.inheritable_method_signature_filter, base_ms);
3686 if (mi_props.Count > 0){
3687 PropertyInfo parent_property = (PropertyInfo) mi_props [0];
3688 string name = parent_property.DeclaringType.Name + "." +
3689 parent_property.Name;
3691 MethodInfo get, set, parent_method;
3692 get = parent_property.GetGetMethod (true);
3693 set = parent_property.GetSetMethod (true);
3696 parent_method = get;
3697 else if (set != null)
3698 parent_method = set;
3700 throw new Exception ("Internal error!");
3702 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
3705 if ((ModFlags & Modifiers.NEW) == 0) {
3706 Type parent_type = TypeManager.TypeToCoreType (
3707 parent_property.PropertyType);
3709 if (parent_type != MemberType) {
3711 508, Location, container.MakeName (Name) + ": cannot " +
3712 "change return type when overriding " +
3713 "inherited member " + name);
3718 if ((ModFlags & Modifiers.NEW) != 0)
3719 WarningNotHiding (container);
3721 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3722 if (this is Indexer)
3723 Report.Error (115, Location,
3724 container.MakeName (Name) +
3725 " no suitable indexers found to override");
3727 Report.Error (115, Location,
3728 container.MakeName (Name) +
3729 " no suitable properties found to override");
3736 public void Emit (TypeContainer tc)
3739 // The PropertyBuilder can be null for explicit implementations, in that
3740 // case, we do not actually emit the ".property", so there is nowhere to
3741 // put the attribute
3743 if (PropertyBuilder != null)
3744 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes);
3746 if (GetData != null) {
3747 GetData.Emit (tc, Get.Block, Get);
3751 if (SetData != null) {
3752 SetData.Emit (tc, Set.Block, Set);
3758 public class Property : PropertyBase {
3759 const int AllowedModifiers =
3762 Modifiers.PROTECTED |
3763 Modifiers.INTERNAL |
3767 Modifiers.OVERRIDE |
3768 Modifiers.ABSTRACT |
3773 public Property (Expression type, string name, int mod_flags,
3774 Accessor get_block, Accessor set_block,
3775 Attributes attrs, Location loc)
3776 : base (type, name, mod_flags, AllowedModifiers,
3777 Parameters.EmptyReadOnlyParameters,
3778 get_block, set_block, attrs, loc)
3782 public override bool Define (TypeContainer container)
3784 if (!DoDefine (container))
3787 if (!CheckBase (container))
3790 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3793 Type [] parameters = TypeManager.NoTypes;
3795 InternalParameters ip = new InternalParameters (
3796 container, Parameters.EmptyReadOnlyParameters);
3798 GetData = new MethodData (this, "get", MemberType,
3799 parameters, ip, CallingConventions.Standard,
3800 Get.OptAttributes, ModFlags, flags, false);
3802 if (!GetData.Define (container))
3805 GetBuilder = GetData.MethodBuilder;
3809 Type [] parameters = new Type [1];
3810 parameters [0] = MemberType;
3812 Parameter [] parms = new Parameter [1];
3813 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3814 InternalParameters ip = new InternalParameters (
3815 container, new Parameters (parms, null, Location));
3817 SetData = new MethodData (this, "set", TypeManager.void_type,
3818 parameters, ip, CallingConventions.Standard,
3819 Set.OptAttributes, ModFlags, flags, false);
3821 if (!SetData.Define (container))
3824 SetBuilder = SetData.MethodBuilder;
3825 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3828 // FIXME - PropertyAttributes.HasDefault ?
3830 PropertyAttributes prop_attr =
3831 PropertyAttributes.RTSpecialName |
3832 PropertyAttributes.SpecialName;
3834 if (!IsExplicitImpl){
3835 PropertyBuilder = container.TypeBuilder.DefineProperty (
3836 Name, prop_attr, MemberType, null);
3839 PropertyBuilder.SetGetMethod (GetBuilder);
3842 PropertyBuilder.SetSetMethod (SetBuilder);
3845 // HACK for the reasons exposed above
3847 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3850 "Class `" + container.Name +
3851 "' already contains a definition for the property `" +
3861 /// Gigantic workaround for lameness in SRE follows :
3862 /// This class derives from EventInfo and attempts to basically
3863 /// wrap around the EventBuilder so that FindMembers can quickly
3864 /// return this in it search for members
3866 public class MyEventBuilder : EventInfo {
3869 // We use this to "point" to our Builder which is
3870 // not really a MemberInfo
3872 EventBuilder MyBuilder;
3875 // We "catch" and wrap these methods
3877 MethodInfo raise, remove, add;
3879 EventAttributes attributes;
3880 Type declaring_type, reflected_type, event_type;
3885 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3887 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3889 // And now store the values in our own fields.
3891 declaring_type = type_builder;
3893 reflected_type = type_builder;
3895 attributes = event_attr;
3898 this.event_type = event_type;
3902 // Methods that you have to override. Note that you only need
3903 // to "implement" the variants that take the argument (those are
3904 // the "abstract" methods, the others (GetAddMethod()) are
3907 public override MethodInfo GetAddMethod (bool nonPublic)
3912 public override MethodInfo GetRemoveMethod (bool nonPublic)
3917 public override MethodInfo GetRaiseMethod (bool nonPublic)
3923 // These methods make "MyEventInfo" look like a Builder
3925 public void SetRaiseMethod (MethodBuilder raiseMethod)
3927 raise = raiseMethod;
3928 MyBuilder.SetRaiseMethod (raiseMethod);
3931 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3933 remove = removeMethod;
3934 MyBuilder.SetRemoveOnMethod (removeMethod);
3937 public void SetAddOnMethod (MethodBuilder addMethod)
3940 MyBuilder.SetAddOnMethod (addMethod);
3943 public void SetCustomAttribute (CustomAttributeBuilder cb)
3945 MyBuilder.SetCustomAttribute (cb);
3948 public override object [] GetCustomAttributes (bool inherit)
3950 // FIXME : There's nothing which can be seemingly done here because
3951 // we have no way of getting at the custom attribute objects of the
3956 public override object [] GetCustomAttributes (Type t, bool inherit)
3958 // FIXME : Same here !
3962 public override bool IsDefined (Type t, bool b)
3967 public override EventAttributes Attributes {
3973 public override string Name {
3979 public override Type DeclaringType {
3981 return declaring_type;
3985 public override Type ReflectedType {
3987 return reflected_type;
3991 public Type EventType {
3997 public void SetUsed ()
3999 if (my_event != null)
4000 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
4004 public class Event : FieldBase {
4005 const int AllowedModifiers =
4008 Modifiers.PROTECTED |
4009 Modifiers.INTERNAL |
4014 Modifiers.OVERRIDE |
4018 public readonly Accessor Add;
4019 public readonly Accessor Remove;
4020 public MyEventBuilder EventBuilder;
4022 MethodBuilder AddBuilder, RemoveBuilder;
4023 MethodData AddData, RemoveData;
4025 public Event (Expression type, string name, Object init, int mod, Accessor add,
4026 Accessor remove, Attributes attrs, Location loc)
4027 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4033 public override bool Define (TypeContainer container)
4035 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4037 if (!DoDefine (container))
4040 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
4041 Report.Error (74, Location, "'" + container.Name + "." + Name +
4042 "': abstract event can not have an initializer");
4046 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4047 Report.Error (66, Location, "'" + container.Name + "." + Name +
4048 "' : event must be of a delegate type");
4052 Type [] parameter_types = new Type [1];
4053 parameter_types [0] = MemberType;
4055 Parameter [] parms = new Parameter [1];
4056 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4057 InternalParameters ip = new InternalParameters (
4058 container, new Parameters (parms, null, Location));
4060 if (!CheckBase (container))
4064 // Now define the accessors
4066 AddData = new MethodData (this, "add", TypeManager.void_type,
4067 parameter_types, ip, CallingConventions.Standard,
4068 (Add != null) ? Add.OptAttributes : null,
4069 ModFlags, flags, false);
4071 if (!AddData.Define (container))
4074 AddBuilder = AddData.MethodBuilder;
4075 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4077 RemoveData = new MethodData (this, "remove", TypeManager.void_type,
4078 parameter_types, ip, CallingConventions.Standard,
4079 (Remove != null) ? Remove.OptAttributes : null,
4080 ModFlags, flags, false);
4082 if (!RemoveData.Define (container))
4085 RemoveBuilder = RemoveData.MethodBuilder;
4086 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4088 if (!IsExplicitImpl){
4089 EventBuilder = new MyEventBuilder (this,
4090 container.TypeBuilder, Name, e_attr, MemberType);
4092 if (Add == null && Remove == null) {
4093 FieldBuilder = container.TypeBuilder.DefineField (
4095 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4096 TypeManager.RegisterPrivateFieldOfEvent (
4097 (EventInfo) EventBuilder, FieldBuilder);
4098 TypeManager.RegisterFieldBase (FieldBuilder, this);
4101 EventBuilder.SetAddOnMethod (AddBuilder);
4102 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4104 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4105 Report.Error (111, Location,
4106 "Class `" + container.Name +
4107 "' already contains a definition for the event `" +
4116 void EmitDefaultMethod (EmitContext ec, bool is_add)
4118 ILGenerator ig = ec.ig;
4119 MethodInfo method = null;
4122 method = TypeManager.delegate_combine_delegate_delegate;
4124 method = TypeManager.delegate_remove_delegate_delegate;
4126 if ((ModFlags & Modifiers.STATIC) != 0) {
4127 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4128 ig.Emit (OpCodes.Ldarg_0);
4129 ig.Emit (OpCodes.Call, method);
4130 ig.Emit (OpCodes.Castclass, MemberType);
4131 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4133 ig.Emit (OpCodes.Ldarg_0);
4134 ig.Emit (OpCodes.Ldarg_0);
4135 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4136 ig.Emit (OpCodes.Ldarg_1);
4137 ig.Emit (OpCodes.Call, method);
4138 ig.Emit (OpCodes.Castclass, MemberType);
4139 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4141 ig.Emit (OpCodes.Ret);
4144 public void Emit (TypeContainer tc)
4148 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4149 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes);
4152 AddData.Emit (tc, Add.Block, Add);
4155 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4156 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4157 EmitDefaultMethod (ec, true);
4160 if (Remove != null) {
4161 RemoveData.Emit (tc, Remove.Block, Remove);
4162 Remove.Block = null;
4164 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4165 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4166 EmitDefaultMethod (ec, false);
4173 // FIXME: This does not handle:
4175 // int INTERFACENAME [ args ]
4180 // int this [ args ]
4182 public class Indexer : PropertyBase {
4184 const int AllowedModifiers =
4187 Modifiers.PROTECTED |
4188 Modifiers.INTERNAL |
4192 Modifiers.OVERRIDE |
4197 public string IndexerName;
4198 public string InterfaceIndexerName;
4201 // Are we implementing an interface ?
4203 bool IsImplementing = false;
4205 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4206 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4207 : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4210 ExplicitInterfaceName = int_type;
4213 public override bool Define (TypeContainer container)
4215 PropertyAttributes prop_attr =
4216 PropertyAttributes.RTSpecialName |
4217 PropertyAttributes.SpecialName;
4219 if (!DoDefine (container))
4222 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4223 if (IndexerName == null)
4224 IndexerName = "Item";
4225 else if (IsExplicitImpl)
4226 Report.Error (592, Location,
4227 "Attribute 'IndexerName' is not valid on this declaration " +
4228 "type. It is valid on `property' declarations only.");
4230 ShortName = IndexerName;
4231 if (IsExplicitImpl) {
4232 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4233 Name = InterfaceType.FullName + "." + IndexerName;
4235 InterfaceIndexerName = IndexerName;
4239 if (!CheckBase (container))
4242 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4244 InternalParameters ip = new InternalParameters (container, Parameters);
4246 GetData = new MethodData (this, "get", MemberType,
4247 ParameterTypes, ip, CallingConventions.Standard,
4248 Get.OptAttributes, ModFlags, flags, false);
4250 if (!GetData.Define (container))
4253 GetBuilder = GetData.MethodBuilder;
4257 int top = ParameterTypes.Length;
4258 Type [] set_pars = new Type [top + 1];
4259 ParameterTypes.CopyTo (set_pars, 0);
4260 set_pars [top] = MemberType;
4262 Parameter [] fixed_parms = Parameters.FixedParameters;
4264 if (fixed_parms == null){
4265 throw new Exception ("We currently do not support only array arguments in an indexer");
4266 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4267 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4269 // Here is the problem: the `value' parameter has
4270 // to come *after* the array parameter in the declaration
4272 // X (object [] x, Type value)
4275 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4276 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4280 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4283 fixed_parms.CopyTo (tmp, 0);
4284 tmp [fixed_parms.Length] = new Parameter (
4285 Type, "value", Parameter.Modifier.NONE, null);
4287 Parameters set_formal_params = new Parameters (tmp, null, Location);
4289 InternalParameters ip = new InternalParameters (container, set_formal_params);
4291 SetData = new MethodData (this, "set", TypeManager.void_type,
4292 set_pars, ip, CallingConventions.Standard,
4293 Set.OptAttributes, ModFlags, flags, false);
4295 if (!SetData.Define (container))
4298 SetBuilder = SetData.MethodBuilder;
4302 // Now name the parameters
4304 Parameter [] p = Parameters.FixedParameters;
4308 for (i = 0; i < p.Length; ++i) {
4310 GetBuilder.DefineParameter (
4311 i + 1, p [i].Attributes, p [i].Name);
4314 SetBuilder.DefineParameter (
4315 i + 1, p [i].Attributes, p [i].Name);
4319 SetBuilder.DefineParameter (
4320 i + 1, ParameterAttributes.None, "value");
4322 if (i != ParameterTypes.Length) {
4323 Parameter array_param = Parameters.ArrayParameter;
4324 SetBuilder.DefineParameter (
4325 i + 1, array_param.Attributes, array_param.Name);
4329 if (GetData != null)
4330 IsImplementing = GetData.IsImplementing;
4331 else if (SetData != null)
4332 IsImplementing = SetData.IsImplementing;
4335 // Define the PropertyBuilder if one of the following conditions are met:
4336 // a) we're not implementing an interface indexer.
4337 // b) the indexer has a different IndexerName and this is no
4338 // explicit interface implementation.
4340 if (!IsExplicitImpl) {
4341 PropertyBuilder = container.TypeBuilder.DefineProperty (
4342 IndexerName, prop_attr, MemberType, ParameterTypes);
4344 if (GetData != null)
4345 PropertyBuilder.SetGetMethod (GetBuilder);
4347 if (SetData != null)
4348 PropertyBuilder.SetSetMethod (SetBuilder);
4350 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4358 public class Operator : MemberCore {
4360 const int AllowedModifiers =
4366 const int RequiredModifiers =
4370 public enum OpType : byte {
4380 // Unary and Binary operators
4403 // Implicit and Explicit
4408 public readonly OpType OperatorType;
4409 public readonly Expression ReturnType;
4410 public readonly Expression FirstArgType, SecondArgType;
4411 public readonly string FirstArgName, SecondArgName;
4413 public Attributes OptAttributes;
4414 public MethodBuilder OperatorMethodBuilder;
4416 public string MethodName;
4417 public Method OperatorMethod;
4419 public Operator (OpType type, Expression ret_type, int flags,
4420 Expression arg1type, string arg1name,
4421 Expression arg2type, string arg2name,
4422 Block block, Attributes attrs, Location loc)
4425 OperatorType = type;
4426 ReturnType = ret_type;
4427 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4428 FirstArgType = arg1type;
4429 FirstArgName = arg1name;
4430 SecondArgType = arg2type;
4431 SecondArgName = arg2name;
4433 OptAttributes = attrs;
4436 string Prototype (TypeContainer container)
4438 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4439 SecondArgType + ")";
4442 public override bool Define (TypeContainer container)
4445 MethodName = "op_" + OperatorType;
4447 if (SecondArgType != null)
4450 Parameter [] param_list = new Parameter [length];
4452 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4455 "User defined operators `" +
4456 Prototype (container) +
4457 "' must be declared static and public");
4461 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4462 Parameter.Modifier.NONE, null);
4463 if (SecondArgType != null)
4464 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4465 Parameter.Modifier.NONE, null);
4467 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4468 new Parameters (param_list, null, Location),
4469 OptAttributes, Location);
4471 OperatorMethod.IsOperator = true;
4472 OperatorMethod.Define (container);
4474 if (OperatorMethod.MethodBuilder == null)
4477 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4479 Type [] param_types = OperatorMethod.ParameterTypes;
4480 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4481 Type return_type = OperatorMethod.GetReturnType ();
4482 Type first_arg_type = param_types [0];
4484 // Rules for conversion operators
4486 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4487 if (first_arg_type == return_type && first_arg_type == declaring_type){
4490 "User-defined conversion cannot take an object of the " +
4491 "enclosing type and convert to an object of the enclosing" +
4496 if (first_arg_type != declaring_type && return_type != declaring_type){
4499 "User-defined conversion must convert to or from the " +
4504 if (first_arg_type == TypeManager.object_type ||
4505 return_type == TypeManager.object_type){
4508 "User-defined conversion cannot convert to or from " +
4513 if (first_arg_type.IsInterface || return_type.IsInterface){
4516 "User-defined conversion cannot convert to or from an " +
4521 if (first_arg_type.IsSubclassOf (return_type) ||
4522 return_type.IsSubclassOf (first_arg_type)){
4525 "User-defined conversion cannot convert between types " +
4526 "that derive from each other");
4529 } else if (SecondArgType == null) {
4530 // Checks for Unary operators
4532 if (first_arg_type != declaring_type){
4535 "The parameter of a unary operator must be the " +
4540 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4541 if (return_type != declaring_type){
4544 "The parameter and return type for ++ and -- " +
4545 "must be the containing type");
4551 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4552 if (return_type != TypeManager.bool_type){
4555 "The return type of operator True or False " +
4562 // Checks for Binary operators
4564 if (first_arg_type != declaring_type &&
4565 param_types [1] != declaring_type){
4568 "One of the parameters of a binary operator must " +
4569 "be the containing type");
4577 public void Emit (TypeContainer container)
4579 EmitContext ec = new EmitContext (container, Location, null, null, ModFlags);
4580 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes);
4583 // abstract or extern methods have no bodies
4585 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4588 OperatorMethod.Block = Block;
4589 OperatorMethod.Emit (container);
4593 public static string GetName (OpType ot)
4596 case OpType.LogicalNot:
4598 case OpType.OnesComplement:
4600 case OpType.Increment:
4602 case OpType.Decrement:
4608 case OpType.Addition:
4610 case OpType.Subtraction:
4612 case OpType.UnaryPlus:
4614 case OpType.UnaryNegation:
4616 case OpType.Multiply:
4618 case OpType.Division:
4620 case OpType.Modulus:
4622 case OpType.BitwiseAnd:
4624 case OpType.BitwiseOr:
4626 case OpType.ExclusiveOr:
4628 case OpType.LeftShift:
4630 case OpType.RightShift:
4632 case OpType.Equality:
4634 case OpType.Inequality:
4636 case OpType.GreaterThan:
4638 case OpType.LessThan:
4640 case OpType.GreaterThanOrEqual:
4642 case OpType.LessThanOrEqual:
4644 case OpType.Implicit:
4646 case OpType.Explicit:
4652 public override string ToString ()
4654 Type return_type = OperatorMethod.GetReturnType();
4655 Type [] param_types = OperatorMethod.ParameterTypes;
4657 if (SecondArgType == null)
4658 return String.Format (
4659 "{0} operator {1}({2})",
4660 TypeManager.CSharpName (return_type),
4661 GetName (OperatorType),
4664 return String.Format (
4665 "{0} operator {1}({2}, {3})",
4666 TypeManager.CSharpName (return_type),
4667 GetName (OperatorType),
4668 param_types [0], param_types [1]);
4673 // This is used to compare method signatures
4675 struct MethodSignature {
4677 public Type RetType;
4678 public Type [] Parameters;
4681 /// This delegate is used to extract methods which have the
4682 /// same signature as the argument
4684 public static MemberFilter method_signature_filter;
4687 /// This delegate is used to extract inheritable methods which
4688 /// have the same signature as the argument. By inheritable,
4689 /// this means that we have permissions to override the method
4690 /// from the current assembly and class
4692 public static MemberFilter inheritable_method_signature_filter;
4694 static MethodSignature ()
4696 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4697 inheritable_method_signature_filter = new MemberFilter (
4698 InheritableMemberSignatureCompare);
4701 public MethodSignature (string name, Type ret_type, Type [] parameters)
4706 if (parameters == null)
4707 Parameters = TypeManager.NoTypes;
4709 Parameters = parameters;
4712 public override string ToString ()
4715 if (Parameters.Length != 0){
4716 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
4717 for (int i = 0; i < Parameters.Length; i++){
4718 sb.Append (Parameters [i]);
4719 if (i+1 < Parameters.Length)
4722 pars = sb.ToString ();
4725 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
4728 public override int GetHashCode ()
4730 return Name.GetHashCode ();
4733 public override bool Equals (Object o)
4735 MethodSignature other = (MethodSignature) o;
4737 if (other.Name != Name)
4740 if (other.RetType != RetType)
4743 if (Parameters == null){
4744 if (other.Parameters == null)
4749 if (other.Parameters == null)
4752 int c = Parameters.Length;
4753 if (other.Parameters.Length != c)
4756 for (int i = 0; i < c; i++)
4757 if (other.Parameters [i] != Parameters [i])
4763 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4765 MethodSignature sig = (MethodSignature) filter_criteria;
4767 if (m.Name != sig.Name)
4771 MethodInfo mi = m as MethodInfo;
4772 PropertyInfo pi = m as PropertyInfo;
4775 ReturnType = mi.ReturnType;
4776 else if (pi != null)
4777 ReturnType = pi.PropertyType;
4782 // we use sig.RetType == null to mean `do not check the
4783 // method return value.
4785 if (sig.RetType != null)
4786 if (ReturnType != sig.RetType)
4791 args = TypeManager.GetArgumentTypes (mi);
4793 args = TypeManager.GetArgumentTypes (pi);
4794 Type [] sigp = sig.Parameters;
4796 if (args.Length != sigp.Length)
4799 for (int i = args.Length; i > 0; ){
4801 if (args [i] != sigp [i])
4808 // This filter should be used when we are requesting methods that
4809 // we want to override.
4811 // This makes a number of assumptions, for example
4812 // that the methods being extracted are of a parent
4813 // class (this means we know implicitly that we are
4814 // being called to find out about members by a derived
4817 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4820 PropertyInfo pi = m as PropertyInfo;
4823 mi = pi.GetGetMethod (true);
4825 mi = pi.GetSetMethod (true);
4827 mi = m as MethodInfo;
4830 Console.WriteLine ("Nothing found");
4833 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4835 // If only accessible to the current class.
4836 if (prot == MethodAttributes.Private)
4839 if (!MemberSignatureCompare (m, filter_criteria))
4842 // If only accessible to the defining assembly or
4843 if (prot == MethodAttributes.FamANDAssem ||
4844 prot == MethodAttributes.Assembly){
4845 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4851 // Anything else (FamOrAssembly and Public) is fine