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)
141 types = new ArrayList ();
148 base_class_name = null;
150 //Console.WriteLine ("New class " + name + " inside " + n);
153 public AdditionResult AddConstant (Const constant)
156 string basename = constant.Name;
157 string fullname = Name + "." + basename;
159 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
162 if (constants == null)
163 constants = new ArrayList ();
165 constants.Add (constant);
166 DefineName (fullname, constant);
168 return AdditionResult.Success;
171 public AdditionResult AddEnum (Mono.CSharp.Enum e)
175 if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
179 enums = new ArrayList ();
182 DefineName (e.Name, e);
184 return AdditionResult.Success;
187 public AdditionResult AddClass (Class c)
190 string name = c.Basename;
192 if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
195 DefineName (c.Name, c);
198 return AdditionResult.Success;
201 public AdditionResult AddStruct (Struct s)
204 string name = s.Basename;
206 if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
209 DefineName (s.Name, s);
212 return AdditionResult.Success;
215 public AdditionResult AddDelegate (Delegate d)
218 string name = d.Basename;
220 if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
223 if (delegates == null)
224 delegates = new ArrayList ();
226 DefineName (d.Name, d);
229 return AdditionResult.Success;
232 public AdditionResult AddMethod (Method method)
234 string basename = method.Name;
235 string fullname = Name + "." + basename;
237 Object value = defined_names [fullname];
239 if (value != null && (!(value is Method)))
240 return AdditionResult.NameExists;
242 if (basename == Basename)
243 return AdditionResult.EnclosingClash;
246 methods = new ArrayList ();
248 if (method.Name.IndexOf ('.') != -1)
249 methods.Insert (0, method);
251 methods.Add (method);
254 DefineName (fullname, method);
256 return AdditionResult.Success;
259 public AdditionResult AddConstructor (Constructor c)
261 if (c.Name != Basename)
262 return AdditionResult.NotAConstructor;
264 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
267 have_static_constructor = true;
268 if (default_static_constructor != null){
269 Console.WriteLine ("I have a static constructor already");
270 Console.WriteLine (" " + default_static_constructor);
271 return AdditionResult.MethodExists;
274 default_static_constructor = c;
277 if (default_constructor != null)
278 return AdditionResult.MethodExists;
279 default_constructor = c;
282 if (instance_constructors == null)
283 instance_constructors = new ArrayList ();
285 instance_constructors.Add (c);
288 return AdditionResult.Success;
291 public AdditionResult AddInterface (Interface iface)
294 string name = iface.Basename;
296 if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
299 if (interfaces == null)
300 interfaces = new ArrayList ();
301 interfaces.Add (iface);
302 DefineName (iface.Name, iface);
304 return AdditionResult.Success;
307 public AdditionResult AddField (Field field)
310 string basename = field.Name;
311 string fullname = Name + "." + basename;
313 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
317 fields = new ArrayList ();
321 if (field.HasInitializer){
322 if ((field.ModFlags & Modifiers.STATIC) != 0){
323 if (initialized_static_fields == null)
324 initialized_static_fields = new ArrayList ();
326 initialized_static_fields.Add (field);
329 // We have not seen a static constructor,
330 // but we will provide static initialization of fields
332 have_static_constructor = true;
334 if (initialized_fields == null)
335 initialized_fields = new ArrayList ();
337 initialized_fields.Add (field);
341 if ((field.ModFlags & Modifiers.STATIC) == 0)
342 have_nonstatic_fields = true;
344 DefineName (fullname, field);
345 return AdditionResult.Success;
348 public AdditionResult AddProperty (Property prop)
351 string basename = prop.Name;
352 string fullname = Name + "." + basename;
354 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
357 if (properties == null)
358 properties = new ArrayList ();
360 if (prop.Name.IndexOf ('.') != -1)
361 properties.Insert (0, prop);
363 properties.Add (prop);
364 DefineName (fullname, prop);
366 return AdditionResult.Success;
369 public AdditionResult AddEvent (Event e)
372 string basename = e.Name;
373 string fullname = Name + "." + basename;
375 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
379 events = new ArrayList ();
382 DefineName (fullname, e);
384 return AdditionResult.Success;
387 public AdditionResult AddIndexer (Indexer i)
389 if (indexers == null)
390 indexers = new ArrayList ();
392 if (i.InterfaceType != null)
393 indexers.Insert (0, i);
397 return AdditionResult.Success;
400 public AdditionResult AddOperator (Operator op)
402 if (operators == null)
403 operators = new ArrayList ();
407 return AdditionResult.Success;
410 public void RegisterOrder (Interface iface)
412 if (interface_order == null)
413 interface_order = new ArrayList ();
415 interface_order.Add (iface);
418 public ArrayList Types {
424 public ArrayList Methods {
430 public ArrayList Constants {
436 public ArrayList Interfaces {
444 return base_class_name;
448 public ArrayList Bases {
458 public ArrayList Fields {
468 public ArrayList InstanceConstructors {
470 return instance_constructors;
474 public ArrayList Properties {
480 public ArrayList Events {
486 public ArrayList Enums {
492 public ArrayList Indexers {
498 public ArrayList Operators {
504 public ArrayList Delegates {
510 public Attributes OptAttributes {
516 public bool HaveStaticConstructor {
518 return have_static_constructor;
522 public virtual TypeAttributes TypeAttr {
524 return Modifiers.TypeAttr (ModFlags, this);
529 // Emits the instance field initializers
531 public bool EmitFieldInitializers (EmitContext ec)
534 ILGenerator ig = ec.ig;
535 Expression instance_expr;
538 fields = initialized_static_fields;
539 instance_expr = null;
541 fields = initialized_fields;
542 instance_expr = new This (Location.Null).Resolve (ec);
548 foreach (Field f in fields){
549 Expression e = f.GetInitializerExpression (ec);
553 Location l = f.Location;
554 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
555 fe.InstanceExpression = instance_expr;
556 ExpressionStatement a = new Assign (fe, e, l);
558 a = a.ResolveStatement (ec);
562 a.EmitStatement (ec);
569 // Defines the default constructors
571 void DefineDefaultConstructor (bool is_static)
576 c = new Constructor (this, Basename, Parameters.EmptyReadOnlyParameters,
577 new ConstructorBaseInitializer (
578 null, Parameters.EmptyReadOnlyParameters,
583 mods = Modifiers.STATIC;
589 c.Block = new Block (null);
593 public void ReportStructInitializedInstanceError ()
595 string n = TypeBuilder.FullName;
597 foreach (Field f in initialized_fields){
600 "`" + n + "." + f.Name + "': can not have " +
601 "instance field initializers in structs");
606 /// The pending methods that need to be implemented (interfaces or abstract methods)
608 public PendingImplementation Pending;
611 /// This function computes the Base class and also the
612 /// list of interfaces that the class or struct @c implements.
614 /// The return value is an array (might be null) of
615 /// interfaces implemented (as Types).
617 /// The @parent argument is set to the parent object or null
618 /// if this is `System.Object'.
620 TypeExpr [] GetClassBases (bool is_class, out TypeExpr parent, out bool error)
622 ArrayList bases = Bases;
631 parent = TypeManager.system_valuetype_expr;
635 if (RootContext.StdLib)
636 parent = TypeManager.system_object_expr;
637 else if (Name != "System.Object")
638 parent = TypeManager.system_object_expr;
641 // If we are compiling our runtime,
642 // and we are defining ValueType, then our
643 // parent is `System.Object'.
645 if (!RootContext.StdLib && Name == "System.ValueType")
646 parent = TypeManager.system_object_expr;
653 // Bases should be null if there are no bases at all
658 TypeExpr name = ResolveTypeExpr ((Expression) bases [0], false, Location);
669 parent = TypeManager.system_object_expr;
675 if (name.IsValueType)
676 detail = " (a class can not inherit from a struct/enum)";
678 Report.Error (509, "class `"+ Name +
679 "': Cannot inherit from sealed class `"+
680 name.Name + "'" + detail);
685 if (!parent.CanInheritFrom ()){
686 Report.Error (644, Location,
687 "`{0}' cannot inherit from special class `{1}'",
693 if (!parent.AsAccessible (this, ModFlags))
694 Report.Error (60, Location,
695 "Inconsistent accessibility: base class `" +
696 name.Name + "' is less accessible than class `" +
704 base_class_name = parent.Name;
706 TypeExpr [] ifaces = new TypeExpr [count-start];
708 for (i = start, j = 0; i < count; i++, j++){
709 Expression name = (Expression) bases [i];
710 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
711 if (resolved == null)
714 bases [i] = resolved;
716 if (is_class == false && !resolved.IsInterface){
717 Report.Error (527, "In Struct `" + Name + "', type `"+
718 name +"' is not an interface");
723 if (resolved.IsClass) {
725 Report.Error (527, "In Class `" + Name + "', type `"+
726 name+"' is not an interface");
732 for (int x = 0; x < j; x++) {
733 if (resolved == ifaces [x]) {
734 Report.Error (528, "`" + name + "' is already listed in interface list");
740 ifaces [j] = resolved;
743 return TypeManager.ExpandInterfaces (ifaces);
749 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
751 public override TypeBuilder DefineType ()
756 if (TypeBuilder != null)
763 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
775 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
777 ifaces = GetClassBases (is_class, out parent, out error);
782 if (!is_class && TypeManager.value_type == null)
783 throw new Exception ();
785 TypeAttributes type_attributes = TypeAttr;
789 ptype = parent.ResolveType (ec);
794 if (TypeManager.NamespaceClash (Name, Location)) {
799 ModuleBuilder builder = CodeGen.ModuleBuilder;
800 TypeBuilder = builder.DefineType (
801 Name, type_attributes, ptype, null);
804 TypeBuilder builder = Parent.DefineType ();
808 TypeBuilder = builder.DefineNestedType (
809 Basename, type_attributes, ptype, null);
813 // Structs with no fields need to have at least one byte.
814 // The right thing would be to set the PackingSize in a DefineType
815 // but there are no functions that allow interfaces *and* the size to
819 if (!is_class && !have_nonstatic_fields){
820 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
821 FieldAttributes.Private);
824 // add interfaces that were not added at type creation
825 if (ifaces != null) {
826 foreach (TypeExpr iface in ifaces) {
827 Type itype = iface.ResolveType (ec);
828 TypeBuilder.AddInterfaceImplementation (itype);
833 // Finish the setup for the EmitContext
835 ec.ContainerType = TypeBuilder;
837 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
839 if ((parent != null) && parent.IsAttribute) {
840 RootContext.RegisterAttribute (this);
841 TypeManager.RegisterAttrType (TypeBuilder, this);
843 RootContext.RegisterOrder (this);
845 if (Interfaces != null) {
846 foreach (Interface iface in Interfaces)
847 if (iface.DefineType () == null) {
854 foreach (TypeContainer tc in Types)
855 if (tc.DefineType () == null) {
861 if (Delegates != null) {
862 foreach (Delegate d in Delegates)
863 if (d.DefineType () == null) {
870 foreach (Enum en in Enums)
871 if (en.DefineType () == null) {
883 /// Defines the MemberCore objects that are in the `list' Arraylist
885 /// The `defined_names' array contains a list of members defined in
888 static ArrayList remove_list = new ArrayList ();
889 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
893 remove_list.Clear ();
895 foreach (MemberCore mc in list){
897 if (defined_names != null)
898 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
903 if (RootContext.WarningLevel >= 4){
904 if ((mc.ModFlags & Modifiers.NEW) != 0)
905 Warning_KeywordNewNotRequired (mc.Location, mc);
907 } else if (mc is MethodCore)
908 ((MethodCore) mc).OverridesSomething = true;
910 if (!mc.Define (this)){
911 remove_list.Add (mc);
918 MemberInfo match = defined_names [idx];
920 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
924 // If we are both methods, let the method resolution emit warnings
926 if (match is MethodBase && mc is MethodCore)
929 if ((mc.ModFlags & Modifiers.NEW) == 0) {
931 if (!(match is EventInfo)) {
932 Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
936 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
940 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
944 foreach (object o in remove_list)
947 remove_list.Clear ();
951 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
952 // class is consisten. Either it is `Item' or it is the name defined by all the
953 // indexers with the `IndexerName' attribute.
955 // Turns out that the IndexerNameAttribute is applied to each indexer,
956 // but it is never emitted, instead a DefaultName attribute is attached
959 void DefineIndexers ()
961 string class_indexer_name = null;
964 // If there's both an explicit and an implicit interface implementation, the
965 // explicit one actually implements the interface while the other one is just
966 // a normal indexer. See bug #37714.
968 ArrayList list = new ArrayList ();
969 foreach (Indexer i in Indexers){
970 if (i.ExplicitInterfaceName != null)
973 foreach (Indexer i in Indexers){
974 if (i.ExplicitInterfaceName == null)
978 foreach (Indexer i in list){
983 name = i.IndexerName;
985 if (i.InterfaceType != null)
988 if (class_indexer_name == null){
989 class_indexer_name = name;
993 if (name == class_indexer_name)
997 668, "Two indexers have different names, " +
998 " you should use the same name for all your indexers");
1000 if (class_indexer_name == null)
1001 class_indexer_name = "Item";
1002 IndexerName = class_indexer_name;
1005 static void Error_KeywordNotAllowed (Location loc)
1007 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1011 /// Populates our TypeBuilder with fields and methods
1013 public override bool DefineMembers (TypeContainer container)
1015 MemberInfo [] defined_names = null;
1017 if (interface_order != null){
1018 foreach (Interface iface in interface_order)
1019 if ((iface.ModFlags & Modifiers.NEW) == 0)
1020 iface.DefineMembers (this);
1022 Error_KeywordNotAllowed (iface.Location);
1025 if (RootContext.WarningLevel > 1){
1029 // This code throws an exception in the comparer
1030 // I guess the string is not an object?
1032 ptype = TypeBuilder.BaseType;
1034 defined_names = (MemberInfo []) FindMembers (
1035 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1036 BindingFlags.Public | BindingFlags.Instance |
1037 BindingFlags.Static, null, null);
1039 Array.Sort (defined_names, mif_compare);
1043 Class pclass = Parent as Class;
1044 if (pclass != null) {
1045 string pname = null;
1047 Type t = pclass.TypeBuilder.BaseType;
1048 while ((t != null) && (ptype == null)) {
1049 pname = t.FullName + "." + Basename;
1050 ptype = RootContext.LookupType (this, pname, true, Location.Null);
1054 if ((ModFlags & Modifiers.NEW) != 0) {
1056 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1057 "inherited member. The keyword new is not required.");
1058 } else if (ptype != null) {
1059 Report.Warning (108, Location, "The keyword new is required on `" +
1060 Name + "' because it hides inherited member '" +
1063 } else if ((ModFlags & Modifiers.NEW) != 0)
1064 Error_KeywordNotAllowed (Location);
1066 if (constants != null)
1067 DefineMembers (constants, defined_names);
1070 DefineMembers (fields, defined_names);
1072 if ((RootContext.WarningLevel >= 4) && (fields != null)) {
1073 foreach (Field f in fields) {
1074 if (((f.ModFlags & Modifiers.READONLY) != 0) && !f.IsAssigned)
1075 Report.Warning (649, "Field `" + MakeFQN (Name, f.Name) + "; is never " +
1076 "assigned and will ever have its default value");
1081 if (instance_constructors == null){
1082 if (default_constructor == null)
1083 DefineDefaultConstructor (false);
1086 if (initialized_static_fields != null &&
1087 default_static_constructor == null)
1088 DefineDefaultConstructor (true);
1091 if (this is Struct){
1093 // Structs can not have initialized instance
1096 if (initialized_static_fields != null &&
1097 default_static_constructor == null)
1098 DefineDefaultConstructor (true);
1100 if (initialized_fields != null)
1101 ReportStructInitializedInstanceError ();
1104 Pending = PendingImplementation.GetPendingImplementations (this);
1107 // Constructors are not in the defined_names array
1109 if (instance_constructors != null)
1110 DefineMembers (instance_constructors, null);
1112 if (default_static_constructor != null)
1113 default_static_constructor.Define (this);
1115 if (methods != null)
1116 DefineMembers (methods, defined_names);
1118 if (properties != null)
1119 DefineMembers (properties, defined_names);
1122 DefineMembers (events, defined_names);
1124 if (indexers != null) {
1127 IndexerName = "Item";
1129 if (operators != null){
1130 DefineMembers (operators, null);
1132 CheckPairedOperators ();
1136 DefineMembers (enums, defined_names);
1138 if (delegates != null)
1139 DefineMembers (delegates, defined_names);
1142 if (TypeBuilder.BaseType != null)
1143 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1145 member_cache = new MemberCache (this);
1152 public override bool Define (TypeContainer container)
1154 if (interface_order != null){
1155 foreach (Interface iface in interface_order)
1156 if ((iface.ModFlags & Modifiers.NEW) == 0)
1157 iface.Define (this);
1164 /// This function is based by a delegate to the FindMembers routine
1166 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1172 /// This filter is used by FindMembers, and we just keep
1173 /// a global for the filter to `AlwaysAccept'
1175 static MemberFilter accepting_filter;
1179 /// A member comparission method based on name only
1181 static IComparer mif_compare;
1183 static TypeContainer ()
1185 accepting_filter = new MemberFilter (AlwaysAccept);
1186 mif_compare = new MemberInfoCompare ();
1190 /// This method returns the members of this type just like Type.FindMembers would
1191 /// Only, we need to use this for types which are _being_ defined because MS'
1192 /// implementation can't take care of that.
1195 // FIXME: return an empty static array instead of null, that cleans up
1196 // some code and is consistent with some coding conventions I just found
1200 // Notice that in various cases we check if our field is non-null,
1201 // something that would normally mean that there was a bug elsewhere.
1203 // The problem happens while we are defining p-invoke methods, as those
1204 // will trigger a FindMembers, but this happens before things are defined
1206 // Since the whole process is a no-op, it is fine to check for null here.
1208 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1209 MemberFilter filter, object criteria)
1211 ArrayList members = null;
1214 if ((bf & BindingFlags.Public) != 0)
1215 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1217 if ((bf & BindingFlags.NonPublic) != 0)
1218 modflags |= Modifiers.PRIVATE;
1220 int static_mask = 0, static_flags = 0;
1221 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1222 case BindingFlags.Static:
1223 static_mask = static_flags = Modifiers.STATIC;
1226 case BindingFlags.Instance:
1227 static_mask = Modifiers.STATIC;
1232 static_mask = static_flags = 0;
1236 Timer.StartTimer (TimerType.TcFindMembers);
1239 filter = accepting_filter;
1241 if ((mt & MemberTypes.Field) != 0) {
1242 if (fields != null) {
1243 int len = fields.Count;
1244 for (int i = 0; i < len; i++) {
1245 Field f = (Field) fields [i];
1247 if ((f.ModFlags & modflags) == 0)
1249 if ((f.ModFlags & static_mask) != static_flags)
1252 FieldBuilder fb = f.FieldBuilder;
1253 if (fb != null && filter (fb, criteria) == true) {
1254 if (members == null)
1255 members = new ArrayList ();
1262 if (constants != null) {
1263 int len = constants.Count;
1264 for (int i = 0; i < len; i++) {
1265 Const con = (Const) constants [i];
1267 if ((con.ModFlags & modflags) == 0)
1269 if ((con.ModFlags & static_mask) != static_flags)
1272 FieldBuilder fb = con.FieldBuilder;
1273 if (fb != null && filter (fb, criteria) == true) {
1274 if (members == null)
1275 members = new ArrayList ();
1283 if ((mt & MemberTypes.Method) != 0) {
1284 if (methods != null) {
1285 int len = methods.Count;
1286 for (int i = 0; i < len; i++) {
1287 Method m = (Method) methods [i];
1289 if ((m.ModFlags & modflags) == 0)
1291 if ((m.ModFlags & static_mask) != static_flags)
1294 MethodBuilder mb = m.MethodBuilder;
1296 if (mb != null && filter (mb, criteria) == true) {
1297 if (members == null)
1298 members = new ArrayList ();
1305 if (operators != null) {
1306 int len = operators.Count;
1307 for (int i = 0; i < len; i++) {
1308 Operator o = (Operator) operators [i];
1310 if ((o.ModFlags & modflags) == 0)
1312 if ((o.ModFlags & static_mask) != static_flags)
1315 MethodBuilder ob = o.OperatorMethodBuilder;
1316 if (ob != null && filter (ob, criteria) == true) {
1317 if (members == null)
1318 members = new ArrayList ();
1325 if (properties != null) {
1326 int len = properties.Count;
1327 for (int i = 0; i < len; i++) {
1328 Property p = (Property) properties [i];
1330 if ((p.ModFlags & modflags) == 0)
1332 if ((p.ModFlags & static_mask) != static_flags)
1338 if (b != null && filter (b, criteria) == true) {
1339 if (members == null)
1340 members = new ArrayList ();
1346 if (b != null && filter (b, criteria) == true) {
1347 if (members == null)
1348 members = new ArrayList ();
1355 if (indexers != null) {
1356 int len = indexers.Count;
1357 for (int i = 0; i < len; i++) {
1358 Indexer ix = (Indexer) indexers [i];
1360 if ((ix.ModFlags & modflags) == 0)
1362 if ((ix.ModFlags & static_mask) != static_flags)
1368 if (b != null && filter (b, criteria) == true) {
1369 if (members == null)
1370 members = new ArrayList ();
1376 if (b != null && filter (b, criteria) == true) {
1377 if (members == null)
1378 members = new ArrayList ();
1386 if ((mt & MemberTypes.Event) != 0) {
1387 if (events != null) {
1388 int len = events.Count;
1389 for (int i = 0; i < len; i++) {
1390 Event e = (Event) events [i];
1392 if ((e.ModFlags & modflags) == 0)
1394 if ((e.ModFlags & static_mask) != static_flags)
1397 MemberInfo eb = e.EventBuilder;
1398 if (eb != null && filter (eb, criteria) == true) {
1399 if (members == null)
1400 members = new ArrayList ();
1402 members.Add (e.EventBuilder);
1408 if ((mt & MemberTypes.Property) != 0){
1409 if (properties != null) {
1410 int len = properties.Count;
1411 for (int i = 0; i < len; i++) {
1412 Property p = (Property) properties [i];
1414 if ((p.ModFlags & modflags) == 0)
1416 if ((p.ModFlags & static_mask) != static_flags)
1419 MemberInfo pb = p.PropertyBuilder;
1420 if (pb != null && filter (pb, criteria) == true) {
1421 if (members == null)
1422 members = new ArrayList ();
1424 members.Add (p.PropertyBuilder);
1429 if (indexers != null) {
1430 int len = indexers.Count;
1431 for (int i = 0; i < len; i++) {
1432 Indexer ix = (Indexer) indexers [i];
1434 if ((ix.ModFlags & modflags) == 0)
1436 if ((ix.ModFlags & static_mask) != static_flags)
1439 MemberInfo ib = ix.PropertyBuilder;
1440 if (ib != null && filter (ib, criteria) == true) {
1441 if (members == null)
1442 members = new ArrayList ();
1444 members.Add (ix.PropertyBuilder);
1450 if ((mt & MemberTypes.NestedType) != 0) {
1451 if (types != null) {
1452 int len = types.Count;
1453 for (int i = 0; i < len; i++) {
1454 TypeContainer t = (TypeContainer) types [i];
1456 if ((t.ModFlags & modflags) == 0)
1459 TypeBuilder tb = t.TypeBuilder;
1460 if (tb != null && (filter (tb, criteria) == true)) {
1461 if (members == null)
1462 members = new ArrayList ();
1469 if (enums != null) {
1470 int len = enums.Count;
1471 for (int i = 0; i < len; i++) {
1472 Enum en = (Enum) enums [i];
1474 if ((en.ModFlags & modflags) == 0)
1477 TypeBuilder tb = en.TypeBuilder;
1478 if (tb != null && (filter (tb, criteria) == true)) {
1479 if (members == null)
1480 members = new ArrayList ();
1487 if (delegates != null) {
1488 int len = delegates.Count;
1489 for (int i = 0; i < len; i++) {
1490 Delegate d = (Delegate) delegates [i];
1492 if ((d.ModFlags & modflags) == 0)
1495 TypeBuilder tb = d.TypeBuilder;
1496 if (tb != null && (filter (tb, criteria) == true)) {
1497 if (members == null)
1498 members = new ArrayList ();
1505 if (interfaces != null) {
1506 int len = interfaces.Count;
1507 for (int i = 0; i < len; i++) {
1508 Interface iface = (Interface) interfaces [i];
1510 if ((iface.ModFlags & modflags) == 0)
1513 TypeBuilder tb = iface.TypeBuilder;
1514 if (tb != null && (filter (tb, criteria) == true)) {
1515 if (members == null)
1516 members = new ArrayList ();
1524 if ((mt & MemberTypes.Constructor) != 0){
1525 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1526 int len = instance_constructors.Count;
1527 for (int i = 0; i < len; i++) {
1528 Constructor c = (Constructor) instance_constructors [i];
1530 ConstructorBuilder cb = c.ConstructorBuilder;
1531 if (cb != null && filter (cb, criteria) == true) {
1532 if (members == null)
1533 members = new ArrayList ();
1540 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1541 ConstructorBuilder cb =
1542 default_static_constructor.ConstructorBuilder;
1544 if (cb != null && filter (cb, criteria) == true) {
1545 if (members == null)
1546 members = new ArrayList ();
1554 // Lookup members in parent if requested.
1556 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1557 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1558 if (list.Count > 0) {
1559 if (members == null)
1560 members = new ArrayList ();
1562 members.AddRange (list);
1566 Timer.StopTimer (TimerType.TcFindMembers);
1568 if (members == null)
1569 return MemberList.Empty;
1571 return new MemberList (members);
1574 public override MemberCache MemberCache {
1576 return member_cache;
1580 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1581 MemberFilter filter, object criteria)
1583 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1586 return ds.FindMembers (mt, bf, filter, criteria);
1588 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1593 // FindMethods will look for methods not only in the type `t', but in
1594 // any interfaces implemented by the type.
1596 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1597 MemberFilter filter, object criteria)
1603 /// Emits the values for the constants
1605 public void EmitConstants ()
1607 if (constants != null)
1608 foreach (Const con in constants)
1609 con.EmitConstant (this);
1614 /// Emits the code, this step is performed after all
1615 /// the types, enumerations, constructors
1619 if (instance_constructors != null)
1620 foreach (Constructor c in instance_constructors)
1623 if (default_static_constructor != null)
1624 default_static_constructor.Emit (this);
1626 if (methods != null)
1627 foreach (Method m in methods)
1630 if (operators != null)
1631 foreach (Operator o in operators)
1634 if (properties != null)
1635 foreach (Property p in properties)
1638 if (indexers != null){
1639 foreach (Indexer ix in indexers)
1642 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1643 this, IndexerName, ModFlags, Location);
1644 TypeBuilder.SetCustomAttribute (cb);
1648 foreach (Field f in fields)
1651 if (events != null){
1652 foreach (Event e in Events)
1656 if (Pending != null)
1657 if (Pending.VerifyPendingMethods ())
1660 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
1663 // Check for internal or private fields that were never assigned
1665 if (RootContext.WarningLevel >= 3) {
1666 if (fields != null){
1667 foreach (Field f in fields) {
1668 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1673 169, f.Location, "Private field " +
1674 MakeName (f.Name) + " is never used");
1679 // Only report 649 on level 4
1681 if (RootContext.WarningLevel < 4)
1684 if ((f.status & Field.Status.ASSIGNED) != 0)
1689 "Field " + MakeName (f.Name) + " is never assigned " +
1690 " to and will always have its default value");
1694 if (events != null){
1695 foreach (Event e in events){
1697 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1702 // if (types != null)
1703 // foreach (TypeContainer tc in types)
1707 public override void CloseType ()
1712 TypeBuilder.CreateType ();
1714 } catch (TypeLoadException){
1716 // This is fine, the code still created the type
1718 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1719 // Console.WriteLine (e.Message);
1721 Console.WriteLine ("In type: " + Name);
1726 foreach (Enum en in Enums)
1729 if (interface_order != null){
1730 foreach (Interface iface in interface_order)
1735 foreach (TypeContainer tc in Types)
1739 foreach (TypeContainer tc in Types)
1740 if (!(tc is Struct))
1744 if (Delegates != null)
1745 foreach (Delegate d in Delegates)
1749 public string MakeName (string n)
1751 return "`" + Name + "." + n + "'";
1754 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1757 108, l, "The keyword new is required on " +
1758 MakeName (mi.Name) + " because it hides `" +
1759 mi.ReflectedType.Name + "." + mi.Name + "'");
1762 public void Warning_KeywordNewNotRequired (Location l, MemberCore mc)
1765 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1766 "inherited member, the keyword new is not required");
1769 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
1772 72, l, MakeName (mi.Name) + " : cannot override; `" +
1773 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
1776 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1782 // Performs the validation on a Method's modifiers (properties have
1783 // the same properties).
1785 public bool MethodModifiersValid (int flags, string n, Location loc)
1787 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1788 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1789 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1793 // At most one of static, virtual or override
1795 if ((flags & Modifiers.STATIC) != 0){
1796 if ((flags & vao) != 0){
1798 112, loc, "static method " + MakeName (n) + "can not be marked " +
1799 "as virtual, abstract or override");
1804 if (this is Struct){
1805 if ((flags & va) != 0){
1806 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1811 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1813 113, loc, MakeName (n) +
1814 " marked as override cannot be marked as new or virtual");
1819 // If the declaration includes the abstract modifier, then the
1820 // declaration does not include static, virtual or extern
1822 if ((flags & Modifiers.ABSTRACT) != 0){
1823 if ((flags & Modifiers.EXTERN) != 0){
1825 180, loc, MakeName (n) + " can not be both abstract and extern");
1829 if ((flags & Modifiers.VIRTUAL) != 0){
1831 503, loc, MakeName (n) + " can not be both abstract and virtual");
1835 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1837 513, loc, MakeName (n) +
1838 " is abstract but its container class is not");
1844 if ((flags & Modifiers.PRIVATE) != 0){
1845 if ((flags & vao) != 0){
1847 621, loc, MakeName (n) +
1848 " virtual or abstract members can not be private");
1853 if ((flags & Modifiers.SEALED) != 0){
1854 if ((flags & Modifiers.OVERRIDE) == 0){
1856 238, loc, MakeName (n) +
1857 " cannot be sealed because it is not an override");
1865 Hashtable builder_and_args;
1867 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1869 if (builder_and_args == null)
1870 builder_and_args = new Hashtable ();
1875 /// Performs checks for an explicit interface implementation. First it
1876 /// checks whether the `interface_type' is a base inteface implementation.
1877 /// Then it checks whether `name' exists in the interface type.
1879 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1883 if (ifaces != null){
1884 foreach (TypeExpr t in ifaces){
1885 if (t.Type == interface_type){
1893 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1900 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1902 Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1909 string IMemberContainer.Name {
1915 Type IMemberContainer.Type {
1921 IMemberContainer IMemberContainer.Parent {
1923 return parent_container;
1927 MemberCache IMemberContainer.MemberCache {
1929 return member_cache;
1933 bool IMemberContainer.IsInterface {
1939 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1941 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1945 // Operator pair checking
1948 class OperatorEntry {
1950 public Type ret_type;
1951 public Type type1, type2;
1953 public Operator.OpType ot;
1955 public OperatorEntry (int f, Operator o)
1959 ret_type = o.OperatorMethod.GetReturnType ();
1960 Type [] pt = o.OperatorMethod.ParameterTypes;
1964 ot = o.OperatorType;
1967 public override int GetHashCode ()
1969 return ret_type.GetHashCode ();
1972 public override bool Equals (object o)
1974 OperatorEntry other = (OperatorEntry) o;
1976 if (other.ret_type != ret_type)
1978 if (other.type1 != type1)
1980 if (other.type2 != type2)
1987 // Checks that some operators come in pairs:
1993 // They are matched based on the return type and the argument types
1995 void CheckPairedOperators ()
1997 Hashtable pairs = new Hashtable (null, null);
1998 Operator true_op = null;
1999 Operator false_op = null;
2000 bool has_equality_or_inequality = false;
2002 // Register all the operators we care about.
2003 foreach (Operator op in operators){
2006 switch (op.OperatorType){
2007 case Operator.OpType.Equality:
2009 has_equality_or_inequality = true;
2011 case Operator.OpType.Inequality:
2013 has_equality_or_inequality = true;
2016 case Operator.OpType.True:
2019 case Operator.OpType.False:
2023 case Operator.OpType.GreaterThan:
2025 case Operator.OpType.LessThan:
2028 case Operator.OpType.GreaterThanOrEqual:
2030 case Operator.OpType.LessThanOrEqual:
2036 OperatorEntry oe = new OperatorEntry (reg, op);
2038 object o = pairs [oe];
2042 oe = (OperatorEntry) o;
2047 if (true_op != null){
2048 if (false_op == null)
2049 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2050 } else if (false_op != null)
2051 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2054 // Look for the mistakes.
2056 foreach (DictionaryEntry de in pairs){
2057 OperatorEntry oe = (OperatorEntry) de.Key;
2064 case Operator.OpType.Equality:
2067 case Operator.OpType.Inequality:
2070 case Operator.OpType.GreaterThan:
2073 case Operator.OpType.LessThan:
2076 case Operator.OpType.GreaterThanOrEqual:
2079 case Operator.OpType.LessThanOrEqual:
2083 Report.Error (216, oe.op.Location,
2084 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2087 if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2088 MethodSignature equals_ms = new MethodSignature (
2089 "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2090 MethodSignature hash_ms = new MethodSignature (
2091 "GetHashCode", TypeManager.int32_type, new Type [0]);
2093 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2094 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2096 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2097 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2100 bool equals_ok = false;
2101 if ((equals_ml != null) && (equals_ml.Count == 1))
2102 equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2103 bool hash_ok = false;
2104 if ((hash_ml != null) && (hash_ml.Count == 1))
2105 hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2108 Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2109 "not override Object.Equals (object o)");
2111 Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2112 "not override Object.GetHashCode ()");
2119 public class Class : TypeContainer {
2121 // Modifiers allowed in a class declaration
2123 public const int AllowedModifiers =
2126 Modifiers.PROTECTED |
2127 Modifiers.INTERNAL |
2129 Modifiers.ABSTRACT |
2133 public Class (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2134 : base (ns, parent, name, l)
2138 if (parent.Parent == null)
2139 accmods = Modifiers.INTERNAL;
2141 accmods = Modifiers.PRIVATE;
2143 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2144 this.attributes = attrs;
2148 // FIXME: How do we deal with the user specifying a different
2151 public override TypeAttributes TypeAttr {
2153 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2158 public class Struct : TypeContainer {
2160 // Modifiers allowed in a struct declaration
2162 public const int AllowedModifiers =
2165 Modifiers.PROTECTED |
2166 Modifiers.INTERNAL |
2170 public Struct (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2171 : base (ns, parent, name, l)
2175 if (parent.Parent == null)
2176 accmods = Modifiers.INTERNAL;
2178 accmods = Modifiers.PRIVATE;
2180 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2182 this.ModFlags |= Modifiers.SEALED;
2183 this.attributes = attrs;
2188 // FIXME: Allow the user to specify a different set of attributes
2189 // in some cases (Sealed for example is mandatory for a class,
2190 // but what SequentialLayout can be changed
2192 public override TypeAttributes TypeAttr {
2194 return base.TypeAttr |
2195 TypeAttributes.SequentialLayout |
2196 TypeAttributes.Sealed |
2197 TypeAttributes.BeforeFieldInit;
2202 public abstract class MethodCore : MemberBase {
2203 public readonly Parameters Parameters;
2204 protected Block block;
2205 protected DeclSpace ds;
2208 // Parameters, cached for semantic analysis.
2210 protected InternalParameters parameter_info;
2211 protected Type [] parameter_types;
2214 // This is set from TypeContainer.DefineMembers if this method overrides something.
2216 public bool OverridesSomething;
2218 public MethodCore (DeclSpace ds, Expression type, int mod, int allowed_mod,
2219 string name, Attributes attrs, Parameters parameters, Location loc)
2220 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
2222 Parameters = parameters;
2227 // Returns the System.Type array for the parameters of this method
2229 public Type [] ParameterTypes {
2231 return parameter_types;
2235 public InternalParameters ParameterInfo
2238 return parameter_info;
2242 public Block Block {
2252 protected virtual bool DoDefineParameters ()
2254 // Check if arguments were correct
2255 parameter_types = Parameters.GetParameterInfo (ds);
2256 if ((parameter_types == null) || !CheckParameters (ds, parameter_types))
2259 parameter_info = new InternalParameters (ds, Parameters);
2261 Parameter array_param = Parameters.ArrayParameter;
2262 if ((array_param != null) &&
2263 (!array_param.ParameterType.IsArray ||
2264 (array_param.ParameterType.GetArrayRank () != 1))) {
2265 Report.Error (225, Location, "params parameter has to be a single dimensional array");
2272 public CallingConventions GetCallingConvention (bool is_class)
2274 CallingConventions cc = 0;
2276 cc = Parameters.GetCallingConvention ();
2279 if ((ModFlags & Modifiers.STATIC) == 0)
2280 cc |= CallingConventions.HasThis;
2282 // FIXME: How is `ExplicitThis' used in C#?
2288 // The method's attributes are passed in because we need to extract
2289 // the "return:" attribute from there to apply on the return type
2291 static public void LabelParameters (EmitContext ec,
2293 Parameters parameters,
2294 Attributes method_attrs,
2298 // Define each type attribute (in/out/ref) and
2299 // the argument names.
2301 Parameter [] p = parameters.FixedParameters;
2304 MethodBuilder mb = null;
2305 ConstructorBuilder cb = null;
2307 if (builder is MethodBuilder)
2308 mb = (MethodBuilder) builder;
2310 cb = (ConstructorBuilder) builder;
2313 for (i = 0; i < p.Length; i++) {
2314 ParameterBuilder pb;
2315 ParameterAttributes par_attr = p [i].Attributes;
2318 pb = cb.DefineParameter (
2319 i + 1, par_attr, p [i].Name);
2321 pb = mb.DefineParameter (
2322 i + 1, par_attr, p [i].Name);
2324 Attributes attr = p [i].OptAttributes;
2326 Attribute.ApplyAttributes (ec, pb, pb, attr);
2328 if (par_attr == ParameterAttributes.Out){
2329 if (attr.Contains (TypeManager.in_attribute_type))
2330 Report.Error (36, loc,
2331 "Can not use [In] attribute on out parameter");
2337 if (parameters.ArrayParameter != null){
2338 ParameterBuilder pb;
2339 Parameter array_param = parameters.ArrayParameter;
2342 pb = cb.DefineParameter (
2343 i + 1, array_param.Attributes,
2346 pb = mb.DefineParameter (
2347 i + 1, array_param.Attributes,
2350 CustomAttributeBuilder a = new CustomAttributeBuilder (
2351 TypeManager.cons_param_array_attribute, new object [0]);
2353 pb.SetCustomAttribute (a);
2357 // And now for the return type attribute decoration
2359 ParameterBuilder ret_pb;
2360 Attributes ret_attrs = null;
2362 if (mb == null || method_attrs == null)
2365 foreach (AttributeSection asec in method_attrs.AttributeSections) {
2367 if (asec.Target != "return")
2370 if (ret_attrs == null)
2371 ret_attrs = new Attributes (asec);
2373 ret_attrs.AddAttributeSection (asec);
2376 if (ret_attrs != null) {
2378 ret_pb = mb.DefineParameter (0, ParameterAttributes.None, "");
2379 Attribute.ApplyAttributes (ec, ret_pb, ret_pb, ret_attrs);
2381 } catch (ArgumentOutOfRangeException) {
2384 ".NET SDK 1.0 does not permit setting custom attributes" +
2385 " on the return type of a method");
2391 public class Method : MethodCore, IIteratorContainer {
2392 public MethodBuilder MethodBuilder;
2393 public MethodData MethodData;
2396 /// Modifiers allowed in a class declaration
2398 const int AllowedModifiers =
2401 Modifiers.PROTECTED |
2402 Modifiers.INTERNAL |
2407 Modifiers.OVERRIDE |
2408 Modifiers.ABSTRACT |
2413 // return_type can be "null" for VOID values.
2415 public Method (DeclSpace ds, Expression return_type, int mod, string name,
2416 Parameters parameters, Attributes attrs, Location l)
2417 : base (ds, return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2421 // Returns the `System.Type' for the ReturnType of this
2422 // function. Provides a nice cache. (used between semantic analysis
2423 // and actual code generation
2425 public Type GetReturnType ()
2430 // Whether this is an operator method.
2431 public bool IsOperator;
2433 void DuplicateEntryPoint (MethodInfo b, Location location)
2437 "Program `" + CodeGen.FileName +
2438 "' has more than one entry point defined: `" +
2439 TypeManager.CSharpSignature(b) + "'");
2442 void Report28 (MethodInfo b)
2446 "`" + TypeManager.CSharpSignature(b) +
2447 "' has the wrong signature to be an entry point");
2450 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2452 if (b.ReturnType != TypeManager.void_type &&
2453 b.ReturnType != TypeManager.int32_type)
2456 if (pinfo.Count == 0)
2459 if (pinfo.Count > 1)
2462 Type t = pinfo.ParameterType(0);
2464 (t.GetArrayRank() == 1) &&
2465 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
2466 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2473 // Checks our base implementation if any
2475 protected override bool CheckBase (TypeContainer container)
2477 base.CheckBase (container);
2479 // Check whether arguments were correct.
2480 if (!DoDefineParameters ())
2483 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2485 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2489 mi_this = TypeContainer.FindMembers (
2490 container.TypeBuilder, MemberTypes.Method,
2491 BindingFlags.NonPublic | BindingFlags.Public |
2492 BindingFlags.Static | BindingFlags.Instance |
2493 BindingFlags.DeclaredOnly,
2494 MethodSignature.method_signature_filter, ms);
2496 if (mi_this.Count > 0) {
2497 Report.Error (111, Location, "Class `" + container.Name + "' " +
2498 "already defines a member called `" + Name + "' " +
2499 "with the same parameter types");
2505 // Verify if the parent has a type with the same name, and then
2506 // check whether we have to create a new slot for it or not.
2508 Type ptype = container.TypeBuilder.BaseType;
2510 // ptype is only null for System.Object while compiling corlib.
2512 MemberList mi, mi_static, mi_instance;
2514 mi_instance = TypeContainer.FindMembers (
2515 ptype, MemberTypes.Method,
2516 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2517 MethodSignature.inheritable_method_signature_filter,
2520 if (mi_instance.Count > 0){
2523 mi_static = TypeContainer.FindMembers (
2524 ptype, MemberTypes.Method,
2525 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2526 MethodSignature.inheritable_method_signature_filter, ms);
2528 if (mi_static.Count > 0)
2534 if (mi != null && mi.Count > 0){
2535 parent_method = (MethodInfo) mi [0];
2536 string name = parent_method.DeclaringType.Name + "." +
2539 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
2542 if ((ModFlags & Modifiers.NEW) == 0) {
2543 Type parent_ret = TypeManager.TypeToCoreType (
2544 parent_method.ReturnType);
2546 if (parent_ret != MemberType) {
2548 508, Location, container.MakeName (Name) + ": cannot " +
2549 "change return type when overriding " +
2550 "inherited member " + name);
2555 if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
2556 WarningNotHiding (container);
2558 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2559 Report.Error (115, Location,
2560 container.MakeName (Name) +
2561 " no suitable methods found to override");
2564 } else if ((ModFlags & Modifiers.NEW) != 0)
2565 WarningNotHiding (container);
2573 public override bool Define (TypeContainer container)
2575 if (!DoDefine (container))
2578 if (!CheckBase (container))
2581 CallingConventions cc = GetCallingConvention (container is Class);
2583 MethodData = new MethodData (container, this, null, MemberType,
2584 ParameterTypes, ParameterInfo, cc,
2585 OptAttributes, ModFlags, flags, true);
2587 if (!MethodData.Define (container))
2591 // Setup iterator if we are one
2593 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
2594 IteratorHandler ih = new IteratorHandler (
2595 Name, container, MemberType,
2596 ParameterTypes, ParameterInfo,
2597 ModFlags, Location);
2599 Block new_block = ih.Setup (block);
2600 if (new_block == null)
2605 MethodBuilder = MethodData.MethodBuilder;
2608 // This is used to track the Entry Point,
2610 if (Name == "Main" &&
2611 ((ModFlags & Modifiers.STATIC) != 0) &&
2612 (RootContext.MainClass == null ||
2613 RootContext.MainClass == container.TypeBuilder.FullName)){
2614 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2615 if (RootContext.EntryPoint == null) {
2616 RootContext.EntryPoint = MethodBuilder;
2617 RootContext.EntryPointLocation = Location;
2619 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2620 DuplicateEntryPoint (MethodBuilder, Location);
2623 Report28(MethodBuilder);
2632 public void Emit (TypeContainer container)
2634 MethodData.Emit (container, Block, this);
2638 void IIteratorContainer.SetYields ()
2640 ModFlags |= Modifiers.METHOD_YIELDS;
2644 public abstract class ConstructorInitializer {
2645 ArrayList argument_list;
2646 ConstructorInfo parent_constructor;
2647 Parameters parameters;
2650 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2653 this.argument_list = argument_list;
2654 this.parameters = parameters;
2658 public ArrayList Arguments {
2660 return argument_list;
2664 public bool Resolve (EmitContext ec)
2666 Expression parent_constructor_group;
2669 ec.CurrentBlock = new Block (null, Block.Flags.Implicit, parameters);
2671 if (argument_list != null){
2672 foreach (Argument a in argument_list){
2673 if (!a.Resolve (ec, loc))
2677 ec.CurrentBlock = null;
2679 if (this is ConstructorBaseInitializer) {
2680 if (ec.ContainerType.BaseType == null)
2683 t = ec.ContainerType.BaseType;
2684 if (ec.ContainerType.IsValueType) {
2685 Report.Error (522, loc,
2686 "structs cannot call base class constructors");
2690 t = ec.ContainerType;
2692 parent_constructor_group = Expression.MemberLookup (
2693 ec, t, null, t, ".ctor",
2694 MemberTypes.Constructor,
2695 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2698 if (parent_constructor_group == null){
2699 Report.Error (1501, loc,
2700 "Can not find a constructor for this argument list");
2704 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2705 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2707 if (parent_constructor == null){
2708 Report.Error (1501, loc,
2709 "Can not find a constructor for this argument list");
2716 public void Emit (EmitContext ec)
2718 if (parent_constructor != null){
2719 ec.Mark (loc, false);
2721 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2723 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
2728 public class ConstructorBaseInitializer : ConstructorInitializer {
2729 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2730 base (argument_list, pars, l)
2735 public class ConstructorThisInitializer : ConstructorInitializer {
2736 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2737 base (argument_list, pars, l)
2742 public class Constructor : MethodCore {
2743 public ConstructorBuilder ConstructorBuilder;
2744 public ConstructorInitializer Initializer;
2745 new public Attributes OptAttributes;
2748 // Modifiers allowed for a constructor.
2750 public const int AllowedModifiers =
2752 Modifiers.PROTECTED |
2753 Modifiers.INTERNAL |
2760 // The spec claims that static is not permitted, but
2761 // my very own code has static constructors.
2763 public Constructor (DeclSpace ds, string name, Parameters args,
2764 ConstructorInitializer init, Location l)
2765 : base (ds, null, 0, AllowedModifiers, name, null, args, l)
2771 // Returns true if this is a default constructor
2773 public bool IsDefault ()
2775 if ((ModFlags & Modifiers.STATIC) != 0)
2776 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2777 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2780 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2781 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2782 (Initializer is ConstructorBaseInitializer) &&
2783 (Initializer.Arguments == null);
2787 // Creates the ConstructorBuilder
2789 public override bool Define (TypeContainer container)
2791 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2792 MethodAttributes.SpecialName);
2794 // Check if arguments were correct.
2795 if (!DoDefineParameters ())
2798 if ((ModFlags & Modifiers.STATIC) != 0){
2799 ca |= MethodAttributes.Static | MethodAttributes.Private;
2801 if (container is Struct && ParameterTypes.Length == 0){
2804 "Structs can not contain explicit parameterless " +
2808 ca |= MethodAttributes.HideBySig;
2810 if ((ModFlags & Modifiers.PUBLIC) != 0)
2811 ca |= MethodAttributes.Public;
2812 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2813 if ((ModFlags & Modifiers.INTERNAL) != 0)
2814 ca |= MethodAttributes.FamORAssem;
2816 ca |= MethodAttributes.Family;
2817 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2818 ca |= MethodAttributes.Assembly;
2819 else if (IsDefault ())
2820 ca |= MethodAttributes.Public;
2822 ca |= MethodAttributes.Private;
2825 ConstructorBuilder = container.TypeBuilder.DefineConstructor (
2826 ca, GetCallingConvention (container is Class), ParameterTypes);
2828 if ((ModFlags & Modifiers.UNSAFE) != 0)
2829 ConstructorBuilder.InitLocals = false;
2832 // HACK because System.Reflection.Emit is lame
2834 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2837 "Class `" +container.Name+ "' already contains a definition with the " +
2838 "same return value and parameter types for constructor `" + Name
2849 public void Emit (TypeContainer container)
2851 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2852 EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
2855 // extern methods have no bodies
2857 if ((ModFlags & Modifiers.EXTERN) != 0) {
2858 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
2860 179, Location, "External constructor `" +
2861 TypeManager.CSharpSignature (ConstructorBuilder) +
2862 "' can not have a body");
2865 } else if (block == null) {
2867 501, Location, "Constructor `" +
2868 TypeManager.CSharpSignature (ConstructorBuilder) +
2869 "' must declare a body since it is not marked extern");
2873 if ((ModFlags & Modifiers.STATIC) == 0){
2874 if (container is Class && Initializer == null)
2875 Initializer = new ConstructorBaseInitializer (
2876 null, Parameters.EmptyReadOnlyParameters, Location);
2880 // Spec mandates that Initializers will not have
2884 if (Initializer != null && !Initializer.Resolve (ec))
2886 ec.IsStatic = false;
2889 MethodCore.LabelParameters (ec, ConstructorBuilder,
2890 Parameters, OptAttributes, Location);
2892 SymbolWriter sw = CodeGen.SymbolWriter;
2893 bool generate_debugging = false;
2895 if ((sw != null) && (block != null) &&
2896 !Location.IsNull (Location) &&
2897 !Location.IsNull (block.EndLocation)) {
2899 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
2901 generate_debugging = true;
2905 // Classes can have base initializers and instance field initializers.
2907 if (container is Class){
2908 if ((ModFlags & Modifiers.STATIC) == 0){
2911 // If we use a "this (...)" constructor initializer, then
2912 // do not emit field initializers, they are initialized in the other constructor
2914 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
2915 container.EmitFieldInitializers (ec);
2918 if (Initializer != null)
2919 Initializer.Emit (ec);
2921 if ((ModFlags & Modifiers.STATIC) != 0)
2922 container.EmitFieldInitializers (ec);
2924 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes);
2926 // If this is a non-static `struct' constructor and doesn't have any
2927 // initializer, it must initialize all of the struct's fields.
2928 if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
2929 Block.AddThisVariable (container, Location);
2931 ec.EmitTopBlock (block, ParameterInfo, Location);
2933 if (generate_debugging)
2941 // Encapsulates most of the Method's state
2943 public class MethodData {
2945 // The return type of this method
2947 public readonly Type ReturnType;
2948 public readonly Type[] ParameterTypes;
2949 public readonly InternalParameters ParameterInfo;
2950 public readonly CallingConventions CallingConventions;
2951 public readonly Attributes OptAttributes;
2952 public readonly Location Location;
2955 // Are we implementing an interface ?
2957 public bool IsImplementing = false;
2962 protected DeclSpace ds;
2963 protected MemberBase member;
2964 protected int modifiers;
2965 protected MethodAttributes flags;
2966 protected bool is_method;
2967 protected string accessor_name;
2970 // It can either hold a string with the condition, or an arraylist of conditions.
2971 object conditionals;
2973 MethodBuilder builder = null;
2974 public MethodBuilder MethodBuilder {
2980 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
2981 Type [] parameter_types, InternalParameters parameters,
2982 CallingConventions cc, Attributes opt_attrs,
2983 int modifiers, MethodAttributes flags, bool is_method)
2986 this.member = member;
2987 this.accessor_name = name;
2988 this.ReturnType = return_type;
2989 this.ParameterTypes = parameter_types;
2990 this.ParameterInfo = parameters;
2991 this.CallingConventions = cc;
2992 this.OptAttributes = opt_attrs;
2993 this.modifiers = modifiers;
2995 this.is_method = is_method;
2996 this.Location = member.Location;
2997 this.conditionals = null;
3003 Attribute dllimport_attribute = null;
3004 string obsolete = null;
3005 bool obsolete_error = false;
3007 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
3009 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
3012 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
3013 if (asec.Attributes == null)
3016 foreach (Attribute a in asec.Attributes) {
3017 if (a.Name == "Conditional") {
3018 if (!ApplyConditionalAttribute (a))
3020 } else if (a.Name == "Obsolete") {
3021 if (!ApplyObsoleteAttribute (a))
3023 } else if (a.Name.IndexOf ("DllImport") != -1) {
3025 a.Type = TypeManager.dllimport_type;
3026 Attribute.Error_AttributeNotValidForElement (a, Location);
3029 if (!ApplyDllImportAttribute (a))
3039 // Applies the `DllImport' attribute to the method.
3041 protected virtual bool ApplyDllImportAttribute (Attribute a)
3043 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3044 if ((modifiers & extern_static) != extern_static) {
3045 Report.Error (601, Location,
3046 "The DllImport attribute must be specified on a method " +
3047 "marked `static' and `extern'.");
3051 flags |= MethodAttributes.PinvokeImpl;
3052 dllimport_attribute = a;
3057 // Applies the `Obsolete' attribute to the method.
3059 protected virtual bool ApplyObsoleteAttribute (Attribute a)
3061 if (obsolete != null) {
3062 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
3066 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
3067 return obsolete != null;
3071 // Applies the `Conditional' attribute to the method.
3073 protected virtual bool ApplyConditionalAttribute (Attribute a)
3075 // The Conditional attribute is only valid on methods.
3077 Attribute.Error_AttributeNotValidForElement (a, Location);
3081 string condition = a.Conditional_GetConditionName ();
3083 if (condition == null)
3086 if (ReturnType != TypeManager.void_type) {
3087 Report.Error (578, Location,
3088 "Conditional not valid on `" + member.Name + "' " +
3089 "because its return type is not void");
3093 if ((modifiers & Modifiers.OVERRIDE) != 0) {
3094 Report.Error (243, Location,
3095 "Conditional not valid on `" + member.Name + "' " +
3096 "because it is an override method");
3100 if (member.IsExplicitImpl) {
3101 Report.Error (577, Location,
3102 "Conditional not valid on `" + member.Name + "' " +
3103 "because it is an explicit interface implementation");
3107 if (IsImplementing) {
3108 Report.Error (623, Location,
3109 "Conditional not valid on `" + member.Name + "' " +
3110 "because it is an interface method");
3115 // The likelyhood that the conditional will be more than 1 is very slim
3117 if (conditionals == null)
3118 conditionals = condition;
3119 else if (conditionals is string){
3120 string s = (string) conditionals;
3121 conditionals = new ArrayList ();
3122 ((ArrayList)conditionals).Add (s);
3124 ((ArrayList)conditionals).Add (condition);
3130 // Checks whether this method should be ignored due to its Conditional attributes.
3132 bool ShouldIgnore (Location loc)
3134 // When we're overriding a virtual method, we implicitly inherit the
3135 // Conditional attributes from our parent.
3136 if (member.ParentMethod != null) {
3137 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3138 member.ParentMethod, loc);
3140 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3144 if (conditionals != null){
3145 if (conditionals is string){
3146 if (RootContext.AllDefines [conditionals] == null)
3149 foreach (string condition in (ArrayList) conditionals)
3150 if (RootContext.AllDefines [condition] == null)
3158 // Returns the TypeManager.MethodFlags for this method.
3159 // This emits an error 619 / warning 618 if the method is obsolete.
3160 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3162 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3164 TypeManager.MethodFlags flags = 0;
3166 if (obsolete != null) {
3167 if (obsolete_error) {
3168 Report.Error (619, loc, "Method `" + member.Name +
3169 "' is obsolete: `" + obsolete + "'");
3170 return TypeManager.MethodFlags.IsObsoleteError;
3172 Report.Warning (618, loc, "Method `" + member.Name +
3173 "' is obsolete: `" + obsolete + "'");
3175 flags |= TypeManager.MethodFlags.IsObsolete;
3178 if (ShouldIgnore (loc))
3179 flags |= TypeManager.MethodFlags.ShouldIgnore;
3184 public virtual bool Define (TypeContainer container)
3186 MethodInfo implementing = null;
3187 string method_name, name, prefix;
3189 if (OptAttributes != null)
3190 if (!ApplyAttributes (OptAttributes, is_method))
3193 if (member.IsExplicitImpl)
3194 prefix = member.InterfaceType.FullName + ".";
3198 if (accessor_name != null)
3199 name = accessor_name + "_" + member.ShortName;
3201 name = member.ShortName;
3202 method_name = prefix + name;
3204 if (container.Pending != null){
3205 if (member is Indexer)
3206 implementing = container.Pending.IsInterfaceIndexer (
3207 member.InterfaceType, ReturnType, ParameterTypes);
3209 implementing = container.Pending.IsInterfaceMethod (
3210 member.InterfaceType, name, ReturnType, ParameterTypes);
3212 if (member.InterfaceType != null && implementing == null){
3213 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
3220 // For implicit implementations, make sure we are public, for
3221 // explicit implementations, make sure we are private.
3223 if (implementing != null){
3225 // Setting null inside this block will trigger a more
3226 // verbose error reporting for missing interface implementations
3228 // The "candidate" function has been flagged already
3229 // but it wont get cleared
3231 if (member.IsExplicitImpl){
3232 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3233 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3234 implementing = null;
3236 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
3237 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
3239 // If this is an interface method implementation,
3240 // check for public accessibility
3242 implementing = null;
3243 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
3244 // We may never be private.
3245 implementing = null;
3246 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
3248 // We may be protected if we're overriding something.
3250 implementing = null;
3255 // Static is not allowed
3257 if ((modifiers & Modifiers.STATIC) != 0){
3258 implementing = null;
3259 Modifiers.Error_InvalidModifier (Location, "static");
3264 // If implementing is still valid, set flags
3266 if (implementing != null){
3268 // When implementing interface methods, set NewSlot
3269 // unless, we are overwriting a method.
3271 if (implementing.DeclaringType.IsInterface){
3272 if ((modifiers & Modifiers.OVERRIDE) == 0)
3273 flags |= MethodAttributes.NewSlot;
3276 MethodAttributes.Virtual |
3277 MethodAttributes.HideBySig;
3279 // Set Final unless we're virtual, abstract or already overriding a method.
3280 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
3281 flags |= MethodAttributes.Final;
3283 // Get the method name from the explicit interface.
3284 if (member.InterfaceType != null) {
3285 name = implementing.Name;
3286 method_name = prefix + name;
3289 IsImplementing = true;
3293 // Create the MethodBuilder for the method
3295 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3296 if ((modifiers & Modifiers.STATIC) == 0) {
3297 Report.Error (601, Location,
3298 "The DllImport attribute must be specified on " +
3299 "a method marked 'static' and 'extern'.");
3303 EmitContext ec = new EmitContext (
3304 container, ds, Location, null, ReturnType, modifiers, false);
3306 builder = dllimport_attribute.DefinePInvokeMethod (
3307 ec, container.TypeBuilder, method_name, flags,
3308 ReturnType, ParameterTypes);
3310 builder = container.TypeBuilder.DefineMethod (
3311 method_name, flags, CallingConventions,
3312 ReturnType, ParameterTypes);
3314 if (builder == null)
3317 if ((modifiers & Modifiers.UNSAFE) != 0)
3318 builder.InitLocals = false;
3320 if (IsImplementing){
3322 // clear the pending implemntation flag
3324 if (member is Indexer) {
3325 container.Pending.ImplementIndexer (
3326 member.InterfaceType, builder, ReturnType,
3327 ParameterTypes, true);
3329 container.Pending.ImplementMethod (
3330 member.InterfaceType, name, ReturnType,
3331 ParameterTypes, member.IsExplicitImpl);
3333 if (member.IsExplicitImpl)
3334 container.TypeBuilder.DefineMethodOverride (
3335 builder, implementing);
3339 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3340 Report.Error (111, Location,
3341 "Class `" + container.Name +
3342 "' already contains a definition with the " +
3343 "same return value and parameter types as the " +
3344 "'get' method of property `" + member.Name + "'");
3348 TypeManager.AddMethod (builder, this);
3356 public virtual void Emit (TypeContainer container, Block block, object kind)
3361 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3362 ig = builder.GetILGenerator ();
3366 ec = new EmitContext (container, ds, Location, ig, ReturnType, modifiers, false);
3368 if (OptAttributes != null)
3369 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes);
3371 if (member is MethodCore)
3372 MethodCore.LabelParameters (ec, MethodBuilder,
3373 ((MethodCore) member).Parameters,
3378 // abstract or extern methods have no bodies
3380 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3381 if (block == null) {
3382 SymbolWriter sw = CodeGen.SymbolWriter;
3384 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0)) {
3385 sw.OpenMethod (container, MethodBuilder, Location, Location);
3393 // abstract or extern methods have no bodies.
3395 if ((modifiers & Modifiers.ABSTRACT) != 0)
3397 500, Location, "Abstract method `" +
3398 TypeManager.CSharpSignature (builder) +
3399 "' can not have a body");
3401 if ((modifiers & Modifiers.EXTERN) != 0)
3403 179, Location, "External method `" +
3404 TypeManager.CSharpSignature (builder) +
3405 "' can not have a body");
3411 // Methods must have a body unless they're extern or abstract
3413 if (block == null) {
3415 501, Location, "Method `" +
3416 TypeManager.CSharpSignature (builder) +
3417 "' must declare a body since it is not marked " +
3418 "abstract or extern");
3423 // Handle destructors specially
3425 // FIXME: This code generates buggy code
3427 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3428 EmitDestructor (ec, block);
3430 SymbolWriter sw = CodeGen.SymbolWriter;
3432 if ((sw != null) && !Location.IsNull (Location) &&
3433 !Location.IsNull (block.EndLocation)) {
3434 sw.OpenMethod (container, MethodBuilder, Location, block.EndLocation);
3436 ec.EmitTopBlock (block, ParameterInfo, Location);
3440 ec.EmitTopBlock (block, ParameterInfo, Location);
3444 void EmitDestructor (EmitContext ec, Block block)
3446 ILGenerator ig = ec.ig;
3448 Label finish = ig.DefineLabel ();
3449 bool old_in_try = ec.InTry;
3451 ig.BeginExceptionBlock ();
3453 ec.ReturnLabel = finish;
3454 ec.HasReturnLabel = true;
3455 ec.EmitTopBlock (block, null, Location);
3456 ec.InTry = old_in_try;
3458 // ig.MarkLabel (finish);
3459 bool old_in_finally = ec.InFinally;
3460 ec.InFinally = true;
3461 ig.BeginFinallyBlock ();
3463 if (ec.ContainerType.BaseType != null) {
3464 Expression member_lookup = Expression.MemberLookup (
3465 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3466 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, Location);
3468 if (member_lookup != null){
3469 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3471 ig.Emit (OpCodes.Ldarg_0);
3472 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3475 ec.InFinally = old_in_finally;
3477 ig.EndExceptionBlock ();
3478 //ig.MarkLabel (ec.ReturnLabel);
3479 ig.Emit (OpCodes.Ret);
3483 abstract public class MemberBase : MemberCore {
3484 public Expression Type;
3485 public readonly Attributes OptAttributes;
3487 protected MethodAttributes flags;
3490 // The "short" name of this property / indexer / event. This is the
3491 // name without the explicit interface.
3493 public string ShortName;
3496 // The type of this property / indexer / event
3498 public Type MemberType;
3501 // If true, this is an explicit interface implementation
3503 public bool IsExplicitImpl = false;
3506 // The name of the interface we are explicitly implementing
3508 public string ExplicitInterfaceName = null;
3511 // If true, the interface type we are explicitly implementing
3513 public Type InterfaceType = null;
3516 // The method we're overriding if this is an override method.
3518 protected MethodInfo parent_method = null;
3519 public MethodInfo ParentMethod {
3521 return parent_method;
3526 // The constructor is only exposed to our children
3528 protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod, string name,
3529 Attributes attrs, Location loc)
3533 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
3534 OptAttributes = attrs;
3537 protected virtual bool CheckBase (TypeContainer container)
3539 if ((container is Struct) || (RootContext.WarningLevel > 3)){
3540 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
3541 if (container is Struct){
3542 Report.Error (666, Location, "Protected member in struct declaration");
3545 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
3551 protected void WarningNotHiding (TypeContainer parent)
3555 "The member " + parent.MakeName (Name) + " does not hide an " +
3556 "inherited member. The keyword new is not required");
3560 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
3564 // FIXME: report the old/new permissions?
3567 507, Location, parent.MakeName (Name) +
3568 ": can't change the access modifiers when overriding inherited " +
3569 "member `" + name + "'");
3573 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3574 // that have been defined.
3576 // `name' is the user visible name for reporting errors (this is used to
3577 // provide the right name regarding method names and properties)
3579 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
3580 MethodInfo mb, string name)
3584 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3585 if (!(mb.IsAbstract || mb.IsVirtual)){
3587 506, Location, parent.MakeName (Name) +
3588 ": cannot override inherited member `" +
3589 name + "' because it is not " +
3590 "virtual, abstract or override");
3594 // Now we check that the overriden method is not final
3597 // This happens when implementing interface methods.
3598 if (mb.IsHideBySig && mb.IsVirtual) {
3600 506, Location, parent.MakeName (Name) +
3601 ": cannot override inherited member `" +
3602 name + "' because it is not " +
3603 "virtual, abstract or override");
3605 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
3606 "override inherited member `" + name +
3607 "' because it is sealed.");
3611 // Check that the permissions are not being changed
3613 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
3614 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
3617 // special case for "protected internal"
3620 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3622 // when overriding protected internal, the method can be declared
3623 // protected internal only within the same assembly
3626 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3627 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
3629 // assemblies differ - report an error
3632 Error_CannotChangeAccessModifiers (parent, mb, name);
3634 } else if (thisp != parentp) {
3636 // same assembly, but other attributes differ - report an error
3639 Error_CannotChangeAccessModifiers (parent, mb, name);
3642 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3644 // if it's not "protected internal", it must be "protected"
3647 Error_CannotChangeAccessModifiers (parent, mb, name);
3649 } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
3651 // protected within the same assembly - an error
3653 Error_CannotChangeAccessModifiers (parent, mb, name);
3655 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3656 (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3658 // protected ok, but other attributes differ - report an error
3660 Error_CannotChangeAccessModifiers (parent, mb, name);
3664 if (thisp != parentp){
3665 Error_CannotChangeAccessModifiers (parent, mb, name);
3671 if (mb.IsVirtual || mb.IsAbstract){
3672 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
3673 if (Name != "Finalize"){
3675 114, 2, Location, parent.MakeName (Name) +
3676 " hides inherited member `" + name +
3677 "'. To make the current member override that " +
3678 "implementation, add the override keyword, " +
3679 "otherwise use the new keyword");
3680 ModFlags |= Modifiers.NEW;
3684 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
3685 if (Name != "Finalize"){
3687 108, 1, Location, "The keyword new is required on " +
3688 parent.MakeName (Name) + " because it hides " +
3689 "inherited member `" + name + "'");
3690 ModFlags |= Modifiers.NEW;
3698 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
3702 foreach (Type partype in parameters){
3703 if (partype.IsPointer){
3706 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
3710 if (ds.AsAccessible (partype, ModFlags))
3713 if (this is Indexer)
3714 Report.Error (55, Location,
3715 "Inconsistent accessibility: parameter type `" +
3716 TypeManager.CSharpName (partype) + "' is less " +
3717 "accessible than indexer `" + Name + "'");
3718 else if ((this is Method) && ((Method) this).IsOperator)
3719 Report.Error (57, Location,
3720 "Inconsistent accessibility: parameter type `" +
3721 TypeManager.CSharpName (partype) + "' is less " +
3722 "accessible than operator `" + Name + "'");
3724 Report.Error (51, Location,
3725 "Inconsistent accessibility: parameter type `" +
3726 TypeManager.CSharpName (partype) + "' is less " +
3727 "accessible than method `" + Name + "'");
3734 protected virtual bool DoDefine (TypeContainer container)
3739 if (!container.MethodModifiersValid (ModFlags, Name, Location))
3742 flags = Modifiers.MethodAttr (ModFlags);
3744 // Lookup Type, verify validity
3745 MemberType = container.ResolveType (Type, false, Location);
3746 if (MemberType == null)
3749 if ((container.ModFlags & Modifiers.SEALED) != 0){
3750 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
3751 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
3756 // verify accessibility
3757 if (!container.AsAccessible (MemberType, ModFlags)) {
3758 if (this is Property)
3759 Report.Error (53, Location,
3760 "Inconsistent accessibility: property type `" +
3761 TypeManager.CSharpName (MemberType) + "' is less " +
3762 "accessible than property `" + Name + "'");
3763 else if (this is Indexer)
3764 Report.Error (54, Location,
3765 "Inconsistent accessibility: indexer return type `" +
3766 TypeManager.CSharpName (MemberType) + "' is less " +
3767 "accessible than indexer `" + Name + "'");
3768 else if (this is Method) {
3769 if (((Method) this).IsOperator)
3770 Report.Error (56, Location,
3771 "Inconsistent accessibility: return type `" +
3772 TypeManager.CSharpName (MemberType) + "' is less " +
3773 "accessible than operator `" + Name + "'");
3775 Report.Error (50, Location,
3776 "Inconsistent accessibility: return type `" +
3777 TypeManager.CSharpName (MemberType) + "' is less " +
3778 "accessible than method `" + Name + "'");
3780 Report.Error (52, Location,
3781 "Inconsistent accessibility: field type `" +
3782 TypeManager.CSharpName (MemberType) + "' is less " +
3783 "accessible than field `" + Name + "'");
3787 if (MemberType.IsPointer && !UnsafeOK (container))
3791 // Check for explicit interface implementation
3793 if ((ExplicitInterfaceName == null) && (Name.IndexOf ('.') != -1)){
3794 int pos = Name.LastIndexOf ('.');
3796 ExplicitInterfaceName = Name.Substring (0, pos);
3797 ShortName = Name.Substring (pos + 1);
3801 if (ExplicitInterfaceName != null) {
3802 InterfaceType = RootContext.LookupType (
3803 container, ExplicitInterfaceName, false, Location);
3804 if (InterfaceType == null)
3807 // Compute the full name that we need to export.
3808 Name = InterfaceType.FullName + "." + ShortName;
3810 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
3813 IsExplicitImpl = true;
3815 IsExplicitImpl = false;
3822 // Fields and Events both generate FieldBuilders, we use this to share
3823 // their common bits. This is also used to flag usage of the field
3825 abstract public class FieldBase : MemberBase {
3826 public FieldBuilder FieldBuilder;
3827 public Status status;
3830 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3833 // The constructor is only exposed to our children
3835 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3836 object init, Attributes attrs, Location loc)
3837 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
3843 // Whether this field has an initializer.
3845 public bool HasInitializer {
3847 return init != null;
3851 public bool IsAssigned;
3853 protected readonly Object init;
3855 Expression init_expr;
3856 bool init_expr_initialized = false;
3859 // Resolves and returns the field initializer.
3861 public Expression GetInitializerExpression (EmitContext ec)
3863 if (init_expr_initialized)
3867 if (init is Expression)
3868 e = (Expression) init;
3870 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3872 ec.IsFieldInitializer = true;
3873 e = e.DoResolve (ec);
3874 ec.IsFieldInitializer = false;
3877 init_expr_initialized = true;
3884 // The Field class is used to represents class/struct fields during parsing.
3886 public class Field : FieldBase {
3888 // Modifiers allowed in a class declaration
3890 const int AllowedModifiers =
3893 Modifiers.PROTECTED |
3894 Modifiers.INTERNAL |
3897 Modifiers.VOLATILE |
3901 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3902 Attributes attrs, Location loc)
3903 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3907 public override bool Define (TypeContainer container)
3909 Type t = container.ResolveType (Type, false, Location);
3914 CheckBase (container);
3916 if (!container.AsAccessible (t, ModFlags)) {
3917 Report.Error (52, Location,
3918 "Inconsistent accessibility: field type `" +
3919 TypeManager.CSharpName (t) + "' is less " +
3920 "accessible than field `" + Name + "'");
3924 if (t.IsPointer && !UnsafeOK (container))
3927 if (RootContext.WarningLevel > 1){
3928 Type ptype = container.TypeBuilder.BaseType;
3930 // ptype is only null for System.Object while compiling corlib.
3932 TypeContainer.FindMembers (
3933 ptype, MemberTypes.Method,
3934 BindingFlags.Public |
3935 BindingFlags.Static | BindingFlags.Instance,
3936 System.Type.FilterName, Name);
3940 if ((ModFlags & Modifiers.VOLATILE) != 0){
3944 if (TypeManager.IsEnumType (vt))
3945 vt = TypeManager.EnumToUnderlying (t);
3947 if (!((vt == TypeManager.bool_type) ||
3948 (vt == TypeManager.sbyte_type) ||
3949 (vt == TypeManager.byte_type) ||
3950 (vt == TypeManager.short_type) ||
3951 (vt == TypeManager.ushort_type) ||
3952 (vt == TypeManager.int32_type) ||
3953 (vt == TypeManager.uint32_type) ||
3954 (vt == TypeManager.char_type) ||
3955 (vt == TypeManager.float_type))){
3957 677, Location, container.MakeName (Name) +
3958 " A volatile field can not be of type `" +
3959 TypeManager.CSharpName (vt) + "'");
3964 if ((ModFlags & Modifiers.READONLY) != 0){
3967 "A field can not be both volatile and readonly");
3972 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3974 if (container is Struct &&
3975 ((fa & FieldAttributes.Static) == 0) &&
3976 t == container.TypeBuilder &&
3977 !TypeManager.IsBuiltinType (t)){
3978 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name +
3979 "' causes a cycle in the structure layout");
3983 FieldBuilder = container.TypeBuilder.DefineField (
3984 Name, t, Modifiers.FieldAttr (ModFlags));
3986 TypeManager.RegisterFieldBase (FieldBuilder, this);
3990 public void Emit (TypeContainer tc)
3992 EmitContext ec = new EmitContext (tc, Location, null,
3993 FieldBuilder.FieldType, ModFlags);
3995 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes);
4000 // `set' and `get' accessors are represented with an Accessor.
4002 public class Accessor {
4004 // Null if the accessor is empty, or a Block if not
4007 public Attributes OptAttributes;
4009 public Accessor (Block b, Attributes attrs)
4012 OptAttributes = attrs;
4017 // Properties and Indexers both generate PropertyBuilders, we use this to share
4018 // their common bits.
4020 abstract public class PropertyBase : MethodCore {
4021 public Accessor Get, Set;
4022 public PropertyBuilder PropertyBuilder;
4023 public MethodBuilder GetBuilder, SetBuilder;
4024 public MethodData GetData, SetData;
4026 protected EmitContext ec;
4028 public PropertyBase (DeclSpace ds, Expression type, string name, int mod_flags,
4029 int allowed_mod, Parameters parameters,
4030 Accessor get_block, Accessor set_block,
4031 Attributes attrs, Location loc)
4032 : base (ds, type, mod_flags, allowed_mod, name, attrs, parameters, loc)
4038 protected override bool DoDefine (TypeContainer container)
4040 if (!base.DoDefine (container))
4043 ec = new EmitContext (container, Location, null, MemberType, ModFlags);
4049 // Checks our base implementation if any
4051 protected override bool CheckBase (TypeContainer container)
4053 base.CheckBase (container);
4055 // Check whether arguments were correct.
4056 if (!DoDefineParameters ())
4063 MethodSignature ms, base_ms;
4064 if (this is Indexer) {
4065 string name, base_name;
4067 report_name = "this";
4068 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
4069 ms = new MethodSignature (name, null, ParameterTypes);
4070 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
4071 base_ms = new MethodSignature (base_name, null, ParameterTypes);
4074 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
4078 // Verify if the parent has a type with the same name, and then
4079 // check whether we have to create a new slot for it or not.
4081 Type ptype = container.TypeBuilder.BaseType;
4083 // ptype is only null for System.Object while compiling corlib.
4084 if (ptype == null) {
4085 if ((ModFlags & Modifiers.NEW) != 0)
4086 WarningNotHiding (container);
4091 MemberList props_this;
4093 props_this = TypeContainer.FindMembers (
4094 container.TypeBuilder, MemberTypes.Property,
4095 BindingFlags.NonPublic | BindingFlags.Public |
4096 BindingFlags.Static | BindingFlags.Instance |
4097 BindingFlags.DeclaredOnly,
4098 MethodSignature.method_signature_filter, ms);
4100 if (props_this.Count > 0) {
4101 Report.Error (111, Location, "Class `" + container.Name + "' " +
4102 "already defines a member called `" + report_name + "' " +
4103 "with the same parameter types");
4107 MemberList mi_props;
4109 mi_props = TypeContainer.FindMembers (
4110 ptype, MemberTypes.Property,
4111 BindingFlags.NonPublic | BindingFlags.Public |
4112 BindingFlags.Instance | BindingFlags.Static,
4113 MethodSignature.inheritable_method_signature_filter, base_ms);
4115 if (mi_props.Count > 0){
4116 PropertyInfo parent_property = (PropertyInfo) mi_props [0];
4117 string name = parent_property.DeclaringType.Name + "." +
4118 parent_property.Name;
4120 MethodInfo get, set, parent_method;
4121 get = parent_property.GetGetMethod (true);
4122 set = parent_property.GetSetMethod (true);
4125 parent_method = get;
4126 else if (set != null)
4127 parent_method = set;
4129 throw new Exception ("Internal error!");
4131 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
4134 if ((ModFlags & Modifiers.NEW) == 0) {
4135 Type parent_type = TypeManager.TypeToCoreType (
4136 parent_property.PropertyType);
4138 if (parent_type != MemberType) {
4140 508, Location, container.MakeName (Name) + ": cannot " +
4141 "change return type when overriding " +
4142 "inherited member " + name);
4147 if ((ModFlags & Modifiers.NEW) != 0)
4148 WarningNotHiding (container);
4150 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4151 if (this is Indexer)
4152 Report.Error (115, Location,
4153 container.MakeName (Name) +
4154 " no suitable indexers found to override");
4156 Report.Error (115, Location,
4157 container.MakeName (Name) +
4158 " no suitable properties found to override");
4165 public void Emit (TypeContainer tc)
4168 // The PropertyBuilder can be null for explicit implementations, in that
4169 // case, we do not actually emit the ".property", so there is nowhere to
4170 // put the attribute
4172 if (PropertyBuilder != null)
4173 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes);
4175 if (GetData != null) {
4176 GetData.Emit (tc, Get.Block, Get);
4180 if (SetData != null) {
4181 SetData.Emit (tc, Set.Block, Set);
4187 public class Property : PropertyBase {
4188 const int AllowedModifiers =
4191 Modifiers.PROTECTED |
4192 Modifiers.INTERNAL |
4196 Modifiers.OVERRIDE |
4197 Modifiers.ABSTRACT |
4202 public Property (DeclSpace ds, Expression type, string name, int mod_flags,
4203 Accessor get_block, Accessor set_block,
4204 Attributes attrs, Location loc)
4205 : base (ds, type, name, mod_flags, AllowedModifiers,
4206 Parameters.EmptyReadOnlyParameters,
4207 get_block, set_block, attrs, loc)
4211 public override bool Define (TypeContainer container)
4213 if (!DoDefine (container))
4216 if (!CheckBase (container))
4219 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4222 Type [] parameters = TypeManager.NoTypes;
4224 InternalParameters ip = new InternalParameters (
4225 container, Parameters.EmptyReadOnlyParameters);
4227 GetData = new MethodData (container, this, "get", MemberType,
4228 parameters, ip, CallingConventions.Standard,
4229 Get.OptAttributes, ModFlags, flags, false);
4231 if (!GetData.Define (container))
4234 GetBuilder = GetData.MethodBuilder;
4238 Type [] parameters = new Type [1];
4239 parameters [0] = MemberType;
4241 Parameter [] parms = new Parameter [1];
4242 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4243 InternalParameters ip = new InternalParameters (
4244 container, new Parameters (parms, null, Location));
4246 SetData = new MethodData (container, this, "set", TypeManager.void_type,
4247 parameters, ip, CallingConventions.Standard,
4248 Set.OptAttributes, ModFlags, flags, false);
4250 if (!SetData.Define (container))
4253 SetBuilder = SetData.MethodBuilder;
4254 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4257 // FIXME - PropertyAttributes.HasDefault ?
4259 PropertyAttributes prop_attr =
4260 PropertyAttributes.RTSpecialName |
4261 PropertyAttributes.SpecialName;
4263 if (!IsExplicitImpl){
4264 PropertyBuilder = container.TypeBuilder.DefineProperty (
4265 Name, prop_attr, MemberType, null);
4268 PropertyBuilder.SetGetMethod (GetBuilder);
4271 PropertyBuilder.SetSetMethod (SetBuilder);
4274 // HACK for the reasons exposed above
4276 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4279 "Class `" + container.Name +
4280 "' already contains a definition for the property `" +
4290 /// Gigantic workaround for lameness in SRE follows :
4291 /// This class derives from EventInfo and attempts to basically
4292 /// wrap around the EventBuilder so that FindMembers can quickly
4293 /// return this in it search for members
4295 public class MyEventBuilder : EventInfo {
4298 // We use this to "point" to our Builder which is
4299 // not really a MemberInfo
4301 EventBuilder MyBuilder;
4304 // We "catch" and wrap these methods
4306 MethodInfo raise, remove, add;
4308 EventAttributes attributes;
4309 Type declaring_type, reflected_type, event_type;
4314 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4316 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4318 // And now store the values in our own fields.
4320 declaring_type = type_builder;
4322 reflected_type = type_builder;
4324 attributes = event_attr;
4327 this.event_type = event_type;
4331 // Methods that you have to override. Note that you only need
4332 // to "implement" the variants that take the argument (those are
4333 // the "abstract" methods, the others (GetAddMethod()) are
4336 public override MethodInfo GetAddMethod (bool nonPublic)
4341 public override MethodInfo GetRemoveMethod (bool nonPublic)
4346 public override MethodInfo GetRaiseMethod (bool nonPublic)
4352 // These methods make "MyEventInfo" look like a Builder
4354 public void SetRaiseMethod (MethodBuilder raiseMethod)
4356 raise = raiseMethod;
4357 MyBuilder.SetRaiseMethod (raiseMethod);
4360 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4362 remove = removeMethod;
4363 MyBuilder.SetRemoveOnMethod (removeMethod);
4366 public void SetAddOnMethod (MethodBuilder addMethod)
4369 MyBuilder.SetAddOnMethod (addMethod);
4372 public void SetCustomAttribute (CustomAttributeBuilder cb)
4374 MyBuilder.SetCustomAttribute (cb);
4377 public override object [] GetCustomAttributes (bool inherit)
4379 // FIXME : There's nothing which can be seemingly done here because
4380 // we have no way of getting at the custom attribute objects of the
4385 public override object [] GetCustomAttributes (Type t, bool inherit)
4387 // FIXME : Same here !
4391 public override bool IsDefined (Type t, bool b)
4396 public override EventAttributes Attributes {
4402 public override string Name {
4408 public override Type DeclaringType {
4410 return declaring_type;
4414 public override Type ReflectedType {
4416 return reflected_type;
4420 public Type EventType {
4426 public void SetUsed ()
4428 if (my_event != null)
4429 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
4433 public class Event : FieldBase {
4434 const int AllowedModifiers =
4437 Modifiers.PROTECTED |
4438 Modifiers.INTERNAL |
4443 Modifiers.OVERRIDE |
4447 public readonly Accessor Add;
4448 public readonly Accessor Remove;
4449 public MyEventBuilder EventBuilder;
4451 MethodBuilder AddBuilder, RemoveBuilder;
4452 MethodData AddData, RemoveData;
4454 public Event (Expression type, string name, Object init, int mod, Accessor add,
4455 Accessor remove, Attributes attrs, Location loc)
4456 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4462 public override bool Define (TypeContainer container)
4464 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4465 MethodAttributes m_attr = MethodAttributes.HideBySig | MethodAttributes.SpecialName
4467 if (!DoDefine (container))
4470 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
4471 Report.Error (74, Location, "'" + container.Name + "." + Name +
4472 "': abstract event can not have an initializer");
4476 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4477 Report.Error (66, Location, "'" + container.Name + "." + Name +
4478 "' : event must be of a delegate type");
4482 Type [] parameter_types = new Type [1];
4483 parameter_types [0] = MemberType;
4485 Parameter [] parms = new Parameter [1];
4486 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4487 InternalParameters ip = new InternalParameters (
4488 container, new Parameters (parms, null, Location));
4490 if (!CheckBase (container))
4494 // Now define the accessors
4496 AddData = new MethodData (container, this, "add", TypeManager.void_type,
4497 parameter_types, ip, CallingConventions.Standard,
4498 (Add != null) ? Add.OptAttributes : null,
4499 ModFlags, flags | m_attr, false);
4501 if (!AddData.Define (container))
4504 AddBuilder = AddData.MethodBuilder;
4505 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4507 RemoveData = new MethodData (container, this, "remove", TypeManager.void_type,
4508 parameter_types, ip, CallingConventions.Standard,
4509 (Remove != null) ? Remove.OptAttributes : null,
4510 ModFlags, flags | m_attr, false);
4512 if (!RemoveData.Define (container))
4515 RemoveBuilder = RemoveData.MethodBuilder;
4516 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4518 if (!IsExplicitImpl){
4519 EventBuilder = new MyEventBuilder (this,
4520 container.TypeBuilder, Name, e_attr, MemberType);
4522 if (Add == null && Remove == null) {
4523 FieldBuilder = container.TypeBuilder.DefineField (
4525 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4526 TypeManager.RegisterPrivateFieldOfEvent (
4527 (EventInfo) EventBuilder, FieldBuilder);
4528 TypeManager.RegisterFieldBase (FieldBuilder, this);
4531 EventBuilder.SetAddOnMethod (AddBuilder);
4532 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4534 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4535 Report.Error (111, Location,
4536 "Class `" + container.Name +
4537 "' already contains a definition for the event `" +
4546 void EmitDefaultMethod (EmitContext ec, bool is_add)
4548 ILGenerator ig = ec.ig;
4549 MethodInfo method = null;
4552 method = TypeManager.delegate_combine_delegate_delegate;
4554 method = TypeManager.delegate_remove_delegate_delegate;
4556 if ((ModFlags & Modifiers.STATIC) != 0) {
4557 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4558 ig.Emit (OpCodes.Ldarg_0);
4559 ig.Emit (OpCodes.Call, method);
4560 ig.Emit (OpCodes.Castclass, MemberType);
4561 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4563 ig.Emit (OpCodes.Ldarg_0);
4564 ig.Emit (OpCodes.Ldarg_0);
4565 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4566 ig.Emit (OpCodes.Ldarg_1);
4567 ig.Emit (OpCodes.Call, method);
4568 ig.Emit (OpCodes.Castclass, MemberType);
4569 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4571 ig.Emit (OpCodes.Ret);
4574 public void Emit (TypeContainer tc)
4578 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4579 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes);
4582 AddData.Emit (tc, Add.Block, Add);
4585 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4586 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4587 EmitDefaultMethod (ec, true);
4590 if (Remove != null) {
4591 RemoveData.Emit (tc, Remove.Block, Remove);
4592 Remove.Block = null;
4594 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4595 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4596 EmitDefaultMethod (ec, false);
4603 // FIXME: This does not handle:
4605 // int INTERFACENAME [ args ]
4610 // int this [ args ]
4612 public class Indexer : PropertyBase {
4614 const int AllowedModifiers =
4617 Modifiers.PROTECTED |
4618 Modifiers.INTERNAL |
4622 Modifiers.OVERRIDE |
4627 public string IndexerName;
4628 public string InterfaceIndexerName;
4631 // Are we implementing an interface ?
4633 bool IsImplementing = false;
4635 public Indexer (DeclSpace ds, Expression type, string int_type, int flags,
4636 Parameters parameters, Accessor get_block, Accessor set_block,
4637 Attributes attrs, Location loc)
4638 : base (ds, type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4641 ExplicitInterfaceName = int_type;
4644 public override bool Define (TypeContainer container)
4646 PropertyAttributes prop_attr =
4647 PropertyAttributes.RTSpecialName |
4648 PropertyAttributes.SpecialName;
4650 if (!DoDefine (container))
4653 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4654 if (IndexerName == null)
4655 IndexerName = "Item";
4656 else if (IsExplicitImpl)
4657 Report.Error (592, Location,
4658 "Attribute 'IndexerName' is not valid on this declaration " +
4659 "type. It is valid on `property' declarations only.");
4661 ShortName = IndexerName;
4662 if (IsExplicitImpl) {
4663 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4664 Name = InterfaceType.FullName + "." + IndexerName;
4666 InterfaceIndexerName = IndexerName;
4670 if (!CheckBase (container))
4673 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4675 InternalParameters ip = new InternalParameters (container, Parameters);
4677 GetData = new MethodData (container, this, "get", MemberType,
4678 ParameterTypes, ip, CallingConventions.Standard,
4679 Get.OptAttributes, ModFlags, flags, false);
4681 if (!GetData.Define (container))
4684 GetBuilder = GetData.MethodBuilder;
4688 int top = ParameterTypes.Length;
4689 Type [] set_pars = new Type [top + 1];
4690 ParameterTypes.CopyTo (set_pars, 0);
4691 set_pars [top] = MemberType;
4693 Parameter [] fixed_parms = Parameters.FixedParameters;
4695 if (fixed_parms == null){
4696 throw new Exception ("We currently do not support only array arguments in an indexer at: " + Location);
4697 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4698 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4700 // Here is the problem: the `value' parameter has
4701 // to come *after* the array parameter in the declaration
4703 // X (object [] x, Type value)
4706 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4707 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4711 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4714 fixed_parms.CopyTo (tmp, 0);
4715 tmp [fixed_parms.Length] = new Parameter (
4716 Type, "value", Parameter.Modifier.NONE, null);
4718 Parameters set_formal_params = new Parameters (tmp, null, Location);
4720 InternalParameters ip = new InternalParameters (container, set_formal_params);
4722 SetData = new MethodData (container, this, "set", TypeManager.void_type,
4723 set_pars, ip, CallingConventions.Standard,
4724 Set.OptAttributes, ModFlags, flags, false);
4726 if (!SetData.Define (container))
4729 SetBuilder = SetData.MethodBuilder;
4733 // Now name the parameters
4735 Parameter [] p = Parameters.FixedParameters;
4739 for (i = 0; i < p.Length; ++i) {
4741 GetBuilder.DefineParameter (
4742 i + 1, p [i].Attributes, p [i].Name);
4745 SetBuilder.DefineParameter (
4746 i + 1, p [i].Attributes, p [i].Name);
4750 SetBuilder.DefineParameter (
4751 i + 1, ParameterAttributes.None, "value");
4753 if (i != ParameterTypes.Length) {
4754 Parameter array_param = Parameters.ArrayParameter;
4756 SetBuilder.DefineParameter (
4757 i + 1, array_param.Attributes, array_param.Name);
4761 if (GetData != null)
4762 IsImplementing = GetData.IsImplementing;
4763 else if (SetData != null)
4764 IsImplementing = SetData.IsImplementing;
4767 // Define the PropertyBuilder if one of the following conditions are met:
4768 // a) we're not implementing an interface indexer.
4769 // b) the indexer has a different IndexerName and this is no
4770 // explicit interface implementation.
4772 if (!IsExplicitImpl) {
4773 PropertyBuilder = container.TypeBuilder.DefineProperty (
4774 IndexerName, prop_attr, MemberType, ParameterTypes);
4776 if (GetData != null)
4777 PropertyBuilder.SetGetMethod (GetBuilder);
4779 if (SetData != null)
4780 PropertyBuilder.SetSetMethod (SetBuilder);
4782 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4790 public class Operator : MemberBase {
4792 const int AllowedModifiers =
4798 const int RequiredModifiers =
4802 public enum OpType : byte {
4812 // Unary and Binary operators
4835 // Implicit and Explicit
4840 public readonly OpType OperatorType;
4841 public readonly Expression ReturnType;
4842 public readonly Expression FirstArgType, SecondArgType;
4843 public readonly string FirstArgName, SecondArgName;
4845 public MethodBuilder OperatorMethodBuilder;
4847 public string MethodName;
4848 public Method OperatorMethod;
4850 public Operator (OpType type, Expression ret_type, int mod_flags,
4851 Expression arg1type, string arg1name,
4852 Expression arg2type, string arg2name,
4853 Block block, Attributes attrs, Location loc)
4854 : base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC, "", attrs, loc)
4856 OperatorType = type;
4857 ReturnType = ret_type;
4858 FirstArgType = arg1type;
4859 FirstArgName = arg1name;
4860 SecondArgType = arg2type;
4861 SecondArgName = arg2name;
4865 string Prototype (TypeContainer container)
4867 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4868 SecondArgType + ")";
4871 public override bool Define (TypeContainer container)
4874 MethodName = "op_" + OperatorType;
4876 if (SecondArgType != null)
4879 Parameter [] param_list = new Parameter [length];
4881 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4884 "User defined operators `" +
4885 Prototype (container) +
4886 "' must be declared static and public");
4890 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4891 Parameter.Modifier.NONE, null);
4892 if (SecondArgType != null)
4893 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4894 Parameter.Modifier.NONE, null);
4896 OperatorMethod = new Method (container, ReturnType, ModFlags, MethodName,
4897 new Parameters (param_list, null, Location),
4898 OptAttributes, Location);
4900 OperatorMethod.IsOperator = true;
4901 OperatorMethod.Define (container);
4903 if (OperatorMethod.MethodBuilder == null)
4906 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4908 Type [] param_types = OperatorMethod.ParameterTypes;
4909 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4910 Type return_type = OperatorMethod.GetReturnType ();
4911 Type first_arg_type = param_types [0];
4913 // Rules for conversion operators
4915 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4916 if (first_arg_type == return_type && first_arg_type == declaring_type){
4919 "User-defined conversion cannot take an object of the " +
4920 "enclosing type and convert to an object of the enclosing" +
4925 if (first_arg_type != declaring_type && return_type != declaring_type){
4928 "User-defined conversion must convert to or from the " +
4933 if (first_arg_type == TypeManager.object_type ||
4934 return_type == TypeManager.object_type){
4937 "User-defined conversion cannot convert to or from " +
4942 if (first_arg_type.IsInterface || return_type.IsInterface){
4945 "User-defined conversion cannot convert to or from an " +
4950 if (first_arg_type.IsSubclassOf (return_type) ||
4951 return_type.IsSubclassOf (first_arg_type)){
4954 "User-defined conversion cannot convert between types " +
4955 "that derive from each other");
4958 } else if (SecondArgType == null) {
4959 // Checks for Unary operators
4961 if (first_arg_type != declaring_type){
4964 "The parameter of a unary operator must be the " +
4969 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4970 if (return_type != declaring_type){
4973 "The parameter and return type for ++ and -- " +
4974 "must be the containing type");
4980 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4981 if (return_type != TypeManager.bool_type){
4984 "The return type of operator True or False " +
4991 // Checks for Binary operators
4993 if (first_arg_type != declaring_type &&
4994 param_types [1] != declaring_type){
4997 "One of the parameters of a binary operator must " +
4998 "be the containing type");
5006 public void Emit (TypeContainer container)
5009 // abstract or extern methods have no bodies
5011 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
5014 OperatorMethod.Block = Block;
5015 OperatorMethod.Emit (container);
5019 public static string GetName (OpType ot)
5022 case OpType.LogicalNot:
5024 case OpType.OnesComplement:
5026 case OpType.Increment:
5028 case OpType.Decrement:
5034 case OpType.Addition:
5036 case OpType.Subtraction:
5038 case OpType.UnaryPlus:
5040 case OpType.UnaryNegation:
5042 case OpType.Multiply:
5044 case OpType.Division:
5046 case OpType.Modulus:
5048 case OpType.BitwiseAnd:
5050 case OpType.BitwiseOr:
5052 case OpType.ExclusiveOr:
5054 case OpType.LeftShift:
5056 case OpType.RightShift:
5058 case OpType.Equality:
5060 case OpType.Inequality:
5062 case OpType.GreaterThan:
5064 case OpType.LessThan:
5066 case OpType.GreaterThanOrEqual:
5068 case OpType.LessThanOrEqual:
5070 case OpType.Implicit:
5072 case OpType.Explicit:
5078 public override string ToString ()
5080 Type return_type = OperatorMethod.GetReturnType();
5081 Type [] param_types = OperatorMethod.ParameterTypes;
5083 if (SecondArgType == null)
5084 return String.Format (
5085 "{0} operator {1}({2})",
5086 TypeManager.CSharpName (return_type),
5087 GetName (OperatorType),
5090 return String.Format (
5091 "{0} operator {1}({2}, {3})",
5092 TypeManager.CSharpName (return_type),
5093 GetName (OperatorType),
5094 param_types [0], param_types [1]);
5099 // This is used to compare method signatures
5101 struct MethodSignature {
5103 public Type RetType;
5104 public Type [] Parameters;
5107 /// This delegate is used to extract methods which have the
5108 /// same signature as the argument
5110 public static MemberFilter method_signature_filter;
5113 /// This delegate is used to extract inheritable methods which
5114 /// have the same signature as the argument. By inheritable,
5115 /// this means that we have permissions to override the method
5116 /// from the current assembly and class
5118 public static MemberFilter inheritable_method_signature_filter;
5120 static MethodSignature ()
5122 method_signature_filter = new MemberFilter (MemberSignatureCompare);
5123 inheritable_method_signature_filter = new MemberFilter (
5124 InheritableMemberSignatureCompare);
5127 public MethodSignature (string name, Type ret_type, Type [] parameters)
5132 if (parameters == null)
5133 Parameters = TypeManager.NoTypes;
5135 Parameters = parameters;
5138 public override string ToString ()
5141 if (Parameters.Length != 0){
5142 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
5143 for (int i = 0; i < Parameters.Length; i++){
5144 sb.Append (Parameters [i]);
5145 if (i+1 < Parameters.Length)
5148 pars = sb.ToString ();
5151 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
5154 public override int GetHashCode ()
5156 return Name.GetHashCode ();
5159 public override bool Equals (Object o)
5161 MethodSignature other = (MethodSignature) o;
5163 if (other.Name != Name)
5166 if (other.RetType != RetType)
5169 if (Parameters == null){
5170 if (other.Parameters == null)
5175 if (other.Parameters == null)
5178 int c = Parameters.Length;
5179 if (other.Parameters.Length != c)
5182 for (int i = 0; i < c; i++)
5183 if (other.Parameters [i] != Parameters [i])
5189 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
5191 MethodSignature sig = (MethodSignature) filter_criteria;
5193 if (m.Name != sig.Name)
5197 MethodInfo mi = m as MethodInfo;
5198 PropertyInfo pi = m as PropertyInfo;
5201 ReturnType = mi.ReturnType;
5202 else if (pi != null)
5203 ReturnType = pi.PropertyType;
5208 // we use sig.RetType == null to mean `do not check the
5209 // method return value.
5211 if (sig.RetType != null)
5212 if (ReturnType != sig.RetType)
5217 args = TypeManager.GetArgumentTypes (mi);
5219 args = TypeManager.GetArgumentTypes (pi);
5220 Type [] sigp = sig.Parameters;
5222 if (args.Length != sigp.Length)
5225 for (int i = args.Length; i > 0; ){
5227 if (args [i] != sigp [i])
5234 // This filter should be used when we are requesting methods that
5235 // we want to override.
5237 // This makes a number of assumptions, for example
5238 // that the methods being extracted are of a parent
5239 // class (this means we know implicitly that we are
5240 // being called to find out about members by a derived
5243 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
5246 PropertyInfo pi = m as PropertyInfo;
5249 mi = pi.GetGetMethod (true);
5251 mi = pi.GetSetMethod (true);
5253 mi = m as MethodInfo;
5256 Console.WriteLine ("Nothing found");
5259 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
5261 // If only accessible to the current class.
5262 if (prot == MethodAttributes.Private)
5265 if (!MemberSignatureCompare (m, filter_criteria))
5268 // If only accessible to the defining assembly or
5269 if (prot == MethodAttributes.FamANDAssem ||
5270 prot == MethodAttributes.Assembly){
5271 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
5277 // Anything else (FamOrAssembly and Public) is fine