3 // class.cs: Class and Struct handlers
5 // Authors: Miguel de Icaza (miguel@gnu.org)
6 // Martin Baulig (martin@gnome.org)
8 // Licensed under the terms of the GNU GPL
10 // (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
15 using System.Collections;
16 using System.Reflection;
17 using System.Reflection.Emit;
18 using System.Runtime.CompilerServices;
19 using System.Diagnostics.SymbolStore;
21 namespace Mono.CSharp {
24 /// This is the base class for structs and classes.
26 public class TypeContainer : DeclSpace, IMemberContainer {
27 // Holds a list of classes and structures
30 // Holds the list of properties
33 // Holds the list of enumerations
36 // Holds the list of delegates
39 // Holds the list of constructors
40 ArrayList instance_constructors;
42 // Holds the list of fields
45 // Holds a list of fields that have initializers
46 ArrayList initialized_fields;
48 // Holds a list of static fields that have initializers
49 ArrayList initialized_static_fields;
51 // Holds the list of constants
57 // Holds order in which interfaces must be closed
58 ArrayList interface_order;
69 // Holds the operators
72 // The emit context for toplevel objects.
76 // Pointers to the default constructor and the default static constructor
78 Constructor default_constructor;
79 Constructor default_static_constructor;
82 // Whether we have seen a static constructor for this class or not
84 bool have_static_constructor = false;
87 // Whether we have at least one non-static field
89 bool have_nonstatic_fields = false;
92 // This one is computed after we can distinguish interfaces
93 // from classes from the arraylist `type_bases'
95 string base_class_name;
99 // Attributes for this type
100 protected Attributes attributes;
102 // Information in the case we are an attribute type
104 public AttributeTargets Targets = AttributeTargets.All;
105 public bool AllowMultiple = false;
106 public bool Inherited;
108 // The interfaces we implement.
111 // The parent member container and our member cache
112 IMemberContainer parent_container;
113 MemberCache member_cache;
116 // The indexer name for this class
118 public string IndexerName;
120 public TypeContainer (TypeContainer parent, string name, Location l)
121 : base (parent, name, l)
124 types = new ArrayList ();
131 base_class_name = null;
133 //Console.WriteLine ("New class " + name + " inside " + n);
136 public AdditionResult AddConstant (Const constant)
139 string name = constant.Name;
141 if ((res = IsValid (name)) != AdditionResult.Success)
144 if (constants == null)
145 constants = new ArrayList ();
147 constants.Add (constant);
148 DefineName (name, constant);
150 return AdditionResult.Success;
153 public AdditionResult AddEnum (Mono.CSharp.Enum e)
156 string name = e.Name;
158 if ((res = IsValid (name)) != AdditionResult.Success)
162 enums = new ArrayList ();
165 DefineName (name, e);
167 return AdditionResult.Success;
170 public AdditionResult AddClass (Class c)
173 string name = c.Name;
176 if ((res = IsValid (name)) != AdditionResult.Success)
179 DefineName (name, c);
182 return AdditionResult.Success;
185 public AdditionResult AddStruct (Struct s)
188 string name = s.Name;
190 if ((res = IsValid (name)) != AdditionResult.Success)
193 DefineName (name, s);
196 return AdditionResult.Success;
199 public AdditionResult AddDelegate (Delegate d)
202 string name = d.Name;
204 if ((res = IsValid (name)) != AdditionResult.Success)
207 if (delegates == null)
208 delegates = new ArrayList ();
210 DefineName (name, d);
213 return AdditionResult.Success;
216 public AdditionResult AddMethod (Method method)
218 string name = Name + "." + method.Name;
219 Object value = defined_names [name];
221 if (value != null && (!(value is Method)))
222 return AdditionResult.NameExists;
224 if (name == Basename)
225 return AdditionResult.EnclosingClash;
228 methods = new ArrayList ();
230 if (method.Name.IndexOf (".") != -1)
231 methods.Insert (0, method);
233 methods.Add (method);
236 DefineName (name, method);
238 return AdditionResult.Success;
241 public AdditionResult AddConstructor (Constructor c)
243 if (c.Name != Basename)
244 return AdditionResult.NotAConstructor;
246 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
249 have_static_constructor = true;
250 if (default_static_constructor != null){
251 Console.WriteLine ("I have a static constructor already");
252 Console.WriteLine (" " + default_static_constructor);
253 return AdditionResult.MethodExists;
256 default_static_constructor = c;
259 if (default_constructor != null)
260 return AdditionResult.MethodExists;
261 default_constructor = c;
264 if (instance_constructors == null)
265 instance_constructors = new ArrayList ();
267 instance_constructors.Add (c);
270 return AdditionResult.Success;
273 public AdditionResult AddInterface (Interface iface)
276 string name = iface.Name;
278 if ((res = IsValid (name)) != AdditionResult.Success)
281 if (interfaces == null)
282 interfaces = new ArrayList ();
283 interfaces.Add (iface);
284 DefineName (name, iface);
286 return AdditionResult.Success;
289 public AdditionResult AddField (Field field)
292 string name = field.Name;
294 if ((res = IsValid (name)) != AdditionResult.Success)
298 fields = new ArrayList ();
302 if (field.HasInitializer){
303 if ((field.ModFlags & Modifiers.STATIC) != 0){
304 if (initialized_static_fields == null)
305 initialized_static_fields = new ArrayList ();
307 initialized_static_fields.Add (field);
310 // We have not seen a static constructor,
311 // but we will provide static initialization of fields
313 have_static_constructor = true;
315 if (initialized_fields == null)
316 initialized_fields = new ArrayList ();
318 initialized_fields.Add (field);
322 if ((field.ModFlags & Modifiers.STATIC) == 0)
323 have_nonstatic_fields = true;
325 DefineName (name, field);
326 return AdditionResult.Success;
329 public AdditionResult AddProperty (Property prop)
332 string name = prop.Name;
334 if ((res = IsValid (name)) != AdditionResult.Success)
337 if (properties == null)
338 properties = new ArrayList ();
340 if (prop.Name.IndexOf (".") != -1)
341 properties.Insert (0, prop);
343 properties.Add (prop);
344 DefineName (name, prop);
346 return AdditionResult.Success;
349 public AdditionResult AddEvent (Event e)
352 string name = e.Name;
354 if ((res = IsValid (name)) != AdditionResult.Success)
358 events = new ArrayList ();
361 DefineName (name, e);
363 return AdditionResult.Success;
366 public AdditionResult AddIndexer (Indexer i)
368 if (indexers == null)
369 indexers = new ArrayList ();
371 if (i.InterfaceType != null)
372 indexers.Insert (0, i);
376 return AdditionResult.Success;
379 public AdditionResult AddOperator (Operator op)
381 if (operators == null)
382 operators = new ArrayList ();
386 return AdditionResult.Success;
389 public void RegisterOrder (Interface iface)
391 if (interface_order == null)
392 interface_order = new ArrayList ();
394 interface_order.Add (iface);
397 public ArrayList Types {
403 public ArrayList Methods {
409 public ArrayList Constants {
415 public ArrayList Interfaces {
423 return base_class_name;
427 public ArrayList Bases {
437 public ArrayList Fields {
447 public ArrayList InstanceConstructors {
449 return instance_constructors;
453 public ArrayList Properties {
459 public ArrayList Events {
465 public ArrayList Enums {
471 public ArrayList Indexers {
477 public ArrayList Operators {
483 public ArrayList Delegates {
489 public Attributes OptAttributes {
495 public bool HaveStaticConstructor {
497 return have_static_constructor;
501 public virtual TypeAttributes TypeAttr {
503 return Modifiers.TypeAttr (ModFlags, this);
508 // Emits the instance field initializers
510 public bool EmitFieldInitializers (EmitContext ec)
513 ILGenerator ig = ec.ig;
514 Expression instance_expr;
517 fields = initialized_static_fields;
518 instance_expr = null;
520 fields = initialized_fields;
521 instance_expr = new This (Location.Null).Resolve (ec);
527 foreach (Field f in fields){
528 Expression e = f.GetInitializerExpression (ec);
532 Location l = f.Location;
533 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
534 fe.InstanceExpression = instance_expr;
535 Expression a = new Assign (fe, e, l);
541 if (a is ExpressionStatement)
542 ((ExpressionStatement) a).EmitStatement (ec);
544 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
552 // Defines the default constructors
554 void DefineDefaultConstructor (bool is_static)
559 c = new Constructor (Basename, Parameters.EmptyReadOnlyParameters,
560 new ConstructorBaseInitializer (
561 null, Parameters.EmptyReadOnlyParameters,
566 mods = Modifiers.STATIC;
572 c.Block = new Block (null);
576 public void ReportStructInitializedInstanceError ()
578 string n = TypeBuilder.FullName;
580 foreach (Field f in initialized_fields){
583 "`" + n + "." + f.Name + "': can not have " +
584 "instance field initializers in structs");
589 /// The pending methods that need to be implemented (interfaces or abstract methods)
591 public PendingImplementation Pending;
594 /// This function computes the Base class and also the
595 /// list of interfaces that the class or struct @c implements.
597 /// The return value is an array (might be null) of
598 /// interfaces implemented (as Types).
600 /// The @parent argument is set to the parent object or null
601 /// if this is `System.Object'.
603 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
605 ArrayList bases = Bases;
614 parent = TypeManager.value_type;
618 if (RootContext.StdLib)
619 parent = TypeManager.object_type;
620 else if (Name != "System.Object")
621 parent = TypeManager.object_type;
624 // If we are compiling our runtime,
625 // and we are defining ValueType, then our
626 // parent is `System.Object'.
628 if (!RootContext.StdLib && Name == "System.ValueType")
629 parent = TypeManager.object_type;
636 // Bases should be null if there are no bases at all
641 Expression name = (Expression) bases [0];
642 name = ResolveTypeExpr (name, false, Location);
649 Type first = name.Type;
655 parent = TypeManager.object_type;
659 if (!AsAccessible (parent, ModFlags))
660 Report.Error (60, Location,
661 "Inconsistent accessibility: base class `" +
662 TypeManager.CSharpName (parent) + "' is less " +
663 "accessible than class `" +
670 Type [] ifaces = new Type [count-start];
672 for (i = start, j = 0; i < count; i++, j++){
673 Expression name = (Expression) bases [i];
674 Expression resolved = ResolveTypeExpr (name, false, Location);
675 bases [i] = resolved;
676 Type t = resolved.Type;
683 if (is_class == false && !t.IsInterface){
684 Report.Error (527, "In Struct `" + Name + "', type `"+
685 name +"' is not an interface");
694 detail = " (a class can not inherit from a struct/enum)";
696 Report.Error (509, "class `"+ Name +
697 "': Cannot inherit from sealed class `"+
698 bases [i]+"'"+detail);
705 Report.Error (527, "In Class `" + Name + "', type `"+
706 name+"' is not an interface");
712 for (int x = 0; x < j; x++) {
713 if (t == ifaces [x]) {
714 Report.Error (528, "`" + name + "' is already listed in interface list");
723 return TypeManager.ExpandInterfaces (ifaces);
727 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
729 public override TypeBuilder DefineType ()
735 if (TypeBuilder != null)
748 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
750 ifaces = GetClassBases (is_class, out parent, out error);
755 if (is_class && parent != null){
756 if (parent == TypeManager.enum_type ||
757 (parent == TypeManager.value_type && RootContext.StdLib) ||
758 parent == TypeManager.delegate_type ||
759 parent == TypeManager.array_type){
761 644, Location, "`" + Name + "' cannot inherit from " +
762 "special class `" + TypeManager.CSharpName (parent) + "'");
767 if (!is_class && TypeManager.value_type == null)
768 throw new Exception ();
770 TypeAttributes type_attributes = TypeAttr;
772 // if (parent_builder is ModuleBuilder) {
774 ModuleBuilder builder = CodeGen.ModuleBuilder;
775 TypeBuilder = builder.DefineType (
776 Name, type_attributes, parent, ifaces);
779 TypeBuilder builder = Parent.TypeBuilder;
780 TypeBuilder = builder.DefineNestedType (
781 Basename, type_attributes, parent, ifaces);
785 // Structs with no fields need to have at least one byte.
786 // The right thing would be to set the PackingSize in a DefineType
787 // but there are no functions that allow interfaces *and* the size to
791 if (!is_class && !have_nonstatic_fields){
792 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
793 FieldAttributes.Private);
796 // add interfaces that were not added at type creation (weird API issue)
797 if (!is_class && !have_nonstatic_fields && (ifaces != null)) {
798 foreach (Type i in ifaces)
799 TypeBuilder.AddInterfaceImplementation (i);
803 // Finish the setup for the EmitContext
805 ec.ContainerType = TypeBuilder;
807 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
809 if ((parent != null) &&
810 (parent == TypeManager.attribute_type ||
811 parent.IsSubclassOf (TypeManager.attribute_type))) {
812 RootContext.RegisterAttribute (this);
813 TypeManager.RegisterAttrType (TypeBuilder, this);
815 RootContext.RegisterOrder (this);
817 if (Interfaces != null) {
818 foreach (Interface iface in Interfaces)
823 foreach (TypeContainer tc in Types)
827 if (Delegates != null) {
828 foreach (Delegate d in Delegates)
833 foreach (Enum en in Enums)
843 /// Defines the MemberCore objects that are in the `list' Arraylist
845 /// The `defined_names' array contains a list of members defined in
848 static ArrayList remove_list = new ArrayList ();
849 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
853 remove_list.Clear ();
855 foreach (MemberCore mc in list){
856 if (!mc.Define (this)){
857 remove_list.Add (mc);
861 if (defined_names == null)
864 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
866 if (RootContext.WarningLevel >= 4){
867 if ((mc.ModFlags & Modifiers.NEW) != 0)
868 Warning_KewywordNewNotRequired (mc.Location, mc);
873 MemberInfo match = defined_names [idx];
875 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
879 // If we are both methods, let the method resolution emit warnings
881 if (match is MethodBase && mc is MethodCore)
884 if ((mc.ModFlags & Modifiers.NEW) == 0)
885 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
888 foreach (object o in remove_list)
891 remove_list.Clear ();
895 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
896 // class is consisten. Either it is `Item' or it is the name defined by all the
897 // indexers with the `IndexerName' attribute.
899 // Turns out that the IndexerNameAttribute is applied to each indexer,
900 // but it is never emitted, instead a DefaultName attribute is attached
903 void DefineIndexers ()
905 string class_indexer_name = null;
907 foreach (Indexer i in Indexers){
912 name = i.IndexerName;
914 if (i.InterfaceType != null)
917 if (class_indexer_name == null){
918 class_indexer_name = name;
922 if (name == class_indexer_name)
926 668, "Two indexers have different names, " +
927 " you should use the same name for all your indexers");
929 if (class_indexer_name == null)
930 class_indexer_name = "Item";
931 IndexerName = class_indexer_name;
934 static void Error_KeywordNotAllowed (Location loc)
936 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
940 /// Populates our TypeBuilder with fields and methods
942 public override bool DefineMembers (TypeContainer parent)
944 MemberInfo [] defined_names = null;
946 if (interface_order != null){
947 foreach (Interface iface in interface_order)
948 if ((iface.ModFlags & Modifiers.NEW) == 0)
949 iface.DefineMembers (this);
951 Error_KeywordNotAllowed (iface.Location);
954 if (RootContext.WarningLevel > 1){
958 // This code throws an exception in the comparer
959 // I guess the string is not an object?
961 ptype = TypeBuilder.BaseType;
963 defined_names = (MemberInfo []) FindMembers (
964 ptype, MemberTypes.All & ~MemberTypes.Constructor,
965 BindingFlags.Public | BindingFlags.Instance |
966 BindingFlags.Static, null, null);
968 Array.Sort (defined_names, mif_compare);
972 if (constants != null)
973 DefineMembers (constants, defined_names);
976 DefineMembers (fields, defined_names);
979 if (instance_constructors == null){
980 if (default_constructor == null)
981 DefineDefaultConstructor (false);
984 if (initialized_static_fields != null &&
985 default_static_constructor == null)
986 DefineDefaultConstructor (true);
991 // Structs can not have initialized instance
994 if (initialized_static_fields != null &&
995 default_static_constructor == null)
996 DefineDefaultConstructor (true);
998 if (initialized_fields != null)
999 ReportStructInitializedInstanceError ();
1002 Pending = PendingImplementation.GetPendingImplementations (this);
1005 // Constructors are not in the defined_names array
1007 if (instance_constructors != null)
1008 DefineMembers (instance_constructors, null);
1010 if (default_static_constructor != null)
1011 default_static_constructor.Define (this);
1013 if (methods != null)
1014 DefineMembers (methods, defined_names);
1016 if (properties != null)
1017 DefineMembers (properties, defined_names);
1020 DefineMembers (events, defined_names);
1022 if (indexers != null) {
1025 IndexerName = "Item";
1027 if (operators != null){
1028 DefineMembers (operators, null);
1030 CheckPairedOperators ();
1034 DefineMembers (enums, defined_names);
1036 if (delegates != null)
1037 DefineMembers (delegates, defined_names);
1040 if (TypeBuilder.BaseType != null)
1041 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1043 member_cache = new MemberCache (this);
1049 public override bool Define (TypeContainer parent)
1051 if (interface_order != null){
1052 foreach (Interface iface in interface_order)
1053 if ((iface.ModFlags & Modifiers.NEW) == 0)
1054 iface.Define (this);
1061 /// This function is based by a delegate to the FindMembers routine
1063 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1069 /// This filter is used by FindMembers, and we just keep
1070 /// a global for the filter to `AlwaysAccept'
1072 static MemberFilter accepting_filter;
1076 /// A member comparission method based on name only
1078 static IComparer mif_compare;
1080 static TypeContainer ()
1082 accepting_filter = new MemberFilter (AlwaysAccept);
1083 mif_compare = new MemberInfoCompare ();
1087 /// This method returns the members of this type just like Type.FindMembers would
1088 /// Only, we need to use this for types which are _being_ defined because MS'
1089 /// implementation can't take care of that.
1092 // FIXME: return an empty static array instead of null, that cleans up
1093 // some code and is consistent with some coding conventions I just found
1097 // Notice that in various cases we check if our field is non-null,
1098 // something that would normally mean that there was a bug elsewhere.
1100 // The problem happens while we are defining p-invoke methods, as those
1101 // will trigger a FindMembers, but this happens before things are defined
1103 // Since the whole process is a no-op, it is fine to check for null here.
1105 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1106 MemberFilter filter, object criteria)
1108 ArrayList members = new ArrayList ();
1111 if ((bf & BindingFlags.Public) != 0)
1112 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1114 if ((bf & BindingFlags.NonPublic) != 0)
1115 modflags |= Modifiers.PRIVATE;
1117 int static_mask = 0, static_flags = 0;
1118 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1119 case BindingFlags.Static:
1120 static_mask = static_flags = Modifiers.STATIC;
1123 case BindingFlags.Instance:
1124 static_mask = Modifiers.STATIC;
1129 static_mask = static_flags = 0;
1133 Timer.StartTimer (TimerType.TcFindMembers);
1136 filter = accepting_filter;
1138 if ((mt & MemberTypes.Field) != 0) {
1139 if (fields != null) {
1140 foreach (Field f in fields) {
1141 if ((f.ModFlags & modflags) == 0)
1143 if ((f.ModFlags & static_mask) != static_flags)
1146 FieldBuilder fb = f.FieldBuilder;
1147 if (fb != null && filter (fb, criteria) == true)
1152 if (constants != null) {
1153 foreach (Const con in constants) {
1154 if ((con.ModFlags & modflags) == 0)
1156 if ((con.ModFlags & static_mask) != static_flags)
1159 FieldBuilder fb = con.FieldBuilder;
1160 if (fb != null && filter (fb, criteria) == true)
1166 if ((mt & MemberTypes.Method) != 0) {
1167 if (methods != null) {
1168 foreach (Method m in methods) {
1169 if ((m.ModFlags & modflags) == 0)
1171 if ((m.ModFlags & static_mask) != static_flags)
1174 MethodBuilder mb = m.MethodBuilder;
1176 if (mb != null && filter (mb, criteria) == true)
1181 if (operators != null){
1182 foreach (Operator o in operators) {
1183 if ((o.ModFlags & modflags) == 0)
1185 if ((o.ModFlags & static_mask) != static_flags)
1188 MethodBuilder ob = o.OperatorMethodBuilder;
1189 if (ob != null && filter (ob, criteria) == true)
1194 if (properties != null){
1195 foreach (Property p in properties){
1196 if ((p.ModFlags & modflags) == 0)
1198 if ((p.ModFlags & static_mask) != static_flags)
1204 if (b != null && filter (b, criteria) == true)
1208 if (b != null && filter (b, criteria) == true)
1213 if (indexers != null){
1214 foreach (Indexer ix in indexers){
1215 if ((ix.ModFlags & modflags) == 0)
1217 if ((ix.ModFlags & static_mask) != static_flags)
1223 if (b != null && filter (b, criteria) == true)
1227 if (b != null && filter (b, criteria) == true)
1233 if ((mt & MemberTypes.Event) != 0) {
1235 foreach (Event e in events) {
1236 if ((e.ModFlags & modflags) == 0)
1238 if ((e.ModFlags & static_mask) != static_flags)
1241 MemberInfo eb = e.EventBuilder;
1242 if (eb != null && filter (eb, criteria) == true)
1243 members.Add (e.EventBuilder);
1247 if ((mt & MemberTypes.Property) != 0){
1248 if (properties != null)
1249 foreach (Property p in properties) {
1250 if ((p.ModFlags & modflags) == 0)
1252 if ((p.ModFlags & static_mask) != static_flags)
1255 MemberInfo pb = p.PropertyBuilder;
1256 if (pb != null && filter (pb, criteria) == true) {
1257 members.Add (p.PropertyBuilder);
1261 if (indexers != null)
1262 foreach (Indexer ix in indexers) {
1263 if ((ix.ModFlags & modflags) == 0)
1265 if ((ix.ModFlags & static_mask) != static_flags)
1268 MemberInfo ib = ix.PropertyBuilder;
1269 if (ib != null && filter (ib, criteria) == true) {
1270 members.Add (ix.PropertyBuilder);
1275 if ((mt & MemberTypes.NestedType) != 0) {
1277 foreach (TypeContainer t in types) {
1278 if ((t.ModFlags & modflags) == 0)
1281 TypeBuilder tb = t.TypeBuilder;
1282 if (tb != null && (filter (tb, criteria) == true))
1288 foreach (Enum en in enums){
1289 if ((en.ModFlags & modflags) == 0)
1292 TypeBuilder tb = en.TypeBuilder;
1293 if (tb != null && (filter (tb, criteria) == true))
1298 if (delegates != null){
1299 foreach (Delegate d in delegates){
1300 if ((d.ModFlags & modflags) == 0)
1303 TypeBuilder tb = d.TypeBuilder;
1304 if (tb != null && (filter (tb, criteria) == true))
1309 if (interfaces != null){
1310 foreach (Interface iface in interfaces){
1311 if ((iface.ModFlags & modflags) == 0)
1314 TypeBuilder tb = iface.TypeBuilder;
1315 if (tb != null && (filter (tb, criteria) == true))
1321 if ((mt & MemberTypes.Constructor) != 0){
1322 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1323 foreach (Constructor c in instance_constructors){
1324 ConstructorBuilder cb = c.ConstructorBuilder;
1326 if (filter (cb, criteria) == true)
1331 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1332 ConstructorBuilder cb =
1333 default_static_constructor.ConstructorBuilder;
1336 if (filter (cb, criteria) == true)
1342 // Lookup members in parent if requested.
1344 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1345 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1346 members.AddRange (list);
1349 Timer.StopTimer (TimerType.TcFindMembers);
1351 return new MemberList (members);
1354 public override MemberCache MemberCache {
1356 return member_cache;
1360 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1361 MemberFilter filter, object criteria)
1363 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1366 return tc.FindMembers (mt, bf, filter, criteria);
1368 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1372 // FindMethods will look for methods not only in the type `t', but in
1373 // any interfaces implemented by the type.
1375 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1376 MemberFilter filter, object criteria)
1382 /// Emits the values for the constants
1384 public void EmitConstants ()
1386 if (constants != null)
1387 foreach (Const con in constants)
1388 con.EmitConstant (this);
1393 /// Emits the code, this step is performed after all
1394 /// the types, enumerations, constructors
1398 if (instance_constructors != null)
1399 foreach (Constructor c in instance_constructors)
1402 if (default_static_constructor != null)
1403 default_static_constructor.Emit (this);
1405 if (methods != null)
1406 foreach (Method m in methods)
1409 if (operators != null)
1410 foreach (Operator o in operators)
1413 if (properties != null)
1414 foreach (Property p in properties)
1417 if (indexers != null){
1418 foreach (Indexer ix in indexers)
1421 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1422 this, IndexerName, ModFlags, Location);
1423 TypeBuilder.SetCustomAttribute (cb);
1427 foreach (Field f in fields)
1430 if (events != null){
1431 foreach (Event e in Events)
1435 if (Pending != null)
1436 if (Pending.VerifyPendingMethods ())
1439 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1442 // Check for internal or private fields that were never assigned
1444 if (fields != null && RootContext.WarningLevel >= 3) {
1445 foreach (Field f in fields) {
1446 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1451 169, f.Location, "Private field " +
1452 MakeName (f.Name) + " is never used");
1457 // Only report 649 on level 4
1459 if (RootContext.WarningLevel < 4)
1462 if ((f.status & Field.Status.ASSIGNED) != 0)
1467 "Field " + MakeName (f.Name) + " is never assigned " +
1468 " to and will always have its default value");
1472 // if (types != null)
1473 // foreach (TypeContainer tc in types)
1477 public override void CloseType ()
1482 TypeBuilder.CreateType ();
1484 } catch (TypeLoadException){
1486 // This is fine, the code still created the type
1488 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1489 // Console.WriteLine (e.Message);
1491 Console.WriteLine ("In type: " + Name);
1496 foreach (Enum en in Enums)
1499 if (interface_order != null){
1500 foreach (Interface iface in interface_order)
1505 foreach (TypeContainer tc in Types)
1509 foreach (TypeContainer tc in Types)
1510 if (!(tc is Struct))
1514 if (Delegates != null)
1515 foreach (Delegate d in Delegates)
1519 public string MakeName (string n)
1521 return "`" + Name + "." + n + "'";
1524 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1527 108, l, "The keyword new is required on " +
1528 MakeName (mi.Name) + " because it hides `" +
1529 mi.ReflectedType.Name + "." + mi.Name + "'");
1532 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1535 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1536 "inherited member, the keyword new is not required");
1539 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1545 // Performs the validation on a Method's modifiers (properties have
1546 // the same properties).
1548 public bool MethodModifiersValid (int flags, string n, Location loc)
1550 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1551 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1552 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1554 string name = MakeName (n);
1557 // At most one of static, virtual or override
1559 if ((flags & Modifiers.STATIC) != 0){
1560 if ((flags & vao) != 0){
1562 112, loc, "static method " + name + "can not be marked " +
1563 "as virtual, abstract or override");
1568 if (this is Struct){
1569 if ((flags & va) != 0){
1570 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1575 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1578 " marked as override cannot be marked as new or virtual");
1583 // If the declaration includes the abstract modifier, then the
1584 // declaration does not include static, virtual or extern
1586 if ((flags & Modifiers.ABSTRACT) != 0){
1587 if ((flags & Modifiers.EXTERN) != 0){
1589 180, loc, name + " can not be both abstract and extern");
1593 if ((flags & Modifiers.VIRTUAL) != 0){
1595 503, loc, name + " can not be both abstract and virtual");
1599 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1602 " is abstract but its container class is not");
1608 if ((flags & Modifiers.PRIVATE) != 0){
1609 if ((flags & vao) != 0){
1612 " virtual or abstract members can not be private");
1617 if ((flags & Modifiers.SEALED) != 0){
1618 if ((flags & Modifiers.OVERRIDE) == 0){
1621 " cannot be sealed because it is not an override");
1629 // Access level of a type.
1632 ProtectedInternal = 1,
1638 // Check whether `flags' denotes a more restricted access than `level'
1639 // and return the new level.
1640 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1642 AccessLevel old_level = level;
1644 if ((flags & Modifiers.INTERNAL) != 0) {
1645 if ((flags & Modifiers.PROTECTED) != 0) {
1646 if ((int) level < (int) AccessLevel.ProtectedInternal)
1647 level = AccessLevel.ProtectedInternal;
1649 if ((int) level < (int) AccessLevel.Internal)
1650 level = AccessLevel.Internal;
1652 } else if ((flags & Modifiers.PROTECTED) != 0) {
1653 if ((int) level < (int) AccessLevel.Protected)
1654 level = AccessLevel.Protected;
1655 } else if ((flags & Modifiers.PRIVATE) != 0)
1656 level = AccessLevel.Private;
1661 // Return the access level for a new member which is defined in the current
1662 // TypeContainer with access modifiers `flags'.
1663 AccessLevel GetAccessLevel (int flags)
1665 if ((flags & Modifiers.PRIVATE) != 0)
1666 return AccessLevel.Private;
1669 if (!IsTopLevel && (Parent != null))
1670 level = Parent.GetAccessLevel (flags);
1672 level = AccessLevel.Public;
1674 return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1677 // Return the access level for type `t', but don't give more access than `flags'.
1678 static AccessLevel GetAccessLevel (Type t, int flags)
1680 if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1681 return AccessLevel.Private;
1684 if (TypeManager.IsBuiltinType (t))
1685 return AccessLevel.Public;
1686 else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1687 level = GetAccessLevel (t.DeclaringType, flags);
1689 level = CheckAccessLevel (AccessLevel.Public, flags);
1692 if (t.IsNestedPublic)
1695 if (t.IsNestedAssembly || t.IsNotPublic) {
1696 if ((int) level < (int) AccessLevel.Internal)
1697 level = AccessLevel.Internal;
1700 if (t.IsNestedFamily) {
1701 if ((int) level < (int) AccessLevel.Protected)
1702 level = AccessLevel.Protected;
1705 if (t.IsNestedFamORAssem) {
1706 if ((int) level < (int) AccessLevel.ProtectedInternal)
1707 level = AccessLevel.ProtectedInternal;
1714 // Returns true if `parent' is as accessible as the flags `flags'
1715 // given for this member.
1717 public bool AsAccessible (Type parent, int flags)
1719 while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1720 parent = parent.GetElementType ();
1722 AccessLevel level = GetAccessLevel (flags);
1723 AccessLevel level2 = GetAccessLevel (parent, flags);
1725 return (int) level >= (int) level2;
1728 Hashtable builder_and_args;
1730 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1732 if (builder_and_args == null)
1733 builder_and_args = new Hashtable ();
1738 /// Performs checks for an explicit interface implementation. First it
1739 /// checks whether the `interface_type' is a base inteface implementation.
1740 /// Then it checks whether `name' exists in the interface type.
1742 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1746 if (ifaces != null){
1747 foreach (Type t in ifaces){
1748 if (t == interface_type){
1756 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1763 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1765 Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1772 string IMemberContainer.Name {
1778 Type IMemberContainer.Type {
1784 IMemberContainer IMemberContainer.Parent {
1786 return parent_container;
1790 MemberCache IMemberContainer.MemberCache {
1792 return member_cache;
1796 bool IMemberContainer.IsInterface {
1802 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1804 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1808 // Operator pair checking
1811 class OperatorEntry {
1813 public Type ret_type;
1814 public Type type1, type2;
1816 public Operator.OpType ot;
1818 public OperatorEntry (int f, Operator o)
1822 ret_type = o.OperatorMethod.GetReturnType ();
1823 Type [] pt = o.OperatorMethod.ParameterTypes;
1827 ot = o.OperatorType;
1830 public override int GetHashCode ()
1832 return ret_type.GetHashCode ();
1835 public override bool Equals (object o)
1837 OperatorEntry other = (OperatorEntry) o;
1839 if (other.ret_type != ret_type)
1841 if (other.type1 != type1)
1843 if (other.type2 != type2)
1850 // Checks that some operators come in pairs:
1855 // They are matched based on the return type and the argument types
1857 void CheckPairedOperators ()
1859 Hashtable pairs = new Hashtable (null, null);
1861 // Register all the operators we care about.
1862 foreach (Operator op in operators){
1865 switch (op.OperatorType){
1866 case Operator.OpType.Equality:
1868 case Operator.OpType.Inequality:
1871 case Operator.OpType.GreaterThan:
1873 case Operator.OpType.LessThan:
1876 case Operator.OpType.GreaterThanOrEqual:
1878 case Operator.OpType.LessThanOrEqual:
1884 OperatorEntry oe = new OperatorEntry (reg, op);
1886 object o = pairs [oe];
1890 oe = (OperatorEntry) o;
1896 // Look for the mistakes.
1898 foreach (DictionaryEntry de in pairs){
1899 OperatorEntry oe = (OperatorEntry) de.Key;
1906 case Operator.OpType.Equality:
1909 case Operator.OpType.Inequality:
1912 case Operator.OpType.GreaterThan:
1915 case Operator.OpType.LessThan:
1918 case Operator.OpType.GreaterThanOrEqual:
1921 case Operator.OpType.LessThanOrEqual:
1925 Report.Error (216, oe.op.Location,
1926 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
1933 public class Class : TypeContainer {
1935 // Modifiers allowed in a class declaration
1937 public const int AllowedModifiers =
1940 Modifiers.PROTECTED |
1941 Modifiers.INTERNAL |
1943 Modifiers.ABSTRACT |
1947 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1948 : base (parent, name, l)
1952 if (parent.Parent == null)
1953 accmods = Modifiers.INTERNAL;
1955 accmods = Modifiers.PRIVATE;
1957 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1958 this.attributes = attrs;
1962 // FIXME: How do we deal with the user specifying a different
1965 public override TypeAttributes TypeAttr {
1967 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1972 public class Struct : TypeContainer {
1974 // Modifiers allowed in a struct declaration
1976 public const int AllowedModifiers =
1979 Modifiers.PROTECTED |
1980 Modifiers.INTERNAL |
1984 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1985 : base (parent, name, l)
1989 if (parent.Parent == null)
1990 accmods = Modifiers.INTERNAL;
1992 accmods = Modifiers.PRIVATE;
1994 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1996 this.ModFlags |= Modifiers.SEALED;
1997 this.attributes = attrs;
2002 // FIXME: Allow the user to specify a different set of attributes
2003 // in some cases (Sealed for example is mandatory for a class,
2004 // but what SequentialLayout can be changed
2006 public override TypeAttributes TypeAttr {
2008 return base.TypeAttr |
2009 TypeAttributes.SequentialLayout |
2010 TypeAttributes.Sealed |
2011 TypeAttributes.BeforeFieldInit;
2016 public abstract class MethodCore : MemberBase {
2017 public readonly Parameters Parameters;
2021 // Parameters, cached for semantic analysis.
2023 protected InternalParameters parameter_info;
2024 protected Type [] parameter_types;
2026 public MethodCore (Expression type, int mod, int allowed_mod, string name,
2027 Attributes attrs, Parameters parameters, Location loc)
2028 : base (type, mod, allowed_mod, name, attrs, loc)
2030 Parameters = parameters;
2034 // Returns the System.Type array for the parameters of this method
2036 public Type [] ParameterTypes {
2038 return parameter_types;
2042 public InternalParameters ParameterInfo
2045 return parameter_info;
2049 public Block Block {
2059 protected virtual bool DoDefineParameters (TypeContainer parent)
2061 // Check if arguments were correct
2062 parameter_types = Parameters.GetParameterInfo (parent);
2063 if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
2066 parameter_info = new InternalParameters (parent, Parameters);
2071 public CallingConventions GetCallingConvention (bool is_class)
2073 CallingConventions cc = 0;
2075 cc = Parameters.GetCallingConvention ();
2078 if ((ModFlags & Modifiers.STATIC) == 0)
2079 cc |= CallingConventions.HasThis;
2081 // FIXME: How is `ExplicitThis' used in C#?
2086 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
2089 // Define each type attribute (in/out/ref) and
2090 // the argument names.
2092 Parameter [] p = Parameters.FixedParameters;
2095 MethodBuilder mb = null;
2096 ConstructorBuilder cb = null;
2098 if (builder is MethodBuilder)
2099 mb = (MethodBuilder) builder;
2101 cb = (ConstructorBuilder) builder;
2104 for (i = 0; i < p.Length; i++) {
2105 ParameterBuilder pb;
2108 pb = cb.DefineParameter (
2109 i + 1, p [i].Attributes, p [i].Name);
2111 pb = mb.DefineParameter (
2112 i + 1, p [i].Attributes, p [i].Name);
2114 Attributes attr = p [i].OptAttributes;
2116 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
2120 if (Parameters.ArrayParameter != null){
2121 ParameterBuilder pb;
2122 Parameter array_param = Parameters.ArrayParameter;
2125 pb = cb.DefineParameter (
2126 i + 1, array_param.Attributes,
2129 pb = mb.DefineParameter (
2130 i + 1, array_param.Attributes,
2133 CustomAttributeBuilder a = new CustomAttributeBuilder (
2134 TypeManager.cons_param_array_attribute, new object [0]);
2136 pb.SetCustomAttribute (a);
2141 public class Method : MethodCore {
2142 public MethodBuilder MethodBuilder;
2143 public MethodData MethodData;
2146 /// Modifiers allowed in a class declaration
2148 const int AllowedModifiers =
2151 Modifiers.PROTECTED |
2152 Modifiers.INTERNAL |
2157 Modifiers.OVERRIDE |
2158 Modifiers.ABSTRACT |
2163 // return_type can be "null" for VOID values.
2165 public Method (Expression return_type, int mod, string name, Parameters parameters,
2166 Attributes attrs, Location l)
2167 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2171 // Returns the `System.Type' for the ReturnType of this
2172 // function. Provides a nice cache. (used between semantic analysis
2173 // and actual code generation
2175 public Type GetReturnType ()
2180 // Whether this is an operator method.
2181 public bool IsOperator;
2183 void DuplicateEntryPoint (MethodInfo b, Location location)
2187 "Program `" + CodeGen.FileName +
2188 "' has more than one entry point defined: `" +
2189 TypeManager.CSharpSignature(b) + "'");
2192 void Report28 (MethodInfo b)
2194 if (RootContext.WarningLevel < 4)
2199 "`" + TypeManager.CSharpSignature(b) +
2200 "' has the wrong signature to be an entry point");
2203 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2205 if (b.ReturnType != TypeManager.void_type &&
2206 b.ReturnType != TypeManager.int32_type)
2209 if (pinfo.Count == 0)
2212 if (pinfo.Count > 1)
2215 Type t = pinfo.ParameterType(0);
2217 (t.GetArrayRank() == 1) &&
2218 (t.GetElementType() == TypeManager.string_type) &&
2219 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2226 // Checks our base implementation if any
2228 protected override bool CheckBase (TypeContainer parent)
2230 // Check whether arguments were correct.
2231 if (!DoDefineParameters (parent))
2234 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2238 mi_this = TypeContainer.FindMembers (
2239 parent.TypeBuilder, MemberTypes.Method,
2240 BindingFlags.NonPublic | BindingFlags.Public |
2241 BindingFlags.Static | BindingFlags.Instance |
2242 BindingFlags.DeclaredOnly,
2243 MethodSignature.method_signature_filter, ms);
2245 if (mi_this.Count > 0) {
2246 Report.Error (111, Location, "Class `" + parent.Name + "' " +
2247 "already defines a member called `" + Name + "' " +
2248 "with the same parameter types");
2254 // Verify if the parent has a type with the same name, and then
2255 // check whether we have to create a new slot for it or not.
2257 Type ptype = parent.TypeBuilder.BaseType;
2259 // ptype is only null for System.Object while compiling corlib.
2261 MemberList mi, mi_static, mi_instance;
2263 mi_static = TypeContainer.FindMembers (
2264 ptype, MemberTypes.Method,
2265 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2266 MethodSignature.inheritable_method_signature_filter, ms);
2268 mi_instance = TypeContainer.FindMembers (
2269 ptype, MemberTypes.Method,
2270 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2271 MethodSignature.inheritable_method_signature_filter,
2274 if (mi_instance.Count > 0){
2276 } else if (mi_static.Count > 0)
2281 if (mi != null && mi.Count > 0){
2282 parent_method = (MethodInfo) mi [0];
2283 string name = parent_method.DeclaringType.Name + "." +
2286 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2289 if ((ModFlags & Modifiers.NEW) == 0) {
2290 Type parent_ret = TypeManager.TypeToCoreType (
2291 parent_method.ReturnType);
2293 if (parent_ret != MemberType) {
2295 508, parent.MakeName (Name) + ": cannot " +
2296 "change return type when overriding " +
2297 "inherited member " + name);
2302 if ((ModFlags & Modifiers.NEW) != 0)
2303 WarningNotHiding (parent);
2305 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2306 Report.Error (115, Location,
2307 parent.MakeName (Name) +
2308 " no suitable methods found to override");
2311 } else if ((ModFlags & Modifiers.NEW) != 0)
2312 WarningNotHiding (parent);
2320 public override bool Define (TypeContainer parent)
2322 if (!DoDefine (parent))
2325 if (!CheckBase (parent))
2328 CallingConventions cc = GetCallingConvention (parent is Class);
2330 MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2331 ParameterInfo, cc, OptAttributes,
2332 ModFlags, flags, true);
2334 if (!MethodData.Define (parent))
2337 MethodBuilder = MethodData.MethodBuilder;
2340 // This is used to track the Entry Point,
2342 if (Name == "Main" &&
2343 ((ModFlags & Modifiers.STATIC) != 0) &&
2344 (RootContext.MainClass == null ||
2345 RootContext.MainClass == parent.TypeBuilder.FullName)){
2346 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2347 if (RootContext.EntryPoint == null) {
2348 RootContext.EntryPoint = MethodBuilder;
2349 RootContext.EntryPointLocation = Location;
2351 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2352 DuplicateEntryPoint (MethodBuilder, Location);
2355 Report28(MethodBuilder);
2364 public void Emit (TypeContainer parent)
2366 MethodData.Emit (parent, Block, this);
2370 public abstract class ConstructorInitializer {
2371 ArrayList argument_list;
2372 ConstructorInfo parent_constructor;
2373 Parameters parameters;
2376 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2379 this.argument_list = argument_list;
2380 this.parameters = parameters;
2384 public ArrayList Arguments {
2386 return argument_list;
2390 public bool Resolve (EmitContext ec)
2392 Expression parent_constructor_group;
2395 ec.CurrentBlock = new Block (null, true, parameters);
2397 if (argument_list != null){
2398 foreach (Argument a in argument_list){
2399 if (!a.Resolve (ec, loc))
2404 ec.CurrentBlock = null;
2406 if (this is ConstructorBaseInitializer) {
2407 if (ec.ContainerType.BaseType == null)
2410 t = ec.ContainerType.BaseType;
2411 if (ec.ContainerType.IsValueType) {
2412 Report.Error (522, loc,
2413 "structs cannot call base class constructors");
2417 t = ec.ContainerType;
2419 parent_constructor_group = Expression.MemberLookup (
2421 MemberTypes.Constructor,
2422 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2425 if (parent_constructor_group == null){
2426 Report.Error (1501, loc,
2427 "Can not find a constructor for this argument list");
2431 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2432 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2434 if (parent_constructor == null){
2435 Report.Error (1501, loc,
2436 "Can not find a constructor for this argument list");
2443 public void Emit (EmitContext ec)
2445 if (parent_constructor != null){
2447 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2449 Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2454 public class ConstructorBaseInitializer : ConstructorInitializer {
2455 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2456 base (argument_list, pars, l)
2461 public class ConstructorThisInitializer : ConstructorInitializer {
2462 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2463 base (argument_list, pars, l)
2468 public class Constructor : MethodCore {
2469 public ConstructorBuilder ConstructorBuilder;
2470 public ConstructorInitializer Initializer;
2471 new public Attributes OptAttributes;
2474 // Modifiers allowed for a constructor.
2476 public const int AllowedModifiers =
2478 Modifiers.PROTECTED |
2479 Modifiers.INTERNAL |
2486 // The spec claims that static is not permitted, but
2487 // my very own code has static constructors.
2489 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2490 : base (null, 0, AllowedModifiers, name, null, args, l)
2496 // Returns true if this is a default constructor
2498 public bool IsDefault ()
2500 if ((ModFlags & Modifiers.STATIC) != 0)
2501 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2502 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2505 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2506 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2507 (Initializer is ConstructorBaseInitializer) &&
2508 (Initializer.Arguments == null);
2512 // Creates the ConstructorBuilder
2514 public override bool Define (TypeContainer parent)
2516 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2517 MethodAttributes.SpecialName);
2519 // Check if arguments were correct.
2520 if (!DoDefineParameters (parent))
2523 if ((ModFlags & Modifiers.STATIC) != 0)
2524 ca |= MethodAttributes.Static;
2526 if (parent is Struct && ParameterTypes.Length == 0){
2529 "Structs can not contain explicit parameterless " +
2533 ca |= MethodAttributes.HideBySig;
2535 if ((ModFlags & Modifiers.PUBLIC) != 0)
2536 ca |= MethodAttributes.Public;
2537 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2538 if ((ModFlags & Modifiers.INTERNAL) != 0)
2539 ca |= MethodAttributes.FamORAssem;
2541 ca |= MethodAttributes.Family;
2542 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2543 ca |= MethodAttributes.Assembly;
2544 else if (IsDefault ())
2545 ca |= MethodAttributes.Public;
2547 ca |= MethodAttributes.Private;
2550 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2551 ca, GetCallingConvention (parent is Class), ParameterTypes);
2554 // HACK because System.Reflection.Emit is lame
2556 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2559 "Class `" +parent.Name+ "' already contains a definition with the " +
2560 "same return value and parameter types for constructor `" + Name
2571 public void Emit (TypeContainer parent)
2573 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2574 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2576 if ((ModFlags & Modifiers.STATIC) == 0){
2577 if (parent is Class && Initializer == null)
2578 Initializer = new ConstructorBaseInitializer (
2579 null, Parameters.EmptyReadOnlyParameters, parent.Location);
2583 // Spec mandates that Initializers will not have
2587 if (Initializer != null && !Initializer.Resolve (ec))
2589 ec.IsStatic = false;
2592 LabelParameters (ec, ParameterTypes, ConstructorBuilder);
2595 // Classes can have base initializers and instance field initializers.
2597 if (parent is Class){
2598 if ((ModFlags & Modifiers.STATIC) == 0)
2599 parent.EmitFieldInitializers (ec);
2601 if (Initializer != null)
2602 Initializer.Emit (ec);
2604 if ((ModFlags & Modifiers.STATIC) != 0)
2605 parent.EmitFieldInitializers (ec);
2607 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2609 // If this is a non-static `struct' constructor and doesn't have any
2610 // initializer, it must initialize all of the struct's fields.
2611 if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2612 (Initializer == null))
2613 Block.AddThisVariable (parent, Location);
2615 ec.EmitTopBlock (Block, ParameterInfo, Location);
2619 public class MethodData {
2621 // The return type of this method
2623 public readonly Type ReturnType;
2624 public readonly Type[] ParameterTypes;
2625 public readonly InternalParameters ParameterInfo;
2626 public readonly CallingConventions CallingConventions;
2627 public readonly Attributes OptAttributes;
2628 public readonly Location Location;
2631 // Are we implementing an interface ?
2633 public bool IsImplementing = false;
2638 protected MemberBase member;
2639 protected int modifiers;
2640 protected MethodAttributes flags;
2641 protected bool is_method;
2642 protected string accessor_name;
2643 ArrayList conditionals;
2645 MethodBuilder builder = null;
2646 public MethodBuilder MethodBuilder {
2652 public MethodData (MemberBase member, string name, Type return_type,
2653 Type [] parameter_types, InternalParameters parameters,
2654 CallingConventions cc, Attributes opt_attrs,
2655 int modifiers, MethodAttributes flags, bool is_method)
2657 this.member = member;
2658 this.accessor_name = name;
2659 this.ReturnType = return_type;
2660 this.ParameterTypes = parameter_types;
2661 this.ParameterInfo = parameters;
2662 this.CallingConventions = cc;
2663 this.OptAttributes = opt_attrs;
2664 this.modifiers = modifiers;
2666 this.is_method = is_method;
2667 this.Location = member.Location;
2668 this.conditionals = new ArrayList ();
2674 Attribute dllimport_attribute = null;
2675 string obsolete = null;
2676 bool obsolete_error = false;
2678 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2680 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2683 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2684 if (asec.Attributes == null)
2687 foreach (Attribute a in asec.Attributes) {
2688 if (a.Name == "Conditional") {
2689 if (!ApplyConditionalAttribute (a))
2691 } else if (a.Name == "Obsolete") {
2692 if (!ApplyObsoleteAttribute (a))
2694 } else if (a.Name.IndexOf ("DllImport") != -1) {
2696 a.Type = TypeManager.dllimport_type;
2697 Attribute.Error_AttributeNotValidForElement (a, Location);
2700 if (!ApplyDllImportAttribute (a))
2710 // Applies the `DllImport' attribute to the method.
2712 protected virtual bool ApplyDllImportAttribute (Attribute a)
2714 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2715 if ((modifiers & extern_static) != extern_static) {
2716 Report.Error (601, Location,
2717 "The DllImport attribute must be specified on a method " +
2718 "marked `static' and `extern'.");
2722 flags |= MethodAttributes.PinvokeImpl;
2723 dllimport_attribute = a;
2728 // Applies the `Obsolete' attribute to the method.
2730 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2732 if (obsolete != null) {
2733 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2737 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2738 return obsolete != null;
2742 // Applies the `Conditional' attribute to the method.
2744 protected virtual bool ApplyConditionalAttribute (Attribute a)
2746 // The Conditional attribute is only valid on methods.
2748 Attribute.Error_AttributeNotValidForElement (a, Location);
2752 string condition = a.Conditional_GetConditionName ();
2754 if (condition == null)
2757 if (ReturnType != TypeManager.void_type) {
2758 Report.Error (578, Location,
2759 "Conditional not valid on `" + member.Name + "' " +
2760 "because its return type is not void");
2764 if ((modifiers & Modifiers.OVERRIDE) != 0) {
2765 Report.Error (243, Location,
2766 "Conditional not valid on `" + member.Name + "' " +
2767 "because it is an override method");
2771 if (member.IsExplicitImpl) {
2772 Report.Error (577, Location,
2773 "Conditional not valid on `" + member.Name + "' " +
2774 "because it is an explicit interface implementation");
2778 if (IsImplementing) {
2779 Report.Error (623, Location,
2780 "Conditional not valid on `" + member.Name + "' " +
2781 "because it is an interface method");
2785 conditionals.Add (condition);
2791 // Checks whether this method should be ignored due to its Conditional attributes.
2793 bool ShouldIgnore (Location loc)
2795 // When we're overriding a virtual method, we implicitly inherit the
2796 // Conditional attributes from our parent.
2797 if (member.ParentMethod != null) {
2798 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2799 member.ParentMethod, loc);
2801 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2805 foreach (string condition in conditionals)
2806 if (RootContext.AllDefines [condition] == null)
2813 // Returns the TypeManager.MethodFlags for this method.
2814 // This emits an error 619 / warning 618 if the method is obsolete.
2815 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2817 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2819 TypeManager.MethodFlags flags = 0;
2821 if (obsolete != null) {
2822 if (obsolete_error) {
2823 Report.Error (619, loc, "Method `" + member.Name +
2824 "' is obsolete: `" + obsolete + "'");
2825 return TypeManager.MethodFlags.IsObsoleteError;
2827 Report.Warning (618, loc, "Method `" + member.Name +
2828 "' is obsolete: `" + obsolete + "'");
2830 flags |= TypeManager.MethodFlags.IsObsolete;
2833 if (ShouldIgnore (loc))
2834 flags |= TypeManager.MethodFlags.ShouldIgnore;
2839 public virtual bool Define (TypeContainer parent)
2841 MethodInfo implementing = null;
2842 string method_name, name, prefix;
2844 if (OptAttributes != null)
2845 if (!ApplyAttributes (OptAttributes, is_method))
2848 if (member.IsExplicitImpl)
2849 prefix = member.InterfaceType.FullName + ".";
2853 if (accessor_name != null)
2854 name = accessor_name + "_" + member.ShortName;
2856 name = member.ShortName;
2857 method_name = prefix + name;
2859 if (parent.Pending != null){
2860 if (member is Indexer)
2861 implementing = parent.Pending.IsInterfaceIndexer (
2862 member.InterfaceType, ReturnType, ParameterTypes);
2864 implementing = parent.Pending.IsInterfaceMethod (
2865 member.InterfaceType, name, ReturnType, ParameterTypes);
2867 if (member.InterfaceType != null && implementing == null){
2868 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
2875 // For implicit implementations, make sure we are public, for
2876 // explicit implementations, make sure we are private.
2878 if (implementing != null){
2880 // Setting null inside this block will trigger a more
2881 // verbose error reporting for missing interface implementations
2883 // The "candidate" function has been flagged already
2884 // but it wont get cleared
2886 if (!member.IsExplicitImpl){
2888 // We already catch different accessibility settings
2889 // so we just need to check that we are not private
2891 if ((modifiers & Modifiers.PRIVATE) != 0)
2892 implementing = null;
2895 // Static is not allowed
2897 if ((modifiers & Modifiers.STATIC) != 0)
2898 implementing = null;
2900 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
2901 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
2902 implementing = null;
2908 // If implementing is still valid, set flags
2910 if (implementing != null){
2912 // When implementing interface methods, set NewSlot.
2914 if (implementing.DeclaringType.IsInterface)
2915 flags |= MethodAttributes.NewSlot;
2918 MethodAttributes.Virtual |
2919 MethodAttributes.HideBySig;
2921 // Get the method name from the explicit interface.
2922 if (member.InterfaceType != null) {
2923 name = implementing.Name;
2924 method_name = prefix + name;
2927 IsImplementing = true;
2931 // Create the MethodBuilder for the method
2933 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2934 if ((modifiers & Modifiers.STATIC) == 0) {
2935 Report.Error (601, Location,
2936 "The DllImport attribute must be specified on " +
2937 "a method marked 'static' and 'extern'.");
2941 EmitContext ec = new EmitContext (
2942 parent, Location, null, ReturnType, modifiers);
2944 builder = dllimport_attribute.DefinePInvokeMethod (
2945 ec, parent.TypeBuilder, method_name, flags,
2946 ReturnType, ParameterTypes);
2948 builder = parent.TypeBuilder.DefineMethod (
2949 method_name, flags, CallingConventions,
2950 ReturnType, ParameterTypes);
2952 if (builder == null)
2955 if (IsImplementing) {
2957 // clear the pending implemntation flag
2959 if (member is Indexer) {
2960 parent.Pending.ImplementIndexer (
2961 member.InterfaceType, builder, ReturnType,
2962 ParameterTypes, true);
2964 parent.Pending.ImplementMethod (
2965 member.InterfaceType, name, ReturnType,
2966 ParameterTypes, member.IsExplicitImpl);
2968 if (member.IsExplicitImpl)
2969 parent.TypeBuilder.DefineMethodOverride (
2970 builder, implementing);
2973 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
2974 Report.Error (111, Location,
2975 "Class `" + parent.Name +
2976 "' already contains a definition with the " +
2977 "same return value and parameter types as the " +
2978 "'get' method of property `" + member.Name + "'");
2982 TypeManager.AddMethod (builder, this);
2990 public virtual void Emit (TypeContainer parent, Block block, object kind)
2995 if ((flags & MethodAttributes.PinvokeImpl) == 0)
2996 ig = builder.GetILGenerator ();
3000 ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3002 if (OptAttributes != null)
3003 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
3005 if (member is MethodCore)
3006 ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder);
3009 // abstract or extern methods have no bodies
3011 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3016 // abstract or extern methods have no bodies.
3018 if ((modifiers & Modifiers.ABSTRACT) != 0)
3020 500, Location, "Abstract method `" +
3021 TypeManager.CSharpSignature (builder) +
3022 "' can not have a body");
3024 if ((modifiers & Modifiers.EXTERN) != 0)
3026 179, Location, "External method `" +
3027 TypeManager.CSharpSignature (builder) +
3028 "' can not have a body");
3034 // Methods must have a body unless they're extern or abstract
3036 if (block == null) {
3038 501, Location, "Method `" +
3039 TypeManager.CSharpSignature (builder) +
3040 "' must declare a body since it is not marked " +
3041 "abstract or extern");
3046 // Handle destructors specially
3048 // FIXME: This code generates buggy code
3050 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3051 EmitDestructor (ec, block);
3053 ISymbolWriter sw = CodeGen.SymbolWriter;
3055 if ((sw != null) && !Location.IsNull (Location) &&
3056 !Location.IsNull (block.EndLocation)) {
3057 Location end = block.EndLocation;
3058 MethodToken token = MethodBuilder.GetToken ();
3059 sw.OpenMethod (new SymbolToken (token.Token));
3060 sw.SetMethodSourceRange (Location.SymbolDocument,
3065 ec.EmitTopBlock (block, ParameterInfo, Location);
3069 ec.EmitTopBlock (block, ParameterInfo, Location);
3073 void EmitDestructor (EmitContext ec, Block block)
3075 ILGenerator ig = ec.ig;
3077 Label finish = ig.DefineLabel ();
3078 bool old_in_try = ec.InTry;
3080 ig.BeginExceptionBlock ();
3082 ec.ReturnLabel = finish;
3083 ec.HasReturnLabel = true;
3084 ec.EmitTopBlock (block, null, Location);
3085 ec.InTry = old_in_try;
3087 // ig.MarkLabel (finish);
3088 bool old_in_finally = ec.InFinally;
3089 ec.InFinally = true;
3090 ig.BeginFinallyBlock ();
3092 if (ec.ContainerType.BaseType != null) {
3093 Expression member_lookup = Expression.MemberLookup (
3094 ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
3095 MemberTypes.Method, Expression.AllBindingFlags, Location);
3097 if (member_lookup != null){
3098 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3100 ig.Emit (OpCodes.Ldarg_0);
3101 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3104 ec.InFinally = old_in_finally;
3106 ig.EndExceptionBlock ();
3107 //ig.MarkLabel (ec.ReturnLabel);
3108 ig.Emit (OpCodes.Ret);
3112 abstract public class MemberBase : MemberCore {
3113 public Expression Type;
3114 public readonly Attributes OptAttributes;
3116 protected MethodAttributes flags;
3119 // The "short" name of this property / indexer / event. This is the
3120 // name without the explicit interface.
3122 public string ShortName;
3125 // The type of this property / indexer / event
3127 public Type MemberType;
3130 // If true, this is an explicit interface implementation
3132 public bool IsExplicitImpl = false;
3135 // The name of the interface we are explicitly implementing
3137 public string ExplicitInterfaceName = null;
3140 // If true, the interface type we are explicitly implementing
3142 public Type InterfaceType = null;
3145 // The method we're overriding if this is an override method.
3147 protected MethodInfo parent_method = null;
3148 public MethodInfo ParentMethod {
3150 return parent_method;
3155 // The constructor is only exposed to our children
3157 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3158 Attributes attrs, Location loc)
3162 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
3163 OptAttributes = attrs;
3166 protected virtual bool CheckBase (TypeContainer parent)
3171 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3175 foreach (Type partype in parameters){
3176 if (partype.IsPointer && !UnsafeOK (parent))
3179 if (parent.AsAccessible (partype, ModFlags))
3182 if (this is Indexer)
3183 Report.Error (55, Location,
3184 "Inconsistent accessibility: parameter type `" +
3185 TypeManager.CSharpName (partype) + "' is less " +
3186 "accessible than indexer `" + Name + "'");
3188 Report.Error (51, Location,
3189 "Inconsistent accessibility: parameter type `" +
3190 TypeManager.CSharpName (partype) + "' is less " +
3191 "accessible than method `" + Name + "'");
3198 protected virtual bool DoDefine (TypeContainer parent)
3203 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3206 flags = Modifiers.MethodAttr (ModFlags);
3208 // Lookup Type, verify validity
3209 MemberType = parent.ResolveType (Type, false, Location);
3210 if (MemberType == null)
3213 // verify accessibility
3214 if (!parent.AsAccessible (MemberType, ModFlags)) {
3215 if (this is Property)
3216 Report.Error (53, Location,
3217 "Inconsistent accessibility: property type `" +
3218 TypeManager.CSharpName (MemberType) + "' is less " +
3219 "accessible than property `" + Name + "'");
3220 else if (this is Indexer)
3221 Report.Error (54, Location,
3222 "Inconsistent accessibility: indexer return type `" +
3223 TypeManager.CSharpName (MemberType) + "' is less " +
3224 "accessible than indexer `" + Name + "'");
3225 else if (this is Method)
3226 Report.Error (50, Location,
3227 "Inconsistent accessibility: return type `" +
3228 TypeManager.CSharpName (MemberType) + "' is less " +
3229 "accessible than method `" + Name + "'");
3231 Report.Error (52, Location,
3232 "Inconsistent accessibility: field type `" +
3233 TypeManager.CSharpName (MemberType) + "' is less " +
3234 "accessible than field `" + Name + "'");
3238 if (MemberType.IsPointer && !UnsafeOK (parent))
3242 // Check for explicit interface implementation
3244 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
3245 int pos = Name.LastIndexOf (".");
3247 ExplicitInterfaceName = Name.Substring (0, pos);
3248 ShortName = Name.Substring (pos + 1);
3252 if (ExplicitInterfaceName != null) {
3253 InterfaceType = RootContext.LookupType (
3254 parent, ExplicitInterfaceName, false, Location);
3255 if (InterfaceType == null)
3258 // Compute the full name that we need to export.
3259 Name = InterfaceType.FullName + "." + ShortName;
3261 if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
3264 IsExplicitImpl = true;
3266 IsExplicitImpl = false;
3273 // Fields and Events both generate FieldBuilders, we use this to share
3274 // their common bits. This is also used to flag usage of the field
3276 abstract public class FieldBase : MemberBase {
3277 public FieldBuilder FieldBuilder;
3278 public Status status;
3281 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3284 // The constructor is only exposed to our children
3286 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3287 object init, Attributes attrs, Location loc)
3288 : base (type, mod, allowed_mod, name, attrs, loc)
3294 // Whether this field has an initializer.
3296 public bool HasInitializer {
3298 return init != null;
3303 readonly Object init;
3304 Expression init_expr;
3305 bool init_expr_initialized = false;
3308 // Resolves and returns the field initializer.
3310 public Expression GetInitializerExpression (EmitContext ec)
3312 if (init_expr_initialized)
3316 if (init is Expression)
3317 e = (Expression) init;
3319 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3321 ec.IsFieldInitializer = true;
3322 e = e.DoResolve (ec);
3323 ec.IsFieldInitializer = false;
3326 init_expr_initialized = true;
3333 // The Field class is used to represents class/struct fields during parsing.
3335 public class Field : FieldBase {
3337 // Modifiers allowed in a class declaration
3339 const int AllowedModifiers =
3342 Modifiers.PROTECTED |
3343 Modifiers.INTERNAL |
3346 Modifiers.VOLATILE |
3350 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3351 Attributes attrs, Location loc)
3352 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3356 public override bool Define (TypeContainer parent)
3358 Type t = parent.ResolveType (Type, false, Location);
3363 if (!parent.AsAccessible (t, ModFlags)) {
3364 Report.Error (52, Location,
3365 "Inconsistent accessibility: field type `" +
3366 TypeManager.CSharpName (t) + "' is less " +
3367 "accessible than field `" + Name + "'");
3371 if (t.IsPointer && !UnsafeOK (parent))
3374 if (RootContext.WarningLevel > 1){
3375 Type ptype = parent.TypeBuilder.BaseType;
3377 // ptype is only null for System.Object while compiling corlib.
3379 TypeContainer.FindMembers (
3380 ptype, MemberTypes.Method,
3381 BindingFlags.Public |
3382 BindingFlags.Static | BindingFlags.Instance,
3383 System.Type.FilterName, Name);
3387 if ((ModFlags & Modifiers.VOLATILE) != 0){
3389 if (TypeManager.IsEnumType (t))
3390 t = TypeManager.EnumToUnderlying (t);
3392 if (!((t == TypeManager.bool_type) ||
3393 (t == TypeManager.sbyte_type) ||
3394 (t == TypeManager.byte_type) ||
3395 (t == TypeManager.short_type) ||
3396 (t == TypeManager.ushort_type) ||
3397 (t == TypeManager.int32_type) ||
3398 (t == TypeManager.uint32_type) ||
3399 (t == TypeManager.char_type) ||
3400 (t == TypeManager.float_type))){
3402 677, Location, parent.MakeName (Name) +
3403 " A volatile field can not be of type `" +
3404 TypeManager.CSharpName (t) + "'");
3410 FieldBuilder = parent.TypeBuilder.DefineField (
3411 Name, t, Modifiers.FieldAttr (ModFlags));
3413 TypeManager.RegisterFieldBase (FieldBuilder, this);
3417 public void Emit (TypeContainer tc)
3419 EmitContext ec = new EmitContext (tc, Location, null,
3420 FieldBuilder.FieldType, ModFlags);
3422 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
3427 // `set' and `get' accessors are represented with an Accessor.
3429 public class Accessor {
3431 // Null if the accessor is empty, or a Block if not
3434 public Attributes OptAttributes;
3436 public Accessor (Block b, Attributes attrs)
3439 OptAttributes = attrs;
3444 // Properties and Indexers both generate PropertyBuilders, we use this to share
3445 // their common bits.
3447 abstract public class PropertyBase : MethodCore {
3448 public Accessor Get, Set;
3449 public PropertyBuilder PropertyBuilder;
3450 public MethodBuilder GetBuilder, SetBuilder;
3451 public MethodData GetData, SetData;
3453 protected EmitContext ec;
3455 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3456 Parameters parameters, Accessor get_block, Accessor set_block,
3457 Attributes attrs, Location loc)
3458 : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3464 protected override bool DoDefine (TypeContainer parent)
3466 if (!base.DoDefine (parent))
3469 ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3475 // Checks our base implementation if any
3477 protected override bool CheckBase (TypeContainer parent)
3479 // Check whether arguments were correct.
3480 if (!DoDefineParameters (parent))
3487 MethodSignature ms, base_ms;
3488 if (this is Indexer) {
3489 string name, base_name;
3491 report_name = "this";
3492 name = TypeManager.IndexerPropertyName (parent.TypeBuilder);
3493 ms = new MethodSignature (name, null, ParameterTypes);
3494 base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType);
3495 base_ms = new MethodSignature (base_name, null, ParameterTypes);
3498 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
3501 MemberList props_this;
3503 props_this = TypeContainer.FindMembers (
3504 parent.TypeBuilder, MemberTypes.Property,
3505 BindingFlags.NonPublic | BindingFlags.Public |
3506 BindingFlags.Static | BindingFlags.Instance |
3507 BindingFlags.DeclaredOnly,
3508 MethodSignature.method_signature_filter, ms);
3510 if (props_this.Count > 0) {
3511 Report.Error (111, Location, "Class `" + parent.Name + "' " +
3512 "already defines a member called `" + report_name + "' " +
3513 "with the same parameter types");
3518 // Find properties with the same name on the base class
3521 MemberList props_static = TypeContainer.FindMembers (
3522 parent.TypeBuilder.BaseType, MemberTypes.Property,
3523 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3524 MethodSignature.inheritable_property_signature_filter, base_ms);
3526 MemberList props_instance = TypeContainer.FindMembers (
3527 parent.TypeBuilder.BaseType, MemberTypes.Property,
3528 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3529 MethodSignature.inheritable_property_signature_filter,
3533 // Find if we have anything
3535 if (props_static.Count > 0)
3536 props = props_static;
3537 else if (props_instance.Count > 0)
3538 props = props_instance;
3543 // If we have something on the base.
3544 if (props != null && props.Count > 0){
3545 PropertyInfo pi = (PropertyInfo) props [0];
3547 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
3548 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
3550 MethodInfo reference = inherited_get == null ?
3551 inherited_set : inherited_get;
3553 if (reference != null) {
3554 string name = reference.DeclaringType.Name + "." + report_name;
3556 if (!CheckMethodAgainstBase (parent, flags, reference, name))
3560 if (((ModFlags & Modifiers.NEW) == 0) && (pi.PropertyType != MemberType)) {
3561 Report.Error (508, parent.MakeName (Name) + ": cannot " +
3562 "change return type when overriding inherited " +
3563 "member `" + pi.DeclaringType + "." + pi.Name + "'");
3567 if ((ModFlags & Modifiers.NEW) != 0)
3568 WarningNotHiding (parent);
3570 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3571 if (this is Indexer)
3572 Report.Error (115, Location,
3573 parent.MakeName (Name) +
3574 " no suitable indexers found to override");
3576 Report.Error (115, Location,
3577 parent.MakeName (Name) +
3578 " no suitable properties found to override");
3585 public void Emit (TypeContainer tc)
3588 // The PropertyBuilder can be null for explicit implementations, in that
3589 // case, we do not actually emit the ".property", so there is nowhere to
3590 // put the attribute
3592 if (PropertyBuilder != null)
3593 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3595 if (GetData != null)
3596 GetData.Emit (tc, Get.Block, Get);
3598 if (SetData != null)
3599 SetData.Emit (tc, Set.Block, Set);
3603 public class Property : PropertyBase {
3604 const int AllowedModifiers =
3607 Modifiers.PROTECTED |
3608 Modifiers.INTERNAL |
3612 Modifiers.OVERRIDE |
3613 Modifiers.ABSTRACT |
3618 public Property (Expression type, string name, int mod_flags,
3619 Accessor get_block, Accessor set_block,
3620 Attributes attrs, Location loc)
3621 : base (type, name, mod_flags, AllowedModifiers,
3622 Parameters.EmptyReadOnlyParameters,
3623 get_block, set_block, attrs, loc)
3627 public override bool Define (TypeContainer parent)
3629 if (!DoDefine (parent))
3632 if (!CheckBase (parent))
3635 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3638 Type [] parameters = TypeManager.NoTypes;
3640 InternalParameters ip = new InternalParameters (
3641 parent, Parameters.EmptyReadOnlyParameters);
3643 GetData = new MethodData (this, "get", MemberType,
3644 parameters, ip, CallingConventions.Standard,
3645 Get.OptAttributes, ModFlags, flags, false);
3647 if (!GetData.Define (parent))
3650 GetBuilder = GetData.MethodBuilder;
3654 Type [] parameters = new Type [1];
3655 parameters [0] = MemberType;
3657 Parameter [] parms = new Parameter [1];
3658 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3659 InternalParameters ip = new InternalParameters (
3660 parent, new Parameters (parms, null, Location));
3662 SetData = new MethodData (this, "set", TypeManager.void_type,
3663 parameters, ip, CallingConventions.Standard,
3664 Set.OptAttributes, ModFlags, flags, false);
3666 if (!SetData.Define (parent))
3669 SetBuilder = SetData.MethodBuilder;
3670 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3673 // FIXME - PropertyAttributes.HasDefault ?
3675 PropertyAttributes prop_attr =
3676 PropertyAttributes.RTSpecialName |
3677 PropertyAttributes.SpecialName;
3679 if (!IsExplicitImpl){
3680 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3681 Name, prop_attr, MemberType, null);
3684 PropertyBuilder.SetGetMethod (GetBuilder);
3687 PropertyBuilder.SetSetMethod (SetBuilder);
3690 // HACK for the reasons exposed above
3692 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3695 "Class `" + parent.Name +
3696 "' already contains a definition for the property `" +
3706 /// Gigantic workaround for lameness in SRE follows :
3707 /// This class derives from EventInfo and attempts to basically
3708 /// wrap around the EventBuilder so that FindMembers can quickly
3709 /// return this in it search for members
3711 public class MyEventBuilder : EventInfo {
3714 // We use this to "point" to our Builder which is
3715 // not really a MemberInfo
3717 EventBuilder MyBuilder;
3720 // We "catch" and wrap these methods
3722 MethodInfo raise, remove, add;
3724 EventAttributes attributes;
3725 Type declaring_type, reflected_type, event_type;
3728 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3730 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3732 // And now store the values in our own fields.
3734 declaring_type = type_builder;
3736 reflected_type = type_builder;
3738 attributes = event_attr;
3740 this.event_type = event_type;
3744 // Methods that you have to override. Note that you only need
3745 // to "implement" the variants that take the argument (those are
3746 // the "abstract" methods, the others (GetAddMethod()) are
3749 public override MethodInfo GetAddMethod (bool nonPublic)
3754 public override MethodInfo GetRemoveMethod (bool nonPublic)
3759 public override MethodInfo GetRaiseMethod (bool nonPublic)
3765 // These methods make "MyEventInfo" look like a Builder
3767 public void SetRaiseMethod (MethodBuilder raiseMethod)
3769 raise = raiseMethod;
3770 MyBuilder.SetRaiseMethod (raiseMethod);
3773 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3775 remove = removeMethod;
3776 MyBuilder.SetRemoveOnMethod (removeMethod);
3779 public void SetAddOnMethod (MethodBuilder addMethod)
3782 MyBuilder.SetAddOnMethod (addMethod);
3785 public void SetCustomAttribute (CustomAttributeBuilder cb)
3787 MyBuilder.SetCustomAttribute (cb);
3790 public override object [] GetCustomAttributes (bool inherit)
3792 // FIXME : There's nothing which can be seemingly done here because
3793 // we have no way of getting at the custom attribute objects of the
3798 public override object [] GetCustomAttributes (Type t, bool inherit)
3800 // FIXME : Same here !
3804 public override bool IsDefined (Type t, bool b)
3809 public override EventAttributes Attributes {
3815 public override string Name {
3821 public override Type DeclaringType {
3823 return declaring_type;
3827 public override Type ReflectedType {
3829 return reflected_type;
3833 public Type EventType {
3840 public class Event : FieldBase {
3841 const int AllowedModifiers =
3844 Modifiers.PROTECTED |
3845 Modifiers.INTERNAL |
3850 Modifiers.OVERRIDE |
3854 public readonly Accessor Add;
3855 public readonly Accessor Remove;
3856 public MyEventBuilder EventBuilder;
3858 MethodBuilder AddBuilder, RemoveBuilder;
3859 MethodData AddData, RemoveData;
3861 public Event (Expression type, string name, Object init, int mod, Accessor add,
3862 Accessor remove, Attributes attrs, Location loc)
3863 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
3869 public override bool Define (TypeContainer parent)
3871 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3873 if (!DoDefine (parent))
3876 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
3877 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3878 "' : event must be of a delegate type");
3882 Type [] parameter_types = new Type [1];
3883 parameter_types [0] = MemberType;
3885 Parameter [] parms = new Parameter [1];
3886 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3887 InternalParameters ip = new InternalParameters (
3888 parent, new Parameters (parms, null, Location));
3890 if (!CheckBase (parent))
3894 // Now define the accessors
3896 AddData = new MethodData (this, "add", TypeManager.void_type,
3897 parameter_types, ip, CallingConventions.Standard,
3898 (Add != null) ? Add.OptAttributes : null,
3899 ModFlags, flags, false);
3901 if (!AddData.Define (parent))
3904 AddBuilder = AddData.MethodBuilder;
3905 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3907 RemoveData = new MethodData (this, "remove", TypeManager.void_type,
3908 parameter_types, ip, CallingConventions.Standard,
3909 (Remove != null) ? Remove.OptAttributes : null,
3910 ModFlags, flags, false);
3912 if (!RemoveData.Define (parent))
3915 RemoveBuilder = RemoveData.MethodBuilder;
3916 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3918 if (!IsExplicitImpl){
3919 EventBuilder = new MyEventBuilder (
3920 parent.TypeBuilder, Name, e_attr, MemberType);
3922 if (Add == null && Remove == null) {
3923 FieldBuilder = parent.TypeBuilder.DefineField (
3924 Name, MemberType, FieldAttributes.FamANDAssem);
3925 TypeManager.RegisterPrivateFieldOfEvent (
3926 (EventInfo) EventBuilder, FieldBuilder);
3927 TypeManager.RegisterFieldBase (FieldBuilder, this);
3930 EventBuilder.SetAddOnMethod (AddBuilder);
3931 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3933 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3934 Report.Error (111, Location,
3935 "Class `" + parent.Name +
3936 "' already contains a definition for the event `" +
3945 void EmitDefaultMethod (EmitContext ec, bool is_add)
3947 ILGenerator ig = ec.ig;
3948 MethodInfo method = null;
3951 method = TypeManager.delegate_combine_delegate_delegate;
3953 method = TypeManager.delegate_remove_delegate_delegate;
3955 if ((ModFlags & Modifiers.STATIC) != 0) {
3956 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
3957 ig.Emit (OpCodes.Ldarg_0);
3958 ig.Emit (OpCodes.Call, method);
3959 ig.Emit (OpCodes.Castclass, MemberType);
3960 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
3962 ig.Emit (OpCodes.Ldarg_0);
3963 ig.Emit (OpCodes.Ldarg_0);
3964 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3965 ig.Emit (OpCodes.Ldarg_1);
3966 ig.Emit (OpCodes.Call, method);
3967 ig.Emit (OpCodes.Castclass, MemberType);
3968 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3970 ig.Emit (OpCodes.Ret);
3973 public void Emit (TypeContainer tc)
3977 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
3978 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3981 AddData.Emit (tc, Add.Block, Add);
3983 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
3984 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3985 EmitDefaultMethod (ec, true);
3989 RemoveData.Emit (tc, Remove.Block, Remove);
3991 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
3992 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3993 EmitDefaultMethod (ec, false);
4000 // FIXME: This does not handle:
4002 // int INTERFACENAME [ args ]
4007 // int this [ args ]
4009 public class Indexer : PropertyBase {
4011 const int AllowedModifiers =
4014 Modifiers.PROTECTED |
4015 Modifiers.INTERNAL |
4019 Modifiers.OVERRIDE |
4024 public string IndexerName;
4025 public string InterfaceIndexerName;
4028 // Are we implementing an interface ?
4030 bool IsImplementing = false;
4032 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4033 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4034 : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4037 ExplicitInterfaceName = int_type;
4040 public override bool Define (TypeContainer parent)
4042 PropertyAttributes prop_attr =
4043 PropertyAttributes.RTSpecialName |
4044 PropertyAttributes.SpecialName;
4046 if (!DoDefine (parent))
4049 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4050 if (IndexerName == null)
4051 IndexerName = "Item";
4052 else if (IsExplicitImpl)
4053 Report.Error (592, Location,
4054 "Attribute 'IndexerName' is not valid on this declaration " +
4055 "type. It is valid on `property' declarations only.");
4057 ShortName = IndexerName;
4058 if (IsExplicitImpl) {
4059 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4060 Name = InterfaceType.FullName + "." + IndexerName;
4062 InterfaceIndexerName = IndexerName;
4066 if (!CheckBase (parent))
4070 InternalParameters ip = new InternalParameters (parent, Parameters);
4072 GetData = new MethodData (this, "get", MemberType,
4073 ParameterTypes, ip, CallingConventions.Standard,
4074 Get.OptAttributes, ModFlags, flags, false);
4076 if (!GetData.Define (parent))
4079 GetBuilder = GetData.MethodBuilder;
4083 int top = ParameterTypes.Length;
4084 Type [] set_pars = new Type [top + 1];
4085 ParameterTypes.CopyTo (set_pars, 0);
4086 set_pars [top] = MemberType;
4088 Parameter [] fixed_parms = Parameters.FixedParameters;
4090 if (fixed_parms == null){
4091 throw new Exception ("We currently do not support only array arguments in an indexer");
4092 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4093 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4095 // Here is the problem: the `value' parameter has
4096 // to come *after* the array parameter in the declaration
4098 // X (object [] x, Type value)
4101 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4102 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4106 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4109 fixed_parms.CopyTo (tmp, 0);
4110 tmp [fixed_parms.Length] = new Parameter (
4111 Type, "value", Parameter.Modifier.NONE, null);
4113 Parameters set_formal_params = new Parameters (tmp, null, Location);
4115 InternalParameters ip = new InternalParameters (parent, set_formal_params);
4117 SetData = new MethodData (this, "set", TypeManager.void_type,
4118 set_pars, ip, CallingConventions.Standard,
4119 Set.OptAttributes, ModFlags, flags, false);
4121 if (!SetData.Define (parent))
4124 SetBuilder = SetData.MethodBuilder;
4128 // Now name the parameters
4130 Parameter [] p = Parameters.FixedParameters;
4134 for (i = 0; i < p.Length; ++i) {
4136 GetBuilder.DefineParameter (
4137 i + 1, p [i].Attributes, p [i].Name);
4140 SetBuilder.DefineParameter (
4141 i + 1, p [i].Attributes, p [i].Name);
4145 SetBuilder.DefineParameter (
4146 i + 1, ParameterAttributes.None, "value");
4148 if (i != ParameterTypes.Length) {
4149 Parameter array_param = Parameters.ArrayParameter;
4150 SetBuilder.DefineParameter (
4151 i + 1, array_param.Attributes, array_param.Name);
4155 if (GetData != null)
4156 IsImplementing = GetData.IsImplementing;
4157 else if (SetData != null)
4158 IsImplementing = SetData.IsImplementing;
4161 // Define the PropertyBuilder if one of the following conditions are met:
4162 // a) we're not implementing an interface indexer.
4163 // b) the indexer has a different IndexerName and this is no
4164 // explicit interface implementation.
4166 if (!IsExplicitImpl) {
4167 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4168 IndexerName, prop_attr, MemberType, ParameterTypes);
4170 if (GetData != null)
4171 PropertyBuilder.SetGetMethod (GetBuilder);
4173 if (SetData != null)
4174 PropertyBuilder.SetSetMethod (SetBuilder);
4176 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4184 public class Operator : MemberCore {
4186 const int AllowedModifiers =
4192 const int RequiredModifiers =
4196 public enum OpType : byte {
4206 // Unary and Binary operators
4229 // Implicit and Explicit
4234 public readonly OpType OperatorType;
4235 public readonly Expression ReturnType;
4236 public readonly Expression FirstArgType, SecondArgType;
4237 public readonly string FirstArgName, SecondArgName;
4238 public readonly Block Block;
4239 public Attributes OptAttributes;
4240 public MethodBuilder OperatorMethodBuilder;
4242 public string MethodName;
4243 public Method OperatorMethod;
4245 public Operator (OpType type, Expression ret_type, int flags,
4246 Expression arg1type, string arg1name,
4247 Expression arg2type, string arg2name,
4248 Block block, Attributes attrs, Location loc)
4251 OperatorType = type;
4252 ReturnType = ret_type;
4253 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4254 FirstArgType = arg1type;
4255 FirstArgName = arg1name;
4256 SecondArgType = arg2type;
4257 SecondArgName = arg2name;
4259 OptAttributes = attrs;
4262 string Prototype (TypeContainer parent)
4264 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4265 SecondArgType + ")";
4268 public override bool Define (TypeContainer parent)
4271 MethodName = "op_" + OperatorType;
4273 if (SecondArgType != null)
4276 Parameter [] param_list = new Parameter [length];
4278 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4281 "User defined operators `" +
4282 Prototype (parent) +
4283 "' must be declared static and public");
4287 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4288 Parameter.Modifier.NONE, null);
4289 if (SecondArgType != null)
4290 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4291 Parameter.Modifier.NONE, null);
4293 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4294 new Parameters (param_list, null, Location),
4295 OptAttributes, Mono.CSharp.Location.Null);
4297 OperatorMethod.IsOperator = true;
4298 OperatorMethod.Define (parent);
4300 if (OperatorMethod.MethodBuilder == null)
4303 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4305 Type [] param_types = OperatorMethod.ParameterTypes;
4306 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4307 Type return_type = OperatorMethod.GetReturnType ();
4308 Type first_arg_type = param_types [0];
4310 // Rules for conversion operators
4312 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4313 if (first_arg_type == return_type && first_arg_type == declaring_type){
4316 "User-defined conversion cannot take an object of the " +
4317 "enclosing type and convert to an object of the enclosing" +
4322 if (first_arg_type != declaring_type && return_type != declaring_type){
4325 "User-defined conversion must convert to or from the " +
4330 if (first_arg_type == TypeManager.object_type ||
4331 return_type == TypeManager.object_type){
4334 "User-defined conversion cannot convert to or from " +
4339 if (first_arg_type.IsInterface || return_type.IsInterface){
4342 "User-defined conversion cannot convert to or from an " +
4347 if (first_arg_type.IsSubclassOf (return_type) ||
4348 return_type.IsSubclassOf (first_arg_type)){
4351 "User-defined conversion cannot convert between types " +
4352 "that derive from each other");
4355 } else if (SecondArgType == null) {
4356 // Checks for Unary operators
4358 if (first_arg_type != declaring_type){
4361 "The parameter of a unary operator must be the " +
4366 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4367 if (return_type != declaring_type){
4370 "The parameter and return type for ++ and -- " +
4371 "must be the containing type");
4377 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4378 if (return_type != TypeManager.bool_type){
4381 "The return type of operator True or False " +
4388 // Checks for Binary operators
4390 if (first_arg_type != declaring_type &&
4391 param_types [1] != declaring_type){
4394 "One of the parameters of a binary operator must " +
4395 "be the containing type");
4403 public void Emit (TypeContainer parent)
4405 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4406 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4409 // abstract or extern methods have no bodies
4411 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4414 OperatorMethod.Block = Block;
4415 OperatorMethod.Emit (parent);
4418 public static string GetName (OpType ot)
4421 case OpType.LogicalNot:
4423 case OpType.OnesComplement:
4425 case OpType.Increment:
4427 case OpType.Decrement:
4433 case OpType.Addition:
4435 case OpType.Subtraction:
4437 case OpType.UnaryPlus:
4439 case OpType.UnaryNegation:
4441 case OpType.Multiply:
4443 case OpType.Division:
4445 case OpType.Modulus:
4447 case OpType.BitwiseAnd:
4449 case OpType.BitwiseOr:
4451 case OpType.ExclusiveOr:
4453 case OpType.LeftShift:
4455 case OpType.RightShift:
4457 case OpType.Equality:
4459 case OpType.Inequality:
4461 case OpType.GreaterThan:
4463 case OpType.LessThan:
4465 case OpType.GreaterThanOrEqual:
4467 case OpType.LessThanOrEqual:
4469 case OpType.Implicit:
4471 case OpType.Explicit:
4477 public override string ToString ()
4479 Type return_type = OperatorMethod.GetReturnType();
4480 Type [] param_types = OperatorMethod.ParameterTypes;
4482 if (SecondArgType == null)
4483 return String.Format (
4484 "{0} operator {1}({2})",
4485 TypeManager.CSharpName (return_type),
4486 GetName (OperatorType),
4489 return String.Format (
4490 "{0} operator {1}({2}, {3})",
4491 TypeManager.CSharpName (return_type),
4492 GetName (OperatorType),
4493 param_types [0], param_types [1]);
4498 // This is used to compare method signatures
4500 struct MethodSignature {
4502 public Type RetType;
4503 public Type [] Parameters;
4506 /// This delegate is used to extract methods which have the
4507 /// same signature as the argument
4509 public static MemberFilter method_signature_filter;
4512 /// This delegate is used to extract inheritable methods which
4513 /// have the same signature as the argument. By inheritable,
4514 /// this means that we have permissions to override the method
4515 /// from the current assembly and class
4517 public static MemberFilter inheritable_method_signature_filter;
4520 /// This delegate is used to extract inheritable methods which
4521 /// have the same signature as the argument. By inheritable,
4522 /// this means that we have permissions to override the method
4523 /// from the current assembly and class
4525 public static MemberFilter inheritable_property_signature_filter;
4527 static MethodSignature ()
4529 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4530 inheritable_method_signature_filter = new MemberFilter (
4531 InheritableMemberSignatureCompare);
4532 inheritable_property_signature_filter = new MemberFilter (
4533 InheritablePropertySignatureCompare);
4536 public MethodSignature (string name, Type ret_type, Type [] parameters)
4541 if (parameters == null)
4542 Parameters = TypeManager.NoTypes;
4544 Parameters = parameters;
4547 public override int GetHashCode ()
4549 return Name.GetHashCode ();
4552 public override bool Equals (Object o)
4554 MethodSignature other = (MethodSignature) o;
4556 if (other.Name != Name)
4559 if (other.RetType != RetType)
4562 if (Parameters == null){
4563 if (other.Parameters == null)
4568 if (other.Parameters == null)
4571 int c = Parameters.Length;
4572 if (other.Parameters.Length != c)
4575 for (int i = 0; i < c; i++)
4576 if (other.Parameters [i] != Parameters [i])
4582 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4584 MethodSignature sig = (MethodSignature) filter_criteria;
4586 if (m.Name != sig.Name)
4590 MethodInfo mi = m as MethodInfo;
4591 PropertyInfo pi = m as PropertyInfo;
4594 ReturnType = mi.ReturnType;
4595 else if (pi != null)
4596 ReturnType = pi.PropertyType;
4601 // we use sig.RetType == null to mean `do not check the
4602 // method return value.
4604 if (sig.RetType != null)
4605 if (ReturnType != sig.RetType)
4610 args = TypeManager.GetArgumentTypes (mi);
4612 args = TypeManager.GetArgumentTypes (pi);
4613 Type [] sigp = sig.Parameters;
4615 if (args.Length != sigp.Length)
4618 for (int i = args.Length; i > 0; ){
4620 if (args [i] != sigp [i])
4627 // This filter should be used when we are requesting methods that
4628 // we want to override.
4630 // This makes a number of assumptions, for example
4631 // that the methods being extracted are of a parent
4632 // class (this means we know implicitly that we are
4633 // being called to find out about members by a derived
4636 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4638 if (MemberSignatureCompare (m, filter_criteria)){
4639 MethodInfo mi = (MethodInfo) m;
4640 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4642 // If only accessible to the current class.
4643 if (prot == MethodAttributes.Private)
4646 // If only accessible to the defining assembly or
4647 if (prot == MethodAttributes.FamANDAssem ||
4648 prot == MethodAttributes.Assembly){
4649 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4655 // Anything else (FamOrAssembly and Public) is fine
4662 // This filter should be used when we are requesting properties that
4663 // we want to override.
4665 // This makes a number of assumptions, for example
4666 // that the methods being extracted are of a parent
4667 // class (this means we know implicitly that we are
4668 // being called to find out about members by a derived
4671 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
4673 if (MemberSignatureCompare (m, filter_criteria)){
4674 PropertyInfo pi = (PropertyInfo) m;
4676 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
4677 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
4679 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
4681 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4683 // If only accessible to the current class.
4684 if (prot == MethodAttributes.Private)
4687 // If only accessible to the defining assembly or
4688 if (prot == MethodAttributes.FamANDAssem ||
4689 prot == MethodAttributes.Assembly){
4690 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4696 // Anything else (FamOrAssembly and Public) is fine