2 // class.cs: Class and Struct handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@gnome.org)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
12 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
14 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
15 // have fixed a remaining problem: not every AddXXXX was adding a
16 // fully qualified name.
18 // Now everyone registers a fully qualified name in the DeclSpace as
19 // being defined instead of the partial name.
21 // Downsides: we are slower than we need to be due to the excess
22 // copies and the names being registered this way.
24 // The reason for this is that we currently depend (on the corlib
25 // bootstrap for instance) that types are fully qualified, because
26 // we dump all the types in the namespace, and we should really have
27 // types inserted into the proper namespace, so we can only store the
28 // basenames in the defined_names array.
33 using System.Collections;
34 using System.Reflection;
35 using System.Reflection.Emit;
36 using System.Runtime.CompilerServices;
38 namespace Mono.CSharp {
41 /// This is the base class for structs and classes.
43 public class TypeContainer : DeclSpace, IMemberContainer {
44 // Holds a list of classes and structures
47 // Holds the list of properties
50 // Holds the list of enumerations
53 // Holds the list of delegates
56 // Holds the list of constructors
57 ArrayList instance_constructors;
59 // Holds the list of fields
62 // Holds a list of fields that have initializers
63 ArrayList initialized_fields;
65 // Holds a list of static fields that have initializers
66 ArrayList initialized_static_fields;
68 // Holds the list of constants
74 // Holds order in which interfaces must be closed
75 ArrayList interface_order;
86 // Holds the operators
89 // The emit context for toplevel objects.
93 // Pointers to the default constructor and the default static constructor
95 Constructor default_constructor;
96 Constructor default_static_constructor;
99 // Whether we have seen a static constructor for this class or not
101 bool have_static_constructor = false;
104 // Whether we have at least one non-static field
106 bool have_nonstatic_fields = false;
109 // This one is computed after we can distinguish interfaces
110 // from classes from the arraylist `type_bases'
112 string base_class_name;
114 ArrayList type_bases;
116 // Information in the case we are an attribute type
118 public AttributeTargets Targets = AttributeTargets.All;
119 public bool AllowMultiple = false;
120 public bool Inherited;
122 // The interfaces we implement.
125 // The parent member container and our member cache
126 IMemberContainer parent_container;
127 MemberCache member_cache;
130 // The indexer name for this class
132 public string IndexerName;
136 public TypeContainer ():
137 this (null, null, "", null, new Location (-1)) {
140 public TypeContainer (NamespaceEntry ns, TypeContainer parent, string name, Attributes attrs, Location l)
141 : base (ns, parent, name, attrs, l)
143 types = new ArrayList ();
145 base_class_name = null;
148 public AdditionResult AddConstant (Const constant)
151 string basename = constant.Name;
152 string fullname = Name + "." + basename;
154 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
157 if (constants == null)
158 constants = new ArrayList ();
160 constants.Add (constant);
161 DefineName (fullname, constant);
163 return AdditionResult.Success;
166 public AdditionResult AddEnum (Mono.CSharp.Enum e)
170 if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
174 enums = new ArrayList ();
177 DefineName (e.Name, e);
179 return AdditionResult.Success;
182 public AdditionResult AddClass (Class c)
185 string name = c.Basename;
187 if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
190 DefineName (c.Name, c);
193 return AdditionResult.Success;
196 public AdditionResult AddStruct (Struct s)
199 string name = s.Basename;
201 if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
204 DefineName (s.Name, s);
207 return AdditionResult.Success;
210 public AdditionResult AddDelegate (Delegate d)
213 string name = d.Basename;
215 if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
218 if (delegates == null)
219 delegates = new ArrayList ();
221 DefineName (d.Name, d);
224 return AdditionResult.Success;
227 public AdditionResult AddMethod (Method method)
229 string basename = method.Name;
230 string fullname = Name + "." + basename;
232 Object value = defined_names [fullname];
234 if (value != null && (!(value is Method)))
235 return AdditionResult.NameExists;
237 if (basename == Basename)
238 return AdditionResult.EnclosingClash;
241 methods = new ArrayList ();
243 if (method.Name.IndexOf ('.') != -1)
244 methods.Insert (0, method);
246 methods.Add (method);
249 DefineName (fullname, method);
251 return AdditionResult.Success;
254 public AdditionResult AddConstructor (Constructor c)
256 if (c.Name != Basename)
257 return AdditionResult.NotAConstructor;
259 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
262 have_static_constructor = true;
263 if (default_static_constructor != null){
264 Console.WriteLine ("I have a static constructor already");
265 Console.WriteLine (" " + default_static_constructor);
266 return AdditionResult.MethodExists;
269 default_static_constructor = c;
272 if (default_constructor != null)
273 return AdditionResult.MethodExists;
274 default_constructor = c;
277 if (instance_constructors == null)
278 instance_constructors = new ArrayList ();
280 instance_constructors.Add (c);
283 return AdditionResult.Success;
286 public AdditionResult AddInterface (Interface iface)
289 string name = iface.Basename;
291 if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
294 if (interfaces == null)
295 interfaces = new ArrayList ();
296 interfaces.Add (iface);
297 DefineName (iface.Name, iface);
299 return AdditionResult.Success;
302 public AdditionResult AddField (Field field)
305 string basename = field.Name;
306 string fullname = Name + "." + basename;
308 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
312 fields = new ArrayList ();
316 if (field.HasInitializer){
317 if ((field.ModFlags & Modifiers.STATIC) != 0){
318 if (initialized_static_fields == null)
319 initialized_static_fields = new ArrayList ();
321 initialized_static_fields.Add (field);
324 // We have not seen a static constructor,
325 // but we will provide static initialization of fields
327 have_static_constructor = true;
329 if (initialized_fields == null)
330 initialized_fields = new ArrayList ();
332 initialized_fields.Add (field);
336 if ((field.ModFlags & Modifiers.STATIC) == 0)
337 have_nonstatic_fields = true;
339 DefineName (fullname, field);
340 return AdditionResult.Success;
343 public AdditionResult AddProperty (Property prop)
346 string basename = prop.Name;
347 string fullname = Name + "." + basename;
349 if ((res = IsValid (basename, fullname)) != 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 (fullname, prop);
361 return AdditionResult.Success;
364 public AdditionResult AddEvent (Event e)
367 string basename = e.Name;
368 string fullname = Name + "." + basename;
370 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
374 events = new ArrayList ();
377 DefineName (fullname, e);
379 return AdditionResult.Success;
382 public AdditionResult AddIndexer (Indexer i)
384 if (indexers == null)
385 indexers = new ArrayList ();
387 if (i.InterfaceType != null)
388 indexers.Insert (0, i);
392 return AdditionResult.Success;
395 public AdditionResult AddOperator (Operator op)
397 if (operators == null)
398 operators = new ArrayList ();
402 return AdditionResult.Success;
405 public void RegisterOrder (Interface iface)
407 if (interface_order == null)
408 interface_order = new ArrayList ();
410 interface_order.Add (iface);
413 public ArrayList Types {
419 public ArrayList Methods {
425 public ArrayList Constants {
431 public ArrayList Interfaces {
439 return base_class_name;
443 public ArrayList Bases {
453 public ArrayList Fields {
463 public ArrayList InstanceConstructors {
465 return instance_constructors;
469 public ArrayList Properties {
475 public ArrayList Events {
481 public ArrayList Enums {
487 public ArrayList Indexers {
493 public ArrayList Operators {
499 public ArrayList Delegates {
505 public bool HaveStaticConstructor {
507 return have_static_constructor;
511 public virtual TypeAttributes TypeAttr {
513 return Modifiers.TypeAttr (ModFlags, this);
518 // Emits the instance field initializers
520 public bool EmitFieldInitializers (EmitContext ec)
523 Expression instance_expr;
526 fields = initialized_static_fields;
527 instance_expr = null;
529 fields = initialized_fields;
530 instance_expr = new This (Location.Null).Resolve (ec);
536 foreach (Field f in fields){
537 Expression e = f.GetInitializerExpression (ec);
541 Location l = f.Location;
542 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
543 fe.InstanceExpression = instance_expr;
544 ExpressionStatement a = new Assign (fe, e, l);
546 a = a.ResolveStatement (ec);
550 a.EmitStatement (ec);
557 // Defines the default constructors
559 void DefineDefaultConstructor (bool is_static)
564 c = new Constructor (this, Basename, Parameters.EmptyReadOnlyParameters,
565 new ConstructorBaseInitializer (
566 null, Parameters.EmptyReadOnlyParameters,
571 mods = Modifiers.STATIC;
574 // If the class is abstract, the default constructor is protected
576 if ((ModFlags & Modifiers.ABSTRACT) != 0)
577 mods |= Modifiers.PROTECTED;
583 c.Block = new ToplevelBlock (null, Location);
587 public void ReportStructInitializedInstanceError ()
589 string n = TypeBuilder.FullName;
591 foreach (Field f in initialized_fields){
594 "`" + n + "." + f.Name + "': can not have " +
595 "instance field initializers in structs");
599 void Error_TypeParameterAsBase (TypeParameterExpr e)
603 String.Format ("Type parameter `{0}' can not be used t as a base class or interface", e.Name));
607 /// The pending methods that need to be implemented (interfaces or abstract methods)
609 public PendingImplementation Pending;
612 /// This function computes the Base class and also the
613 /// list of interfaces that the class or struct @c implements.
615 /// The return value is an array (might be null) of
616 /// interfaces implemented (as Types).
618 /// The @parent argument is set to the parent object or null
619 /// if this is `System.Object'.
621 TypeExpr [] GetClassBases (bool is_class, out TypeExpr parent, out bool error)
623 ArrayList bases = Bases;
632 parent = TypeManager.system_valuetype_expr;
636 if (RootContext.StdLib)
637 parent = TypeManager.system_object_expr;
638 else if (Name != "System.Object")
639 parent = TypeManager.system_object_expr;
642 // If we are compiling our runtime,
643 // and we are defining ValueType, then our
644 // parent is `System.Object'.
646 if (!RootContext.StdLib && Name == "System.ValueType")
647 parent = TypeManager.system_object_expr;
654 // Bases should be null if there are no bases at all
659 TypeExpr name = ResolveTypeExpr ((Expression) bases [0], false, Location);
666 if (name is TypeParameterExpr){
667 Error_TypeParameterAsBase ((TypeParameterExpr) name);
676 parent = TypeManager.system_object_expr;
682 if (name.IsValueType)
683 detail = " (a class can not inherit from a struct/enum)";
685 Report.Error (509, "class `"+ Name +
686 "': Cannot inherit from sealed class `"+
687 name.Name + "'" + detail);
692 if (!parent.CanInheritFrom ()){
693 Report.Error (644, Location,
694 "`{0}' cannot inherit from special class `{1}'",
700 if (!parent.AsAccessible (this, ModFlags))
701 Report.Error (60, Location,
702 "Inconsistent accessibility: base class `" +
703 name.Name + "' is less accessible than class `" +
711 base_class_name = parent.Name;
713 TypeExpr [] ifaces = new TypeExpr [count-start];
715 for (i = start, j = 0; i < count; i++, j++){
716 Expression name = (Expression) bases [i];
717 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
718 if (resolved == null)
721 bases [i] = resolved;
723 if (is_class == false && !resolved.IsInterface){
724 Report.Error (527, "In Struct `" + Name + "', type `"+
725 name +"' is not an interface");
730 if (resolved.IsClass) {
732 Report.Error (527, "In Class `" + Name + "', type `"+
733 name+"' is not an interface");
739 for (int x = 0; x < j; x++) {
740 if (resolved == ifaces [x]) {
741 Report.Error (528, "`" + name + "' is already listed in interface list");
747 ifaces [j] = resolved;
750 return TypeManager.ExpandInterfaces (ifaces);
756 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
758 public override TypeBuilder DefineType ()
763 if (TypeBuilder != null)
770 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
782 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
784 ifaces = GetClassBases (is_class, out parent, out error);
790 foreach (TypeParameter type_param in TypeParameters)
791 if (!type_param.Resolve (this)) {
797 if (!is_class && TypeManager.value_type == null)
798 throw new Exception ();
800 TypeAttributes type_attributes = TypeAttr;
803 ConstructedType constructed = parent as ConstructedType;
804 if ((constructed == null) && (parent != null))
805 ptype = parent.ResolveType (ec);
810 if (TypeManager.NamespaceClash (Name, Location)) {
815 ModuleBuilder builder = CodeGen.ModuleBuilder;
816 TypeBuilder = builder.DefineType (
817 Name, type_attributes, ptype, null);
820 TypeBuilder builder = Parent.DefineType ();
824 TypeBuilder = builder.DefineNestedType (
825 Basename, type_attributes, ptype, null);
829 CurrentType = new ConstructedType (
830 Name, CurrentTypeParameters, Location);
832 foreach (TypeParameter type_param in TypeParameters)
833 type_param.Define (TypeBuilder);
836 if (constructed != null) {
837 ptype = constructed.ResolveType (ec);
841 TypeBuilder.SetParent (ptype);
845 foreach (TypeParameter type_param in TypeParameters)
846 type_param.DefineType (ec, TypeBuilder);
850 // Structs with no fields need to have at least one byte.
851 // The right thing would be to set the PackingSize in a DefineType
852 // but there are no functions that allow interfaces *and* the size to
856 if (!is_class && !have_nonstatic_fields){
857 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
858 FieldAttributes.Private);
861 // add interfaces that were not added at type creation
862 if (ifaces != null) {
863 foreach (TypeExpr iface in ifaces) {
864 Type itype = iface.ResolveType (ec);
865 TypeBuilder.AddInterfaceImplementation (itype);
870 // Finish the setup for the EmitContext
872 ec.ContainerType = TypeBuilder;
874 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
876 if ((parent != null) && parent.IsAttribute) {
877 RootContext.RegisterAttribute (this);
878 TypeManager.RegisterAttrType (TypeBuilder, this);
880 RootContext.RegisterOrder (this);
882 if (Interfaces != null) {
883 foreach (Interface iface in Interfaces)
884 if (iface.DefineType () == null) {
891 foreach (TypeContainer tc in Types)
892 if (tc.DefineType () == null) {
898 if (Delegates != null) {
899 foreach (Delegate d in Delegates)
900 if (d.DefineType () == null) {
907 foreach (Enum en in Enums)
908 if (en.DefineType () == null) {
920 /// Defines the MemberCore objects that are in the `list' Arraylist
922 /// The `defined_names' array contains a list of members defined in
925 static ArrayList remove_list = new ArrayList ();
926 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
930 remove_list.Clear ();
932 foreach (MemberCore mc in list){
934 if (defined_names != null)
935 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
940 if (RootContext.WarningLevel >= 4){
941 if ((mc.ModFlags & Modifiers.NEW) != 0)
942 Warning_KeywordNewNotRequired (mc.Location, mc);
944 } else if (mc is MethodCore)
945 ((MethodCore) mc).OverridesSomething = true;
947 if (!mc.Define (this)){
948 remove_list.Add (mc);
955 MemberInfo match = defined_names [idx];
957 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
961 // If we are both methods, let the method resolution emit warnings
963 if (match is MethodBase && mc is MethodCore)
966 if ((mc.ModFlags & Modifiers.NEW) == 0) {
968 if (!(match is EventInfo)) {
969 Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
973 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
977 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
981 foreach (object o in remove_list)
984 remove_list.Clear ();
988 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
989 // class is consisten. Either it is `Item' or it is the name defined by all the
990 // indexers with the `IndexerName' attribute.
992 // Turns out that the IndexerNameAttribute is applied to each indexer,
993 // but it is never emitted, instead a DefaultName attribute is attached
996 void DefineIndexers ()
998 string class_indexer_name = null;
1001 // If there's both an explicit and an implicit interface implementation, the
1002 // explicit one actually implements the interface while the other one is just
1003 // a normal indexer. See bug #37714.
1005 ArrayList list = new ArrayList ();
1006 foreach (Indexer i in Indexers){
1007 if (i.ExplicitInterfaceName != null)
1010 foreach (Indexer i in Indexers){
1011 if (i.ExplicitInterfaceName == null)
1015 foreach (Indexer i in list){
1020 name = i.IndexerName;
1022 if (i.InterfaceType != null)
1025 if (class_indexer_name == null){
1026 class_indexer_name = name;
1030 if (name == class_indexer_name)
1034 668, "Two indexers have different names, " +
1035 " you should use the same name for all your indexers");
1037 if (class_indexer_name == null)
1038 class_indexer_name = "Item";
1039 IndexerName = class_indexer_name;
1042 static void Error_KeywordNotAllowed (Location loc)
1044 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1048 /// Populates our TypeBuilder with fields and methods
1050 public override bool DefineMembers (TypeContainer container)
1052 MemberInfo [] defined_names = null;
1054 if (interface_order != null){
1055 foreach (Interface iface in interface_order)
1056 if ((iface.ModFlags & Modifiers.NEW) == 0)
1057 iface.DefineMembers (this);
1059 Error_KeywordNotAllowed (iface.Location);
1062 if (RootContext.WarningLevel > 1){
1066 // This code throws an exception in the comparer
1067 // I guess the string is not an object?
1069 ptype = TypeBuilder.BaseType;
1071 defined_names = (MemberInfo []) FindMembers (
1072 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1073 BindingFlags.Public | BindingFlags.Instance |
1074 BindingFlags.Static, null, null);
1076 Array.Sort (defined_names, mif_compare);
1080 Class pclass = Parent as Class;
1081 if (pclass != null) {
1082 string pname = null;
1084 Type t = pclass.TypeBuilder.BaseType;
1085 while ((t != null) && (ptype == null)) {
1086 pname = t.FullName + "." + Basename;
1087 ptype = RootContext.LookupType (this, pname, true, Location.Null);
1091 if ((ModFlags & Modifiers.NEW) != 0) {
1093 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1094 "inherited member. The keyword new is not required.");
1095 } else if (ptype != null) {
1096 Report.Warning (108, Location, "The keyword new is required on `" +
1097 Name + "' because it hides inherited member '" +
1100 } else if ((ModFlags & Modifiers.NEW) != 0)
1101 Error_KeywordNotAllowed (Location);
1103 if (constants != null)
1104 DefineMembers (constants, defined_names);
1107 DefineMembers (fields, defined_names);
1110 if (instance_constructors == null){
1111 if (default_constructor == null)
1112 DefineDefaultConstructor (false);
1115 if (initialized_static_fields != null &&
1116 default_static_constructor == null)
1117 DefineDefaultConstructor (true);
1120 if (this is Struct){
1122 // Structs can not have initialized instance
1125 if (initialized_static_fields != null &&
1126 default_static_constructor == null)
1127 DefineDefaultConstructor (true);
1129 if (initialized_fields != null)
1130 ReportStructInitializedInstanceError ();
1133 Pending = PendingImplementation.GetPendingImplementations (this);
1136 // Constructors are not in the defined_names array
1138 if (instance_constructors != null)
1139 DefineMembers (instance_constructors, null);
1141 if (default_static_constructor != null)
1142 default_static_constructor.Define (this);
1144 if (methods != null)
1145 DefineMembers (methods, defined_names);
1147 if (properties != null)
1148 DefineMembers (properties, defined_names);
1151 DefineMembers (events, defined_names);
1153 if (indexers != null) {
1156 IndexerName = "Item";
1158 if (operators != null){
1159 DefineMembers (operators, null);
1161 CheckPairedOperators ();
1165 DefineMembers (enums, defined_names);
1167 if (delegates != null)
1168 DefineMembers (delegates, defined_names);
1170 if (CurrentType != null) {
1171 GenericType = CurrentType.ResolveType (ec);
1173 ec.ContainerType = GenericType;
1178 if (TypeBuilder.BaseType != null)
1179 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1181 member_cache = new MemberCache (this);
1188 public override bool Define (TypeContainer container)
1190 if (interface_order != null){
1191 foreach (Interface iface in interface_order)
1192 if ((iface.ModFlags & Modifiers.NEW) == 0)
1193 iface.Define (this);
1200 /// This function is based by a delegate to the FindMembers routine
1202 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1208 /// This filter is used by FindMembers, and we just keep
1209 /// a global for the filter to `AlwaysAccept'
1211 static MemberFilter accepting_filter;
1215 /// A member comparission method based on name only
1217 static IComparer mif_compare;
1219 static TypeContainer ()
1221 accepting_filter = new MemberFilter (AlwaysAccept);
1222 mif_compare = new MemberInfoCompare ();
1226 /// This method returns the members of this type just like Type.FindMembers would
1227 /// Only, we need to use this for types which are _being_ defined because MS'
1228 /// implementation can't take care of that.
1231 // FIXME: return an empty static array instead of null, that cleans up
1232 // some code and is consistent with some coding conventions I just found
1236 // Notice that in various cases we check if our field is non-null,
1237 // something that would normally mean that there was a bug elsewhere.
1239 // The problem happens while we are defining p-invoke methods, as those
1240 // will trigger a FindMembers, but this happens before things are defined
1242 // Since the whole process is a no-op, it is fine to check for null here.
1244 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1245 MemberFilter filter, object criteria)
1247 ArrayList members = null;
1250 if ((bf & BindingFlags.Public) != 0)
1251 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1253 if ((bf & BindingFlags.NonPublic) != 0)
1254 modflags |= Modifiers.PRIVATE;
1256 int static_mask = 0, static_flags = 0;
1257 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1258 case BindingFlags.Static:
1259 static_mask = static_flags = Modifiers.STATIC;
1262 case BindingFlags.Instance:
1263 static_mask = Modifiers.STATIC;
1268 static_mask = static_flags = 0;
1272 Timer.StartTimer (TimerType.TcFindMembers);
1275 filter = accepting_filter;
1277 if ((mt & MemberTypes.Field) != 0) {
1278 if (fields != null) {
1279 int len = fields.Count;
1280 for (int i = 0; i < len; i++) {
1281 Field f = (Field) fields [i];
1283 if ((f.ModFlags & modflags) == 0)
1285 if ((f.ModFlags & static_mask) != static_flags)
1288 FieldBuilder fb = f.FieldBuilder;
1289 if (fb != null && filter (fb, criteria) == true) {
1290 if (members == null)
1291 members = new ArrayList ();
1298 if (constants != null) {
1299 int len = constants.Count;
1300 for (int i = 0; i < len; i++) {
1301 Const con = (Const) constants [i];
1303 if ((con.ModFlags & modflags) == 0)
1305 if ((con.ModFlags & static_mask) != static_flags)
1308 FieldBuilder fb = con.FieldBuilder;
1309 if (fb != null && filter (fb, criteria) == true) {
1310 if (members == null)
1311 members = new ArrayList ();
1319 if ((mt & MemberTypes.Method) != 0) {
1320 if (methods != null) {
1321 int len = methods.Count;
1322 for (int i = 0; i < len; i++) {
1323 Method m = (Method) methods [i];
1325 if ((m.ModFlags & modflags) == 0)
1327 if ((m.ModFlags & static_mask) != static_flags)
1330 MethodBuilder mb = m.MethodBuilder;
1332 if (mb != null && filter (mb, criteria) == true) {
1333 if (members == null)
1334 members = new ArrayList ();
1341 if (operators != null) {
1342 int len = operators.Count;
1343 for (int i = 0; i < len; i++) {
1344 Operator o = (Operator) operators [i];
1346 if ((o.ModFlags & modflags) == 0)
1348 if ((o.ModFlags & static_mask) != static_flags)
1351 MethodBuilder ob = o.OperatorMethodBuilder;
1352 if (ob != null && filter (ob, criteria) == true) {
1353 if (members == null)
1354 members = new ArrayList ();
1361 if (properties != null) {
1362 int len = properties.Count;
1363 for (int i = 0; i < len; i++) {
1364 Property p = (Property) properties [i];
1366 if ((p.ModFlags & modflags) == 0)
1368 if ((p.ModFlags & static_mask) != static_flags)
1374 if (b != null && filter (b, criteria) == true) {
1375 if (members == null)
1376 members = new ArrayList ();
1382 if (b != null && filter (b, criteria) == true) {
1383 if (members == null)
1384 members = new ArrayList ();
1391 if (indexers != null) {
1392 int len = indexers.Count;
1393 for (int i = 0; i < len; i++) {
1394 Indexer ix = (Indexer) indexers [i];
1396 if ((ix.ModFlags & modflags) == 0)
1398 if ((ix.ModFlags & static_mask) != static_flags)
1404 if (b != null && filter (b, criteria) == true) {
1405 if (members == null)
1406 members = new ArrayList ();
1412 if (b != null && filter (b, criteria) == true) {
1413 if (members == null)
1414 members = new ArrayList ();
1422 if ((mt & MemberTypes.Event) != 0) {
1423 if (events != null) {
1424 int len = events.Count;
1425 for (int i = 0; i < len; i++) {
1426 Event e = (Event) events [i];
1428 if ((e.ModFlags & modflags) == 0)
1430 if ((e.ModFlags & static_mask) != static_flags)
1433 MemberInfo eb = e.EventBuilder;
1434 if (eb != null && filter (eb, criteria) == true) {
1435 if (members == null)
1436 members = new ArrayList ();
1438 members.Add (e.EventBuilder);
1444 if ((mt & MemberTypes.Property) != 0){
1445 if (properties != null) {
1446 int len = properties.Count;
1447 for (int i = 0; i < len; i++) {
1448 Property p = (Property) properties [i];
1450 if ((p.ModFlags & modflags) == 0)
1452 if ((p.ModFlags & static_mask) != static_flags)
1455 MemberInfo pb = p.PropertyBuilder;
1456 if (pb != null && filter (pb, criteria) == true) {
1457 if (members == null)
1458 members = new ArrayList ();
1460 members.Add (p.PropertyBuilder);
1465 if (indexers != null) {
1466 int len = indexers.Count;
1467 for (int i = 0; i < len; i++) {
1468 Indexer ix = (Indexer) indexers [i];
1470 if ((ix.ModFlags & modflags) == 0)
1472 if ((ix.ModFlags & static_mask) != static_flags)
1475 MemberInfo ib = ix.PropertyBuilder;
1476 if (ib != null && filter (ib, criteria) == true) {
1477 if (members == null)
1478 members = new ArrayList ();
1480 members.Add (ix.PropertyBuilder);
1486 if ((mt & MemberTypes.NestedType) != 0) {
1487 if (types != null) {
1488 int len = types.Count;
1489 for (int i = 0; i < len; i++) {
1490 TypeContainer t = (TypeContainer) types [i];
1492 if ((t.ModFlags & modflags) == 0)
1495 TypeBuilder tb = t.TypeBuilder;
1496 if (tb != null && (filter (tb, criteria) == true)) {
1497 if (members == null)
1498 members = new ArrayList ();
1505 if (enums != null) {
1506 int len = enums.Count;
1507 for (int i = 0; i < len; i++) {
1508 Enum en = (Enum) enums [i];
1510 if ((en.ModFlags & modflags) == 0)
1513 TypeBuilder tb = en.TypeBuilder;
1514 if (tb != null && (filter (tb, criteria) == true)) {
1515 if (members == null)
1516 members = new ArrayList ();
1523 if (delegates != null) {
1524 int len = delegates.Count;
1525 for (int i = 0; i < len; i++) {
1526 Delegate d = (Delegate) delegates [i];
1528 if ((d.ModFlags & modflags) == 0)
1531 TypeBuilder tb = d.TypeBuilder;
1532 if (tb != null && (filter (tb, criteria) == true)) {
1533 if (members == null)
1534 members = new ArrayList ();
1541 if (interfaces != null) {
1542 int len = interfaces.Count;
1543 for (int i = 0; i < len; i++) {
1544 Interface iface = (Interface) interfaces [i];
1546 if ((iface.ModFlags & modflags) == 0)
1549 TypeBuilder tb = iface.TypeBuilder;
1550 if (tb != null && (filter (tb, criteria) == true)) {
1551 if (members == null)
1552 members = new ArrayList ();
1560 if ((mt & MemberTypes.Constructor) != 0){
1561 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1562 int len = instance_constructors.Count;
1563 for (int i = 0; i < len; i++) {
1564 Constructor c = (Constructor) instance_constructors [i];
1566 ConstructorBuilder cb = c.ConstructorBuilder;
1567 if (cb != null && filter (cb, criteria) == true) {
1568 if (members == null)
1569 members = new ArrayList ();
1576 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1577 ConstructorBuilder cb =
1578 default_static_constructor.ConstructorBuilder;
1580 if (cb != null && filter (cb, criteria) == true) {
1581 if (members == null)
1582 members = new ArrayList ();
1590 // Lookup members in parent if requested.
1592 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1593 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1594 if (list.Count > 0) {
1595 if (members == null)
1596 members = new ArrayList ();
1598 members.AddRange (list);
1602 Timer.StopTimer (TimerType.TcFindMembers);
1604 if (members == null)
1605 return MemberList.Empty;
1607 return new MemberList (members);
1610 public override MemberCache MemberCache {
1612 return member_cache;
1616 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1617 MemberFilter filter, object criteria)
1619 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1622 return ds.FindMembers (mt, bf, filter, criteria);
1624 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1628 // FindMethods will look for methods not only in the type `t', but in
1629 // any interfaces implemented by the type.
1631 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1632 MemberFilter filter, object criteria)
1638 /// Emits the values for the constants
1640 public void EmitConstants ()
1642 if (constants != null)
1643 foreach (Const con in constants)
1644 con.EmitConstant (this);
1649 /// Emits the code, this step is performed after all
1650 /// the types, enumerations, constructors
1654 if (instance_constructors != null)
1655 foreach (Constructor c in instance_constructors)
1658 if (default_static_constructor != null)
1659 default_static_constructor.Emit (this);
1661 if (methods != null)
1662 foreach (Method m in methods)
1665 if (operators != null)
1666 foreach (Operator o in operators)
1669 if (properties != null)
1670 foreach (Property p in properties)
1673 if (indexers != null){
1674 foreach (Indexer ix in indexers)
1677 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1678 this, IndexerName, ModFlags, Location);
1679 TypeBuilder.SetCustomAttribute (cb);
1683 foreach (Field f in fields)
1686 if (events != null){
1687 foreach (Event e in Events)
1691 if (Pending != null)
1692 if (Pending.VerifyPendingMethods ())
1695 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
1698 // Check for internal or private fields that were never assigned
1700 if (RootContext.WarningLevel >= 3) {
1701 if (fields != null){
1702 foreach (Field f in fields) {
1703 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
1706 if ((f.status & Field.Status.USED) == 0){
1708 169, f.Location, "Private field " +
1709 MakeName (f.Name) + " is never used");
1714 // Only report 649 on level 4
1716 if (RootContext.WarningLevel < 4)
1719 if ((f.status & Field.Status.ASSIGNED) != 0)
1724 "Field " + MakeName (f.Name) + " is never assigned " +
1725 " to and will always have its default value");
1729 if (events != null){
1730 foreach (Event e in events){
1732 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1737 // if (types != null)
1738 // foreach (TypeContainer tc in types)
1742 public override void CloseType ()
1749 TypeBuilder.CreateType ();
1750 } catch (TypeLoadException){
1752 // This is fine, the code still created the type
1754 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1755 // Console.WriteLine (e.Message);
1757 Console.WriteLine ("In type: " + Name);
1762 foreach (Enum en in Enums)
1765 if (interface_order != null){
1766 foreach (Interface iface in interface_order)
1771 foreach (TypeContainer tc in Types)
1775 foreach (TypeContainer tc in Types)
1776 if (!(tc is Struct))
1780 if (Delegates != null)
1781 foreach (Delegate d in Delegates)
1789 initialized_fields = null;
1790 initialized_static_fields = null;
1793 interface_order = null;
1799 default_constructor = null;
1800 default_static_constructor = null;
1802 OptAttributes = null;
1804 parent_container = null;
1805 member_cache = null;
1808 public string MakeName (string n)
1810 return "`" + Name + "." + n + "'";
1813 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1816 108, l, "The keyword new is required on " +
1817 MakeName (mi.Name) + " because it hides `" +
1818 mi.ReflectedType.Name + "." + mi.Name + "'");
1821 public void Warning_KeywordNewNotRequired (Location l, MemberCore mc)
1824 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1825 "inherited member, the keyword new is not required");
1828 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
1831 72, l, MakeName (mi.Name) + " : cannot override; `" +
1832 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
1835 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1841 // Performs the validation on a Method's modifiers (properties have
1842 // the same properties).
1844 public bool MethodModifiersValid (int flags, string n, Location loc)
1846 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1847 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1848 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1852 // At most one of static, virtual or override
1854 if ((flags & Modifiers.STATIC) != 0){
1855 if ((flags & vao) != 0){
1857 112, loc, "static method " + MakeName (n) + "can not be marked " +
1858 "as virtual, abstract or override");
1863 if (this is Struct){
1864 if ((flags & va) != 0){
1865 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1870 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1872 113, loc, MakeName (n) +
1873 " marked as override cannot be marked as new or virtual");
1878 // If the declaration includes the abstract modifier, then the
1879 // declaration does not include static, virtual or extern
1881 if ((flags & Modifiers.ABSTRACT) != 0){
1882 if ((flags & Modifiers.EXTERN) != 0){
1884 180, loc, MakeName (n) + " can not be both abstract and extern");
1888 if ((flags & Modifiers.VIRTUAL) != 0){
1890 503, loc, MakeName (n) + " can not be both abstract and virtual");
1894 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1896 513, loc, MakeName (n) +
1897 " is abstract but its container class is not");
1903 if ((flags & Modifiers.PRIVATE) != 0){
1904 if ((flags & vao) != 0){
1906 621, loc, MakeName (n) +
1907 " virtual or abstract members can not be private");
1912 if ((flags & Modifiers.SEALED) != 0){
1913 if ((flags & Modifiers.OVERRIDE) == 0){
1915 238, loc, MakeName (n) +
1916 " cannot be sealed because it is not an override");
1924 Hashtable builder_and_args;
1926 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1928 if (builder_and_args == null)
1929 builder_and_args = new Hashtable ();
1934 /// Performs checks for an explicit interface implementation. First it
1935 /// checks whether the `interface_type' is a base inteface implementation.
1936 /// Then it checks whether `name' exists in the interface type.
1938 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1942 if (ifaces != null){
1943 foreach (TypeExpr t in ifaces){
1944 if (t.Type == interface_type){
1952 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1963 string IMemberContainer.Name {
1969 Type IMemberContainer.Type {
1975 IMemberContainer IMemberContainer.Parent {
1977 return parent_container;
1981 MemberCache IMemberContainer.MemberCache {
1983 return member_cache;
1987 bool IMemberContainer.IsInterface {
1993 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1995 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
1997 if (GenericType != null)
1998 return TypeManager.FindMembers (GenericType, mt, new_bf,
2001 return FindMembers (mt, new_bf, null, null);
2005 // Operator pair checking
2008 class OperatorEntry {
2010 public Type ret_type;
2011 public Type type1, type2;
2013 public Operator.OpType ot;
2015 public OperatorEntry (int f, Operator o)
2019 ret_type = o.OperatorMethod.GetReturnType ();
2020 Type [] pt = o.OperatorMethod.ParameterTypes;
2024 ot = o.OperatorType;
2027 public override int GetHashCode ()
2029 return ret_type.GetHashCode ();
2032 public override bool Equals (object o)
2034 OperatorEntry other = (OperatorEntry) o;
2036 if (other.ret_type != ret_type)
2038 if (other.type1 != type1)
2040 if (other.type2 != type2)
2047 // Checks that some operators come in pairs:
2053 // They are matched based on the return type and the argument types
2055 void CheckPairedOperators ()
2057 Hashtable pairs = new Hashtable (null, null);
2058 Operator true_op = null;
2059 Operator false_op = null;
2060 bool has_equality_or_inequality = false;
2062 // Register all the operators we care about.
2063 foreach (Operator op in operators){
2066 switch (op.OperatorType){
2067 case Operator.OpType.Equality:
2069 has_equality_or_inequality = true;
2071 case Operator.OpType.Inequality:
2073 has_equality_or_inequality = true;
2076 case Operator.OpType.True:
2079 case Operator.OpType.False:
2083 case Operator.OpType.GreaterThan:
2085 case Operator.OpType.LessThan:
2088 case Operator.OpType.GreaterThanOrEqual:
2090 case Operator.OpType.LessThanOrEqual:
2096 OperatorEntry oe = new OperatorEntry (reg, op);
2098 object o = pairs [oe];
2102 oe = (OperatorEntry) o;
2107 if (true_op != null){
2108 if (false_op == null)
2109 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2110 } else if (false_op != null)
2111 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2114 // Look for the mistakes.
2116 foreach (DictionaryEntry de in pairs){
2117 OperatorEntry oe = (OperatorEntry) de.Key;
2124 case Operator.OpType.Equality:
2127 case Operator.OpType.Inequality:
2130 case Operator.OpType.GreaterThan:
2133 case Operator.OpType.LessThan:
2136 case Operator.OpType.GreaterThanOrEqual:
2139 case Operator.OpType.LessThanOrEqual:
2143 Report.Error (216, oe.op.Location,
2144 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2147 if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2148 MethodSignature equals_ms = new MethodSignature (
2149 "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2150 MethodSignature hash_ms = new MethodSignature (
2151 "GetHashCode", TypeManager.int32_type, new Type [0]);
2153 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2154 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2156 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2157 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2160 bool equals_ok = false;
2161 if ((equals_ml != null) && (equals_ml.Count == 1))
2162 equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2163 bool hash_ok = false;
2164 if ((hash_ml != null) && (hash_ml.Count == 1))
2165 hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2168 Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2169 "not override Object.Equals (object o)");
2171 Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2172 "not override Object.GetHashCode ()");
2178 public class Class : TypeContainer {
2180 // Modifiers allowed in a class declaration
2182 public const int AllowedModifiers =
2185 Modifiers.PROTECTED |
2186 Modifiers.INTERNAL |
2188 Modifiers.ABSTRACT |
2192 public Class (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2193 : base (ns, parent, name, attrs, l)
2197 if (parent.Parent == null)
2198 accmods = Modifiers.INTERNAL;
2200 accmods = Modifiers.PRIVATE;
2202 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2206 // FIXME: How do we deal with the user specifying a different
2209 public override TypeAttributes TypeAttr {
2211 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2216 public class Struct : TypeContainer {
2218 // Modifiers allowed in a struct declaration
2220 public const int AllowedModifiers =
2223 Modifiers.PROTECTED |
2224 Modifiers.INTERNAL |
2228 public Struct (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2229 : base (ns, parent, name, attrs, l)
2233 if (parent.Parent == null)
2234 accmods = Modifiers.INTERNAL;
2236 accmods = Modifiers.PRIVATE;
2238 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2240 this.ModFlags |= Modifiers.SEALED;
2244 // FIXME: Allow the user to specify a different set of attributes
2245 // in some cases (Sealed for example is mandatory for a class,
2246 // but what SequentialLayout can be changed
2248 public override TypeAttributes TypeAttr {
2250 return base.TypeAttr |
2251 TypeAttributes.SequentialLayout |
2252 TypeAttributes.Sealed |
2253 TypeAttributes.BeforeFieldInit;
2258 public abstract class MethodCore : MemberBase {
2259 public readonly Parameters Parameters;
2260 protected Block block;
2261 protected DeclSpace ds;
2264 // Parameters, cached for semantic analysis.
2266 protected InternalParameters parameter_info;
2267 protected Type [] parameter_types;
2270 // This is set from TypeContainer.DefineMembers if this method overrides something.
2272 public bool OverridesSomething;
2274 public MethodCore (DeclSpace ds, Expression type, int mod, int allowed_mod,
2275 string name, Attributes attrs, Parameters parameters, Location loc)
2276 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
2278 Parameters = parameters;
2283 // Returns the System.Type array for the parameters of this method
2285 public Type [] ParameterTypes {
2287 return parameter_types;
2291 public InternalParameters ParameterInfo
2294 return parameter_info;
2298 public Block Block {
2308 protected virtual bool DoDefineParameters ()
2310 // Check if arguments were correct
2311 parameter_types = Parameters.GetParameterInfo (ds);
2312 if ((parameter_types == null) || !CheckParameters (ds, parameter_types))
2315 parameter_info = new InternalParameters (ds, Parameters);
2317 Parameter array_param = Parameters.ArrayParameter;
2318 if ((array_param != null) &&
2319 (!array_param.ParameterType.IsArray ||
2320 (array_param.ParameterType.GetArrayRank () != 1))) {
2321 Report.Error (225, Location, "params parameter has to be a single dimensional array");
2328 public CallingConventions GetCallingConvention (bool is_class)
2330 CallingConventions cc = 0;
2332 cc = Parameters.GetCallingConvention ();
2335 if ((ModFlags & Modifiers.STATIC) == 0)
2336 cc |= CallingConventions.HasThis;
2338 // FIXME: How is `ExplicitThis' used in C#?
2344 // The method's attributes are passed in because we need to extract
2345 // the "return:" attribute from there to apply on the return type
2347 static public void LabelParameters (EmitContext ec,
2349 Parameters parameters,
2350 Attributes method_attrs,
2354 // Define each type attribute (in/out/ref) and
2355 // the argument names.
2357 Parameter [] p = parameters.FixedParameters;
2360 MethodBuilder mb = null;
2361 ConstructorBuilder cb = null;
2363 if (builder is MethodBuilder)
2364 mb = (MethodBuilder) builder;
2366 cb = (ConstructorBuilder) builder;
2369 for (i = 0; i < p.Length; i++) {
2370 ParameterBuilder pb;
2371 ParameterAttributes par_attr = p [i].Attributes;
2374 pb = cb.DefineParameter (
2375 i + 1, par_attr, p [i].Name);
2377 pb = mb.DefineParameter (
2378 i + 1, par_attr, p [i].Name);
2380 Attributes attr = p [i].OptAttributes;
2382 Attribute.ApplyAttributes (ec, pb, pb, attr);
2384 if (par_attr == ParameterAttributes.Out){
2385 if (attr.Contains (TypeManager.in_attribute_type))
2386 Report.Error (36, loc,
2387 "Can not use [In] attribute on out parameter");
2393 if (parameters.ArrayParameter != null){
2394 ParameterBuilder pb;
2395 Parameter array_param = parameters.ArrayParameter;
2398 pb = cb.DefineParameter (
2399 i + 1, array_param.Attributes,
2402 pb = mb.DefineParameter (
2403 i + 1, array_param.Attributes,
2406 CustomAttributeBuilder a = new CustomAttributeBuilder (
2407 TypeManager.cons_param_array_attribute, new object [0]);
2409 pb.SetCustomAttribute (a);
2413 // And now for the return type attribute decoration
2415 ParameterBuilder ret_pb;
2416 Attributes ret_attrs = null;
2418 if (mb == null || method_attrs == null)
2421 foreach (AttributeSection asec in method_attrs.AttributeSections) {
2423 if (asec.Target != "return")
2426 if (ret_attrs == null)
2427 ret_attrs = new Attributes (asec);
2429 ret_attrs.AddAttributeSection (asec);
2432 if (ret_attrs != null) {
2434 ret_pb = mb.DefineParameter (0, ParameterAttributes.None, "");
2435 Attribute.ApplyAttributes (ec, ret_pb, ret_pb, ret_attrs);
2437 } catch (ArgumentOutOfRangeException) {
2440 ".NET SDK 1.0 does not permit setting custom attributes" +
2441 " on the return type of a method");
2447 public class Method : MethodCore, IIteratorContainer {
2448 public MethodBuilder MethodBuilder;
2449 public MethodData MethodData;
2450 public readonly GenericMethod GenericMethod;
2453 /// Modifiers allowed in a class declaration
2455 const int AllowedModifiers =
2458 Modifiers.PROTECTED |
2459 Modifiers.INTERNAL |
2464 Modifiers.OVERRIDE |
2465 Modifiers.ABSTRACT |
2470 // return_type can be "null" for VOID values.
2472 public Method (DeclSpace ds, Expression return_type, int mod, string name,
2473 Parameters parameters, Attributes attrs, Location l)
2474 : base (ds, return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2477 public Method (GenericMethod generic, Expression return_type, int mod, string name,
2478 Parameters parameters, Attributes attrs, Location l)
2479 : base (generic, return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2481 GenericMethod = generic;
2485 // Returns the `System.Type' for the ReturnType of this
2486 // function. Provides a nice cache. (used between semantic analysis
2487 // and actual code generation
2489 public Type GetReturnType ()
2494 // Whether this is an operator method.
2495 public bool IsOperator;
2497 void DuplicateEntryPoint (MethodInfo b, Location location)
2501 "Program `" + CodeGen.FileName +
2502 "' has more than one entry point defined: `" +
2503 TypeManager.CSharpSignature(b) + "'");
2506 void Report28 (MethodInfo b)
2510 "`" + TypeManager.CSharpSignature(b) +
2511 "' has the wrong signature to be an entry point");
2514 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2516 if (b.ReturnType != TypeManager.void_type &&
2517 b.ReturnType != TypeManager.int32_type)
2520 if (pinfo.Count == 0)
2523 if (pinfo.Count > 1)
2526 Type t = pinfo.ParameterType(0);
2528 (t.GetArrayRank() == 1) &&
2529 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
2530 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2537 // Checks our base implementation if any
2539 protected override bool CheckBase (TypeContainer container)
2541 base.CheckBase (container);
2543 // Check whether arguments were correct.
2544 if (!DoDefineParameters ())
2547 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2549 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2553 mi_this = TypeContainer.FindMembers (
2554 container.TypeBuilder, MemberTypes.Method,
2555 BindingFlags.NonPublic | BindingFlags.Public |
2556 BindingFlags.Static | BindingFlags.Instance |
2557 BindingFlags.DeclaredOnly,
2558 MethodSignature.method_signature_filter, ms);
2560 if (mi_this.Count > 0) {
2561 Report.Error (111, Location, "Class `" + container.Name + "' " +
2562 "already defines a member called `" + Name + "' " +
2563 "with the same parameter types");
2569 // Verify if the parent has a type with the same name, and then
2570 // check whether we have to create a new slot for it or not.
2572 Type ptype = container.TypeBuilder.BaseType;
2574 // ptype is only null for System.Object while compiling corlib.
2576 MemberList mi, mi_static, mi_instance;
2578 mi_instance = TypeContainer.FindMembers (
2579 ptype, MemberTypes.Method,
2580 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2581 MethodSignature.inheritable_method_signature_filter,
2584 if (mi_instance.Count > 0){
2587 mi_static = TypeContainer.FindMembers (
2588 ptype, MemberTypes.Method,
2589 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2590 MethodSignature.inheritable_method_signature_filter, ms);
2592 if (mi_static.Count > 0)
2598 if (mi != null && mi.Count > 0){
2599 parent_method = (MethodInfo) mi [0];
2600 string name = parent_method.DeclaringType.Name + "." +
2603 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
2606 if ((ModFlags & Modifiers.NEW) == 0) {
2607 Type parent_ret = TypeManager.TypeToCoreType (
2608 parent_method.ReturnType);
2610 if (parent_ret != MemberType) {
2612 508, Location, container.MakeName (Name) + ": cannot " +
2613 "change return type when overriding " +
2614 "inherited member " + name);
2619 if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
2620 WarningNotHiding (container);
2622 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2623 Report.Error (115, Location,
2624 container.MakeName (Name) +
2625 " no suitable methods found to override");
2628 } else if ((ModFlags & Modifiers.NEW) != 0)
2629 WarningNotHiding (container);
2637 public override bool Define (TypeContainer container)
2640 MethodBuilder mb = null;
2641 if (GenericMethod != null) {
2642 mb = container.TypeBuilder.DefineGenericMethod (Name, flags);
2643 if (!GenericMethod.Define (mb))
2645 decl = GenericMethod;
2649 if (!DoDefine (decl, container))
2652 if (!CheckBase (container))
2655 CallingConventions cc = GetCallingConvention (container is Class);
2657 MethodData = new MethodData (ds, this, null, MemberType,
2658 ParameterTypes, ParameterInfo, cc,
2659 OptAttributes, ModFlags, flags, true, mb);
2661 if (!MethodData.Define (container))
2665 // Setup iterator if we are one
2667 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
2668 IteratorHandler ih = new IteratorHandler (
2669 Name, container, MemberType,
2670 ParameterTypes, ParameterInfo,
2671 ModFlags, Location);
2673 Block new_block = ih.Setup (block);
2674 if (new_block == null)
2679 MethodBuilder = MethodData.MethodBuilder;
2682 // This is used to track the Entry Point,
2684 if (Name == "Main" &&
2685 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
2686 (RootContext.MainClass == null ||
2687 RootContext.MainClass == container.TypeBuilder.FullName)){
2688 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2689 if (RootContext.EntryPoint == null) {
2690 if (container.IsGeneric){
2691 Report.Error (-201, Location,
2692 "Entry point can not be defined in a generic class");
2695 RootContext.EntryPoint = MethodBuilder;
2696 RootContext.EntryPointLocation = Location;
2698 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2699 DuplicateEntryPoint (MethodBuilder, Location);
2702 Report28(MethodBuilder);
2711 public void Emit (TypeContainer container)
2713 MethodData.Emit (container, Block, this);
2718 void IIteratorContainer.SetYields ()
2720 ModFlags |= Modifiers.METHOD_YIELDS;
2724 public abstract class ConstructorInitializer {
2725 ArrayList argument_list;
2726 ConstructorInfo parent_constructor;
2727 Parameters parameters;
2730 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2733 this.argument_list = argument_list;
2734 this.parameters = parameters;
2738 public ArrayList Arguments {
2740 return argument_list;
2744 public bool Resolve (EmitContext ec)
2746 Expression parent_constructor_group;
2749 ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
2751 if (argument_list != null){
2752 foreach (Argument a in argument_list){
2753 if (!a.Resolve (ec, loc))
2757 ec.CurrentBlock = null;
2759 if (this is ConstructorBaseInitializer) {
2760 if (ec.ContainerType.BaseType == null)
2763 t = ec.ContainerType.BaseType;
2764 if (ec.ContainerType.IsValueType) {
2765 Report.Error (522, loc,
2766 "structs cannot call base class constructors");
2770 t = ec.ContainerType;
2772 parent_constructor_group = Expression.MemberLookup (
2773 ec, t, null, t, ".ctor",
2774 MemberTypes.Constructor,
2775 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2778 if (parent_constructor_group == null){
2779 Report.Error (1501, loc,
2780 "Can not find a constructor for this argument list");
2784 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2785 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2787 if (parent_constructor == null){
2788 Report.Error (1501, loc,
2789 "Can not find a constructor for this argument list");
2796 public void Emit (EmitContext ec)
2798 if (parent_constructor != null){
2799 ec.Mark (loc, false);
2801 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2803 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
2808 public class ConstructorBaseInitializer : ConstructorInitializer {
2809 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2810 base (argument_list, pars, l)
2815 public class ConstructorThisInitializer : ConstructorInitializer {
2816 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2817 base (argument_list, pars, l)
2822 public class Constructor : MethodCore {
2823 public ConstructorBuilder ConstructorBuilder;
2824 public ConstructorInitializer Initializer;
2827 // Modifiers allowed for a constructor.
2829 public const int AllowedModifiers =
2831 Modifiers.PROTECTED |
2832 Modifiers.INTERNAL |
2839 // The spec claims that static is not permitted, but
2840 // my very own code has static constructors.
2842 public Constructor (DeclSpace ds, string name, Parameters args,
2843 ConstructorInitializer init, Location l)
2844 : base (ds, null, 0, AllowedModifiers, name, null, args, l)
2850 // Returns true if this is a default constructor
2852 public bool IsDefault ()
2854 if ((ModFlags & Modifiers.STATIC) != 0)
2855 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2856 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2859 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2860 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2861 (Initializer is ConstructorBaseInitializer) &&
2862 (Initializer.Arguments == null);
2866 // Creates the ConstructorBuilder
2868 public override bool Define (TypeContainer container)
2870 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2871 MethodAttributes.SpecialName);
2873 // Check if arguments were correct.
2874 if (!DoDefineParameters ())
2877 if ((ModFlags & Modifiers.STATIC) != 0){
2878 ca |= MethodAttributes.Static | MethodAttributes.Private;
2880 if (container is Struct && ParameterTypes.Length == 0){
2883 "Structs can not contain explicit parameterless " +
2887 ca |= MethodAttributes.HideBySig;
2889 if ((ModFlags & Modifiers.PUBLIC) != 0)
2890 ca |= MethodAttributes.Public;
2891 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2892 if ((ModFlags & Modifiers.INTERNAL) != 0)
2893 ca |= MethodAttributes.FamORAssem;
2895 ca |= MethodAttributes.Family;
2896 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2897 ca |= MethodAttributes.Assembly;
2898 else if (IsDefault ())
2899 ca |= MethodAttributes.Public;
2901 ca |= MethodAttributes.Private;
2904 ConstructorBuilder = container.TypeBuilder.DefineConstructor (
2905 ca, GetCallingConvention (container is Class), ParameterTypes);
2907 if ((ModFlags & Modifiers.UNSAFE) != 0)
2908 ConstructorBuilder.InitLocals = false;
2911 // HACK because System.Reflection.Emit is lame
2913 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2916 "Class `" +container.Name+ "' already contains a definition with the " +
2917 "same return value and parameter types for constructor `" + Name
2928 public void Emit (TypeContainer container)
2930 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2931 EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
2934 // extern methods have no bodies
2936 if ((ModFlags & Modifiers.EXTERN) != 0) {
2937 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
2939 179, Location, "External constructor `" +
2940 TypeManager.CSharpSignature (ConstructorBuilder) +
2941 "' can not have a body");
2944 } else if (block == null) {
2946 501, Location, "Constructor `" +
2947 TypeManager.CSharpSignature (ConstructorBuilder) +
2948 "' must declare a body since it is not marked extern");
2952 if ((ModFlags & Modifiers.STATIC) == 0){
2953 if (container is Class && Initializer == null)
2954 Initializer = new ConstructorBaseInitializer (
2955 null, Parameters.EmptyReadOnlyParameters, Location);
2959 // Spec mandates that Initializers will not have
2963 if (Initializer != null && !Initializer.Resolve (ec))
2965 ec.IsStatic = false;
2968 MethodCore.LabelParameters (ec, ConstructorBuilder,
2969 Parameters, OptAttributes, Location);
2971 SymbolWriter sw = CodeGen.SymbolWriter;
2972 bool generate_debugging = false;
2974 if ((sw != null) && (block != null) &&
2975 !Location.IsNull (Location) &&
2976 !Location.IsNull (block.EndLocation)) {
2978 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
2980 generate_debugging = true;
2984 // Classes can have base initializers and instance field initializers.
2986 if (container is Class){
2987 if ((ModFlags & Modifiers.STATIC) == 0){
2990 // If we use a "this (...)" constructor initializer, then
2991 // do not emit field initializers, they are initialized in the other constructor
2993 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
2994 container.EmitFieldInitializers (ec);
2997 if (Initializer != null)
2998 Initializer.Emit (ec);
3000 if ((ModFlags & Modifiers.STATIC) != 0)
3001 container.EmitFieldInitializers (ec);
3003 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes);
3005 // If this is a non-static `struct' constructor and doesn't have any
3006 // initializer, it must initialize all of the struct's fields.
3007 if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
3008 Block.AddThisVariable (container, Location);
3010 ec.EmitTopBlock (block, ParameterInfo, Location);
3012 if (generate_debugging)
3020 // Encapsulates most of the Method's state
3022 public class MethodData {
3024 // The return type of this method
3026 public readonly Type ReturnType;
3027 public readonly Type[] ParameterTypes;
3028 public readonly InternalParameters ParameterInfo;
3029 public readonly CallingConventions CallingConventions;
3030 public readonly Attributes OptAttributes;
3031 public readonly Location Location;
3034 // Are we implementing an interface ?
3036 public bool IsImplementing = false;
3041 protected DeclSpace ds;
3042 protected MemberBase member;
3043 protected int modifiers;
3044 protected MethodAttributes flags;
3045 protected bool is_method;
3046 protected string accessor_name;
3049 // It can either hold a string with the condition, or an arraylist of conditions.
3050 object conditionals;
3052 MethodBuilder builder = null;
3053 public MethodBuilder MethodBuilder {
3059 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
3060 Type [] parameter_types, InternalParameters parameters,
3061 CallingConventions cc, Attributes opt_attrs,
3062 int modifiers, MethodAttributes flags, bool is_method)
3065 this.member = member;
3066 this.accessor_name = name;
3067 this.ReturnType = return_type;
3068 this.ParameterTypes = parameter_types;
3069 this.ParameterInfo = parameters;
3070 this.CallingConventions = cc;
3071 this.OptAttributes = opt_attrs;
3072 this.modifiers = modifiers;
3074 this.is_method = is_method;
3075 this.Location = member.Location;
3076 this.conditionals = null;
3079 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
3080 Type [] parameter_types, InternalParameters parameters,
3081 CallingConventions cc, Attributes opt_attrs,
3082 int modifiers, MethodAttributes flags, bool is_method,
3083 MethodBuilder builder)
3084 : this (ds, member, name, return_type, parameter_types, parameters,
3085 cc, opt_attrs, modifiers, flags, is_method)
3087 this.builder = builder;
3093 Attribute dllimport_attribute = null;
3094 string obsolete = null;
3095 bool obsolete_error = false;
3097 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
3099 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
3102 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
3103 if (asec.Attributes == null)
3106 foreach (Attribute a in asec.Attributes) {
3107 if (a.Name == "Conditional") {
3108 if (!ApplyConditionalAttribute (a))
3110 } else if (a.Name == "Obsolete") {
3111 if (!ApplyObsoleteAttribute (a))
3113 } else if (a.Name.IndexOf ("DllImport") != -1) {
3115 a.Type = TypeManager.dllimport_type;
3116 Attribute.Error_AttributeNotValidForElement (a, Location);
3119 if (!ApplyDllImportAttribute (a))
3129 // Applies the `DllImport' attribute to the method.
3131 protected virtual bool ApplyDllImportAttribute (Attribute a)
3133 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3134 if ((modifiers & extern_static) != extern_static) {
3135 Report.Error (601, Location,
3136 "The DllImport attribute must be specified on a method " +
3137 "marked `static' and `extern'.");
3141 flags |= MethodAttributes.PinvokeImpl;
3142 dllimport_attribute = a;
3147 // Applies the `Obsolete' attribute to the method.
3149 protected virtual bool ApplyObsoleteAttribute (Attribute a)
3151 if (obsolete != null) {
3152 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
3156 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
3157 return obsolete != null;
3161 // Applies the `Conditional' attribute to the method.
3163 protected virtual bool ApplyConditionalAttribute (Attribute a)
3165 // The Conditional attribute is only valid on methods.
3167 Attribute.Error_AttributeNotValidForElement (a, Location);
3171 string condition = a.Conditional_GetConditionName ();
3173 if (condition == null)
3176 if (ReturnType != TypeManager.void_type) {
3177 Report.Error (578, Location,
3178 "Conditional not valid on `" + member.Name + "' " +
3179 "because its return type is not void");
3183 if ((modifiers & Modifiers.OVERRIDE) != 0) {
3184 Report.Error (243, Location,
3185 "Conditional not valid on `" + member.Name + "' " +
3186 "because it is an override method");
3190 if (member.IsExplicitImpl) {
3191 Report.Error (577, Location,
3192 "Conditional not valid on `" + member.Name + "' " +
3193 "because it is an explicit interface implementation");
3197 if (IsImplementing) {
3198 Report.Error (623, Location,
3199 "Conditional not valid on `" + member.Name + "' " +
3200 "because it is an interface method");
3205 // The likelyhood that the conditional will be more than 1 is very slim
3207 if (conditionals == null)
3208 conditionals = condition;
3209 else if (conditionals is string){
3210 string s = (string) conditionals;
3211 conditionals = new ArrayList ();
3212 ((ArrayList)conditionals).Add (s);
3214 ((ArrayList)conditionals).Add (condition);
3220 // Checks whether this method should be ignored due to its Conditional attributes.
3222 bool ShouldIgnore (Location loc)
3224 // When we're overriding a virtual method, we implicitly inherit the
3225 // Conditional attributes from our parent.
3226 if (member.ParentMethod != null) {
3227 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3228 member.ParentMethod, loc);
3230 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3234 if (conditionals != null){
3235 if (conditionals is string){
3236 if (RootContext.AllDefines [conditionals] == null)
3239 foreach (string condition in (ArrayList) conditionals)
3240 if (RootContext.AllDefines [condition] == null)
3248 // Returns the TypeManager.MethodFlags for this method.
3249 // This emits an error 619 / warning 618 if the method is obsolete.
3250 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3252 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3254 TypeManager.MethodFlags flags = 0;
3256 if (obsolete != null) {
3257 if (obsolete_error) {
3258 Report.Error (619, loc, "Method `" + member.Name +
3259 "' is obsolete: `" + obsolete + "'");
3260 return TypeManager.MethodFlags.IsObsoleteError;
3262 Report.Warning (618, loc, "Method `" + member.Name +
3263 "' is obsolete: `" + obsolete + "'");
3265 flags |= TypeManager.MethodFlags.IsObsolete;
3268 if (ShouldIgnore (loc))
3269 flags |= TypeManager.MethodFlags.ShouldIgnore;
3274 public virtual bool Define (TypeContainer container)
3276 MethodInfo implementing = null;
3277 string method_name, name, prefix;
3279 if (OptAttributes != null)
3280 if (!ApplyAttributes (OptAttributes, is_method))
3283 if (member.IsExplicitImpl)
3284 prefix = member.InterfaceType.FullName + ".";
3288 if (accessor_name != null)
3289 name = accessor_name + "_" + member.ShortName;
3291 name = member.ShortName;
3292 method_name = prefix + name;
3294 if (container.Pending != null){
3295 if (member is Indexer)
3296 implementing = container.Pending.IsInterfaceIndexer (
3297 member.InterfaceType, ReturnType, ParameterTypes);
3299 implementing = container.Pending.IsInterfaceMethod (
3300 member.InterfaceType, name, ReturnType, ParameterTypes);
3302 if (member.InterfaceType != null && implementing == null){
3303 Report.Error (539, Location, "'{0}' in explicit interface declaration is not an interface", method_name);
3309 // For implicit implementations, make sure we are public, for
3310 // explicit implementations, make sure we are private.
3312 if (implementing != null){
3314 // Setting null inside this block will trigger a more
3315 // verbose error reporting for missing interface implementations
3317 // The "candidate" function has been flagged already
3318 // but it wont get cleared
3320 if (member.IsExplicitImpl){
3321 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3322 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3323 implementing = null;
3325 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
3326 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
3328 // If this is an interface method implementation,
3329 // check for public accessibility
3331 implementing = null;
3332 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
3333 // We may never be private.
3334 implementing = null;
3335 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
3337 // We may be protected if we're overriding something.
3339 implementing = null;
3344 // Static is not allowed
3346 if ((modifiers & Modifiers.STATIC) != 0){
3347 implementing = null;
3348 Modifiers.Error_InvalidModifier (Location, "static");
3353 // If implementing is still valid, set flags
3355 if (implementing != null){
3357 // When implementing interface methods, set NewSlot
3358 // unless, we are overwriting a method.
3360 if (implementing.DeclaringType.IsInterface){
3361 if ((modifiers & Modifiers.OVERRIDE) == 0)
3362 flags |= MethodAttributes.NewSlot;
3365 MethodAttributes.Virtual |
3366 MethodAttributes.HideBySig;
3368 // Set Final unless we're virtual, abstract or already overriding a method.
3369 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
3370 flags |= MethodAttributes.Final;
3372 // Get the method name from the explicit interface.
3373 if (member.InterfaceType != null) {
3374 name = implementing.Name;
3375 method_name = prefix + name;
3378 IsImplementing = true;
3382 // Create the MethodBuilder for the method
3384 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3385 if ((modifiers & Modifiers.STATIC) == 0) {
3386 Report.Error (601, Location,
3387 "The DllImport attribute must be specified on " +
3388 "a method marked 'static' and 'extern'.");
3392 EmitContext ec = new EmitContext (
3393 container, ds, Location, null, ReturnType, modifiers, false);
3395 builder = dllimport_attribute.DefinePInvokeMethod (
3396 ec, container.TypeBuilder, method_name, flags,
3397 ReturnType, ParameterTypes);
3398 } else if (builder == null)
3399 builder = container.TypeBuilder.DefineMethod (
3400 method_name, flags, CallingConventions,
3401 ReturnType, ParameterTypes);
3403 builder.SetGenericMethodSignature (
3404 flags, CallingConventions,
3405 ReturnType, ParameterTypes);
3407 if (builder == null)
3410 if ((modifiers & Modifiers.UNSAFE) != 0)
3411 builder.InitLocals = false;
3413 if (IsImplementing){
3415 // clear the pending implemntation flag
3417 if (member is Indexer) {
3418 container.Pending.ImplementIndexer (
3419 member.InterfaceType, builder, ReturnType,
3420 ParameterTypes, true);
3422 container.Pending.ImplementMethod (
3423 member.InterfaceType, name, ReturnType,
3424 ParameterTypes, member.IsExplicitImpl);
3426 if (member.IsExplicitImpl)
3427 container.TypeBuilder.DefineMethodOverride (
3428 builder, implementing);
3432 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3433 Report.Error (111, Location,
3434 "Class `" + container.Name +
3435 "' already contains a definition with the " +
3436 "same return value and parameter types as the " +
3437 "'get' method of property `" + member.Name + "'");
3441 TypeManager.AddMethod (builder, this);
3449 public virtual void Emit (TypeContainer container, Block block, object kind)
3454 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3455 ig = builder.GetILGenerator ();
3459 ec = new EmitContext (container, ds, Location, ig, ReturnType, modifiers, false);
3461 if (OptAttributes != null)
3462 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes);
3464 if (member is MethodCore)
3465 MethodCore.LabelParameters (ec, MethodBuilder,
3466 ((MethodCore) member).Parameters,
3471 // abstract or extern methods have no bodies
3473 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3474 if (block == null) {
3475 SymbolWriter sw = CodeGen.SymbolWriter;
3477 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0)) {
3478 sw.OpenMethod (container, MethodBuilder, Location, Location);
3486 // abstract or extern methods have no bodies.
3488 if ((modifiers & Modifiers.ABSTRACT) != 0)
3490 500, Location, "Abstract method `" +
3491 TypeManager.CSharpSignature (builder) +
3492 "' can not have a body");
3494 if ((modifiers & Modifiers.EXTERN) != 0)
3496 179, Location, "External method `" +
3497 TypeManager.CSharpSignature (builder) +
3498 "' can not have a body");
3504 // Methods must have a body unless they're extern or abstract
3506 if (block == null) {
3508 501, Location, "Method `" +
3509 TypeManager.CSharpSignature (builder) +
3510 "' must declare a body since it is not marked " +
3511 "abstract or extern");
3516 // Handle destructors specially
3518 // FIXME: This code generates buggy code
3520 if (member is Destructor)
3521 EmitDestructor (ec, block);
3523 SymbolWriter sw = CodeGen.SymbolWriter;
3525 if ((sw != null) && !Location.IsNull (Location) &&
3526 !Location.IsNull (block.EndLocation)) {
3527 sw.OpenMethod (container, MethodBuilder, Location, block.EndLocation);
3529 ec.EmitTopBlock (block, ParameterInfo, Location);
3533 ec.EmitTopBlock (block, ParameterInfo, Location);
3537 void EmitDestructor (EmitContext ec, Block block)
3539 ILGenerator ig = ec.ig;
3541 Label finish = ig.DefineLabel ();
3543 block.SetDestructor ();
3545 ig.BeginExceptionBlock ();
3546 ec.ReturnLabel = finish;
3547 ec.HasReturnLabel = true;
3548 ec.EmitTopBlock (block, null, Location);
3550 // ig.MarkLabel (finish);
3551 ig.BeginFinallyBlock ();
3553 if (ec.ContainerType.BaseType != null) {
3554 Expression member_lookup = Expression.MemberLookup (
3555 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3556 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, Location);
3558 if (member_lookup != null){
3559 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3561 ig.Emit (OpCodes.Ldarg_0);
3562 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3566 ig.EndExceptionBlock ();
3567 //ig.MarkLabel (ec.ReturnLabel);
3568 ig.Emit (OpCodes.Ret);
3572 public class Destructor : Method {
3574 public Destructor (DeclSpace ds, Expression return_type, int mod, string name,
3575 Parameters parameters, Attributes attrs, Location l)
3576 : base (ds, return_type, mod, name, parameters, attrs, l)
3581 abstract public class MemberBase : MemberCore {
3582 public Expression Type;
3584 protected MethodAttributes flags;
3586 protected readonly int explicit_mod_flags;
3589 // The "short" name of this property / indexer / event. This is the
3590 // name without the explicit interface.
3592 public string ShortName;
3595 // The type of this property / indexer / event
3597 public Type MemberType;
3600 // If true, this is an explicit interface implementation
3602 public bool IsExplicitImpl = false;
3605 // The name of the interface we are explicitly implementing
3607 public string ExplicitInterfaceName = null;
3610 // If true, the interface type we are explicitly implementing
3612 public Type InterfaceType = null;
3615 // The method we're overriding if this is an override method.
3617 protected MethodInfo parent_method = null;
3618 public MethodInfo ParentMethod {
3620 return parent_method;
3625 // The constructor is only exposed to our children
3627 protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod, string name,
3628 Attributes attrs, Location loc)
3629 : base (name, attrs, loc)
3631 explicit_mod_flags = mod;
3633 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
3636 protected virtual bool CheckBase (TypeContainer container)
3638 if ((container is Struct) || (RootContext.WarningLevel > 3)){
3639 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
3640 if (container is Struct){
3641 Report.Error (666, Location, "Protected member in struct declaration");
3644 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
3650 protected void WarningNotHiding (TypeContainer parent)
3654 "The member " + parent.MakeName (Name) + " does not hide an " +
3655 "inherited member. The keyword new is not required");
3659 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
3663 // FIXME: report the old/new permissions?
3666 507, Location, parent.MakeName (Name) +
3667 ": can't change the access modifiers when overriding inherited " +
3668 "member `" + name + "'");
3672 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3673 // that have been defined.
3675 // `name' is the user visible name for reporting errors (this is used to
3676 // provide the right name regarding method names and properties)
3678 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
3679 MethodInfo mb, string name)
3683 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3684 if (!(mb.IsAbstract || mb.IsVirtual)){
3686 506, Location, parent.MakeName (Name) +
3687 ": cannot override inherited member `" +
3688 name + "' because it is not " +
3689 "virtual, abstract or override");
3693 // Now we check that the overriden method is not final
3696 // This happens when implementing interface methods.
3697 if (mb.IsHideBySig && mb.IsVirtual) {
3699 506, Location, parent.MakeName (Name) +
3700 ": cannot override inherited member `" +
3701 name + "' because it is not " +
3702 "virtual, abstract or override");
3704 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
3705 "override inherited member `" + name +
3706 "' because it is sealed.");
3710 // Check that the permissions are not being changed
3712 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
3713 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
3716 // special case for "protected internal"
3719 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3721 // when overriding protected internal, the method can be declared
3722 // protected internal only within the same assembly
3725 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3726 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
3728 // assemblies differ - report an error
3731 Error_CannotChangeAccessModifiers (parent, mb, name);
3733 } else if (thisp != parentp) {
3735 // same assembly, but other attributes differ - report an error
3738 Error_CannotChangeAccessModifiers (parent, mb, name);
3741 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3743 // if it's not "protected internal", it must be "protected"
3746 Error_CannotChangeAccessModifiers (parent, mb, name);
3748 } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
3750 // protected within the same assembly - an error
3752 Error_CannotChangeAccessModifiers (parent, mb, name);
3754 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3755 (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3757 // protected ok, but other attributes differ - report an error
3759 Error_CannotChangeAccessModifiers (parent, mb, name);
3763 if (thisp != parentp){
3764 Error_CannotChangeAccessModifiers (parent, mb, name);
3770 if (mb.IsVirtual || mb.IsAbstract){
3771 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
3772 if (Name != "Finalize"){
3774 114, 2, Location, parent.MakeName (Name) +
3775 " hides inherited member `" + name +
3776 "'. To make the current member override that " +
3777 "implementation, add the override keyword, " +
3778 "otherwise use the new keyword");
3779 ModFlags |= Modifiers.NEW;
3783 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
3784 if (Name != "Finalize"){
3786 108, 1, Location, "The keyword new is required on " +
3787 parent.MakeName (Name) + " because it hides " +
3788 "inherited member `" + name + "'");
3789 ModFlags |= Modifiers.NEW;
3797 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
3801 foreach (Type partype in parameters){
3802 if (partype.IsPointer){
3805 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
3809 if (ds.AsAccessible (partype, ModFlags))
3812 if (this is Indexer)
3813 Report.Error (55, Location,
3814 "Inconsistent accessibility: parameter type `" +
3815 TypeManager.CSharpName (partype) + "' is less " +
3816 "accessible than indexer `" + Name + "'");
3817 else if ((this is Method) && ((Method) this).IsOperator)
3818 Report.Error (57, Location,
3819 "Inconsistent accessibility: parameter type `" +
3820 TypeManager.CSharpName (partype) + "' is less " +
3821 "accessible than operator `" + Name + "'");
3823 Report.Error (51, Location,
3824 "Inconsistent accessibility: parameter type `" +
3825 TypeManager.CSharpName (partype) + "' is less " +
3826 "accessible than method `" + Name + "'");
3833 protected virtual bool DoDefine (DeclSpace decl, TypeContainer container)
3838 if (!container.MethodModifiersValid (ModFlags, Name, Location))
3841 flags = Modifiers.MethodAttr (ModFlags);
3843 // Lookup Type, verify validity
3844 MemberType = decl.ResolveType (Type, false, Location);
3845 if (MemberType == null)
3848 if ((container.ModFlags & Modifiers.SEALED) != 0){
3849 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
3850 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
3855 // verify accessibility
3856 if (!container.AsAccessible (MemberType, ModFlags)) {
3857 if (this is Property)
3858 Report.Error (53, Location,
3859 "Inconsistent accessibility: property type `" +
3860 TypeManager.CSharpName (MemberType) + "' is less " +
3861 "accessible than property `" + Name + "'");
3862 else if (this is Indexer)
3863 Report.Error (54, Location,
3864 "Inconsistent accessibility: indexer return type `" +
3865 TypeManager.CSharpName (MemberType) + "' is less " +
3866 "accessible than indexer `" + Name + "'");
3867 else if (this is Method) {
3868 if (((Method) this).IsOperator)
3869 Report.Error (56, Location,
3870 "Inconsistent accessibility: return type `" +
3871 TypeManager.CSharpName (MemberType) + "' is less " +
3872 "accessible than operator `" + Name + "'");
3874 Report.Error (50, Location,
3875 "Inconsistent accessibility: return type `" +
3876 TypeManager.CSharpName (MemberType) + "' is less " +
3877 "accessible than method `" + Name + "'");
3879 Report.Error (52, Location,
3880 "Inconsistent accessibility: field type `" +
3881 TypeManager.CSharpName (MemberType) + "' is less " +
3882 "accessible than field `" + Name + "'");
3886 if (MemberType.IsPointer && !UnsafeOK (container))
3890 // Check for explicit interface implementation
3892 if ((ExplicitInterfaceName == null) && (Name.IndexOf ('.') != -1)){
3893 int pos = Name.LastIndexOf ('.');
3895 ExplicitInterfaceName = Name.Substring (0, pos);
3896 ShortName = Name.Substring (pos + 1);
3900 if (ExplicitInterfaceName != null) {
3901 InterfaceType = RootContext.LookupType (
3902 container, ExplicitInterfaceName, false, Location);
3903 if (InterfaceType == null)
3906 if (InterfaceType.IsClass) {
3907 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
3911 // Compute the full name that we need to export.
3912 Name = InterfaceType.FullName + "." + ShortName;
3914 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
3917 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
3919 IsExplicitImpl = true;
3921 IsExplicitImpl = false;
3928 // Fields and Events both generate FieldBuilders, we use this to share
3929 // their common bits. This is also used to flag usage of the field
3931 abstract public class FieldBase : MemberBase {
3932 public FieldBuilder FieldBuilder;
3933 public Status status;
3936 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3939 // The constructor is only exposed to our children
3941 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3942 object init, Attributes attrs, Location loc)
3943 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
3949 // Whether this field has an initializer.
3951 public bool HasInitializer {
3953 return init != null;
3957 protected readonly Object init;
3959 Expression init_expr;
3960 bool init_expr_initialized = false;
3963 // Resolves and returns the field initializer.
3965 public Expression GetInitializerExpression (EmitContext ec)
3967 if (init_expr_initialized)
3971 if (init is Expression)
3972 e = (Expression) init;
3974 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3976 ec.IsFieldInitializer = true;
3977 e = e.DoResolve (ec);
3978 ec.IsFieldInitializer = false;
3981 init_expr_initialized = true;
3986 public void SetAssigned ()
3988 status |= Status.ASSIGNED;
3993 // The Field class is used to represents class/struct fields during parsing.
3995 public class Field : FieldBase {
3997 // Modifiers allowed in a class declaration
3999 const int AllowedModifiers =
4002 Modifiers.PROTECTED |
4003 Modifiers.INTERNAL |
4006 Modifiers.VOLATILE |
4010 public Field (Expression type, int mod, string name, Object expr_or_array_init,
4011 Attributes attrs, Location loc)
4012 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
4016 public override bool Define (TypeContainer container)
4018 Type t = container.ResolveType (Type, false, Location);
4023 CheckBase (container);
4025 if (!container.AsAccessible (t, ModFlags)) {
4026 Report.Error (52, Location,
4027 "Inconsistent accessibility: field type `" +
4028 TypeManager.CSharpName (t) + "' is less " +
4029 "accessible than field `" + Name + "'");
4033 if (t.IsPointer && !UnsafeOK (container))
4036 if (RootContext.WarningLevel > 1){
4037 Type ptype = container.TypeBuilder.BaseType;
4039 // ptype is only null for System.Object while compiling corlib.
4041 TypeContainer.FindMembers (
4042 ptype, MemberTypes.Method,
4043 BindingFlags.Public |
4044 BindingFlags.Static | BindingFlags.Instance,
4045 System.Type.FilterName, Name);
4049 if ((ModFlags & Modifiers.VOLATILE) != 0){
4053 if (TypeManager.IsEnumType (vt))
4054 vt = TypeManager.EnumToUnderlying (t);
4056 if (!((vt == TypeManager.bool_type) ||
4057 (vt == TypeManager.sbyte_type) ||
4058 (vt == TypeManager.byte_type) ||
4059 (vt == TypeManager.short_type) ||
4060 (vt == TypeManager.ushort_type) ||
4061 (vt == TypeManager.int32_type) ||
4062 (vt == TypeManager.uint32_type) ||
4063 (vt == TypeManager.char_type) ||
4064 (vt == TypeManager.float_type))){
4066 677, Location, container.MakeName (Name) +
4067 " A volatile field can not be of type `" +
4068 TypeManager.CSharpName (vt) + "'");
4073 if ((ModFlags & Modifiers.READONLY) != 0){
4076 "A field can not be both volatile and readonly");
4081 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
4083 if (container is Struct &&
4084 ((fa & FieldAttributes.Static) == 0) &&
4085 t == container.TypeBuilder &&
4086 !TypeManager.IsBuiltinType (t)){
4087 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name +
4088 "' causes a cycle in the structure layout");
4093 FieldBuilder = container.TypeBuilder.DefineField (
4094 Name, t, Modifiers.FieldAttr (ModFlags));
4096 TypeManager.RegisterFieldBase (FieldBuilder, this);
4098 catch (ArgumentException) {
4099 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
4106 public void Emit (TypeContainer tc)
4108 EmitContext ec = new EmitContext (tc, Location, null,
4109 FieldBuilder.FieldType, ModFlags);
4111 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes);
4116 // `set' and `get' accessors are represented with an Accessor.
4118 public class Accessor {
4120 // Null if the accessor is empty, or a Block if not
4123 public Attributes OptAttributes;
4125 public Accessor (Block b, Attributes attrs)
4128 OptAttributes = attrs;
4133 // Properties and Indexers both generate PropertyBuilders, we use this to share
4134 // their common bits.
4136 abstract public class PropertyBase : MethodCore {
4137 public Accessor Get, Set;
4138 public PropertyBuilder PropertyBuilder;
4139 public MethodBuilder GetBuilder, SetBuilder;
4140 public MethodData GetData, SetData;
4142 protected EmitContext ec;
4144 public PropertyBase (DeclSpace ds, Expression type, string name, int mod_flags,
4145 int allowed_mod, Parameters parameters,
4146 Accessor get_block, Accessor set_block,
4147 Attributes attrs, Location loc)
4148 : base (ds, type, mod_flags, allowed_mod, name, attrs, parameters, loc)
4154 protected override bool DoDefine (DeclSpace decl, TypeContainer container)
4156 if (!base.DoDefine (decl, container))
4159 ec = new EmitContext (container, Location, null, MemberType, ModFlags);
4165 // Checks our base implementation if any
4167 protected override bool CheckBase (TypeContainer container)
4169 base.CheckBase (container);
4171 // Check whether arguments were correct.
4172 if (!DoDefineParameters ())
4179 MethodSignature ms, base_ms;
4180 if (this is Indexer) {
4181 string name, base_name;
4183 report_name = "this";
4184 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
4185 ms = new MethodSignature (name, null, ParameterTypes);
4186 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
4187 base_ms = new MethodSignature (base_name, null, ParameterTypes);
4190 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
4194 // Verify if the parent has a type with the same name, and then
4195 // check whether we have to create a new slot for it or not.
4197 Type ptype = container.TypeBuilder.BaseType;
4199 // ptype is only null for System.Object while compiling corlib.
4200 if (ptype == null) {
4201 if ((ModFlags & Modifiers.NEW) != 0)
4202 WarningNotHiding (container);
4207 MemberList props_this;
4209 props_this = TypeContainer.FindMembers (
4210 container.TypeBuilder, MemberTypes.Property,
4211 BindingFlags.NonPublic | BindingFlags.Public |
4212 BindingFlags.Static | BindingFlags.Instance |
4213 BindingFlags.DeclaredOnly,
4214 MethodSignature.method_signature_filter, ms);
4216 if (props_this.Count > 0) {
4217 Report.Error (111, Location, "Class `" + container.Name + "' " +
4218 "already defines a member called `" + report_name + "' " +
4219 "with the same parameter types");
4223 MemberList mi_props;
4225 mi_props = TypeContainer.FindMembers (
4226 ptype, MemberTypes.Property,
4227 BindingFlags.NonPublic | BindingFlags.Public |
4228 BindingFlags.Instance | BindingFlags.Static,
4229 MethodSignature.inheritable_method_signature_filter, base_ms);
4231 if (mi_props.Count > 0){
4232 PropertyInfo parent_property = (PropertyInfo) mi_props [0];
4233 string name = parent_property.DeclaringType.Name + "." +
4234 parent_property.Name;
4236 MethodInfo get, set, parent_method;
4237 get = parent_property.GetGetMethod (true);
4238 set = parent_property.GetSetMethod (true);
4241 parent_method = get;
4242 else if (set != null)
4243 parent_method = set;
4245 throw new Exception ("Internal error!");
4247 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
4250 if ((ModFlags & Modifiers.NEW) == 0) {
4251 Type parent_type = TypeManager.TypeToCoreType (
4252 parent_property.PropertyType);
4254 if (parent_type != MemberType) {
4256 508, Location, container.MakeName (Name) + ": cannot " +
4257 "change return type when overriding " +
4258 "inherited member " + name);
4263 if ((ModFlags & Modifiers.NEW) != 0)
4264 WarningNotHiding (container);
4266 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4267 if (this is Indexer)
4268 Report.Error (115, Location,
4269 container.MakeName (Name) +
4270 " no suitable indexers found to override");
4272 Report.Error (115, Location,
4273 container.MakeName (Name) +
4274 " no suitable properties found to override");
4281 public void Emit (TypeContainer tc)
4284 // The PropertyBuilder can be null for explicit implementations, in that
4285 // case, we do not actually emit the ".property", so there is nowhere to
4286 // put the attribute
4288 if (PropertyBuilder != null)
4289 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes);
4291 if (GetData != null) {
4292 GetData.Emit (tc, Get.Block, Get);
4296 if (SetData != null) {
4297 SetData.Emit (tc, Set.Block, Set);
4303 public class Property : PropertyBase {
4304 const int AllowedModifiers =
4307 Modifiers.PROTECTED |
4308 Modifiers.INTERNAL |
4312 Modifiers.OVERRIDE |
4313 Modifiers.ABSTRACT |
4318 public Property (DeclSpace ds, Expression type, string name, int mod_flags,
4319 Accessor get_block, Accessor set_block,
4320 Attributes attrs, Location loc)
4321 : base (ds, type, name, mod_flags, AllowedModifiers,
4322 Parameters.EmptyReadOnlyParameters,
4323 get_block, set_block, attrs, loc)
4327 public override bool Define (TypeContainer container)
4329 if (!DoDefine (container, container))
4332 if (!CheckBase (container))
4335 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4338 Type [] parameters = TypeManager.NoTypes;
4340 InternalParameters ip = new InternalParameters (
4341 container, Parameters.EmptyReadOnlyParameters);
4343 GetData = new MethodData (container, this, "get", MemberType,
4344 parameters, ip, CallingConventions.Standard,
4345 Get.OptAttributes, ModFlags, flags, false);
4347 if (!GetData.Define (container))
4350 GetBuilder = GetData.MethodBuilder;
4354 Type [] parameters = new Type [1];
4355 parameters [0] = MemberType;
4357 Parameter [] parms = new Parameter [1];
4358 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4359 InternalParameters ip = new InternalParameters (
4360 container, new Parameters (parms, null, Location));
4362 SetData = new MethodData (container, this, "set", TypeManager.void_type,
4363 parameters, ip, CallingConventions.Standard,
4364 Set.OptAttributes, ModFlags, flags, false);
4366 if (!SetData.Define (container))
4369 SetBuilder = SetData.MethodBuilder;
4370 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4373 // FIXME - PropertyAttributes.HasDefault ?
4375 PropertyAttributes prop_attr =
4376 PropertyAttributes.RTSpecialName |
4377 PropertyAttributes.SpecialName;
4379 if (!IsExplicitImpl){
4380 PropertyBuilder = container.TypeBuilder.DefineProperty (
4381 Name, prop_attr, MemberType, null);
4384 PropertyBuilder.SetGetMethod (GetBuilder);
4387 PropertyBuilder.SetSetMethod (SetBuilder);
4390 // HACK for the reasons exposed above
4392 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4395 "Class `" + container.Name +
4396 "' already contains a definition for the property `" +
4406 /// Gigantic workaround for lameness in SRE follows :
4407 /// This class derives from EventInfo and attempts to basically
4408 /// wrap around the EventBuilder so that FindMembers can quickly
4409 /// return this in it search for members
4411 public class MyEventBuilder : EventInfo {
4414 // We use this to "point" to our Builder which is
4415 // not really a MemberInfo
4417 EventBuilder MyBuilder;
4420 // We "catch" and wrap these methods
4422 MethodInfo raise, remove, add;
4424 EventAttributes attributes;
4425 Type declaring_type, reflected_type, event_type;
4430 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4432 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4434 // And now store the values in our own fields.
4436 declaring_type = type_builder;
4438 reflected_type = type_builder;
4440 attributes = event_attr;
4443 this.event_type = event_type;
4447 // Methods that you have to override. Note that you only need
4448 // to "implement" the variants that take the argument (those are
4449 // the "abstract" methods, the others (GetAddMethod()) are
4452 public override MethodInfo GetAddMethod (bool nonPublic)
4457 public override MethodInfo GetRemoveMethod (bool nonPublic)
4462 public override MethodInfo GetRaiseMethod (bool nonPublic)
4468 // These methods make "MyEventInfo" look like a Builder
4470 public void SetRaiseMethod (MethodBuilder raiseMethod)
4472 raise = raiseMethod;
4473 MyBuilder.SetRaiseMethod (raiseMethod);
4476 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4478 remove = removeMethod;
4479 MyBuilder.SetRemoveOnMethod (removeMethod);
4482 public void SetAddOnMethod (MethodBuilder addMethod)
4485 MyBuilder.SetAddOnMethod (addMethod);
4488 public void SetCustomAttribute (CustomAttributeBuilder cb)
4490 MyBuilder.SetCustomAttribute (cb);
4493 public override object [] GetCustomAttributes (bool inherit)
4495 // FIXME : There's nothing which can be seemingly done here because
4496 // we have no way of getting at the custom attribute objects of the
4501 public override object [] GetCustomAttributes (Type t, bool inherit)
4503 // FIXME : Same here !
4507 public override bool IsDefined (Type t, bool b)
4512 public override EventAttributes Attributes {
4518 public override string Name {
4524 public override Type DeclaringType {
4526 return declaring_type;
4530 public override Type ReflectedType {
4532 return reflected_type;
4536 public Type EventType {
4542 public void SetUsed ()
4544 if (my_event != null)
4545 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
4549 public class Event : FieldBase {
4550 const int AllowedModifiers =
4553 Modifiers.PROTECTED |
4554 Modifiers.INTERNAL |
4559 Modifiers.OVERRIDE |
4563 public readonly Accessor Add;
4564 public readonly Accessor Remove;
4565 public MyEventBuilder EventBuilder;
4567 MethodBuilder AddBuilder, RemoveBuilder;
4568 MethodData AddData, RemoveData;
4570 public Event (Expression type, string name, Object init, int mod, Accessor add,
4571 Accessor remove, Attributes attrs, Location loc)
4572 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4578 public override bool Define (TypeContainer container)
4580 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4581 MethodAttributes m_attr = MethodAttributes.HideBySig | MethodAttributes.SpecialName
4583 if (!DoDefine (container, container))
4586 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
4587 Report.Error (74, Location, "'" + container.Name + "." + Name +
4588 "': abstract event can not have an initializer");
4592 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4593 Report.Error (66, Location, "'" + container.Name + "." + Name +
4594 "' : event must be of a delegate type");
4598 Type [] parameter_types = new Type [1];
4599 parameter_types [0] = MemberType;
4601 Parameter [] parms = new Parameter [1];
4602 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4603 InternalParameters ip = new InternalParameters (
4604 container, new Parameters (parms, null, Location));
4606 if (!CheckBase (container))
4610 // Now define the accessors
4612 AddData = new MethodData (container, this, "add", TypeManager.void_type,
4613 parameter_types, ip, CallingConventions.Standard,
4614 (Add != null) ? Add.OptAttributes : null,
4615 ModFlags, flags | m_attr, false);
4617 if (!AddData.Define (container))
4620 AddBuilder = AddData.MethodBuilder;
4621 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4623 RemoveData = new MethodData (container, this, "remove", TypeManager.void_type,
4624 parameter_types, ip, CallingConventions.Standard,
4625 (Remove != null) ? Remove.OptAttributes : null,
4626 ModFlags, flags | m_attr, false);
4628 if (!RemoveData.Define (container))
4631 RemoveBuilder = RemoveData.MethodBuilder;
4632 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4634 if (!IsExplicitImpl){
4635 EventBuilder = new MyEventBuilder (this,
4636 container.TypeBuilder, Name, e_attr, MemberType);
4638 if (Add == null && Remove == null) {
4639 FieldBuilder = container.TypeBuilder.DefineField (
4641 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4642 TypeManager.RegisterPrivateFieldOfEvent (
4643 (EventInfo) EventBuilder, FieldBuilder);
4644 TypeManager.RegisterFieldBase (FieldBuilder, this);
4647 EventBuilder.SetAddOnMethod (AddBuilder);
4648 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4650 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4651 Report.Error (111, Location,
4652 "Class `" + container.Name +
4653 "' already contains a definition for the event `" +
4662 void EmitDefaultMethod (EmitContext ec, bool is_add)
4664 ILGenerator ig = ec.ig;
4665 MethodInfo method = null;
4668 method = TypeManager.delegate_combine_delegate_delegate;
4670 method = TypeManager.delegate_remove_delegate_delegate;
4672 if ((ModFlags & Modifiers.STATIC) != 0) {
4673 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4674 ig.Emit (OpCodes.Ldarg_0);
4675 ig.Emit (OpCodes.Call, method);
4676 ig.Emit (OpCodes.Castclass, MemberType);
4677 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4679 ig.Emit (OpCodes.Ldarg_0);
4680 ig.Emit (OpCodes.Ldarg_0);
4681 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4682 ig.Emit (OpCodes.Ldarg_1);
4683 ig.Emit (OpCodes.Call, method);
4684 ig.Emit (OpCodes.Castclass, MemberType);
4685 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4687 ig.Emit (OpCodes.Ret);
4690 public void Emit (TypeContainer tc)
4694 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4695 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes);
4698 AddData.Emit (tc, Add.Block, Add);
4701 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4702 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4703 EmitDefaultMethod (ec, true);
4706 if (Remove != null) {
4707 RemoveData.Emit (tc, Remove.Block, Remove);
4708 Remove.Block = null;
4710 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4711 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4712 EmitDefaultMethod (ec, false);
4719 // FIXME: This does not handle:
4721 // int INTERFACENAME [ args ]
4726 // int this [ args ]
4728 public class Indexer : PropertyBase {
4730 const int AllowedModifiers =
4733 Modifiers.PROTECTED |
4734 Modifiers.INTERNAL |
4738 Modifiers.OVERRIDE |
4743 public string IndexerName;
4744 public string InterfaceIndexerName;
4747 // Are we implementing an interface ?
4749 public Indexer (DeclSpace ds, Expression type, string int_type, int flags,
4750 Parameters parameters, Accessor get_block, Accessor set_block,
4751 Attributes attrs, Location loc)
4752 : base (ds, type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4755 ExplicitInterfaceName = int_type;
4758 public override bool Define (TypeContainer container)
4760 PropertyAttributes prop_attr =
4761 PropertyAttributes.RTSpecialName |
4762 PropertyAttributes.SpecialName;
4764 if (!DoDefine (container, container))
4767 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4768 if (IndexerName == null)
4769 IndexerName = "Item";
4770 else if (IsExplicitImpl)
4771 Report.Error (592, Location,
4772 "Attribute 'IndexerName' is not valid on this declaration " +
4773 "type. It is valid on `property' declarations only.");
4775 ShortName = IndexerName;
4776 if (IsExplicitImpl) {
4777 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4778 Name = InterfaceType.FullName + "." + IndexerName;
4780 InterfaceIndexerName = IndexerName;
4784 if (!CheckBase (container))
4787 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4789 InternalParameters ip = new InternalParameters (container, Parameters);
4791 GetData = new MethodData (container, this, "get", MemberType,
4792 ParameterTypes, ip, CallingConventions.Standard,
4793 Get.OptAttributes, ModFlags, flags, false);
4795 if (!GetData.Define (container))
4798 GetBuilder = GetData.MethodBuilder;
4802 int top = ParameterTypes.Length;
4803 Type [] set_pars = new Type [top + 1];
4804 ParameterTypes.CopyTo (set_pars, 0);
4805 set_pars [top] = MemberType;
4807 Parameter [] fixed_parms = Parameters.FixedParameters;
4809 if (fixed_parms == null){
4810 throw new Exception ("We currently do not support only array arguments in an indexer at: " + Location);
4811 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4812 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4814 // Here is the problem: the `value' parameter has
4815 // to come *after* the array parameter in the declaration
4817 // X (object [] x, Type value)
4820 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4821 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4825 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4828 fixed_parms.CopyTo (tmp, 0);
4829 tmp [fixed_parms.Length] = new Parameter (
4830 Type, "value", Parameter.Modifier.NONE, null);
4832 Parameters set_formal_params = new Parameters (tmp, null, Location);
4834 InternalParameters ip = new InternalParameters (container, set_formal_params);
4836 SetData = new MethodData (container, this, "set", TypeManager.void_type,
4837 set_pars, ip, CallingConventions.Standard,
4838 Set.OptAttributes, ModFlags, flags, false);
4840 if (!SetData.Define (container))
4843 SetBuilder = SetData.MethodBuilder;
4847 // Now name the parameters
4849 Parameter [] p = Parameters.FixedParameters;
4853 for (i = 0; i < p.Length; ++i) {
4855 GetBuilder.DefineParameter (
4856 i + 1, p [i].Attributes, p [i].Name);
4859 SetBuilder.DefineParameter (
4860 i + 1, p [i].Attributes, p [i].Name);
4864 SetBuilder.DefineParameter (
4865 i + 1, ParameterAttributes.None, "value");
4867 if (i != ParameterTypes.Length) {
4868 Parameter array_param = Parameters.ArrayParameter;
4870 SetBuilder.DefineParameter (
4871 i + 1, array_param.Attributes, array_param.Name);
4876 // Define the PropertyBuilder if one of the following conditions are met:
4877 // a) we're not implementing an interface indexer.
4878 // b) the indexer has a different IndexerName and this is no
4879 // explicit interface implementation.
4881 if (!IsExplicitImpl) {
4882 PropertyBuilder = container.TypeBuilder.DefineProperty (
4883 IndexerName, prop_attr, MemberType, ParameterTypes);
4885 if (GetData != null)
4886 PropertyBuilder.SetGetMethod (GetBuilder);
4888 if (SetData != null)
4889 PropertyBuilder.SetSetMethod (SetBuilder);
4891 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4899 public class Operator : MemberBase {
4901 const int AllowedModifiers =
4907 const int RequiredModifiers =
4911 public enum OpType : byte {
4921 // Unary and Binary operators
4944 // Implicit and Explicit
4949 public readonly OpType OperatorType;
4950 public readonly Expression ReturnType;
4951 public readonly Expression FirstArgType, SecondArgType;
4952 public readonly string FirstArgName, SecondArgName;
4954 public MethodBuilder OperatorMethodBuilder;
4956 public string MethodName;
4957 public Method OperatorMethod;
4959 public Operator (OpType type, Expression ret_type, int mod_flags,
4960 Expression arg1type, string arg1name,
4961 Expression arg2type, string arg2name,
4962 Block block, Attributes attrs, Location loc)
4963 : base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC, "", attrs, loc)
4965 OperatorType = type;
4966 ReturnType = ret_type;
4967 FirstArgType = arg1type;
4968 FirstArgName = arg1name;
4969 SecondArgType = arg2type;
4970 SecondArgName = arg2name;
4974 string Prototype (TypeContainer container)
4976 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4977 SecondArgType + ")";
4980 public override bool Define (TypeContainer container)
4983 MethodName = "op_" + OperatorType;
4985 if (SecondArgType != null)
4988 Parameter [] param_list = new Parameter [length];
4990 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4993 "User defined operators `" +
4994 Prototype (container) +
4995 "' must be declared static and public");
4999 param_list[0] = new Parameter (FirstArgType, FirstArgName,
5000 Parameter.Modifier.NONE, null);
5001 if (SecondArgType != null)
5002 param_list[1] = new Parameter (SecondArgType, SecondArgName,
5003 Parameter.Modifier.NONE, null);
5005 OperatorMethod = new Method (container, ReturnType, ModFlags, MethodName,
5006 new Parameters (param_list, null, Location),
5007 OptAttributes, Location);
5009 OperatorMethod.IsOperator = true;
5010 OperatorMethod.Define (container);
5012 if (OperatorMethod.MethodBuilder == null)
5015 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
5017 Type [] param_types = OperatorMethod.ParameterTypes;
5018 Type declaring_type = OperatorMethodBuilder.DeclaringType;
5019 Type return_type = OperatorMethod.GetReturnType ();
5020 Type first_arg_type = param_types [0];
5022 // Rules for conversion operators
5024 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
5025 if (first_arg_type == return_type && first_arg_type == declaring_type){
5028 "User-defined conversion cannot take an object of the " +
5029 "enclosing type and convert to an object of the enclosing" +
5034 if (first_arg_type != declaring_type && return_type != declaring_type){
5037 "User-defined conversion must convert to or from the " +
5042 if (first_arg_type == TypeManager.object_type ||
5043 return_type == TypeManager.object_type){
5046 "User-defined conversion cannot convert to or from " +
5051 if (first_arg_type.IsInterface || return_type.IsInterface){
5054 "User-defined conversion cannot convert to or from an " +
5059 if (first_arg_type.IsSubclassOf (return_type) ||
5060 return_type.IsSubclassOf (first_arg_type)){
5063 "User-defined conversion cannot convert between types " +
5064 "that derive from each other");
5067 } else if (SecondArgType == null) {
5068 // Checks for Unary operators
5070 if (first_arg_type != declaring_type){
5073 "The parameter of a unary operator must be the " +
5078 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
5079 if (return_type != declaring_type){
5082 "The parameter and return type for ++ and -- " +
5083 "must be the containing type");
5089 if (OperatorType == OpType.True || OperatorType == OpType.False) {
5090 if (return_type != TypeManager.bool_type){
5093 "The return type of operator True or False " +
5100 // Checks for Binary operators
5102 if (first_arg_type != declaring_type &&
5103 param_types [1] != declaring_type){
5106 "One of the parameters of a binary operator must " +
5107 "be the containing type");
5115 public void Emit (TypeContainer container)
5118 // abstract or extern methods have no bodies
5120 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
5123 OperatorMethod.Block = Block;
5124 OperatorMethod.Emit (container);
5128 public static string GetName (OpType ot)
5131 case OpType.LogicalNot:
5133 case OpType.OnesComplement:
5135 case OpType.Increment:
5137 case OpType.Decrement:
5143 case OpType.Addition:
5145 case OpType.Subtraction:
5147 case OpType.UnaryPlus:
5149 case OpType.UnaryNegation:
5151 case OpType.Multiply:
5153 case OpType.Division:
5155 case OpType.Modulus:
5157 case OpType.BitwiseAnd:
5159 case OpType.BitwiseOr:
5161 case OpType.ExclusiveOr:
5163 case OpType.LeftShift:
5165 case OpType.RightShift:
5167 case OpType.Equality:
5169 case OpType.Inequality:
5171 case OpType.GreaterThan:
5173 case OpType.LessThan:
5175 case OpType.GreaterThanOrEqual:
5177 case OpType.LessThanOrEqual:
5179 case OpType.Implicit:
5181 case OpType.Explicit:
5187 public override string ToString ()
5189 Type return_type = OperatorMethod.GetReturnType();
5190 Type [] param_types = OperatorMethod.ParameterTypes;
5192 if (SecondArgType == null)
5193 return String.Format (
5194 "{0} operator {1}({2})",
5195 TypeManager.CSharpName (return_type),
5196 GetName (OperatorType),
5199 return String.Format (
5200 "{0} operator {1}({2}, {3})",
5201 TypeManager.CSharpName (return_type),
5202 GetName (OperatorType),
5203 param_types [0], param_types [1]);
5208 // This is used to compare method signatures
5210 struct MethodSignature {
5212 public Type RetType;
5213 public Type [] Parameters;
5216 /// This delegate is used to extract methods which have the
5217 /// same signature as the argument
5219 public static MemberFilter method_signature_filter;
5222 /// This delegate is used to extract inheritable methods which
5223 /// have the same signature as the argument. By inheritable,
5224 /// this means that we have permissions to override the method
5225 /// from the current assembly and class
5227 public static MemberFilter inheritable_method_signature_filter;
5229 static MethodSignature ()
5231 method_signature_filter = new MemberFilter (MemberSignatureCompare);
5232 inheritable_method_signature_filter = new MemberFilter (
5233 InheritableMemberSignatureCompare);
5236 public MethodSignature (string name, Type ret_type, Type [] parameters)
5241 if (parameters == null)
5242 Parameters = TypeManager.NoTypes;
5244 Parameters = parameters;
5247 public override string ToString ()
5250 if (Parameters.Length != 0){
5251 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
5252 for (int i = 0; i < Parameters.Length; i++){
5253 sb.Append (Parameters [i]);
5254 if (i+1 < Parameters.Length)
5257 pars = sb.ToString ();
5260 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
5263 public override int GetHashCode ()
5265 return Name.GetHashCode ();
5268 public override bool Equals (Object o)
5270 MethodSignature other = (MethodSignature) o;
5272 if (other.Name != Name)
5275 if (other.RetType != RetType)
5278 if (Parameters == null){
5279 if (other.Parameters == null)
5284 if (other.Parameters == null)
5287 int c = Parameters.Length;
5288 if (other.Parameters.Length != c)
5291 for (int i = 0; i < c; i++)
5292 if (other.Parameters [i] != Parameters [i])
5298 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
5300 MethodSignature sig = (MethodSignature) filter_criteria;
5302 if (m.Name != sig.Name)
5306 MethodInfo mi = m as MethodInfo;
5307 PropertyInfo pi = m as PropertyInfo;
5310 ReturnType = mi.ReturnType;
5311 else if (pi != null)
5312 ReturnType = pi.PropertyType;
5317 // we use sig.RetType == null to mean `do not check the
5318 // method return value.
5320 if (sig.RetType != null)
5321 if (ReturnType != sig.RetType)
5326 args = TypeManager.GetArgumentTypes (mi);
5328 args = TypeManager.GetArgumentTypes (pi);
5329 Type [] sigp = sig.Parameters;
5331 if (args.Length != sigp.Length)
5334 for (int i = args.Length; i > 0; ){
5336 if (args [i] != sigp [i])
5343 // This filter should be used when we are requesting methods that
5344 // we want to override.
5346 // This makes a number of assumptions, for example
5347 // that the methods being extracted are of a parent
5348 // class (this means we know implicitly that we are
5349 // being called to find out about members by a derived
5352 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
5355 PropertyInfo pi = m as PropertyInfo;
5358 mi = pi.GetGetMethod (true);
5360 mi = pi.GetSetMethod (true);
5362 mi = m as MethodInfo;
5365 Console.WriteLine ("Nothing found");
5368 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
5370 // If only accessible to the current class.
5371 if (prot == MethodAttributes.Private)
5374 if (!MemberSignatureCompare (m, filter_criteria))
5377 // If only accessible to the defining assembly or
5378 if (prot == MethodAttributes.FamANDAssem ||
5379 prot == MethodAttributes.Assembly){
5380 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
5386 // Anything else (FamOrAssembly and Public) is fine