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)
13 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
15 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
16 // have fixed a remaining problem: not every AddXXXX was adding a
17 // fully qualified name.
19 // Now everyone registers a fully qualified name in the DeclSpace as
20 // being defined instead of the partial name.
22 // Downsides: we are slower than we need to be due to the excess
23 // copies and the names being registered this way.
25 // The reason for this is that we currently depend (on the corlib
26 // bootstrap for instance) that types are fully qualified, because
27 // we dump all the types in the namespace, and we should really have
28 // types inserted into the proper namespace, so we can only store the
29 // basenames in the defined_names array.
34 using System.Collections;
35 using System.Reflection;
36 using System.Reflection.Emit;
37 using System.Runtime.CompilerServices;
38 using System.Diagnostics.SymbolStore;
40 namespace Mono.CSharp {
43 /// This is the base class for structs and classes.
45 public class TypeContainer : DeclSpace, IMemberContainer {
46 // Holds a list of classes and structures
49 // Holds the list of properties
52 // Holds the list of enumerations
55 // Holds the list of delegates
58 // Holds the list of constructors
59 ArrayList instance_constructors;
61 // Holds the list of fields
64 // Holds a list of fields that have initializers
65 ArrayList initialized_fields;
67 // Holds a list of static fields that have initializers
68 ArrayList initialized_static_fields;
70 // Holds the list of constants
76 // Holds order in which interfaces must be closed
77 ArrayList interface_order;
88 // Holds the operators
91 // The emit context for toplevel objects.
95 // Pointers to the default constructor and the default static constructor
97 Constructor default_constructor;
98 Constructor default_static_constructor;
101 // Whether we have seen a static constructor for this class or not
103 bool have_static_constructor = false;
106 // Whether we have at least one non-static field
108 bool have_nonstatic_fields = false;
111 // This one is computed after we can distinguish interfaces
112 // from classes from the arraylist `type_bases'
114 string base_class_name;
116 ArrayList type_bases;
118 // Attributes for this type
119 protected Attributes attributes;
121 // Information in the case we are an attribute type
123 public AttributeTargets Targets = AttributeTargets.All;
124 public bool AllowMultiple = false;
125 public bool Inherited;
127 // The interfaces we implement.
130 // The parent member container and our member cache
131 IMemberContainer parent_container;
132 MemberCache member_cache;
135 // The indexer name for this class
137 public string IndexerName;
139 public TypeContainer (TypeContainer parent, string name, Location l)
140 : base (parent, name, l)
143 types = new ArrayList ();
150 base_class_name = null;
152 //Console.WriteLine ("New class " + name + " inside " + n);
155 public AdditionResult AddConstant (Const constant)
158 string basename = constant.Name;
160 if ((res = IsValid (basename)) != AdditionResult.Success)
163 if (constants == null)
164 constants = new ArrayList ();
166 constants.Add (constant);
167 DefineName (Name + "." + basename, constant);
169 return AdditionResult.Success;
172 public AdditionResult AddEnum (Mono.CSharp.Enum e)
176 if ((res = IsValid (e.Basename)) != AdditionResult.Success)
180 enums = new ArrayList ();
183 DefineName (e.Name, e);
185 return AdditionResult.Success;
188 public AdditionResult AddClass (Class c)
192 if ((res = IsValid (c.Basename)) != AdditionResult.Success)
195 DefineName (c.Name, c);
198 return AdditionResult.Success;
201 public AdditionResult AddStruct (Struct s)
205 if ((res = IsValid (s.Basename)) != AdditionResult.Success)
208 DefineName (s.Name, s);
211 return AdditionResult.Success;
214 public AdditionResult AddDelegate (Delegate d)
218 if ((res = IsValid (d.Basename)) != AdditionResult.Success)
221 if (delegates == null)
222 delegates = new ArrayList ();
224 DefineName (d.Name, d);
227 return AdditionResult.Success;
230 public AdditionResult AddMethod (Method method)
232 string basename = method.Name;
233 string fullname = Name + "." + basename;
235 Object value = defined_names [fullname];
237 if (value != null && (!(value is Method)))
238 return AdditionResult.NameExists;
240 if (basename == Basename)
241 return AdditionResult.EnclosingClash;
244 methods = new ArrayList ();
246 if (method.Name.IndexOf (".") != -1)
247 methods.Insert (0, method);
249 methods.Add (method);
252 DefineName (fullname, method);
254 return AdditionResult.Success;
257 public AdditionResult AddConstructor (Constructor c)
260 return AdditionResult.NotAConstructor;
262 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
265 have_static_constructor = true;
266 if (default_static_constructor != null){
267 Console.WriteLine ("I have a static constructor already");
268 Console.WriteLine (" " + default_static_constructor);
269 return AdditionResult.MethodExists;
272 default_static_constructor = c;
275 if (default_constructor != null)
276 return AdditionResult.MethodExists;
277 default_constructor = c;
280 if (instance_constructors == null)
281 instance_constructors = new ArrayList ();
283 instance_constructors.Add (c);
286 return AdditionResult.Success;
289 public AdditionResult AddInterface (Interface iface)
293 if ((res = IsValid (iface.Basename)) != AdditionResult.Success)
296 if (interfaces == null)
297 interfaces = new ArrayList ();
298 interfaces.Add (iface);
299 DefineName (iface.Name, iface);
301 return AdditionResult.Success;
304 public AdditionResult AddField (Field field)
307 string basename = field.Name;
309 if ((res = IsValid (basename)) != AdditionResult.Success)
313 fields = new ArrayList ();
317 if (field.HasInitializer){
318 if ((field.ModFlags & Modifiers.STATIC) != 0){
319 if (initialized_static_fields == null)
320 initialized_static_fields = new ArrayList ();
322 initialized_static_fields.Add (field);
325 // We have not seen a static constructor,
326 // but we will provide static initialization of fields
328 have_static_constructor = true;
330 if (initialized_fields == null)
331 initialized_fields = new ArrayList ();
333 initialized_fields.Add (field);
337 if ((field.ModFlags & Modifiers.STATIC) == 0)
338 have_nonstatic_fields = true;
340 DefineName (Name + "." + basename, field);
341 return AdditionResult.Success;
344 public AdditionResult AddProperty (Property prop)
347 string basename = prop.Name;
349 if ((res = IsValid (basename)) != AdditionResult.Success)
352 if (properties == null)
353 properties = new ArrayList ();
355 if (prop.Name.IndexOf (".") != -1)
356 properties.Insert (0, prop);
358 properties.Add (prop);
359 DefineName (Name + "." + basename, prop);
361 return AdditionResult.Success;
364 public AdditionResult AddEvent (Event e)
367 string basename = e.Name;
369 if ((res = IsValid (basename)) != AdditionResult.Success)
373 events = new ArrayList ();
376 DefineName (Name + "." + basename, e);
378 return AdditionResult.Success;
381 public AdditionResult AddIndexer (Indexer i)
383 if (indexers == null)
384 indexers = new ArrayList ();
386 if (i.InterfaceType != null)
387 indexers.Insert (0, i);
391 return AdditionResult.Success;
394 public AdditionResult AddOperator (Operator op)
396 if (operators == null)
397 operators = new ArrayList ();
401 return AdditionResult.Success;
404 public void RegisterOrder (Interface iface)
406 if (interface_order == null)
407 interface_order = new ArrayList ();
409 interface_order.Add (iface);
412 public ArrayList Types {
418 public ArrayList Methods {
424 public ArrayList Constants {
430 public ArrayList Interfaces {
438 return base_class_name;
442 public ArrayList Bases {
452 public ArrayList Fields {
462 public ArrayList InstanceConstructors {
464 return instance_constructors;
468 public ArrayList Properties {
474 public ArrayList Events {
480 public ArrayList Enums {
486 public ArrayList Indexers {
492 public ArrayList Operators {
498 public ArrayList Delegates {
504 public Attributes OptAttributes {
510 public bool HaveStaticConstructor {
512 return have_static_constructor;
516 public virtual TypeAttributes TypeAttr {
518 return Modifiers.TypeAttr (ModFlags, this);
523 // Emits the instance field initializers
525 public bool EmitFieldInitializers (EmitContext ec)
528 ILGenerator ig = ec.ig;
529 Expression instance_expr;
532 fields = initialized_static_fields;
533 instance_expr = null;
535 fields = initialized_fields;
536 instance_expr = new This (Location.Null).Resolve (ec);
542 foreach (Field f in fields){
543 Expression e = f.GetInitializerExpression (ec);
547 Location l = f.Location;
548 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
549 fe.InstanceExpression = instance_expr;
550 Expression a = new Assign (fe, e, l);
556 if (a is ExpressionStatement)
557 ((ExpressionStatement) a).EmitStatement (ec);
559 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
567 // Defines the default constructors
569 void DefineDefaultConstructor (bool is_static)
574 c = new Constructor (Basename, Parameters.EmptyReadOnlyParameters,
575 new ConstructorBaseInitializer (
576 null, Parameters.EmptyReadOnlyParameters,
581 mods = Modifiers.STATIC;
587 c.Block = new Block (null);
591 public void ReportStructInitializedInstanceError ()
593 string n = TypeBuilder.FullName;
595 foreach (Field f in initialized_fields){
598 "`" + n + "." + f.Name + "': can not have " +
599 "instance field initializers in structs");
604 /// The pending methods that need to be implemented (interfaces or abstract methods)
606 public PendingImplementation Pending;
609 /// This function computes the Base class and also the
610 /// list of interfaces that the class or struct @c implements.
612 /// The return value is an array (might be null) of
613 /// interfaces implemented (as Types).
615 /// The @parent argument is set to the parent object or null
616 /// if this is `System.Object'.
618 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
620 ArrayList bases = Bases;
629 parent = TypeManager.value_type;
633 if (RootContext.StdLib)
634 parent = TypeManager.object_type;
635 else if (Name != "System.Object")
636 parent = TypeManager.object_type;
639 // If we are compiling our runtime,
640 // and we are defining ValueType, then our
641 // parent is `System.Object'.
643 if (!RootContext.StdLib && Name == "System.ValueType")
644 parent = TypeManager.object_type;
651 // Bases should be null if there are no bases at all
656 Expression name = (Expression) bases [0];
657 name = ResolveTypeExpr (name, false, Location);
664 Type first = name.Type;
670 parent = TypeManager.object_type;
674 if (!AsAccessible (parent, ModFlags))
675 Report.Error (60, Location,
676 "Inconsistent accessibility: base class `" +
677 TypeManager.CSharpName (parent) + "' is less " +
678 "accessible than class `" +
685 Type [] ifaces = new Type [count-start];
687 for (i = start, j = 0; i < count; i++, j++){
688 Expression name = (Expression) bases [i];
689 Expression resolved = ResolveTypeExpr (name, false, Location);
690 bases [i] = resolved;
691 Type t = resolved.Type;
698 if (is_class == false && !t.IsInterface){
699 Report.Error (527, "In Struct `" + Name + "', type `"+
700 name +"' is not an interface");
709 detail = " (a class can not inherit from a struct/enum)";
711 Report.Error (509, "class `"+ Name +
712 "': Cannot inherit from sealed class `"+
713 bases [i]+"'"+detail);
720 Report.Error (527, "In Class `" + Name + "', type `"+
721 name+"' is not an interface");
727 for (int x = 0; x < j; x++) {
728 if (t == ifaces [x]) {
729 Report.Error (528, "`" + name + "' is already listed in interface list");
738 return TypeManager.ExpandInterfaces (ifaces);
742 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
744 public override TypeBuilder DefineType ()
750 if (TypeBuilder != null)
763 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
765 ifaces = GetClassBases (is_class, out parent, out error);
770 if (is_class && parent != null){
771 if (parent == TypeManager.enum_type ||
772 (parent == TypeManager.value_type && RootContext.StdLib) ||
773 parent == TypeManager.delegate_type ||
774 parent == TypeManager.array_type){
776 644, Location, "`" + Name + "' cannot inherit from " +
777 "special class `" + TypeManager.CSharpName (parent) + "'");
782 if (!is_class && TypeManager.value_type == null)
783 throw new Exception ();
785 TypeAttributes type_attributes = TypeAttr;
787 // if (parent_builder is ModuleBuilder) {
789 ModuleBuilder builder = CodeGen.ModuleBuilder;
790 TypeBuilder = builder.DefineType (
791 Name, type_attributes, parent, ifaces);
794 TypeBuilder builder = Parent.TypeBuilder;
795 TypeBuilder = builder.DefineNestedType (
796 Basename, type_attributes, parent, ifaces);
800 // Structs with no fields need to have at least one byte.
801 // The right thing would be to set the PackingSize in a DefineType
802 // but there are no functions that allow interfaces *and* the size to
806 if (!is_class && !have_nonstatic_fields){
807 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
808 FieldAttributes.Private);
811 // add interfaces that were not added at type creation (weird API issue)
812 if (!is_class && !have_nonstatic_fields && (ifaces != null)) {
813 foreach (Type i in ifaces)
814 TypeBuilder.AddInterfaceImplementation (i);
818 // Finish the setup for the EmitContext
820 ec.ContainerType = TypeBuilder;
822 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
824 if ((parent != null) &&
825 (parent == TypeManager.attribute_type ||
826 parent.IsSubclassOf (TypeManager.attribute_type))) {
827 RootContext.RegisterAttribute (this);
828 TypeManager.RegisterAttrType (TypeBuilder, this);
830 RootContext.RegisterOrder (this);
832 if (Interfaces != null) {
833 foreach (Interface iface in Interfaces)
838 foreach (TypeContainer tc in Types)
842 if (Delegates != null) {
843 foreach (Delegate d in Delegates)
848 foreach (Enum en in Enums)
858 /// Defines the MemberCore objects that are in the `list' Arraylist
860 /// The `defined_names' array contains a list of members defined in
863 static ArrayList remove_list = new ArrayList ();
864 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
868 remove_list.Clear ();
870 foreach (MemberCore mc in list){
871 if (!mc.Define (this)){
872 remove_list.Add (mc);
876 if (defined_names == null)
879 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
881 if (RootContext.WarningLevel >= 4){
882 if ((mc.ModFlags & Modifiers.NEW) != 0)
883 Warning_KewywordNewNotRequired (mc.Location, mc);
888 MemberInfo match = defined_names [idx];
890 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
894 // If we are both methods, let the method resolution emit warnings
896 if (match is MethodBase && mc is MethodCore)
899 if ((mc.ModFlags & Modifiers.NEW) == 0)
900 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
903 foreach (object o in remove_list)
906 remove_list.Clear ();
910 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
911 // class is consisten. Either it is `Item' or it is the name defined by all the
912 // indexers with the `IndexerName' attribute.
914 // Turns out that the IndexerNameAttribute is applied to each indexer,
915 // but it is never emitted, instead a DefaultName attribute is attached
918 void DefineIndexers ()
920 string class_indexer_name = null;
922 foreach (Indexer i in Indexers){
927 name = i.IndexerName;
929 if (i.InterfaceType != null)
932 if (class_indexer_name == null){
933 class_indexer_name = name;
937 if (name == class_indexer_name)
941 668, "Two indexers have different names, " +
942 " you should use the same name for all your indexers");
944 if (class_indexer_name == null)
945 class_indexer_name = "Item";
946 IndexerName = class_indexer_name;
949 static void Error_KeywordNotAllowed (Location loc)
951 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
955 /// Populates our TypeBuilder with fields and methods
957 public override bool DefineMembers (TypeContainer parent)
959 MemberInfo [] defined_names = null;
961 if (interface_order != null){
962 foreach (Interface iface in interface_order)
963 if ((iface.ModFlags & Modifiers.NEW) == 0)
964 iface.DefineMembers (this);
966 Error_KeywordNotAllowed (iface.Location);
969 if (RootContext.WarningLevel > 1){
973 // This code throws an exception in the comparer
974 // I guess the string is not an object?
976 ptype = TypeBuilder.BaseType;
978 defined_names = (MemberInfo []) FindMembers (
979 ptype, MemberTypes.All & ~MemberTypes.Constructor,
980 BindingFlags.Public | BindingFlags.Instance |
981 BindingFlags.Static, null, null);
983 Array.Sort (defined_names, mif_compare);
987 if (constants != null)
988 DefineMembers (constants, defined_names);
991 DefineMembers (fields, defined_names);
994 if (instance_constructors == null){
995 if (default_constructor == null)
996 DefineDefaultConstructor (false);
999 if (initialized_static_fields != null &&
1000 default_static_constructor == null)
1001 DefineDefaultConstructor (true);
1004 if (this is Struct){
1006 // Structs can not have initialized instance
1009 if (initialized_static_fields != null &&
1010 default_static_constructor == null)
1011 DefineDefaultConstructor (true);
1013 if (initialized_fields != null)
1014 ReportStructInitializedInstanceError ();
1017 Pending = PendingImplementation.GetPendingImplementations (this);
1020 // Constructors are not in the defined_names array
1022 if (instance_constructors != null)
1023 DefineMembers (instance_constructors, null);
1025 if (default_static_constructor != null)
1026 default_static_constructor.Define (this);
1028 if (methods != null)
1029 DefineMembers (methods, defined_names);
1031 if (properties != null)
1032 DefineMembers (properties, defined_names);
1035 DefineMembers (events, defined_names);
1037 if (indexers != null) {
1040 IndexerName = "Item";
1042 if (operators != null){
1043 DefineMembers (operators, null);
1045 CheckPairedOperators ();
1049 DefineMembers (enums, defined_names);
1051 if (delegates != null)
1052 DefineMembers (delegates, defined_names);
1055 if (TypeBuilder.BaseType != null)
1056 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1058 member_cache = new MemberCache (this);
1064 public override bool Define (TypeContainer parent)
1066 if (interface_order != null){
1067 foreach (Interface iface in interface_order)
1068 if ((iface.ModFlags & Modifiers.NEW) == 0)
1069 iface.Define (this);
1076 /// This function is based by a delegate to the FindMembers routine
1078 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1084 /// This filter is used by FindMembers, and we just keep
1085 /// a global for the filter to `AlwaysAccept'
1087 static MemberFilter accepting_filter;
1091 /// A member comparission method based on name only
1093 static IComparer mif_compare;
1095 static TypeContainer ()
1097 accepting_filter = new MemberFilter (AlwaysAccept);
1098 mif_compare = new MemberInfoCompare ();
1102 /// This method returns the members of this type just like Type.FindMembers would
1103 /// Only, we need to use this for types which are _being_ defined because MS'
1104 /// implementation can't take care of that.
1107 // FIXME: return an empty static array instead of null, that cleans up
1108 // some code and is consistent with some coding conventions I just found
1112 // Notice that in various cases we check if our field is non-null,
1113 // something that would normally mean that there was a bug elsewhere.
1115 // The problem happens while we are defining p-invoke methods, as those
1116 // will trigger a FindMembers, but this happens before things are defined
1118 // Since the whole process is a no-op, it is fine to check for null here.
1120 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1121 MemberFilter filter, object criteria)
1123 ArrayList members = new ArrayList ();
1126 if ((bf & BindingFlags.Public) != 0)
1127 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1129 if ((bf & BindingFlags.NonPublic) != 0)
1130 modflags |= Modifiers.PRIVATE;
1132 int static_mask = 0, static_flags = 0;
1133 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1134 case BindingFlags.Static:
1135 static_mask = static_flags = Modifiers.STATIC;
1138 case BindingFlags.Instance:
1139 static_mask = Modifiers.STATIC;
1144 static_mask = static_flags = 0;
1148 Timer.StartTimer (TimerType.TcFindMembers);
1151 filter = accepting_filter;
1153 if ((mt & MemberTypes.Field) != 0) {
1154 if (fields != null) {
1155 foreach (Field f in fields) {
1156 if ((f.ModFlags & modflags) == 0)
1158 if ((f.ModFlags & static_mask) != static_flags)
1161 FieldBuilder fb = f.FieldBuilder;
1162 if (fb != null && filter (fb, criteria) == true)
1167 if (constants != null) {
1168 foreach (Const con in constants) {
1169 if ((con.ModFlags & modflags) == 0)
1171 if ((con.ModFlags & static_mask) != static_flags)
1174 FieldBuilder fb = con.FieldBuilder;
1175 if (fb != null && filter (fb, criteria) == true)
1181 if ((mt & MemberTypes.Method) != 0) {
1182 if (methods != null) {
1183 foreach (Method m in methods) {
1184 if ((m.ModFlags & modflags) == 0)
1186 if ((m.ModFlags & static_mask) != static_flags)
1189 MethodBuilder mb = m.MethodBuilder;
1191 if (mb != null && filter (mb, criteria) == true)
1196 if (operators != null){
1197 foreach (Operator o in operators) {
1198 if ((o.ModFlags & modflags) == 0)
1200 if ((o.ModFlags & static_mask) != static_flags)
1203 MethodBuilder ob = o.OperatorMethodBuilder;
1204 if (ob != null && filter (ob, criteria) == true)
1209 if (properties != null){
1210 foreach (Property p in properties){
1211 if ((p.ModFlags & modflags) == 0)
1213 if ((p.ModFlags & static_mask) != static_flags)
1219 if (b != null && filter (b, criteria) == true)
1223 if (b != null && filter (b, criteria) == true)
1228 if (indexers != null){
1229 foreach (Indexer ix in indexers){
1230 if ((ix.ModFlags & modflags) == 0)
1232 if ((ix.ModFlags & static_mask) != static_flags)
1238 if (b != null && filter (b, criteria) == true)
1242 if (b != null && filter (b, criteria) == true)
1248 if ((mt & MemberTypes.Event) != 0) {
1250 foreach (Event e in events) {
1251 if ((e.ModFlags & modflags) == 0)
1253 if ((e.ModFlags & static_mask) != static_flags)
1256 MemberInfo eb = e.EventBuilder;
1257 if (eb != null && filter (eb, criteria) == true)
1258 members.Add (e.EventBuilder);
1262 if ((mt & MemberTypes.Property) != 0){
1263 if (properties != null)
1264 foreach (Property p in properties) {
1265 if ((p.ModFlags & modflags) == 0)
1267 if ((p.ModFlags & static_mask) != static_flags)
1270 MemberInfo pb = p.PropertyBuilder;
1271 if (pb != null && filter (pb, criteria) == true) {
1272 members.Add (p.PropertyBuilder);
1276 if (indexers != null)
1277 foreach (Indexer ix in indexers) {
1278 if ((ix.ModFlags & modflags) == 0)
1280 if ((ix.ModFlags & static_mask) != static_flags)
1283 MemberInfo ib = ix.PropertyBuilder;
1284 if (ib != null && filter (ib, criteria) == true) {
1285 members.Add (ix.PropertyBuilder);
1290 if ((mt & MemberTypes.NestedType) != 0) {
1292 foreach (TypeContainer t in types) {
1293 if ((t.ModFlags & modflags) == 0)
1296 TypeBuilder tb = t.TypeBuilder;
1297 if (tb != null && (filter (tb, criteria) == true))
1303 foreach (Enum en in enums){
1304 if ((en.ModFlags & modflags) == 0)
1307 TypeBuilder tb = en.TypeBuilder;
1308 if (tb != null && (filter (tb, criteria) == true))
1313 if (delegates != null){
1314 foreach (Delegate d in delegates){
1315 if ((d.ModFlags & modflags) == 0)
1318 TypeBuilder tb = d.TypeBuilder;
1319 if (tb != null && (filter (tb, criteria) == true))
1324 if (interfaces != null){
1325 foreach (Interface iface in interfaces){
1326 if ((iface.ModFlags & modflags) == 0)
1329 TypeBuilder tb = iface.TypeBuilder;
1330 if (tb != null && (filter (tb, criteria) == true))
1336 if ((mt & MemberTypes.Constructor) != 0){
1337 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1338 foreach (Constructor c in instance_constructors){
1339 ConstructorBuilder cb = c.ConstructorBuilder;
1341 if (filter (cb, criteria) == true)
1346 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1347 ConstructorBuilder cb =
1348 default_static_constructor.ConstructorBuilder;
1351 if (filter (cb, criteria) == true)
1357 // Lookup members in parent if requested.
1359 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1360 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1361 members.AddRange (list);
1364 Timer.StopTimer (TimerType.TcFindMembers);
1366 return new MemberList (members);
1369 public override MemberCache MemberCache {
1371 return member_cache;
1375 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1376 MemberFilter filter, object criteria)
1378 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1381 return tc.FindMembers (mt, bf, filter, criteria);
1383 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1387 // FindMethods will look for methods not only in the type `t', but in
1388 // any interfaces implemented by the type.
1390 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1391 MemberFilter filter, object criteria)
1397 /// Emits the values for the constants
1399 public void EmitConstants ()
1401 if (constants != null)
1402 foreach (Const con in constants)
1403 con.EmitConstant (this);
1408 /// Emits the code, this step is performed after all
1409 /// the types, enumerations, constructors
1413 if (instance_constructors != null)
1414 foreach (Constructor c in instance_constructors)
1417 if (default_static_constructor != null)
1418 default_static_constructor.Emit (this);
1420 if (methods != null)
1421 foreach (Method m in methods)
1424 if (operators != null)
1425 foreach (Operator o in operators)
1428 if (properties != null)
1429 foreach (Property p in properties)
1432 if (indexers != null){
1433 foreach (Indexer ix in indexers)
1436 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1437 this, IndexerName, ModFlags, Location);
1438 TypeBuilder.SetCustomAttribute (cb);
1442 foreach (Field f in fields)
1445 if (events != null){
1446 foreach (Event e in Events)
1450 if (Pending != null)
1451 if (Pending.VerifyPendingMethods ())
1454 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1457 // Check for internal or private fields that were never assigned
1459 if (fields != null && RootContext.WarningLevel >= 3) {
1460 foreach (Field f in fields) {
1461 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1466 169, f.Location, "Private field " +
1467 MakeName (f.Name) + " is never used");
1472 // Only report 649 on level 4
1474 if (RootContext.WarningLevel < 4)
1477 if ((f.status & Field.Status.ASSIGNED) != 0)
1482 "Field " + MakeName (f.Name) + " is never assigned " +
1483 " to and will always have its default value");
1487 // if (types != null)
1488 // foreach (TypeContainer tc in types)
1492 public override void CloseType ()
1497 TypeBuilder.CreateType ();
1499 } catch (TypeLoadException){
1501 // This is fine, the code still created the type
1503 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1504 // Console.WriteLine (e.Message);
1506 Console.WriteLine ("In type: " + Name);
1511 foreach (Enum en in Enums)
1514 if (interface_order != null){
1515 foreach (Interface iface in interface_order)
1520 foreach (TypeContainer tc in Types)
1524 foreach (TypeContainer tc in Types)
1525 if (!(tc is Struct))
1529 if (Delegates != null)
1530 foreach (Delegate d in Delegates)
1534 public string MakeName (string n)
1536 return "`" + Name + "." + n + "'";
1539 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1542 108, l, "The keyword new is required on " +
1543 MakeName (mi.Name) + " because it hides `" +
1544 mi.ReflectedType.Name + "." + mi.Name + "'");
1547 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1550 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1551 "inherited member, the keyword new is not required");
1554 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1560 // Performs the validation on a Method's modifiers (properties have
1561 // the same properties).
1563 public bool MethodModifiersValid (int flags, string n, Location loc)
1565 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1566 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1567 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1569 string name = MakeName (n);
1572 // At most one of static, virtual or override
1574 if ((flags & Modifiers.STATIC) != 0){
1575 if ((flags & vao) != 0){
1577 112, loc, "static method " + name + "can not be marked " +
1578 "as virtual, abstract or override");
1583 if (this is Struct){
1584 if ((flags & va) != 0){
1585 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1590 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1593 " marked as override cannot be marked as new or virtual");
1598 // If the declaration includes the abstract modifier, then the
1599 // declaration does not include static, virtual or extern
1601 if ((flags & Modifiers.ABSTRACT) != 0){
1602 if ((flags & Modifiers.EXTERN) != 0){
1604 180, loc, name + " can not be both abstract and extern");
1608 if ((flags & Modifiers.VIRTUAL) != 0){
1610 503, loc, name + " can not be both abstract and virtual");
1614 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1617 " is abstract but its container class is not");
1623 if ((flags & Modifiers.PRIVATE) != 0){
1624 if ((flags & vao) != 0){
1627 " virtual or abstract members can not be private");
1632 if ((flags & Modifiers.SEALED) != 0){
1633 if ((flags & Modifiers.OVERRIDE) == 0){
1636 " cannot be sealed because it is not an override");
1644 // Access level of a type.
1647 ProtectedInternal = 1,
1653 // Check whether `flags' denotes a more restricted access than `level'
1654 // and return the new level.
1655 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1657 AccessLevel old_level = level;
1659 if ((flags & Modifiers.INTERNAL) != 0) {
1660 if ((flags & Modifiers.PROTECTED) != 0) {
1661 if ((int) level < (int) AccessLevel.ProtectedInternal)
1662 level = AccessLevel.ProtectedInternal;
1664 if ((int) level < (int) AccessLevel.Internal)
1665 level = AccessLevel.Internal;
1667 } else if ((flags & Modifiers.PROTECTED) != 0) {
1668 if ((int) level < (int) AccessLevel.Protected)
1669 level = AccessLevel.Protected;
1670 } else if ((flags & Modifiers.PRIVATE) != 0)
1671 level = AccessLevel.Private;
1676 // Return the access level for a new member which is defined in the current
1677 // TypeContainer with access modifiers `flags'.
1678 AccessLevel GetAccessLevel (int flags)
1680 if ((flags & Modifiers.PRIVATE) != 0)
1681 return AccessLevel.Private;
1684 if (!IsTopLevel && (Parent != null))
1685 level = Parent.GetAccessLevel (flags);
1687 level = AccessLevel.Public;
1689 return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1692 // Return the access level for type `t', but don't give more access than `flags'.
1693 static AccessLevel GetAccessLevel (Type t, int flags)
1695 if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1696 return AccessLevel.Private;
1699 if (TypeManager.IsBuiltinType (t))
1700 return AccessLevel.Public;
1701 else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1702 level = GetAccessLevel (t.DeclaringType, flags);
1704 level = CheckAccessLevel (AccessLevel.Public, flags);
1707 if (t.IsNestedPublic)
1710 if (t.IsNestedAssembly || t.IsNotPublic) {
1711 if ((int) level < (int) AccessLevel.Internal)
1712 level = AccessLevel.Internal;
1715 if (t.IsNestedFamily) {
1716 if ((int) level < (int) AccessLevel.Protected)
1717 level = AccessLevel.Protected;
1720 if (t.IsNestedFamORAssem) {
1721 if ((int) level < (int) AccessLevel.ProtectedInternal)
1722 level = AccessLevel.ProtectedInternal;
1729 // Returns true if `parent' is as accessible as the flags `flags'
1730 // given for this member.
1732 public bool AsAccessible (Type parent, int flags)
1734 while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1735 parent = parent.GetElementType ();
1737 AccessLevel level = GetAccessLevel (flags);
1738 AccessLevel level2 = GetAccessLevel (parent, flags);
1740 return (int) level >= (int) level2;
1743 Hashtable builder_and_args;
1745 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1747 if (builder_and_args == null)
1748 builder_and_args = new Hashtable ();
1753 /// Performs checks for an explicit interface implementation. First it
1754 /// checks whether the `interface_type' is a base inteface implementation.
1755 /// Then it checks whether `name' exists in the interface type.
1757 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1761 if (ifaces != null){
1762 foreach (Type t in ifaces){
1763 if (t == interface_type){
1771 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1778 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1780 Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1787 string IMemberContainer.Name {
1793 Type IMemberContainer.Type {
1799 IMemberContainer IMemberContainer.Parent {
1801 return parent_container;
1805 MemberCache IMemberContainer.MemberCache {
1807 return member_cache;
1811 bool IMemberContainer.IsInterface {
1817 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1819 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1823 // Operator pair checking
1826 class OperatorEntry {
1828 public Type ret_type;
1829 public Type type1, type2;
1831 public Operator.OpType ot;
1833 public OperatorEntry (int f, Operator o)
1837 ret_type = o.OperatorMethod.GetReturnType ();
1838 Type [] pt = o.OperatorMethod.ParameterTypes;
1842 ot = o.OperatorType;
1845 public override int GetHashCode ()
1847 return ret_type.GetHashCode ();
1850 public override bool Equals (object o)
1852 OperatorEntry other = (OperatorEntry) o;
1854 if (other.ret_type != ret_type)
1856 if (other.type1 != type1)
1858 if (other.type2 != type2)
1865 // Checks that some operators come in pairs:
1870 // They are matched based on the return type and the argument types
1872 void CheckPairedOperators ()
1874 Hashtable pairs = new Hashtable (null, null);
1876 // Register all the operators we care about.
1877 foreach (Operator op in operators){
1880 switch (op.OperatorType){
1881 case Operator.OpType.Equality:
1883 case Operator.OpType.Inequality:
1886 case Operator.OpType.GreaterThan:
1888 case Operator.OpType.LessThan:
1891 case Operator.OpType.GreaterThanOrEqual:
1893 case Operator.OpType.LessThanOrEqual:
1899 OperatorEntry oe = new OperatorEntry (reg, op);
1901 object o = pairs [oe];
1905 oe = (OperatorEntry) o;
1911 // Look for the mistakes.
1913 foreach (DictionaryEntry de in pairs){
1914 OperatorEntry oe = (OperatorEntry) de.Key;
1921 case Operator.OpType.Equality:
1924 case Operator.OpType.Inequality:
1927 case Operator.OpType.GreaterThan:
1930 case Operator.OpType.LessThan:
1933 case Operator.OpType.GreaterThanOrEqual:
1936 case Operator.OpType.LessThanOrEqual:
1940 Report.Error (216, oe.op.Location,
1941 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
1948 public class Class : TypeContainer {
1950 // Modifiers allowed in a class declaration
1952 public const int AllowedModifiers =
1955 Modifiers.PROTECTED |
1956 Modifiers.INTERNAL |
1958 Modifiers.ABSTRACT |
1962 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1963 : base (parent, name, l)
1967 if (parent.Parent == null)
1968 accmods = Modifiers.INTERNAL;
1970 accmods = Modifiers.PRIVATE;
1972 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1973 this.attributes = attrs;
1977 // FIXME: How do we deal with the user specifying a different
1980 public override TypeAttributes TypeAttr {
1982 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1987 public class Struct : TypeContainer {
1989 // Modifiers allowed in a struct declaration
1991 public const int AllowedModifiers =
1994 Modifiers.PROTECTED |
1995 Modifiers.INTERNAL |
1999 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2000 : base (parent, name, l)
2004 if (parent.Parent == null)
2005 accmods = Modifiers.INTERNAL;
2007 accmods = Modifiers.PRIVATE;
2009 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2011 this.ModFlags |= Modifiers.SEALED;
2012 this.attributes = attrs;
2017 // FIXME: Allow the user to specify a different set of attributes
2018 // in some cases (Sealed for example is mandatory for a class,
2019 // but what SequentialLayout can be changed
2021 public override TypeAttributes TypeAttr {
2023 return base.TypeAttr |
2024 TypeAttributes.SequentialLayout |
2025 TypeAttributes.Sealed |
2026 TypeAttributes.BeforeFieldInit;
2031 public abstract class MethodCore : MemberBase {
2032 public readonly Parameters Parameters;
2036 // Parameters, cached for semantic analysis.
2038 protected InternalParameters parameter_info;
2039 protected Type [] parameter_types;
2041 public MethodCore (Expression type, int mod, int allowed_mod, string name,
2042 Attributes attrs, Parameters parameters, Location loc)
2043 : base (type, mod, allowed_mod, name, attrs, loc)
2045 Parameters = parameters;
2049 // Returns the System.Type array for the parameters of this method
2051 public Type [] ParameterTypes {
2053 return parameter_types;
2057 public InternalParameters ParameterInfo
2060 return parameter_info;
2064 public Block Block {
2074 protected virtual bool DoDefineParameters (TypeContainer parent)
2076 // Check if arguments were correct
2077 parameter_types = Parameters.GetParameterInfo (parent);
2078 if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
2081 parameter_info = new InternalParameters (parent, Parameters);
2086 public CallingConventions GetCallingConvention (bool is_class)
2088 CallingConventions cc = 0;
2090 cc = Parameters.GetCallingConvention ();
2093 if ((ModFlags & Modifiers.STATIC) == 0)
2094 cc |= CallingConventions.HasThis;
2096 // FIXME: How is `ExplicitThis' used in C#?
2101 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
2104 // Define each type attribute (in/out/ref) and
2105 // the argument names.
2107 Parameter [] p = Parameters.FixedParameters;
2110 MethodBuilder mb = null;
2111 ConstructorBuilder cb = null;
2113 if (builder is MethodBuilder)
2114 mb = (MethodBuilder) builder;
2116 cb = (ConstructorBuilder) builder;
2119 for (i = 0; i < p.Length; i++) {
2120 ParameterBuilder pb;
2123 pb = cb.DefineParameter (
2124 i + 1, p [i].Attributes, p [i].Name);
2126 pb = mb.DefineParameter (
2127 i + 1, p [i].Attributes, p [i].Name);
2129 Attributes attr = p [i].OptAttributes;
2131 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
2135 if (Parameters.ArrayParameter != null){
2136 ParameterBuilder pb;
2137 Parameter array_param = Parameters.ArrayParameter;
2140 pb = cb.DefineParameter (
2141 i + 1, array_param.Attributes,
2144 pb = mb.DefineParameter (
2145 i + 1, array_param.Attributes,
2148 CustomAttributeBuilder a = new CustomAttributeBuilder (
2149 TypeManager.cons_param_array_attribute, new object [0]);
2151 pb.SetCustomAttribute (a);
2156 public class Method : MethodCore {
2157 public MethodBuilder MethodBuilder;
2158 public MethodData MethodData;
2161 /// Modifiers allowed in a class declaration
2163 const int AllowedModifiers =
2166 Modifiers.PROTECTED |
2167 Modifiers.INTERNAL |
2172 Modifiers.OVERRIDE |
2173 Modifiers.ABSTRACT |
2178 // return_type can be "null" for VOID values.
2180 public Method (Expression return_type, int mod, string name, Parameters parameters,
2181 Attributes attrs, Location l)
2182 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2186 // Returns the `System.Type' for the ReturnType of this
2187 // function. Provides a nice cache. (used between semantic analysis
2188 // and actual code generation
2190 public Type GetReturnType ()
2195 // Whether this is an operator method.
2196 public bool IsOperator;
2198 void DuplicateEntryPoint (MethodInfo b, Location location)
2202 "Program `" + CodeGen.FileName +
2203 "' has more than one entry point defined: `" +
2204 TypeManager.CSharpSignature(b) + "'");
2207 void Report28 (MethodInfo b)
2209 if (RootContext.WarningLevel < 4)
2214 "`" + TypeManager.CSharpSignature(b) +
2215 "' has the wrong signature to be an entry point");
2218 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2220 if (b.ReturnType != TypeManager.void_type &&
2221 b.ReturnType != TypeManager.int32_type)
2224 if (pinfo.Count == 0)
2227 if (pinfo.Count > 1)
2230 Type t = pinfo.ParameterType(0);
2232 (t.GetArrayRank() == 1) &&
2233 (t.GetElementType() == TypeManager.string_type) &&
2234 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2241 // Checks our base implementation if any
2243 protected override bool CheckBase (TypeContainer parent)
2245 // Check whether arguments were correct.
2246 if (!DoDefineParameters (parent))
2249 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2253 mi_this = TypeContainer.FindMembers (
2254 parent.TypeBuilder, MemberTypes.Method,
2255 BindingFlags.NonPublic | BindingFlags.Public |
2256 BindingFlags.Static | BindingFlags.Instance |
2257 BindingFlags.DeclaredOnly,
2258 MethodSignature.method_signature_filter, ms);
2260 if (mi_this.Count > 0) {
2261 Report.Error (111, Location, "Class `" + parent.Name + "' " +
2262 "already defines a member called `" + Name + "' " +
2263 "with the same parameter types");
2269 // Verify if the parent has a type with the same name, and then
2270 // check whether we have to create a new slot for it or not.
2272 Type ptype = parent.TypeBuilder.BaseType;
2274 // ptype is only null for System.Object while compiling corlib.
2276 MemberList mi, mi_static, mi_instance;
2278 mi_static = TypeContainer.FindMembers (
2279 ptype, MemberTypes.Method,
2280 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2281 MethodSignature.inheritable_method_signature_filter, ms);
2283 mi_instance = TypeContainer.FindMembers (
2284 ptype, MemberTypes.Method,
2285 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2286 MethodSignature.inheritable_method_signature_filter,
2289 if (mi_instance.Count > 0){
2291 } else if (mi_static.Count > 0)
2296 if (mi != null && mi.Count > 0){
2297 parent_method = (MethodInfo) mi [0];
2298 string name = parent_method.DeclaringType.Name + "." +
2301 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2304 if ((ModFlags & Modifiers.NEW) == 0) {
2305 Type parent_ret = TypeManager.TypeToCoreType (
2306 parent_method.ReturnType);
2308 if (parent_ret != MemberType) {
2310 508, parent.MakeName (Name) + ": cannot " +
2311 "change return type when overriding " +
2312 "inherited member " + name);
2317 if ((ModFlags & Modifiers.NEW) != 0)
2318 WarningNotHiding (parent);
2320 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2321 Report.Error (115, Location,
2322 parent.MakeName (Name) +
2323 " no suitable methods found to override");
2326 } else if ((ModFlags & Modifiers.NEW) != 0)
2327 WarningNotHiding (parent);
2335 public override bool Define (TypeContainer parent)
2337 if (!DoDefine (parent))
2340 if (!CheckBase (parent))
2343 CallingConventions cc = GetCallingConvention (parent is Class);
2345 MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2346 ParameterInfo, cc, OptAttributes,
2347 ModFlags, flags, true);
2349 if (!MethodData.Define (parent))
2352 MethodBuilder = MethodData.MethodBuilder;
2355 // This is used to track the Entry Point,
2357 if (Name == "Main" &&
2358 ((ModFlags & Modifiers.STATIC) != 0) &&
2359 (RootContext.MainClass == null ||
2360 RootContext.MainClass == parent.TypeBuilder.FullName)){
2361 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2362 if (RootContext.EntryPoint == null) {
2363 RootContext.EntryPoint = MethodBuilder;
2364 RootContext.EntryPointLocation = Location;
2366 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2367 DuplicateEntryPoint (MethodBuilder, Location);
2370 Report28(MethodBuilder);
2379 public void Emit (TypeContainer parent)
2381 MethodData.Emit (parent, Block, this);
2385 public abstract class ConstructorInitializer {
2386 ArrayList argument_list;
2387 ConstructorInfo parent_constructor;
2388 Parameters parameters;
2391 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2394 this.argument_list = argument_list;
2395 this.parameters = parameters;
2399 public ArrayList Arguments {
2401 return argument_list;
2405 public bool Resolve (EmitContext ec)
2407 Expression parent_constructor_group;
2410 ec.CurrentBlock = new Block (null, true, parameters);
2412 if (argument_list != null){
2413 foreach (Argument a in argument_list){
2414 if (!a.Resolve (ec, loc))
2419 ec.CurrentBlock = null;
2421 if (this is ConstructorBaseInitializer) {
2422 if (ec.ContainerType.BaseType == null)
2425 t = ec.ContainerType.BaseType;
2426 if (ec.ContainerType.IsValueType) {
2427 Report.Error (522, loc,
2428 "structs cannot call base class constructors");
2432 t = ec.ContainerType;
2434 parent_constructor_group = Expression.MemberLookup (
2436 MemberTypes.Constructor,
2437 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2440 if (parent_constructor_group == null){
2441 Report.Error (1501, loc,
2442 "Can not find a constructor for this argument list");
2446 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2447 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2449 if (parent_constructor == null){
2450 Report.Error (1501, loc,
2451 "Can not find a constructor for this argument list");
2458 public void Emit (EmitContext ec)
2460 if (parent_constructor != null){
2462 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2464 Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2469 public class ConstructorBaseInitializer : ConstructorInitializer {
2470 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2471 base (argument_list, pars, l)
2476 public class ConstructorThisInitializer : ConstructorInitializer {
2477 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2478 base (argument_list, pars, l)
2483 public class Constructor : MethodCore {
2484 public ConstructorBuilder ConstructorBuilder;
2485 public ConstructorInitializer Initializer;
2486 new public Attributes OptAttributes;
2489 // Modifiers allowed for a constructor.
2491 public const int AllowedModifiers =
2493 Modifiers.PROTECTED |
2494 Modifiers.INTERNAL |
2501 // The spec claims that static is not permitted, but
2502 // my very own code has static constructors.
2504 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2505 : base (null, 0, AllowedModifiers, name, null, args, l)
2511 // Returns true if this is a default constructor
2513 public bool IsDefault ()
2515 if ((ModFlags & Modifiers.STATIC) != 0)
2516 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2517 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2520 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2521 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2522 (Initializer is ConstructorBaseInitializer) &&
2523 (Initializer.Arguments == null);
2527 // Creates the ConstructorBuilder
2529 public override bool Define (TypeContainer parent)
2531 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2532 MethodAttributes.SpecialName);
2534 // Check if arguments were correct.
2535 if (!DoDefineParameters (parent))
2538 if ((ModFlags & Modifiers.STATIC) != 0)
2539 ca |= MethodAttributes.Static;
2541 if (parent is Struct && ParameterTypes.Length == 0){
2544 "Structs can not contain explicit parameterless " +
2548 ca |= MethodAttributes.HideBySig;
2550 if ((ModFlags & Modifiers.PUBLIC) != 0)
2551 ca |= MethodAttributes.Public;
2552 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2553 if ((ModFlags & Modifiers.INTERNAL) != 0)
2554 ca |= MethodAttributes.FamORAssem;
2556 ca |= MethodAttributes.Family;
2557 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2558 ca |= MethodAttributes.Assembly;
2559 else if (IsDefault ())
2560 ca |= MethodAttributes.Public;
2562 ca |= MethodAttributes.Private;
2565 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2566 ca, GetCallingConvention (parent is Class), ParameterTypes);
2569 // HACK because System.Reflection.Emit is lame
2571 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2574 "Class `" +parent.Name+ "' already contains a definition with the " +
2575 "same return value and parameter types for constructor `" + Name
2586 public void Emit (TypeContainer parent)
2588 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2589 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2591 if ((ModFlags & Modifiers.STATIC) == 0){
2592 if (parent is Class && Initializer == null)
2593 Initializer = new ConstructorBaseInitializer (
2594 null, Parameters.EmptyReadOnlyParameters, parent.Location);
2598 // Spec mandates that Initializers will not have
2602 if (Initializer != null && !Initializer.Resolve (ec))
2604 ec.IsStatic = false;
2607 LabelParameters (ec, ParameterTypes, ConstructorBuilder);
2610 // Classes can have base initializers and instance field initializers.
2612 if (parent is Class){
2613 if ((ModFlags & Modifiers.STATIC) == 0)
2614 parent.EmitFieldInitializers (ec);
2616 if (Initializer != null)
2617 Initializer.Emit (ec);
2619 if ((ModFlags & Modifiers.STATIC) != 0)
2620 parent.EmitFieldInitializers (ec);
2622 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2624 // If this is a non-static `struct' constructor and doesn't have any
2625 // initializer, it must initialize all of the struct's fields.
2626 if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2627 (Initializer == null))
2628 Block.AddThisVariable (parent, Location);
2630 ec.EmitTopBlock (Block, ParameterInfo, Location);
2634 public class MethodData {
2636 // The return type of this method
2638 public readonly Type ReturnType;
2639 public readonly Type[] ParameterTypes;
2640 public readonly InternalParameters ParameterInfo;
2641 public readonly CallingConventions CallingConventions;
2642 public readonly Attributes OptAttributes;
2643 public readonly Location Location;
2646 // Are we implementing an interface ?
2648 public bool IsImplementing = false;
2653 protected MemberBase member;
2654 protected int modifiers;
2655 protected MethodAttributes flags;
2656 protected bool is_method;
2657 protected string accessor_name;
2658 ArrayList conditionals;
2660 MethodBuilder builder = null;
2661 public MethodBuilder MethodBuilder {
2667 public MethodData (MemberBase member, string name, Type return_type,
2668 Type [] parameter_types, InternalParameters parameters,
2669 CallingConventions cc, Attributes opt_attrs,
2670 int modifiers, MethodAttributes flags, bool is_method)
2672 this.member = member;
2673 this.accessor_name = name;
2674 this.ReturnType = return_type;
2675 this.ParameterTypes = parameter_types;
2676 this.ParameterInfo = parameters;
2677 this.CallingConventions = cc;
2678 this.OptAttributes = opt_attrs;
2679 this.modifiers = modifiers;
2681 this.is_method = is_method;
2682 this.Location = member.Location;
2683 this.conditionals = new ArrayList ();
2689 Attribute dllimport_attribute = null;
2690 string obsolete = null;
2691 bool obsolete_error = false;
2693 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2695 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2698 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2699 if (asec.Attributes == null)
2702 foreach (Attribute a in asec.Attributes) {
2703 if (a.Name == "Conditional") {
2704 if (!ApplyConditionalAttribute (a))
2706 } else if (a.Name == "Obsolete") {
2707 if (!ApplyObsoleteAttribute (a))
2709 } else if (a.Name.IndexOf ("DllImport") != -1) {
2711 a.Type = TypeManager.dllimport_type;
2712 Attribute.Error_AttributeNotValidForElement (a, Location);
2715 if (!ApplyDllImportAttribute (a))
2725 // Applies the `DllImport' attribute to the method.
2727 protected virtual bool ApplyDllImportAttribute (Attribute a)
2729 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2730 if ((modifiers & extern_static) != extern_static) {
2731 Report.Error (601, Location,
2732 "The DllImport attribute must be specified on a method " +
2733 "marked `static' and `extern'.");
2737 flags |= MethodAttributes.PinvokeImpl;
2738 dllimport_attribute = a;
2743 // Applies the `Obsolete' attribute to the method.
2745 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2747 if (obsolete != null) {
2748 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2752 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2753 return obsolete != null;
2757 // Applies the `Conditional' attribute to the method.
2759 protected virtual bool ApplyConditionalAttribute (Attribute a)
2761 // The Conditional attribute is only valid on methods.
2763 Attribute.Error_AttributeNotValidForElement (a, Location);
2767 string condition = a.Conditional_GetConditionName ();
2769 if (condition == null)
2772 if (ReturnType != TypeManager.void_type) {
2773 Report.Error (578, Location,
2774 "Conditional not valid on `" + member.Name + "' " +
2775 "because its return type is not void");
2779 if ((modifiers & Modifiers.OVERRIDE) != 0) {
2780 Report.Error (243, Location,
2781 "Conditional not valid on `" + member.Name + "' " +
2782 "because it is an override method");
2786 if (member.IsExplicitImpl) {
2787 Report.Error (577, Location,
2788 "Conditional not valid on `" + member.Name + "' " +
2789 "because it is an explicit interface implementation");
2793 if (IsImplementing) {
2794 Report.Error (623, Location,
2795 "Conditional not valid on `" + member.Name + "' " +
2796 "because it is an interface method");
2800 conditionals.Add (condition);
2806 // Checks whether this method should be ignored due to its Conditional attributes.
2808 bool ShouldIgnore (Location loc)
2810 // When we're overriding a virtual method, we implicitly inherit the
2811 // Conditional attributes from our parent.
2812 if (member.ParentMethod != null) {
2813 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2814 member.ParentMethod, loc);
2816 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2820 foreach (string condition in conditionals)
2821 if (RootContext.AllDefines [condition] == null)
2828 // Returns the TypeManager.MethodFlags for this method.
2829 // This emits an error 619 / warning 618 if the method is obsolete.
2830 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2832 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2834 TypeManager.MethodFlags flags = 0;
2836 if (obsolete != null) {
2837 if (obsolete_error) {
2838 Report.Error (619, loc, "Method `" + member.Name +
2839 "' is obsolete: `" + obsolete + "'");
2840 return TypeManager.MethodFlags.IsObsoleteError;
2842 Report.Warning (618, loc, "Method `" + member.Name +
2843 "' is obsolete: `" + obsolete + "'");
2845 flags |= TypeManager.MethodFlags.IsObsolete;
2848 if (ShouldIgnore (loc))
2849 flags |= TypeManager.MethodFlags.ShouldIgnore;
2854 public virtual bool Define (TypeContainer parent)
2856 MethodInfo implementing = null;
2857 string method_name, name, prefix;
2859 if (OptAttributes != null)
2860 if (!ApplyAttributes (OptAttributes, is_method))
2863 if (member.IsExplicitImpl)
2864 prefix = member.InterfaceType.FullName + ".";
2868 if (accessor_name != null)
2869 name = accessor_name + "_" + member.ShortName;
2871 name = member.ShortName;
2872 method_name = prefix + name;
2874 if (parent.Pending != null){
2875 if (member is Indexer)
2876 implementing = parent.Pending.IsInterfaceIndexer (
2877 member.InterfaceType, ReturnType, ParameterTypes);
2879 implementing = parent.Pending.IsInterfaceMethod (
2880 member.InterfaceType, name, ReturnType, ParameterTypes);
2882 if (member.InterfaceType != null && implementing == null){
2883 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
2890 // For implicit implementations, make sure we are public, for
2891 // explicit implementations, make sure we are private.
2893 if (implementing != null){
2895 // Setting null inside this block will trigger a more
2896 // verbose error reporting for missing interface implementations
2898 // The "candidate" function has been flagged already
2899 // but it wont get cleared
2901 if (!member.IsExplicitImpl){
2903 // We already catch different accessibility settings
2904 // so we just need to check that we are not private
2906 if ((modifiers & Modifiers.PRIVATE) != 0)
2907 implementing = null;
2910 // Static is not allowed
2912 if ((modifiers & Modifiers.STATIC) != 0)
2913 implementing = null;
2915 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
2916 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
2917 implementing = null;
2923 // If implementing is still valid, set flags
2925 if (implementing != null){
2927 // When implementing interface methods, set NewSlot.
2929 if (implementing.DeclaringType.IsInterface)
2930 flags |= MethodAttributes.NewSlot;
2933 MethodAttributes.Virtual |
2934 MethodAttributes.HideBySig;
2936 // Get the method name from the explicit interface.
2937 if (member.InterfaceType != null) {
2938 name = implementing.Name;
2939 method_name = prefix + name;
2942 IsImplementing = true;
2946 // Create the MethodBuilder for the method
2948 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2949 if ((modifiers & Modifiers.STATIC) == 0) {
2950 Report.Error (601, Location,
2951 "The DllImport attribute must be specified on " +
2952 "a method marked 'static' and 'extern'.");
2956 EmitContext ec = new EmitContext (
2957 parent, Location, null, ReturnType, modifiers);
2959 builder = dllimport_attribute.DefinePInvokeMethod (
2960 ec, parent.TypeBuilder, method_name, flags,
2961 ReturnType, ParameterTypes);
2963 builder = parent.TypeBuilder.DefineMethod (
2964 method_name, flags, CallingConventions,
2965 ReturnType, ParameterTypes);
2967 if (builder == null)
2970 if (IsImplementing) {
2972 // clear the pending implemntation flag
2974 if (member is Indexer) {
2975 parent.Pending.ImplementIndexer (
2976 member.InterfaceType, builder, ReturnType,
2977 ParameterTypes, true);
2979 parent.Pending.ImplementMethod (
2980 member.InterfaceType, name, ReturnType,
2981 ParameterTypes, member.IsExplicitImpl);
2983 if (member.IsExplicitImpl)
2984 parent.TypeBuilder.DefineMethodOverride (
2985 builder, implementing);
2988 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
2989 Report.Error (111, Location,
2990 "Class `" + parent.Name +
2991 "' already contains a definition with the " +
2992 "same return value and parameter types as the " +
2993 "'get' method of property `" + member.Name + "'");
2997 TypeManager.AddMethod (builder, this);
3005 public virtual void Emit (TypeContainer parent, Block block, object kind)
3010 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3011 ig = builder.GetILGenerator ();
3015 ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3017 if (OptAttributes != null)
3018 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
3020 if (member is MethodCore)
3021 ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder);
3024 // abstract or extern methods have no bodies
3026 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3031 // abstract or extern methods have no bodies.
3033 if ((modifiers & Modifiers.ABSTRACT) != 0)
3035 500, Location, "Abstract method `" +
3036 TypeManager.CSharpSignature (builder) +
3037 "' can not have a body");
3039 if ((modifiers & Modifiers.EXTERN) != 0)
3041 179, Location, "External method `" +
3042 TypeManager.CSharpSignature (builder) +
3043 "' can not have a body");
3049 // Methods must have a body unless they're extern or abstract
3051 if (block == null) {
3053 501, Location, "Method `" +
3054 TypeManager.CSharpSignature (builder) +
3055 "' must declare a body since it is not marked " +
3056 "abstract or extern");
3061 // Handle destructors specially
3063 // FIXME: This code generates buggy code
3065 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3066 EmitDestructor (ec, block);
3068 ISymbolWriter sw = CodeGen.SymbolWriter;
3070 if ((sw != null) && !Location.IsNull (Location) &&
3071 !Location.IsNull (block.EndLocation)) {
3072 Location end = block.EndLocation;
3073 MethodToken token = MethodBuilder.GetToken ();
3074 sw.OpenMethod (new SymbolToken (token.Token));
3075 // Avoid error if we don't support debugging for the platform
3077 sw.SetMethodSourceRange (Location.SymbolDocument,
3081 } catch (Exception) {
3084 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3088 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3092 void EmitDestructor (EmitContext ec, Block block)
3094 ILGenerator ig = ec.ig;
3096 Label finish = ig.DefineLabel ();
3097 bool old_in_try = ec.InTry;
3099 ig.BeginExceptionBlock ();
3101 ec.ReturnLabel = finish;
3102 ec.HasReturnLabel = true;
3103 ec.EmitTopBlock (block, null, Location);
3104 ec.InTry = old_in_try;
3106 // ig.MarkLabel (finish);
3107 bool old_in_finally = ec.InFinally;
3108 ec.InFinally = true;
3109 ig.BeginFinallyBlock ();
3111 if (ec.ContainerType.BaseType != null) {
3112 Expression member_lookup = Expression.MemberLookup (
3113 ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
3114 MemberTypes.Method, Expression.AllBindingFlags, Location);
3116 if (member_lookup != null){
3117 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3119 ig.Emit (OpCodes.Ldarg_0);
3120 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3123 ec.InFinally = old_in_finally;
3125 ig.EndExceptionBlock ();
3126 //ig.MarkLabel (ec.ReturnLabel);
3127 ig.Emit (OpCodes.Ret);
3131 abstract public class MemberBase : MemberCore {
3132 public Expression Type;
3133 public readonly Attributes OptAttributes;
3135 protected MethodAttributes flags;
3138 // The "short" name of this property / indexer / event. This is the
3139 // name without the explicit interface.
3141 public string ShortName;
3144 // The type of this property / indexer / event
3146 public Type MemberType;
3149 // If true, this is an explicit interface implementation
3151 public bool IsExplicitImpl = false;
3154 // The name of the interface we are explicitly implementing
3156 public string ExplicitInterfaceName = null;
3159 // If true, the interface type we are explicitly implementing
3161 public Type InterfaceType = null;
3164 // The method we're overriding if this is an override method.
3166 protected MethodInfo parent_method = null;
3167 public MethodInfo ParentMethod {
3169 return parent_method;
3174 // The constructor is only exposed to our children
3176 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3177 Attributes attrs, Location loc)
3181 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
3182 OptAttributes = attrs;
3185 protected virtual bool CheckBase (TypeContainer parent)
3190 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3194 foreach (Type partype in parameters){
3195 if (partype.IsPointer && !UnsafeOK (parent))
3198 if (parent.AsAccessible (partype, ModFlags))
3201 if (this is Indexer)
3202 Report.Error (55, Location,
3203 "Inconsistent accessibility: parameter type `" +
3204 TypeManager.CSharpName (partype) + "' is less " +
3205 "accessible than indexer `" + Name + "'");
3207 Report.Error (51, Location,
3208 "Inconsistent accessibility: parameter type `" +
3209 TypeManager.CSharpName (partype) + "' is less " +
3210 "accessible than method `" + Name + "'");
3217 protected virtual bool DoDefine (TypeContainer parent)
3222 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3225 flags = Modifiers.MethodAttr (ModFlags);
3227 // Lookup Type, verify validity
3228 MemberType = parent.ResolveType (Type, false, Location);
3229 if (MemberType == null)
3232 // verify accessibility
3233 if (!parent.AsAccessible (MemberType, ModFlags)) {
3234 if (this is Property)
3235 Report.Error (53, Location,
3236 "Inconsistent accessibility: property type `" +
3237 TypeManager.CSharpName (MemberType) + "' is less " +
3238 "accessible than property `" + Name + "'");
3239 else if (this is Indexer)
3240 Report.Error (54, Location,
3241 "Inconsistent accessibility: indexer return type `" +
3242 TypeManager.CSharpName (MemberType) + "' is less " +
3243 "accessible than indexer `" + Name + "'");
3244 else if (this is Method)
3245 Report.Error (50, Location,
3246 "Inconsistent accessibility: return type `" +
3247 TypeManager.CSharpName (MemberType) + "' is less " +
3248 "accessible than method `" + Name + "'");
3250 Report.Error (52, Location,
3251 "Inconsistent accessibility: field type `" +
3252 TypeManager.CSharpName (MemberType) + "' is less " +
3253 "accessible than field `" + Name + "'");
3257 if (MemberType.IsPointer && !UnsafeOK (parent))
3261 // Check for explicit interface implementation
3263 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
3264 int pos = Name.LastIndexOf (".");
3266 ExplicitInterfaceName = Name.Substring (0, pos);
3267 ShortName = Name.Substring (pos + 1);
3271 if (ExplicitInterfaceName != null) {
3272 InterfaceType = RootContext.LookupType (
3273 parent, ExplicitInterfaceName, false, Location);
3274 if (InterfaceType == null)
3277 // Compute the full name that we need to export.
3278 Name = InterfaceType.FullName + "." + ShortName;
3280 if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
3283 IsExplicitImpl = true;
3285 IsExplicitImpl = false;
3292 // Fields and Events both generate FieldBuilders, we use this to share
3293 // their common bits. This is also used to flag usage of the field
3295 abstract public class FieldBase : MemberBase {
3296 public FieldBuilder FieldBuilder;
3297 public Status status;
3300 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3303 // The constructor is only exposed to our children
3305 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3306 object init, Attributes attrs, Location loc)
3307 : base (type, mod, allowed_mod, name, attrs, loc)
3313 // Whether this field has an initializer.
3315 public bool HasInitializer {
3317 return init != null;
3322 readonly Object init;
3323 Expression init_expr;
3324 bool init_expr_initialized = false;
3327 // Resolves and returns the field initializer.
3329 public Expression GetInitializerExpression (EmitContext ec)
3331 if (init_expr_initialized)
3335 if (init is Expression)
3336 e = (Expression) init;
3338 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3340 ec.IsFieldInitializer = true;
3341 e = e.DoResolve (ec);
3342 ec.IsFieldInitializer = false;
3345 init_expr_initialized = true;
3352 // The Field class is used to represents class/struct fields during parsing.
3354 public class Field : FieldBase {
3356 // Modifiers allowed in a class declaration
3358 const int AllowedModifiers =
3361 Modifiers.PROTECTED |
3362 Modifiers.INTERNAL |
3365 Modifiers.VOLATILE |
3369 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3370 Attributes attrs, Location loc)
3371 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3375 public override bool Define (TypeContainer parent)
3377 Type t = parent.ResolveType (Type, false, Location);
3382 if (!parent.AsAccessible (t, ModFlags)) {
3383 Report.Error (52, Location,
3384 "Inconsistent accessibility: field type `" +
3385 TypeManager.CSharpName (t) + "' is less " +
3386 "accessible than field `" + Name + "'");
3390 if (t.IsPointer && !UnsafeOK (parent))
3393 if (RootContext.WarningLevel > 1){
3394 Type ptype = parent.TypeBuilder.BaseType;
3396 // ptype is only null for System.Object while compiling corlib.
3398 TypeContainer.FindMembers (
3399 ptype, MemberTypes.Method,
3400 BindingFlags.Public |
3401 BindingFlags.Static | BindingFlags.Instance,
3402 System.Type.FilterName, Name);
3406 if ((ModFlags & Modifiers.VOLATILE) != 0){
3408 if (TypeManager.IsEnumType (t))
3409 t = TypeManager.EnumToUnderlying (t);
3411 if (!((t == TypeManager.bool_type) ||
3412 (t == TypeManager.sbyte_type) ||
3413 (t == TypeManager.byte_type) ||
3414 (t == TypeManager.short_type) ||
3415 (t == TypeManager.ushort_type) ||
3416 (t == TypeManager.int32_type) ||
3417 (t == TypeManager.uint32_type) ||
3418 (t == TypeManager.char_type) ||
3419 (t == TypeManager.float_type))){
3421 677, Location, parent.MakeName (Name) +
3422 " A volatile field can not be of type `" +
3423 TypeManager.CSharpName (t) + "'");
3429 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3431 if (parent is Struct &&
3432 ((fa & FieldAttributes.Static) == 0) &&
3433 t == parent.TypeBuilder &&
3434 !TypeManager.IsBuiltinType (t)){
3435 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name +
3436 "' causes a cycle in the structure layout");
3439 FieldBuilder = parent.TypeBuilder.DefineField (
3440 Name, t, Modifiers.FieldAttr (ModFlags));
3442 TypeManager.RegisterFieldBase (FieldBuilder, this);
3446 public void Emit (TypeContainer tc)
3448 EmitContext ec = new EmitContext (tc, Location, null,
3449 FieldBuilder.FieldType, ModFlags);
3451 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
3456 // `set' and `get' accessors are represented with an Accessor.
3458 public class Accessor {
3460 // Null if the accessor is empty, or a Block if not
3463 public Attributes OptAttributes;
3465 public Accessor (Block b, Attributes attrs)
3468 OptAttributes = attrs;
3473 // Properties and Indexers both generate PropertyBuilders, we use this to share
3474 // their common bits.
3476 abstract public class PropertyBase : MethodCore {
3477 public Accessor Get, Set;
3478 public PropertyBuilder PropertyBuilder;
3479 public MethodBuilder GetBuilder, SetBuilder;
3480 public MethodData GetData, SetData;
3482 protected EmitContext ec;
3484 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3485 Parameters parameters, Accessor get_block, Accessor set_block,
3486 Attributes attrs, Location loc)
3487 : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3493 protected override bool DoDefine (TypeContainer parent)
3495 if (!base.DoDefine (parent))
3498 ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3504 // Checks our base implementation if any
3506 protected override bool CheckBase (TypeContainer parent)
3508 // Check whether arguments were correct.
3509 if (!DoDefineParameters (parent))
3516 MethodSignature ms, base_ms;
3517 if (this is Indexer) {
3518 string name, base_name;
3520 report_name = "this";
3521 name = TypeManager.IndexerPropertyName (parent.TypeBuilder);
3522 ms = new MethodSignature (name, null, ParameterTypes);
3523 base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType);
3524 base_ms = new MethodSignature (base_name, null, ParameterTypes);
3527 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
3530 MemberList props_this;
3532 props_this = TypeContainer.FindMembers (
3533 parent.TypeBuilder, MemberTypes.Property,
3534 BindingFlags.NonPublic | BindingFlags.Public |
3535 BindingFlags.Static | BindingFlags.Instance |
3536 BindingFlags.DeclaredOnly,
3537 MethodSignature.method_signature_filter, ms);
3539 if (props_this.Count > 0) {
3540 Report.Error (111, Location, "Class `" + parent.Name + "' " +
3541 "already defines a member called `" + report_name + "' " +
3542 "with the same parameter types");
3547 // Find properties with the same name on the base class
3550 MemberList props_static = TypeContainer.FindMembers (
3551 parent.TypeBuilder.BaseType, MemberTypes.Property,
3552 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3553 MethodSignature.inheritable_property_signature_filter, base_ms);
3555 MemberList props_instance = TypeContainer.FindMembers (
3556 parent.TypeBuilder.BaseType, MemberTypes.Property,
3557 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3558 MethodSignature.inheritable_property_signature_filter,
3562 // Find if we have anything
3564 if (props_static.Count > 0)
3565 props = props_static;
3566 else if (props_instance.Count > 0)
3567 props = props_instance;
3572 // If we have something on the base.
3573 if (props != null && props.Count > 0){
3574 PropertyInfo pi = (PropertyInfo) props [0];
3576 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
3577 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
3579 MethodInfo reference = inherited_get == null ?
3580 inherited_set : inherited_get;
3582 if (reference != null) {
3583 string name = reference.DeclaringType.Name + "." + report_name;
3585 if (!CheckMethodAgainstBase (parent, flags, reference, name))
3589 if (((ModFlags & Modifiers.NEW) == 0) && (pi.PropertyType != MemberType)) {
3590 Report.Error (508, parent.MakeName (Name) + ": cannot " +
3591 "change return type when overriding inherited " +
3592 "member `" + pi.DeclaringType + "." + pi.Name + "'");
3596 if ((ModFlags & Modifiers.NEW) != 0)
3597 WarningNotHiding (parent);
3599 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3600 if (this is Indexer)
3601 Report.Error (115, Location,
3602 parent.MakeName (Name) +
3603 " no suitable indexers found to override");
3605 Report.Error (115, Location,
3606 parent.MakeName (Name) +
3607 " no suitable properties found to override");
3614 public void Emit (TypeContainer tc)
3617 // The PropertyBuilder can be null for explicit implementations, in that
3618 // case, we do not actually emit the ".property", so there is nowhere to
3619 // put the attribute
3621 if (PropertyBuilder != null)
3622 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3624 if (GetData != null)
3625 GetData.Emit (tc, Get.Block, Get);
3627 if (SetData != null)
3628 SetData.Emit (tc, Set.Block, Set);
3632 public class Property : PropertyBase {
3633 const int AllowedModifiers =
3636 Modifiers.PROTECTED |
3637 Modifiers.INTERNAL |
3641 Modifiers.OVERRIDE |
3642 Modifiers.ABSTRACT |
3647 string set_parameter_name;
3649 public Property (Expression type, string name, int mod_flags,
3650 Accessor get_block, Accessor set_block,
3651 Attributes attrs, Location loc, string set_name)
3652 : base (type, name, mod_flags, AllowedModifiers,
3653 Parameters.EmptyReadOnlyParameters,
3654 get_block, set_block, attrs, loc)
3656 set_parameter_name = set_name;
3659 public Property (Expression type, string name, int mod_flags,
3660 Accessor get_block, Accessor set_block,
3661 Attributes attrs, Location loc)
3662 : base (type, name, mod_flags, AllowedModifiers,
3663 Parameters.EmptyReadOnlyParameters,
3664 get_block, set_block, attrs, loc)
3666 set_parameter_name = "Value";
3669 public override bool Define (TypeContainer parent)
3671 if (!DoDefine (parent))
3674 if (!CheckBase (parent))
3677 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3680 Type [] parameters = TypeManager.NoTypes;
3682 InternalParameters ip = new InternalParameters (
3683 parent, Parameters.EmptyReadOnlyParameters);
3685 GetData = new MethodData (this, "get", MemberType,
3686 parameters, ip, CallingConventions.Standard,
3687 Get.OptAttributes, ModFlags, flags, false);
3689 if (!GetData.Define (parent))
3692 GetBuilder = GetData.MethodBuilder;
3696 Type [] parameters = new Type [1];
3697 parameters [0] = MemberType;
3699 Parameter [] parms = new Parameter [1];
3700 parms [0] = new Parameter (Type, /* was "value" */ set_parameter_name,
3701 Parameter.Modifier.NONE, null);
3702 InternalParameters ip = new InternalParameters (
3703 parent, new Parameters (parms, null, Location));
3705 SetData = new MethodData (this, "set", TypeManager.void_type,
3706 parameters, ip, CallingConventions.Standard,
3707 Set.OptAttributes, ModFlags, flags, false);
3709 if (!SetData.Define (parent))
3712 SetBuilder = SetData.MethodBuilder;
3713 SetBuilder.DefineParameter (1, ParameterAttributes.None,
3714 /* was "value" */ set_parameter_name);
3717 // FIXME - PropertyAttributes.HasDefault ?
3719 PropertyAttributes prop_attr =
3720 PropertyAttributes.RTSpecialName |
3721 PropertyAttributes.SpecialName;
3723 if (!IsExplicitImpl){
3724 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3725 Name, prop_attr, MemberType, null);
3728 PropertyBuilder.SetGetMethod (GetBuilder);
3731 PropertyBuilder.SetSetMethod (SetBuilder);
3734 // HACK for the reasons exposed above
3736 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3739 "Class `" + parent.Name +
3740 "' already contains a definition for the property `" +
3750 /// Gigantic workaround for lameness in SRE follows :
3751 /// This class derives from EventInfo and attempts to basically
3752 /// wrap around the EventBuilder so that FindMembers can quickly
3753 /// return this in it search for members
3755 public class MyEventBuilder : EventInfo {
3758 // We use this to "point" to our Builder which is
3759 // not really a MemberInfo
3761 EventBuilder MyBuilder;
3764 // We "catch" and wrap these methods
3766 MethodInfo raise, remove, add;
3768 EventAttributes attributes;
3769 Type declaring_type, reflected_type, event_type;
3772 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3774 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3776 // And now store the values in our own fields.
3778 declaring_type = type_builder;
3780 reflected_type = type_builder;
3782 attributes = event_attr;
3784 this.event_type = event_type;
3788 // Methods that you have to override. Note that you only need
3789 // to "implement" the variants that take the argument (those are
3790 // the "abstract" methods, the others (GetAddMethod()) are
3793 public override MethodInfo GetAddMethod (bool nonPublic)
3798 public override MethodInfo GetRemoveMethod (bool nonPublic)
3803 public override MethodInfo GetRaiseMethod (bool nonPublic)
3809 // These methods make "MyEventInfo" look like a Builder
3811 public void SetRaiseMethod (MethodBuilder raiseMethod)
3813 raise = raiseMethod;
3814 MyBuilder.SetRaiseMethod (raiseMethod);
3817 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3819 remove = removeMethod;
3820 MyBuilder.SetRemoveOnMethod (removeMethod);
3823 public void SetAddOnMethod (MethodBuilder addMethod)
3826 MyBuilder.SetAddOnMethod (addMethod);
3829 public void SetCustomAttribute (CustomAttributeBuilder cb)
3831 MyBuilder.SetCustomAttribute (cb);
3834 public override object [] GetCustomAttributes (bool inherit)
3836 // FIXME : There's nothing which can be seemingly done here because
3837 // we have no way of getting at the custom attribute objects of the
3842 public override object [] GetCustomAttributes (Type t, bool inherit)
3844 // FIXME : Same here !
3848 public override bool IsDefined (Type t, bool b)
3853 public override EventAttributes Attributes {
3859 public override string Name {
3865 public override Type DeclaringType {
3867 return declaring_type;
3871 public override Type ReflectedType {
3873 return reflected_type;
3877 public Type EventType {
3884 public class Event : FieldBase {
3885 const int AllowedModifiers =
3888 Modifiers.PROTECTED |
3889 Modifiers.INTERNAL |
3894 Modifiers.OVERRIDE |
3898 public readonly Accessor Add;
3899 public readonly Accessor Remove;
3900 public MyEventBuilder EventBuilder;
3902 MethodBuilder AddBuilder, RemoveBuilder;
3903 MethodData AddData, RemoveData;
3905 public Event (Expression type, string name, Object init, int mod, Accessor add,
3906 Accessor remove, Attributes attrs, Location loc)
3907 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
3913 public override bool Define (TypeContainer parent)
3915 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3917 if (!DoDefine (parent))
3920 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
3921 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3922 "' : event must be of a delegate type");
3926 Type [] parameter_types = new Type [1];
3927 parameter_types [0] = MemberType;
3929 Parameter [] parms = new Parameter [1];
3930 parms [0] = new Parameter (Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
3931 InternalParameters ip = new InternalParameters (
3932 parent, new Parameters (parms, null, Location));
3934 if (!CheckBase (parent))
3938 // Now define the accessors
3940 AddData = new MethodData (this, "add", TypeManager.void_type,
3941 parameter_types, ip, CallingConventions.Standard,
3942 (Add != null) ? Add.OptAttributes : null,
3943 ModFlags, flags, false);
3945 if (!AddData.Define (parent))
3948 AddBuilder = AddData.MethodBuilder;
3949 AddBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
3951 RemoveData = new MethodData (this, "remove", TypeManager.void_type,
3952 parameter_types, ip, CallingConventions.Standard,
3953 (Remove != null) ? Remove.OptAttributes : null,
3954 ModFlags, flags, false);
3956 if (!RemoveData.Define (parent))
3959 RemoveBuilder = RemoveData.MethodBuilder;
3960 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
3962 if (!IsExplicitImpl){
3963 EventBuilder = new MyEventBuilder (
3964 parent.TypeBuilder, Name, e_attr, MemberType);
3966 if (Add == null && Remove == null) {
3967 FieldBuilder = parent.TypeBuilder.DefineField (
3969 FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
3970 TypeManager.RegisterPrivateFieldOfEvent (
3971 (EventInfo) EventBuilder, FieldBuilder);
3972 TypeManager.RegisterFieldBase (FieldBuilder, this);
3975 EventBuilder.SetAddOnMethod (AddBuilder);
3976 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3978 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3979 Report.Error (111, Location,
3980 "Class `" + parent.Name +
3981 "' already contains a definition for the event `" +
3990 void EmitDefaultMethod (EmitContext ec, bool is_add)
3992 ILGenerator ig = ec.ig;
3993 MethodInfo method = null;
3996 method = TypeManager.delegate_combine_delegate_delegate;
3998 method = TypeManager.delegate_remove_delegate_delegate;
4000 if ((ModFlags & Modifiers.STATIC) != 0) {
4001 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4002 ig.Emit (OpCodes.Ldarg_0);
4003 ig.Emit (OpCodes.Call, method);
4004 ig.Emit (OpCodes.Castclass, MemberType);
4005 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4007 ig.Emit (OpCodes.Ldarg_0);
4008 ig.Emit (OpCodes.Ldarg_0);
4009 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4010 ig.Emit (OpCodes.Ldarg_1);
4011 ig.Emit (OpCodes.Call, method);
4012 ig.Emit (OpCodes.Castclass, MemberType);
4013 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4015 ig.Emit (OpCodes.Ret);
4018 public void Emit (TypeContainer tc)
4022 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4023 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
4026 AddData.Emit (tc, Add.Block, Add);
4028 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4029 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4030 EmitDefaultMethod (ec, true);
4034 RemoveData.Emit (tc, Remove.Block, Remove);
4036 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4037 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4038 EmitDefaultMethod (ec, false);
4045 // FIXME: This does not handle:
4047 // int INTERFACENAME [ args ]
4052 // int this [ args ]
4054 public class Indexer : PropertyBase {
4056 const int AllowedModifiers =
4059 Modifiers.PROTECTED |
4060 Modifiers.INTERNAL |
4064 Modifiers.OVERRIDE |
4069 public string IndexerName;
4070 public string InterfaceIndexerName;
4073 // Are we implementing an interface ?
4075 bool IsImplementing = false;
4077 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4078 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4079 : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4082 ExplicitInterfaceName = int_type;
4085 public override bool Define (TypeContainer parent)
4087 PropertyAttributes prop_attr =
4088 PropertyAttributes.RTSpecialName |
4089 PropertyAttributes.SpecialName;
4091 if (!DoDefine (parent))
4094 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4095 if (IndexerName == null)
4096 IndexerName = "Item";
4097 else if (IsExplicitImpl)
4098 Report.Error (592, Location,
4099 "Attribute 'IndexerName' is not valid on this declaration " +
4100 "type. It is valid on `property' declarations only.");
4102 ShortName = IndexerName;
4103 if (IsExplicitImpl) {
4104 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4105 Name = InterfaceType.FullName + "." + IndexerName;
4107 InterfaceIndexerName = IndexerName;
4111 if (!CheckBase (parent))
4115 InternalParameters ip = new InternalParameters (parent, Parameters);
4117 GetData = new MethodData (this, "get", MemberType,
4118 ParameterTypes, ip, CallingConventions.Standard,
4119 Get.OptAttributes, ModFlags, flags, false);
4121 if (!GetData.Define (parent))
4124 GetBuilder = GetData.MethodBuilder;
4128 int top = ParameterTypes.Length;
4129 Type [] set_pars = new Type [top + 1];
4130 ParameterTypes.CopyTo (set_pars, 0);
4131 set_pars [top] = MemberType;
4133 Parameter [] fixed_parms = Parameters.FixedParameters;
4135 if (fixed_parms == null){
4136 throw new Exception ("We currently do not support only array arguments in an indexer");
4137 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4138 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4140 // Here is the problem: the `value' parameter has
4141 // to come *after* the array parameter in the declaration
4143 // X (object [] x, Type value)
4146 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4147 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4151 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4154 fixed_parms.CopyTo (tmp, 0);
4155 tmp [fixed_parms.Length] = new Parameter (
4156 Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4158 Parameters set_formal_params = new Parameters (tmp, null, Location);
4160 InternalParameters ip = new InternalParameters (parent, set_formal_params);
4162 SetData = new MethodData (this, "set", TypeManager.void_type,
4163 set_pars, ip, CallingConventions.Standard,
4164 Set.OptAttributes, ModFlags, flags, false);
4166 if (!SetData.Define (parent))
4169 SetBuilder = SetData.MethodBuilder;
4173 // Now name the parameters
4175 Parameter [] p = Parameters.FixedParameters;
4179 for (i = 0; i < p.Length; ++i) {
4181 GetBuilder.DefineParameter (
4182 i + 1, p [i].Attributes, p [i].Name);
4185 SetBuilder.DefineParameter (
4186 i + 1, p [i].Attributes, p [i].Name);
4191 SetBuilder.DefineParameter (
4192 i + 1, ParameterAttributes.None, /* was "value" */ this.Name);
4194 if (i != ParameterTypes.Length) {
4195 Parameter array_param = Parameters.ArrayParameter;
4196 SetBuilder.DefineParameter (
4197 i + 1, array_param.Attributes, array_param.Name);
4201 if (GetData != null)
4202 IsImplementing = GetData.IsImplementing;
4203 else if (SetData != null)
4204 IsImplementing = SetData.IsImplementing;
4207 // Define the PropertyBuilder if one of the following conditions are met:
4208 // a) we're not implementing an interface indexer.
4209 // b) the indexer has a different IndexerName and this is no
4210 // explicit interface implementation.
4212 if (!IsExplicitImpl) {
4213 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4214 IndexerName, prop_attr, MemberType, ParameterTypes);
4216 if (GetData != null)
4217 PropertyBuilder.SetGetMethod (GetBuilder);
4219 if (SetData != null)
4220 PropertyBuilder.SetSetMethod (SetBuilder);
4222 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4230 public class Operator : MemberCore {
4232 const int AllowedModifiers =
4238 const int RequiredModifiers =
4242 public enum OpType : byte {
4252 // Unary and Binary operators
4275 // Implicit and Explicit
4280 public readonly OpType OperatorType;
4281 public readonly Expression ReturnType;
4282 public readonly Expression FirstArgType, SecondArgType;
4283 public readonly string FirstArgName, SecondArgName;
4284 public readonly Block Block;
4285 public Attributes OptAttributes;
4286 public MethodBuilder OperatorMethodBuilder;
4288 public string MethodName;
4289 public Method OperatorMethod;
4291 public Operator (OpType type, Expression ret_type, int flags,
4292 Expression arg1type, string arg1name,
4293 Expression arg2type, string arg2name,
4294 Block block, Attributes attrs, Location loc)
4297 OperatorType = type;
4298 ReturnType = ret_type;
4299 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4300 FirstArgType = arg1type;
4301 FirstArgName = arg1name;
4302 SecondArgType = arg2type;
4303 SecondArgName = arg2name;
4305 OptAttributes = attrs;
4308 string Prototype (TypeContainer parent)
4310 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4311 SecondArgType + ")";
4314 public override bool Define (TypeContainer parent)
4317 MethodName = "op_" + OperatorType;
4319 if (SecondArgType != null)
4322 Parameter [] param_list = new Parameter [length];
4324 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4327 "User defined operators `" +
4328 Prototype (parent) +
4329 "' must be declared static and public");
4333 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4334 Parameter.Modifier.NONE, null);
4335 if (SecondArgType != null)
4336 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4337 Parameter.Modifier.NONE, null);
4339 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4340 new Parameters (param_list, null, Location),
4341 OptAttributes, Mono.CSharp.Location.Null);
4343 OperatorMethod.IsOperator = true;
4344 OperatorMethod.Define (parent);
4346 if (OperatorMethod.MethodBuilder == null)
4349 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4351 Type [] param_types = OperatorMethod.ParameterTypes;
4352 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4353 Type return_type = OperatorMethod.GetReturnType ();
4354 Type first_arg_type = param_types [0];
4356 // Rules for conversion operators
4358 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4359 if (first_arg_type == return_type && first_arg_type == declaring_type){
4362 "User-defined conversion cannot take an object of the " +
4363 "enclosing type and convert to an object of the enclosing" +
4368 if (first_arg_type != declaring_type && return_type != declaring_type){
4371 "User-defined conversion must convert to or from the " +
4376 if (first_arg_type == TypeManager.object_type ||
4377 return_type == TypeManager.object_type){
4380 "User-defined conversion cannot convert to or from " +
4385 if (first_arg_type.IsInterface || return_type.IsInterface){
4388 "User-defined conversion cannot convert to or from an " +
4393 if (first_arg_type.IsSubclassOf (return_type) ||
4394 return_type.IsSubclassOf (first_arg_type)){
4397 "User-defined conversion cannot convert between types " +
4398 "that derive from each other");
4401 } else if (SecondArgType == null) {
4402 // Checks for Unary operators
4404 if (first_arg_type != declaring_type){
4407 "The parameter of a unary operator must be the " +
4412 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4413 if (return_type != declaring_type){
4416 "The parameter and return type for ++ and -- " +
4417 "must be the containing type");
4423 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4424 if (return_type != TypeManager.bool_type){
4427 "The return type of operator True or False " +
4434 // Checks for Binary operators
4436 if (first_arg_type != declaring_type &&
4437 param_types [1] != declaring_type){
4440 "One of the parameters of a binary operator must " +
4441 "be the containing type");
4449 public void Emit (TypeContainer parent)
4451 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4452 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4455 // abstract or extern methods have no bodies
4457 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4460 OperatorMethod.Block = Block;
4461 OperatorMethod.Emit (parent);
4464 public static string GetName (OpType ot)
4467 case OpType.LogicalNot:
4469 case OpType.OnesComplement:
4471 case OpType.Increment:
4473 case OpType.Decrement:
4479 case OpType.Addition:
4481 case OpType.Subtraction:
4483 case OpType.UnaryPlus:
4485 case OpType.UnaryNegation:
4487 case OpType.Multiply:
4489 case OpType.Division:
4491 case OpType.Modulus:
4493 case OpType.BitwiseAnd:
4495 case OpType.BitwiseOr:
4497 case OpType.ExclusiveOr:
4499 case OpType.LeftShift:
4501 case OpType.RightShift:
4503 case OpType.Equality:
4505 case OpType.Inequality:
4507 case OpType.GreaterThan:
4509 case OpType.LessThan:
4511 case OpType.GreaterThanOrEqual:
4513 case OpType.LessThanOrEqual:
4515 case OpType.Implicit:
4517 case OpType.Explicit:
4523 public override string ToString ()
4525 Type return_type = OperatorMethod.GetReturnType();
4526 Type [] param_types = OperatorMethod.ParameterTypes;
4528 if (SecondArgType == null)
4529 return String.Format (
4530 "{0} operator {1}({2})",
4531 TypeManager.CSharpName (return_type),
4532 GetName (OperatorType),
4535 return String.Format (
4536 "{0} operator {1}({2}, {3})",
4537 TypeManager.CSharpName (return_type),
4538 GetName (OperatorType),
4539 param_types [0], param_types [1]);
4544 // This is used to compare method signatures
4546 struct MethodSignature {
4548 public Type RetType;
4549 public Type [] Parameters;
4552 /// This delegate is used to extract methods which have the
4553 /// same signature as the argument
4555 public static MemberFilter method_signature_filter;
4558 /// This delegate is used to extract inheritable methods which
4559 /// have the same signature as the argument. By inheritable,
4560 /// this means that we have permissions to override the method
4561 /// from the current assembly and class
4563 public static MemberFilter inheritable_method_signature_filter;
4566 /// This delegate is used to extract inheritable methods which
4567 /// have the same signature as the argument. By inheritable,
4568 /// this means that we have permissions to override the method
4569 /// from the current assembly and class
4571 public static MemberFilter inheritable_property_signature_filter;
4573 static MethodSignature ()
4575 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4576 inheritable_method_signature_filter = new MemberFilter (
4577 InheritableMemberSignatureCompare);
4578 inheritable_property_signature_filter = new MemberFilter (
4579 InheritablePropertySignatureCompare);
4582 public MethodSignature (string name, Type ret_type, Type [] parameters)
4587 if (parameters == null)
4588 Parameters = TypeManager.NoTypes;
4590 Parameters = parameters;
4593 public override int GetHashCode ()
4595 return Name.GetHashCode ();
4598 public override bool Equals (Object o)
4600 MethodSignature other = (MethodSignature) o;
4602 if (other.Name != Name)
4605 if (other.RetType != RetType)
4608 if (Parameters == null){
4609 if (other.Parameters == null)
4614 if (other.Parameters == null)
4617 int c = Parameters.Length;
4618 if (other.Parameters.Length != c)
4621 for (int i = 0; i < c; i++)
4622 if (other.Parameters [i] != Parameters [i])
4628 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4630 MethodSignature sig = (MethodSignature) filter_criteria;
4632 if (m.Name != sig.Name)
4636 MethodInfo mi = m as MethodInfo;
4637 PropertyInfo pi = m as PropertyInfo;
4640 ReturnType = mi.ReturnType;
4641 else if (pi != null)
4642 ReturnType = pi.PropertyType;
4647 // we use sig.RetType == null to mean `do not check the
4648 // method return value.
4650 if (sig.RetType != null)
4651 if (ReturnType != sig.RetType)
4656 args = TypeManager.GetArgumentTypes (mi);
4658 args = TypeManager.GetArgumentTypes (pi);
4659 Type [] sigp = sig.Parameters;
4661 if (args.Length != sigp.Length)
4664 for (int i = args.Length; i > 0; ){
4666 if (args [i] != sigp [i])
4673 // This filter should be used when we are requesting methods that
4674 // we want to override.
4676 // This makes a number of assumptions, for example
4677 // that the methods being extracted are of a parent
4678 // class (this means we know implicitly that we are
4679 // being called to find out about members by a derived
4682 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4684 if (MemberSignatureCompare (m, filter_criteria)){
4685 MethodInfo mi = (MethodInfo) m;
4686 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4688 // If only accessible to the current class.
4689 if (prot == MethodAttributes.Private)
4692 // If only accessible to the defining assembly or
4693 if (prot == MethodAttributes.FamANDAssem ||
4694 prot == MethodAttributes.Assembly){
4695 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4701 // Anything else (FamOrAssembly and Public) is fine
4708 // This filter should be used when we are requesting properties that
4709 // we want to override.
4711 // This makes a number of assumptions, for example
4712 // that the methods being extracted are of a parent
4713 // class (this means we know implicitly that we are
4714 // being called to find out about members by a derived
4717 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
4719 if (MemberSignatureCompare (m, filter_criteria)){
4720 PropertyInfo pi = (PropertyInfo) m;
4722 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
4723 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
4725 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
4727 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4729 // If only accessible to the current class.
4730 if (prot == MethodAttributes.Private)
4733 // If only accessible to the defining assembly or
4734 if (prot == MethodAttributes.FamANDAssem ||
4735 prot == MethodAttributes.Assembly){
4736 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4742 // Anything else (FamOrAssembly and Public) is fine