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 (TypeContainer parent, string name, Location l)
138 : base (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 (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 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
622 ArrayList bases = Bases;
631 parent = TypeManager.value_type;
635 if (RootContext.StdLib)
636 parent = TypeManager.object_type;
637 else if (Name != "System.Object")
638 parent = TypeManager.object_type;
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.object_type;
653 // Bases should be null if there are no bases at all
658 Expression name = (Expression) bases [0];
659 name = ResolveTypeExpr (name, false, Location);
666 Type first = name.Type;
672 parent = TypeManager.object_type;
678 if (first.IsValueType)
679 detail = " (a class can not inherit from a struct/enum)";
681 Report.Error (509, "class `"+ Name +
682 "': Cannot inherit from sealed class `"+
683 first + "'" + detail);
688 if (!AsAccessible (parent, ModFlags))
689 Report.Error (60, Location,
690 "Inconsistent accessibility: base class `" +
691 TypeManager.CSharpName (parent) + "' is less " +
692 "accessible than class `" +
700 base_class_name = parent.Name;
702 Type [] ifaces = new Type [count-start];
704 for (i = start, j = 0; i < count; i++, j++){
705 Expression name = (Expression) bases [i];
706 Expression resolved = ResolveTypeExpr (name, false, Location);
707 if (resolved == null)
710 bases [i] = resolved;
711 Type t = resolved.Type;
718 if (is_class == false && !t.IsInterface){
719 Report.Error (527, "In Struct `" + Name + "', type `"+
720 name +"' is not an interface");
727 Report.Error (527, "In Class `" + Name + "', type `"+
728 name+"' is not an interface");
734 for (int x = 0; x < j; x++) {
735 if (t == ifaces [x]) {
736 Report.Error (528, "`" + name + "' is already listed in interface list");
745 return TypeManager.ExpandInterfaces (ifaces);
749 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
751 public override TypeBuilder DefineType ()
757 if (TypeBuilder != null)
770 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
772 ifaces = GetClassBases (is_class, out parent, out error);
777 if (is_class && parent != null){
778 if (parent == TypeManager.enum_type ||
779 (parent == TypeManager.value_type && RootContext.StdLib) ||
780 parent == TypeManager.delegate_type ||
781 parent == TypeManager.array_type){
783 644, Location, "`" + Name + "' cannot inherit from " +
784 "special class `" + TypeManager.CSharpName (parent) + "'");
789 if (!is_class && TypeManager.value_type == null)
790 throw new Exception ();
792 TypeAttributes type_attributes = TypeAttr;
794 // if (parent_builder is ModuleBuilder) {
796 if (TypeManager.NamespaceClash (Name, Location))
799 ModuleBuilder builder = CodeGen.ModuleBuilder;
800 TypeBuilder = builder.DefineType (
801 Name, type_attributes, parent, ifaces);
804 TypeBuilder builder = Parent.TypeBuilder;
805 TypeBuilder = builder.DefineNestedType (
806 Basename, type_attributes, parent, ifaces);
810 // Structs with no fields need to have at least one byte.
811 // The right thing would be to set the PackingSize in a DefineType
812 // but there are no functions that allow interfaces *and* the size to
816 if (!is_class && !have_nonstatic_fields){
817 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
818 FieldAttributes.Private);
819 // add interfaces that were not added at type creation
820 if (ifaces != null) {
821 foreach (Type i in ifaces)
822 TypeBuilder.AddInterfaceImplementation (i);
827 // Finish the setup for the EmitContext
829 ec.ContainerType = TypeBuilder;
831 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
833 if ((parent != null) &&
834 (parent == TypeManager.attribute_type ||
835 parent.IsSubclassOf (TypeManager.attribute_type))) {
836 RootContext.RegisterAttribute (this);
837 TypeManager.RegisterAttrType (TypeBuilder, this);
839 RootContext.RegisterOrder (this);
841 if (Interfaces != null) {
842 foreach (Interface iface in Interfaces)
847 foreach (TypeContainer tc in Types)
851 if (Delegates != null) {
852 foreach (Delegate d in Delegates)
857 foreach (Enum en in Enums)
867 /// Defines the MemberCore objects that are in the `list' Arraylist
869 /// The `defined_names' array contains a list of members defined in
872 static ArrayList remove_list = new ArrayList ();
873 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
877 remove_list.Clear ();
879 foreach (MemberCore mc in list){
881 if (defined_names != null)
882 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
887 if (RootContext.WarningLevel >= 4){
888 if ((mc.ModFlags & Modifiers.NEW) != 0)
889 Warning_KewywordNewNotRequired (mc.Location, mc);
891 } else if (mc is MethodCore)
892 ((MethodCore) mc).OverridesSomething = true;
894 if (!mc.Define (this)){
895 remove_list.Add (mc);
902 MemberInfo match = defined_names [idx];
904 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
908 // If we are both methods, let the method resolution emit warnings
910 if (match is MethodBase && mc is MethodCore)
913 if ((mc.ModFlags & Modifiers.NEW) == 0) {
915 if (!(match is EventInfo)) {
916 Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
920 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
924 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
928 foreach (object o in remove_list)
931 remove_list.Clear ();
935 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
936 // class is consisten. Either it is `Item' or it is the name defined by all the
937 // indexers with the `IndexerName' attribute.
939 // Turns out that the IndexerNameAttribute is applied to each indexer,
940 // but it is never emitted, instead a DefaultName attribute is attached
943 void DefineIndexers ()
945 string class_indexer_name = null;
948 // If there's both an explicit and an implicit interface implementation, the
949 // explicit one actually implements the interface while the other one is just
950 // a normal indexer. See bug #37714.
952 ArrayList list = new ArrayList ();
953 foreach (Indexer i in Indexers){
954 if (i.ExplicitInterfaceName != null)
957 foreach (Indexer i in Indexers){
958 if (i.ExplicitInterfaceName == null)
962 foreach (Indexer i in list){
967 name = i.IndexerName;
969 if (i.InterfaceType != null)
972 if (class_indexer_name == null){
973 class_indexer_name = name;
977 if (name == class_indexer_name)
981 668, "Two indexers have different names, " +
982 " you should use the same name for all your indexers");
984 if (class_indexer_name == null)
985 class_indexer_name = "Item";
986 IndexerName = class_indexer_name;
989 static void Error_KeywordNotAllowed (Location loc)
991 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
995 /// Populates our TypeBuilder with fields and methods
997 public override bool DefineMembers (TypeContainer container)
999 MemberInfo [] defined_names = null;
1001 if (interface_order != null){
1002 foreach (Interface iface in interface_order)
1003 if ((iface.ModFlags & Modifiers.NEW) == 0)
1004 iface.DefineMembers (this);
1006 Error_KeywordNotAllowed (iface.Location);
1009 if (RootContext.WarningLevel > 1){
1013 // This code throws an exception in the comparer
1014 // I guess the string is not an object?
1016 ptype = TypeBuilder.BaseType;
1018 defined_names = (MemberInfo []) FindMembers (
1019 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1020 BindingFlags.Public | BindingFlags.Instance |
1021 BindingFlags.Static, null, null);
1023 Array.Sort (defined_names, mif_compare);
1027 Class pclass = Parent as Class;
1028 if (pclass != null) {
1029 string pname = null;
1031 Type t = pclass.TypeBuilder.BaseType;
1032 while ((t != null) && (ptype == null)) {
1033 pname = t.FullName + "." + Basename;
1034 ptype = RootContext.LookupType (this, pname, true, Location.Null);
1038 if ((ModFlags & Modifiers.NEW) != 0) {
1040 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1041 "inherited member. The keyword new is not required.");
1042 } else if (ptype != null) {
1043 Report.Warning (108, Location, "The keyword new is required on `" +
1044 Name + "' because it hides inherited member '" +
1047 } else if ((ModFlags & Modifiers.NEW) != 0)
1048 Error_KeywordNotAllowed (Location);
1050 if (constants != null)
1051 DefineMembers (constants, defined_names);
1054 DefineMembers (fields, defined_names);
1056 if ((RootContext.WarningLevel >= 4) && (fields != null)) {
1057 foreach (Field f in fields) {
1058 if (((f.ModFlags & Modifiers.READONLY) != 0) && !f.IsAssigned)
1059 Report.Warning (649, "Field `" + MakeFQN (Name, f.Name) + "; is never " +
1060 "assigned and will ever have its default value");
1065 if (instance_constructors == null){
1066 if (default_constructor == null)
1067 DefineDefaultConstructor (false);
1070 if (initialized_static_fields != null &&
1071 default_static_constructor == null)
1072 DefineDefaultConstructor (true);
1075 if (this is Struct){
1077 // Structs can not have initialized instance
1080 if (initialized_static_fields != null &&
1081 default_static_constructor == null)
1082 DefineDefaultConstructor (true);
1084 if (initialized_fields != null)
1085 ReportStructInitializedInstanceError ();
1088 Pending = PendingImplementation.GetPendingImplementations (this);
1091 // Constructors are not in the defined_names array
1093 if (instance_constructors != null)
1094 DefineMembers (instance_constructors, null);
1096 if (default_static_constructor != null)
1097 default_static_constructor.Define (this);
1099 if (methods != null)
1100 DefineMembers (methods, defined_names);
1102 if (properties != null)
1103 DefineMembers (properties, defined_names);
1106 DefineMembers (events, defined_names);
1108 if (indexers != null) {
1111 IndexerName = "Item";
1113 if (operators != null){
1114 DefineMembers (operators, null);
1116 CheckPairedOperators ();
1120 DefineMembers (enums, defined_names);
1122 if (delegates != null)
1123 DefineMembers (delegates, defined_names);
1126 if (TypeBuilder.BaseType != null)
1127 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1129 member_cache = new MemberCache (this);
1136 public override bool Define (TypeContainer container)
1138 if (interface_order != null){
1139 foreach (Interface iface in interface_order)
1140 if ((iface.ModFlags & Modifiers.NEW) == 0)
1141 iface.Define (this);
1148 /// This function is based by a delegate to the FindMembers routine
1150 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1156 /// This filter is used by FindMembers, and we just keep
1157 /// a global for the filter to `AlwaysAccept'
1159 static MemberFilter accepting_filter;
1163 /// A member comparission method based on name only
1165 static IComparer mif_compare;
1167 static TypeContainer ()
1169 accepting_filter = new MemberFilter (AlwaysAccept);
1170 mif_compare = new MemberInfoCompare ();
1174 /// This method returns the members of this type just like Type.FindMembers would
1175 /// Only, we need to use this for types which are _being_ defined because MS'
1176 /// implementation can't take care of that.
1179 // FIXME: return an empty static array instead of null, that cleans up
1180 // some code and is consistent with some coding conventions I just found
1184 // Notice that in various cases we check if our field is non-null,
1185 // something that would normally mean that there was a bug elsewhere.
1187 // The problem happens while we are defining p-invoke methods, as those
1188 // will trigger a FindMembers, but this happens before things are defined
1190 // Since the whole process is a no-op, it is fine to check for null here.
1192 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1193 MemberFilter filter, object criteria)
1195 ArrayList members = new ArrayList ();
1198 if ((bf & BindingFlags.Public) != 0)
1199 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1201 if ((bf & BindingFlags.NonPublic) != 0)
1202 modflags |= Modifiers.PRIVATE;
1204 int static_mask = 0, static_flags = 0;
1205 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1206 case BindingFlags.Static:
1207 static_mask = static_flags = Modifiers.STATIC;
1210 case BindingFlags.Instance:
1211 static_mask = Modifiers.STATIC;
1216 static_mask = static_flags = 0;
1220 Timer.StartTimer (TimerType.TcFindMembers);
1223 filter = accepting_filter;
1225 if ((mt & MemberTypes.Field) != 0) {
1226 if (fields != null) {
1227 foreach (Field f in fields) {
1228 if ((f.ModFlags & modflags) == 0)
1230 if ((f.ModFlags & static_mask) != static_flags)
1233 FieldBuilder fb = f.FieldBuilder;
1234 if (fb != null && filter (fb, criteria) == true)
1239 if (constants != null) {
1240 foreach (Const con in constants) {
1241 if ((con.ModFlags & modflags) == 0)
1243 if ((con.ModFlags & static_mask) != static_flags)
1246 FieldBuilder fb = con.FieldBuilder;
1247 if (fb != null && filter (fb, criteria) == true)
1253 if ((mt & MemberTypes.Method) != 0) {
1254 if (methods != null) {
1255 foreach (Method m in methods) {
1256 if ((m.ModFlags & modflags) == 0)
1258 if ((m.ModFlags & static_mask) != static_flags)
1261 MethodBuilder mb = m.MethodBuilder;
1263 if (mb != null && filter (mb, criteria) == true)
1268 if (operators != null){
1269 foreach (Operator o in operators) {
1270 if ((o.ModFlags & modflags) == 0)
1272 if ((o.ModFlags & static_mask) != static_flags)
1275 MethodBuilder ob = o.OperatorMethodBuilder;
1276 if (ob != null && filter (ob, criteria) == true)
1281 if (properties != null){
1282 foreach (Property p in properties){
1283 if ((p.ModFlags & modflags) == 0)
1285 if ((p.ModFlags & static_mask) != static_flags)
1291 if (b != null && filter (b, criteria) == true)
1295 if (b != null && filter (b, criteria) == true)
1300 if (indexers != null){
1301 foreach (Indexer ix in indexers){
1302 if ((ix.ModFlags & modflags) == 0)
1304 if ((ix.ModFlags & static_mask) != static_flags)
1310 if (b != null && filter (b, criteria) == true)
1314 if (b != null && filter (b, criteria) == true)
1320 if ((mt & MemberTypes.Event) != 0) {
1322 foreach (Event e in events) {
1323 if ((e.ModFlags & modflags) == 0)
1325 if ((e.ModFlags & static_mask) != static_flags)
1328 MemberInfo eb = e.EventBuilder;
1329 if (eb != null && filter (eb, criteria) == true)
1330 members.Add (e.EventBuilder);
1334 if ((mt & MemberTypes.Property) != 0){
1335 if (properties != null)
1336 foreach (Property p in properties) {
1337 if ((p.ModFlags & modflags) == 0)
1339 if ((p.ModFlags & static_mask) != static_flags)
1342 MemberInfo pb = p.PropertyBuilder;
1343 if (pb != null && filter (pb, criteria) == true) {
1344 members.Add (p.PropertyBuilder);
1348 if (indexers != null)
1349 foreach (Indexer ix in indexers) {
1350 if ((ix.ModFlags & modflags) == 0)
1352 if ((ix.ModFlags & static_mask) != static_flags)
1355 MemberInfo ib = ix.PropertyBuilder;
1356 if (ib != null && filter (ib, criteria) == true) {
1357 members.Add (ix.PropertyBuilder);
1362 if ((mt & MemberTypes.NestedType) != 0) {
1364 foreach (TypeContainer t in types) {
1365 if ((t.ModFlags & modflags) == 0)
1368 TypeBuilder tb = t.TypeBuilder;
1369 if (tb != null && (filter (tb, criteria) == true))
1375 foreach (Enum en in enums){
1376 if ((en.ModFlags & modflags) == 0)
1379 TypeBuilder tb = en.TypeBuilder;
1380 if (tb != null && (filter (tb, criteria) == true))
1385 if (delegates != null){
1386 foreach (Delegate d in delegates){
1387 if ((d.ModFlags & modflags) == 0)
1390 TypeBuilder tb = d.TypeBuilder;
1391 if (tb != null && (filter (tb, criteria) == true))
1396 if (interfaces != null){
1397 foreach (Interface iface in interfaces){
1398 if ((iface.ModFlags & modflags) == 0)
1401 TypeBuilder tb = iface.TypeBuilder;
1402 if (tb != null && (filter (tb, criteria) == true))
1408 if ((mt & MemberTypes.Constructor) != 0){
1409 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1410 foreach (Constructor c in instance_constructors){
1411 ConstructorBuilder cb = c.ConstructorBuilder;
1413 if (filter (cb, criteria) == true)
1418 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1419 ConstructorBuilder cb =
1420 default_static_constructor.ConstructorBuilder;
1423 if (filter (cb, criteria) == true)
1429 // Lookup members in parent if requested.
1431 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1432 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1433 members.AddRange (list);
1436 Timer.StopTimer (TimerType.TcFindMembers);
1438 return new MemberList (members);
1441 public override MemberCache MemberCache {
1443 return member_cache;
1447 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1448 MemberFilter filter, object criteria)
1450 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1453 return ds.FindMembers (mt, bf, filter, criteria);
1455 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1460 // FindMethods will look for methods not only in the type `t', but in
1461 // any interfaces implemented by the type.
1463 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1464 MemberFilter filter, object criteria)
1470 /// Emits the values for the constants
1472 public void EmitConstants ()
1474 if (constants != null)
1475 foreach (Const con in constants)
1476 con.EmitConstant (this);
1481 /// Emits the code, this step is performed after all
1482 /// the types, enumerations, constructors
1486 if (instance_constructors != null)
1487 foreach (Constructor c in instance_constructors)
1490 if (default_static_constructor != null)
1491 default_static_constructor.Emit (this);
1493 if (methods != null)
1494 foreach (Method m in methods)
1497 if (operators != null)
1498 foreach (Operator o in operators)
1501 if (properties != null)
1502 foreach (Property p in properties)
1505 if (indexers != null){
1506 foreach (Indexer ix in indexers)
1509 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1510 this, IndexerName, ModFlags, Location);
1511 TypeBuilder.SetCustomAttribute (cb);
1515 foreach (Field f in fields)
1518 if (events != null){
1519 foreach (Event e in Events)
1523 if (Pending != null)
1524 if (Pending.VerifyPendingMethods ())
1527 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
1530 // Check for internal or private fields that were never assigned
1532 if (RootContext.WarningLevel >= 3) {
1533 if (fields != null){
1534 foreach (Field f in fields) {
1535 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1540 169, f.Location, "Private field " +
1541 MakeName (f.Name) + " is never used");
1546 // Only report 649 on level 4
1548 if (RootContext.WarningLevel < 4)
1551 if ((f.status & Field.Status.ASSIGNED) != 0)
1556 "Field " + MakeName (f.Name) + " is never assigned " +
1557 " to and will always have its default value");
1561 if (events != null){
1562 foreach (Event e in events){
1564 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1569 // if (types != null)
1570 // foreach (TypeContainer tc in types)
1574 public override void CloseType ()
1579 TypeBuilder.CreateType ();
1581 } catch (TypeLoadException){
1583 // This is fine, the code still created the type
1585 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1586 // Console.WriteLine (e.Message);
1588 Console.WriteLine ("In type: " + Name);
1593 foreach (Enum en in Enums)
1596 if (interface_order != null){
1597 foreach (Interface iface in interface_order)
1602 foreach (TypeContainer tc in Types)
1606 foreach (TypeContainer tc in Types)
1607 if (!(tc is Struct))
1611 if (Delegates != null)
1612 foreach (Delegate d in Delegates)
1616 public string MakeName (string n)
1618 return "`" + Name + "." + n + "'";
1621 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1624 108, l, "The keyword new is required on " +
1625 MakeName (mi.Name) + " because it hides `" +
1626 mi.ReflectedType.Name + "." + mi.Name + "'");
1629 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1632 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1633 "inherited member, the keyword new is not required");
1636 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
1639 72, l, MakeName (mi.Name) + " : cannot override; `" +
1640 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
1643 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1649 // Performs the validation on a Method's modifiers (properties have
1650 // the same properties).
1652 public bool MethodModifiersValid (int flags, string n, Location loc)
1654 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1655 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1656 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1660 // At most one of static, virtual or override
1662 if ((flags & Modifiers.STATIC) != 0){
1663 if ((flags & vao) != 0){
1665 112, loc, "static method " + MakeName (n) + "can not be marked " +
1666 "as virtual, abstract or override");
1671 if (this is Struct){
1672 if ((flags & va) != 0){
1673 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1678 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1680 113, loc, MakeName (n) +
1681 " marked as override cannot be marked as new or virtual");
1686 // If the declaration includes the abstract modifier, then the
1687 // declaration does not include static, virtual or extern
1689 if ((flags & Modifiers.ABSTRACT) != 0){
1690 if ((flags & Modifiers.EXTERN) != 0){
1692 180, loc, MakeName (n) + " can not be both abstract and extern");
1696 if ((flags & Modifiers.VIRTUAL) != 0){
1698 503, loc, MakeName (n) + " can not be both abstract and virtual");
1702 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1704 513, loc, MakeName (n) +
1705 " is abstract but its container class is not");
1711 if ((flags & Modifiers.PRIVATE) != 0){
1712 if ((flags & vao) != 0){
1714 621, loc, MakeName (n) +
1715 " virtual or abstract members can not be private");
1720 if ((flags & Modifiers.SEALED) != 0){
1721 if ((flags & Modifiers.OVERRIDE) == 0){
1723 238, loc, MakeName (n) +
1724 " cannot be sealed because it is not an override");
1732 // Access level of a type.
1735 ProtectedInternal = 1,
1741 // Check whether `flags' denotes a more restricted access than `level'
1742 // and return the new level.
1743 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1745 AccessLevel old_level = level;
1747 if ((flags & Modifiers.INTERNAL) != 0) {
1748 if ((flags & Modifiers.PROTECTED) != 0) {
1749 if ((int) level < (int) AccessLevel.ProtectedInternal)
1750 level = AccessLevel.ProtectedInternal;
1752 if ((int) level < (int) AccessLevel.Internal)
1753 level = AccessLevel.Internal;
1755 } else if ((flags & Modifiers.PROTECTED) != 0) {
1756 if ((int) level < (int) AccessLevel.Protected)
1757 level = AccessLevel.Protected;
1758 } else if ((flags & Modifiers.PRIVATE) != 0)
1759 level = AccessLevel.Private;
1764 // Return the access level for a new member which is defined in the current
1765 // TypeContainer with access modifiers `flags'.
1766 AccessLevel GetAccessLevel (int flags)
1768 if ((flags & Modifiers.PRIVATE) != 0)
1769 return AccessLevel.Private;
1772 if (!IsTopLevel && (Parent != null))
1773 level = Parent.GetAccessLevel (flags);
1775 level = AccessLevel.Public;
1777 return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1780 // Return the access level for type `t', but don't give more access than `flags'.
1781 static AccessLevel GetAccessLevel (Type t, int flags)
1783 if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1784 return AccessLevel.Private;
1787 if (TypeManager.IsBuiltinType (t))
1788 return AccessLevel.Public;
1789 else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1790 level = GetAccessLevel (t.DeclaringType, flags);
1792 level = CheckAccessLevel (AccessLevel.Public, flags);
1795 if (t.IsNestedPublic)
1798 if (t.IsNestedAssembly || t.IsNotPublic) {
1799 if ((int) level < (int) AccessLevel.Internal)
1800 level = AccessLevel.Internal;
1803 if (t.IsNestedFamily) {
1804 if ((int) level < (int) AccessLevel.Protected)
1805 level = AccessLevel.Protected;
1808 if (t.IsNestedFamORAssem) {
1809 if ((int) level < (int) AccessLevel.ProtectedInternal)
1810 level = AccessLevel.ProtectedInternal;
1817 // Returns true if `parent' is as accessible as the flags `flags'
1818 // given for this member.
1820 public bool AsAccessible (Type parent, int flags)
1822 while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1823 parent = TypeManager.GetElementType (parent);
1825 AccessLevel level = GetAccessLevel (flags);
1826 AccessLevel level2 = GetAccessLevel (parent, flags);
1828 return (int) level >= (int) level2;
1831 Hashtable builder_and_args;
1833 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1835 if (builder_and_args == null)
1836 builder_and_args = new Hashtable ();
1841 /// Performs checks for an explicit interface implementation. First it
1842 /// checks whether the `interface_type' is a base inteface implementation.
1843 /// Then it checks whether `name' exists in the interface type.
1845 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1849 if (ifaces != null){
1850 foreach (Type t in ifaces){
1851 if (t == interface_type){
1859 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1866 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1868 Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1875 string IMemberContainer.Name {
1881 Type IMemberContainer.Type {
1887 IMemberContainer IMemberContainer.Parent {
1889 return parent_container;
1893 MemberCache IMemberContainer.MemberCache {
1895 return member_cache;
1899 bool IMemberContainer.IsInterface {
1905 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1907 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1911 // Operator pair checking
1914 class OperatorEntry {
1916 public Type ret_type;
1917 public Type type1, type2;
1919 public Operator.OpType ot;
1921 public OperatorEntry (int f, Operator o)
1925 ret_type = o.OperatorMethod.GetReturnType ();
1926 Type [] pt = o.OperatorMethod.ParameterTypes;
1930 ot = o.OperatorType;
1933 public override int GetHashCode ()
1935 return ret_type.GetHashCode ();
1938 public override bool Equals (object o)
1940 OperatorEntry other = (OperatorEntry) o;
1942 if (other.ret_type != ret_type)
1944 if (other.type1 != type1)
1946 if (other.type2 != type2)
1953 // Checks that some operators come in pairs:
1959 // They are matched based on the return type and the argument types
1961 void CheckPairedOperators ()
1963 Hashtable pairs = new Hashtable (null, null);
1964 Operator true_op = null;
1965 Operator false_op = null;
1966 bool has_equality_or_inequality = false;
1968 // Register all the operators we care about.
1969 foreach (Operator op in operators){
1972 switch (op.OperatorType){
1973 case Operator.OpType.Equality:
1975 has_equality_or_inequality = true;
1977 case Operator.OpType.Inequality:
1979 has_equality_or_inequality = true;
1982 case Operator.OpType.True:
1985 case Operator.OpType.False:
1989 case Operator.OpType.GreaterThan:
1991 case Operator.OpType.LessThan:
1994 case Operator.OpType.GreaterThanOrEqual:
1996 case Operator.OpType.LessThanOrEqual:
2002 OperatorEntry oe = new OperatorEntry (reg, op);
2004 object o = pairs [oe];
2008 oe = (OperatorEntry) o;
2013 if (true_op != null){
2014 if (false_op == null)
2015 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2016 } else if (false_op != null)
2017 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2020 // Look for the mistakes.
2022 foreach (DictionaryEntry de in pairs){
2023 OperatorEntry oe = (OperatorEntry) de.Key;
2030 case Operator.OpType.Equality:
2033 case Operator.OpType.Inequality:
2036 case Operator.OpType.GreaterThan:
2039 case Operator.OpType.LessThan:
2042 case Operator.OpType.GreaterThanOrEqual:
2045 case Operator.OpType.LessThanOrEqual:
2049 Report.Error (216, oe.op.Location,
2050 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2053 if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2054 MethodSignature equals_ms = new MethodSignature (
2055 "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2056 MethodSignature hash_ms = new MethodSignature (
2057 "GetHashCode", TypeManager.int32_type, new Type [0]);
2059 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2060 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2062 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2063 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2066 bool equals_ok = false;
2067 if ((equals_ml != null) && (equals_ml.Count == 1))
2068 equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2069 bool hash_ok = false;
2070 if ((hash_ml != null) && (hash_ml.Count == 1))
2071 hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2074 Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2075 "not override Object.Equals (object o)");
2077 Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2078 "not override Object.GetHashCode ()");
2085 public class Class : TypeContainer {
2087 // Modifiers allowed in a class declaration
2089 public const int AllowedModifiers =
2092 Modifiers.PROTECTED |
2093 Modifiers.INTERNAL |
2095 Modifiers.ABSTRACT |
2099 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2100 : base (parent, name, l)
2104 if (parent.Parent == null)
2105 accmods = Modifiers.INTERNAL;
2107 accmods = Modifiers.PRIVATE;
2109 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2110 this.attributes = attrs;
2114 // FIXME: How do we deal with the user specifying a different
2117 public override TypeAttributes TypeAttr {
2119 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2124 public class Struct : TypeContainer {
2126 // Modifiers allowed in a struct declaration
2128 public const int AllowedModifiers =
2131 Modifiers.PROTECTED |
2132 Modifiers.INTERNAL |
2136 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2137 : base (parent, name, l)
2141 if (parent.Parent == null)
2142 accmods = Modifiers.INTERNAL;
2144 accmods = Modifiers.PRIVATE;
2146 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2148 this.ModFlags |= Modifiers.SEALED;
2149 this.attributes = attrs;
2154 // FIXME: Allow the user to specify a different set of attributes
2155 // in some cases (Sealed for example is mandatory for a class,
2156 // but what SequentialLayout can be changed
2158 public override TypeAttributes TypeAttr {
2160 return base.TypeAttr |
2161 TypeAttributes.SequentialLayout |
2162 TypeAttributes.Sealed |
2163 TypeAttributes.BeforeFieldInit;
2168 public abstract class MethodCore : MemberBase {
2169 public readonly Parameters Parameters;
2170 protected Block block;
2173 // Parameters, cached for semantic analysis.
2175 protected InternalParameters parameter_info;
2176 protected Type [] parameter_types;
2179 // This is set from TypeContainer.DefineMembers if this method overrides something.
2181 public bool OverridesSomething;
2183 public MethodCore (Expression type, int mod, int allowed_mod, string name,
2184 Attributes attrs, Parameters parameters, Location loc)
2185 : base (type, mod, allowed_mod, name, attrs, loc)
2187 Parameters = parameters;
2191 // Returns the System.Type array for the parameters of this method
2193 public Type [] ParameterTypes {
2195 return parameter_types;
2199 public InternalParameters ParameterInfo
2202 return parameter_info;
2206 public Block Block {
2216 protected virtual bool DoDefineParameters (TypeContainer container)
2218 // Check if arguments were correct
2219 parameter_types = Parameters.GetParameterInfo (container);
2220 if ((parameter_types == null) || !CheckParameters (container, parameter_types))
2223 parameter_info = new InternalParameters (container, Parameters);
2225 Parameter array_param = Parameters.ArrayParameter;
2226 if ((array_param != null) &&
2227 (!array_param.ParameterType.IsArray ||
2228 (array_param.ParameterType.GetArrayRank () != 1))) {
2229 Report.Error (225, Location, "params parameter has to be a single dimensional array");
2236 public CallingConventions GetCallingConvention (bool is_class)
2238 CallingConventions cc = 0;
2240 cc = Parameters.GetCallingConvention ();
2243 if ((ModFlags & Modifiers.STATIC) == 0)
2244 cc |= CallingConventions.HasThis;
2246 // FIXME: How is `ExplicitThis' used in C#?
2252 // The method's attributes are passed in because we need to extract
2253 // the "return:" attribute from there to apply on the return type
2255 public void LabelParameters (EmitContext ec, MethodBase builder, Attributes method_attrs)
2258 // Define each type attribute (in/out/ref) and
2259 // the argument names.
2261 Parameter [] p = Parameters.FixedParameters;
2264 MethodBuilder mb = null;
2265 ConstructorBuilder cb = null;
2267 if (builder is MethodBuilder)
2268 mb = (MethodBuilder) builder;
2270 cb = (ConstructorBuilder) builder;
2273 for (i = 0; i < p.Length; i++) {
2274 ParameterBuilder pb;
2275 ParameterAttributes par_attr = p [i].Attributes;
2278 pb = cb.DefineParameter (
2279 i + 1, par_attr, p [i].Name);
2281 pb = mb.DefineParameter (
2282 i + 1, par_attr, p [i].Name);
2284 Attributes attr = p [i].OptAttributes;
2286 Attribute.ApplyAttributes (ec, pb, pb, attr);
2288 if (par_attr == ParameterAttributes.Out){
2289 if (attr.Contains (TypeManager.in_attribute_type))
2290 Report.Error (36, Location,
2291 "Can not use [In] attribute on out parameter");
2297 if (Parameters.ArrayParameter != null){
2298 ParameterBuilder pb;
2299 Parameter array_param = Parameters.ArrayParameter;
2302 pb = cb.DefineParameter (
2303 i + 1, array_param.Attributes,
2306 pb = mb.DefineParameter (
2307 i + 1, array_param.Attributes,
2310 CustomAttributeBuilder a = new CustomAttributeBuilder (
2311 TypeManager.cons_param_array_attribute, new object [0]);
2313 pb.SetCustomAttribute (a);
2317 // And now for the return type attribute decoration
2319 ParameterBuilder ret_pb;
2320 Attributes ret_attrs = null;
2322 if (mb == null || method_attrs == null)
2325 foreach (AttributeSection asec in method_attrs.AttributeSections) {
2327 if (asec.Target != "return")
2330 if (ret_attrs == null)
2331 ret_attrs = new Attributes (asec);
2333 ret_attrs.AddAttributeSection (asec);
2336 if (ret_attrs != null) {
2338 ret_pb = mb.DefineParameter (0, ParameterAttributes.None, "");
2339 Attribute.ApplyAttributes (ec, ret_pb, ret_pb, ret_attrs);
2340 } catch (ArgumentOutOfRangeException) {
2343 ".NET SDK 1.0 does not permit setting custom attributes" +
2344 " on the return type of a method");
2350 public class Method : MethodCore, IIteratorContainer {
2351 public MethodBuilder MethodBuilder;
2352 public MethodData MethodData;
2355 /// Modifiers allowed in a class declaration
2357 const int AllowedModifiers =
2360 Modifiers.PROTECTED |
2361 Modifiers.INTERNAL |
2366 Modifiers.OVERRIDE |
2367 Modifiers.ABSTRACT |
2372 // return_type can be "null" for VOID values.
2374 public Method (Expression return_type, int mod, string name, Parameters parameters,
2375 Attributes attrs, Location l)
2376 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2380 // Returns the `System.Type' for the ReturnType of this
2381 // function. Provides a nice cache. (used between semantic analysis
2382 // and actual code generation
2384 public Type GetReturnType ()
2389 // Whether this is an operator method.
2390 public bool IsOperator;
2392 void DuplicateEntryPoint (MethodInfo b, Location location)
2396 "Program `" + CodeGen.FileName +
2397 "' has more than one entry point defined: `" +
2398 TypeManager.CSharpSignature(b) + "'");
2401 void Report28 (MethodInfo b)
2405 "`" + TypeManager.CSharpSignature(b) +
2406 "' has the wrong signature to be an entry point");
2409 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2411 if (b.ReturnType != TypeManager.void_type &&
2412 b.ReturnType != TypeManager.int32_type)
2415 if (pinfo.Count == 0)
2418 if (pinfo.Count > 1)
2421 Type t = pinfo.ParameterType(0);
2423 (t.GetArrayRank() == 1) &&
2424 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
2425 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2432 // Checks our base implementation if any
2434 protected override bool CheckBase (TypeContainer container)
2436 base.CheckBase (container);
2438 // Check whether arguments were correct.
2439 if (!DoDefineParameters (container))
2442 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2444 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2448 mi_this = TypeContainer.FindMembers (
2449 container.TypeBuilder, MemberTypes.Method,
2450 BindingFlags.NonPublic | BindingFlags.Public |
2451 BindingFlags.Static | BindingFlags.Instance |
2452 BindingFlags.DeclaredOnly,
2453 MethodSignature.method_signature_filter, ms);
2455 if (mi_this.Count > 0) {
2456 Report.Error (111, Location, "Class `" + container.Name + "' " +
2457 "already defines a member called `" + Name + "' " +
2458 "with the same parameter types");
2464 // Verify if the parent has a type with the same name, and then
2465 // check whether we have to create a new slot for it or not.
2467 Type ptype = container.TypeBuilder.BaseType;
2469 // ptype is only null for System.Object while compiling corlib.
2471 MemberList mi, mi_static, mi_instance;
2473 mi_instance = TypeContainer.FindMembers (
2474 ptype, MemberTypes.Method,
2475 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2476 MethodSignature.inheritable_method_signature_filter,
2479 if (mi_instance.Count > 0){
2482 mi_static = TypeContainer.FindMembers (
2483 ptype, MemberTypes.Method,
2484 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2485 MethodSignature.inheritable_method_signature_filter, ms);
2487 if (mi_static.Count > 0)
2493 if (mi != null && mi.Count > 0){
2494 parent_method = (MethodInfo) mi [0];
2495 string name = parent_method.DeclaringType.Name + "." +
2498 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
2501 if ((ModFlags & Modifiers.NEW) == 0) {
2502 Type parent_ret = TypeManager.TypeToCoreType (
2503 parent_method.ReturnType);
2505 if (parent_ret != MemberType) {
2507 508, Location, container.MakeName (Name) + ": cannot " +
2508 "change return type when overriding " +
2509 "inherited member " + name);
2514 if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
2515 WarningNotHiding (container);
2517 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2518 Report.Error (115, Location,
2519 container.MakeName (Name) +
2520 " no suitable methods found to override");
2523 } else if ((ModFlags & Modifiers.NEW) != 0)
2524 WarningNotHiding (container);
2532 public override bool Define (TypeContainer container)
2534 if (!DoDefine (container))
2537 if (!CheckBase (container))
2540 CallingConventions cc = GetCallingConvention (container is Class);
2542 MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2543 ParameterInfo, cc, OptAttributes,
2544 ModFlags, flags, true);
2546 if (!MethodData.Define (container))
2550 // Setup iterator if we are one
2552 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
2553 IteratorHandler ih = new IteratorHandler (
2554 Name, container, MemberType,
2555 ParameterTypes, ParameterInfo,
2556 ModFlags, Location);
2558 Block new_block = ih.Setup (block);
2559 if (new_block == null)
2564 MethodBuilder = MethodData.MethodBuilder;
2567 // This is used to track the Entry Point,
2569 if (Name == "Main" &&
2570 ((ModFlags & Modifiers.STATIC) != 0) &&
2571 (RootContext.MainClass == null ||
2572 RootContext.MainClass == container.TypeBuilder.FullName)){
2573 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2574 if (RootContext.EntryPoint == null) {
2575 RootContext.EntryPoint = MethodBuilder;
2576 RootContext.EntryPointLocation = Location;
2578 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2579 DuplicateEntryPoint (MethodBuilder, Location);
2582 Report28(MethodBuilder);
2591 public void Emit (TypeContainer container)
2593 MethodData.Emit (container, Block, this);
2597 void IIteratorContainer.SetYields ()
2599 ModFlags |= Modifiers.METHOD_YIELDS;
2603 public abstract class ConstructorInitializer {
2604 ArrayList argument_list;
2605 ConstructorInfo parent_constructor;
2606 Parameters parameters;
2609 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2612 this.argument_list = argument_list;
2613 this.parameters = parameters;
2617 public ArrayList Arguments {
2619 return argument_list;
2623 public bool Resolve (EmitContext ec)
2625 Expression parent_constructor_group;
2628 ec.CurrentBlock = new Block (null, Block.Flags.Implicit, parameters);
2630 if (argument_list != null){
2631 foreach (Argument a in argument_list){
2632 if (!a.Resolve (ec, loc))
2636 ec.CurrentBlock = null;
2638 if (this is ConstructorBaseInitializer) {
2639 if (ec.ContainerType.BaseType == null)
2642 t = ec.ContainerType.BaseType;
2643 if (ec.ContainerType.IsValueType) {
2644 Report.Error (522, loc,
2645 "structs cannot call base class constructors");
2649 t = ec.ContainerType;
2651 parent_constructor_group = Expression.MemberLookup (
2652 ec, t, null, t, ".ctor",
2653 MemberTypes.Constructor,
2654 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2657 if (parent_constructor_group == null){
2658 Report.Error (1501, loc,
2659 "Can not find a constructor for this argument list");
2663 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2664 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2666 if (parent_constructor == null){
2667 Report.Error (1501, loc,
2668 "Can not find a constructor for this argument list");
2675 public void Emit (EmitContext ec)
2677 if (parent_constructor != null){
2678 ec.Mark (loc, false);
2680 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2682 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
2687 public class ConstructorBaseInitializer : ConstructorInitializer {
2688 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2689 base (argument_list, pars, l)
2694 public class ConstructorThisInitializer : ConstructorInitializer {
2695 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2696 base (argument_list, pars, l)
2701 public class Constructor : MethodCore {
2702 public ConstructorBuilder ConstructorBuilder;
2703 public ConstructorInitializer Initializer;
2704 new public Attributes OptAttributes;
2707 // Modifiers allowed for a constructor.
2709 public const int AllowedModifiers =
2711 Modifiers.PROTECTED |
2712 Modifiers.INTERNAL |
2719 // The spec claims that static is not permitted, but
2720 // my very own code has static constructors.
2722 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2723 : base (null, 0, AllowedModifiers, name, null, args, l)
2729 // Returns true if this is a default constructor
2731 public bool IsDefault ()
2733 if ((ModFlags & Modifiers.STATIC) != 0)
2734 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2735 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2738 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2739 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2740 (Initializer is ConstructorBaseInitializer) &&
2741 (Initializer.Arguments == null);
2745 // Creates the ConstructorBuilder
2747 public override bool Define (TypeContainer container)
2749 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2750 MethodAttributes.SpecialName);
2752 // Check if arguments were correct.
2753 if (!DoDefineParameters (container))
2756 if ((ModFlags & Modifiers.STATIC) != 0){
2757 ca |= MethodAttributes.Static | MethodAttributes.Private;
2759 if (container is Struct && ParameterTypes.Length == 0){
2762 "Structs can not contain explicit parameterless " +
2766 ca |= MethodAttributes.HideBySig;
2768 if ((ModFlags & Modifiers.PUBLIC) != 0)
2769 ca |= MethodAttributes.Public;
2770 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2771 if ((ModFlags & Modifiers.INTERNAL) != 0)
2772 ca |= MethodAttributes.FamORAssem;
2774 ca |= MethodAttributes.Family;
2775 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2776 ca |= MethodAttributes.Assembly;
2777 else if (IsDefault ())
2778 ca |= MethodAttributes.Public;
2780 ca |= MethodAttributes.Private;
2783 ConstructorBuilder = container.TypeBuilder.DefineConstructor (
2784 ca, GetCallingConvention (container is Class), ParameterTypes);
2786 if ((ModFlags & Modifiers.UNSAFE) != 0)
2787 ConstructorBuilder.InitLocals = false;
2790 // HACK because System.Reflection.Emit is lame
2792 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2795 "Class `" +container.Name+ "' already contains a definition with the " +
2796 "same return value and parameter types for constructor `" + Name
2807 public void Emit (TypeContainer container)
2809 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2810 EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
2813 // extern methods have no bodies
2815 if ((ModFlags & Modifiers.EXTERN) != 0) {
2816 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
2818 179, Location, "External constructor `" +
2819 TypeManager.CSharpSignature (ConstructorBuilder) +
2820 "' can not have a body");
2823 } else if (block == null) {
2825 501, Location, "Constructor `" +
2826 TypeManager.CSharpSignature (ConstructorBuilder) +
2827 "' must declare a body since it is not marked extern");
2831 if ((ModFlags & Modifiers.STATIC) == 0){
2832 if (container is Class && Initializer == null)
2833 Initializer = new ConstructorBaseInitializer (
2834 null, Parameters.EmptyReadOnlyParameters, Location);
2838 // Spec mandates that Initializers will not have
2842 if (Initializer != null && !Initializer.Resolve (ec))
2844 ec.IsStatic = false;
2847 LabelParameters (ec, ConstructorBuilder, OptAttributes);
2849 SymbolWriter sw = CodeGen.SymbolWriter;
2850 bool generate_debugging = false;
2852 if ((sw != null) && (block != null) &&
2853 !Location.IsNull (Location) &&
2854 !Location.IsNull (block.EndLocation)) {
2856 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
2858 generate_debugging = true;
2862 // Classes can have base initializers and instance field initializers.
2864 if (container is Class){
2865 if ((ModFlags & Modifiers.STATIC) == 0){
2868 // If we use a "this (...)" constructor initializer, then
2869 // do not emit field initializers, they are initialized in the other constructor
2871 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
2872 container.EmitFieldInitializers (ec);
2875 if (Initializer != null)
2876 Initializer.Emit (ec);
2878 if ((ModFlags & Modifiers.STATIC) != 0)
2879 container.EmitFieldInitializers (ec);
2881 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes);
2883 // If this is a non-static `struct' constructor and doesn't have any
2884 // initializer, it must initialize all of the struct's fields.
2885 if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
2886 Block.AddThisVariable (container, Location);
2888 ec.EmitTopBlock (block, ParameterInfo, Location);
2890 if (generate_debugging)
2898 // Encapsulates most of the Method's state
2900 public class MethodData {
2902 // The return type of this method
2904 public readonly Type ReturnType;
2905 public readonly Type[] ParameterTypes;
2906 public readonly InternalParameters ParameterInfo;
2907 public readonly CallingConventions CallingConventions;
2908 public readonly Attributes OptAttributes;
2909 public readonly Location Location;
2912 // Are we implementing an interface ?
2914 public bool IsImplementing = false;
2919 protected MemberBase member;
2920 protected int modifiers;
2921 protected MethodAttributes flags;
2922 protected bool is_method;
2923 protected string accessor_name;
2926 // It can either hold a string with the condition, or an arraylist of conditions.
2927 object conditionals;
2929 MethodBuilder builder = null;
2930 public MethodBuilder MethodBuilder {
2936 public MethodData (MemberBase member, string name, Type return_type,
2937 Type [] parameter_types, InternalParameters parameters,
2938 CallingConventions cc, Attributes opt_attrs,
2939 int modifiers, MethodAttributes flags, bool is_method)
2941 this.member = member;
2942 this.accessor_name = name;
2943 this.ReturnType = return_type;
2944 this.ParameterTypes = parameter_types;
2945 this.ParameterInfo = parameters;
2946 this.CallingConventions = cc;
2947 this.OptAttributes = opt_attrs;
2948 this.modifiers = modifiers;
2950 this.is_method = is_method;
2951 this.Location = member.Location;
2952 this.conditionals = null;
2958 Attribute dllimport_attribute = null;
2959 string obsolete = null;
2960 bool obsolete_error = false;
2962 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2964 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2967 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2968 if (asec.Attributes == null)
2971 foreach (Attribute a in asec.Attributes) {
2972 if (a.Name == "Conditional") {
2973 if (!ApplyConditionalAttribute (a))
2975 } else if (a.Name == "Obsolete") {
2976 if (!ApplyObsoleteAttribute (a))
2978 } else if (a.Name.IndexOf ("DllImport") != -1) {
2980 a.Type = TypeManager.dllimport_type;
2981 Attribute.Error_AttributeNotValidForElement (a, Location);
2984 if (!ApplyDllImportAttribute (a))
2994 // Applies the `DllImport' attribute to the method.
2996 protected virtual bool ApplyDllImportAttribute (Attribute a)
2998 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2999 if ((modifiers & extern_static) != extern_static) {
3000 Report.Error (601, Location,
3001 "The DllImport attribute must be specified on a method " +
3002 "marked `static' and `extern'.");
3006 flags |= MethodAttributes.PinvokeImpl;
3007 dllimport_attribute = a;
3012 // Applies the `Obsolete' attribute to the method.
3014 protected virtual bool ApplyObsoleteAttribute (Attribute a)
3016 if (obsolete != null) {
3017 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
3021 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
3022 return obsolete != null;
3026 // Applies the `Conditional' attribute to the method.
3028 protected virtual bool ApplyConditionalAttribute (Attribute a)
3030 // The Conditional attribute is only valid on methods.
3032 Attribute.Error_AttributeNotValidForElement (a, Location);
3036 string condition = a.Conditional_GetConditionName ();
3038 if (condition == null)
3041 if (ReturnType != TypeManager.void_type) {
3042 Report.Error (578, Location,
3043 "Conditional not valid on `" + member.Name + "' " +
3044 "because its return type is not void");
3048 if ((modifiers & Modifiers.OVERRIDE) != 0) {
3049 Report.Error (243, Location,
3050 "Conditional not valid on `" + member.Name + "' " +
3051 "because it is an override method");
3055 if (member.IsExplicitImpl) {
3056 Report.Error (577, Location,
3057 "Conditional not valid on `" + member.Name + "' " +
3058 "because it is an explicit interface implementation");
3062 if (IsImplementing) {
3063 Report.Error (623, Location,
3064 "Conditional not valid on `" + member.Name + "' " +
3065 "because it is an interface method");
3070 // The likelyhood that the conditional will be more than 1 is very slim
3072 if (conditionals == null)
3073 conditionals = condition;
3074 else if (conditionals is string){
3075 string s = (string) conditionals;
3076 conditionals = new ArrayList ();
3077 ((ArrayList)conditionals).Add (s);
3079 ((ArrayList)conditionals).Add (condition);
3085 // Checks whether this method should be ignored due to its Conditional attributes.
3087 bool ShouldIgnore (Location loc)
3089 // When we're overriding a virtual method, we implicitly inherit the
3090 // Conditional attributes from our parent.
3091 if (member.ParentMethod != null) {
3092 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3093 member.ParentMethod, loc);
3095 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3099 if (conditionals != null){
3100 if (conditionals is string){
3101 if (RootContext.AllDefines [conditionals] == null)
3104 foreach (string condition in (ArrayList) conditionals)
3105 if (RootContext.AllDefines [condition] == null)
3113 // Returns the TypeManager.MethodFlags for this method.
3114 // This emits an error 619 / warning 618 if the method is obsolete.
3115 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3117 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3119 TypeManager.MethodFlags flags = 0;
3121 if (obsolete != null) {
3122 if (obsolete_error) {
3123 Report.Error (619, loc, "Method `" + member.Name +
3124 "' is obsolete: `" + obsolete + "'");
3125 return TypeManager.MethodFlags.IsObsoleteError;
3127 Report.Warning (618, loc, "Method `" + member.Name +
3128 "' is obsolete: `" + obsolete + "'");
3130 flags |= TypeManager.MethodFlags.IsObsolete;
3133 if (ShouldIgnore (loc))
3134 flags |= TypeManager.MethodFlags.ShouldIgnore;
3139 public virtual bool Define (TypeContainer container)
3141 MethodInfo implementing = null;
3142 string method_name, name, prefix;
3144 if (OptAttributes != null)
3145 if (!ApplyAttributes (OptAttributes, is_method))
3148 if (member.IsExplicitImpl)
3149 prefix = member.InterfaceType.FullName + ".";
3153 if (accessor_name != null)
3154 name = accessor_name + "_" + member.ShortName;
3156 name = member.ShortName;
3157 method_name = prefix + name;
3159 if (container.Pending != null){
3160 if (member is Indexer)
3161 implementing = container.Pending.IsInterfaceIndexer (
3162 member.InterfaceType, ReturnType, ParameterTypes);
3164 implementing = container.Pending.IsInterfaceMethod (
3165 member.InterfaceType, name, ReturnType, ParameterTypes);
3167 if (member.InterfaceType != null && implementing == null){
3168 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
3175 // For implicit implementations, make sure we are public, for
3176 // explicit implementations, make sure we are private.
3178 if (implementing != null){
3180 // Setting null inside this block will trigger a more
3181 // verbose error reporting for missing interface implementations
3183 // The "candidate" function has been flagged already
3184 // but it wont get cleared
3186 if (member.IsExplicitImpl){
3187 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3188 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3189 implementing = null;
3191 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
3192 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
3194 // If this is an interface method implementation,
3195 // check for public accessibility
3197 implementing = null;
3198 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
3199 // We may never be private.
3200 implementing = null;
3201 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
3203 // We may be protected if we're overriding something.
3205 implementing = null;
3210 // Static is not allowed
3212 if ((modifiers & Modifiers.STATIC) != 0){
3213 implementing = null;
3214 Modifiers.Error_InvalidModifier (Location, "static");
3219 // If implementing is still valid, set flags
3221 if (implementing != null){
3223 // When implementing interface methods, set NewSlot
3224 // unless, we are overwriting a method.
3226 if (implementing.DeclaringType.IsInterface){
3227 if ((modifiers & Modifiers.OVERRIDE) == 0)
3228 flags |= MethodAttributes.NewSlot;
3231 MethodAttributes.Virtual |
3232 MethodAttributes.HideBySig;
3234 // Set Final unless we're virtual, abstract or already overriding a method.
3235 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
3236 flags |= MethodAttributes.Final;
3238 // Get the method name from the explicit interface.
3239 if (member.InterfaceType != null) {
3240 name = implementing.Name;
3241 method_name = prefix + name;
3244 IsImplementing = true;
3248 // Create the MethodBuilder for the method
3250 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3251 if ((modifiers & Modifiers.STATIC) == 0) {
3252 Report.Error (601, Location,
3253 "The DllImport attribute must be specified on " +
3254 "a method marked 'static' and 'extern'.");
3258 EmitContext ec = new EmitContext (
3259 container, Location, null, ReturnType, modifiers);
3261 builder = dllimport_attribute.DefinePInvokeMethod (
3262 ec, container.TypeBuilder, method_name, flags,
3263 ReturnType, ParameterTypes);
3265 builder = container.TypeBuilder.DefineMethod (
3266 method_name, flags, CallingConventions,
3267 ReturnType, ParameterTypes);
3269 if (builder == null)
3272 if ((modifiers & Modifiers.UNSAFE) != 0)
3273 builder.InitLocals = false;
3275 if (IsImplementing){
3277 // clear the pending implemntation flag
3279 if (member is Indexer) {
3280 container.Pending.ImplementIndexer (
3281 member.InterfaceType, builder, ReturnType,
3282 ParameterTypes, true);
3284 container.Pending.ImplementMethod (
3285 member.InterfaceType, name, ReturnType,
3286 ParameterTypes, member.IsExplicitImpl);
3288 if (member.IsExplicitImpl)
3289 container.TypeBuilder.DefineMethodOverride (
3290 builder, implementing);
3294 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3295 Report.Error (111, Location,
3296 "Class `" + container.Name +
3297 "' already contains a definition with the " +
3298 "same return value and parameter types as the " +
3299 "'get' method of property `" + member.Name + "'");
3303 TypeManager.AddMethod (builder, this);
3311 public virtual void Emit (TypeContainer container, Block block, object kind)
3316 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3317 ig = builder.GetILGenerator ();
3321 ec = new EmitContext (container, Location, ig, ReturnType, modifiers);
3323 if (OptAttributes != null)
3324 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes);
3326 if (member is MethodCore)
3327 ((MethodCore) member).LabelParameters (ec, MethodBuilder, OptAttributes);
3330 // abstract or extern methods have no bodies
3332 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3333 if (block == null) {
3334 SymbolWriter sw = CodeGen.SymbolWriter;
3336 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0)) {
3337 sw.OpenMethod (container, MethodBuilder, Location, Location);
3345 // abstract or extern methods have no bodies.
3347 if ((modifiers & Modifiers.ABSTRACT) != 0)
3349 500, Location, "Abstract method `" +
3350 TypeManager.CSharpSignature (builder) +
3351 "' can not have a body");
3353 if ((modifiers & Modifiers.EXTERN) != 0)
3355 179, Location, "External method `" +
3356 TypeManager.CSharpSignature (builder) +
3357 "' can not have a body");
3363 // Methods must have a body unless they're extern or abstract
3365 if (block == null) {
3367 501, Location, "Method `" +
3368 TypeManager.CSharpSignature (builder) +
3369 "' must declare a body since it is not marked " +
3370 "abstract or extern");
3375 // Handle destructors specially
3377 // FIXME: This code generates buggy code
3379 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3380 EmitDestructor (ec, block);
3382 SymbolWriter sw = CodeGen.SymbolWriter;
3384 if ((sw != null) && !Location.IsNull (Location) &&
3385 !Location.IsNull (block.EndLocation)) {
3386 sw.OpenMethod (container, MethodBuilder, Location, block.EndLocation);
3388 ec.EmitTopBlock (block, ParameterInfo, Location);
3392 ec.EmitTopBlock (block, ParameterInfo, Location);
3396 void EmitDestructor (EmitContext ec, Block block)
3398 ILGenerator ig = ec.ig;
3400 Label finish = ig.DefineLabel ();
3401 bool old_in_try = ec.InTry;
3403 ig.BeginExceptionBlock ();
3405 ec.ReturnLabel = finish;
3406 ec.HasReturnLabel = true;
3407 ec.EmitTopBlock (block, null, Location);
3408 ec.InTry = old_in_try;
3410 // ig.MarkLabel (finish);
3411 bool old_in_finally = ec.InFinally;
3412 ec.InFinally = true;
3413 ig.BeginFinallyBlock ();
3415 if (ec.ContainerType.BaseType != null) {
3416 Expression member_lookup = Expression.MemberLookup (
3417 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3418 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, Location);
3420 if (member_lookup != null){
3421 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3423 ig.Emit (OpCodes.Ldarg_0);
3424 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3427 ec.InFinally = old_in_finally;
3429 ig.EndExceptionBlock ();
3430 //ig.MarkLabel (ec.ReturnLabel);
3431 ig.Emit (OpCodes.Ret);
3435 abstract public class MemberBase : MemberCore {
3436 public Expression Type;
3437 public readonly Attributes OptAttributes;
3439 protected MethodAttributes flags;
3442 // The "short" name of this property / indexer / event. This is the
3443 // name without the explicit interface.
3445 public string ShortName;
3448 // The type of this property / indexer / event
3450 public Type MemberType;
3453 // If true, this is an explicit interface implementation
3455 public bool IsExplicitImpl = false;
3458 // The name of the interface we are explicitly implementing
3460 public string ExplicitInterfaceName = null;
3463 // If true, the interface type we are explicitly implementing
3465 public Type InterfaceType = null;
3468 // The method we're overriding if this is an override method.
3470 protected MethodInfo parent_method = null;
3471 public MethodInfo ParentMethod {
3473 return parent_method;
3478 // The constructor is only exposed to our children
3480 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3481 Attributes attrs, Location loc)
3485 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
3486 OptAttributes = attrs;
3489 protected virtual bool CheckBase (TypeContainer container)
3491 if ((container is Struct) || (RootContext.WarningLevel > 3)){
3492 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
3493 if (container is Struct){
3494 Report.Error (666, Location, "Protected member in struct declaration");
3497 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
3503 protected virtual bool CheckParameters (TypeContainer container, Type [] parameters)
3507 foreach (Type partype in parameters){
3508 if (partype.IsPointer){
3509 if (!UnsafeOK (container))
3511 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
3515 if (container.AsAccessible (partype, ModFlags))
3518 if (this is Indexer)
3519 Report.Error (55, Location,
3520 "Inconsistent accessibility: parameter type `" +
3521 TypeManager.CSharpName (partype) + "' is less " +
3522 "accessible than indexer `" + Name + "'");
3523 else if ((this is Method) && ((Method) this).IsOperator)
3524 Report.Error (57, Location,
3525 "Inconsistent accessibility: parameter type `" +
3526 TypeManager.CSharpName (partype) + "' is less " +
3527 "accessible than operator `" + Name + "'");
3529 Report.Error (51, Location,
3530 "Inconsistent accessibility: parameter type `" +
3531 TypeManager.CSharpName (partype) + "' is less " +
3532 "accessible than method `" + Name + "'");
3539 protected virtual bool DoDefine (TypeContainer container)
3544 if (!container.MethodModifiersValid (ModFlags, Name, Location))
3547 flags = Modifiers.MethodAttr (ModFlags);
3549 // Lookup Type, verify validity
3550 MemberType = container.ResolveType (Type, false, Location);
3551 if (MemberType == null)
3554 if ((container.ModFlags & Modifiers.SEALED) != 0){
3555 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
3556 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
3561 // verify accessibility
3562 if (!container.AsAccessible (MemberType, ModFlags)) {
3563 if (this is Property)
3564 Report.Error (53, Location,
3565 "Inconsistent accessibility: property type `" +
3566 TypeManager.CSharpName (MemberType) + "' is less " +
3567 "accessible than property `" + Name + "'");
3568 else if (this is Indexer)
3569 Report.Error (54, Location,
3570 "Inconsistent accessibility: indexer return type `" +
3571 TypeManager.CSharpName (MemberType) + "' is less " +
3572 "accessible than indexer `" + Name + "'");
3573 else if (this is Method) {
3574 if (((Method) this).IsOperator)
3575 Report.Error (56, Location,
3576 "Inconsistent accessibility: return type `" +
3577 TypeManager.CSharpName (MemberType) + "' is less " +
3578 "accessible than operator `" + Name + "'");
3580 Report.Error (50, Location,
3581 "Inconsistent accessibility: return type `" +
3582 TypeManager.CSharpName (MemberType) + "' is less " +
3583 "accessible than method `" + Name + "'");
3585 Report.Error (52, Location,
3586 "Inconsistent accessibility: field type `" +
3587 TypeManager.CSharpName (MemberType) + "' is less " +
3588 "accessible than field `" + Name + "'");
3592 if (MemberType.IsPointer && !UnsafeOK (container))
3596 // Check for explicit interface implementation
3598 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
3599 int pos = Name.LastIndexOf (".");
3601 ExplicitInterfaceName = Name.Substring (0, pos);
3602 ShortName = Name.Substring (pos + 1);
3606 if (ExplicitInterfaceName != null) {
3607 InterfaceType = RootContext.LookupType (
3608 container, ExplicitInterfaceName, false, Location);
3609 if (InterfaceType == null)
3612 // Compute the full name that we need to export.
3613 Name = InterfaceType.FullName + "." + ShortName;
3615 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
3618 IsExplicitImpl = true;
3620 IsExplicitImpl = false;
3627 // Fields and Events both generate FieldBuilders, we use this to share
3628 // their common bits. This is also used to flag usage of the field
3630 abstract public class FieldBase : MemberBase {
3631 public FieldBuilder FieldBuilder;
3632 public Status status;
3635 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3638 // The constructor is only exposed to our children
3640 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3641 object init, Attributes attrs, Location loc)
3642 : base (type, mod, allowed_mod, name, attrs, loc)
3648 // Whether this field has an initializer.
3650 public bool HasInitializer {
3652 return init != null;
3656 public bool IsAssigned;
3658 protected readonly Object init;
3660 Expression init_expr;
3661 bool init_expr_initialized = false;
3664 // Resolves and returns the field initializer.
3666 public Expression GetInitializerExpression (EmitContext ec)
3668 if (init_expr_initialized)
3672 if (init is Expression)
3673 e = (Expression) init;
3675 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3677 ec.IsFieldInitializer = true;
3678 e = e.DoResolve (ec);
3679 ec.IsFieldInitializer = false;
3682 init_expr_initialized = true;
3689 // The Field class is used to represents class/struct fields during parsing.
3691 public class Field : FieldBase {
3693 // Modifiers allowed in a class declaration
3695 const int AllowedModifiers =
3698 Modifiers.PROTECTED |
3699 Modifiers.INTERNAL |
3702 Modifiers.VOLATILE |
3706 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3707 Attributes attrs, Location loc)
3708 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3712 public override bool Define (TypeContainer container)
3714 Type t = container.ResolveType (Type, false, Location);
3719 CheckBase (container);
3721 if (!container.AsAccessible (t, ModFlags)) {
3722 Report.Error (52, Location,
3723 "Inconsistent accessibility: field type `" +
3724 TypeManager.CSharpName (t) + "' is less " +
3725 "accessible than field `" + Name + "'");
3729 if (t.IsPointer && !UnsafeOK (container))
3732 if (RootContext.WarningLevel > 1){
3733 Type ptype = container.TypeBuilder.BaseType;
3735 // ptype is only null for System.Object while compiling corlib.
3737 TypeContainer.FindMembers (
3738 ptype, MemberTypes.Method,
3739 BindingFlags.Public |
3740 BindingFlags.Static | BindingFlags.Instance,
3741 System.Type.FilterName, Name);
3745 if ((ModFlags & Modifiers.VOLATILE) != 0){
3749 if (TypeManager.IsEnumType (vt))
3750 vt = TypeManager.EnumToUnderlying (t);
3752 if (!((vt == TypeManager.bool_type) ||
3753 (vt == TypeManager.sbyte_type) ||
3754 (vt == TypeManager.byte_type) ||
3755 (vt == TypeManager.short_type) ||
3756 (vt == TypeManager.ushort_type) ||
3757 (vt == TypeManager.int32_type) ||
3758 (vt == TypeManager.uint32_type) ||
3759 (vt == TypeManager.char_type) ||
3760 (vt == TypeManager.float_type))){
3762 677, Location, container.MakeName (Name) +
3763 " A volatile field can not be of type `" +
3764 TypeManager.CSharpName (vt) + "'");
3769 if ((ModFlags & Modifiers.READONLY) != 0){
3772 "A field can not be both volatile and readonly");
3777 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3779 if (container is Struct &&
3780 ((fa & FieldAttributes.Static) == 0) &&
3781 t == container.TypeBuilder &&
3782 !TypeManager.IsBuiltinType (t)){
3783 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name +
3784 "' causes a cycle in the structure layout");
3788 FieldBuilder = container.TypeBuilder.DefineField (
3789 Name, t, Modifiers.FieldAttr (ModFlags));
3791 TypeManager.RegisterFieldBase (FieldBuilder, this);
3795 public void Emit (TypeContainer tc)
3797 EmitContext ec = new EmitContext (tc, Location, null,
3798 FieldBuilder.FieldType, ModFlags);
3800 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes);
3805 // `set' and `get' accessors are represented with an Accessor.
3807 public class Accessor {
3809 // Null if the accessor is empty, or a Block if not
3812 public Attributes OptAttributes;
3814 public Accessor (Block b, Attributes attrs)
3817 OptAttributes = attrs;
3822 // Properties and Indexers both generate PropertyBuilders, we use this to share
3823 // their common bits.
3825 abstract public class PropertyBase : MethodCore {
3826 public Accessor Get, Set;
3827 public PropertyBuilder PropertyBuilder;
3828 public MethodBuilder GetBuilder, SetBuilder;
3829 public MethodData GetData, SetData;
3831 protected EmitContext ec;
3833 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3834 Parameters parameters, Accessor get_block, Accessor set_block,
3835 Attributes attrs, Location loc)
3836 : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3842 protected override bool DoDefine (TypeContainer container)
3844 if (!base.DoDefine (container))
3847 ec = new EmitContext (container, Location, null, MemberType, ModFlags);
3853 // Checks our base implementation if any
3855 protected override bool CheckBase (TypeContainer container)
3857 base.CheckBase (container);
3859 // Check whether arguments were correct.
3860 if (!DoDefineParameters (container))
3867 MethodSignature ms, base_ms;
3868 if (this is Indexer) {
3869 string name, base_name;
3871 report_name = "this";
3872 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
3873 ms = new MethodSignature (name, null, ParameterTypes);
3874 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
3875 base_ms = new MethodSignature (base_name, null, ParameterTypes);
3878 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
3882 // Verify if the parent has a type with the same name, and then
3883 // check whether we have to create a new slot for it or not.
3885 Type ptype = container.TypeBuilder.BaseType;
3887 // ptype is only null for System.Object while compiling corlib.
3888 if (ptype == null) {
3889 if ((ModFlags & Modifiers.NEW) != 0)
3890 WarningNotHiding (container);
3895 MemberList props_this;
3897 props_this = TypeContainer.FindMembers (
3898 container.TypeBuilder, MemberTypes.Property,
3899 BindingFlags.NonPublic | BindingFlags.Public |
3900 BindingFlags.Static | BindingFlags.Instance |
3901 BindingFlags.DeclaredOnly,
3902 MethodSignature.method_signature_filter, ms);
3904 if (props_this.Count > 0) {
3905 Report.Error (111, Location, "Class `" + container.Name + "' " +
3906 "already defines a member called `" + report_name + "' " +
3907 "with the same parameter types");
3911 MemberList mi_props;
3913 mi_props = TypeContainer.FindMembers (
3914 ptype, MemberTypes.Property,
3915 BindingFlags.NonPublic | BindingFlags.Public |
3916 BindingFlags.Instance | BindingFlags.Static,
3917 MethodSignature.inheritable_method_signature_filter, base_ms);
3919 if (mi_props.Count > 0){
3920 PropertyInfo parent_property = (PropertyInfo) mi_props [0];
3921 string name = parent_property.DeclaringType.Name + "." +
3922 parent_property.Name;
3924 MethodInfo get, set, parent_method;
3925 get = parent_property.GetGetMethod (true);
3926 set = parent_property.GetSetMethod (true);
3929 parent_method = get;
3930 else if (set != null)
3931 parent_method = set;
3933 throw new Exception ("Internal error!");
3935 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
3938 if ((ModFlags & Modifiers.NEW) == 0) {
3939 Type parent_type = TypeManager.TypeToCoreType (
3940 parent_property.PropertyType);
3942 if (parent_type != MemberType) {
3944 508, Location, container.MakeName (Name) + ": cannot " +
3945 "change return type when overriding " +
3946 "inherited member " + name);
3951 if ((ModFlags & Modifiers.NEW) != 0)
3952 WarningNotHiding (container);
3954 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3955 if (this is Indexer)
3956 Report.Error (115, Location,
3957 container.MakeName (Name) +
3958 " no suitable indexers found to override");
3960 Report.Error (115, Location,
3961 container.MakeName (Name) +
3962 " no suitable properties found to override");
3969 public void Emit (TypeContainer tc)
3972 // The PropertyBuilder can be null for explicit implementations, in that
3973 // case, we do not actually emit the ".property", so there is nowhere to
3974 // put the attribute
3976 if (PropertyBuilder != null)
3977 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes);
3979 if (GetData != null) {
3980 GetData.Emit (tc, Get.Block, Get);
3984 if (SetData != null) {
3985 SetData.Emit (tc, Set.Block, Set);
3991 public class Property : PropertyBase {
3992 const int AllowedModifiers =
3995 Modifiers.PROTECTED |
3996 Modifiers.INTERNAL |
4000 Modifiers.OVERRIDE |
4001 Modifiers.ABSTRACT |
4006 public Property (Expression type, string name, int mod_flags,
4007 Accessor get_block, Accessor set_block,
4008 Attributes attrs, Location loc)
4009 : base (type, name, mod_flags, AllowedModifiers,
4010 Parameters.EmptyReadOnlyParameters,
4011 get_block, set_block, attrs, loc)
4015 public override bool Define (TypeContainer container)
4017 if (!DoDefine (container))
4020 if (!CheckBase (container))
4023 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4026 Type [] parameters = TypeManager.NoTypes;
4028 InternalParameters ip = new InternalParameters (
4029 container, Parameters.EmptyReadOnlyParameters);
4031 GetData = new MethodData (this, "get", MemberType,
4032 parameters, ip, CallingConventions.Standard,
4033 Get.OptAttributes, ModFlags, flags, false);
4035 if (!GetData.Define (container))
4038 GetBuilder = GetData.MethodBuilder;
4042 Type [] parameters = new Type [1];
4043 parameters [0] = MemberType;
4045 Parameter [] parms = new Parameter [1];
4046 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4047 InternalParameters ip = new InternalParameters (
4048 container, new Parameters (parms, null, Location));
4050 SetData = new MethodData (this, "set", TypeManager.void_type,
4051 parameters, ip, CallingConventions.Standard,
4052 Set.OptAttributes, ModFlags, flags, false);
4054 if (!SetData.Define (container))
4057 SetBuilder = SetData.MethodBuilder;
4058 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4061 // FIXME - PropertyAttributes.HasDefault ?
4063 PropertyAttributes prop_attr =
4064 PropertyAttributes.RTSpecialName |
4065 PropertyAttributes.SpecialName;
4067 if (!IsExplicitImpl){
4068 PropertyBuilder = container.TypeBuilder.DefineProperty (
4069 Name, prop_attr, MemberType, null);
4072 PropertyBuilder.SetGetMethod (GetBuilder);
4075 PropertyBuilder.SetSetMethod (SetBuilder);
4078 // HACK for the reasons exposed above
4080 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4083 "Class `" + container.Name +
4084 "' already contains a definition for the property `" +
4094 /// Gigantic workaround for lameness in SRE follows :
4095 /// This class derives from EventInfo and attempts to basically
4096 /// wrap around the EventBuilder so that FindMembers can quickly
4097 /// return this in it search for members
4099 public class MyEventBuilder : EventInfo {
4102 // We use this to "point" to our Builder which is
4103 // not really a MemberInfo
4105 EventBuilder MyBuilder;
4108 // We "catch" and wrap these methods
4110 MethodInfo raise, remove, add;
4112 EventAttributes attributes;
4113 Type declaring_type, reflected_type, event_type;
4118 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4120 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4122 // And now store the values in our own fields.
4124 declaring_type = type_builder;
4126 reflected_type = type_builder;
4128 attributes = event_attr;
4131 this.event_type = event_type;
4135 // Methods that you have to override. Note that you only need
4136 // to "implement" the variants that take the argument (those are
4137 // the "abstract" methods, the others (GetAddMethod()) are
4140 public override MethodInfo GetAddMethod (bool nonPublic)
4145 public override MethodInfo GetRemoveMethod (bool nonPublic)
4150 public override MethodInfo GetRaiseMethod (bool nonPublic)
4156 // These methods make "MyEventInfo" look like a Builder
4158 public void SetRaiseMethod (MethodBuilder raiseMethod)
4160 raise = raiseMethod;
4161 MyBuilder.SetRaiseMethod (raiseMethod);
4164 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4166 remove = removeMethod;
4167 MyBuilder.SetRemoveOnMethod (removeMethod);
4170 public void SetAddOnMethod (MethodBuilder addMethod)
4173 MyBuilder.SetAddOnMethod (addMethod);
4176 public void SetCustomAttribute (CustomAttributeBuilder cb)
4178 MyBuilder.SetCustomAttribute (cb);
4181 public override object [] GetCustomAttributes (bool inherit)
4183 // FIXME : There's nothing which can be seemingly done here because
4184 // we have no way of getting at the custom attribute objects of the
4189 public override object [] GetCustomAttributes (Type t, bool inherit)
4191 // FIXME : Same here !
4195 public override bool IsDefined (Type t, bool b)
4200 public override EventAttributes Attributes {
4206 public override string Name {
4212 public override Type DeclaringType {
4214 return declaring_type;
4218 public override Type ReflectedType {
4220 return reflected_type;
4224 public Type EventType {
4230 public void SetUsed ()
4232 if (my_event != null)
4233 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
4237 public class Event : FieldBase {
4238 const int AllowedModifiers =
4241 Modifiers.PROTECTED |
4242 Modifiers.INTERNAL |
4247 Modifiers.OVERRIDE |
4251 public readonly Accessor Add;
4252 public readonly Accessor Remove;
4253 public MyEventBuilder EventBuilder;
4255 MethodBuilder AddBuilder, RemoveBuilder;
4256 MethodData AddData, RemoveData;
4258 public Event (Expression type, string name, Object init, int mod, Accessor add,
4259 Accessor remove, Attributes attrs, Location loc)
4260 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4266 public override bool Define (TypeContainer container)
4268 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4269 MethodAttributes m_attr = MethodAttributes.HideBySig | MethodAttributes.SpecialName
4271 if (!DoDefine (container))
4274 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
4275 Report.Error (74, Location, "'" + container.Name + "." + Name +
4276 "': abstract event can not have an initializer");
4280 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4281 Report.Error (66, Location, "'" + container.Name + "." + Name +
4282 "' : event must be of a delegate type");
4286 Type [] parameter_types = new Type [1];
4287 parameter_types [0] = MemberType;
4289 Parameter [] parms = new Parameter [1];
4290 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4291 InternalParameters ip = new InternalParameters (
4292 container, new Parameters (parms, null, Location));
4294 if (!CheckBase (container))
4298 // Now define the accessors
4300 AddData = new MethodData (this, "add", TypeManager.void_type,
4301 parameter_types, ip, CallingConventions.Standard,
4302 (Add != null) ? Add.OptAttributes : null,
4303 ModFlags, flags | m_attr, false);
4305 if (!AddData.Define (container))
4308 AddBuilder = AddData.MethodBuilder;
4309 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4311 RemoveData = new MethodData (this, "remove", TypeManager.void_type,
4312 parameter_types, ip, CallingConventions.Standard,
4313 (Remove != null) ? Remove.OptAttributes : null,
4314 ModFlags, flags | m_attr, false);
4316 if (!RemoveData.Define (container))
4319 RemoveBuilder = RemoveData.MethodBuilder;
4320 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4322 if (!IsExplicitImpl){
4323 EventBuilder = new MyEventBuilder (this,
4324 container.TypeBuilder, Name, e_attr, MemberType);
4326 if (Add == null && Remove == null) {
4327 FieldBuilder = container.TypeBuilder.DefineField (
4329 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4330 TypeManager.RegisterPrivateFieldOfEvent (
4331 (EventInfo) EventBuilder, FieldBuilder);
4332 TypeManager.RegisterFieldBase (FieldBuilder, this);
4335 EventBuilder.SetAddOnMethod (AddBuilder);
4336 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4338 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4339 Report.Error (111, Location,
4340 "Class `" + container.Name +
4341 "' already contains a definition for the event `" +
4350 void EmitDefaultMethod (EmitContext ec, bool is_add)
4352 ILGenerator ig = ec.ig;
4353 MethodInfo method = null;
4356 method = TypeManager.delegate_combine_delegate_delegate;
4358 method = TypeManager.delegate_remove_delegate_delegate;
4360 if ((ModFlags & Modifiers.STATIC) != 0) {
4361 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4362 ig.Emit (OpCodes.Ldarg_0);
4363 ig.Emit (OpCodes.Call, method);
4364 ig.Emit (OpCodes.Castclass, MemberType);
4365 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4367 ig.Emit (OpCodes.Ldarg_0);
4368 ig.Emit (OpCodes.Ldarg_0);
4369 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4370 ig.Emit (OpCodes.Ldarg_1);
4371 ig.Emit (OpCodes.Call, method);
4372 ig.Emit (OpCodes.Castclass, MemberType);
4373 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4375 ig.Emit (OpCodes.Ret);
4378 public void Emit (TypeContainer tc)
4382 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4383 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes);
4386 AddData.Emit (tc, Add.Block, Add);
4389 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4390 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4391 EmitDefaultMethod (ec, true);
4394 if (Remove != null) {
4395 RemoveData.Emit (tc, Remove.Block, Remove);
4396 Remove.Block = null;
4398 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4399 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4400 EmitDefaultMethod (ec, false);
4407 // FIXME: This does not handle:
4409 // int INTERFACENAME [ args ]
4414 // int this [ args ]
4416 public class Indexer : PropertyBase {
4418 const int AllowedModifiers =
4421 Modifiers.PROTECTED |
4422 Modifiers.INTERNAL |
4426 Modifiers.OVERRIDE |
4431 public string IndexerName;
4432 public string InterfaceIndexerName;
4435 // Are we implementing an interface ?
4437 bool IsImplementing = false;
4439 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4440 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4441 : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4444 ExplicitInterfaceName = int_type;
4447 public override bool Define (TypeContainer container)
4449 PropertyAttributes prop_attr =
4450 PropertyAttributes.RTSpecialName |
4451 PropertyAttributes.SpecialName;
4453 if (!DoDefine (container))
4456 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4457 if (IndexerName == null)
4458 IndexerName = "Item";
4459 else if (IsExplicitImpl)
4460 Report.Error (592, Location,
4461 "Attribute 'IndexerName' is not valid on this declaration " +
4462 "type. It is valid on `property' declarations only.");
4464 ShortName = IndexerName;
4465 if (IsExplicitImpl) {
4466 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4467 Name = InterfaceType.FullName + "." + IndexerName;
4469 InterfaceIndexerName = IndexerName;
4473 if (!CheckBase (container))
4476 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4478 InternalParameters ip = new InternalParameters (container, Parameters);
4480 GetData = new MethodData (this, "get", MemberType,
4481 ParameterTypes, ip, CallingConventions.Standard,
4482 Get.OptAttributes, ModFlags, flags, false);
4484 if (!GetData.Define (container))
4487 GetBuilder = GetData.MethodBuilder;
4491 int top = ParameterTypes.Length;
4492 Type [] set_pars = new Type [top + 1];
4493 ParameterTypes.CopyTo (set_pars, 0);
4494 set_pars [top] = MemberType;
4496 Parameter [] fixed_parms = Parameters.FixedParameters;
4498 if (fixed_parms == null){
4499 throw new Exception ("We currently do not support only array arguments in an indexer at: " + Location);
4500 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4501 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4503 // Here is the problem: the `value' parameter has
4504 // to come *after* the array parameter in the declaration
4506 // X (object [] x, Type value)
4509 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4510 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4514 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4517 fixed_parms.CopyTo (tmp, 0);
4518 tmp [fixed_parms.Length] = new Parameter (
4519 Type, "value", Parameter.Modifier.NONE, null);
4521 Parameters set_formal_params = new Parameters (tmp, null, Location);
4523 InternalParameters ip = new InternalParameters (container, set_formal_params);
4525 SetData = new MethodData (this, "set", TypeManager.void_type,
4526 set_pars, ip, CallingConventions.Standard,
4527 Set.OptAttributes, ModFlags, flags, false);
4529 if (!SetData.Define (container))
4532 SetBuilder = SetData.MethodBuilder;
4536 // Now name the parameters
4538 Parameter [] p = Parameters.FixedParameters;
4542 for (i = 0; i < p.Length; ++i) {
4544 GetBuilder.DefineParameter (
4545 i + 1, p [i].Attributes, p [i].Name);
4548 SetBuilder.DefineParameter (
4549 i + 1, p [i].Attributes, p [i].Name);
4553 SetBuilder.DefineParameter (
4554 i + 1, ParameterAttributes.None, "value");
4556 if (i != ParameterTypes.Length) {
4557 Parameter array_param = Parameters.ArrayParameter;
4559 SetBuilder.DefineParameter (
4560 i + 1, array_param.Attributes, array_param.Name);
4564 if (GetData != null)
4565 IsImplementing = GetData.IsImplementing;
4566 else if (SetData != null)
4567 IsImplementing = SetData.IsImplementing;
4570 // Define the PropertyBuilder if one of the following conditions are met:
4571 // a) we're not implementing an interface indexer.
4572 // b) the indexer has a different IndexerName and this is no
4573 // explicit interface implementation.
4575 if (!IsExplicitImpl) {
4576 PropertyBuilder = container.TypeBuilder.DefineProperty (
4577 IndexerName, prop_attr, MemberType, ParameterTypes);
4579 if (GetData != null)
4580 PropertyBuilder.SetGetMethod (GetBuilder);
4582 if (SetData != null)
4583 PropertyBuilder.SetSetMethod (SetBuilder);
4585 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4593 public class Operator : MemberCore {
4595 const int AllowedModifiers =
4601 const int RequiredModifiers =
4605 public enum OpType : byte {
4615 // Unary and Binary operators
4638 // Implicit and Explicit
4643 public readonly OpType OperatorType;
4644 public readonly Expression ReturnType;
4645 public readonly Expression FirstArgType, SecondArgType;
4646 public readonly string FirstArgName, SecondArgName;
4648 public Attributes OptAttributes;
4649 public MethodBuilder OperatorMethodBuilder;
4651 public string MethodName;
4652 public Method OperatorMethod;
4654 public Operator (OpType type, Expression ret_type, int flags,
4655 Expression arg1type, string arg1name,
4656 Expression arg2type, string arg2name,
4657 Block block, Attributes attrs, Location loc)
4660 OperatorType = type;
4661 ReturnType = ret_type;
4662 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4663 FirstArgType = arg1type;
4664 FirstArgName = arg1name;
4665 SecondArgType = arg2type;
4666 SecondArgName = arg2name;
4668 OptAttributes = attrs;
4671 string Prototype (TypeContainer container)
4673 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4674 SecondArgType + ")";
4677 public override bool Define (TypeContainer container)
4680 MethodName = "op_" + OperatorType;
4682 if (SecondArgType != null)
4685 Parameter [] param_list = new Parameter [length];
4687 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4690 "User defined operators `" +
4691 Prototype (container) +
4692 "' must be declared static and public");
4696 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4697 Parameter.Modifier.NONE, null);
4698 if (SecondArgType != null)
4699 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4700 Parameter.Modifier.NONE, null);
4702 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4703 new Parameters (param_list, null, Location),
4704 OptAttributes, Location);
4706 OperatorMethod.IsOperator = true;
4707 OperatorMethod.Define (container);
4709 if (OperatorMethod.MethodBuilder == null)
4712 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4714 Type [] param_types = OperatorMethod.ParameterTypes;
4715 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4716 Type return_type = OperatorMethod.GetReturnType ();
4717 Type first_arg_type = param_types [0];
4719 // Rules for conversion operators
4721 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4722 if (first_arg_type == return_type && first_arg_type == declaring_type){
4725 "User-defined conversion cannot take an object of the " +
4726 "enclosing type and convert to an object of the enclosing" +
4731 if (first_arg_type != declaring_type && return_type != declaring_type){
4734 "User-defined conversion must convert to or from the " +
4739 if (first_arg_type == TypeManager.object_type ||
4740 return_type == TypeManager.object_type){
4743 "User-defined conversion cannot convert to or from " +
4748 if (first_arg_type.IsInterface || return_type.IsInterface){
4751 "User-defined conversion cannot convert to or from an " +
4756 if (first_arg_type.IsSubclassOf (return_type) ||
4757 return_type.IsSubclassOf (first_arg_type)){
4760 "User-defined conversion cannot convert between types " +
4761 "that derive from each other");
4764 } else if (SecondArgType == null) {
4765 // Checks for Unary operators
4767 if (first_arg_type != declaring_type){
4770 "The parameter of a unary operator must be the " +
4775 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4776 if (return_type != declaring_type){
4779 "The parameter and return type for ++ and -- " +
4780 "must be the containing type");
4786 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4787 if (return_type != TypeManager.bool_type){
4790 "The return type of operator True or False " +
4797 // Checks for Binary operators
4799 if (first_arg_type != declaring_type &&
4800 param_types [1] != declaring_type){
4803 "One of the parameters of a binary operator must " +
4804 "be the containing type");
4812 public void Emit (TypeContainer container)
4815 // abstract or extern methods have no bodies
4817 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4820 OperatorMethod.Block = Block;
4821 OperatorMethod.Emit (container);
4825 public static string GetName (OpType ot)
4828 case OpType.LogicalNot:
4830 case OpType.OnesComplement:
4832 case OpType.Increment:
4834 case OpType.Decrement:
4840 case OpType.Addition:
4842 case OpType.Subtraction:
4844 case OpType.UnaryPlus:
4846 case OpType.UnaryNegation:
4848 case OpType.Multiply:
4850 case OpType.Division:
4852 case OpType.Modulus:
4854 case OpType.BitwiseAnd:
4856 case OpType.BitwiseOr:
4858 case OpType.ExclusiveOr:
4860 case OpType.LeftShift:
4862 case OpType.RightShift:
4864 case OpType.Equality:
4866 case OpType.Inequality:
4868 case OpType.GreaterThan:
4870 case OpType.LessThan:
4872 case OpType.GreaterThanOrEqual:
4874 case OpType.LessThanOrEqual:
4876 case OpType.Implicit:
4878 case OpType.Explicit:
4884 public override string ToString ()
4886 Type return_type = OperatorMethod.GetReturnType();
4887 Type [] param_types = OperatorMethod.ParameterTypes;
4889 if (SecondArgType == null)
4890 return String.Format (
4891 "{0} operator {1}({2})",
4892 TypeManager.CSharpName (return_type),
4893 GetName (OperatorType),
4896 return String.Format (
4897 "{0} operator {1}({2}, {3})",
4898 TypeManager.CSharpName (return_type),
4899 GetName (OperatorType),
4900 param_types [0], param_types [1]);
4905 // This is used to compare method signatures
4907 struct MethodSignature {
4909 public Type RetType;
4910 public Type [] Parameters;
4913 /// This delegate is used to extract methods which have the
4914 /// same signature as the argument
4916 public static MemberFilter method_signature_filter;
4919 /// This delegate is used to extract inheritable methods which
4920 /// have the same signature as the argument. By inheritable,
4921 /// this means that we have permissions to override the method
4922 /// from the current assembly and class
4924 public static MemberFilter inheritable_method_signature_filter;
4926 static MethodSignature ()
4928 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4929 inheritable_method_signature_filter = new MemberFilter (
4930 InheritableMemberSignatureCompare);
4933 public MethodSignature (string name, Type ret_type, Type [] parameters)
4938 if (parameters == null)
4939 Parameters = TypeManager.NoTypes;
4941 Parameters = parameters;
4944 public override string ToString ()
4947 if (Parameters.Length != 0){
4948 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
4949 for (int i = 0; i < Parameters.Length; i++){
4950 sb.Append (Parameters [i]);
4951 if (i+1 < Parameters.Length)
4954 pars = sb.ToString ();
4957 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
4960 public override int GetHashCode ()
4962 return Name.GetHashCode ();
4965 public override bool Equals (Object o)
4967 MethodSignature other = (MethodSignature) o;
4969 if (other.Name != Name)
4972 if (other.RetType != RetType)
4975 if (Parameters == null){
4976 if (other.Parameters == null)
4981 if (other.Parameters == null)
4984 int c = Parameters.Length;
4985 if (other.Parameters.Length != c)
4988 for (int i = 0; i < c; i++)
4989 if (other.Parameters [i] != Parameters [i])
4995 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4997 MethodSignature sig = (MethodSignature) filter_criteria;
4999 if (m.Name != sig.Name)
5003 MethodInfo mi = m as MethodInfo;
5004 PropertyInfo pi = m as PropertyInfo;
5007 ReturnType = mi.ReturnType;
5008 else if (pi != null)
5009 ReturnType = pi.PropertyType;
5014 // we use sig.RetType == null to mean `do not check the
5015 // method return value.
5017 if (sig.RetType != null)
5018 if (ReturnType != sig.RetType)
5023 args = TypeManager.GetArgumentTypes (mi);
5025 args = TypeManager.GetArgumentTypes (pi);
5026 Type [] sigp = sig.Parameters;
5028 if (args.Length != sigp.Length)
5031 for (int i = args.Length; i > 0; ){
5033 if (args [i] != sigp [i])
5040 // This filter should be used when we are requesting methods that
5041 // we want to override.
5043 // This makes a number of assumptions, for example
5044 // that the methods being extracted are of a parent
5045 // class (this means we know implicitly that we are
5046 // being called to find out about members by a derived
5049 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
5052 PropertyInfo pi = m as PropertyInfo;
5055 mi = pi.GetGetMethod (true);
5057 mi = pi.GetSetMethod (true);
5059 mi = m as MethodInfo;
5062 Console.WriteLine ("Nothing found");
5065 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
5067 // If only accessible to the current class.
5068 if (prot == MethodAttributes.Private)
5071 if (!MemberSignatureCompare (m, filter_criteria))
5074 // If only accessible to the defining assembly or
5075 if (prot == MethodAttributes.FamANDAssem ||
5076 prot == MethodAttributes.Assembly){
5077 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
5083 // Anything else (FamOrAssembly and Public) is fine