2 // class.cs: Class and Struct handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@gnome.org)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
12 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
14 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
15 // have fixed a remaining problem: not every AddXXXX was adding a
16 // fully qualified name.
18 // Now everyone registers a fully qualified name in the DeclSpace as
19 // being defined instead of the partial name.
21 // Downsides: we are slower than we need to be due to the excess
22 // copies and the names being registered this way.
24 // The reason for this is that we currently depend (on the corlib
25 // bootstrap for instance) that types are fully qualified, because
26 // we dump all the types in the namespace, and we should really have
27 // types inserted into the proper namespace, so we can only store the
28 // basenames in the defined_names array.
33 using System.Collections;
34 using System.Reflection;
35 using System.Reflection.Emit;
36 using System.Runtime.CompilerServices;
37 using System.Diagnostics.SymbolStore;
39 namespace Mono.CSharp {
42 /// This is the base class for structs and classes.
44 public class TypeContainer : DeclSpace, IMemberContainer {
45 // Holds a list of classes and structures
48 // Holds the list of properties
51 // Holds the list of enumerations
54 // Holds the list of delegates
57 // Holds the list of constructors
58 ArrayList instance_constructors;
60 // Holds the list of fields
63 // Holds a list of fields that have initializers
64 ArrayList initialized_fields;
66 // Holds a list of static fields that have initializers
67 ArrayList initialized_static_fields;
69 // Holds the list of constants
75 // Holds order in which interfaces must be closed
76 ArrayList interface_order;
87 // Holds the operators
90 // The emit context for toplevel objects.
94 // Pointers to the default constructor and the default static constructor
96 Constructor default_constructor;
97 Constructor default_static_constructor;
100 // Whether we have seen a static constructor for this class or not
102 bool have_static_constructor = false;
105 // Whether we have at least one non-static field
107 bool have_nonstatic_fields = false;
110 // This one is computed after we can distinguish interfaces
111 // from classes from the arraylist `type_bases'
113 string base_class_name;
115 ArrayList type_bases;
117 // Attributes for this type
118 protected Attributes attributes;
120 // Information in the case we are an attribute type
122 public AttributeTargets Targets = AttributeTargets.All;
123 public bool AllowMultiple = false;
124 public bool Inherited;
126 // The interfaces we implement.
129 // The parent member container and our member cache
130 IMemberContainer parent_container;
131 MemberCache member_cache;
134 // The indexer name for this class
136 public string IndexerName;
138 public TypeContainer (TypeContainer parent, string name, Location l)
139 : base (parent, name, l)
142 types = new ArrayList ();
149 base_class_name = null;
151 //Console.WriteLine ("New class " + name + " inside " + n);
154 public AdditionResult AddConstant (Const constant)
157 string basename = constant.Name;
159 if ((res = IsValid (basename)) != AdditionResult.Success)
162 if (constants == null)
163 constants = new ArrayList ();
165 constants.Add (constant);
166 DefineName (Name + "." + basename, constant);
168 return AdditionResult.Success;
171 public AdditionResult AddEnum (Mono.CSharp.Enum e)
175 if ((res = IsValid (e.Basename)) != AdditionResult.Success)
179 enums = new ArrayList ();
182 DefineName (e.Name, e);
184 return AdditionResult.Success;
187 public AdditionResult AddClass (Class c)
191 if ((res = IsValid (c.Basename)) != AdditionResult.Success)
194 DefineName (c.Name, c);
197 return AdditionResult.Success;
200 public AdditionResult AddStruct (Struct s)
204 if ((res = IsValid (s.Basename)) != AdditionResult.Success)
207 DefineName (s.Name, s);
210 return AdditionResult.Success;
213 public AdditionResult AddDelegate (Delegate d)
217 if ((res = IsValid (d.Basename)) != AdditionResult.Success)
220 if (delegates == null)
221 delegates = new ArrayList ();
223 DefineName (d.Name, d);
226 return AdditionResult.Success;
229 public AdditionResult AddMethod (Method method)
231 string basename = method.Name;
232 string fullname = Name + "." + basename;
234 Object value = defined_names [fullname];
236 if (value != null && (!(value is Method)))
237 return AdditionResult.NameExists;
239 if (basename == Basename)
240 return AdditionResult.EnclosingClash;
243 methods = new ArrayList ();
245 if (method.Name.IndexOf (".") != -1)
246 methods.Insert (0, method);
248 methods.Add (method);
251 DefineName (fullname, method);
253 return AdditionResult.Success;
256 public AdditionResult AddConstructor (Constructor c)
258 if (c.Name != Basename)
259 return AdditionResult.NotAConstructor;
261 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
264 have_static_constructor = true;
265 if (default_static_constructor != null){
266 Console.WriteLine ("I have a static constructor already");
267 Console.WriteLine (" " + default_static_constructor);
268 return AdditionResult.MethodExists;
271 default_static_constructor = c;
274 if (default_constructor != null)
275 return AdditionResult.MethodExists;
276 default_constructor = c;
279 if (instance_constructors == null)
280 instance_constructors = new ArrayList ();
282 instance_constructors.Add (c);
285 return AdditionResult.Success;
288 public AdditionResult AddInterface (Interface iface)
292 if ((res = IsValid (iface.Basename)) != AdditionResult.Success)
295 if (interfaces == null)
296 interfaces = new ArrayList ();
297 interfaces.Add (iface);
298 DefineName (iface.Name, iface);
300 return AdditionResult.Success;
303 public AdditionResult AddField (Field field)
306 string basename = field.Name;
308 if ((res = IsValid (basename)) != AdditionResult.Success)
312 fields = new ArrayList ();
316 if (field.HasInitializer){
317 if ((field.ModFlags & Modifiers.STATIC) != 0){
318 if (initialized_static_fields == null)
319 initialized_static_fields = new ArrayList ();
321 initialized_static_fields.Add (field);
324 // We have not seen a static constructor,
325 // but we will provide static initialization of fields
327 have_static_constructor = true;
329 if (initialized_fields == null)
330 initialized_fields = new ArrayList ();
332 initialized_fields.Add (field);
336 if ((field.ModFlags & Modifiers.STATIC) == 0)
337 have_nonstatic_fields = true;
339 DefineName (Name + "." + basename, field);
340 return AdditionResult.Success;
343 public AdditionResult AddProperty (Property prop)
346 string basename = prop.Name;
348 if ((res = IsValid (basename)) != AdditionResult.Success)
351 if (properties == null)
352 properties = new ArrayList ();
354 if (prop.Name.IndexOf (".") != -1)
355 properties.Insert (0, prop);
357 properties.Add (prop);
358 DefineName (Name + "." + basename, prop);
360 return AdditionResult.Success;
363 public AdditionResult AddEvent (Event e)
366 string basename = e.Name;
368 if ((res = IsValid (basename)) != AdditionResult.Success)
372 events = new ArrayList ();
375 DefineName (Name + "." + basename, e);
377 return AdditionResult.Success;
380 public AdditionResult AddIndexer (Indexer i)
382 if (indexers == null)
383 indexers = new ArrayList ();
385 if (i.InterfaceType != null)
386 indexers.Insert (0, i);
390 return AdditionResult.Success;
393 public AdditionResult AddOperator (Operator op)
395 if (operators == null)
396 operators = new ArrayList ();
400 return AdditionResult.Success;
403 public void RegisterOrder (Interface iface)
405 if (interface_order == null)
406 interface_order = new ArrayList ();
408 interface_order.Add (iface);
411 public ArrayList Types {
417 public ArrayList Methods {
423 public ArrayList Constants {
429 public ArrayList Interfaces {
437 return base_class_name;
441 public ArrayList Bases {
451 public ArrayList Fields {
461 public ArrayList InstanceConstructors {
463 return instance_constructors;
467 public ArrayList Properties {
473 public ArrayList Events {
479 public ArrayList Enums {
485 public ArrayList Indexers {
491 public ArrayList Operators {
497 public ArrayList Delegates {
503 public Attributes OptAttributes {
509 public bool HaveStaticConstructor {
511 return have_static_constructor;
515 public virtual TypeAttributes TypeAttr {
517 return Modifiers.TypeAttr (ModFlags, this);
522 // Emits the instance field initializers
524 public bool EmitFieldInitializers (EmitContext ec)
527 ILGenerator ig = ec.ig;
528 Expression instance_expr;
531 fields = initialized_static_fields;
532 instance_expr = null;
534 fields = initialized_fields;
535 instance_expr = new This (Location.Null).Resolve (ec);
541 foreach (Field f in fields){
542 Expression e = f.GetInitializerExpression (ec);
546 Location l = f.Location;
547 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
548 fe.InstanceExpression = instance_expr;
549 Expression a = new Assign (fe, e, l);
555 if (a is ExpressionStatement)
556 ((ExpressionStatement) a).EmitStatement (ec);
558 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
566 // Defines the default constructors
568 void DefineDefaultConstructor (bool is_static)
573 c = new Constructor (Basename, Parameters.EmptyReadOnlyParameters,
574 new ConstructorBaseInitializer (
575 null, Parameters.EmptyReadOnlyParameters,
580 mods = Modifiers.STATIC;
586 c.Block = new Block (null);
590 public void ReportStructInitializedInstanceError ()
592 string n = TypeBuilder.FullName;
594 foreach (Field f in initialized_fields){
597 "`" + n + "." + f.Name + "': can not have " +
598 "instance field initializers in structs");
603 /// The pending methods that need to be implemented (interfaces or abstract methods)
605 public PendingImplementation Pending;
608 /// This function computes the Base class and also the
609 /// list of interfaces that the class or struct @c implements.
611 /// The return value is an array (might be null) of
612 /// interfaces implemented (as Types).
614 /// The @parent argument is set to the parent object or null
615 /// if this is `System.Object'.
617 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
619 ArrayList bases = Bases;
628 parent = TypeManager.value_type;
632 if (RootContext.StdLib)
633 parent = TypeManager.object_type;
634 else if (Name != "System.Object")
635 parent = TypeManager.object_type;
638 // If we are compiling our runtime,
639 // and we are defining ValueType, then our
640 // parent is `System.Object'.
642 if (!RootContext.StdLib && Name == "System.ValueType")
643 parent = TypeManager.object_type;
650 // Bases should be null if there are no bases at all
655 Expression name = (Expression) bases [0];
656 name = ResolveTypeExpr (name, false, Location);
663 Type first = name.Type;
669 parent = TypeManager.object_type;
673 if (!AsAccessible (parent, ModFlags))
674 Report.Error (60, Location,
675 "Inconsistent accessibility: base class `" +
676 TypeManager.CSharpName (parent) + "' is less " +
677 "accessible than class `" +
684 Type [] ifaces = new Type [count-start];
686 for (i = start, j = 0; i < count; i++, j++){
687 Expression name = (Expression) bases [i];
688 Expression resolved = ResolveTypeExpr (name, false, Location);
689 if (resolved == null)
692 bases [i] = resolved;
693 Type t = resolved.Type;
700 if (is_class == false && !t.IsInterface){
701 Report.Error (527, "In Struct `" + Name + "', type `"+
702 name +"' is not an interface");
711 detail = " (a class can not inherit from a struct/enum)";
713 Report.Error (509, "class `"+ Name +
714 "': Cannot inherit from sealed class `"+
715 bases [i]+"'"+detail);
722 Report.Error (527, "In Class `" + Name + "', type `"+
723 name+"' is not an interface");
729 for (int x = 0; x < j; x++) {
730 if (t == ifaces [x]) {
731 Report.Error (528, "`" + name + "' is already listed in interface list");
740 return TypeManager.ExpandInterfaces (ifaces);
744 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
746 public override TypeBuilder DefineType ()
752 if (TypeBuilder != null)
765 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
767 ifaces = GetClassBases (is_class, out parent, out error);
772 if (is_class && parent != null){
773 if (parent == TypeManager.enum_type ||
774 (parent == TypeManager.value_type && RootContext.StdLib) ||
775 parent == TypeManager.delegate_type ||
776 parent == TypeManager.array_type){
778 644, Location, "`" + Name + "' cannot inherit from " +
779 "special class `" + TypeManager.CSharpName (parent) + "'");
784 if (!is_class && TypeManager.value_type == null)
785 throw new Exception ();
787 TypeAttributes type_attributes = TypeAttr;
789 // if (parent_builder is ModuleBuilder) {
791 ModuleBuilder builder = CodeGen.ModuleBuilder;
792 TypeBuilder = builder.DefineType (
793 Name, type_attributes, parent, ifaces);
796 TypeBuilder builder = Parent.TypeBuilder;
797 TypeBuilder = builder.DefineNestedType (
798 Basename, type_attributes, parent, ifaces);
802 // Structs with no fields need to have at least one byte.
803 // The right thing would be to set the PackingSize in a DefineType
804 // but there are no functions that allow interfaces *and* the size to
808 if (!is_class && !have_nonstatic_fields){
809 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
810 FieldAttributes.Private);
813 // add interfaces that were not added at type creation (weird API issue)
814 if (!is_class && !have_nonstatic_fields && (ifaces != null)) {
815 foreach (Type i in ifaces)
816 TypeBuilder.AddInterfaceImplementation (i);
820 // Finish the setup for the EmitContext
822 ec.ContainerType = TypeBuilder;
824 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
826 if ((parent != null) &&
827 (parent == TypeManager.attribute_type ||
828 parent.IsSubclassOf (TypeManager.attribute_type))) {
829 RootContext.RegisterAttribute (this);
830 TypeManager.RegisterAttrType (TypeBuilder, this);
832 RootContext.RegisterOrder (this);
834 if (Interfaces != null) {
835 foreach (Interface iface in Interfaces)
840 foreach (TypeContainer tc in Types)
844 if (Delegates != null) {
845 foreach (Delegate d in Delegates)
850 foreach (Enum en in Enums)
860 /// Defines the MemberCore objects that are in the `list' Arraylist
862 /// The `defined_names' array contains a list of members defined in
865 static ArrayList remove_list = new ArrayList ();
866 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
870 remove_list.Clear ();
872 foreach (MemberCore mc in list){
873 if (!mc.Define (this)){
874 remove_list.Add (mc);
878 if (defined_names == null)
881 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
883 if (RootContext.WarningLevel >= 4){
884 if ((mc.ModFlags & Modifiers.NEW) != 0)
885 Warning_KewywordNewNotRequired (mc.Location, mc);
890 MemberInfo match = defined_names [idx];
892 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
896 // If we are both methods, let the method resolution emit warnings
898 if (match is MethodBase && mc is MethodCore)
901 if ((mc.ModFlags & Modifiers.NEW) == 0)
902 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
905 foreach (object o in remove_list)
908 remove_list.Clear ();
912 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
913 // class is consisten. Either it is `Item' or it is the name defined by all the
914 // indexers with the `IndexerName' attribute.
916 // Turns out that the IndexerNameAttribute is applied to each indexer,
917 // but it is never emitted, instead a DefaultName attribute is attached
920 void DefineIndexers ()
922 string class_indexer_name = null;
924 foreach (Indexer i in Indexers){
929 name = i.IndexerName;
931 if (i.InterfaceType != null)
934 if (class_indexer_name == null){
935 class_indexer_name = name;
939 if (name == class_indexer_name)
943 668, "Two indexers have different names, " +
944 " you should use the same name for all your indexers");
946 if (class_indexer_name == null)
947 class_indexer_name = "Item";
948 IndexerName = class_indexer_name;
951 static void Error_KeywordNotAllowed (Location loc)
953 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
957 /// Populates our TypeBuilder with fields and methods
959 public override bool DefineMembers (TypeContainer parent)
961 MemberInfo [] defined_names = null;
963 if (interface_order != null){
964 foreach (Interface iface in interface_order)
965 if ((iface.ModFlags & Modifiers.NEW) == 0)
966 iface.DefineMembers (this);
968 Error_KeywordNotAllowed (iface.Location);
971 if (RootContext.WarningLevel > 1){
975 // This code throws an exception in the comparer
976 // I guess the string is not an object?
978 ptype = TypeBuilder.BaseType;
980 defined_names = (MemberInfo []) FindMembers (
981 ptype, MemberTypes.All & ~MemberTypes.Constructor,
982 BindingFlags.Public | BindingFlags.Instance |
983 BindingFlags.Static, null, null);
985 Array.Sort (defined_names, mif_compare);
989 if (constants != null)
990 DefineMembers (constants, defined_names);
993 DefineMembers (fields, defined_names);
996 if (instance_constructors == null){
997 if (default_constructor == null)
998 DefineDefaultConstructor (false);
1001 if (initialized_static_fields != null &&
1002 default_static_constructor == null)
1003 DefineDefaultConstructor (true);
1006 if (this is Struct){
1008 // Structs can not have initialized instance
1011 if (initialized_static_fields != null &&
1012 default_static_constructor == null)
1013 DefineDefaultConstructor (true);
1015 if (initialized_fields != null)
1016 ReportStructInitializedInstanceError ();
1019 Pending = PendingImplementation.GetPendingImplementations (this);
1022 // Constructors are not in the defined_names array
1024 if (instance_constructors != null)
1025 DefineMembers (instance_constructors, null);
1027 if (default_static_constructor != null)
1028 default_static_constructor.Define (this);
1030 if (methods != null)
1031 DefineMembers (methods, defined_names);
1033 if (properties != null)
1034 DefineMembers (properties, defined_names);
1037 DefineMembers (events, defined_names);
1039 if (indexers != null) {
1042 IndexerName = "Item";
1044 if (operators != null){
1045 DefineMembers (operators, null);
1047 CheckPairedOperators ();
1051 DefineMembers (enums, defined_names);
1053 if (delegates != null)
1054 DefineMembers (delegates, defined_names);
1057 if (TypeBuilder.BaseType != null)
1058 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1060 member_cache = new MemberCache (this);
1066 public override bool Define (TypeContainer parent)
1068 if (interface_order != null){
1069 foreach (Interface iface in interface_order)
1070 if ((iface.ModFlags & Modifiers.NEW) == 0)
1071 iface.Define (this);
1078 /// This function is based by a delegate to the FindMembers routine
1080 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1086 /// This filter is used by FindMembers, and we just keep
1087 /// a global for the filter to `AlwaysAccept'
1089 static MemberFilter accepting_filter;
1093 /// A member comparission method based on name only
1095 static IComparer mif_compare;
1097 static TypeContainer ()
1099 accepting_filter = new MemberFilter (AlwaysAccept);
1100 mif_compare = new MemberInfoCompare ();
1104 /// This method returns the members of this type just like Type.FindMembers would
1105 /// Only, we need to use this for types which are _being_ defined because MS'
1106 /// implementation can't take care of that.
1109 // FIXME: return an empty static array instead of null, that cleans up
1110 // some code and is consistent with some coding conventions I just found
1114 // Notice that in various cases we check if our field is non-null,
1115 // something that would normally mean that there was a bug elsewhere.
1117 // The problem happens while we are defining p-invoke methods, as those
1118 // will trigger a FindMembers, but this happens before things are defined
1120 // Since the whole process is a no-op, it is fine to check for null here.
1122 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1123 MemberFilter filter, object criteria)
1125 ArrayList members = new ArrayList ();
1128 if ((bf & BindingFlags.Public) != 0)
1129 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1131 if ((bf & BindingFlags.NonPublic) != 0)
1132 modflags |= Modifiers.PRIVATE;
1134 int static_mask = 0, static_flags = 0;
1135 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1136 case BindingFlags.Static:
1137 static_mask = static_flags = Modifiers.STATIC;
1140 case BindingFlags.Instance:
1141 static_mask = Modifiers.STATIC;
1146 static_mask = static_flags = 0;
1150 Timer.StartTimer (TimerType.TcFindMembers);
1153 filter = accepting_filter;
1155 if ((mt & MemberTypes.Field) != 0) {
1156 if (fields != null) {
1157 foreach (Field f in fields) {
1158 if ((f.ModFlags & modflags) == 0)
1160 if ((f.ModFlags & static_mask) != static_flags)
1163 FieldBuilder fb = f.FieldBuilder;
1164 if (fb != null && filter (fb, criteria) == true)
1169 if (constants != null) {
1170 foreach (Const con in constants) {
1171 if ((con.ModFlags & modflags) == 0)
1173 if ((con.ModFlags & static_mask) != static_flags)
1176 FieldBuilder fb = con.FieldBuilder;
1177 if (fb != null && filter (fb, criteria) == true)
1183 if ((mt & MemberTypes.Method) != 0) {
1184 if (methods != null) {
1185 foreach (Method m in methods) {
1186 if ((m.ModFlags & modflags) == 0)
1188 if ((m.ModFlags & static_mask) != static_flags)
1191 MethodBuilder mb = m.MethodBuilder;
1193 if (mb != null && filter (mb, criteria) == true)
1198 if (operators != null){
1199 foreach (Operator o in operators) {
1200 if ((o.ModFlags & modflags) == 0)
1202 if ((o.ModFlags & static_mask) != static_flags)
1205 MethodBuilder ob = o.OperatorMethodBuilder;
1206 if (ob != null && filter (ob, criteria) == true)
1211 if (properties != null){
1212 foreach (Property p in properties){
1213 if ((p.ModFlags & modflags) == 0)
1215 if ((p.ModFlags & static_mask) != static_flags)
1221 if (b != null && filter (b, criteria) == true)
1225 if (b != null && filter (b, criteria) == true)
1230 if (indexers != null){
1231 foreach (Indexer ix in indexers){
1232 if ((ix.ModFlags & modflags) == 0)
1234 if ((ix.ModFlags & static_mask) != static_flags)
1240 if (b != null && filter (b, criteria) == true)
1244 if (b != null && filter (b, criteria) == true)
1250 if ((mt & MemberTypes.Event) != 0) {
1252 foreach (Event e in events) {
1253 if ((e.ModFlags & modflags) == 0)
1255 if ((e.ModFlags & static_mask) != static_flags)
1258 MemberInfo eb = e.EventBuilder;
1259 if (eb != null && filter (eb, criteria) == true)
1260 members.Add (e.EventBuilder);
1264 if ((mt & MemberTypes.Property) != 0){
1265 if (properties != null)
1266 foreach (Property p in properties) {
1267 if ((p.ModFlags & modflags) == 0)
1269 if ((p.ModFlags & static_mask) != static_flags)
1272 MemberInfo pb = p.PropertyBuilder;
1273 if (pb != null && filter (pb, criteria) == true) {
1274 members.Add (p.PropertyBuilder);
1278 if (indexers != null)
1279 foreach (Indexer ix in indexers) {
1280 if ((ix.ModFlags & modflags) == 0)
1282 if ((ix.ModFlags & static_mask) != static_flags)
1285 MemberInfo ib = ix.PropertyBuilder;
1286 if (ib != null && filter (ib, criteria) == true) {
1287 members.Add (ix.PropertyBuilder);
1292 if ((mt & MemberTypes.NestedType) != 0) {
1294 foreach (TypeContainer t in types) {
1295 if ((t.ModFlags & modflags) == 0)
1298 TypeBuilder tb = t.TypeBuilder;
1299 if (tb != null && (filter (tb, criteria) == true))
1305 foreach (Enum en in enums){
1306 if ((en.ModFlags & modflags) == 0)
1309 TypeBuilder tb = en.TypeBuilder;
1310 if (tb != null && (filter (tb, criteria) == true))
1315 if (delegates != null){
1316 foreach (Delegate d in delegates){
1317 if ((d.ModFlags & modflags) == 0)
1320 TypeBuilder tb = d.TypeBuilder;
1321 if (tb != null && (filter (tb, criteria) == true))
1326 if (interfaces != null){
1327 foreach (Interface iface in interfaces){
1328 if ((iface.ModFlags & modflags) == 0)
1331 TypeBuilder tb = iface.TypeBuilder;
1332 if (tb != null && (filter (tb, criteria) == true))
1338 if ((mt & MemberTypes.Constructor) != 0){
1339 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1340 foreach (Constructor c in instance_constructors){
1341 ConstructorBuilder cb = c.ConstructorBuilder;
1343 if (filter (cb, criteria) == true)
1348 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1349 ConstructorBuilder cb =
1350 default_static_constructor.ConstructorBuilder;
1353 if (filter (cb, criteria) == true)
1359 // Lookup members in parent if requested.
1361 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1362 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1363 members.AddRange (list);
1366 Timer.StopTimer (TimerType.TcFindMembers);
1368 return new MemberList (members);
1371 public override MemberCache MemberCache {
1373 return member_cache;
1377 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1378 MemberFilter filter, object criteria)
1380 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1383 return tc.FindMembers (mt, bf, filter, criteria);
1385 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1389 // FindMethods will look for methods not only in the type `t', but in
1390 // any interfaces implemented by the type.
1392 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1393 MemberFilter filter, object criteria)
1399 /// Emits the values for the constants
1401 public void EmitConstants ()
1403 if (constants != null)
1404 foreach (Const con in constants)
1405 con.EmitConstant (this);
1410 /// Emits the code, this step is performed after all
1411 /// the types, enumerations, constructors
1415 if (instance_constructors != null)
1416 foreach (Constructor c in instance_constructors)
1419 if (default_static_constructor != null)
1420 default_static_constructor.Emit (this);
1422 if (methods != null)
1423 foreach (Method m in methods)
1426 if (operators != null)
1427 foreach (Operator o in operators)
1430 if (properties != null)
1431 foreach (Property p in properties)
1434 if (indexers != null){
1435 foreach (Indexer ix in indexers)
1438 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1439 this, IndexerName, ModFlags, Location);
1440 TypeBuilder.SetCustomAttribute (cb);
1444 foreach (Field f in fields)
1447 if (events != null){
1448 foreach (Event e in Events)
1452 if (Pending != null)
1453 if (Pending.VerifyPendingMethods ())
1456 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1459 // Check for internal or private fields that were never assigned
1461 if (RootContext.WarningLevel >= 3) {
1462 if (fields != null){
1463 foreach (Field f in fields) {
1464 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1469 169, f.Location, "Private field " +
1470 MakeName (f.Name) + " is never used");
1475 // Only report 649 on level 4
1477 if (RootContext.WarningLevel < 4)
1480 if ((f.status & Field.Status.ASSIGNED) != 0)
1485 "Field " + MakeName (f.Name) + " is never assigned " +
1486 " to and will always have its default value");
1490 if (events != null){
1491 foreach (Event e in events){
1493 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1498 // if (types != null)
1499 // foreach (TypeContainer tc in types)
1503 public override void CloseType ()
1508 TypeBuilder.CreateType ();
1510 } catch (TypeLoadException){
1512 // This is fine, the code still created the type
1514 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1515 // Console.WriteLine (e.Message);
1517 Console.WriteLine ("In type: " + Name);
1522 foreach (Enum en in Enums)
1525 if (interface_order != null){
1526 foreach (Interface iface in interface_order)
1531 foreach (TypeContainer tc in Types)
1535 foreach (TypeContainer tc in Types)
1536 if (!(tc is Struct))
1540 if (Delegates != null)
1541 foreach (Delegate d in Delegates)
1545 public string MakeName (string n)
1547 return "`" + Name + "." + n + "'";
1550 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1553 108, l, "The keyword new is required on " +
1554 MakeName (mi.Name) + " because it hides `" +
1555 mi.ReflectedType.Name + "." + mi.Name + "'");
1558 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1561 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1562 "inherited member, the keyword new is not required");
1565 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1571 // Performs the validation on a Method's modifiers (properties have
1572 // the same properties).
1574 public bool MethodModifiersValid (int flags, string n, Location loc)
1576 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1577 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1578 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1580 string name = MakeName (n);
1583 // At most one of static, virtual or override
1585 if ((flags & Modifiers.STATIC) != 0){
1586 if ((flags & vao) != 0){
1588 112, loc, "static method " + name + "can not be marked " +
1589 "as virtual, abstract or override");
1594 if (this is Struct){
1595 if ((flags & va) != 0){
1596 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1601 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1604 " marked as override cannot be marked as new or virtual");
1609 // If the declaration includes the abstract modifier, then the
1610 // declaration does not include static, virtual or extern
1612 if ((flags & Modifiers.ABSTRACT) != 0){
1613 if ((flags & Modifiers.EXTERN) != 0){
1615 180, loc, name + " can not be both abstract and extern");
1619 if ((flags & Modifiers.VIRTUAL) != 0){
1621 503, loc, name + " can not be both abstract and virtual");
1625 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1628 " is abstract but its container class is not");
1634 if ((flags & Modifiers.PRIVATE) != 0){
1635 if ((flags & vao) != 0){
1638 " virtual or abstract members can not be private");
1643 if ((flags & Modifiers.SEALED) != 0){
1644 if ((flags & Modifiers.OVERRIDE) == 0){
1647 " cannot be sealed because it is not an override");
1655 // Access level of a type.
1658 ProtectedInternal = 1,
1664 // Check whether `flags' denotes a more restricted access than `level'
1665 // and return the new level.
1666 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1668 AccessLevel old_level = level;
1670 if ((flags & Modifiers.INTERNAL) != 0) {
1671 if ((flags & Modifiers.PROTECTED) != 0) {
1672 if ((int) level < (int) AccessLevel.ProtectedInternal)
1673 level = AccessLevel.ProtectedInternal;
1675 if ((int) level < (int) AccessLevel.Internal)
1676 level = AccessLevel.Internal;
1678 } else if ((flags & Modifiers.PROTECTED) != 0) {
1679 if ((int) level < (int) AccessLevel.Protected)
1680 level = AccessLevel.Protected;
1681 } else if ((flags & Modifiers.PRIVATE) != 0)
1682 level = AccessLevel.Private;
1687 // Return the access level for a new member which is defined in the current
1688 // TypeContainer with access modifiers `flags'.
1689 AccessLevel GetAccessLevel (int flags)
1691 if ((flags & Modifiers.PRIVATE) != 0)
1692 return AccessLevel.Private;
1695 if (!IsTopLevel && (Parent != null))
1696 level = Parent.GetAccessLevel (flags);
1698 level = AccessLevel.Public;
1700 return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1703 // Return the access level for type `t', but don't give more access than `flags'.
1704 static AccessLevel GetAccessLevel (Type t, int flags)
1706 if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1707 return AccessLevel.Private;
1710 if (TypeManager.IsBuiltinType (t))
1711 return AccessLevel.Public;
1712 else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1713 level = GetAccessLevel (t.DeclaringType, flags);
1715 level = CheckAccessLevel (AccessLevel.Public, flags);
1718 if (t.IsNestedPublic)
1721 if (t.IsNestedAssembly || t.IsNotPublic) {
1722 if ((int) level < (int) AccessLevel.Internal)
1723 level = AccessLevel.Internal;
1726 if (t.IsNestedFamily) {
1727 if ((int) level < (int) AccessLevel.Protected)
1728 level = AccessLevel.Protected;
1731 if (t.IsNestedFamORAssem) {
1732 if ((int) level < (int) AccessLevel.ProtectedInternal)
1733 level = AccessLevel.ProtectedInternal;
1740 // Returns true if `parent' is as accessible as the flags `flags'
1741 // given for this member.
1743 public bool AsAccessible (Type parent, int flags)
1745 while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1746 parent = parent.GetElementType ();
1748 AccessLevel level = GetAccessLevel (flags);
1749 AccessLevel level2 = GetAccessLevel (parent, flags);
1751 return (int) level >= (int) level2;
1754 Hashtable builder_and_args;
1756 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1758 if (builder_and_args == null)
1759 builder_and_args = new Hashtable ();
1764 /// Performs checks for an explicit interface implementation. First it
1765 /// checks whether the `interface_type' is a base inteface implementation.
1766 /// Then it checks whether `name' exists in the interface type.
1768 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1772 if (ifaces != null){
1773 foreach (Type t in ifaces){
1774 if (t == interface_type){
1782 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1789 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1791 Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1798 string IMemberContainer.Name {
1804 Type IMemberContainer.Type {
1810 IMemberContainer IMemberContainer.Parent {
1812 return parent_container;
1816 MemberCache IMemberContainer.MemberCache {
1818 return member_cache;
1822 bool IMemberContainer.IsInterface {
1828 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1830 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1834 // Operator pair checking
1837 class OperatorEntry {
1839 public Type ret_type;
1840 public Type type1, type2;
1842 public Operator.OpType ot;
1844 public OperatorEntry (int f, Operator o)
1848 ret_type = o.OperatorMethod.GetReturnType ();
1849 Type [] pt = o.OperatorMethod.ParameterTypes;
1853 ot = o.OperatorType;
1856 public override int GetHashCode ()
1858 return ret_type.GetHashCode ();
1861 public override bool Equals (object o)
1863 OperatorEntry other = (OperatorEntry) o;
1865 if (other.ret_type != ret_type)
1867 if (other.type1 != type1)
1869 if (other.type2 != type2)
1876 // Checks that some operators come in pairs:
1881 // They are matched based on the return type and the argument types
1883 void CheckPairedOperators ()
1885 Hashtable pairs = new Hashtable (null, null);
1887 // Register all the operators we care about.
1888 foreach (Operator op in operators){
1891 switch (op.OperatorType){
1892 case Operator.OpType.Equality:
1894 case Operator.OpType.Inequality:
1897 case Operator.OpType.GreaterThan:
1899 case Operator.OpType.LessThan:
1902 case Operator.OpType.GreaterThanOrEqual:
1904 case Operator.OpType.LessThanOrEqual:
1910 OperatorEntry oe = new OperatorEntry (reg, op);
1912 object o = pairs [oe];
1916 oe = (OperatorEntry) o;
1922 // Look for the mistakes.
1924 foreach (DictionaryEntry de in pairs){
1925 OperatorEntry oe = (OperatorEntry) de.Key;
1932 case Operator.OpType.Equality:
1935 case Operator.OpType.Inequality:
1938 case Operator.OpType.GreaterThan:
1941 case Operator.OpType.LessThan:
1944 case Operator.OpType.GreaterThanOrEqual:
1947 case Operator.OpType.LessThanOrEqual:
1951 Report.Error (216, oe.op.Location,
1952 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
1959 public class Class : TypeContainer {
1961 // Modifiers allowed in a class declaration
1963 public const int AllowedModifiers =
1966 Modifiers.PROTECTED |
1967 Modifiers.INTERNAL |
1969 Modifiers.ABSTRACT |
1973 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1974 : base (parent, name, l)
1978 if (parent.Parent == null)
1979 accmods = Modifiers.INTERNAL;
1981 accmods = Modifiers.PRIVATE;
1983 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1984 this.attributes = attrs;
1988 // FIXME: How do we deal with the user specifying a different
1991 public override TypeAttributes TypeAttr {
1993 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1998 public class Struct : TypeContainer {
2000 // Modifiers allowed in a struct declaration
2002 public const int AllowedModifiers =
2005 Modifiers.PROTECTED |
2006 Modifiers.INTERNAL |
2010 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2011 : base (parent, name, l)
2015 if (parent.Parent == null)
2016 accmods = Modifiers.INTERNAL;
2018 accmods = Modifiers.PRIVATE;
2020 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2022 this.ModFlags |= Modifiers.SEALED;
2023 this.attributes = attrs;
2028 // FIXME: Allow the user to specify a different set of attributes
2029 // in some cases (Sealed for example is mandatory for a class,
2030 // but what SequentialLayout can be changed
2032 public override TypeAttributes TypeAttr {
2034 return base.TypeAttr |
2035 TypeAttributes.SequentialLayout |
2036 TypeAttributes.Sealed |
2037 TypeAttributes.BeforeFieldInit;
2042 public abstract class MethodCore : MemberBase {
2043 public readonly Parameters Parameters;
2044 protected Block block;
2047 // Parameters, cached for semantic analysis.
2049 protected InternalParameters parameter_info;
2050 protected Type [] parameter_types;
2052 public MethodCore (Expression type, int mod, int allowed_mod, string name,
2053 Attributes attrs, Parameters parameters, Location loc)
2054 : base (type, mod, allowed_mod, name, attrs, loc)
2056 Parameters = parameters;
2060 // Returns the System.Type array for the parameters of this method
2062 public Type [] ParameterTypes {
2064 return parameter_types;
2068 public InternalParameters ParameterInfo
2071 return parameter_info;
2075 public Block Block {
2085 protected virtual bool DoDefineParameters (TypeContainer parent)
2087 // Check if arguments were correct
2088 parameter_types = Parameters.GetParameterInfo (parent);
2089 if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
2092 parameter_info = new InternalParameters (parent, Parameters);
2097 public CallingConventions GetCallingConvention (bool is_class)
2099 CallingConventions cc = 0;
2101 cc = Parameters.GetCallingConvention ();
2104 if ((ModFlags & Modifiers.STATIC) == 0)
2105 cc |= CallingConventions.HasThis;
2107 // FIXME: How is `ExplicitThis' used in C#?
2112 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
2115 // Define each type attribute (in/out/ref) and
2116 // the argument names.
2118 Parameter [] p = Parameters.FixedParameters;
2121 MethodBuilder mb = null;
2122 ConstructorBuilder cb = null;
2124 if (builder is MethodBuilder)
2125 mb = (MethodBuilder) builder;
2127 cb = (ConstructorBuilder) builder;
2130 for (i = 0; i < p.Length; i++) {
2131 ParameterBuilder pb;
2134 pb = cb.DefineParameter (
2135 i + 1, p [i].Attributes, p [i].Name);
2137 pb = mb.DefineParameter (
2138 i + 1, p [i].Attributes, p [i].Name);
2140 Attributes attr = p [i].OptAttributes;
2142 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
2146 if (Parameters.ArrayParameter != null){
2147 ParameterBuilder pb;
2148 Parameter array_param = Parameters.ArrayParameter;
2151 pb = cb.DefineParameter (
2152 i + 1, array_param.Attributes,
2155 pb = mb.DefineParameter (
2156 i + 1, array_param.Attributes,
2159 CustomAttributeBuilder a = new CustomAttributeBuilder (
2160 TypeManager.cons_param_array_attribute, new object [0]);
2162 pb.SetCustomAttribute (a);
2167 public class Method : MethodCore {
2168 public MethodBuilder MethodBuilder;
2169 public MethodData MethodData;
2172 /// Modifiers allowed in a class declaration
2174 const int AllowedModifiers =
2177 Modifiers.PROTECTED |
2178 Modifiers.INTERNAL |
2183 Modifiers.OVERRIDE |
2184 Modifiers.ABSTRACT |
2189 // return_type can be "null" for VOID values.
2191 public Method (Expression return_type, int mod, string name, Parameters parameters,
2192 Attributes attrs, Location l)
2193 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2197 // Returns the `System.Type' for the ReturnType of this
2198 // function. Provides a nice cache. (used between semantic analysis
2199 // and actual code generation
2201 public Type GetReturnType ()
2206 // Whether this is an operator method.
2207 public bool IsOperator;
2209 void DuplicateEntryPoint (MethodInfo b, Location location)
2213 "Program `" + CodeGen.FileName +
2214 "' has more than one entry point defined: `" +
2215 TypeManager.CSharpSignature(b) + "'");
2218 void Report28 (MethodInfo b)
2220 if (RootContext.WarningLevel < 4)
2225 "`" + TypeManager.CSharpSignature(b) +
2226 "' has the wrong signature to be an entry point");
2229 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2231 if (b.ReturnType != TypeManager.void_type &&
2232 b.ReturnType != TypeManager.int32_type)
2235 if (pinfo.Count == 0)
2238 if (pinfo.Count > 1)
2241 Type t = pinfo.ParameterType(0);
2243 (t.GetArrayRank() == 1) &&
2244 (t.GetElementType() == TypeManager.string_type) &&
2245 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2252 // Checks our base implementation if any
2254 protected override bool CheckBase (TypeContainer parent)
2256 // Check whether arguments were correct.
2257 if (!DoDefineParameters (parent))
2260 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2264 mi_this = TypeContainer.FindMembers (
2265 parent.TypeBuilder, MemberTypes.Method,
2266 BindingFlags.NonPublic | BindingFlags.Public |
2267 BindingFlags.Static | BindingFlags.Instance |
2268 BindingFlags.DeclaredOnly,
2269 MethodSignature.method_signature_filter, ms);
2271 if (mi_this.Count > 0) {
2272 Report.Error (111, Location, "Class `" + parent.Name + "' " +
2273 "already defines a member called `" + Name + "' " +
2274 "with the same parameter types");
2280 // Verify if the parent has a type with the same name, and then
2281 // check whether we have to create a new slot for it or not.
2283 Type ptype = parent.TypeBuilder.BaseType;
2285 // ptype is only null for System.Object while compiling corlib.
2287 MemberList mi, mi_static, mi_instance;
2289 mi_static = TypeContainer.FindMembers (
2290 ptype, MemberTypes.Method,
2291 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2292 MethodSignature.inheritable_method_signature_filter, ms);
2294 mi_instance = TypeContainer.FindMembers (
2295 ptype, MemberTypes.Method,
2296 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2297 MethodSignature.inheritable_method_signature_filter,
2300 if (mi_instance.Count > 0){
2302 } else if (mi_static.Count > 0)
2307 if (mi != null && mi.Count > 0){
2308 parent_method = (MethodInfo) mi [0];
2309 string name = parent_method.DeclaringType.Name + "." +
2312 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2315 if ((ModFlags & Modifiers.NEW) == 0) {
2316 Type parent_ret = TypeManager.TypeToCoreType (
2317 parent_method.ReturnType);
2319 if (parent_ret != MemberType) {
2321 508, parent.MakeName (Name) + ": cannot " +
2322 "change return type when overriding " +
2323 "inherited member " + name);
2328 if ((ModFlags & Modifiers.NEW) != 0)
2329 WarningNotHiding (parent);
2331 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2332 Report.Error (115, Location,
2333 parent.MakeName (Name) +
2334 " no suitable methods found to override");
2337 } else if ((ModFlags & Modifiers.NEW) != 0)
2338 WarningNotHiding (parent);
2346 public override bool Define (TypeContainer parent)
2348 if (!DoDefine (parent))
2351 if (!CheckBase (parent))
2354 CallingConventions cc = GetCallingConvention (parent is Class);
2356 MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2357 ParameterInfo, cc, OptAttributes,
2358 ModFlags, flags, true);
2360 if (!MethodData.Define (parent))
2363 MethodBuilder = MethodData.MethodBuilder;
2366 // This is used to track the Entry Point,
2368 if (Name == "Main" &&
2369 ((ModFlags & Modifiers.STATIC) != 0) &&
2370 (RootContext.MainClass == null ||
2371 RootContext.MainClass == parent.TypeBuilder.FullName)){
2372 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2373 if (RootContext.EntryPoint == null) {
2374 RootContext.EntryPoint = MethodBuilder;
2375 RootContext.EntryPointLocation = Location;
2377 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2378 DuplicateEntryPoint (MethodBuilder, Location);
2381 Report28(MethodBuilder);
2390 public void Emit (TypeContainer parent)
2392 MethodData.Emit (parent, Block, this);
2396 public abstract class ConstructorInitializer {
2397 ArrayList argument_list;
2398 ConstructorInfo parent_constructor;
2399 Parameters parameters;
2402 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2405 this.argument_list = argument_list;
2406 this.parameters = parameters;
2410 public ArrayList Arguments {
2412 return argument_list;
2416 public bool Resolve (EmitContext ec)
2418 Expression parent_constructor_group;
2421 ec.CurrentBlock = new Block (null, true, parameters);
2423 if (argument_list != null){
2424 foreach (Argument a in argument_list){
2425 if (!a.Resolve (ec, loc))
2430 ec.CurrentBlock = null;
2432 if (this is ConstructorBaseInitializer) {
2433 if (ec.ContainerType.BaseType == null)
2436 t = ec.ContainerType.BaseType;
2437 if (ec.ContainerType.IsValueType) {
2438 Report.Error (522, loc,
2439 "structs cannot call base class constructors");
2443 t = ec.ContainerType;
2445 parent_constructor_group = Expression.MemberLookup (
2446 ec, t, null, t, ".ctor",
2447 MemberTypes.Constructor,
2448 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2451 if (parent_constructor_group == null){
2452 Report.Error (1501, loc,
2453 "Can not find a constructor for this argument list");
2457 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2458 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2460 if (parent_constructor == null){
2461 Report.Error (1501, loc,
2462 "Can not find a constructor for this argument list");
2469 public void Emit (EmitContext ec)
2471 if (parent_constructor != null){
2473 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2475 Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2480 public class ConstructorBaseInitializer : ConstructorInitializer {
2481 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2482 base (argument_list, pars, l)
2487 public class ConstructorThisInitializer : ConstructorInitializer {
2488 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2489 base (argument_list, pars, l)
2494 public class Constructor : MethodCore {
2495 public ConstructorBuilder ConstructorBuilder;
2496 public ConstructorInitializer Initializer;
2497 new public Attributes OptAttributes;
2500 // Modifiers allowed for a constructor.
2502 public const int AllowedModifiers =
2504 Modifiers.PROTECTED |
2505 Modifiers.INTERNAL |
2512 // The spec claims that static is not permitted, but
2513 // my very own code has static constructors.
2515 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2516 : base (null, 0, AllowedModifiers, name, null, args, l)
2522 // Returns true if this is a default constructor
2524 public bool IsDefault ()
2526 if ((ModFlags & Modifiers.STATIC) != 0)
2527 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2528 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2531 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2532 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2533 (Initializer is ConstructorBaseInitializer) &&
2534 (Initializer.Arguments == null);
2538 // Creates the ConstructorBuilder
2540 public override bool Define (TypeContainer parent)
2542 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2543 MethodAttributes.SpecialName);
2545 // Check if arguments were correct.
2546 if (!DoDefineParameters (parent))
2549 if ((ModFlags & Modifiers.STATIC) != 0)
2550 ca |= MethodAttributes.Static;
2552 if (parent is Struct && ParameterTypes.Length == 0){
2555 "Structs can not contain explicit parameterless " +
2559 ca |= MethodAttributes.HideBySig;
2561 if ((ModFlags & Modifiers.PUBLIC) != 0)
2562 ca |= MethodAttributes.Public;
2563 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2564 if ((ModFlags & Modifiers.INTERNAL) != 0)
2565 ca |= MethodAttributes.FamORAssem;
2567 ca |= MethodAttributes.Family;
2568 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2569 ca |= MethodAttributes.Assembly;
2570 else if (IsDefault ())
2571 ca |= MethodAttributes.Public;
2573 ca |= MethodAttributes.Private;
2576 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2577 ca, GetCallingConvention (parent is Class), ParameterTypes);
2580 // HACK because System.Reflection.Emit is lame
2582 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2585 "Class `" +parent.Name+ "' already contains a definition with the " +
2586 "same return value and parameter types for constructor `" + Name
2597 public void Emit (TypeContainer parent)
2599 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2600 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2603 // extern methods have no bodies
2605 if ((ModFlags & Modifiers.EXTERN) != 0) {
2606 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
2608 179, Location, "External constructor `" +
2609 TypeManager.CSharpSignature (ConstructorBuilder) +
2610 "' can not have a body");
2613 } else if (block == null) {
2615 501, Location, "Constructor `" +
2616 TypeManager.CSharpSignature (ConstructorBuilder) +
2617 "' must declare a body since it is not marked extern");
2621 if ((ModFlags & Modifiers.STATIC) == 0){
2622 if (parent is Class && Initializer == null)
2623 Initializer = new ConstructorBaseInitializer (
2624 null, Parameters.EmptyReadOnlyParameters, parent.Location);
2628 // Spec mandates that Initializers will not have
2632 if (Initializer != null && !Initializer.Resolve (ec))
2634 ec.IsStatic = false;
2637 LabelParameters (ec, ParameterTypes, ConstructorBuilder);
2640 // Classes can have base initializers and instance field initializers.
2642 if (parent is Class){
2643 if ((ModFlags & Modifiers.STATIC) == 0)
2644 parent.EmitFieldInitializers (ec);
2646 if (Initializer != null)
2647 Initializer.Emit (ec);
2649 if ((ModFlags & Modifiers.STATIC) != 0)
2650 parent.EmitFieldInitializers (ec);
2652 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2654 // If this is a non-static `struct' constructor and doesn't have any
2655 // initializer, it must initialize all of the struct's fields.
2656 if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2657 (Initializer == null))
2658 Block.AddThisVariable (parent, Location);
2660 ec.EmitTopBlock (Block, ParameterInfo, Location);
2664 public class MethodData {
2666 // The return type of this method
2668 public readonly Type ReturnType;
2669 public readonly Type[] ParameterTypes;
2670 public readonly InternalParameters ParameterInfo;
2671 public readonly CallingConventions CallingConventions;
2672 public readonly Attributes OptAttributes;
2673 public readonly Location Location;
2676 // Are we implementing an interface ?
2678 public bool IsImplementing = false;
2683 protected MemberBase member;
2684 protected int modifiers;
2685 protected MethodAttributes flags;
2686 protected bool is_method;
2687 protected string accessor_name;
2688 ArrayList conditionals;
2690 MethodBuilder builder = null;
2691 public MethodBuilder MethodBuilder {
2697 public MethodData (MemberBase member, string name, Type return_type,
2698 Type [] parameter_types, InternalParameters parameters,
2699 CallingConventions cc, Attributes opt_attrs,
2700 int modifiers, MethodAttributes flags, bool is_method)
2702 this.member = member;
2703 this.accessor_name = name;
2704 this.ReturnType = return_type;
2705 this.ParameterTypes = parameter_types;
2706 this.ParameterInfo = parameters;
2707 this.CallingConventions = cc;
2708 this.OptAttributes = opt_attrs;
2709 this.modifiers = modifiers;
2711 this.is_method = is_method;
2712 this.Location = member.Location;
2713 this.conditionals = new ArrayList ();
2719 Attribute dllimport_attribute = null;
2720 string obsolete = null;
2721 bool obsolete_error = false;
2723 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2725 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2728 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2729 if (asec.Attributes == null)
2732 foreach (Attribute a in asec.Attributes) {
2733 if (a.Name == "Conditional") {
2734 if (!ApplyConditionalAttribute (a))
2736 } else if (a.Name == "Obsolete") {
2737 if (!ApplyObsoleteAttribute (a))
2739 } else if (a.Name.IndexOf ("DllImport") != -1) {
2741 a.Type = TypeManager.dllimport_type;
2742 Attribute.Error_AttributeNotValidForElement (a, Location);
2745 if (!ApplyDllImportAttribute (a))
2755 // Applies the `DllImport' attribute to the method.
2757 protected virtual bool ApplyDllImportAttribute (Attribute a)
2759 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2760 if ((modifiers & extern_static) != extern_static) {
2761 Report.Error (601, Location,
2762 "The DllImport attribute must be specified on a method " +
2763 "marked `static' and `extern'.");
2767 flags |= MethodAttributes.PinvokeImpl;
2768 dllimport_attribute = a;
2773 // Applies the `Obsolete' attribute to the method.
2775 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2777 if (obsolete != null) {
2778 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2782 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2783 return obsolete != null;
2787 // Applies the `Conditional' attribute to the method.
2789 protected virtual bool ApplyConditionalAttribute (Attribute a)
2791 // The Conditional attribute is only valid on methods.
2793 Attribute.Error_AttributeNotValidForElement (a, Location);
2797 string condition = a.Conditional_GetConditionName ();
2799 if (condition == null)
2802 if (ReturnType != TypeManager.void_type) {
2803 Report.Error (578, Location,
2804 "Conditional not valid on `" + member.Name + "' " +
2805 "because its return type is not void");
2809 if ((modifiers & Modifiers.OVERRIDE) != 0) {
2810 Report.Error (243, Location,
2811 "Conditional not valid on `" + member.Name + "' " +
2812 "because it is an override method");
2816 if (member.IsExplicitImpl) {
2817 Report.Error (577, Location,
2818 "Conditional not valid on `" + member.Name + "' " +
2819 "because it is an explicit interface implementation");
2823 if (IsImplementing) {
2824 Report.Error (623, Location,
2825 "Conditional not valid on `" + member.Name + "' " +
2826 "because it is an interface method");
2830 conditionals.Add (condition);
2836 // Checks whether this method should be ignored due to its Conditional attributes.
2838 bool ShouldIgnore (Location loc)
2840 // When we're overriding a virtual method, we implicitly inherit the
2841 // Conditional attributes from our parent.
2842 if (member.ParentMethod != null) {
2843 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2844 member.ParentMethod, loc);
2846 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2850 foreach (string condition in conditionals)
2851 if (RootContext.AllDefines [condition] == null)
2858 // Returns the TypeManager.MethodFlags for this method.
2859 // This emits an error 619 / warning 618 if the method is obsolete.
2860 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2862 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2864 TypeManager.MethodFlags flags = 0;
2866 if (obsolete != null) {
2867 if (obsolete_error) {
2868 Report.Error (619, loc, "Method `" + member.Name +
2869 "' is obsolete: `" + obsolete + "'");
2870 return TypeManager.MethodFlags.IsObsoleteError;
2872 Report.Warning (618, loc, "Method `" + member.Name +
2873 "' is obsolete: `" + obsolete + "'");
2875 flags |= TypeManager.MethodFlags.IsObsolete;
2878 if (ShouldIgnore (loc))
2879 flags |= TypeManager.MethodFlags.ShouldIgnore;
2884 public virtual bool Define (TypeContainer parent)
2886 MethodInfo implementing = null;
2887 string method_name, name, prefix;
2889 if (OptAttributes != null)
2890 if (!ApplyAttributes (OptAttributes, is_method))
2893 if (member.IsExplicitImpl)
2894 prefix = member.InterfaceType.FullName + ".";
2898 if (accessor_name != null)
2899 name = accessor_name + "_" + member.ShortName;
2901 name = member.ShortName;
2902 method_name = prefix + name;
2904 if (parent.Pending != null){
2905 if (member is Indexer)
2906 implementing = parent.Pending.IsInterfaceIndexer (
2907 member.InterfaceType, ReturnType, ParameterTypes);
2909 implementing = parent.Pending.IsInterfaceMethod (
2910 member.InterfaceType, name, ReturnType, ParameterTypes);
2912 if (member.InterfaceType != null && implementing == null){
2913 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
2920 // For implicit implementations, make sure we are public, for
2921 // explicit implementations, make sure we are private.
2923 if (implementing != null){
2925 // Setting null inside this block will trigger a more
2926 // verbose error reporting for missing interface implementations
2928 // The "candidate" function has been flagged already
2929 // but it wont get cleared
2931 if (!member.IsExplicitImpl){
2933 // We already catch different accessibility settings
2934 // so we just need to check that we are not private
2936 if ((modifiers & Modifiers.PRIVATE) != 0)
2937 implementing = null;
2940 // Static is not allowed
2942 if ((modifiers & Modifiers.STATIC) != 0)
2943 implementing = null;
2945 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
2946 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
2947 implementing = null;
2953 // If implementing is still valid, set flags
2955 if (implementing != null){
2957 // When implementing interface methods, set NewSlot.
2959 if (implementing.DeclaringType.IsInterface)
2960 flags |= MethodAttributes.NewSlot;
2963 MethodAttributes.Virtual |
2964 MethodAttributes.HideBySig;
2966 // Get the method name from the explicit interface.
2967 if (member.InterfaceType != null) {
2968 name = implementing.Name;
2969 method_name = prefix + name;
2972 IsImplementing = true;
2976 // Create the MethodBuilder for the method
2978 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2979 if ((modifiers & Modifiers.STATIC) == 0) {
2980 Report.Error (601, Location,
2981 "The DllImport attribute must be specified on " +
2982 "a method marked 'static' and 'extern'.");
2986 EmitContext ec = new EmitContext (
2987 parent, Location, null, ReturnType, modifiers);
2989 builder = dllimport_attribute.DefinePInvokeMethod (
2990 ec, parent.TypeBuilder, method_name, flags,
2991 ReturnType, ParameterTypes);
2993 builder = parent.TypeBuilder.DefineMethod (
2994 method_name, flags, CallingConventions,
2995 ReturnType, ParameterTypes);
2997 if (builder == null)
3000 if (IsImplementing) {
3002 // clear the pending implemntation flag
3004 if (member is Indexer) {
3005 parent.Pending.ImplementIndexer (
3006 member.InterfaceType, builder, ReturnType,
3007 ParameterTypes, true);
3009 parent.Pending.ImplementMethod (
3010 member.InterfaceType, name, ReturnType,
3011 ParameterTypes, member.IsExplicitImpl);
3013 if (member.IsExplicitImpl)
3014 parent.TypeBuilder.DefineMethodOverride (
3015 builder, implementing);
3018 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3019 Report.Error (111, Location,
3020 "Class `" + parent.Name +
3021 "' already contains a definition with the " +
3022 "same return value and parameter types as the " +
3023 "'get' method of property `" + member.Name + "'");
3027 TypeManager.AddMethod (builder, this);
3035 public virtual void Emit (TypeContainer parent, Block block, object kind)
3040 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3041 ig = builder.GetILGenerator ();
3045 ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3047 if (OptAttributes != null)
3048 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
3050 if (member is MethodCore)
3051 ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder);
3054 // abstract or extern methods have no bodies
3056 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3061 // abstract or extern methods have no bodies.
3063 if ((modifiers & Modifiers.ABSTRACT) != 0)
3065 500, Location, "Abstract method `" +
3066 TypeManager.CSharpSignature (builder) +
3067 "' can not have a body");
3069 if ((modifiers & Modifiers.EXTERN) != 0)
3071 179, Location, "External method `" +
3072 TypeManager.CSharpSignature (builder) +
3073 "' can not have a body");
3079 // Methods must have a body unless they're extern or abstract
3081 if (block == null) {
3083 501, Location, "Method `" +
3084 TypeManager.CSharpSignature (builder) +
3085 "' must declare a body since it is not marked " +
3086 "abstract or extern");
3091 // Handle destructors specially
3093 // FIXME: This code generates buggy code
3095 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3096 EmitDestructor (ec, block);
3098 ISymbolWriter sw = CodeGen.SymbolWriter;
3100 if ((sw != null) && !Location.IsNull (Location) &&
3101 !Location.IsNull (block.EndLocation)) {
3102 Location end = block.EndLocation;
3103 MethodToken token = MethodBuilder.GetToken ();
3104 sw.OpenMethod (new SymbolToken (token.Token));
3105 // Avoid error if we don't support debugging for the platform
3107 sw.SetMethodSourceRange (Location.SymbolDocument,
3111 } catch (Exception) {
3114 ec.EmitTopBlock (block, ParameterInfo, Location);
3118 ec.EmitTopBlock (block, ParameterInfo, Location);
3122 void EmitDestructor (EmitContext ec, Block block)
3124 ILGenerator ig = ec.ig;
3126 Label finish = ig.DefineLabel ();
3127 bool old_in_try = ec.InTry;
3129 ig.BeginExceptionBlock ();
3131 ec.ReturnLabel = finish;
3132 ec.HasReturnLabel = true;
3133 ec.EmitTopBlock (block, null, Location);
3134 ec.InTry = old_in_try;
3136 // ig.MarkLabel (finish);
3137 bool old_in_finally = ec.InFinally;
3138 ec.InFinally = true;
3139 ig.BeginFinallyBlock ();
3141 if (ec.ContainerType.BaseType != null) {
3142 Expression member_lookup = Expression.MemberLookup (
3143 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3144 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, Location);
3146 if (member_lookup != null){
3147 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3149 ig.Emit (OpCodes.Ldarg_0);
3150 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3153 ec.InFinally = old_in_finally;
3155 ig.EndExceptionBlock ();
3156 //ig.MarkLabel (ec.ReturnLabel);
3157 ig.Emit (OpCodes.Ret);
3161 abstract public class MemberBase : MemberCore {
3162 public Expression Type;
3163 public readonly Attributes OptAttributes;
3165 protected MethodAttributes flags;
3168 // The "short" name of this property / indexer / event. This is the
3169 // name without the explicit interface.
3171 public string ShortName;
3174 // The type of this property / indexer / event
3176 public Type MemberType;
3179 // If true, this is an explicit interface implementation
3181 public bool IsExplicitImpl = false;
3184 // The name of the interface we are explicitly implementing
3186 public string ExplicitInterfaceName = null;
3189 // If true, the interface type we are explicitly implementing
3191 public Type InterfaceType = null;
3194 // The method we're overriding if this is an override method.
3196 protected MethodInfo parent_method = null;
3197 public MethodInfo ParentMethod {
3199 return parent_method;
3204 // The constructor is only exposed to our children
3206 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3207 Attributes attrs, Location loc)
3211 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
3212 OptAttributes = attrs;
3215 protected virtual bool CheckBase (TypeContainer parent)
3220 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3224 foreach (Type partype in parameters){
3225 if (partype.IsPointer && !UnsafeOK (parent))
3228 if (parent.AsAccessible (partype, ModFlags))
3231 if (this is Indexer)
3232 Report.Error (55, Location,
3233 "Inconsistent accessibility: parameter type `" +
3234 TypeManager.CSharpName (partype) + "' is less " +
3235 "accessible than indexer `" + Name + "'");
3237 Report.Error (51, Location,
3238 "Inconsistent accessibility: parameter type `" +
3239 TypeManager.CSharpName (partype) + "' is less " +
3240 "accessible than method `" + Name + "'");
3247 protected virtual bool DoDefine (TypeContainer parent)
3252 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3255 flags = Modifiers.MethodAttr (ModFlags);
3257 // Lookup Type, verify validity
3258 MemberType = parent.ResolveType (Type, false, Location);
3259 if (MemberType == null)
3262 // verify accessibility
3263 if (!parent.AsAccessible (MemberType, ModFlags)) {
3264 if (this is Property)
3265 Report.Error (53, Location,
3266 "Inconsistent accessibility: property type `" +
3267 TypeManager.CSharpName (MemberType) + "' is less " +
3268 "accessible than property `" + Name + "'");
3269 else if (this is Indexer)
3270 Report.Error (54, Location,
3271 "Inconsistent accessibility: indexer return type `" +
3272 TypeManager.CSharpName (MemberType) + "' is less " +
3273 "accessible than indexer `" + Name + "'");
3274 else if (this is Method)
3275 Report.Error (50, Location,
3276 "Inconsistent accessibility: return type `" +
3277 TypeManager.CSharpName (MemberType) + "' is less " +
3278 "accessible than method `" + Name + "'");
3280 Report.Error (52, Location,
3281 "Inconsistent accessibility: field type `" +
3282 TypeManager.CSharpName (MemberType) + "' is less " +
3283 "accessible than field `" + Name + "'");
3287 if (MemberType.IsPointer && !UnsafeOK (parent))
3291 // Check for explicit interface implementation
3293 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
3294 int pos = Name.LastIndexOf (".");
3296 ExplicitInterfaceName = Name.Substring (0, pos);
3297 ShortName = Name.Substring (pos + 1);
3301 if (ExplicitInterfaceName != null) {
3302 InterfaceType = RootContext.LookupType (
3303 parent, ExplicitInterfaceName, false, Location);
3304 if (InterfaceType == null)
3307 // Compute the full name that we need to export.
3308 Name = InterfaceType.FullName + "." + ShortName;
3310 if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
3313 IsExplicitImpl = true;
3315 IsExplicitImpl = false;
3322 // Fields and Events both generate FieldBuilders, we use this to share
3323 // their common bits. This is also used to flag usage of the field
3325 abstract public class FieldBase : MemberBase {
3326 public FieldBuilder FieldBuilder;
3327 public Status status;
3330 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3333 // The constructor is only exposed to our children
3335 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3336 object init, Attributes attrs, Location loc)
3337 : base (type, mod, allowed_mod, name, attrs, loc)
3343 // Whether this field has an initializer.
3345 public bool HasInitializer {
3347 return init != null;
3352 readonly Object init;
3353 Expression init_expr;
3354 bool init_expr_initialized = false;
3357 // Resolves and returns the field initializer.
3359 public Expression GetInitializerExpression (EmitContext ec)
3361 if (init_expr_initialized)
3365 if (init is Expression)
3366 e = (Expression) init;
3368 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3370 ec.IsFieldInitializer = true;
3371 e = e.DoResolve (ec);
3372 ec.IsFieldInitializer = false;
3375 init_expr_initialized = true;
3382 // The Field class is used to represents class/struct fields during parsing.
3384 public class Field : FieldBase {
3386 // Modifiers allowed in a class declaration
3388 const int AllowedModifiers =
3391 Modifiers.PROTECTED |
3392 Modifiers.INTERNAL |
3395 Modifiers.VOLATILE |
3399 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3400 Attributes attrs, Location loc)
3401 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3405 public override bool Define (TypeContainer parent)
3407 Type t = parent.ResolveType (Type, false, Location);
3412 if (!parent.AsAccessible (t, ModFlags)) {
3413 Report.Error (52, Location,
3414 "Inconsistent accessibility: field type `" +
3415 TypeManager.CSharpName (t) + "' is less " +
3416 "accessible than field `" + Name + "'");
3420 if (t.IsPointer && !UnsafeOK (parent))
3423 if (RootContext.WarningLevel > 1){
3424 Type ptype = parent.TypeBuilder.BaseType;
3426 // ptype is only null for System.Object while compiling corlib.
3428 TypeContainer.FindMembers (
3429 ptype, MemberTypes.Method,
3430 BindingFlags.Public |
3431 BindingFlags.Static | BindingFlags.Instance,
3432 System.Type.FilterName, Name);
3436 if ((ModFlags & Modifiers.VOLATILE) != 0){
3438 if (TypeManager.IsEnumType (t))
3439 t = TypeManager.EnumToUnderlying (t);
3441 if (!((t == TypeManager.bool_type) ||
3442 (t == TypeManager.sbyte_type) ||
3443 (t == TypeManager.byte_type) ||
3444 (t == TypeManager.short_type) ||
3445 (t == TypeManager.ushort_type) ||
3446 (t == TypeManager.int32_type) ||
3447 (t == TypeManager.uint32_type) ||
3448 (t == TypeManager.char_type) ||
3449 (t == TypeManager.float_type))){
3451 677, Location, parent.MakeName (Name) +
3452 " A volatile field can not be of type `" +
3453 TypeManager.CSharpName (t) + "'");
3459 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3461 if (parent is Struct &&
3462 ((fa & FieldAttributes.Static) == 0) &&
3463 t == parent.TypeBuilder &&
3464 !TypeManager.IsBuiltinType (t)){
3465 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name +
3466 "' causes a cycle in the structure layout");
3469 FieldBuilder = parent.TypeBuilder.DefineField (
3470 Name, t, Modifiers.FieldAttr (ModFlags));
3472 TypeManager.RegisterFieldBase (FieldBuilder, this);
3476 public void Emit (TypeContainer tc)
3478 EmitContext ec = new EmitContext (tc, Location, null,
3479 FieldBuilder.FieldType, ModFlags);
3481 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
3486 // `set' and `get' accessors are represented with an Accessor.
3488 public class Accessor {
3490 // Null if the accessor is empty, or a Block if not
3493 public Attributes OptAttributes;
3495 public Accessor (Block b, Attributes attrs)
3498 OptAttributes = attrs;
3503 // Properties and Indexers both generate PropertyBuilders, we use this to share
3504 // their common bits.
3506 abstract public class PropertyBase : MethodCore {
3507 public Accessor Get, Set;
3508 public PropertyBuilder PropertyBuilder;
3509 public MethodBuilder GetBuilder, SetBuilder;
3510 public MethodData GetData, SetData;
3512 protected EmitContext ec;
3514 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3515 Parameters parameters, Accessor get_block, Accessor set_block,
3516 Attributes attrs, Location loc)
3517 : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3523 protected override bool DoDefine (TypeContainer parent)
3525 if (!base.DoDefine (parent))
3528 ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3534 // Checks our base implementation if any
3536 protected override bool CheckBase (TypeContainer parent)
3538 // Check whether arguments were correct.
3539 if (!DoDefineParameters (parent))
3546 MethodSignature ms, base_ms;
3547 if (this is Indexer) {
3548 string name, base_name;
3550 report_name = "this";
3551 name = TypeManager.IndexerPropertyName (parent.TypeBuilder);
3552 ms = new MethodSignature (name, null, ParameterTypes);
3553 base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType);
3554 base_ms = new MethodSignature (base_name, null, ParameterTypes);
3557 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
3561 // Verify if the parent has a type with the same name, and then
3562 // check whether we have to create a new slot for it or not.
3564 Type ptype = parent.TypeBuilder.BaseType;
3566 // ptype is only null for System.Object while compiling corlib.
3567 if (ptype == null) {
3568 if ((ModFlags & Modifiers.NEW) != 0)
3569 WarningNotHiding (parent);
3574 MemberList props_this;
3576 props_this = TypeContainer.FindMembers (
3577 parent.TypeBuilder, MemberTypes.Property,
3578 BindingFlags.NonPublic | BindingFlags.Public |
3579 BindingFlags.Static | BindingFlags.Instance |
3580 BindingFlags.DeclaredOnly,
3581 MethodSignature.method_signature_filter, ms);
3583 if (props_this.Count > 0) {
3584 Report.Error (111, Location, "Class `" + parent.Name + "' " +
3585 "already defines a member called `" + report_name + "' " +
3586 "with the same parameter types");
3590 MemberList mi_props;
3592 mi_props = TypeContainer.FindMembers (
3593 ptype, MemberTypes.Property,
3594 BindingFlags.NonPublic | BindingFlags.Public |
3595 BindingFlags.Instance | BindingFlags.Static,
3596 MethodSignature.inheritable_method_signature_filter, base_ms);
3598 if (mi_props.Count > 0){
3599 PropertyInfo parent_property = (PropertyInfo) mi_props [0];
3600 string name = parent_property.DeclaringType.Name + "." +
3601 parent_property.Name;
3603 MethodInfo get, set, parent_method;
3604 get = parent_property.GetGetMethod (true);
3605 set = parent_property.GetSetMethod (true);
3608 parent_method = get;
3609 else if (set != null)
3610 parent_method = set;
3612 throw new Exception ("Internal error!");
3614 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
3617 if ((ModFlags & Modifiers.NEW) == 0) {
3618 Type parent_type = TypeManager.TypeToCoreType (
3619 parent_property.PropertyType);
3621 if (parent_type != MemberType) {
3623 508, parent.MakeName (Name) + ": cannot " +
3624 "change return type when overriding " +
3625 "inherited member " + name);
3630 if ((ModFlags & Modifiers.NEW) != 0)
3631 WarningNotHiding (parent);
3633 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3634 if (this is Indexer)
3635 Report.Error (115, Location,
3636 parent.MakeName (Name) +
3637 " no suitable indexers found to override");
3639 Report.Error (115, Location,
3640 parent.MakeName (Name) +
3641 " no suitable properties found to override");
3648 public void Emit (TypeContainer tc)
3651 // The PropertyBuilder can be null for explicit implementations, in that
3652 // case, we do not actually emit the ".property", so there is nowhere to
3653 // put the attribute
3655 if (PropertyBuilder != null)
3656 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3658 if (GetData != null)
3659 GetData.Emit (tc, Get.Block, Get);
3661 if (SetData != null)
3662 SetData.Emit (tc, Set.Block, Set);
3666 public class Property : PropertyBase {
3667 const int AllowedModifiers =
3670 Modifiers.PROTECTED |
3671 Modifiers.INTERNAL |
3675 Modifiers.OVERRIDE |
3676 Modifiers.ABSTRACT |
3681 public Property (Expression type, string name, int mod_flags,
3682 Accessor get_block, Accessor set_block,
3683 Attributes attrs, Location loc)
3684 : base (type, name, mod_flags, AllowedModifiers,
3685 Parameters.EmptyReadOnlyParameters,
3686 get_block, set_block, attrs, loc)
3690 public override bool Define (TypeContainer parent)
3692 if (!DoDefine (parent))
3695 if (!CheckBase (parent))
3698 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3701 Type [] parameters = TypeManager.NoTypes;
3703 InternalParameters ip = new InternalParameters (
3704 parent, Parameters.EmptyReadOnlyParameters);
3706 GetData = new MethodData (this, "get", MemberType,
3707 parameters, ip, CallingConventions.Standard,
3708 Get.OptAttributes, ModFlags, flags, false);
3710 if (!GetData.Define (parent))
3713 GetBuilder = GetData.MethodBuilder;
3717 Type [] parameters = new Type [1];
3718 parameters [0] = MemberType;
3720 Parameter [] parms = new Parameter [1];
3721 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3722 InternalParameters ip = new InternalParameters (
3723 parent, new Parameters (parms, null, Location));
3725 SetData = new MethodData (this, "set", TypeManager.void_type,
3726 parameters, ip, CallingConventions.Standard,
3727 Set.OptAttributes, ModFlags, flags, false);
3729 if (!SetData.Define (parent))
3732 SetBuilder = SetData.MethodBuilder;
3733 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3736 // FIXME - PropertyAttributes.HasDefault ?
3738 PropertyAttributes prop_attr =
3739 PropertyAttributes.RTSpecialName |
3740 PropertyAttributes.SpecialName;
3742 if (!IsExplicitImpl){
3743 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3744 Name, prop_attr, MemberType, null);
3747 PropertyBuilder.SetGetMethod (GetBuilder);
3750 PropertyBuilder.SetSetMethod (SetBuilder);
3753 // HACK for the reasons exposed above
3755 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3758 "Class `" + parent.Name +
3759 "' already contains a definition for the property `" +
3769 /// Gigantic workaround for lameness in SRE follows :
3770 /// This class derives from EventInfo and attempts to basically
3771 /// wrap around the EventBuilder so that FindMembers can quickly
3772 /// return this in it search for members
3774 public class MyEventBuilder : EventInfo {
3777 // We use this to "point" to our Builder which is
3778 // not really a MemberInfo
3780 EventBuilder MyBuilder;
3783 // We "catch" and wrap these methods
3785 MethodInfo raise, remove, add;
3787 EventAttributes attributes;
3788 Type declaring_type, reflected_type, event_type;
3793 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3795 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3797 // And now store the values in our own fields.
3799 declaring_type = type_builder;
3801 reflected_type = type_builder;
3803 attributes = event_attr;
3806 this.event_type = event_type;
3810 // Methods that you have to override. Note that you only need
3811 // to "implement" the variants that take the argument (those are
3812 // the "abstract" methods, the others (GetAddMethod()) are
3815 public override MethodInfo GetAddMethod (bool nonPublic)
3820 public override MethodInfo GetRemoveMethod (bool nonPublic)
3825 public override MethodInfo GetRaiseMethod (bool nonPublic)
3831 // These methods make "MyEventInfo" look like a Builder
3833 public void SetRaiseMethod (MethodBuilder raiseMethod)
3835 raise = raiseMethod;
3836 MyBuilder.SetRaiseMethod (raiseMethod);
3839 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3841 remove = removeMethod;
3842 MyBuilder.SetRemoveOnMethod (removeMethod);
3845 public void SetAddOnMethod (MethodBuilder addMethod)
3848 MyBuilder.SetAddOnMethod (addMethod);
3851 public void SetCustomAttribute (CustomAttributeBuilder cb)
3853 MyBuilder.SetCustomAttribute (cb);
3856 public override object [] GetCustomAttributes (bool inherit)
3858 // FIXME : There's nothing which can be seemingly done here because
3859 // we have no way of getting at the custom attribute objects of the
3864 public override object [] GetCustomAttributes (Type t, bool inherit)
3866 // FIXME : Same here !
3870 public override bool IsDefined (Type t, bool b)
3875 public override EventAttributes Attributes {
3881 public override string Name {
3887 public override Type DeclaringType {
3889 return declaring_type;
3893 public override Type ReflectedType {
3895 return reflected_type;
3899 public Type EventType {
3905 public void SetUsed ()
3907 if (my_event != null)
3908 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
3912 public class Event : FieldBase {
3913 const int AllowedModifiers =
3916 Modifiers.PROTECTED |
3917 Modifiers.INTERNAL |
3922 Modifiers.OVERRIDE |
3926 public readonly Accessor Add;
3927 public readonly Accessor Remove;
3928 public MyEventBuilder EventBuilder;
3930 MethodBuilder AddBuilder, RemoveBuilder;
3931 MethodData AddData, RemoveData;
3933 public Event (Expression type, string name, Object init, int mod, Accessor add,
3934 Accessor remove, Attributes attrs, Location loc)
3935 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
3941 public override bool Define (TypeContainer parent)
3943 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3945 if (!DoDefine (parent))
3948 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
3949 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3950 "' : event must be of a delegate type");
3954 Type [] parameter_types = new Type [1];
3955 parameter_types [0] = MemberType;
3957 Parameter [] parms = new Parameter [1];
3958 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3959 InternalParameters ip = new InternalParameters (
3960 parent, new Parameters (parms, null, Location));
3962 if (!CheckBase (parent))
3966 // Now define the accessors
3968 AddData = new MethodData (this, "add", TypeManager.void_type,
3969 parameter_types, ip, CallingConventions.Standard,
3970 (Add != null) ? Add.OptAttributes : null,
3971 ModFlags, flags, false);
3973 if (!AddData.Define (parent))
3976 AddBuilder = AddData.MethodBuilder;
3977 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3979 RemoveData = new MethodData (this, "remove", TypeManager.void_type,
3980 parameter_types, ip, CallingConventions.Standard,
3981 (Remove != null) ? Remove.OptAttributes : null,
3982 ModFlags, flags, false);
3984 if (!RemoveData.Define (parent))
3987 RemoveBuilder = RemoveData.MethodBuilder;
3988 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3990 if (!IsExplicitImpl){
3991 EventBuilder = new MyEventBuilder (this,
3992 parent.TypeBuilder, Name, e_attr, MemberType);
3994 if (Add == null && Remove == null) {
3995 FieldBuilder = parent.TypeBuilder.DefineField (
3997 FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
3998 TypeManager.RegisterPrivateFieldOfEvent (
3999 (EventInfo) EventBuilder, FieldBuilder);
4000 TypeManager.RegisterFieldBase (FieldBuilder, this);
4003 EventBuilder.SetAddOnMethod (AddBuilder);
4004 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4006 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4007 Report.Error (111, Location,
4008 "Class `" + parent.Name +
4009 "' already contains a definition for the event `" +
4018 void EmitDefaultMethod (EmitContext ec, bool is_add)
4020 ILGenerator ig = ec.ig;
4021 MethodInfo method = null;
4024 method = TypeManager.delegate_combine_delegate_delegate;
4026 method = TypeManager.delegate_remove_delegate_delegate;
4028 if ((ModFlags & Modifiers.STATIC) != 0) {
4029 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4030 ig.Emit (OpCodes.Ldarg_0);
4031 ig.Emit (OpCodes.Call, method);
4032 ig.Emit (OpCodes.Castclass, MemberType);
4033 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4035 ig.Emit (OpCodes.Ldarg_0);
4036 ig.Emit (OpCodes.Ldarg_0);
4037 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4038 ig.Emit (OpCodes.Ldarg_1);
4039 ig.Emit (OpCodes.Call, method);
4040 ig.Emit (OpCodes.Castclass, MemberType);
4041 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4043 ig.Emit (OpCodes.Ret);
4046 public void Emit (TypeContainer tc)
4050 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4051 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
4054 AddData.Emit (tc, Add.Block, Add);
4056 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4057 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4058 EmitDefaultMethod (ec, true);
4062 RemoveData.Emit (tc, Remove.Block, Remove);
4064 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4065 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4066 EmitDefaultMethod (ec, false);
4073 // FIXME: This does not handle:
4075 // int INTERFACENAME [ args ]
4080 // int this [ args ]
4082 public class Indexer : PropertyBase {
4084 const int AllowedModifiers =
4087 Modifiers.PROTECTED |
4088 Modifiers.INTERNAL |
4092 Modifiers.OVERRIDE |
4097 public string IndexerName;
4098 public string InterfaceIndexerName;
4101 // Are we implementing an interface ?
4103 bool IsImplementing = false;
4105 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4106 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4107 : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4110 ExplicitInterfaceName = int_type;
4113 public override bool Define (TypeContainer parent)
4115 PropertyAttributes prop_attr =
4116 PropertyAttributes.RTSpecialName |
4117 PropertyAttributes.SpecialName;
4119 if (!DoDefine (parent))
4122 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4123 if (IndexerName == null)
4124 IndexerName = "Item";
4125 else if (IsExplicitImpl)
4126 Report.Error (592, Location,
4127 "Attribute 'IndexerName' is not valid on this declaration " +
4128 "type. It is valid on `property' declarations only.");
4130 ShortName = IndexerName;
4131 if (IsExplicitImpl) {
4132 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4133 Name = InterfaceType.FullName + "." + IndexerName;
4135 InterfaceIndexerName = IndexerName;
4139 if (!CheckBase (parent))
4143 InternalParameters ip = new InternalParameters (parent, Parameters);
4145 GetData = new MethodData (this, "get", MemberType,
4146 ParameterTypes, ip, CallingConventions.Standard,
4147 Get.OptAttributes, ModFlags, flags, false);
4149 if (!GetData.Define (parent))
4152 GetBuilder = GetData.MethodBuilder;
4156 int top = ParameterTypes.Length;
4157 Type [] set_pars = new Type [top + 1];
4158 ParameterTypes.CopyTo (set_pars, 0);
4159 set_pars [top] = MemberType;
4161 Parameter [] fixed_parms = Parameters.FixedParameters;
4163 if (fixed_parms == null){
4164 throw new Exception ("We currently do not support only array arguments in an indexer");
4165 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4166 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4168 // Here is the problem: the `value' parameter has
4169 // to come *after* the array parameter in the declaration
4171 // X (object [] x, Type value)
4174 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4175 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4179 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4182 fixed_parms.CopyTo (tmp, 0);
4183 tmp [fixed_parms.Length] = new Parameter (
4184 Type, "value", Parameter.Modifier.NONE, null);
4186 Parameters set_formal_params = new Parameters (tmp, null, Location);
4188 InternalParameters ip = new InternalParameters (parent, set_formal_params);
4190 SetData = new MethodData (this, "set", TypeManager.void_type,
4191 set_pars, ip, CallingConventions.Standard,
4192 Set.OptAttributes, ModFlags, flags, false);
4194 if (!SetData.Define (parent))
4197 SetBuilder = SetData.MethodBuilder;
4201 // Now name the parameters
4203 Parameter [] p = Parameters.FixedParameters;
4207 for (i = 0; i < p.Length; ++i) {
4209 GetBuilder.DefineParameter (
4210 i + 1, p [i].Attributes, p [i].Name);
4213 SetBuilder.DefineParameter (
4214 i + 1, p [i].Attributes, p [i].Name);
4218 SetBuilder.DefineParameter (
4219 i + 1, ParameterAttributes.None, "value");
4221 if (i != ParameterTypes.Length) {
4222 Parameter array_param = Parameters.ArrayParameter;
4223 SetBuilder.DefineParameter (
4224 i + 1, array_param.Attributes, array_param.Name);
4228 if (GetData != null)
4229 IsImplementing = GetData.IsImplementing;
4230 else if (SetData != null)
4231 IsImplementing = SetData.IsImplementing;
4234 // Define the PropertyBuilder if one of the following conditions are met:
4235 // a) we're not implementing an interface indexer.
4236 // b) the indexer has a different IndexerName and this is no
4237 // explicit interface implementation.
4239 if (!IsExplicitImpl) {
4240 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4241 IndexerName, prop_attr, MemberType, ParameterTypes);
4243 if (GetData != null)
4244 PropertyBuilder.SetGetMethod (GetBuilder);
4246 if (SetData != null)
4247 PropertyBuilder.SetSetMethod (SetBuilder);
4249 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4257 public class Operator : MemberCore {
4259 const int AllowedModifiers =
4265 const int RequiredModifiers =
4269 public enum OpType : byte {
4279 // Unary and Binary operators
4302 // Implicit and Explicit
4307 public readonly OpType OperatorType;
4308 public readonly Expression ReturnType;
4309 public readonly Expression FirstArgType, SecondArgType;
4310 public readonly string FirstArgName, SecondArgName;
4311 public readonly Block Block;
4312 public Attributes OptAttributes;
4313 public MethodBuilder OperatorMethodBuilder;
4315 public string MethodName;
4316 public Method OperatorMethod;
4318 public Operator (OpType type, Expression ret_type, int flags,
4319 Expression arg1type, string arg1name,
4320 Expression arg2type, string arg2name,
4321 Block block, Attributes attrs, Location loc)
4324 OperatorType = type;
4325 ReturnType = ret_type;
4326 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4327 FirstArgType = arg1type;
4328 FirstArgName = arg1name;
4329 SecondArgType = arg2type;
4330 SecondArgName = arg2name;
4332 OptAttributes = attrs;
4335 string Prototype (TypeContainer parent)
4337 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4338 SecondArgType + ")";
4341 public override bool Define (TypeContainer parent)
4344 MethodName = "op_" + OperatorType;
4346 if (SecondArgType != null)
4349 Parameter [] param_list = new Parameter [length];
4351 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4354 "User defined operators `" +
4355 Prototype (parent) +
4356 "' must be declared static and public");
4360 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4361 Parameter.Modifier.NONE, null);
4362 if (SecondArgType != null)
4363 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4364 Parameter.Modifier.NONE, null);
4366 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4367 new Parameters (param_list, null, Location),
4368 OptAttributes, Mono.CSharp.Location.Null);
4370 OperatorMethod.IsOperator = true;
4371 OperatorMethod.Define (parent);
4373 if (OperatorMethod.MethodBuilder == null)
4376 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4378 Type [] param_types = OperatorMethod.ParameterTypes;
4379 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4380 Type return_type = OperatorMethod.GetReturnType ();
4381 Type first_arg_type = param_types [0];
4383 // Rules for conversion operators
4385 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4386 if (first_arg_type == return_type && first_arg_type == declaring_type){
4389 "User-defined conversion cannot take an object of the " +
4390 "enclosing type and convert to an object of the enclosing" +
4395 if (first_arg_type != declaring_type && return_type != declaring_type){
4398 "User-defined conversion must convert to or from the " +
4403 if (first_arg_type == TypeManager.object_type ||
4404 return_type == TypeManager.object_type){
4407 "User-defined conversion cannot convert to or from " +
4412 if (first_arg_type.IsInterface || return_type.IsInterface){
4415 "User-defined conversion cannot convert to or from an " +
4420 if (first_arg_type.IsSubclassOf (return_type) ||
4421 return_type.IsSubclassOf (first_arg_type)){
4424 "User-defined conversion cannot convert between types " +
4425 "that derive from each other");
4428 } else if (SecondArgType == null) {
4429 // Checks for Unary operators
4431 if (first_arg_type != declaring_type){
4434 "The parameter of a unary operator must be the " +
4439 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4440 if (return_type != declaring_type){
4443 "The parameter and return type for ++ and -- " +
4444 "must be the containing type");
4450 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4451 if (return_type != TypeManager.bool_type){
4454 "The return type of operator True or False " +
4461 // Checks for Binary operators
4463 if (first_arg_type != declaring_type &&
4464 param_types [1] != declaring_type){
4467 "One of the parameters of a binary operator must " +
4468 "be the containing type");
4476 public void Emit (TypeContainer parent)
4478 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4479 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4482 // abstract or extern methods have no bodies
4484 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4487 OperatorMethod.Block = Block;
4488 OperatorMethod.Emit (parent);
4491 public static string GetName (OpType ot)
4494 case OpType.LogicalNot:
4496 case OpType.OnesComplement:
4498 case OpType.Increment:
4500 case OpType.Decrement:
4506 case OpType.Addition:
4508 case OpType.Subtraction:
4510 case OpType.UnaryPlus:
4512 case OpType.UnaryNegation:
4514 case OpType.Multiply:
4516 case OpType.Division:
4518 case OpType.Modulus:
4520 case OpType.BitwiseAnd:
4522 case OpType.BitwiseOr:
4524 case OpType.ExclusiveOr:
4526 case OpType.LeftShift:
4528 case OpType.RightShift:
4530 case OpType.Equality:
4532 case OpType.Inequality:
4534 case OpType.GreaterThan:
4536 case OpType.LessThan:
4538 case OpType.GreaterThanOrEqual:
4540 case OpType.LessThanOrEqual:
4542 case OpType.Implicit:
4544 case OpType.Explicit:
4550 public override string ToString ()
4552 Type return_type = OperatorMethod.GetReturnType();
4553 Type [] param_types = OperatorMethod.ParameterTypes;
4555 if (SecondArgType == null)
4556 return String.Format (
4557 "{0} operator {1}({2})",
4558 TypeManager.CSharpName (return_type),
4559 GetName (OperatorType),
4562 return String.Format (
4563 "{0} operator {1}({2}, {3})",
4564 TypeManager.CSharpName (return_type),
4565 GetName (OperatorType),
4566 param_types [0], param_types [1]);
4571 // This is used to compare method signatures
4573 struct MethodSignature {
4575 public Type RetType;
4576 public Type [] Parameters;
4579 /// This delegate is used to extract methods which have the
4580 /// same signature as the argument
4582 public static MemberFilter method_signature_filter;
4585 /// This delegate is used to extract inheritable methods which
4586 /// have the same signature as the argument. By inheritable,
4587 /// this means that we have permissions to override the method
4588 /// from the current assembly and class
4590 public static MemberFilter inheritable_method_signature_filter;
4592 static MethodSignature ()
4594 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4595 inheritable_method_signature_filter = new MemberFilter (
4596 InheritableMemberSignatureCompare);
4599 public MethodSignature (string name, Type ret_type, Type [] parameters)
4604 if (parameters == null)
4605 Parameters = TypeManager.NoTypes;
4607 Parameters = parameters;
4610 public override int GetHashCode ()
4612 return Name.GetHashCode ();
4615 public override bool Equals (Object o)
4617 MethodSignature other = (MethodSignature) o;
4619 if (other.Name != Name)
4622 if (other.RetType != RetType)
4625 if (Parameters == null){
4626 if (other.Parameters == null)
4631 if (other.Parameters == null)
4634 int c = Parameters.Length;
4635 if (other.Parameters.Length != c)
4638 for (int i = 0; i < c; i++)
4639 if (other.Parameters [i] != Parameters [i])
4645 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4647 MethodSignature sig = (MethodSignature) filter_criteria;
4649 if (m.Name != sig.Name)
4653 MethodInfo mi = m as MethodInfo;
4654 PropertyInfo pi = m as PropertyInfo;
4657 ReturnType = mi.ReturnType;
4658 else if (pi != null)
4659 ReturnType = pi.PropertyType;
4664 // we use sig.RetType == null to mean `do not check the
4665 // method return value.
4667 if (sig.RetType != null)
4668 if (ReturnType != sig.RetType)
4673 args = TypeManager.GetArgumentTypes (mi);
4675 args = TypeManager.GetArgumentTypes (pi);
4676 Type [] sigp = sig.Parameters;
4678 if (args.Length != sigp.Length)
4681 for (int i = args.Length; i > 0; ){
4683 if (args [i] != sigp [i])
4690 // This filter should be used when we are requesting methods that
4691 // we want to override.
4693 // This makes a number of assumptions, for example
4694 // that the methods being extracted are of a parent
4695 // class (this means we know implicitly that we are
4696 // being called to find out about members by a derived
4699 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4701 if (!MemberSignatureCompare (m, filter_criteria))
4705 PropertyInfo pi = m as PropertyInfo;
4708 mi = pi.GetGetMethod (true);
4710 mi = pi.GetSetMethod (true);
4712 mi = m as MethodInfo;
4715 Console.WriteLine ("Nothing found");
4718 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4720 // If only accessible to the current class.
4721 if (prot == MethodAttributes.Private)
4724 // If only accessible to the defining assembly or
4725 if (prot == MethodAttributes.FamANDAssem ||
4726 prot == MethodAttributes.Assembly){
4727 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4733 // Anything else (FamOrAssembly and Public) is fine