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 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;
158 if ((res = IsValid (basename)) != AdditionResult.Success)
161 if (constants == null)
162 constants = new ArrayList ();
164 constants.Add (constant);
165 DefineName (Name + "." + basename, constant);
167 return AdditionResult.Success;
170 public AdditionResult AddEnum (Mono.CSharp.Enum e)
174 if ((res = IsValid (e.Basename)) != AdditionResult.Success)
178 enums = new ArrayList ();
181 DefineName (e.Name, e);
183 return AdditionResult.Success;
186 public AdditionResult AddClass (Class c)
190 if ((res = IsValid (c.Basename)) != AdditionResult.Success)
193 DefineName (c.Name, c);
196 return AdditionResult.Success;
199 public AdditionResult AddStruct (Struct s)
203 if ((res = IsValid (s.Basename)) != AdditionResult.Success)
206 DefineName (s.Name, s);
209 return AdditionResult.Success;
212 public AdditionResult AddDelegate (Delegate d)
216 if ((res = IsValid (d.Basename)) != AdditionResult.Success)
219 if (delegates == null)
220 delegates = new ArrayList ();
222 DefineName (d.Name, d);
225 return AdditionResult.Success;
228 public AdditionResult AddMethod (Method method)
230 string basename = method.Name;
231 string fullname = Name + "." + basename;
233 Object value = defined_names [fullname];
235 if (value != null && (!(value is Method)))
236 return AdditionResult.NameExists;
238 if (basename == Basename)
239 return AdditionResult.EnclosingClash;
242 methods = new ArrayList ();
244 if (method.Name.IndexOf (".") != -1)
245 methods.Insert (0, method);
247 methods.Add (method);
250 DefineName (fullname, method);
252 return AdditionResult.Success;
255 public AdditionResult AddConstructor (Constructor c)
257 if (c.Name != Basename)
258 return AdditionResult.NotAConstructor;
260 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
263 have_static_constructor = true;
264 if (default_static_constructor != null){
265 Console.WriteLine ("I have a static constructor already");
266 Console.WriteLine (" " + default_static_constructor);
267 return AdditionResult.MethodExists;
270 default_static_constructor = c;
273 if (default_constructor != null)
274 return AdditionResult.MethodExists;
275 default_constructor = c;
278 if (instance_constructors == null)
279 instance_constructors = new ArrayList ();
281 instance_constructors.Add (c);
284 return AdditionResult.Success;
287 public AdditionResult AddInterface (Interface iface)
291 if ((res = IsValid (iface.Basename)) != AdditionResult.Success)
294 if (interfaces == null)
295 interfaces = new ArrayList ();
296 interfaces.Add (iface);
297 DefineName (iface.Name, iface);
299 return AdditionResult.Success;
302 public AdditionResult AddField (Field field)
305 string basename = field.Name;
307 if ((res = IsValid (basename)) != AdditionResult.Success)
311 fields = new ArrayList ();
315 if (field.HasInitializer){
316 if ((field.ModFlags & Modifiers.STATIC) != 0){
317 if (initialized_static_fields == null)
318 initialized_static_fields = new ArrayList ();
320 initialized_static_fields.Add (field);
323 // We have not seen a static constructor,
324 // but we will provide static initialization of fields
326 have_static_constructor = true;
328 if (initialized_fields == null)
329 initialized_fields = new ArrayList ();
331 initialized_fields.Add (field);
335 if ((field.ModFlags & Modifiers.STATIC) == 0)
336 have_nonstatic_fields = true;
338 DefineName (Name + "." + basename, field);
339 return AdditionResult.Success;
342 public AdditionResult AddProperty (Property prop)
345 string basename = prop.Name;
347 if ((res = IsValid (basename)) != AdditionResult.Success)
350 if (properties == null)
351 properties = new ArrayList ();
353 if (prop.Name.IndexOf (".") != -1)
354 properties.Insert (0, prop);
356 properties.Add (prop);
357 DefineName (Name + "." + basename, prop);
359 return AdditionResult.Success;
362 public AdditionResult AddEvent (Event e)
365 string basename = e.Name;
367 if ((res = IsValid (basename)) != AdditionResult.Success)
371 events = new ArrayList ();
374 DefineName (Name + "." + basename, e);
376 return AdditionResult.Success;
379 public AdditionResult AddIndexer (Indexer i)
381 if (indexers == null)
382 indexers = new ArrayList ();
384 if (i.InterfaceType != null)
385 indexers.Insert (0, i);
389 return AdditionResult.Success;
392 public AdditionResult AddOperator (Operator op)
394 if (operators == null)
395 operators = new ArrayList ();
399 return AdditionResult.Success;
402 public void RegisterOrder (Interface iface)
404 if (interface_order == null)
405 interface_order = new ArrayList ();
407 interface_order.Add (iface);
410 public ArrayList Types {
416 public ArrayList Methods {
422 public ArrayList Constants {
428 public ArrayList Interfaces {
436 return base_class_name;
440 public ArrayList Bases {
450 public ArrayList Fields {
460 public ArrayList InstanceConstructors {
462 return instance_constructors;
466 public ArrayList Properties {
472 public ArrayList Events {
478 public ArrayList Enums {
484 public ArrayList Indexers {
490 public ArrayList Operators {
496 public ArrayList Delegates {
502 public Attributes OptAttributes {
508 public bool HaveStaticConstructor {
510 return have_static_constructor;
514 public virtual TypeAttributes TypeAttr {
516 return Modifiers.TypeAttr (ModFlags, this);
521 // Emits the instance field initializers
523 public bool EmitFieldInitializers (EmitContext ec)
526 ILGenerator ig = ec.ig;
527 Expression instance_expr;
530 fields = initialized_static_fields;
531 instance_expr = null;
533 fields = initialized_fields;
534 instance_expr = new This (Location.Null).Resolve (ec);
540 foreach (Field f in fields){
541 Expression e = f.GetInitializerExpression (ec);
545 Location l = f.Location;
546 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
547 fe.InstanceExpression = instance_expr;
548 Expression a = new Assign (fe, e, l);
554 if (a is ExpressionStatement)
555 ((ExpressionStatement) a).EmitStatement (ec);
557 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
565 // Defines the default constructors
567 void DefineDefaultConstructor (bool is_static)
572 c = new Constructor (Basename, Parameters.EmptyReadOnlyParameters,
573 new ConstructorBaseInitializer (
574 null, Parameters.EmptyReadOnlyParameters,
579 mods = Modifiers.STATIC;
585 c.Block = new Block (null);
589 public void ReportStructInitializedInstanceError ()
591 string n = TypeBuilder.FullName;
593 foreach (Field f in initialized_fields){
596 "`" + n + "." + f.Name + "': can not have " +
597 "instance field initializers in structs");
602 /// The pending methods that need to be implemented (interfaces or abstract methods)
604 public PendingImplementation Pending;
607 /// This function computes the Base class and also the
608 /// list of interfaces that the class or struct @c implements.
610 /// The return value is an array (might be null) of
611 /// interfaces implemented (as Types).
613 /// The @parent argument is set to the parent object or null
614 /// if this is `System.Object'.
616 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
618 ArrayList bases = Bases;
627 parent = TypeManager.value_type;
631 if (RootContext.StdLib)
632 parent = TypeManager.object_type;
633 else if (Name != "System.Object")
634 parent = TypeManager.object_type;
637 // If we are compiling our runtime,
638 // and we are defining ValueType, then our
639 // parent is `System.Object'.
641 if (!RootContext.StdLib && Name == "System.ValueType")
642 parent = TypeManager.object_type;
649 // Bases should be null if there are no bases at all
654 Expression name = (Expression) bases [0];
655 name = ResolveTypeExpr (name, false, Location);
662 Type first = name.Type;
668 parent = TypeManager.object_type;
672 if (!AsAccessible (parent, ModFlags))
673 Report.Error (60, Location,
674 "Inconsistent accessibility: base class `" +
675 TypeManager.CSharpName (parent) + "' is less " +
676 "accessible than class `" +
683 Type [] ifaces = new Type [count-start];
685 for (i = start, j = 0; i < count; i++, j++){
686 Expression name = (Expression) bases [i];
687 Expression resolved = ResolveTypeExpr (name, false, Location);
688 if (resolved == null)
691 bases [i] = resolved;
692 Type t = resolved.Type;
699 if (is_class == false && !t.IsInterface){
700 Report.Error (527, "In Struct `" + Name + "', type `"+
701 name +"' is not an interface");
710 detail = " (a class can not inherit from a struct/enum)";
712 Report.Error (509, "class `"+ Name +
713 "': Cannot inherit from sealed class `"+
714 bases [i]+"'"+detail);
721 Report.Error (527, "In Class `" + Name + "', type `"+
722 name+"' is not an interface");
728 for (int x = 0; x < j; x++) {
729 if (t == ifaces [x]) {
730 Report.Error (528, "`" + name + "' is already listed in interface list");
739 return TypeManager.ExpandInterfaces (ifaces);
743 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
745 public override TypeBuilder DefineType ()
751 if (TypeBuilder != null)
764 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
766 ifaces = GetClassBases (is_class, out parent, out error);
771 if (is_class && parent != null){
772 if (parent == TypeManager.enum_type ||
773 (parent == TypeManager.value_type && RootContext.StdLib) ||
774 parent == TypeManager.delegate_type ||
775 parent == TypeManager.array_type){
777 644, Location, "`" + Name + "' cannot inherit from " +
778 "special class `" + TypeManager.CSharpName (parent) + "'");
783 if (!is_class && TypeManager.value_type == null)
784 throw new Exception ();
786 TypeAttributes type_attributes = TypeAttr;
788 // if (parent_builder is ModuleBuilder) {
790 ModuleBuilder builder = CodeGen.ModuleBuilder;
791 TypeBuilder = builder.DefineType (
792 Name, type_attributes, parent, ifaces);
795 TypeBuilder builder = Parent.TypeBuilder;
796 TypeBuilder = builder.DefineNestedType (
797 Basename, type_attributes, parent, ifaces);
801 // Structs with no fields need to have at least one byte.
802 // The right thing would be to set the PackingSize in a DefineType
803 // but there are no functions that allow interfaces *and* the size to
807 if (!is_class && !have_nonstatic_fields){
808 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
809 FieldAttributes.Private);
810 // add interfaces that were not added at type creation
811 if (ifaces != null) {
812 foreach (Type i in ifaces)
813 TypeBuilder.AddInterfaceImplementation (i);
818 // Finish the setup for the EmitContext
820 ec.ContainerType = TypeBuilder;
822 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
824 if ((parent != null) &&
825 (parent == TypeManager.attribute_type ||
826 parent.IsSubclassOf (TypeManager.attribute_type))) {
827 RootContext.RegisterAttribute (this);
828 TypeManager.RegisterAttrType (TypeBuilder, this);
830 RootContext.RegisterOrder (this);
832 if (Interfaces != null) {
833 foreach (Interface iface in Interfaces)
838 foreach (TypeContainer tc in Types)
842 if (Delegates != null) {
843 foreach (Delegate d in Delegates)
848 foreach (Enum en in Enums)
858 /// Defines the MemberCore objects that are in the `list' Arraylist
860 /// The `defined_names' array contains a list of members defined in
863 static ArrayList remove_list = new ArrayList ();
864 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
868 remove_list.Clear ();
870 foreach (MemberCore mc in list){
871 if (!mc.Define (this)){
872 remove_list.Add (mc);
876 if (defined_names == null)
879 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
881 if (RootContext.WarningLevel >= 4){
882 if ((mc.ModFlags & Modifiers.NEW) != 0)
883 Warning_KewywordNewNotRequired (mc.Location, mc);
888 MemberInfo match = defined_names [idx];
890 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
894 // If we are both methods, let the method resolution emit warnings
896 if (match is MethodBase && mc is MethodCore)
899 if ((mc.ModFlags & Modifiers.NEW) == 0)
900 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
903 foreach (object o in remove_list)
906 remove_list.Clear ();
910 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
911 // class is consisten. Either it is `Item' or it is the name defined by all the
912 // indexers with the `IndexerName' attribute.
914 // Turns out that the IndexerNameAttribute is applied to each indexer,
915 // but it is never emitted, instead a DefaultName attribute is attached
918 void DefineIndexers ()
920 string class_indexer_name = null;
922 foreach (Indexer i in Indexers){
927 name = i.IndexerName;
929 if (i.InterfaceType != null)
932 if (class_indexer_name == null){
933 class_indexer_name = name;
937 if (name == class_indexer_name)
941 668, "Two indexers have different names, " +
942 " you should use the same name for all your indexers");
944 if (class_indexer_name == null)
945 class_indexer_name = "Item";
946 IndexerName = class_indexer_name;
949 static void Error_KeywordNotAllowed (Location loc)
951 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
955 /// Populates our TypeBuilder with fields and methods
957 public override bool DefineMembers (TypeContainer parent)
959 MemberInfo [] defined_names = null;
961 if (interface_order != null){
962 foreach (Interface iface in interface_order)
963 if ((iface.ModFlags & Modifiers.NEW) == 0)
964 iface.DefineMembers (this);
966 Error_KeywordNotAllowed (iface.Location);
969 if (RootContext.WarningLevel > 1){
973 // This code throws an exception in the comparer
974 // I guess the string is not an object?
976 ptype = TypeBuilder.BaseType;
978 defined_names = (MemberInfo []) FindMembers (
979 ptype, MemberTypes.All & ~MemberTypes.Constructor,
980 BindingFlags.Public | BindingFlags.Instance |
981 BindingFlags.Static, null, null);
983 Array.Sort (defined_names, mif_compare);
987 if (constants != null)
988 DefineMembers (constants, defined_names);
991 DefineMembers (fields, defined_names);
994 if (instance_constructors == null){
995 if (default_constructor == null)
996 DefineDefaultConstructor (false);
999 if (initialized_static_fields != null &&
1000 default_static_constructor == null)
1001 DefineDefaultConstructor (true);
1004 if (this is Struct){
1006 // Structs can not have initialized instance
1009 if (initialized_static_fields != null &&
1010 default_static_constructor == null)
1011 DefineDefaultConstructor (true);
1013 if (initialized_fields != null)
1014 ReportStructInitializedInstanceError ();
1017 Pending = PendingImplementation.GetPendingImplementations (this);
1020 // Constructors are not in the defined_names array
1022 if (instance_constructors != null)
1023 DefineMembers (instance_constructors, null);
1025 if (default_static_constructor != null)
1026 default_static_constructor.Define (this);
1028 if (methods != null)
1029 DefineMembers (methods, defined_names);
1031 if (properties != null)
1032 DefineMembers (properties, defined_names);
1035 DefineMembers (events, defined_names);
1037 if (indexers != null) {
1040 IndexerName = "Item";
1042 if (operators != null){
1043 DefineMembers (operators, null);
1045 CheckPairedOperators ();
1049 DefineMembers (enums, defined_names);
1051 if (delegates != null)
1052 DefineMembers (delegates, defined_names);
1055 if (TypeBuilder.BaseType != null)
1056 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1058 member_cache = new MemberCache (this);
1064 public override bool Define (TypeContainer parent)
1066 if (interface_order != null){
1067 foreach (Interface iface in interface_order)
1068 if ((iface.ModFlags & Modifiers.NEW) == 0)
1069 iface.Define (this);
1076 /// This function is based by a delegate to the FindMembers routine
1078 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1084 /// This filter is used by FindMembers, and we just keep
1085 /// a global for the filter to `AlwaysAccept'
1087 static MemberFilter accepting_filter;
1091 /// A member comparission method based on name only
1093 static IComparer mif_compare;
1095 static TypeContainer ()
1097 accepting_filter = new MemberFilter (AlwaysAccept);
1098 mif_compare = new MemberInfoCompare ();
1102 /// This method returns the members of this type just like Type.FindMembers would
1103 /// Only, we need to use this for types which are _being_ defined because MS'
1104 /// implementation can't take care of that.
1107 // FIXME: return an empty static array instead of null, that cleans up
1108 // some code and is consistent with some coding conventions I just found
1112 // Notice that in various cases we check if our field is non-null,
1113 // something that would normally mean that there was a bug elsewhere.
1115 // The problem happens while we are defining p-invoke methods, as those
1116 // will trigger a FindMembers, but this happens before things are defined
1118 // Since the whole process is a no-op, it is fine to check for null here.
1120 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1121 MemberFilter filter, object criteria)
1123 ArrayList members = new ArrayList ();
1126 if ((bf & BindingFlags.Public) != 0)
1127 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1129 if ((bf & BindingFlags.NonPublic) != 0)
1130 modflags |= Modifiers.PRIVATE;
1132 int static_mask = 0, static_flags = 0;
1133 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1134 case BindingFlags.Static:
1135 static_mask = static_flags = Modifiers.STATIC;
1138 case BindingFlags.Instance:
1139 static_mask = Modifiers.STATIC;
1144 static_mask = static_flags = 0;
1148 Timer.StartTimer (TimerType.TcFindMembers);
1151 filter = accepting_filter;
1153 if ((mt & MemberTypes.Field) != 0) {
1154 if (fields != null) {
1155 foreach (Field f in fields) {
1156 if ((f.ModFlags & modflags) == 0)
1158 if ((f.ModFlags & static_mask) != static_flags)
1161 FieldBuilder fb = f.FieldBuilder;
1162 if (fb != null && filter (fb, criteria) == true)
1167 if (constants != null) {
1168 foreach (Const con in constants) {
1169 if ((con.ModFlags & modflags) == 0)
1171 if ((con.ModFlags & static_mask) != static_flags)
1174 FieldBuilder fb = con.FieldBuilder;
1175 if (fb != null && filter (fb, criteria) == true)
1181 if ((mt & MemberTypes.Method) != 0) {
1182 if (methods != null) {
1183 foreach (Method m in methods) {
1184 if ((m.ModFlags & modflags) == 0)
1186 if ((m.ModFlags & static_mask) != static_flags)
1189 MethodBuilder mb = m.MethodBuilder;
1191 if (mb != null && filter (mb, criteria) == true)
1196 if (operators != null){
1197 foreach (Operator o in operators) {
1198 if ((o.ModFlags & modflags) == 0)
1200 if ((o.ModFlags & static_mask) != static_flags)
1203 MethodBuilder ob = o.OperatorMethodBuilder;
1204 if (ob != null && filter (ob, criteria) == true)
1209 if (properties != null){
1210 foreach (Property p in properties){
1211 if ((p.ModFlags & modflags) == 0)
1213 if ((p.ModFlags & static_mask) != static_flags)
1219 if (b != null && filter (b, criteria) == true)
1223 if (b != null && filter (b, criteria) == true)
1228 if (indexers != null){
1229 foreach (Indexer ix in indexers){
1230 if ((ix.ModFlags & modflags) == 0)
1232 if ((ix.ModFlags & static_mask) != static_flags)
1238 if (b != null && filter (b, criteria) == true)
1242 if (b != null && filter (b, criteria) == true)
1248 if ((mt & MemberTypes.Event) != 0) {
1250 foreach (Event e in events) {
1251 if ((e.ModFlags & modflags) == 0)
1253 if ((e.ModFlags & static_mask) != static_flags)
1256 MemberInfo eb = e.EventBuilder;
1257 if (eb != null && filter (eb, criteria) == true)
1258 members.Add (e.EventBuilder);
1262 if ((mt & MemberTypes.Property) != 0){
1263 if (properties != null)
1264 foreach (Property p in properties) {
1265 if ((p.ModFlags & modflags) == 0)
1267 if ((p.ModFlags & static_mask) != static_flags)
1270 MemberInfo pb = p.PropertyBuilder;
1271 if (pb != null && filter (pb, criteria) == true) {
1272 members.Add (p.PropertyBuilder);
1276 if (indexers != null)
1277 foreach (Indexer ix in indexers) {
1278 if ((ix.ModFlags & modflags) == 0)
1280 if ((ix.ModFlags & static_mask) != static_flags)
1283 MemberInfo ib = ix.PropertyBuilder;
1284 if (ib != null && filter (ib, criteria) == true) {
1285 members.Add (ix.PropertyBuilder);
1290 if ((mt & MemberTypes.NestedType) != 0) {
1292 foreach (TypeContainer t in types) {
1293 if ((t.ModFlags & modflags) == 0)
1296 TypeBuilder tb = t.TypeBuilder;
1297 if (tb != null && (filter (tb, criteria) == true))
1303 foreach (Enum en in enums){
1304 if ((en.ModFlags & modflags) == 0)
1307 TypeBuilder tb = en.TypeBuilder;
1308 if (tb != null && (filter (tb, criteria) == true))
1313 if (delegates != null){
1314 foreach (Delegate d in delegates){
1315 if ((d.ModFlags & modflags) == 0)
1318 TypeBuilder tb = d.TypeBuilder;
1319 if (tb != null && (filter (tb, criteria) == true))
1324 if (interfaces != null){
1325 foreach (Interface iface in interfaces){
1326 if ((iface.ModFlags & modflags) == 0)
1329 TypeBuilder tb = iface.TypeBuilder;
1330 if (tb != null && (filter (tb, criteria) == true))
1336 if ((mt & MemberTypes.Constructor) != 0){
1337 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1338 foreach (Constructor c in instance_constructors){
1339 ConstructorBuilder cb = c.ConstructorBuilder;
1341 if (filter (cb, criteria) == true)
1346 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1347 ConstructorBuilder cb =
1348 default_static_constructor.ConstructorBuilder;
1351 if (filter (cb, criteria) == true)
1357 // Lookup members in parent if requested.
1359 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1360 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1361 members.AddRange (list);
1364 Timer.StopTimer (TimerType.TcFindMembers);
1366 return new MemberList (members);
1369 public override MemberCache MemberCache {
1371 return member_cache;
1375 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1376 MemberFilter filter, object criteria)
1378 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1381 return tc.FindMembers (mt, bf, filter, criteria);
1383 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1387 // FindMethods will look for methods not only in the type `t', but in
1388 // any interfaces implemented by the type.
1390 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1391 MemberFilter filter, object criteria)
1397 /// Emits the values for the constants
1399 public void EmitConstants ()
1401 if (constants != null)
1402 foreach (Const con in constants)
1403 con.EmitConstant (this);
1408 /// Emits the code, this step is performed after all
1409 /// the types, enumerations, constructors
1413 if (instance_constructors != null)
1414 foreach (Constructor c in instance_constructors)
1417 if (default_static_constructor != null)
1418 default_static_constructor.Emit (this);
1420 if (methods != null)
1421 foreach (Method m in methods)
1424 if (operators != null)
1425 foreach (Operator o in operators)
1428 if (properties != null)
1429 foreach (Property p in properties)
1432 if (indexers != null){
1433 foreach (Indexer ix in indexers)
1436 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1437 this, IndexerName, ModFlags, Location);
1438 TypeBuilder.SetCustomAttribute (cb);
1442 foreach (Field f in fields)
1445 if (events != null){
1446 foreach (Event e in Events)
1450 if (Pending != null)
1451 if (Pending.VerifyPendingMethods ())
1454 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
1457 // Check for internal or private fields that were never assigned
1459 if (RootContext.WarningLevel >= 3) {
1460 if (fields != null){
1461 foreach (Field f in fields) {
1462 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1467 169, f.Location, "Private field " +
1468 MakeName (f.Name) + " is never used");
1473 // Only report 649 on level 4
1475 if (RootContext.WarningLevel < 4)
1478 if ((f.status & Field.Status.ASSIGNED) != 0)
1483 "Field " + MakeName (f.Name) + " is never assigned " +
1484 " to and will always have its default value");
1488 if (events != null){
1489 foreach (Event e in events){
1491 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1496 // if (types != null)
1497 // foreach (TypeContainer tc in types)
1501 public override void CloseType ()
1506 TypeBuilder.CreateType ();
1508 } catch (TypeLoadException){
1510 // This is fine, the code still created the type
1512 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1513 // Console.WriteLine (e.Message);
1515 Console.WriteLine ("In type: " + Name);
1520 foreach (Enum en in Enums)
1523 if (interface_order != null){
1524 foreach (Interface iface in interface_order)
1529 foreach (TypeContainer tc in Types)
1533 foreach (TypeContainer tc in Types)
1534 if (!(tc is Struct))
1538 if (Delegates != null)
1539 foreach (Delegate d in Delegates)
1543 public string MakeName (string n)
1545 return "`" + Name + "." + n + "'";
1548 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1551 108, l, "The keyword new is required on " +
1552 MakeName (mi.Name) + " because it hides `" +
1553 mi.ReflectedType.Name + "." + mi.Name + "'");
1556 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1559 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1560 "inherited member, the keyword new is not required");
1563 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1569 // Performs the validation on a Method's modifiers (properties have
1570 // the same properties).
1572 public bool MethodModifiersValid (int flags, string n, Location loc)
1574 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1575 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1576 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1580 // At most one of static, virtual or override
1582 if ((flags & Modifiers.STATIC) != 0){
1583 if ((flags & vao) != 0){
1585 112, loc, "static method " + MakeName (n) + "can not be marked " +
1586 "as virtual, abstract or override");
1591 if (this is Struct){
1592 if ((flags & va) != 0){
1593 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1598 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1600 113, loc, MakeName (n) +
1601 " marked as override cannot be marked as new or virtual");
1606 // If the declaration includes the abstract modifier, then the
1607 // declaration does not include static, virtual or extern
1609 if ((flags & Modifiers.ABSTRACT) != 0){
1610 if ((flags & Modifiers.EXTERN) != 0){
1612 180, loc, MakeName (n) + " can not be both abstract and extern");
1616 if ((flags & Modifiers.VIRTUAL) != 0){
1618 503, loc, MakeName (n) + " can not be both abstract and virtual");
1622 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1624 513, loc, MakeName (n) +
1625 " is abstract but its container class is not");
1631 if ((flags & Modifiers.PRIVATE) != 0){
1632 if ((flags & vao) != 0){
1634 621, loc, MakeName (n) +
1635 " virtual or abstract members can not be private");
1640 if ((flags & Modifiers.SEALED) != 0){
1641 if ((flags & Modifiers.OVERRIDE) == 0){
1643 238, loc, MakeName (n) +
1644 " cannot be sealed because it is not an override");
1652 // Access level of a type.
1655 ProtectedInternal = 1,
1661 // Check whether `flags' denotes a more restricted access than `level'
1662 // and return the new level.
1663 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1665 AccessLevel old_level = level;
1667 if ((flags & Modifiers.INTERNAL) != 0) {
1668 if ((flags & Modifiers.PROTECTED) != 0) {
1669 if ((int) level < (int) AccessLevel.ProtectedInternal)
1670 level = AccessLevel.ProtectedInternal;
1672 if ((int) level < (int) AccessLevel.Internal)
1673 level = AccessLevel.Internal;
1675 } else if ((flags & Modifiers.PROTECTED) != 0) {
1676 if ((int) level < (int) AccessLevel.Protected)
1677 level = AccessLevel.Protected;
1678 } else if ((flags & Modifiers.PRIVATE) != 0)
1679 level = AccessLevel.Private;
1684 // Return the access level for a new member which is defined in the current
1685 // TypeContainer with access modifiers `flags'.
1686 AccessLevel GetAccessLevel (int flags)
1688 if ((flags & Modifiers.PRIVATE) != 0)
1689 return AccessLevel.Private;
1692 if (!IsTopLevel && (Parent != null))
1693 level = Parent.GetAccessLevel (flags);
1695 level = AccessLevel.Public;
1697 return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1700 // Return the access level for type `t', but don't give more access than `flags'.
1701 static AccessLevel GetAccessLevel (Type t, int flags)
1703 if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1704 return AccessLevel.Private;
1707 if (TypeManager.IsBuiltinType (t))
1708 return AccessLevel.Public;
1709 else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1710 level = GetAccessLevel (t.DeclaringType, flags);
1712 level = CheckAccessLevel (AccessLevel.Public, flags);
1715 if (t.IsNestedPublic)
1718 if (t.IsNestedAssembly || t.IsNotPublic) {
1719 if ((int) level < (int) AccessLevel.Internal)
1720 level = AccessLevel.Internal;
1723 if (t.IsNestedFamily) {
1724 if ((int) level < (int) AccessLevel.Protected)
1725 level = AccessLevel.Protected;
1728 if (t.IsNestedFamORAssem) {
1729 if ((int) level < (int) AccessLevel.ProtectedInternal)
1730 level = AccessLevel.ProtectedInternal;
1737 // Returns true if `parent' is as accessible as the flags `flags'
1738 // given for this member.
1740 public bool AsAccessible (Type parent, int flags)
1742 while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1743 parent = parent.GetElementType ();
1745 AccessLevel level = GetAccessLevel (flags);
1746 AccessLevel level2 = GetAccessLevel (parent, flags);
1748 return (int) level >= (int) level2;
1751 Hashtable builder_and_args;
1753 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1755 if (builder_and_args == null)
1756 builder_and_args = new Hashtable ();
1761 /// Performs checks for an explicit interface implementation. First it
1762 /// checks whether the `interface_type' is a base inteface implementation.
1763 /// Then it checks whether `name' exists in the interface type.
1765 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1769 if (ifaces != null){
1770 foreach (Type t in ifaces){
1771 if (t == interface_type){
1779 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1786 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1788 Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1795 string IMemberContainer.Name {
1801 Type IMemberContainer.Type {
1807 IMemberContainer IMemberContainer.Parent {
1809 return parent_container;
1813 MemberCache IMemberContainer.MemberCache {
1815 return member_cache;
1819 bool IMemberContainer.IsInterface {
1825 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1827 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1831 // Operator pair checking
1834 class OperatorEntry {
1836 public Type ret_type;
1837 public Type type1, type2;
1839 public Operator.OpType ot;
1841 public OperatorEntry (int f, Operator o)
1845 ret_type = o.OperatorMethod.GetReturnType ();
1846 Type [] pt = o.OperatorMethod.ParameterTypes;
1850 ot = o.OperatorType;
1853 public override int GetHashCode ()
1855 return ret_type.GetHashCode ();
1858 public override bool Equals (object o)
1860 OperatorEntry other = (OperatorEntry) o;
1862 if (other.ret_type != ret_type)
1864 if (other.type1 != type1)
1866 if (other.type2 != type2)
1873 // Checks that some operators come in pairs:
1879 // They are matched based on the return type and the argument types
1881 void CheckPairedOperators ()
1883 Hashtable pairs = new Hashtable (null, null);
1884 Operator true_op = null;
1885 Operator false_op = null;
1887 // Register all the operators we care about.
1888 foreach (Operator op in operators){
1891 switch (op.OperatorType){
1892 case Operator.OpType.Equality:
1894 case Operator.OpType.Inequality:
1897 case Operator.OpType.True:
1900 case Operator.OpType.False:
1904 case Operator.OpType.GreaterThan:
1906 case Operator.OpType.LessThan:
1909 case Operator.OpType.GreaterThanOrEqual:
1911 case Operator.OpType.LessThanOrEqual:
1917 OperatorEntry oe = new OperatorEntry (reg, op);
1919 object o = pairs [oe];
1923 oe = (OperatorEntry) o;
1928 if (true_op != null){
1929 if (false_op == null)
1930 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
1931 } else if (false_op != null)
1932 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
1935 // Look for the mistakes.
1937 foreach (DictionaryEntry de in pairs){
1938 OperatorEntry oe = (OperatorEntry) de.Key;
1945 case Operator.OpType.Equality:
1948 case Operator.OpType.Inequality:
1951 case Operator.OpType.GreaterThan:
1954 case Operator.OpType.LessThan:
1957 case Operator.OpType.GreaterThanOrEqual:
1960 case Operator.OpType.LessThanOrEqual:
1964 Report.Error (216, oe.op.Location,
1965 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
1972 public class Class : TypeContainer {
1974 // Modifiers allowed in a class declaration
1976 public const int AllowedModifiers =
1979 Modifiers.PROTECTED |
1980 Modifiers.INTERNAL |
1982 Modifiers.ABSTRACT |
1986 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1987 : base (parent, name, l)
1991 if (parent.Parent == null)
1992 accmods = Modifiers.INTERNAL;
1994 accmods = Modifiers.PRIVATE;
1996 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1997 this.attributes = attrs;
2001 // FIXME: How do we deal with the user specifying a different
2004 public override TypeAttributes TypeAttr {
2006 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2011 public class Struct : TypeContainer {
2013 // Modifiers allowed in a struct declaration
2015 public const int AllowedModifiers =
2018 Modifiers.PROTECTED |
2019 Modifiers.INTERNAL |
2023 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2024 : base (parent, name, l)
2028 if (parent.Parent == null)
2029 accmods = Modifiers.INTERNAL;
2031 accmods = Modifiers.PRIVATE;
2033 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2035 this.ModFlags |= Modifiers.SEALED;
2036 this.attributes = attrs;
2041 // FIXME: Allow the user to specify a different set of attributes
2042 // in some cases (Sealed for example is mandatory for a class,
2043 // but what SequentialLayout can be changed
2045 public override TypeAttributes TypeAttr {
2047 return base.TypeAttr |
2048 TypeAttributes.SequentialLayout |
2049 TypeAttributes.Sealed |
2050 TypeAttributes.BeforeFieldInit;
2055 public abstract class MethodCore : MemberBase {
2056 public readonly Parameters Parameters;
2057 protected Block block;
2060 // Parameters, cached for semantic analysis.
2062 protected InternalParameters parameter_info;
2063 protected Type [] parameter_types;
2065 public MethodCore (Expression type, int mod, int allowed_mod, string name,
2066 Attributes attrs, Parameters parameters, Location loc)
2067 : base (type, mod, allowed_mod, name, attrs, loc)
2069 Parameters = parameters;
2073 // Returns the System.Type array for the parameters of this method
2075 public Type [] ParameterTypes {
2077 return parameter_types;
2081 public InternalParameters ParameterInfo
2084 return parameter_info;
2088 public Block Block {
2098 protected virtual bool DoDefineParameters (TypeContainer parent)
2100 // Check if arguments were correct
2101 parameter_types = Parameters.GetParameterInfo (parent);
2102 if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
2105 parameter_info = new InternalParameters (parent, Parameters);
2110 public CallingConventions GetCallingConvention (bool is_class)
2112 CallingConventions cc = 0;
2114 cc = Parameters.GetCallingConvention ();
2117 if ((ModFlags & Modifiers.STATIC) == 0)
2118 cc |= CallingConventions.HasThis;
2120 // FIXME: How is `ExplicitThis' used in C#?
2126 // The method's attributes are passed in because we need to extract
2127 // the "return:" attribute from there to apply on the return type
2129 public void LabelParameters (EmitContext ec, MethodBase builder, Attributes method_attrs)
2132 // Define each type attribute (in/out/ref) and
2133 // the argument names.
2135 Parameter [] p = Parameters.FixedParameters;
2138 MethodBuilder mb = null;
2139 ConstructorBuilder cb = null;
2141 if (builder is MethodBuilder)
2142 mb = (MethodBuilder) builder;
2144 cb = (ConstructorBuilder) builder;
2147 for (i = 0; i < p.Length; i++) {
2148 ParameterBuilder pb;
2149 ParameterAttributes par_attr = p [i].Attributes;
2152 pb = cb.DefineParameter (
2153 i + 1, par_attr, p [i].Name);
2155 pb = mb.DefineParameter (
2156 i + 1, par_attr, p [i].Name);
2158 Attributes attr = p [i].OptAttributes;
2160 Attribute.ApplyAttributes (ec, pb, pb, attr);
2162 if (par_attr == ParameterAttributes.Out){
2163 if (attr.Contains (TypeManager.in_attribute_type))
2164 Report.Error (36, Location, "Can not use [In] attribute on out parameter");
2170 if (Parameters.ArrayParameter != null){
2171 ParameterBuilder pb;
2172 Parameter array_param = Parameters.ArrayParameter;
2175 pb = cb.DefineParameter (
2176 i + 1, array_param.Attributes,
2179 pb = mb.DefineParameter (
2180 i + 1, array_param.Attributes,
2183 CustomAttributeBuilder a = new CustomAttributeBuilder (
2184 TypeManager.cons_param_array_attribute, new object [0]);
2186 pb.SetCustomAttribute (a);
2190 // And now for the return type attribute decoration
2192 ParameterBuilder ret_pb;
2193 Attributes ret_attrs = null;
2195 if (mb == null || method_attrs == null)
2198 foreach (AttributeSection asec in method_attrs.AttributeSections) {
2200 if (asec.Target != "return")
2203 if (ret_attrs == null)
2204 ret_attrs = new Attributes (asec);
2206 ret_attrs.AddAttributeSection (asec);
2209 if (ret_attrs != null) {
2211 ret_pb = mb.DefineParameter (0, ParameterAttributes.None, "");
2212 Attribute.ApplyAttributes (ec, ret_pb, ret_pb, ret_attrs);
2213 } catch (ArgumentOutOfRangeException) {
2216 ".NET SDK 1.0 does not permit to set custom attributes to the return type of a method");
2222 public class Method : MethodCore {
2223 public MethodBuilder MethodBuilder;
2224 public MethodData MethodData;
2227 /// Modifiers allowed in a class declaration
2229 const int AllowedModifiers =
2232 Modifiers.PROTECTED |
2233 Modifiers.INTERNAL |
2238 Modifiers.OVERRIDE |
2239 Modifiers.ABSTRACT |
2244 // return_type can be "null" for VOID values.
2246 public Method (Expression return_type, int mod, string name, Parameters parameters,
2247 Attributes attrs, Location l)
2248 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2252 // Returns the `System.Type' for the ReturnType of this
2253 // function. Provides a nice cache. (used between semantic analysis
2254 // and actual code generation
2256 public Type GetReturnType ()
2261 // Whether this is an operator method.
2262 public bool IsOperator;
2264 void DuplicateEntryPoint (MethodInfo b, Location location)
2268 "Program `" + CodeGen.FileName +
2269 "' has more than one entry point defined: `" +
2270 TypeManager.CSharpSignature(b) + "'");
2273 void Report28 (MethodInfo b)
2275 if (RootContext.WarningLevel < 4)
2280 "`" + TypeManager.CSharpSignature(b) +
2281 "' has the wrong signature to be an entry point");
2284 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2286 if (b.ReturnType != TypeManager.void_type &&
2287 b.ReturnType != TypeManager.int32_type)
2290 if (pinfo.Count == 0)
2293 if (pinfo.Count > 1)
2296 Type t = pinfo.ParameterType(0);
2298 (t.GetArrayRank() == 1) &&
2299 (t.GetElementType() == TypeManager.string_type) &&
2300 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2307 // Checks our base implementation if any
2309 protected override bool CheckBase (TypeContainer parent)
2311 // Check whether arguments were correct.
2312 if (!DoDefineParameters (parent))
2315 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2317 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2321 mi_this = TypeContainer.FindMembers (
2322 parent.TypeBuilder, MemberTypes.Method,
2323 BindingFlags.NonPublic | BindingFlags.Public |
2324 BindingFlags.Static | BindingFlags.Instance |
2325 BindingFlags.DeclaredOnly,
2326 MethodSignature.method_signature_filter, ms);
2328 if (mi_this.Count > 0) {
2329 Report.Error (111, Location, "Class `" + parent.Name + "' " +
2330 "already defines a member called `" + Name + "' " +
2331 "with the same parameter types");
2337 // Verify if the parent has a type with the same name, and then
2338 // check whether we have to create a new slot for it or not.
2340 Type ptype = parent.TypeBuilder.BaseType;
2342 // ptype is only null for System.Object while compiling corlib.
2344 MemberList mi, mi_static, mi_instance;
2346 mi_static = TypeContainer.FindMembers (
2347 ptype, MemberTypes.Method,
2348 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2349 MethodSignature.inheritable_method_signature_filter, ms);
2351 mi_instance = TypeContainer.FindMembers (
2352 ptype, MemberTypes.Method,
2353 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2354 MethodSignature.inheritable_method_signature_filter,
2357 if (mi_instance.Count > 0){
2359 } else if (mi_static.Count > 0)
2364 if (mi != null && mi.Count > 0){
2365 parent_method = (MethodInfo) mi [0];
2366 string name = parent_method.DeclaringType.Name + "." +
2369 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2372 if ((ModFlags & Modifiers.NEW) == 0) {
2373 Type parent_ret = TypeManager.TypeToCoreType (
2374 parent_method.ReturnType);
2376 if (parent_ret != MemberType) {
2378 508, Location, parent.MakeName (Name) + ": cannot " +
2379 "change return type when overriding " +
2380 "inherited member " + name);
2385 if ((ModFlags & Modifiers.NEW) != 0)
2386 WarningNotHiding (parent);
2388 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2389 Report.Error (115, Location,
2390 parent.MakeName (Name) +
2391 " no suitable methods found to override");
2394 } else if ((ModFlags & Modifiers.NEW) != 0)
2395 WarningNotHiding (parent);
2403 public override bool Define (TypeContainer parent)
2405 if (!DoDefine (parent))
2408 if (!CheckBase (parent))
2411 CallingConventions cc = GetCallingConvention (parent is Class);
2413 MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2414 ParameterInfo, cc, OptAttributes,
2415 ModFlags, flags, true);
2417 if (!MethodData.Define (parent))
2420 MethodBuilder = MethodData.MethodBuilder;
2423 // This is used to track the Entry Point,
2425 if (Name == "Main" &&
2426 ((ModFlags & Modifiers.STATIC) != 0) &&
2427 (RootContext.MainClass == null ||
2428 RootContext.MainClass == parent.TypeBuilder.FullName)){
2429 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2430 if (RootContext.EntryPoint == null) {
2431 RootContext.EntryPoint = MethodBuilder;
2432 RootContext.EntryPointLocation = Location;
2434 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2435 DuplicateEntryPoint (MethodBuilder, Location);
2438 Report28(MethodBuilder);
2447 public void Emit (TypeContainer parent)
2449 MethodData.Emit (parent, Block, this);
2453 public abstract class ConstructorInitializer {
2454 ArrayList argument_list;
2455 ConstructorInfo parent_constructor;
2456 Parameters parameters;
2459 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2462 this.argument_list = argument_list;
2463 this.parameters = parameters;
2467 public ArrayList Arguments {
2469 return argument_list;
2473 public bool Resolve (EmitContext ec)
2475 Expression parent_constructor_group;
2478 ec.CurrentBlock = new Block (null, true, parameters);
2480 if (argument_list != null){
2481 foreach (Argument a in argument_list){
2482 if (!a.Resolve (ec, loc))
2487 ec.CurrentBlock = null;
2489 if (this is ConstructorBaseInitializer) {
2490 if (ec.ContainerType.BaseType == null)
2493 t = ec.ContainerType.BaseType;
2494 if (ec.ContainerType.IsValueType) {
2495 Report.Error (522, loc,
2496 "structs cannot call base class constructors");
2500 t = ec.ContainerType;
2502 parent_constructor_group = Expression.MemberLookup (
2503 ec, t, null, t, ".ctor",
2504 MemberTypes.Constructor,
2505 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2508 if (parent_constructor_group == null){
2509 Report.Error (1501, loc,
2510 "Can not find a constructor for this argument list");
2514 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2515 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2517 if (parent_constructor == null){
2518 Report.Error (1501, loc,
2519 "Can not find a constructor for this argument list");
2526 public void Emit (EmitContext ec)
2528 if (parent_constructor != null){
2531 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2533 Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2538 public class ConstructorBaseInitializer : ConstructorInitializer {
2539 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2540 base (argument_list, pars, l)
2545 public class ConstructorThisInitializer : ConstructorInitializer {
2546 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2547 base (argument_list, pars, l)
2552 public class Constructor : MethodCore {
2553 public ConstructorBuilder ConstructorBuilder;
2554 public ConstructorInitializer Initializer;
2555 new public Attributes OptAttributes;
2558 // Modifiers allowed for a constructor.
2560 public const int AllowedModifiers =
2562 Modifiers.PROTECTED |
2563 Modifiers.INTERNAL |
2570 // The spec claims that static is not permitted, but
2571 // my very own code has static constructors.
2573 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2574 : base (null, 0, AllowedModifiers, name, null, args, l)
2580 // Returns true if this is a default constructor
2582 public bool IsDefault ()
2584 if ((ModFlags & Modifiers.STATIC) != 0)
2585 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2586 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2589 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2590 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2591 (Initializer is ConstructorBaseInitializer) &&
2592 (Initializer.Arguments == null);
2596 // Creates the ConstructorBuilder
2598 public override bool Define (TypeContainer parent)
2600 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2601 MethodAttributes.SpecialName);
2603 // Check if arguments were correct.
2604 if (!DoDefineParameters (parent))
2607 if ((ModFlags & Modifiers.STATIC) != 0)
2608 ca |= MethodAttributes.Static;
2610 if (parent is Struct && ParameterTypes.Length == 0){
2613 "Structs can not contain explicit parameterless " +
2617 ca |= MethodAttributes.HideBySig;
2619 if ((ModFlags & Modifiers.PUBLIC) != 0)
2620 ca |= MethodAttributes.Public;
2621 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2622 if ((ModFlags & Modifiers.INTERNAL) != 0)
2623 ca |= MethodAttributes.FamORAssem;
2625 ca |= MethodAttributes.Family;
2626 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2627 ca |= MethodAttributes.Assembly;
2628 else if (IsDefault ())
2629 ca |= MethodAttributes.Public;
2631 ca |= MethodAttributes.Private;
2634 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2635 ca, GetCallingConvention (parent is Class), ParameterTypes);
2638 // HACK because System.Reflection.Emit is lame
2640 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2643 "Class `" +parent.Name+ "' already contains a definition with the " +
2644 "same return value and parameter types for constructor `" + Name
2655 public void Emit (TypeContainer parent)
2657 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2658 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2661 // extern methods have no bodies
2663 if ((ModFlags & Modifiers.EXTERN) != 0) {
2664 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
2666 179, Location, "External constructor `" +
2667 TypeManager.CSharpSignature (ConstructorBuilder) +
2668 "' can not have a body");
2671 } else if (block == null) {
2673 501, Location, "Constructor `" +
2674 TypeManager.CSharpSignature (ConstructorBuilder) +
2675 "' must declare a body since it is not marked extern");
2679 if ((ModFlags & Modifiers.STATIC) == 0){
2680 if (parent is Class && Initializer == null)
2681 Initializer = new ConstructorBaseInitializer (
2682 null, Parameters.EmptyReadOnlyParameters, Location.Null);
2686 // Spec mandates that Initializers will not have
2690 if (Initializer != null && !Initializer.Resolve (ec))
2692 ec.IsStatic = false;
2695 LabelParameters (ec, ConstructorBuilder, OptAttributes);
2697 SymbolWriter sw = CodeGen.SymbolWriter;
2698 bool generate_debugging = false;
2700 if ((sw != null) && (block != null) &&
2701 !Location.IsNull (Location) &&
2702 !Location.IsNull (block.EndLocation)) {
2704 sw.OpenMethod (parent, ConstructorBuilder, Location, block.EndLocation);
2706 generate_debugging = true;
2710 // Classes can have base initializers and instance field initializers.
2712 if (parent is Class){
2713 if ((ModFlags & Modifiers.STATIC) == 0)
2714 parent.EmitFieldInitializers (ec);
2716 if (Initializer != null)
2717 Initializer.Emit (ec);
2719 if ((ModFlags & Modifiers.STATIC) != 0)
2720 parent.EmitFieldInitializers (ec);
2722 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes);
2724 // If this is a non-static `struct' constructor and doesn't have any
2725 // initializer, it must initialize all of the struct's fields.
2726 if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2727 (Initializer == null))
2728 Block.AddThisVariable (parent, Location);
2730 ec.EmitTopBlock (block, ParameterInfo, Location);
2732 if (generate_debugging)
2737 public class MethodData {
2739 // The return type of this method
2741 public readonly Type ReturnType;
2742 public readonly Type[] ParameterTypes;
2743 public readonly InternalParameters ParameterInfo;
2744 public readonly CallingConventions CallingConventions;
2745 public readonly Attributes OptAttributes;
2746 public readonly Location Location;
2749 // Are we implementing an interface ?
2751 public bool IsImplementing = false;
2756 protected MemberBase member;
2757 protected int modifiers;
2758 protected MethodAttributes flags;
2759 protected bool is_method;
2760 protected string accessor_name;
2761 ArrayList conditionals;
2763 MethodBuilder builder = null;
2764 public MethodBuilder MethodBuilder {
2770 public MethodData (MemberBase member, string name, Type return_type,
2771 Type [] parameter_types, InternalParameters parameters,
2772 CallingConventions cc, Attributes opt_attrs,
2773 int modifiers, MethodAttributes flags, bool is_method)
2775 this.member = member;
2776 this.accessor_name = name;
2777 this.ReturnType = return_type;
2778 this.ParameterTypes = parameter_types;
2779 this.ParameterInfo = parameters;
2780 this.CallingConventions = cc;
2781 this.OptAttributes = opt_attrs;
2782 this.modifiers = modifiers;
2784 this.is_method = is_method;
2785 this.Location = member.Location;
2786 this.conditionals = new ArrayList ();
2792 Attribute dllimport_attribute = null;
2793 string obsolete = null;
2794 bool obsolete_error = false;
2796 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2798 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2801 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2802 if (asec.Attributes == null)
2805 foreach (Attribute a in asec.Attributes) {
2806 if (a.Name == "Conditional") {
2807 if (!ApplyConditionalAttribute (a))
2809 } else if (a.Name == "Obsolete") {
2810 if (!ApplyObsoleteAttribute (a))
2812 } else if (a.Name.IndexOf ("DllImport") != -1) {
2814 a.Type = TypeManager.dllimport_type;
2815 Attribute.Error_AttributeNotValidForElement (a, Location);
2818 if (!ApplyDllImportAttribute (a))
2828 // Applies the `DllImport' attribute to the method.
2830 protected virtual bool ApplyDllImportAttribute (Attribute a)
2832 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2833 if ((modifiers & extern_static) != extern_static) {
2834 Report.Error (601, Location,
2835 "The DllImport attribute must be specified on a method " +
2836 "marked `static' and `extern'.");
2840 flags |= MethodAttributes.PinvokeImpl;
2841 dllimport_attribute = a;
2846 // Applies the `Obsolete' attribute to the method.
2848 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2850 if (obsolete != null) {
2851 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2855 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2856 return obsolete != null;
2860 // Applies the `Conditional' attribute to the method.
2862 protected virtual bool ApplyConditionalAttribute (Attribute a)
2864 // The Conditional attribute is only valid on methods.
2866 Attribute.Error_AttributeNotValidForElement (a, Location);
2870 string condition = a.Conditional_GetConditionName ();
2872 if (condition == null)
2875 if (ReturnType != TypeManager.void_type) {
2876 Report.Error (578, Location,
2877 "Conditional not valid on `" + member.Name + "' " +
2878 "because its return type is not void");
2882 if ((modifiers & Modifiers.OVERRIDE) != 0) {
2883 Report.Error (243, Location,
2884 "Conditional not valid on `" + member.Name + "' " +
2885 "because it is an override method");
2889 if (member.IsExplicitImpl) {
2890 Report.Error (577, Location,
2891 "Conditional not valid on `" + member.Name + "' " +
2892 "because it is an explicit interface implementation");
2896 if (IsImplementing) {
2897 Report.Error (623, Location,
2898 "Conditional not valid on `" + member.Name + "' " +
2899 "because it is an interface method");
2903 conditionals.Add (condition);
2909 // Checks whether this method should be ignored due to its Conditional attributes.
2911 bool ShouldIgnore (Location loc)
2913 // When we're overriding a virtual method, we implicitly inherit the
2914 // Conditional attributes from our parent.
2915 if (member.ParentMethod != null) {
2916 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2917 member.ParentMethod, loc);
2919 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2923 foreach (string condition in conditionals)
2924 if (RootContext.AllDefines [condition] == null)
2931 // Returns the TypeManager.MethodFlags for this method.
2932 // This emits an error 619 / warning 618 if the method is obsolete.
2933 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2935 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2937 TypeManager.MethodFlags flags = 0;
2939 if (obsolete != null) {
2940 if (obsolete_error) {
2941 Report.Error (619, loc, "Method `" + member.Name +
2942 "' is obsolete: `" + obsolete + "'");
2943 return TypeManager.MethodFlags.IsObsoleteError;
2945 Report.Warning (618, loc, "Method `" + member.Name +
2946 "' is obsolete: `" + obsolete + "'");
2948 flags |= TypeManager.MethodFlags.IsObsolete;
2951 if (ShouldIgnore (loc))
2952 flags |= TypeManager.MethodFlags.ShouldIgnore;
2957 public virtual bool Define (TypeContainer parent)
2959 MethodInfo implementing = null;
2960 string method_name, name, prefix;
2962 if (OptAttributes != null)
2963 if (!ApplyAttributes (OptAttributes, is_method))
2966 if (member.IsExplicitImpl)
2967 prefix = member.InterfaceType.FullName + ".";
2971 if (accessor_name != null)
2972 name = accessor_name + "_" + member.ShortName;
2974 name = member.ShortName;
2975 method_name = prefix + name;
2977 if (parent.Pending != null){
2978 if (member is Indexer)
2979 implementing = parent.Pending.IsInterfaceIndexer (
2980 member.InterfaceType, ReturnType, ParameterTypes);
2982 implementing = parent.Pending.IsInterfaceMethod (
2983 member.InterfaceType, name, ReturnType, ParameterTypes);
2985 if (member.InterfaceType != null && implementing == null){
2986 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
2993 // For implicit implementations, make sure we are public, for
2994 // explicit implementations, make sure we are private.
2996 if (implementing != null){
2998 // Setting null inside this block will trigger a more
2999 // verbose error reporting for missing interface implementations
3001 // The "candidate" function has been flagged already
3002 // but it wont get cleared
3004 if (member.IsExplicitImpl){
3005 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3006 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3007 implementing = null;
3011 // We already catch different accessibility settings
3012 // so we just need to check that we are not private
3014 if ((modifiers & Modifiers.PRIVATE) != 0)
3015 implementing = null;
3019 // Static is not allowed
3021 if ((modifiers & Modifiers.STATIC) != 0){
3022 implementing = null;
3023 Modifiers.Error_InvalidModifier (Location, "static");
3028 // If implementing is still valid, set flags
3030 if (implementing != null){
3032 // When implementing interface methods, set NewSlot.
3034 if (implementing.DeclaringType.IsInterface)
3035 flags |= MethodAttributes.NewSlot;
3038 MethodAttributes.Virtual |
3039 MethodAttributes.HideBySig;
3041 // Get the method name from the explicit interface.
3042 if (member.InterfaceType != null) {
3043 name = implementing.Name;
3044 method_name = prefix + name;
3047 IsImplementing = true;
3051 // Create the MethodBuilder for the method
3053 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3054 if ((modifiers & Modifiers.STATIC) == 0) {
3055 Report.Error (601, Location,
3056 "The DllImport attribute must be specified on " +
3057 "a method marked 'static' and 'extern'.");
3061 EmitContext ec = new EmitContext (
3062 parent, Location, null, ReturnType, modifiers);
3064 builder = dllimport_attribute.DefinePInvokeMethod (
3065 ec, parent.TypeBuilder, method_name, flags,
3066 ReturnType, ParameterTypes);
3068 builder = parent.TypeBuilder.DefineMethod (
3069 method_name, flags, CallingConventions,
3070 ReturnType, ParameterTypes);
3072 if (builder == null)
3075 if (IsImplementing) {
3077 // clear the pending implemntation flag
3079 if (member is Indexer) {
3080 parent.Pending.ImplementIndexer (
3081 member.InterfaceType, builder, ReturnType,
3082 ParameterTypes, true);
3084 parent.Pending.ImplementMethod (
3085 member.InterfaceType, name, ReturnType,
3086 ParameterTypes, member.IsExplicitImpl);
3088 if (member.IsExplicitImpl)
3089 parent.TypeBuilder.DefineMethodOverride (
3090 builder, implementing);
3093 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3094 Report.Error (111, Location,
3095 "Class `" + parent.Name +
3096 "' already contains a definition with the " +
3097 "same return value and parameter types as the " +
3098 "'get' method of property `" + member.Name + "'");
3102 TypeManager.AddMethod (builder, this);
3110 public virtual void Emit (TypeContainer parent, Block block, object kind)
3115 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3116 ig = builder.GetILGenerator ();
3120 ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3122 if (OptAttributes != null)
3123 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes);
3125 if (member is MethodCore)
3126 ((MethodCore) member).LabelParameters (ec, MethodBuilder, OptAttributes);
3129 // abstract or extern methods have no bodies
3131 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3132 if (block == null) {
3133 SymbolWriter sw = CodeGen.SymbolWriter;
3135 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0)) {
3136 sw.OpenMethod (parent, MethodBuilder, Location, Location);
3144 // abstract or extern methods have no bodies.
3146 if ((modifiers & Modifiers.ABSTRACT) != 0)
3148 500, Location, "Abstract method `" +
3149 TypeManager.CSharpSignature (builder) +
3150 "' can not have a body");
3152 if ((modifiers & Modifiers.EXTERN) != 0)
3154 179, Location, "External method `" +
3155 TypeManager.CSharpSignature (builder) +
3156 "' can not have a body");
3162 // Methods must have a body unless they're extern or abstract
3164 if (block == null) {
3166 501, Location, "Method `" +
3167 TypeManager.CSharpSignature (builder) +
3168 "' must declare a body since it is not marked " +
3169 "abstract or extern");
3174 // Handle destructors specially
3176 // FIXME: This code generates buggy code
3178 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3179 EmitDestructor (ec, block);
3181 SymbolWriter sw = CodeGen.SymbolWriter;
3183 if ((sw != null) && !Location.IsNull (Location) &&
3184 !Location.IsNull (block.EndLocation)) {
3185 sw.OpenMethod (parent, MethodBuilder, Location, block.EndLocation);
3187 ec.EmitTopBlock (block, ParameterInfo, Location);
3191 ec.EmitTopBlock (block, ParameterInfo, Location);
3195 void EmitDestructor (EmitContext ec, Block block)
3197 ILGenerator ig = ec.ig;
3199 Label finish = ig.DefineLabel ();
3200 bool old_in_try = ec.InTry;
3202 ig.BeginExceptionBlock ();
3204 ec.ReturnLabel = finish;
3205 ec.HasReturnLabel = true;
3206 ec.EmitTopBlock (block, null, Location);
3207 ec.InTry = old_in_try;
3209 // ig.MarkLabel (finish);
3210 bool old_in_finally = ec.InFinally;
3211 ec.InFinally = true;
3212 ig.BeginFinallyBlock ();
3214 if (ec.ContainerType.BaseType != null) {
3215 Expression member_lookup = Expression.MemberLookup (
3216 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3217 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, Location);
3219 if (member_lookup != null){
3220 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3222 ig.Emit (OpCodes.Ldarg_0);
3223 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3226 ec.InFinally = old_in_finally;
3228 ig.EndExceptionBlock ();
3229 //ig.MarkLabel (ec.ReturnLabel);
3230 ig.Emit (OpCodes.Ret);
3234 abstract public class MemberBase : MemberCore {
3235 public Expression Type;
3236 public readonly Attributes OptAttributes;
3238 protected MethodAttributes flags;
3241 // The "short" name of this property / indexer / event. This is the
3242 // name without the explicit interface.
3244 public string ShortName;
3247 // The type of this property / indexer / event
3249 public Type MemberType;
3252 // If true, this is an explicit interface implementation
3254 public bool IsExplicitImpl = false;
3257 // The name of the interface we are explicitly implementing
3259 public string ExplicitInterfaceName = null;
3262 // If true, the interface type we are explicitly implementing
3264 public Type InterfaceType = null;
3267 // The method we're overriding if this is an override method.
3269 protected MethodInfo parent_method = null;
3270 public MethodInfo ParentMethod {
3272 return parent_method;
3277 // The constructor is only exposed to our children
3279 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3280 Attributes attrs, Location loc)
3284 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
3285 OptAttributes = attrs;
3288 protected virtual bool CheckBase (TypeContainer parent)
3293 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3297 foreach (Type partype in parameters){
3298 if (partype.IsPointer){
3299 if (!UnsafeOK (parent))
3301 if (!TypeManager.VerifyUnManaged (partype.GetElementType (), Location))
3305 if (parent.AsAccessible (partype, ModFlags))
3308 if (this is Indexer)
3309 Report.Error (55, Location,
3310 "Inconsistent accessibility: parameter type `" +
3311 TypeManager.CSharpName (partype) + "' is less " +
3312 "accessible than indexer `" + Name + "'");
3314 Report.Error (51, Location,
3315 "Inconsistent accessibility: parameter type `" +
3316 TypeManager.CSharpName (partype) + "' is less " +
3317 "accessible than method `" + Name + "'");
3324 protected virtual bool DoDefine (TypeContainer parent)
3329 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3332 flags = Modifiers.MethodAttr (ModFlags);
3334 // Lookup Type, verify validity
3335 MemberType = parent.ResolveType (Type, false, Location);
3336 if (MemberType == null)
3339 if ((parent.ModFlags & Modifiers.SEALED) != 0){
3340 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
3341 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
3346 // verify accessibility
3347 if (!parent.AsAccessible (MemberType, ModFlags)) {
3348 if (this is Property)
3349 Report.Error (53, Location,
3350 "Inconsistent accessibility: property type `" +
3351 TypeManager.CSharpName (MemberType) + "' is less " +
3352 "accessible than property `" + Name + "'");
3353 else if (this is Indexer)
3354 Report.Error (54, Location,
3355 "Inconsistent accessibility: indexer return type `" +
3356 TypeManager.CSharpName (MemberType) + "' is less " +
3357 "accessible than indexer `" + Name + "'");
3358 else if (this is Method)
3359 Report.Error (50, Location,
3360 "Inconsistent accessibility: return type `" +
3361 TypeManager.CSharpName (MemberType) + "' is less " +
3362 "accessible than method `" + Name + "'");
3364 Report.Error (52, Location,
3365 "Inconsistent accessibility: field type `" +
3366 TypeManager.CSharpName (MemberType) + "' is less " +
3367 "accessible than field `" + Name + "'");
3371 if (MemberType.IsPointer && !UnsafeOK (parent))
3375 // Check for explicit interface implementation
3377 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
3378 int pos = Name.LastIndexOf (".");
3380 ExplicitInterfaceName = Name.Substring (0, pos);
3381 ShortName = Name.Substring (pos + 1);
3385 if (ExplicitInterfaceName != null) {
3386 InterfaceType = RootContext.LookupType (
3387 parent, ExplicitInterfaceName, false, Location);
3388 if (InterfaceType == null)
3391 // Compute the full name that we need to export.
3392 Name = InterfaceType.FullName + "." + ShortName;
3394 if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
3397 IsExplicitImpl = true;
3399 IsExplicitImpl = false;
3406 // Fields and Events both generate FieldBuilders, we use this to share
3407 // their common bits. This is also used to flag usage of the field
3409 abstract public class FieldBase : MemberBase {
3410 public FieldBuilder FieldBuilder;
3411 public Status status;
3414 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3417 // The constructor is only exposed to our children
3419 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3420 object init, Attributes attrs, Location loc)
3421 : base (type, mod, allowed_mod, name, attrs, loc)
3427 // Whether this field has an initializer.
3429 public bool HasInitializer {
3431 return init != null;
3436 readonly Object init;
3437 Expression init_expr;
3438 bool init_expr_initialized = false;
3441 // Resolves and returns the field initializer.
3443 public Expression GetInitializerExpression (EmitContext ec)
3445 if (init_expr_initialized)
3449 if (init is Expression)
3450 e = (Expression) init;
3452 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3454 ec.IsFieldInitializer = true;
3455 e = e.DoResolve (ec);
3456 ec.IsFieldInitializer = false;
3459 init_expr_initialized = true;
3466 // The Field class is used to represents class/struct fields during parsing.
3468 public class Field : FieldBase {
3470 // Modifiers allowed in a class declaration
3472 const int AllowedModifiers =
3475 Modifiers.PROTECTED |
3476 Modifiers.INTERNAL |
3479 Modifiers.VOLATILE |
3483 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3484 Attributes attrs, Location loc)
3485 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3489 public override bool Define (TypeContainer parent)
3491 Type t = parent.ResolveType (Type, false, Location);
3496 if (!parent.AsAccessible (t, ModFlags)) {
3497 Report.Error (52, Location,
3498 "Inconsistent accessibility: field type `" +
3499 TypeManager.CSharpName (t) + "' is less " +
3500 "accessible than field `" + Name + "'");
3504 if (RootContext.WarningLevel > 1){
3505 Type ptype = parent.TypeBuilder.BaseType;
3507 // ptype is only null for System.Object while compiling corlib.
3509 TypeContainer.FindMembers (
3510 ptype, MemberTypes.Method,
3511 BindingFlags.Public |
3512 BindingFlags.Static | BindingFlags.Instance,
3513 System.Type.FilterName, Name);
3517 if ((ModFlags & Modifiers.VOLATILE) != 0){
3521 if (TypeManager.IsEnumType (vt))
3522 vt = TypeManager.EnumToUnderlying (t);
3524 if (!((vt == TypeManager.bool_type) ||
3525 (vt == TypeManager.sbyte_type) ||
3526 (vt == TypeManager.byte_type) ||
3527 (vt == TypeManager.short_type) ||
3528 (vt == TypeManager.ushort_type) ||
3529 (vt == TypeManager.int32_type) ||
3530 (vt == TypeManager.uint32_type) ||
3531 (vt == TypeManager.char_type) ||
3532 (vt == TypeManager.float_type))){
3534 677, Location, parent.MakeName (Name) +
3535 " A volatile field can not be of type `" +
3536 TypeManager.CSharpName (vt) + "'");
3542 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3544 if (parent is Struct &&
3545 ((fa & FieldAttributes.Static) == 0) &&
3546 t == parent.TypeBuilder &&
3547 !TypeManager.IsBuiltinType (t)){
3548 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name +
3549 "' causes a cycle in the structure layout");
3552 FieldBuilder = parent.TypeBuilder.DefineField (
3553 Name, t, Modifiers.FieldAttr (ModFlags));
3555 TypeManager.RegisterFieldBase (FieldBuilder, this);
3559 public void Emit (TypeContainer tc)
3561 EmitContext ec = new EmitContext (tc, Location, null,
3562 FieldBuilder.FieldType, ModFlags);
3564 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes);
3569 // `set' and `get' accessors are represented with an Accessor.
3571 public class Accessor {
3573 // Null if the accessor is empty, or a Block if not
3576 public Attributes OptAttributes;
3578 public Accessor (Block b, Attributes attrs)
3581 OptAttributes = attrs;
3586 // Properties and Indexers both generate PropertyBuilders, we use this to share
3587 // their common bits.
3589 abstract public class PropertyBase : MethodCore {
3590 public Accessor Get, Set;
3591 public PropertyBuilder PropertyBuilder;
3592 public MethodBuilder GetBuilder, SetBuilder;
3593 public MethodData GetData, SetData;
3595 protected EmitContext ec;
3597 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3598 Parameters parameters, Accessor get_block, Accessor set_block,
3599 Attributes attrs, Location loc)
3600 : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3606 protected override bool DoDefine (TypeContainer parent)
3608 if (!base.DoDefine (parent))
3611 ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3617 // Checks our base implementation if any
3619 protected override bool CheckBase (TypeContainer parent)
3621 // Check whether arguments were correct.
3622 if (!DoDefineParameters (parent))
3629 MethodSignature ms, base_ms;
3630 if (this is Indexer) {
3631 string name, base_name;
3633 report_name = "this";
3634 name = TypeManager.IndexerPropertyName (parent.TypeBuilder);
3635 ms = new MethodSignature (name, null, ParameterTypes);
3636 base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType);
3637 base_ms = new MethodSignature (base_name, null, ParameterTypes);
3640 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
3644 // Verify if the parent has a type with the same name, and then
3645 // check whether we have to create a new slot for it or not.
3647 Type ptype = parent.TypeBuilder.BaseType;
3649 // ptype is only null for System.Object while compiling corlib.
3650 if (ptype == null) {
3651 if ((ModFlags & Modifiers.NEW) != 0)
3652 WarningNotHiding (parent);
3657 MemberList props_this;
3659 props_this = TypeContainer.FindMembers (
3660 parent.TypeBuilder, MemberTypes.Property,
3661 BindingFlags.NonPublic | BindingFlags.Public |
3662 BindingFlags.Static | BindingFlags.Instance |
3663 BindingFlags.DeclaredOnly,
3664 MethodSignature.method_signature_filter, ms);
3666 if (props_this.Count > 0) {
3667 Report.Error (111, Location, "Class `" + parent.Name + "' " +
3668 "already defines a member called `" + report_name + "' " +
3669 "with the same parameter types");
3673 MemberList mi_props;
3675 mi_props = TypeContainer.FindMembers (
3676 ptype, MemberTypes.Property,
3677 BindingFlags.NonPublic | BindingFlags.Public |
3678 BindingFlags.Instance | BindingFlags.Static,
3679 MethodSignature.inheritable_method_signature_filter, base_ms);
3681 if (mi_props.Count > 0){
3682 PropertyInfo parent_property = (PropertyInfo) mi_props [0];
3683 string name = parent_property.DeclaringType.Name + "." +
3684 parent_property.Name;
3686 MethodInfo get, set, parent_method;
3687 get = parent_property.GetGetMethod (true);
3688 set = parent_property.GetSetMethod (true);
3691 parent_method = get;
3692 else if (set != null)
3693 parent_method = set;
3695 throw new Exception ("Internal error!");
3697 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
3700 if ((ModFlags & Modifiers.NEW) == 0) {
3701 Type parent_type = TypeManager.TypeToCoreType (
3702 parent_property.PropertyType);
3704 if (parent_type != MemberType) {
3706 508, Location, parent.MakeName (Name) + ": cannot " +
3707 "change return type when overriding " +
3708 "inherited member " + name);
3713 if ((ModFlags & Modifiers.NEW) != 0)
3714 WarningNotHiding (parent);
3716 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3717 if (this is Indexer)
3718 Report.Error (115, Location,
3719 parent.MakeName (Name) +
3720 " no suitable indexers found to override");
3722 Report.Error (115, Location,
3723 parent.MakeName (Name) +
3724 " no suitable properties found to override");
3731 public void Emit (TypeContainer tc)
3734 // The PropertyBuilder can be null for explicit implementations, in that
3735 // case, we do not actually emit the ".property", so there is nowhere to
3736 // put the attribute
3738 if (PropertyBuilder != null)
3739 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes);
3741 if (GetData != null)
3742 GetData.Emit (tc, Get.Block, Get);
3744 if (SetData != null)
3745 SetData.Emit (tc, Set.Block, Set);
3749 public class Property : PropertyBase {
3750 const int AllowedModifiers =
3753 Modifiers.PROTECTED |
3754 Modifiers.INTERNAL |
3758 Modifiers.OVERRIDE |
3759 Modifiers.ABSTRACT |
3764 public Property (Expression type, string name, int mod_flags,
3765 Accessor get_block, Accessor set_block,
3766 Attributes attrs, Location loc)
3767 : base (type, name, mod_flags, AllowedModifiers,
3768 Parameters.EmptyReadOnlyParameters,
3769 get_block, set_block, attrs, loc)
3773 public override bool Define (TypeContainer parent)
3775 if (!DoDefine (parent))
3778 if (!CheckBase (parent))
3781 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3784 Type [] parameters = TypeManager.NoTypes;
3786 InternalParameters ip = new InternalParameters (
3787 parent, Parameters.EmptyReadOnlyParameters);
3789 GetData = new MethodData (this, "get", MemberType,
3790 parameters, ip, CallingConventions.Standard,
3791 Get.OptAttributes, ModFlags, flags, false);
3793 if (!GetData.Define (parent))
3796 GetBuilder = GetData.MethodBuilder;
3800 Type [] parameters = new Type [1];
3801 parameters [0] = MemberType;
3803 Parameter [] parms = new Parameter [1];
3804 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3805 InternalParameters ip = new InternalParameters (
3806 parent, new Parameters (parms, null, Location));
3808 SetData = new MethodData (this, "set", TypeManager.void_type,
3809 parameters, ip, CallingConventions.Standard,
3810 Set.OptAttributes, ModFlags, flags, false);
3812 if (!SetData.Define (parent))
3815 SetBuilder = SetData.MethodBuilder;
3816 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3819 // FIXME - PropertyAttributes.HasDefault ?
3821 PropertyAttributes prop_attr =
3822 PropertyAttributes.RTSpecialName |
3823 PropertyAttributes.SpecialName;
3825 if (!IsExplicitImpl){
3826 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3827 Name, prop_attr, MemberType, null);
3830 PropertyBuilder.SetGetMethod (GetBuilder);
3833 PropertyBuilder.SetSetMethod (SetBuilder);
3836 // HACK for the reasons exposed above
3838 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3841 "Class `" + parent.Name +
3842 "' already contains a definition for the property `" +
3852 /// Gigantic workaround for lameness in SRE follows :
3853 /// This class derives from EventInfo and attempts to basically
3854 /// wrap around the EventBuilder so that FindMembers can quickly
3855 /// return this in it search for members
3857 public class MyEventBuilder : EventInfo {
3860 // We use this to "point" to our Builder which is
3861 // not really a MemberInfo
3863 EventBuilder MyBuilder;
3866 // We "catch" and wrap these methods
3868 MethodInfo raise, remove, add;
3870 EventAttributes attributes;
3871 Type declaring_type, reflected_type, event_type;
3876 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3878 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3880 // And now store the values in our own fields.
3882 declaring_type = type_builder;
3884 reflected_type = type_builder;
3886 attributes = event_attr;
3889 this.event_type = event_type;
3893 // Methods that you have to override. Note that you only need
3894 // to "implement" the variants that take the argument (those are
3895 // the "abstract" methods, the others (GetAddMethod()) are
3898 public override MethodInfo GetAddMethod (bool nonPublic)
3903 public override MethodInfo GetRemoveMethod (bool nonPublic)
3908 public override MethodInfo GetRaiseMethod (bool nonPublic)
3914 // These methods make "MyEventInfo" look like a Builder
3916 public void SetRaiseMethod (MethodBuilder raiseMethod)
3918 raise = raiseMethod;
3919 MyBuilder.SetRaiseMethod (raiseMethod);
3922 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3924 remove = removeMethod;
3925 MyBuilder.SetRemoveOnMethod (removeMethod);
3928 public void SetAddOnMethod (MethodBuilder addMethod)
3931 MyBuilder.SetAddOnMethod (addMethod);
3934 public void SetCustomAttribute (CustomAttributeBuilder cb)
3936 MyBuilder.SetCustomAttribute (cb);
3939 public override object [] GetCustomAttributes (bool inherit)
3941 // FIXME : There's nothing which can be seemingly done here because
3942 // we have no way of getting at the custom attribute objects of the
3947 public override object [] GetCustomAttributes (Type t, bool inherit)
3949 // FIXME : Same here !
3953 public override bool IsDefined (Type t, bool b)
3958 public override EventAttributes Attributes {
3964 public override string Name {
3970 public override Type DeclaringType {
3972 return declaring_type;
3976 public override Type ReflectedType {
3978 return reflected_type;
3982 public Type EventType {
3988 public void SetUsed ()
3990 if (my_event != null)
3991 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
3995 public class Event : FieldBase {
3996 const int AllowedModifiers =
3999 Modifiers.PROTECTED |
4000 Modifiers.INTERNAL |
4005 Modifiers.OVERRIDE |
4009 public readonly Accessor Add;
4010 public readonly Accessor Remove;
4011 public MyEventBuilder EventBuilder;
4013 MethodBuilder AddBuilder, RemoveBuilder;
4014 MethodData AddData, RemoveData;
4016 public Event (Expression type, string name, Object init, int mod, Accessor add,
4017 Accessor remove, Attributes attrs, Location loc)
4018 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4024 public override bool Define (TypeContainer parent)
4026 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4028 if (!DoDefine (parent))
4031 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4032 Report.Error (66, Location, "'" + parent.Name + "." + Name +
4033 "' : event must be of a delegate type");
4037 Type [] parameter_types = new Type [1];
4038 parameter_types [0] = MemberType;
4040 Parameter [] parms = new Parameter [1];
4041 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4042 InternalParameters ip = new InternalParameters (
4043 parent, new Parameters (parms, null, Location));
4045 if (!CheckBase (parent))
4049 // Now define the accessors
4051 AddData = new MethodData (this, "add", TypeManager.void_type,
4052 parameter_types, ip, CallingConventions.Standard,
4053 (Add != null) ? Add.OptAttributes : null,
4054 ModFlags, flags, false);
4056 if (!AddData.Define (parent))
4059 AddBuilder = AddData.MethodBuilder;
4060 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4062 RemoveData = new MethodData (this, "remove", TypeManager.void_type,
4063 parameter_types, ip, CallingConventions.Standard,
4064 (Remove != null) ? Remove.OptAttributes : null,
4065 ModFlags, flags, false);
4067 if (!RemoveData.Define (parent))
4070 RemoveBuilder = RemoveData.MethodBuilder;
4071 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4073 if (!IsExplicitImpl){
4074 EventBuilder = new MyEventBuilder (this,
4075 parent.TypeBuilder, Name, e_attr, MemberType);
4077 if (Add == null && Remove == null) {
4078 FieldBuilder = parent.TypeBuilder.DefineField (
4080 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4081 TypeManager.RegisterPrivateFieldOfEvent (
4082 (EventInfo) EventBuilder, FieldBuilder);
4083 TypeManager.RegisterFieldBase (FieldBuilder, this);
4086 EventBuilder.SetAddOnMethod (AddBuilder);
4087 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4089 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4090 Report.Error (111, Location,
4091 "Class `" + parent.Name +
4092 "' already contains a definition for the event `" +
4101 void EmitDefaultMethod (EmitContext ec, bool is_add)
4103 ILGenerator ig = ec.ig;
4104 MethodInfo method = null;
4107 method = TypeManager.delegate_combine_delegate_delegate;
4109 method = TypeManager.delegate_remove_delegate_delegate;
4111 if ((ModFlags & Modifiers.STATIC) != 0) {
4112 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4113 ig.Emit (OpCodes.Ldarg_0);
4114 ig.Emit (OpCodes.Call, method);
4115 ig.Emit (OpCodes.Castclass, MemberType);
4116 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4118 ig.Emit (OpCodes.Ldarg_0);
4119 ig.Emit (OpCodes.Ldarg_0);
4120 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4121 ig.Emit (OpCodes.Ldarg_1);
4122 ig.Emit (OpCodes.Call, method);
4123 ig.Emit (OpCodes.Castclass, MemberType);
4124 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4126 ig.Emit (OpCodes.Ret);
4129 public void Emit (TypeContainer tc)
4133 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4134 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes);
4137 AddData.Emit (tc, Add.Block, Add);
4139 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4140 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4141 EmitDefaultMethod (ec, true);
4145 RemoveData.Emit (tc, Remove.Block, Remove);
4147 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4148 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4149 EmitDefaultMethod (ec, false);
4156 // FIXME: This does not handle:
4158 // int INTERFACENAME [ args ]
4163 // int this [ args ]
4165 public class Indexer : PropertyBase {
4167 const int AllowedModifiers =
4170 Modifiers.PROTECTED |
4171 Modifiers.INTERNAL |
4175 Modifiers.OVERRIDE |
4180 public string IndexerName;
4181 public string InterfaceIndexerName;
4184 // Are we implementing an interface ?
4186 bool IsImplementing = false;
4188 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4189 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4190 : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4193 ExplicitInterfaceName = int_type;
4196 public override bool Define (TypeContainer parent)
4198 PropertyAttributes prop_attr =
4199 PropertyAttributes.RTSpecialName |
4200 PropertyAttributes.SpecialName;
4202 if (!DoDefine (parent))
4205 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4206 if (IndexerName == null)
4207 IndexerName = "Item";
4208 else if (IsExplicitImpl)
4209 Report.Error (592, Location,
4210 "Attribute 'IndexerName' is not valid on this declaration " +
4211 "type. It is valid on `property' declarations only.");
4213 ShortName = IndexerName;
4214 if (IsExplicitImpl) {
4215 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4216 Name = InterfaceType.FullName + "." + IndexerName;
4218 InterfaceIndexerName = IndexerName;
4222 if (!CheckBase (parent))
4225 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4227 InternalParameters ip = new InternalParameters (parent, Parameters);
4229 GetData = new MethodData (this, "get", MemberType,
4230 ParameterTypes, ip, CallingConventions.Standard,
4231 Get.OptAttributes, ModFlags, flags, false);
4233 if (!GetData.Define (parent))
4236 GetBuilder = GetData.MethodBuilder;
4240 int top = ParameterTypes.Length;
4241 Type [] set_pars = new Type [top + 1];
4242 ParameterTypes.CopyTo (set_pars, 0);
4243 set_pars [top] = MemberType;
4245 Parameter [] fixed_parms = Parameters.FixedParameters;
4247 if (fixed_parms == null){
4248 throw new Exception ("We currently do not support only array arguments in an indexer");
4249 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4250 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4252 // Here is the problem: the `value' parameter has
4253 // to come *after* the array parameter in the declaration
4255 // X (object [] x, Type value)
4258 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4259 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4263 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4266 fixed_parms.CopyTo (tmp, 0);
4267 tmp [fixed_parms.Length] = new Parameter (
4268 Type, "value", Parameter.Modifier.NONE, null);
4270 Parameters set_formal_params = new Parameters (tmp, null, Location);
4272 InternalParameters ip = new InternalParameters (parent, set_formal_params);
4274 SetData = new MethodData (this, "set", TypeManager.void_type,
4275 set_pars, ip, CallingConventions.Standard,
4276 Set.OptAttributes, ModFlags, flags, false);
4278 if (!SetData.Define (parent))
4281 SetBuilder = SetData.MethodBuilder;
4285 // Now name the parameters
4287 Parameter [] p = Parameters.FixedParameters;
4291 for (i = 0; i < p.Length; ++i) {
4293 GetBuilder.DefineParameter (
4294 i + 1, p [i].Attributes, p [i].Name);
4297 SetBuilder.DefineParameter (
4298 i + 1, p [i].Attributes, p [i].Name);
4302 SetBuilder.DefineParameter (
4303 i + 1, ParameterAttributes.None, "value");
4305 if (i != ParameterTypes.Length) {
4306 Parameter array_param = Parameters.ArrayParameter;
4307 SetBuilder.DefineParameter (
4308 i + 1, array_param.Attributes, array_param.Name);
4312 if (GetData != null)
4313 IsImplementing = GetData.IsImplementing;
4314 else if (SetData != null)
4315 IsImplementing = SetData.IsImplementing;
4318 // Define the PropertyBuilder if one of the following conditions are met:
4319 // a) we're not implementing an interface indexer.
4320 // b) the indexer has a different IndexerName and this is no
4321 // explicit interface implementation.
4323 if (!IsExplicitImpl) {
4324 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4325 IndexerName, prop_attr, MemberType, ParameterTypes);
4327 if (GetData != null)
4328 PropertyBuilder.SetGetMethod (GetBuilder);
4330 if (SetData != null)
4331 PropertyBuilder.SetSetMethod (SetBuilder);
4333 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4341 public class Operator : MemberCore {
4343 const int AllowedModifiers =
4349 const int RequiredModifiers =
4353 public enum OpType : byte {
4363 // Unary and Binary operators
4386 // Implicit and Explicit
4391 public readonly OpType OperatorType;
4392 public readonly Expression ReturnType;
4393 public readonly Expression FirstArgType, SecondArgType;
4394 public readonly string FirstArgName, SecondArgName;
4395 public readonly Block Block;
4396 public Attributes OptAttributes;
4397 public MethodBuilder OperatorMethodBuilder;
4399 public string MethodName;
4400 public Method OperatorMethod;
4402 public Operator (OpType type, Expression ret_type, int flags,
4403 Expression arg1type, string arg1name,
4404 Expression arg2type, string arg2name,
4405 Block block, Attributes attrs, Location loc)
4408 OperatorType = type;
4409 ReturnType = ret_type;
4410 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4411 FirstArgType = arg1type;
4412 FirstArgName = arg1name;
4413 SecondArgType = arg2type;
4414 SecondArgName = arg2name;
4416 OptAttributes = attrs;
4419 string Prototype (TypeContainer parent)
4421 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4422 SecondArgType + ")";
4425 public override bool Define (TypeContainer parent)
4428 MethodName = "op_" + OperatorType;
4430 if (SecondArgType != null)
4433 Parameter [] param_list = new Parameter [length];
4435 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4438 "User defined operators `" +
4439 Prototype (parent) +
4440 "' must be declared static and public");
4444 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4445 Parameter.Modifier.NONE, null);
4446 if (SecondArgType != null)
4447 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4448 Parameter.Modifier.NONE, null);
4450 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4451 new Parameters (param_list, null, Location),
4452 OptAttributes, Mono.CSharp.Location.Null);
4454 OperatorMethod.IsOperator = true;
4455 OperatorMethod.Define (parent);
4457 if (OperatorMethod.MethodBuilder == null)
4460 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4462 Type [] param_types = OperatorMethod.ParameterTypes;
4463 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4464 Type return_type = OperatorMethod.GetReturnType ();
4465 Type first_arg_type = param_types [0];
4467 // Rules for conversion operators
4469 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4470 if (first_arg_type == return_type && first_arg_type == declaring_type){
4473 "User-defined conversion cannot take an object of the " +
4474 "enclosing type and convert to an object of the enclosing" +
4479 if (first_arg_type != declaring_type && return_type != declaring_type){
4482 "User-defined conversion must convert to or from the " +
4487 if (first_arg_type == TypeManager.object_type ||
4488 return_type == TypeManager.object_type){
4491 "User-defined conversion cannot convert to or from " +
4496 if (first_arg_type.IsInterface || return_type.IsInterface){
4499 "User-defined conversion cannot convert to or from an " +
4504 if (first_arg_type.IsSubclassOf (return_type) ||
4505 return_type.IsSubclassOf (first_arg_type)){
4508 "User-defined conversion cannot convert between types " +
4509 "that derive from each other");
4512 } else if (SecondArgType == null) {
4513 // Checks for Unary operators
4515 if (first_arg_type != declaring_type){
4518 "The parameter of a unary operator must be the " +
4523 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4524 if (return_type != declaring_type){
4527 "The parameter and return type for ++ and -- " +
4528 "must be the containing type");
4534 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4535 if (return_type != TypeManager.bool_type){
4538 "The return type of operator True or False " +
4545 // Checks for Binary operators
4547 if (first_arg_type != declaring_type &&
4548 param_types [1] != declaring_type){
4551 "One of the parameters of a binary operator must " +
4552 "be the containing type");
4560 public void Emit (TypeContainer parent)
4562 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4563 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes);
4566 // abstract or extern methods have no bodies
4568 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4571 OperatorMethod.Block = Block;
4572 OperatorMethod.Emit (parent);
4575 public static string GetName (OpType ot)
4578 case OpType.LogicalNot:
4580 case OpType.OnesComplement:
4582 case OpType.Increment:
4584 case OpType.Decrement:
4590 case OpType.Addition:
4592 case OpType.Subtraction:
4594 case OpType.UnaryPlus:
4596 case OpType.UnaryNegation:
4598 case OpType.Multiply:
4600 case OpType.Division:
4602 case OpType.Modulus:
4604 case OpType.BitwiseAnd:
4606 case OpType.BitwiseOr:
4608 case OpType.ExclusiveOr:
4610 case OpType.LeftShift:
4612 case OpType.RightShift:
4614 case OpType.Equality:
4616 case OpType.Inequality:
4618 case OpType.GreaterThan:
4620 case OpType.LessThan:
4622 case OpType.GreaterThanOrEqual:
4624 case OpType.LessThanOrEqual:
4626 case OpType.Implicit:
4628 case OpType.Explicit:
4634 public override string ToString ()
4636 Type return_type = OperatorMethod.GetReturnType();
4637 Type [] param_types = OperatorMethod.ParameterTypes;
4639 if (SecondArgType == null)
4640 return String.Format (
4641 "{0} operator {1}({2})",
4642 TypeManager.CSharpName (return_type),
4643 GetName (OperatorType),
4646 return String.Format (
4647 "{0} operator {1}({2}, {3})",
4648 TypeManager.CSharpName (return_type),
4649 GetName (OperatorType),
4650 param_types [0], param_types [1]);
4655 // This is used to compare method signatures
4657 struct MethodSignature {
4659 public Type RetType;
4660 public Type [] Parameters;
4663 /// This delegate is used to extract methods which have the
4664 /// same signature as the argument
4666 public static MemberFilter method_signature_filter;
4669 /// This delegate is used to extract inheritable methods which
4670 /// have the same signature as the argument. By inheritable,
4671 /// this means that we have permissions to override the method
4672 /// from the current assembly and class
4674 public static MemberFilter inheritable_method_signature_filter;
4676 static MethodSignature ()
4678 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4679 inheritable_method_signature_filter = new MemberFilter (
4680 InheritableMemberSignatureCompare);
4683 public MethodSignature (string name, Type ret_type, Type [] parameters)
4688 if (parameters == null)
4689 Parameters = TypeManager.NoTypes;
4691 Parameters = parameters;
4694 public override int GetHashCode ()
4696 return Name.GetHashCode ();
4699 public override bool Equals (Object o)
4701 MethodSignature other = (MethodSignature) o;
4703 if (other.Name != Name)
4706 if (other.RetType != RetType)
4709 if (Parameters == null){
4710 if (other.Parameters == null)
4715 if (other.Parameters == null)
4718 int c = Parameters.Length;
4719 if (other.Parameters.Length != c)
4722 for (int i = 0; i < c; i++)
4723 if (other.Parameters [i] != Parameters [i])
4729 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4731 MethodSignature sig = (MethodSignature) filter_criteria;
4733 if (m.Name != sig.Name)
4737 MethodInfo mi = m as MethodInfo;
4738 PropertyInfo pi = m as PropertyInfo;
4741 ReturnType = mi.ReturnType;
4742 else if (pi != null)
4743 ReturnType = pi.PropertyType;
4748 // we use sig.RetType == null to mean `do not check the
4749 // method return value.
4751 if (sig.RetType != null)
4752 if (ReturnType != sig.RetType)
4757 args = TypeManager.GetArgumentTypes (mi);
4759 args = TypeManager.GetArgumentTypes (pi);
4760 Type [] sigp = sig.Parameters;
4762 if (args.Length != sigp.Length)
4765 for (int i = args.Length; i > 0; ){
4767 if (args [i] != sigp [i])
4774 // This filter should be used when we are requesting methods that
4775 // we want to override.
4777 // This makes a number of assumptions, for example
4778 // that the methods being extracted are of a parent
4779 // class (this means we know implicitly that we are
4780 // being called to find out about members by a derived
4783 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4785 if (!MemberSignatureCompare (m, filter_criteria))
4789 PropertyInfo pi = m as PropertyInfo;
4792 mi = pi.GetGetMethod (true);
4794 mi = pi.GetSetMethod (true);
4796 mi = m as MethodInfo;
4799 Console.WriteLine ("Nothing found");
4802 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4804 // If only accessible to the current class.
4805 if (prot == MethodAttributes.Private)
4808 // If only accessible to the defining assembly or
4809 if (prot == MethodAttributes.FamANDAssem ||
4810 prot == MethodAttributes.Assembly){
4811 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4817 // Anything else (FamOrAssembly and Public) is fine