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 public bool UserDefinedStaticConstructor = false;
104 // Whether we have at least one non-static field
106 bool have_nonstatic_fields = false;
109 // This one is computed after we can distinguish interfaces
110 // from classes from the arraylist `type_bases'
112 string base_class_name;
114 ArrayList type_bases;
116 // Information in the case we are an attribute type
118 public AttributeTargets Targets = AttributeTargets.All;
119 public bool AllowMultiple = false;
120 public bool Inherited;
122 // The interfaces we implement.
125 // The parent member container and our member cache
126 IMemberContainer parent_container;
127 MemberCache member_cache;
130 // The indexer name for this class
132 public string IndexerName;
136 public TypeContainer ():
137 this (null, null, "", null, new Location (-1)) {
140 public TypeContainer (NamespaceEntry ns, TypeContainer parent, string name, Attributes attrs, Location l)
141 : base (ns, parent, name, attrs, l)
143 types = new ArrayList ();
145 base_class_name = null;
148 public AdditionResult AddConstant (Const constant)
151 string basename = constant.Name;
152 string fullname = Name + "." + basename;
154 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
157 if (constants == null)
158 constants = new ArrayList ();
160 constants.Add (constant);
161 DefineName (fullname, constant);
163 return AdditionResult.Success;
166 public AdditionResult AddEnum (Mono.CSharp.Enum e)
170 if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
174 enums = new ArrayList ();
177 DefineName (e.Name, e);
179 return AdditionResult.Success;
182 public AdditionResult AddClass (Class c)
185 string name = c.Basename;
187 if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
190 DefineName (c.Name, c);
193 return AdditionResult.Success;
196 public AdditionResult AddStruct (Struct s)
199 string name = s.Basename;
201 if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
204 DefineName (s.Name, s);
207 return AdditionResult.Success;
210 public AdditionResult AddDelegate (Delegate d)
213 string name = d.Basename;
215 if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
218 if (delegates == null)
219 delegates = new ArrayList ();
221 DefineName (d.Name, d);
224 return AdditionResult.Success;
227 public AdditionResult AddMethod (Method method)
229 string basename = method.Name;
230 string fullname = Name + "." + basename;
232 Object value = defined_names [fullname];
234 if (value != null && (!(value is Method)))
235 return AdditionResult.NameExists;
237 if (basename == Basename)
238 return AdditionResult.EnclosingClash;
241 methods = new ArrayList ();
243 if (method.Name.IndexOf ('.') != -1)
244 methods.Insert (0, method);
246 methods.Add (method);
249 DefineName (fullname, method);
251 return AdditionResult.Success;
254 public AdditionResult AddConstructor (Constructor c)
256 if (c.Name != Basename)
257 return AdditionResult.NotAConstructor;
259 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
262 UserDefinedStaticConstructor = true;
263 if (default_static_constructor != null)
264 return AdditionResult.MethodExists;
266 default_static_constructor = c;
269 if (default_constructor != null)
270 return AdditionResult.MethodExists;
271 default_constructor = c;
274 if (instance_constructors == null)
275 instance_constructors = new ArrayList ();
277 instance_constructors.Add (c);
280 return AdditionResult.Success;
283 public AdditionResult AddInterface (Interface iface)
286 string name = iface.Basename;
288 if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
291 if (interfaces == null)
292 interfaces = new ArrayList ();
293 interfaces.Add (iface);
294 DefineName (iface.Name, iface);
296 return AdditionResult.Success;
299 public AdditionResult AddField (Field field)
302 string basename = field.Name;
303 string fullname = Name + "." + basename;
305 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
309 fields = new ArrayList ();
313 if (field.HasInitializer){
314 if ((field.ModFlags & Modifiers.STATIC) != 0){
315 if (initialized_static_fields == null)
316 initialized_static_fields = new ArrayList ();
318 initialized_static_fields.Add (field);
321 if (initialized_fields == null)
322 initialized_fields = new ArrayList ();
324 initialized_fields.Add (field);
328 if ((field.ModFlags & Modifiers.STATIC) == 0)
329 have_nonstatic_fields = true;
331 DefineName (fullname, field);
332 return AdditionResult.Success;
335 public AdditionResult AddProperty (Property prop)
339 if ((res = AddProperty (prop, prop.Name)) != AdditionResult.Success)
342 if (prop.Get != null) {
343 if ((res = AddProperty (prop, "get_" + prop.Name)) != AdditionResult.Success)
347 if (prop.Set != null) {
348 if ((res = AddProperty (prop, "set_" + prop.Name)) != AdditionResult.Success)
352 if (properties == null)
353 properties = new ArrayList ();
355 if (prop.Name.IndexOf ('.') != -1)
356 properties.Insert (0, prop);
358 properties.Add (prop);
360 return AdditionResult.Success;
363 AdditionResult AddProperty (Property prop, string basename)
366 string fullname = Name + "." + basename;
368 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
371 DefineName (fullname, prop);
373 return AdditionResult.Success;
376 public AdditionResult AddEvent (Event e)
379 string basename = e.Name;
380 string fullname = Name + "." + basename;
382 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
386 events = new ArrayList ();
389 DefineName (fullname, e);
391 return AdditionResult.Success;
394 public void AddIndexer (Indexer i)
396 if (indexers == null)
397 indexers = new ArrayList ();
399 if (i.InterfaceType != null)
400 indexers.Insert (0, i);
405 public AdditionResult AddOperator (Operator op)
407 if (operators == null)
408 operators = new ArrayList ();
412 string basename = op.Name;
413 string fullname = Name + "." + basename;
414 if (!defined_names.Contains (fullname))
416 DefineName (fullname, op);
418 return AdditionResult.Success;
421 public void RegisterOrder (Interface iface)
423 if (interface_order == null)
424 interface_order = new ArrayList ();
426 interface_order.Add (iface);
429 public ArrayList Types {
435 public ArrayList Methods {
441 public ArrayList Constants {
447 public ArrayList Interfaces {
455 return base_class_name;
459 public ArrayList Bases {
469 public ArrayList Fields {
479 public ArrayList InstanceConstructors {
481 return instance_constructors;
485 public ArrayList Properties {
491 public ArrayList Events {
497 public ArrayList Enums {
503 public ArrayList Indexers {
509 public ArrayList Operators {
515 public ArrayList Delegates {
521 public virtual TypeAttributes TypeAttr {
523 return Modifiers.TypeAttr (ModFlags, this);
528 // Emits the instance field initializers
530 public bool EmitFieldInitializers (EmitContext ec)
533 Expression instance_expr;
536 fields = initialized_static_fields;
537 instance_expr = null;
539 fields = initialized_fields;
540 instance_expr = new This (Location.Null).Resolve (ec);
546 foreach (Field f in fields){
547 Expression e = f.GetInitializerExpression (ec);
551 Location l = f.Location;
552 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
553 fe.InstanceExpression = instance_expr;
554 ExpressionStatement a = new Assign (fe, e, l);
556 a = a.ResolveStatement (ec);
560 a.EmitStatement (ec);
567 // Defines the default constructors
569 void DefineDefaultConstructor (bool is_static)
573 // The default constructor is public
574 // If the class is abstract, the default constructor is protected
575 // The default static constructor is private
577 int mods = Modifiers.PUBLIC;
579 mods = Modifiers.STATIC | Modifiers.PRIVATE;
580 else if ((ModFlags & Modifiers.ABSTRACT) != 0)
581 mods = Modifiers.PROTECTED;
583 c = new Constructor (this, Basename, mods, Parameters.EmptyReadOnlyParameters,
584 new ConstructorBaseInitializer (
585 null, Parameters.EmptyReadOnlyParameters,
591 c.Block = new ToplevelBlock (null, Location);
595 public void ReportStructInitializedInstanceError ()
597 string n = TypeBuilder.FullName;
599 foreach (Field f in initialized_fields){
602 "`" + n + "." + f.Name + "': can not have " +
603 "instance field initializers in structs");
608 /// The pending methods that need to be implemented (interfaces or abstract methods)
610 public PendingImplementation Pending;
613 /// This function computes the Base class and also the
614 /// list of interfaces that the class or struct @c implements.
616 /// The return value is an array (might be null) of
617 /// interfaces implemented (as Types).
619 /// The @parent argument is set to the parent object or null
620 /// if this is `System.Object'.
622 TypeExpr [] GetClassBases (bool is_class, out TypeExpr parent, out bool error)
624 ArrayList bases = Bases;
633 parent = TypeManager.system_valuetype_expr;
637 if (RootContext.StdLib)
638 parent = TypeManager.system_object_expr;
639 else if (Name != "System.Object")
640 parent = TypeManager.system_object_expr;
643 // If we are compiling our runtime,
644 // and we are defining ValueType, then our
645 // parent is `System.Object'.
647 if (!RootContext.StdLib && Name == "System.ValueType")
648 parent = TypeManager.system_object_expr;
655 // Bases should be null if there are no bases at all
660 TypeExpr name = ResolveTypeExpr ((Expression) bases [0], false, Location);
667 if (name is TypeParameterExpr){
670 "Type parameter `{0}' can not be used as a " +
671 "base class or interface", name.Name);
676 if (IsGeneric && name.IsAttribute){
679 "A generic type cannot derive from `{0}' " +
680 "because it is an attribute class", name.Name);
689 parent = TypeManager.system_object_expr;
695 if (name.IsValueType)
696 detail = " (a class can not inherit from a struct/enum)";
698 Report.Error (509, "class `"+ Name +
699 "': Cannot inherit from sealed class `"+
700 name.Name + "'" + detail);
705 if (!parent.CanInheritFrom ()){
706 Report.Error (644, Location,
707 "`{0}' cannot inherit from special class `{1}'",
713 if (!parent.AsAccessible (this, ModFlags))
714 Report.Error (60, Location,
715 "Inconsistent accessibility: base class `" +
716 name.Name + "' is less accessible than class `" +
724 base_class_name = parent.Name;
726 TypeExpr [] ifaces = new TypeExpr [count-start];
728 for (i = start, j = 0; i < count; i++, j++){
729 Expression name = (Expression) bases [i];
730 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
732 if (resolved == null)
735 bases [i] = resolved;
737 if (is_class == false && !resolved.IsInterface){
738 Report.Error (527, "In Struct `" + Name + "', type `"+
739 name +"' is not an interface");
744 if (resolved.IsClass) {
746 Report.Error (527, "In Class `" + Name + "', type `"+
747 name+"' is not an interface");
753 for (int x = 0; x < j; x++) {
754 if (resolved.Equals (ifaces [x])) {
755 Report.Error (528, "`" + name + "' is already listed in interface list");
761 ifaces [j] = resolved;
764 return TypeManager.ExpandInterfaces (ifaces);
767 bool CheckGenericInterfaces (Type[] ifaces)
769 ArrayList already_checked = new ArrayList ();
771 for (int i = 0; i < ifaces.Length; i++) {
772 Type iface = ifaces [i];
773 foreach (Type t in already_checked) {
777 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t))
782 "`{0}' cannot implement both `{1}' and `{2}' " +
783 "because they may unify for some type " +
784 "parameter substitutions",
785 TypeManager.GetFullName (TypeBuilder),
790 already_checked.Add (iface);
799 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
801 public override TypeBuilder DefineType ()
806 if (TypeBuilder != null)
813 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
825 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
827 ifaces = GetClassBases (is_class, out parent, out error);
833 foreach (TypeParameter type_param in TypeParameters)
834 if (!type_param.Resolve (this)) {
840 if (!is_class && TypeManager.value_type == null)
841 throw new Exception ();
843 TypeAttributes type_attributes = TypeAttr;
846 ConstructedType constructed = parent as ConstructedType;
847 if ((constructed == null) && (parent != null))
848 ptype = parent.ResolveType (ec);
853 if (TypeManager.NamespaceClash (Name, Location)) {
858 ModuleBuilder builder = CodeGen.Module.Builder;
859 TypeBuilder = builder.DefineType (
860 Name, type_attributes, ptype, null);
863 TypeBuilder builder = Parent.DefineType ();
867 TypeBuilder = builder.DefineNestedType (
868 Basename, type_attributes, ptype, null);
871 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
874 CurrentType = new ConstructedType (
875 Name, TypeParameters, Location);
877 foreach (TypeParameter type_param in TypeParameters)
878 type_param.Define (TypeBuilder);
881 if (constructed != null) {
882 ptype = constructed.ResolveType (ec);
886 TypeBuilder.SetParent (ptype);
890 foreach (TypeParameter type_param in TypeParameters)
891 type_param.DefineType (ec, TypeBuilder);
895 // Structs with no fields need to have at least one byte.
896 // The right thing would be to set the PackingSize in a DefineType
897 // but there are no functions that allow interfaces *and* the size to
901 if (!is_class && !have_nonstatic_fields){
902 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
903 FieldAttributes.Private);
906 // add interfaces that were not added at type creation
907 if (ifaces != null) {
908 Type[] itypes = new Type [ifaces.Length];
909 for (int i = 0; i < ifaces.Length; i++) {
910 itypes [i] = ifaces [i].ResolveType (ec);
911 if (itypes [i] == null)
918 if (!CheckGenericInterfaces (itypes)) {
923 for (int i = 0; i < ifaces.Length; i++)
924 TypeBuilder.AddInterfaceImplementation (itypes [i]);
928 // Finish the setup for the EmitContext
930 ec.ContainerType = TypeBuilder;
932 if ((parent != null) && parent.IsAttribute) {
933 RootContext.RegisterAttribute (this);
934 TypeManager.RegisterAttrType (TypeBuilder, this);
936 RootContext.RegisterOrder (this);
938 if (Interfaces != null) {
939 foreach (Interface iface in Interfaces)
940 if (iface.DefineType () == null) {
947 foreach (TypeContainer tc in Types)
948 if (tc.DefineType () == null) {
954 if (Delegates != null) {
955 foreach (Delegate d in Delegates)
956 if (d.DefineType () == null) {
963 foreach (Enum en in Enums)
964 if (en.DefineType () == null) {
976 /// Defines the MemberCore objects that are in the `list' Arraylist
978 /// The `defined_names' array contains a list of members defined in
981 static ArrayList remove_list = new ArrayList ();
982 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
986 remove_list.Clear ();
988 foreach (MemberCore mc in list){
990 if (defined_names != null)
991 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
996 if (RootContext.WarningLevel >= 4){
997 if ((mc.ModFlags & Modifiers.NEW) != 0)
998 Warning_KeywordNewNotRequired (mc.Location, mc);
1000 } else if (mc is MethodCore)
1001 ((MethodCore) mc).OverridesSomething = true;
1003 if (!mc.Define (this)){
1004 remove_list.Add (mc);
1011 MemberInfo match = defined_names [idx];
1013 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
1017 // If we are both methods, let the method resolution emit warnings
1019 if (match is MethodBase && mc is MethodCore)
1022 if ((mc.ModFlags & Modifiers.NEW) == 0) {
1024 if (!(match is EventInfo)) {
1025 Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
1029 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
1033 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
1037 foreach (object o in remove_list)
1040 remove_list.Clear ();
1044 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
1045 // class is consisten. Either it is `Item' or it is the name defined by all the
1046 // indexers with the `IndexerName' attribute.
1048 // Turns out that the IndexerNameAttribute is applied to each indexer,
1049 // but it is never emitted, instead a DefaultName attribute is attached
1052 void DefineIndexers ()
1054 string class_indexer_name = null;
1057 // If there's both an explicit and an implicit interface implementation, the
1058 // explicit one actually implements the interface while the other one is just
1059 // a normal indexer. See bug #37714.
1061 ArrayList list = new ArrayList ();
1062 foreach (Indexer i in Indexers){
1063 if (i.ExplicitInterfaceName != null)
1066 foreach (Indexer i in Indexers){
1067 if (i.ExplicitInterfaceName == null)
1071 foreach (Indexer i in list){
1076 name = i.IndexerName;
1078 if (i.InterfaceType != null)
1081 if (class_indexer_name == null){
1082 class_indexer_name = name;
1086 if (name == class_indexer_name)
1090 668, "Two indexers have different names, " +
1091 " you should use the same name for all your indexers");
1093 if (class_indexer_name == null)
1094 class_indexer_name = "Item";
1095 IndexerName = class_indexer_name;
1098 static void Error_KeywordNotAllowed (Location loc)
1100 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1104 /// Populates our TypeBuilder with fields and methods
1106 public override bool DefineMembers (TypeContainer container)
1108 MemberInfo [] defined_names = null;
1111 // We need to be able to use the member cache while we are checking/defining
1114 if (TypeBuilder.BaseType != null)
1115 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1118 if (interface_order != null){
1119 foreach (Interface iface in interface_order)
1120 if ((iface.ModFlags & Modifiers.NEW) == 0)
1121 iface.DefineMembers (this);
1123 Error_KeywordNotAllowed (iface.Location);
1126 if (RootContext.WarningLevel > 1){
1130 // This code throws an exception in the comparer
1131 // I guess the string is not an object?
1133 ptype = TypeBuilder.BaseType;
1135 defined_names = (MemberInfo []) FindMembers (
1136 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1137 BindingFlags.Public | BindingFlags.Instance |
1138 BindingFlags.Static, null, null);
1140 Array.Sort (defined_names, mif_compare);
1144 Class pclass = Parent as Class;
1145 if (pclass != null) {
1146 string pname = null;
1148 Type t = pclass.TypeBuilder.BaseType;
1149 while ((t != null) && (ptype == null)) {
1150 pname = t.FullName + "." + Basename;
1151 ptype = RootContext.LookupType (this, pname, true, Location.Null);
1155 if ((ModFlags & Modifiers.NEW) != 0) {
1157 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1158 "inherited member. The keyword new is not required.");
1159 } else if (ptype != null) {
1160 Report.Warning (108, Location, "The keyword new is required on `" +
1161 Name + "' because it hides inherited member '" +
1164 } else if ((ModFlags & Modifiers.NEW) != 0)
1165 Error_KeywordNotAllowed (Location);
1167 if (constants != null)
1168 DefineMembers (constants, defined_names);
1171 DefineMembers (fields, defined_names);
1174 if (instance_constructors == null){
1175 if (default_constructor == null)
1176 DefineDefaultConstructor (false);
1179 if (initialized_static_fields != null &&
1180 default_static_constructor == null)
1181 DefineDefaultConstructor (true);
1184 if (this is Struct){
1186 // Structs can not have initialized instance
1189 if (initialized_static_fields != null &&
1190 default_static_constructor == null)
1191 DefineDefaultConstructor (true);
1193 if (initialized_fields != null)
1194 ReportStructInitializedInstanceError ();
1197 Pending = PendingImplementation.GetPendingImplementations (this);
1200 // Constructors are not in the defined_names array
1202 if (instance_constructors != null)
1203 DefineMembers (instance_constructors, null);
1205 if (default_static_constructor != null)
1206 default_static_constructor.Define (this);
1208 if (methods != null)
1209 DefineMembers (methods, defined_names);
1211 if (properties != null)
1212 DefineMembers (properties, defined_names);
1215 DefineMembers (events, defined_names);
1217 if (indexers != null) {
1220 IndexerName = "Item";
1222 if (operators != null){
1223 DefineMembers (operators, null);
1225 CheckPairedOperators ();
1229 DefineMembers (enums, defined_names);
1231 if (delegates != null)
1232 DefineMembers (delegates, defined_names);
1234 if (CurrentType != null) {
1235 GenericType = CurrentType.ResolveType (ec);
1237 ec.ContainerType = GenericType;
1242 member_cache = new MemberCache (this);
1249 public override bool Define (TypeContainer container)
1251 if (interface_order != null){
1252 foreach (Interface iface in interface_order)
1253 if ((iface.ModFlags & Modifiers.NEW) == 0)
1254 iface.Define (this);
1261 /// This function is based by a delegate to the FindMembers routine
1263 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1269 /// This filter is used by FindMembers, and we just keep
1270 /// a global for the filter to `AlwaysAccept'
1272 static MemberFilter accepting_filter;
1276 /// A member comparission method based on name only
1278 static IComparer mif_compare;
1280 static TypeContainer ()
1282 accepting_filter = new MemberFilter (AlwaysAccept);
1283 mif_compare = new MemberInfoCompare ();
1287 /// This method returns the members of this type just like Type.FindMembers would
1288 /// Only, we need to use this for types which are _being_ defined because MS'
1289 /// implementation can't take care of that.
1292 // FIXME: return an empty static array instead of null, that cleans up
1293 // some code and is consistent with some coding conventions I just found
1297 // Notice that in various cases we check if our field is non-null,
1298 // something that would normally mean that there was a bug elsewhere.
1300 // The problem happens while we are defining p-invoke methods, as those
1301 // will trigger a FindMembers, but this happens before things are defined
1303 // Since the whole process is a no-op, it is fine to check for null here.
1305 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1306 MemberFilter filter, object criteria)
1308 ArrayList members = null;
1311 if ((bf & BindingFlags.Public) != 0)
1312 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1314 if ((bf & BindingFlags.NonPublic) != 0)
1315 modflags |= Modifiers.PRIVATE;
1317 int static_mask = 0, static_flags = 0;
1318 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1319 case BindingFlags.Static:
1320 static_mask = static_flags = Modifiers.STATIC;
1323 case BindingFlags.Instance:
1324 static_mask = Modifiers.STATIC;
1329 static_mask = static_flags = 0;
1333 Timer.StartTimer (TimerType.TcFindMembers);
1336 filter = accepting_filter;
1338 if ((mt & MemberTypes.Field) != 0) {
1339 if (fields != null) {
1340 int len = fields.Count;
1341 for (int i = 0; i < len; i++) {
1342 Field f = (Field) fields [i];
1344 if ((f.ModFlags & modflags) == 0)
1346 if ((f.ModFlags & static_mask) != static_flags)
1349 FieldBuilder fb = f.FieldBuilder;
1350 if (fb != null && filter (fb, criteria) == true) {
1351 if (members == null)
1352 members = new ArrayList ();
1359 if (constants != null) {
1360 int len = constants.Count;
1361 for (int i = 0; i < len; i++) {
1362 Const con = (Const) constants [i];
1364 if ((con.ModFlags & modflags) == 0)
1366 if ((con.ModFlags & static_mask) != static_flags)
1369 FieldBuilder fb = con.FieldBuilder;
1370 if (fb != null && filter (fb, criteria) == true) {
1371 if (members == null)
1372 members = new ArrayList ();
1380 if ((mt & MemberTypes.Method) != 0) {
1381 if (methods != null) {
1382 int len = methods.Count;
1383 for (int i = 0; i < len; i++) {
1384 Method m = (Method) methods [i];
1386 if ((m.ModFlags & modflags) == 0)
1388 if ((m.ModFlags & static_mask) != static_flags)
1391 MethodBuilder mb = m.MethodBuilder;
1393 if (mb != null && filter (mb, criteria) == true) {
1394 if (members == null)
1395 members = new ArrayList ();
1402 if (operators != null) {
1403 int len = operators.Count;
1404 for (int i = 0; i < len; i++) {
1405 Operator o = (Operator) operators [i];
1407 if ((o.ModFlags & modflags) == 0)
1409 if ((o.ModFlags & static_mask) != static_flags)
1412 MethodBuilder ob = o.OperatorMethodBuilder;
1413 if (ob != null && filter (ob, criteria) == true) {
1414 if (members == null)
1415 members = new ArrayList ();
1422 if (properties != null) {
1423 int len = properties.Count;
1424 for (int i = 0; i < len; i++) {
1425 Property p = (Property) properties [i];
1427 if ((p.ModFlags & modflags) == 0)
1429 if ((p.ModFlags & static_mask) != static_flags)
1435 if (b != null && filter (b, criteria) == true) {
1436 if (members == null)
1437 members = new ArrayList ();
1443 if (b != null && filter (b, criteria) == true) {
1444 if (members == null)
1445 members = new ArrayList ();
1452 if (indexers != null) {
1453 int len = indexers.Count;
1454 for (int i = 0; i < len; i++) {
1455 Indexer ix = (Indexer) indexers [i];
1457 if ((ix.ModFlags & modflags) == 0)
1459 if ((ix.ModFlags & static_mask) != static_flags)
1465 if (b != null && filter (b, criteria) == true) {
1466 if (members == null)
1467 members = new ArrayList ();
1473 if (b != null && filter (b, criteria) == true) {
1474 if (members == null)
1475 members = new ArrayList ();
1483 if ((mt & MemberTypes.Event) != 0) {
1484 if (events != null) {
1485 int len = events.Count;
1486 for (int i = 0; i < len; i++) {
1487 Event e = (Event) events [i];
1489 if ((e.ModFlags & modflags) == 0)
1491 if ((e.ModFlags & static_mask) != static_flags)
1494 MemberInfo eb = e.EventBuilder;
1495 if (eb != null && filter (eb, criteria) == true) {
1496 if (members == null)
1497 members = new ArrayList ();
1499 members.Add (e.EventBuilder);
1505 if ((mt & MemberTypes.Property) != 0){
1506 if (properties != null) {
1507 int len = properties.Count;
1508 for (int i = 0; i < len; i++) {
1509 Property p = (Property) properties [i];
1511 if ((p.ModFlags & modflags) == 0)
1513 if ((p.ModFlags & static_mask) != static_flags)
1516 MemberInfo pb = p.PropertyBuilder;
1517 if (pb != null && filter (pb, criteria) == true) {
1518 if (members == null)
1519 members = new ArrayList ();
1521 members.Add (p.PropertyBuilder);
1526 if (indexers != null) {
1527 int len = indexers.Count;
1528 for (int i = 0; i < len; i++) {
1529 Indexer ix = (Indexer) indexers [i];
1531 if ((ix.ModFlags & modflags) == 0)
1533 if ((ix.ModFlags & static_mask) != static_flags)
1536 MemberInfo ib = ix.PropertyBuilder;
1537 if (ib != null && filter (ib, criteria) == true) {
1538 if (members == null)
1539 members = new ArrayList ();
1541 members.Add (ix.PropertyBuilder);
1547 if ((mt & MemberTypes.NestedType) != 0) {
1548 if (types != null) {
1549 int len = types.Count;
1550 for (int i = 0; i < len; i++) {
1551 TypeContainer t = (TypeContainer) types [i];
1553 if ((t.ModFlags & modflags) == 0)
1556 TypeBuilder tb = t.TypeBuilder;
1557 if (tb != null && (filter (tb, criteria) == true)) {
1558 if (members == null)
1559 members = new ArrayList ();
1566 if (enums != null) {
1567 int len = enums.Count;
1568 for (int i = 0; i < len; i++) {
1569 Enum en = (Enum) enums [i];
1571 if ((en.ModFlags & modflags) == 0)
1574 TypeBuilder tb = en.TypeBuilder;
1575 if (tb != null && (filter (tb, criteria) == true)) {
1576 if (members == null)
1577 members = new ArrayList ();
1584 if (delegates != null) {
1585 int len = delegates.Count;
1586 for (int i = 0; i < len; i++) {
1587 Delegate d = (Delegate) delegates [i];
1589 if ((d.ModFlags & modflags) == 0)
1592 TypeBuilder tb = d.TypeBuilder;
1593 if (tb != null && (filter (tb, criteria) == true)) {
1594 if (members == null)
1595 members = new ArrayList ();
1602 if (interfaces != null) {
1603 int len = interfaces.Count;
1604 for (int i = 0; i < len; i++) {
1605 Interface iface = (Interface) interfaces [i];
1607 if ((iface.ModFlags & modflags) == 0)
1610 TypeBuilder tb = iface.TypeBuilder;
1611 if (tb != null && (filter (tb, criteria) == true)) {
1612 if (members == null)
1613 members = new ArrayList ();
1621 if ((mt & MemberTypes.Constructor) != 0){
1622 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1623 int len = instance_constructors.Count;
1624 for (int i = 0; i < len; i++) {
1625 Constructor c = (Constructor) instance_constructors [i];
1627 ConstructorBuilder cb = c.ConstructorBuilder;
1628 if (cb != null && filter (cb, criteria) == true) {
1629 if (members == null)
1630 members = new ArrayList ();
1637 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1638 ConstructorBuilder cb =
1639 default_static_constructor.ConstructorBuilder;
1641 if (cb != null && filter (cb, criteria) == true) {
1642 if (members == null)
1643 members = new ArrayList ();
1651 // Lookup members in parent if requested.
1653 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1654 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1655 if (list.Count > 0) {
1656 if (members == null)
1657 members = new ArrayList ();
1659 members.AddRange (list);
1663 Timer.StopTimer (TimerType.TcFindMembers);
1665 if (members == null)
1666 return MemberList.Empty;
1668 return new MemberList (members);
1671 public override MemberCache MemberCache {
1673 return member_cache;
1677 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1678 MemberFilter filter, object criteria)
1680 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1683 return ds.FindMembers (mt, bf, filter, criteria);
1685 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1689 // FindMethods will look for methods not only in the type `t', but in
1690 // any interfaces implemented by the type.
1692 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1693 MemberFilter filter, object criteria)
1699 /// Emits the values for the constants
1701 public void EmitConstants ()
1703 if (constants != null)
1704 foreach (Const con in constants)
1710 /// Emits the code, this step is performed after all
1711 /// the types, enumerations, constructors
1715 if (instance_constructors != null)
1716 foreach (Constructor c in instance_constructors)
1719 if (default_static_constructor != null)
1720 default_static_constructor.Emit (this);
1722 if (methods != null)
1723 foreach (Method m in methods)
1726 if (operators != null)
1727 foreach (Operator o in operators)
1730 if (properties != null)
1731 foreach (Property p in properties)
1734 if (indexers != null){
1735 foreach (Indexer ix in indexers)
1738 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1739 this, IndexerName, ModFlags, Location);
1740 TypeBuilder.SetCustomAttribute (cb);
1744 foreach (Field f in fields)
1747 if (events != null){
1748 foreach (Event e in Events)
1752 if (Pending != null)
1753 if (Pending.VerifyPendingMethods ())
1756 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
1759 // Check for internal or private fields that were never assigned
1761 if (RootContext.WarningLevel >= 3) {
1762 if (fields != null){
1763 foreach (Field f in fields) {
1764 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
1767 if ((f.status & Field.Status.USED) == 0){
1769 169, f.Location, "Private field " +
1770 MakeName (f.Name) + " is never used");
1775 // Only report 649 on level 4
1777 if (RootContext.WarningLevel < 4)
1780 if ((f.status & Field.Status.ASSIGNED) != 0)
1785 "Field " + MakeName (f.Name) + " is never assigned " +
1786 " to and will always have its default value");
1790 if (events != null){
1791 foreach (Event e in events){
1793 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1798 // if (types != null)
1799 // foreach (TypeContainer tc in types)
1803 public override void CloseType ()
1810 TypeBuilder.CreateType ();
1811 } catch (TypeLoadException){
1813 // This is fine, the code still created the type
1815 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1816 // Console.WriteLine (e.Message);
1818 Console.WriteLine ("In type: " + Name);
1823 foreach (Enum en in Enums)
1826 if (interface_order != null){
1827 foreach (Interface iface in interface_order)
1832 foreach (TypeContainer tc in Types)
1836 foreach (TypeContainer tc in Types)
1837 if (!(tc is Struct))
1841 if (Delegates != null)
1842 foreach (Delegate d in Delegates)
1850 initialized_fields = null;
1851 initialized_static_fields = null;
1854 interface_order = null;
1860 default_constructor = null;
1861 default_static_constructor = null;
1863 OptAttributes = null;
1865 parent_container = null;
1866 member_cache = null;
1869 public string MakeName (string n)
1871 return "`" + Name + "." + n + "'";
1874 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1877 108, l, "The keyword new is required on " +
1878 MakeName (mi.Name) + " because it hides `" +
1879 mi.ReflectedType.Name + "." + mi.Name + "'");
1882 public void Warning_KeywordNewNotRequired (Location l, MemberCore mc)
1885 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1886 "inherited member, the keyword new is not required");
1889 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
1892 72, l, MakeName (mi.Name) + " : cannot override; `" +
1893 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
1896 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1902 // Performs the validation on a Method's modifiers (properties have
1903 // the same properties).
1905 public bool MethodModifiersValid (int flags, string n, Location loc)
1907 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1908 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1909 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1913 // At most one of static, virtual or override
1915 if ((flags & Modifiers.STATIC) != 0){
1916 if ((flags & vao) != 0){
1918 112, loc, "static method " + MakeName (n) + "can not be marked " +
1919 "as virtual, abstract or override");
1924 if (this is Struct){
1925 if ((flags & va) != 0){
1926 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1931 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1933 113, loc, MakeName (n) +
1934 " marked as override cannot be marked as new or virtual");
1939 // If the declaration includes the abstract modifier, then the
1940 // declaration does not include static, virtual or extern
1942 if ((flags & Modifiers.ABSTRACT) != 0){
1943 if ((flags & Modifiers.EXTERN) != 0){
1945 180, loc, MakeName (n) + " can not be both abstract and extern");
1949 if ((flags & Modifiers.VIRTUAL) != 0){
1951 503, loc, MakeName (n) + " can not be both abstract and virtual");
1955 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1957 513, loc, MakeName (n) +
1958 " is abstract but its container class is not");
1964 if ((flags & Modifiers.PRIVATE) != 0){
1965 if ((flags & vao) != 0){
1967 621, loc, MakeName (n) +
1968 " virtual or abstract members can not be private");
1973 if ((flags & Modifiers.SEALED) != 0){
1974 if ((flags & Modifiers.OVERRIDE) == 0){
1976 238, loc, MakeName (n) +
1977 " cannot be sealed because it is not an override");
1985 Hashtable builder_and_args;
1987 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1989 if (builder_and_args == null)
1990 builder_and_args = new Hashtable ();
1995 /// Performs checks for an explicit interface implementation. First it
1996 /// checks whether the `interface_type' is a base inteface implementation.
1997 /// Then it checks whether `name' exists in the interface type.
1999 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
2003 if (ifaces != null){
2004 foreach (TypeExpr t in ifaces){
2005 if (t.Type == interface_type){
2013 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
2024 string IMemberContainer.Name {
2030 Type IMemberContainer.Type {
2036 IMemberContainer IMemberContainer.Parent {
2038 return parent_container;
2042 MemberCache IMemberContainer.MemberCache {
2044 return member_cache;
2048 bool IMemberContainer.IsInterface {
2054 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2056 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2058 if (GenericType != null)
2059 return TypeManager.FindMembers (GenericType, mt, new_bf,
2062 return FindMembers (mt, new_bf, null, null);
2066 // Operator pair checking
2069 class OperatorEntry {
2071 public Type ret_type;
2072 public Type type1, type2;
2074 public Operator.OpType ot;
2076 public OperatorEntry (int f, Operator o)
2080 ret_type = o.OperatorMethod.GetReturnType ();
2081 Type [] pt = o.OperatorMethod.ParameterTypes;
2085 ot = o.OperatorType;
2088 public override int GetHashCode ()
2090 return ret_type.GetHashCode ();
2093 public override bool Equals (object o)
2095 OperatorEntry other = (OperatorEntry) o;
2097 if (other.ret_type != ret_type)
2099 if (other.type1 != type1)
2101 if (other.type2 != type2)
2108 // Checks that some operators come in pairs:
2114 // They are matched based on the return type and the argument types
2116 void CheckPairedOperators ()
2118 Hashtable pairs = new Hashtable (null, null);
2119 Operator true_op = null;
2120 Operator false_op = null;
2121 bool has_equality_or_inequality = false;
2123 // Register all the operators we care about.
2124 foreach (Operator op in operators){
2127 switch (op.OperatorType){
2128 case Operator.OpType.Equality:
2130 has_equality_or_inequality = true;
2132 case Operator.OpType.Inequality:
2134 has_equality_or_inequality = true;
2137 case Operator.OpType.True:
2140 case Operator.OpType.False:
2144 case Operator.OpType.GreaterThan:
2146 case Operator.OpType.LessThan:
2149 case Operator.OpType.GreaterThanOrEqual:
2151 case Operator.OpType.LessThanOrEqual:
2157 OperatorEntry oe = new OperatorEntry (reg, op);
2159 object o = pairs [oe];
2163 oe = (OperatorEntry) o;
2168 if (true_op != null){
2169 if (false_op == null)
2170 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2171 } else if (false_op != null)
2172 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2175 // Look for the mistakes.
2177 foreach (DictionaryEntry de in pairs){
2178 OperatorEntry oe = (OperatorEntry) de.Key;
2185 case Operator.OpType.Equality:
2188 case Operator.OpType.Inequality:
2191 case Operator.OpType.GreaterThan:
2194 case Operator.OpType.LessThan:
2197 case Operator.OpType.GreaterThanOrEqual:
2200 case Operator.OpType.LessThanOrEqual:
2204 Report.Error (216, oe.op.Location,
2205 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2208 if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2209 MethodSignature equals_ms = new MethodSignature (
2210 "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2211 MethodSignature hash_ms = new MethodSignature (
2212 "GetHashCode", TypeManager.int32_type, new Type [0]);
2214 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2215 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2217 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2218 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2221 bool equals_ok = false;
2222 if ((equals_ml != null) && (equals_ml.Count == 1))
2223 equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2224 bool hash_ok = false;
2225 if ((hash_ml != null) && (hash_ml.Count == 1))
2226 hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2229 Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2230 "not override Object.Equals (object o)");
2232 Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2233 "not override Object.GetHashCode ()");
2239 public class Class : TypeContainer {
2241 // Modifiers allowed in a class declaration
2243 public const int AllowedModifiers =
2246 Modifiers.PROTECTED |
2247 Modifiers.INTERNAL |
2249 Modifiers.ABSTRACT |
2253 public Class (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2254 : base (ns, parent, name, attrs, l)
2258 if (parent.Parent == null)
2259 accmods = Modifiers.INTERNAL;
2261 accmods = Modifiers.PRIVATE;
2263 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2267 // FIXME: How do we deal with the user specifying a different
2270 public override TypeAttributes TypeAttr {
2272 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2277 public class Struct : TypeContainer {
2279 // Modifiers allowed in a struct declaration
2281 public const int AllowedModifiers =
2284 Modifiers.PROTECTED |
2285 Modifiers.INTERNAL |
2289 public Struct (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2290 : base (ns, parent, name, attrs, l)
2294 if (parent.Parent == null)
2295 accmods = Modifiers.INTERNAL;
2297 accmods = Modifiers.PRIVATE;
2299 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2301 this.ModFlags |= Modifiers.SEALED;
2305 // FIXME: Allow the user to specify a different set of attributes
2306 // in some cases (Sealed for example is mandatory for a class,
2307 // but what SequentialLayout can be changed
2309 public override TypeAttributes TypeAttr {
2311 return base.TypeAttr |
2312 TypeAttributes.SequentialLayout |
2313 TypeAttributes.Sealed |
2314 TypeAttributes.BeforeFieldInit;
2319 public abstract class MethodCore : MemberBase {
2320 public readonly Parameters Parameters;
2321 protected Block block;
2322 protected DeclSpace ds;
2325 // Parameters, cached for semantic analysis.
2327 protected InternalParameters parameter_info;
2328 protected Type [] parameter_types;
2331 // This is set from TypeContainer.DefineMembers if this method overrides something.
2333 public bool OverridesSomething;
2335 public MethodCore (DeclSpace ds, Expression type, int mod, int allowed_mod,
2336 string name, Attributes attrs, Parameters parameters, Location loc)
2337 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
2339 Parameters = parameters;
2344 // Returns the System.Type array for the parameters of this method
2346 public Type [] ParameterTypes {
2348 return parameter_types;
2352 public InternalParameters ParameterInfo
2355 return parameter_info;
2359 public Block Block {
2369 protected virtual bool DoDefineParameters ()
2371 // Check if arguments were correct
2372 parameter_types = Parameters.GetParameterInfo (ds);
2373 if ((parameter_types == null) || !CheckParameters (ds, parameter_types))
2376 parameter_info = new InternalParameters (ds, Parameters);
2378 Parameter array_param = Parameters.ArrayParameter;
2379 if ((array_param != null) &&
2380 (!array_param.ParameterType.IsArray ||
2381 (array_param.ParameterType.GetArrayRank () != 1))) {
2382 Report.Error (225, Location, "params parameter has to be a single dimensional array");
2389 public CallingConventions GetCallingConvention (bool is_class)
2391 CallingConventions cc = 0;
2393 cc = Parameters.GetCallingConvention ();
2396 if ((ModFlags & Modifiers.STATIC) == 0)
2397 cc |= CallingConventions.HasThis;
2399 // FIXME: How is `ExplicitThis' used in C#?
2405 // The method's attributes are passed in because we need to extract
2406 // the "return:" attribute from there to apply on the return type
2408 static public void LabelParameters (EmitContext ec,
2410 Parameters parameters,
2411 Attributes method_attrs,
2415 // Define each type attribute (in/out/ref) and
2416 // the argument names.
2418 Parameter [] p = parameters.FixedParameters;
2421 MethodBuilder mb = null;
2422 ConstructorBuilder cb = null;
2424 if (builder is MethodBuilder)
2425 mb = (MethodBuilder) builder;
2427 cb = (ConstructorBuilder) builder;
2430 for (i = 0; i < p.Length; i++) {
2431 ParameterBuilder pb;
2432 ParameterAttributes par_attr = p [i].Attributes;
2435 pb = cb.DefineParameter (
2436 i + 1, par_attr, p [i].Name);
2438 pb = mb.DefineParameter (
2439 i + 1, par_attr, p [i].Name);
2441 Attributes attr = p [i].OptAttributes;
2443 Attribute.ApplyAttributes (ec, pb, pb, attr);
2445 if (par_attr == ParameterAttributes.Out){
2446 if (attr.Contains (TypeManager.in_attribute_type))
2447 Report.Error (36, loc,
2448 "Can not use [In] attribute on out parameter");
2454 if (parameters.ArrayParameter != null){
2455 ParameterBuilder pb;
2456 Parameter array_param = parameters.ArrayParameter;
2459 pb = cb.DefineParameter (
2460 i + 1, array_param.Attributes,
2463 pb = mb.DefineParameter (
2464 i + 1, array_param.Attributes,
2467 CustomAttributeBuilder a = new CustomAttributeBuilder (
2468 TypeManager.cons_param_array_attribute, new object [0]);
2470 pb.SetCustomAttribute (a);
2474 // And now for the return type attribute decoration
2476 ParameterBuilder ret_pb;
2477 Attributes ret_attrs = null;
2479 if (mb == null || method_attrs == null)
2482 foreach (AttributeSection asec in method_attrs.AttributeSections) {
2484 if (asec.Target != "return")
2487 if (ret_attrs == null)
2488 ret_attrs = new Attributes (asec);
2490 ret_attrs.AddAttributeSection (asec);
2493 if (ret_attrs != null) {
2495 ret_pb = mb.DefineParameter (0, ParameterAttributes.None, "");
2496 Attribute.ApplyAttributes (ec, ret_pb, ret_pb, ret_attrs);
2498 } catch (ArgumentOutOfRangeException) {
2501 ".NET SDK 1.0 does not permit setting custom attributes" +
2502 " on the return type of a method");
2508 public class Method : MethodCore, IIteratorContainer {
2509 public MethodBuilder MethodBuilder;
2510 public MethodData MethodData;
2511 public readonly GenericMethod GenericMethod;
2514 /// Modifiers allowed in a class declaration
2516 const int AllowedModifiers =
2519 Modifiers.PROTECTED |
2520 Modifiers.INTERNAL |
2525 Modifiers.OVERRIDE |
2526 Modifiers.ABSTRACT |
2528 Modifiers.METHOD_YIELDS |
2532 // return_type can be "null" for VOID values.
2534 public Method (DeclSpace ds, Expression return_type, int mod, string name,
2535 Parameters parameters, Attributes attrs, Location l)
2536 : base (ds, return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2540 public Method (GenericMethod generic, Expression return_type, int mod, string name,
2541 Parameters parameters, Attributes attrs, Location l)
2542 : base (generic, return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2544 GenericMethod = generic;
2548 // Returns the `System.Type' for the ReturnType of this
2549 // function. Provides a nice cache. (used between semantic analysis
2550 // and actual code generation
2552 public Type GetReturnType ()
2557 // Whether this is an operator method.
2558 public bool IsOperator;
2560 void DuplicateEntryPoint (MethodInfo b, Location location)
2564 "Program `" + CodeGen.FileName +
2565 "' has more than one entry point defined: `" +
2566 TypeManager.CSharpSignature(b) + "'");
2569 void Report28 (MethodInfo b)
2573 "`" + TypeManager.CSharpSignature(b) +
2574 "' has the wrong signature to be an entry point");
2577 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2579 if (b.ReturnType != TypeManager.void_type &&
2580 b.ReturnType != TypeManager.int32_type)
2583 if (pinfo.Count == 0)
2586 if (pinfo.Count > 1)
2589 Type t = pinfo.ParameterType(0);
2591 (t.GetArrayRank() == 1) &&
2592 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
2593 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2600 // Checks our base implementation if any
2602 protected override bool CheckBase (TypeContainer container)
2604 base.CheckBase (container);
2606 // Check whether arguments were correct.
2607 if (!DoDefineParameters ())
2610 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2612 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2616 // Check in our class for dups
2618 ArrayList ar = container.Methods;
2620 int arLen = ar.Count;
2622 for (int i = 0; i < arLen; i++) {
2623 Method m = (Method) ar [i];
2624 if (m == this || m.Name != this.Name)
2627 if (m.MethodBuilder != null && m.ParameterTypes.Length == ParameterTypes.Length) {
2629 for (int j = ParameterTypes.Length - 1; j >= 0; j --)
2630 if (m.ParameterTypes [j] != ParameterTypes [j])
2633 Report.Error (111, Location, "Class `" + container.Name + "' " +
2634 "already defines a member called `" + Name + "' " +
2635 "with the same parameter types");
2647 // Verify if the parent has a type with the same name, and then
2648 // check whether we have to create a new slot for it or not.
2650 Type ptype = container.TypeBuilder.BaseType;
2652 // ptype is only null for System.Object while compiling corlib.
2654 MemberList mi, mi_static, mi_instance;
2656 mi_instance = TypeContainer.FindMembers (
2657 ptype, MemberTypes.Method,
2658 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2659 MethodSignature.inheritable_method_signature_filter,
2662 if (mi_instance.Count > 0){
2665 mi_static = TypeContainer.FindMembers (
2666 ptype, MemberTypes.Method,
2667 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2668 MethodSignature.inheritable_method_signature_filter, ms);
2670 if (mi_static.Count > 0)
2676 if (mi != null && mi.Count > 0){
2677 parent_method = (MethodInfo) mi [0];
2678 string name = parent_method.DeclaringType.Name + "." +
2681 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
2684 if ((ModFlags & Modifiers.NEW) == 0) {
2685 Type parent_ret = TypeManager.TypeToCoreType (
2686 parent_method.ReturnType);
2688 if (parent_ret != MemberType) {
2690 508, Location, container.MakeName (Name) + ": cannot " +
2691 "change return type when overriding " +
2692 "inherited member " + name);
2697 if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
2698 WarningNotHiding (container);
2700 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2701 Report.Error (115, Location,
2702 container.MakeName (Name) +
2703 " no suitable methods found to override");
2706 } else if ((ModFlags & Modifiers.NEW) != 0)
2707 WarningNotHiding (container);
2715 public override bool Define (TypeContainer container)
2718 MethodBuilder mb = null;
2719 if (GenericMethod != null) {
2720 mb = container.TypeBuilder.DefineGenericMethod (Name, flags);
2721 if (!GenericMethod.Define (mb))
2723 decl = GenericMethod;
2727 if (!DoDefine (decl, container))
2730 if (!CheckBase (container))
2733 CallingConventions cc = GetCallingConvention (container is Class);
2735 MethodData = new MethodData (ds, this, null, MemberType,
2736 ParameterTypes, ParameterInfo, cc,
2737 OptAttributes, ModFlags, flags, true,
2740 if (!MethodData.Define (container))
2744 // Setup iterator if we are one
2746 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
2747 IteratorHandler ih = new IteratorHandler (
2748 Name, container, MemberType,
2749 ParameterTypes, ParameterInfo,
2750 ModFlags, Location);
2752 Block new_block = ih.Setup (block);
2753 if (new_block == null)
2758 MethodBuilder = MethodData.MethodBuilder;
2761 // This is used to track the Entry Point,
2763 if (Name == "Main" &&
2764 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
2765 (RootContext.MainClass == null ||
2766 RootContext.MainClass == container.TypeBuilder.FullName)){
2767 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2768 if (RootContext.EntryPoint == null) {
2769 if (container.IsGeneric){
2770 Report.Error (-201, Location,
2771 "Entry point can not be defined in a generic class");
2774 RootContext.EntryPoint = MethodBuilder;
2775 RootContext.EntryPointLocation = Location;
2777 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2778 DuplicateEntryPoint (MethodBuilder, Location);
2781 Report28(MethodBuilder);
2790 public void Emit (TypeContainer container)
2792 MethodData.Emit (container, Block, this);
2797 void IIteratorContainer.SetYields ()
2799 ModFlags |= Modifiers.METHOD_YIELDS;
2803 public abstract class ConstructorInitializer {
2804 ArrayList argument_list;
2805 ConstructorInfo parent_constructor;
2806 Parameters parameters;
2809 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2812 this.argument_list = argument_list;
2813 this.parameters = parameters;
2817 public ArrayList Arguments {
2819 return argument_list;
2823 public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
2825 Expression parent_constructor_group;
2828 ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
2830 if (argument_list != null){
2831 foreach (Argument a in argument_list){
2832 if (!a.Resolve (ec, loc))
2836 ec.CurrentBlock = null;
2838 if (this is ConstructorBaseInitializer) {
2839 if (ec.ContainerType.BaseType == null)
2842 t = ec.ContainerType.BaseType;
2843 if (ec.ContainerType.IsValueType) {
2844 Report.Error (522, loc,
2845 "structs cannot call base class constructors");
2849 t = ec.ContainerType;
2851 parent_constructor_group = Expression.MemberLookup (
2852 ec, t, null, t, ".ctor", 0,
2853 MemberTypes.Constructor,
2854 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2857 if (parent_constructor_group == null){
2858 Report.Error (1501, loc,
2859 "Can not find a constructor for this argument list");
2863 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2864 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2866 if (parent_constructor == null){
2867 Report.Error (1501, loc,
2868 "Can not find a constructor for this argument list");
2872 if (parent_constructor == caller_builder){
2873 Report.Error (515, String.Format ("Constructor `{0}' can not call itself", TypeManager.CSharpSignature (caller_builder)));
2880 public void Emit (EmitContext ec)
2882 if (parent_constructor != null){
2883 ec.Mark (loc, false);
2885 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2887 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
2892 public class ConstructorBaseInitializer : ConstructorInitializer {
2893 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2894 base (argument_list, pars, l)
2899 public class ConstructorThisInitializer : ConstructorInitializer {
2900 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2901 base (argument_list, pars, l)
2906 public class Constructor : MethodCore {
2907 public ConstructorBuilder ConstructorBuilder;
2908 public ConstructorInitializer Initializer;
2911 // Modifiers allowed for a constructor.
2913 public const int AllowedModifiers =
2915 Modifiers.PROTECTED |
2916 Modifiers.INTERNAL |
2923 // The spec claims that static is not permitted, but
2924 // my very own code has static constructors.
2926 public Constructor (DeclSpace ds, string name, int mod, Parameters args,
2927 ConstructorInitializer init, Location l)
2928 : base (ds, null, mod, AllowedModifiers, name, null, args, l)
2934 // Returns true if this is a default constructor
2936 public bool IsDefault ()
2938 if ((ModFlags & Modifiers.STATIC) != 0)
2939 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2940 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2943 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2944 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2945 (Initializer is ConstructorBaseInitializer) &&
2946 (Initializer.Arguments == null);
2949 protected override bool CheckBase (TypeContainer container)
2951 base.CheckBase (container);
2953 // Check whether arguments were correct.
2954 if (!DoDefineParameters ())
2957 if ((ModFlags & Modifiers.STATIC) != 0)
2960 if (container is Struct && ParameterTypes.Length == 0) {
2961 Report.Error (568, Location,
2962 "Structs can not contain explicit parameterless " +
2968 // Check in our class for dups
2970 ArrayList ar = container.InstanceConstructors;
2972 // I don't think this is possible (there should be
2973 // at least one, us). However, just in case:
2977 int arLen = ar.Count;
2978 for (int i = 0; i < arLen; i++) {
2979 Constructor m = (Constructor) ar [i];
2982 // Check for a ctor with identical args
2984 if (m == this || m.ConstructorBuilder == null || m.ParameterTypes.Length != ParameterTypes.Length)
2987 for (int j = ParameterTypes.Length - 1; j >= 0; j --)
2988 if (m.ParameterTypes [j] != ParameterTypes [j])
2993 "Class `{0}' already contains a definition with the " +
2994 "same return value and parameter types for constructor `{1}'",
2995 container.Name, Name);
3006 // Creates the ConstructorBuilder
3008 public override bool Define (TypeContainer container)
3010 MethodAttributes ca = (MethodAttributes.RTSpecialName |
3011 MethodAttributes.SpecialName);
3013 if ((ModFlags & Modifiers.STATIC) != 0){
3014 ca |= MethodAttributes.Static | MethodAttributes.Private;
3016 ca |= MethodAttributes.HideBySig;
3018 if ((ModFlags & Modifiers.PUBLIC) != 0)
3019 ca |= MethodAttributes.Public;
3020 else if ((ModFlags & Modifiers.PROTECTED) != 0){
3021 if ((ModFlags & Modifiers.INTERNAL) != 0)
3022 ca |= MethodAttributes.FamORAssem;
3024 ca |= MethodAttributes.Family;
3025 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
3026 ca |= MethodAttributes.Assembly;
3027 else if (IsDefault ())
3028 ca |= MethodAttributes.Public;
3030 ca |= MethodAttributes.Private;
3033 // Check if arguments were correct.
3034 if (!CheckBase (container))
3037 ConstructorBuilder = container.TypeBuilder.DefineConstructor (
3038 ca, GetCallingConvention (container is Class), ParameterTypes);
3040 if ((ModFlags & Modifiers.UNSAFE) != 0)
3041 ConstructorBuilder.InitLocals = false;
3044 // HACK because System.Reflection.Emit is lame
3046 TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
3054 public void Emit (TypeContainer container)
3056 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
3057 EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
3060 // extern methods have no bodies
3062 if ((ModFlags & Modifiers.EXTERN) != 0) {
3063 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
3065 179, Location, "External constructor `" +
3066 TypeManager.CSharpSignature (ConstructorBuilder) +
3067 "' can not have a body");
3070 } else if (block == null) {
3072 501, Location, "Constructor `" +
3073 TypeManager.CSharpSignature (ConstructorBuilder) +
3074 "' must declare a body since it is not marked extern");
3078 if ((ModFlags & Modifiers.STATIC) == 0){
3079 if (container is Class && Initializer == null)
3080 Initializer = new ConstructorBaseInitializer (
3081 null, Parameters.EmptyReadOnlyParameters, Location);
3085 // Spec mandates that Initializers will not have
3089 if (Initializer != null && !Initializer.Resolve (ConstructorBuilder, ec))
3091 ec.IsStatic = false;
3094 MethodCore.LabelParameters (ec, ConstructorBuilder,
3095 Parameters, OptAttributes, Location);
3097 SymbolWriter sw = CodeGen.SymbolWriter;
3098 bool generate_debugging = false;
3100 if ((sw != null) && (block != null) &&
3101 !Location.IsNull (Location) &&
3102 !Location.IsNull (block.EndLocation) &&
3103 (Location.SymbolDocument != null)) {
3104 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
3106 generate_debugging = true;
3110 // Classes can have base initializers and instance field initializers.
3112 if (container is Class){
3113 if ((ModFlags & Modifiers.STATIC) == 0){
3116 // If we use a "this (...)" constructor initializer, then
3117 // do not emit field initializers, they are initialized in the other constructor
3119 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
3120 container.EmitFieldInitializers (ec);
3123 if (Initializer != null)
3124 Initializer.Emit (ec);
3126 if ((ModFlags & Modifiers.STATIC) != 0)
3127 container.EmitFieldInitializers (ec);
3129 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes);
3131 // If this is a non-static `struct' constructor and doesn't have any
3132 // initializer, it must initialize all of the struct's fields.
3133 if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
3134 Block.AddThisVariable (container, Location);
3136 ec.EmitTopBlock (block, ParameterInfo, Location);
3138 if (generate_debugging)
3146 // Encapsulates most of the Method's state
3148 public class MethodData {
3150 // The return type of this method
3152 public readonly Type ReturnType;
3153 public readonly Type[] ParameterTypes;
3154 public readonly GenericMethod GenericMethod;
3155 public readonly InternalParameters ParameterInfo;
3156 public readonly CallingConventions CallingConventions;
3157 public readonly Attributes OptAttributes;
3158 public readonly Location Location;
3161 // Are we implementing an interface ?
3163 public bool IsImplementing = false;
3168 protected DeclSpace ds;
3169 protected MemberBase member;
3170 protected int modifiers;
3171 protected MethodAttributes flags;
3172 protected bool is_method;
3173 protected string accessor_name;
3176 // It can either hold a string with the condition, or an arraylist of conditions.
3177 object conditionals;
3180 MethodBuilder builder = null;
3181 public MethodBuilder MethodBuilder {
3187 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
3188 Type [] parameter_types, InternalParameters parameters,
3189 CallingConventions cc, Attributes opt_attrs,
3190 int modifiers, MethodAttributes flags, bool is_method)
3193 this.member = member;
3194 this.accessor_name = name;
3195 this.ReturnType = return_type;
3196 this.ParameterTypes = parameter_types;
3197 this.ParameterInfo = parameters;
3198 this.CallingConventions = cc;
3199 this.OptAttributes = opt_attrs;
3200 this.modifiers = modifiers;
3202 this.is_method = is_method;
3203 this.Location = member.Location;
3204 this.conditionals = null;
3207 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
3208 Type [] parameter_types, InternalParameters parameters,
3209 CallingConventions cc, Attributes opt_attrs,
3210 int modifiers, MethodAttributes flags, bool is_method,
3211 MethodBuilder builder, GenericMethod generic)
3212 : this (ds, member, name, return_type, parameter_types, parameters,
3213 cc, opt_attrs, modifiers, flags, is_method)
3215 this.builder = builder;
3216 this.GenericMethod = generic;
3222 Attribute dllimport_attribute = null;
3223 string obsolete = null;
3224 bool obsolete_error = false;
3226 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
3228 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
3231 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
3232 if (asec.Attributes == null)
3235 foreach (Attribute a in asec.Attributes) {
3236 if (a.Name == "Conditional") {
3237 if (!ApplyConditionalAttribute (a))
3239 } else if (a.Name == "Obsolete") {
3240 if (!ApplyObsoleteAttribute (a))
3242 } else if (a.Name.IndexOf ("DllImport") != -1) {
3244 a.Type = TypeManager.dllimport_type;
3245 Attribute.Error_AttributeNotValidForElement (a, Location);
3248 if (!ApplyDllImportAttribute (a))
3258 // Applies the `DllImport' attribute to the method.
3260 protected virtual bool ApplyDllImportAttribute (Attribute a)
3262 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3263 if ((modifiers & extern_static) != extern_static) {
3264 Report.Error (601, Location,
3265 "The DllImport attribute must be specified on a method " +
3266 "marked `static' and `extern'.");
3270 flags |= MethodAttributes.PinvokeImpl;
3271 dllimport_attribute = a;
3276 // Applies the `Obsolete' attribute to the method.
3278 protected virtual bool ApplyObsoleteAttribute (Attribute a)
3280 if (obsolete != null) {
3281 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
3285 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
3286 return obsolete != null;
3290 // Applies the `Conditional' attribute to the method.
3292 protected virtual bool ApplyConditionalAttribute (Attribute a)
3294 // The Conditional attribute is only valid on methods.
3296 Attribute.Error_AttributeNotValidForElement (a, Location);
3300 string condition = a.Conditional_GetConditionName ();
3302 if (condition == null)
3305 if (ReturnType != TypeManager.void_type) {
3306 Report.Error (578, Location,
3307 "Conditional not valid on `" + member.Name + "' " +
3308 "because its return type is not void");
3312 if ((modifiers & Modifiers.OVERRIDE) != 0) {
3313 Report.Error (243, Location,
3314 "Conditional not valid on `" + member.Name + "' " +
3315 "because it is an override method");
3319 if (member.IsExplicitImpl) {
3320 Report.Error (577, Location,
3321 "Conditional not valid on `" + member.Name + "' " +
3322 "because it is an explicit interface implementation");
3326 if (IsImplementing) {
3327 Report.Error (623, Location,
3328 "Conditional not valid on `" + member.Name + "' " +
3329 "because it is an interface method");
3334 // The likelyhood that the conditional will be more than 1 is very slim
3336 if (conditionals == null)
3337 conditionals = condition;
3338 else if (conditionals is string){
3339 string s = (string) conditionals;
3340 conditionals = new ArrayList ();
3341 ((ArrayList)conditionals).Add (s);
3343 ((ArrayList)conditionals).Add (condition);
3349 // Checks whether this method should be ignored due to its Conditional attributes.
3351 bool ShouldIgnore (Location loc)
3353 // When we're overriding a virtual method, we implicitly inherit the
3354 // Conditional attributes from our parent.
3355 if (member.ParentMethod != null) {
3356 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3357 member.ParentMethod, loc);
3359 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3363 if (conditionals != null){
3364 if (conditionals is string){
3365 if (RootContext.AllDefines [conditionals] == null)
3368 foreach (string condition in (ArrayList) conditionals)
3369 if (RootContext.AllDefines [condition] == null)
3377 // Returns the TypeManager.MethodFlags for this method.
3378 // This emits an error 619 / warning 618 if the method is obsolete.
3379 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3381 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3383 TypeManager.MethodFlags flags = 0;
3385 if (obsolete != null) {
3386 if (obsolete_error) {
3387 Report.Error (619, loc, "Method `" + member.Name +
3388 "' is obsolete: `" + obsolete + "'");
3389 return TypeManager.MethodFlags.IsObsoleteError;
3391 Report.Warning (618, loc, "Method `" + member.Name +
3392 "' is obsolete: `" + obsolete + "'");
3394 flags |= TypeManager.MethodFlags.IsObsolete;
3397 if (ShouldIgnore (loc))
3398 flags |= TypeManager.MethodFlags.ShouldIgnore;
3403 public virtual bool Define (TypeContainer container)
3405 MethodInfo implementing = null;
3406 string method_name, name, prefix;
3408 if (OptAttributes != null)
3409 if (!ApplyAttributes (OptAttributes, is_method))
3412 if (member.IsExplicitImpl)
3413 prefix = member.InterfaceType.FullName + ".";
3417 if (accessor_name != null)
3418 name = accessor_name + "_" + member.ShortName;
3420 name = member.ShortName;
3421 method_name = prefix + name;
3423 if (container.Pending != null){
3424 if (member is Indexer)
3425 implementing = container.Pending.IsInterfaceIndexer (
3426 member.InterfaceType, ReturnType, ParameterTypes);
3428 implementing = container.Pending.IsInterfaceMethod (
3429 member.InterfaceType, name, ReturnType, ParameterTypes);
3431 if (member.InterfaceType != null && implementing == null){
3432 Report.Error (539, Location, "'{0}' in explicit interface declaration is not an interface", method_name);
3438 // For implicit implementations, make sure we are public, for
3439 // explicit implementations, make sure we are private.
3441 if (implementing != null){
3443 // Setting null inside this block will trigger a more
3444 // verbose error reporting for missing interface implementations
3446 // The "candidate" function has been flagged already
3447 // but it wont get cleared
3449 if (member.IsExplicitImpl){
3450 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3451 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3452 implementing = null;
3454 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
3455 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
3457 // If this is an interface method implementation,
3458 // check for public accessibility
3460 implementing = null;
3461 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
3462 // We may never be private.
3463 implementing = null;
3464 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
3466 // We may be protected if we're overriding something.
3468 implementing = null;
3473 // Static is not allowed
3475 if ((modifiers & Modifiers.STATIC) != 0){
3476 implementing = null;
3477 Modifiers.Error_InvalidModifier (Location, "static");
3482 // If implementing is still valid, set flags
3484 if (implementing != null){
3486 // When implementing interface methods, set NewSlot
3487 // unless, we are overwriting a method.
3489 if (implementing.DeclaringType.IsInterface){
3490 if ((modifiers & Modifiers.OVERRIDE) == 0)
3491 flags |= MethodAttributes.NewSlot;
3494 MethodAttributes.Virtual |
3495 MethodAttributes.HideBySig;
3497 // Set Final unless we're virtual, abstract or already overriding a method.
3498 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
3499 flags |= MethodAttributes.Final;
3501 // Get the method name from the explicit interface.
3502 if (member.InterfaceType != null) {
3503 name = implementing.Name;
3504 method_name = prefix + name;
3507 IsImplementing = true;
3510 ec = new EmitContext (
3511 container, ds, Location, null, ReturnType, modifiers, false);
3514 // Create the MethodBuilder for the method
3516 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3517 if ((modifiers & Modifiers.STATIC) == 0) {
3518 Report.Error (601, Location,
3519 "The DllImport attribute must be specified on " +
3520 "a method marked 'static' and 'extern'.");
3523 builder = dllimport_attribute.DefinePInvokeMethod (
3524 ec, container.TypeBuilder, method_name, flags,
3525 ReturnType, ParameterTypes);
3526 } else if (builder == null)
3527 builder = container.TypeBuilder.DefineMethod (
3528 method_name, flags, CallingConventions,
3529 ReturnType, ParameterTypes);
3531 builder.SetGenericMethodSignature (
3532 flags, CallingConventions,
3533 ReturnType, ParameterTypes);
3535 if (builder == null)
3538 if (GenericMethod != null) {
3539 if (!GenericMethod.DefineType (ec, builder))
3543 if ((modifiers & Modifiers.UNSAFE) != 0)
3544 builder.InitLocals = false;
3546 if (IsImplementing){
3548 // clear the pending implemntation flag
3550 if (member is Indexer) {
3551 container.Pending.ImplementIndexer (
3552 member.InterfaceType, builder, ReturnType,
3553 ParameterTypes, true);
3555 container.Pending.ImplementMethod (
3556 member.InterfaceType, name, ReturnType,
3557 ParameterTypes, member.IsExplicitImpl);
3559 if (member.IsExplicitImpl)
3560 container.TypeBuilder.DefineMethodOverride (
3561 builder, implementing);
3565 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3566 Report.Error (111, Location,
3567 "Class `" + container.Name +
3568 "' already contains a definition with the " +
3569 "same return value and parameter types as the " +
3570 "'get' method of property `" + member.Name + "'");
3574 TypeManager.AddMethod (builder, this);
3582 public virtual void Emit (TypeContainer container, Block block, object kind)
3587 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3588 ig = builder.GetILGenerator ();
3592 ec = new EmitContext (container, ds, Location, ig, ReturnType, modifiers, false);
3594 if (OptAttributes != null)
3595 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes);
3597 if (member is MethodCore)
3598 MethodCore.LabelParameters (ec, MethodBuilder,
3599 ((MethodCore) member).Parameters,
3603 SymbolWriter sw = CodeGen.SymbolWriter;
3606 // abstract or extern methods have no bodies
3608 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3609 if (block == null) {
3610 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0) &&
3611 !Location.IsNull (Location) &&
3612 (Location.SymbolDocument != null)) {
3613 sw.OpenMethod (container, MethodBuilder, Location, Location);
3621 // abstract or extern methods have no bodies.
3623 if ((modifiers & Modifiers.ABSTRACT) != 0)
3625 500, Location, "Abstract method `" +
3626 TypeManager.CSharpSignature (builder) +
3627 "' can not have a body");
3629 if ((modifiers & Modifiers.EXTERN) != 0)
3631 179, Location, "External method `" +
3632 TypeManager.CSharpSignature (builder) +
3633 "' can not have a body");
3639 // Methods must have a body unless they're extern or abstract
3641 if (block == null) {
3643 501, Location, "Method `" +
3644 TypeManager.CSharpSignature (builder) +
3645 "' must declare a body since it is not marked " +
3646 "abstract or extern");
3651 // Handle destructors specially
3653 // FIXME: This code generates buggy code
3655 if ((sw != null) && !Location.IsNull (Location) &&
3656 !Location.IsNull (block.EndLocation) &&
3657 (Location.SymbolDocument != null)) {
3658 sw.OpenMethod (container, MethodBuilder, Location, block.EndLocation);
3660 if (member is Destructor)
3661 EmitDestructor (ec, block);
3663 ec.EmitTopBlock (block, ParameterInfo, Location);
3667 if (member is Destructor)
3668 EmitDestructor (ec, block);
3670 ec.EmitTopBlock (block, ParameterInfo, Location);
3674 void EmitDestructor (EmitContext ec, Block block)
3676 ILGenerator ig = ec.ig;
3678 Label finish = ig.DefineLabel ();
3680 block.SetDestructor ();
3682 ig.BeginExceptionBlock ();
3683 ec.ReturnLabel = finish;
3684 ec.HasReturnLabel = true;
3685 ec.EmitTopBlock (block, null, Location);
3687 // ig.MarkLabel (finish);
3688 ig.BeginFinallyBlock ();
3690 if (ec.ContainerType.BaseType != null) {
3691 Expression member_lookup = Expression.MemberLookup (
3692 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3693 "Finalize", 0, MemberTypes.Method, Expression.AllBindingFlags, Location);
3695 if (member_lookup != null){
3696 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3698 ig.Emit (OpCodes.Ldarg_0);
3699 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3703 ig.EndExceptionBlock ();
3704 //ig.MarkLabel (ec.ReturnLabel);
3705 ig.Emit (OpCodes.Ret);
3709 public class Destructor : Method {
3711 public Destructor (DeclSpace ds, Expression return_type, int mod, string name,
3712 Parameters parameters, Attributes attrs, Location l)
3713 : base (ds, return_type, mod, name, parameters, attrs, l)
3718 abstract public class MemberBase : MemberCore {
3719 public Expression Type;
3721 protected MethodAttributes flags;
3723 protected readonly int explicit_mod_flags;
3726 // The "short" name of this property / indexer / event. This is the
3727 // name without the explicit interface.
3729 public string ShortName;
3732 // The type of this property / indexer / event
3734 public Type MemberType;
3737 // If true, this is an explicit interface implementation
3739 public bool IsExplicitImpl = false;
3742 // The name of the interface we are explicitly implementing
3744 public string ExplicitInterfaceName = null;
3747 // If true, the interface type we are explicitly implementing
3749 public Type InterfaceType = null;
3752 // The method we're overriding if this is an override method.
3754 protected MethodInfo parent_method = null;
3755 public MethodInfo ParentMethod {
3757 return parent_method;
3762 // The constructor is only exposed to our children
3764 protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod, string name,
3765 Attributes attrs, Location loc)
3766 : base (name, attrs, loc)
3768 explicit_mod_flags = mod;
3770 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
3773 protected virtual bool CheckBase (TypeContainer container)
3775 if ((container is Struct) || (RootContext.WarningLevel > 3)){
3776 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
3777 if (container is Struct){
3778 Report.Error (666, Location, "Protected member in struct declaration");
3781 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
3787 protected void WarningNotHiding (TypeContainer parent)
3791 "The member " + parent.MakeName (Name) + " does not hide an " +
3792 "inherited member. The keyword new is not required");
3796 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
3800 // FIXME: report the old/new permissions?
3803 507, Location, parent.MakeName (Name) +
3804 ": can't change the access modifiers when overriding inherited " +
3805 "member `" + name + "'");
3809 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3810 // that have been defined.
3812 // `name' is the user visible name for reporting errors (this is used to
3813 // provide the right name regarding method names and properties)
3815 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
3816 MethodInfo mb, string name)
3820 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3821 if (!(mb.IsAbstract || mb.IsVirtual)){
3823 506, Location, parent.MakeName (Name) +
3824 ": cannot override inherited member `" +
3825 name + "' because it is not " +
3826 "virtual, abstract or override");
3830 // Now we check that the overriden method is not final
3833 // This happens when implementing interface methods.
3834 if (mb.IsHideBySig && mb.IsVirtual) {
3836 506, Location, parent.MakeName (Name) +
3837 ": cannot override inherited member `" +
3838 name + "' because it is not " +
3839 "virtual, abstract or override");
3841 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
3842 "override inherited member `" + name +
3843 "' because it is sealed.");
3847 // Check that the permissions are not being changed
3849 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
3850 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
3853 // special case for "protected internal"
3856 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3858 // when overriding protected internal, the method can be declared
3859 // protected internal only within the same assembly
3862 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3863 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
3865 // assemblies differ - report an error
3868 Error_CannotChangeAccessModifiers (parent, mb, name);
3870 } else if (thisp != parentp) {
3872 // same assembly, but other attributes differ - report an error
3875 Error_CannotChangeAccessModifiers (parent, mb, name);
3878 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3880 // if it's not "protected internal", it must be "protected"
3883 Error_CannotChangeAccessModifiers (parent, mb, name);
3885 } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
3887 // protected within the same assembly - an error
3889 Error_CannotChangeAccessModifiers (parent, mb, name);
3891 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3892 (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3894 // protected ok, but other attributes differ - report an error
3896 Error_CannotChangeAccessModifiers (parent, mb, name);
3900 if (thisp != parentp){
3901 Error_CannotChangeAccessModifiers (parent, mb, name);
3907 if (mb.IsVirtual || mb.IsAbstract){
3908 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
3909 if (Name != "Finalize"){
3911 114, 2, Location, parent.MakeName (Name) +
3912 " hides inherited member `" + name +
3913 "'. To make the current member override that " +
3914 "implementation, add the override keyword, " +
3915 "otherwise use the new keyword");
3916 ModFlags |= Modifiers.NEW;
3920 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
3921 if (Name != "Finalize"){
3923 108, 1, Location, "The keyword new is required on " +
3924 parent.MakeName (Name) + " because it hides " +
3925 "inherited member `" + name + "'");
3926 ModFlags |= Modifiers.NEW;
3934 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
3938 foreach (Type partype in parameters){
3939 if (partype.IsPointer){
3942 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
3946 if (ds.AsAccessible (partype, ModFlags))
3949 if (this is Indexer)
3950 Report.Error (55, Location,
3951 "Inconsistent accessibility: parameter type `" +
3952 TypeManager.CSharpName (partype) + "' is less " +
3953 "accessible than indexer `" + Name + "'");
3954 else if ((this is Method) && ((Method) this).IsOperator)
3955 Report.Error (57, Location,
3956 "Inconsistent accessibility: parameter type `" +
3957 TypeManager.CSharpName (partype) + "' is less " +
3958 "accessible than operator `" + Name + "'");
3960 Report.Error (51, Location,
3961 "Inconsistent accessibility: parameter type `" +
3962 TypeManager.CSharpName (partype) + "' is less " +
3963 "accessible than method `" + Name + "'");
3970 protected virtual bool DoDefine (DeclSpace decl, TypeContainer container)
3975 if (!container.MethodModifiersValid (ModFlags, Name, Location))
3978 flags = Modifiers.MethodAttr (ModFlags);
3980 // Lookup Type, verify validity
3981 MemberType = decl.ResolveType (Type, false, Location);
3982 if (MemberType == null)
3985 if ((container.ModFlags & Modifiers.SEALED) != 0){
3986 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
3987 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
3992 // verify accessibility
3993 if (!container.AsAccessible (MemberType, ModFlags)) {
3994 if (this is Property)
3995 Report.Error (53, Location,
3996 "Inconsistent accessibility: property type `" +
3997 TypeManager.CSharpName (MemberType) + "' is less " +
3998 "accessible than property `" + Name + "'");
3999 else if (this is Indexer)
4000 Report.Error (54, Location,
4001 "Inconsistent accessibility: indexer return type `" +
4002 TypeManager.CSharpName (MemberType) + "' is less " +
4003 "accessible than indexer `" + Name + "'");
4004 else if (this is Method) {
4005 if (((Method) this).IsOperator)
4006 Report.Error (56, Location,
4007 "Inconsistent accessibility: return type `" +
4008 TypeManager.CSharpName (MemberType) + "' is less " +
4009 "accessible than operator `" + Name + "'");
4011 Report.Error (50, Location,
4012 "Inconsistent accessibility: return type `" +
4013 TypeManager.CSharpName (MemberType) + "' is less " +
4014 "accessible than method `" + Name + "'");
4016 Report.Error (52, Location,
4017 "Inconsistent accessibility: field type `" +
4018 TypeManager.CSharpName (MemberType) + "' is less " +
4019 "accessible than field `" + Name + "'");
4023 if (MemberType.IsPointer && !UnsafeOK (container))
4027 // Check for explicit interface implementation
4029 if ((ExplicitInterfaceName == null) && (Name.IndexOf ('.') != -1)){
4030 int pos = Name.LastIndexOf ('.');
4032 ExplicitInterfaceName = Name.Substring (0, pos);
4033 ShortName = Name.Substring (pos + 1);
4037 if (ExplicitInterfaceName != null) {
4038 InterfaceType = RootContext.LookupType (
4039 container, ExplicitInterfaceName, false, Location);
4040 if (InterfaceType == null)
4043 if (InterfaceType.IsClass) {
4044 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
4048 // Compute the full name that we need to export.
4049 Name = InterfaceType.FullName + "." + ShortName;
4051 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
4054 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
4056 IsExplicitImpl = true;
4058 IsExplicitImpl = false;
4065 // Fields and Events both generate FieldBuilders, we use this to share
4066 // their common bits. This is also used to flag usage of the field
4068 abstract public class FieldBase : MemberBase {
4069 public FieldBuilder FieldBuilder;
4070 public Status status;
4073 public enum Status : byte { ASSIGNED = 1, USED = 2 }
4076 // The constructor is only exposed to our children
4078 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
4079 object init, Attributes attrs, Location loc)
4080 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
4086 // Whether this field has an initializer.
4088 public bool HasInitializer {
4090 return init != null;
4094 protected readonly Object init;
4096 Expression init_expr;
4097 bool init_expr_initialized = false;
4100 // Resolves and returns the field initializer.
4102 public Expression GetInitializerExpression (EmitContext ec)
4104 if (init_expr_initialized)
4108 if (init is Expression)
4109 e = (Expression) init;
4111 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
4113 ec.IsFieldInitializer = true;
4114 e = e.DoResolve (ec);
4115 ec.IsFieldInitializer = false;
4118 init_expr_initialized = true;
4123 public void SetAssigned ()
4125 status |= Status.ASSIGNED;
4130 // The Field class is used to represents class/struct fields during parsing.
4132 public class Field : FieldBase {
4134 // Modifiers allowed in a class declaration
4136 const int AllowedModifiers =
4139 Modifiers.PROTECTED |
4140 Modifiers.INTERNAL |
4143 Modifiers.VOLATILE |
4147 public Field (Expression type, int mod, string name, Object expr_or_array_init,
4148 Attributes attrs, Location loc)
4149 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
4153 public override bool Define (TypeContainer container)
4155 Type t = container.ResolveType (Type, false, Location);
4160 CheckBase (container);
4162 if (!container.AsAccessible (t, ModFlags)) {
4163 Report.Error (52, Location,
4164 "Inconsistent accessibility: field type `" +
4165 TypeManager.CSharpName (t) + "' is less " +
4166 "accessible than field `" + Name + "'");
4170 if (t.IsPointer && !UnsafeOK (container))
4173 if (RootContext.WarningLevel > 1){
4174 Type ptype = container.TypeBuilder.BaseType;
4176 // ptype is only null for System.Object while compiling corlib.
4178 TypeContainer.FindMembers (
4179 ptype, MemberTypes.Method,
4180 BindingFlags.Public |
4181 BindingFlags.Static | BindingFlags.Instance,
4182 System.Type.FilterName, Name);
4186 if ((ModFlags & Modifiers.VOLATILE) != 0){
4190 if (TypeManager.IsEnumType (vt))
4191 vt = TypeManager.EnumToUnderlying (t);
4193 if (!((vt == TypeManager.bool_type) ||
4194 (vt == TypeManager.sbyte_type) ||
4195 (vt == TypeManager.byte_type) ||
4196 (vt == TypeManager.short_type) ||
4197 (vt == TypeManager.ushort_type) ||
4198 (vt == TypeManager.int32_type) ||
4199 (vt == TypeManager.uint32_type) ||
4200 (vt == TypeManager.char_type) ||
4201 (vt == TypeManager.float_type))){
4203 677, Location, container.MakeName (Name) +
4204 " A volatile field can not be of type `" +
4205 TypeManager.CSharpName (vt) + "'");
4210 if ((ModFlags & Modifiers.READONLY) != 0){
4213 "A field can not be both volatile and readonly");
4218 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
4220 if (container is Struct &&
4221 ((fa & FieldAttributes.Static) == 0) &&
4222 t == container.TypeBuilder &&
4223 !TypeManager.IsBuiltinType (t)){
4224 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name +
4225 "' causes a cycle in the structure layout");
4230 FieldBuilder = container.TypeBuilder.DefineField (
4231 Name, t, Modifiers.FieldAttr (ModFlags));
4233 TypeManager.RegisterFieldBase (FieldBuilder, this);
4235 catch (ArgumentException) {
4236 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
4243 public void Emit (TypeContainer tc)
4245 EmitContext ec = new EmitContext (tc, Location, null,
4246 FieldBuilder.FieldType, ModFlags);
4248 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes);
4253 // `set' and `get' accessors are represented with an Accessor.
4255 public class Accessor {
4257 // Null if the accessor is empty, or a Block if not
4260 public Attributes OptAttributes;
4262 public Accessor (Block b, Attributes attrs)
4265 OptAttributes = attrs;
4270 // Properties and Indexers both generate PropertyBuilders, we use this to share
4271 // their common bits.
4273 abstract public class PropertyBase : MethodCore {
4274 public Accessor Get, Set;
4275 public PropertyBuilder PropertyBuilder;
4276 public MethodBuilder GetBuilder, SetBuilder;
4277 public MethodData GetData, SetData;
4279 protected EmitContext ec;
4281 public PropertyBase (DeclSpace ds, Expression type, string name, int mod_flags,
4282 int allowed_mod, Parameters parameters,
4283 Accessor get_block, Accessor set_block,
4284 Attributes attrs, Location loc)
4285 : base (ds, type, mod_flags, allowed_mod, name, attrs, parameters, loc)
4291 protected override bool DoDefine (DeclSpace decl, TypeContainer container)
4293 if (!base.DoDefine (decl, container))
4296 ec = new EmitContext (container, Location, null, MemberType, ModFlags);
4302 // Checks our base implementation if any
4304 protected override bool CheckBase (TypeContainer container)
4306 base.CheckBase (container);
4308 // Check whether arguments were correct.
4309 if (!DoDefineParameters ())
4316 MethodSignature ms, base_ms;
4317 if (this is Indexer) {
4318 string name, base_name;
4320 report_name = "this";
4321 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
4322 ms = new MethodSignature (name, null, ParameterTypes);
4323 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
4324 base_ms = new MethodSignature (base_name, null, ParameterTypes);
4327 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
4331 // Verify if the parent has a type with the same name, and then
4332 // check whether we have to create a new slot for it or not.
4334 Type ptype = container.TypeBuilder.BaseType;
4336 // ptype is only null for System.Object while compiling corlib.
4337 if (ptype == null) {
4338 if ((ModFlags & Modifiers.NEW) != 0)
4339 WarningNotHiding (container);
4344 MemberList props_this;
4346 props_this = TypeContainer.FindMembers (
4347 container.TypeBuilder, MemberTypes.Property,
4348 BindingFlags.NonPublic | BindingFlags.Public |
4349 BindingFlags.Static | BindingFlags.Instance |
4350 BindingFlags.DeclaredOnly,
4351 MethodSignature.method_signature_filter, ms);
4353 if (props_this.Count > 0) {
4354 Report.Error (111, Location, "Class `" + container.Name + "' " +
4355 "already defines a member called `" + report_name + "' " +
4356 "with the same parameter types");
4360 MemberList mi_props;
4362 mi_props = TypeContainer.FindMembers (
4363 ptype, MemberTypes.Property,
4364 BindingFlags.NonPublic | BindingFlags.Public |
4365 BindingFlags.Instance | BindingFlags.Static,
4366 MethodSignature.inheritable_method_signature_filter, base_ms);
4368 if (mi_props.Count > 0){
4369 PropertyInfo parent_property = (PropertyInfo) mi_props [0];
4370 string name = parent_property.DeclaringType.Name + "." +
4371 parent_property.Name;
4373 MethodInfo get, set, parent_method;
4374 get = parent_property.GetGetMethod (true);
4375 set = parent_property.GetSetMethod (true);
4378 parent_method = get;
4379 else if (set != null)
4380 parent_method = set;
4382 throw new Exception ("Internal error!");
4384 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
4387 if ((ModFlags & Modifiers.NEW) == 0) {
4388 Type parent_type = TypeManager.TypeToCoreType (
4389 parent_property.PropertyType);
4391 if (parent_type != MemberType) {
4393 508, Location, container.MakeName (Name) + ": cannot " +
4394 "change return type when overriding " +
4395 "inherited member " + name);
4400 if ((ModFlags & Modifiers.NEW) != 0)
4401 WarningNotHiding (container);
4403 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4404 if (this is Indexer)
4405 Report.Error (115, Location,
4406 container.MakeName (Name) +
4407 " no suitable indexers found to override");
4409 Report.Error (115, Location,
4410 container.MakeName (Name) +
4411 " no suitable properties found to override");
4418 public void Emit (TypeContainer tc)
4421 // The PropertyBuilder can be null for explicit implementations, in that
4422 // case, we do not actually emit the ".property", so there is nowhere to
4423 // put the attribute
4425 if (PropertyBuilder != null)
4426 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes);
4428 if (GetData != null) {
4429 GetData.Emit (tc, Get.Block, Get);
4433 if (SetData != null) {
4434 SetData.Emit (tc, Set.Block, Set);
4440 public class Property : PropertyBase, IIteratorContainer {
4441 const int AllowedModifiers =
4444 Modifiers.PROTECTED |
4445 Modifiers.INTERNAL |
4449 Modifiers.OVERRIDE |
4450 Modifiers.ABSTRACT |
4453 Modifiers.METHOD_YIELDS |
4456 public Property (DeclSpace ds, Expression type, string name, int mod_flags,
4457 Accessor get_block, Accessor set_block,
4458 Attributes attrs, Location loc)
4459 : base (ds, type, name, mod_flags, AllowedModifiers,
4460 Parameters.EmptyReadOnlyParameters,
4461 get_block, set_block, attrs, loc)
4465 public override bool Define (TypeContainer container)
4467 if (!DoDefine (container, container))
4470 if (!CheckBase (container))
4473 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4476 Type [] parameters = TypeManager.NoTypes;
4478 InternalParameters ip = new InternalParameters (
4479 container, Parameters.EmptyReadOnlyParameters);
4481 GetData = new MethodData (container, this, "get", MemberType,
4482 parameters, ip, CallingConventions.Standard,
4483 Get.OptAttributes, ModFlags, flags, false);
4486 // Setup iterator if we are one
4488 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
4489 IteratorHandler ih = new IteratorHandler (
4490 "get", container, MemberType,
4491 parameters, ip, ModFlags, Location);
4493 Block new_block = ih.Setup (block);
4494 if (new_block == null)
4499 if (!GetData.Define (container))
4502 GetBuilder = GetData.MethodBuilder;
4506 Type [] parameters = new Type [1];
4507 parameters [0] = MemberType;
4509 Parameter [] parms = new Parameter [1];
4510 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4511 InternalParameters ip = new InternalParameters (
4512 container, new Parameters (parms, null, Location));
4514 SetData = new MethodData (container, this, "set", TypeManager.void_type,
4515 parameters, ip, CallingConventions.Standard,
4516 Set.OptAttributes, ModFlags, flags, false);
4518 if (!SetData.Define (container))
4521 SetBuilder = SetData.MethodBuilder;
4522 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4525 // FIXME - PropertyAttributes.HasDefault ?
4527 PropertyAttributes prop_attr =
4528 PropertyAttributes.RTSpecialName |
4529 PropertyAttributes.SpecialName;
4531 if (!IsExplicitImpl){
4532 PropertyBuilder = container.TypeBuilder.DefineProperty (
4533 Name, prop_attr, MemberType, null);
4536 PropertyBuilder.SetGetMethod (GetBuilder);
4539 PropertyBuilder.SetSetMethod (SetBuilder);
4542 // HACK for the reasons exposed above
4544 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4547 "Class `" + container.Name +
4548 "' already contains a definition for the property `" +
4556 public void SetYields ()
4558 ModFlags |= Modifiers.METHOD_YIELDS;
4563 /// Gigantic workaround for lameness in SRE follows :
4564 /// This class derives from EventInfo and attempts to basically
4565 /// wrap around the EventBuilder so that FindMembers can quickly
4566 /// return this in it search for members
4568 public class MyEventBuilder : EventInfo {
4571 // We use this to "point" to our Builder which is
4572 // not really a MemberInfo
4574 EventBuilder MyBuilder;
4577 // We "catch" and wrap these methods
4579 MethodInfo raise, remove, add;
4581 EventAttributes attributes;
4582 Type declaring_type, reflected_type, event_type;
4587 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4589 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4591 // And now store the values in our own fields.
4593 declaring_type = type_builder;
4595 reflected_type = type_builder;
4597 attributes = event_attr;
4600 this.event_type = event_type;
4604 // Methods that you have to override. Note that you only need
4605 // to "implement" the variants that take the argument (those are
4606 // the "abstract" methods, the others (GetAddMethod()) are
4609 public override MethodInfo GetAddMethod (bool nonPublic)
4614 public override MethodInfo GetRemoveMethod (bool nonPublic)
4619 public override MethodInfo GetRaiseMethod (bool nonPublic)
4625 // These methods make "MyEventInfo" look like a Builder
4627 public void SetRaiseMethod (MethodBuilder raiseMethod)
4629 raise = raiseMethod;
4630 MyBuilder.SetRaiseMethod (raiseMethod);
4633 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4635 remove = removeMethod;
4636 MyBuilder.SetRemoveOnMethod (removeMethod);
4639 public void SetAddOnMethod (MethodBuilder addMethod)
4642 MyBuilder.SetAddOnMethod (addMethod);
4645 public void SetCustomAttribute (CustomAttributeBuilder cb)
4647 MyBuilder.SetCustomAttribute (cb);
4650 public override object [] GetCustomAttributes (bool inherit)
4652 // FIXME : There's nothing which can be seemingly done here because
4653 // we have no way of getting at the custom attribute objects of the
4658 public override object [] GetCustomAttributes (Type t, bool inherit)
4660 // FIXME : Same here !
4664 public override bool IsDefined (Type t, bool b)
4669 public override EventAttributes Attributes {
4675 public override string Name {
4681 public override Type DeclaringType {
4683 return declaring_type;
4687 public override Type ReflectedType {
4689 return reflected_type;
4693 public Type EventType {
4699 public void SetUsed ()
4701 if (my_event != null)
4702 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
4706 public class Event : FieldBase {
4707 const int AllowedModifiers =
4710 Modifiers.PROTECTED |
4711 Modifiers.INTERNAL |
4716 Modifiers.OVERRIDE |
4720 public readonly Accessor Add;
4721 public readonly Accessor Remove;
4722 public MyEventBuilder EventBuilder;
4724 MethodBuilder AddBuilder, RemoveBuilder;
4725 MethodData AddData, RemoveData;
4727 public Event (Expression type, string name, Object init, int mod, Accessor add,
4728 Accessor remove, Attributes attrs, Location loc)
4729 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4735 public override bool Define (TypeContainer container)
4737 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4738 MethodAttributes m_attr = MethodAttributes.HideBySig | MethodAttributes.SpecialName
4740 if (!DoDefine (container, container))
4743 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
4744 Report.Error (74, Location, "'" + container.Name + "." + Name +
4745 "': abstract event can not have an initializer");
4749 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4750 Report.Error (66, Location, "'" + container.Name + "." + Name +
4751 "' : event must be of a delegate type");
4755 Type [] parameter_types = new Type [1];
4756 parameter_types [0] = MemberType;
4758 Parameter [] parms = new Parameter [1];
4759 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4760 InternalParameters ip = new InternalParameters (
4761 container, new Parameters (parms, null, Location));
4763 if (!CheckBase (container))
4767 // Now define the accessors
4769 AddData = new MethodData (container, this, "add", TypeManager.void_type,
4770 parameter_types, ip, CallingConventions.Standard,
4771 (Add != null) ? Add.OptAttributes : null,
4772 ModFlags, flags | m_attr, false);
4774 if (!AddData.Define (container))
4777 AddBuilder = AddData.MethodBuilder;
4778 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4780 RemoveData = new MethodData (container, this, "remove", TypeManager.void_type,
4781 parameter_types, ip, CallingConventions.Standard,
4782 (Remove != null) ? Remove.OptAttributes : null,
4783 ModFlags, flags | m_attr, false);
4785 if (!RemoveData.Define (container))
4788 RemoveBuilder = RemoveData.MethodBuilder;
4789 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4791 if (!IsExplicitImpl){
4792 EventBuilder = new MyEventBuilder (this,
4793 container.TypeBuilder, Name, e_attr, MemberType);
4795 if (Add == null && Remove == null) {
4796 FieldBuilder = container.TypeBuilder.DefineField (
4798 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4799 TypeManager.RegisterPrivateFieldOfEvent (
4800 (EventInfo) EventBuilder, FieldBuilder);
4801 TypeManager.RegisterFieldBase (FieldBuilder, this);
4804 EventBuilder.SetAddOnMethod (AddBuilder);
4805 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4807 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4808 Report.Error (111, Location,
4809 "Class `" + container.Name +
4810 "' already contains a definition for the event `" +
4819 void EmitDefaultMethod (EmitContext ec, bool is_add)
4821 ILGenerator ig = ec.ig;
4822 MethodInfo method = null;
4825 method = TypeManager.delegate_combine_delegate_delegate;
4827 method = TypeManager.delegate_remove_delegate_delegate;
4829 if ((ModFlags & Modifiers.STATIC) != 0) {
4830 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4831 ig.Emit (OpCodes.Ldarg_0);
4832 ig.Emit (OpCodes.Call, method);
4833 ig.Emit (OpCodes.Castclass, MemberType);
4834 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4836 ig.Emit (OpCodes.Ldarg_0);
4837 ig.Emit (OpCodes.Ldarg_0);
4838 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4839 ig.Emit (OpCodes.Ldarg_1);
4840 ig.Emit (OpCodes.Call, method);
4841 ig.Emit (OpCodes.Castclass, MemberType);
4842 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4844 ig.Emit (OpCodes.Ret);
4847 public void Emit (TypeContainer tc)
4851 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4852 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes);
4855 AddData.Emit (tc, Add.Block, Add);
4858 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4859 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4860 EmitDefaultMethod (ec, true);
4863 if (Remove != null) {
4864 RemoveData.Emit (tc, Remove.Block, Remove);
4865 Remove.Block = null;
4867 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4868 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4869 EmitDefaultMethod (ec, false);
4876 // FIXME: This does not handle:
4878 // int INTERFACENAME [ args ]
4883 // int this [ args ]
4885 public class Indexer : PropertyBase {
4887 const int AllowedModifiers =
4890 Modifiers.PROTECTED |
4891 Modifiers.INTERNAL |
4895 Modifiers.OVERRIDE |
4900 public string IndexerName;
4901 public string InterfaceIndexerName;
4904 // Are we implementing an interface ?
4906 public Indexer (DeclSpace ds, Expression type, string int_type, int flags,
4907 Parameters parameters, Accessor get_block, Accessor set_block,
4908 Attributes attrs, Location loc)
4909 : base (ds, type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4912 ExplicitInterfaceName = int_type;
4915 public override bool Define (TypeContainer container)
4917 PropertyAttributes prop_attr =
4918 PropertyAttributes.RTSpecialName |
4919 PropertyAttributes.SpecialName;
4921 if (!DoDefine (container, container))
4924 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4925 if (IndexerName == null)
4926 IndexerName = "Item";
4927 else if (IsExplicitImpl)
4928 Report.Error (592, Location,
4929 "Attribute 'IndexerName' is not valid on this declaration " +
4930 "type. It is valid on `property' declarations only.");
4932 ShortName = IndexerName;
4933 if (IsExplicitImpl) {
4934 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4935 Name = InterfaceType.FullName + "." + IndexerName;
4937 InterfaceIndexerName = IndexerName;
4941 if (!CheckNameCollision (container))
4944 if (!CheckBase (container))
4947 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4949 InternalParameters ip = new InternalParameters (container, Parameters);
4951 GetData = new MethodData (container, this, "get", MemberType,
4952 ParameterTypes, ip, CallingConventions.Standard,
4953 Get.OptAttributes, ModFlags, flags, false);
4955 if (!GetData.Define (container))
4958 GetBuilder = GetData.MethodBuilder;
4962 int top = ParameterTypes.Length;
4963 Type [] set_pars = new Type [top + 1];
4964 ParameterTypes.CopyTo (set_pars, 0);
4965 set_pars [top] = MemberType;
4967 Parameter [] fixed_parms = Parameters.FixedParameters;
4969 if (fixed_parms == null){
4970 throw new Exception ("We currently do not support only array arguments in an indexer at: " + Location);
4971 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4972 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4974 // Here is the problem: the `value' parameter has
4975 // to come *after* the array parameter in the declaration
4977 // X (object [] x, Type value)
4980 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4981 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4985 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4988 fixed_parms.CopyTo (tmp, 0);
4989 tmp [fixed_parms.Length] = new Parameter (
4990 Type, "value", Parameter.Modifier.NONE, null);
4992 Parameters set_formal_params = new Parameters (tmp, null, Location);
4994 InternalParameters ip = new InternalParameters (container, set_formal_params);
4996 SetData = new MethodData (container, this, "set", TypeManager.void_type,
4997 set_pars, ip, CallingConventions.Standard,
4998 Set.OptAttributes, ModFlags, flags, false);
5000 if (!SetData.Define (container))
5003 SetBuilder = SetData.MethodBuilder;
5007 // Now name the parameters
5009 Parameter [] p = Parameters.FixedParameters;
5013 for (i = 0; i < p.Length; ++i) {
5015 GetBuilder.DefineParameter (
5016 i + 1, p [i].Attributes, p [i].Name);
5019 SetBuilder.DefineParameter (
5020 i + 1, p [i].Attributes, p [i].Name);
5024 SetBuilder.DefineParameter (
5025 i + 1, ParameterAttributes.None, "value");
5027 if (i != ParameterTypes.Length) {
5028 Parameter array_param = Parameters.ArrayParameter;
5030 SetBuilder.DefineParameter (
5031 i + 1, array_param.Attributes, array_param.Name);
5036 // Define the PropertyBuilder if one of the following conditions are met:
5037 // a) we're not implementing an interface indexer.
5038 // b) the indexer has a different IndexerName and this is no
5039 // explicit interface implementation.
5041 if (!IsExplicitImpl) {
5042 PropertyBuilder = container.TypeBuilder.DefineProperty (
5043 IndexerName, prop_attr, MemberType, ParameterTypes);
5045 if (GetData != null)
5046 PropertyBuilder.SetGetMethod (GetBuilder);
5048 if (SetData != null)
5049 PropertyBuilder.SetSetMethod (SetBuilder);
5051 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
5058 bool CheckNameCollision (TypeContainer container) {
5059 switch (VerifyName (container)){
5060 case DeclSpace.AdditionResult.NameExists:
5061 Report.Error (102, Location, "The container '{0}' already contains a definition for '{1}'", container.GetSignatureForError (), Name);
5064 case DeclSpace.AdditionResult.Success:
5067 throw new NotImplementedException ();
5070 DeclSpace.AdditionResult VerifyName (TypeContainer container) {
5071 if (!AddIndexer (container, container.Name + "." + Name))
5072 return DeclSpace.AdditionResult.NameExists;
5075 if (!AddIndexer (container, container.Name + ".get_" + Name))
5076 return DeclSpace.AdditionResult.NameExists;
5080 if (!AddIndexer (container, container.Name + ".set_" + Name))
5081 return DeclSpace.AdditionResult.NameExists;
5083 return DeclSpace.AdditionResult.Success;
5086 bool AddIndexer (TypeContainer container, string fullname)
5088 object value = container.GetDefinition (fullname);
5090 if (value != null) {
5091 return value.GetType () != GetType () ? false : true;
5094 container.DefineName (fullname, this);
5098 public override string GetSignatureForError () {
5099 return TypeManager.CSharpSignature (PropertyBuilder, true);
5103 public class Operator : MemberBase, IIteratorContainer {
5105 const int AllowedModifiers =
5111 const int RequiredModifiers =
5115 public enum OpType : byte {
5125 // Unary and Binary operators
5148 // Implicit and Explicit
5153 public readonly OpType OperatorType;
5154 public readonly Expression ReturnType;
5155 public readonly Expression FirstArgType, SecondArgType;
5156 public readonly string FirstArgName, SecondArgName;
5158 public MethodBuilder OperatorMethodBuilder;
5160 public string MethodName;
5161 public Method OperatorMethod;
5163 public Operator (OpType type, Expression ret_type, int mod_flags,
5164 Expression arg1type, string arg1name,
5165 Expression arg2type, string arg2name,
5166 Block block, Attributes attrs, Location loc)
5167 : base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC, "", attrs, loc)
5169 OperatorType = type;
5170 Name = "op_" + OperatorType;
5171 ReturnType = ret_type;
5172 FirstArgType = arg1type;
5173 FirstArgName = arg1name;
5174 SecondArgType = arg2type;
5175 SecondArgName = arg2name;
5179 string Prototype (TypeContainer container)
5181 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
5182 SecondArgType + ")";
5185 public override bool Define (TypeContainer container)
5188 MethodName = "op_" + OperatorType;
5190 if (SecondArgType != null)
5193 Parameter [] param_list = new Parameter [length];
5195 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
5198 "User defined operators `" +
5199 Prototype (container) +
5200 "' must be declared static and public");
5204 param_list[0] = new Parameter (FirstArgType, FirstArgName,
5205 Parameter.Modifier.NONE, null);
5206 if (SecondArgType != null)
5207 param_list[1] = new Parameter (SecondArgType, SecondArgName,
5208 Parameter.Modifier.NONE, null);
5210 OperatorMethod = new Method (container, ReturnType, ModFlags, MethodName,
5211 new Parameters (param_list, null, Location),
5212 OptAttributes, Location);
5214 OperatorMethod.Block = Block;
5215 OperatorMethod.IsOperator = true;
5216 OperatorMethod.Define (container);
5218 if (OperatorMethod.MethodBuilder == null)
5221 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
5223 Type [] param_types = OperatorMethod.ParameterTypes;
5224 Type declaring_type = OperatorMethodBuilder.DeclaringType;
5225 Type return_type = OperatorMethod.GetReturnType ();
5226 Type first_arg_type = param_types [0];
5228 // Rules for conversion operators
5230 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
5231 if (first_arg_type == return_type && first_arg_type == declaring_type){
5234 "User-defined conversion cannot take an object of the " +
5235 "enclosing type and convert to an object of the enclosing" +
5240 if (first_arg_type != declaring_type && return_type != declaring_type){
5243 "User-defined conversion must convert to or from the " +
5248 if (first_arg_type == TypeManager.object_type ||
5249 return_type == TypeManager.object_type){
5252 "User-defined conversion cannot convert to or from " +
5257 if (first_arg_type.IsInterface || return_type.IsInterface){
5260 "User-defined conversion cannot convert to or from an " +
5265 if (first_arg_type.IsSubclassOf (return_type) ||
5266 return_type.IsSubclassOf (first_arg_type)){
5269 "User-defined conversion cannot convert between types " +
5270 "that derive from each other");
5273 } else if (SecondArgType == null) {
5274 // Checks for Unary operators
5276 if (first_arg_type != declaring_type){
5279 "The parameter of a unary operator must be the " +
5284 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
5285 if (return_type != declaring_type){
5288 "The parameter and return type for ++ and -- " +
5289 "must be the containing type");
5295 if (OperatorType == OpType.True || OperatorType == OpType.False) {
5296 if (return_type != TypeManager.bool_type){
5299 "The return type of operator True or False " +
5306 // Checks for Binary operators
5308 if (first_arg_type != declaring_type &&
5309 param_types [1] != declaring_type){
5312 "One of the parameters of a binary operator must " +
5313 "be the containing type");
5321 public void Emit (TypeContainer container)
5324 // abstract or extern methods have no bodies
5326 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
5329 OperatorMethod.Emit (container);
5333 public static string GetName (OpType ot)
5336 case OpType.LogicalNot:
5338 case OpType.OnesComplement:
5340 case OpType.Increment:
5342 case OpType.Decrement:
5348 case OpType.Addition:
5350 case OpType.Subtraction:
5352 case OpType.UnaryPlus:
5354 case OpType.UnaryNegation:
5356 case OpType.Multiply:
5358 case OpType.Division:
5360 case OpType.Modulus:
5362 case OpType.BitwiseAnd:
5364 case OpType.BitwiseOr:
5366 case OpType.ExclusiveOr:
5368 case OpType.LeftShift:
5370 case OpType.RightShift:
5372 case OpType.Equality:
5374 case OpType.Inequality:
5376 case OpType.GreaterThan:
5378 case OpType.LessThan:
5380 case OpType.GreaterThanOrEqual:
5382 case OpType.LessThanOrEqual:
5384 case OpType.Implicit:
5386 case OpType.Explicit:
5392 public override string ToString ()
5394 Type return_type = OperatorMethod.GetReturnType();
5395 Type [] param_types = OperatorMethod.ParameterTypes;
5397 if (SecondArgType == null)
5398 return String.Format (
5399 "{0} operator {1}({2})",
5400 TypeManager.CSharpName (return_type),
5401 GetName (OperatorType),
5404 return String.Format (
5405 "{0} operator {1}({2}, {3})",
5406 TypeManager.CSharpName (return_type),
5407 GetName (OperatorType),
5408 param_types [0], param_types [1]);
5411 public void SetYields ()
5413 ModFlags |= Modifiers.METHOD_YIELDS;
5418 // This is used to compare method signatures
5420 struct MethodSignature {
5422 public Type RetType;
5423 public Type [] Parameters;
5426 /// This delegate is used to extract methods which have the
5427 /// same signature as the argument
5429 public static MemberFilter method_signature_filter;
5432 /// This delegate is used to extract inheritable methods which
5433 /// have the same signature as the argument. By inheritable,
5434 /// this means that we have permissions to override the method
5435 /// from the current assembly and class
5437 public static MemberFilter inheritable_method_signature_filter;
5439 static MethodSignature ()
5441 method_signature_filter = new MemberFilter (MemberSignatureCompare);
5442 inheritable_method_signature_filter = new MemberFilter (
5443 InheritableMemberSignatureCompare);
5446 public MethodSignature (string name, Type ret_type, Type [] parameters)
5451 if (parameters == null)
5452 Parameters = TypeManager.NoTypes;
5454 Parameters = parameters;
5457 public override string ToString ()
5460 if (Parameters.Length != 0){
5461 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
5462 for (int i = 0; i < Parameters.Length; i++){
5463 sb.Append (Parameters [i]);
5464 if (i+1 < Parameters.Length)
5467 pars = sb.ToString ();
5470 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
5473 public override int GetHashCode ()
5475 return Name.GetHashCode ();
5478 public override bool Equals (Object o)
5480 MethodSignature other = (MethodSignature) o;
5482 if (other.Name != Name)
5485 if (other.RetType != RetType)
5488 if (Parameters == null){
5489 if (other.Parameters == null)
5494 if (other.Parameters == null)
5497 int c = Parameters.Length;
5498 if (other.Parameters.Length != c)
5501 for (int i = 0; i < c; i++)
5502 if (other.Parameters [i] != Parameters [i])
5508 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
5510 MethodSignature sig = (MethodSignature) filter_criteria;
5512 if (m.Name != sig.Name)
5516 MethodInfo mi = m as MethodInfo;
5517 PropertyInfo pi = m as PropertyInfo;
5520 ReturnType = mi.ReturnType;
5521 else if (pi != null)
5522 ReturnType = pi.PropertyType;
5527 // we use sig.RetType == null to mean `do not check the
5528 // method return value.
5530 if (sig.RetType != null)
5531 if (ReturnType != sig.RetType)
5536 args = TypeManager.GetArgumentTypes (mi);
5538 args = TypeManager.GetArgumentTypes (pi);
5539 Type [] sigp = sig.Parameters;
5541 if (args.Length != sigp.Length)
5544 for (int i = args.Length; i > 0; ){
5546 if (args [i] != sigp [i])
5553 // This filter should be used when we are requesting methods that
5554 // we want to override.
5556 // This makes a number of assumptions, for example
5557 // that the methods being extracted are of a parent
5558 // class (this means we know implicitly that we are
5559 // being called to find out about members by a derived
5562 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
5565 PropertyInfo pi = m as PropertyInfo;
5568 mi = pi.GetGetMethod (true);
5570 mi = pi.GetSetMethod (true);
5572 mi = m as MethodInfo;
5575 Console.WriteLine ("Nothing found");
5578 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
5580 // If only accessible to the current class.
5581 if (prot == MethodAttributes.Private)
5584 if (!MemberSignatureCompare (m, filter_criteria))
5587 // If only accessible to the defining assembly or
5588 if (prot == MethodAttributes.FamANDAssem ||
5589 prot == MethodAttributes.Assembly){
5590 return m.DeclaringType.Assembly == CodeGen.Assembly.Builder;
5593 // Anything else (FamOrAssembly and Public) is fine