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;
134 public TypeContainer ():
135 this (null, null, "", null, new Location (-1)) {
138 public TypeContainer (NamespaceEntry ns, TypeContainer parent, string name, Attributes attrs, Location l)
139 : base (ns, parent, name, attrs, l)
141 types = new ArrayList ();
143 base_class_name = null;
146 public AdditionResult AddConstant (Const constant)
149 string basename = constant.Name;
150 string fullname = Name + "." + basename;
152 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
155 if (constants == null)
156 constants = new ArrayList ();
158 constants.Add (constant);
159 DefineName (fullname, constant);
161 return AdditionResult.Success;
164 public AdditionResult AddEnum (Mono.CSharp.Enum e)
168 if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
172 enums = new ArrayList ();
175 DefineName (e.Name, e);
177 return AdditionResult.Success;
180 public AdditionResult AddClass (Class c)
183 string name = c.Basename;
185 if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
188 DefineName (c.Name, c);
191 return AdditionResult.Success;
194 public AdditionResult AddStruct (Struct s)
197 string name = s.Basename;
199 if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
202 DefineName (s.Name, s);
205 return AdditionResult.Success;
208 public AdditionResult AddDelegate (Delegate d)
211 string name = d.Basename;
213 if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
216 if (delegates == null)
217 delegates = new ArrayList ();
219 DefineName (d.Name, d);
222 return AdditionResult.Success;
225 public AdditionResult AddMethod (Method method)
227 string basename = method.Name;
228 string fullname = Name + "." + basename;
230 Object value = defined_names [fullname];
232 if (value != null && (!(value is Method)))
233 return AdditionResult.NameExists;
235 if (basename == Basename)
236 return AdditionResult.EnclosingClash;
239 methods = new ArrayList ();
241 if (method.Name.IndexOf ('.') != -1)
242 methods.Insert (0, method);
244 methods.Add (method);
247 DefineName (fullname, method);
249 return AdditionResult.Success;
252 public AdditionResult AddConstructor (Constructor c)
254 if (c.Name != Basename)
255 return AdditionResult.NotAConstructor;
257 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
260 have_static_constructor = true;
261 if (default_static_constructor != null){
262 Console.WriteLine ("I have a static constructor already");
263 Console.WriteLine (" " + default_static_constructor);
264 return AdditionResult.MethodExists;
267 default_static_constructor = c;
270 if (default_constructor != null)
271 return AdditionResult.MethodExists;
272 default_constructor = c;
275 if (instance_constructors == null)
276 instance_constructors = new ArrayList ();
278 instance_constructors.Add (c);
281 return AdditionResult.Success;
284 public AdditionResult AddInterface (Interface iface)
287 string name = iface.Basename;
289 if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
292 if (interfaces == null)
293 interfaces = new ArrayList ();
294 interfaces.Add (iface);
295 DefineName (iface.Name, iface);
297 return AdditionResult.Success;
300 public AdditionResult AddField (Field field)
303 string basename = field.Name;
304 string fullname = Name + "." + basename;
306 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
310 fields = new ArrayList ();
314 if (field.HasInitializer){
315 if ((field.ModFlags & Modifiers.STATIC) != 0){
316 if (initialized_static_fields == null)
317 initialized_static_fields = new ArrayList ();
319 initialized_static_fields.Add (field);
322 // We have not seen a static constructor,
323 // but we will provide static initialization of fields
325 have_static_constructor = true;
327 if (initialized_fields == null)
328 initialized_fields = new ArrayList ();
330 initialized_fields.Add (field);
334 if ((field.ModFlags & Modifiers.STATIC) == 0)
335 have_nonstatic_fields = true;
337 DefineName (fullname, field);
338 return AdditionResult.Success;
341 public AdditionResult AddProperty (Property prop)
344 string basename = prop.Name;
345 string fullname = Name + "." + basename;
347 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
350 if (properties == null)
351 properties = new ArrayList ();
353 if (prop.Name.IndexOf ('.') != -1)
354 properties.Insert (0, prop);
356 properties.Add (prop);
357 DefineName (fullname, prop);
359 return AdditionResult.Success;
362 public AdditionResult AddEvent (Event e)
365 string basename = e.Name;
366 string fullname = Name + "." + basename;
368 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
372 events = new ArrayList ();
375 DefineName (fullname, e);
377 return AdditionResult.Success;
380 public AdditionResult AddIndexer (Indexer i)
382 if (indexers == null)
383 indexers = new ArrayList ();
385 if (i.InterfaceType != null)
386 indexers.Insert (0, i);
390 return AdditionResult.Success;
393 public AdditionResult AddOperator (Operator op)
395 if (operators == null)
396 operators = new ArrayList ();
400 return AdditionResult.Success;
403 public void RegisterOrder (Interface iface)
405 if (interface_order == null)
406 interface_order = new ArrayList ();
408 interface_order.Add (iface);
411 public ArrayList Types {
417 public ArrayList Methods {
423 public ArrayList Constants {
429 public ArrayList Interfaces {
437 return base_class_name;
441 public ArrayList Bases {
451 public ArrayList Fields {
461 public ArrayList InstanceConstructors {
463 return instance_constructors;
467 public ArrayList Properties {
473 public ArrayList Events {
479 public ArrayList Enums {
485 public ArrayList Indexers {
491 public ArrayList Operators {
497 public ArrayList Delegates {
503 public bool HaveStaticConstructor {
505 return have_static_constructor;
509 public virtual TypeAttributes TypeAttr {
511 return Modifiers.TypeAttr (ModFlags, this);
516 // Emits the instance field initializers
518 public bool EmitFieldInitializers (EmitContext ec)
521 Expression instance_expr;
524 fields = initialized_static_fields;
525 instance_expr = null;
527 fields = initialized_fields;
528 instance_expr = new This (Location.Null).Resolve (ec);
534 foreach (Field f in fields){
535 Expression e = f.GetInitializerExpression (ec);
539 Location l = f.Location;
540 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
541 fe.InstanceExpression = instance_expr;
542 ExpressionStatement a = new Assign (fe, e, l);
544 a = a.ResolveStatement (ec);
548 a.EmitStatement (ec);
555 // Defines the default constructors
557 void DefineDefaultConstructor (bool is_static)
562 c = new Constructor (this, Basename, Parameters.EmptyReadOnlyParameters,
563 new ConstructorBaseInitializer (
564 null, Parameters.EmptyReadOnlyParameters,
569 mods = Modifiers.STATIC;
572 // If the class is abstract, the default constructor is protected
574 if ((ModFlags & Modifiers.ABSTRACT) != 0)
575 mods |= Modifiers.PROTECTED;
581 c.Block = new ToplevelBlock (null, Location);
585 public void ReportStructInitializedInstanceError ()
587 string n = TypeBuilder.FullName;
589 foreach (Field f in initialized_fields){
592 "`" + n + "." + f.Name + "': can not have " +
593 "instance field initializers in structs");
597 void Error_TypeParameterAsBase (TypeParameterExpr e)
601 String.Format ("Type parameter `{0}' can not be used t as a base class or interface", e.Name));
605 /// The pending methods that need to be implemented (interfaces or abstract methods)
607 public PendingImplementation Pending;
610 /// This function computes the Base class and also the
611 /// list of interfaces that the class or struct @c implements.
613 /// The return value is an array (might be null) of
614 /// interfaces implemented (as Types).
616 /// The @parent argument is set to the parent object or null
617 /// if this is `System.Object'.
619 TypeExpr [] GetClassBases (bool is_class, out TypeExpr parent, out bool error)
621 ArrayList bases = Bases;
630 parent = TypeManager.system_valuetype_expr;
634 if (RootContext.StdLib)
635 parent = TypeManager.system_object_expr;
636 else if (Name != "System.Object")
637 parent = TypeManager.system_object_expr;
640 // If we are compiling our runtime,
641 // and we are defining ValueType, then our
642 // parent is `System.Object'.
644 if (!RootContext.StdLib && Name == "System.ValueType")
645 parent = TypeManager.system_object_expr;
652 // Bases should be null if there are no bases at all
657 TypeExpr name = ResolveTypeExpr ((Expression) bases [0], false, Location);
664 if (name is TypeParameterExpr){
665 Error_TypeParameterAsBase ((TypeParameterExpr) name);
674 parent = TypeManager.system_object_expr;
680 if (name.IsValueType)
681 detail = " (a class can not inherit from a struct/enum)";
683 Report.Error (509, "class `"+ Name +
684 "': Cannot inherit from sealed class `"+
685 name.Name + "'" + detail);
690 if (!parent.CanInheritFrom ()){
691 Report.Error (644, Location,
692 "`{0}' cannot inherit from special class `{1}'",
698 if (!parent.AsAccessible (this, ModFlags))
699 Report.Error (60, Location,
700 "Inconsistent accessibility: base class `" +
701 name.Name + "' is less accessible than class `" +
709 base_class_name = parent.Name;
711 TypeExpr [] ifaces = new TypeExpr [count-start];
713 for (i = start, j = 0; i < count; i++, j++){
714 Expression name = (Expression) bases [i];
715 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
716 if (resolved == null)
719 bases [i] = resolved;
721 if (is_class == false && !resolved.IsInterface){
722 Report.Error (527, "In Struct `" + Name + "', type `"+
723 name +"' is not an interface");
728 if (resolved.IsClass) {
730 Report.Error (527, "In Class `" + Name + "', type `"+
731 name+"' is not an interface");
737 for (int x = 0; x < j; x++) {
738 if (resolved == ifaces [x]) {
739 Report.Error (528, "`" + name + "' is already listed in interface list");
745 ifaces [j] = resolved;
748 return TypeManager.ExpandInterfaces (ifaces);
754 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
756 public override TypeBuilder DefineType ()
761 if (TypeBuilder != null)
768 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
780 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
782 ifaces = GetClassBases (is_class, out parent, out error);
788 foreach (TypeParameter type_param in TypeParameters)
789 if (!type_param.Resolve (this)) {
795 if (!is_class && TypeManager.value_type == null)
796 throw new Exception ();
798 TypeAttributes type_attributes = TypeAttr;
801 ConstructedType constructed = parent as ConstructedType;
802 if ((constructed == null) && (parent != null))
803 ptype = parent.ResolveType (ec);
808 if (TypeManager.NamespaceClash (Name, Location)) {
813 ModuleBuilder builder = CodeGen.ModuleBuilder;
814 TypeBuilder = builder.DefineType (
815 Name, type_attributes, ptype, null);
818 TypeBuilder builder = Parent.DefineType ();
822 TypeBuilder = builder.DefineNestedType (
823 Basename, type_attributes, ptype, null);
827 foreach (TypeParameter type_param in TypeParameters)
828 type_param.Define (TypeBuilder);
831 if (constructed != null) {
832 ptype = constructed.ResolveType (ec);
836 TypeBuilder.SetParent (ptype);
840 foreach (TypeParameter type_param in TypeParameters)
841 type_param.DefineType (ec, TypeBuilder);
845 // Structs with no fields need to have at least one byte.
846 // The right thing would be to set the PackingSize in a DefineType
847 // but there are no functions that allow interfaces *and* the size to
851 if (!is_class && !have_nonstatic_fields){
852 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
853 FieldAttributes.Private);
856 // add interfaces that were not added at type creation
857 if (ifaces != null) {
858 foreach (TypeExpr iface in ifaces) {
859 Type itype = iface.ResolveType (ec);
860 TypeBuilder.AddInterfaceImplementation (itype);
865 // Finish the setup for the EmitContext
867 ec.ContainerType = TypeBuilder;
869 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
871 if ((parent != null) && parent.IsAttribute) {
872 RootContext.RegisterAttribute (this);
873 TypeManager.RegisterAttrType (TypeBuilder, this);
875 RootContext.RegisterOrder (this);
877 if (Interfaces != null) {
878 foreach (Interface iface in Interfaces)
879 if (iface.DefineType () == null) {
886 foreach (TypeContainer tc in Types)
887 if (tc.DefineType () == null) {
893 if (Delegates != null) {
894 foreach (Delegate d in Delegates)
895 if (d.DefineType () == null) {
902 foreach (Enum en in Enums)
903 if (en.DefineType () == null) {
915 /// Defines the MemberCore objects that are in the `list' Arraylist
917 /// The `defined_names' array contains a list of members defined in
920 static ArrayList remove_list = new ArrayList ();
921 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
925 remove_list.Clear ();
927 foreach (MemberCore mc in list){
929 if (defined_names != null)
930 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
935 if (RootContext.WarningLevel >= 4){
936 if ((mc.ModFlags & Modifiers.NEW) != 0)
937 Warning_KeywordNewNotRequired (mc.Location, mc);
939 } else if (mc is MethodCore)
940 ((MethodCore) mc).OverridesSomething = true;
942 if (!mc.Define (this)){
943 remove_list.Add (mc);
950 MemberInfo match = defined_names [idx];
952 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
956 // If we are both methods, let the method resolution emit warnings
958 if (match is MethodBase && mc is MethodCore)
961 if ((mc.ModFlags & Modifiers.NEW) == 0) {
963 if (!(match is EventInfo)) {
964 Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
968 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
972 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
976 foreach (object o in remove_list)
979 remove_list.Clear ();
983 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
984 // class is consisten. Either it is `Item' or it is the name defined by all the
985 // indexers with the `IndexerName' attribute.
987 // Turns out that the IndexerNameAttribute is applied to each indexer,
988 // but it is never emitted, instead a DefaultName attribute is attached
991 void DefineIndexers ()
993 string class_indexer_name = null;
996 // If there's both an explicit and an implicit interface implementation, the
997 // explicit one actually implements the interface while the other one is just
998 // a normal indexer. See bug #37714.
1000 ArrayList list = new ArrayList ();
1001 foreach (Indexer i in Indexers){
1002 if (i.ExplicitInterfaceName != null)
1005 foreach (Indexer i in Indexers){
1006 if (i.ExplicitInterfaceName == null)
1010 foreach (Indexer i in list){
1015 name = i.IndexerName;
1017 if (i.InterfaceType != null)
1020 if (class_indexer_name == null){
1021 class_indexer_name = name;
1025 if (name == class_indexer_name)
1029 668, "Two indexers have different names, " +
1030 " you should use the same name for all your indexers");
1032 if (class_indexer_name == null)
1033 class_indexer_name = "Item";
1034 IndexerName = class_indexer_name;
1037 static void Error_KeywordNotAllowed (Location loc)
1039 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1043 /// Populates our TypeBuilder with fields and methods
1045 public override bool DefineMembers (TypeContainer container)
1047 MemberInfo [] defined_names = null;
1049 if (interface_order != null){
1050 foreach (Interface iface in interface_order)
1051 if ((iface.ModFlags & Modifiers.NEW) == 0)
1052 iface.DefineMembers (this);
1054 Error_KeywordNotAllowed (iface.Location);
1057 if (RootContext.WarningLevel > 1){
1061 // This code throws an exception in the comparer
1062 // I guess the string is not an object?
1064 ptype = TypeBuilder.BaseType;
1066 defined_names = (MemberInfo []) FindMembers (
1067 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1068 BindingFlags.Public | BindingFlags.Instance |
1069 BindingFlags.Static, null, null);
1071 Array.Sort (defined_names, mif_compare);
1075 Class pclass = Parent as Class;
1076 if (pclass != null) {
1077 string pname = null;
1079 Type t = pclass.TypeBuilder.BaseType;
1080 while ((t != null) && (ptype == null)) {
1081 pname = t.FullName + "." + Basename;
1082 ptype = RootContext.LookupType (this, pname, true, Location.Null);
1086 if ((ModFlags & Modifiers.NEW) != 0) {
1088 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1089 "inherited member. The keyword new is not required.");
1090 } else if (ptype != null) {
1091 Report.Warning (108, Location, "The keyword new is required on `" +
1092 Name + "' because it hides inherited member '" +
1095 } else if ((ModFlags & Modifiers.NEW) != 0)
1096 Error_KeywordNotAllowed (Location);
1098 if (constants != null)
1099 DefineMembers (constants, defined_names);
1102 DefineMembers (fields, defined_names);
1105 if (instance_constructors == null){
1106 if (default_constructor == null)
1107 DefineDefaultConstructor (false);
1110 if (initialized_static_fields != null &&
1111 default_static_constructor == null)
1112 DefineDefaultConstructor (true);
1115 if (this is Struct){
1117 // Structs can not have initialized instance
1120 if (initialized_static_fields != null &&
1121 default_static_constructor == null)
1122 DefineDefaultConstructor (true);
1124 if (initialized_fields != null)
1125 ReportStructInitializedInstanceError ();
1128 Pending = PendingImplementation.GetPendingImplementations (this);
1131 // Constructors are not in the defined_names array
1133 if (instance_constructors != null)
1134 DefineMembers (instance_constructors, null);
1136 if (default_static_constructor != null)
1137 default_static_constructor.Define (this);
1139 if (methods != null)
1140 DefineMembers (methods, defined_names);
1142 if (properties != null)
1143 DefineMembers (properties, defined_names);
1146 DefineMembers (events, defined_names);
1148 if (indexers != null) {
1151 IndexerName = "Item";
1153 if (operators != null){
1154 DefineMembers (operators, null);
1156 CheckPairedOperators ();
1160 DefineMembers (enums, defined_names);
1162 if (delegates != null)
1163 DefineMembers (delegates, defined_names);
1166 if (TypeBuilder.BaseType != null)
1167 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1169 member_cache = new MemberCache (this);
1176 public override bool Define (TypeContainer container)
1178 if (interface_order != null){
1179 foreach (Interface iface in interface_order)
1180 if ((iface.ModFlags & Modifiers.NEW) == 0)
1181 iface.Define (this);
1188 /// This function is based by a delegate to the FindMembers routine
1190 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1196 /// This filter is used by FindMembers, and we just keep
1197 /// a global for the filter to `AlwaysAccept'
1199 static MemberFilter accepting_filter;
1203 /// A member comparission method based on name only
1205 static IComparer mif_compare;
1207 static TypeContainer ()
1209 accepting_filter = new MemberFilter (AlwaysAccept);
1210 mif_compare = new MemberInfoCompare ();
1214 /// This method returns the members of this type just like Type.FindMembers would
1215 /// Only, we need to use this for types which are _being_ defined because MS'
1216 /// implementation can't take care of that.
1219 // FIXME: return an empty static array instead of null, that cleans up
1220 // some code and is consistent with some coding conventions I just found
1224 // Notice that in various cases we check if our field is non-null,
1225 // something that would normally mean that there was a bug elsewhere.
1227 // The problem happens while we are defining p-invoke methods, as those
1228 // will trigger a FindMembers, but this happens before things are defined
1230 // Since the whole process is a no-op, it is fine to check for null here.
1232 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1233 MemberFilter filter, object criteria)
1235 ArrayList members = null;
1238 if ((bf & BindingFlags.Public) != 0)
1239 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1241 if ((bf & BindingFlags.NonPublic) != 0)
1242 modflags |= Modifiers.PRIVATE;
1244 int static_mask = 0, static_flags = 0;
1245 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1246 case BindingFlags.Static:
1247 static_mask = static_flags = Modifiers.STATIC;
1250 case BindingFlags.Instance:
1251 static_mask = Modifiers.STATIC;
1256 static_mask = static_flags = 0;
1260 Timer.StartTimer (TimerType.TcFindMembers);
1263 filter = accepting_filter;
1265 if ((mt & MemberTypes.Field) != 0) {
1266 if (fields != null) {
1267 int len = fields.Count;
1268 for (int i = 0; i < len; i++) {
1269 Field f = (Field) fields [i];
1271 if ((f.ModFlags & modflags) == 0)
1273 if ((f.ModFlags & static_mask) != static_flags)
1276 FieldBuilder fb = f.FieldBuilder;
1277 if (fb != null && filter (fb, criteria) == true) {
1278 if (members == null)
1279 members = new ArrayList ();
1286 if (constants != null) {
1287 int len = constants.Count;
1288 for (int i = 0; i < len; i++) {
1289 Const con = (Const) constants [i];
1291 if ((con.ModFlags & modflags) == 0)
1293 if ((con.ModFlags & static_mask) != static_flags)
1296 FieldBuilder fb = con.FieldBuilder;
1297 if (fb != null && filter (fb, criteria) == true) {
1298 if (members == null)
1299 members = new ArrayList ();
1307 if ((mt & MemberTypes.Method) != 0) {
1308 if (methods != null) {
1309 int len = methods.Count;
1310 for (int i = 0; i < len; i++) {
1311 Method m = (Method) methods [i];
1313 if ((m.ModFlags & modflags) == 0)
1315 if ((m.ModFlags & static_mask) != static_flags)
1318 MethodBuilder mb = m.MethodBuilder;
1320 if (mb != null && filter (mb, criteria) == true) {
1321 if (members == null)
1322 members = new ArrayList ();
1329 if (operators != null) {
1330 int len = operators.Count;
1331 for (int i = 0; i < len; i++) {
1332 Operator o = (Operator) operators [i];
1334 if ((o.ModFlags & modflags) == 0)
1336 if ((o.ModFlags & static_mask) != static_flags)
1339 MethodBuilder ob = o.OperatorMethodBuilder;
1340 if (ob != null && filter (ob, criteria) == true) {
1341 if (members == null)
1342 members = new ArrayList ();
1349 if (properties != null) {
1350 int len = properties.Count;
1351 for (int i = 0; i < len; i++) {
1352 Property p = (Property) properties [i];
1354 if ((p.ModFlags & modflags) == 0)
1356 if ((p.ModFlags & static_mask) != static_flags)
1362 if (b != null && filter (b, criteria) == true) {
1363 if (members == null)
1364 members = new ArrayList ();
1370 if (b != null && filter (b, criteria) == true) {
1371 if (members == null)
1372 members = new ArrayList ();
1379 if (indexers != null) {
1380 int len = indexers.Count;
1381 for (int i = 0; i < len; i++) {
1382 Indexer ix = (Indexer) indexers [i];
1384 if ((ix.ModFlags & modflags) == 0)
1386 if ((ix.ModFlags & static_mask) != static_flags)
1392 if (b != null && filter (b, criteria) == true) {
1393 if (members == null)
1394 members = new ArrayList ();
1400 if (b != null && filter (b, criteria) == true) {
1401 if (members == null)
1402 members = new ArrayList ();
1410 if ((mt & MemberTypes.Event) != 0) {
1411 if (events != null) {
1412 int len = events.Count;
1413 for (int i = 0; i < len; i++) {
1414 Event e = (Event) events [i];
1416 if ((e.ModFlags & modflags) == 0)
1418 if ((e.ModFlags & static_mask) != static_flags)
1421 MemberInfo eb = e.EventBuilder;
1422 if (eb != null && filter (eb, criteria) == true) {
1423 if (members == null)
1424 members = new ArrayList ();
1426 members.Add (e.EventBuilder);
1432 if ((mt & MemberTypes.Property) != 0){
1433 if (properties != null) {
1434 int len = properties.Count;
1435 for (int i = 0; i < len; i++) {
1436 Property p = (Property) properties [i];
1438 if ((p.ModFlags & modflags) == 0)
1440 if ((p.ModFlags & static_mask) != static_flags)
1443 MemberInfo pb = p.PropertyBuilder;
1444 if (pb != null && filter (pb, criteria) == true) {
1445 if (members == null)
1446 members = new ArrayList ();
1448 members.Add (p.PropertyBuilder);
1453 if (indexers != null) {
1454 int len = indexers.Count;
1455 for (int i = 0; i < len; i++) {
1456 Indexer ix = (Indexer) indexers [i];
1458 if ((ix.ModFlags & modflags) == 0)
1460 if ((ix.ModFlags & static_mask) != static_flags)
1463 MemberInfo ib = ix.PropertyBuilder;
1464 if (ib != null && filter (ib, criteria) == true) {
1465 if (members == null)
1466 members = new ArrayList ();
1468 members.Add (ix.PropertyBuilder);
1474 if ((mt & MemberTypes.NestedType) != 0) {
1475 if (types != null) {
1476 int len = types.Count;
1477 for (int i = 0; i < len; i++) {
1478 TypeContainer t = (TypeContainer) types [i];
1480 if ((t.ModFlags & modflags) == 0)
1483 TypeBuilder tb = t.TypeBuilder;
1484 if (tb != null && (filter (tb, criteria) == true)) {
1485 if (members == null)
1486 members = new ArrayList ();
1493 if (enums != null) {
1494 int len = enums.Count;
1495 for (int i = 0; i < len; i++) {
1496 Enum en = (Enum) enums [i];
1498 if ((en.ModFlags & modflags) == 0)
1501 TypeBuilder tb = en.TypeBuilder;
1502 if (tb != null && (filter (tb, criteria) == true)) {
1503 if (members == null)
1504 members = new ArrayList ();
1511 if (delegates != null) {
1512 int len = delegates.Count;
1513 for (int i = 0; i < len; i++) {
1514 Delegate d = (Delegate) delegates [i];
1516 if ((d.ModFlags & modflags) == 0)
1519 TypeBuilder tb = d.TypeBuilder;
1520 if (tb != null && (filter (tb, criteria) == true)) {
1521 if (members == null)
1522 members = new ArrayList ();
1529 if (interfaces != null) {
1530 int len = interfaces.Count;
1531 for (int i = 0; i < len; i++) {
1532 Interface iface = (Interface) interfaces [i];
1534 if ((iface.ModFlags & modflags) == 0)
1537 TypeBuilder tb = iface.TypeBuilder;
1538 if (tb != null && (filter (tb, criteria) == true)) {
1539 if (members == null)
1540 members = new ArrayList ();
1548 if ((mt & MemberTypes.Constructor) != 0){
1549 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1550 int len = instance_constructors.Count;
1551 for (int i = 0; i < len; i++) {
1552 Constructor c = (Constructor) instance_constructors [i];
1554 ConstructorBuilder cb = c.ConstructorBuilder;
1555 if (cb != null && filter (cb, criteria) == true) {
1556 if (members == null)
1557 members = new ArrayList ();
1564 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1565 ConstructorBuilder cb =
1566 default_static_constructor.ConstructorBuilder;
1568 if (cb != null && filter (cb, criteria) == true) {
1569 if (members == null)
1570 members = new ArrayList ();
1578 // Lookup members in parent if requested.
1580 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1581 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1582 if (list.Count > 0) {
1583 if (members == null)
1584 members = new ArrayList ();
1586 members.AddRange (list);
1590 Timer.StopTimer (TimerType.TcFindMembers);
1592 if (members == null)
1593 return MemberList.Empty;
1595 return new MemberList (members);
1598 public override MemberCache MemberCache {
1600 return member_cache;
1604 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1605 MemberFilter filter, object criteria)
1607 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1610 return ds.FindMembers (mt, bf, filter, criteria);
1612 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1616 // FindMethods will look for methods not only in the type `t', but in
1617 // any interfaces implemented by the type.
1619 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1620 MemberFilter filter, object criteria)
1626 /// Emits the values for the constants
1628 public void EmitConstants ()
1630 if (constants != null)
1631 foreach (Const con in constants)
1632 con.EmitConstant (this);
1637 /// Emits the code, this step is performed after all
1638 /// the types, enumerations, constructors
1642 if (instance_constructors != null)
1643 foreach (Constructor c in instance_constructors)
1646 if (default_static_constructor != null)
1647 default_static_constructor.Emit (this);
1649 if (methods != null)
1650 foreach (Method m in methods)
1653 if (operators != null)
1654 foreach (Operator o in operators)
1657 if (properties != null)
1658 foreach (Property p in properties)
1661 if (indexers != null){
1662 foreach (Indexer ix in indexers)
1665 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1666 this, IndexerName, ModFlags, Location);
1667 TypeBuilder.SetCustomAttribute (cb);
1671 foreach (Field f in fields)
1674 if (events != null){
1675 foreach (Event e in Events)
1679 if (Pending != null)
1680 if (Pending.VerifyPendingMethods ())
1683 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
1686 // Check for internal or private fields that were never assigned
1688 if (RootContext.WarningLevel >= 3) {
1689 if (fields != null){
1690 foreach (Field f in fields) {
1691 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
1694 if ((f.status & Field.Status.USED) == 0){
1696 169, f.Location, "Private field " +
1697 MakeName (f.Name) + " is never used");
1702 // Only report 649 on level 4
1704 if (RootContext.WarningLevel < 4)
1707 if ((f.status & Field.Status.ASSIGNED) != 0)
1712 "Field " + MakeName (f.Name) + " is never assigned " +
1713 " to and will always have its default value");
1717 if (events != null){
1718 foreach (Event e in events){
1720 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1725 // if (types != null)
1726 // foreach (TypeContainer tc in types)
1730 public override void CloseType ()
1737 TypeBuilder.CreateType ();
1738 } catch (TypeLoadException){
1740 // This is fine, the code still created the type
1742 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1743 // Console.WriteLine (e.Message);
1745 Console.WriteLine ("In type: " + Name);
1750 foreach (Enum en in Enums)
1753 if (interface_order != null){
1754 foreach (Interface iface in interface_order)
1759 foreach (TypeContainer tc in Types)
1763 foreach (TypeContainer tc in Types)
1764 if (!(tc is Struct))
1768 if (Delegates != null)
1769 foreach (Delegate d in Delegates)
1777 initialized_fields = null;
1778 initialized_static_fields = null;
1781 interface_order = null;
1787 default_constructor = null;
1788 default_static_constructor = null;
1790 OptAttributes = null;
1792 parent_container = null;
1793 member_cache = null;
1796 public string MakeName (string n)
1798 return "`" + Name + "." + n + "'";
1801 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1804 108, l, "The keyword new is required on " +
1805 MakeName (mi.Name) + " because it hides `" +
1806 mi.ReflectedType.Name + "." + mi.Name + "'");
1809 public void Warning_KeywordNewNotRequired (Location l, MemberCore mc)
1812 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1813 "inherited member, the keyword new is not required");
1816 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
1819 72, l, MakeName (mi.Name) + " : cannot override; `" +
1820 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
1823 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1829 // Performs the validation on a Method's modifiers (properties have
1830 // the same properties).
1832 public bool MethodModifiersValid (int flags, string n, Location loc)
1834 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1835 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1836 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1840 // At most one of static, virtual or override
1842 if ((flags & Modifiers.STATIC) != 0){
1843 if ((flags & vao) != 0){
1845 112, loc, "static method " + MakeName (n) + "can not be marked " +
1846 "as virtual, abstract or override");
1851 if (this is Struct){
1852 if ((flags & va) != 0){
1853 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1858 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1860 113, loc, MakeName (n) +
1861 " marked as override cannot be marked as new or virtual");
1866 // If the declaration includes the abstract modifier, then the
1867 // declaration does not include static, virtual or extern
1869 if ((flags & Modifiers.ABSTRACT) != 0){
1870 if ((flags & Modifiers.EXTERN) != 0){
1872 180, loc, MakeName (n) + " can not be both abstract and extern");
1876 if ((flags & Modifiers.VIRTUAL) != 0){
1878 503, loc, MakeName (n) + " can not be both abstract and virtual");
1882 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1884 513, loc, MakeName (n) +
1885 " is abstract but its container class is not");
1891 if ((flags & Modifiers.PRIVATE) != 0){
1892 if ((flags & vao) != 0){
1894 621, loc, MakeName (n) +
1895 " virtual or abstract members can not be private");
1900 if ((flags & Modifiers.SEALED) != 0){
1901 if ((flags & Modifiers.OVERRIDE) == 0){
1903 238, loc, MakeName (n) +
1904 " cannot be sealed because it is not an override");
1912 Hashtable builder_and_args;
1914 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1916 if (builder_and_args == null)
1917 builder_and_args = new Hashtable ();
1922 /// Performs checks for an explicit interface implementation. First it
1923 /// checks whether the `interface_type' is a base inteface implementation.
1924 /// Then it checks whether `name' exists in the interface type.
1926 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1930 if (ifaces != null){
1931 foreach (TypeExpr t in ifaces){
1932 if (t.Type == interface_type){
1940 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1951 string IMemberContainer.Name {
1957 Type IMemberContainer.Type {
1963 IMemberContainer IMemberContainer.Parent {
1965 return parent_container;
1969 MemberCache IMemberContainer.MemberCache {
1971 return member_cache;
1975 bool IMemberContainer.IsInterface {
1981 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1983 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1987 // Operator pair checking
1990 class OperatorEntry {
1992 public Type ret_type;
1993 public Type type1, type2;
1995 public Operator.OpType ot;
1997 public OperatorEntry (int f, Operator o)
2001 ret_type = o.OperatorMethod.GetReturnType ();
2002 Type [] pt = o.OperatorMethod.ParameterTypes;
2006 ot = o.OperatorType;
2009 public override int GetHashCode ()
2011 return ret_type.GetHashCode ();
2014 public override bool Equals (object o)
2016 OperatorEntry other = (OperatorEntry) o;
2018 if (other.ret_type != ret_type)
2020 if (other.type1 != type1)
2022 if (other.type2 != type2)
2029 // Checks that some operators come in pairs:
2035 // They are matched based on the return type and the argument types
2037 void CheckPairedOperators ()
2039 Hashtable pairs = new Hashtable (null, null);
2040 Operator true_op = null;
2041 Operator false_op = null;
2042 bool has_equality_or_inequality = false;
2044 // Register all the operators we care about.
2045 foreach (Operator op in operators){
2048 switch (op.OperatorType){
2049 case Operator.OpType.Equality:
2051 has_equality_or_inequality = true;
2053 case Operator.OpType.Inequality:
2055 has_equality_or_inequality = true;
2058 case Operator.OpType.True:
2061 case Operator.OpType.False:
2065 case Operator.OpType.GreaterThan:
2067 case Operator.OpType.LessThan:
2070 case Operator.OpType.GreaterThanOrEqual:
2072 case Operator.OpType.LessThanOrEqual:
2078 OperatorEntry oe = new OperatorEntry (reg, op);
2080 object o = pairs [oe];
2084 oe = (OperatorEntry) o;
2089 if (true_op != null){
2090 if (false_op == null)
2091 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2092 } else if (false_op != null)
2093 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2096 // Look for the mistakes.
2098 foreach (DictionaryEntry de in pairs){
2099 OperatorEntry oe = (OperatorEntry) de.Key;
2106 case Operator.OpType.Equality:
2109 case Operator.OpType.Inequality:
2112 case Operator.OpType.GreaterThan:
2115 case Operator.OpType.LessThan:
2118 case Operator.OpType.GreaterThanOrEqual:
2121 case Operator.OpType.LessThanOrEqual:
2125 Report.Error (216, oe.op.Location,
2126 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2129 if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2130 MethodSignature equals_ms = new MethodSignature (
2131 "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2132 MethodSignature hash_ms = new MethodSignature (
2133 "GetHashCode", TypeManager.int32_type, new Type [0]);
2135 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2136 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2138 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2139 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2142 bool equals_ok = false;
2143 if ((equals_ml != null) && (equals_ml.Count == 1))
2144 equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2145 bool hash_ok = false;
2146 if ((hash_ml != null) && (hash_ml.Count == 1))
2147 hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2150 Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2151 "not override Object.Equals (object o)");
2153 Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2154 "not override Object.GetHashCode ()");
2160 public class Class : TypeContainer {
2162 // Modifiers allowed in a class declaration
2164 public const int AllowedModifiers =
2167 Modifiers.PROTECTED |
2168 Modifiers.INTERNAL |
2170 Modifiers.ABSTRACT |
2174 public Class (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2175 : base (ns, parent, name, attrs, l)
2179 if (parent.Parent == null)
2180 accmods = Modifiers.INTERNAL;
2182 accmods = Modifiers.PRIVATE;
2184 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2188 // FIXME: How do we deal with the user specifying a different
2191 public override TypeAttributes TypeAttr {
2193 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2198 public class Struct : TypeContainer {
2200 // Modifiers allowed in a struct declaration
2202 public const int AllowedModifiers =
2205 Modifiers.PROTECTED |
2206 Modifiers.INTERNAL |
2210 public Struct (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2211 : base (ns, parent, name, attrs, l)
2215 if (parent.Parent == null)
2216 accmods = Modifiers.INTERNAL;
2218 accmods = Modifiers.PRIVATE;
2220 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2222 this.ModFlags |= Modifiers.SEALED;
2226 // FIXME: Allow the user to specify a different set of attributes
2227 // in some cases (Sealed for example is mandatory for a class,
2228 // but what SequentialLayout can be changed
2230 public override TypeAttributes TypeAttr {
2232 return base.TypeAttr |
2233 TypeAttributes.SequentialLayout |
2234 TypeAttributes.Sealed |
2235 TypeAttributes.BeforeFieldInit;
2240 public abstract class MethodCore : MemberBase {
2241 public readonly Parameters Parameters;
2242 protected Block block;
2243 protected DeclSpace ds;
2246 // Parameters, cached for semantic analysis.
2248 protected InternalParameters parameter_info;
2249 protected Type [] parameter_types;
2252 // This is set from TypeContainer.DefineMembers if this method overrides something.
2254 public bool OverridesSomething;
2256 public MethodCore (DeclSpace ds, Expression type, int mod, int allowed_mod,
2257 string name, Attributes attrs, Parameters parameters, Location loc)
2258 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
2260 Parameters = parameters;
2265 // Returns the System.Type array for the parameters of this method
2267 public Type [] ParameterTypes {
2269 return parameter_types;
2273 public InternalParameters ParameterInfo
2276 return parameter_info;
2280 public Block Block {
2290 protected virtual bool DoDefineParameters ()
2292 // Check if arguments were correct
2293 parameter_types = Parameters.GetParameterInfo (ds);
2294 if ((parameter_types == null) || !CheckParameters (ds, parameter_types))
2297 parameter_info = new InternalParameters (ds, Parameters);
2299 Parameter array_param = Parameters.ArrayParameter;
2300 if ((array_param != null) &&
2301 (!array_param.ParameterType.IsArray ||
2302 (array_param.ParameterType.GetArrayRank () != 1))) {
2303 Report.Error (225, Location, "params parameter has to be a single dimensional array");
2310 public CallingConventions GetCallingConvention (bool is_class)
2312 CallingConventions cc = 0;
2314 cc = Parameters.GetCallingConvention ();
2317 if ((ModFlags & Modifiers.STATIC) == 0)
2318 cc |= CallingConventions.HasThis;
2320 // FIXME: How is `ExplicitThis' used in C#?
2326 // The method's attributes are passed in because we need to extract
2327 // the "return:" attribute from there to apply on the return type
2329 static public void LabelParameters (EmitContext ec,
2331 Parameters parameters,
2332 Attributes method_attrs,
2336 // Define each type attribute (in/out/ref) and
2337 // the argument names.
2339 Parameter [] p = parameters.FixedParameters;
2342 MethodBuilder mb = null;
2343 ConstructorBuilder cb = null;
2345 if (builder is MethodBuilder)
2346 mb = (MethodBuilder) builder;
2348 cb = (ConstructorBuilder) builder;
2351 for (i = 0; i < p.Length; i++) {
2352 ParameterBuilder pb;
2353 ParameterAttributes par_attr = p [i].Attributes;
2356 pb = cb.DefineParameter (
2357 i + 1, par_attr, p [i].Name);
2359 pb = mb.DefineParameter (
2360 i + 1, par_attr, p [i].Name);
2362 Attributes attr = p [i].OptAttributes;
2364 Attribute.ApplyAttributes (ec, pb, pb, attr);
2366 if (par_attr == ParameterAttributes.Out){
2367 if (attr.Contains (TypeManager.in_attribute_type))
2368 Report.Error (36, loc,
2369 "Can not use [In] attribute on out parameter");
2375 if (parameters.ArrayParameter != null){
2376 ParameterBuilder pb;
2377 Parameter array_param = parameters.ArrayParameter;
2380 pb = cb.DefineParameter (
2381 i + 1, array_param.Attributes,
2384 pb = mb.DefineParameter (
2385 i + 1, array_param.Attributes,
2388 CustomAttributeBuilder a = new CustomAttributeBuilder (
2389 TypeManager.cons_param_array_attribute, new object [0]);
2391 pb.SetCustomAttribute (a);
2395 // And now for the return type attribute decoration
2397 ParameterBuilder ret_pb;
2398 Attributes ret_attrs = null;
2400 if (mb == null || method_attrs == null)
2403 foreach (AttributeSection asec in method_attrs.AttributeSections) {
2405 if (asec.Target != "return")
2408 if (ret_attrs == null)
2409 ret_attrs = new Attributes (asec);
2411 ret_attrs.AddAttributeSection (asec);
2414 if (ret_attrs != null) {
2416 ret_pb = mb.DefineParameter (0, ParameterAttributes.None, "");
2417 Attribute.ApplyAttributes (ec, ret_pb, ret_pb, ret_attrs);
2419 } catch (ArgumentOutOfRangeException) {
2422 ".NET SDK 1.0 does not permit setting custom attributes" +
2423 " on the return type of a method");
2429 public class Method : MethodCore, IIteratorContainer {
2430 public MethodBuilder MethodBuilder;
2431 public MethodData MethodData;
2432 public readonly GenericMethod GenericMethod;
2435 /// Modifiers allowed in a class declaration
2437 const int AllowedModifiers =
2440 Modifiers.PROTECTED |
2441 Modifiers.INTERNAL |
2446 Modifiers.OVERRIDE |
2447 Modifiers.ABSTRACT |
2452 // return_type can be "null" for VOID values.
2454 public Method (DeclSpace ds, Expression return_type, int mod, string name,
2455 Parameters parameters, Attributes attrs, Location l)
2456 : base (ds, return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2459 public Method (GenericMethod generic, Expression return_type, int mod, string name,
2460 Parameters parameters, Attributes attrs, Location l)
2461 : base (generic, return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2463 GenericMethod = generic;
2467 // Returns the `System.Type' for the ReturnType of this
2468 // function. Provides a nice cache. (used between semantic analysis
2469 // and actual code generation
2471 public Type GetReturnType ()
2476 // Whether this is an operator method.
2477 public bool IsOperator;
2479 void DuplicateEntryPoint (MethodInfo b, Location location)
2483 "Program `" + CodeGen.FileName +
2484 "' has more than one entry point defined: `" +
2485 TypeManager.CSharpSignature(b) + "'");
2488 void Report28 (MethodInfo b)
2492 "`" + TypeManager.CSharpSignature(b) +
2493 "' has the wrong signature to be an entry point");
2496 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2498 if (b.ReturnType != TypeManager.void_type &&
2499 b.ReturnType != TypeManager.int32_type)
2502 if (pinfo.Count == 0)
2505 if (pinfo.Count > 1)
2508 Type t = pinfo.ParameterType(0);
2510 (t.GetArrayRank() == 1) &&
2511 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
2512 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2519 // Checks our base implementation if any
2521 protected override bool CheckBase (TypeContainer container)
2523 base.CheckBase (container);
2525 // Check whether arguments were correct.
2526 if (!DoDefineParameters ())
2529 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2531 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2535 mi_this = TypeContainer.FindMembers (
2536 container.TypeBuilder, MemberTypes.Method,
2537 BindingFlags.NonPublic | BindingFlags.Public |
2538 BindingFlags.Static | BindingFlags.Instance |
2539 BindingFlags.DeclaredOnly,
2540 MethodSignature.method_signature_filter, ms);
2542 if (mi_this.Count > 0) {
2543 Report.Error (111, Location, "Class `" + container.Name + "' " +
2544 "already defines a member called `" + Name + "' " +
2545 "with the same parameter types");
2551 // Verify if the parent has a type with the same name, and then
2552 // check whether we have to create a new slot for it or not.
2554 Type ptype = container.TypeBuilder.BaseType;
2556 // ptype is only null for System.Object while compiling corlib.
2558 MemberList mi, mi_static, mi_instance;
2560 mi_instance = TypeContainer.FindMembers (
2561 ptype, MemberTypes.Method,
2562 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2563 MethodSignature.inheritable_method_signature_filter,
2566 if (mi_instance.Count > 0){
2569 mi_static = TypeContainer.FindMembers (
2570 ptype, MemberTypes.Method,
2571 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2572 MethodSignature.inheritable_method_signature_filter, ms);
2574 if (mi_static.Count > 0)
2580 if (mi != null && mi.Count > 0){
2581 parent_method = (MethodInfo) mi [0];
2582 string name = parent_method.DeclaringType.Name + "." +
2585 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
2588 if ((ModFlags & Modifiers.NEW) == 0) {
2589 Type parent_ret = TypeManager.TypeToCoreType (
2590 parent_method.ReturnType);
2592 if (parent_ret != MemberType) {
2594 508, Location, container.MakeName (Name) + ": cannot " +
2595 "change return type when overriding " +
2596 "inherited member " + name);
2601 if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
2602 WarningNotHiding (container);
2604 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2605 Report.Error (115, Location,
2606 container.MakeName (Name) +
2607 " no suitable methods found to override");
2610 } else if ((ModFlags & Modifiers.NEW) != 0)
2611 WarningNotHiding (container);
2619 public override bool Define (TypeContainer container)
2621 if (!DoDefine (container))
2624 MethodBuilder mb = null;
2625 if (GenericMethod != null) {
2626 mb = container.TypeBuilder.DefineGenericMethod (Name, flags);
2627 if (!GenericMethod.Define (mb))
2631 if (!CheckBase (container))
2634 CallingConventions cc = GetCallingConvention (container is Class);
2636 MethodData = new MethodData (ds, this, null, MemberType,
2637 ParameterTypes, ParameterInfo, cc,
2638 OptAttributes, ModFlags, flags, true, mb);
2640 if (!MethodData.Define (container))
2644 // Setup iterator if we are one
2646 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
2647 IteratorHandler ih = new IteratorHandler (
2648 Name, container, MemberType,
2649 ParameterTypes, ParameterInfo,
2650 ModFlags, Location);
2652 Block new_block = ih.Setup (block);
2653 if (new_block == null)
2658 MethodBuilder = MethodData.MethodBuilder;
2661 // This is used to track the Entry Point,
2663 if (Name == "Main" &&
2664 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
2665 (RootContext.MainClass == null ||
2666 RootContext.MainClass == container.TypeBuilder.FullName)){
2667 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2668 if (RootContext.EntryPoint == null) {
2669 if (container.IsGeneric){
2670 Report.Error (-201, Location,
2671 "Entry point can not be defined in a generic class");
2674 RootContext.EntryPoint = MethodBuilder;
2675 RootContext.EntryPointLocation = Location;
2677 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2678 DuplicateEntryPoint (MethodBuilder, Location);
2681 Report28(MethodBuilder);
2690 public void Emit (TypeContainer container)
2692 MethodData.Emit (container, Block, this);
2697 void IIteratorContainer.SetYields ()
2699 ModFlags |= Modifiers.METHOD_YIELDS;
2703 public abstract class ConstructorInitializer {
2704 ArrayList argument_list;
2705 ConstructorInfo parent_constructor;
2706 Parameters parameters;
2709 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2712 this.argument_list = argument_list;
2713 this.parameters = parameters;
2717 public ArrayList Arguments {
2719 return argument_list;
2723 public bool Resolve (EmitContext ec)
2725 Expression parent_constructor_group;
2728 ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
2730 if (argument_list != null){
2731 foreach (Argument a in argument_list){
2732 if (!a.Resolve (ec, loc))
2736 ec.CurrentBlock = null;
2738 if (this is ConstructorBaseInitializer) {
2739 if (ec.ContainerType.BaseType == null)
2742 t = ec.ContainerType.BaseType;
2743 if (ec.ContainerType.IsValueType) {
2744 Report.Error (522, loc,
2745 "structs cannot call base class constructors");
2749 t = ec.ContainerType;
2751 parent_constructor_group = Expression.MemberLookup (
2752 ec, t, null, t, ".ctor",
2753 MemberTypes.Constructor,
2754 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2757 if (parent_constructor_group == null){
2758 Report.Error (1501, loc,
2759 "Can not find a constructor for this argument list");
2763 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2764 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2766 if (parent_constructor == null){
2767 Report.Error (1501, loc,
2768 "Can not find a constructor for this argument list");
2775 public void Emit (EmitContext ec)
2777 if (parent_constructor != null){
2778 ec.Mark (loc, false);
2780 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2782 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
2787 public class ConstructorBaseInitializer : ConstructorInitializer {
2788 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2789 base (argument_list, pars, l)
2794 public class ConstructorThisInitializer : ConstructorInitializer {
2795 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2796 base (argument_list, pars, l)
2801 public class Constructor : MethodCore {
2802 public ConstructorBuilder ConstructorBuilder;
2803 public ConstructorInitializer Initializer;
2806 // Modifiers allowed for a constructor.
2808 public const int AllowedModifiers =
2810 Modifiers.PROTECTED |
2811 Modifiers.INTERNAL |
2818 // The spec claims that static is not permitted, but
2819 // my very own code has static constructors.
2821 public Constructor (DeclSpace ds, string name, Parameters args,
2822 ConstructorInitializer init, Location l)
2823 : base (ds, null, 0, AllowedModifiers, name, null, args, l)
2829 // Returns true if this is a default constructor
2831 public bool IsDefault ()
2833 if ((ModFlags & Modifiers.STATIC) != 0)
2834 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2835 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2838 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2839 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2840 (Initializer is ConstructorBaseInitializer) &&
2841 (Initializer.Arguments == null);
2845 // Creates the ConstructorBuilder
2847 public override bool Define (TypeContainer container)
2849 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2850 MethodAttributes.SpecialName);
2852 // Check if arguments were correct.
2853 if (!DoDefineParameters ())
2856 if ((ModFlags & Modifiers.STATIC) != 0){
2857 ca |= MethodAttributes.Static | MethodAttributes.Private;
2859 if (container is Struct && ParameterTypes.Length == 0){
2862 "Structs can not contain explicit parameterless " +
2866 ca |= MethodAttributes.HideBySig;
2868 if ((ModFlags & Modifiers.PUBLIC) != 0)
2869 ca |= MethodAttributes.Public;
2870 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2871 if ((ModFlags & Modifiers.INTERNAL) != 0)
2872 ca |= MethodAttributes.FamORAssem;
2874 ca |= MethodAttributes.Family;
2875 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2876 ca |= MethodAttributes.Assembly;
2877 else if (IsDefault ())
2878 ca |= MethodAttributes.Public;
2880 ca |= MethodAttributes.Private;
2883 ConstructorBuilder = container.TypeBuilder.DefineConstructor (
2884 ca, GetCallingConvention (container is Class), ParameterTypes);
2886 if ((ModFlags & Modifiers.UNSAFE) != 0)
2887 ConstructorBuilder.InitLocals = false;
2890 // HACK because System.Reflection.Emit is lame
2892 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2895 "Class `" +container.Name+ "' already contains a definition with the " +
2896 "same return value and parameter types for constructor `" + Name
2907 public void Emit (TypeContainer container)
2909 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2910 EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
2913 // extern methods have no bodies
2915 if ((ModFlags & Modifiers.EXTERN) != 0) {
2916 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
2918 179, Location, "External constructor `" +
2919 TypeManager.CSharpSignature (ConstructorBuilder) +
2920 "' can not have a body");
2923 } else if (block == null) {
2925 501, Location, "Constructor `" +
2926 TypeManager.CSharpSignature (ConstructorBuilder) +
2927 "' must declare a body since it is not marked extern");
2931 if ((ModFlags & Modifiers.STATIC) == 0){
2932 if (container is Class && Initializer == null)
2933 Initializer = new ConstructorBaseInitializer (
2934 null, Parameters.EmptyReadOnlyParameters, Location);
2938 // Spec mandates that Initializers will not have
2942 if (Initializer != null && !Initializer.Resolve (ec))
2944 ec.IsStatic = false;
2947 MethodCore.LabelParameters (ec, ConstructorBuilder,
2948 Parameters, OptAttributes, Location);
2950 SymbolWriter sw = CodeGen.SymbolWriter;
2951 bool generate_debugging = false;
2953 if ((sw != null) && (block != null) &&
2954 !Location.IsNull (Location) &&
2955 !Location.IsNull (block.EndLocation)) {
2957 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
2959 generate_debugging = true;
2963 // Classes can have base initializers and instance field initializers.
2965 if (container is Class){
2966 if ((ModFlags & Modifiers.STATIC) == 0){
2969 // If we use a "this (...)" constructor initializer, then
2970 // do not emit field initializers, they are initialized in the other constructor
2972 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
2973 container.EmitFieldInitializers (ec);
2976 if (Initializer != null)
2977 Initializer.Emit (ec);
2979 if ((ModFlags & Modifiers.STATIC) != 0)
2980 container.EmitFieldInitializers (ec);
2982 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes);
2984 // If this is a non-static `struct' constructor and doesn't have any
2985 // initializer, it must initialize all of the struct's fields.
2986 if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
2987 Block.AddThisVariable (container, Location);
2989 ec.EmitTopBlock (block, ParameterInfo, Location);
2991 if (generate_debugging)
2999 // Encapsulates most of the Method's state
3001 public class MethodData {
3003 // The return type of this method
3005 public readonly Type ReturnType;
3006 public readonly Type[] ParameterTypes;
3007 public readonly InternalParameters ParameterInfo;
3008 public readonly CallingConventions CallingConventions;
3009 public readonly Attributes OptAttributes;
3010 public readonly Location Location;
3013 // Are we implementing an interface ?
3015 public bool IsImplementing = false;
3020 protected DeclSpace ds;
3021 protected MemberBase member;
3022 protected int modifiers;
3023 protected MethodAttributes flags;
3024 protected bool is_method;
3025 protected string accessor_name;
3028 // It can either hold a string with the condition, or an arraylist of conditions.
3029 object conditionals;
3031 MethodBuilder builder = null;
3032 public MethodBuilder MethodBuilder {
3038 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
3039 Type [] parameter_types, InternalParameters parameters,
3040 CallingConventions cc, Attributes opt_attrs,
3041 int modifiers, MethodAttributes flags, bool is_method)
3044 this.member = member;
3045 this.accessor_name = name;
3046 this.ReturnType = return_type;
3047 this.ParameterTypes = parameter_types;
3048 this.ParameterInfo = parameters;
3049 this.CallingConventions = cc;
3050 this.OptAttributes = opt_attrs;
3051 this.modifiers = modifiers;
3053 this.is_method = is_method;
3054 this.Location = member.Location;
3055 this.conditionals = null;
3058 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
3059 Type [] parameter_types, InternalParameters parameters,
3060 CallingConventions cc, Attributes opt_attrs,
3061 int modifiers, MethodAttributes flags, bool is_method,
3062 MethodBuilder builder)
3063 : this (ds, member, name, return_type, parameter_types, parameters,
3064 cc, opt_attrs, modifiers, flags, is_method)
3066 this.builder = builder;
3072 Attribute dllimport_attribute = null;
3073 string obsolete = null;
3074 bool obsolete_error = false;
3076 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
3078 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
3081 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
3082 if (asec.Attributes == null)
3085 foreach (Attribute a in asec.Attributes) {
3086 if (a.Name == "Conditional") {
3087 if (!ApplyConditionalAttribute (a))
3089 } else if (a.Name == "Obsolete") {
3090 if (!ApplyObsoleteAttribute (a))
3092 } else if (a.Name.IndexOf ("DllImport") != -1) {
3094 a.Type = TypeManager.dllimport_type;
3095 Attribute.Error_AttributeNotValidForElement (a, Location);
3098 if (!ApplyDllImportAttribute (a))
3108 // Applies the `DllImport' attribute to the method.
3110 protected virtual bool ApplyDllImportAttribute (Attribute a)
3112 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3113 if ((modifiers & extern_static) != extern_static) {
3114 Report.Error (601, Location,
3115 "The DllImport attribute must be specified on a method " +
3116 "marked `static' and `extern'.");
3120 flags |= MethodAttributes.PinvokeImpl;
3121 dllimport_attribute = a;
3126 // Applies the `Obsolete' attribute to the method.
3128 protected virtual bool ApplyObsoleteAttribute (Attribute a)
3130 if (obsolete != null) {
3131 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
3135 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
3136 return obsolete != null;
3140 // Applies the `Conditional' attribute to the method.
3142 protected virtual bool ApplyConditionalAttribute (Attribute a)
3144 // The Conditional attribute is only valid on methods.
3146 Attribute.Error_AttributeNotValidForElement (a, Location);
3150 string condition = a.Conditional_GetConditionName ();
3152 if (condition == null)
3155 if (ReturnType != TypeManager.void_type) {
3156 Report.Error (578, Location,
3157 "Conditional not valid on `" + member.Name + "' " +
3158 "because its return type is not void");
3162 if ((modifiers & Modifiers.OVERRIDE) != 0) {
3163 Report.Error (243, Location,
3164 "Conditional not valid on `" + member.Name + "' " +
3165 "because it is an override method");
3169 if (member.IsExplicitImpl) {
3170 Report.Error (577, Location,
3171 "Conditional not valid on `" + member.Name + "' " +
3172 "because it is an explicit interface implementation");
3176 if (IsImplementing) {
3177 Report.Error (623, Location,
3178 "Conditional not valid on `" + member.Name + "' " +
3179 "because it is an interface method");
3184 // The likelyhood that the conditional will be more than 1 is very slim
3186 if (conditionals == null)
3187 conditionals = condition;
3188 else if (conditionals is string){
3189 string s = (string) conditionals;
3190 conditionals = new ArrayList ();
3191 ((ArrayList)conditionals).Add (s);
3193 ((ArrayList)conditionals).Add (condition);
3199 // Checks whether this method should be ignored due to its Conditional attributes.
3201 bool ShouldIgnore (Location loc)
3203 // When we're overriding a virtual method, we implicitly inherit the
3204 // Conditional attributes from our parent.
3205 if (member.ParentMethod != null) {
3206 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3207 member.ParentMethod, loc);
3209 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3213 if (conditionals != null){
3214 if (conditionals is string){
3215 if (RootContext.AllDefines [conditionals] == null)
3218 foreach (string condition in (ArrayList) conditionals)
3219 if (RootContext.AllDefines [condition] == null)
3227 // Returns the TypeManager.MethodFlags for this method.
3228 // This emits an error 619 / warning 618 if the method is obsolete.
3229 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3231 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3233 TypeManager.MethodFlags flags = 0;
3235 if (obsolete != null) {
3236 if (obsolete_error) {
3237 Report.Error (619, loc, "Method `" + member.Name +
3238 "' is obsolete: `" + obsolete + "'");
3239 return TypeManager.MethodFlags.IsObsoleteError;
3241 Report.Warning (618, loc, "Method `" + member.Name +
3242 "' is obsolete: `" + obsolete + "'");
3244 flags |= TypeManager.MethodFlags.IsObsolete;
3247 if (ShouldIgnore (loc))
3248 flags |= TypeManager.MethodFlags.ShouldIgnore;
3253 public virtual bool Define (TypeContainer container)
3255 MethodInfo implementing = null;
3256 string method_name, name, prefix;
3258 if (OptAttributes != null)
3259 if (!ApplyAttributes (OptAttributes, is_method))
3262 if (member.IsExplicitImpl)
3263 prefix = member.InterfaceType.FullName + ".";
3267 if (accessor_name != null)
3268 name = accessor_name + "_" + member.ShortName;
3270 name = member.ShortName;
3271 method_name = prefix + name;
3273 if (container.Pending != null){
3274 if (member is Indexer)
3275 implementing = container.Pending.IsInterfaceIndexer (
3276 member.InterfaceType, ReturnType, ParameterTypes);
3278 implementing = container.Pending.IsInterfaceMethod (
3279 member.InterfaceType, name, ReturnType, ParameterTypes);
3281 if (member.InterfaceType != null && implementing == null){
3282 Report.Error (539, Location, "'{0}' in explicit interface declaration is not an interface", method_name);
3288 // For implicit implementations, make sure we are public, for
3289 // explicit implementations, make sure we are private.
3291 if (implementing != null){
3293 // Setting null inside this block will trigger a more
3294 // verbose error reporting for missing interface implementations
3296 // The "candidate" function has been flagged already
3297 // but it wont get cleared
3299 if (member.IsExplicitImpl){
3300 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3301 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3302 implementing = null;
3304 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
3305 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
3307 // If this is an interface method implementation,
3308 // check for public accessibility
3310 implementing = null;
3311 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
3312 // We may never be private.
3313 implementing = null;
3314 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
3316 // We may be protected if we're overriding something.
3318 implementing = null;
3323 // Static is not allowed
3325 if ((modifiers & Modifiers.STATIC) != 0){
3326 implementing = null;
3327 Modifiers.Error_InvalidModifier (Location, "static");
3332 // If implementing is still valid, set flags
3334 if (implementing != null){
3336 // When implementing interface methods, set NewSlot
3337 // unless, we are overwriting a method.
3339 if (implementing.DeclaringType.IsInterface){
3340 if ((modifiers & Modifiers.OVERRIDE) == 0)
3341 flags |= MethodAttributes.NewSlot;
3344 MethodAttributes.Virtual |
3345 MethodAttributes.HideBySig;
3347 // Set Final unless we're virtual, abstract or already overriding a method.
3348 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
3349 flags |= MethodAttributes.Final;
3351 // Get the method name from the explicit interface.
3352 if (member.InterfaceType != null) {
3353 name = implementing.Name;
3354 method_name = prefix + name;
3357 IsImplementing = true;
3361 // Create the MethodBuilder for the method
3363 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3364 if ((modifiers & Modifiers.STATIC) == 0) {
3365 Report.Error (601, Location,
3366 "The DllImport attribute must be specified on " +
3367 "a method marked 'static' and 'extern'.");
3371 EmitContext ec = new EmitContext (
3372 container, ds, Location, null, ReturnType, modifiers, false);
3374 builder = dllimport_attribute.DefinePInvokeMethod (
3375 ec, container.TypeBuilder, method_name, flags,
3376 ReturnType, ParameterTypes);
3377 } else if (builder == null)
3378 builder = container.TypeBuilder.DefineMethod (
3379 method_name, flags, CallingConventions,
3380 ReturnType, ParameterTypes);
3382 builder.SetGenericMethodSignature (ReturnType, ParameterTypes);
3384 if (builder == null)
3387 if ((modifiers & Modifiers.UNSAFE) != 0)
3388 builder.InitLocals = false;
3390 if (IsImplementing){
3392 // clear the pending implemntation flag
3394 if (member is Indexer) {
3395 container.Pending.ImplementIndexer (
3396 member.InterfaceType, builder, ReturnType,
3397 ParameterTypes, true);
3399 container.Pending.ImplementMethod (
3400 member.InterfaceType, name, ReturnType,
3401 ParameterTypes, member.IsExplicitImpl);
3403 if (member.IsExplicitImpl)
3404 container.TypeBuilder.DefineMethodOverride (
3405 builder, implementing);
3409 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3410 Report.Error (111, Location,
3411 "Class `" + container.Name +
3412 "' already contains a definition with the " +
3413 "same return value and parameter types as the " +
3414 "'get' method of property `" + member.Name + "'");
3418 TypeManager.AddMethod (builder, this);
3426 public virtual void Emit (TypeContainer container, Block block, object kind)
3431 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3432 ig = builder.GetILGenerator ();
3436 ec = new EmitContext (container, ds, Location, ig, ReturnType, modifiers, false);
3438 if (OptAttributes != null)
3439 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes);
3441 if (member is MethodCore)
3442 MethodCore.LabelParameters (ec, MethodBuilder,
3443 ((MethodCore) member).Parameters,
3448 // abstract or extern methods have no bodies
3450 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3451 if (block == null) {
3452 SymbolWriter sw = CodeGen.SymbolWriter;
3454 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0)) {
3455 sw.OpenMethod (container, MethodBuilder, Location, Location);
3463 // abstract or extern methods have no bodies.
3465 if ((modifiers & Modifiers.ABSTRACT) != 0)
3467 500, Location, "Abstract method `" +
3468 TypeManager.CSharpSignature (builder) +
3469 "' can not have a body");
3471 if ((modifiers & Modifiers.EXTERN) != 0)
3473 179, Location, "External method `" +
3474 TypeManager.CSharpSignature (builder) +
3475 "' can not have a body");
3481 // Methods must have a body unless they're extern or abstract
3483 if (block == null) {
3485 501, Location, "Method `" +
3486 TypeManager.CSharpSignature (builder) +
3487 "' must declare a body since it is not marked " +
3488 "abstract or extern");
3493 // Handle destructors specially
3495 // FIXME: This code generates buggy code
3497 if (member is Destructor)
3498 EmitDestructor (ec, block);
3500 SymbolWriter sw = CodeGen.SymbolWriter;
3502 if ((sw != null) && !Location.IsNull (Location) &&
3503 !Location.IsNull (block.EndLocation)) {
3504 sw.OpenMethod (container, MethodBuilder, Location, block.EndLocation);
3506 ec.EmitTopBlock (block, ParameterInfo, Location);
3510 ec.EmitTopBlock (block, ParameterInfo, Location);
3514 void EmitDestructor (EmitContext ec, Block block)
3516 ILGenerator ig = ec.ig;
3518 Label finish = ig.DefineLabel ();
3520 block.SetDestructor ();
3522 ig.BeginExceptionBlock ();
3523 ec.ReturnLabel = finish;
3524 ec.HasReturnLabel = true;
3525 ec.EmitTopBlock (block, null, Location);
3527 // ig.MarkLabel (finish);
3528 ig.BeginFinallyBlock ();
3530 if (ec.ContainerType.BaseType != null) {
3531 Expression member_lookup = Expression.MemberLookup (
3532 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3533 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, Location);
3535 if (member_lookup != null){
3536 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3538 ig.Emit (OpCodes.Ldarg_0);
3539 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3543 ig.EndExceptionBlock ();
3544 //ig.MarkLabel (ec.ReturnLabel);
3545 ig.Emit (OpCodes.Ret);
3549 public class Destructor : Method {
3551 public Destructor (DeclSpace ds, Expression return_type, int mod, string name,
3552 Parameters parameters, Attributes attrs, Location l)
3553 : base (ds, return_type, mod, name, parameters, attrs, l)
3558 abstract public class MemberBase : MemberCore {
3559 public Expression Type;
3561 protected MethodAttributes flags;
3563 protected readonly int explicit_mod_flags;
3566 // The "short" name of this property / indexer / event. This is the
3567 // name without the explicit interface.
3569 public string ShortName;
3572 // The type of this property / indexer / event
3574 public Type MemberType;
3577 // If true, this is an explicit interface implementation
3579 public bool IsExplicitImpl = false;
3582 // The name of the interface we are explicitly implementing
3584 public string ExplicitInterfaceName = null;
3587 // If true, the interface type we are explicitly implementing
3589 public Type InterfaceType = null;
3592 // The method we're overriding if this is an override method.
3594 protected MethodInfo parent_method = null;
3595 public MethodInfo ParentMethod {
3597 return parent_method;
3602 // The constructor is only exposed to our children
3604 protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod, string name,
3605 Attributes attrs, Location loc)
3606 : base (name, attrs, loc)
3608 explicit_mod_flags = mod;
3610 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
3613 protected virtual bool CheckBase (TypeContainer container)
3615 if ((container is Struct) || (RootContext.WarningLevel > 3)){
3616 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
3617 if (container is Struct){
3618 Report.Error (666, Location, "Protected member in struct declaration");
3621 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
3627 protected void WarningNotHiding (TypeContainer parent)
3631 "The member " + parent.MakeName (Name) + " does not hide an " +
3632 "inherited member. The keyword new is not required");
3636 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
3640 // FIXME: report the old/new permissions?
3643 507, Location, parent.MakeName (Name) +
3644 ": can't change the access modifiers when overriding inherited " +
3645 "member `" + name + "'");
3649 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3650 // that have been defined.
3652 // `name' is the user visible name for reporting errors (this is used to
3653 // provide the right name regarding method names and properties)
3655 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
3656 MethodInfo mb, string name)
3660 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3661 if (!(mb.IsAbstract || mb.IsVirtual)){
3663 506, Location, parent.MakeName (Name) +
3664 ": cannot override inherited member `" +
3665 name + "' because it is not " +
3666 "virtual, abstract or override");
3670 // Now we check that the overriden method is not final
3673 // This happens when implementing interface methods.
3674 if (mb.IsHideBySig && mb.IsVirtual) {
3676 506, Location, parent.MakeName (Name) +
3677 ": cannot override inherited member `" +
3678 name + "' because it is not " +
3679 "virtual, abstract or override");
3681 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
3682 "override inherited member `" + name +
3683 "' because it is sealed.");
3687 // Check that the permissions are not being changed
3689 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
3690 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
3693 // special case for "protected internal"
3696 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3698 // when overriding protected internal, the method can be declared
3699 // protected internal only within the same assembly
3702 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3703 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
3705 // assemblies differ - report an error
3708 Error_CannotChangeAccessModifiers (parent, mb, name);
3710 } else if (thisp != parentp) {
3712 // same assembly, but other attributes differ - report an error
3715 Error_CannotChangeAccessModifiers (parent, mb, name);
3718 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3720 // if it's not "protected internal", it must be "protected"
3723 Error_CannotChangeAccessModifiers (parent, mb, name);
3725 } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
3727 // protected within the same assembly - an error
3729 Error_CannotChangeAccessModifiers (parent, mb, name);
3731 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3732 (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3734 // protected ok, but other attributes differ - report an error
3736 Error_CannotChangeAccessModifiers (parent, mb, name);
3740 if (thisp != parentp){
3741 Error_CannotChangeAccessModifiers (parent, mb, name);
3747 if (mb.IsVirtual || mb.IsAbstract){
3748 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
3749 if (Name != "Finalize"){
3751 114, 2, Location, parent.MakeName (Name) +
3752 " hides inherited member `" + name +
3753 "'. To make the current member override that " +
3754 "implementation, add the override keyword, " +
3755 "otherwise use the new keyword");
3756 ModFlags |= Modifiers.NEW;
3760 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
3761 if (Name != "Finalize"){
3763 108, 1, Location, "The keyword new is required on " +
3764 parent.MakeName (Name) + " because it hides " +
3765 "inherited member `" + name + "'");
3766 ModFlags |= Modifiers.NEW;
3774 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
3778 foreach (Type partype in parameters){
3779 if (partype.IsPointer){
3782 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
3786 if (ds.AsAccessible (partype, ModFlags))
3789 if (this is Indexer)
3790 Report.Error (55, Location,
3791 "Inconsistent accessibility: parameter type `" +
3792 TypeManager.CSharpName (partype) + "' is less " +
3793 "accessible than indexer `" + Name + "'");
3794 else if ((this is Method) && ((Method) this).IsOperator)
3795 Report.Error (57, Location,
3796 "Inconsistent accessibility: parameter type `" +
3797 TypeManager.CSharpName (partype) + "' is less " +
3798 "accessible than operator `" + Name + "'");
3800 Report.Error (51, Location,
3801 "Inconsistent accessibility: parameter type `" +
3802 TypeManager.CSharpName (partype) + "' is less " +
3803 "accessible than method `" + Name + "'");
3810 protected virtual bool DoDefine (TypeContainer container)
3815 if (!container.MethodModifiersValid (ModFlags, Name, Location))
3818 flags = Modifiers.MethodAttr (ModFlags);
3820 // Lookup Type, verify validity
3821 MemberType = container.ResolveType (Type, false, Location);
3822 if (MemberType == null)
3825 if ((container.ModFlags & Modifiers.SEALED) != 0){
3826 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
3827 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
3832 // verify accessibility
3833 if (!container.AsAccessible (MemberType, ModFlags)) {
3834 if (this is Property)
3835 Report.Error (53, Location,
3836 "Inconsistent accessibility: property type `" +
3837 TypeManager.CSharpName (MemberType) + "' is less " +
3838 "accessible than property `" + Name + "'");
3839 else if (this is Indexer)
3840 Report.Error (54, Location,
3841 "Inconsistent accessibility: indexer return type `" +
3842 TypeManager.CSharpName (MemberType) + "' is less " +
3843 "accessible than indexer `" + Name + "'");
3844 else if (this is Method) {
3845 if (((Method) this).IsOperator)
3846 Report.Error (56, Location,
3847 "Inconsistent accessibility: return type `" +
3848 TypeManager.CSharpName (MemberType) + "' is less " +
3849 "accessible than operator `" + Name + "'");
3851 Report.Error (50, Location,
3852 "Inconsistent accessibility: return type `" +
3853 TypeManager.CSharpName (MemberType) + "' is less " +
3854 "accessible than method `" + Name + "'");
3856 Report.Error (52, Location,
3857 "Inconsistent accessibility: field type `" +
3858 TypeManager.CSharpName (MemberType) + "' is less " +
3859 "accessible than field `" + Name + "'");
3863 if (MemberType.IsPointer && !UnsafeOK (container))
3867 // Check for explicit interface implementation
3869 if ((ExplicitInterfaceName == null) && (Name.IndexOf ('.') != -1)){
3870 int pos = Name.LastIndexOf ('.');
3872 ExplicitInterfaceName = Name.Substring (0, pos);
3873 ShortName = Name.Substring (pos + 1);
3877 if (ExplicitInterfaceName != null) {
3878 InterfaceType = RootContext.LookupType (
3879 container, ExplicitInterfaceName, false, Location);
3880 if (InterfaceType == null)
3883 if (InterfaceType.IsClass) {
3884 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
3888 // Compute the full name that we need to export.
3889 Name = InterfaceType.FullName + "." + ShortName;
3891 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
3894 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
3896 IsExplicitImpl = true;
3898 IsExplicitImpl = false;
3905 // Fields and Events both generate FieldBuilders, we use this to share
3906 // their common bits. This is also used to flag usage of the field
3908 abstract public class FieldBase : MemberBase {
3909 public FieldBuilder FieldBuilder;
3910 public Status status;
3913 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3916 // The constructor is only exposed to our children
3918 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3919 object init, Attributes attrs, Location loc)
3920 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
3926 // Whether this field has an initializer.
3928 public bool HasInitializer {
3930 return init != null;
3934 protected readonly Object init;
3936 Expression init_expr;
3937 bool init_expr_initialized = false;
3940 // Resolves and returns the field initializer.
3942 public Expression GetInitializerExpression (EmitContext ec)
3944 if (init_expr_initialized)
3948 if (init is Expression)
3949 e = (Expression) init;
3951 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3953 ec.IsFieldInitializer = true;
3954 e = e.DoResolve (ec);
3955 ec.IsFieldInitializer = false;
3958 init_expr_initialized = true;
3963 public void SetAssigned ()
3965 status |= Status.ASSIGNED;
3970 // The Field class is used to represents class/struct fields during parsing.
3972 public class Field : FieldBase {
3974 // Modifiers allowed in a class declaration
3976 const int AllowedModifiers =
3979 Modifiers.PROTECTED |
3980 Modifiers.INTERNAL |
3983 Modifiers.VOLATILE |
3987 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3988 Attributes attrs, Location loc)
3989 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3993 public override bool Define (TypeContainer container)
3995 Type t = container.ResolveType (Type, false, Location);
4000 CheckBase (container);
4002 if (!container.AsAccessible (t, ModFlags)) {
4003 Report.Error (52, Location,
4004 "Inconsistent accessibility: field type `" +
4005 TypeManager.CSharpName (t) + "' is less " +
4006 "accessible than field `" + Name + "'");
4010 if (t.IsPointer && !UnsafeOK (container))
4013 if (RootContext.WarningLevel > 1){
4014 Type ptype = container.TypeBuilder.BaseType;
4016 // ptype is only null for System.Object while compiling corlib.
4018 TypeContainer.FindMembers (
4019 ptype, MemberTypes.Method,
4020 BindingFlags.Public |
4021 BindingFlags.Static | BindingFlags.Instance,
4022 System.Type.FilterName, Name);
4026 if ((ModFlags & Modifiers.VOLATILE) != 0){
4030 if (TypeManager.IsEnumType (vt))
4031 vt = TypeManager.EnumToUnderlying (t);
4033 if (!((vt == TypeManager.bool_type) ||
4034 (vt == TypeManager.sbyte_type) ||
4035 (vt == TypeManager.byte_type) ||
4036 (vt == TypeManager.short_type) ||
4037 (vt == TypeManager.ushort_type) ||
4038 (vt == TypeManager.int32_type) ||
4039 (vt == TypeManager.uint32_type) ||
4040 (vt == TypeManager.char_type) ||
4041 (vt == TypeManager.float_type))){
4043 677, Location, container.MakeName (Name) +
4044 " A volatile field can not be of type `" +
4045 TypeManager.CSharpName (vt) + "'");
4050 if ((ModFlags & Modifiers.READONLY) != 0){
4053 "A field can not be both volatile and readonly");
4058 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
4060 if (container is Struct &&
4061 ((fa & FieldAttributes.Static) == 0) &&
4062 t == container.TypeBuilder &&
4063 !TypeManager.IsBuiltinType (t)){
4064 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name +
4065 "' causes a cycle in the structure layout");
4070 FieldBuilder = container.TypeBuilder.DefineField (
4071 Name, t, Modifiers.FieldAttr (ModFlags));
4073 TypeManager.RegisterFieldBase (FieldBuilder, this);
4075 catch (ArgumentException) {
4076 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
4083 public void Emit (TypeContainer tc)
4085 EmitContext ec = new EmitContext (tc, Location, null,
4086 FieldBuilder.FieldType, ModFlags);
4088 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes);
4093 // `set' and `get' accessors are represented with an Accessor.
4095 public class Accessor {
4097 // Null if the accessor is empty, or a Block if not
4100 public Attributes OptAttributes;
4102 public Accessor (Block b, Attributes attrs)
4105 OptAttributes = attrs;
4110 // Properties and Indexers both generate PropertyBuilders, we use this to share
4111 // their common bits.
4113 abstract public class PropertyBase : MethodCore {
4114 public Accessor Get, Set;
4115 public PropertyBuilder PropertyBuilder;
4116 public MethodBuilder GetBuilder, SetBuilder;
4117 public MethodData GetData, SetData;
4119 protected EmitContext ec;
4121 public PropertyBase (DeclSpace ds, Expression type, string name, int mod_flags,
4122 int allowed_mod, Parameters parameters,
4123 Accessor get_block, Accessor set_block,
4124 Attributes attrs, Location loc)
4125 : base (ds, type, mod_flags, allowed_mod, name, attrs, parameters, loc)
4131 protected override bool DoDefine (TypeContainer container)
4133 if (!base.DoDefine (container))
4136 ec = new EmitContext (container, Location, null, MemberType, ModFlags);
4142 // Checks our base implementation if any
4144 protected override bool CheckBase (TypeContainer container)
4146 base.CheckBase (container);
4148 // Check whether arguments were correct.
4149 if (!DoDefineParameters ())
4156 MethodSignature ms, base_ms;
4157 if (this is Indexer) {
4158 string name, base_name;
4160 report_name = "this";
4161 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
4162 ms = new MethodSignature (name, null, ParameterTypes);
4163 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
4164 base_ms = new MethodSignature (base_name, null, ParameterTypes);
4167 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
4171 // Verify if the parent has a type with the same name, and then
4172 // check whether we have to create a new slot for it or not.
4174 Type ptype = container.TypeBuilder.BaseType;
4176 // ptype is only null for System.Object while compiling corlib.
4177 if (ptype == null) {
4178 if ((ModFlags & Modifiers.NEW) != 0)
4179 WarningNotHiding (container);
4184 MemberList props_this;
4186 props_this = TypeContainer.FindMembers (
4187 container.TypeBuilder, MemberTypes.Property,
4188 BindingFlags.NonPublic | BindingFlags.Public |
4189 BindingFlags.Static | BindingFlags.Instance |
4190 BindingFlags.DeclaredOnly,
4191 MethodSignature.method_signature_filter, ms);
4193 if (props_this.Count > 0) {
4194 Report.Error (111, Location, "Class `" + container.Name + "' " +
4195 "already defines a member called `" + report_name + "' " +
4196 "with the same parameter types");
4200 MemberList mi_props;
4202 mi_props = TypeContainer.FindMembers (
4203 ptype, MemberTypes.Property,
4204 BindingFlags.NonPublic | BindingFlags.Public |
4205 BindingFlags.Instance | BindingFlags.Static,
4206 MethodSignature.inheritable_method_signature_filter, base_ms);
4208 if (mi_props.Count > 0){
4209 PropertyInfo parent_property = (PropertyInfo) mi_props [0];
4210 string name = parent_property.DeclaringType.Name + "." +
4211 parent_property.Name;
4213 MethodInfo get, set, parent_method;
4214 get = parent_property.GetGetMethod (true);
4215 set = parent_property.GetSetMethod (true);
4218 parent_method = get;
4219 else if (set != null)
4220 parent_method = set;
4222 throw new Exception ("Internal error!");
4224 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
4227 if ((ModFlags & Modifiers.NEW) == 0) {
4228 Type parent_type = TypeManager.TypeToCoreType (
4229 parent_property.PropertyType);
4231 if (parent_type != MemberType) {
4233 508, Location, container.MakeName (Name) + ": cannot " +
4234 "change return type when overriding " +
4235 "inherited member " + name);
4240 if ((ModFlags & Modifiers.NEW) != 0)
4241 WarningNotHiding (container);
4243 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4244 if (this is Indexer)
4245 Report.Error (115, Location,
4246 container.MakeName (Name) +
4247 " no suitable indexers found to override");
4249 Report.Error (115, Location,
4250 container.MakeName (Name) +
4251 " no suitable properties found to override");
4258 public void Emit (TypeContainer tc)
4261 // The PropertyBuilder can be null for explicit implementations, in that
4262 // case, we do not actually emit the ".property", so there is nowhere to
4263 // put the attribute
4265 if (PropertyBuilder != null)
4266 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes);
4268 if (GetData != null) {
4269 GetData.Emit (tc, Get.Block, Get);
4273 if (SetData != null) {
4274 SetData.Emit (tc, Set.Block, Set);
4280 public class Property : PropertyBase {
4281 const int AllowedModifiers =
4284 Modifiers.PROTECTED |
4285 Modifiers.INTERNAL |
4289 Modifiers.OVERRIDE |
4290 Modifiers.ABSTRACT |
4295 public Property (DeclSpace ds, Expression type, string name, int mod_flags,
4296 Accessor get_block, Accessor set_block,
4297 Attributes attrs, Location loc)
4298 : base (ds, type, name, mod_flags, AllowedModifiers,
4299 Parameters.EmptyReadOnlyParameters,
4300 get_block, set_block, attrs, loc)
4304 public override bool Define (TypeContainer container)
4306 if (!DoDefine (container))
4309 if (!CheckBase (container))
4312 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4315 Type [] parameters = TypeManager.NoTypes;
4317 InternalParameters ip = new InternalParameters (
4318 container, Parameters.EmptyReadOnlyParameters);
4320 GetData = new MethodData (container, this, "get", MemberType,
4321 parameters, ip, CallingConventions.Standard,
4322 Get.OptAttributes, ModFlags, flags, false);
4324 if (!GetData.Define (container))
4327 GetBuilder = GetData.MethodBuilder;
4331 Type [] parameters = new Type [1];
4332 parameters [0] = MemberType;
4334 Parameter [] parms = new Parameter [1];
4335 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4336 InternalParameters ip = new InternalParameters (
4337 container, new Parameters (parms, null, Location));
4339 SetData = new MethodData (container, this, "set", TypeManager.void_type,
4340 parameters, ip, CallingConventions.Standard,
4341 Set.OptAttributes, ModFlags, flags, false);
4343 if (!SetData.Define (container))
4346 SetBuilder = SetData.MethodBuilder;
4347 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4350 // FIXME - PropertyAttributes.HasDefault ?
4352 PropertyAttributes prop_attr =
4353 PropertyAttributes.RTSpecialName |
4354 PropertyAttributes.SpecialName;
4356 if (!IsExplicitImpl){
4357 PropertyBuilder = container.TypeBuilder.DefineProperty (
4358 Name, prop_attr, MemberType, null);
4361 PropertyBuilder.SetGetMethod (GetBuilder);
4364 PropertyBuilder.SetSetMethod (SetBuilder);
4367 // HACK for the reasons exposed above
4369 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4372 "Class `" + container.Name +
4373 "' already contains a definition for the property `" +
4383 /// Gigantic workaround for lameness in SRE follows :
4384 /// This class derives from EventInfo and attempts to basically
4385 /// wrap around the EventBuilder so that FindMembers can quickly
4386 /// return this in it search for members
4388 public class MyEventBuilder : EventInfo {
4391 // We use this to "point" to our Builder which is
4392 // not really a MemberInfo
4394 EventBuilder MyBuilder;
4397 // We "catch" and wrap these methods
4399 MethodInfo raise, remove, add;
4401 EventAttributes attributes;
4402 Type declaring_type, reflected_type, event_type;
4407 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4409 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4411 // And now store the values in our own fields.
4413 declaring_type = type_builder;
4415 reflected_type = type_builder;
4417 attributes = event_attr;
4420 this.event_type = event_type;
4424 // Methods that you have to override. Note that you only need
4425 // to "implement" the variants that take the argument (those are
4426 // the "abstract" methods, the others (GetAddMethod()) are
4429 public override MethodInfo GetAddMethod (bool nonPublic)
4434 public override MethodInfo GetRemoveMethod (bool nonPublic)
4439 public override MethodInfo GetRaiseMethod (bool nonPublic)
4445 // These methods make "MyEventInfo" look like a Builder
4447 public void SetRaiseMethod (MethodBuilder raiseMethod)
4449 raise = raiseMethod;
4450 MyBuilder.SetRaiseMethod (raiseMethod);
4453 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4455 remove = removeMethod;
4456 MyBuilder.SetRemoveOnMethod (removeMethod);
4459 public void SetAddOnMethod (MethodBuilder addMethod)
4462 MyBuilder.SetAddOnMethod (addMethod);
4465 public void SetCustomAttribute (CustomAttributeBuilder cb)
4467 MyBuilder.SetCustomAttribute (cb);
4470 public override object [] GetCustomAttributes (bool inherit)
4472 // FIXME : There's nothing which can be seemingly done here because
4473 // we have no way of getting at the custom attribute objects of the
4478 public override object [] GetCustomAttributes (Type t, bool inherit)
4480 // FIXME : Same here !
4484 public override bool IsDefined (Type t, bool b)
4489 public override EventAttributes Attributes {
4495 public override string Name {
4501 public override Type DeclaringType {
4503 return declaring_type;
4507 public override Type ReflectedType {
4509 return reflected_type;
4513 public Type EventType {
4519 public void SetUsed ()
4521 if (my_event != null)
4522 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
4526 public class Event : FieldBase {
4527 const int AllowedModifiers =
4530 Modifiers.PROTECTED |
4531 Modifiers.INTERNAL |
4536 Modifiers.OVERRIDE |
4540 public readonly Accessor Add;
4541 public readonly Accessor Remove;
4542 public MyEventBuilder EventBuilder;
4544 MethodBuilder AddBuilder, RemoveBuilder;
4545 MethodData AddData, RemoveData;
4547 public Event (Expression type, string name, Object init, int mod, Accessor add,
4548 Accessor remove, Attributes attrs, Location loc)
4549 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4555 public override bool Define (TypeContainer container)
4557 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4558 MethodAttributes m_attr = MethodAttributes.HideBySig | MethodAttributes.SpecialName
4560 if (!DoDefine (container))
4563 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
4564 Report.Error (74, Location, "'" + container.Name + "." + Name +
4565 "': abstract event can not have an initializer");
4569 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4570 Report.Error (66, Location, "'" + container.Name + "." + Name +
4571 "' : event must be of a delegate type");
4575 Type [] parameter_types = new Type [1];
4576 parameter_types [0] = MemberType;
4578 Parameter [] parms = new Parameter [1];
4579 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4580 InternalParameters ip = new InternalParameters (
4581 container, new Parameters (parms, null, Location));
4583 if (!CheckBase (container))
4587 // Now define the accessors
4589 AddData = new MethodData (container, this, "add", TypeManager.void_type,
4590 parameter_types, ip, CallingConventions.Standard,
4591 (Add != null) ? Add.OptAttributes : null,
4592 ModFlags, flags | m_attr, false);
4594 if (!AddData.Define (container))
4597 AddBuilder = AddData.MethodBuilder;
4598 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4600 RemoveData = new MethodData (container, this, "remove", TypeManager.void_type,
4601 parameter_types, ip, CallingConventions.Standard,
4602 (Remove != null) ? Remove.OptAttributes : null,
4603 ModFlags, flags | m_attr, false);
4605 if (!RemoveData.Define (container))
4608 RemoveBuilder = RemoveData.MethodBuilder;
4609 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4611 if (!IsExplicitImpl){
4612 EventBuilder = new MyEventBuilder (this,
4613 container.TypeBuilder, Name, e_attr, MemberType);
4615 if (Add == null && Remove == null) {
4616 FieldBuilder = container.TypeBuilder.DefineField (
4618 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4619 TypeManager.RegisterPrivateFieldOfEvent (
4620 (EventInfo) EventBuilder, FieldBuilder);
4621 TypeManager.RegisterFieldBase (FieldBuilder, this);
4624 EventBuilder.SetAddOnMethod (AddBuilder);
4625 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4627 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4628 Report.Error (111, Location,
4629 "Class `" + container.Name +
4630 "' already contains a definition for the event `" +
4639 void EmitDefaultMethod (EmitContext ec, bool is_add)
4641 ILGenerator ig = ec.ig;
4642 MethodInfo method = null;
4645 method = TypeManager.delegate_combine_delegate_delegate;
4647 method = TypeManager.delegate_remove_delegate_delegate;
4649 if ((ModFlags & Modifiers.STATIC) != 0) {
4650 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4651 ig.Emit (OpCodes.Ldarg_0);
4652 ig.Emit (OpCodes.Call, method);
4653 ig.Emit (OpCodes.Castclass, MemberType);
4654 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4656 ig.Emit (OpCodes.Ldarg_0);
4657 ig.Emit (OpCodes.Ldarg_0);
4658 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4659 ig.Emit (OpCodes.Ldarg_1);
4660 ig.Emit (OpCodes.Call, method);
4661 ig.Emit (OpCodes.Castclass, MemberType);
4662 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4664 ig.Emit (OpCodes.Ret);
4667 public void Emit (TypeContainer tc)
4671 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4672 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes);
4675 AddData.Emit (tc, Add.Block, Add);
4678 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4679 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4680 EmitDefaultMethod (ec, true);
4683 if (Remove != null) {
4684 RemoveData.Emit (tc, Remove.Block, Remove);
4685 Remove.Block = null;
4687 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4688 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4689 EmitDefaultMethod (ec, false);
4696 // FIXME: This does not handle:
4698 // int INTERFACENAME [ args ]
4703 // int this [ args ]
4705 public class Indexer : PropertyBase {
4707 const int AllowedModifiers =
4710 Modifiers.PROTECTED |
4711 Modifiers.INTERNAL |
4715 Modifiers.OVERRIDE |
4720 public string IndexerName;
4721 public string InterfaceIndexerName;
4724 // Are we implementing an interface ?
4726 public Indexer (DeclSpace ds, Expression type, string int_type, int flags,
4727 Parameters parameters, Accessor get_block, Accessor set_block,
4728 Attributes attrs, Location loc)
4729 : base (ds, type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4732 ExplicitInterfaceName = int_type;
4735 public override bool Define (TypeContainer container)
4737 PropertyAttributes prop_attr =
4738 PropertyAttributes.RTSpecialName |
4739 PropertyAttributes.SpecialName;
4741 if (!DoDefine (container))
4744 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4745 if (IndexerName == null)
4746 IndexerName = "Item";
4747 else if (IsExplicitImpl)
4748 Report.Error (592, Location,
4749 "Attribute 'IndexerName' is not valid on this declaration " +
4750 "type. It is valid on `property' declarations only.");
4752 ShortName = IndexerName;
4753 if (IsExplicitImpl) {
4754 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4755 Name = InterfaceType.FullName + "." + IndexerName;
4757 InterfaceIndexerName = IndexerName;
4761 if (!CheckBase (container))
4764 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4766 InternalParameters ip = new InternalParameters (container, Parameters);
4768 GetData = new MethodData (container, this, "get", MemberType,
4769 ParameterTypes, ip, CallingConventions.Standard,
4770 Get.OptAttributes, ModFlags, flags, false);
4772 if (!GetData.Define (container))
4775 GetBuilder = GetData.MethodBuilder;
4779 int top = ParameterTypes.Length;
4780 Type [] set_pars = new Type [top + 1];
4781 ParameterTypes.CopyTo (set_pars, 0);
4782 set_pars [top] = MemberType;
4784 Parameter [] fixed_parms = Parameters.FixedParameters;
4786 if (fixed_parms == null){
4787 throw new Exception ("We currently do not support only array arguments in an indexer at: " + Location);
4788 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4789 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4791 // Here is the problem: the `value' parameter has
4792 // to come *after* the array parameter in the declaration
4794 // X (object [] x, Type value)
4797 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4798 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4802 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4805 fixed_parms.CopyTo (tmp, 0);
4806 tmp [fixed_parms.Length] = new Parameter (
4807 Type, "value", Parameter.Modifier.NONE, null);
4809 Parameters set_formal_params = new Parameters (tmp, null, Location);
4811 InternalParameters ip = new InternalParameters (container, set_formal_params);
4813 SetData = new MethodData (container, this, "set", TypeManager.void_type,
4814 set_pars, ip, CallingConventions.Standard,
4815 Set.OptAttributes, ModFlags, flags, false);
4817 if (!SetData.Define (container))
4820 SetBuilder = SetData.MethodBuilder;
4824 // Now name the parameters
4826 Parameter [] p = Parameters.FixedParameters;
4830 for (i = 0; i < p.Length; ++i) {
4832 GetBuilder.DefineParameter (
4833 i + 1, p [i].Attributes, p [i].Name);
4836 SetBuilder.DefineParameter (
4837 i + 1, p [i].Attributes, p [i].Name);
4841 SetBuilder.DefineParameter (
4842 i + 1, ParameterAttributes.None, "value");
4844 if (i != ParameterTypes.Length) {
4845 Parameter array_param = Parameters.ArrayParameter;
4847 SetBuilder.DefineParameter (
4848 i + 1, array_param.Attributes, array_param.Name);
4853 // Define the PropertyBuilder if one of the following conditions are met:
4854 // a) we're not implementing an interface indexer.
4855 // b) the indexer has a different IndexerName and this is no
4856 // explicit interface implementation.
4858 if (!IsExplicitImpl) {
4859 PropertyBuilder = container.TypeBuilder.DefineProperty (
4860 IndexerName, prop_attr, MemberType, ParameterTypes);
4862 if (GetData != null)
4863 PropertyBuilder.SetGetMethod (GetBuilder);
4865 if (SetData != null)
4866 PropertyBuilder.SetSetMethod (SetBuilder);
4868 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4876 public class Operator : MemberBase {
4878 const int AllowedModifiers =
4884 const int RequiredModifiers =
4888 public enum OpType : byte {
4898 // Unary and Binary operators
4921 // Implicit and Explicit
4926 public readonly OpType OperatorType;
4927 public readonly Expression ReturnType;
4928 public readonly Expression FirstArgType, SecondArgType;
4929 public readonly string FirstArgName, SecondArgName;
4931 public MethodBuilder OperatorMethodBuilder;
4933 public string MethodName;
4934 public Method OperatorMethod;
4936 public Operator (OpType type, Expression ret_type, int mod_flags,
4937 Expression arg1type, string arg1name,
4938 Expression arg2type, string arg2name,
4939 Block block, Attributes attrs, Location loc)
4940 : base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC, "", attrs, loc)
4942 OperatorType = type;
4943 ReturnType = ret_type;
4944 FirstArgType = arg1type;
4945 FirstArgName = arg1name;
4946 SecondArgType = arg2type;
4947 SecondArgName = arg2name;
4951 string Prototype (TypeContainer container)
4953 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4954 SecondArgType + ")";
4957 public override bool Define (TypeContainer container)
4960 MethodName = "op_" + OperatorType;
4962 if (SecondArgType != null)
4965 Parameter [] param_list = new Parameter [length];
4967 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4970 "User defined operators `" +
4971 Prototype (container) +
4972 "' must be declared static and public");
4976 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4977 Parameter.Modifier.NONE, null);
4978 if (SecondArgType != null)
4979 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4980 Parameter.Modifier.NONE, null);
4982 OperatorMethod = new Method (container, ReturnType, ModFlags, MethodName,
4983 new Parameters (param_list, null, Location),
4984 OptAttributes, Location);
4986 OperatorMethod.IsOperator = true;
4987 OperatorMethod.Define (container);
4989 if (OperatorMethod.MethodBuilder == null)
4992 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4994 Type [] param_types = OperatorMethod.ParameterTypes;
4995 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4996 Type return_type = OperatorMethod.GetReturnType ();
4997 Type first_arg_type = param_types [0];
4999 // Rules for conversion operators
5001 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
5002 if (first_arg_type == return_type && first_arg_type == declaring_type){
5005 "User-defined conversion cannot take an object of the " +
5006 "enclosing type and convert to an object of the enclosing" +
5011 if (first_arg_type != declaring_type && return_type != declaring_type){
5014 "User-defined conversion must convert to or from the " +
5019 if (first_arg_type == TypeManager.object_type ||
5020 return_type == TypeManager.object_type){
5023 "User-defined conversion cannot convert to or from " +
5028 if (first_arg_type.IsInterface || return_type.IsInterface){
5031 "User-defined conversion cannot convert to or from an " +
5036 if (first_arg_type.IsSubclassOf (return_type) ||
5037 return_type.IsSubclassOf (first_arg_type)){
5040 "User-defined conversion cannot convert between types " +
5041 "that derive from each other");
5044 } else if (SecondArgType == null) {
5045 // Checks for Unary operators
5047 if (first_arg_type != declaring_type){
5050 "The parameter of a unary operator must be the " +
5055 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
5056 if (return_type != declaring_type){
5059 "The parameter and return type for ++ and -- " +
5060 "must be the containing type");
5066 if (OperatorType == OpType.True || OperatorType == OpType.False) {
5067 if (return_type != TypeManager.bool_type){
5070 "The return type of operator True or False " +
5077 // Checks for Binary operators
5079 if (first_arg_type != declaring_type &&
5080 param_types [1] != declaring_type){
5083 "One of the parameters of a binary operator must " +
5084 "be the containing type");
5092 public void Emit (TypeContainer container)
5095 // abstract or extern methods have no bodies
5097 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
5100 OperatorMethod.Block = Block;
5101 OperatorMethod.Emit (container);
5105 public static string GetName (OpType ot)
5108 case OpType.LogicalNot:
5110 case OpType.OnesComplement:
5112 case OpType.Increment:
5114 case OpType.Decrement:
5120 case OpType.Addition:
5122 case OpType.Subtraction:
5124 case OpType.UnaryPlus:
5126 case OpType.UnaryNegation:
5128 case OpType.Multiply:
5130 case OpType.Division:
5132 case OpType.Modulus:
5134 case OpType.BitwiseAnd:
5136 case OpType.BitwiseOr:
5138 case OpType.ExclusiveOr:
5140 case OpType.LeftShift:
5142 case OpType.RightShift:
5144 case OpType.Equality:
5146 case OpType.Inequality:
5148 case OpType.GreaterThan:
5150 case OpType.LessThan:
5152 case OpType.GreaterThanOrEqual:
5154 case OpType.LessThanOrEqual:
5156 case OpType.Implicit:
5158 case OpType.Explicit:
5164 public override string ToString ()
5166 Type return_type = OperatorMethod.GetReturnType();
5167 Type [] param_types = OperatorMethod.ParameterTypes;
5169 if (SecondArgType == null)
5170 return String.Format (
5171 "{0} operator {1}({2})",
5172 TypeManager.CSharpName (return_type),
5173 GetName (OperatorType),
5176 return String.Format (
5177 "{0} operator {1}({2}, {3})",
5178 TypeManager.CSharpName (return_type),
5179 GetName (OperatorType),
5180 param_types [0], param_types [1]);
5185 // This is used to compare method signatures
5187 struct MethodSignature {
5189 public Type RetType;
5190 public Type [] Parameters;
5193 /// This delegate is used to extract methods which have the
5194 /// same signature as the argument
5196 public static MemberFilter method_signature_filter;
5199 /// This delegate is used to extract inheritable methods which
5200 /// have the same signature as the argument. By inheritable,
5201 /// this means that we have permissions to override the method
5202 /// from the current assembly and class
5204 public static MemberFilter inheritable_method_signature_filter;
5206 static MethodSignature ()
5208 method_signature_filter = new MemberFilter (MemberSignatureCompare);
5209 inheritable_method_signature_filter = new MemberFilter (
5210 InheritableMemberSignatureCompare);
5213 public MethodSignature (string name, Type ret_type, Type [] parameters)
5218 if (parameters == null)
5219 Parameters = TypeManager.NoTypes;
5221 Parameters = parameters;
5224 public override string ToString ()
5227 if (Parameters.Length != 0){
5228 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
5229 for (int i = 0; i < Parameters.Length; i++){
5230 sb.Append (Parameters [i]);
5231 if (i+1 < Parameters.Length)
5234 pars = sb.ToString ();
5237 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
5240 public override int GetHashCode ()
5242 return Name.GetHashCode ();
5245 public override bool Equals (Object o)
5247 MethodSignature other = (MethodSignature) o;
5249 if (other.Name != Name)
5252 if (other.RetType != RetType)
5255 if (Parameters == null){
5256 if (other.Parameters == null)
5261 if (other.Parameters == null)
5264 int c = Parameters.Length;
5265 if (other.Parameters.Length != c)
5268 for (int i = 0; i < c; i++)
5269 if (other.Parameters [i] != Parameters [i])
5275 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
5277 MethodSignature sig = (MethodSignature) filter_criteria;
5279 if (m.Name != sig.Name)
5283 MethodInfo mi = m as MethodInfo;
5284 PropertyInfo pi = m as PropertyInfo;
5287 ReturnType = mi.ReturnType;
5288 else if (pi != null)
5289 ReturnType = pi.PropertyType;
5294 // we use sig.RetType == null to mean `do not check the
5295 // method return value.
5297 if (sig.RetType != null)
5298 if (ReturnType != sig.RetType)
5303 args = TypeManager.GetArgumentTypes (mi);
5305 args = TypeManager.GetArgumentTypes (pi);
5306 Type [] sigp = sig.Parameters;
5308 if (args.Length != sigp.Length)
5311 for (int i = args.Length; i > 0; ){
5313 if (args [i] != sigp [i])
5320 // This filter should be used when we are requesting methods that
5321 // we want to override.
5323 // This makes a number of assumptions, for example
5324 // that the methods being extracted are of a parent
5325 // class (this means we know implicitly that we are
5326 // being called to find out about members by a derived
5329 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
5332 PropertyInfo pi = m as PropertyInfo;
5335 mi = pi.GetGetMethod (true);
5337 mi = pi.GetSetMethod (true);
5339 mi = m as MethodInfo;
5342 Console.WriteLine ("Nothing found");
5345 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
5347 // If only accessible to the current class.
5348 if (prot == MethodAttributes.Private)
5351 if (!MemberSignatureCompare (m, filter_criteria))
5354 // If only accessible to the defining assembly or
5355 if (prot == MethodAttributes.FamANDAssem ||
5356 prot == MethodAttributes.Assembly){
5357 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
5363 // Anything else (FamOrAssembly and Public) is fine