2 // class.cs: Class and Struct handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@gnome.org)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
12 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
14 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
15 // have fixed a remaining problem: not every AddXXXX was adding a
16 // fully qualified name.
18 // Now everyone registers a fully qualified name in the DeclSpace as
19 // being defined instead of the partial name.
21 // Downsides: we are slower than we need to be due to the excess
22 // copies and the names being registered this way.
24 // The reason for this is that we currently depend (on the corlib
25 // bootstrap for instance) that types are fully qualified, because
26 // we dump all the types in the namespace, and we should really have
27 // types inserted into the proper namespace, so we can only store the
28 // basenames in the defined_names array.
33 using System.Collections;
34 using System.Reflection;
35 using System.Reflection.Emit;
36 using System.Runtime.CompilerServices;
38 namespace Mono.CSharp {
41 /// This is the base class for structs and classes.
43 public class TypeContainer : DeclSpace, IMemberContainer {
44 // Holds a list of classes and structures
47 // Holds the list of properties
50 // Holds the list of enumerations
53 // Holds the list of delegates
56 // Holds the list of constructors
57 ArrayList instance_constructors;
59 // Holds the list of fields
62 // Holds a list of fields that have initializers
63 ArrayList initialized_fields;
65 // Holds a list of static fields that have initializers
66 ArrayList initialized_static_fields;
68 // Holds the list of constants
74 // Holds order in which interfaces must be closed
75 ArrayList interface_order;
86 // Holds the operators
89 // The emit context for toplevel objects.
93 // Pointers to the default constructor and the default static constructor
95 Constructor default_constructor;
96 Constructor default_static_constructor;
99 // Whether we have seen a static constructor for this class or not
101 bool have_static_constructor = false;
104 // Whether we have at least one non-static field
106 bool have_nonstatic_fields = false;
109 // This one is computed after we can distinguish interfaces
110 // from classes from the arraylist `type_bases'
112 string base_class_name;
114 ArrayList type_bases;
116 // Attributes for this type
117 protected Attributes attributes;
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.
128 // The parent member container and our member cache
129 IMemberContainer parent_container;
130 MemberCache member_cache;
133 // The indexer name for this class
135 public string IndexerName;
137 public TypeContainer (NamespaceEntry ns, TypeContainer parent, string name, Location l)
138 : base (ns, parent, name, l)
140 types = new ArrayList ();
142 base_class_name = null;
145 public AdditionResult AddConstant (Const constant)
148 string basename = constant.Name;
149 string fullname = Name + "." + basename;
151 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
154 if (constants == null)
155 constants = new ArrayList ();
157 constants.Add (constant);
158 DefineName (fullname, constant);
160 return AdditionResult.Success;
163 public AdditionResult AddEnum (Mono.CSharp.Enum e)
167 if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
171 enums = new ArrayList ();
174 DefineName (e.Name, e);
176 return AdditionResult.Success;
179 public AdditionResult AddClass (Class c)
182 string name = c.Basename;
184 if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
187 DefineName (c.Name, c);
190 return AdditionResult.Success;
193 public AdditionResult AddStruct (Struct s)
196 string name = s.Basename;
198 if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
201 DefineName (s.Name, s);
204 return AdditionResult.Success;
207 public AdditionResult AddDelegate (Delegate d)
210 string name = d.Basename;
212 if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
215 if (delegates == null)
216 delegates = new ArrayList ();
218 DefineName (d.Name, d);
221 return AdditionResult.Success;
224 public AdditionResult AddMethod (Method method)
226 string basename = method.Name;
227 string fullname = Name + "." + basename;
229 Object value = defined_names [fullname];
231 if (value != null && (!(value is Method)))
232 return AdditionResult.NameExists;
234 if (basename == Basename)
235 return AdditionResult.EnclosingClash;
238 methods = new ArrayList ();
240 if (method.Name.IndexOf ('.') != -1)
241 methods.Insert (0, method);
243 methods.Add (method);
246 DefineName (fullname, method);
248 return AdditionResult.Success;
251 public AdditionResult AddConstructor (Constructor c)
253 if (c.Name != Basename)
254 return AdditionResult.NotAConstructor;
256 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
259 have_static_constructor = true;
260 if (default_static_constructor != null){
261 Console.WriteLine ("I have a static constructor already");
262 Console.WriteLine (" " + default_static_constructor);
263 return AdditionResult.MethodExists;
266 default_static_constructor = c;
269 if (default_constructor != null)
270 return AdditionResult.MethodExists;
271 default_constructor = c;
274 if (instance_constructors == null)
275 instance_constructors = new ArrayList ();
277 instance_constructors.Add (c);
280 return AdditionResult.Success;
283 public AdditionResult AddInterface (Interface iface)
286 string name = iface.Basename;
288 if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
291 if (interfaces == null)
292 interfaces = new ArrayList ();
293 interfaces.Add (iface);
294 DefineName (iface.Name, iface);
296 return AdditionResult.Success;
299 public AdditionResult AddField (Field field)
302 string basename = field.Name;
303 string fullname = Name + "." + basename;
305 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
309 fields = new ArrayList ();
313 if (field.HasInitializer){
314 if ((field.ModFlags & Modifiers.STATIC) != 0){
315 if (initialized_static_fields == null)
316 initialized_static_fields = new ArrayList ();
318 initialized_static_fields.Add (field);
321 // We have not seen a static constructor,
322 // but we will provide static initialization of fields
324 have_static_constructor = true;
326 if (initialized_fields == null)
327 initialized_fields = new ArrayList ();
329 initialized_fields.Add (field);
333 if ((field.ModFlags & Modifiers.STATIC) == 0)
334 have_nonstatic_fields = true;
336 DefineName (fullname, field);
337 return AdditionResult.Success;
340 public AdditionResult AddProperty (Property prop)
343 string basename = prop.Name;
344 string fullname = Name + "." + basename;
346 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
349 if (properties == null)
350 properties = new ArrayList ();
352 if (prop.Name.IndexOf ('.') != -1)
353 properties.Insert (0, prop);
355 properties.Add (prop);
356 DefineName (fullname, prop);
358 return AdditionResult.Success;
361 public AdditionResult AddEvent (Event e)
364 string basename = e.Name;
365 string fullname = Name + "." + basename;
367 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
371 events = new ArrayList ();
374 DefineName (fullname, e);
376 return AdditionResult.Success;
379 public AdditionResult AddIndexer (Indexer i)
381 if (indexers == null)
382 indexers = new ArrayList ();
384 if (i.InterfaceType != null)
385 indexers.Insert (0, i);
389 return AdditionResult.Success;
392 public AdditionResult AddOperator (Operator op)
394 if (operators == null)
395 operators = new ArrayList ();
399 return AdditionResult.Success;
402 public void RegisterOrder (Interface iface)
404 if (interface_order == null)
405 interface_order = new ArrayList ();
407 interface_order.Add (iface);
410 public ArrayList Types {
416 public ArrayList Methods {
422 public ArrayList Constants {
428 public ArrayList Interfaces {
436 return base_class_name;
440 public ArrayList Bases {
450 public ArrayList Fields {
460 public ArrayList InstanceConstructors {
462 return instance_constructors;
466 public ArrayList Properties {
472 public ArrayList Events {
478 public ArrayList Enums {
484 public ArrayList Indexers {
490 public ArrayList Operators {
496 public ArrayList Delegates {
502 public Attributes OptAttributes {
508 public bool HaveStaticConstructor {
510 return have_static_constructor;
514 public virtual TypeAttributes TypeAttr {
516 return Modifiers.TypeAttr (ModFlags, this);
521 // Emits the instance field initializers
523 public bool EmitFieldInitializers (EmitContext ec)
526 Expression instance_expr;
529 fields = initialized_static_fields;
530 instance_expr = null;
532 fields = initialized_fields;
533 instance_expr = new This (Location.Null).Resolve (ec);
539 foreach (Field f in fields){
540 Expression e = f.GetInitializerExpression (ec);
544 Location l = f.Location;
545 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
546 fe.InstanceExpression = instance_expr;
547 ExpressionStatement a = new Assign (fe, e, l);
549 a = a.ResolveStatement (ec);
553 a.EmitStatement (ec);
560 // Defines the default constructors
562 void DefineDefaultConstructor (bool is_static)
567 c = new Constructor (this, Basename, Parameters.EmptyReadOnlyParameters,
568 new ConstructorBaseInitializer (
569 null, Parameters.EmptyReadOnlyParameters,
574 mods = Modifiers.STATIC;
577 // If the class is abstract, the default constructor is protected
579 if ((ModFlags & Modifiers.ABSTRACT) != 0)
580 mods |= Modifiers.PROTECTED;
586 c.Block = new Block (null);
590 public void ReportStructInitializedInstanceError ()
592 string n = TypeBuilder.FullName;
594 foreach (Field f in initialized_fields){
597 "`" + n + "." + f.Name + "': can not have " +
598 "instance field initializers in structs");
603 /// The pending methods that need to be implemented (interfaces or abstract methods)
605 public PendingImplementation Pending;
608 /// This function computes the Base class and also the
609 /// list of interfaces that the class or struct @c implements.
611 /// The return value is an array (might be null) of
612 /// interfaces implemented (as Types).
614 /// The @parent argument is set to the parent object or null
615 /// if this is `System.Object'.
617 TypeExpr [] GetClassBases (bool is_class, out TypeExpr parent, out bool error)
619 ArrayList bases = Bases;
628 parent = TypeManager.system_valuetype_expr;
632 if (RootContext.StdLib)
633 parent = TypeManager.system_object_expr;
634 else if (Name != "System.Object")
635 parent = TypeManager.system_object_expr;
638 // If we are compiling our runtime,
639 // and we are defining ValueType, then our
640 // parent is `System.Object'.
642 if (!RootContext.StdLib && Name == "System.ValueType")
643 parent = TypeManager.system_object_expr;
650 // Bases should be null if there are no bases at all
655 TypeExpr name = ResolveTypeExpr ((Expression) bases [0], false, Location);
666 parent = TypeManager.system_object_expr;
672 if (name.IsValueType)
673 detail = " (a class can not inherit from a struct/enum)";
675 Report.Error (509, "class `"+ Name +
676 "': Cannot inherit from sealed class `"+
677 name.Name + "'" + detail);
682 if (!parent.CanInheritFrom ()){
683 Report.Error (644, Location,
684 "`{0}' cannot inherit from special class `{1}'",
690 if (!parent.AsAccessible (this, ModFlags))
691 Report.Error (60, Location,
692 "Inconsistent accessibility: base class `" +
693 name.Name + "' is less accessible than class `" +
701 base_class_name = parent.Name;
703 TypeExpr [] ifaces = new TypeExpr [count-start];
705 for (i = start, j = 0; i < count; i++, j++){
706 Expression name = (Expression) bases [i];
707 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
708 if (resolved == null)
711 bases [i] = resolved;
713 if (is_class == false && !resolved.IsInterface){
714 Report.Error (527, "In Struct `" + Name + "', type `"+
715 name +"' is not an interface");
720 if (resolved.IsClass) {
722 Report.Error (527, "In Class `" + Name + "', type `"+
723 name+"' is not an interface");
729 for (int x = 0; x < j; x++) {
730 if (resolved == ifaces [x]) {
731 Report.Error (528, "`" + name + "' is already listed in interface list");
737 ifaces [j] = resolved;
740 return TypeManager.ExpandInterfaces (ifaces);
746 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
748 public override TypeBuilder DefineType ()
753 if (TypeBuilder != null)
760 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
772 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
774 ifaces = GetClassBases (is_class, out parent, out error);
779 if (!is_class && TypeManager.value_type == null)
780 throw new Exception ();
782 TypeAttributes type_attributes = TypeAttr;
786 ptype = parent.ResolveType (ec);
791 if (TypeManager.NamespaceClash (Name, Location)) {
796 ModuleBuilder builder = CodeGen.ModuleBuilder;
797 TypeBuilder = builder.DefineType (
798 Name, type_attributes, ptype, null);
801 TypeBuilder builder = Parent.DefineType ();
805 TypeBuilder = builder.DefineNestedType (
806 Basename, type_attributes, ptype, null);
810 // Structs with no fields need to have at least one byte.
811 // The right thing would be to set the PackingSize in a DefineType
812 // but there are no functions that allow interfaces *and* the size to
816 if (!is_class && !have_nonstatic_fields){
817 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
818 FieldAttributes.Private);
821 // add interfaces that were not added at type creation
822 if (ifaces != null) {
823 foreach (TypeExpr iface in ifaces) {
824 Type itype = iface.ResolveType (ec);
825 TypeBuilder.AddInterfaceImplementation (itype);
830 // Finish the setup for the EmitContext
832 ec.ContainerType = TypeBuilder;
834 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
836 if ((parent != null) && parent.IsAttribute) {
837 RootContext.RegisterAttribute (this);
838 TypeManager.RegisterAttrType (TypeBuilder, this);
840 RootContext.RegisterOrder (this);
842 if (Interfaces != null) {
843 foreach (Interface iface in Interfaces)
844 if (iface.DefineType () == null) {
851 foreach (TypeContainer tc in Types)
852 if (tc.DefineType () == null) {
858 if (Delegates != null) {
859 foreach (Delegate d in Delegates)
860 if (d.DefineType () == null) {
867 foreach (Enum en in Enums)
868 if (en.DefineType () == null) {
880 /// Defines the MemberCore objects that are in the `list' Arraylist
882 /// The `defined_names' array contains a list of members defined in
885 static ArrayList remove_list = new ArrayList ();
886 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
890 remove_list.Clear ();
892 foreach (MemberCore mc in list){
894 if (defined_names != null)
895 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
900 if (RootContext.WarningLevel >= 4){
901 if ((mc.ModFlags & Modifiers.NEW) != 0)
902 Warning_KeywordNewNotRequired (mc.Location, mc);
904 } else if (mc is MethodCore)
905 ((MethodCore) mc).OverridesSomething = true;
907 if (!mc.Define (this)){
908 remove_list.Add (mc);
915 MemberInfo match = defined_names [idx];
917 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
921 // If we are both methods, let the method resolution emit warnings
923 if (match is MethodBase && mc is MethodCore)
926 if ((mc.ModFlags & Modifiers.NEW) == 0) {
928 if (!(match is EventInfo)) {
929 Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
933 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
937 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
941 foreach (object o in remove_list)
944 remove_list.Clear ();
948 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
949 // class is consisten. Either it is `Item' or it is the name defined by all the
950 // indexers with the `IndexerName' attribute.
952 // Turns out that the IndexerNameAttribute is applied to each indexer,
953 // but it is never emitted, instead a DefaultName attribute is attached
956 void DefineIndexers ()
958 string class_indexer_name = null;
961 // If there's both an explicit and an implicit interface implementation, the
962 // explicit one actually implements the interface while the other one is just
963 // a normal indexer. See bug #37714.
965 ArrayList list = new ArrayList ();
966 foreach (Indexer i in Indexers){
967 if (i.ExplicitInterfaceName != null)
970 foreach (Indexer i in Indexers){
971 if (i.ExplicitInterfaceName == null)
975 foreach (Indexer i in list){
980 name = i.IndexerName;
982 if (i.InterfaceType != null)
985 if (class_indexer_name == null){
986 class_indexer_name = name;
990 if (name == class_indexer_name)
994 668, "Two indexers have different names, " +
995 " you should use the same name for all your indexers");
997 if (class_indexer_name == null)
998 class_indexer_name = "Item";
999 IndexerName = class_indexer_name;
1002 static void Error_KeywordNotAllowed (Location loc)
1004 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1008 /// Populates our TypeBuilder with fields and methods
1010 public override bool DefineMembers (TypeContainer container)
1012 MemberInfo [] defined_names = null;
1014 if (interface_order != null){
1015 foreach (Interface iface in interface_order)
1016 if ((iface.ModFlags & Modifiers.NEW) == 0)
1017 iface.DefineMembers (this);
1019 Error_KeywordNotAllowed (iface.Location);
1022 if (RootContext.WarningLevel > 1){
1026 // This code throws an exception in the comparer
1027 // I guess the string is not an object?
1029 ptype = TypeBuilder.BaseType;
1031 defined_names = (MemberInfo []) FindMembers (
1032 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1033 BindingFlags.Public | BindingFlags.Instance |
1034 BindingFlags.Static, null, null);
1036 Array.Sort (defined_names, mif_compare);
1040 Class pclass = Parent as Class;
1041 if (pclass != null) {
1042 string pname = null;
1044 Type t = pclass.TypeBuilder.BaseType;
1045 while ((t != null) && (ptype == null)) {
1046 pname = t.FullName + "." + Basename;
1047 ptype = RootContext.LookupType (this, pname, true, Location.Null);
1051 if ((ModFlags & Modifiers.NEW) != 0) {
1053 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1054 "inherited member. The keyword new is not required.");
1055 } else if (ptype != null) {
1056 Report.Warning (108, Location, "The keyword new is required on `" +
1057 Name + "' because it hides inherited member '" +
1060 } else if ((ModFlags & Modifiers.NEW) != 0)
1061 Error_KeywordNotAllowed (Location);
1063 if (constants != null)
1064 DefineMembers (constants, defined_names);
1067 DefineMembers (fields, defined_names);
1070 if (instance_constructors == null){
1071 if (default_constructor == null)
1072 DefineDefaultConstructor (false);
1075 if (initialized_static_fields != null &&
1076 default_static_constructor == null)
1077 DefineDefaultConstructor (true);
1080 if (this is Struct){
1082 // Structs can not have initialized instance
1085 if (initialized_static_fields != null &&
1086 default_static_constructor == null)
1087 DefineDefaultConstructor (true);
1089 if (initialized_fields != null)
1090 ReportStructInitializedInstanceError ();
1093 Pending = PendingImplementation.GetPendingImplementations (this);
1096 // Constructors are not in the defined_names array
1098 if (instance_constructors != null)
1099 DefineMembers (instance_constructors, null);
1101 if (default_static_constructor != null)
1102 default_static_constructor.Define (this);
1104 if (methods != null)
1105 DefineMembers (methods, defined_names);
1107 if (properties != null)
1108 DefineMembers (properties, defined_names);
1111 DefineMembers (events, defined_names);
1113 if (indexers != null) {
1116 IndexerName = "Item";
1118 if (operators != null){
1119 DefineMembers (operators, null);
1121 CheckPairedOperators ();
1125 DefineMembers (enums, defined_names);
1127 if (delegates != null)
1128 DefineMembers (delegates, defined_names);
1131 if (TypeBuilder.BaseType != null)
1132 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1134 member_cache = new MemberCache (this);
1141 public override bool Define (TypeContainer container)
1143 if (interface_order != null){
1144 foreach (Interface iface in interface_order)
1145 if ((iface.ModFlags & Modifiers.NEW) == 0)
1146 iface.Define (this);
1153 /// This function is based by a delegate to the FindMembers routine
1155 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1161 /// This filter is used by FindMembers, and we just keep
1162 /// a global for the filter to `AlwaysAccept'
1164 static MemberFilter accepting_filter;
1168 /// A member comparission method based on name only
1170 static IComparer mif_compare;
1172 static TypeContainer ()
1174 accepting_filter = new MemberFilter (AlwaysAccept);
1175 mif_compare = new MemberInfoCompare ();
1179 /// This method returns the members of this type just like Type.FindMembers would
1180 /// Only, we need to use this for types which are _being_ defined because MS'
1181 /// implementation can't take care of that.
1184 // FIXME: return an empty static array instead of null, that cleans up
1185 // some code and is consistent with some coding conventions I just found
1189 // Notice that in various cases we check if our field is non-null,
1190 // something that would normally mean that there was a bug elsewhere.
1192 // The problem happens while we are defining p-invoke methods, as those
1193 // will trigger a FindMembers, but this happens before things are defined
1195 // Since the whole process is a no-op, it is fine to check for null here.
1197 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1198 MemberFilter filter, object criteria)
1200 ArrayList members = null;
1203 if ((bf & BindingFlags.Public) != 0)
1204 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1206 if ((bf & BindingFlags.NonPublic) != 0)
1207 modflags |= Modifiers.PRIVATE;
1209 int static_mask = 0, static_flags = 0;
1210 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1211 case BindingFlags.Static:
1212 static_mask = static_flags = Modifiers.STATIC;
1215 case BindingFlags.Instance:
1216 static_mask = Modifiers.STATIC;
1221 static_mask = static_flags = 0;
1225 Timer.StartTimer (TimerType.TcFindMembers);
1228 filter = accepting_filter;
1230 if ((mt & MemberTypes.Field) != 0) {
1231 if (fields != null) {
1232 int len = fields.Count;
1233 for (int i = 0; i < len; i++) {
1234 Field f = (Field) fields [i];
1236 if ((f.ModFlags & modflags) == 0)
1238 if ((f.ModFlags & static_mask) != static_flags)
1241 FieldBuilder fb = f.FieldBuilder;
1242 if (fb != null && filter (fb, criteria) == true) {
1243 if (members == null)
1244 members = new ArrayList ();
1251 if (constants != null) {
1252 int len = constants.Count;
1253 for (int i = 0; i < len; i++) {
1254 Const con = (Const) constants [i];
1256 if ((con.ModFlags & modflags) == 0)
1258 if ((con.ModFlags & static_mask) != static_flags)
1261 FieldBuilder fb = con.FieldBuilder;
1262 if (fb != null && filter (fb, criteria) == true) {
1263 if (members == null)
1264 members = new ArrayList ();
1272 if ((mt & MemberTypes.Method) != 0) {
1273 if (methods != null) {
1274 int len = methods.Count;
1275 for (int i = 0; i < len; i++) {
1276 Method m = (Method) methods [i];
1278 if ((m.ModFlags & modflags) == 0)
1280 if ((m.ModFlags & static_mask) != static_flags)
1283 MethodBuilder mb = m.MethodBuilder;
1285 if (mb != null && filter (mb, criteria) == true) {
1286 if (members == null)
1287 members = new ArrayList ();
1294 if (operators != null) {
1295 int len = operators.Count;
1296 for (int i = 0; i < len; i++) {
1297 Operator o = (Operator) operators [i];
1299 if ((o.ModFlags & modflags) == 0)
1301 if ((o.ModFlags & static_mask) != static_flags)
1304 MethodBuilder ob = o.OperatorMethodBuilder;
1305 if (ob != null && filter (ob, criteria) == true) {
1306 if (members == null)
1307 members = new ArrayList ();
1314 if (properties != null) {
1315 int len = properties.Count;
1316 for (int i = 0; i < len; i++) {
1317 Property p = (Property) properties [i];
1319 if ((p.ModFlags & modflags) == 0)
1321 if ((p.ModFlags & static_mask) != static_flags)
1327 if (b != null && filter (b, criteria) == true) {
1328 if (members == null)
1329 members = new ArrayList ();
1335 if (b != null && filter (b, criteria) == true) {
1336 if (members == null)
1337 members = new ArrayList ();
1344 if (indexers != null) {
1345 int len = indexers.Count;
1346 for (int i = 0; i < len; i++) {
1347 Indexer ix = (Indexer) indexers [i];
1349 if ((ix.ModFlags & modflags) == 0)
1351 if ((ix.ModFlags & static_mask) != static_flags)
1357 if (b != null && filter (b, criteria) == true) {
1358 if (members == null)
1359 members = new ArrayList ();
1365 if (b != null && filter (b, criteria) == true) {
1366 if (members == null)
1367 members = new ArrayList ();
1375 if ((mt & MemberTypes.Event) != 0) {
1376 if (events != null) {
1377 int len = events.Count;
1378 for (int i = 0; i < len; i++) {
1379 Event e = (Event) events [i];
1381 if ((e.ModFlags & modflags) == 0)
1383 if ((e.ModFlags & static_mask) != static_flags)
1386 MemberInfo eb = e.EventBuilder;
1387 if (eb != null && filter (eb, criteria) == true) {
1388 if (members == null)
1389 members = new ArrayList ();
1391 members.Add (e.EventBuilder);
1397 if ((mt & MemberTypes.Property) != 0){
1398 if (properties != null) {
1399 int len = properties.Count;
1400 for (int i = 0; i < len; i++) {
1401 Property p = (Property) properties [i];
1403 if ((p.ModFlags & modflags) == 0)
1405 if ((p.ModFlags & static_mask) != static_flags)
1408 MemberInfo pb = p.PropertyBuilder;
1409 if (pb != null && filter (pb, criteria) == true) {
1410 if (members == null)
1411 members = new ArrayList ();
1413 members.Add (p.PropertyBuilder);
1418 if (indexers != null) {
1419 int len = indexers.Count;
1420 for (int i = 0; i < len; i++) {
1421 Indexer ix = (Indexer) indexers [i];
1423 if ((ix.ModFlags & modflags) == 0)
1425 if ((ix.ModFlags & static_mask) != static_flags)
1428 MemberInfo ib = ix.PropertyBuilder;
1429 if (ib != null && filter (ib, criteria) == true) {
1430 if (members == null)
1431 members = new ArrayList ();
1433 members.Add (ix.PropertyBuilder);
1439 if ((mt & MemberTypes.NestedType) != 0) {
1440 if (types != null) {
1441 int len = types.Count;
1442 for (int i = 0; i < len; i++) {
1443 TypeContainer t = (TypeContainer) types [i];
1445 if ((t.ModFlags & modflags) == 0)
1448 TypeBuilder tb = t.TypeBuilder;
1449 if (tb != null && (filter (tb, criteria) == true)) {
1450 if (members == null)
1451 members = new ArrayList ();
1458 if (enums != null) {
1459 int len = enums.Count;
1460 for (int i = 0; i < len; i++) {
1461 Enum en = (Enum) enums [i];
1463 if ((en.ModFlags & modflags) == 0)
1466 TypeBuilder tb = en.TypeBuilder;
1467 if (tb != null && (filter (tb, criteria) == true)) {
1468 if (members == null)
1469 members = new ArrayList ();
1476 if (delegates != null) {
1477 int len = delegates.Count;
1478 for (int i = 0; i < len; i++) {
1479 Delegate d = (Delegate) delegates [i];
1481 if ((d.ModFlags & modflags) == 0)
1484 TypeBuilder tb = d.TypeBuilder;
1485 if (tb != null && (filter (tb, criteria) == true)) {
1486 if (members == null)
1487 members = new ArrayList ();
1494 if (interfaces != null) {
1495 int len = interfaces.Count;
1496 for (int i = 0; i < len; i++) {
1497 Interface iface = (Interface) interfaces [i];
1499 if ((iface.ModFlags & modflags) == 0)
1502 TypeBuilder tb = iface.TypeBuilder;
1503 if (tb != null && (filter (tb, criteria) == true)) {
1504 if (members == null)
1505 members = new ArrayList ();
1513 if ((mt & MemberTypes.Constructor) != 0){
1514 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1515 int len = instance_constructors.Count;
1516 for (int i = 0; i < len; i++) {
1517 Constructor c = (Constructor) instance_constructors [i];
1519 ConstructorBuilder cb = c.ConstructorBuilder;
1520 if (cb != null && filter (cb, criteria) == true) {
1521 if (members == null)
1522 members = new ArrayList ();
1529 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1530 ConstructorBuilder cb =
1531 default_static_constructor.ConstructorBuilder;
1533 if (cb != null && filter (cb, criteria) == true) {
1534 if (members == null)
1535 members = new ArrayList ();
1543 // Lookup members in parent if requested.
1545 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1546 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1547 if (list.Count > 0) {
1548 if (members == null)
1549 members = new ArrayList ();
1551 members.AddRange (list);
1555 Timer.StopTimer (TimerType.TcFindMembers);
1557 if (members == null)
1558 return MemberList.Empty;
1560 return new MemberList (members);
1563 public override MemberCache MemberCache {
1565 return member_cache;
1569 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1570 MemberFilter filter, object criteria)
1572 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1575 return ds.FindMembers (mt, bf, filter, criteria);
1577 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1582 // FindMethods will look for methods not only in the type `t', but in
1583 // any interfaces implemented by the type.
1585 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1586 MemberFilter filter, object criteria)
1592 /// Emits the values for the constants
1594 public void EmitConstants ()
1596 if (constants != null)
1597 foreach (Const con in constants)
1598 con.EmitConstant (this);
1603 /// Emits the code, this step is performed after all
1604 /// the types, enumerations, constructors
1608 if (instance_constructors != null)
1609 foreach (Constructor c in instance_constructors)
1612 if (default_static_constructor != null)
1613 default_static_constructor.Emit (this);
1615 if (methods != null)
1616 foreach (Method m in methods)
1619 if (operators != null)
1620 foreach (Operator o in operators)
1623 if (properties != null)
1624 foreach (Property p in properties)
1627 if (indexers != null){
1628 foreach (Indexer ix in indexers)
1631 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1632 this, IndexerName, ModFlags, Location);
1633 TypeBuilder.SetCustomAttribute (cb);
1637 foreach (Field f in fields)
1640 if (events != null){
1641 foreach (Event e in Events)
1645 if (Pending != null)
1646 if (Pending.VerifyPendingMethods ())
1649 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
1652 // Check for internal or private fields that were never assigned
1654 if (RootContext.WarningLevel >= 3) {
1655 if (fields != null){
1656 foreach (Field f in fields) {
1657 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
1660 if ((f.status & Field.Status.USED) == 0){
1662 169, f.Location, "Private field " +
1663 MakeName (f.Name) + " is never used");
1668 // Only report 649 on level 4
1670 if (RootContext.WarningLevel < 4)
1673 if ((f.status & Field.Status.ASSIGNED) != 0)
1678 "Field " + MakeName (f.Name) + " is never assigned " +
1679 " to and will always have its default value");
1683 if (events != null){
1684 foreach (Event e in events){
1686 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1691 // if (types != null)
1692 // foreach (TypeContainer tc in types)
1696 public override void CloseType ()
1703 TypeBuilder.CreateType ();
1704 } catch (TypeLoadException){
1706 // This is fine, the code still created the type
1708 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1709 // Console.WriteLine (e.Message);
1711 Console.WriteLine ("In type: " + Name);
1716 foreach (Enum en in Enums)
1719 if (interface_order != null){
1720 foreach (Interface iface in interface_order)
1725 foreach (TypeContainer tc in Types)
1729 foreach (TypeContainer tc in Types)
1730 if (!(tc is Struct))
1734 if (Delegates != null)
1735 foreach (Delegate d in Delegates)
1743 initialized_fields = null;
1744 initialized_static_fields = null;
1747 interface_order = null;
1753 default_constructor = null;
1754 default_static_constructor = null;
1758 parent_container = null;
1759 member_cache = null;
1762 public string MakeName (string n)
1764 return "`" + Name + "." + n + "'";
1767 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1770 108, l, "The keyword new is required on " +
1771 MakeName (mi.Name) + " because it hides `" +
1772 mi.ReflectedType.Name + "." + mi.Name + "'");
1775 public void Warning_KeywordNewNotRequired (Location l, MemberCore mc)
1778 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1779 "inherited member, the keyword new is not required");
1782 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
1785 72, l, MakeName (mi.Name) + " : cannot override; `" +
1786 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
1789 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1795 // Performs the validation on a Method's modifiers (properties have
1796 // the same properties).
1798 public bool MethodModifiersValid (int flags, string n, Location loc)
1800 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1801 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1802 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1806 // At most one of static, virtual or override
1808 if ((flags & Modifiers.STATIC) != 0){
1809 if ((flags & vao) != 0){
1811 112, loc, "static method " + MakeName (n) + "can not be marked " +
1812 "as virtual, abstract or override");
1817 if (this is Struct){
1818 if ((flags & va) != 0){
1819 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1824 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1826 113, loc, MakeName (n) +
1827 " marked as override cannot be marked as new or virtual");
1832 // If the declaration includes the abstract modifier, then the
1833 // declaration does not include static, virtual or extern
1835 if ((flags & Modifiers.ABSTRACT) != 0){
1836 if ((flags & Modifiers.EXTERN) != 0){
1838 180, loc, MakeName (n) + " can not be both abstract and extern");
1842 if ((flags & Modifiers.VIRTUAL) != 0){
1844 503, loc, MakeName (n) + " can not be both abstract and virtual");
1848 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1850 513, loc, MakeName (n) +
1851 " is abstract but its container class is not");
1857 if ((flags & Modifiers.PRIVATE) != 0){
1858 if ((flags & vao) != 0){
1860 621, loc, MakeName (n) +
1861 " virtual or abstract members can not be private");
1866 if ((flags & Modifiers.SEALED) != 0){
1867 if ((flags & Modifiers.OVERRIDE) == 0){
1869 238, loc, MakeName (n) +
1870 " cannot be sealed because it is not an override");
1878 Hashtable builder_and_args;
1880 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1882 if (builder_and_args == null)
1883 builder_and_args = new Hashtable ();
1888 /// Performs checks for an explicit interface implementation. First it
1889 /// checks whether the `interface_type' is a base inteface implementation.
1890 /// Then it checks whether `name' exists in the interface type.
1892 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1896 if (ifaces != null){
1897 foreach (TypeExpr t in ifaces){
1898 if (t.Type == interface_type){
1906 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1913 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1915 Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1922 string IMemberContainer.Name {
1928 Type IMemberContainer.Type {
1934 IMemberContainer IMemberContainer.Parent {
1936 return parent_container;
1940 MemberCache IMemberContainer.MemberCache {
1942 return member_cache;
1946 bool IMemberContainer.IsInterface {
1952 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1954 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1958 // Operator pair checking
1961 class OperatorEntry {
1963 public Type ret_type;
1964 public Type type1, type2;
1966 public Operator.OpType ot;
1968 public OperatorEntry (int f, Operator o)
1972 ret_type = o.OperatorMethod.GetReturnType ();
1973 Type [] pt = o.OperatorMethod.ParameterTypes;
1977 ot = o.OperatorType;
1980 public override int GetHashCode ()
1982 return ret_type.GetHashCode ();
1985 public override bool Equals (object o)
1987 OperatorEntry other = (OperatorEntry) o;
1989 if (other.ret_type != ret_type)
1991 if (other.type1 != type1)
1993 if (other.type2 != type2)
2000 // Checks that some operators come in pairs:
2006 // They are matched based on the return type and the argument types
2008 void CheckPairedOperators ()
2010 Hashtable pairs = new Hashtable (null, null);
2011 Operator true_op = null;
2012 Operator false_op = null;
2013 bool has_equality_or_inequality = false;
2015 // Register all the operators we care about.
2016 foreach (Operator op in operators){
2019 switch (op.OperatorType){
2020 case Operator.OpType.Equality:
2022 has_equality_or_inequality = true;
2024 case Operator.OpType.Inequality:
2026 has_equality_or_inequality = true;
2029 case Operator.OpType.True:
2032 case Operator.OpType.False:
2036 case Operator.OpType.GreaterThan:
2038 case Operator.OpType.LessThan:
2041 case Operator.OpType.GreaterThanOrEqual:
2043 case Operator.OpType.LessThanOrEqual:
2049 OperatorEntry oe = new OperatorEntry (reg, op);
2051 object o = pairs [oe];
2055 oe = (OperatorEntry) o;
2060 if (true_op != null){
2061 if (false_op == null)
2062 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2063 } else if (false_op != null)
2064 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2067 // Look for the mistakes.
2069 foreach (DictionaryEntry de in pairs){
2070 OperatorEntry oe = (OperatorEntry) de.Key;
2077 case Operator.OpType.Equality:
2080 case Operator.OpType.Inequality:
2083 case Operator.OpType.GreaterThan:
2086 case Operator.OpType.LessThan:
2089 case Operator.OpType.GreaterThanOrEqual:
2092 case Operator.OpType.LessThanOrEqual:
2096 Report.Error (216, oe.op.Location,
2097 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2100 if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2101 MethodSignature equals_ms = new MethodSignature (
2102 "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2103 MethodSignature hash_ms = new MethodSignature (
2104 "GetHashCode", TypeManager.int32_type, new Type [0]);
2106 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2107 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2109 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2110 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2113 bool equals_ok = false;
2114 if ((equals_ml != null) && (equals_ml.Count == 1))
2115 equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2116 bool hash_ok = false;
2117 if ((hash_ml != null) && (hash_ml.Count == 1))
2118 hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2121 Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2122 "not override Object.Equals (object o)");
2124 Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2125 "not override Object.GetHashCode ()");
2132 public class Class : TypeContainer {
2134 // Modifiers allowed in a class declaration
2136 public const int AllowedModifiers =
2139 Modifiers.PROTECTED |
2140 Modifiers.INTERNAL |
2142 Modifiers.ABSTRACT |
2146 public Class (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2147 : base (ns, parent, name, l)
2151 if (parent.Parent == null)
2152 accmods = Modifiers.INTERNAL;
2154 accmods = Modifiers.PRIVATE;
2156 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2157 this.attributes = attrs;
2161 // FIXME: How do we deal with the user specifying a different
2164 public override TypeAttributes TypeAttr {
2166 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2171 public class Struct : TypeContainer {
2173 // Modifiers allowed in a struct declaration
2175 public const int AllowedModifiers =
2178 Modifiers.PROTECTED |
2179 Modifiers.INTERNAL |
2183 public Struct (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2184 : base (ns, parent, name, l)
2188 if (parent.Parent == null)
2189 accmods = Modifiers.INTERNAL;
2191 accmods = Modifiers.PRIVATE;
2193 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2195 this.ModFlags |= Modifiers.SEALED;
2196 this.attributes = attrs;
2201 // FIXME: Allow the user to specify a different set of attributes
2202 // in some cases (Sealed for example is mandatory for a class,
2203 // but what SequentialLayout can be changed
2205 public override TypeAttributes TypeAttr {
2207 return base.TypeAttr |
2208 TypeAttributes.SequentialLayout |
2209 TypeAttributes.Sealed |
2210 TypeAttributes.BeforeFieldInit;
2215 public abstract class MethodCore : MemberBase {
2216 public readonly Parameters Parameters;
2217 protected Block block;
2218 protected DeclSpace ds;
2221 // Parameters, cached for semantic analysis.
2223 protected InternalParameters parameter_info;
2224 protected Type [] parameter_types;
2227 // This is set from TypeContainer.DefineMembers if this method overrides something.
2229 public bool OverridesSomething;
2231 public MethodCore (DeclSpace ds, Expression type, int mod, int allowed_mod,
2232 string name, Attributes attrs, Parameters parameters, Location loc)
2233 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
2235 Parameters = parameters;
2240 // Returns the System.Type array for the parameters of this method
2242 public Type [] ParameterTypes {
2244 return parameter_types;
2248 public InternalParameters ParameterInfo
2251 return parameter_info;
2255 public Block Block {
2265 protected virtual bool DoDefineParameters ()
2267 // Check if arguments were correct
2268 parameter_types = Parameters.GetParameterInfo (ds);
2269 if ((parameter_types == null) || !CheckParameters (ds, parameter_types))
2272 parameter_info = new InternalParameters (ds, Parameters);
2274 Parameter array_param = Parameters.ArrayParameter;
2275 if ((array_param != null) &&
2276 (!array_param.ParameterType.IsArray ||
2277 (array_param.ParameterType.GetArrayRank () != 1))) {
2278 Report.Error (225, Location, "params parameter has to be a single dimensional array");
2285 public CallingConventions GetCallingConvention (bool is_class)
2287 CallingConventions cc = 0;
2289 cc = Parameters.GetCallingConvention ();
2292 if ((ModFlags & Modifiers.STATIC) == 0)
2293 cc |= CallingConventions.HasThis;
2295 // FIXME: How is `ExplicitThis' used in C#?
2301 // The method's attributes are passed in because we need to extract
2302 // the "return:" attribute from there to apply on the return type
2304 static public void LabelParameters (EmitContext ec,
2306 Parameters parameters,
2307 Attributes method_attrs,
2311 // Define each type attribute (in/out/ref) and
2312 // the argument names.
2314 Parameter [] p = parameters.FixedParameters;
2317 MethodBuilder mb = null;
2318 ConstructorBuilder cb = null;
2320 if (builder is MethodBuilder)
2321 mb = (MethodBuilder) builder;
2323 cb = (ConstructorBuilder) builder;
2326 for (i = 0; i < p.Length; i++) {
2327 ParameterBuilder pb;
2328 ParameterAttributes par_attr = p [i].Attributes;
2331 pb = cb.DefineParameter (
2332 i + 1, par_attr, p [i].Name);
2334 pb = mb.DefineParameter (
2335 i + 1, par_attr, p [i].Name);
2337 Attributes attr = p [i].OptAttributes;
2339 Attribute.ApplyAttributes (ec, pb, pb, attr);
2341 if (par_attr == ParameterAttributes.Out){
2342 if (attr.Contains (TypeManager.in_attribute_type))
2343 Report.Error (36, loc,
2344 "Can not use [In] attribute on out parameter");
2350 if (parameters.ArrayParameter != null){
2351 ParameterBuilder pb;
2352 Parameter array_param = parameters.ArrayParameter;
2355 pb = cb.DefineParameter (
2356 i + 1, array_param.Attributes,
2359 pb = mb.DefineParameter (
2360 i + 1, array_param.Attributes,
2363 CustomAttributeBuilder a = new CustomAttributeBuilder (
2364 TypeManager.cons_param_array_attribute, new object [0]);
2366 pb.SetCustomAttribute (a);
2370 // And now for the return type attribute decoration
2372 ParameterBuilder ret_pb;
2373 Attributes ret_attrs = null;
2375 if (mb == null || method_attrs == null)
2378 foreach (AttributeSection asec in method_attrs.AttributeSections) {
2380 if (asec.Target != "return")
2383 if (ret_attrs == null)
2384 ret_attrs = new Attributes (asec);
2386 ret_attrs.AddAttributeSection (asec);
2389 if (ret_attrs != null) {
2391 ret_pb = mb.DefineParameter (0, ParameterAttributes.None, "");
2392 Attribute.ApplyAttributes (ec, ret_pb, ret_pb, ret_attrs);
2394 } catch (ArgumentOutOfRangeException) {
2397 ".NET SDK 1.0 does not permit setting custom attributes" +
2398 " on the return type of a method");
2404 public class Method : MethodCore, IIteratorContainer {
2405 public MethodBuilder MethodBuilder;
2406 public MethodData MethodData;
2409 /// Modifiers allowed in a class declaration
2411 const int AllowedModifiers =
2414 Modifiers.PROTECTED |
2415 Modifiers.INTERNAL |
2420 Modifiers.OVERRIDE |
2421 Modifiers.ABSTRACT |
2426 // return_type can be "null" for VOID values.
2428 public Method (DeclSpace ds, Expression return_type, int mod, string name,
2429 Parameters parameters, Attributes attrs, Location l)
2430 : base (ds, return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2434 // Returns the `System.Type' for the ReturnType of this
2435 // function. Provides a nice cache. (used between semantic analysis
2436 // and actual code generation
2438 public Type GetReturnType ()
2443 // Whether this is an operator method.
2444 public bool IsOperator;
2446 void DuplicateEntryPoint (MethodInfo b, Location location)
2450 "Program `" + CodeGen.FileName +
2451 "' has more than one entry point defined: `" +
2452 TypeManager.CSharpSignature(b) + "'");
2455 void Report28 (MethodInfo b)
2459 "`" + TypeManager.CSharpSignature(b) +
2460 "' has the wrong signature to be an entry point");
2463 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2465 if (b.ReturnType != TypeManager.void_type &&
2466 b.ReturnType != TypeManager.int32_type)
2469 if (pinfo.Count == 0)
2472 if (pinfo.Count > 1)
2475 Type t = pinfo.ParameterType(0);
2477 (t.GetArrayRank() == 1) &&
2478 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
2479 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2486 // Checks our base implementation if any
2488 protected override bool CheckBase (TypeContainer container)
2490 base.CheckBase (container);
2492 // Check whether arguments were correct.
2493 if (!DoDefineParameters ())
2496 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2498 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2502 mi_this = TypeContainer.FindMembers (
2503 container.TypeBuilder, MemberTypes.Method,
2504 BindingFlags.NonPublic | BindingFlags.Public |
2505 BindingFlags.Static | BindingFlags.Instance |
2506 BindingFlags.DeclaredOnly,
2507 MethodSignature.method_signature_filter, ms);
2509 if (mi_this.Count > 0) {
2510 Report.Error (111, Location, "Class `" + container.Name + "' " +
2511 "already defines a member called `" + Name + "' " +
2512 "with the same parameter types");
2518 // Verify if the parent has a type with the same name, and then
2519 // check whether we have to create a new slot for it or not.
2521 Type ptype = container.TypeBuilder.BaseType;
2523 // ptype is only null for System.Object while compiling corlib.
2525 MemberList mi, mi_static, mi_instance;
2527 mi_instance = TypeContainer.FindMembers (
2528 ptype, MemberTypes.Method,
2529 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2530 MethodSignature.inheritable_method_signature_filter,
2533 if (mi_instance.Count > 0){
2536 mi_static = TypeContainer.FindMembers (
2537 ptype, MemberTypes.Method,
2538 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2539 MethodSignature.inheritable_method_signature_filter, ms);
2541 if (mi_static.Count > 0)
2547 if (mi != null && mi.Count > 0){
2548 parent_method = (MethodInfo) mi [0];
2549 string name = parent_method.DeclaringType.Name + "." +
2552 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
2555 if ((ModFlags & Modifiers.NEW) == 0) {
2556 Type parent_ret = TypeManager.TypeToCoreType (
2557 parent_method.ReturnType);
2559 if (parent_ret != MemberType) {
2561 508, Location, container.MakeName (Name) + ": cannot " +
2562 "change return type when overriding " +
2563 "inherited member " + name);
2568 if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
2569 WarningNotHiding (container);
2571 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2572 Report.Error (115, Location,
2573 container.MakeName (Name) +
2574 " no suitable methods found to override");
2577 } else if ((ModFlags & Modifiers.NEW) != 0)
2578 WarningNotHiding (container);
2586 public override bool Define (TypeContainer container)
2588 if (!DoDefine (container))
2591 if (!CheckBase (container))
2594 CallingConventions cc = GetCallingConvention (container is Class);
2596 MethodData = new MethodData (container, this, null, MemberType,
2597 ParameterTypes, ParameterInfo, cc,
2598 OptAttributes, ModFlags, flags, true);
2600 if (!MethodData.Define (container))
2604 // Setup iterator if we are one
2606 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
2607 IteratorHandler ih = new IteratorHandler (
2608 Name, container, MemberType,
2609 ParameterTypes, ParameterInfo,
2610 ModFlags, Location);
2612 Block new_block = ih.Setup (block);
2613 if (new_block == null)
2618 MethodBuilder = MethodData.MethodBuilder;
2621 // This is used to track the Entry Point,
2623 if (Name == "Main" &&
2624 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
2625 (RootContext.MainClass == null ||
2626 RootContext.MainClass == container.TypeBuilder.FullName)){
2627 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2628 if (RootContext.EntryPoint == null) {
2629 RootContext.EntryPoint = MethodBuilder;
2630 RootContext.EntryPointLocation = Location;
2632 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2633 DuplicateEntryPoint (MethodBuilder, Location);
2636 Report28(MethodBuilder);
2645 public void Emit (TypeContainer container)
2647 MethodData.Emit (container, Block, this);
2652 void IIteratorContainer.SetYields ()
2654 ModFlags |= Modifiers.METHOD_YIELDS;
2658 public abstract class ConstructorInitializer {
2659 ArrayList argument_list;
2660 ConstructorInfo parent_constructor;
2661 Parameters parameters;
2664 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2667 this.argument_list = argument_list;
2668 this.parameters = parameters;
2672 public ArrayList Arguments {
2674 return argument_list;
2678 public bool Resolve (EmitContext ec)
2680 Expression parent_constructor_group;
2683 ec.CurrentBlock = new Block (null, Block.Flags.Implicit, parameters);
2685 if (argument_list != null){
2686 foreach (Argument a in argument_list){
2687 if (!a.Resolve (ec, loc))
2691 ec.CurrentBlock = null;
2693 if (this is ConstructorBaseInitializer) {
2694 if (ec.ContainerType.BaseType == null)
2697 t = ec.ContainerType.BaseType;
2698 if (ec.ContainerType.IsValueType) {
2699 Report.Error (522, loc,
2700 "structs cannot call base class constructors");
2704 t = ec.ContainerType;
2706 parent_constructor_group = Expression.MemberLookup (
2707 ec, t, null, t, ".ctor",
2708 MemberTypes.Constructor,
2709 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2712 if (parent_constructor_group == null){
2713 Report.Error (1501, loc,
2714 "Can not find a constructor for this argument list");
2718 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2719 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2721 if (parent_constructor == null){
2722 Report.Error (1501, loc,
2723 "Can not find a constructor for this argument list");
2730 public void Emit (EmitContext ec)
2732 if (parent_constructor != null){
2733 ec.Mark (loc, false);
2735 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2737 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
2742 public class ConstructorBaseInitializer : ConstructorInitializer {
2743 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2744 base (argument_list, pars, l)
2749 public class ConstructorThisInitializer : ConstructorInitializer {
2750 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2751 base (argument_list, pars, l)
2756 public class Constructor : MethodCore {
2757 public ConstructorBuilder ConstructorBuilder;
2758 public ConstructorInitializer Initializer;
2759 new public Attributes OptAttributes;
2762 // Modifiers allowed for a constructor.
2764 public const int AllowedModifiers =
2766 Modifiers.PROTECTED |
2767 Modifiers.INTERNAL |
2774 // The spec claims that static is not permitted, but
2775 // my very own code has static constructors.
2777 public Constructor (DeclSpace ds, string name, Parameters args,
2778 ConstructorInitializer init, Location l)
2779 : base (ds, null, 0, AllowedModifiers, name, null, args, l)
2785 // Returns true if this is a default constructor
2787 public bool IsDefault ()
2789 if ((ModFlags & Modifiers.STATIC) != 0)
2790 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2791 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2794 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2795 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2796 (Initializer is ConstructorBaseInitializer) &&
2797 (Initializer.Arguments == null);
2801 // Creates the ConstructorBuilder
2803 public override bool Define (TypeContainer container)
2805 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2806 MethodAttributes.SpecialName);
2808 // Check if arguments were correct.
2809 if (!DoDefineParameters ())
2812 if ((ModFlags & Modifiers.STATIC) != 0){
2813 ca |= MethodAttributes.Static | MethodAttributes.Private;
2815 if (container is Struct && ParameterTypes.Length == 0){
2818 "Structs can not contain explicit parameterless " +
2822 ca |= MethodAttributes.HideBySig;
2824 if ((ModFlags & Modifiers.PUBLIC) != 0)
2825 ca |= MethodAttributes.Public;
2826 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2827 if ((ModFlags & Modifiers.INTERNAL) != 0)
2828 ca |= MethodAttributes.FamORAssem;
2830 ca |= MethodAttributes.Family;
2831 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2832 ca |= MethodAttributes.Assembly;
2833 else if (IsDefault ())
2834 ca |= MethodAttributes.Public;
2836 ca |= MethodAttributes.Private;
2839 ConstructorBuilder = container.TypeBuilder.DefineConstructor (
2840 ca, GetCallingConvention (container is Class), ParameterTypes);
2842 if ((ModFlags & Modifiers.UNSAFE) != 0)
2843 ConstructorBuilder.InitLocals = false;
2846 // HACK because System.Reflection.Emit is lame
2848 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2851 "Class `" +container.Name+ "' already contains a definition with the " +
2852 "same return value and parameter types for constructor `" + Name
2863 public void Emit (TypeContainer container)
2865 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2866 EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
2869 // extern methods have no bodies
2871 if ((ModFlags & Modifiers.EXTERN) != 0) {
2872 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
2874 179, Location, "External constructor `" +
2875 TypeManager.CSharpSignature (ConstructorBuilder) +
2876 "' can not have a body");
2879 } else if (block == null) {
2881 501, Location, "Constructor `" +
2882 TypeManager.CSharpSignature (ConstructorBuilder) +
2883 "' must declare a body since it is not marked extern");
2887 if ((ModFlags & Modifiers.STATIC) == 0){
2888 if (container is Class && Initializer == null)
2889 Initializer = new ConstructorBaseInitializer (
2890 null, Parameters.EmptyReadOnlyParameters, Location);
2894 // Spec mandates that Initializers will not have
2898 if (Initializer != null && !Initializer.Resolve (ec))
2900 ec.IsStatic = false;
2903 MethodCore.LabelParameters (ec, ConstructorBuilder,
2904 Parameters, OptAttributes, Location);
2906 SymbolWriter sw = CodeGen.SymbolWriter;
2907 bool generate_debugging = false;
2909 if ((sw != null) && (block != null) &&
2910 !Location.IsNull (Location) &&
2911 !Location.IsNull (block.EndLocation)) {
2913 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
2915 generate_debugging = true;
2919 // Classes can have base initializers and instance field initializers.
2921 if (container is Class){
2922 if ((ModFlags & Modifiers.STATIC) == 0){
2925 // If we use a "this (...)" constructor initializer, then
2926 // do not emit field initializers, they are initialized in the other constructor
2928 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
2929 container.EmitFieldInitializers (ec);
2932 if (Initializer != null)
2933 Initializer.Emit (ec);
2935 if ((ModFlags & Modifiers.STATIC) != 0)
2936 container.EmitFieldInitializers (ec);
2938 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes);
2940 // If this is a non-static `struct' constructor and doesn't have any
2941 // initializer, it must initialize all of the struct's fields.
2942 if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
2943 Block.AddThisVariable (container, Location);
2945 ec.EmitTopBlock (block, ParameterInfo, Location);
2947 if (generate_debugging)
2955 // Encapsulates most of the Method's state
2957 public class MethodData {
2959 // The return type of this method
2961 public readonly Type ReturnType;
2962 public readonly Type[] ParameterTypes;
2963 public readonly InternalParameters ParameterInfo;
2964 public readonly CallingConventions CallingConventions;
2965 public readonly Attributes OptAttributes;
2966 public readonly Location Location;
2969 // Are we implementing an interface ?
2971 public bool IsImplementing = false;
2976 protected DeclSpace ds;
2977 protected MemberBase member;
2978 protected int modifiers;
2979 protected MethodAttributes flags;
2980 protected bool is_method;
2981 protected string accessor_name;
2984 // It can either hold a string with the condition, or an arraylist of conditions.
2985 object conditionals;
2987 MethodBuilder builder = null;
2988 public MethodBuilder MethodBuilder {
2994 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
2995 Type [] parameter_types, InternalParameters parameters,
2996 CallingConventions cc, Attributes opt_attrs,
2997 int modifiers, MethodAttributes flags, bool is_method)
3000 this.member = member;
3001 this.accessor_name = name;
3002 this.ReturnType = return_type;
3003 this.ParameterTypes = parameter_types;
3004 this.ParameterInfo = parameters;
3005 this.CallingConventions = cc;
3006 this.OptAttributes = opt_attrs;
3007 this.modifiers = modifiers;
3009 this.is_method = is_method;
3010 this.Location = member.Location;
3011 this.conditionals = null;
3017 Attribute dllimport_attribute = null;
3018 string obsolete = null;
3019 bool obsolete_error = false;
3021 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
3023 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
3026 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
3027 if (asec.Attributes == null)
3030 foreach (Attribute a in asec.Attributes) {
3031 if (a.Name == "Conditional") {
3032 if (!ApplyConditionalAttribute (a))
3034 } else if (a.Name == "Obsolete") {
3035 if (!ApplyObsoleteAttribute (a))
3037 } else if (a.Name.IndexOf ("DllImport") != -1) {
3039 a.Type = TypeManager.dllimport_type;
3040 Attribute.Error_AttributeNotValidForElement (a, Location);
3043 if (!ApplyDllImportAttribute (a))
3053 // Applies the `DllImport' attribute to the method.
3055 protected virtual bool ApplyDllImportAttribute (Attribute a)
3057 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3058 if ((modifiers & extern_static) != extern_static) {
3059 Report.Error (601, Location,
3060 "The DllImport attribute must be specified on a method " +
3061 "marked `static' and `extern'.");
3065 flags |= MethodAttributes.PinvokeImpl;
3066 dllimport_attribute = a;
3071 // Applies the `Obsolete' attribute to the method.
3073 protected virtual bool ApplyObsoleteAttribute (Attribute a)
3075 if (obsolete != null) {
3076 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
3080 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
3081 return obsolete != null;
3085 // Applies the `Conditional' attribute to the method.
3087 protected virtual bool ApplyConditionalAttribute (Attribute a)
3089 // The Conditional attribute is only valid on methods.
3091 Attribute.Error_AttributeNotValidForElement (a, Location);
3095 string condition = a.Conditional_GetConditionName ();
3097 if (condition == null)
3100 if (ReturnType != TypeManager.void_type) {
3101 Report.Error (578, Location,
3102 "Conditional not valid on `" + member.Name + "' " +
3103 "because its return type is not void");
3107 if ((modifiers & Modifiers.OVERRIDE) != 0) {
3108 Report.Error (243, Location,
3109 "Conditional not valid on `" + member.Name + "' " +
3110 "because it is an override method");
3114 if (member.IsExplicitImpl) {
3115 Report.Error (577, Location,
3116 "Conditional not valid on `" + member.Name + "' " +
3117 "because it is an explicit interface implementation");
3121 if (IsImplementing) {
3122 Report.Error (623, Location,
3123 "Conditional not valid on `" + member.Name + "' " +
3124 "because it is an interface method");
3129 // The likelyhood that the conditional will be more than 1 is very slim
3131 if (conditionals == null)
3132 conditionals = condition;
3133 else if (conditionals is string){
3134 string s = (string) conditionals;
3135 conditionals = new ArrayList ();
3136 ((ArrayList)conditionals).Add (s);
3138 ((ArrayList)conditionals).Add (condition);
3144 // Checks whether this method should be ignored due to its Conditional attributes.
3146 bool ShouldIgnore (Location loc)
3148 // When we're overriding a virtual method, we implicitly inherit the
3149 // Conditional attributes from our parent.
3150 if (member.ParentMethod != null) {
3151 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3152 member.ParentMethod, loc);
3154 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3158 if (conditionals != null){
3159 if (conditionals is string){
3160 if (RootContext.AllDefines [conditionals] == null)
3163 foreach (string condition in (ArrayList) conditionals)
3164 if (RootContext.AllDefines [condition] == null)
3172 // Returns the TypeManager.MethodFlags for this method.
3173 // This emits an error 619 / warning 618 if the method is obsolete.
3174 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3176 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3178 TypeManager.MethodFlags flags = 0;
3180 if (obsolete != null) {
3181 if (obsolete_error) {
3182 Report.Error (619, loc, "Method `" + member.Name +
3183 "' is obsolete: `" + obsolete + "'");
3184 return TypeManager.MethodFlags.IsObsoleteError;
3186 Report.Warning (618, loc, "Method `" + member.Name +
3187 "' is obsolete: `" + obsolete + "'");
3189 flags |= TypeManager.MethodFlags.IsObsolete;
3192 if (ShouldIgnore (loc))
3193 flags |= TypeManager.MethodFlags.ShouldIgnore;
3198 public virtual bool Define (TypeContainer container)
3200 MethodInfo implementing = null;
3201 string method_name, name, prefix;
3203 if (OptAttributes != null)
3204 if (!ApplyAttributes (OptAttributes, is_method))
3207 if (member.IsExplicitImpl)
3208 prefix = member.InterfaceType.FullName + ".";
3212 if (accessor_name != null)
3213 name = accessor_name + "_" + member.ShortName;
3215 name = member.ShortName;
3216 method_name = prefix + name;
3218 if (container.Pending != null){
3219 if (member is Indexer)
3220 implementing = container.Pending.IsInterfaceIndexer (
3221 member.InterfaceType, ReturnType, ParameterTypes);
3223 implementing = container.Pending.IsInterfaceMethod (
3224 member.InterfaceType, name, ReturnType, ParameterTypes);
3226 if (member.InterfaceType != null && implementing == null){
3227 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
3234 // For implicit implementations, make sure we are public, for
3235 // explicit implementations, make sure we are private.
3237 if (implementing != null){
3239 // Setting null inside this block will trigger a more
3240 // verbose error reporting for missing interface implementations
3242 // The "candidate" function has been flagged already
3243 // but it wont get cleared
3245 if (member.IsExplicitImpl){
3246 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3247 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3248 implementing = null;
3250 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
3251 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
3253 // If this is an interface method implementation,
3254 // check for public accessibility
3256 implementing = null;
3257 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
3258 // We may never be private.
3259 implementing = null;
3260 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
3262 // We may be protected if we're overriding something.
3264 implementing = null;
3269 // Static is not allowed
3271 if ((modifiers & Modifiers.STATIC) != 0){
3272 implementing = null;
3273 Modifiers.Error_InvalidModifier (Location, "static");
3278 // If implementing is still valid, set flags
3280 if (implementing != null){
3282 // When implementing interface methods, set NewSlot
3283 // unless, we are overwriting a method.
3285 if (implementing.DeclaringType.IsInterface){
3286 if ((modifiers & Modifiers.OVERRIDE) == 0)
3287 flags |= MethodAttributes.NewSlot;
3290 MethodAttributes.Virtual |
3291 MethodAttributes.HideBySig;
3293 // Set Final unless we're virtual, abstract or already overriding a method.
3294 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
3295 flags |= MethodAttributes.Final;
3297 // Get the method name from the explicit interface.
3298 if (member.InterfaceType != null) {
3299 name = implementing.Name;
3300 method_name = prefix + name;
3303 IsImplementing = true;
3307 // Create the MethodBuilder for the method
3309 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3310 if ((modifiers & Modifiers.STATIC) == 0) {
3311 Report.Error (601, Location,
3312 "The DllImport attribute must be specified on " +
3313 "a method marked 'static' and 'extern'.");
3317 EmitContext ec = new EmitContext (
3318 container, ds, Location, null, ReturnType, modifiers, false);
3320 builder = dllimport_attribute.DefinePInvokeMethod (
3321 ec, container.TypeBuilder, method_name, flags,
3322 ReturnType, ParameterTypes);
3324 builder = container.TypeBuilder.DefineMethod (
3325 method_name, flags, CallingConventions,
3326 ReturnType, ParameterTypes);
3328 if (builder == null)
3331 if ((modifiers & Modifiers.UNSAFE) != 0)
3332 builder.InitLocals = false;
3334 if (IsImplementing){
3336 // clear the pending implemntation flag
3338 if (member is Indexer) {
3339 container.Pending.ImplementIndexer (
3340 member.InterfaceType, builder, ReturnType,
3341 ParameterTypes, true);
3343 container.Pending.ImplementMethod (
3344 member.InterfaceType, name, ReturnType,
3345 ParameterTypes, member.IsExplicitImpl);
3347 if (member.IsExplicitImpl)
3348 container.TypeBuilder.DefineMethodOverride (
3349 builder, implementing);
3353 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3354 Report.Error (111, Location,
3355 "Class `" + container.Name +
3356 "' already contains a definition with the " +
3357 "same return value and parameter types as the " +
3358 "'get' method of property `" + member.Name + "'");
3362 TypeManager.AddMethod (builder, this);
3370 public virtual void Emit (TypeContainer container, Block block, object kind)
3375 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3376 ig = builder.GetILGenerator ();
3380 ec = new EmitContext (container, ds, Location, ig, ReturnType, modifiers, false);
3382 if (OptAttributes != null)
3383 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes);
3385 if (member is MethodCore)
3386 MethodCore.LabelParameters (ec, MethodBuilder,
3387 ((MethodCore) member).Parameters,
3392 // abstract or extern methods have no bodies
3394 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3395 if (block == null) {
3396 SymbolWriter sw = CodeGen.SymbolWriter;
3398 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0)) {
3399 sw.OpenMethod (container, MethodBuilder, Location, Location);
3407 // abstract or extern methods have no bodies.
3409 if ((modifiers & Modifiers.ABSTRACT) != 0)
3411 500, Location, "Abstract method `" +
3412 TypeManager.CSharpSignature (builder) +
3413 "' can not have a body");
3415 if ((modifiers & Modifiers.EXTERN) != 0)
3417 179, Location, "External method `" +
3418 TypeManager.CSharpSignature (builder) +
3419 "' can not have a body");
3425 // Methods must have a body unless they're extern or abstract
3427 if (block == null) {
3429 501, Location, "Method `" +
3430 TypeManager.CSharpSignature (builder) +
3431 "' must declare a body since it is not marked " +
3432 "abstract or extern");
3437 // Handle destructors specially
3439 // FIXME: This code generates buggy code
3441 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3442 EmitDestructor (ec, block);
3444 SymbolWriter sw = CodeGen.SymbolWriter;
3446 if ((sw != null) && !Location.IsNull (Location) &&
3447 !Location.IsNull (block.EndLocation)) {
3448 sw.OpenMethod (container, MethodBuilder, Location, block.EndLocation);
3450 ec.EmitTopBlock (block, ParameterInfo, Location);
3454 ec.EmitTopBlock (block, ParameterInfo, Location);
3458 void EmitDestructor (EmitContext ec, Block block)
3460 ILGenerator ig = ec.ig;
3462 Label finish = ig.DefineLabel ();
3463 bool old_in_try = ec.InTry;
3465 ig.BeginExceptionBlock ();
3467 ec.ReturnLabel = finish;
3468 ec.HasReturnLabel = true;
3469 ec.EmitTopBlock (block, null, Location);
3470 ec.InTry = old_in_try;
3472 // ig.MarkLabel (finish);
3473 bool old_in_finally = ec.InFinally;
3474 ec.InFinally = true;
3475 ig.BeginFinallyBlock ();
3477 if (ec.ContainerType.BaseType != null) {
3478 Expression member_lookup = Expression.MemberLookup (
3479 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3480 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, Location);
3482 if (member_lookup != null){
3483 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3485 ig.Emit (OpCodes.Ldarg_0);
3486 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3489 ec.InFinally = old_in_finally;
3491 ig.EndExceptionBlock ();
3492 //ig.MarkLabel (ec.ReturnLabel);
3493 ig.Emit (OpCodes.Ret);
3497 abstract public class MemberBase : MemberCore {
3498 public Expression Type;
3499 public readonly Attributes OptAttributes;
3501 protected MethodAttributes flags;
3503 protected readonly int explicit_mod_flags;
3506 // The "short" name of this property / indexer / event. This is the
3507 // name without the explicit interface.
3509 public string ShortName;
3512 // The type of this property / indexer / event
3514 public Type MemberType;
3517 // If true, this is an explicit interface implementation
3519 public bool IsExplicitImpl = false;
3522 // The name of the interface we are explicitly implementing
3524 public string ExplicitInterfaceName = null;
3527 // If true, the interface type we are explicitly implementing
3529 public Type InterfaceType = null;
3532 // The method we're overriding if this is an override method.
3534 protected MethodInfo parent_method = null;
3535 public MethodInfo ParentMethod {
3537 return parent_method;
3542 // The constructor is only exposed to our children
3544 protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod, string name,
3545 Attributes attrs, Location loc)
3548 explicit_mod_flags = mod;
3550 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
3551 OptAttributes = attrs;
3554 protected virtual bool CheckBase (TypeContainer container)
3556 if ((container is Struct) || (RootContext.WarningLevel > 3)){
3557 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
3558 if (container is Struct){
3559 Report.Error (666, Location, "Protected member in struct declaration");
3562 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
3568 protected void WarningNotHiding (TypeContainer parent)
3572 "The member " + parent.MakeName (Name) + " does not hide an " +
3573 "inherited member. The keyword new is not required");
3577 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
3581 // FIXME: report the old/new permissions?
3584 507, Location, parent.MakeName (Name) +
3585 ": can't change the access modifiers when overriding inherited " +
3586 "member `" + name + "'");
3590 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3591 // that have been defined.
3593 // `name' is the user visible name for reporting errors (this is used to
3594 // provide the right name regarding method names and properties)
3596 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
3597 MethodInfo mb, string name)
3601 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3602 if (!(mb.IsAbstract || mb.IsVirtual)){
3604 506, Location, parent.MakeName (Name) +
3605 ": cannot override inherited member `" +
3606 name + "' because it is not " +
3607 "virtual, abstract or override");
3611 // Now we check that the overriden method is not final
3614 // This happens when implementing interface methods.
3615 if (mb.IsHideBySig && mb.IsVirtual) {
3617 506, Location, parent.MakeName (Name) +
3618 ": cannot override inherited member `" +
3619 name + "' because it is not " +
3620 "virtual, abstract or override");
3622 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
3623 "override inherited member `" + name +
3624 "' because it is sealed.");
3628 // Check that the permissions are not being changed
3630 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
3631 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
3634 // special case for "protected internal"
3637 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3639 // when overriding protected internal, the method can be declared
3640 // protected internal only within the same assembly
3643 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3644 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
3646 // assemblies differ - report an error
3649 Error_CannotChangeAccessModifiers (parent, mb, name);
3651 } else if (thisp != parentp) {
3653 // same assembly, but other attributes differ - report an error
3656 Error_CannotChangeAccessModifiers (parent, mb, name);
3659 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3661 // if it's not "protected internal", it must be "protected"
3664 Error_CannotChangeAccessModifiers (parent, mb, name);
3666 } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
3668 // protected within the same assembly - an error
3670 Error_CannotChangeAccessModifiers (parent, mb, name);
3672 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3673 (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3675 // protected ok, but other attributes differ - report an error
3677 Error_CannotChangeAccessModifiers (parent, mb, name);
3681 if (thisp != parentp){
3682 Error_CannotChangeAccessModifiers (parent, mb, name);
3688 if (mb.IsVirtual || mb.IsAbstract){
3689 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
3690 if (Name != "Finalize"){
3692 114, 2, Location, parent.MakeName (Name) +
3693 " hides inherited member `" + name +
3694 "'. To make the current member override that " +
3695 "implementation, add the override keyword, " +
3696 "otherwise use the new keyword");
3697 ModFlags |= Modifiers.NEW;
3701 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
3702 if (Name != "Finalize"){
3704 108, 1, Location, "The keyword new is required on " +
3705 parent.MakeName (Name) + " because it hides " +
3706 "inherited member `" + name + "'");
3707 ModFlags |= Modifiers.NEW;
3715 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
3719 foreach (Type partype in parameters){
3720 if (partype.IsPointer){
3723 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
3727 if (ds.AsAccessible (partype, ModFlags))
3730 if (this is Indexer)
3731 Report.Error (55, Location,
3732 "Inconsistent accessibility: parameter type `" +
3733 TypeManager.CSharpName (partype) + "' is less " +
3734 "accessible than indexer `" + Name + "'");
3735 else if ((this is Method) && ((Method) this).IsOperator)
3736 Report.Error (57, Location,
3737 "Inconsistent accessibility: parameter type `" +
3738 TypeManager.CSharpName (partype) + "' is less " +
3739 "accessible than operator `" + Name + "'");
3741 Report.Error (51, Location,
3742 "Inconsistent accessibility: parameter type `" +
3743 TypeManager.CSharpName (partype) + "' is less " +
3744 "accessible than method `" + Name + "'");
3751 protected virtual bool DoDefine (TypeContainer container)
3756 if (!container.MethodModifiersValid (ModFlags, Name, Location))
3759 flags = Modifiers.MethodAttr (ModFlags);
3761 // Lookup Type, verify validity
3762 MemberType = container.ResolveType (Type, false, Location);
3763 if (MemberType == null)
3766 if ((container.ModFlags & Modifiers.SEALED) != 0){
3767 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
3768 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
3773 // verify accessibility
3774 if (!container.AsAccessible (MemberType, ModFlags)) {
3775 if (this is Property)
3776 Report.Error (53, Location,
3777 "Inconsistent accessibility: property type `" +
3778 TypeManager.CSharpName (MemberType) + "' is less " +
3779 "accessible than property `" + Name + "'");
3780 else if (this is Indexer)
3781 Report.Error (54, Location,
3782 "Inconsistent accessibility: indexer return type `" +
3783 TypeManager.CSharpName (MemberType) + "' is less " +
3784 "accessible than indexer `" + Name + "'");
3785 else if (this is Method) {
3786 if (((Method) this).IsOperator)
3787 Report.Error (56, Location,
3788 "Inconsistent accessibility: return type `" +
3789 TypeManager.CSharpName (MemberType) + "' is less " +
3790 "accessible than operator `" + Name + "'");
3792 Report.Error (50, Location,
3793 "Inconsistent accessibility: return type `" +
3794 TypeManager.CSharpName (MemberType) + "' is less " +
3795 "accessible than method `" + Name + "'");
3797 Report.Error (52, Location,
3798 "Inconsistent accessibility: field type `" +
3799 TypeManager.CSharpName (MemberType) + "' is less " +
3800 "accessible than field `" + Name + "'");
3804 if (MemberType.IsPointer && !UnsafeOK (container))
3808 // Check for explicit interface implementation
3810 if ((ExplicitInterfaceName == null) && (Name.IndexOf ('.') != -1)){
3811 int pos = Name.LastIndexOf ('.');
3813 ExplicitInterfaceName = Name.Substring (0, pos);
3814 ShortName = Name.Substring (pos + 1);
3818 if (ExplicitInterfaceName != null) {
3819 InterfaceType = RootContext.LookupType (
3820 container, ExplicitInterfaceName, false, Location);
3821 if (InterfaceType == null)
3824 // Compute the full name that we need to export.
3825 Name = InterfaceType.FullName + "." + ShortName;
3827 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
3830 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
3832 IsExplicitImpl = true;
3834 IsExplicitImpl = false;
3841 // Fields and Events both generate FieldBuilders, we use this to share
3842 // their common bits. This is also used to flag usage of the field
3844 abstract public class FieldBase : MemberBase {
3845 public FieldBuilder FieldBuilder;
3846 public Status status;
3849 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3852 // The constructor is only exposed to our children
3854 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3855 object init, Attributes attrs, Location loc)
3856 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
3862 // Whether this field has an initializer.
3864 public bool HasInitializer {
3866 return init != null;
3870 protected readonly Object init;
3872 Expression init_expr;
3873 bool init_expr_initialized = false;
3876 // Resolves and returns the field initializer.
3878 public Expression GetInitializerExpression (EmitContext ec)
3880 if (init_expr_initialized)
3884 if (init is Expression)
3885 e = (Expression) init;
3887 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3889 ec.IsFieldInitializer = true;
3890 e = e.DoResolve (ec);
3891 ec.IsFieldInitializer = false;
3894 init_expr_initialized = true;
3899 public void SetAssigned ()
3901 status |= Status.ASSIGNED;
3906 // The Field class is used to represents class/struct fields during parsing.
3908 public class Field : FieldBase {
3910 // Modifiers allowed in a class declaration
3912 const int AllowedModifiers =
3915 Modifiers.PROTECTED |
3916 Modifiers.INTERNAL |
3919 Modifiers.VOLATILE |
3923 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3924 Attributes attrs, Location loc)
3925 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3929 public override bool Define (TypeContainer container)
3931 Type t = container.ResolveType (Type, false, Location);
3936 CheckBase (container);
3938 if (!container.AsAccessible (t, ModFlags)) {
3939 Report.Error (52, Location,
3940 "Inconsistent accessibility: field type `" +
3941 TypeManager.CSharpName (t) + "' is less " +
3942 "accessible than field `" + Name + "'");
3946 if (t.IsPointer && !UnsafeOK (container))
3949 if (RootContext.WarningLevel > 1){
3950 Type ptype = container.TypeBuilder.BaseType;
3952 // ptype is only null for System.Object while compiling corlib.
3954 TypeContainer.FindMembers (
3955 ptype, MemberTypes.Method,
3956 BindingFlags.Public |
3957 BindingFlags.Static | BindingFlags.Instance,
3958 System.Type.FilterName, Name);
3962 if ((ModFlags & Modifiers.VOLATILE) != 0){
3966 if (TypeManager.IsEnumType (vt))
3967 vt = TypeManager.EnumToUnderlying (t);
3969 if (!((vt == TypeManager.bool_type) ||
3970 (vt == TypeManager.sbyte_type) ||
3971 (vt == TypeManager.byte_type) ||
3972 (vt == TypeManager.short_type) ||
3973 (vt == TypeManager.ushort_type) ||
3974 (vt == TypeManager.int32_type) ||
3975 (vt == TypeManager.uint32_type) ||
3976 (vt == TypeManager.char_type) ||
3977 (vt == TypeManager.float_type))){
3979 677, Location, container.MakeName (Name) +
3980 " A volatile field can not be of type `" +
3981 TypeManager.CSharpName (vt) + "'");
3986 if ((ModFlags & Modifiers.READONLY) != 0){
3989 "A field can not be both volatile and readonly");
3994 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3996 if (container is Struct &&
3997 ((fa & FieldAttributes.Static) == 0) &&
3998 t == container.TypeBuilder &&
3999 !TypeManager.IsBuiltinType (t)){
4000 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name +
4001 "' causes a cycle in the structure layout");
4005 FieldBuilder = container.TypeBuilder.DefineField (
4006 Name, t, Modifiers.FieldAttr (ModFlags));
4008 TypeManager.RegisterFieldBase (FieldBuilder, this);
4012 public void Emit (TypeContainer tc)
4014 EmitContext ec = new EmitContext (tc, Location, null,
4015 FieldBuilder.FieldType, ModFlags);
4017 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes);
4022 // `set' and `get' accessors are represented with an Accessor.
4024 public class Accessor {
4026 // Null if the accessor is empty, or a Block if not
4029 public Attributes OptAttributes;
4031 public Accessor (Block b, Attributes attrs)
4034 OptAttributes = attrs;
4039 // Properties and Indexers both generate PropertyBuilders, we use this to share
4040 // their common bits.
4042 abstract public class PropertyBase : MethodCore {
4043 public Accessor Get, Set;
4044 public PropertyBuilder PropertyBuilder;
4045 public MethodBuilder GetBuilder, SetBuilder;
4046 public MethodData GetData, SetData;
4048 protected EmitContext ec;
4050 public PropertyBase (DeclSpace ds, Expression type, string name, int mod_flags,
4051 int allowed_mod, Parameters parameters,
4052 Accessor get_block, Accessor set_block,
4053 Attributes attrs, Location loc)
4054 : base (ds, type, mod_flags, allowed_mod, name, attrs, parameters, loc)
4060 protected override bool DoDefine (TypeContainer container)
4062 if (!base.DoDefine (container))
4065 ec = new EmitContext (container, Location, null, MemberType, ModFlags);
4071 // Checks our base implementation if any
4073 protected override bool CheckBase (TypeContainer container)
4075 base.CheckBase (container);
4077 // Check whether arguments were correct.
4078 if (!DoDefineParameters ())
4085 MethodSignature ms, base_ms;
4086 if (this is Indexer) {
4087 string name, base_name;
4089 report_name = "this";
4090 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
4091 ms = new MethodSignature (name, null, ParameterTypes);
4092 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
4093 base_ms = new MethodSignature (base_name, null, ParameterTypes);
4096 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
4100 // Verify if the parent has a type with the same name, and then
4101 // check whether we have to create a new slot for it or not.
4103 Type ptype = container.TypeBuilder.BaseType;
4105 // ptype is only null for System.Object while compiling corlib.
4106 if (ptype == null) {
4107 if ((ModFlags & Modifiers.NEW) != 0)
4108 WarningNotHiding (container);
4113 MemberList props_this;
4115 props_this = TypeContainer.FindMembers (
4116 container.TypeBuilder, MemberTypes.Property,
4117 BindingFlags.NonPublic | BindingFlags.Public |
4118 BindingFlags.Static | BindingFlags.Instance |
4119 BindingFlags.DeclaredOnly,
4120 MethodSignature.method_signature_filter, ms);
4122 if (props_this.Count > 0) {
4123 Report.Error (111, Location, "Class `" + container.Name + "' " +
4124 "already defines a member called `" + report_name + "' " +
4125 "with the same parameter types");
4129 MemberList mi_props;
4131 mi_props = TypeContainer.FindMembers (
4132 ptype, MemberTypes.Property,
4133 BindingFlags.NonPublic | BindingFlags.Public |
4134 BindingFlags.Instance | BindingFlags.Static,
4135 MethodSignature.inheritable_method_signature_filter, base_ms);
4137 if (mi_props.Count > 0){
4138 PropertyInfo parent_property = (PropertyInfo) mi_props [0];
4139 string name = parent_property.DeclaringType.Name + "." +
4140 parent_property.Name;
4142 MethodInfo get, set, parent_method;
4143 get = parent_property.GetGetMethod (true);
4144 set = parent_property.GetSetMethod (true);
4147 parent_method = get;
4148 else if (set != null)
4149 parent_method = set;
4151 throw new Exception ("Internal error!");
4153 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
4156 if ((ModFlags & Modifiers.NEW) == 0) {
4157 Type parent_type = TypeManager.TypeToCoreType (
4158 parent_property.PropertyType);
4160 if (parent_type != MemberType) {
4162 508, Location, container.MakeName (Name) + ": cannot " +
4163 "change return type when overriding " +
4164 "inherited member " + name);
4169 if ((ModFlags & Modifiers.NEW) != 0)
4170 WarningNotHiding (container);
4172 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4173 if (this is Indexer)
4174 Report.Error (115, Location,
4175 container.MakeName (Name) +
4176 " no suitable indexers found to override");
4178 Report.Error (115, Location,
4179 container.MakeName (Name) +
4180 " no suitable properties found to override");
4187 public void Emit (TypeContainer tc)
4190 // The PropertyBuilder can be null for explicit implementations, in that
4191 // case, we do not actually emit the ".property", so there is nowhere to
4192 // put the attribute
4194 if (PropertyBuilder != null)
4195 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes);
4197 if (GetData != null) {
4198 GetData.Emit (tc, Get.Block, Get);
4202 if (SetData != null) {
4203 SetData.Emit (tc, Set.Block, Set);
4209 public class Property : PropertyBase {
4210 const int AllowedModifiers =
4213 Modifiers.PROTECTED |
4214 Modifiers.INTERNAL |
4218 Modifiers.OVERRIDE |
4219 Modifiers.ABSTRACT |
4224 public Property (DeclSpace ds, Expression type, string name, int mod_flags,
4225 Accessor get_block, Accessor set_block,
4226 Attributes attrs, Location loc)
4227 : base (ds, type, name, mod_flags, AllowedModifiers,
4228 Parameters.EmptyReadOnlyParameters,
4229 get_block, set_block, attrs, loc)
4233 public override bool Define (TypeContainer container)
4235 if (!DoDefine (container))
4238 if (!CheckBase (container))
4241 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4244 Type [] parameters = TypeManager.NoTypes;
4246 InternalParameters ip = new InternalParameters (
4247 container, Parameters.EmptyReadOnlyParameters);
4249 GetData = new MethodData (container, this, "get", MemberType,
4250 parameters, ip, CallingConventions.Standard,
4251 Get.OptAttributes, ModFlags, flags, false);
4253 if (!GetData.Define (container))
4256 GetBuilder = GetData.MethodBuilder;
4260 Type [] parameters = new Type [1];
4261 parameters [0] = MemberType;
4263 Parameter [] parms = new Parameter [1];
4264 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4265 InternalParameters ip = new InternalParameters (
4266 container, new Parameters (parms, null, Location));
4268 SetData = new MethodData (container, this, "set", TypeManager.void_type,
4269 parameters, ip, CallingConventions.Standard,
4270 Set.OptAttributes, ModFlags, flags, false);
4272 if (!SetData.Define (container))
4275 SetBuilder = SetData.MethodBuilder;
4276 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4279 // FIXME - PropertyAttributes.HasDefault ?
4281 PropertyAttributes prop_attr =
4282 PropertyAttributes.RTSpecialName |
4283 PropertyAttributes.SpecialName;
4285 if (!IsExplicitImpl){
4286 PropertyBuilder = container.TypeBuilder.DefineProperty (
4287 Name, prop_attr, MemberType, null);
4290 PropertyBuilder.SetGetMethod (GetBuilder);
4293 PropertyBuilder.SetSetMethod (SetBuilder);
4296 // HACK for the reasons exposed above
4298 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4301 "Class `" + container.Name +
4302 "' already contains a definition for the property `" +
4312 /// Gigantic workaround for lameness in SRE follows :
4313 /// This class derives from EventInfo and attempts to basically
4314 /// wrap around the EventBuilder so that FindMembers can quickly
4315 /// return this in it search for members
4317 public class MyEventBuilder : EventInfo {
4320 // We use this to "point" to our Builder which is
4321 // not really a MemberInfo
4323 EventBuilder MyBuilder;
4326 // We "catch" and wrap these methods
4328 MethodInfo raise, remove, add;
4330 EventAttributes attributes;
4331 Type declaring_type, reflected_type, event_type;
4336 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4338 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4340 // And now store the values in our own fields.
4342 declaring_type = type_builder;
4344 reflected_type = type_builder;
4346 attributes = event_attr;
4349 this.event_type = event_type;
4353 // Methods that you have to override. Note that you only need
4354 // to "implement" the variants that take the argument (those are
4355 // the "abstract" methods, the others (GetAddMethod()) are
4358 public override MethodInfo GetAddMethod (bool nonPublic)
4363 public override MethodInfo GetRemoveMethod (bool nonPublic)
4368 public override MethodInfo GetRaiseMethod (bool nonPublic)
4374 // These methods make "MyEventInfo" look like a Builder
4376 public void SetRaiseMethod (MethodBuilder raiseMethod)
4378 raise = raiseMethod;
4379 MyBuilder.SetRaiseMethod (raiseMethod);
4382 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4384 remove = removeMethod;
4385 MyBuilder.SetRemoveOnMethod (removeMethod);
4388 public void SetAddOnMethod (MethodBuilder addMethod)
4391 MyBuilder.SetAddOnMethod (addMethod);
4394 public void SetCustomAttribute (CustomAttributeBuilder cb)
4396 MyBuilder.SetCustomAttribute (cb);
4399 public override object [] GetCustomAttributes (bool inherit)
4401 // FIXME : There's nothing which can be seemingly done here because
4402 // we have no way of getting at the custom attribute objects of the
4407 public override object [] GetCustomAttributes (Type t, bool inherit)
4409 // FIXME : Same here !
4413 public override bool IsDefined (Type t, bool b)
4418 public override EventAttributes Attributes {
4424 public override string Name {
4430 public override Type DeclaringType {
4432 return declaring_type;
4436 public override Type ReflectedType {
4438 return reflected_type;
4442 public Type EventType {
4448 public void SetUsed ()
4450 if (my_event != null)
4451 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
4455 public class Event : FieldBase {
4456 const int AllowedModifiers =
4459 Modifiers.PROTECTED |
4460 Modifiers.INTERNAL |
4465 Modifiers.OVERRIDE |
4469 public readonly Accessor Add;
4470 public readonly Accessor Remove;
4471 public MyEventBuilder EventBuilder;
4473 MethodBuilder AddBuilder, RemoveBuilder;
4474 MethodData AddData, RemoveData;
4476 public Event (Expression type, string name, Object init, int mod, Accessor add,
4477 Accessor remove, Attributes attrs, Location loc)
4478 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4484 public override bool Define (TypeContainer container)
4486 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4487 MethodAttributes m_attr = MethodAttributes.HideBySig | MethodAttributes.SpecialName
4489 if (!DoDefine (container))
4492 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
4493 Report.Error (74, Location, "'" + container.Name + "." + Name +
4494 "': abstract event can not have an initializer");
4498 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4499 Report.Error (66, Location, "'" + container.Name + "." + Name +
4500 "' : event must be of a delegate type");
4504 Type [] parameter_types = new Type [1];
4505 parameter_types [0] = MemberType;
4507 Parameter [] parms = new Parameter [1];
4508 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4509 InternalParameters ip = new InternalParameters (
4510 container, new Parameters (parms, null, Location));
4512 if (!CheckBase (container))
4516 // Now define the accessors
4518 AddData = new MethodData (container, this, "add", TypeManager.void_type,
4519 parameter_types, ip, CallingConventions.Standard,
4520 (Add != null) ? Add.OptAttributes : null,
4521 ModFlags, flags | m_attr, false);
4523 if (!AddData.Define (container))
4526 AddBuilder = AddData.MethodBuilder;
4527 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4529 RemoveData = new MethodData (container, this, "remove", TypeManager.void_type,
4530 parameter_types, ip, CallingConventions.Standard,
4531 (Remove != null) ? Remove.OptAttributes : null,
4532 ModFlags, flags | m_attr, false);
4534 if (!RemoveData.Define (container))
4537 RemoveBuilder = RemoveData.MethodBuilder;
4538 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4540 if (!IsExplicitImpl){
4541 EventBuilder = new MyEventBuilder (this,
4542 container.TypeBuilder, Name, e_attr, MemberType);
4544 if (Add == null && Remove == null) {
4545 FieldBuilder = container.TypeBuilder.DefineField (
4547 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4548 TypeManager.RegisterPrivateFieldOfEvent (
4549 (EventInfo) EventBuilder, FieldBuilder);
4550 TypeManager.RegisterFieldBase (FieldBuilder, this);
4553 EventBuilder.SetAddOnMethod (AddBuilder);
4554 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4556 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4557 Report.Error (111, Location,
4558 "Class `" + container.Name +
4559 "' already contains a definition for the event `" +
4568 void EmitDefaultMethod (EmitContext ec, bool is_add)
4570 ILGenerator ig = ec.ig;
4571 MethodInfo method = null;
4574 method = TypeManager.delegate_combine_delegate_delegate;
4576 method = TypeManager.delegate_remove_delegate_delegate;
4578 if ((ModFlags & Modifiers.STATIC) != 0) {
4579 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4580 ig.Emit (OpCodes.Ldarg_0);
4581 ig.Emit (OpCodes.Call, method);
4582 ig.Emit (OpCodes.Castclass, MemberType);
4583 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4585 ig.Emit (OpCodes.Ldarg_0);
4586 ig.Emit (OpCodes.Ldarg_0);
4587 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4588 ig.Emit (OpCodes.Ldarg_1);
4589 ig.Emit (OpCodes.Call, method);
4590 ig.Emit (OpCodes.Castclass, MemberType);
4591 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4593 ig.Emit (OpCodes.Ret);
4596 public void Emit (TypeContainer tc)
4600 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4601 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes);
4604 AddData.Emit (tc, Add.Block, Add);
4607 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4608 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4609 EmitDefaultMethod (ec, true);
4612 if (Remove != null) {
4613 RemoveData.Emit (tc, Remove.Block, Remove);
4614 Remove.Block = null;
4616 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4617 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4618 EmitDefaultMethod (ec, false);
4625 // FIXME: This does not handle:
4627 // int INTERFACENAME [ args ]
4632 // int this [ args ]
4634 public class Indexer : PropertyBase {
4636 const int AllowedModifiers =
4639 Modifiers.PROTECTED |
4640 Modifiers.INTERNAL |
4644 Modifiers.OVERRIDE |
4649 public string IndexerName;
4650 public string InterfaceIndexerName;
4653 // Are we implementing an interface ?
4655 public Indexer (DeclSpace ds, Expression type, string int_type, int flags,
4656 Parameters parameters, Accessor get_block, Accessor set_block,
4657 Attributes attrs, Location loc)
4658 : base (ds, type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4661 ExplicitInterfaceName = int_type;
4664 public override bool Define (TypeContainer container)
4666 PropertyAttributes prop_attr =
4667 PropertyAttributes.RTSpecialName |
4668 PropertyAttributes.SpecialName;
4670 if (!DoDefine (container))
4673 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4674 if (IndexerName == null)
4675 IndexerName = "Item";
4676 else if (IsExplicitImpl)
4677 Report.Error (592, Location,
4678 "Attribute 'IndexerName' is not valid on this declaration " +
4679 "type. It is valid on `property' declarations only.");
4681 ShortName = IndexerName;
4682 if (IsExplicitImpl) {
4683 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4684 Name = InterfaceType.FullName + "." + IndexerName;
4686 InterfaceIndexerName = IndexerName;
4690 if (!CheckBase (container))
4693 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4695 InternalParameters ip = new InternalParameters (container, Parameters);
4697 GetData = new MethodData (container, this, "get", MemberType,
4698 ParameterTypes, ip, CallingConventions.Standard,
4699 Get.OptAttributes, ModFlags, flags, false);
4701 if (!GetData.Define (container))
4704 GetBuilder = GetData.MethodBuilder;
4708 int top = ParameterTypes.Length;
4709 Type [] set_pars = new Type [top + 1];
4710 ParameterTypes.CopyTo (set_pars, 0);
4711 set_pars [top] = MemberType;
4713 Parameter [] fixed_parms = Parameters.FixedParameters;
4715 if (fixed_parms == null){
4716 throw new Exception ("We currently do not support only array arguments in an indexer at: " + Location);
4717 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4718 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4720 // Here is the problem: the `value' parameter has
4721 // to come *after* the array parameter in the declaration
4723 // X (object [] x, Type value)
4726 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4727 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4731 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4734 fixed_parms.CopyTo (tmp, 0);
4735 tmp [fixed_parms.Length] = new Parameter (
4736 Type, "value", Parameter.Modifier.NONE, null);
4738 Parameters set_formal_params = new Parameters (tmp, null, Location);
4740 InternalParameters ip = new InternalParameters (container, set_formal_params);
4742 SetData = new MethodData (container, this, "set", TypeManager.void_type,
4743 set_pars, ip, CallingConventions.Standard,
4744 Set.OptAttributes, ModFlags, flags, false);
4746 if (!SetData.Define (container))
4749 SetBuilder = SetData.MethodBuilder;
4753 // Now name the parameters
4755 Parameter [] p = Parameters.FixedParameters;
4759 for (i = 0; i < p.Length; ++i) {
4761 GetBuilder.DefineParameter (
4762 i + 1, p [i].Attributes, p [i].Name);
4765 SetBuilder.DefineParameter (
4766 i + 1, p [i].Attributes, p [i].Name);
4770 SetBuilder.DefineParameter (
4771 i + 1, ParameterAttributes.None, "value");
4773 if (i != ParameterTypes.Length) {
4774 Parameter array_param = Parameters.ArrayParameter;
4776 SetBuilder.DefineParameter (
4777 i + 1, array_param.Attributes, array_param.Name);
4782 // Define the PropertyBuilder if one of the following conditions are met:
4783 // a) we're not implementing an interface indexer.
4784 // b) the indexer has a different IndexerName and this is no
4785 // explicit interface implementation.
4787 if (!IsExplicitImpl) {
4788 PropertyBuilder = container.TypeBuilder.DefineProperty (
4789 IndexerName, prop_attr, MemberType, ParameterTypes);
4791 if (GetData != null)
4792 PropertyBuilder.SetGetMethod (GetBuilder);
4794 if (SetData != null)
4795 PropertyBuilder.SetSetMethod (SetBuilder);
4797 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4805 public class Operator : MemberBase {
4807 const int AllowedModifiers =
4813 const int RequiredModifiers =
4817 public enum OpType : byte {
4827 // Unary and Binary operators
4850 // Implicit and Explicit
4855 public readonly OpType OperatorType;
4856 public readonly Expression ReturnType;
4857 public readonly Expression FirstArgType, SecondArgType;
4858 public readonly string FirstArgName, SecondArgName;
4860 public MethodBuilder OperatorMethodBuilder;
4862 public string MethodName;
4863 public Method OperatorMethod;
4865 public Operator (OpType type, Expression ret_type, int mod_flags,
4866 Expression arg1type, string arg1name,
4867 Expression arg2type, string arg2name,
4868 Block block, Attributes attrs, Location loc)
4869 : base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC, "", attrs, loc)
4871 OperatorType = type;
4872 ReturnType = ret_type;
4873 FirstArgType = arg1type;
4874 FirstArgName = arg1name;
4875 SecondArgType = arg2type;
4876 SecondArgName = arg2name;
4880 string Prototype (TypeContainer container)
4882 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4883 SecondArgType + ")";
4886 public override bool Define (TypeContainer container)
4889 MethodName = "op_" + OperatorType;
4891 if (SecondArgType != null)
4894 Parameter [] param_list = new Parameter [length];
4896 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4899 "User defined operators `" +
4900 Prototype (container) +
4901 "' must be declared static and public");
4905 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4906 Parameter.Modifier.NONE, null);
4907 if (SecondArgType != null)
4908 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4909 Parameter.Modifier.NONE, null);
4911 OperatorMethod = new Method (container, ReturnType, ModFlags, MethodName,
4912 new Parameters (param_list, null, Location),
4913 OptAttributes, Location);
4915 OperatorMethod.IsOperator = true;
4916 OperatorMethod.Define (container);
4918 if (OperatorMethod.MethodBuilder == null)
4921 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4923 Type [] param_types = OperatorMethod.ParameterTypes;
4924 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4925 Type return_type = OperatorMethod.GetReturnType ();
4926 Type first_arg_type = param_types [0];
4928 // Rules for conversion operators
4930 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4931 if (first_arg_type == return_type && first_arg_type == declaring_type){
4934 "User-defined conversion cannot take an object of the " +
4935 "enclosing type and convert to an object of the enclosing" +
4940 if (first_arg_type != declaring_type && return_type != declaring_type){
4943 "User-defined conversion must convert to or from the " +
4948 if (first_arg_type == TypeManager.object_type ||
4949 return_type == TypeManager.object_type){
4952 "User-defined conversion cannot convert to or from " +
4957 if (first_arg_type.IsInterface || return_type.IsInterface){
4960 "User-defined conversion cannot convert to or from an " +
4965 if (first_arg_type.IsSubclassOf (return_type) ||
4966 return_type.IsSubclassOf (first_arg_type)){
4969 "User-defined conversion cannot convert between types " +
4970 "that derive from each other");
4973 } else if (SecondArgType == null) {
4974 // Checks for Unary operators
4976 if (first_arg_type != declaring_type){
4979 "The parameter of a unary operator must be the " +
4984 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4985 if (return_type != declaring_type){
4988 "The parameter and return type for ++ and -- " +
4989 "must be the containing type");
4995 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4996 if (return_type != TypeManager.bool_type){
4999 "The return type of operator True or False " +
5006 // Checks for Binary operators
5008 if (first_arg_type != declaring_type &&
5009 param_types [1] != declaring_type){
5012 "One of the parameters of a binary operator must " +
5013 "be the containing type");
5021 public void Emit (TypeContainer container)
5024 // abstract or extern methods have no bodies
5026 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
5029 OperatorMethod.Block = Block;
5030 OperatorMethod.Emit (container);
5034 public static string GetName (OpType ot)
5037 case OpType.LogicalNot:
5039 case OpType.OnesComplement:
5041 case OpType.Increment:
5043 case OpType.Decrement:
5049 case OpType.Addition:
5051 case OpType.Subtraction:
5053 case OpType.UnaryPlus:
5055 case OpType.UnaryNegation:
5057 case OpType.Multiply:
5059 case OpType.Division:
5061 case OpType.Modulus:
5063 case OpType.BitwiseAnd:
5065 case OpType.BitwiseOr:
5067 case OpType.ExclusiveOr:
5069 case OpType.LeftShift:
5071 case OpType.RightShift:
5073 case OpType.Equality:
5075 case OpType.Inequality:
5077 case OpType.GreaterThan:
5079 case OpType.LessThan:
5081 case OpType.GreaterThanOrEqual:
5083 case OpType.LessThanOrEqual:
5085 case OpType.Implicit:
5087 case OpType.Explicit:
5093 public override string ToString ()
5095 Type return_type = OperatorMethod.GetReturnType();
5096 Type [] param_types = OperatorMethod.ParameterTypes;
5098 if (SecondArgType == null)
5099 return String.Format (
5100 "{0} operator {1}({2})",
5101 TypeManager.CSharpName (return_type),
5102 GetName (OperatorType),
5105 return String.Format (
5106 "{0} operator {1}({2}, {3})",
5107 TypeManager.CSharpName (return_type),
5108 GetName (OperatorType),
5109 param_types [0], param_types [1]);
5114 // This is used to compare method signatures
5116 struct MethodSignature {
5118 public Type RetType;
5119 public Type [] Parameters;
5122 /// This delegate is used to extract methods which have the
5123 /// same signature as the argument
5125 public static MemberFilter method_signature_filter;
5128 /// This delegate is used to extract inheritable methods which
5129 /// have the same signature as the argument. By inheritable,
5130 /// this means that we have permissions to override the method
5131 /// from the current assembly and class
5133 public static MemberFilter inheritable_method_signature_filter;
5135 static MethodSignature ()
5137 method_signature_filter = new MemberFilter (MemberSignatureCompare);
5138 inheritable_method_signature_filter = new MemberFilter (
5139 InheritableMemberSignatureCompare);
5142 public MethodSignature (string name, Type ret_type, Type [] parameters)
5147 if (parameters == null)
5148 Parameters = TypeManager.NoTypes;
5150 Parameters = parameters;
5153 public override string ToString ()
5156 if (Parameters.Length != 0){
5157 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
5158 for (int i = 0; i < Parameters.Length; i++){
5159 sb.Append (Parameters [i]);
5160 if (i+1 < Parameters.Length)
5163 pars = sb.ToString ();
5166 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
5169 public override int GetHashCode ()
5171 return Name.GetHashCode ();
5174 public override bool Equals (Object o)
5176 MethodSignature other = (MethodSignature) o;
5178 if (other.Name != Name)
5181 if (other.RetType != RetType)
5184 if (Parameters == null){
5185 if (other.Parameters == null)
5190 if (other.Parameters == null)
5193 int c = Parameters.Length;
5194 if (other.Parameters.Length != c)
5197 for (int i = 0; i < c; i++)
5198 if (other.Parameters [i] != Parameters [i])
5204 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
5206 MethodSignature sig = (MethodSignature) filter_criteria;
5208 if (m.Name != sig.Name)
5212 MethodInfo mi = m as MethodInfo;
5213 PropertyInfo pi = m as PropertyInfo;
5216 ReturnType = mi.ReturnType;
5217 else if (pi != null)
5218 ReturnType = pi.PropertyType;
5223 // we use sig.RetType == null to mean `do not check the
5224 // method return value.
5226 if (sig.RetType != null)
5227 if (ReturnType != sig.RetType)
5232 args = TypeManager.GetArgumentTypes (mi);
5234 args = TypeManager.GetArgumentTypes (pi);
5235 Type [] sigp = sig.Parameters;
5237 if (args.Length != sigp.Length)
5240 for (int i = args.Length; i > 0; ){
5242 if (args [i] != sigp [i])
5249 // This filter should be used when we are requesting methods that
5250 // we want to override.
5252 // This makes a number of assumptions, for example
5253 // that the methods being extracted are of a parent
5254 // class (this means we know implicitly that we are
5255 // being called to find out about members by a derived
5258 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
5261 PropertyInfo pi = m as PropertyInfo;
5264 mi = pi.GetGetMethod (true);
5266 mi = pi.GetSetMethod (true);
5268 mi = m as MethodInfo;
5271 Console.WriteLine ("Nothing found");
5274 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
5276 // If only accessible to the current class.
5277 if (prot == MethodAttributes.Private)
5280 if (!MemberSignatureCompare (m, filter_criteria))
5283 // If only accessible to the defining assembly or
5284 if (prot == MethodAttributes.FamANDAssem ||
5285 prot == MethodAttributes.Assembly){
5286 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
5292 // Anything else (FamOrAssembly and Public) is fine