3 // class.cs: Class and Struct handlers
5 // Authors: Miguel de Icaza (miguel@gnu.org)
6 // Martin Baulig (martin@gnome.org)
8 // Licensed under the terms of the GNU GPL
10 // (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
13 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
15 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
16 // have fixed a remaining problem: not every AddXXXX was adding a
17 // fully qualified name.
19 // Now everyone registers a fully qualified name in the DeclSpace as
20 // being defined instead of the partial name.
22 // Downsides: we are slower than we need to be due to the excess
23 // copies and the names being registered this way.
25 // The reason for this is that we currently depend (on the corlib
26 // bootstrap for instance) that types are fully qualified, because
27 // we dump all the types in the namespace, and we should really have
28 // types inserted into the proper namespace, so we can only store the
29 // basenames in the defined_names array.
34 using System.Collections;
35 using System.Reflection;
36 using System.Reflection.Emit;
37 using System.Runtime.CompilerServices;
38 using System.Diagnostics.SymbolStore;
40 namespace Mono.CSharp {
43 /// This is the base class for structs and classes.
45 public class TypeContainer : DeclSpace, IMemberContainer {
46 // Holds a list of classes and structures
49 // Holds the list of properties
52 // Holds the list of enumerations
55 // Holds the list of delegates
58 // Holds the list of constructors
59 ArrayList instance_constructors;
61 // Holds the list of fields
64 // Holds a list of fields that have initializers
65 ArrayList initialized_fields;
67 // Holds a list of static fields that have initializers
68 ArrayList initialized_static_fields;
70 // Holds the list of constants
76 // Holds order in which interfaces must be closed
77 ArrayList interface_order;
88 // Holds the operators
91 // The emit context for toplevel objects.
95 // Pointers to the default constructor and the default static constructor
97 Constructor default_constructor;
98 Constructor default_static_constructor;
101 // Whether we have seen a static constructor for this class or not
103 bool have_static_constructor = false;
106 // Whether we have at least one non-static field
108 bool have_nonstatic_fields = false;
111 // This one is computed after we can distinguish interfaces
112 // from classes from the arraylist `type_bases'
114 string base_class_name;
116 ArrayList type_bases;
118 // Attributes for this type
119 protected Attributes attributes;
121 // Information in the case we are an attribute type
123 public AttributeTargets Targets = AttributeTargets.All;
124 public bool AllowMultiple = false;
125 public bool Inherited;
127 // The interfaces we implement.
130 // The parent member container and our member cache
131 IMemberContainer parent_container;
132 MemberCache member_cache;
135 // The indexer name for this class
137 public string IndexerName;
139 public TypeContainer (TypeContainer parent, string name, Location l)
140 : base (parent, name, l)
143 types = new ArrayList ();
150 base_class_name = null;
152 //Console.WriteLine ("New class " + name + " inside " + n);
155 public AdditionResult AddConstant (Const constant)
158 string basename = constant.Name;
160 if ((res = IsValid (basename)) != AdditionResult.Success)
163 if (constants == null)
164 constants = new ArrayList ();
166 constants.Add (constant);
167 DefineName (Name + "." + basename, constant);
169 return AdditionResult.Success;
172 public AdditionResult AddEnum (Mono.CSharp.Enum e)
176 if ((res = IsValid (e.Basename)) != AdditionResult.Success)
180 enums = new ArrayList ();
183 DefineName (e.Name, e);
185 return AdditionResult.Success;
188 public AdditionResult AddClass (Class c)
192 if ((res = IsValid (c.Basename)) != AdditionResult.Success)
195 DefineName (c.Name, c);
198 // FIXME: Do we really need to explicitly add an empty default static constructor?
199 // Apparently we don't
200 /* if (c.default_static_constructor == null)
202 bool isModule = c is Mono.MonoBASIC.Module;
203 Constructor dc = new Constructor ("New", Parameters.EmptyReadOnlyParameters, null, c.Location);
204 dc.ModFlags = isModule ? Modifiers.PUBLIC | Modifiers.STATIC : Modifiers.PUBLIC;
205 c.AddConstructor (dc);
208 // --------------------------------------------------------------
210 return AdditionResult.Success;
213 public AdditionResult AddStruct (Struct s)
217 if ((res = IsValid (s.Basename)) != AdditionResult.Success)
220 DefineName (s.Name, s);
223 return AdditionResult.Success;
226 public AdditionResult AddDelegate (Delegate d)
230 if ((res = IsValid (d.Basename)) != AdditionResult.Success)
233 if (delegates == null)
234 delegates = new ArrayList ();
236 DefineName (d.Name, d);
239 return AdditionResult.Success;
242 public AdditionResult AddMethod (Method method)
244 string basename = method.Name;
245 string fullname = Name + "." + basename;
247 Object value = defined_names [fullname];
249 if (value != null && (!(value is Method)))
250 return AdditionResult.NameExists;
252 if (basename == Basename)
253 return AdditionResult.EnclosingClash;
256 methods = new ArrayList ();
258 if (method.Name.IndexOf (".") != -1)
259 methods.Insert (0, method);
261 methods.Add (method);
264 DefineName (fullname, method);
266 return AdditionResult.Success;
269 public AdditionResult AddConstructor (Constructor c)
272 return AdditionResult.NotAConstructor;
274 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
277 have_static_constructor = true;
278 if (default_static_constructor != null){
279 Console.WriteLine ("I have a static constructor already");
280 Console.WriteLine (" " + default_static_constructor);
281 return AdditionResult.MethodExists;
284 default_static_constructor = c;
287 if (default_constructor != null)
288 return AdditionResult.MethodExists;
289 default_constructor = c;
292 if (instance_constructors == null)
293 instance_constructors = new ArrayList ();
295 instance_constructors.Add (c);
298 return AdditionResult.Success;
301 public AdditionResult AddInterface (Interface iface)
305 if ((res = IsValid (iface.Basename)) != AdditionResult.Success)
308 if (interfaces == null)
309 interfaces = new ArrayList ();
310 interfaces.Add (iface);
311 DefineName (iface.Name, iface);
313 return AdditionResult.Success;
316 public AdditionResult AddField (Field field)
319 string basename = field.Name;
321 if ((res = IsValid (basename)) != AdditionResult.Success)
325 fields = new ArrayList ();
329 if (field.HasInitializer){
330 if ((field.ModFlags & Modifiers.STATIC) != 0) {
331 if (initialized_static_fields == null)
332 initialized_static_fields = new ArrayList ();
334 initialized_static_fields.Add (field);
337 // We have not seen a static constructor,
338 // but we will provide static initialization of fields
340 have_static_constructor = true;
342 if (initialized_fields == null)
343 initialized_fields = new ArrayList ();
345 initialized_fields.Add (field);
349 if ((field.ModFlags & Modifiers.STATIC) == 0)
350 have_nonstatic_fields = true;
352 DefineName (Name + "." + basename, field);
353 return AdditionResult.Success;
356 public AdditionResult AddProperty (Property prop)
359 string basename = prop.Name;
361 if ((res = IsValid (basename)) != AdditionResult.Success)
364 if (properties == null)
365 properties = new ArrayList ();
367 if (prop.Name.IndexOf (".") != -1)
368 properties.Insert (0, prop);
370 properties.Add (prop);
371 DefineName (Name + "." + basename, prop);
373 return AdditionResult.Success;
376 public AdditionResult AddEvent (Event e)
379 string basename = e.Name;
381 if ((res = IsValid (basename)) != AdditionResult.Success)
385 events = new ArrayList ();
388 DefineName (Name + "." + basename, e);
390 return AdditionResult.Success;
393 public AdditionResult AddIndexer (Indexer i)
395 if (indexers == null)
396 indexers = new ArrayList ();
398 if (i.InterfaceType != null)
399 indexers.Insert (0, i);
403 return AdditionResult.Success;
406 public AdditionResult AddOperator (Operator op)
408 if (operators == null)
409 operators = new ArrayList ();
413 return AdditionResult.Success;
416 public void RegisterOrder (Interface iface)
418 if (interface_order == null)
419 interface_order = new ArrayList ();
421 interface_order.Add (iface);
424 public ArrayList Types {
430 public ArrayList Methods {
436 public ArrayList Constants {
442 public ArrayList Interfaces {
450 return base_class_name;
454 public ArrayList Bases {
464 public ArrayList Fields {
474 public ArrayList InstanceConstructors {
476 return instance_constructors;
480 public ArrayList Properties {
486 public ArrayList Events {
492 public ArrayList Enums {
498 public ArrayList Indexers {
504 public ArrayList Operators {
510 public ArrayList Delegates {
516 public Attributes OptAttributes {
522 public bool HaveStaticConstructor {
524 return have_static_constructor;
528 public virtual TypeAttributes TypeAttr {
530 return Modifiers.TypeAttr (ModFlags, this);
535 // Emits the instance field initializers
537 public bool EmitFieldInitializers (EmitContext ec)
540 ILGenerator ig = ec.ig;
541 Expression instance_expr;
544 fields = initialized_static_fields;
545 instance_expr = null;
547 fields = initialized_fields;
548 instance_expr = new This (Location.Null).Resolve (ec);
554 foreach (Field f in fields){
555 Expression e = f.GetInitializerExpression (ec);
559 Location l = f.Location;
560 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
561 fe.InstanceExpression = instance_expr;
562 Expression a = new Assign (fe, e, l);
568 if (a is ExpressionStatement)
569 ((ExpressionStatement) a).EmitStatement (ec);
571 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
579 // Defines the default constructors
581 void DefineDefaultConstructor (bool is_static)
586 c = new Constructor (Basename, Parameters.EmptyReadOnlyParameters,
587 new ConstructorBaseInitializer (
588 null, Parameters.EmptyReadOnlyParameters,
593 mods = Modifiers.STATIC;
599 c.Block = new Block (null);
603 public void ReportStructInitializedInstanceError ()
605 string n = TypeBuilder.FullName;
607 foreach (Field f in initialized_fields){
610 "`" + n + "." + f.Name + "': can not have " +
611 "instance field initializers in structs");
616 /// The pending methods that need to be implemented (interfaces or abstract methods)
618 public PendingImplementation Pending;
621 /// This function computes the Base class and also the
622 /// list of interfaces that the class or struct @c implements.
624 /// The return value is an array (might be null) of
625 /// interfaces implemented (as Types).
627 /// The @parent argument is set to the parent object or null
628 /// if this is `System.Object'.
630 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
632 ArrayList bases = Bases;
641 parent = TypeManager.value_type;
645 if (RootContext.StdLib)
646 parent = TypeManager.object_type;
647 else if (Name != "System.Object")
648 parent = TypeManager.object_type;
651 // If we are compiling our runtime,
652 // and we are defining ValueType, then our
653 // parent is `System.Object'.
655 if (!RootContext.StdLib && Name == "System.ValueType")
656 parent = TypeManager.object_type;
663 // Bases should be null if there are no bases at all
668 Expression name = (Expression) bases [0];
669 name = ResolveTypeExpr (name, false, Location);
676 Type first = name.Type;
682 parent = TypeManager.object_type;
686 if (!AsAccessible (parent, ModFlags))
687 Report.Error (60, Location,
688 "Inconsistent accessibility: base class `" +
689 TypeManager.CSharpName (parent) + "' is less " +
690 "accessible than class `" +
697 Type [] ifaces = new Type [count-start];
699 for (i = start, j = 0; i < count; i++, j++){
700 Expression name = (Expression) bases [i];
701 Expression resolved = ResolveTypeExpr (name, false, Location);
702 bases [i] = resolved;
703 Type t = resolved.Type;
710 if (is_class == false && !t.IsInterface){
711 Report.Error (527, "In Struct `" + Name + "', type `"+
712 name +"' is not an interface");
721 detail = " (a class can not inherit from a struct/enum)";
723 Report.Error (509, "class `"+ Name +
724 "': Cannot inherit from sealed class `"+
725 bases [i]+"'"+detail);
732 Report.Error (527, "In Class `" + Name + "', type `"+
733 name+"' is not an interface");
739 for (int x = 0; x < j; x++) {
740 if (t == ifaces [x]) {
741 Report.Error (528, "`" + name + "' is already listed in interface list");
750 return TypeManager.ExpandInterfaces (ifaces);
754 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
756 public override TypeBuilder DefineType ()
762 if (TypeBuilder != null)
775 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
777 ifaces = GetClassBases (is_class, out parent, out error);
782 if (is_class && parent != null){
783 if (parent == TypeManager.enum_type ||
784 (parent == TypeManager.value_type && RootContext.StdLib) ||
785 parent == TypeManager.delegate_type ||
786 parent == TypeManager.array_type){
788 644, Location, "`" + Name + "' cannot inherit from " +
789 "special class `" + TypeManager.CSharpName (parent) + "'");
794 if (!is_class && TypeManager.value_type == null)
795 throw new Exception ();
797 TypeAttributes type_attributes = TypeAttr;
799 // if (parent_builder is ModuleBuilder) {
801 ModuleBuilder builder = CodeGen.ModuleBuilder;
802 TypeBuilder = builder.DefineType (
803 Name, type_attributes, parent, ifaces);
806 TypeBuilder builder = Parent.TypeBuilder;
807 TypeBuilder = builder.DefineNestedType (
808 Basename, type_attributes, parent, ifaces);
812 // Structs with no fields need to have at least one byte.
813 // The right thing would be to set the PackingSize in a DefineType
814 // but there are no functions that allow interfaces *and* the size to
818 if (!is_class && !have_nonstatic_fields){
819 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
820 FieldAttributes.Private);
823 // add interfaces that were not added at type creation (weird API issue)
824 if (!is_class && !have_nonstatic_fields && (ifaces != null)) {
825 foreach (Type i in ifaces)
826 TypeBuilder.AddInterfaceImplementation (i);
830 // Finish the setup for the EmitContext
832 ec.ContainerType = TypeBuilder;
834 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
836 if ((parent != null) &&
837 (parent == TypeManager.attribute_type ||
838 parent.IsSubclassOf (TypeManager.attribute_type))) {
839 RootContext.RegisterAttribute (this);
840 TypeManager.RegisterAttrType (TypeBuilder, this);
842 RootContext.RegisterOrder (this);
844 if (Interfaces != null) {
845 foreach (Interface iface in Interfaces)
850 foreach (TypeContainer tc in Types)
854 if (Delegates != null) {
855 foreach (Delegate d in Delegates)
860 foreach (Enum en in Enums)
870 /// Defines the MemberCore objects that are in the `list' Arraylist
872 /// The `defined_names' array contains a list of members defined in
875 static ArrayList remove_list = new ArrayList ();
876 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
880 remove_list.Clear ();
882 foreach (MemberCore mc in list){
883 if (!mc.Define (this)){
884 remove_list.Add (mc);
888 if (defined_names == null)
891 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
893 if (RootContext.WarningLevel >= 4){
894 if ((mc.ModFlags & Modifiers.NEW) != 0)
895 Warning_KewywordNewNotRequired (mc.Location, mc);
900 MemberInfo match = defined_names [idx];
902 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
906 // If we are both methods, let the method resolution emit warnings
908 if (match is MethodBase && mc is MethodCore)
911 if ((mc.ModFlags & Modifiers.NEW) == 0)
912 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
915 foreach (object o in remove_list)
918 remove_list.Clear ();
922 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
923 // class is consisten. Either it is `Item' or it is the name defined by all the
924 // indexers with the `IndexerName' attribute.
926 // Turns out that the IndexerNameAttribute is applied to each indexer,
927 // but it is never emitted, instead a DefaultName attribute is attached
930 void DefineIndexers ()
932 string class_indexer_name = null;
934 foreach (Indexer i in Indexers){
939 name = i.IndexerName;
941 if (i.InterfaceType != null)
944 if (class_indexer_name == null){
945 class_indexer_name = name;
949 if (name == class_indexer_name)
953 668, "Two indexers have different names, " +
954 " you should use the same name for all your indexers");
956 if (class_indexer_name == null)
957 class_indexer_name = "Item";
958 IndexerName = class_indexer_name;
961 static void Error_KeywordNotAllowed (Location loc)
963 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
967 /// Populates our TypeBuilder with fields and methods
969 public override bool DefineMembers (TypeContainer parent)
971 MemberInfo [] defined_names = null;
973 if (interface_order != null){
974 foreach (Interface iface in interface_order)
975 if ((iface.ModFlags & Modifiers.NEW) == 0)
976 iface.DefineMembers (this);
978 Error_KeywordNotAllowed (iface.Location);
981 if (RootContext.WarningLevel > 1){
985 // This code throws an exception in the comparer
986 // I guess the string is not an object?
988 ptype = TypeBuilder.BaseType;
990 defined_names = (MemberInfo []) FindMembers (
991 ptype, MemberTypes.All & ~MemberTypes.Constructor,
992 BindingFlags.Public | BindingFlags.Instance |
993 BindingFlags.Static, null, null);
995 Array.Sort (defined_names, mif_compare);
999 if (constants != null)
1000 DefineMembers (constants, defined_names);
1003 DefineMembers (fields, defined_names);
1006 if (instance_constructors == null){
1007 if (default_constructor == null)
1008 DefineDefaultConstructor (false);
1011 if (initialized_static_fields != null &&
1012 default_static_constructor == null)
1013 DefineDefaultConstructor (true);
1016 if (this is Struct){
1018 // Structs can not have initialized instance
1021 if (initialized_static_fields != null &&
1022 default_static_constructor == null)
1023 DefineDefaultConstructor (true);
1025 if (initialized_fields != null)
1026 ReportStructInitializedInstanceError ();
1029 Pending = PendingImplementation.GetPendingImplementations (this);
1032 // Constructors are not in the defined_names array
1034 if (instance_constructors != null)
1035 DefineMembers (instance_constructors, null);
1037 if (default_static_constructor != null)
1038 default_static_constructor.Define (this);
1040 if (methods != null)
1041 DefineMembers (methods, defined_names);
1043 if (properties != null)
1044 DefineMembers (properties, defined_names);
1047 DefineMembers (events, defined_names);
1049 if (indexers != null) {
1052 IndexerName = "Item";
1054 if (operators != null){
1055 DefineMembers (operators, null);
1057 CheckPairedOperators ();
1061 DefineMembers (enums, defined_names);
1063 if (delegates != null)
1064 DefineMembers (delegates, defined_names);
1067 if (TypeBuilder.BaseType != null)
1068 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1070 member_cache = new MemberCache (this);
1076 public override bool Define (TypeContainer parent)
1078 if (interface_order != null){
1079 foreach (Interface iface in interface_order)
1080 if ((iface.ModFlags & Modifiers.NEW) == 0)
1081 iface.Define (this);
1088 /// This function is based by a delegate to the FindMembers routine
1090 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1096 /// This filter is used by FindMembers, and we just keep
1097 /// a global for the filter to `AlwaysAccept'
1099 static MemberFilter accepting_filter;
1103 /// A member comparission method based on name only
1105 static IComparer mif_compare;
1107 static TypeContainer ()
1109 accepting_filter = new MemberFilter (AlwaysAccept);
1110 mif_compare = new MemberInfoCompare ();
1114 /// This method returns the members of this type just like Type.FindMembers would
1115 /// Only, we need to use this for types which are _being_ defined because MS'
1116 /// implementation can't take care of that.
1119 // FIXME: return an empty static array instead of null, that cleans up
1120 // some code and is consistent with some coding conventions I just found
1124 // Notice that in various cases we check if our field is non-null,
1125 // something that would normally mean that there was a bug elsewhere.
1127 // The problem happens while we are defining p-invoke methods, as those
1128 // will trigger a FindMembers, but this happens before things are defined
1130 // Since the whole process is a no-op, it is fine to check for null here.
1132 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1133 MemberFilter filter, object criteria)
1135 ArrayList members = new ArrayList ();
1138 if ((bf & BindingFlags.Public) != 0)
1139 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1141 if ((bf & BindingFlags.NonPublic) != 0)
1142 modflags |= Modifiers.PRIVATE;
1144 int static_mask = 0, static_flags = 0;
1145 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1146 case BindingFlags.Static:
1147 static_mask = static_flags = Modifiers.STATIC;
1150 case BindingFlags.Instance:
1151 static_mask = Modifiers.STATIC;
1156 static_mask = static_flags = 0;
1160 Timer.StartTimer (TimerType.TcFindMembers);
1163 filter = accepting_filter;
1165 if ((mt & MemberTypes.Field) != 0) {
1166 if (fields != null) {
1167 foreach (Field f in fields) {
1168 if ((f.ModFlags & modflags) == 0)
1170 if ((f.ModFlags & static_mask) != static_flags)
1173 FieldBuilder fb = f.FieldBuilder;
1174 if (fb != null && filter (fb, criteria) == true)
1179 if (constants != null) {
1180 foreach (Const con in constants) {
1181 if ((con.ModFlags & modflags) == 0)
1183 if ((con.ModFlags & static_mask) != static_flags)
1186 FieldBuilder fb = con.FieldBuilder;
1187 if (fb != null && filter (fb, criteria) == true)
1193 if ((mt & MemberTypes.Method) != 0) {
1194 if (methods != null) {
1195 foreach (Method m in methods) {
1196 if ((m.ModFlags & modflags) == 0)
1198 if ((m.ModFlags & static_mask) != static_flags)
1201 MethodBuilder mb = m.MethodBuilder;
1203 if (mb != null && filter (mb, criteria) == true)
1208 if (operators != null){
1209 foreach (Operator o in operators) {
1210 if ((o.ModFlags & modflags) == 0)
1212 if ((o.ModFlags & static_mask) != static_flags)
1215 MethodBuilder ob = o.OperatorMethodBuilder;
1216 if (ob != null && filter (ob, criteria) == true)
1221 if (properties != null){
1222 foreach (Property p in properties){
1223 if ((p.ModFlags & modflags) == 0)
1225 if ((p.ModFlags & static_mask) != static_flags)
1231 if (b != null && filter (b, criteria) == true)
1235 if (b != null && filter (b, criteria) == true)
1240 if (indexers != null){
1241 foreach (Indexer ix in indexers){
1242 if ((ix.ModFlags & modflags) == 0)
1244 if ((ix.ModFlags & static_mask) != static_flags)
1250 if (b != null && filter (b, criteria) == true)
1254 if (b != null && filter (b, criteria) == true)
1260 if ((mt & MemberTypes.Event) != 0) {
1262 foreach (Event e in events) {
1263 if ((e.ModFlags & modflags) == 0)
1265 if ((e.ModFlags & static_mask) != static_flags)
1268 MemberInfo eb = e.EventBuilder;
1269 if (eb != null && filter (eb, criteria) == true)
1270 members.Add (e.EventBuilder);
1274 if ((mt & MemberTypes.Property) != 0){
1275 if (properties != null)
1276 foreach (Property p in properties) {
1277 if ((p.ModFlags & modflags) == 0)
1279 if ((p.ModFlags & static_mask) != static_flags)
1282 MemberInfo pb = p.PropertyBuilder;
1283 if (pb != null && filter (pb, criteria) == true) {
1284 members.Add (p.PropertyBuilder);
1288 if (indexers != null)
1289 foreach (Indexer ix in indexers) {
1290 if ((ix.ModFlags & modflags) == 0)
1292 if ((ix.ModFlags & static_mask) != static_flags)
1295 MemberInfo ib = ix.PropertyBuilder;
1296 if (ib != null && filter (ib, criteria) == true) {
1297 members.Add (ix.PropertyBuilder);
1302 if ((mt & MemberTypes.NestedType) != 0) {
1304 foreach (TypeContainer t in types) {
1305 if ((t.ModFlags & modflags) == 0)
1308 TypeBuilder tb = t.TypeBuilder;
1309 if (tb != null && (filter (tb, criteria) == true))
1315 foreach (Enum en in enums){
1316 if ((en.ModFlags & modflags) == 0)
1319 TypeBuilder tb = en.TypeBuilder;
1320 if (tb != null && (filter (tb, criteria) == true))
1325 if (delegates != null){
1326 foreach (Delegate d in delegates){
1327 if ((d.ModFlags & modflags) == 0)
1330 TypeBuilder tb = d.TypeBuilder;
1331 if (tb != null && (filter (tb, criteria) == true))
1336 if (interfaces != null){
1337 foreach (Interface iface in interfaces){
1338 if ((iface.ModFlags & modflags) == 0)
1341 TypeBuilder tb = iface.TypeBuilder;
1342 if (tb != null && (filter (tb, criteria) == true))
1348 if ((mt & MemberTypes.Constructor) != 0){
1349 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1350 foreach (Constructor c in instance_constructors){
1351 ConstructorBuilder cb = c.ConstructorBuilder;
1353 if (filter (cb, criteria) == true)
1358 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1359 ConstructorBuilder cb =
1360 default_static_constructor.ConstructorBuilder;
1363 if (filter (cb, criteria) == true)
1369 // Lookup members in parent if requested.
1371 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1372 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1373 members.AddRange (list);
1376 Timer.StopTimer (TimerType.TcFindMembers);
1378 return new MemberList (members);
1381 public override MemberCache MemberCache {
1383 return member_cache;
1387 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1388 MemberFilter filter, object criteria)
1390 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1393 return tc.FindMembers (mt, bf, filter, criteria);
1395 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1399 // FindMethods will look for methods not only in the type `t', but in
1400 // any interfaces implemented by the type.
1402 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1403 MemberFilter filter, object criteria)
1409 /// Emits the values for the constants
1411 public void EmitConstants ()
1413 if (constants != null)
1414 foreach (Const con in constants)
1415 con.EmitConstant (this);
1420 /// Emits the code, this step is performed after all
1421 /// the types, enumerations, constructors
1425 if (instance_constructors != null)
1426 foreach (Constructor c in instance_constructors)
1429 if (default_static_constructor != null)
1430 default_static_constructor.Emit (this);
1432 if (methods != null)
1433 foreach (Method m in methods)
1436 if (operators != null)
1437 foreach (Operator o in operators)
1440 if (properties != null)
1441 foreach (Property p in properties)
1444 if (indexers != null){
1445 foreach (Indexer ix in indexers)
1448 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1449 this, IndexerName, ModFlags, Location);
1450 TypeBuilder.SetCustomAttribute (cb);
1454 foreach (Field f in fields)
1457 if (events != null){
1458 foreach (Event e in Events)
1462 if (Pending != null)
1463 if (Pending.VerifyPendingMethods ())
1466 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1469 // Check for internal or private fields that were never assigned
1471 if (fields != null && RootContext.WarningLevel >= 3) {
1472 foreach (Field f in fields) {
1473 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1478 169, f.Location, "Private field " +
1479 MakeName (f.Name) + " is never used");
1484 // Only report 649 on level 4
1486 if (RootContext.WarningLevel < 4)
1489 if ((f.status & Field.Status.ASSIGNED) != 0)
1494 "Field " + MakeName (f.Name) + " is never assigned " +
1495 " to and will always have its default value");
1499 // if (types != null)
1500 // foreach (TypeContainer tc in types)
1504 public override void CloseType ()
1509 TypeBuilder.CreateType ();
1511 } catch (TypeLoadException){
1513 // This is fine, the code still created the type
1515 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1516 // Console.WriteLine (e.Message);
1518 Console.WriteLine ("In type: " + Name);
1523 foreach (Enum en in Enums)
1526 if (interface_order != null){
1527 foreach (Interface iface in interface_order)
1532 foreach (TypeContainer tc in Types)
1536 foreach (TypeContainer tc in Types)
1537 if (!(tc is Struct))
1541 if (Delegates != null)
1542 foreach (Delegate d in Delegates)
1546 public string MakeName (string n)
1548 return "`" + Name + "." + n + "'";
1551 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1554 108, l, "The keyword new is required on " +
1555 MakeName (mi.Name) + " because it hides `" +
1556 mi.ReflectedType.Name + "." + mi.Name + "'");
1559 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1562 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1563 "inherited member, the keyword new is not required");
1566 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1572 // Performs the validation on a Method's modifiers (properties have
1573 // the same properties).
1575 public bool MethodModifiersValid (int flags, string n, Location loc)
1577 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1578 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1579 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1581 string name = MakeName (n);
1584 // At most one of static, virtual or override
1586 if ((flags & Modifiers.STATIC) != 0){
1587 if ((flags & vao) != 0){
1589 112, loc, "static method " + name + "can not be marked " +
1590 "as virtual, abstract or override");
1595 if (this is Struct){
1596 if ((flags & va) != 0){
1597 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1602 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1605 " marked as override cannot be marked as new or virtual");
1610 // If the declaration includes the abstract modifier, then the
1611 // declaration does not include static, virtual or extern
1613 if ((flags & Modifiers.ABSTRACT) != 0){
1614 if ((flags & Modifiers.EXTERN) != 0){
1616 180, loc, name + " can not be both abstract and extern");
1620 if ((flags & Modifiers.VIRTUAL) != 0){
1622 503, loc, name + " can not be both abstract and virtual");
1626 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1629 " is abstract but its container class is not");
1635 if ((flags & Modifiers.PRIVATE) != 0){
1636 if ((flags & vao) != 0){
1639 " virtual or abstract members can not be private");
1644 if ((flags & Modifiers.SEALED) != 0){
1645 if ((flags & Modifiers.OVERRIDE) == 0){
1648 " cannot be sealed because it is not an override");
1656 // Access level of a type.
1659 ProtectedInternal = 1,
1665 // Check whether `flags' denotes a more restricted access than `level'
1666 // and return the new level.
1667 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1669 AccessLevel old_level = level;
1671 if ((flags & Modifiers.INTERNAL) != 0) {
1672 if ((flags & Modifiers.PROTECTED) != 0) {
1673 if ((int) level < (int) AccessLevel.ProtectedInternal)
1674 level = AccessLevel.ProtectedInternal;
1676 if ((int) level < (int) AccessLevel.Internal)
1677 level = AccessLevel.Internal;
1679 } else if ((flags & Modifiers.PROTECTED) != 0) {
1680 if ((int) level < (int) AccessLevel.Protected)
1681 level = AccessLevel.Protected;
1682 } else if ((flags & Modifiers.PRIVATE) != 0)
1683 level = AccessLevel.Private;
1688 // Return the access level for a new member which is defined in the current
1689 // TypeContainer with access modifiers `flags'.
1690 AccessLevel GetAccessLevel (int flags)
1692 if ((flags & Modifiers.PRIVATE) != 0)
1693 return AccessLevel.Private;
1696 if (!IsTopLevel && (Parent != null))
1697 level = Parent.GetAccessLevel (flags);
1699 level = AccessLevel.Public;
1701 return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1704 // Return the access level for type `t', but don't give more access than `flags'.
1705 static AccessLevel GetAccessLevel (Type t, int flags)
1707 if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1708 return AccessLevel.Private;
1711 if (TypeManager.IsBuiltinType (t))
1712 return AccessLevel.Public;
1713 else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1714 level = GetAccessLevel (t.DeclaringType, flags);
1716 level = CheckAccessLevel (AccessLevel.Public, flags);
1719 if (t.IsNestedPublic)
1722 if (t.IsNestedAssembly || t.IsNotPublic) {
1723 if ((int) level < (int) AccessLevel.Internal)
1724 level = AccessLevel.Internal;
1727 if (t.IsNestedFamily) {
1728 if ((int) level < (int) AccessLevel.Protected)
1729 level = AccessLevel.Protected;
1732 if (t.IsNestedFamORAssem) {
1733 if ((int) level < (int) AccessLevel.ProtectedInternal)
1734 level = AccessLevel.ProtectedInternal;
1741 // Returns true if `parent' is as accessible as the flags `flags'
1742 // given for this member.
1744 public bool AsAccessible (Type parent, int flags)
1746 while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1747 parent = parent.GetElementType ();
1749 AccessLevel level = GetAccessLevel (flags);
1750 AccessLevel level2 = GetAccessLevel (parent, flags);
1752 return (int) level >= (int) level2;
1755 Hashtable builder_and_args;
1757 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1759 if (builder_and_args == null)
1760 builder_and_args = new Hashtable ();
1765 /// Performs checks for an explicit interface implementation. First it
1766 /// checks whether the `interface_type' is a base inteface implementation.
1767 /// Then it checks whether `name' exists in the interface type.
1769 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1773 if (ifaces != null){
1774 foreach (Type t in ifaces){
1775 if (t == interface_type){
1783 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1790 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1792 Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1799 string IMemberContainer.Name {
1805 Type IMemberContainer.Type {
1811 IMemberContainer IMemberContainer.Parent {
1813 return parent_container;
1817 MemberCache IMemberContainer.MemberCache {
1819 return member_cache;
1823 bool IMemberContainer.IsInterface {
1829 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1831 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1835 // Operator pair checking
1838 class OperatorEntry {
1840 public Type ret_type;
1841 public Type type1, type2;
1843 public Operator.OpType ot;
1845 public OperatorEntry (int f, Operator o)
1849 ret_type = o.OperatorMethod.GetReturnType ();
1850 Type [] pt = o.OperatorMethod.ParameterTypes;
1854 ot = o.OperatorType;
1857 public override int GetHashCode ()
1859 return ret_type.GetHashCode ();
1862 public override bool Equals (object o)
1864 OperatorEntry other = (OperatorEntry) o;
1866 if (other.ret_type != ret_type)
1868 if (other.type1 != type1)
1870 if (other.type2 != type2)
1877 // Checks that some operators come in pairs:
1882 // They are matched based on the return type and the argument types
1884 void CheckPairedOperators ()
1886 Hashtable pairs = new Hashtable (null, null);
1888 // Register all the operators we care about.
1889 foreach (Operator op in operators){
1892 switch (op.OperatorType){
1893 case Operator.OpType.Equality:
1895 case Operator.OpType.Inequality:
1898 case Operator.OpType.GreaterThan:
1900 case Operator.OpType.LessThan:
1903 case Operator.OpType.GreaterThanOrEqual:
1905 case Operator.OpType.LessThanOrEqual:
1911 OperatorEntry oe = new OperatorEntry (reg, op);
1913 object o = pairs [oe];
1917 oe = (OperatorEntry) o;
1923 // Look for the mistakes.
1925 foreach (DictionaryEntry de in pairs){
1926 OperatorEntry oe = (OperatorEntry) de.Key;
1933 case Operator.OpType.Equality:
1936 case Operator.OpType.Inequality:
1939 case Operator.OpType.GreaterThan:
1942 case Operator.OpType.LessThan:
1945 case Operator.OpType.GreaterThanOrEqual:
1948 case Operator.OpType.LessThanOrEqual:
1952 Report.Error (216, oe.op.Location,
1953 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
1960 public class Class : TypeContainer {
1962 // Modifiers allowed in a class declaration
1964 public const int AllowedModifiers =
1967 Modifiers.PROTECTED |
1968 Modifiers.INTERNAL |
1970 Modifiers.ABSTRACT |
1974 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1975 : base (parent, name, l)
1979 if (parent.Parent == null)
1980 accmods = Modifiers.INTERNAL;
1982 accmods = Modifiers.PRIVATE;
1984 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1985 this.attributes = attrs;
1989 // FIXME: How do we deal with the user specifying a different
1992 public override TypeAttributes TypeAttr {
1994 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1999 public class Struct : TypeContainer {
2001 // Modifiers allowed in a struct declaration
2003 public const int AllowedModifiers =
2006 Modifiers.PROTECTED |
2007 Modifiers.INTERNAL |
2011 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2012 : base (parent, name, l)
2016 if (parent.Parent == null)
2017 accmods = Modifiers.INTERNAL;
2019 accmods = Modifiers.PRIVATE;
2021 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2023 this.ModFlags |= Modifiers.SEALED;
2024 this.attributes = attrs;
2029 // FIXME: Allow the user to specify a different set of attributes
2030 // in some cases (Sealed for example is mandatory for a class,
2031 // but what SequentialLayout can be changed
2033 public override TypeAttributes TypeAttr {
2035 return base.TypeAttr |
2036 TypeAttributes.SequentialLayout |
2037 TypeAttributes.Sealed |
2038 TypeAttributes.BeforeFieldInit;
2043 public abstract class MethodCore : MemberBase {
2044 public /* readonly */ Parameters Parameters;
2048 // Parameters, cached for semantic analysis.
2050 protected InternalParameters parameter_info;
2051 protected Type [] parameter_types;
2053 public MethodCore (Expression type, int mod, int allowed_mod, string name,
2054 Attributes attrs, Parameters parameters, Location loc)
2055 : base (type, mod, allowed_mod, name, attrs, loc)
2057 Parameters = parameters;
2061 // Returns the System.Type array for the parameters of this method
2063 public Type [] ParameterTypes {
2065 return parameter_types;
2069 public InternalParameters ParameterInfo
2072 return parameter_info;
2076 public Block Block {
2086 protected virtual bool DoDefineParameters (TypeContainer parent)
2088 // Check if arguments were correct
2089 parameter_types = Parameters.GetParameterInfo (parent);
2090 if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
2093 parameter_info = new InternalParameters (parent, Parameters);
2098 public CallingConventions GetCallingConvention (bool is_class)
2100 CallingConventions cc = 0;
2102 cc = Parameters.GetCallingConvention ();
2105 if ((ModFlags & Modifiers.STATIC) == 0)
2106 cc |= CallingConventions.HasThis;
2108 // FIXME: How is `ExplicitThis' used in C#?
2113 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
2115 LabelParameters (ec, parameters, builder, null);
2118 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder, Parameters p_params)
2121 // Define each type attribute (in/out/ref) and
2122 // the argument names.
2124 Parameter [] p = p_params == null ? Parameters.FixedParameters : p_params.FixedParameters;
2127 MethodBuilder mb = null;
2128 ConstructorBuilder cb = null;
2130 if (builder is MethodBuilder)
2131 mb = (MethodBuilder) builder;
2133 cb = (ConstructorBuilder) builder;
2136 for (i = 0; i < p.Length; i++) {
2137 ParameterBuilder pb;
2140 pb = cb.DefineParameter (
2141 i + 1, p [i].Attributes, p [i].Name);
2143 pb = mb.DefineParameter (
2144 i + 1, p [i].Attributes, p [i].Name);
2146 Attributes attr = p [i].OptAttributes;
2148 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
2152 if (Parameters.ArrayParameter != null){
2153 ParameterBuilder pb;
2154 Parameter array_param = Parameters.ArrayParameter;
2157 pb = cb.DefineParameter (
2158 i + 1, array_param.Attributes,
2161 pb = mb.DefineParameter (
2162 i + 1, array_param.Attributes,
2165 CustomAttributeBuilder a = new CustomAttributeBuilder (
2166 TypeManager.cons_param_array_attribute, new object [0]);
2168 pb.SetCustomAttribute (a);
2173 public class Method : MethodCore {
2174 public MethodBuilder MethodBuilder;
2175 public MethodData MethodData;
2178 /// Modifiers allowed in a class declaration
2180 const int AllowedModifiers =
2183 Modifiers.PROTECTED |
2184 Modifiers.INTERNAL |
2189 Modifiers.OVERRIDE |
2190 Modifiers.ABSTRACT |
2195 // return_type can be "null" for VOID values.
2197 public Method (Expression return_type, int mod, string name, Parameters parameters,
2198 Attributes attrs, Location l)
2199 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2204 public Method (Expression return_type, int mod, string name, Parameters parameters,
2205 Attributes attrs, Expression impl_what, Location l)
2206 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2208 Implements = impl_what;
2212 // Returns the `System.Type' for the ReturnType of this
2213 // function. Provides a nice cache. (used between semantic analysis
2214 // and actual code generation
2216 public Type GetReturnType ()
2221 // Whether this is an operator method.
2222 public bool IsOperator;
2224 void DuplicateEntryPoint (MethodInfo b, Location location)
2228 "Program `" + CodeGen.FileName +
2229 "' has more than one entry point defined: `" +
2230 TypeManager.CSharpSignature(b) + "'");
2233 void Report28 (MethodInfo b)
2235 if (RootContext.WarningLevel < 4)
2240 "`" + TypeManager.CSharpSignature(b) +
2241 "' has the wrong signature to be an entry point");
2244 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2246 if (b.ReturnType != TypeManager.void_type &&
2247 b.ReturnType != TypeManager.int32_type)
2250 if (pinfo.Count == 0)
2253 if (pinfo.Count > 1)
2256 Type t = pinfo.ParameterType(0);
2258 (t.GetArrayRank() == 1) &&
2259 (t.GetElementType() == TypeManager.string_type) &&
2260 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2267 // Checks our base implementation if any
2269 protected override bool CheckBase (TypeContainer parent)
2271 // Check whether arguments were correct.
2272 if (!DoDefineParameters (parent))
2275 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2279 mi_this = TypeContainer.FindMembers (
2280 parent.TypeBuilder, MemberTypes.Method,
2281 BindingFlags.NonPublic | BindingFlags.Public |
2282 BindingFlags.Static | BindingFlags.Instance |
2283 BindingFlags.DeclaredOnly,
2284 MethodSignature.method_signature_filter, ms);
2286 if (mi_this.Count > 0) {
2287 Report.Error (111, Location, "Class `" + parent.Name + "' " +
2288 "already defines a member called `" + Name + "' " +
2289 "with the same parameter types");
2295 // Verify if the parent has a type with the same name, and then
2296 // check whether we have to create a new slot for it or not.
2298 Type ptype = parent.TypeBuilder.BaseType;
2300 // ptype is only null for System.Object while compiling corlib.
2302 MemberList mi, mi_static, mi_instance;
2304 mi_static = TypeContainer.FindMembers (
2305 ptype, MemberTypes.Method,
2306 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2307 MethodSignature.inheritable_method_signature_filter, ms);
2309 mi_instance = TypeContainer.FindMembers (
2310 ptype, MemberTypes.Method,
2311 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2312 MethodSignature.inheritable_method_signature_filter,
2315 if (mi_instance.Count > 0){
2317 } else if (mi_static.Count > 0)
2322 if (mi != null && mi.Count > 0){
2323 parent_method = (MethodInfo) mi [0];
2324 string name = parent_method.DeclaringType.Name + "." +
2327 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2330 if ((ModFlags & Modifiers.NEW) == 0) {
2331 Type parent_ret = TypeManager.TypeToCoreType (
2332 parent_method.ReturnType);
2334 if (parent_ret != MemberType) {
2336 508, parent.MakeName (Name) + ": cannot " +
2337 "change return type when overriding " +
2338 "inherited member " + name);
2343 if ((ModFlags & Modifiers.NEW) != 0)
2344 WarningNotHiding (parent);
2346 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2347 Report.Error (115, Location,
2348 parent.MakeName (Name) +
2349 " no suitable methods found to override");
2352 } else if ((ModFlags & Modifiers.NEW) != 0)
2353 WarningNotHiding (parent);
2361 public override bool Define (TypeContainer parent)
2363 if (!DoDefine (parent))
2366 if (!CheckBase (parent))
2369 CallingConventions cc = GetCallingConvention (parent is Class);
2371 MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2372 ParameterInfo, cc, OptAttributes,
2373 ModFlags, flags, true);
2375 if (!MethodData.Define (parent))
2378 MethodBuilder = MethodData.MethodBuilder;
2381 // This is used to track the Entry Point,
2383 if (Name == "Main" &&
2384 ((ModFlags & Modifiers.STATIC) != 0) &&
2385 (RootContext.MainClass == null ||
2386 RootContext.MainClass == parent.TypeBuilder.FullName ||
2387 (RootContext.RootNamespace != null &&
2388 RootContext.RootNamespace.Length > 0 &&
2389 (RootContext.RootNamespace + "." + RootContext.MainClass) == parent.TypeBuilder.FullName))) {
2390 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2391 if (RootContext.EntryPoint == null) {
2392 RootContext.EntryPoint = MethodBuilder;
2393 RootContext.EntryPointLocation = Location;
2395 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2396 DuplicateEntryPoint (MethodBuilder, Location);
2399 Report28(MethodBuilder);
2408 public void Emit (TypeContainer parent)
2410 MethodData.Emit (parent, Block, this);
2414 public abstract class ConstructorInitializer {
2415 ArrayList argument_list;
2416 ConstructorInfo parent_constructor;
2417 Parameters parameters;
2420 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2423 this.argument_list = argument_list;
2424 this.parameters = parameters;
2428 public ArrayList Arguments {
2430 return argument_list;
2434 public bool Resolve (EmitContext ec)
2436 Expression parent_constructor_group;
2439 ec.CurrentBlock = new Block (null, true, parameters);
2441 if (argument_list != null){
2442 foreach (Argument a in argument_list){
2443 if (!a.Resolve (ec, loc))
2448 ec.CurrentBlock = null;
2450 if (this is ConstructorBaseInitializer) {
2451 if (ec.ContainerType.BaseType == null)
2454 t = ec.ContainerType.BaseType;
2455 if (ec.ContainerType.IsValueType) {
2456 Report.Error (522, loc,
2457 "structs cannot call base class constructors");
2461 t = ec.ContainerType;
2463 parent_constructor_group = Expression.MemberLookup (
2465 MemberTypes.Constructor,
2466 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2469 if (parent_constructor_group == null){
2470 Report.Error (1501, loc,
2471 "Can not find a constructor for this argument list");
2475 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2476 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2478 if (parent_constructor == null){
2479 Report.Error (1501, loc,
2480 "Can not find a constructor for this argument list");
2487 public void Emit (EmitContext ec)
2489 if (parent_constructor != null){
2491 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2493 Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2498 public class ConstructorBaseInitializer : ConstructorInitializer {
2499 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2500 base (argument_list, pars, l)
2505 public class ConstructorThisInitializer : ConstructorInitializer {
2506 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2507 base (argument_list, pars, l)
2512 public class Constructor : MethodCore {
2513 public ConstructorBuilder ConstructorBuilder;
2514 public ConstructorInitializer Initializer;
2515 new public Attributes OptAttributes;
2518 // Modifiers allowed for a constructor.
2520 public const int AllowedModifiers =
2522 Modifiers.PROTECTED |
2523 Modifiers.INTERNAL |
2530 // The spec claims that static is not permitted, but
2531 // my very own code has static constructors.
2533 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2534 : base (null, 0, AllowedModifiers, name, null, args, l)
2540 // Returns true if this is a default constructor
2542 public bool IsDefault ()
2544 if ((ModFlags & Modifiers.STATIC) != 0)
2545 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2546 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2549 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2550 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2551 (Initializer is ConstructorBaseInitializer) &&
2552 (Initializer.Arguments == null);
2556 // Creates the ConstructorBuilder
2558 public override bool Define (TypeContainer parent)
2560 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2561 MethodAttributes.SpecialName);
2563 // Check if arguments were correct.
2564 if (!DoDefineParameters (parent))
2567 if ((ModFlags & Modifiers.STATIC) != 0)
2568 ca |= MethodAttributes.Static;
2570 if (parent is Struct && ParameterTypes.Length == 0){
2573 "Structs can not contain explicit parameterless " +
2577 ca |= MethodAttributes.HideBySig;
2579 if ((ModFlags & Modifiers.PUBLIC) != 0)
2580 ca |= MethodAttributes.Public;
2581 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2582 if ((ModFlags & Modifiers.INTERNAL) != 0)
2583 ca |= MethodAttributes.FamORAssem;
2585 ca |= MethodAttributes.Family;
2586 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2587 ca |= MethodAttributes.Assembly;
2588 else if (IsDefault ())
2589 ca |= MethodAttributes.Public;
2591 ca |= MethodAttributes.Private;
2594 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2595 ca, GetCallingConvention (parent is Class), ParameterTypes);
2598 // HACK because System.Reflection.Emit is lame
2600 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2603 "Class `" +parent.Name+ "' already contains a definition with the " +
2604 "same return value and parameter types for constructor `" + Name
2615 public void Emit (TypeContainer parent)
2617 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2618 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2620 if ((ModFlags & Modifiers.STATIC) == 0){
2621 if (parent is Class && Initializer == null)
2622 Initializer = new ConstructorBaseInitializer (
2623 null, Parameters.EmptyReadOnlyParameters, parent.Location);
2627 // Spec mandates that Initializers will not have
2631 if (Initializer != null && !Initializer.Resolve (ec))
2633 ec.IsStatic = false;
2636 LabelParameters (ec, ParameterTypes, ConstructorBuilder);
2639 // Classes can have base initializers and instance field initializers.
2641 if (parent is Class){
2642 if ((ModFlags & Modifiers.STATIC) == 0)
2643 parent.EmitFieldInitializers (ec);
2645 if (Initializer != null)
2646 Initializer.Emit (ec);
2648 if ((ModFlags & Modifiers.STATIC) != 0)
2649 parent.EmitFieldInitializers (ec);
2651 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2653 // If this is a non-static `struct' constructor and doesn't have any
2654 // initializer, it must initialize all of the struct's fields.
2655 if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2656 (Initializer == null))
2657 Block.AddThisVariable (parent, Location);
2659 ec.EmitTopBlock (Block, ParameterInfo, Location);
2663 public class MethodData {
2665 // The return type of this method
2667 public readonly Type ReturnType;
2668 public readonly Type[] ParameterTypes;
2669 public readonly InternalParameters ParameterInfo;
2670 public readonly CallingConventions CallingConventions;
2671 public readonly Attributes OptAttributes;
2672 public readonly Location Location;
2675 // Are we implementing an interface ?
2677 public bool IsImplementing = false;
2682 protected MemberBase member;
2683 protected int modifiers;
2684 protected MethodAttributes flags;
2685 protected bool is_method;
2686 protected string accessor_name;
2687 ArrayList conditionals;
2689 MethodBuilder builder = null;
2690 public MethodBuilder MethodBuilder {
2696 public MethodData (MemberBase member, string name, Type return_type,
2697 Type [] parameter_types, InternalParameters parameters,
2698 CallingConventions cc, Attributes opt_attrs,
2699 int modifiers, MethodAttributes flags, bool is_method)
2701 this.member = member;
2702 this.accessor_name = name;
2703 this.ReturnType = return_type;
2704 this.ParameterTypes = parameter_types;
2705 this.ParameterInfo = parameters;
2706 this.CallingConventions = cc;
2707 this.OptAttributes = opt_attrs;
2708 this.modifiers = modifiers;
2710 this.is_method = is_method;
2711 this.Location = member.Location;
2712 this.conditionals = new ArrayList ();
2718 Attribute dllimport_attribute = null;
2719 string obsolete = null;
2720 bool obsolete_error = false;
2722 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2724 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2727 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2728 if (asec.Attributes == null)
2731 foreach (Attribute a in asec.Attributes) {
2732 if (a.Name == "Conditional") {
2733 if (!ApplyConditionalAttribute (a))
2735 } else if (a.Name == "Obsolete") {
2736 if (!ApplyObsoleteAttribute (a))
2738 } else if (a.Name.IndexOf ("DllImport") != -1) {
2740 a.Type = TypeManager.dllimport_type;
2741 Attribute.Error_AttributeNotValidForElement (a, Location);
2744 if (!ApplyDllImportAttribute (a))
2754 // Applies the `DllImport' attribute to the method.
2756 protected virtual bool ApplyDllImportAttribute (Attribute a)
2758 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2759 if ((modifiers & extern_static) != extern_static) {
2760 Report.Error (601, Location,
2761 "The DllImport attribute must be specified on a method " +
2762 "marked `static' and `extern'.");
2766 flags |= MethodAttributes.PinvokeImpl;
2767 dllimport_attribute = a;
2772 // Applies the `Obsolete' attribute to the method.
2774 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2776 if (obsolete != null) {
2777 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2781 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2782 return obsolete != null;
2786 // Applies the `Conditional' attribute to the method.
2788 protected virtual bool ApplyConditionalAttribute (Attribute a)
2790 // The Conditional attribute is only valid on methods.
2792 Attribute.Error_AttributeNotValidForElement (a, Location);
2796 string condition = a.Conditional_GetConditionName ();
2798 if (condition == null)
2801 if (ReturnType != TypeManager.void_type) {
2802 Report.Error (578, Location,
2803 "Conditional not valid on `" + member.Name + "' " +
2804 "because its return type is not void");
2808 if ((modifiers & Modifiers.OVERRIDE) != 0) {
2809 Report.Error (243, Location,
2810 "Conditional not valid on `" + member.Name + "' " +
2811 "because it is an override method");
2815 if (member.IsExplicitImpl) {
2816 Report.Error (577, Location,
2817 "Conditional not valid on `" + member.Name + "' " +
2818 "because it is an explicit interface implementation");
2822 if (IsImplementing) {
2823 Report.Error (623, Location,
2824 "Conditional not valid on `" + member.Name + "' " +
2825 "because it is an interface method");
2829 conditionals.Add (condition);
2835 // Checks whether this method should be ignored due to its Conditional attributes.
2837 bool ShouldIgnore (Location loc)
2839 // When we're overriding a virtual method, we implicitly inherit the
2840 // Conditional attributes from our parent.
2841 if (member.ParentMethod != null) {
2842 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2843 member.ParentMethod, loc);
2845 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2849 foreach (string condition in conditionals)
2850 if (RootContext.AllDefines [condition] == null)
2857 // Returns the TypeManager.MethodFlags for this method.
2858 // This emits an error 619 / warning 618 if the method is obsolete.
2859 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2861 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2863 TypeManager.MethodFlags flags = 0;
2865 if (obsolete != null) {
2866 if (obsolete_error) {
2867 Report.Error (619, loc, "Method `" + member.Name +
2868 "' is obsolete: `" + obsolete + "'");
2869 return TypeManager.MethodFlags.IsObsoleteError;
2871 Report.Warning (618, loc, "Method `" + member.Name +
2872 "' is obsolete: `" + obsolete + "'");
2874 flags |= TypeManager.MethodFlags.IsObsolete;
2877 if (ShouldIgnore (loc))
2878 flags |= TypeManager.MethodFlags.ShouldIgnore;
2883 public virtual bool Define (TypeContainer parent)
2885 MethodInfo implementing = null;
2886 string method_name, name, prefix;
2888 if (OptAttributes != null)
2889 if (!ApplyAttributes (OptAttributes, is_method))
2892 if (member.IsExplicitImpl)
2893 prefix = member.InterfaceType.FullName + ".";
2897 if (accessor_name != null)
2898 name = accessor_name + "_" + member.ShortName;
2900 name = member.ShortName;
2901 method_name = prefix + name;
2903 if (parent.Pending != null){
2904 if (member is Indexer)
2905 implementing = parent.Pending.IsInterfaceIndexer (
2906 member.InterfaceType, ReturnType, ParameterTypes);
2908 implementing = parent.Pending.IsInterfaceMethod (
2909 member.InterfaceType, name, ReturnType, ParameterTypes);
2911 if (member.InterfaceType != null && implementing == null){
2912 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
2919 // For implicit implementations, make sure we are public, for
2920 // explicit implementations, make sure we are private.
2922 if (implementing != null){
2924 // Setting null inside this block will trigger a more
2925 // verbose error reporting for missing interface implementations
2927 // The "candidate" function has been flagged already
2928 // but it wont get cleared
2930 if (!member.IsExplicitImpl){
2932 // We already catch different accessibility settings
2933 // so we just need to check that we are not private
2935 if ((modifiers & Modifiers.PRIVATE) != 0)
2936 implementing = null;
2939 // Static is not allowed
2941 if ((modifiers & Modifiers.STATIC) != 0)
2942 implementing = null;
2944 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
2945 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
2946 implementing = null;
2952 // If implementing is still valid, set flags
2954 if (implementing != null){
2956 // When implementing interface methods, set NewSlot.
2958 if (implementing.DeclaringType.IsInterface)
2959 flags |= MethodAttributes.NewSlot;
2962 MethodAttributes.Virtual |
2963 MethodAttributes.HideBySig;
2965 // Get the method name from the explicit interface.
2966 if (member.InterfaceType != null) {
2967 name = implementing.Name;
2968 method_name = prefix + name;
2971 IsImplementing = true;
2975 // Create the MethodBuilder for the method
2977 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2978 if ((modifiers & Modifiers.STATIC) == 0) {
2979 Report.Error (601, Location,
2980 "The DllImport attribute must be specified on " +
2981 "a method marked 'static' and 'extern'.");
2985 EmitContext ec = new EmitContext (
2986 parent, Location, null, ReturnType, modifiers);
2988 builder = dllimport_attribute.DefinePInvokeMethod (
2989 ec, parent.TypeBuilder, method_name, flags,
2990 ReturnType, ParameterTypes);
2992 builder = parent.TypeBuilder.DefineMethod (
2993 method_name, flags, CallingConventions,
2994 ReturnType, ParameterTypes);
2996 if (builder == null)
2999 if (IsImplementing) {
3001 // clear the pending implemntation flag
3003 if (member is Indexer) {
3004 parent.Pending.ImplementIndexer (
3005 member.InterfaceType, builder, ReturnType,
3006 ParameterTypes, true);
3008 parent.Pending.ImplementMethod (
3009 member.InterfaceType, name, ReturnType,
3010 ParameterTypes, member.IsExplicitImpl);
3012 if (member.IsExplicitImpl)
3013 parent.TypeBuilder.DefineMethodOverride (
3014 builder, implementing);
3017 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3018 Report.Error (111, Location,
3019 "Class `" + parent.Name +
3020 "' already contains a definition with the " +
3021 "same return value and parameter types as the " +
3022 "'get' method of property `" + member.Name + "'");
3026 TypeManager.AddMethod (builder, this);
3034 public virtual void Emit (TypeContainer parent, Block block, object kind)
3039 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3040 ig = builder.GetILGenerator ();
3044 ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3046 if (OptAttributes != null)
3047 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
3049 if (member is MethodCore)
3050 ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder);
3053 // abstract or extern methods have no bodies
3055 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3060 // abstract or extern methods have no bodies.
3062 if ((modifiers & Modifiers.ABSTRACT) != 0)
3064 500, Location, "Abstract method `" +
3065 TypeManager.CSharpSignature (builder) +
3066 "' can not have a body");
3068 if ((modifiers & Modifiers.EXTERN) != 0)
3070 179, Location, "External method `" +
3071 TypeManager.CSharpSignature (builder) +
3072 "' can not have a body");
3078 // Methods must have a body unless they're extern or abstract
3080 if (block == null) {
3082 501, Location, "Method `" +
3083 TypeManager.CSharpSignature (builder) +
3084 "' must declare a body since it is not marked " +
3085 "abstract or extern");
3090 // Handle destructors specially
3092 // FIXME: This code generates buggy code
3094 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3095 EmitDestructor (ec, block);
3097 ISymbolWriter sw = CodeGen.SymbolWriter;
3099 if ((sw != null) && !Location.IsNull (Location) &&
3100 !Location.IsNull (block.EndLocation)) {
3101 Location end = block.EndLocation;
3102 MethodToken token = MethodBuilder.GetToken ();
3103 sw.OpenMethod (new SymbolToken (token.Token));
3104 // Avoid error if we don't support debugging for the platform
3106 sw.SetMethodSourceRange (Location.SymbolDocument,
3110 } catch (Exception) {
3113 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3117 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3121 void EmitDestructor (EmitContext ec, Block block)
3123 ILGenerator ig = ec.ig;
3125 Label finish = ig.DefineLabel ();
3126 bool old_in_try = ec.InTry;
3128 ig.BeginExceptionBlock ();
3130 ec.ReturnLabel = finish;
3131 ec.HasReturnLabel = true;
3132 ec.EmitTopBlock (block, null, Location);
3133 ec.InTry = old_in_try;
3135 // ig.MarkLabel (finish);
3136 bool old_in_finally = ec.InFinally;
3137 ec.InFinally = true;
3138 ig.BeginFinallyBlock ();
3140 if (ec.ContainerType.BaseType != null) {
3141 Expression member_lookup = Expression.MemberLookup (
3142 ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
3143 MemberTypes.Method, Expression.AllBindingFlags, Location);
3145 if (member_lookup != null){
3146 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3148 ig.Emit (OpCodes.Ldarg_0);
3149 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3152 ec.InFinally = old_in_finally;
3154 ig.EndExceptionBlock ();
3155 //ig.MarkLabel (ec.ReturnLabel);
3156 ig.Emit (OpCodes.Ret);
3160 abstract public class MemberBase : MemberCore {
3161 public Expression Type;
3162 public readonly Attributes OptAttributes;
3163 public Expression Implements;
3165 protected MethodAttributes flags;
3168 // The "short" name of this property / indexer / event. This is the
3169 // name without the explicit interface.
3171 public string ShortName;
3174 // The type of this property / indexer / event
3176 public Type MemberType;
3179 // If true, this is an explicit interface implementation
3181 public bool IsExplicitImpl = false;
3184 // The name of the interface we are explicitly implementing
3186 public string ExplicitInterfaceName = null;
3189 // If true, the interface type we are explicitly implementing
3191 public Type InterfaceType = null;
3194 // The method we're overriding if this is an override method.
3196 protected MethodInfo parent_method = null;
3197 public MethodInfo ParentMethod {
3199 return parent_method;
3204 // The constructor is only exposed to our children
3206 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3207 Attributes attrs, Location loc)
3211 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
3212 OptAttributes = attrs;
3215 protected virtual bool CheckBase (TypeContainer parent)
3220 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3224 foreach (Type partype in parameters){
3225 if (partype.IsPointer && !UnsafeOK (parent))
3228 if (parent.AsAccessible (partype, ModFlags))
3231 if (this is Indexer)
3232 Report.Error (55, Location,
3233 "Inconsistent accessibility: parameter type `" +
3234 TypeManager.CSharpName (partype) + "' is less " +
3235 "accessible than indexer `" + Name + "'");
3237 Report.Error (51, Location,
3238 "Inconsistent accessibility: parameter type `" +
3239 TypeManager.CSharpName (partype) + "' is less " +
3240 "accessible than method `" + Name + "'");
3247 protected virtual bool DoDefine (TypeContainer parent)
3252 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3255 flags = Modifiers.MethodAttr (ModFlags);
3257 // Lookup Type, verify validity
3258 MemberType = parent.ResolveType (Type, false, Location);
3259 if (MemberType == null)
3262 // verify accessibility
3263 if (!parent.AsAccessible (MemberType, ModFlags)) {
3264 if (this is Property)
3265 Report.Error (53, Location,
3266 "Inconsistent accessibility: property type `" +
3267 TypeManager.CSharpName (MemberType) + "' is less " +
3268 "accessible than property `" + Name + "'");
3269 else if (this is Indexer)
3270 Report.Error (54, Location,
3271 "Inconsistent accessibility: indexer return type `" +
3272 TypeManager.CSharpName (MemberType) + "' is less " +
3273 "accessible than indexer `" + Name + "'");
3274 else if (this is Method)
3275 Report.Error (50, Location,
3276 "Inconsistent accessibility: return type `" +
3277 TypeManager.CSharpName (MemberType) + "' is less " +
3278 "accessible than method `" + Name + "'");
3280 Report.Error (52, Location,
3281 "Inconsistent accessibility: field type `" +
3282 TypeManager.CSharpName (MemberType) + "' is less " +
3283 "accessible than field `" + Name + "'");
3287 if (MemberType.IsPointer && !UnsafeOK (parent))
3291 // Check for explicit interface implementation
3293 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
3294 int pos = Name.LastIndexOf (".");
3296 ExplicitInterfaceName = Name.Substring (0, pos);
3297 ShortName = Name.Substring (pos + 1);
3301 if (ExplicitInterfaceName != null) {
3302 InterfaceType = RootContext.LookupType (
3303 parent, ExplicitInterfaceName, false, Location);
3304 if (InterfaceType == null)
3307 // Compute the full name that we need to export.
3308 Name = InterfaceType.FullName + "." + ShortName;
3310 if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
3313 IsExplicitImpl = true;
3315 IsExplicitImpl = false;
3322 // Fields and Events both generate FieldBuilders, we use this to share
3323 // their common bits. This is also used to flag usage of the field
3325 abstract public class FieldBase : MemberBase {
3326 public FieldBuilder FieldBuilder;
3327 public Status status;
3330 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3333 // The constructor is only exposed to our children
3335 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3336 object init, Attributes attrs, Location loc)
3337 : base (type, mod, allowed_mod, name, attrs, loc)
3343 // Whether this field has an initializer.
3345 public bool HasInitializer {
3347 return init != null;
3352 readonly Object init;
3353 Expression init_expr;
3354 bool init_expr_initialized = false;
3357 // Resolves and returns the field initializer.
3359 public Expression GetInitializerExpression (EmitContext ec)
3361 if (init_expr_initialized)
3365 if (init is Expression)
3366 e = (Expression) init;
3368 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3370 ec.IsFieldInitializer = true;
3371 e = e.DoResolve (ec);
3372 ec.IsFieldInitializer = false;
3375 init_expr_initialized = true;
3382 // The Field class is used to represents class/struct fields during parsing.
3384 public class Field : FieldBase {
3386 // Modifiers allowed in a class declaration
3388 const int AllowedModifiers =
3391 Modifiers.PROTECTED |
3392 Modifiers.INTERNAL |
3395 Modifiers.VOLATILE |
3399 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3400 Attributes attrs, Location loc)
3401 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3405 public override bool Define (TypeContainer parent)
3407 Type t = parent.ResolveType (Type, false, Location);
3412 if (!parent.AsAccessible (t, ModFlags)) {
3413 Report.Error (52, Location,
3414 "Inconsistent accessibility: field type `" +
3415 TypeManager.CSharpName (t) + "' is less " +
3416 "accessible than field `" + Name + "'");
3420 if (t.IsPointer && !UnsafeOK (parent))
3423 if (RootContext.WarningLevel > 1){
3424 Type ptype = parent.TypeBuilder.BaseType;
3426 // ptype is only null for System.Object while compiling corlib.
3428 TypeContainer.FindMembers (
3429 ptype, MemberTypes.Method,
3430 BindingFlags.Public |
3431 BindingFlags.Static | BindingFlags.Instance,
3432 System.Type.FilterName, Name);
3436 if ((ModFlags & Modifiers.VOLATILE) != 0){
3438 if (TypeManager.IsEnumType (t))
3439 t = TypeManager.EnumToUnderlying (t);
3441 if (!((t == TypeManager.bool_type) ||
3442 (t == TypeManager.sbyte_type) ||
3443 (t == TypeManager.byte_type) ||
3444 (t == TypeManager.short_type) ||
3445 (t == TypeManager.ushort_type) ||
3446 (t == TypeManager.int32_type) ||
3447 (t == TypeManager.uint32_type) ||
3448 (t == TypeManager.char_type) ||
3449 (t == TypeManager.float_type))){
3451 677, Location, parent.MakeName (Name) +
3452 " A volatile field can not be of type `" +
3453 TypeManager.CSharpName (t) + "'");
3459 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3461 if (parent is Struct &&
3462 ((fa & FieldAttributes.Static) == 0) &&
3463 t == parent.TypeBuilder &&
3464 !TypeManager.IsBuiltinType (t)){
3465 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name +
3466 "' causes a cycle in the structure layout");
3469 FieldBuilder = parent.TypeBuilder.DefineField (
3470 Name, t, Modifiers.FieldAttr (ModFlags));
3472 TypeManager.RegisterFieldBase (FieldBuilder, this);
3476 public void Emit (TypeContainer tc)
3478 EmitContext ec = new EmitContext (tc, Location, null,
3479 FieldBuilder.FieldType, ModFlags);
3481 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
3486 // `set' and `get' accessors are represented with an Accessor.
3488 public class Accessor {
3490 // Null if the accessor is empty, or a Block if not
3493 public Attributes OptAttributes;
3495 public Accessor (Block b, Attributes attrs)
3498 OptAttributes = attrs;
3503 // Properties and Indexers both generate PropertyBuilders, we use this to share
3504 // their common bits.
3506 abstract public class PropertyBase : MethodCore {
3507 public Accessor Get, Set;
3508 public PropertyBuilder PropertyBuilder;
3509 public MethodBuilder GetBuilder, SetBuilder;
3510 public MethodData GetData, SetData;
3512 protected EmitContext ec;
3514 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3515 Parameters parameters, Accessor get_block, Accessor set_block,
3516 Attributes attrs, Location loc)
3517 : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3523 protected override bool DoDefine (TypeContainer parent)
3525 if (!base.DoDefine (parent))
3528 ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3534 // Checks our base implementation if any
3536 protected override bool CheckBase (TypeContainer parent)
3538 // Check whether arguments were correct.
3539 if (!DoDefineParameters (parent))
3546 MethodSignature ms, base_ms;
3547 if (this is Indexer) {
3548 string name, base_name;
3550 report_name = "this";
3551 name = TypeManager.IndexerPropertyName (parent.TypeBuilder);
3552 ms = new MethodSignature (name, null, ParameterTypes);
3553 base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType);
3554 base_ms = new MethodSignature (base_name, null, ParameterTypes);
3557 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
3560 MemberList props_this;
3562 props_this = TypeContainer.FindMembers (
3563 parent.TypeBuilder, MemberTypes.Property,
3564 BindingFlags.NonPublic | BindingFlags.Public |
3565 BindingFlags.Static | BindingFlags.Instance |
3566 BindingFlags.DeclaredOnly,
3567 MethodSignature.method_signature_filter, ms);
3569 if (props_this.Count > 0) {
3570 Report.Error (111, Location, "Class `" + parent.Name + "' " +
3571 "already defines a member called `" + report_name + "' " +
3572 "with the same parameter types");
3577 // Find properties with the same name on the base class
3580 MemberList props_static = TypeContainer.FindMembers (
3581 parent.TypeBuilder.BaseType, MemberTypes.Property,
3582 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3583 MethodSignature.inheritable_property_signature_filter, base_ms);
3585 MemberList props_instance = TypeContainer.FindMembers (
3586 parent.TypeBuilder.BaseType, MemberTypes.Property,
3587 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3588 MethodSignature.inheritable_property_signature_filter,
3592 // Find if we have anything
3594 if (props_static.Count > 0)
3595 props = props_static;
3596 else if (props_instance.Count > 0)
3597 props = props_instance;
3602 // If we have something on the base.
3603 if (props != null && props.Count > 0){
3604 PropertyInfo pi = (PropertyInfo) props [0];
3606 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
3607 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
3609 MethodInfo reference = inherited_get == null ?
3610 inherited_set : inherited_get;
3612 if (reference != null) {
3613 string name = reference.DeclaringType.Name + "." + report_name;
3615 if (!CheckMethodAgainstBase (parent, flags, reference, name))
3619 if (((ModFlags & Modifiers.NEW) == 0) && (pi.PropertyType != MemberType)) {
3620 Report.Error (508, parent.MakeName (Name) + ": cannot " +
3621 "change return type when overriding inherited " +
3622 "member `" + pi.DeclaringType + "." + pi.Name + "'");
3626 if ((ModFlags & Modifiers.NEW) != 0)
3627 WarningNotHiding (parent);
3629 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3630 if (this is Indexer)
3631 Report.Error (115, Location,
3632 parent.MakeName (Name) +
3633 " no suitable indexers found to override");
3635 Report.Error (115, Location,
3636 parent.MakeName (Name) +
3637 " no suitable properties found to override");
3644 public virtual void Emit (TypeContainer tc)
3647 // The PropertyBuilder can be null for explicit implementations, in that
3648 // case, we do not actually emit the ".property", so there is nowhere to
3649 // put the attribute
3651 if (PropertyBuilder != null)
3652 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3654 if (GetData != null)
3655 GetData.Emit (tc, Get.Block, Get);
3657 if (SetData != null)
3658 SetData.Emit (tc, Set.Block, Set);
3663 public class Property : PropertyBase {
3664 const int AllowedModifiers =
3667 Modifiers.PROTECTED |
3668 Modifiers.INTERNAL |
3672 Modifiers.OVERRIDE |
3673 Modifiers.ABSTRACT |
3678 string set_parameter_name;
3679 Parameters get_params;
3680 Parameters set_params;
3682 public Property (Expression type, string name, int mod_flags,
3683 Accessor get_block, Accessor set_block,
3684 Attributes attrs, Location loc, string set_name,
3685 Parameters p_get, Parameters p_set)
3686 : base (type, name, mod_flags, AllowedModifiers,
3688 get_block, set_block, attrs, loc)
3690 set_parameter_name = set_name;
3696 public Property (Expression type, string name, int mod_flags,
3697 Accessor get_block, Accessor set_block,
3698 Attributes attrs, Location loc, string set_name,
3699 Parameters p_get, Parameters p_set, Expression impl_what)
3700 : base (type, name, mod_flags, AllowedModifiers,
3702 get_block, set_block, attrs, loc)
3704 set_parameter_name = set_name;
3707 Implements = impl_what;
3710 public Property (Expression type, string name, int mod_flags,
3711 Accessor get_block, Accessor set_block,
3712 Attributes attrs, Location loc)
3713 : base (type, name, mod_flags, AllowedModifiers,
3714 Parameters.EmptyReadOnlyParameters,
3715 get_block, set_block, attrs, loc)
3717 set_parameter_name = "Value";
3718 get_params = Parameters.EmptyReadOnlyParameters;
3719 set_params = Parameters.EmptyReadOnlyParameters;
3722 public override bool Define (TypeContainer parent)
3724 Type [] g_parameters=null, s_parameters=null;
3725 Parameter [] g_parms, s_parms;
3726 InternalParameters g_ip=null, s_ip=null;
3728 if (!DoDefine (parent))
3731 if (!CheckBase (parent))
3734 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3737 if (get_params == Parameters.EmptyReadOnlyParameters)
3739 g_parameters = TypeManager.NoTypes;
3740 g_ip = new InternalParameters (
3741 parent, Parameters.EmptyReadOnlyParameters);
3745 g_parameters = new Type [get_params.FixedParameters.Length];
3746 for (int i = 0; i < get_params.FixedParameters.Length; i ++)
3748 g_parameters[i] = get_params.FixedParameters[i].ParameterType;
3750 g_parms = new Parameter [get_params.FixedParameters.Length];
3751 for (int i = 0; i < get_params.FixedParameters.Length; i ++)
3753 Parameter tp = get_params.FixedParameters[i];
3754 g_parms[i] = new Parameter (tp.TypeName, tp.Name,
3755 Parameter.Modifier.NONE, null);
3757 g_ip = new InternalParameters (
3758 parent, new Parameters (g_parms, null, Location));
3761 GetData = new MethodData (this, "get", MemberType,
3762 g_parameters, g_ip, CallingConventions.Standard,
3763 Get.OptAttributes, ModFlags, flags, false);
3765 if (!GetData.Define (parent))
3768 GetBuilder = GetData.MethodBuilder;
3772 if (set_params == Parameters.EmptyReadOnlyParameters)
3774 s_parameters = new Type [1];
3775 s_parameters [0] = MemberType;
3777 s_parms = new Parameter [1];
3778 s_parms [0] = new Parameter (Type, /* was "value" */ set_parameter_name,
3779 Parameter.Modifier.NONE, null);
3783 s_parameters = new Type [set_params.FixedParameters.Length];
3784 for (int i = 0; i < set_params.FixedParameters.Length; i ++)
3786 s_parameters[i] = set_params.FixedParameters[i].ParameterType;
3789 s_parms = new Parameter [set_params.FixedParameters.Length];
3790 for (int i = 0; i < set_params.FixedParameters.Length; i ++)
3792 Parameter tp = set_params.FixedParameters[i];
3793 s_parms[i] = new Parameter (tp.TypeName, tp.Name,
3794 Parameter.Modifier.NONE, null);
3798 s_ip = new InternalParameters (
3799 parent, new Parameters (s_parms, null, Location));
3802 SetData = new MethodData (this, "set", TypeManager.void_type,
3803 s_parameters, s_ip, CallingConventions.Standard,
3804 Set.OptAttributes, ModFlags, flags, false);
3806 if (!SetData.Define (parent))
3809 SetBuilder = SetData.MethodBuilder;
3810 SetBuilder.DefineParameter (1, ParameterAttributes.None,
3811 /* was "value" */ set_parameter_name);
3814 // FIXME - PropertyAttributes.HasDefault ?
3816 PropertyAttributes prop_attr =
3817 PropertyAttributes.RTSpecialName |
3818 PropertyAttributes.SpecialName;
3820 if (!IsExplicitImpl){
3821 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3822 Name, prop_attr, MemberType, null);
3825 PropertyBuilder.SetGetMethod (GetBuilder);
3828 PropertyBuilder.SetSetMethod (SetBuilder);
3831 // HACK for the reasons exposed above
3833 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3836 "Class `" + parent.Name +
3837 "' already contains a definition for the property `" +
3845 public override void Emit (TypeContainer tc)
3849 if (GetData != null)
3851 Parameters = get_params;
3852 GetData.Emit (tc, Get.Block, Get);
3855 if (SetData != null)
3857 Parameters = set_params;
3858 SetData.Emit (tc, Set.Block, Set);
3865 /// Gigantic workaround for lameness in SRE follows :
3866 /// This class derives from EventInfo and attempts to basically
3867 /// wrap around the EventBuilder so that FindMembers can quickly
3868 /// return this in it search for members
3870 public class MyEventBuilder : EventInfo {
3873 // We use this to "point" to our Builder which is
3874 // not really a MemberInfo
3876 EventBuilder MyBuilder;
3879 // We "catch" and wrap these methods
3881 MethodInfo raise, remove, add;
3883 EventAttributes attributes;
3884 Type declaring_type, reflected_type, event_type;
3887 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3889 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3891 // And now store the values in our own fields.
3893 declaring_type = type_builder;
3895 reflected_type = type_builder;
3897 attributes = event_attr;
3899 this.event_type = event_type;
3903 // Methods that you have to override. Note that you only need
3904 // to "implement" the variants that take the argument (those are
3905 // the "abstract" methods, the others (GetAddMethod()) are
3908 public override MethodInfo GetAddMethod (bool nonPublic)
3913 public override MethodInfo GetRemoveMethod (bool nonPublic)
3918 public override MethodInfo GetRaiseMethod (bool nonPublic)
3924 // These methods make "MyEventInfo" look like a Builder
3926 public void SetRaiseMethod (MethodBuilder raiseMethod)
3928 raise = raiseMethod;
3929 MyBuilder.SetRaiseMethod (raiseMethod);
3932 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3934 remove = removeMethod;
3935 MyBuilder.SetRemoveOnMethod (removeMethod);
3938 public void SetAddOnMethod (MethodBuilder addMethod)
3941 MyBuilder.SetAddOnMethod (addMethod);
3944 public void SetCustomAttribute (CustomAttributeBuilder cb)
3946 MyBuilder.SetCustomAttribute (cb);
3949 public override object [] GetCustomAttributes (bool inherit)
3951 // FIXME : There's nothing which can be seemingly done here because
3952 // we have no way of getting at the custom attribute objects of the
3957 public override object [] GetCustomAttributes (Type t, bool inherit)
3959 // FIXME : Same here !
3963 public override bool IsDefined (Type t, bool b)
3968 public override EventAttributes Attributes {
3974 public override string Name {
3980 public override Type DeclaringType {
3982 return declaring_type;
3986 public override Type ReflectedType {
3988 return reflected_type;
3992 public Type EventType {
3999 public class Event : FieldBase {
4000 const int AllowedModifiers =
4003 Modifiers.PROTECTED |
4004 Modifiers.INTERNAL |
4009 Modifiers.OVERRIDE |
4013 public readonly Accessor Add;
4014 public readonly Accessor Remove;
4015 public MyEventBuilder EventBuilder;
4017 MethodBuilder AddBuilder, RemoveBuilder;
4018 MethodData AddData, RemoveData;
4020 public Event (Expression type, string name, Object init, int mod, Accessor add,
4021 Accessor remove, Attributes attrs, Location loc)
4022 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4028 public override bool Define (TypeContainer parent)
4030 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4032 if (!DoDefine (parent))
4035 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4036 Report.Error (66, Location, "'" + parent.Name + "." + Name +
4037 "' : event must be of a delegate type");
4041 Type [] parameter_types = new Type [1];
4042 parameter_types [0] = MemberType;
4044 Parameter [] parms = new Parameter [1];
4045 parms [0] = new Parameter (Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4046 InternalParameters ip = new InternalParameters (
4047 parent, new Parameters (parms, null, Location));
4049 if (!CheckBase (parent))
4053 // Now define the accessors
4055 AddData = new MethodData (this, "add", TypeManager.void_type,
4056 parameter_types, ip, CallingConventions.Standard,
4057 (Add != null) ? Add.OptAttributes : null,
4058 ModFlags, flags, false);
4060 if (!AddData.Define (parent))
4063 AddBuilder = AddData.MethodBuilder;
4064 AddBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4066 RemoveData = new MethodData (this, "remove", TypeManager.void_type,
4067 parameter_types, ip, CallingConventions.Standard,
4068 (Remove != null) ? Remove.OptAttributes : null,
4069 ModFlags, flags, false);
4071 if (!RemoveData.Define (parent))
4074 RemoveBuilder = RemoveData.MethodBuilder;
4075 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4077 if (!IsExplicitImpl){
4078 EventBuilder = new MyEventBuilder (
4079 parent.TypeBuilder, Name, e_attr, MemberType);
4081 if (Add == null && Remove == null) {
4082 FieldBuilder = parent.TypeBuilder.DefineField (
4084 FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4085 TypeManager.RegisterPrivateFieldOfEvent (
4086 (EventInfo) EventBuilder, FieldBuilder);
4087 TypeManager.RegisterFieldBase (FieldBuilder, this);
4090 EventBuilder.SetAddOnMethod (AddBuilder);
4091 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4093 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4094 Report.Error (111, Location,
4095 "Class `" + parent.Name +
4096 "' already contains a definition for the event `" +
4105 void EmitDefaultMethod (EmitContext ec, bool is_add)
4107 ILGenerator ig = ec.ig;
4108 MethodInfo method = null;
4111 method = TypeManager.delegate_combine_delegate_delegate;
4113 method = TypeManager.delegate_remove_delegate_delegate;
4115 if ((ModFlags & Modifiers.STATIC) != 0) {
4116 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4117 ig.Emit (OpCodes.Ldarg_0);
4118 ig.Emit (OpCodes.Call, method);
4119 ig.Emit (OpCodes.Castclass, MemberType);
4120 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4122 ig.Emit (OpCodes.Ldarg_0);
4123 ig.Emit (OpCodes.Ldarg_0);
4124 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4125 ig.Emit (OpCodes.Ldarg_1);
4126 ig.Emit (OpCodes.Call, method);
4127 ig.Emit (OpCodes.Castclass, MemberType);
4128 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4130 ig.Emit (OpCodes.Ret);
4133 public void Emit (TypeContainer tc)
4137 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4138 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
4141 AddData.Emit (tc, Add.Block, Add);
4143 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4144 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4145 EmitDefaultMethod (ec, true);
4149 RemoveData.Emit (tc, Remove.Block, Remove);
4151 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4152 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4153 EmitDefaultMethod (ec, false);
4160 // FIXME: This does not handle:
4162 // int INTERFACENAME [ args ]
4167 // int this [ args ]
4169 public class Indexer : PropertyBase {
4171 const int AllowedModifiers =
4174 Modifiers.PROTECTED |
4175 Modifiers.INTERNAL |
4179 Modifiers.OVERRIDE |
4184 public string IndexerName;
4185 public string InterfaceIndexerName;
4188 // Are we implementing an interface ?
4190 bool IsImplementing = false;
4192 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4193 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4194 : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4197 ExplicitInterfaceName = int_type;
4200 public override bool Define (TypeContainer parent)
4202 PropertyAttributes prop_attr =
4203 PropertyAttributes.RTSpecialName |
4204 PropertyAttributes.SpecialName;
4206 if (!DoDefine (parent))
4209 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4210 if (IndexerName == null)
4211 IndexerName = "Item";
4212 else if (IsExplicitImpl)
4213 Report.Error (592, Location,
4214 "Attribute 'IndexerName' is not valid on this declaration " +
4215 "type. It is valid on `property' declarations only.");
4217 ShortName = IndexerName;
4218 if (IsExplicitImpl) {
4219 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4220 Name = InterfaceType.FullName + "." + IndexerName;
4222 InterfaceIndexerName = IndexerName;
4226 if (!CheckBase (parent))
4230 InternalParameters ip = new InternalParameters (parent, Parameters);
4232 GetData = new MethodData (this, "get", MemberType,
4233 ParameterTypes, ip, CallingConventions.Standard,
4234 Get.OptAttributes, ModFlags, flags, false);
4236 if (!GetData.Define (parent))
4239 GetBuilder = GetData.MethodBuilder;
4243 int top = ParameterTypes.Length;
4244 Type [] set_pars = new Type [top + 1];
4245 ParameterTypes.CopyTo (set_pars, 0);
4246 set_pars [top] = MemberType;
4248 Parameter [] fixed_parms = Parameters.FixedParameters;
4250 if (fixed_parms == null){
4251 throw new Exception ("We currently do not support only array arguments in an indexer");
4252 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4253 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4255 // Here is the problem: the `value' parameter has
4256 // to come *after* the array parameter in the declaration
4258 // X (object [] x, Type value)
4261 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4262 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4266 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4269 fixed_parms.CopyTo (tmp, 0);
4270 tmp [fixed_parms.Length] = new Parameter (
4271 Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4273 Parameters set_formal_params = new Parameters (tmp, null, Location);
4275 InternalParameters ip = new InternalParameters (parent, set_formal_params);
4277 SetData = new MethodData (this, "set", TypeManager.void_type,
4278 set_pars, ip, CallingConventions.Standard,
4279 Set.OptAttributes, ModFlags, flags, false);
4281 if (!SetData.Define (parent))
4284 SetBuilder = SetData.MethodBuilder;
4288 // Now name the parameters
4290 Parameter [] p = Parameters.FixedParameters;
4294 for (i = 0; i < p.Length; ++i) {
4296 GetBuilder.DefineParameter (
4297 i + 1, p [i].Attributes, p [i].Name);
4300 SetBuilder.DefineParameter (
4301 i + 1, p [i].Attributes, p [i].Name);
4306 SetBuilder.DefineParameter (
4307 i + 1, ParameterAttributes.None, /* was "value" */ this.Name);
4309 if (i != ParameterTypes.Length) {
4310 Parameter array_param = Parameters.ArrayParameter;
4311 SetBuilder.DefineParameter (
4312 i + 1, array_param.Attributes, array_param.Name);
4316 if (GetData != null)
4317 IsImplementing = GetData.IsImplementing;
4318 else if (SetData != null)
4319 IsImplementing = SetData.IsImplementing;
4322 // Define the PropertyBuilder if one of the following conditions are met:
4323 // a) we're not implementing an interface indexer.
4324 // b) the indexer has a different IndexerName and this is no
4325 // explicit interface implementation.
4327 if (!IsExplicitImpl) {
4328 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4329 IndexerName, prop_attr, MemberType, ParameterTypes);
4331 if (GetData != null)
4332 PropertyBuilder.SetGetMethod (GetBuilder);
4334 if (SetData != null)
4335 PropertyBuilder.SetSetMethod (SetBuilder);
4337 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4345 public class Operator : MemberCore {
4347 const int AllowedModifiers =
4353 const int RequiredModifiers =
4357 public enum OpType : byte {
4367 // Unary and Binary operators
4390 // Implicit and Explicit
4395 public readonly OpType OperatorType;
4396 public readonly Expression ReturnType;
4397 public readonly Expression FirstArgType, SecondArgType;
4398 public readonly string FirstArgName, SecondArgName;
4399 public readonly Block Block;
4400 public Attributes OptAttributes;
4401 public MethodBuilder OperatorMethodBuilder;
4403 public string MethodName;
4404 public Method OperatorMethod;
4406 public Operator (OpType type, Expression ret_type, int flags,
4407 Expression arg1type, string arg1name,
4408 Expression arg2type, string arg2name,
4409 Block block, Attributes attrs, Location loc)
4412 OperatorType = type;
4413 ReturnType = ret_type;
4414 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4415 FirstArgType = arg1type;
4416 FirstArgName = arg1name;
4417 SecondArgType = arg2type;
4418 SecondArgName = arg2name;
4420 OptAttributes = attrs;
4423 string Prototype (TypeContainer parent)
4425 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4426 SecondArgType + ")";
4429 public override bool Define (TypeContainer parent)
4432 MethodName = "op_" + OperatorType;
4434 if (SecondArgType != null)
4437 Parameter [] param_list = new Parameter [length];
4439 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4442 "User defined operators `" +
4443 Prototype (parent) +
4444 "' must be declared static and public");
4448 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4449 Parameter.Modifier.NONE, null);
4450 if (SecondArgType != null)
4451 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4452 Parameter.Modifier.NONE, null);
4454 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4455 new Parameters (param_list, null, Location),
4456 OptAttributes, Mono.CSharp.Location.Null);
4458 OperatorMethod.IsOperator = true;
4459 OperatorMethod.Define (parent);
4461 if (OperatorMethod.MethodBuilder == null)
4464 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4466 Type [] param_types = OperatorMethod.ParameterTypes;
4467 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4468 Type return_type = OperatorMethod.GetReturnType ();
4469 Type first_arg_type = param_types [0];
4471 // Rules for conversion operators
4473 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4474 if (first_arg_type == return_type && first_arg_type == declaring_type){
4477 "User-defined conversion cannot take an object of the " +
4478 "enclosing type and convert to an object of the enclosing" +
4483 if (first_arg_type != declaring_type && return_type != declaring_type){
4486 "User-defined conversion must convert to or from the " +
4491 if (first_arg_type == TypeManager.object_type ||
4492 return_type == TypeManager.object_type){
4495 "User-defined conversion cannot convert to or from " +
4500 if (first_arg_type.IsInterface || return_type.IsInterface){
4503 "User-defined conversion cannot convert to or from an " +
4508 if (first_arg_type.IsSubclassOf (return_type) ||
4509 return_type.IsSubclassOf (first_arg_type)){
4512 "User-defined conversion cannot convert between types " +
4513 "that derive from each other");
4516 } else if (SecondArgType == null) {
4517 // Checks for Unary operators
4519 if (first_arg_type != declaring_type){
4522 "The parameter of a unary operator must be the " +
4527 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4528 if (return_type != declaring_type){
4531 "The parameter and return type for ++ and -- " +
4532 "must be the containing type");
4538 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4539 if (return_type != TypeManager.bool_type){
4542 "The return type of operator True or False " +
4549 // Checks for Binary operators
4551 if (first_arg_type != declaring_type &&
4552 param_types [1] != declaring_type){
4555 "One of the parameters of a binary operator must " +
4556 "be the containing type");
4564 public void Emit (TypeContainer parent)
4566 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4567 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4570 // abstract or extern methods have no bodies
4572 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4575 OperatorMethod.Block = Block;
4576 OperatorMethod.Emit (parent);
4579 public static string GetName (OpType ot)
4582 case OpType.LogicalNot:
4584 case OpType.OnesComplement:
4586 case OpType.Increment:
4588 case OpType.Decrement:
4594 case OpType.Addition:
4596 case OpType.Subtraction:
4598 case OpType.UnaryPlus:
4600 case OpType.UnaryNegation:
4602 case OpType.Multiply:
4604 case OpType.Division:
4606 case OpType.Modulus:
4608 case OpType.BitwiseAnd:
4610 case OpType.BitwiseOr:
4612 case OpType.ExclusiveOr:
4614 case OpType.LeftShift:
4616 case OpType.RightShift:
4618 case OpType.Equality:
4620 case OpType.Inequality:
4622 case OpType.GreaterThan:
4624 case OpType.LessThan:
4626 case OpType.GreaterThanOrEqual:
4628 case OpType.LessThanOrEqual:
4630 case OpType.Implicit:
4632 case OpType.Explicit:
4638 public override string ToString ()
4640 Type return_type = OperatorMethod.GetReturnType();
4641 Type [] param_types = OperatorMethod.ParameterTypes;
4643 if (SecondArgType == null)
4644 return String.Format (
4645 "{0} operator {1}({2})",
4646 TypeManager.CSharpName (return_type),
4647 GetName (OperatorType),
4650 return String.Format (
4651 "{0} operator {1}({2}, {3})",
4652 TypeManager.CSharpName (return_type),
4653 GetName (OperatorType),
4654 param_types [0], param_types [1]);
4659 // This is used to compare method signatures
4661 struct MethodSignature {
4663 public Type RetType;
4664 public Type [] Parameters;
4667 /// This delegate is used to extract methods which have the
4668 /// same signature as the argument
4670 public static MemberFilter method_signature_filter;
4673 /// This delegate is used to extract methods which have the
4674 /// same signature as the argument except for the name
4676 public static MemberFilter method_signature_noname_filter;
4679 /// This delegate is used to extract inheritable methods which
4680 /// have the same signature as the argument. By inheritable,
4681 /// this means that we have permissions to override the method
4682 /// from the current assembly and class
4684 public static MemberFilter inheritable_method_signature_filter;
4687 /// This delegate is used to extract inheritable methods which
4688 /// have the same signature as the argument. By inheritable,
4689 /// this means that we have permissions to override the method
4690 /// from the current assembly and class
4692 public static MemberFilter inheritable_property_signature_filter;
4694 static MethodSignature ()
4696 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4697 method_signature_noname_filter = new MemberFilter (MemberSignatureCompareNoName);
4698 inheritable_method_signature_filter = new MemberFilter (
4699 InheritableMemberSignatureCompare);
4700 inheritable_property_signature_filter = new MemberFilter (
4701 InheritablePropertySignatureCompare);
4704 public MethodSignature (string name, Type ret_type, Type [] parameters)
4709 if (parameters == null)
4710 Parameters = TypeManager.NoTypes;
4712 Parameters = parameters;
4715 public override int GetHashCode ()
4717 return Name.GetHashCode ();
4720 public override bool Equals (Object o)
4722 MethodSignature other = (MethodSignature) o;
4724 if (other.Name != Name)
4727 if (other.RetType != RetType)
4730 if (Parameters == null){
4731 if (other.Parameters == null)
4736 if (other.Parameters == null)
4739 int c = Parameters.Length;
4740 if (other.Parameters.Length != c)
4743 for (int i = 0; i < c; i++)
4744 if (other.Parameters [i] != Parameters [i])
4750 static bool MemberSignatureCompareNoName (MemberInfo m, object filter_criteria)
4752 return MemberSignatureCompare (m, filter_criteria, false);
4755 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4757 return MemberSignatureCompare (m, filter_criteria, true);
4760 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria, bool use_name)
4762 MethodSignature sig = (MethodSignature) filter_criteria;
4764 if (use_name && (m.Name != sig.Name))
4768 MethodInfo mi = m as MethodInfo;
4769 PropertyInfo pi = m as PropertyInfo;
4772 ReturnType = mi.ReturnType;
4773 else if (pi != null)
4774 ReturnType = pi.PropertyType;
4779 // we use sig.RetType == null to mean `do not check the
4780 // method return value.
4782 if (sig.RetType != null)
4783 if (ReturnType != sig.RetType)
4788 args = TypeManager.GetArgumentTypes (mi);
4790 args = TypeManager.GetArgumentTypes (pi);
4791 Type [] sigp = sig.Parameters;
4793 if (args.Length != sigp.Length)
4796 for (int i = args.Length; i > 0; ){
4798 if (args [i] != sigp [i])
4805 // This filter should be used when we are requesting methods that
4806 // we want to override.
4808 // This makes a number of assumptions, for example
4809 // that the methods being extracted are of a parent
4810 // class (this means we know implicitly that we are
4811 // being called to find out about members by a derived
4814 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4816 if (MemberSignatureCompare (m, filter_criteria)){
4817 MethodInfo mi = (MethodInfo) m;
4818 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4820 // If only accessible to the current class.
4821 if (prot == MethodAttributes.Private)
4824 // If only accessible to the defining assembly or
4825 if (prot == MethodAttributes.FamANDAssem ||
4826 prot == MethodAttributes.Assembly){
4827 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4833 // Anything else (FamOrAssembly and Public) is fine
4840 // This filter should be used when we are requesting properties that
4841 // we want to override.
4843 // This makes a number of assumptions, for example
4844 // that the methods being extracted are of a parent
4845 // class (this means we know implicitly that we are
4846 // being called to find out about members by a derived
4849 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
4851 if (MemberSignatureCompare (m, filter_criteria)){
4852 PropertyInfo pi = (PropertyInfo) m;
4854 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
4855 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
4857 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
4859 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4861 // If only accessible to the current class.
4862 if (prot == MethodAttributes.Private)
4865 // If only accessible to the defining assembly or
4866 if (prot == MethodAttributes.FamANDAssem ||
4867 prot == MethodAttributes.Assembly){
4868 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4874 // Anything else (FamOrAssembly and Public) is fine