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)
197 DefineName (c.Name, c);
200 // FIXME: Do we really need to explicitly add an empty default static constructor?
201 // Apparently we don't
202 /* if (c.default_static_constructor == null)
204 bool isModule = c is Mono.MonoBASIC.Module;
205 Constructor dc = new Constructor ("New", Parameters.EmptyReadOnlyParameters, null, c.Location);
206 dc.ModFlags = isModule ? Modifiers.PUBLIC | Modifiers.STATIC : Modifiers.PUBLIC;
207 c.AddConstructor (dc);
210 // --------------------------------------------------------------
212 return AdditionResult.Success;
215 public AdditionResult AddStruct (Struct s)
219 if ((res = IsValid (s.Basename)) != AdditionResult.Success)
222 DefineName (s.Name, s);
225 return AdditionResult.Success;
228 public AdditionResult AddDelegate (Delegate d)
232 if ((res = IsValid (d.Basename)) != AdditionResult.Success)
235 if (delegates == null)
236 delegates = new ArrayList ();
238 DefineName (d.Name, d);
241 return AdditionResult.Success;
244 public AdditionResult AddMethod (Method method)
246 string basename = method.Name;
247 string fullname = Name + "." + basename;
249 Object value = defined_names [fullname];
251 if (value != null && (!(value is Method)))
252 return AdditionResult.NameExists;
254 if (basename == Basename)
255 return AdditionResult.EnclosingClash;
258 methods = new ArrayList ();
260 if (method.Name.IndexOf (".") != -1)
261 methods.Insert (0, method);
263 methods.Add (method);
266 DefineName (fullname, method);
268 return AdditionResult.Success;
271 public AdditionResult AddConstructor (Constructor c)
274 return AdditionResult.NotAConstructor;
276 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
279 have_static_constructor = true;
280 if (default_static_constructor != null){
281 Console.WriteLine ("I have a static constructor already");
282 Console.WriteLine (" " + default_static_constructor);
283 return AdditionResult.MethodExists;
286 default_static_constructor = c;
289 if (default_constructor != null)
290 return AdditionResult.MethodExists;
291 default_constructor = c;
294 if (instance_constructors == null)
295 instance_constructors = new ArrayList ();
297 instance_constructors.Add (c);
300 return AdditionResult.Success;
303 public AdditionResult AddInterface (Interface iface)
307 if ((res = IsValid (iface.Basename)) != AdditionResult.Success)
310 if (interfaces == null)
311 interfaces = new ArrayList ();
312 interfaces.Add (iface);
313 DefineName (iface.Name, iface);
315 return AdditionResult.Success;
318 public AdditionResult AddField (Field field)
321 string basename = field.Name;
323 if ((res = IsValid (basename)) != AdditionResult.Success)
327 fields = new ArrayList ();
331 if (field.HasInitializer){
332 if ((field.ModFlags & Modifiers.STATIC) != 0) {
333 if (initialized_static_fields == null)
334 initialized_static_fields = new ArrayList ();
336 initialized_static_fields.Add (field);
339 // We have not seen a static constructor,
340 // but we will provide static initialization of fields
342 have_static_constructor = true;
344 if (initialized_fields == null)
345 initialized_fields = new ArrayList ();
347 initialized_fields.Add (field);
351 if ((field.ModFlags & Modifiers.STATIC) == 0)
352 have_nonstatic_fields = true;
354 DefineName (Name + "." + basename, field);
355 return AdditionResult.Success;
358 public AdditionResult AddProperty (Property prop)
361 string basename = prop.Name;
363 if ((res = IsValid (basename)) != AdditionResult.Success)
366 if (properties == null)
367 properties = new ArrayList ();
369 if (prop.Name.IndexOf (".") != -1)
370 properties.Insert (0, prop);
372 properties.Add (prop);
373 DefineName (Name + "." + basename, prop);
375 return AdditionResult.Success;
378 public AdditionResult AddEvent (Event e)
381 string basename = e.Name;
383 if ((res = IsValid (basename)) != AdditionResult.Success)
387 events = new ArrayList ();
390 DefineName (Name + "." + basename, e);
392 return AdditionResult.Success;
395 public AdditionResult AddIndexer (Indexer i)
397 if (indexers == null)
398 indexers = new ArrayList ();
400 if (i.InterfaceType != null)
401 indexers.Insert (0, i);
405 return AdditionResult.Success;
408 public AdditionResult AddOperator (Operator op)
410 if (operators == null)
411 operators = new ArrayList ();
415 return AdditionResult.Success;
418 public void RegisterOrder (Interface iface)
420 if (interface_order == null)
421 interface_order = new ArrayList ();
423 interface_order.Add (iface);
426 public ArrayList Types {
432 public ArrayList Methods {
438 public ArrayList Constants {
444 public ArrayList Interfaces {
452 return base_class_name;
456 public ArrayList Bases {
466 public ArrayList Fields {
476 public ArrayList InstanceConstructors {
478 return instance_constructors;
482 public ArrayList Properties {
488 public ArrayList Events {
494 public ArrayList Enums {
500 public ArrayList Indexers {
506 public ArrayList Operators {
512 public ArrayList Delegates {
518 public Attributes OptAttributes {
524 public bool HaveStaticConstructor {
526 return have_static_constructor;
530 public virtual TypeAttributes TypeAttr {
532 return Modifiers.TypeAttr (ModFlags, this);
537 // Emits the instance field initializers
539 public bool EmitFieldInitializers (EmitContext ec)
542 ILGenerator ig = ec.ig;
543 Expression instance_expr;
546 fields = initialized_static_fields;
547 instance_expr = null;
549 fields = initialized_fields;
550 instance_expr = new This (Location.Null).Resolve (ec);
556 foreach (Field f in fields){
557 Expression e = f.GetInitializerExpression (ec);
561 Location l = f.Location;
562 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
563 fe.InstanceExpression = instance_expr;
564 Expression a = new Assign (fe, e, l);
570 if (a is ExpressionStatement)
571 ((ExpressionStatement) a).EmitStatement (ec);
573 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
581 // Defines the default constructors
583 void DefineDefaultConstructor (bool is_static)
588 c = new Constructor (Basename, Parameters.EmptyReadOnlyParameters,
589 new ConstructorBaseInitializer (
590 null, Parameters.EmptyReadOnlyParameters,
595 mods = Modifiers.STATIC;
601 c.Block = new Block (null);
605 public void ReportStructInitializedInstanceError ()
607 string n = TypeBuilder.FullName;
609 foreach (Field f in initialized_fields){
612 "`" + n + "." + f.Name + "': can not have " +
613 "instance field initializers in structs");
618 /// The pending methods that need to be implemented (interfaces or abstract methods)
620 public PendingImplementation Pending;
623 /// This function computes the Base class and also the
624 /// list of interfaces that the class or struct @c implements.
626 /// The return value is an array (might be null) of
627 /// interfaces implemented (as Types).
629 /// The @parent argument is set to the parent object or null
630 /// if this is `System.Object'.
632 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
634 ArrayList bases = Bases;
643 parent = TypeManager.value_type;
647 if (RootContext.StdLib)
648 parent = TypeManager.object_type;
649 else if (Name != "System.Object")
650 parent = TypeManager.object_type;
653 // If we are compiling our runtime,
654 // and we are defining ValueType, then our
655 // parent is `System.Object'.
657 if (!RootContext.StdLib && Name == "System.ValueType")
658 parent = TypeManager.object_type;
665 // Bases should be null if there are no bases at all
670 Expression name = (Expression) bases [0];
671 name = ResolveTypeExpr (name, false, Location);
678 Type first = name.Type;
684 parent = TypeManager.object_type;
688 if (!AsAccessible (parent, ModFlags))
689 Report.Error (60, Location,
690 "Inconsistent accessibility: base class `" +
691 TypeManager.CSharpName (parent) + "' is less " +
692 "accessible than class `" +
699 Type [] ifaces = new Type [count-start];
701 for (i = start, j = 0; i < count; i++, j++){
702 Expression name = (Expression) bases [i];
703 Expression resolved = ResolveTypeExpr (name, false, Location);
704 bases [i] = resolved;
705 Type t = resolved.Type;
712 if (is_class == false && !t.IsInterface){
713 Report.Error (527, "In Struct `" + Name + "', type `"+
714 name +"' is not an interface");
723 detail = " (a class can not inherit from a struct/enum)";
725 Report.Error (509, "class `"+ Name +
726 "': Cannot inherit from sealed class `"+
727 bases [i]+"'"+detail);
734 Report.Error (527, "In Class `" + Name + "', type `"+
735 name+"' is not an interface");
741 for (int x = 0; x < j; x++) {
742 if (t == ifaces [x]) {
743 Report.Error (528, "`" + name + "' is already listed in interface list");
752 return TypeManager.ExpandInterfaces (ifaces);
756 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
758 public override TypeBuilder DefineType ()
764 if (TypeBuilder != null)
777 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
779 ifaces = GetClassBases (is_class, out parent, out error);
784 if (is_class && parent != null){
785 if (parent == TypeManager.enum_type ||
786 (parent == TypeManager.value_type && RootContext.StdLib) ||
787 parent == TypeManager.delegate_type ||
788 parent == TypeManager.array_type){
790 644, Location, "`" + Name + "' cannot inherit from " +
791 "special class `" + TypeManager.CSharpName (parent) + "'");
796 if (!is_class && TypeManager.value_type == null)
797 throw new Exception ();
799 TypeAttributes type_attributes = TypeAttr;
801 // if (parent_builder is ModuleBuilder) {
803 ModuleBuilder builder = CodeGen.ModuleBuilder;
804 TypeBuilder = builder.DefineType (
805 Name, type_attributes, parent, ifaces);
808 TypeBuilder builder = Parent.TypeBuilder;
809 TypeBuilder = builder.DefineNestedType (
810 Basename, type_attributes, parent, ifaces);
814 // Structs with no fields need to have at least one byte.
815 // The right thing would be to set the PackingSize in a DefineType
816 // but there are no functions that allow interfaces *and* the size to
820 if (!is_class && !have_nonstatic_fields){
821 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
822 FieldAttributes.Private);
825 // add interfaces that were not added at type creation (weird API issue)
826 if (!is_class && !have_nonstatic_fields && (ifaces != null)) {
827 foreach (Type i in ifaces)
828 TypeBuilder.AddInterfaceImplementation (i);
832 // Finish the setup for the EmitContext
834 ec.ContainerType = TypeBuilder;
836 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
838 if ((parent != null) &&
839 (parent == TypeManager.attribute_type ||
840 parent.IsSubclassOf (TypeManager.attribute_type))) {
841 RootContext.RegisterAttribute (this);
842 TypeManager.RegisterAttrType (TypeBuilder, this);
844 RootContext.RegisterOrder (this);
846 if (Interfaces != null) {
847 foreach (Interface iface in Interfaces)
852 foreach (TypeContainer tc in Types)
856 if (Delegates != null) {
857 foreach (Delegate d in Delegates)
862 foreach (Enum en in Enums)
872 /// Defines the MemberCore objects that are in the `list' Arraylist
874 /// The `defined_names' array contains a list of members defined in
877 static ArrayList remove_list = new ArrayList ();
878 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
882 remove_list.Clear ();
884 foreach (MemberCore mc in list){
885 if (!mc.Define (this)){
886 remove_list.Add (mc);
890 if (defined_names == null)
893 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
895 if (RootContext.WarningLevel >= 4){
896 if ((mc.ModFlags & Modifiers.NEW) != 0)
897 Warning_KewywordNewNotRequired (mc.Location, mc);
902 MemberInfo match = defined_names [idx];
904 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
908 // If we are both methods, let the method resolution emit warnings
910 if (match is MethodBase && mc is MethodCore)
913 if ((mc.ModFlags & Modifiers.NEW) == 0)
914 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
917 foreach (object o in remove_list)
920 remove_list.Clear ();
924 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
925 // class is consisten. Either it is `Item' or it is the name defined by all the
926 // indexers with the `IndexerName' attribute.
928 // Turns out that the IndexerNameAttribute is applied to each indexer,
929 // but it is never emitted, instead a DefaultName attribute is attached
932 void DefineIndexers ()
934 string class_indexer_name = null;
936 foreach (Indexer i in Indexers){
941 name = i.IndexerName;
943 if (i.InterfaceType != null)
946 if (class_indexer_name == null){
947 class_indexer_name = name;
951 if (name == class_indexer_name)
955 668, "Two indexers have different names, " +
956 " you should use the same name for all your indexers");
958 if (class_indexer_name == null)
959 class_indexer_name = "Item";
960 IndexerName = class_indexer_name;
963 static void Error_KeywordNotAllowed (Location loc)
965 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
969 /// Populates our TypeBuilder with fields and methods
971 public override bool DefineMembers (TypeContainer parent)
973 MemberInfo [] defined_names = null;
975 if (interface_order != null){
976 foreach (Interface iface in interface_order)
977 if ((iface.ModFlags & Modifiers.NEW) == 0)
978 iface.DefineMembers (this);
980 Error_KeywordNotAllowed (iface.Location);
983 if (RootContext.WarningLevel > 1){
987 // This code throws an exception in the comparer
988 // I guess the string is not an object?
990 ptype = TypeBuilder.BaseType;
992 defined_names = (MemberInfo []) FindMembers (
993 ptype, MemberTypes.All & ~MemberTypes.Constructor,
994 BindingFlags.Public | BindingFlags.Instance |
995 BindingFlags.Static, null, null);
997 Array.Sort (defined_names, mif_compare);
1001 if (constants != null)
1002 DefineMembers (constants, defined_names);
1005 DefineMembers (fields, defined_names);
1008 if (instance_constructors == null){
1009 if (default_constructor == null)
1010 DefineDefaultConstructor (false);
1013 if (initialized_static_fields != null &&
1014 default_static_constructor == null)
1015 DefineDefaultConstructor (true);
1018 if (this is Struct){
1020 // Structs can not have initialized instance
1023 if (initialized_static_fields != null &&
1024 default_static_constructor == null)
1025 DefineDefaultConstructor (true);
1027 if (initialized_fields != null)
1028 ReportStructInitializedInstanceError ();
1031 Pending = PendingImplementation.GetPendingImplementations (this);
1034 // Constructors are not in the defined_names array
1036 if (instance_constructors != null)
1037 DefineMembers (instance_constructors, null);
1039 if (default_static_constructor != null)
1040 default_static_constructor.Define (this);
1042 if (methods != null)
1043 DefineMembers (methods, defined_names);
1045 if (properties != null)
1046 DefineMembers (properties, defined_names);
1049 DefineMembers (events, defined_names);
1051 if (indexers != null) {
1054 IndexerName = "Item";
1056 if (operators != null){
1057 DefineMembers (operators, null);
1059 CheckPairedOperators ();
1063 DefineMembers (enums, defined_names);
1065 if (delegates != null)
1066 DefineMembers (delegates, defined_names);
1069 if (TypeBuilder.BaseType != null)
1070 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1072 member_cache = new MemberCache (this);
1078 public override bool Define (TypeContainer parent)
1080 if (interface_order != null){
1081 foreach (Interface iface in interface_order)
1082 if ((iface.ModFlags & Modifiers.NEW) == 0)
1083 iface.Define (this);
1090 /// This function is based by a delegate to the FindMembers routine
1092 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1098 /// This filter is used by FindMembers, and we just keep
1099 /// a global for the filter to `AlwaysAccept'
1101 static MemberFilter accepting_filter;
1105 /// A member comparission method based on name only
1107 static IComparer mif_compare;
1109 static TypeContainer ()
1111 accepting_filter = new MemberFilter (AlwaysAccept);
1112 mif_compare = new MemberInfoCompare ();
1116 /// This method returns the members of this type just like Type.FindMembers would
1117 /// Only, we need to use this for types which are _being_ defined because MS'
1118 /// implementation can't take care of that.
1121 // FIXME: return an empty static array instead of null, that cleans up
1122 // some code and is consistent with some coding conventions I just found
1126 // Notice that in various cases we check if our field is non-null,
1127 // something that would normally mean that there was a bug elsewhere.
1129 // The problem happens while we are defining p-invoke methods, as those
1130 // will trigger a FindMembers, but this happens before things are defined
1132 // Since the whole process is a no-op, it is fine to check for null here.
1134 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1135 MemberFilter filter, object criteria)
1137 ArrayList members = new ArrayList ();
1140 if ((bf & BindingFlags.Public) != 0)
1141 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1143 if ((bf & BindingFlags.NonPublic) != 0)
1144 modflags |= Modifiers.PRIVATE;
1146 int static_mask = 0, static_flags = 0;
1147 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1148 case BindingFlags.Static:
1149 static_mask = static_flags = Modifiers.STATIC;
1152 case BindingFlags.Instance:
1153 static_mask = Modifiers.STATIC;
1158 static_mask = static_flags = 0;
1162 Timer.StartTimer (TimerType.TcFindMembers);
1165 filter = accepting_filter;
1167 if ((mt & MemberTypes.Field) != 0) {
1168 if (fields != null) {
1169 foreach (Field f in fields) {
1170 if ((f.ModFlags & modflags) == 0)
1172 if ((f.ModFlags & static_mask) != static_flags)
1175 FieldBuilder fb = f.FieldBuilder;
1176 if (fb != null && filter (fb, criteria) == true)
1181 if (constants != null) {
1182 foreach (Const con in constants) {
1183 if ((con.ModFlags & modflags) == 0)
1185 if ((con.ModFlags & static_mask) != static_flags)
1188 FieldBuilder fb = con.FieldBuilder;
1189 if (fb != null && filter (fb, criteria) == true)
1195 if ((mt & MemberTypes.Method) != 0) {
1196 if (methods != null) {
1197 foreach (Method m in methods) {
1198 if ((m.ModFlags & modflags) == 0)
1200 if ((m.ModFlags & static_mask) != static_flags)
1203 MethodBuilder mb = m.MethodBuilder;
1205 if (mb != null && filter (mb, criteria) == true)
1210 if (operators != null){
1211 foreach (Operator o in operators) {
1212 if ((o.ModFlags & modflags) == 0)
1214 if ((o.ModFlags & static_mask) != static_flags)
1217 MethodBuilder ob = o.OperatorMethodBuilder;
1218 if (ob != null && filter (ob, criteria) == true)
1223 if (properties != null){
1224 foreach (Property p in properties){
1225 if ((p.ModFlags & modflags) == 0)
1227 if ((p.ModFlags & static_mask) != static_flags)
1233 if (b != null && filter (b, criteria) == true)
1237 if (b != null && filter (b, criteria) == true)
1242 if (indexers != null){
1243 foreach (Indexer ix in indexers){
1244 if ((ix.ModFlags & modflags) == 0)
1246 if ((ix.ModFlags & static_mask) != static_flags)
1252 if (b != null && filter (b, criteria) == true)
1256 if (b != null && filter (b, criteria) == true)
1262 if ((mt & MemberTypes.Event) != 0) {
1264 foreach (Event e in events) {
1265 if ((e.ModFlags & modflags) == 0)
1267 if ((e.ModFlags & static_mask) != static_flags)
1270 MemberInfo eb = e.EventBuilder;
1271 if (eb != null && filter (eb, criteria) == true)
1272 members.Add (e.EventBuilder);
1276 if ((mt & MemberTypes.Property) != 0){
1277 if (properties != null)
1278 foreach (Property p in properties) {
1279 if ((p.ModFlags & modflags) == 0)
1281 if ((p.ModFlags & static_mask) != static_flags)
1284 MemberInfo pb = p.PropertyBuilder;
1285 if (pb != null && filter (pb, criteria) == true) {
1286 members.Add (p.PropertyBuilder);
1290 if (indexers != null)
1291 foreach (Indexer ix in indexers) {
1292 if ((ix.ModFlags & modflags) == 0)
1294 if ((ix.ModFlags & static_mask) != static_flags)
1297 MemberInfo ib = ix.PropertyBuilder;
1298 if (ib != null && filter (ib, criteria) == true) {
1299 members.Add (ix.PropertyBuilder);
1304 if ((mt & MemberTypes.NestedType) != 0) {
1306 foreach (TypeContainer t in types) {
1307 if ((t.ModFlags & modflags) == 0)
1310 TypeBuilder tb = t.TypeBuilder;
1311 if (tb != null && (filter (tb, criteria) == true))
1317 foreach (Enum en in enums){
1318 if ((en.ModFlags & modflags) == 0)
1321 TypeBuilder tb = en.TypeBuilder;
1322 if (tb != null && (filter (tb, criteria) == true))
1327 if (delegates != null){
1328 foreach (Delegate d in delegates){
1329 if ((d.ModFlags & modflags) == 0)
1332 TypeBuilder tb = d.TypeBuilder;
1333 if (tb != null && (filter (tb, criteria) == true))
1338 if (interfaces != null){
1339 foreach (Interface iface in interfaces){
1340 if ((iface.ModFlags & modflags) == 0)
1343 TypeBuilder tb = iface.TypeBuilder;
1344 if (tb != null && (filter (tb, criteria) == true))
1350 if ((mt & MemberTypes.Constructor) != 0){
1351 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1352 foreach (Constructor c in instance_constructors){
1353 ConstructorBuilder cb = c.ConstructorBuilder;
1355 if (filter (cb, criteria) == true)
1360 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1361 ConstructorBuilder cb =
1362 default_static_constructor.ConstructorBuilder;
1365 if (filter (cb, criteria) == true)
1371 // Lookup members in parent if requested.
1373 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1374 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1375 members.AddRange (list);
1378 Timer.StopTimer (TimerType.TcFindMembers);
1380 return new MemberList (members);
1383 public override MemberCache MemberCache {
1385 return member_cache;
1389 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1390 MemberFilter filter, object criteria)
1392 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1395 return tc.FindMembers (mt, bf, filter, criteria);
1397 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1401 // FindMethods will look for methods not only in the type `t', but in
1402 // any interfaces implemented by the type.
1404 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1405 MemberFilter filter, object criteria)
1411 /// Emits the values for the constants
1413 public void EmitConstants ()
1415 if (constants != null)
1416 foreach (Const con in constants)
1417 con.EmitConstant (this);
1422 /// Emits the code, this step is performed after all
1423 /// the types, enumerations, constructors
1427 if (instance_constructors != null)
1428 foreach (Constructor c in instance_constructors)
1431 if (default_static_constructor != null)
1432 default_static_constructor.Emit (this);
1434 if (methods != null)
1435 foreach (Method m in methods)
1438 if (operators != null)
1439 foreach (Operator o in operators)
1442 if (properties != null)
1443 foreach (Property p in properties)
1446 if (indexers != null){
1447 foreach (Indexer ix in indexers)
1450 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1451 this, IndexerName, ModFlags, Location);
1452 TypeBuilder.SetCustomAttribute (cb);
1456 foreach (Field f in fields)
1459 if (events != null){
1460 foreach (Event e in Events)
1464 if (Pending != null)
1465 if (Pending.VerifyPendingMethods ())
1468 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1471 // Check for internal or private fields that were never assigned
1473 if (fields != null && RootContext.WarningLevel >= 3) {
1474 foreach (Field f in fields) {
1475 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1480 169, f.Location, "Private field " +
1481 MakeName (f.Name) + " is never used");
1486 // Only report 649 on level 4
1488 if (RootContext.WarningLevel < 4)
1491 if ((f.status & Field.Status.ASSIGNED) != 0)
1496 "Field " + MakeName (f.Name) + " is never assigned " +
1497 " to and will always have its default value");
1501 // if (types != null)
1502 // foreach (TypeContainer tc in types)
1506 public override void CloseType ()
1511 TypeBuilder.CreateType ();
1513 } catch (TypeLoadException){
1515 // This is fine, the code still created the type
1517 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1518 // Console.WriteLine (e.Message);
1520 Console.WriteLine ("In type: " + Name);
1525 foreach (Enum en in Enums)
1528 if (interface_order != null){
1529 foreach (Interface iface in interface_order)
1534 foreach (TypeContainer tc in Types)
1538 foreach (TypeContainer tc in Types)
1539 if (!(tc is Struct))
1543 if (Delegates != null)
1544 foreach (Delegate d in Delegates)
1548 public string MakeName (string n)
1550 return "`" + Name + "." + n + "'";
1553 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1556 108, l, "The keyword new is required on " +
1557 MakeName (mi.Name) + " because it hides `" +
1558 mi.ReflectedType.Name + "." + mi.Name + "'");
1561 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1564 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1565 "inherited member, the keyword new is not required");
1568 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1574 // Performs the validation on a Method's modifiers (properties have
1575 // the same properties).
1577 public bool MethodModifiersValid (int flags, string n, Location loc)
1579 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1580 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1581 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1583 string name = MakeName (n);
1586 // At most one of static, virtual or override
1588 if ((flags & Modifiers.STATIC) != 0){
1589 if ((flags & vao) != 0){
1591 112, loc, "static method " + name + "can not be marked " +
1592 "as virtual, abstract or override");
1597 if (this is Struct){
1598 if ((flags & va) != 0){
1599 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1604 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1607 " marked as override cannot be marked as new or virtual");
1612 // If the declaration includes the abstract modifier, then the
1613 // declaration does not include static, virtual or extern
1615 if ((flags & Modifiers.ABSTRACT) != 0){
1616 if ((flags & Modifiers.EXTERN) != 0){
1618 180, loc, name + " can not be both abstract and extern");
1622 if ((flags & Modifiers.VIRTUAL) != 0){
1624 503, loc, name + " can not be both abstract and virtual");
1628 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1631 " is abstract but its container class is not");
1637 if ((flags & Modifiers.PRIVATE) != 0){
1638 if ((flags & vao) != 0){
1641 " virtual or abstract members can not be private");
1646 if ((flags & Modifiers.SEALED) != 0){
1647 if ((flags & Modifiers.OVERRIDE) == 0){
1650 " cannot be sealed because it is not an override");
1658 // Access level of a type.
1661 ProtectedInternal = 1,
1667 // Check whether `flags' denotes a more restricted access than `level'
1668 // and return the new level.
1669 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1671 AccessLevel old_level = level;
1673 if ((flags & Modifiers.INTERNAL) != 0) {
1674 if ((flags & Modifiers.PROTECTED) != 0) {
1675 if ((int) level < (int) AccessLevel.ProtectedInternal)
1676 level = AccessLevel.ProtectedInternal;
1678 if ((int) level < (int) AccessLevel.Internal)
1679 level = AccessLevel.Internal;
1681 } else if ((flags & Modifiers.PROTECTED) != 0) {
1682 if ((int) level < (int) AccessLevel.Protected)
1683 level = AccessLevel.Protected;
1684 } else if ((flags & Modifiers.PRIVATE) != 0)
1685 level = AccessLevel.Private;
1690 // Return the access level for a new member which is defined in the current
1691 // TypeContainer with access modifiers `flags'.
1692 AccessLevel GetAccessLevel (int flags)
1694 if ((flags & Modifiers.PRIVATE) != 0)
1695 return AccessLevel.Private;
1698 if (!IsTopLevel && (Parent != null))
1699 level = Parent.GetAccessLevel (flags);
1701 level = AccessLevel.Public;
1703 return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1706 // Return the access level for type `t', but don't give more access than `flags'.
1707 static AccessLevel GetAccessLevel (Type t, int flags)
1709 if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1710 return AccessLevel.Private;
1713 if (TypeManager.IsBuiltinType (t))
1714 return AccessLevel.Public;
1715 else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1716 level = GetAccessLevel (t.DeclaringType, flags);
1718 level = CheckAccessLevel (AccessLevel.Public, flags);
1721 if (t.IsNestedPublic)
1724 if (t.IsNestedAssembly || t.IsNotPublic) {
1725 if ((int) level < (int) AccessLevel.Internal)
1726 level = AccessLevel.Internal;
1729 if (t.IsNestedFamily) {
1730 if ((int) level < (int) AccessLevel.Protected)
1731 level = AccessLevel.Protected;
1734 if (t.IsNestedFamORAssem) {
1735 if ((int) level < (int) AccessLevel.ProtectedInternal)
1736 level = AccessLevel.ProtectedInternal;
1743 // Returns true if `parent' is as accessible as the flags `flags'
1744 // given for this member.
1746 public bool AsAccessible (Type parent, int flags)
1748 while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1749 parent = parent.GetElementType ();
1751 AccessLevel level = GetAccessLevel (flags);
1752 AccessLevel level2 = GetAccessLevel (parent, flags);
1754 return (int) level >= (int) level2;
1757 Hashtable builder_and_args;
1759 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1761 if (builder_and_args == null)
1762 builder_and_args = new Hashtable ();
1767 /// Performs checks for an explicit interface implementation. First it
1768 /// checks whether the `interface_type' is a base inteface implementation.
1769 /// Then it checks whether `name' exists in the interface type.
1771 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1775 if (ifaces != null){
1776 foreach (Type t in ifaces){
1777 if (t == interface_type){
1785 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1792 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1794 Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1801 string IMemberContainer.Name {
1807 Type IMemberContainer.Type {
1813 IMemberContainer IMemberContainer.Parent {
1815 return parent_container;
1819 MemberCache IMemberContainer.MemberCache {
1821 return member_cache;
1825 bool IMemberContainer.IsInterface {
1831 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1833 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1837 // Operator pair checking
1840 class OperatorEntry {
1842 public Type ret_type;
1843 public Type type1, type2;
1845 public Operator.OpType ot;
1847 public OperatorEntry (int f, Operator o)
1851 ret_type = o.OperatorMethod.GetReturnType ();
1852 Type [] pt = o.OperatorMethod.ParameterTypes;
1856 ot = o.OperatorType;
1859 public override int GetHashCode ()
1861 return ret_type.GetHashCode ();
1864 public override bool Equals (object o)
1866 OperatorEntry other = (OperatorEntry) o;
1868 if (other.ret_type != ret_type)
1870 if (other.type1 != type1)
1872 if (other.type2 != type2)
1879 // Checks that some operators come in pairs:
1884 // They are matched based on the return type and the argument types
1886 void CheckPairedOperators ()
1888 Hashtable pairs = new Hashtable (null, null);
1890 // Register all the operators we care about.
1891 foreach (Operator op in operators){
1894 switch (op.OperatorType){
1895 case Operator.OpType.Equality:
1897 case Operator.OpType.Inequality:
1900 case Operator.OpType.GreaterThan:
1902 case Operator.OpType.LessThan:
1905 case Operator.OpType.GreaterThanOrEqual:
1907 case Operator.OpType.LessThanOrEqual:
1913 OperatorEntry oe = new OperatorEntry (reg, op);
1915 object o = pairs [oe];
1919 oe = (OperatorEntry) o;
1925 // Look for the mistakes.
1927 foreach (DictionaryEntry de in pairs){
1928 OperatorEntry oe = (OperatorEntry) de.Key;
1935 case Operator.OpType.Equality:
1938 case Operator.OpType.Inequality:
1941 case Operator.OpType.GreaterThan:
1944 case Operator.OpType.LessThan:
1947 case Operator.OpType.GreaterThanOrEqual:
1950 case Operator.OpType.LessThanOrEqual:
1954 Report.Error (216, oe.op.Location,
1955 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
1962 public class Class : TypeContainer {
1964 // Modifiers allowed in a class declaration
1966 public const int AllowedModifiers =
1969 Modifiers.PROTECTED |
1970 Modifiers.INTERNAL |
1972 Modifiers.ABSTRACT |
1976 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1977 : base (parent, name, l)
1981 if (parent.Parent == null)
1982 accmods = Modifiers.INTERNAL;
1984 accmods = Modifiers.PRIVATE;
1986 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1987 this.attributes = attrs;
1991 // FIXME: How do we deal with the user specifying a different
1994 public override TypeAttributes TypeAttr {
1996 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2001 public class Struct : TypeContainer {
2003 // Modifiers allowed in a struct declaration
2005 public const int AllowedModifiers =
2008 Modifiers.PROTECTED |
2009 Modifiers.INTERNAL |
2013 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2014 : base (parent, name, l)
2018 if (parent.Parent == null)
2019 accmods = Modifiers.INTERNAL;
2021 accmods = Modifiers.PRIVATE;
2023 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2025 this.ModFlags |= Modifiers.SEALED;
2026 this.attributes = attrs;
2031 // FIXME: Allow the user to specify a different set of attributes
2032 // in some cases (Sealed for example is mandatory for a class,
2033 // but what SequentialLayout can be changed
2035 public override TypeAttributes TypeAttr {
2037 return base.TypeAttr |
2038 TypeAttributes.SequentialLayout |
2039 TypeAttributes.Sealed |
2040 TypeAttributes.BeforeFieldInit;
2045 public abstract class MethodCore : MemberBase {
2046 public /* readonly */ Parameters Parameters;
2050 // Parameters, cached for semantic analysis.
2052 protected InternalParameters parameter_info;
2053 protected Type [] parameter_types;
2055 public MethodCore (Expression type, int mod, int allowed_mod, string name,
2056 Attributes attrs, Parameters parameters, Location loc)
2057 : base (type, mod, allowed_mod, name, attrs, loc)
2059 Parameters = parameters;
2063 // Returns the System.Type array for the parameters of this method
2065 public Type [] ParameterTypes {
2067 return parameter_types;
2071 public InternalParameters ParameterInfo
2074 return parameter_info;
2078 public Block Block {
2088 protected virtual bool DoDefineParameters (TypeContainer parent)
2090 // Check if arguments were correct
2091 parameter_types = Parameters.GetParameterInfo (parent);
2092 if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
2095 parameter_info = new InternalParameters (parent, Parameters);
2100 public CallingConventions GetCallingConvention (bool is_class)
2102 CallingConventions cc = 0;
2104 cc = Parameters.GetCallingConvention ();
2107 if ((ModFlags & Modifiers.STATIC) == 0)
2108 cc |= CallingConventions.HasThis;
2110 // FIXME: How is `ExplicitThis' used in C#?
2115 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
2117 LabelParameters (ec, parameters, builder, null);
2120 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder, Parameters p_params)
2123 // Define each type attribute (in/out/ref) and
2124 // the argument names.
2126 Parameter [] p = p_params == null ? Parameters.FixedParameters : p_params.FixedParameters;
2129 MethodBuilder mb = null;
2130 ConstructorBuilder cb = null;
2132 if (builder is MethodBuilder)
2133 mb = (MethodBuilder) builder;
2135 cb = (ConstructorBuilder) builder;
2138 for (i = 0; i < p.Length; i++) {
2139 ParameterBuilder pb;
2142 pb = cb.DefineParameter (
2143 i + 1, p [i].Attributes, p [i].Name);
2145 pb = mb.DefineParameter (
2146 i + 1, p [i].Attributes, p [i].Name);
2148 Attributes attr = p [i].OptAttributes;
2150 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
2154 if (Parameters.ArrayParameter != null){
2155 ParameterBuilder pb;
2156 Parameter array_param = Parameters.ArrayParameter;
2159 pb = cb.DefineParameter (
2160 i + 1, array_param.Attributes,
2163 pb = mb.DefineParameter (
2164 i + 1, array_param.Attributes,
2167 CustomAttributeBuilder a = new CustomAttributeBuilder (
2168 TypeManager.cons_param_array_attribute, new object [0]);
2170 pb.SetCustomAttribute (a);
2175 public class Method : MethodCore {
2176 public MethodBuilder MethodBuilder;
2177 public MethodData MethodData;
2180 /// Modifiers allowed in a class declaration
2182 const int AllowedModifiers =
2185 Modifiers.PROTECTED |
2186 Modifiers.INTERNAL |
2191 Modifiers.OVERRIDE |
2192 Modifiers.ABSTRACT |
2197 // return_type can be "null" for VOID values.
2199 public Method (Expression return_type, int mod, string name, Parameters parameters,
2200 Attributes attrs, Location l)
2201 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2206 public Method (Expression return_type, int mod, string name, Parameters parameters,
2207 Attributes attrs, Expression impl_what, Location l)
2208 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2210 Implements = impl_what;
2214 // Returns the `System.Type' for the ReturnType of this
2215 // function. Provides a nice cache. (used between semantic analysis
2216 // and actual code generation
2218 public Type GetReturnType ()
2223 // Whether this is an operator method.
2224 public bool IsOperator;
2226 void DuplicateEntryPoint (MethodInfo b, Location location)
2230 "Program `" + CodeGen.FileName +
2231 "' has more than one entry point defined: `" +
2232 TypeManager.CSharpSignature(b) + "'");
2235 void Report28 (MethodInfo b)
2237 if (RootContext.WarningLevel < 4)
2242 "`" + TypeManager.CSharpSignature(b) +
2243 "' has the wrong signature to be an entry point");
2246 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2248 if (b.ReturnType != TypeManager.void_type &&
2249 b.ReturnType != TypeManager.int32_type)
2252 if (pinfo.Count == 0)
2255 if (pinfo.Count > 1)
2258 Type t = pinfo.ParameterType(0);
2260 (t.GetArrayRank() == 1) &&
2261 (t.GetElementType() == TypeManager.string_type) &&
2262 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2269 // Checks our base implementation if any
2271 protected override bool CheckBase (TypeContainer parent)
2273 // Check whether arguments were correct.
2274 if (!DoDefineParameters (parent))
2277 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2281 mi_this = TypeContainer.FindMembers (
2282 parent.TypeBuilder, MemberTypes.Method,
2283 BindingFlags.NonPublic | BindingFlags.Public |
2284 BindingFlags.Static | BindingFlags.Instance |
2285 BindingFlags.DeclaredOnly,
2286 MethodSignature.method_signature_filter, ms);
2288 if (mi_this.Count > 0) {
2289 Report.Error (111, Location, "Class `" + parent.Name + "' " +
2290 "already defines a member called `" + Name + "' " +
2291 "with the same parameter types");
2297 // Verify if the parent has a type with the same name, and then
2298 // check whether we have to create a new slot for it or not.
2300 Type ptype = parent.TypeBuilder.BaseType;
2302 // ptype is only null for System.Object while compiling corlib.
2304 MemberList mi, mi_static, mi_instance;
2306 mi_static = TypeContainer.FindMembers (
2307 ptype, MemberTypes.Method,
2308 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2309 MethodSignature.inheritable_method_signature_filter, ms);
2311 mi_instance = TypeContainer.FindMembers (
2312 ptype, MemberTypes.Method,
2313 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2314 MethodSignature.inheritable_method_signature_filter,
2317 if (mi_instance.Count > 0){
2319 } else if (mi_static.Count > 0)
2324 if (mi != null && mi.Count > 0){
2325 parent_method = (MethodInfo) mi [0];
2326 string name = parent_method.DeclaringType.Name + "." +
2329 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2332 if ((ModFlags & Modifiers.NEW) == 0) {
2333 Type parent_ret = TypeManager.TypeToCoreType (
2334 parent_method.ReturnType);
2336 if (parent_ret != MemberType) {
2338 508, parent.MakeName (Name) + ": cannot " +
2339 "change return type when overriding " +
2340 "inherited member " + name);
2345 if ((ModFlags & Modifiers.NEW) != 0)
2346 WarningNotHiding (parent);
2348 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2349 Report.Error (115, Location,
2350 parent.MakeName (Name) +
2351 " no suitable methods found to override");
2354 } else if ((ModFlags & Modifiers.NEW) != 0)
2355 WarningNotHiding (parent);
2363 public override bool Define (TypeContainer parent)
2365 if (!DoDefine (parent))
2368 if (!CheckBase (parent))
2371 CallingConventions cc = GetCallingConvention (parent is Class);
2373 MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2374 ParameterInfo, cc, OptAttributes,
2375 ModFlags, flags, true);
2377 if (!MethodData.Define (parent))
2380 MethodBuilder = MethodData.MethodBuilder;
2383 // This is used to track the Entry Point,
2385 if (Name == "Main" &&
2386 ((ModFlags & Modifiers.STATIC) != 0) &&
2387 (RootContext.MainClass == null ||
2388 RootContext.MainClass == parent.TypeBuilder.FullName ||
2389 (RootContext.RootNamespace != null &&
2390 RootContext.RootNamespace.Length > 0 &&
2391 (RootContext.RootNamespace + "." + RootContext.MainClass) == parent.TypeBuilder.FullName))) {
2392 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2393 if (RootContext.EntryPoint == null) {
2394 RootContext.EntryPoint = MethodBuilder;
2395 RootContext.EntryPointLocation = Location;
2397 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2398 DuplicateEntryPoint (MethodBuilder, Location);
2401 Report28(MethodBuilder);
2410 public void Emit (TypeContainer parent)
2412 MethodData.Emit (parent, Block, this);
2416 public abstract class ConstructorInitializer {
2417 ArrayList argument_list;
2418 ConstructorInfo parent_constructor;
2419 Parameters parameters;
2422 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2425 this.argument_list = argument_list;
2426 this.parameters = parameters;
2430 public ArrayList Arguments {
2432 return argument_list;
2436 public bool Resolve (EmitContext ec)
2438 Expression parent_constructor_group;
2441 ec.CurrentBlock = new Block (null, true, parameters);
2443 if (argument_list != null){
2444 foreach (Argument a in argument_list){
2445 if (!a.Resolve (ec, loc))
2450 ec.CurrentBlock = null;
2452 if (this is ConstructorBaseInitializer) {
2453 if (ec.ContainerType.BaseType == null)
2456 t = ec.ContainerType.BaseType;
2457 if (ec.ContainerType.IsValueType) {
2458 Report.Error (522, loc,
2459 "structs cannot call base class constructors");
2463 t = ec.ContainerType;
2465 parent_constructor_group = Expression.MemberLookup (
2467 MemberTypes.Constructor,
2468 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2471 if (parent_constructor_group == null){
2472 string s = String.Format ("'{0}': Can not find a constructor for this argument list", t);
2473 Report.Error (1501, loc, s);
2477 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2478 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2480 if (parent_constructor == null){
2481 string s = String.Format ("'{0}': Can not find a constructor for this argument list", t);
2482 Report.Error (1501, loc, s);
2489 public void Emit (EmitContext ec)
2491 if (parent_constructor != null){
2493 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2495 Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2500 public class ConstructorBaseInitializer : ConstructorInitializer {
2501 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2502 base (argument_list, pars, l)
2507 public class ConstructorThisInitializer : ConstructorInitializer {
2508 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2509 base (argument_list, pars, l)
2514 public class Constructor : MethodCore {
2515 public ConstructorBuilder ConstructorBuilder;
2516 public ConstructorInitializer Initializer;
2517 new public Attributes OptAttributes;
2520 // Modifiers allowed for a constructor.
2522 public const int AllowedModifiers =
2524 Modifiers.PROTECTED |
2525 Modifiers.INTERNAL |
2532 // The spec claims that static is not permitted, but
2533 // my very own code has static constructors.
2535 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2536 : base (null, 0, AllowedModifiers, name, null, args, l)
2542 // Returns true if this is a default constructor
2544 public bool IsDefault ()
2546 if ((ModFlags & Modifiers.STATIC) != 0)
2547 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2548 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2551 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2552 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2553 (Initializer is ConstructorBaseInitializer) &&
2554 (Initializer.Arguments == null);
2558 // Creates the ConstructorBuilder
2560 public override bool Define (TypeContainer parent)
2562 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2563 MethodAttributes.SpecialName);
2565 // Check if arguments were correct.
2566 if (!DoDefineParameters (parent))
2569 if ((ModFlags & Modifiers.STATIC) != 0)
2570 ca |= MethodAttributes.Static;
2572 if (parent is Struct && ParameterTypes.Length == 0){
2575 "Structs can not contain explicit parameterless " +
2579 ca |= MethodAttributes.HideBySig;
2581 if ((ModFlags & Modifiers.PUBLIC) != 0)
2582 ca |= MethodAttributes.Public;
2583 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2584 if ((ModFlags & Modifiers.INTERNAL) != 0)
2585 ca |= MethodAttributes.FamORAssem;
2587 ca |= MethodAttributes.Family;
2588 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2589 ca |= MethodAttributes.Assembly;
2590 else if (IsDefault ())
2591 ca |= MethodAttributes.Public;
2593 ca |= MethodAttributes.Private;
2596 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2597 ca, GetCallingConvention (parent is Class), ParameterTypes);
2600 // HACK because System.Reflection.Emit is lame
2602 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2605 "Class `" +parent.Name+ "' already contains a definition with the " +
2606 "same return value and parameter types for constructor `" + Name
2617 public void Emit (TypeContainer parent)
2619 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2620 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2622 if ((ModFlags & Modifiers.STATIC) == 0){
2623 if (parent is Class && Initializer == null)
2624 Initializer = new ConstructorBaseInitializer (
2625 null, Parameters.EmptyReadOnlyParameters, parent.Location);
2629 // Spec mandates that Initializers will not have
2633 if (Initializer != null && !Initializer.Resolve (ec))
2635 ec.IsStatic = false;
2638 LabelParameters (ec, ParameterTypes, ConstructorBuilder);
2641 // Classes can have base initializers and instance field initializers.
2643 if (parent is Class){
2644 if ((ModFlags & Modifiers.STATIC) == 0)
2645 parent.EmitFieldInitializers (ec);
2647 if (Initializer != null)
2648 Initializer.Emit (ec);
2650 if ((ModFlags & Modifiers.STATIC) != 0)
2651 parent.EmitFieldInitializers (ec);
2653 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2655 // If this is a non-static `struct' constructor and doesn't have any
2656 // initializer, it must initialize all of the struct's fields.
2657 if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2658 (Initializer == null))
2659 Block.AddThisVariable (parent, Location);
2661 ec.EmitTopBlock (Block, ParameterInfo, Location);
2665 public class MethodData {
2667 // The return type of this method
2669 public readonly Type ReturnType;
2670 public readonly Type[] ParameterTypes;
2671 public readonly InternalParameters ParameterInfo;
2672 public readonly CallingConventions CallingConventions;
2673 public readonly Attributes OptAttributes;
2674 public readonly Location Location;
2677 // Are we implementing an interface ?
2679 public bool IsImplementing = false;
2684 protected MemberBase member;
2685 protected int modifiers;
2686 protected MethodAttributes flags;
2687 protected bool is_method;
2688 protected string accessor_name;
2689 ArrayList conditionals;
2691 MethodBuilder builder = null;
2692 public MethodBuilder MethodBuilder {
2698 public MethodData (MemberBase member, string name, Type return_type,
2699 Type [] parameter_types, InternalParameters parameters,
2700 CallingConventions cc, Attributes opt_attrs,
2701 int modifiers, MethodAttributes flags, bool is_method)
2703 this.member = member;
2704 this.accessor_name = name;
2705 this.ReturnType = return_type;
2706 this.ParameterTypes = parameter_types;
2707 this.ParameterInfo = parameters;
2708 this.CallingConventions = cc;
2709 this.OptAttributes = opt_attrs;
2710 this.modifiers = modifiers;
2712 this.is_method = is_method;
2713 this.Location = member.Location;
2714 this.conditionals = new ArrayList ();
2720 Attribute dllimport_attribute = null;
2721 string obsolete = null;
2722 bool obsolete_error = false;
2724 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2726 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2729 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2730 if (asec.Attributes == null)
2733 foreach (Attribute a in asec.Attributes) {
2734 if (a.Name == "Conditional") {
2735 if (!ApplyConditionalAttribute (a))
2737 } else if (a.Name == "Obsolete") {
2738 if (!ApplyObsoleteAttribute (a))
2740 } else if (a.Name.IndexOf ("DllImport") != -1) {
2742 a.Type = TypeManager.dllimport_type;
2743 Attribute.Error_AttributeNotValidForElement (a, Location);
2746 if (!ApplyDllImportAttribute (a))
2756 // Applies the `DllImport' attribute to the method.
2758 protected virtual bool ApplyDllImportAttribute (Attribute a)
2760 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2761 if ((modifiers & extern_static) != extern_static) {
2762 Report.Error (601, Location,
2763 "The DllImport attribute must be specified on a method " +
2764 "marked `static' and `extern'.");
2768 flags |= MethodAttributes.PinvokeImpl;
2769 dllimport_attribute = a;
2774 // Applies the `Obsolete' attribute to the method.
2776 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2778 if (obsolete != null) {
2779 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2783 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2784 return obsolete != null;
2788 // Applies the `Conditional' attribute to the method.
2790 protected virtual bool ApplyConditionalAttribute (Attribute a)
2792 // The Conditional attribute is only valid on methods.
2794 Attribute.Error_AttributeNotValidForElement (a, Location);
2798 string condition = a.Conditional_GetConditionName ();
2800 if (condition == null)
2803 if (ReturnType != TypeManager.void_type) {
2804 Report.Error (578, Location,
2805 "Conditional not valid on `" + member.Name + "' " +
2806 "because its return type is not void");
2810 if ((modifiers & Modifiers.OVERRIDE) != 0) {
2811 Report.Error (243, Location,
2812 "Conditional not valid on `" + member.Name + "' " +
2813 "because it is an override method");
2817 if (member.IsExplicitImpl) {
2818 Report.Error (577, Location,
2819 "Conditional not valid on `" + member.Name + "' " +
2820 "because it is an explicit interface implementation");
2824 if (IsImplementing) {
2825 Report.Error (623, Location,
2826 "Conditional not valid on `" + member.Name + "' " +
2827 "because it is an interface method");
2831 conditionals.Add (condition);
2837 // Checks whether this method should be ignored due to its Conditional attributes.
2839 bool ShouldIgnore (Location loc)
2841 // When we're overriding a virtual method, we implicitly inherit the
2842 // Conditional attributes from our parent.
2843 if (member.ParentMethod != null) {
2844 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2845 member.ParentMethod, loc);
2847 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2851 foreach (string condition in conditionals)
2852 if (RootContext.AllDefines [condition] == null)
2859 // Returns the TypeManager.MethodFlags for this method.
2860 // This emits an error 619 / warning 618 if the method is obsolete.
2861 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2863 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2865 TypeManager.MethodFlags flags = 0;
2867 if (obsolete != null) {
2868 if (obsolete_error) {
2869 Report.Error (619, loc, "Method `" + member.Name +
2870 "' is obsolete: `" + obsolete + "'");
2871 return TypeManager.MethodFlags.IsObsoleteError;
2873 Report.Warning (618, loc, "Method `" + member.Name +
2874 "' is obsolete: `" + obsolete + "'");
2876 flags |= TypeManager.MethodFlags.IsObsolete;
2879 if (ShouldIgnore (loc))
2880 flags |= TypeManager.MethodFlags.ShouldIgnore;
2885 public virtual bool Define (TypeContainer parent)
2887 MethodInfo implementing = null;
2888 string method_name, name, prefix;
2890 if (OptAttributes != null)
2891 if (!ApplyAttributes (OptAttributes, is_method))
2894 if (member.IsExplicitImpl)
2895 prefix = member.InterfaceType.FullName + ".";
2899 if (accessor_name != null)
2900 name = accessor_name + "_" + member.ShortName;
2902 name = member.ShortName;
2903 method_name = prefix + name;
2905 if (parent.Pending != null){
2906 if (member is Indexer)
2907 implementing = parent.Pending.IsInterfaceIndexer (
2908 member.InterfaceType, ReturnType, ParameterTypes);
2910 implementing = parent.Pending.IsInterfaceMethod (
2911 member.InterfaceType, name, ReturnType, ParameterTypes);
2913 if (member.InterfaceType != null && implementing == null){
2914 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
2921 // For implicit implementations, make sure we are public, for
2922 // explicit implementations, make sure we are private.
2924 if (implementing != null){
2926 // Setting null inside this block will trigger a more
2927 // verbose error reporting for missing interface implementations
2929 // The "candidate" function has been flagged already
2930 // but it wont get cleared
2932 if (!member.IsExplicitImpl){
2934 // We already catch different accessibility settings
2935 // so we just need to check that we are not private
2937 if ((modifiers & Modifiers.PRIVATE) != 0)
2938 implementing = null;
2941 // Static is not allowed
2943 if ((modifiers & Modifiers.STATIC) != 0)
2944 implementing = null;
2946 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
2947 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
2948 implementing = null;
2954 // If implementing is still valid, set flags
2956 if (implementing != null){
2958 // When implementing interface methods, set NewSlot.
2960 if (implementing.DeclaringType.IsInterface)
2961 flags |= MethodAttributes.NewSlot;
2964 MethodAttributes.Virtual |
2965 MethodAttributes.HideBySig;
2967 // Get the method name from the explicit interface.
2968 if (member.InterfaceType != null) {
2969 name = implementing.Name;
2970 method_name = prefix + name;
2973 IsImplementing = true;
2977 // Create the MethodBuilder for the method
2979 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2980 if ((modifiers & Modifiers.STATIC) == 0) {
2981 Report.Error (601, Location,
2982 "The DllImport attribute must be specified on " +
2983 "a method marked 'static' and 'extern'.");
2987 EmitContext ec = new EmitContext (
2988 parent, Location, null, ReturnType, modifiers);
2990 builder = dllimport_attribute.DefinePInvokeMethod (
2991 ec, parent.TypeBuilder, method_name, flags,
2992 ReturnType, ParameterTypes);
2994 builder = parent.TypeBuilder.DefineMethod (
2995 method_name, flags, CallingConventions,
2996 ReturnType, ParameterTypes);
2998 if (builder == null)
3001 if (IsImplementing) {
3003 // clear the pending implemntation flag
3005 if (member is Indexer) {
3006 parent.Pending.ImplementIndexer (
3007 member.InterfaceType, builder, ReturnType,
3008 ParameterTypes, true);
3010 parent.Pending.ImplementMethod (
3011 member.InterfaceType, name, ReturnType,
3012 ParameterTypes, member.IsExplicitImpl);
3014 if (member.IsExplicitImpl)
3015 parent.TypeBuilder.DefineMethodOverride (
3016 builder, implementing);
3019 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3020 Report.Error (111, Location,
3021 "Class `" + parent.Name +
3022 "' already contains a definition with the " +
3023 "same return value and parameter types as the " +
3024 "'get' method of property `" + member.Name + "'");
3028 TypeManager.AddMethod (builder, this);
3036 public virtual void Emit (TypeContainer parent, Block block, object kind)
3041 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3042 ig = builder.GetILGenerator ();
3046 ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3048 if (OptAttributes != null)
3049 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
3051 if (member is MethodCore)
3052 ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder);
3055 // abstract or extern methods have no bodies
3057 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3062 // abstract or extern methods have no bodies.
3064 if ((modifiers & Modifiers.ABSTRACT) != 0)
3066 500, Location, "Abstract method `" +
3067 TypeManager.CSharpSignature (builder) +
3068 "' can not have a body");
3070 if ((modifiers & Modifiers.EXTERN) != 0)
3072 179, Location, "External method `" +
3073 TypeManager.CSharpSignature (builder) +
3074 "' can not have a body");
3080 // Methods must have a body unless they're extern or abstract
3082 if (block == null) {
3084 501, Location, "Method `" +
3085 TypeManager.CSharpSignature (builder) +
3086 "' must declare a body since it is not marked " +
3087 "abstract or extern");
3092 // Handle destructors specially
3094 // FIXME: This code generates buggy code
3096 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3097 EmitDestructor (ec, block);
3099 ISymbolWriter sw = CodeGen.SymbolWriter;
3101 if ((sw != null) && !Location.IsNull (Location) &&
3102 !Location.IsNull (block.EndLocation)) {
3103 Location end = block.EndLocation;
3104 MethodToken token = MethodBuilder.GetToken ();
3105 sw.OpenMethod (new SymbolToken (token.Token));
3106 // Avoid error if we don't support debugging for the platform
3108 sw.SetMethodSourceRange (Location.SymbolDocument,
3112 } catch (Exception) {
3115 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3119 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3123 void EmitDestructor (EmitContext ec, Block block)
3125 ILGenerator ig = ec.ig;
3127 Label finish = ig.DefineLabel ();
3128 bool old_in_try = ec.InTry;
3130 ig.BeginExceptionBlock ();
3132 ec.ReturnLabel = finish;
3133 ec.HasReturnLabel = true;
3134 ec.EmitTopBlock (block, null, Location);
3135 ec.InTry = old_in_try;
3137 // ig.MarkLabel (finish);
3138 bool old_in_finally = ec.InFinally;
3139 ec.InFinally = true;
3140 ig.BeginFinallyBlock ();
3142 if (ec.ContainerType.BaseType != null) {
3143 Expression member_lookup = Expression.MemberLookup (
3144 ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
3145 MemberTypes.Method, Expression.AllBindingFlags, Location);
3147 if (member_lookup != null){
3148 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3150 ig.Emit (OpCodes.Ldarg_0);
3151 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3154 ec.InFinally = old_in_finally;
3156 ig.EndExceptionBlock ();
3157 //ig.MarkLabel (ec.ReturnLabel);
3158 ig.Emit (OpCodes.Ret);
3162 abstract public class MemberBase : MemberCore {
3163 public Expression Type;
3164 public readonly Attributes OptAttributes;
3165 public Expression Implements;
3167 protected MethodAttributes flags;
3170 // The "short" name of this property / indexer / event. This is the
3171 // name without the explicit interface.
3173 public string ShortName;
3176 // The type of this property / indexer / event
3178 public Type MemberType;
3181 // If true, this is an explicit interface implementation
3183 public bool IsExplicitImpl = false;
3186 // The name of the interface we are explicitly implementing
3188 public string ExplicitInterfaceName = null;
3191 // If true, the interface type we are explicitly implementing
3193 public Type InterfaceType = null;
3196 // The method we're overriding if this is an override method.
3198 protected MethodInfo parent_method = null;
3199 public MethodInfo ParentMethod {
3201 return parent_method;
3206 // The constructor is only exposed to our children
3208 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3209 Attributes attrs, Location loc)
3213 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
3214 OptAttributes = attrs;
3217 protected virtual bool CheckBase (TypeContainer parent)
3222 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3226 foreach (Type partype in parameters){
3227 if (partype.IsPointer && !UnsafeOK (parent))
3230 if (parent.AsAccessible (partype, ModFlags))
3233 if (this is Indexer)
3234 Report.Error (55, Location,
3235 "Inconsistent accessibility: parameter type `" +
3236 TypeManager.CSharpName (partype) + "' is less " +
3237 "accessible than indexer `" + Name + "'");
3239 Report.Error (51, Location,
3240 "Inconsistent accessibility: parameter type `" +
3241 TypeManager.CSharpName (partype) + "' is less " +
3242 "accessible than method `" + Name + "'");
3249 protected virtual bool DoDefine (TypeContainer parent)
3254 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3257 flags = Modifiers.MethodAttr (ModFlags);
3259 // Lookup Type, verify validity
3260 MemberType = parent.ResolveType (Type, false, Location);
3261 if (MemberType == null)
3264 // verify accessibility
3265 if (!parent.AsAccessible (MemberType, ModFlags)) {
3266 if (this is Property)
3267 Report.Error (53, Location,
3268 "Inconsistent accessibility: property type `" +
3269 TypeManager.CSharpName (MemberType) + "' is less " +
3270 "accessible than property `" + Name + "'");
3271 else if (this is Indexer)
3272 Report.Error (54, Location,
3273 "Inconsistent accessibility: indexer return type `" +
3274 TypeManager.CSharpName (MemberType) + "' is less " +
3275 "accessible than indexer `" + Name + "'");
3276 else if (this is Method)
3277 Report.Error (50, Location,
3278 "Inconsistent accessibility: return type `" +
3279 TypeManager.CSharpName (MemberType) + "' is less " +
3280 "accessible than method `" + Name + "'");
3282 Report.Error (52, Location,
3283 "Inconsistent accessibility: field type `" +
3284 TypeManager.CSharpName (MemberType) + "' is less " +
3285 "accessible than field `" + Name + "'");
3289 if (MemberType.IsPointer && !UnsafeOK (parent))
3293 // Check for explicit interface implementation
3295 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
3296 int pos = Name.LastIndexOf (".");
3298 ExplicitInterfaceName = Name.Substring (0, pos);
3299 ShortName = Name.Substring (pos + 1);
3303 if (ExplicitInterfaceName != null) {
3304 InterfaceType = RootContext.LookupType (
3305 parent, ExplicitInterfaceName, false, Location);
3306 if (InterfaceType == null)
3309 // Compute the full name that we need to export.
3310 Name = InterfaceType.FullName + "." + ShortName;
3312 if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
3315 IsExplicitImpl = true;
3317 IsExplicitImpl = false;
3324 // Fields and Events both generate FieldBuilders, we use this to share
3325 // their common bits. This is also used to flag usage of the field
3327 abstract public class FieldBase : MemberBase {
3328 public FieldBuilder FieldBuilder;
3329 public Status status;
3332 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3335 // The constructor is only exposed to our children
3337 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3338 object init, Attributes attrs, Location loc)
3339 : base (type, mod, allowed_mod, name, attrs, loc)
3345 // Whether this field has an initializer.
3347 public bool HasInitializer {
3349 return init != null;
3354 readonly Object init;
3355 Expression init_expr;
3356 bool init_expr_initialized = false;
3359 // Resolves and returns the field initializer.
3361 public Expression GetInitializerExpression (EmitContext ec)
3363 if (init_expr_initialized)
3367 if (init is Expression)
3368 e = (Expression) init;
3370 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3372 ec.IsFieldInitializer = true;
3373 e = e.DoResolve (ec);
3374 ec.IsFieldInitializer = false;
3377 init_expr_initialized = true;
3384 // The Field class is used to represents class/struct fields during parsing.
3386 public class Field : FieldBase {
3388 // Modifiers allowed in a class declaration
3390 const int AllowedModifiers =
3393 Modifiers.PROTECTED |
3394 Modifiers.INTERNAL |
3397 Modifiers.VOLATILE |
3401 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3402 Attributes attrs, Location loc)
3403 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3407 public override bool Define (TypeContainer parent)
3409 Type t = parent.ResolveType (Type, false, Location);
3414 if (!parent.AsAccessible (t, ModFlags)) {
3415 Report.Error (52, Location,
3416 "Inconsistent accessibility: field type `" +
3417 TypeManager.CSharpName (t) + "' is less " +
3418 "accessible than field `" + Name + "'");
3422 if (t.IsPointer && !UnsafeOK (parent))
3425 if (RootContext.WarningLevel > 1){
3426 Type ptype = parent.TypeBuilder.BaseType;
3428 // ptype is only null for System.Object while compiling corlib.
3430 TypeContainer.FindMembers (
3431 ptype, MemberTypes.Method,
3432 BindingFlags.Public |
3433 BindingFlags.Static | BindingFlags.Instance,
3434 System.Type.FilterName, Name);
3438 if ((ModFlags & Modifiers.VOLATILE) != 0){
3440 if (TypeManager.IsEnumType (t))
3441 t = TypeManager.EnumToUnderlying (t);
3443 if (!((t == TypeManager.bool_type) ||
3444 (t == TypeManager.sbyte_type) ||
3445 (t == TypeManager.byte_type) ||
3446 (t == TypeManager.short_type) ||
3447 (t == TypeManager.ushort_type) ||
3448 (t == TypeManager.int32_type) ||
3449 (t == TypeManager.uint32_type) ||
3450 (t == TypeManager.char_type) ||
3451 (t == TypeManager.float_type))){
3453 677, Location, parent.MakeName (Name) +
3454 " A volatile field can not be of type `" +
3455 TypeManager.CSharpName (t) + "'");
3461 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3463 if (parent is Struct &&
3464 ((fa & FieldAttributes.Static) == 0) &&
3465 t == parent.TypeBuilder &&
3466 !TypeManager.IsBuiltinType (t)){
3467 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name +
3468 "' causes a cycle in the structure layout");
3471 FieldBuilder = parent.TypeBuilder.DefineField (
3472 Name, t, Modifiers.FieldAttr (ModFlags));
3474 TypeManager.RegisterFieldBase (FieldBuilder, this);
3478 public void Emit (TypeContainer tc)
3480 EmitContext ec = new EmitContext (tc, Location, null,
3481 FieldBuilder.FieldType, ModFlags);
3483 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
3488 // `set' and `get' accessors are represented with an Accessor.
3490 public class Accessor {
3492 // Null if the accessor is empty, or a Block if not
3495 public Attributes OptAttributes;
3497 public Accessor (Block b, Attributes attrs)
3500 OptAttributes = attrs;
3505 // Properties and Indexers both generate PropertyBuilders, we use this to share
3506 // their common bits.
3508 abstract public class PropertyBase : MethodCore {
3509 public Accessor Get, Set;
3510 public PropertyBuilder PropertyBuilder;
3511 public MethodBuilder GetBuilder, SetBuilder;
3512 public MethodData GetData, SetData;
3514 protected EmitContext ec;
3516 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3517 Parameters parameters, Accessor get_block, Accessor set_block,
3518 Attributes attrs, Location loc)
3519 : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3525 protected override bool DoDefine (TypeContainer parent)
3527 if (!base.DoDefine (parent))
3530 ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3536 // Checks our base implementation if any
3538 protected override bool CheckBase (TypeContainer parent)
3540 // Check whether arguments were correct.
3541 if (!DoDefineParameters (parent))
3548 MethodSignature ms, base_ms;
3549 if (this is Indexer) {
3550 string name, base_name;
3552 report_name = "this";
3553 name = TypeManager.IndexerPropertyName (parent.TypeBuilder);
3554 ms = new MethodSignature (name, null, ParameterTypes);
3555 base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType);
3556 base_ms = new MethodSignature (base_name, null, ParameterTypes);
3559 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
3562 MemberList props_this;
3564 props_this = TypeContainer.FindMembers (
3565 parent.TypeBuilder, MemberTypes.Property,
3566 BindingFlags.NonPublic | BindingFlags.Public |
3567 BindingFlags.Static | BindingFlags.Instance |
3568 BindingFlags.DeclaredOnly,
3569 MethodSignature.method_signature_filter, ms);
3571 if (props_this.Count > 0) {
3572 Report.Error (111, Location, "Class `" + parent.Name + "' " +
3573 "already defines a member called `" + report_name + "' " +
3574 "with the same parameter types");
3579 // Find properties with the same name on the base class
3582 MemberList props_static = TypeContainer.FindMembers (
3583 parent.TypeBuilder.BaseType, MemberTypes.Property,
3584 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3585 MethodSignature.inheritable_property_signature_filter, base_ms);
3587 MemberList props_instance = TypeContainer.FindMembers (
3588 parent.TypeBuilder.BaseType, MemberTypes.Property,
3589 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3590 MethodSignature.inheritable_property_signature_filter,
3594 // Find if we have anything
3596 if (props_static.Count > 0)
3597 props = props_static;
3598 else if (props_instance.Count > 0)
3599 props = props_instance;
3604 // If we have something on the base.
3605 if (props != null && props.Count > 0){
3606 PropertyInfo pi = (PropertyInfo) props [0];
3608 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
3609 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
3611 MethodInfo reference = inherited_get == null ?
3612 inherited_set : inherited_get;
3614 if (reference != null) {
3615 string name = reference.DeclaringType.Name + "." + report_name;
3617 if (!CheckMethodAgainstBase (parent, flags, reference, name))
3621 if (((ModFlags & Modifiers.NEW) == 0) && (pi.PropertyType != MemberType)) {
3622 Report.Error (508, parent.MakeName (Name) + ": cannot " +
3623 "change return type when overriding inherited " +
3624 "member `" + pi.DeclaringType + "." + pi.Name + "'");
3628 if ((ModFlags & Modifiers.NEW) != 0)
3629 WarningNotHiding (parent);
3631 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3632 if (this is Indexer)
3633 Report.Error (115, Location,
3634 parent.MakeName (Name) +
3635 " no suitable indexers found to override");
3637 Report.Error (115, Location,
3638 parent.MakeName (Name) +
3639 " no suitable properties found to override");
3646 public virtual void Emit (TypeContainer tc)
3649 // The PropertyBuilder can be null for explicit implementations, in that
3650 // case, we do not actually emit the ".property", so there is nowhere to
3651 // put the attribute
3653 if (PropertyBuilder != null)
3654 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3656 if (GetData != null)
3657 GetData.Emit (tc, Get.Block, Get);
3659 if (SetData != null)
3660 SetData.Emit (tc, Set.Block, Set);
3665 public class Property : PropertyBase {
3666 const int AllowedModifiers =
3669 Modifiers.PROTECTED |
3670 Modifiers.INTERNAL |
3674 Modifiers.OVERRIDE |
3675 Modifiers.ABSTRACT |
3680 Modifiers.READONLY |
3681 Modifiers.WRITEONLY ;
3683 string set_parameter_name;
3684 Parameters get_params;
3685 Parameters set_params;
3687 public Property (Expression type, string name, int mod_flags,
3688 Accessor get_block, Accessor set_block,
3689 Attributes attrs, Location loc, string set_name,
3690 Parameters p_get, Parameters p_set, Expression impl_what)
3691 : base (type, name, mod_flags, AllowedModifiers,
3693 get_block, set_block, attrs, loc)
3695 set_parameter_name = set_name;
3698 Implements = impl_what;
3701 public Property (Expression type, string name, int mod_flags,
3702 Accessor get_block, Accessor set_block,
3703 Attributes attrs, Location loc)
3704 : this (type, name, mod_flags, get_block, set_block, attrs, loc,
3705 "Value", Parameters.EmptyReadOnlyParameters, Parameters.EmptyReadOnlyParameters, null)
3709 public override bool Define (TypeContainer parent)
3711 Type [] g_parameters=null, s_parameters=null;
3712 Parameter [] g_parms, s_parms;
3713 InternalParameters g_ip=null, s_ip=null;
3715 if (!DoDefine (parent))
3718 if (!CheckBase (parent))
3721 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3724 if (get_params == Parameters.EmptyReadOnlyParameters)
3726 g_parameters = TypeManager.NoTypes;
3727 g_ip = new InternalParameters (
3728 parent, Parameters.EmptyReadOnlyParameters);
3732 g_parameters = new Type [get_params.FixedParameters.Length];
3733 for (int i = 0; i < get_params.FixedParameters.Length; i ++)
3735 g_parameters[i] = get_params.FixedParameters[i].ParameterType;
3737 g_parms = new Parameter [get_params.FixedParameters.Length];
3738 for (int i = 0; i < get_params.FixedParameters.Length; i ++)
3740 Parameter tp = get_params.FixedParameters[i];
3741 g_parms[i] = new Parameter (tp.TypeName, tp.Name,
3742 Parameter.Modifier.NONE, null);
3744 g_ip = new InternalParameters (
3745 parent, new Parameters (g_parms, null, Location));
3748 GetData = new MethodData (this, "get", MemberType,
3749 g_parameters, g_ip, CallingConventions.Standard,
3750 Get.OptAttributes, ModFlags, flags, false);
3752 if (!GetData.Define (parent))
3755 GetBuilder = GetData.MethodBuilder;
3759 if (set_params == Parameters.EmptyReadOnlyParameters)
3761 s_parameters = new Type [1];
3762 s_parameters [0] = MemberType;
3764 s_parms = new Parameter [1];
3765 s_parms [0] = new Parameter (Type, /* was "value" */ set_parameter_name,
3766 Parameter.Modifier.NONE, null);
3770 s_parameters = new Type [set_params.FixedParameters.Length];
3771 for (int i = 0; i < set_params.FixedParameters.Length; i ++)
3773 s_parameters[i] = set_params.FixedParameters[i].ParameterType;
3776 s_parms = new Parameter [set_params.FixedParameters.Length];
3777 for (int i = 0; i < set_params.FixedParameters.Length; i ++)
3779 Parameter tp = set_params.FixedParameters[i];
3780 s_parms[i] = new Parameter (tp.TypeName, tp.Name,
3781 Parameter.Modifier.NONE, null);
3785 s_ip = new InternalParameters (
3786 parent, new Parameters (s_parms, null, Location));
3789 SetData = new MethodData (this, "set", TypeManager.void_type,
3790 s_parameters, s_ip, CallingConventions.Standard,
3791 Set.OptAttributes, ModFlags, flags, false);
3793 if (!SetData.Define (parent))
3796 SetBuilder = SetData.MethodBuilder;
3797 SetBuilder.DefineParameter (1, ParameterAttributes.None,
3798 /* was "value" */ set_parameter_name);
3801 // FIXME - PropertyAttributes.HasDefault ?
3803 PropertyAttributes prop_attr =
3804 PropertyAttributes.RTSpecialName |
3805 PropertyAttributes.SpecialName;
3807 if (!IsExplicitImpl){
3808 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3809 Name, prop_attr, MemberType, null);
3812 PropertyBuilder.SetGetMethod (GetBuilder);
3815 PropertyBuilder.SetSetMethod (SetBuilder);
3818 // HACK for the reasons exposed above
3820 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3823 "Class `" + parent.Name +
3824 "' already contains a definition for the property `" +
3832 public override void Emit (TypeContainer tc)
3836 if (GetData != null)
3838 Parameters = get_params;
3839 GetData.Emit (tc, Get.Block, Get);
3842 if (SetData != null)
3844 Parameters = set_params;
3845 SetData.Emit (tc, Set.Block, Set);
3852 /// Gigantic workaround for lameness in SRE follows :
3853 /// This class derives from EventInfo and attempts to basically
3854 /// wrap around the EventBuilder so that FindMembers can quickly
3855 /// return this in it search for members
3857 public class MyEventBuilder : EventInfo {
3860 // We use this to "point" to our Builder which is
3861 // not really a MemberInfo
3863 EventBuilder MyBuilder;
3866 // We "catch" and wrap these methods
3868 MethodInfo raise, remove, add;
3870 EventAttributes attributes;
3871 Type declaring_type, reflected_type, event_type;
3874 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3876 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3878 // And now store the values in our own fields.
3880 declaring_type = type_builder;
3882 reflected_type = type_builder;
3884 attributes = event_attr;
3886 this.event_type = event_type;
3890 // Methods that you have to override. Note that you only need
3891 // to "implement" the variants that take the argument (those are
3892 // the "abstract" methods, the others (GetAddMethod()) are
3895 public override MethodInfo GetAddMethod (bool nonPublic)
3900 public override MethodInfo GetRemoveMethod (bool nonPublic)
3905 public override MethodInfo GetRaiseMethod (bool nonPublic)
3911 // These methods make "MyEventInfo" look like a Builder
3913 public void SetRaiseMethod (MethodBuilder raiseMethod)
3915 raise = raiseMethod;
3916 MyBuilder.SetRaiseMethod (raiseMethod);
3919 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3921 remove = removeMethod;
3922 MyBuilder.SetRemoveOnMethod (removeMethod);
3925 public void SetAddOnMethod (MethodBuilder addMethod)
3928 MyBuilder.SetAddOnMethod (addMethod);
3931 public void SetCustomAttribute (CustomAttributeBuilder cb)
3933 MyBuilder.SetCustomAttribute (cb);
3936 public override object [] GetCustomAttributes (bool inherit)
3938 // FIXME : There's nothing which can be seemingly done here because
3939 // we have no way of getting at the custom attribute objects of the
3944 public override object [] GetCustomAttributes (Type t, bool inherit)
3946 // FIXME : Same here !
3950 public override bool IsDefined (Type t, bool b)
3955 public override EventAttributes Attributes {
3961 public override string Name {
3967 public override Type DeclaringType {
3969 return declaring_type;
3973 public override Type ReflectedType {
3975 return reflected_type;
3979 public Type EventType {
3986 public class Event : FieldBase {
3987 const int AllowedModifiers =
3990 Modifiers.PROTECTED |
3991 Modifiers.INTERNAL |
3996 Modifiers.OVERRIDE |
4000 public readonly Accessor Add;
4001 public readonly Accessor Remove;
4002 public MyEventBuilder EventBuilder;
4004 MethodBuilder AddBuilder, RemoveBuilder;
4005 MethodData AddData, RemoveData;
4007 public Event (Expression type, string name, Object init, int mod, Accessor add,
4008 Accessor remove, Attributes attrs, Location loc)
4009 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4015 public override bool Define (TypeContainer parent)
4017 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4019 if (!DoDefine (parent))
4022 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4023 Report.Error (66, Location, "'" + parent.Name + "." + Name +
4024 "' : event must be of a delegate type");
4028 Type [] parameter_types = new Type [1];
4029 parameter_types [0] = MemberType;
4031 Parameter [] parms = new Parameter [1];
4032 parms [0] = new Parameter (Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4033 InternalParameters ip = new InternalParameters (
4034 parent, new Parameters (parms, null, Location));
4036 if (!CheckBase (parent))
4040 // Now define the accessors
4042 AddData = new MethodData (this, "add", TypeManager.void_type,
4043 parameter_types, ip, CallingConventions.Standard,
4044 (Add != null) ? Add.OptAttributes : null,
4045 ModFlags, flags, false);
4047 if (!AddData.Define (parent))
4050 AddBuilder = AddData.MethodBuilder;
4051 AddBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4053 RemoveData = new MethodData (this, "remove", TypeManager.void_type,
4054 parameter_types, ip, CallingConventions.Standard,
4055 (Remove != null) ? Remove.OptAttributes : null,
4056 ModFlags, flags, false);
4058 if (!RemoveData.Define (parent))
4061 RemoveBuilder = RemoveData.MethodBuilder;
4062 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4064 if (!IsExplicitImpl){
4065 EventBuilder = new MyEventBuilder (
4066 parent.TypeBuilder, Name, e_attr, MemberType);
4068 if (Add == null && Remove == null) {
4069 FieldBuilder = parent.TypeBuilder.DefineField (
4071 FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4072 TypeManager.RegisterPrivateFieldOfEvent (
4073 (EventInfo) EventBuilder, FieldBuilder);
4074 TypeManager.RegisterFieldBase (FieldBuilder, this);
4077 EventBuilder.SetAddOnMethod (AddBuilder);
4078 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4080 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4081 Report.Error (111, Location,
4082 "Class `" + parent.Name +
4083 "' already contains a definition for the event `" +
4092 void EmitDefaultMethod (EmitContext ec, bool is_add)
4094 ILGenerator ig = ec.ig;
4095 MethodInfo method = null;
4098 method = TypeManager.delegate_combine_delegate_delegate;
4100 method = TypeManager.delegate_remove_delegate_delegate;
4102 if ((ModFlags & Modifiers.STATIC) != 0) {
4103 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4104 ig.Emit (OpCodes.Ldarg_0);
4105 ig.Emit (OpCodes.Call, method);
4106 ig.Emit (OpCodes.Castclass, MemberType);
4107 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4109 ig.Emit (OpCodes.Ldarg_0);
4110 ig.Emit (OpCodes.Ldarg_0);
4111 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4112 ig.Emit (OpCodes.Ldarg_1);
4113 ig.Emit (OpCodes.Call, method);
4114 ig.Emit (OpCodes.Castclass, MemberType);
4115 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4117 ig.Emit (OpCodes.Ret);
4120 public void Emit (TypeContainer tc)
4124 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4125 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
4128 AddData.Emit (tc, Add.Block, Add);
4130 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4131 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4132 EmitDefaultMethod (ec, true);
4136 RemoveData.Emit (tc, Remove.Block, Remove);
4138 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4139 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4140 EmitDefaultMethod (ec, false);
4147 // FIXME: This does not handle:
4149 // int INTERFACENAME [ args ]
4154 // int this [ args ]
4156 public class Indexer : PropertyBase {
4158 const int AllowedModifiers =
4161 Modifiers.PROTECTED |
4162 Modifiers.INTERNAL |
4166 Modifiers.OVERRIDE |
4171 public string IndexerName;
4172 public string InterfaceIndexerName;
4175 // Are we implementing an interface ?
4177 bool IsImplementing = false;
4179 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4180 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4181 : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4184 ExplicitInterfaceName = int_type;
4187 public override bool Define (TypeContainer parent)
4189 PropertyAttributes prop_attr =
4190 PropertyAttributes.RTSpecialName |
4191 PropertyAttributes.SpecialName;
4193 if (!DoDefine (parent))
4196 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4197 if (IndexerName == null)
4198 IndexerName = "Item";
4199 else if (IsExplicitImpl)
4200 Report.Error (592, Location,
4201 "Attribute 'IndexerName' is not valid on this declaration " +
4202 "type. It is valid on `property' declarations only.");
4204 ShortName = IndexerName;
4205 if (IsExplicitImpl) {
4206 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4207 Name = InterfaceType.FullName + "." + IndexerName;
4209 InterfaceIndexerName = IndexerName;
4213 if (!CheckBase (parent))
4217 InternalParameters ip = new InternalParameters (parent, Parameters);
4219 GetData = new MethodData (this, "get", MemberType,
4220 ParameterTypes, ip, CallingConventions.Standard,
4221 Get.OptAttributes, ModFlags, flags, false);
4223 if (!GetData.Define (parent))
4226 GetBuilder = GetData.MethodBuilder;
4230 int top = ParameterTypes.Length;
4231 Type [] set_pars = new Type [top + 1];
4232 ParameterTypes.CopyTo (set_pars, 0);
4233 set_pars [top] = MemberType;
4235 Parameter [] fixed_parms = Parameters.FixedParameters;
4237 if (fixed_parms == null){
4238 throw new Exception ("We currently do not support only array arguments in an indexer");
4239 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4240 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4242 // Here is the problem: the `value' parameter has
4243 // to come *after* the array parameter in the declaration
4245 // X (object [] x, Type value)
4248 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4249 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4253 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4256 fixed_parms.CopyTo (tmp, 0);
4257 tmp [fixed_parms.Length] = new Parameter (
4258 Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4260 Parameters set_formal_params = new Parameters (tmp, null, Location);
4262 InternalParameters ip = new InternalParameters (parent, set_formal_params);
4264 SetData = new MethodData (this, "set", TypeManager.void_type,
4265 set_pars, ip, CallingConventions.Standard,
4266 Set.OptAttributes, ModFlags, flags, false);
4268 if (!SetData.Define (parent))
4271 SetBuilder = SetData.MethodBuilder;
4275 // Now name the parameters
4277 Parameter [] p = Parameters.FixedParameters;
4281 for (i = 0; i < p.Length; ++i) {
4283 GetBuilder.DefineParameter (
4284 i + 1, p [i].Attributes, p [i].Name);
4287 SetBuilder.DefineParameter (
4288 i + 1, p [i].Attributes, p [i].Name);
4293 SetBuilder.DefineParameter (
4294 i + 1, ParameterAttributes.None, /* was "value" */ this.Name);
4296 if (i != ParameterTypes.Length) {
4297 Parameter array_param = Parameters.ArrayParameter;
4298 SetBuilder.DefineParameter (
4299 i + 1, array_param.Attributes, array_param.Name);
4303 if (GetData != null)
4304 IsImplementing = GetData.IsImplementing;
4305 else if (SetData != null)
4306 IsImplementing = SetData.IsImplementing;
4309 // Define the PropertyBuilder if one of the following conditions are met:
4310 // a) we're not implementing an interface indexer.
4311 // b) the indexer has a different IndexerName and this is no
4312 // explicit interface implementation.
4314 if (!IsExplicitImpl) {
4315 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4316 IndexerName, prop_attr, MemberType, ParameterTypes);
4318 if (GetData != null)
4319 PropertyBuilder.SetGetMethod (GetBuilder);
4321 if (SetData != null)
4322 PropertyBuilder.SetSetMethod (SetBuilder);
4324 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4332 public class Operator : MemberCore {
4334 const int AllowedModifiers =
4340 const int RequiredModifiers =
4344 public enum OpType : byte {
4354 // Unary and Binary operators
4377 // Implicit and Explicit
4382 public readonly OpType OperatorType;
4383 public readonly Expression ReturnType;
4384 public readonly Expression FirstArgType, SecondArgType;
4385 public readonly string FirstArgName, SecondArgName;
4386 public readonly Block Block;
4387 public Attributes OptAttributes;
4388 public MethodBuilder OperatorMethodBuilder;
4390 public string MethodName;
4391 public Method OperatorMethod;
4393 public Operator (OpType type, Expression ret_type, int flags,
4394 Expression arg1type, string arg1name,
4395 Expression arg2type, string arg2name,
4396 Block block, Attributes attrs, Location loc)
4399 OperatorType = type;
4400 ReturnType = ret_type;
4401 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4402 FirstArgType = arg1type;
4403 FirstArgName = arg1name;
4404 SecondArgType = arg2type;
4405 SecondArgName = arg2name;
4407 OptAttributes = attrs;
4410 string Prototype (TypeContainer parent)
4412 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4413 SecondArgType + ")";
4416 public override bool Define (TypeContainer parent)
4419 MethodName = "op_" + OperatorType;
4421 if (SecondArgType != null)
4424 Parameter [] param_list = new Parameter [length];
4426 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4429 "User defined operators `" +
4430 Prototype (parent) +
4431 "' must be declared static and public");
4435 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4436 Parameter.Modifier.NONE, null);
4437 if (SecondArgType != null)
4438 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4439 Parameter.Modifier.NONE, null);
4441 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4442 new Parameters (param_list, null, Location),
4443 OptAttributes, Mono.CSharp.Location.Null);
4445 OperatorMethod.IsOperator = true;
4446 OperatorMethod.Define (parent);
4448 if (OperatorMethod.MethodBuilder == null)
4451 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4453 Type [] param_types = OperatorMethod.ParameterTypes;
4454 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4455 Type return_type = OperatorMethod.GetReturnType ();
4456 Type first_arg_type = param_types [0];
4458 // Rules for conversion operators
4460 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4461 if (first_arg_type == return_type && first_arg_type == declaring_type){
4464 "User-defined conversion cannot take an object of the " +
4465 "enclosing type and convert to an object of the enclosing" +
4470 if (first_arg_type != declaring_type && return_type != declaring_type){
4473 "User-defined conversion must convert to or from the " +
4478 if (first_arg_type == TypeManager.object_type ||
4479 return_type == TypeManager.object_type){
4482 "User-defined conversion cannot convert to or from " +
4487 if (first_arg_type.IsInterface || return_type.IsInterface){
4490 "User-defined conversion cannot convert to or from an " +
4495 if (first_arg_type.IsSubclassOf (return_type) ||
4496 return_type.IsSubclassOf (first_arg_type)){
4499 "User-defined conversion cannot convert between types " +
4500 "that derive from each other");
4503 } else if (SecondArgType == null) {
4504 // Checks for Unary operators
4506 if (first_arg_type != declaring_type){
4509 "The parameter of a unary operator must be the " +
4514 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4515 if (return_type != declaring_type){
4518 "The parameter and return type for ++ and -- " +
4519 "must be the containing type");
4525 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4526 if (return_type != TypeManager.bool_type){
4529 "The return type of operator True or False " +
4536 // Checks for Binary operators
4538 if (first_arg_type != declaring_type &&
4539 param_types [1] != declaring_type){
4542 "One of the parameters of a binary operator must " +
4543 "be the containing type");
4551 public void Emit (TypeContainer parent)
4553 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4554 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4557 // abstract or extern methods have no bodies
4559 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4562 OperatorMethod.Block = Block;
4563 OperatorMethod.Emit (parent);
4566 public static string GetName (OpType ot)
4569 case OpType.LogicalNot:
4571 case OpType.OnesComplement:
4573 case OpType.Increment:
4575 case OpType.Decrement:
4581 case OpType.Addition:
4583 case OpType.Subtraction:
4585 case OpType.UnaryPlus:
4587 case OpType.UnaryNegation:
4589 case OpType.Multiply:
4591 case OpType.Division:
4593 case OpType.Modulus:
4595 case OpType.BitwiseAnd:
4597 case OpType.BitwiseOr:
4599 case OpType.ExclusiveOr:
4601 case OpType.LeftShift:
4603 case OpType.RightShift:
4605 case OpType.Equality:
4607 case OpType.Inequality:
4609 case OpType.GreaterThan:
4611 case OpType.LessThan:
4613 case OpType.GreaterThanOrEqual:
4615 case OpType.LessThanOrEqual:
4617 case OpType.Implicit:
4619 case OpType.Explicit:
4625 public override string ToString ()
4627 Type return_type = OperatorMethod.GetReturnType();
4628 Type [] param_types = OperatorMethod.ParameterTypes;
4630 if (SecondArgType == null)
4631 return String.Format (
4632 "{0} operator {1}({2})",
4633 TypeManager.CSharpName (return_type),
4634 GetName (OperatorType),
4637 return String.Format (
4638 "{0} operator {1}({2}, {3})",
4639 TypeManager.CSharpName (return_type),
4640 GetName (OperatorType),
4641 param_types [0], param_types [1]);
4646 // This is used to compare method signatures
4648 struct MethodSignature {
4650 public Type RetType;
4651 public Type [] Parameters;
4654 /// This delegate is used to extract methods which have the
4655 /// same signature as the argument
4657 public static MemberFilter method_signature_filter;
4660 /// This delegate is used to extract methods which have the
4661 /// same signature as the argument except for the name
4663 public static MemberFilter method_signature_noname_filter;
4666 /// This delegate is used to extract inheritable methods which
4667 /// have the same signature as the argument. By inheritable,
4668 /// this means that we have permissions to override the method
4669 /// from the current assembly and class
4671 public static MemberFilter inheritable_method_signature_filter;
4674 /// This delegate is used to extract inheritable methods which
4675 /// have the same signature as the argument. By inheritable,
4676 /// this means that we have permissions to override the method
4677 /// from the current assembly and class
4679 public static MemberFilter inheritable_property_signature_filter;
4681 static MethodSignature ()
4683 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4684 method_signature_noname_filter = new MemberFilter (MemberSignatureCompareNoName);
4685 inheritable_method_signature_filter = new MemberFilter (
4686 InheritableMemberSignatureCompare);
4687 inheritable_property_signature_filter = new MemberFilter (
4688 InheritablePropertySignatureCompare);
4691 public MethodSignature (string name, Type ret_type, Type [] parameters)
4696 if (parameters == null)
4697 Parameters = TypeManager.NoTypes;
4699 Parameters = parameters;
4702 public override int GetHashCode ()
4704 return Name.GetHashCode ();
4707 public override bool Equals (Object o)
4709 MethodSignature other = (MethodSignature) o;
4711 if (other.Name != Name)
4714 if (other.RetType != RetType)
4717 if (Parameters == null){
4718 if (other.Parameters == null)
4723 if (other.Parameters == null)
4726 int c = Parameters.Length;
4727 if (other.Parameters.Length != c)
4730 for (int i = 0; i < c; i++)
4731 if (other.Parameters [i] != Parameters [i])
4737 static bool MemberSignatureCompareNoName (MemberInfo m, object filter_criteria)
4739 return MemberSignatureCompare (m, filter_criteria, false);
4742 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4744 return MemberSignatureCompare (m, filter_criteria, true);
4747 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria, bool use_name)
4749 MethodSignature sig = (MethodSignature) filter_criteria;
4751 if (use_name && (m.Name != sig.Name))
4755 MethodInfo mi = m as MethodInfo;
4756 PropertyInfo pi = m as PropertyInfo;
4759 ReturnType = mi.ReturnType;
4760 else if (pi != null)
4761 ReturnType = pi.PropertyType;
4766 // we use sig.RetType == null to mean `do not check the
4767 // method return value.
4769 if (sig.RetType != null)
4770 if (ReturnType != sig.RetType)
4775 args = TypeManager.GetArgumentTypes (mi);
4777 args = TypeManager.GetArgumentTypes (pi);
4778 Type [] sigp = sig.Parameters;
4780 if (args.Length != sigp.Length)
4783 for (int i = args.Length; i > 0; ){
4785 if (args [i] != sigp [i])
4792 // This filter should be used when we are requesting methods that
4793 // we want to override.
4795 // This makes a number of assumptions, for example
4796 // that the methods being extracted are of a parent
4797 // class (this means we know implicitly that we are
4798 // being called to find out about members by a derived
4801 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4803 if (MemberSignatureCompare (m, filter_criteria)){
4804 MethodInfo mi = (MethodInfo) m;
4805 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4807 // If only accessible to the current class.
4808 if (prot == MethodAttributes.Private)
4811 // If only accessible to the defining assembly or
4812 if (prot == MethodAttributes.FamANDAssem ||
4813 prot == MethodAttributes.Assembly){
4814 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4820 // Anything else (FamOrAssembly and Public) is fine
4827 // This filter should be used when we are requesting properties that
4828 // we want to override.
4830 // This makes a number of assumptions, for example
4831 // that the methods being extracted are of a parent
4832 // class (this means we know implicitly that we are
4833 // being called to find out about members by a derived
4836 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
4838 if (MemberSignatureCompare (m, filter_criteria)){
4839 PropertyInfo pi = (PropertyInfo) m;
4841 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
4842 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
4844 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
4846 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4848 // If only accessible to the current class.
4849 if (prot == MethodAttributes.Private)
4852 // If only accessible to the defining assembly or
4853 if (prot == MethodAttributes.FamANDAssem ||
4854 prot == MethodAttributes.Assembly){
4855 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4861 // Anything else (FamOrAssembly and Public) is fine