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)
259 if (c.Name != Basename)
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 sw.SetMethodSourceRange (Location.SymbolDocument,
3080 ec.EmitTopBlock (block, ParameterInfo, Location);
3084 ec.EmitTopBlock (block, ParameterInfo, Location);
3088 void EmitDestructor (EmitContext ec, Block block)
3090 ILGenerator ig = ec.ig;
3092 Label finish = ig.DefineLabel ();
3093 bool old_in_try = ec.InTry;
3095 ig.BeginExceptionBlock ();
3097 ec.ReturnLabel = finish;
3098 ec.HasReturnLabel = true;
3099 ec.EmitTopBlock (block, null, Location);
3100 ec.InTry = old_in_try;
3102 // ig.MarkLabel (finish);
3103 bool old_in_finally = ec.InFinally;
3104 ec.InFinally = true;
3105 ig.BeginFinallyBlock ();
3107 if (ec.ContainerType.BaseType != null) {
3108 Expression member_lookup = Expression.MemberLookup (
3109 ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
3110 MemberTypes.Method, Expression.AllBindingFlags, Location);
3112 if (member_lookup != null){
3113 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3115 ig.Emit (OpCodes.Ldarg_0);
3116 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3119 ec.InFinally = old_in_finally;
3121 ig.EndExceptionBlock ();
3122 //ig.MarkLabel (ec.ReturnLabel);
3123 ig.Emit (OpCodes.Ret);
3127 abstract public class MemberBase : MemberCore {
3128 public Expression Type;
3129 public readonly Attributes OptAttributes;
3131 protected MethodAttributes flags;
3134 // The "short" name of this property / indexer / event. This is the
3135 // name without the explicit interface.
3137 public string ShortName;
3140 // The type of this property / indexer / event
3142 public Type MemberType;
3145 // If true, this is an explicit interface implementation
3147 public bool IsExplicitImpl = false;
3150 // The name of the interface we are explicitly implementing
3152 public string ExplicitInterfaceName = null;
3155 // If true, the interface type we are explicitly implementing
3157 public Type InterfaceType = null;
3160 // The method we're overriding if this is an override method.
3162 protected MethodInfo parent_method = null;
3163 public MethodInfo ParentMethod {
3165 return parent_method;
3170 // The constructor is only exposed to our children
3172 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3173 Attributes attrs, Location loc)
3177 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
3178 OptAttributes = attrs;
3181 protected virtual bool CheckBase (TypeContainer parent)
3186 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3190 foreach (Type partype in parameters){
3191 if (partype.IsPointer && !UnsafeOK (parent))
3194 if (parent.AsAccessible (partype, ModFlags))
3197 if (this is Indexer)
3198 Report.Error (55, Location,
3199 "Inconsistent accessibility: parameter type `" +
3200 TypeManager.CSharpName (partype) + "' is less " +
3201 "accessible than indexer `" + Name + "'");
3203 Report.Error (51, Location,
3204 "Inconsistent accessibility: parameter type `" +
3205 TypeManager.CSharpName (partype) + "' is less " +
3206 "accessible than method `" + Name + "'");
3213 protected virtual bool DoDefine (TypeContainer parent)
3218 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3221 flags = Modifiers.MethodAttr (ModFlags);
3223 // Lookup Type, verify validity
3224 MemberType = parent.ResolveType (Type, false, Location);
3225 if (MemberType == null)
3228 // verify accessibility
3229 if (!parent.AsAccessible (MemberType, ModFlags)) {
3230 if (this is Property)
3231 Report.Error (53, Location,
3232 "Inconsistent accessibility: property type `" +
3233 TypeManager.CSharpName (MemberType) + "' is less " +
3234 "accessible than property `" + Name + "'");
3235 else if (this is Indexer)
3236 Report.Error (54, Location,
3237 "Inconsistent accessibility: indexer return type `" +
3238 TypeManager.CSharpName (MemberType) + "' is less " +
3239 "accessible than indexer `" + Name + "'");
3240 else if (this is Method)
3241 Report.Error (50, Location,
3242 "Inconsistent accessibility: return type `" +
3243 TypeManager.CSharpName (MemberType) + "' is less " +
3244 "accessible than method `" + Name + "'");
3246 Report.Error (52, Location,
3247 "Inconsistent accessibility: field type `" +
3248 TypeManager.CSharpName (MemberType) + "' is less " +
3249 "accessible than field `" + Name + "'");
3253 if (MemberType.IsPointer && !UnsafeOK (parent))
3257 // Check for explicit interface implementation
3259 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
3260 int pos = Name.LastIndexOf (".");
3262 ExplicitInterfaceName = Name.Substring (0, pos);
3263 ShortName = Name.Substring (pos + 1);
3267 if (ExplicitInterfaceName != null) {
3268 InterfaceType = RootContext.LookupType (
3269 parent, ExplicitInterfaceName, false, Location);
3270 if (InterfaceType == null)
3273 // Compute the full name that we need to export.
3274 Name = InterfaceType.FullName + "." + ShortName;
3276 if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
3279 IsExplicitImpl = true;
3281 IsExplicitImpl = false;
3288 // Fields and Events both generate FieldBuilders, we use this to share
3289 // their common bits. This is also used to flag usage of the field
3291 abstract public class FieldBase : MemberBase {
3292 public FieldBuilder FieldBuilder;
3293 public Status status;
3296 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3299 // The constructor is only exposed to our children
3301 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3302 object init, Attributes attrs, Location loc)
3303 : base (type, mod, allowed_mod, name, attrs, loc)
3309 // Whether this field has an initializer.
3311 public bool HasInitializer {
3313 return init != null;
3318 readonly Object init;
3319 Expression init_expr;
3320 bool init_expr_initialized = false;
3323 // Resolves and returns the field initializer.
3325 public Expression GetInitializerExpression (EmitContext ec)
3327 if (init_expr_initialized)
3331 if (init is Expression)
3332 e = (Expression) init;
3334 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3336 ec.IsFieldInitializer = true;
3337 e = e.DoResolve (ec);
3338 ec.IsFieldInitializer = false;
3341 init_expr_initialized = true;
3348 // The Field class is used to represents class/struct fields during parsing.
3350 public class Field : FieldBase {
3352 // Modifiers allowed in a class declaration
3354 const int AllowedModifiers =
3357 Modifiers.PROTECTED |
3358 Modifiers.INTERNAL |
3361 Modifiers.VOLATILE |
3365 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3366 Attributes attrs, Location loc)
3367 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3371 public override bool Define (TypeContainer parent)
3373 Type t = parent.ResolveType (Type, false, Location);
3378 if (!parent.AsAccessible (t, ModFlags)) {
3379 Report.Error (52, Location,
3380 "Inconsistent accessibility: field type `" +
3381 TypeManager.CSharpName (t) + "' is less " +
3382 "accessible than field `" + Name + "'");
3386 if (t.IsPointer && !UnsafeOK (parent))
3389 if (RootContext.WarningLevel > 1){
3390 Type ptype = parent.TypeBuilder.BaseType;
3392 // ptype is only null for System.Object while compiling corlib.
3394 TypeContainer.FindMembers (
3395 ptype, MemberTypes.Method,
3396 BindingFlags.Public |
3397 BindingFlags.Static | BindingFlags.Instance,
3398 System.Type.FilterName, Name);
3402 if ((ModFlags & Modifiers.VOLATILE) != 0){
3404 if (TypeManager.IsEnumType (t))
3405 t = TypeManager.EnumToUnderlying (t);
3407 if (!((t == TypeManager.bool_type) ||
3408 (t == TypeManager.sbyte_type) ||
3409 (t == TypeManager.byte_type) ||
3410 (t == TypeManager.short_type) ||
3411 (t == TypeManager.ushort_type) ||
3412 (t == TypeManager.int32_type) ||
3413 (t == TypeManager.uint32_type) ||
3414 (t == TypeManager.char_type) ||
3415 (t == TypeManager.float_type))){
3417 677, Location, parent.MakeName (Name) +
3418 " A volatile field can not be of type `" +
3419 TypeManager.CSharpName (t) + "'");
3425 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3427 if (parent is Struct &&
3428 ((fa & FieldAttributes.Static) == 0) &&
3429 t == parent.TypeBuilder &&
3430 !TypeManager.IsBuiltinType (t)){
3431 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name +
3432 "' causes a cycle in the structure layout");
3435 FieldBuilder = parent.TypeBuilder.DefineField (
3436 Name, t, Modifiers.FieldAttr (ModFlags));
3438 TypeManager.RegisterFieldBase (FieldBuilder, this);
3442 public void Emit (TypeContainer tc)
3444 EmitContext ec = new EmitContext (tc, Location, null,
3445 FieldBuilder.FieldType, ModFlags);
3447 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
3452 // `set' and `get' accessors are represented with an Accessor.
3454 public class Accessor {
3456 // Null if the accessor is empty, or a Block if not
3459 public Attributes OptAttributes;
3461 public Accessor (Block b, Attributes attrs)
3464 OptAttributes = attrs;
3469 // Properties and Indexers both generate PropertyBuilders, we use this to share
3470 // their common bits.
3472 abstract public class PropertyBase : MethodCore {
3473 public Accessor Get, Set;
3474 public PropertyBuilder PropertyBuilder;
3475 public MethodBuilder GetBuilder, SetBuilder;
3476 public MethodData GetData, SetData;
3478 protected EmitContext ec;
3480 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3481 Parameters parameters, Accessor get_block, Accessor set_block,
3482 Attributes attrs, Location loc)
3483 : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3489 protected override bool DoDefine (TypeContainer parent)
3491 if (!base.DoDefine (parent))
3494 ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3500 // Checks our base implementation if any
3502 protected override bool CheckBase (TypeContainer parent)
3504 // Check whether arguments were correct.
3505 if (!DoDefineParameters (parent))
3512 MethodSignature ms, base_ms;
3513 if (this is Indexer) {
3514 string name, base_name;
3516 report_name = "this";
3517 name = TypeManager.IndexerPropertyName (parent.TypeBuilder);
3518 ms = new MethodSignature (name, null, ParameterTypes);
3519 base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType);
3520 base_ms = new MethodSignature (base_name, null, ParameterTypes);
3523 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
3526 MemberList props_this;
3528 props_this = TypeContainer.FindMembers (
3529 parent.TypeBuilder, MemberTypes.Property,
3530 BindingFlags.NonPublic | BindingFlags.Public |
3531 BindingFlags.Static | BindingFlags.Instance |
3532 BindingFlags.DeclaredOnly,
3533 MethodSignature.method_signature_filter, ms);
3535 if (props_this.Count > 0) {
3536 Report.Error (111, Location, "Class `" + parent.Name + "' " +
3537 "already defines a member called `" + report_name + "' " +
3538 "with the same parameter types");
3543 // Find properties with the same name on the base class
3546 MemberList props_static = TypeContainer.FindMembers (
3547 parent.TypeBuilder.BaseType, MemberTypes.Property,
3548 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3549 MethodSignature.inheritable_property_signature_filter, base_ms);
3551 MemberList props_instance = TypeContainer.FindMembers (
3552 parent.TypeBuilder.BaseType, MemberTypes.Property,
3553 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3554 MethodSignature.inheritable_property_signature_filter,
3558 // Find if we have anything
3560 if (props_static.Count > 0)
3561 props = props_static;
3562 else if (props_instance.Count > 0)
3563 props = props_instance;
3568 // If we have something on the base.
3569 if (props != null && props.Count > 0){
3570 PropertyInfo pi = (PropertyInfo) props [0];
3572 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
3573 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
3575 MethodInfo reference = inherited_get == null ?
3576 inherited_set : inherited_get;
3578 if (reference != null) {
3579 string name = reference.DeclaringType.Name + "." + report_name;
3581 if (!CheckMethodAgainstBase (parent, flags, reference, name))
3585 if (((ModFlags & Modifiers.NEW) == 0) && (pi.PropertyType != MemberType)) {
3586 Report.Error (508, parent.MakeName (Name) + ": cannot " +
3587 "change return type when overriding inherited " +
3588 "member `" + pi.DeclaringType + "." + pi.Name + "'");
3592 if ((ModFlags & Modifiers.NEW) != 0)
3593 WarningNotHiding (parent);
3595 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3596 if (this is Indexer)
3597 Report.Error (115, Location,
3598 parent.MakeName (Name) +
3599 " no suitable indexers found to override");
3601 Report.Error (115, Location,
3602 parent.MakeName (Name) +
3603 " no suitable properties found to override");
3610 public void Emit (TypeContainer tc)
3613 // The PropertyBuilder can be null for explicit implementations, in that
3614 // case, we do not actually emit the ".property", so there is nowhere to
3615 // put the attribute
3617 if (PropertyBuilder != null)
3618 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3620 if (GetData != null)
3621 GetData.Emit (tc, Get.Block, Get);
3623 if (SetData != null)
3624 SetData.Emit (tc, Set.Block, Set);
3628 public class Property : PropertyBase {
3629 const int AllowedModifiers =
3632 Modifiers.PROTECTED |
3633 Modifiers.INTERNAL |
3637 Modifiers.OVERRIDE |
3638 Modifiers.ABSTRACT |
3643 public Property (Expression type, string name, int mod_flags,
3644 Accessor get_block, Accessor set_block,
3645 Attributes attrs, Location loc)
3646 : base (type, name, mod_flags, AllowedModifiers,
3647 Parameters.EmptyReadOnlyParameters,
3648 get_block, set_block, attrs, loc)
3652 public override bool Define (TypeContainer parent)
3654 if (!DoDefine (parent))
3657 if (!CheckBase (parent))
3660 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3663 Type [] parameters = TypeManager.NoTypes;
3665 InternalParameters ip = new InternalParameters (
3666 parent, Parameters.EmptyReadOnlyParameters);
3668 GetData = new MethodData (this, "get", MemberType,
3669 parameters, ip, CallingConventions.Standard,
3670 Get.OptAttributes, ModFlags, flags, false);
3672 if (!GetData.Define (parent))
3675 GetBuilder = GetData.MethodBuilder;
3679 Type [] parameters = new Type [1];
3680 parameters [0] = MemberType;
3682 Parameter [] parms = new Parameter [1];
3683 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3684 InternalParameters ip = new InternalParameters (
3685 parent, new Parameters (parms, null, Location));
3687 SetData = new MethodData (this, "set", TypeManager.void_type,
3688 parameters, ip, CallingConventions.Standard,
3689 Set.OptAttributes, ModFlags, flags, false);
3691 if (!SetData.Define (parent))
3694 SetBuilder = SetData.MethodBuilder;
3695 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3698 // FIXME - PropertyAttributes.HasDefault ?
3700 PropertyAttributes prop_attr =
3701 PropertyAttributes.RTSpecialName |
3702 PropertyAttributes.SpecialName;
3704 if (!IsExplicitImpl){
3705 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3706 Name, prop_attr, MemberType, null);
3709 PropertyBuilder.SetGetMethod (GetBuilder);
3712 PropertyBuilder.SetSetMethod (SetBuilder);
3715 // HACK for the reasons exposed above
3717 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3720 "Class `" + parent.Name +
3721 "' already contains a definition for the property `" +
3731 /// Gigantic workaround for lameness in SRE follows :
3732 /// This class derives from EventInfo and attempts to basically
3733 /// wrap around the EventBuilder so that FindMembers can quickly
3734 /// return this in it search for members
3736 public class MyEventBuilder : EventInfo {
3739 // We use this to "point" to our Builder which is
3740 // not really a MemberInfo
3742 EventBuilder MyBuilder;
3745 // We "catch" and wrap these methods
3747 MethodInfo raise, remove, add;
3749 EventAttributes attributes;
3750 Type declaring_type, reflected_type, event_type;
3753 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3755 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3757 // And now store the values in our own fields.
3759 declaring_type = type_builder;
3761 reflected_type = type_builder;
3763 attributes = event_attr;
3765 this.event_type = event_type;
3769 // Methods that you have to override. Note that you only need
3770 // to "implement" the variants that take the argument (those are
3771 // the "abstract" methods, the others (GetAddMethod()) are
3774 public override MethodInfo GetAddMethod (bool nonPublic)
3779 public override MethodInfo GetRemoveMethod (bool nonPublic)
3784 public override MethodInfo GetRaiseMethod (bool nonPublic)
3790 // These methods make "MyEventInfo" look like a Builder
3792 public void SetRaiseMethod (MethodBuilder raiseMethod)
3794 raise = raiseMethod;
3795 MyBuilder.SetRaiseMethod (raiseMethod);
3798 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3800 remove = removeMethod;
3801 MyBuilder.SetRemoveOnMethod (removeMethod);
3804 public void SetAddOnMethod (MethodBuilder addMethod)
3807 MyBuilder.SetAddOnMethod (addMethod);
3810 public void SetCustomAttribute (CustomAttributeBuilder cb)
3812 MyBuilder.SetCustomAttribute (cb);
3815 public override object [] GetCustomAttributes (bool inherit)
3817 // FIXME : There's nothing which can be seemingly done here because
3818 // we have no way of getting at the custom attribute objects of the
3823 public override object [] GetCustomAttributes (Type t, bool inherit)
3825 // FIXME : Same here !
3829 public override bool IsDefined (Type t, bool b)
3834 public override EventAttributes Attributes {
3840 public override string Name {
3846 public override Type DeclaringType {
3848 return declaring_type;
3852 public override Type ReflectedType {
3854 return reflected_type;
3858 public Type EventType {
3865 public class Event : FieldBase {
3866 const int AllowedModifiers =
3869 Modifiers.PROTECTED |
3870 Modifiers.INTERNAL |
3875 Modifiers.OVERRIDE |
3879 public readonly Accessor Add;
3880 public readonly Accessor Remove;
3881 public MyEventBuilder EventBuilder;
3883 MethodBuilder AddBuilder, RemoveBuilder;
3884 MethodData AddData, RemoveData;
3886 public Event (Expression type, string name, Object init, int mod, Accessor add,
3887 Accessor remove, Attributes attrs, Location loc)
3888 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
3894 public override bool Define (TypeContainer parent)
3896 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3898 if (!DoDefine (parent))
3901 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
3902 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3903 "' : event must be of a delegate type");
3907 Type [] parameter_types = new Type [1];
3908 parameter_types [0] = MemberType;
3910 Parameter [] parms = new Parameter [1];
3911 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3912 InternalParameters ip = new InternalParameters (
3913 parent, new Parameters (parms, null, Location));
3915 if (!CheckBase (parent))
3919 // Now define the accessors
3921 AddData = new MethodData (this, "add", TypeManager.void_type,
3922 parameter_types, ip, CallingConventions.Standard,
3923 (Add != null) ? Add.OptAttributes : null,
3924 ModFlags, flags, false);
3926 if (!AddData.Define (parent))
3929 AddBuilder = AddData.MethodBuilder;
3930 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3932 RemoveData = new MethodData (this, "remove", TypeManager.void_type,
3933 parameter_types, ip, CallingConventions.Standard,
3934 (Remove != null) ? Remove.OptAttributes : null,
3935 ModFlags, flags, false);
3937 if (!RemoveData.Define (parent))
3940 RemoveBuilder = RemoveData.MethodBuilder;
3941 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3943 if (!IsExplicitImpl){
3944 EventBuilder = new MyEventBuilder (
3945 parent.TypeBuilder, Name, e_attr, MemberType);
3947 if (Add == null && Remove == null) {
3948 FieldBuilder = parent.TypeBuilder.DefineField (
3949 Name, MemberType, Modifiers.FieldAttr (ModFlags));
3950 TypeManager.RegisterPrivateFieldOfEvent (
3951 (EventInfo) EventBuilder, FieldBuilder);
3952 TypeManager.RegisterFieldBase (FieldBuilder, this);
3955 EventBuilder.SetAddOnMethod (AddBuilder);
3956 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3958 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3959 Report.Error (111, Location,
3960 "Class `" + parent.Name +
3961 "' already contains a definition for the event `" +
3970 void EmitDefaultMethod (EmitContext ec, bool is_add)
3972 ILGenerator ig = ec.ig;
3973 MethodInfo method = null;
3976 method = TypeManager.delegate_combine_delegate_delegate;
3978 method = TypeManager.delegate_remove_delegate_delegate;
3980 if ((ModFlags & Modifiers.STATIC) != 0) {
3981 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
3982 ig.Emit (OpCodes.Ldarg_0);
3983 ig.Emit (OpCodes.Call, method);
3984 ig.Emit (OpCodes.Castclass, MemberType);
3985 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
3987 ig.Emit (OpCodes.Ldarg_0);
3988 ig.Emit (OpCodes.Ldarg_0);
3989 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3990 ig.Emit (OpCodes.Ldarg_1);
3991 ig.Emit (OpCodes.Call, method);
3992 ig.Emit (OpCodes.Castclass, MemberType);
3993 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3995 ig.Emit (OpCodes.Ret);
3998 public void Emit (TypeContainer tc)
4002 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4003 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
4006 AddData.Emit (tc, Add.Block, Add);
4008 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4009 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4010 EmitDefaultMethod (ec, true);
4014 RemoveData.Emit (tc, Remove.Block, Remove);
4016 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4017 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4018 EmitDefaultMethod (ec, false);
4025 // FIXME: This does not handle:
4027 // int INTERFACENAME [ args ]
4032 // int this [ args ]
4034 public class Indexer : PropertyBase {
4036 const int AllowedModifiers =
4039 Modifiers.PROTECTED |
4040 Modifiers.INTERNAL |
4044 Modifiers.OVERRIDE |
4049 public string IndexerName;
4050 public string InterfaceIndexerName;
4053 // Are we implementing an interface ?
4055 bool IsImplementing = false;
4057 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4058 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4059 : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4062 ExplicitInterfaceName = int_type;
4065 public override bool Define (TypeContainer parent)
4067 PropertyAttributes prop_attr =
4068 PropertyAttributes.RTSpecialName |
4069 PropertyAttributes.SpecialName;
4071 if (!DoDefine (parent))
4074 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4075 if (IndexerName == null)
4076 IndexerName = "Item";
4077 else if (IsExplicitImpl)
4078 Report.Error (592, Location,
4079 "Attribute 'IndexerName' is not valid on this declaration " +
4080 "type. It is valid on `property' declarations only.");
4082 ShortName = IndexerName;
4083 if (IsExplicitImpl) {
4084 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4085 Name = InterfaceType.FullName + "." + IndexerName;
4087 InterfaceIndexerName = IndexerName;
4091 if (!CheckBase (parent))
4095 InternalParameters ip = new InternalParameters (parent, Parameters);
4097 GetData = new MethodData (this, "get", MemberType,
4098 ParameterTypes, ip, CallingConventions.Standard,
4099 Get.OptAttributes, ModFlags, flags, false);
4101 if (!GetData.Define (parent))
4104 GetBuilder = GetData.MethodBuilder;
4108 int top = ParameterTypes.Length;
4109 Type [] set_pars = new Type [top + 1];
4110 ParameterTypes.CopyTo (set_pars, 0);
4111 set_pars [top] = MemberType;
4113 Parameter [] fixed_parms = Parameters.FixedParameters;
4115 if (fixed_parms == null){
4116 throw new Exception ("We currently do not support only array arguments in an indexer");
4117 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4118 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4120 // Here is the problem: the `value' parameter has
4121 // to come *after* the array parameter in the declaration
4123 // X (object [] x, Type value)
4126 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4127 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4131 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4134 fixed_parms.CopyTo (tmp, 0);
4135 tmp [fixed_parms.Length] = new Parameter (
4136 Type, "value", Parameter.Modifier.NONE, null);
4138 Parameters set_formal_params = new Parameters (tmp, null, Location);
4140 InternalParameters ip = new InternalParameters (parent, set_formal_params);
4142 SetData = new MethodData (this, "set", TypeManager.void_type,
4143 set_pars, ip, CallingConventions.Standard,
4144 Set.OptAttributes, ModFlags, flags, false);
4146 if (!SetData.Define (parent))
4149 SetBuilder = SetData.MethodBuilder;
4153 // Now name the parameters
4155 Parameter [] p = Parameters.FixedParameters;
4159 for (i = 0; i < p.Length; ++i) {
4161 GetBuilder.DefineParameter (
4162 i + 1, p [i].Attributes, p [i].Name);
4165 SetBuilder.DefineParameter (
4166 i + 1, p [i].Attributes, p [i].Name);
4170 SetBuilder.DefineParameter (
4171 i + 1, ParameterAttributes.None, "value");
4173 if (i != ParameterTypes.Length) {
4174 Parameter array_param = Parameters.ArrayParameter;
4175 SetBuilder.DefineParameter (
4176 i + 1, array_param.Attributes, array_param.Name);
4180 if (GetData != null)
4181 IsImplementing = GetData.IsImplementing;
4182 else if (SetData != null)
4183 IsImplementing = SetData.IsImplementing;
4186 // Define the PropertyBuilder if one of the following conditions are met:
4187 // a) we're not implementing an interface indexer.
4188 // b) the indexer has a different IndexerName and this is no
4189 // explicit interface implementation.
4191 if (!IsExplicitImpl) {
4192 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4193 IndexerName, prop_attr, MemberType, ParameterTypes);
4195 if (GetData != null)
4196 PropertyBuilder.SetGetMethod (GetBuilder);
4198 if (SetData != null)
4199 PropertyBuilder.SetSetMethod (SetBuilder);
4201 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4209 public class Operator : MemberCore {
4211 const int AllowedModifiers =
4217 const int RequiredModifiers =
4221 public enum OpType : byte {
4231 // Unary and Binary operators
4254 // Implicit and Explicit
4259 public readonly OpType OperatorType;
4260 public readonly Expression ReturnType;
4261 public readonly Expression FirstArgType, SecondArgType;
4262 public readonly string FirstArgName, SecondArgName;
4263 public readonly Block Block;
4264 public Attributes OptAttributes;
4265 public MethodBuilder OperatorMethodBuilder;
4267 public string MethodName;
4268 public Method OperatorMethod;
4270 public Operator (OpType type, Expression ret_type, int flags,
4271 Expression arg1type, string arg1name,
4272 Expression arg2type, string arg2name,
4273 Block block, Attributes attrs, Location loc)
4276 OperatorType = type;
4277 ReturnType = ret_type;
4278 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4279 FirstArgType = arg1type;
4280 FirstArgName = arg1name;
4281 SecondArgType = arg2type;
4282 SecondArgName = arg2name;
4284 OptAttributes = attrs;
4287 string Prototype (TypeContainer parent)
4289 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4290 SecondArgType + ")";
4293 public override bool Define (TypeContainer parent)
4296 MethodName = "op_" + OperatorType;
4298 if (SecondArgType != null)
4301 Parameter [] param_list = new Parameter [length];
4303 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4306 "User defined operators `" +
4307 Prototype (parent) +
4308 "' must be declared static and public");
4312 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4313 Parameter.Modifier.NONE, null);
4314 if (SecondArgType != null)
4315 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4316 Parameter.Modifier.NONE, null);
4318 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4319 new Parameters (param_list, null, Location),
4320 OptAttributes, Mono.CSharp.Location.Null);
4322 OperatorMethod.IsOperator = true;
4323 OperatorMethod.Define (parent);
4325 if (OperatorMethod.MethodBuilder == null)
4328 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4330 Type [] param_types = OperatorMethod.ParameterTypes;
4331 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4332 Type return_type = OperatorMethod.GetReturnType ();
4333 Type first_arg_type = param_types [0];
4335 // Rules for conversion operators
4337 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4338 if (first_arg_type == return_type && first_arg_type == declaring_type){
4341 "User-defined conversion cannot take an object of the " +
4342 "enclosing type and convert to an object of the enclosing" +
4347 if (first_arg_type != declaring_type && return_type != declaring_type){
4350 "User-defined conversion must convert to or from the " +
4355 if (first_arg_type == TypeManager.object_type ||
4356 return_type == TypeManager.object_type){
4359 "User-defined conversion cannot convert to or from " +
4364 if (first_arg_type.IsInterface || return_type.IsInterface){
4367 "User-defined conversion cannot convert to or from an " +
4372 if (first_arg_type.IsSubclassOf (return_type) ||
4373 return_type.IsSubclassOf (first_arg_type)){
4376 "User-defined conversion cannot convert between types " +
4377 "that derive from each other");
4380 } else if (SecondArgType == null) {
4381 // Checks for Unary operators
4383 if (first_arg_type != declaring_type){
4386 "The parameter of a unary operator must be the " +
4391 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4392 if (return_type != declaring_type){
4395 "The parameter and return type for ++ and -- " +
4396 "must be the containing type");
4402 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4403 if (return_type != TypeManager.bool_type){
4406 "The return type of operator True or False " +
4413 // Checks for Binary operators
4415 if (first_arg_type != declaring_type &&
4416 param_types [1] != declaring_type){
4419 "One of the parameters of a binary operator must " +
4420 "be the containing type");
4428 public void Emit (TypeContainer parent)
4430 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4431 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4434 // abstract or extern methods have no bodies
4436 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4439 OperatorMethod.Block = Block;
4440 OperatorMethod.Emit (parent);
4443 public static string GetName (OpType ot)
4446 case OpType.LogicalNot:
4448 case OpType.OnesComplement:
4450 case OpType.Increment:
4452 case OpType.Decrement:
4458 case OpType.Addition:
4460 case OpType.Subtraction:
4462 case OpType.UnaryPlus:
4464 case OpType.UnaryNegation:
4466 case OpType.Multiply:
4468 case OpType.Division:
4470 case OpType.Modulus:
4472 case OpType.BitwiseAnd:
4474 case OpType.BitwiseOr:
4476 case OpType.ExclusiveOr:
4478 case OpType.LeftShift:
4480 case OpType.RightShift:
4482 case OpType.Equality:
4484 case OpType.Inequality:
4486 case OpType.GreaterThan:
4488 case OpType.LessThan:
4490 case OpType.GreaterThanOrEqual:
4492 case OpType.LessThanOrEqual:
4494 case OpType.Implicit:
4496 case OpType.Explicit:
4502 public override string ToString ()
4504 Type return_type = OperatorMethod.GetReturnType();
4505 Type [] param_types = OperatorMethod.ParameterTypes;
4507 if (SecondArgType == null)
4508 return String.Format (
4509 "{0} operator {1}({2})",
4510 TypeManager.CSharpName (return_type),
4511 GetName (OperatorType),
4514 return String.Format (
4515 "{0} operator {1}({2}, {3})",
4516 TypeManager.CSharpName (return_type),
4517 GetName (OperatorType),
4518 param_types [0], param_types [1]);
4523 // This is used to compare method signatures
4525 struct MethodSignature {
4527 public Type RetType;
4528 public Type [] Parameters;
4531 /// This delegate is used to extract methods which have the
4532 /// same signature as the argument
4534 public static MemberFilter method_signature_filter;
4537 /// This delegate is used to extract inheritable methods which
4538 /// have the same signature as the argument. By inheritable,
4539 /// this means that we have permissions to override the method
4540 /// from the current assembly and class
4542 public static MemberFilter inheritable_method_signature_filter;
4545 /// This delegate is used to extract inheritable methods which
4546 /// have the same signature as the argument. By inheritable,
4547 /// this means that we have permissions to override the method
4548 /// from the current assembly and class
4550 public static MemberFilter inheritable_property_signature_filter;
4552 static MethodSignature ()
4554 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4555 inheritable_method_signature_filter = new MemberFilter (
4556 InheritableMemberSignatureCompare);
4557 inheritable_property_signature_filter = new MemberFilter (
4558 InheritablePropertySignatureCompare);
4561 public MethodSignature (string name, Type ret_type, Type [] parameters)
4566 if (parameters == null)
4567 Parameters = TypeManager.NoTypes;
4569 Parameters = parameters;
4572 public override int GetHashCode ()
4574 return Name.GetHashCode ();
4577 public override bool Equals (Object o)
4579 MethodSignature other = (MethodSignature) o;
4581 if (other.Name != Name)
4584 if (other.RetType != RetType)
4587 if (Parameters == null){
4588 if (other.Parameters == null)
4593 if (other.Parameters == null)
4596 int c = Parameters.Length;
4597 if (other.Parameters.Length != c)
4600 for (int i = 0; i < c; i++)
4601 if (other.Parameters [i] != Parameters [i])
4607 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4609 MethodSignature sig = (MethodSignature) filter_criteria;
4611 if (m.Name != sig.Name)
4615 MethodInfo mi = m as MethodInfo;
4616 PropertyInfo pi = m as PropertyInfo;
4619 ReturnType = mi.ReturnType;
4620 else if (pi != null)
4621 ReturnType = pi.PropertyType;
4626 // we use sig.RetType == null to mean `do not check the
4627 // method return value.
4629 if (sig.RetType != null)
4630 if (ReturnType != sig.RetType)
4635 args = TypeManager.GetArgumentTypes (mi);
4637 args = TypeManager.GetArgumentTypes (pi);
4638 Type [] sigp = sig.Parameters;
4640 if (args.Length != sigp.Length)
4643 for (int i = args.Length; i > 0; ){
4645 if (args [i] != sigp [i])
4652 // This filter should be used when we are requesting methods that
4653 // we want to override.
4655 // This makes a number of assumptions, for example
4656 // that the methods being extracted are of a parent
4657 // class (this means we know implicitly that we are
4658 // being called to find out about members by a derived
4661 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4663 if (MemberSignatureCompare (m, filter_criteria)){
4664 MethodInfo mi = (MethodInfo) m;
4665 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4667 // If only accessible to the current class.
4668 if (prot == MethodAttributes.Private)
4671 // If only accessible to the defining assembly or
4672 if (prot == MethodAttributes.FamANDAssem ||
4673 prot == MethodAttributes.Assembly){
4674 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4680 // Anything else (FamOrAssembly and Public) is fine
4687 // This filter should be used when we are requesting properties that
4688 // we want to override.
4690 // This makes a number of assumptions, for example
4691 // that the methods being extracted are of a parent
4692 // class (this means we know implicitly that we are
4693 // being called to find out about members by a derived
4696 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
4698 if (MemberSignatureCompare (m, filter_criteria)){
4699 PropertyInfo pi = (PropertyInfo) m;
4701 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
4702 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
4704 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
4706 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4708 // If only accessible to the current class.
4709 if (prot == MethodAttributes.Private)
4712 // If only accessible to the defining assembly or
4713 if (prot == MethodAttributes.FamANDAssem ||
4714 prot == MethodAttributes.Assembly){
4715 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4721 // Anything else (FamOrAssembly and Public) is fine