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 bool members_defined;
117 bool members_defined_ok;
119 // Information in the case we are an attribute type
121 public AttributeTargets Targets = AttributeTargets.All;
122 public bool AllowMultiple = false;
123 public bool Inherited;
125 // The interfaces we implement.
127 Type[] base_inteface_types;
129 // The parent member container and our member cache
130 IMemberContainer parent_container;
131 MemberCache member_cache;
134 // The indexer name for this class
136 public string IndexerName;
138 public TypeContainer ():
139 this (null, null, "", null, new Location (-1)) {
142 public TypeContainer (NamespaceEntry ns, TypeContainer parent, string name, Attributes attrs, Location l)
143 : base (ns, parent, name, attrs, l)
145 types = new ArrayList ();
147 base_class_name = null;
150 public AdditionResult AddConstant (Const constant)
153 string basename = constant.Name;
154 string fullname = Name + "." + basename;
156 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
159 if (constants == null)
160 constants = new ArrayList ();
162 constants.Add (constant);
163 DefineName (fullname, constant);
165 return AdditionResult.Success;
168 public AdditionResult AddEnum (Mono.CSharp.Enum e)
172 if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
176 enums = new ArrayList ();
179 DefineName (e.Name, e);
181 return AdditionResult.Success;
184 public AdditionResult AddClass (Class c)
187 string name = c.Basename;
189 if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
192 DefineName (c.Name, c);
195 return AdditionResult.Success;
198 public AdditionResult AddStruct (Struct s)
201 string name = s.Basename;
203 if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
206 DefineName (s.Name, s);
209 return AdditionResult.Success;
212 public AdditionResult AddDelegate (Delegate d)
215 string name = d.Basename;
217 if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
220 if (delegates == null)
221 delegates = new ArrayList ();
223 DefineName (d.Name, d);
226 return AdditionResult.Success;
229 public AdditionResult AddMethod (Method method)
231 string basename = method.Name;
232 string fullname = Name + "." + basename;
234 Object value = defined_names [fullname];
236 if (value != null && (!(value is Method)))
237 return AdditionResult.NameExists;
239 if (basename == Basename)
240 return AdditionResult.EnclosingClash;
243 methods = new ArrayList ();
245 if (method.Name.IndexOf ('.') != -1)
246 methods.Insert (0, method);
248 methods.Add (method);
251 DefineName (fullname, method);
253 return AdditionResult.Success;
256 public AdditionResult AddConstructor (Constructor c)
258 if (c.Name != Basename)
259 return AdditionResult.NotAConstructor;
261 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
264 UserDefinedStaticConstructor = true;
265 if (default_static_constructor != null)
266 return AdditionResult.MethodExists;
268 default_static_constructor = c;
271 if (default_constructor != null)
272 return AdditionResult.MethodExists;
273 default_constructor = c;
276 if (instance_constructors == null)
277 instance_constructors = new ArrayList ();
279 instance_constructors.Add (c);
282 return AdditionResult.Success;
285 public AdditionResult AddInterface (Interface iface)
288 string name = iface.Basename;
290 if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
293 if (interfaces == null)
294 interfaces = new ArrayList ();
295 interfaces.Add (iface);
296 DefineName (iface.Name, iface);
298 return AdditionResult.Success;
301 public AdditionResult AddField (Field field)
304 string basename = field.Name;
305 string fullname = Name + "." + basename;
307 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
311 fields = new ArrayList ();
315 if (field.HasInitializer){
316 if ((field.ModFlags & Modifiers.STATIC) != 0){
317 if (initialized_static_fields == null)
318 initialized_static_fields = new ArrayList ();
320 initialized_static_fields.Add (field);
323 if (initialized_fields == null)
324 initialized_fields = new ArrayList ();
326 initialized_fields.Add (field);
330 if ((field.ModFlags & Modifiers.STATIC) == 0)
331 have_nonstatic_fields = true;
333 DefineName (fullname, field);
334 return AdditionResult.Success;
337 public AdditionResult AddProperty (Property prop)
341 if ((res = AddProperty (prop, prop.Name)) != AdditionResult.Success)
344 if (prop.Get != null) {
345 if ((res = AddProperty (prop, "get_" + prop.Name)) != AdditionResult.Success)
349 if (prop.Set != null) {
350 if ((res = AddProperty (prop, "set_" + prop.Name)) != AdditionResult.Success)
354 if (properties == null)
355 properties = new ArrayList ();
357 if (prop.Name.IndexOf ('.') != -1)
358 properties.Insert (0, prop);
360 properties.Add (prop);
362 return AdditionResult.Success;
365 AdditionResult AddProperty (Property prop, string basename)
368 string fullname = Name + "." + basename;
370 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
373 DefineName (fullname, prop);
375 return AdditionResult.Success;
378 public AdditionResult AddEvent (Event e)
381 string basename = e.Name;
382 string fullname = Name + "." + basename;
384 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
388 events = new ArrayList ();
391 DefineName (fullname, e);
393 return AdditionResult.Success;
396 public void AddIndexer (Indexer i)
398 if (indexers == null)
399 indexers = new ArrayList ();
401 if (i.ExplicitInterfaceName != null)
402 indexers.Insert (0, i);
407 public AdditionResult AddOperator (Operator op)
409 if (operators == null)
410 operators = new ArrayList ();
414 string basename = op.Name;
415 string fullname = Name + "." + basename;
416 if (!defined_names.Contains (fullname))
418 DefineName (fullname, op);
420 return AdditionResult.Success;
423 public void RegisterOrder (Interface iface)
425 if (interface_order == null)
426 interface_order = new ArrayList ();
428 interface_order.Add (iface);
431 public ArrayList Types {
437 public ArrayList Methods {
443 public ArrayList Constants {
449 public ArrayList Interfaces {
457 return base_class_name;
461 public ArrayList Bases {
471 public ArrayList Fields {
481 public ArrayList InstanceConstructors {
483 return instance_constructors;
487 public ArrayList Properties {
493 public ArrayList Events {
499 public ArrayList Enums {
505 public ArrayList Indexers {
511 public ArrayList Operators {
517 public ArrayList Delegates {
523 public virtual TypeAttributes TypeAttr {
525 return Modifiers.TypeAttr (ModFlags, this);
530 // Emits the instance field initializers
532 public bool EmitFieldInitializers (EmitContext ec)
535 Expression instance_expr;
538 fields = initialized_static_fields;
539 instance_expr = null;
541 fields = initialized_fields;
542 instance_expr = new This (Location.Null).Resolve (ec);
548 foreach (Field f in fields){
549 Expression e = f.GetInitializerExpression (ec);
553 Location l = f.Location;
554 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
555 fe.InstanceExpression = instance_expr;
556 ExpressionStatement a = new Assign (fe, e, l);
558 a = a.ResolveStatement (ec);
562 a.EmitStatement (ec);
569 // Defines the default constructors
571 void DefineDefaultConstructor (bool is_static)
575 // The default constructor is public
576 // If the class is abstract, the default constructor is protected
577 // The default static constructor is private
579 int mods = Modifiers.PUBLIC;
581 mods = Modifiers.STATIC | Modifiers.PRIVATE;
582 else if ((ModFlags & Modifiers.ABSTRACT) != 0)
583 mods = Modifiers.PROTECTED;
585 c = new Constructor (this, Basename, mods, Parameters.EmptyReadOnlyParameters,
586 new ConstructorBaseInitializer (
587 null, Parameters.EmptyReadOnlyParameters,
593 c.Block = new ToplevelBlock (null, Location);
597 public void ReportStructInitializedInstanceError ()
599 string n = TypeBuilder.FullName;
601 foreach (Field f in initialized_fields){
604 "`" + n + "." + f.Name + "': can not have " +
605 "instance field initializers in structs");
610 /// The pending methods that need to be implemented (interfaces or abstract methods)
612 public PendingImplementation Pending;
615 /// This function computes the Base class and also the
616 /// list of interfaces that the class or struct @c implements.
618 /// The return value is an array (might be null) of
619 /// interfaces implemented (as Types).
621 /// The @parent argument is set to the parent object or null
622 /// if this is `System.Object'.
624 TypeExpr [] GetClassBases (bool is_class, bool is_iface,
625 out TypeExpr parent, out bool error)
627 ArrayList bases = Bases;
633 if (is_class || is_iface)
636 parent = TypeManager.system_valuetype_expr;
640 if (RootContext.StdLib)
641 parent = TypeManager.system_object_expr;
642 else if (Name != "System.Object")
643 parent = TypeManager.system_object_expr;
646 // If we are compiling our runtime,
647 // and we are defining ValueType, then our
648 // parent is `System.Object'.
650 if (!RootContext.StdLib && Name == "System.ValueType")
651 parent = TypeManager.system_object_expr;
658 // Bases should be null if there are no bases at all
663 TypeExpr name = ResolveTypeExpr ((Expression) bases [0], false, Location);
674 parent = TypeManager.system_object_expr;
680 if (name.IsValueType)
681 detail = " (a class can not inherit from a struct/enum)";
683 Report.Error (509, "class `"+ Name +
684 "': Cannot inherit from sealed class `"+
685 name.Name + "'" + detail);
690 if (!parent.CanInheritFrom ()){
691 Report.Error (644, Location,
692 "`{0}' cannot inherit from special class `{1}'",
698 if (!parent.AsAccessible (this, ModFlags))
699 Report.Error (60, Location,
700 "Inconsistent accessibility: base class `" +
701 name.Name + "' is less accessible than class `" +
709 base_class_name = parent.Name;
711 TypeExpr [] ifaces = new TypeExpr [count-start];
713 for (i = start, j = 0; i < count; i++, j++){
714 Expression name = (Expression) bases [i];
715 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
716 if (resolved == null)
719 bases [i] = resolved;
721 if (is_class == false && !resolved.IsInterface){
722 Report.Error (527, "In Struct `" + Name + "', type `"+
723 name +"' is not an interface");
728 if (resolved.IsClass) {
730 Report.Error (527, "In Class `" + Name + "', type `"+
731 name+"' is not an interface");
737 for (int x = 0; x < j; x++) {
738 if (resolved.Equals (ifaces [x])) {
739 Report.Error (528, "`" + name + "' is already listed in interface list");
746 !resolved.AsAccessible (Parent, ModFlags))
747 Report.Error (61, Location,
748 "Inconsistent accessibility: base interface `" +
749 name + "' is less accessible than interface `" +
752 ifaces [j] = resolved;
755 return TypeManager.ExpandInterfaces (ifaces);
761 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
763 public override TypeBuilder DefineType ()
766 bool is_class, is_iface;
768 if (TypeBuilder != null)
775 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
782 if (this is Interface) {
793 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
795 ifaces = GetClassBases (is_class, is_iface, out parent, out error);
800 if (!is_class && TypeManager.value_type == null)
801 throw new Exception ();
803 TypeAttributes type_attributes = TypeAttr;
807 ptype = parent.ResolveType (ec);
812 if (TypeManager.NamespaceClash (Name, Location)) {
817 ModuleBuilder builder = CodeGen.Module.Builder;
818 TypeBuilder = builder.DefineType (
819 Name, type_attributes, ptype, null);
821 TypeBuilder builder = Parent.DefineType ();
825 TypeBuilder = builder.DefineNestedType (
826 Basename, type_attributes, ptype, null);
830 // Structs with no fields need to have at least one byte.
831 // The right thing would be to set the PackingSize in a DefineType
832 // but there are no functions that allow interfaces *and* the size to
836 if (!is_class && !is_iface && !have_nonstatic_fields){
837 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
838 FieldAttributes.Private);
841 // add interfaces that were not added at type creation
842 if (ifaces != null) {
843 base_inteface_types = new Type[ifaces.Length];
844 for (int i = 0; i < ifaces.Length; ++i) {
845 Type itype = ifaces [i].ResolveType (ec);
846 TypeBuilder.AddInterfaceImplementation (itype);
847 base_inteface_types [i] = itype;
852 // Finish the setup for the EmitContext
854 ec.ContainerType = TypeBuilder;
856 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
858 if ((parent != null) && parent.IsAttribute) {
859 RootContext.RegisterAttribute (this);
860 TypeManager.RegisterAttrType (TypeBuilder, this);
862 RootContext.RegisterOrder (this);
864 if (Interfaces != null) {
865 foreach (Interface iface in Interfaces)
866 if (iface.DefineType () == null) {
873 foreach (TypeContainer tc in Types)
874 if (tc.DefineType () == null) {
880 if (Delegates != null) {
881 foreach (Delegate d in Delegates)
882 if (d.DefineType () == null) {
889 foreach (Enum en in Enums)
890 if (en.DefineType () == null) {
902 /// Defines the MemberCore objects that are in the `list' Arraylist
904 /// The `defined_names' array contains a list of members defined in
907 static ArrayList remove_list = new ArrayList ();
908 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
912 remove_list.Clear ();
914 foreach (MemberCore mc in list){
916 if (defined_names != null)
917 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
922 if (RootContext.WarningLevel >= 4){
923 if ((mc.ModFlags & Modifiers.NEW) != 0)
924 Warning_KeywordNewNotRequired (mc.Location, mc);
926 } else if (mc is MethodCore)
927 ((MethodCore) mc).OverridesSomething = true;
929 if (!mc.Define (this)){
930 remove_list.Add (mc);
937 MemberInfo match = defined_names [idx];
939 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
943 // If we are both methods, let the method resolution emit warnings
945 if (match is MethodBase && mc is MethodCore)
948 if ((mc.ModFlags & Modifiers.NEW) == 0) {
950 if (!(match is EventInfo)) {
951 Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
955 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
959 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
963 foreach (object o in remove_list)
966 remove_list.Clear ();
970 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
971 // class is consistent. Either it is `Item' or it is the name defined by all the
972 // indexers with the `IndexerName' attribute.
974 // Turns out that the IndexerNameAttribute is applied to each indexer,
975 // but it is never emitted, instead a DefaultMember attribute is attached
978 void DefineIndexers ()
980 string class_indexer_name = null;
983 // If there's both an explicit and an implicit interface implementation, the
984 // explicit one actually implements the interface while the other one is just
985 // a normal indexer. See bug #37714.
988 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
989 bool seen_normal_indexers = false;
990 foreach (Indexer i in Indexers) {
991 if (i.ExplicitInterfaceName == null)
992 seen_normal_indexers = true;
993 else if (seen_normal_indexers)
994 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
997 foreach (Indexer i in Indexers) {
1002 name = i.IndexerName;
1004 if (i.InterfaceType != null)
1007 if (class_indexer_name == null){
1008 class_indexer_name = name;
1012 if (name == class_indexer_name)
1016 668, "Two indexers have different names, " +
1017 " you should use the same name for all your indexers");
1020 if (seen_normal_indexers && class_indexer_name == null)
1021 class_indexer_name = "Item";
1022 IndexerName = class_indexer_name;
1025 static void Error_KeywordNotAllowed (Location loc)
1027 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1031 /// Populates our TypeBuilder with fields and methods
1033 public override bool DefineMembers (TypeContainer container)
1035 if (members_defined)
1036 return members_defined_ok;
1038 members_defined_ok = DoDefineMembers ();
1039 members_defined = true;
1041 return members_defined_ok;
1044 bool DoDefineMembers ()
1046 MemberInfo [] defined_names = null;
1049 // We need to be able to use the member cache while we are checking/defining
1052 if (TypeBuilder.BaseType != null)
1053 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1056 if (interface_order != null){
1057 foreach (Interface iface in interface_order)
1058 if ((iface.ModFlags & Modifiers.NEW) == 0)
1059 iface.DefineMembers (this);
1061 Error_KeywordNotAllowed (iface.Location);
1064 if (RootContext.WarningLevel > 1){
1068 // This code throws an exception in the comparer
1069 // I guess the string is not an object?
1071 ptype = TypeBuilder.BaseType;
1073 defined_names = (MemberInfo []) FindMembers (
1074 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1075 BindingFlags.Public | BindingFlags.Instance |
1076 BindingFlags.Static, null, null);
1078 Array.Sort (defined_names, mif_compare);
1082 Class pclass = Parent as Class;
1083 if (pclass != null) {
1084 string pname = null;
1086 Type t = pclass.TypeBuilder.BaseType;
1087 while ((t != null) && (ptype == null)) {
1088 pname = t.FullName + "." + Basename;
1089 ptype = RootContext.LookupType (this, pname, true, Location.Null);
1093 if ((ModFlags & Modifiers.NEW) != 0) {
1095 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1096 "inherited member. The keyword new is not required.");
1097 } else if (ptype != null) {
1098 Report.Warning (108, Location, "The keyword new is required on `" +
1099 Name + "' because it hides inherited member '" +
1102 } else if ((ModFlags & Modifiers.NEW) != 0)
1103 Error_KeywordNotAllowed (Location);
1105 if (constants != null)
1106 DefineMembers (constants, defined_names);
1109 DefineMembers (fields, defined_names);
1112 if (instance_constructors == null){
1113 if (default_constructor == null)
1114 DefineDefaultConstructor (false);
1117 if (initialized_static_fields != null &&
1118 default_static_constructor == null)
1119 DefineDefaultConstructor (true);
1122 if (this is Struct){
1124 // Structs can not have initialized instance
1127 if (initialized_static_fields != null &&
1128 default_static_constructor == null)
1129 DefineDefaultConstructor (true);
1131 if (initialized_fields != null)
1132 ReportStructInitializedInstanceError ();
1135 if (!(this is Interface))
1136 Pending = PendingImplementation.GetPendingImplementations (this);
1139 // Constructors are not in the defined_names array
1141 if (instance_constructors != null)
1142 DefineMembers (instance_constructors, null);
1144 if (default_static_constructor != null)
1145 default_static_constructor.Define (this);
1147 if (methods != null)
1148 DefineMembers (methods, defined_names);
1150 if (properties != null)
1151 DefineMembers (properties, defined_names);
1154 DefineMembers (events, defined_names);
1156 if (indexers != null)
1159 if (operators != null){
1160 DefineMembers (operators, null);
1162 CheckPairedOperators ();
1166 DefineMembers (enums, defined_names);
1168 if (delegates != null)
1169 DefineMembers (delegates, defined_names);
1172 member_cache = new MemberCache (this);
1179 public override bool Define (TypeContainer container)
1181 if (interface_order != null){
1182 foreach (Interface iface in interface_order)
1183 if ((iface.ModFlags & Modifiers.NEW) == 0)
1184 iface.Define (this);
1191 /// This function is based by a delegate to the FindMembers routine
1193 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1199 /// This filter is used by FindMembers, and we just keep
1200 /// a global for the filter to `AlwaysAccept'
1202 static MemberFilter accepting_filter;
1206 /// A member comparission method based on name only
1208 static IComparer mif_compare;
1210 static TypeContainer ()
1212 accepting_filter = new MemberFilter (AlwaysAccept);
1213 mif_compare = new MemberInfoCompare ();
1216 public MethodInfo[] GetMethods ()
1218 ArrayList members = new ArrayList ();
1220 DefineMembers (null);
1222 if (methods != null) {
1223 int len = methods.Count;
1224 for (int i = 0; i < len; i++) {
1225 Method m = (Method) methods [i];
1227 members.Add (m.MethodBuilder);
1231 if (operators != null) {
1232 int len = operators.Count;
1233 for (int i = 0; i < len; i++) {
1234 Operator o = (Operator) operators [i];
1236 members.Add (o.OperatorMethodBuilder);
1240 if (properties != null) {
1241 int len = properties.Count;
1242 for (int i = 0; i < len; i++) {
1243 Property p = (Property) properties [i];
1245 if (p.GetBuilder != null)
1246 members.Add (p.GetBuilder);
1247 if (p.SetBuilder != null)
1248 members.Add (p.SetBuilder);
1252 if (indexers != null) {
1253 int len = indexers.Count;
1254 for (int i = 0; i < len; i++) {
1255 Indexer ix = (Indexer) indexers [i];
1257 if (ix.GetBuilder != null)
1258 members.Add (ix.GetBuilder);
1259 if (ix.SetBuilder != null)
1260 members.Add (ix.SetBuilder);
1264 if (events != null) {
1265 int len = events.Count;
1266 for (int i = 0; i < len; i++) {
1267 Event e = (Event) events [i];
1269 if (e.AddBuilder != null)
1270 members.Add (e.AddBuilder);
1271 if (e.RemoveBuilder != null)
1272 members.Add (e.RemoveBuilder);
1276 MethodInfo[] retMethods = new MethodInfo [members.Count];
1277 members.CopyTo (retMethods, 0);
1282 /// This method returns the members of this type just like Type.FindMembers would
1283 /// Only, we need to use this for types which are _being_ defined because MS'
1284 /// implementation can't take care of that.
1287 // FIXME: return an empty static array instead of null, that cleans up
1288 // some code and is consistent with some coding conventions I just found
1292 // Notice that in various cases we check if our field is non-null,
1293 // something that would normally mean that there was a bug elsewhere.
1295 // The problem happens while we are defining p-invoke methods, as those
1296 // will trigger a FindMembers, but this happens before things are defined
1298 // Since the whole process is a no-op, it is fine to check for null here.
1300 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1301 MemberFilter filter, object criteria)
1303 ArrayList members = null;
1306 if ((bf & BindingFlags.Public) != 0)
1307 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1309 if ((bf & BindingFlags.NonPublic) != 0)
1310 modflags |= Modifiers.PRIVATE;
1312 int static_mask = 0, static_flags = 0;
1313 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1314 case BindingFlags.Static:
1315 static_mask = static_flags = Modifiers.STATIC;
1318 case BindingFlags.Instance:
1319 static_mask = Modifiers.STATIC;
1324 static_mask = static_flags = 0;
1328 Timer.StartTimer (TimerType.TcFindMembers);
1331 filter = accepting_filter;
1333 if ((mt & MemberTypes.Field) != 0) {
1334 if (fields != null) {
1335 int len = fields.Count;
1336 for (int i = 0; i < len; i++) {
1337 Field f = (Field) fields [i];
1339 if ((f.ModFlags & modflags) == 0)
1341 if ((f.ModFlags & static_mask) != static_flags)
1344 FieldBuilder fb = f.FieldBuilder;
1345 if (fb != null && filter (fb, criteria) == true) {
1346 if (members == null)
1347 members = new ArrayList ();
1354 if (constants != null) {
1355 int len = constants.Count;
1356 for (int i = 0; i < len; i++) {
1357 Const con = (Const) constants [i];
1359 if ((con.ModFlags & modflags) == 0)
1361 if ((con.ModFlags & static_mask) != static_flags)
1364 FieldBuilder fb = con.FieldBuilder;
1365 if (fb != null && filter (fb, criteria) == true) {
1366 if (members == null)
1367 members = new ArrayList ();
1375 if ((mt & MemberTypes.Method) != 0) {
1376 if (methods != null) {
1377 int len = methods.Count;
1378 for (int i = 0; i < len; i++) {
1379 Method m = (Method) methods [i];
1381 if ((m.ModFlags & modflags) == 0)
1383 if ((m.ModFlags & static_mask) != static_flags)
1386 MethodBuilder mb = m.MethodBuilder;
1388 if (mb != null && filter (mb, criteria) == true) {
1389 if (members == null)
1390 members = new ArrayList ();
1397 if (operators != null) {
1398 int len = operators.Count;
1399 for (int i = 0; i < len; i++) {
1400 Operator o = (Operator) operators [i];
1402 if ((o.ModFlags & modflags) == 0)
1404 if ((o.ModFlags & static_mask) != static_flags)
1407 MethodBuilder ob = o.OperatorMethodBuilder;
1408 if (ob != null && filter (ob, criteria) == true) {
1409 if (members == null)
1410 members = new ArrayList ();
1417 if (properties != null) {
1418 int len = properties.Count;
1419 for (int i = 0; i < len; i++) {
1420 Property p = (Property) properties [i];
1422 if ((p.ModFlags & modflags) == 0)
1424 if ((p.ModFlags & static_mask) != static_flags)
1430 if (b != null && filter (b, criteria) == true) {
1431 if (members == null)
1432 members = new ArrayList ();
1438 if (b != null && filter (b, criteria) == true) {
1439 if (members == null)
1440 members = new ArrayList ();
1447 if (indexers != null) {
1448 int len = indexers.Count;
1449 for (int i = 0; i < len; i++) {
1450 Indexer ix = (Indexer) indexers [i];
1452 if ((ix.ModFlags & modflags) == 0)
1454 if ((ix.ModFlags & static_mask) != static_flags)
1460 if (b != null && filter (b, criteria) == true) {
1461 if (members == null)
1462 members = new ArrayList ();
1468 if (b != null && filter (b, criteria) == true) {
1469 if (members == null)
1470 members = new ArrayList ();
1478 if ((mt & MemberTypes.Event) != 0) {
1479 if (events != null) {
1480 int len = events.Count;
1481 for (int i = 0; i < len; i++) {
1482 Event e = (Event) events [i];
1484 if ((e.ModFlags & modflags) == 0)
1486 if ((e.ModFlags & static_mask) != static_flags)
1489 MemberInfo eb = e.EventBuilder;
1490 if (eb != null && filter (eb, criteria) == true) {
1491 if (members == null)
1492 members = new ArrayList ();
1494 members.Add (e.EventBuilder);
1500 if ((mt & MemberTypes.Property) != 0){
1501 if (properties != null) {
1502 int len = properties.Count;
1503 for (int i = 0; i < len; i++) {
1504 Property p = (Property) properties [i];
1506 if ((p.ModFlags & modflags) == 0)
1508 if ((p.ModFlags & static_mask) != static_flags)
1511 MemberInfo pb = p.PropertyBuilder;
1512 if (pb != null && filter (pb, criteria) == true) {
1513 if (members == null)
1514 members = new ArrayList ();
1516 members.Add (p.PropertyBuilder);
1521 if (indexers != null) {
1522 int len = indexers.Count;
1523 for (int i = 0; i < len; i++) {
1524 Indexer ix = (Indexer) indexers [i];
1526 if ((ix.ModFlags & modflags) == 0)
1528 if ((ix.ModFlags & static_mask) != static_flags)
1531 MemberInfo ib = ix.PropertyBuilder;
1532 if (ib != null && filter (ib, criteria) == true) {
1533 if (members == null)
1534 members = new ArrayList ();
1536 members.Add (ix.PropertyBuilder);
1542 if ((mt & MemberTypes.NestedType) != 0) {
1543 if (types != null) {
1544 int len = types.Count;
1545 for (int i = 0; i < len; i++) {
1546 TypeContainer t = (TypeContainer) types [i];
1548 if ((t.ModFlags & modflags) == 0)
1551 TypeBuilder tb = t.TypeBuilder;
1552 if (tb != null && (filter (tb, criteria) == true)) {
1553 if (members == null)
1554 members = new ArrayList ();
1561 if (enums != null) {
1562 int len = enums.Count;
1563 for (int i = 0; i < len; i++) {
1564 Enum en = (Enum) enums [i];
1566 if ((en.ModFlags & modflags) == 0)
1569 TypeBuilder tb = en.TypeBuilder;
1570 if (tb != null && (filter (tb, criteria) == true)) {
1571 if (members == null)
1572 members = new ArrayList ();
1579 if (delegates != null) {
1580 int len = delegates.Count;
1581 for (int i = 0; i < len; i++) {
1582 Delegate d = (Delegate) delegates [i];
1584 if ((d.ModFlags & modflags) == 0)
1587 TypeBuilder tb = d.TypeBuilder;
1588 if (tb != null && (filter (tb, criteria) == true)) {
1589 if (members == null)
1590 members = new ArrayList ();
1597 if (interfaces != null) {
1598 int len = interfaces.Count;
1599 for (int i = 0; i < len; i++) {
1600 Interface iface = (Interface) interfaces [i];
1602 if ((iface.ModFlags & modflags) == 0)
1605 TypeBuilder tb = iface.TypeBuilder;
1606 if (tb != null && (filter (tb, criteria) == true)) {
1607 if (members == null)
1608 members = new ArrayList ();
1616 if ((mt & MemberTypes.Constructor) != 0){
1617 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1618 int len = instance_constructors.Count;
1619 for (int i = 0; i < len; i++) {
1620 Constructor c = (Constructor) instance_constructors [i];
1622 ConstructorBuilder cb = c.ConstructorBuilder;
1623 if (cb != null && filter (cb, criteria) == true) {
1624 if (members == null)
1625 members = new ArrayList ();
1632 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1633 ConstructorBuilder cb =
1634 default_static_constructor.ConstructorBuilder;
1636 if (cb != null && filter (cb, criteria) == true) {
1637 if (members == null)
1638 members = new ArrayList ();
1646 // Lookup members in parent if requested.
1648 if ((bf & BindingFlags.DeclaredOnly) == 0) {
1649 if (TypeBuilder.BaseType != null) {
1650 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1651 if (list.Count > 0) {
1652 if (members == null)
1653 members = new ArrayList ();
1655 members.AddRange (list);
1658 if (base_inteface_types != null) {
1659 foreach (Type base_type in base_inteface_types) {
1660 MemberList list = TypeContainer.FindMembers (base_type, mt, bf, filter, criteria);
1662 if (list.Count > 0) {
1663 if (members == null)
1664 members = new ArrayList ();
1665 members.AddRange (list);
1671 Timer.StopTimer (TimerType.TcFindMembers);
1673 if (members == null)
1674 return MemberList.Empty;
1676 return new MemberList (members);
1679 public override MemberCache MemberCache {
1681 return member_cache;
1685 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1686 MemberFilter filter, object criteria)
1688 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1691 return ds.FindMembers (mt, bf, filter, criteria);
1693 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1698 // FindMethods will look for methods not only in the type `t', but in
1699 // any interfaces implemented by the type.
1701 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1702 MemberFilter filter, object criteria)
1708 /// Emits the values for the constants
1710 public void EmitConstants ()
1712 if (constants != null)
1713 foreach (Const con in constants)
1719 /// Emits the code, this step is performed after all
1720 /// the types, enumerations, constructors
1724 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
1728 if (instance_constructors != null) {
1729 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && IsClsCompliaceRequired (this)) {
1730 bool has_compliant_args = false;
1732 foreach (Constructor c in instance_constructors) {
1735 if (has_compliant_args)
1738 has_compliant_args = c.HasCompliantArgs;
1740 if (!has_compliant_args)
1741 Report.Error_T (3015, Location, GetSignatureForError ());
1743 foreach (Constructor c in instance_constructors)
1748 if (default_static_constructor != null)
1749 default_static_constructor.Emit (this);
1751 if (methods != null)
1752 foreach (Method m in methods)
1755 if (operators != null)
1756 foreach (Operator o in operators)
1759 if (properties != null)
1760 foreach (Property p in properties)
1763 if (indexers != null){
1764 foreach (Indexer ix in indexers)
1766 if (IndexerName != null) {
1767 CustomAttributeBuilder cb = EmitDefaultMemberAttr ();
1768 TypeBuilder.SetCustomAttribute (cb);
1773 foreach (Field f in fields)
1776 if (events != null){
1777 foreach (Event e in Events)
1781 if (delegates != null) {
1782 foreach (Delegate d in Delegates) {
1787 if (Pending != null)
1788 if (Pending.VerifyPendingMethods ())
1792 // Check for internal or private fields that were never assigned
1794 if (RootContext.WarningLevel >= 3) {
1795 if (fields != null){
1796 foreach (Field f in fields) {
1797 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
1800 if ((f.status & Field.Status.USED) == 0){
1802 169, f.Location, "Private field " +
1803 MakeName (f.Name) + " is never used");
1808 // Only report 649 on level 4
1810 if (RootContext.WarningLevel < 4)
1813 if ((f.status & Field.Status.ASSIGNED) != 0)
1818 "Field " + MakeName (f.Name) + " is never assigned " +
1819 " to and will always have its default value");
1823 if (events != null){
1824 foreach (Event e in events){
1826 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1831 // if (types != null)
1832 // foreach (TypeContainer tc in types)
1836 CustomAttributeBuilder EmitDefaultMemberAttr ()
1838 EmitContext ec = new EmitContext (this, Location, null, null, ModFlags);
1840 Expression ml = Expression.MemberLookup (ec, TypeManager.default_member_type,
1841 ".ctor", MemberTypes.Constructor,
1842 BindingFlags.Public | BindingFlags.Instance,
1845 MethodGroupExpr mg = (MethodGroupExpr) ml;
1847 MethodBase constructor = mg.Methods [0];
1849 string [] vals = { IndexerName };
1851 CustomAttributeBuilder cb = null;
1853 cb = new CustomAttributeBuilder ((ConstructorInfo) constructor, vals);
1855 Report.Warning (-100, "Can not set the indexer default member attribute");
1861 public override void CloseType ()
1863 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1867 caching_flags |= Flags.CloseTypeCreated;
1868 TypeBuilder.CreateType ();
1869 } catch (TypeLoadException){
1871 // This is fine, the code still created the type
1873 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1874 // Console.WriteLine (e.Message);
1876 Console.WriteLine ("In type: " + Name);
1881 foreach (Enum en in Enums)
1884 if (interface_order != null){
1885 foreach (Interface iface in interface_order)
1890 foreach (TypeContainer tc in Types)
1894 foreach (TypeContainer tc in Types)
1895 if (!(tc is Struct))
1899 if (Delegates != null)
1900 foreach (Delegate d in Delegates)
1908 initialized_fields = null;
1909 initialized_static_fields = null;
1912 interface_order = null;
1918 default_constructor = null;
1919 default_static_constructor = null;
1921 OptAttributes = null;
1923 parent_container = null;
1924 member_cache = null;
1927 public string MakeName (string n)
1929 return "`" + Name + "." + n + "'";
1932 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1935 108, l, "The keyword new is required on " +
1936 MakeName (mi.Name) + " because it hides `" +
1937 mi.ReflectedType.Name + "." + mi.Name + "'");
1940 public void Warning_KeywordNewNotRequired (Location l, MemberCore mc)
1943 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1944 "inherited member, the keyword new is not required");
1947 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
1950 72, l, MakeName (mi.Name) + " : cannot override; `" +
1951 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
1954 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1960 // Performs the validation on a Method's modifiers (properties have
1961 // the same properties).
1963 public bool MethodModifiersValid (int flags, string n, Location loc)
1965 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1966 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1967 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1971 // At most one of static, virtual or override
1973 if ((flags & Modifiers.STATIC) != 0){
1974 if ((flags & vao) != 0){
1976 112, loc, "static method " + MakeName (n) + "can not be marked " +
1977 "as virtual, abstract or override");
1982 if (this is Struct){
1983 if ((flags & va) != 0){
1984 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1989 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1991 113, loc, MakeName (n) +
1992 " marked as override cannot be marked as new or virtual");
1997 // If the declaration includes the abstract modifier, then the
1998 // declaration does not include static, virtual or extern
2000 if ((flags & Modifiers.ABSTRACT) != 0){
2001 if ((flags & Modifiers.EXTERN) != 0){
2003 180, loc, MakeName (n) + " can not be both abstract and extern");
2007 if ((flags & Modifiers.VIRTUAL) != 0){
2009 503, loc, MakeName (n) + " can not be both abstract and virtual");
2013 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2015 513, loc, MakeName (n) +
2016 " is abstract but its container class is not");
2022 if ((flags & Modifiers.PRIVATE) != 0){
2023 if ((flags & vao) != 0){
2025 621, loc, MakeName (n) +
2026 " virtual or abstract members can not be private");
2031 if ((flags & Modifiers.SEALED) != 0){
2032 if ((flags & Modifiers.OVERRIDE) == 0){
2034 238, loc, MakeName (n) +
2035 " cannot be sealed because it is not an override");
2043 Hashtable builder_and_args;
2045 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
2047 if (builder_and_args == null)
2048 builder_and_args = new Hashtable ();
2052 protected override bool VerifyClsCompliance (DeclSpace ds)
2054 if (!base.VerifyClsCompliance (ds))
2057 // parent_container is null for System.Object
2058 if (parent_container != null && !AttributeTester.IsClsCompliant (parent_container.Type)) {
2059 Report.Error_T (3009, Location, GetSignatureForError (), TypeManager.CSharpName (parent_container.Type));
2066 /// Performs checks for an explicit interface implementation. First it
2067 /// checks whether the `interface_type' is a base inteface implementation.
2068 /// Then it checks whether `name' exists in the interface type.
2070 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
2074 if (ifaces != null){
2075 foreach (TypeExpr t in ifaces){
2076 if (t.Type == interface_type){
2084 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
2095 string IMemberContainer.Name {
2101 Type IMemberContainer.Type {
2107 IMemberContainer IMemberContainer.Parent {
2109 return parent_container;
2113 MemberCache IMemberContainer.MemberCache {
2115 return member_cache;
2119 bool IMemberContainer.IsInterface {
2121 return this is Interface;
2125 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2127 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
2131 // Operator pair checking
2134 class OperatorEntry {
2136 public Type ret_type;
2137 public Type type1, type2;
2139 public Operator.OpType ot;
2141 public OperatorEntry (int f, Operator o)
2145 ret_type = o.OperatorMethod.GetReturnType ();
2146 Type [] pt = o.OperatorMethod.ParameterTypes;
2150 ot = o.OperatorType;
2153 public override int GetHashCode ()
2155 return ret_type.GetHashCode ();
2158 public override bool Equals (object o)
2160 OperatorEntry other = (OperatorEntry) o;
2162 if (other.ret_type != ret_type)
2164 if (other.type1 != type1)
2166 if (other.type2 != type2)
2173 // Checks that some operators come in pairs:
2179 // They are matched based on the return type and the argument types
2181 void CheckPairedOperators ()
2183 Hashtable pairs = new Hashtable (null, null);
2184 Operator true_op = null;
2185 Operator false_op = null;
2186 bool has_equality_or_inequality = false;
2188 // Register all the operators we care about.
2189 foreach (Operator op in operators){
2192 switch (op.OperatorType){
2193 case Operator.OpType.Equality:
2195 has_equality_or_inequality = true;
2197 case Operator.OpType.Inequality:
2199 has_equality_or_inequality = true;
2202 case Operator.OpType.True:
2205 case Operator.OpType.False:
2209 case Operator.OpType.GreaterThan:
2211 case Operator.OpType.LessThan:
2214 case Operator.OpType.GreaterThanOrEqual:
2216 case Operator.OpType.LessThanOrEqual:
2222 OperatorEntry oe = new OperatorEntry (reg, op);
2224 object o = pairs [oe];
2228 oe = (OperatorEntry) o;
2233 if (true_op != null){
2234 if (false_op == null)
2235 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2236 } else if (false_op != null)
2237 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2240 // Look for the mistakes.
2242 foreach (DictionaryEntry de in pairs){
2243 OperatorEntry oe = (OperatorEntry) de.Key;
2250 case Operator.OpType.Equality:
2253 case Operator.OpType.Inequality:
2256 case Operator.OpType.GreaterThan:
2259 case Operator.OpType.LessThan:
2262 case Operator.OpType.GreaterThanOrEqual:
2265 case Operator.OpType.LessThanOrEqual:
2269 Report.Error (216, oe.op.Location,
2270 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2273 if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2274 MethodSignature equals_ms = new MethodSignature (
2275 "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2276 MethodSignature hash_ms = new MethodSignature (
2277 "GetHashCode", TypeManager.int32_type, new Type [0]);
2279 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2280 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2282 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2283 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2286 bool equals_ok = false;
2287 if ((equals_ml != null) && (equals_ml.Count == 1))
2288 equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2289 bool hash_ok = false;
2290 if ((hash_ml != null) && (hash_ml.Count == 1))
2291 hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2294 Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2295 "not override Object.Equals (object o)");
2297 Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2298 "not override Object.GetHashCode ()");
2305 public class Class : TypeContainer {
2307 // Modifiers allowed in a class declaration
2309 public const int AllowedModifiers =
2312 Modifiers.PROTECTED |
2313 Modifiers.INTERNAL |
2315 Modifiers.ABSTRACT |
2319 public Class (NamespaceEntry ns, TypeContainer parent, string name, int mod,
2320 Attributes attrs, Location l)
2321 : base (ns, parent, name, attrs, l)
2325 if (parent.Parent == null)
2326 accmods = Modifiers.INTERNAL;
2328 accmods = Modifiers.PRIVATE;
2330 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2334 // FIXME: How do we deal with the user specifying a different
2337 public override TypeAttributes TypeAttr {
2339 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2344 public class Struct : TypeContainer {
2346 // Modifiers allowed in a struct declaration
2348 public const int AllowedModifiers =
2351 Modifiers.PROTECTED |
2352 Modifiers.INTERNAL |
2356 public Struct (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2357 : base (ns, parent, name, attrs, l)
2361 if (parent.Parent == null)
2362 accmods = Modifiers.INTERNAL;
2364 accmods = Modifiers.PRIVATE;
2366 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2368 this.ModFlags |= Modifiers.SEALED;
2372 // FIXME: Allow the user to specify a different set of attributes
2373 // in some cases (Sealed for example is mandatory for a class,
2374 // but what SequentialLayout can be changed
2376 public override TypeAttributes TypeAttr {
2378 return base.TypeAttr |
2379 TypeAttributes.SequentialLayout |
2380 TypeAttributes.Sealed |
2381 TypeAttributes.BeforeFieldInit;
2389 public class Interface : TypeContainer, IMemberContainer {
2391 /// Modifiers allowed in a class declaration
2393 public const int AllowedModifiers =
2396 Modifiers.PROTECTED |
2397 Modifiers.INTERNAL |
2401 public Interface (NamespaceEntry ns, TypeContainer parent, string name, int mod,
2402 Attributes attrs, Location l)
2403 : base (ns, parent, name, attrs, l)
2407 if (parent.Parent == null)
2408 accmods = Modifiers.INTERNAL;
2410 accmods = Modifiers.PRIVATE;
2412 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2415 public override TypeAttributes TypeAttr {
2417 return base.TypeAttr |
2418 TypeAttributes.AutoLayout |
2419 TypeAttributes.Abstract |
2420 TypeAttributes.Interface;
2425 public abstract class MethodCore : MemberBase {
2426 public readonly Parameters Parameters;
2427 protected Block block;
2428 public DeclSpace ds;
2431 // Parameters, cached for semantic analysis.
2433 protected InternalParameters parameter_info;
2434 protected Type [] parameter_types;
2437 // This is set from TypeContainer.DefineMembers if this method overrides something.
2439 public bool OverridesSomething;
2441 // Whether this is an operator method.
2442 public bool IsOperator;
2444 public MethodCore (DeclSpace ds, Expression type, int mod, int allowed_mod,
2445 bool is_interface, string name, Attributes attrs,
2446 Parameters parameters, Location loc)
2447 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
2449 Parameters = parameters;
2450 IsInterface = is_interface;
2455 // Returns the System.Type array for the parameters of this method
2457 public Type [] ParameterTypes {
2459 return parameter_types;
2463 public InternalParameters ParameterInfo
2466 return parameter_info;
2470 public Block Block {
2480 protected virtual bool DoDefineParameters ()
2482 // Check if arguments were correct
2483 parameter_types = Parameters.GetParameterInfo (ds);
2484 if ((parameter_types == null) || !CheckParameters (ds, parameter_types))
2487 parameter_info = new InternalParameters (ds, Parameters);
2489 Parameter array_param = Parameters.ArrayParameter;
2490 if ((array_param != null) &&
2491 (!array_param.ParameterType.IsArray ||
2492 (array_param.ParameterType.GetArrayRank () != 1))) {
2493 Report.Error (225, Location, "params parameter has to be a single dimensional array");
2500 protected override bool VerifyClsCompliance (DeclSpace ds)
2502 if (!base.VerifyClsCompliance (ds)) {
2503 if ((ModFlags & Modifiers.ABSTRACT) != 0 && IsExposedFromAssembly (ds) && ds.IsClsCompliaceRequired (ds)) {
2504 Report.Error_T (3011, Location, GetSignatureForError ());
2509 AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);
2511 if (!AttributeTester.IsClsCompliant (MemberType)) {
2512 Report.Error_T (3002, Location, GetSignatureForError ());
2518 protected bool IsDuplicateImplementation (TypeContainer tc, MethodCore method)
2520 if ((method == this) || (method.Name != Name))
2523 Type[] param_types = method.ParameterTypes;
2524 if (param_types == null)
2527 if (param_types.Length != ParameterTypes.Length)
2530 for (int i = 0; i < param_types.Length; i++)
2531 if (param_types [i] != ParameterTypes [i])
2535 // Try to report 663: method only differs on out/ref
2537 ParameterData info = ParameterInfo;
2538 ParameterData other_info = method.ParameterInfo;
2539 for (int i = 0; i < info.Count; i++){
2540 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
2541 Report.Error (663, Location, "Overload method only differs in parameter modifier");
2546 Report.Error (111, Location, "Class `{0}' already defines a " +
2547 "member called `{1}' with the same parameter types",
2552 public CallingConventions GetCallingConvention (bool is_class)
2554 CallingConventions cc = 0;
2556 cc = Parameters.GetCallingConvention ();
2559 if ((ModFlags & Modifiers.STATIC) == 0)
2560 cc |= CallingConventions.HasThis;
2562 // FIXME: How is `ExplicitThis' used in C#?
2568 // The method's attributes are passed in because we need to extract
2569 // the "return:" attribute from there to apply on the return type
2571 static public void LabelParameters (EmitContext ec,
2573 Parameters parameters,
2574 Attributes method_attrs,
2578 // Define each type attribute (in/out/ref) and
2579 // the argument names.
2581 Parameter [] p = parameters.FixedParameters;
2584 MethodBuilder mb = null;
2585 ConstructorBuilder cb = null;
2587 if (builder is MethodBuilder)
2588 mb = (MethodBuilder) builder;
2590 cb = (ConstructorBuilder) builder;
2593 for (i = 0; i < p.Length; i++) {
2594 ParameterBuilder pb;
2595 ParameterAttributes par_attr = p [i].Attributes;
2598 pb = cb.DefineParameter (
2599 i + 1, par_attr, p [i].Name);
2601 pb = mb.DefineParameter (
2602 i + 1, par_attr, p [i].Name);
2604 Attributes attr = p [i].OptAttributes;
2606 Attribute.ApplyAttributes (ec, pb, pb, attr);
2608 if (par_attr == ParameterAttributes.Out){
2609 if (attr.Contains (TypeManager.in_attribute_type))
2610 Report.Error (36, loc,
2611 "Can not use [In] attribute on out parameter");
2617 if (parameters.ArrayParameter != null){
2618 ParameterBuilder pb;
2619 Parameter array_param = parameters.ArrayParameter;
2622 pb = cb.DefineParameter (
2623 i + 1, array_param.Attributes,
2626 pb = mb.DefineParameter (
2627 i + 1, array_param.Attributes,
2630 CustomAttributeBuilder a = new CustomAttributeBuilder (
2631 TypeManager.cons_param_array_attribute, new object [0]);
2633 pb.SetCustomAttribute (a);
2637 // And now for the return type attribute decoration
2639 ParameterBuilder ret_pb;
2640 Attributes ret_attrs = null;
2642 if (mb == null || method_attrs == null)
2645 foreach (AttributeSection asec in method_attrs.AttributeSections) {
2647 if (asec.Target != "return")
2650 if (ret_attrs == null)
2651 ret_attrs = new Attributes (asec);
2653 ret_attrs.AddAttributeSection (asec);
2656 if (ret_attrs != null) {
2658 ret_pb = mb.DefineParameter (0, ParameterAttributes.None, "");
2659 Attribute.ApplyAttributes (ec, ret_pb, ret_pb, ret_attrs);
2661 } catch (ArgumentOutOfRangeException) {
2664 ".NET SDK 1.0 does not permit setting custom attributes" +
2665 " on the return type of a method");
2671 public class Method : MethodCore, IIteratorContainer, IMethodData {
2672 public MethodBuilder MethodBuilder;
2673 public MethodData MethodData;
2676 /// Modifiers allowed in a class declaration
2678 const int AllowedModifiers =
2681 Modifiers.PROTECTED |
2682 Modifiers.INTERNAL |
2687 Modifiers.OVERRIDE |
2688 Modifiers.ABSTRACT |
2690 Modifiers.METHOD_YIELDS |
2693 const int AllowedInterfaceModifiers =
2697 // return_type can be "null" for VOID values.
2699 public Method (DeclSpace ds, Expression return_type, int mod, bool is_iface,
2700 string name, Parameters parameters, Attributes attrs, Location l)
2701 : base (ds, return_type, mod,
2702 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
2703 is_iface, name, attrs, parameters, l)
2708 // Returns the `System.Type' for the ReturnType of this
2709 // function. Provides a nice cache. (used between semantic analysis
2710 // and actual code generation
2712 public Type GetReturnType ()
2717 public override string GetSignatureForError()
2719 return TypeManager.CSharpSignature (MethodBuilder);
2722 void DuplicateEntryPoint (MethodInfo b, Location location)
2726 "Program `" + CodeGen.FileName +
2727 "' has more than one entry point defined: `" +
2728 TypeManager.CSharpSignature(b) + "'");
2731 void Report28 (MethodInfo b)
2735 "`" + TypeManager.CSharpSignature(b) +
2736 "' has the wrong signature to be an entry point");
2739 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2741 if (b.ReturnType != TypeManager.void_type &&
2742 b.ReturnType != TypeManager.int32_type)
2745 if (pinfo.Count == 0)
2748 if (pinfo.Count > 1)
2751 Type t = pinfo.ParameterType(0);
2753 (t.GetArrayRank() == 1) &&
2754 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
2755 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2762 // Checks our base implementation if any
2764 protected override bool CheckBase (TypeContainer container)
2766 base.CheckBase (container);
2768 // Check whether arguments were correct.
2769 if (!DoDefineParameters ())
2772 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2774 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2777 // Check in our class for dups
2779 ArrayList ar = container.Methods;
2781 int arLen = ar.Count;
2783 for (int i = 0; i < arLen; i++) {
2784 Method m = (Method) ar [i];
2785 if (IsDuplicateImplementation (container, m))
2793 // Verify if the parent has a type with the same name, and then
2794 // check whether we have to create a new slot for it or not.
2796 Type ptype = container.TypeBuilder.BaseType;
2798 // ptype is only null for System.Object while compiling corlib.
2799 if (ptype != null) {
2802 // Explicit implementations do not have `parent' methods, however,
2803 // the member cache stores them there. Without this check, we get
2804 // an incorrect warning in corlib.
2806 if (! IsExplicitImpl) {
2807 parent_method = (MethodInfo)((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
2808 container.TypeBuilder, Name, ParameterTypes, false);
2811 if (parent_method != null) {
2812 string name = parent_method.DeclaringType.Name + "." +
2815 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
2818 if ((ModFlags & Modifiers.NEW) == 0) {
2819 Type parent_ret = TypeManager.TypeToCoreType (
2820 parent_method.ReturnType);
2822 if (parent_ret != MemberType) {
2824 508, Location, container.MakeName (Name) + ": cannot " +
2825 "change return type when overriding " +
2826 "inherited member " + name);
2831 if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
2832 WarningNotHiding (container);
2834 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2835 Report.Error (115, Location,
2836 container.MakeName (Name) +
2837 " no suitable methods found to override");
2840 } else if ((ModFlags & Modifiers.NEW) != 0)
2841 WarningNotHiding (container);
2849 public override bool Define (TypeContainer container)
2851 if (!DoDefine (container))
2854 if (!CheckBase (container))
2857 MethodData = new MethodData (this, ParameterInfo, ModFlags, flags, true, this);
2859 if (!MethodData.Define (container))
2863 // Setup iterator if we are one
2865 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
2866 IteratorHandler ih = new IteratorHandler (
2867 Name, container, MemberType,
2868 ParameterTypes, ParameterInfo,
2869 ModFlags, Location);
2871 Block new_block = ih.Setup (block);
2872 if (new_block == null)
2877 MethodBuilder = MethodData.MethodBuilder;
2880 // This is used to track the Entry Point,
2882 if (Name == "Main" &&
2883 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
2884 (RootContext.MainClass == null ||
2885 RootContext.MainClass == container.TypeBuilder.FullName)){
2886 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2887 if (RootContext.EntryPoint == null) {
2888 RootContext.EntryPoint = MethodBuilder;
2889 RootContext.EntryPointLocation = Location;
2891 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2892 DuplicateEntryPoint (MethodBuilder, Location);
2895 Report28(MethodBuilder);
2904 public override void Emit (TypeContainer container)
2906 MethodData.Emit (container, this);
2907 base.Emit (container);
2912 void IIteratorContainer.SetYields ()
2914 ModFlags |= Modifiers.METHOD_YIELDS;
2917 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
2919 return IsIdentifierAndParamClsCompliant (ds, Name, MethodBuilder, parameter_types);
2922 #region IMethodData Members
2924 public CallingConventions CallingConventions {
2926 CallingConventions cc = Parameters.GetCallingConvention ();
2929 if ((ModFlags & Modifiers.STATIC) == 0)
2930 cc |= CallingConventions.HasThis;
2932 // FIXME: How is `ExplicitThis' used in C#?
2938 public Type ReturnType {
2944 public string MethodName {
2950 public new Location Location {
2952 return base.Location;
2956 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
2958 return new EmitContext (tc, ds, Location, ig, ReturnType, ModFlags, false);
2964 public abstract class ConstructorInitializer {
2965 ArrayList argument_list;
2966 ConstructorInfo parent_constructor;
2967 Parameters parameters;
2970 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2973 this.argument_list = argument_list;
2974 this.parameters = parameters;
2978 public ArrayList Arguments {
2980 return argument_list;
2984 public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
2986 Expression parent_constructor_group;
2989 ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
2991 if (argument_list != null){
2992 foreach (Argument a in argument_list){
2993 if (!a.Resolve (ec, loc))
2997 ec.CurrentBlock = null;
2999 if (this is ConstructorBaseInitializer) {
3000 if (ec.ContainerType.BaseType == null)
3003 t = ec.ContainerType.BaseType;
3004 if (ec.ContainerType.IsValueType) {
3005 Report.Error (522, loc,
3006 "structs cannot call base class constructors");
3010 t = ec.ContainerType;
3012 parent_constructor_group = Expression.MemberLookup (
3013 ec, t, null, t, ".ctor",
3014 MemberTypes.Constructor,
3015 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3018 if (parent_constructor_group == null){
3019 Report.Error (1501, loc,
3020 "Can not find a constructor for this argument list");
3024 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
3025 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
3027 if (parent_constructor == null){
3028 Report.Error (1501, loc,
3029 "Can not find a constructor for this argument list");
3033 if (parent_constructor == caller_builder){
3034 Report.Error (515, String.Format ("Constructor `{0}' can not call itself", TypeManager.CSharpSignature (caller_builder)));
3041 public void Emit (EmitContext ec)
3043 if (parent_constructor != null){
3044 ec.Mark (loc, false);
3046 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
3048 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
3053 public class ConstructorBaseInitializer : ConstructorInitializer {
3054 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
3055 base (argument_list, pars, l)
3060 public class ConstructorThisInitializer : ConstructorInitializer {
3061 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
3062 base (argument_list, pars, l)
3067 public class Constructor : MethodCore {
3068 public ConstructorBuilder ConstructorBuilder;
3069 public ConstructorInitializer Initializer;
3072 // Modifiers allowed for a constructor.
3074 public const int AllowedModifiers =
3076 Modifiers.PROTECTED |
3077 Modifiers.INTERNAL |
3083 bool has_compliant_args = false;
3085 // The spec claims that static is not permitted, but
3086 // my very own code has static constructors.
3088 public Constructor (DeclSpace ds, string name, int mod, Parameters args,
3089 ConstructorInitializer init, Location l)
3090 : base (ds, null, mod, AllowedModifiers, false, name, null, args, l)
3095 public override string GetSignatureForError()
3097 return TypeManager.CSharpSignature (ConstructorBuilder);
3100 public bool HasCompliantArgs {
3102 return has_compliant_args;
3107 // Returns true if this is a default constructor
3109 public bool IsDefault ()
3111 if ((ModFlags & Modifiers.STATIC) != 0)
3112 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3113 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
3116 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3117 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
3118 (Initializer is ConstructorBaseInitializer) &&
3119 (Initializer.Arguments == null);
3122 protected override bool CheckBase (TypeContainer container)
3124 base.CheckBase (container);
3126 // Check whether arguments were correct.
3127 if (!DoDefineParameters ())
3130 if ((ModFlags & Modifiers.STATIC) != 0)
3133 if (container is Struct && ParameterTypes.Length == 0) {
3134 Report.Error (568, Location,
3135 "Structs can not contain explicit parameterless " +
3141 // Check in our class for dups
3143 ArrayList ar = container.InstanceConstructors;
3145 int arLen = ar.Count;
3147 for (int i = 0; i < arLen; i++) {
3148 Constructor m = (Constructor) ar [i];
3149 if (IsDuplicateImplementation (container, m))
3158 // Creates the ConstructorBuilder
3160 public override bool Define (TypeContainer container)
3162 MethodAttributes ca = (MethodAttributes.RTSpecialName |
3163 MethodAttributes.SpecialName);
3165 if ((ModFlags & Modifiers.STATIC) != 0) {
3166 ca |= MethodAttributes.Static | MethodAttributes.Private;
3168 ca |= MethodAttributes.HideBySig;
3170 if ((ModFlags & Modifiers.PUBLIC) != 0)
3171 ca |= MethodAttributes.Public;
3172 else if ((ModFlags & Modifiers.PROTECTED) != 0){
3173 if ((ModFlags & Modifiers.INTERNAL) != 0)
3174 ca |= MethodAttributes.FamORAssem;
3176 ca |= MethodAttributes.Family;
3177 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
3178 ca |= MethodAttributes.Assembly;
3179 else if (IsDefault ())
3180 ca |= MethodAttributes.Public;
3182 ca |= MethodAttributes.Private;
3185 // Check if arguments were correct.
3186 if (!CheckBase (container))
3189 ConstructorBuilder = container.TypeBuilder.DefineConstructor (
3190 ca, GetCallingConvention (container is Class), ParameterTypes);
3192 if ((ModFlags & Modifiers.UNSAFE) != 0)
3193 ConstructorBuilder.InitLocals = false;
3196 // HACK because System.Reflection.Emit is lame
3198 TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
3206 public override void Emit (TypeContainer container)
3208 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
3209 EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
3212 // extern methods have no bodies
3214 if ((ModFlags & Modifiers.EXTERN) != 0) {
3215 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
3217 179, Location, "External constructor `" +
3218 TypeManager.CSharpSignature (ConstructorBuilder) +
3219 "' can not have a body");
3222 } else if (block == null) {
3224 501, Location, "Constructor `" +
3225 TypeManager.CSharpSignature (ConstructorBuilder) +
3226 "' must declare a body since it is not marked extern");
3230 if ((ModFlags & Modifiers.STATIC) == 0){
3231 if (container is Class && Initializer == null)
3232 Initializer = new ConstructorBaseInitializer (
3233 null, Parameters.EmptyReadOnlyParameters, Location);
3237 // Spec mandates that Initializers will not have
3241 if (Initializer != null && !Initializer.Resolve (ConstructorBuilder, ec))
3243 ec.IsStatic = false;
3246 MethodCore.LabelParameters (ec, ConstructorBuilder,
3247 Parameters, OptAttributes, Location);
3249 SymbolWriter sw = CodeGen.SymbolWriter;
3250 bool generate_debugging = false;
3252 if ((sw != null) && (block != null) &&
3253 !Location.IsNull (Location) &&
3254 !Location.IsNull (block.EndLocation) &&
3255 (Location.SymbolDocument != null)) {
3256 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
3258 generate_debugging = true;
3262 // Classes can have base initializers and instance field initializers.
3264 if (container is Class){
3265 if ((ModFlags & Modifiers.STATIC) == 0){
3268 // If we use a "this (...)" constructor initializer, then
3269 // do not emit field initializers, they are initialized in the other constructor
3271 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
3272 container.EmitFieldInitializers (ec);
3275 if (Initializer != null)
3276 Initializer.Emit (ec);
3278 if ((ModFlags & Modifiers.STATIC) != 0)
3279 container.EmitFieldInitializers (ec);
3281 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes);
3283 // If this is a non-static `struct' constructor and doesn't have any
3284 // initializer, it must initialize all of the struct's fields.
3285 if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
3286 Block.AddThisVariable (container, Location);
3288 ec.EmitTopBlock (block, ParameterInfo, Location);
3290 if (generate_debugging)
3293 base.Emit (container);
3298 // For constructors is needed to test only parameters
3299 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
3301 if (parameter_types == null || parameter_types.Length == 0)
3304 TypeContainer tc = ds as TypeContainer;
3306 for (int i = 0; i < tc.InstanceConstructors.Count; i++) {
3307 Constructor c = (Constructor) tc.InstanceConstructors [i];
3309 if (c == this || c.ParameterTypes.Length == 0)
3312 if (!c.IsClsCompliaceRequired (ds))
3315 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, c.ParameterTypes)) {
3316 Report.Error_T (3006, Location, GetSignatureForError ());
3321 if (tc.TypeBuilder.BaseType == null)
3324 DeclSpace temp_ds = TypeManager.LookupDeclSpace (tc.TypeBuilder.BaseType);
3325 if (temp_ds != null)
3326 return IsIdentifierClsCompliant (temp_ds);
3328 MemberInfo[] ml = tc.TypeBuilder.BaseType.FindMembers (MemberTypes.Constructor, BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance, null, null);
3329 // Skip parameter-less ctor
3333 foreach (ConstructorInfo ci in ml) {
3334 object[] cls_attribute = ci.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
3335 if (cls_attribute.Length == 1 && (!((CLSCompliantAttribute)cls_attribute[0]).IsCompliant))
3338 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, TypeManager.GetArgumentTypes (ci))) {
3339 Report.Error_T (3006, Location, GetSignatureForError ());
3347 protected override bool VerifyClsCompliance (DeclSpace ds)
3349 if (!base.VerifyClsCompliance (ds)) {
3353 if (ds.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
3354 foreach (Type param in parameter_types) {
3355 if (param.IsArray) {
3360 has_compliant_args = true;
3367 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
3369 public interface IMethodData
3371 CallingConventions CallingConventions { get; }
3372 Location Location { get; }
3373 string MethodName { get; }
3374 Type[] ParameterTypes { get; }
3375 Type ReturnType { get; }
3377 Attributes OptAttributes { get; }
3378 Block Block { get; }
3380 EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig);
3384 // Encapsulates most of the Method's state
3386 public class MethodData {
3388 readonly IMethodData method;
3391 // The return type of this method
3393 public readonly InternalParameters ParameterInfo;
3396 // Are we implementing an interface ?
3398 public bool IsImplementing = false;
3403 protected MemberBase member;
3404 protected int modifiers;
3405 protected MethodAttributes flags;
3406 protected bool is_method;
3409 // It can either hold a string with the condition, or an arraylist of conditions.
3410 object conditionals;
3412 MethodBuilder builder = null;
3413 public MethodBuilder MethodBuilder {
3419 public MethodData (MemberBase member, InternalParameters parameters,
3420 int modifiers, MethodAttributes flags, bool is_method, IMethodData method)
3422 this.member = member;
3423 this.ParameterInfo = parameters;
3424 this.modifiers = modifiers;
3426 this.is_method = is_method;
3427 this.conditionals = null;
3429 this.method = method;
3435 Attribute dllimport_attribute = null;
3436 string obsolete = null;
3437 bool obsolete_error = false;
3439 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
3441 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
3444 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
3445 if (asec.Attributes == null)
3448 foreach (Attribute a in asec.Attributes) {
3449 if (a.Name == "Conditional") {
3450 if (!ApplyConditionalAttribute (a))
3452 } else if (a.Name == "Obsolete") {
3453 if (!ApplyObsoleteAttribute (a))
3455 } else if (a.Name.IndexOf ("DllImport") != -1) {
3457 a.Type = TypeManager.dllimport_type;
3458 Attribute.Error_AttributeNotValidForElement (a, method.Location);
3461 if (!ApplyDllImportAttribute (a))
3471 // Applies the `DllImport' attribute to the method.
3473 protected virtual bool ApplyDllImportAttribute (Attribute a)
3475 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3476 if ((modifiers & extern_static) != extern_static) {
3477 Report.Error (601, method.Location,
3478 "The DllImport attribute must be specified on a method " +
3479 "marked `static' and `extern'.");
3483 flags |= MethodAttributes.PinvokeImpl;
3484 dllimport_attribute = a;
3489 // Applies the `Obsolete' attribute to the method.
3491 protected virtual bool ApplyObsoleteAttribute (Attribute a)
3493 if (obsolete != null) {
3494 Report.Error (579, method.Location, "Duplicate `Obsolete' attribute");
3498 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
3499 return obsolete != null;
3503 // Applies the `Conditional' attribute to the method.
3505 protected virtual bool ApplyConditionalAttribute (Attribute a)
3507 // The Conditional attribute is only valid on methods.
3509 Attribute.Error_AttributeNotValidForElement (a, method.Location);
3513 string condition = a.Conditional_GetConditionName ();
3515 if (condition == null)
3518 if (method.ReturnType != TypeManager.void_type) {
3519 Report.Error (578, method.Location,
3520 "Conditional not valid on `" + member.Name + "' " +
3521 "because its return type is not void");
3525 if ((modifiers & Modifiers.OVERRIDE) != 0) {
3526 Report.Error (243, method.Location,
3527 "Conditional not valid on `" + member.Name + "' " +
3528 "because it is an override method");
3532 if (member.IsExplicitImpl) {
3533 Report.Error (577, method.Location,
3534 "Conditional not valid on `" + member.Name + "' " +
3535 "because it is an explicit interface implementation");
3539 if (IsImplementing) {
3540 Report.Error (623, method.Location,
3541 "Conditional not valid on `" + member.Name + "' " +
3542 "because it is an interface method");
3547 // The likelyhood that the conditional will be more than 1 is very slim
3549 if (conditionals == null)
3550 conditionals = condition;
3551 else if (conditionals is string){
3552 string s = (string) conditionals;
3553 conditionals = new ArrayList ();
3554 ((ArrayList)conditionals).Add (s);
3556 ((ArrayList)conditionals).Add (condition);
3562 // Checks whether this method should be ignored due to its Conditional attributes.
3564 bool ShouldIgnore (Location loc)
3566 // When we're overriding a virtual method, we implicitly inherit the
3567 // Conditional attributes from our parent.
3568 if (member.ParentMethod != null) {
3569 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3570 member.ParentMethod, loc);
3572 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3576 if (conditionals != null){
3577 if (conditionals is string){
3578 if (RootContext.AllDefines [conditionals] == null)
3581 foreach (string condition in (ArrayList) conditionals)
3582 if (RootContext.AllDefines [condition] == null)
3590 // Returns the TypeManager.MethodFlags for this method.
3591 // This emits an error 619 / warning 618 if the method is obsolete.
3592 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3594 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3596 TypeManager.MethodFlags flags = 0;
3598 if (obsolete != null) {
3599 if (obsolete_error) {
3600 Report.Error (619, loc, "Method `" + member.Name +
3601 "' is obsolete: `" + obsolete + "'");
3602 return TypeManager.MethodFlags.IsObsoleteError;
3604 Report.Warning (618, loc, "Method `" + member.Name +
3605 "' is obsolete: `" + obsolete + "'");
3607 flags |= TypeManager.MethodFlags.IsObsolete;
3610 if (ShouldIgnore (loc))
3611 flags |= TypeManager.MethodFlags.ShouldIgnore;
3616 public bool Define (TypeContainer container)
3618 MethodInfo implementing = null;
3621 if (method.OptAttributes != null)
3622 if (!ApplyAttributes (method.OptAttributes, is_method))
3625 if (member.IsExplicitImpl)
3626 prefix = member.InterfaceType.FullName + ".";
3630 string name = method.MethodName;
3631 string method_name = prefix + name;
3632 Type[] ParameterTypes = method.ParameterTypes;
3634 if (container.Pending != null){
3635 if (member is Indexer)
3636 implementing = container.Pending.IsInterfaceIndexer (
3637 member.InterfaceType, method.ReturnType, ParameterTypes);
3639 implementing = container.Pending.IsInterfaceMethod (
3640 member.InterfaceType, name, method.ReturnType, ParameterTypes);
3642 if (member.InterfaceType != null && implementing == null){
3643 Report.Error (539, method.Location, "'{0}' in explicit interface declaration is not an interface", method_name);
3649 // For implicit implementations, make sure we are public, for
3650 // explicit implementations, make sure we are private.
3652 if (implementing != null){
3654 // Setting null inside this block will trigger a more
3655 // verbose error reporting for missing interface implementations
3657 // The "candidate" function has been flagged already
3658 // but it wont get cleared
3660 if (member.IsExplicitImpl){
3661 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3662 Modifiers.Error_InvalidModifier (method.Location, "public, virtual or abstract");
3663 implementing = null;
3665 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
3666 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
3668 // If this is an interface method implementation,
3669 // check for public accessibility
3671 implementing = null;
3672 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
3673 // We may never be private.
3674 implementing = null;
3675 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
3677 // We may be protected if we're overriding something.
3679 implementing = null;
3684 // Static is not allowed
3686 if ((modifiers & Modifiers.STATIC) != 0){
3687 implementing = null;
3688 Modifiers.Error_InvalidModifier (method.Location, "static");
3693 // If implementing is still valid, set flags
3695 if (implementing != null){
3697 // When implementing interface methods, set NewSlot
3698 // unless, we are overwriting a method.
3700 if (implementing.DeclaringType.IsInterface){
3701 if ((modifiers & Modifiers.OVERRIDE) == 0)
3702 flags |= MethodAttributes.NewSlot;
3705 MethodAttributes.Virtual |
3706 MethodAttributes.HideBySig;
3708 // Set Final unless we're virtual, abstract or already overriding a method.
3709 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
3710 flags |= MethodAttributes.Final;
3712 // Get the method name from the explicit interface.
3713 if (member.InterfaceType != null) {
3714 name = implementing.Name;
3715 method_name = prefix + name;
3718 IsImplementing = true;
3722 // Create the MethodBuilder for the method
3724 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3725 if ((modifiers & Modifiers.STATIC) == 0) {
3726 Report.Error (601, method.Location,
3727 "The DllImport attribute must be specified on " +
3728 "a method marked 'static' and 'extern'.");
3732 EmitContext ec = method.CreateEmitContext (container, null);
3734 builder = dllimport_attribute.DefinePInvokeMethod (
3735 ec, container.TypeBuilder, method_name, flags,
3736 method.ReturnType, ParameterTypes);
3738 builder = container.TypeBuilder.DefineMethod (
3739 method_name, flags, method.CallingConventions,
3740 method.ReturnType, ParameterTypes);
3742 if (builder == null)
3745 if ((modifiers & Modifiers.UNSAFE) != 0)
3746 builder.InitLocals = false;
3748 if (IsImplementing){
3750 // clear the pending implemntation flag
3752 if (member is Indexer) {
3753 container.Pending.ImplementIndexer (
3754 member.InterfaceType, builder, method.ReturnType,
3755 ParameterTypes, true);
3757 container.Pending.ImplementMethod (
3758 member.InterfaceType, name, method.ReturnType,
3759 ParameterTypes, member.IsExplicitImpl);
3761 if (member.IsExplicitImpl)
3762 container.TypeBuilder.DefineMethodOverride (
3763 builder, implementing);
3767 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3768 Report.Error (111, method.Location,
3769 "Class `" + container.Name +
3770 "' already contains a definition with the " +
3771 "same return value and parameter types as the " +
3772 "'get' method of property `" + member.Name + "'");
3776 TypeManager.AddMethod (builder, this);
3784 public void Emit (TypeContainer container, object kind)
3788 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3789 ec = method.CreateEmitContext (container, builder.GetILGenerator ());
3791 ec = method.CreateEmitContext (container, null);
3793 Location loc = method.Location;
3794 Attributes OptAttributes = method.OptAttributes;
3796 if (OptAttributes != null)
3797 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes);
3799 if (member is MethodCore)
3800 MethodCore.LabelParameters (ec, MethodBuilder,
3801 ((MethodCore) member).Parameters,
3805 SymbolWriter sw = CodeGen.SymbolWriter;
3806 Block block = method.Block;
3809 // abstract or extern methods have no bodies
3811 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3812 if (block == null) {
3813 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0) &&
3814 !Location.IsNull (loc) &&
3815 (method.Location.SymbolDocument != null)) {
3816 sw.OpenMethod (container, MethodBuilder, loc, loc);
3824 // abstract or extern methods have no bodies.
3826 if ((modifiers & Modifiers.ABSTRACT) != 0)
3828 500, method.Location, "Abstract method `" +
3829 TypeManager.CSharpSignature (builder) +
3830 "' can not have a body");
3832 if ((modifiers & Modifiers.EXTERN) != 0)
3834 179, method.Location, "External method `" +
3835 TypeManager.CSharpSignature (builder) +
3836 "' can not have a body");
3842 // Methods must have a body unless they're extern or abstract
3844 if (block == null) {
3846 501, method.Location, "Method `" +
3847 TypeManager.CSharpSignature (builder) +
3848 "' must declare a body since it is not marked " +
3849 "abstract or extern");
3854 // Handle destructors specially
3856 // FIXME: This code generates buggy code
3858 if ((sw != null) && !Location.IsNull (loc) &&
3859 !Location.IsNull (block.EndLocation) &&
3860 (loc.SymbolDocument != null)) {
3861 sw.OpenMethod (container, MethodBuilder, loc, block.EndLocation);
3863 if (member is Destructor)
3864 EmitDestructor (ec, block);
3866 ec.EmitTopBlock (block, ParameterInfo, loc);
3870 if (member is Destructor)
3871 EmitDestructor (ec, block);
3873 ec.EmitTopBlock (block, ParameterInfo, loc);
3877 void EmitDestructor (EmitContext ec, Block block)
3879 ILGenerator ig = ec.ig;
3881 Label finish = ig.DefineLabel ();
3883 block.SetDestructor ();
3885 ig.BeginExceptionBlock ();
3886 ec.ReturnLabel = finish;
3887 ec.HasReturnLabel = true;
3888 ec.EmitTopBlock (block, null, method.Location);
3890 // ig.MarkLabel (finish);
3891 ig.BeginFinallyBlock ();
3893 if (ec.ContainerType.BaseType != null) {
3894 Expression member_lookup = Expression.MemberLookup (
3895 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3896 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
3898 if (member_lookup != null){
3899 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3901 ig.Emit (OpCodes.Ldarg_0);
3902 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3906 ig.EndExceptionBlock ();
3907 //ig.MarkLabel (ec.ReturnLabel);
3908 ig.Emit (OpCodes.Ret);
3912 public class Destructor : Method {
3914 public Destructor (DeclSpace ds, Expression return_type, int mod, string name,
3915 Parameters parameters, Attributes attrs, Location l)
3916 : base (ds, return_type, mod, false, name, parameters, attrs, l)
3921 abstract public class MemberBase : MemberCore {
3922 public Expression Type;
3924 public MethodAttributes flags;
3926 protected readonly int explicit_mod_flags;
3929 // The "short" name of this property / indexer / event. This is the
3930 // name without the explicit interface.
3932 public string ShortName;
3935 // The type of this property / indexer / event
3937 public Type MemberType;
3940 // If true, this is an explicit interface implementation
3942 public bool IsExplicitImpl = false;
3945 // The name of the interface we are explicitly implementing
3947 public string ExplicitInterfaceName = null;
3950 // Whether this is an interface member.
3952 public bool IsInterface;
3955 // If true, the interface type we are explicitly implementing
3957 public Type InterfaceType = null;
3960 // The method we're overriding if this is an override method.
3962 protected MethodInfo parent_method = null;
3963 public MethodInfo ParentMethod {
3965 return parent_method;
3970 // The constructor is only exposed to our children
3972 protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod, string name,
3973 Attributes attrs, Location loc)
3974 : base (name, attrs, loc)
3976 explicit_mod_flags = mod;
3978 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
3981 protected virtual bool CheckBase (TypeContainer container)
3983 if ((container is Struct) || (RootContext.WarningLevel > 3)){
3984 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
3985 if (container is Struct){
3986 Report.Error (666, Location, "Protected member in struct declaration");
3989 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
3995 protected void WarningNotHiding (TypeContainer parent)
3999 "The member " + parent.MakeName (Name) + " does not hide an " +
4000 "inherited member. The keyword new is not required");
4004 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
4008 // FIXME: report the old/new permissions?
4011 507, Location, parent.MakeName (Name) +
4012 ": can't change the access modifiers when overriding inherited " +
4013 "member `" + name + "'");
4017 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
4018 // that have been defined.
4020 // `name' is the user visible name for reporting errors (this is used to
4021 // provide the right name regarding method names and properties)
4023 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
4024 MethodInfo mb, string name)
4028 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4029 if (!(mb.IsAbstract || mb.IsVirtual)){
4031 506, Location, parent.MakeName (Name) +
4032 ": cannot override inherited member `" +
4033 name + "' because it is not " +
4034 "virtual, abstract or override");
4038 // Now we check that the overriden method is not final
4041 // This happens when implementing interface methods.
4042 if (mb.IsHideBySig && mb.IsVirtual) {
4044 506, Location, parent.MakeName (Name) +
4045 ": cannot override inherited member `" +
4046 name + "' because it is not " +
4047 "virtual, abstract or override");
4049 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
4050 "override inherited member `" + name +
4051 "' because it is sealed.");
4055 // Check that the permissions are not being changed
4057 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
4058 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
4061 // special case for "protected internal"
4064 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4066 // when overriding protected internal, the method can be declared
4067 // protected internal only within the same assembly
4070 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4071 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
4073 // assemblies differ - report an error
4076 Error_CannotChangeAccessModifiers (parent, mb, name);
4078 } else if (thisp != parentp) {
4080 // same assembly, but other attributes differ - report an error
4083 Error_CannotChangeAccessModifiers (parent, mb, name);
4086 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
4088 // if it's not "protected internal", it must be "protected"
4091 Error_CannotChangeAccessModifiers (parent, mb, name);
4093 } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
4095 // protected within the same assembly - an error
4097 Error_CannotChangeAccessModifiers (parent, mb, name);
4099 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
4100 (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
4102 // protected ok, but other attributes differ - report an error
4104 Error_CannotChangeAccessModifiers (parent, mb, name);
4108 if (thisp != parentp){
4109 Error_CannotChangeAccessModifiers (parent, mb, name);
4115 if (mb.IsVirtual || mb.IsAbstract){
4116 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4117 if (Name != "Finalize"){
4119 114, 2, Location, parent.MakeName (Name) +
4120 " hides inherited member `" + name +
4121 "'. To make the current member override that " +
4122 "implementation, add the override keyword, " +
4123 "otherwise use the new keyword");
4124 ModFlags |= Modifiers.NEW;
4128 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4129 if (Name != "Finalize"){
4131 108, 1, Location, "The keyword new is required on " +
4132 parent.MakeName (Name) + " because it hides " +
4133 "inherited member `" + name + "'");
4134 ModFlags |= Modifiers.NEW;
4142 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
4146 foreach (Type partype in parameters){
4147 if (partype == TypeManager.void_type) {
4149 1547, Location, "Keyword 'void' cannot " +
4150 "be used in this context");
4154 if (partype.IsPointer){
4157 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
4161 if (ds.AsAccessible (partype, ModFlags))
4164 if (this is Indexer)
4165 Report.Error (55, Location,
4166 "Inconsistent accessibility: parameter type `" +
4167 TypeManager.CSharpName (partype) + "' is less " +
4168 "accessible than indexer `" + Name + "'");
4169 else if ((this is Method) && ((Method) this).IsOperator)
4170 Report.Error (57, Location,
4171 "Inconsistent accessibility: parameter type `" +
4172 TypeManager.CSharpName (partype) + "' is less " +
4173 "accessible than operator `" + Name + "'");
4175 Report.Error (51, Location,
4176 "Inconsistent accessibility: parameter type `" +
4177 TypeManager.CSharpName (partype) + "' is less " +
4178 "accessible than method `" + Name + "'");
4185 protected virtual bool DoDefine (TypeContainer container)
4191 ModFlags = Modifiers.PUBLIC |
4192 Modifiers.ABSTRACT |
4195 flags = MethodAttributes.Public |
4196 MethodAttributes.Abstract |
4197 MethodAttributes.HideBySig |
4198 MethodAttributes.NewSlot |
4199 MethodAttributes.Virtual;
4201 if (!container.MethodModifiersValid (ModFlags, Name, Location))
4204 flags = Modifiers.MethodAttr (ModFlags);
4207 // Lookup Type, verify validity
4208 MemberType = container.ResolveType (Type, false, Location);
4209 if (MemberType == null)
4212 if ((container.ModFlags & Modifiers.SEALED) != 0){
4213 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
4214 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
4219 // verify accessibility
4220 if (!container.AsAccessible (MemberType, ModFlags)) {
4221 if (this is Property)
4222 Report.Error (53, Location,
4223 "Inconsistent accessibility: property type `" +
4224 TypeManager.CSharpName (MemberType) + "' is less " +
4225 "accessible than property `" + Name + "'");
4226 else if (this is Indexer)
4227 Report.Error (54, Location,
4228 "Inconsistent accessibility: indexer return type `" +
4229 TypeManager.CSharpName (MemberType) + "' is less " +
4230 "accessible than indexer `" + Name + "'");
4231 else if (this is Method) {
4232 if (((Method) this).IsOperator)
4233 Report.Error (56, Location,
4234 "Inconsistent accessibility: return type `" +
4235 TypeManager.CSharpName (MemberType) + "' is less " +
4236 "accessible than operator `" + Name + "'");
4238 Report.Error (50, Location,
4239 "Inconsistent accessibility: return type `" +
4240 TypeManager.CSharpName (MemberType) + "' is less " +
4241 "accessible than method `" + Name + "'");
4243 Report.Error (52, Location,
4244 "Inconsistent accessibility: field type `" +
4245 TypeManager.CSharpName (MemberType) + "' is less " +
4246 "accessible than field `" + Name + "'");
4250 if (MemberType.IsPointer && !UnsafeOK (container))
4254 // Check for explicit interface implementation
4256 if ((ExplicitInterfaceName == null) && (Name.IndexOf ('.') != -1)){
4257 int pos = Name.LastIndexOf ('.');
4259 ExplicitInterfaceName = Name.Substring (0, pos);
4260 ShortName = Name.Substring (pos + 1);
4264 if (ExplicitInterfaceName != null) {
4265 InterfaceType = RootContext.LookupType (
4266 container, ExplicitInterfaceName, false, Location);
4267 if (InterfaceType == null)
4270 if (InterfaceType.IsClass) {
4271 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
4275 // Compute the full name that we need to export.
4276 Name = InterfaceType.FullName + "." + ShortName;
4278 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
4281 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
4283 IsExplicitImpl = true;
4285 IsExplicitImpl = false;
4290 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
4292 return IsIdentifierAndParamClsCompliant (ds, Name, null, null);
4295 protected override bool VerifyClsCompliance(DeclSpace ds)
4297 if (base.VerifyClsCompliance (ds)) {
4301 if (IsInterface && HasClsCompliantAttribute (ds) && ds.IsClsCompliaceRequired (ds)) {
4302 Report.Error_T (3010, Location, GetSignatureForError ());
4311 // Fields and Events both generate FieldBuilders, we use this to share
4312 // their common bits. This is also used to flag usage of the field
4314 abstract public class FieldBase : MemberBase {
4315 public FieldBuilder FieldBuilder;
4316 public Status status;
4319 public enum Status : byte { ASSIGNED = 1, USED = 2 }
4322 // The constructor is only exposed to our children
4324 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
4325 object init, Attributes attrs, Location loc)
4326 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
4332 // Whether this field has an initializer.
4334 public bool HasInitializer {
4336 return init != null;
4340 protected readonly Object init;
4342 Expression init_expr;
4343 bool init_expr_initialized = false;
4346 // Resolves and returns the field initializer.
4348 public Expression GetInitializerExpression (EmitContext ec)
4350 if (init_expr_initialized)
4354 if (init is Expression)
4355 e = (Expression) init;
4357 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
4359 ec.IsFieldInitializer = true;
4360 e = e.DoResolve (ec);
4361 ec.IsFieldInitializer = false;
4364 init_expr_initialized = true;
4369 protected override bool DoDefine (TypeContainer container)
4371 if (!base.DoDefine (container))
4374 if (MemberType == TypeManager.void_type) {
4375 Report.Error (1547, Location,
4376 "Keyword 'void' cannot be used in this context");
4383 public override string GetSignatureForError ()
4385 return TypeManager.GetFullNameSignature (FieldBuilder);
4388 protected override bool VerifyClsCompliance (DeclSpace ds)
4390 if (!base.VerifyClsCompliance (ds))
4393 if (FieldBuilder == null) {
4397 if (!AttributeTester.IsClsCompliant (FieldBuilder.FieldType)) {
4398 Report.Error_T (3003, Location, GetSignatureForError ());
4404 public void SetAssigned ()
4406 status |= Status.ASSIGNED;
4411 // The Field class is used to represents class/struct fields during parsing.
4413 public class Field : FieldBase {
4415 // Modifiers allowed in a class declaration
4417 const int AllowedModifiers =
4420 Modifiers.PROTECTED |
4421 Modifiers.INTERNAL |
4424 Modifiers.VOLATILE |
4428 public Field (Expression type, int mod, string name, Object expr_or_array_init,
4429 Attributes attrs, Location loc)
4430 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
4434 public override bool Define (TypeContainer container)
4436 Type t = container.ResolveType (Type, false, Location);
4441 CheckBase (container);
4443 if (!container.AsAccessible (t, ModFlags)) {
4444 Report.Error (52, Location,
4445 "Inconsistent accessibility: field type `" +
4446 TypeManager.CSharpName (t) + "' is less " +
4447 "accessible than field `" + Name + "'");
4451 if (t.IsPointer && !UnsafeOK (container))
4454 if (RootContext.WarningLevel > 1){
4455 Type ptype = container.TypeBuilder.BaseType;
4457 // ptype is only null for System.Object while compiling corlib.
4459 TypeContainer.FindMembers (
4460 ptype, MemberTypes.Method,
4461 BindingFlags.Public |
4462 BindingFlags.Static | BindingFlags.Instance,
4463 System.Type.FilterName, Name);
4467 if ((ModFlags & Modifiers.VOLATILE) != 0){
4471 if (TypeManager.IsEnumType (vt))
4472 vt = TypeManager.EnumToUnderlying (t);
4474 if (!((vt == TypeManager.bool_type) ||
4475 (vt == TypeManager.sbyte_type) ||
4476 (vt == TypeManager.byte_type) ||
4477 (vt == TypeManager.short_type) ||
4478 (vt == TypeManager.ushort_type) ||
4479 (vt == TypeManager.int32_type) ||
4480 (vt == TypeManager.uint32_type) ||
4481 (vt == TypeManager.char_type) ||
4482 (vt == TypeManager.float_type))){
4484 677, Location, container.MakeName (Name) +
4485 " A volatile field can not be of type `" +
4486 TypeManager.CSharpName (vt) + "'");
4491 if ((ModFlags & Modifiers.READONLY) != 0){
4494 "A field can not be both volatile and readonly");
4499 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
4501 if (container is Struct &&
4502 ((fa & FieldAttributes.Static) == 0) &&
4503 t == container.TypeBuilder &&
4504 !TypeManager.IsBuiltinType (t)){
4505 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name +
4506 "' causes a cycle in the structure layout");
4511 FieldBuilder = container.TypeBuilder.DefineField (
4512 Name, t, Modifiers.FieldAttr (ModFlags));
4514 TypeManager.RegisterFieldBase (FieldBuilder, this);
4516 catch (ArgumentException) {
4517 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
4524 public override void Emit (TypeContainer tc)
4526 if (OptAttributes != null) {
4527 EmitContext ec = new EmitContext (tc, Location, null, FieldBuilder.FieldType, ModFlags);
4528 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes);
4536 // `set' and `get' accessors are represented with an Accessor.
4538 public class Accessor {
4540 // Null if the accessor is empty, or a Block if not
4543 public Attributes OptAttributes;
4545 public Accessor (Block b, Attributes attrs)
4548 OptAttributes = attrs;
4553 // Properties and Indexers both generate PropertyBuilders, we use this to share
4554 // their common bits.
4556 abstract public class PropertyBase : MethodCore {
4558 public class GetMethod: PropertyMethod
4560 public GetMethod (MethodCore method, Accessor accessor):
4561 base (method, accessor)
4565 public override MethodBuilder Define(TypeContainer container)
4567 method_data = new MethodData (method, method.ParameterInfo, method.ModFlags, method.flags, false, this);
4569 if (!method_data.Define (container))
4572 return method_data.MethodBuilder;
4575 public override string MethodName {
4577 return "get_" + method.ShortName;
4581 public override Type ReturnType {
4583 return method.MemberType;
4588 public class SetMethod: PropertyMethod {
4589 public SetMethod (MethodCore method, Accessor accessor):
4590 base (method, accessor)
4594 protected virtual InternalParameters GetParameterInfo (TypeContainer container)
4596 Parameter [] parms = new Parameter [1];
4597 parms [0] = new Parameter (method.Type, "value", Parameter.Modifier.NONE, null);
4598 return new InternalParameters (
4599 container, new Parameters (parms, null, method.Location));
4602 public override MethodBuilder Define(TypeContainer container)
4604 method_data = new MethodData (method, GetParameterInfo (container), method.ModFlags, method.flags, false, this);
4606 if (!method_data.Define (container))
4609 return method_data.MethodBuilder;
4612 public override string MethodName {
4614 return "set_" + method.ShortName;
4618 public override Type[] ParameterTypes {
4620 return new Type[] { method.MemberType };
4624 public override Type ReturnType {
4626 return TypeManager.void_type;
4632 public abstract class PropertyMethod: IMethodData {
4633 protected readonly MethodCore method;
4634 public readonly Accessor Accessor;
4635 protected MethodData method_data;
4637 public PropertyMethod (MethodCore method, Accessor accessor)
4639 this.method = method;
4640 this.Accessor = accessor;
4643 public InternalParameters ParameterInfo {
4645 return method_data.ParameterInfo;
4649 #region IMethodData Members
4651 public Block Block {
4653 return Accessor.Block;
4657 public CallingConventions CallingConventions {
4659 return CallingConventions.Standard;
4663 public abstract MethodBuilder Define (TypeContainer container);
4665 public void Emit (TypeContainer container)
4667 method_data.Emit (container, Accessor);
4668 Accessor.Block = null;
4671 public Attributes OptAttributes {
4673 return Accessor.OptAttributes;
4677 public virtual Type[] ParameterTypes {
4679 return TypeManager.NoTypes;
4683 public abstract Type ReturnType { get; }
4685 public Location Location {
4687 return method.Location;
4691 public abstract string MethodName { get; }
4693 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
4695 return new EmitContext (tc, method.ds, method.Location, ig, ReturnType, method.ModFlags, false);
4702 public PropertyMethod Get, Set;
4703 public PropertyBuilder PropertyBuilder;
4704 public MethodBuilder GetBuilder, SetBuilder;
4706 protected EmitContext ec;
4708 public PropertyBase (DeclSpace ds, Expression type, int mod_flags,
4709 int allowed_mod, bool is_iface, string name,
4710 Parameters parameters, Attributes attrs,
4712 : base (ds, type, mod_flags, allowed_mod, is_iface, name,
4713 attrs, parameters, loc)
4717 protected override bool DoDefine (TypeContainer container)
4719 if (!base.DoDefine (container))
4722 ec = new EmitContext (container, Location, null, MemberType, ModFlags);
4727 public override string GetSignatureForError()
4729 return TypeManager.CSharpSignature (PropertyBuilder, false);
4732 protected virtual string RealMethodName {
4738 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
4740 if (!IsIdentifierAndParamClsCompliant (ds, RealMethodName, null, null))
4743 if (Get != null && !IsIdentifierAndParamClsCompliant (ds, "get_" + RealMethodName, null, null))
4746 if (Set != null && !IsIdentifierAndParamClsCompliant (ds, "set_" + RealMethodName, null, null))
4754 // Checks our base implementation if any
4756 protected override bool CheckBase (TypeContainer container)
4758 base.CheckBase (container);
4760 // Check whether arguments were correct.
4761 if (!DoDefineParameters ())
4768 // Check in our class for dups
4770 ArrayList ar = container.Properties;
4772 int arLen = ar.Count;
4774 for (int i = 0; i < arLen; i++) {
4775 Property m = (Property) ar [i];
4776 if (IsDuplicateImplementation (container, m))
4785 MethodSignature ms, base_ms;
4786 if (this is Indexer) {
4787 string name, base_name;
4789 report_name = "this";
4790 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
4791 ms = new MethodSignature (name, null, ParameterTypes);
4792 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
4793 base_ms = new MethodSignature (base_name, null, ParameterTypes);
4796 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
4800 // Verify if the parent has a type with the same name, and then
4801 // check whether we have to create a new slot for it or not.
4803 Type ptype = container.TypeBuilder.BaseType;
4805 // ptype is only null for System.Object while compiling corlib.
4806 if (ptype == null) {
4807 if ((ModFlags & Modifiers.NEW) != 0)
4808 WarningNotHiding (container);
4813 MemberInfo parent_member = null;
4816 // Explicit implementations do not have `parent' methods, however,
4817 // the member cache stores them there. Without this check, we get
4818 // an incorrect warning in corlib.
4820 if (! IsExplicitImpl) {
4821 parent_member = ((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
4822 container.TypeBuilder, Name, ParameterTypes, true);
4825 if (parent_member is PropertyInfo) {
4826 PropertyInfo parent_property = (PropertyInfo)parent_member;
4828 string name = parent_property.DeclaringType.Name + "." +
4829 parent_property.Name;
4831 MethodInfo get, set, parent_method;
4832 get = parent_property.GetGetMethod (true);
4833 set = parent_property.GetSetMethod (true);
4836 parent_method = get;
4837 else if (set != null)
4838 parent_method = set;
4840 throw new Exception ("Internal error!");
4842 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
4845 if ((ModFlags & Modifiers.NEW) == 0) {
4846 Type parent_type = TypeManager.TypeToCoreType (
4847 parent_property.PropertyType);
4849 if (parent_type != MemberType) {
4851 508, Location, container.MakeName (Name) + ": cannot " +
4852 "change return type when overriding " +
4853 "inherited member " + name);
4857 } else if (parent_member == null){
4858 if ((ModFlags & Modifiers.NEW) != 0)
4859 WarningNotHiding (container);
4861 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4862 if (this is Indexer)
4863 Report.Error (115, Location,
4864 container.MakeName (Name) +
4865 " no suitable indexers found to override");
4867 Report.Error (115, Location,
4868 container.MakeName (Name) +
4869 " no suitable properties found to override");
4876 public override void Emit (TypeContainer tc)
4879 // The PropertyBuilder can be null for explicit implementations, in that
4880 // case, we do not actually emit the ".property", so there is nowhere to
4881 // put the attribute
4883 if (PropertyBuilder != null)
4884 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes);
4896 public class Property : PropertyBase, IIteratorContainer {
4897 const int AllowedModifiers =
4900 Modifiers.PROTECTED |
4901 Modifiers.INTERNAL |
4905 Modifiers.OVERRIDE |
4906 Modifiers.ABSTRACT |
4909 Modifiers.METHOD_YIELDS |
4912 const int AllowedInterfaceModifiers =
4915 public Property (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
4916 string name, Attributes attrs, Accessor get_block,
4917 Accessor set_block, Location loc)
4918 : base (ds, type, mod_flags,
4919 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
4920 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
4923 if (get_block != null)
4924 Get = new GetMethod (this, get_block);
4926 if (set_block != null)
4927 Set = new SetMethod (this, set_block);
4930 public override bool Define (TypeContainer container)
4932 if (!DoDefine (container))
4935 if (!CheckBase (container))
4938 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4942 GetBuilder = Get.Define (container);
4943 if (GetBuilder == null)
4947 // Setup iterator if we are one
4949 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
4950 IteratorHandler ih = new IteratorHandler (
4951 "get", container, MemberType,
4952 TypeManager.NoTypes, Get.ParameterInfo, ModFlags, Location);
4954 Block new_block = ih.Setup (block);
4955 if (new_block == null)
4962 SetBuilder = Set.Define (container);
4963 if (SetBuilder == null)
4966 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4969 // FIXME - PropertyAttributes.HasDefault ?
4971 PropertyAttributes prop_attr = PropertyAttributes.None;
4973 prop_attr |= PropertyAttributes.RTSpecialName |
4974 PropertyAttributes.SpecialName;
4976 if (!IsExplicitImpl){
4977 PropertyBuilder = container.TypeBuilder.DefineProperty (
4978 Name, prop_attr, MemberType, null);
4981 PropertyBuilder.SetGetMethod (GetBuilder);
4984 PropertyBuilder.SetSetMethod (SetBuilder);
4987 // HACK for the reasons exposed above
4989 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4992 "Class `" + container.Name +
4993 "' already contains a definition for the property `" +
5001 public void SetYields ()
5003 ModFlags |= Modifiers.METHOD_YIELDS;
5008 /// Gigantic workaround for lameness in SRE follows :
5009 /// This class derives from EventInfo and attempts to basically
5010 /// wrap around the EventBuilder so that FindMembers can quickly
5011 /// return this in it search for members
5013 public class MyEventBuilder : EventInfo {
5016 // We use this to "point" to our Builder which is
5017 // not really a MemberInfo
5019 EventBuilder MyBuilder;
5022 // We "catch" and wrap these methods
5024 MethodInfo raise, remove, add;
5026 EventAttributes attributes;
5027 Type declaring_type, reflected_type, event_type;
5032 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
5034 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
5036 // And now store the values in our own fields.
5038 declaring_type = type_builder;
5040 reflected_type = type_builder;
5042 attributes = event_attr;
5045 this.event_type = event_type;
5049 // Methods that you have to override. Note that you only need
5050 // to "implement" the variants that take the argument (those are
5051 // the "abstract" methods, the others (GetAddMethod()) are
5054 public override MethodInfo GetAddMethod (bool nonPublic)
5059 public override MethodInfo GetRemoveMethod (bool nonPublic)
5064 public override MethodInfo GetRaiseMethod (bool nonPublic)
5070 // These methods make "MyEventInfo" look like a Builder
5072 public void SetRaiseMethod (MethodBuilder raiseMethod)
5074 raise = raiseMethod;
5075 MyBuilder.SetRaiseMethod (raiseMethod);
5078 public void SetRemoveOnMethod (MethodBuilder removeMethod)
5080 remove = removeMethod;
5081 MyBuilder.SetRemoveOnMethod (removeMethod);
5084 public void SetAddOnMethod (MethodBuilder addMethod)
5087 MyBuilder.SetAddOnMethod (addMethod);
5090 public void SetCustomAttribute (CustomAttributeBuilder cb)
5092 MyBuilder.SetCustomAttribute (cb);
5095 public override object [] GetCustomAttributes (bool inherit)
5097 // FIXME : There's nothing which can be seemingly done here because
5098 // we have no way of getting at the custom attribute objects of the
5103 public override object [] GetCustomAttributes (Type t, bool inherit)
5105 // FIXME : Same here !
5109 public override bool IsDefined (Type t, bool b)
5114 public override EventAttributes Attributes {
5120 public override string Name {
5126 public override Type DeclaringType {
5128 return declaring_type;
5132 public override Type ReflectedType {
5134 return reflected_type;
5138 public Type EventType {
5144 public void SetUsed ()
5146 if (my_event != null)
5147 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
5151 public class Event : FieldBase {
5153 sealed class AddDelegateMethod: DelegateMethod
5155 public AddDelegateMethod (Event method, Accessor accessor):
5156 base (method, accessor)
5160 public override string MethodName {
5162 return "add_" + method.ShortName;
5166 protected override MethodInfo DelegateMethodInfo {
5168 return TypeManager.delegate_combine_delegate_delegate;
5174 sealed class RemoveDelegateMethod: DelegateMethod
5176 public RemoveDelegateMethod (Event method, Accessor accessor):
5177 base (method, accessor)
5181 public override string MethodName {
5183 return "remove_" + method.ShortName;
5187 protected override MethodInfo DelegateMethodInfo {
5189 return TypeManager.delegate_combine_delegate_delegate;
5195 abstract class DelegateMethod: IMethodData
5197 protected readonly Event method;
5198 public readonly Accessor Accessor;
5199 protected MethodData method_data;
5201 public DelegateMethod (Event method, Accessor accessor)
5203 this.method = method;
5204 this.Accessor = accessor;
5207 public MethodBuilder Define (TypeContainer container, InternalParameters ip)
5209 method_data = new MethodData (method, ip, method.ModFlags,
5210 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, false, this);
5212 if (!method_data.Define (container))
5215 MethodBuilder mb = method_data.MethodBuilder;
5216 mb.DefineParameter (1, ParameterAttributes.None, "value");
5220 #region IMethodData Members
5222 public Block Block {
5224 return Accessor.Block;
5228 public CallingConventions CallingConventions {
5230 return CallingConventions.Standard;
5234 public void Emit (TypeContainer tc)
5236 if (Accessor != null) {
5237 method_data.Emit (tc, Accessor);
5238 Accessor.Block = null;
5242 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
5243 EmitContext ec = CreateEmitContext (tc, ig);
5244 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
5246 if ((method.ModFlags & Modifiers.STATIC) != 0) {
5247 ig.Emit (OpCodes.Ldsfld, field_info);
5248 ig.Emit (OpCodes.Ldarg_0);
5249 ig.Emit (OpCodes.Call, DelegateMethodInfo);
5250 ig.Emit (OpCodes.Castclass, method.MemberType);
5251 ig.Emit (OpCodes.Stsfld, field_info);
5253 ig.Emit (OpCodes.Ldarg_0);
5254 ig.Emit (OpCodes.Ldarg_0);
5255 ig.Emit (OpCodes.Ldfld, field_info);
5256 ig.Emit (OpCodes.Ldarg_1);
5257 ig.Emit (OpCodes.Call, DelegateMethodInfo);
5258 ig.Emit (OpCodes.Castclass, method.MemberType);
5259 ig.Emit (OpCodes.Stfld, field_info);
5261 ig.Emit (OpCodes.Ret);
5264 protected abstract MethodInfo DelegateMethodInfo { get; }
5266 public Attributes OptAttributes {
5268 return Accessor == null ? null : Accessor.OptAttributes;
5272 public Type[] ParameterTypes {
5274 return new Type[] { method.MemberType };
5278 public Type ReturnType {
5280 return TypeManager.void_type;
5284 public Location Location {
5286 return method.Location;
5290 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
5292 return new EmitContext (tc, method.ds, method.Location, ig, ReturnType, method.ModFlags, false);
5295 public abstract string MethodName { get; }
5302 const int AllowedModifiers =
5305 Modifiers.PROTECTED |
5306 Modifiers.INTERNAL |
5311 Modifiers.OVERRIDE |
5315 const int AllowedInterfaceModifiers =
5318 readonly DelegateMethod Add, Remove;
5319 public MyEventBuilder EventBuilder;
5320 public MethodBuilder AddBuilder, RemoveBuilder;
5321 public DeclSpace ds;
5323 public Event (DeclSpace ds, Expression type, int mod_flags, bool is_iface, string name,
5324 Object init, Attributes attrs, Accessor add, Accessor remove,
5326 : base (type, mod_flags,
5327 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5328 name, init, attrs, loc)
5330 Add = new AddDelegateMethod (this, add);
5331 Remove = new RemoveDelegateMethod (this, remove);
5332 IsInterface = is_iface;
5336 public override bool Define (TypeContainer container)
5338 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
5340 if (!DoDefine (container))
5343 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
5344 Report.Error (74, Location, "'" + container.Name + "." + Name +
5345 "': abstract event can not have an initializer");
5349 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
5350 Report.Error (66, Location, "'" + container.Name + "." + Name +
5351 "' : event must be of a delegate type");
5355 Parameter [] parms = new Parameter [1];
5356 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
5357 InternalParameters ip = new InternalParameters (
5358 container, new Parameters (parms, null, Location));
5360 if (!CheckBase (container))
5364 // Now define the accessors
5367 AddBuilder = Add.Define (container, ip);
5368 if (AddBuilder == null)
5371 RemoveBuilder = Remove.Define (container, ip);
5372 if (RemoveBuilder == null)
5375 if (!IsExplicitImpl){
5376 EventBuilder = new MyEventBuilder (this,
5377 container.TypeBuilder, Name, e_attr, MemberType);
5379 if (Add.Accessor == null && Remove.Accessor == null) {
5380 FieldBuilder = container.TypeBuilder.DefineField (
5382 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
5383 TypeManager.RegisterPrivateFieldOfEvent (
5384 (EventInfo) EventBuilder, FieldBuilder);
5385 TypeManager.RegisterFieldBase (FieldBuilder, this);
5388 EventBuilder.SetAddOnMethod (AddBuilder);
5389 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
5391 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
5392 Report.Error (111, Location,
5393 "Class `" + container.Name +
5394 "' already contains a definition for the event `" +
5403 public override void Emit (TypeContainer tc)
5405 if (OptAttributes != null) {
5406 EmitContext ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
5407 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes);
5419 // FIXME: This does not handle:
5421 // int INTERFACENAME [ args ]
5426 // int this [ args ]
5428 public class Indexer : PropertyBase {
5430 class GetIndexerMethod: GetMethod
5432 public GetIndexerMethod (MethodCore method, Accessor accessor):
5433 base (method, accessor)
5437 public override Type[] ParameterTypes {
5439 return method.ParameterTypes;
5444 class SetIndexerMethod: SetMethod
5446 readonly Parameters parameters;
5448 public SetIndexerMethod (MethodCore method, Parameters parameters, Accessor accessor):
5449 base (method, accessor)
5451 this.parameters = parameters;
5454 public override Type[] ParameterTypes {
5456 int top = method.ParameterTypes.Length;
5457 Type [] set_pars = new Type [top + 1];
5458 method.ParameterTypes.CopyTo (set_pars, 0);
5459 set_pars [top] = method.MemberType;
5464 protected override InternalParameters GetParameterInfo (TypeContainer container)
5466 Parameter [] fixed_parms = parameters.FixedParameters;
5468 if (fixed_parms == null){
5469 throw new Exception ("We currently do not support only array arguments in an indexer at: " + method.Location);
5470 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5471 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5473 // Here is the problem: the `value' parameter has
5474 // to come *after* the array parameter in the declaration
5476 // X (object [] x, Type value)
5479 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5480 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5484 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
5486 fixed_parms.CopyTo (tmp, 0);
5487 tmp [fixed_parms.Length] = new Parameter (
5488 method.Type, "value", Parameter.Modifier.NONE, null);
5490 Parameters set_formal_params = new Parameters (tmp, null, method.Location);
5492 return new InternalParameters (container, set_formal_params);
5498 const int AllowedModifiers =
5501 Modifiers.PROTECTED |
5502 Modifiers.INTERNAL |
5506 Modifiers.OVERRIDE |
5511 const int AllowedInterfaceModifiers =
5514 public string IndexerName;
5515 public string InterfaceIndexerName;
5518 // Are we implementing an interface ?
5520 public Indexer (DeclSpace ds, Expression type, string int_type, int mod_flags,
5521 bool is_iface, Parameters parameters, Attributes attrs,
5522 Accessor get_block, Accessor set_block, Location loc)
5523 : base (ds, type, mod_flags,
5524 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5525 is_iface, "", parameters, attrs, loc)
5527 ExplicitInterfaceName = int_type;
5529 if (get_block != null)
5530 Get = new GetIndexerMethod (this, get_block);
5532 if (set_block != null)
5533 Set = new SetIndexerMethod (this, parameters, set_block);
5536 public override bool Define (TypeContainer container)
5538 PropertyAttributes prop_attr =
5539 PropertyAttributes.RTSpecialName |
5540 PropertyAttributes.SpecialName;
5542 if (!DoDefine (container))
5545 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
5546 if (IndexerName == null)
5547 IndexerName = "Item";
5549 if (! Tokenizer.IsValidIdentifier (IndexerName)) {
5550 Report.Error (633, Location, "The IndexerName specified is an invalid identifier");
5554 if (IsExplicitImpl) {
5555 Report.Error (592, Location,
5556 "Attribute 'IndexerName' is not valid on explicit " +
5557 "implementations.");
5563 ShortName = IndexerName;
5564 if (IsExplicitImpl) {
5565 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
5566 Name = InterfaceType.FullName + "." + IndexerName;
5568 InterfaceIndexerName = IndexerName;
5572 if (!CheckNameCollision (container))
5575 if (!CheckBase (container))
5578 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
5580 GetBuilder = Get.Define (container);
5581 if (GetBuilder == null)
5586 SetBuilder = Set.Define (container);
5587 if (SetBuilder == null)
5592 // Now name the parameters
5594 Parameter [] p = Parameters.FixedParameters;
5598 for (i = 0; i < p.Length; ++i) {
5600 GetBuilder.DefineParameter (
5601 i + 1, p [i].Attributes, p [i].Name);
5604 SetBuilder.DefineParameter (
5605 i + 1, p [i].Attributes, p [i].Name);
5609 SetBuilder.DefineParameter (
5610 i + 1, ParameterAttributes.None, "value");
5612 if (i != ParameterTypes.Length) {
5613 Parameter array_param = Parameters.ArrayParameter;
5615 SetBuilder.DefineParameter (
5616 i + 1, array_param.Attributes, array_param.Name);
5621 // Define the PropertyBuilder if one of the following conditions are met:
5622 // a) we're not implementing an interface indexer.
5623 // b) the indexer has a different IndexerName and this is no
5624 // explicit interface implementation.
5626 if (!IsExplicitImpl) {
5627 PropertyBuilder = container.TypeBuilder.DefineProperty (
5628 IndexerName, prop_attr, MemberType, ParameterTypes);
5631 PropertyBuilder.SetGetMethod (GetBuilder);
5634 PropertyBuilder.SetSetMethod (SetBuilder);
5636 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
5643 bool CheckNameCollision (TypeContainer container) {
5644 switch (VerifyName (container)){
5645 case DeclSpace.AdditionResult.NameExists:
5646 Report.Error (102, Location, "The container '{0}' already contains a definition for '{1}'", container.GetSignatureForError (), Name);
5649 case DeclSpace.AdditionResult.Success:
5652 throw new NotImplementedException ();
5655 DeclSpace.AdditionResult VerifyName (TypeContainer container) {
5656 if (!AddIndexer (container, container.Name + "." + Name))
5657 return DeclSpace.AdditionResult.NameExists;
5660 if (!AddIndexer (container, container.Name + ".get_" + Name))
5661 return DeclSpace.AdditionResult.NameExists;
5665 if (!AddIndexer (container, container.Name + ".set_" + Name))
5666 return DeclSpace.AdditionResult.NameExists;
5668 return DeclSpace.AdditionResult.Success;
5671 bool AddIndexer (TypeContainer container, string fullname)
5673 object value = container.GetDefinition (fullname);
5675 if (value != null) {
5676 return value.GetType () != GetType () ? false : true;
5679 container.DefineName (fullname, this);
5683 public override string GetSignatureForError ()
5685 return TypeManager.CSharpSignature (PropertyBuilder, true);
5688 protected override string RealMethodName {
5695 public class Operator : MemberBase, IIteratorContainer {
5697 const int AllowedModifiers =
5703 const int RequiredModifiers =
5707 public enum OpType : byte {
5717 // Unary and Binary operators
5740 // Implicit and Explicit
5745 public readonly OpType OperatorType;
5746 public readonly Expression ReturnType;
5747 public readonly Expression FirstArgType, SecondArgType;
5748 public readonly string FirstArgName, SecondArgName;
5750 public MethodBuilder OperatorMethodBuilder;
5752 public string MethodName;
5753 public Method OperatorMethod;
5755 public Operator (OpType type, Expression ret_type, int mod_flags,
5756 Expression arg1type, string arg1name,
5757 Expression arg2type, string arg2name,
5758 Block block, Attributes attrs, Location loc)
5759 : base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC, "", attrs, loc)
5761 OperatorType = type;
5762 Name = "op_" + OperatorType;
5763 ReturnType = ret_type;
5764 FirstArgType = arg1type;
5765 FirstArgName = arg1name;
5766 SecondArgType = arg2type;
5767 SecondArgName = arg2name;
5771 string Prototype (TypeContainer container)
5773 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
5774 SecondArgType + ")";
5777 public override bool Define (TypeContainer container)
5780 MethodName = "op_" + OperatorType;
5782 if (SecondArgType != null)
5785 Parameter [] param_list = new Parameter [length];
5787 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
5790 "User defined operators `" +
5791 Prototype (container) +
5792 "' must be declared static and public");
5796 param_list[0] = new Parameter (FirstArgType, FirstArgName,
5797 Parameter.Modifier.NONE, null);
5798 if (SecondArgType != null)
5799 param_list[1] = new Parameter (SecondArgType, SecondArgName,
5800 Parameter.Modifier.NONE, null);
5802 OperatorMethod = new Method (
5803 container, ReturnType, ModFlags, false, MethodName,
5804 new Parameters (param_list, null, Location),
5805 OptAttributes, Location);
5807 OperatorMethod.Block = Block;
5808 OperatorMethod.IsOperator = true;
5809 OperatorMethod.Define (container);
5811 if (OperatorMethod.MethodBuilder == null)
5814 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
5816 Type [] param_types = OperatorMethod.ParameterTypes;
5817 Type declaring_type = OperatorMethodBuilder.DeclaringType;
5818 Type return_type = OperatorMethod.GetReturnType ();
5819 Type first_arg_type = param_types [0];
5821 // Rules for conversion operators
5823 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
5824 if (first_arg_type == return_type && first_arg_type == declaring_type){
5827 "User-defined conversion cannot take an object of the " +
5828 "enclosing type and convert to an object of the enclosing" +
5833 if (first_arg_type != declaring_type && return_type != declaring_type){
5836 "User-defined conversion must convert to or from the " +
5841 if (first_arg_type == TypeManager.object_type ||
5842 return_type == TypeManager.object_type){
5845 "User-defined conversion cannot convert to or from " +
5850 if (first_arg_type.IsInterface || return_type.IsInterface){
5853 "User-defined conversion cannot convert to or from an " +
5858 if (first_arg_type.IsSubclassOf (return_type) ||
5859 return_type.IsSubclassOf (first_arg_type)){
5862 "User-defined conversion cannot convert between types " +
5863 "that derive from each other");
5866 } else if (SecondArgType == null) {
5867 // Checks for Unary operators
5869 if (first_arg_type != declaring_type){
5872 "The parameter of a unary operator must be the " +
5877 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
5878 if (return_type != declaring_type){
5881 "The parameter and return type for ++ and -- " +
5882 "must be the containing type");
5888 if (OperatorType == OpType.True || OperatorType == OpType.False) {
5889 if (return_type != TypeManager.bool_type){
5892 "The return type of operator True or False " +
5899 // Checks for Binary operators
5901 if (first_arg_type != declaring_type &&
5902 param_types [1] != declaring_type){
5905 "One of the parameters of a binary operator must " +
5906 "be the containing type");
5914 public override void Emit (TypeContainer container)
5917 // abstract or extern methods have no bodies
5919 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
5922 OperatorMethod.Emit (container);
5926 public static string GetName (OpType ot)
5929 case OpType.LogicalNot:
5931 case OpType.OnesComplement:
5933 case OpType.Increment:
5935 case OpType.Decrement:
5941 case OpType.Addition:
5943 case OpType.Subtraction:
5945 case OpType.UnaryPlus:
5947 case OpType.UnaryNegation:
5949 case OpType.Multiply:
5951 case OpType.Division:
5953 case OpType.Modulus:
5955 case OpType.BitwiseAnd:
5957 case OpType.BitwiseOr:
5959 case OpType.ExclusiveOr:
5961 case OpType.LeftShift:
5963 case OpType.RightShift:
5965 case OpType.Equality:
5967 case OpType.Inequality:
5969 case OpType.GreaterThan:
5971 case OpType.LessThan:
5973 case OpType.GreaterThanOrEqual:
5975 case OpType.LessThanOrEqual:
5977 case OpType.Implicit:
5979 case OpType.Explicit:
5985 public override string ToString ()
5987 Type return_type = OperatorMethod.GetReturnType();
5988 Type [] param_types = OperatorMethod.ParameterTypes;
5990 if (SecondArgType == null)
5991 return String.Format (
5992 "{0} operator {1}({2})",
5993 TypeManager.CSharpName (return_type),
5994 GetName (OperatorType),
5997 return String.Format (
5998 "{0} operator {1}({2}, {3})",
5999 TypeManager.CSharpName (return_type),
6000 GetName (OperatorType),
6001 param_types [0], param_types [1]);
6004 public void SetYields ()
6006 ModFlags |= Modifiers.METHOD_YIELDS;
6011 // This is used to compare method signatures
6013 struct MethodSignature {
6015 public Type RetType;
6016 public Type [] Parameters;
6019 /// This delegate is used to extract methods which have the
6020 /// same signature as the argument
6022 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
6024 public MethodSignature (string name, Type ret_type, Type [] parameters)
6029 if (parameters == null)
6030 Parameters = TypeManager.NoTypes;
6032 Parameters = parameters;
6035 public override string ToString ()
6038 if (Parameters.Length != 0){
6039 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
6040 for (int i = 0; i < Parameters.Length; i++){
6041 sb.Append (Parameters [i]);
6042 if (i+1 < Parameters.Length)
6045 pars = sb.ToString ();
6048 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
6051 public override int GetHashCode ()
6053 return Name.GetHashCode ();
6056 public override bool Equals (Object o)
6058 MethodSignature other = (MethodSignature) o;
6060 if (other.Name != Name)
6063 if (other.RetType != RetType)
6066 if (Parameters == null){
6067 if (other.Parameters == null)
6072 if (other.Parameters == null)
6075 int c = Parameters.Length;
6076 if (other.Parameters.Length != c)
6079 for (int i = 0; i < c; i++)
6080 if (other.Parameters [i] != Parameters [i])
6086 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
6088 MethodSignature sig = (MethodSignature) filter_criteria;
6090 if (m.Name != sig.Name)
6094 MethodInfo mi = m as MethodInfo;
6095 PropertyInfo pi = m as PropertyInfo;
6098 ReturnType = mi.ReturnType;
6099 else if (pi != null)
6100 ReturnType = pi.PropertyType;
6105 // we use sig.RetType == null to mean `do not check the
6106 // method return value.
6108 if (sig.RetType != null)
6109 if (ReturnType != sig.RetType)
6114 args = TypeManager.GetArgumentTypes (mi);
6116 args = TypeManager.GetArgumentTypes (pi);
6117 Type [] sigp = sig.Parameters;
6119 if (args.Length != sigp.Length)
6122 for (int i = args.Length; i > 0; ){
6124 if (args [i] != sigp [i])