2 // class.cs: Class and Struct handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@gnome.org)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
12 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
14 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
15 // have fixed a remaining problem: not every AddXXXX was adding a
16 // fully qualified name.
18 // Now everyone registers a fully qualified name in the DeclSpace as
19 // being defined instead of the partial name.
21 // Downsides: we are slower than we need to be due to the excess
22 // copies and the names being registered this way.
24 // The reason for this is that we currently depend (on the corlib
25 // bootstrap for instance) that types are fully qualified, because
26 // we dump all the types in the namespace, and we should really have
27 // types inserted into the proper namespace, so we can only store the
28 // basenames in the defined_names array.
33 using System.Collections;
34 using System.Reflection;
35 using System.Reflection.Emit;
36 using System.Runtime.CompilerServices;
38 namespace Mono.CSharp {
41 /// This is the base class for structs and classes.
43 public class TypeContainer : DeclSpace, IMemberContainer {
44 // Holds a list of classes and structures
47 // Holds the list of properties
50 // Holds the list of enumerations
53 // Holds the list of delegates
56 // Holds the list of constructors
57 ArrayList instance_constructors;
59 // Holds the list of fields
62 // Holds a list of fields that have initializers
63 ArrayList initialized_fields;
65 // Holds a list of static fields that have initializers
66 ArrayList initialized_static_fields;
68 // Holds the list of constants
74 // Holds order in which interfaces must be closed
75 ArrayList interface_order;
86 // Holds the operators
89 // The emit context for toplevel objects.
93 // Pointers to the default constructor and the default static constructor
95 Constructor default_constructor;
96 Constructor default_static_constructor;
99 // Whether we have seen a static constructor for this class or not
101 public bool UserDefinedStaticConstructor = false;
104 // Whether we have at least one non-static field
106 bool have_nonstatic_fields = false;
109 // This one is computed after we can distinguish interfaces
110 // from classes from the arraylist `type_bases'
112 string base_class_name;
114 ArrayList type_bases;
116 bool members_defined;
117 bool members_defined_ok;
119 // Information in the case we are an attribute type
121 public AttributeTargets Targets = AttributeTargets.All;
122 public bool AllowMultiple = false;
123 public bool Inherited;
125 // The interfaces we implement.
128 // The parent member container and our member cache
129 IMemberContainer parent_container;
130 MemberCache member_cache;
133 // The indexer name for this class
135 public string IndexerName;
139 public TypeContainer ():
140 this (null, null, "", null, new Location (-1)) {
143 public TypeContainer (NamespaceEntry ns, TypeContainer parent, string name, Attributes attrs, Location l)
144 : base (ns, parent, name, attrs, l)
146 types = new ArrayList ();
148 base_class_name = null;
151 public AdditionResult AddConstant (Const constant)
154 string basename = constant.Name;
155 string fullname = Name + "." + basename;
157 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
160 if (constants == null)
161 constants = new ArrayList ();
163 constants.Add (constant);
164 DefineName (fullname, constant);
166 return AdditionResult.Success;
169 public AdditionResult AddEnum (Mono.CSharp.Enum e)
173 if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
177 enums = new ArrayList ();
180 DefineName (e.Name, e);
182 return AdditionResult.Success;
185 public AdditionResult AddClass (Class c)
188 string name = c.Basename;
190 if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
193 DefineName (c.Name, c);
196 return AdditionResult.Success;
199 public AdditionResult AddStruct (Struct s)
202 string name = s.Basename;
204 if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
207 DefineName (s.Name, s);
210 return AdditionResult.Success;
213 public AdditionResult AddDelegate (Delegate d)
216 string name = d.Basename;
218 if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
221 if (delegates == null)
222 delegates = new ArrayList ();
224 DefineName (d.Name, d);
227 return AdditionResult.Success;
230 public AdditionResult AddMethod (Method method)
232 string basename = method.Name;
233 string fullname = Name + "." + basename;
235 Object value = defined_names [fullname];
237 if (value != null && (!(value is Method)))
238 return AdditionResult.NameExists;
240 if (basename == Basename)
241 return AdditionResult.EnclosingClash;
244 methods = new ArrayList ();
246 if (method.Name.IndexOf ('.') != -1)
247 methods.Insert (0, method);
249 methods.Add (method);
252 DefineName (fullname, method);
254 return AdditionResult.Success;
257 public AdditionResult AddConstructor (Constructor c)
259 if (c.Name != Basename)
260 return AdditionResult.NotAConstructor;
262 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
265 UserDefinedStaticConstructor = true;
266 if (default_static_constructor != null)
267 return AdditionResult.MethodExists;
269 default_static_constructor = c;
272 if (default_constructor != null)
273 return AdditionResult.MethodExists;
274 default_constructor = c;
277 if (instance_constructors == null)
278 instance_constructors = new ArrayList ();
280 instance_constructors.Add (c);
283 return AdditionResult.Success;
286 public AdditionResult AddInterface (Interface iface)
289 string name = iface.Basename;
291 if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
294 if (interfaces == null)
295 interfaces = new ArrayList ();
296 interfaces.Add (iface);
297 DefineName (iface.Name, iface);
299 return AdditionResult.Success;
302 public AdditionResult AddField (Field field)
305 string basename = field.Name;
306 string fullname = Name + "." + basename;
308 if ((res = IsValid (basename, fullname)) != 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 if (initialized_fields == null)
325 initialized_fields = new ArrayList ();
327 initialized_fields.Add (field);
331 if ((field.ModFlags & Modifiers.STATIC) == 0)
332 have_nonstatic_fields = true;
334 DefineName (fullname, field);
335 return AdditionResult.Success;
338 public AdditionResult AddProperty (Property prop)
342 if ((res = AddProperty (prop, prop.Name)) != AdditionResult.Success)
345 if (prop.Get != null) {
346 if ((res = AddProperty (prop, "get_" + prop.Name)) != AdditionResult.Success)
350 if (prop.Set != null) {
351 if ((res = AddProperty (prop, "set_" + prop.Name)) != AdditionResult.Success)
355 if (properties == null)
356 properties = new ArrayList ();
358 if (prop.Name.IndexOf ('.') != -1)
359 properties.Insert (0, prop);
361 properties.Add (prop);
363 return AdditionResult.Success;
366 AdditionResult AddProperty (Property prop, string basename)
369 string fullname = Name + "." + basename;
371 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
374 DefineName (fullname, prop);
376 return AdditionResult.Success;
379 public AdditionResult AddEvent (Event e)
382 string basename = e.Name;
383 string fullname = Name + "." + basename;
385 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
389 events = new ArrayList ();
392 DefineName (fullname, e);
394 return AdditionResult.Success;
397 public void AddIndexer (Indexer i)
399 if (indexers == null)
400 indexers = new ArrayList ();
402 if (i.InterfaceType != null)
403 indexers.Insert (0, i);
408 public AdditionResult AddOperator (Operator op)
410 if (operators == null)
411 operators = new ArrayList ();
415 string basename = op.Name;
416 string fullname = Name + "." + basename;
417 if (!defined_names.Contains (fullname))
419 DefineName (fullname, op);
421 return AdditionResult.Success;
424 public void RegisterOrder (Interface iface)
426 if (interface_order == null)
427 interface_order = new ArrayList ();
429 interface_order.Add (iface);
432 public ArrayList Types {
438 public ArrayList Methods {
444 public ArrayList Constants {
450 public ArrayList Interfaces {
458 return base_class_name;
462 public ArrayList Bases {
472 public ArrayList Fields {
482 public ArrayList InstanceConstructors {
484 return instance_constructors;
488 public ArrayList Properties {
494 public ArrayList Events {
500 public ArrayList Enums {
506 public ArrayList Indexers {
512 public ArrayList Operators {
518 public ArrayList Delegates {
524 public virtual TypeAttributes TypeAttr {
526 return Modifiers.TypeAttr (ModFlags, this);
531 // Emits the instance field initializers
533 public bool EmitFieldInitializers (EmitContext ec)
536 Expression instance_expr;
539 fields = initialized_static_fields;
540 instance_expr = null;
542 fields = initialized_fields;
543 instance_expr = new This (Location.Null).Resolve (ec);
549 foreach (Field f in fields){
550 Expression e = f.GetInitializerExpression (ec);
554 Location l = f.Location;
555 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
556 fe.InstanceExpression = instance_expr;
557 ExpressionStatement a = new Assign (fe, e, l);
559 a = a.ResolveStatement (ec);
563 a.EmitStatement (ec);
570 // Defines the default constructors
572 void DefineDefaultConstructor (bool is_static)
576 // The default constructor is public
577 // If the class is abstract, the default constructor is protected
578 // The default static constructor is private
580 int mods = Modifiers.PUBLIC;
582 mods = Modifiers.STATIC | Modifiers.PRIVATE;
583 else if ((ModFlags & Modifiers.ABSTRACT) != 0)
584 mods = Modifiers.PROTECTED;
586 c = new Constructor (this, Basename, mods, Parameters.EmptyReadOnlyParameters,
587 new ConstructorBaseInitializer (
588 null, Parameters.EmptyReadOnlyParameters,
594 c.Block = new ToplevelBlock (null, Location);
598 public void ReportStructInitializedInstanceError ()
600 string n = TypeBuilder.FullName;
602 foreach (Field f in initialized_fields){
605 "`" + n + "." + f.Name + "': can not have " +
606 "instance field initializers in structs");
611 /// The pending methods that need to be implemented (interfaces or abstract methods)
613 public PendingImplementation Pending;
616 /// This function computes the Base class and also the
617 /// list of interfaces that the class or struct @c implements.
619 /// The return value is an array (might be null) of
620 /// interfaces implemented (as Types).
622 /// The @parent argument is set to the parent object or null
623 /// if this is `System.Object'.
625 TypeExpr [] GetClassBases (bool is_class, bool is_iface,
626 out TypeExpr parent, out bool error)
628 ArrayList bases = Bases;
634 if (is_class || is_iface)
637 parent = TypeManager.system_valuetype_expr;
641 if (RootContext.StdLib)
642 parent = TypeManager.system_object_expr;
643 else if (Name != "System.Object")
644 parent = TypeManager.system_object_expr;
647 // If we are compiling our runtime,
648 // and we are defining ValueType, then our
649 // parent is `System.Object'.
651 if (!RootContext.StdLib && Name == "System.ValueType")
652 parent = TypeManager.system_object_expr;
659 // Bases should be null if there are no bases at all
664 TypeExpr name = ResolveTypeExpr ((Expression) bases [0], false, Location);
671 if (name is TypeParameterExpr){
674 "Type parameter `{0}' can not be used as a " +
675 "base class or interface", name.Name);
680 if (IsGeneric && name.IsAttribute){
683 "A generic type cannot derive from `{0}' " +
684 "because it is an attribute class", name.Name);
693 parent = TypeManager.system_object_expr;
699 if (name.IsValueType)
700 detail = " (a class can not inherit from a struct/enum)";
702 Report.Error (509, "class `"+ Name +
703 "': Cannot inherit from sealed class `"+
704 name.Name + "'" + detail);
709 if (!parent.CanInheritFrom ()){
710 Report.Error (644, Location,
711 "`{0}' cannot inherit from special class `{1}'",
717 if (!parent.AsAccessible (this, ModFlags))
718 Report.Error (60, Location,
719 "Inconsistent accessibility: base class `" +
720 name.Name + "' is less accessible than class `" +
728 base_class_name = parent.Name;
730 TypeExpr [] ifaces = new TypeExpr [count-start];
732 for (i = start, j = 0; i < count; i++, j++){
733 Expression name = (Expression) bases [i];
734 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
736 if (resolved == null)
739 bases [i] = resolved;
741 if (is_class == false && !resolved.IsInterface){
742 Report.Error (527, "In Struct `" + Name + "', type `"+
743 name +"' is not an interface");
748 if (resolved.IsClass) {
750 Report.Error (527, "In Class `" + Name + "', type `"+
751 name+"' is not an interface");
757 for (int x = 0; x < j; x++) {
758 if (resolved.Equals (ifaces [x])) {
759 Report.Error (528, "`" + name + "' is already listed in interface list");
766 !resolved.AsAccessible (Parent, ModFlags))
767 Report.Error (61, Location,
768 "Inconsistent accessibility: base interface `" +
769 name + "' is less accessible than interface `" +
772 ifaces [j] = resolved;
775 return TypeManager.ExpandInterfaces (ifaces);
778 bool CheckGenericInterfaces (Type[] ifaces)
780 ArrayList already_checked = new ArrayList ();
782 for (int i = 0; i < ifaces.Length; i++) {
783 Type iface = ifaces [i];
784 foreach (Type t in already_checked) {
788 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t))
793 "`{0}' cannot implement both `{1}' and `{2}' " +
794 "because they may unify for some type " +
795 "parameter substitutions",
796 TypeManager.GetFullName (TypeBuilder),
801 already_checked.Add (iface);
810 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
812 public override TypeBuilder DefineType ()
815 bool is_class, is_iface;
817 if (TypeBuilder != null)
824 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
831 if (this is Interface) {
842 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
844 ifaces = GetClassBases (is_class, is_iface, out parent, out error);
850 foreach (TypeParameter type_param in TypeParameters)
851 if (!type_param.Resolve (this)) {
857 if (!is_class && TypeManager.value_type == null)
858 throw new Exception ();
860 TypeAttributes type_attributes = TypeAttr;
863 ConstructedType constructed = parent as ConstructedType;
864 if ((constructed == null) && (parent != null))
865 ptype = parent.ResolveType (ec);
870 if (TypeManager.NamespaceClash (Name, Location)) {
875 ModuleBuilder builder = CodeGen.Module.Builder;
876 TypeBuilder = builder.DefineType (
877 Name, type_attributes, ptype, null);
880 TypeBuilder builder = Parent.DefineType ();
884 TypeBuilder = builder.DefineNestedType (
885 Basename, type_attributes, ptype, null);
888 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
891 CurrentType = new ConstructedType (
892 Name, TypeParameters, Location);
894 foreach (TypeParameter type_param in TypeParameters)
895 type_param.Define (TypeBuilder);
898 if (constructed != null) {
899 ptype = constructed.ResolveType (ec);
903 TypeBuilder.SetParent (ptype);
907 foreach (TypeParameter type_param in TypeParameters)
908 type_param.DefineType (ec, TypeBuilder);
912 // Structs with no fields need to have at least one byte.
913 // The right thing would be to set the PackingSize in a DefineType
914 // but there are no functions that allow interfaces *and* the size to
918 if (!is_class && !is_iface && !have_nonstatic_fields){
919 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
920 FieldAttributes.Private);
923 // add interfaces that were not added at type creation
924 if (ifaces != null) {
925 Type[] itypes = new Type [ifaces.Length];
926 for (int i = 0; i < ifaces.Length; i++) {
927 itypes [i] = ifaces [i].ResolveType (ec);
928 if (itypes [i] == null)
935 if (!CheckGenericInterfaces (itypes)) {
940 for (int i = 0; i < ifaces.Length; i++)
941 TypeBuilder.AddInterfaceImplementation (itypes [i]);
945 // Finish the setup for the EmitContext
947 ec.ContainerType = TypeBuilder;
949 if ((parent != null) && parent.IsAttribute) {
950 RootContext.RegisterAttribute (this);
951 TypeManager.RegisterAttrType (TypeBuilder, this);
953 RootContext.RegisterOrder (this);
955 if (Interfaces != null) {
956 foreach (Interface iface in Interfaces)
957 if (iface.DefineType () == null) {
964 foreach (TypeContainer tc in Types)
965 if (tc.DefineType () == null) {
971 if (Delegates != null) {
972 foreach (Delegate d in Delegates)
973 if (d.DefineType () == null) {
980 foreach (Enum en in Enums)
981 if (en.DefineType () == null) {
993 /// Defines the MemberCore objects that are in the `list' Arraylist
995 /// The `defined_names' array contains a list of members defined in
998 static ArrayList remove_list = new ArrayList ();
999 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
1003 remove_list.Clear ();
1005 foreach (MemberCore mc in list){
1007 if (defined_names != null)
1008 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
1013 if (RootContext.WarningLevel >= 4){
1014 if ((mc.ModFlags & Modifiers.NEW) != 0)
1015 Warning_KeywordNewNotRequired (mc.Location, mc);
1017 } else if (mc is MethodCore)
1018 ((MethodCore) mc).OverridesSomething = true;
1020 if (!mc.Define (this)){
1021 remove_list.Add (mc);
1028 MemberInfo match = defined_names [idx];
1030 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
1034 // If we are both methods, let the method resolution emit warnings
1036 if (match is MethodBase && mc is MethodCore)
1039 if ((mc.ModFlags & Modifiers.NEW) == 0) {
1041 if (!(match is EventInfo)) {
1042 Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
1046 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
1050 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
1054 foreach (object o in remove_list)
1057 remove_list.Clear ();
1061 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
1062 // class is consisten. Either it is `Item' or it is the name defined by all the
1063 // indexers with the `IndexerName' attribute.
1065 // Turns out that the IndexerNameAttribute is applied to each indexer,
1066 // but it is never emitted, instead a DefaultName attribute is attached
1069 void DefineIndexers ()
1071 string class_indexer_name = null;
1074 // If there's both an explicit and an implicit interface implementation, the
1075 // explicit one actually implements the interface while the other one is just
1076 // a normal indexer. See bug #37714.
1079 ArrayList list = new ArrayList ();
1080 foreach (Indexer i in Indexers){
1081 if (i.MemberName.Left != null)
1084 foreach (Indexer i in Indexers){
1085 if (i.MemberName.Left == null)
1089 foreach (Indexer i in list){
1094 name = i.IndexerName;
1096 if (i.InterfaceType != null)
1099 if (class_indexer_name == null){
1100 class_indexer_name = name;
1104 if (name == class_indexer_name)
1108 668, "Two indexers have different names, " +
1109 " you should use the same name for all your indexers");
1111 if (class_indexer_name == null)
1112 class_indexer_name = "Item";
1113 IndexerName = class_indexer_name;
1116 static void Error_KeywordNotAllowed (Location loc)
1118 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1122 /// Populates our TypeBuilder with fields and methods
1124 public override bool DefineMembers (TypeContainer container)
1126 if (members_defined)
1127 return members_defined_ok;
1129 members_defined_ok = DoDefineMembers ();
1130 members_defined = true;
1132 return members_defined_ok;
1135 bool DoDefineMembers ()
1137 MemberInfo [] defined_names = null;
1140 // We need to be able to use the member cache while we are checking/defining
1143 if (TypeBuilder.BaseType != null)
1144 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1147 if (interface_order != null){
1148 foreach (Interface iface in interface_order)
1149 if ((iface.ModFlags & Modifiers.NEW) == 0)
1150 iface.DefineMembers (this);
1152 Error_KeywordNotAllowed (iface.Location);
1155 if (RootContext.WarningLevel > 1){
1159 // This code throws an exception in the comparer
1160 // I guess the string is not an object?
1162 ptype = TypeBuilder.BaseType;
1164 defined_names = (MemberInfo []) FindMembers (
1165 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1166 BindingFlags.Public | BindingFlags.Instance |
1167 BindingFlags.Static, null, null);
1169 Array.Sort (defined_names, mif_compare);
1173 Class pclass = Parent as Class;
1174 if (pclass != null) {
1175 string pname = null;
1177 Type t = pclass.TypeBuilder.BaseType;
1178 while ((t != null) && (ptype == null)) {
1179 pname = t.FullName + "." + Basename;
1180 ptype = RootContext.LookupType (this, pname, true, Location.Null);
1184 if ((ModFlags & Modifiers.NEW) != 0) {
1186 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1187 "inherited member. The keyword new is not required.");
1188 } else if (ptype != null) {
1189 Report.Warning (108, Location, "The keyword new is required on `" +
1190 Name + "' because it hides inherited member '" +
1193 } else if ((ModFlags & Modifiers.NEW) != 0)
1194 Error_KeywordNotAllowed (Location);
1196 if (constants != null)
1197 DefineMembers (constants, defined_names);
1200 DefineMembers (fields, defined_names);
1203 if (instance_constructors == null){
1204 if (default_constructor == null)
1205 DefineDefaultConstructor (false);
1208 if (initialized_static_fields != null &&
1209 default_static_constructor == null)
1210 DefineDefaultConstructor (true);
1213 if (this is Struct){
1215 // Structs can not have initialized instance
1218 if (initialized_static_fields != null &&
1219 default_static_constructor == null)
1220 DefineDefaultConstructor (true);
1222 if (initialized_fields != null)
1223 ReportStructInitializedInstanceError ();
1226 if (!(this is Interface))
1227 Pending = PendingImplementation.GetPendingImplementations (this);
1230 // Constructors are not in the defined_names array
1232 if (instance_constructors != null)
1233 DefineMembers (instance_constructors, null);
1235 if (default_static_constructor != null)
1236 default_static_constructor.Define (this);
1238 if (methods != null)
1239 DefineMembers (methods, defined_names);
1241 if (properties != null)
1242 DefineMembers (properties, defined_names);
1245 DefineMembers (events, defined_names);
1247 if (indexers != null) {
1250 IndexerName = "Item";
1252 if (operators != null){
1253 DefineMembers (operators, null);
1255 CheckPairedOperators ();
1259 DefineMembers (enums, defined_names);
1261 if (delegates != null)
1262 DefineMembers (delegates, defined_names);
1264 if (CurrentType != null) {
1265 GenericType = CurrentType.ResolveType (ec);
1267 ec.ContainerType = GenericType;
1272 member_cache = new MemberCache (this);
1279 public override bool Define (TypeContainer container)
1281 if (interface_order != null){
1282 foreach (Interface iface in interface_order)
1283 if ((iface.ModFlags & Modifiers.NEW) == 0)
1284 iface.Define (this);
1291 /// This function is based by a delegate to the FindMembers routine
1293 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1299 /// This filter is used by FindMembers, and we just keep
1300 /// a global for the filter to `AlwaysAccept'
1302 static MemberFilter accepting_filter;
1306 /// A member comparission method based on name only
1308 static IComparer mif_compare;
1310 static TypeContainer ()
1312 accepting_filter = new MemberFilter (AlwaysAccept);
1313 mif_compare = new MemberInfoCompare ();
1316 public MethodInfo[] GetMethods ()
1318 ArrayList members = new ArrayList ();
1320 DefineMembers (null);
1322 if (methods != null) {
1323 int len = methods.Count;
1324 for (int i = 0; i < len; i++) {
1325 Method m = (Method) methods [i];
1327 members.Add (m.MethodBuilder);
1331 if (operators != null) {
1332 int len = operators.Count;
1333 for (int i = 0; i < len; i++) {
1334 Operator o = (Operator) operators [i];
1336 members.Add (o.OperatorMethodBuilder);
1340 if (properties != null) {
1341 int len = properties.Count;
1342 for (int i = 0; i < len; i++) {
1343 Property p = (Property) properties [i];
1345 if (p.GetBuilder != null)
1346 members.Add (p.GetBuilder);
1347 if (p.SetBuilder != null)
1348 members.Add (p.SetBuilder);
1352 if (indexers != null) {
1353 int len = indexers.Count;
1354 for (int i = 0; i < len; i++) {
1355 Indexer ix = (Indexer) indexers [i];
1357 if (ix.GetBuilder != null)
1358 members.Add (ix.GetBuilder);
1359 if (ix.SetBuilder != null)
1360 members.Add (ix.SetBuilder);
1364 if (events != null) {
1365 int len = events.Count;
1366 for (int i = 0; i < len; i++) {
1367 Event e = (Event) events [i];
1369 if (e.AddBuilder != null)
1370 members.Add (e.AddBuilder);
1371 if (e.RemoveBuilder != null)
1372 members.Add (e.RemoveBuilder);
1376 MethodInfo[] methods = new MethodInfo [members.Count];
1377 members.CopyTo (methods, 0);
1382 /// This method returns the members of this type just like Type.FindMembers would
1383 /// Only, we need to use this for types which are _being_ defined because MS'
1384 /// implementation can't take care of that.
1387 // FIXME: return an empty static array instead of null, that cleans up
1388 // some code and is consistent with some coding conventions I just found
1392 // Notice that in various cases we check if our field is non-null,
1393 // something that would normally mean that there was a bug elsewhere.
1395 // The problem happens while we are defining p-invoke methods, as those
1396 // will trigger a FindMembers, but this happens before things are defined
1398 // Since the whole process is a no-op, it is fine to check for null here.
1400 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1401 MemberFilter filter, object criteria)
1403 ArrayList members = null;
1406 if ((bf & BindingFlags.Public) != 0)
1407 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1409 if ((bf & BindingFlags.NonPublic) != 0)
1410 modflags |= Modifiers.PRIVATE;
1412 int static_mask = 0, static_flags = 0;
1413 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1414 case BindingFlags.Static:
1415 static_mask = static_flags = Modifiers.STATIC;
1418 case BindingFlags.Instance:
1419 static_mask = Modifiers.STATIC;
1424 static_mask = static_flags = 0;
1428 Timer.StartTimer (TimerType.TcFindMembers);
1431 filter = accepting_filter;
1433 if ((mt & MemberTypes.Field) != 0) {
1434 if (fields != null) {
1435 int len = fields.Count;
1436 for (int i = 0; i < len; i++) {
1437 Field f = (Field) fields [i];
1439 if ((f.ModFlags & modflags) == 0)
1441 if ((f.ModFlags & static_mask) != static_flags)
1444 FieldBuilder fb = f.FieldBuilder;
1445 if (fb != null && filter (fb, criteria) == true) {
1446 if (members == null)
1447 members = new ArrayList ();
1454 if (constants != null) {
1455 int len = constants.Count;
1456 for (int i = 0; i < len; i++) {
1457 Const con = (Const) constants [i];
1459 if ((con.ModFlags & modflags) == 0)
1461 if ((con.ModFlags & static_mask) != static_flags)
1464 FieldBuilder fb = con.FieldBuilder;
1465 if (fb != null && filter (fb, criteria) == true) {
1466 if (members == null)
1467 members = new ArrayList ();
1475 if ((mt & MemberTypes.Method) != 0) {
1476 if (methods != null) {
1477 int len = methods.Count;
1478 for (int i = 0; i < len; i++) {
1479 Method m = (Method) methods [i];
1481 if ((m.ModFlags & modflags) == 0)
1483 if ((m.ModFlags & static_mask) != static_flags)
1486 MethodBuilder mb = m.MethodBuilder;
1488 if (mb != null && filter (mb, criteria) == true) {
1489 if (members == null)
1490 members = new ArrayList ();
1497 if (operators != null) {
1498 int len = operators.Count;
1499 for (int i = 0; i < len; i++) {
1500 Operator o = (Operator) operators [i];
1502 if ((o.ModFlags & modflags) == 0)
1504 if ((o.ModFlags & static_mask) != static_flags)
1507 MethodBuilder ob = o.OperatorMethodBuilder;
1508 if (ob != null && filter (ob, criteria) == true) {
1509 if (members == null)
1510 members = new ArrayList ();
1517 if (properties != null) {
1518 int len = properties.Count;
1519 for (int i = 0; i < len; i++) {
1520 Property p = (Property) properties [i];
1522 if ((p.ModFlags & modflags) == 0)
1524 if ((p.ModFlags & static_mask) != static_flags)
1530 if (b != null && filter (b, criteria) == true) {
1531 if (members == null)
1532 members = new ArrayList ();
1538 if (b != null && filter (b, criteria) == true) {
1539 if (members == null)
1540 members = new ArrayList ();
1547 if (indexers != null) {
1548 int len = indexers.Count;
1549 for (int i = 0; i < len; i++) {
1550 Indexer ix = (Indexer) indexers [i];
1552 if ((ix.ModFlags & modflags) == 0)
1554 if ((ix.ModFlags & static_mask) != static_flags)
1560 if (b != null && filter (b, criteria) == true) {
1561 if (members == null)
1562 members = new ArrayList ();
1568 if (b != null && filter (b, criteria) == true) {
1569 if (members == null)
1570 members = new ArrayList ();
1578 if ((mt & MemberTypes.Event) != 0) {
1579 if (events != null) {
1580 int len = events.Count;
1581 for (int i = 0; i < len; i++) {
1582 Event e = (Event) events [i];
1584 if ((e.ModFlags & modflags) == 0)
1586 if ((e.ModFlags & static_mask) != static_flags)
1589 MemberInfo eb = e.EventBuilder;
1590 if (eb != null && filter (eb, criteria) == true) {
1591 if (members == null)
1592 members = new ArrayList ();
1594 members.Add (e.EventBuilder);
1600 if ((mt & MemberTypes.Property) != 0){
1601 if (properties != null) {
1602 int len = properties.Count;
1603 for (int i = 0; i < len; i++) {
1604 Property p = (Property) properties [i];
1606 if ((p.ModFlags & modflags) == 0)
1608 if ((p.ModFlags & static_mask) != static_flags)
1611 MemberInfo pb = p.PropertyBuilder;
1612 if (pb != null && filter (pb, criteria) == true) {
1613 if (members == null)
1614 members = new ArrayList ();
1616 members.Add (p.PropertyBuilder);
1621 if (indexers != null) {
1622 int len = indexers.Count;
1623 for (int i = 0; i < len; i++) {
1624 Indexer ix = (Indexer) indexers [i];
1626 if ((ix.ModFlags & modflags) == 0)
1628 if ((ix.ModFlags & static_mask) != static_flags)
1631 MemberInfo ib = ix.PropertyBuilder;
1632 if (ib != null && filter (ib, criteria) == true) {
1633 if (members == null)
1634 members = new ArrayList ();
1636 members.Add (ix.PropertyBuilder);
1642 if ((mt & MemberTypes.NestedType) != 0) {
1643 if (types != null) {
1644 int len = types.Count;
1645 for (int i = 0; i < len; i++) {
1646 TypeContainer t = (TypeContainer) types [i];
1648 if ((t.ModFlags & modflags) == 0)
1651 TypeBuilder tb = t.TypeBuilder;
1652 if (tb != null && (filter (tb, criteria) == true)) {
1653 if (members == null)
1654 members = new ArrayList ();
1661 if (enums != null) {
1662 int len = enums.Count;
1663 for (int i = 0; i < len; i++) {
1664 Enum en = (Enum) enums [i];
1666 if ((en.ModFlags & modflags) == 0)
1669 TypeBuilder tb = en.TypeBuilder;
1670 if (tb != null && (filter (tb, criteria) == true)) {
1671 if (members == null)
1672 members = new ArrayList ();
1679 if (delegates != null) {
1680 int len = delegates.Count;
1681 for (int i = 0; i < len; i++) {
1682 Delegate d = (Delegate) delegates [i];
1684 if ((d.ModFlags & modflags) == 0)
1687 TypeBuilder tb = d.TypeBuilder;
1688 if (tb != null && (filter (tb, criteria) == true)) {
1689 if (members == null)
1690 members = new ArrayList ();
1697 if (interfaces != null) {
1698 int len = interfaces.Count;
1699 for (int i = 0; i < len; i++) {
1700 Interface iface = (Interface) interfaces [i];
1702 if ((iface.ModFlags & modflags) == 0)
1705 TypeBuilder tb = iface.TypeBuilder;
1706 if (tb != null && (filter (tb, criteria) == true)) {
1707 if (members == null)
1708 members = new ArrayList ();
1716 if ((mt & MemberTypes.Constructor) != 0){
1717 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1718 int len = instance_constructors.Count;
1719 for (int i = 0; i < len; i++) {
1720 Constructor c = (Constructor) instance_constructors [i];
1722 ConstructorBuilder cb = c.ConstructorBuilder;
1723 if (cb != null && filter (cb, criteria) == true) {
1724 if (members == null)
1725 members = new ArrayList ();
1732 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1733 ConstructorBuilder cb =
1734 default_static_constructor.ConstructorBuilder;
1736 if (cb != null && filter (cb, criteria) == true) {
1737 if (members == null)
1738 members = new ArrayList ();
1746 // Lookup members in parent if requested.
1748 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1749 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1750 if (list.Count > 0) {
1751 if (members == null)
1752 members = new ArrayList ();
1754 members.AddRange (list);
1758 Timer.StopTimer (TimerType.TcFindMembers);
1760 if (members == null)
1761 return MemberList.Empty;
1763 return new MemberList (members);
1766 public override MemberCache MemberCache {
1768 return member_cache;
1772 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1773 MemberFilter filter, object criteria)
1775 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1778 return ds.FindMembers (mt, bf, filter, criteria);
1780 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1784 // FindMethods will look for methods not only in the type `t', but in
1785 // any interfaces implemented by the type.
1787 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1788 MemberFilter filter, object criteria)
1794 /// Emits the values for the constants
1796 public void EmitConstants ()
1798 if (constants != null)
1799 foreach (Const con in constants)
1805 /// Emits the code, this step is performed after all
1806 /// the types, enumerations, constructors
1810 if (instance_constructors != null)
1811 foreach (Constructor c in instance_constructors)
1814 if (default_static_constructor != null)
1815 default_static_constructor.Emit (this);
1817 if (methods != null)
1818 foreach (Method m in methods)
1821 if (operators != null)
1822 foreach (Operator o in operators)
1825 if (properties != null)
1826 foreach (Property p in properties)
1829 if (indexers != null){
1830 foreach (Indexer ix in indexers)
1833 CustomAttributeBuilder cb = EmitDefaultMemberAttr ();
1834 TypeBuilder.SetCustomAttribute (cb);
1838 foreach (Field f in fields)
1841 if (events != null){
1842 foreach (Event e in Events)
1846 if (Pending != null)
1847 if (Pending.VerifyPendingMethods ())
1850 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
1853 // Check for internal or private fields that were never assigned
1855 if (RootContext.WarningLevel >= 3) {
1856 if (fields != null){
1857 foreach (Field f in fields) {
1858 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
1861 if ((f.status & Field.Status.USED) == 0){
1863 169, f.Location, "Private field " +
1864 MakeName (f.Name) + " is never used");
1869 // Only report 649 on level 4
1871 if (RootContext.WarningLevel < 4)
1874 if ((f.status & Field.Status.ASSIGNED) != 0)
1879 "Field " + MakeName (f.Name) + " is never assigned " +
1880 " to and will always have its default value");
1884 if (events != null){
1885 foreach (Event e in events){
1887 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1892 // if (types != null)
1893 // foreach (TypeContainer tc in types)
1897 CustomAttributeBuilder EmitDefaultMemberAttr ()
1899 EmitContext ec = new EmitContext (this, Location, null, null, ModFlags);
1901 Expression ml = Expression.MemberLookup (ec, TypeManager.default_member_type,
1902 ".ctor", MemberTypes.Constructor,
1903 BindingFlags.Public | BindingFlags.Instance,
1906 MethodGroupExpr mg = (MethodGroupExpr) ml;
1908 MethodBase constructor = mg.Methods [0];
1910 string [] vals = { IndexerName };
1912 CustomAttributeBuilder cb = null;
1914 cb = new CustomAttributeBuilder ((ConstructorInfo) constructor, vals);
1916 Report.Warning (-100, "Can not set the indexer default member attribute");
1922 public override void CloseType ()
1929 TypeBuilder.CreateType ();
1930 } catch (TypeLoadException){
1932 // This is fine, the code still created the type
1934 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1935 // Console.WriteLine (e.Message);
1937 Console.WriteLine ("In type: " + Name);
1942 foreach (Enum en in Enums)
1945 if (interface_order != null){
1946 foreach (Interface iface in interface_order)
1951 foreach (TypeContainer tc in Types)
1955 foreach (TypeContainer tc in Types)
1956 if (!(tc is Struct))
1960 if (Delegates != null)
1961 foreach (Delegate d in Delegates)
1969 initialized_fields = null;
1970 initialized_static_fields = null;
1973 interface_order = null;
1979 default_constructor = null;
1980 default_static_constructor = null;
1982 OptAttributes = null;
1984 parent_container = null;
1985 member_cache = null;
1988 public string MakeName (string n)
1990 return "`" + Name + "." + n + "'";
1993 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1996 108, l, "The keyword new is required on " +
1997 MakeName (mi.Name) + " because it hides `" +
1998 mi.ReflectedType.Name + "." + mi.Name + "'");
2001 public void Warning_KeywordNewNotRequired (Location l, MemberCore mc)
2004 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
2005 "inherited member, the keyword new is not required");
2008 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
2011 72, l, MakeName (mi.Name) + " : cannot override; `" +
2012 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
2015 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
2021 // Performs the validation on a Method's modifiers (properties have
2022 // the same properties).
2024 public bool MethodModifiersValid (int flags, string n, Location loc)
2026 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2027 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2028 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2032 // At most one of static, virtual or override
2034 if ((flags & Modifiers.STATIC) != 0){
2035 if ((flags & vao) != 0){
2037 112, loc, "static method " + MakeName (n) + "can not be marked " +
2038 "as virtual, abstract or override");
2043 if (this is Struct){
2044 if ((flags & va) != 0){
2045 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
2050 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2052 113, loc, MakeName (n) +
2053 " marked as override cannot be marked as new or virtual");
2058 // If the declaration includes the abstract modifier, then the
2059 // declaration does not include static, virtual or extern
2061 if ((flags & Modifiers.ABSTRACT) != 0){
2062 if ((flags & Modifiers.EXTERN) != 0){
2064 180, loc, MakeName (n) + " can not be both abstract and extern");
2068 if ((flags & Modifiers.VIRTUAL) != 0){
2070 503, loc, MakeName (n) + " can not be both abstract and virtual");
2074 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2076 513, loc, MakeName (n) +
2077 " is abstract but its container class is not");
2083 if ((flags & Modifiers.PRIVATE) != 0){
2084 if ((flags & vao) != 0){
2086 621, loc, MakeName (n) +
2087 " virtual or abstract members can not be private");
2092 if ((flags & Modifiers.SEALED) != 0){
2093 if ((flags & Modifiers.OVERRIDE) == 0){
2095 238, loc, MakeName (n) +
2096 " cannot be sealed because it is not an override");
2104 Hashtable builder_and_args;
2106 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
2108 if (builder_and_args == null)
2109 builder_and_args = new Hashtable ();
2114 /// Performs checks for an explicit interface implementation. First it
2115 /// checks whether the `interface_type' is a base inteface implementation.
2116 /// Then it checks whether `name' exists in the interface type.
2118 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
2122 if (ifaces != null){
2123 foreach (TypeExpr t in ifaces){
2124 if (t.Type == interface_type){
2132 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
2143 string IMemberContainer.Name {
2149 Type IMemberContainer.Type {
2155 IMemberContainer IMemberContainer.Parent {
2157 return parent_container;
2161 MemberCache IMemberContainer.MemberCache {
2163 return member_cache;
2167 bool IMemberContainer.IsInterface {
2169 return this is Interface;
2173 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2175 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2177 if (GenericType != null)
2178 return TypeManager.FindMembers (GenericType, mt, new_bf,
2181 return FindMembers (mt, new_bf, null, null);
2185 // Operator pair checking
2188 class OperatorEntry {
2190 public Type ret_type;
2191 public Type type1, type2;
2193 public Operator.OpType ot;
2195 public OperatorEntry (int f, Operator o)
2199 ret_type = o.OperatorMethod.GetReturnType ();
2200 Type [] pt = o.OperatorMethod.ParameterTypes;
2204 ot = o.OperatorType;
2207 public override int GetHashCode ()
2209 return ret_type.GetHashCode ();
2212 public override bool Equals (object o)
2214 OperatorEntry other = (OperatorEntry) o;
2216 if (other.ret_type != ret_type)
2218 if (other.type1 != type1)
2220 if (other.type2 != type2)
2227 // Checks that some operators come in pairs:
2233 // They are matched based on the return type and the argument types
2235 void CheckPairedOperators ()
2237 Hashtable pairs = new Hashtable (null, null);
2238 Operator true_op = null;
2239 Operator false_op = null;
2240 bool has_equality_or_inequality = false;
2242 // Register all the operators we care about.
2243 foreach (Operator op in operators){
2246 switch (op.OperatorType){
2247 case Operator.OpType.Equality:
2249 has_equality_or_inequality = true;
2251 case Operator.OpType.Inequality:
2253 has_equality_or_inequality = true;
2256 case Operator.OpType.True:
2259 case Operator.OpType.False:
2263 case Operator.OpType.GreaterThan:
2265 case Operator.OpType.LessThan:
2268 case Operator.OpType.GreaterThanOrEqual:
2270 case Operator.OpType.LessThanOrEqual:
2276 OperatorEntry oe = new OperatorEntry (reg, op);
2278 object o = pairs [oe];
2282 oe = (OperatorEntry) o;
2287 if (true_op != null){
2288 if (false_op == null)
2289 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2290 } else if (false_op != null)
2291 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2294 // Look for the mistakes.
2296 foreach (DictionaryEntry de in pairs){
2297 OperatorEntry oe = (OperatorEntry) de.Key;
2304 case Operator.OpType.Equality:
2307 case Operator.OpType.Inequality:
2310 case Operator.OpType.GreaterThan:
2313 case Operator.OpType.LessThan:
2316 case Operator.OpType.GreaterThanOrEqual:
2319 case Operator.OpType.LessThanOrEqual:
2323 Report.Error (216, oe.op.Location,
2324 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2327 if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2328 MethodSignature equals_ms = new MethodSignature (
2329 "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2330 MethodSignature hash_ms = new MethodSignature (
2331 "GetHashCode", TypeManager.int32_type, new Type [0]);
2333 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2334 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2336 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2337 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2340 bool equals_ok = false;
2341 if ((equals_ml != null) && (equals_ml.Count == 1))
2342 equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2343 bool hash_ok = false;
2344 if ((hash_ml != null) && (hash_ml.Count == 1))
2345 hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2348 Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2349 "not override Object.Equals (object o)");
2351 Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2352 "not override Object.GetHashCode ()");
2358 public class Class : TypeContainer {
2360 // Modifiers allowed in a class declaration
2362 public const int AllowedModifiers =
2365 Modifiers.PROTECTED |
2366 Modifiers.INTERNAL |
2368 Modifiers.ABSTRACT |
2372 public Class (NamespaceEntry ns, TypeContainer parent, string name, int mod,
2373 Attributes attrs, Location l)
2374 : base (ns, parent, name, attrs, l)
2378 if (parent.Parent == null)
2379 accmods = Modifiers.INTERNAL;
2381 accmods = Modifiers.PRIVATE;
2383 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2387 // FIXME: How do we deal with the user specifying a different
2390 public override TypeAttributes TypeAttr {
2392 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2397 public class Struct : TypeContainer {
2399 // Modifiers allowed in a struct declaration
2401 public const int AllowedModifiers =
2404 Modifiers.PROTECTED |
2405 Modifiers.INTERNAL |
2409 public Struct (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2410 : base (ns, parent, name, attrs, l)
2414 if (parent.Parent == null)
2415 accmods = Modifiers.INTERNAL;
2417 accmods = Modifiers.PRIVATE;
2419 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2421 this.ModFlags |= Modifiers.SEALED;
2425 // FIXME: Allow the user to specify a different set of attributes
2426 // in some cases (Sealed for example is mandatory for a class,
2427 // but what SequentialLayout can be changed
2429 public override TypeAttributes TypeAttr {
2431 return base.TypeAttr |
2432 TypeAttributes.SequentialLayout |
2433 TypeAttributes.Sealed |
2434 TypeAttributes.BeforeFieldInit;
2442 public class Interface : TypeContainer, IMemberContainer {
2444 /// Modifiers allowed in a class declaration
2446 public const int AllowedModifiers =
2449 Modifiers.PROTECTED |
2450 Modifiers.INTERNAL |
2454 public Interface (NamespaceEntry ns, TypeContainer parent, string name, int mod,
2455 Attributes attrs, Location l)
2456 : base (ns, parent, name, attrs, l)
2460 if (parent.Parent == null)
2461 accmods = Modifiers.INTERNAL;
2463 accmods = Modifiers.PRIVATE;
2465 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2468 public override TypeAttributes TypeAttr {
2470 return base.TypeAttr |
2471 TypeAttributes.AutoLayout |
2472 TypeAttributes.Abstract |
2473 TypeAttributes.Interface;
2478 public abstract class MethodCore : MemberBase {
2479 public readonly Parameters Parameters;
2480 protected Block block;
2481 protected DeclSpace ds;
2484 // Parameters, cached for semantic analysis.
2486 protected InternalParameters parameter_info;
2487 protected Type [] parameter_types;
2490 // This is set from TypeContainer.DefineMembers if this method overrides something.
2492 public bool OverridesSomething;
2494 // Whether this is an operator method.
2495 public bool IsOperator;
2497 public MethodCore (DeclSpace ds, Expression type, int mod, int allowed_mod,
2498 bool is_interface, MemberName name, Attributes attrs,
2499 Parameters parameters, Location loc)
2500 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
2502 Parameters = parameters;
2503 IsInterface = is_interface;
2508 // Returns the System.Type array for the parameters of this method
2510 public Type [] ParameterTypes {
2512 return parameter_types;
2516 public InternalParameters ParameterInfo
2519 return parameter_info;
2523 public Block Block {
2533 protected virtual bool DoDefineParameters ()
2535 // Check if arguments were correct
2536 parameter_types = Parameters.GetParameterInfo (ds);
2537 if ((parameter_types == null) || !CheckParameters (ds, parameter_types))
2540 parameter_info = new InternalParameters (ds, Parameters);
2542 Parameter array_param = Parameters.ArrayParameter;
2543 if ((array_param != null) &&
2544 (!array_param.ParameterType.IsArray ||
2545 (array_param.ParameterType.GetArrayRank () != 1))) {
2546 Report.Error (225, Location, "params parameter has to be a single dimensional array");
2553 void error_425 (Type old, Type t, string name)
2555 Report.Error (425, Location,
2556 "The constraints of type parameter `{0}' " +
2557 "of method `{1}' must match the constraints for " +
2558 "type parameter `{2}' of method `{3}'",
2559 TypeManager.CSharpName (old), Name,
2560 TypeManager.CSharpName (t), name);
2563 protected override bool CheckGenericOverride (MethodInfo method, string name)
2565 ParameterData pd = Invocation.GetParameterData (method);
2567 for (int i = 0; i < ParameterTypes.Length; i++) {
2568 GenericConstraints ogc = pd.GenericConstraints (i);
2569 GenericConstraints gc = ParameterInfo.GenericConstraints (i);
2571 if ((gc == null) && (ogc == null))
2574 Type ot = pd.ParameterType (i);
2575 Type t = ParameterTypes [i];
2577 if (!((gc != null) && (ogc != null))) {
2578 error_425 (ot, t, name);
2582 if (gc.HasConstructor != ogc.HasConstructor) {
2583 error_425 (ot, t, name);
2587 Type[] oct = ogc.Types;
2588 Type[] ct = gc.Types;
2590 if (oct.Length != ct.Length) {
2591 error_425 (ot, t, name);
2595 for (int j = 0; j < oct.Length; j++)
2596 if (!oct [j].Equals (ct [j])) {
2597 error_425 (ot, t, name);
2605 protected bool IsDuplicateImplementation (TypeContainer tc, MethodCore method)
2607 if ((method == this) || (method.Name != Name))
2610 Type[] param_types = method.ParameterTypes;
2611 if (param_types == null)
2614 if (param_types.Length != ParameterTypes.Length)
2620 Type[] infered_types = new Type [param_types.Length];
2621 may_unify = Invocation.InferTypeArguments (
2622 param_types, ParameterTypes, ref infered_types);
2625 infered_types = new Type [param_types.Length];
2626 may_unify = Invocation.InferTypeArguments (
2627 ParameterTypes, param_types, ref infered_types);
2630 for (int i = 0; i < param_types.Length; i++) {
2631 Type a = param_types [i];
2632 Type b = ParameterTypes [i];
2639 Report.Error (111, Location,
2640 "Class `{0}' already defines a member called " +
2641 "`{1}' with the same parameter types",
2644 } else if (may_unify) {
2645 Report.Error (408, Location,
2646 "`{0}' cannot define overload members that " +
2647 "may unify for some type parameter substitutions",
2655 public CallingConventions GetCallingConvention (bool is_class)
2657 CallingConventions cc = 0;
2659 cc = Parameters.GetCallingConvention ();
2662 if ((ModFlags & Modifiers.STATIC) == 0)
2663 cc |= CallingConventions.HasThis;
2665 // FIXME: How is `ExplicitThis' used in C#?
2671 // The method's attributes are passed in because we need to extract
2672 // the "return:" attribute from there to apply on the return type
2674 static public void LabelParameters (EmitContext ec,
2676 Parameters parameters,
2677 Attributes method_attrs,
2681 // Define each type attribute (in/out/ref) and
2682 // the argument names.
2684 Parameter [] p = parameters.FixedParameters;
2687 MethodBuilder mb = null;
2688 ConstructorBuilder cb = null;
2690 if (builder is MethodBuilder)
2691 mb = (MethodBuilder) builder;
2693 cb = (ConstructorBuilder) builder;
2696 for (i = 0; i < p.Length; i++) {
2697 ParameterBuilder pb;
2698 ParameterAttributes par_attr = p [i].Attributes;
2701 pb = cb.DefineParameter (
2702 i + 1, par_attr, p [i].Name);
2704 pb = mb.DefineParameter (
2705 i + 1, par_attr, p [i].Name);
2707 Attributes attr = p [i].OptAttributes;
2709 Attribute.ApplyAttributes (ec, pb, pb, attr);
2711 if (par_attr == ParameterAttributes.Out){
2712 if (attr.Contains (TypeManager.in_attribute_type))
2713 Report.Error (36, loc,
2714 "Can not use [In] attribute on out parameter");
2720 if (parameters.ArrayParameter != null){
2721 ParameterBuilder pb;
2722 Parameter array_param = parameters.ArrayParameter;
2725 pb = cb.DefineParameter (
2726 i + 1, array_param.Attributes,
2729 pb = mb.DefineParameter (
2730 i + 1, array_param.Attributes,
2733 CustomAttributeBuilder a = new CustomAttributeBuilder (
2734 TypeManager.cons_param_array_attribute, new object [0]);
2736 pb.SetCustomAttribute (a);
2740 // And now for the return type attribute decoration
2742 ParameterBuilder ret_pb;
2743 Attributes ret_attrs = null;
2745 if (mb == null || method_attrs == null)
2748 foreach (AttributeSection asec in method_attrs.AttributeSections) {
2750 if (asec.Target != "return")
2753 if (ret_attrs == null)
2754 ret_attrs = new Attributes (asec);
2756 ret_attrs.AddAttributeSection (asec);
2759 if (ret_attrs != null) {
2761 ret_pb = mb.DefineParameter (0, ParameterAttributes.None, "");
2762 Attribute.ApplyAttributes (ec, ret_pb, ret_pb, ret_attrs);
2764 } catch (ArgumentOutOfRangeException) {
2767 ".NET SDK 1.0 does not permit setting custom attributes" +
2768 " on the return type of a method");
2774 public class Method : MethodCore, IIteratorContainer {
2775 public MethodBuilder MethodBuilder;
2776 public MethodData MethodData;
2777 public readonly GenericMethod GenericMethod;
2780 /// Modifiers allowed in a class declaration
2782 const int AllowedModifiers =
2785 Modifiers.PROTECTED |
2786 Modifiers.INTERNAL |
2791 Modifiers.OVERRIDE |
2792 Modifiers.ABSTRACT |
2794 Modifiers.METHOD_YIELDS |
2797 const int AllowedInterfaceModifiers =
2801 // return_type can be "null" for VOID values.
2803 public Method (DeclSpace ds, Expression return_type, int mod, bool is_iface,
2804 MemberName name, Parameters parameters, Attributes attrs,
2806 : base (ds, return_type, mod,
2807 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
2808 is_iface, name, attrs, parameters, l)
2813 // return_type can be "null" for VOID values.
2815 public Method (GenericMethod generic, Expression return_type, int mod,
2816 bool is_iface, MemberName name, Parameters parameters,
2817 Attributes attrs, Location l)
2818 : this ((DeclSpace) generic, return_type, mod, is_iface, name,
2819 parameters, attrs, l)
2821 GenericMethod = generic;
2825 // Returns the `System.Type' for the ReturnType of this
2826 // function. Provides a nice cache. (used between semantic analysis
2827 // and actual code generation
2829 public Type GetReturnType ()
2834 void DuplicateEntryPoint (MethodInfo b, Location location)
2838 "Program `" + CodeGen.FileName +
2839 "' has more than one entry point defined: `" +
2840 TypeManager.CSharpSignature(b) + "'");
2843 void Report28 (MethodInfo b)
2847 "`" + TypeManager.CSharpSignature(b) +
2848 "' has the wrong signature to be an entry point");
2851 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2853 if (b.ReturnType != TypeManager.void_type &&
2854 b.ReturnType != TypeManager.int32_type)
2857 if (pinfo.Count == 0)
2860 if (pinfo.Count > 1)
2863 Type t = pinfo.ParameterType(0);
2865 (t.GetArrayRank() == 1) &&
2866 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
2867 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2874 // Checks our base implementation if any
2876 protected override bool CheckBase (TypeContainer container)
2878 base.CheckBase (container);
2880 // Check whether arguments were correct.
2881 if (!DoDefineParameters ())
2884 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2886 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2889 // Check in our class for dups
2891 ArrayList ar = container.Methods;
2893 int arLen = ar.Count;
2895 for (int i = 0; i < arLen; i++) {
2896 Method m = (Method) ar [i];
2897 if (IsDuplicateImplementation (container, m))
2905 // Verify if the parent has a type with the same name, and then
2906 // check whether we have to create a new slot for it or not.
2908 Type ptype = container.TypeBuilder.BaseType;
2910 // ptype is only null for System.Object while compiling corlib.
2911 if (ptype != null) {
2914 // Explicit implementations do not have `parent' methods, however,
2915 // the member cache stores them there. Without this check, we get
2916 // an incorrect warning in corlib.
2918 if (! IsExplicitImpl) {
2919 parent_method = (MethodInfo)((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
2920 container.TypeBuilder, Name, ParameterTypes, false);
2923 if (parent_method != null) {
2924 string name = parent_method.DeclaringType.Name + "." +
2927 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
2930 if ((ModFlags & Modifiers.NEW) == 0) {
2931 Type parent_ret = TypeManager.TypeToCoreType (
2932 parent_method.ReturnType);
2934 if (!parent_ret.Equals (MemberType)) {
2936 508, Location, container.MakeName (Name) + ": cannot " +
2937 "change return type when overriding " +
2938 "inherited member " + name);
2943 if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
2944 WarningNotHiding (container);
2946 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2947 Report.Error (115, Location,
2948 container.MakeName (Name) +
2949 " no suitable methods found to override");
2952 } else if ((ModFlags & Modifiers.NEW) != 0)
2953 WarningNotHiding (container);
2961 public override bool Define (TypeContainer container)
2964 MethodBuilder mb = null;
2965 if (GenericMethod != null) {
2966 mb = container.TypeBuilder.DefineGenericMethod (Name, flags);
2967 if (!GenericMethod.Define (container, mb))
2969 decl = GenericMethod;
2973 if (!DoDefine (decl, container))
2976 if (!CheckBase (container))
2979 CallingConventions cc = GetCallingConvention (container is Class);
2981 MethodData = new MethodData (ds, this, null, MemberType,
2982 ParameterTypes, ParameterInfo, cc,
2983 OptAttributes, ModFlags, flags, true,
2986 if (!MethodData.Define (container))
2990 // Setup iterator if we are one
2992 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
2993 IteratorHandler ih = new IteratorHandler (
2994 Name, container, MemberType,
2995 ParameterTypes, ParameterInfo,
2996 ModFlags, Location);
2998 Block new_block = ih.Setup (block);
2999 if (new_block == null)
3004 MethodBuilder = MethodData.MethodBuilder;
3007 // This is used to track the Entry Point,
3009 if (Name == "Main" &&
3010 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
3011 (RootContext.MainClass == null ||
3012 RootContext.MainClass == container.TypeBuilder.FullName)){
3013 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
3014 if (RootContext.EntryPoint == null) {
3015 if (container.IsGeneric){
3016 Report.Error (-201, Location,
3017 "Entry point can not be defined in a generic class");
3020 RootContext.EntryPoint = MethodBuilder;
3021 RootContext.EntryPointLocation = Location;
3023 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
3024 DuplicateEntryPoint (MethodBuilder, Location);
3027 Report28(MethodBuilder);
3036 public void Emit (TypeContainer container)
3038 MethodData.Emit (container, Block, this);
3043 void IIteratorContainer.SetYields ()
3045 ModFlags |= Modifiers.METHOD_YIELDS;
3049 public abstract class ConstructorInitializer {
3050 ArrayList argument_list;
3051 ConstructorInfo parent_constructor;
3052 Parameters parameters;
3055 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
3058 this.argument_list = argument_list;
3059 this.parameters = parameters;
3063 public ArrayList Arguments {
3065 return argument_list;
3069 public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
3071 Expression parent_constructor_group;
3074 ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
3076 if (argument_list != null){
3077 foreach (Argument a in argument_list){
3078 if (!a.Resolve (ec, loc))
3082 ec.CurrentBlock = null;
3084 if (this is ConstructorBaseInitializer) {
3085 if (ec.ContainerType.BaseType == null)
3088 t = ec.ContainerType.BaseType;
3089 if (ec.ContainerType.IsValueType) {
3090 Report.Error (522, loc,
3091 "structs cannot call base class constructors");
3095 t = ec.ContainerType;
3097 parent_constructor_group = Expression.MemberLookup (
3098 ec, t, null, t, ".ctor", 0,
3099 MemberTypes.Constructor,
3100 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3103 if (parent_constructor_group == null){
3104 Report.Error (1501, loc,
3105 "Can not find a constructor for this argument list");
3109 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (
3110 ec, (MethodGroupExpr) parent_constructor_group, argument_list,
3113 if (parent_constructor == null){
3114 Report.Error (1501, loc,
3115 "Can not find a constructor for this argument list");
3119 if (parent_constructor == caller_builder){
3120 Report.Error (515, String.Format ("Constructor `{0}' can not call itself", TypeManager.CSharpSignature (caller_builder)));
3127 public void Emit (EmitContext ec)
3129 if (parent_constructor != null){
3130 ec.Mark (loc, false);
3132 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
3134 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
3139 public class ConstructorBaseInitializer : ConstructorInitializer {
3140 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
3141 base (argument_list, pars, l)
3146 public class ConstructorThisInitializer : ConstructorInitializer {
3147 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
3148 base (argument_list, pars, l)
3153 public class Constructor : MethodCore {
3154 public ConstructorBuilder ConstructorBuilder;
3155 public ConstructorInitializer Initializer;
3158 // Modifiers allowed for a constructor.
3160 public const int AllowedModifiers =
3162 Modifiers.PROTECTED |
3163 Modifiers.INTERNAL |
3170 // The spec claims that static is not permitted, but
3171 // my very own code has static constructors.
3173 public Constructor (DeclSpace ds, string name, int mod, Parameters args,
3174 ConstructorInitializer init, Location l)
3175 : base (ds, null, mod, AllowedModifiers, false,
3176 new MemberName (name), null, args, l)
3182 // Returns true if this is a default constructor
3184 public bool IsDefault ()
3186 if ((ModFlags & Modifiers.STATIC) != 0)
3187 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3188 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
3191 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3192 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
3193 (Initializer is ConstructorBaseInitializer) &&
3194 (Initializer.Arguments == null);
3197 protected override bool CheckBase (TypeContainer container)
3199 base.CheckBase (container);
3201 // Check whether arguments were correct.
3202 if (!DoDefineParameters ())
3205 if ((ModFlags & Modifiers.STATIC) != 0)
3208 if (container is Struct && ParameterTypes.Length == 0) {
3209 Report.Error (568, Location,
3210 "Structs can not contain explicit parameterless " +
3216 // Check in our class for dups
3218 ArrayList ar = container.InstanceConstructors;
3220 int arLen = ar.Count;
3222 for (int i = 0; i < arLen; i++) {
3223 Constructor m = (Constructor) ar [i];
3224 if (IsDuplicateImplementation (container, m))
3233 // Creates the ConstructorBuilder
3235 public override bool Define (TypeContainer container)
3237 MethodAttributes ca = (MethodAttributes.RTSpecialName |
3238 MethodAttributes.SpecialName);
3240 if ((ModFlags & Modifiers.STATIC) != 0){
3241 ca |= MethodAttributes.Static | MethodAttributes.Private;
3243 ca |= MethodAttributes.HideBySig;
3245 if ((ModFlags & Modifiers.PUBLIC) != 0)
3246 ca |= MethodAttributes.Public;
3247 else if ((ModFlags & Modifiers.PROTECTED) != 0){
3248 if ((ModFlags & Modifiers.INTERNAL) != 0)
3249 ca |= MethodAttributes.FamORAssem;
3251 ca |= MethodAttributes.Family;
3252 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
3253 ca |= MethodAttributes.Assembly;
3254 else if (IsDefault ())
3255 ca |= MethodAttributes.Public;
3257 ca |= MethodAttributes.Private;
3260 // Check if arguments were correct.
3261 if (!CheckBase (container))
3264 ConstructorBuilder = container.TypeBuilder.DefineConstructor (
3265 ca, GetCallingConvention (container is Class), ParameterTypes);
3267 if ((ModFlags & Modifiers.UNSAFE) != 0)
3268 ConstructorBuilder.InitLocals = false;
3271 // HACK because System.Reflection.Emit is lame
3273 TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
3281 public void Emit (TypeContainer container)
3283 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
3284 EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
3287 // extern methods have no bodies
3289 if ((ModFlags & Modifiers.EXTERN) != 0) {
3290 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
3292 179, Location, "External constructor `" +
3293 TypeManager.CSharpSignature (ConstructorBuilder) +
3294 "' can not have a body");
3297 } else if (block == null) {
3299 501, Location, "Constructor `" +
3300 TypeManager.CSharpSignature (ConstructorBuilder) +
3301 "' must declare a body since it is not marked extern");
3305 if ((ModFlags & Modifiers.STATIC) == 0){
3306 if (container is Class && Initializer == null)
3307 Initializer = new ConstructorBaseInitializer (
3308 null, Parameters.EmptyReadOnlyParameters, Location);
3312 // Spec mandates that Initializers will not have
3316 if (Initializer != null && !Initializer.Resolve (ConstructorBuilder, ec))
3318 ec.IsStatic = false;
3321 MethodCore.LabelParameters (ec, ConstructorBuilder,
3322 Parameters, OptAttributes, Location);
3324 SymbolWriter sw = CodeGen.SymbolWriter;
3325 bool generate_debugging = false;
3327 if ((sw != null) && (block != null) &&
3328 !Location.IsNull (Location) &&
3329 !Location.IsNull (block.EndLocation) &&
3330 (Location.SymbolDocument != null)) {
3331 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
3333 generate_debugging = true;
3337 // Classes can have base initializers and instance field initializers.
3339 if (container is Class){
3340 if ((ModFlags & Modifiers.STATIC) == 0){
3343 // If we use a "this (...)" constructor initializer, then
3344 // do not emit field initializers, they are initialized in the other constructor
3346 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
3347 container.EmitFieldInitializers (ec);
3350 if (Initializer != null)
3351 Initializer.Emit (ec);
3353 if ((ModFlags & Modifiers.STATIC) != 0)
3354 container.EmitFieldInitializers (ec);
3356 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes);
3358 // If this is a non-static `struct' constructor and doesn't have any
3359 // initializer, it must initialize all of the struct's fields.
3360 if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
3361 Block.AddThisVariable (container, Location);
3363 ec.EmitTopBlock (block, ParameterInfo, Location);
3365 if (generate_debugging)
3373 // Encapsulates most of the Method's state
3375 public class MethodData {
3377 // The return type of this method
3379 public readonly Type ReturnType;
3380 public readonly Type[] ParameterTypes;
3381 public readonly GenericMethod GenericMethod;
3382 public readonly InternalParameters ParameterInfo;
3383 public readonly CallingConventions CallingConventions;
3384 public readonly Attributes OptAttributes;
3385 public readonly Location Location;
3388 // Are we implementing an interface ?
3390 public bool IsImplementing = false;
3395 protected DeclSpace ds;
3396 protected MemberBase member;
3397 protected int modifiers;
3398 protected MethodAttributes flags;
3399 protected bool is_method;
3400 protected string accessor_name;
3401 protected Type declaring_type;
3404 // It can either hold a string with the condition, or an arraylist of conditions.
3405 object conditionals;
3408 MethodBuilder builder = null;
3409 public MethodBuilder MethodBuilder {
3415 public Type DeclaringType {
3417 return declaring_type;
3421 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
3422 Type [] parameter_types, InternalParameters parameters,
3423 CallingConventions cc, Attributes opt_attrs,
3424 int modifiers, MethodAttributes flags, bool is_method)
3427 this.member = member;
3428 this.accessor_name = name;
3429 this.ReturnType = return_type;
3430 this.ParameterTypes = parameter_types;
3431 this.ParameterInfo = parameters;
3432 this.CallingConventions = cc;
3433 this.OptAttributes = opt_attrs;
3434 this.modifiers = modifiers;
3436 this.is_method = is_method;
3437 this.Location = member.Location;
3438 this.conditionals = null;
3441 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
3442 Type [] parameter_types, InternalParameters parameters,
3443 CallingConventions cc, Attributes opt_attrs,
3444 int modifiers, MethodAttributes flags, bool is_method,
3445 MethodBuilder builder, GenericMethod generic)
3446 : this (ds, member, name, return_type, parameter_types, parameters,
3447 cc, opt_attrs, modifiers, flags, is_method)
3449 this.builder = builder;
3450 this.GenericMethod = generic;
3456 Attribute dllimport_attribute = null;
3457 string obsolete = null;
3458 bool obsolete_error = false;
3460 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
3462 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
3465 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
3466 if (asec.Attributes == null)
3469 foreach (Attribute a in asec.Attributes) {
3470 if (a.Name == "Conditional") {
3471 if (!ApplyConditionalAttribute (a))
3473 } else if (a.Name == "Obsolete") {
3474 if (!ApplyObsoleteAttribute (a))
3476 } else if (a.Name.IndexOf ("DllImport") != -1) {
3478 a.Type = TypeManager.dllimport_type;
3479 Attribute.Error_AttributeNotValidForElement (a, Location);
3482 if (!ApplyDllImportAttribute (a))
3492 // Applies the `DllImport' attribute to the method.
3494 protected virtual bool ApplyDllImportAttribute (Attribute a)
3496 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3497 if ((modifiers & extern_static) != extern_static) {
3498 Report.Error (601, Location,
3499 "The DllImport attribute must be specified on a method " +
3500 "marked `static' and `extern'.");
3504 flags |= MethodAttributes.PinvokeImpl;
3505 dllimport_attribute = a;
3510 // Applies the `Obsolete' attribute to the method.
3512 protected virtual bool ApplyObsoleteAttribute (Attribute a)
3514 if (obsolete != null) {
3515 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
3519 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
3520 return obsolete != null;
3524 // Applies the `Conditional' attribute to the method.
3526 protected virtual bool ApplyConditionalAttribute (Attribute a)
3528 // The Conditional attribute is only valid on methods.
3530 Attribute.Error_AttributeNotValidForElement (a, Location);
3534 string condition = a.Conditional_GetConditionName ();
3536 if (condition == null)
3539 if (ReturnType != TypeManager.void_type) {
3540 Report.Error (578, Location,
3541 "Conditional not valid on `" + member.Name + "' " +
3542 "because its return type is not void");
3546 if ((modifiers & Modifiers.OVERRIDE) != 0) {
3547 Report.Error (243, Location,
3548 "Conditional not valid on `" + member.Name + "' " +
3549 "because it is an override method");
3553 if (member.IsExplicitImpl) {
3554 Report.Error (577, Location,
3555 "Conditional not valid on `" + member.Name + "' " +
3556 "because it is an explicit interface implementation");
3560 if (IsImplementing) {
3561 Report.Error (623, Location,
3562 "Conditional not valid on `" + member.Name + "' " +
3563 "because it is an interface method");
3568 // The likelyhood that the conditional will be more than 1 is very slim
3570 if (conditionals == null)
3571 conditionals = condition;
3572 else if (conditionals is string){
3573 string s = (string) conditionals;
3574 conditionals = new ArrayList ();
3575 ((ArrayList)conditionals).Add (s);
3577 ((ArrayList)conditionals).Add (condition);
3583 // Checks whether this method should be ignored due to its Conditional attributes.
3585 bool ShouldIgnore (Location loc)
3587 // When we're overriding a virtual method, we implicitly inherit the
3588 // Conditional attributes from our parent.
3589 if (member.ParentMethod != null) {
3590 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3591 member.ParentMethod, loc);
3593 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3597 if (conditionals != null){
3598 if (conditionals is string){
3599 if (RootContext.AllDefines [conditionals] == null)
3602 foreach (string condition in (ArrayList) conditionals)
3603 if (RootContext.AllDefines [condition] == null)
3611 // Returns the TypeManager.MethodFlags for this method.
3612 // This emits an error 619 / warning 618 if the method is obsolete.
3613 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3615 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3617 TypeManager.MethodFlags flags = 0;
3619 if (obsolete != null) {
3620 if (obsolete_error) {
3621 Report.Error (619, loc, "Method `" + member.Name +
3622 "' is obsolete: `" + obsolete + "'");
3623 return TypeManager.MethodFlags.IsObsoleteError;
3625 Report.Warning (618, loc, "Method `" + member.Name +
3626 "' is obsolete: `" + obsolete + "'");
3628 flags |= TypeManager.MethodFlags.IsObsolete;
3631 if (ShouldIgnore (loc))
3632 flags |= TypeManager.MethodFlags.ShouldIgnore;
3637 public virtual bool Define (TypeContainer container)
3639 MethodInfo implementing = null;
3640 string method_name, name, prefix;
3642 if (OptAttributes != null)
3643 if (!ApplyAttributes (OptAttributes, is_method))
3646 if (member.IsExplicitImpl)
3647 prefix = member.InterfaceType.FullName + ".";
3651 if (accessor_name != null)
3652 name = accessor_name + "_" + member.ShortName;
3654 name = member.ShortName;
3655 method_name = prefix + name;
3657 if (container.Pending != null){
3658 if (member is Indexer)
3659 implementing = container.Pending.IsInterfaceIndexer (
3660 member.InterfaceType, ReturnType, ParameterTypes);
3662 implementing = container.Pending.IsInterfaceMethod (
3663 member.InterfaceType, name, ReturnType, ParameterTypes);
3665 if (member.InterfaceType != null && implementing == null){
3666 Report.Error (539, Location, "'{0}' in explicit interface declaration is not an interface", method_name);
3672 // For implicit implementations, make sure we are public, for
3673 // explicit implementations, make sure we are private.
3675 if (implementing != null){
3677 // Setting null inside this block will trigger a more
3678 // verbose error reporting for missing interface implementations
3680 // The "candidate" function has been flagged already
3681 // but it wont get cleared
3683 if (member.IsExplicitImpl){
3684 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3685 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3686 implementing = null;
3688 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
3689 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
3691 // If this is an interface method implementation,
3692 // check for public accessibility
3694 implementing = null;
3695 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
3696 // We may never be private.
3697 implementing = null;
3698 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
3700 // We may be protected if we're overriding something.
3702 implementing = null;
3707 // Static is not allowed
3709 if ((modifiers & Modifiers.STATIC) != 0){
3710 implementing = null;
3711 Modifiers.Error_InvalidModifier (Location, "static");
3716 // If implementing is still valid, set flags
3718 if (implementing != null){
3720 // When implementing interface methods, set NewSlot
3721 // unless, we are overwriting a method.
3723 if (implementing.DeclaringType.IsInterface){
3724 if ((modifiers & Modifiers.OVERRIDE) == 0)
3725 flags |= MethodAttributes.NewSlot;
3728 MethodAttributes.Virtual |
3729 MethodAttributes.HideBySig;
3731 // Set Final unless we're virtual, abstract or already overriding a method.
3732 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
3733 flags |= MethodAttributes.Final;
3735 // Get the method name from the explicit interface.
3736 if (member.InterfaceType != null) {
3737 name = implementing.Name;
3738 method_name = prefix + name;
3741 IsImplementing = true;
3744 ec = new EmitContext (
3745 container, ds, Location, null, ReturnType, modifiers, false);
3748 // Create the MethodBuilder for the method
3750 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3751 if ((modifiers & Modifiers.STATIC) == 0) {
3752 Report.Error (601, Location,
3753 "The DllImport attribute must be specified on " +
3754 "a method marked 'static' and 'extern'.");
3757 builder = dllimport_attribute.DefinePInvokeMethod (
3758 ec, container.TypeBuilder, method_name, flags,
3759 ReturnType, ParameterTypes);
3760 } else if (builder == null)
3761 builder = container.TypeBuilder.DefineMethod (
3762 method_name, flags, CallingConventions,
3763 ReturnType, ParameterTypes);
3765 builder.SetGenericMethodSignature (
3766 flags, CallingConventions,
3767 ReturnType, ParameterTypes);
3769 if (builder == null)
3772 if (GenericMethod != null) {
3773 if (!GenericMethod.DefineType (ec, builder))
3777 if (container.CurrentType != null)
3778 declaring_type = container.CurrentType.ResolveType (ec);
3780 declaring_type = container.TypeBuilder;
3782 if ((modifiers & Modifiers.UNSAFE) != 0)
3783 builder.InitLocals = false;
3785 if (IsImplementing){
3787 // clear the pending implemntation flag
3789 if (member is Indexer) {
3790 container.Pending.ImplementIndexer (
3791 member.InterfaceType, builder, ReturnType,
3792 ParameterTypes, true);
3794 container.Pending.ImplementMethod (
3795 member.InterfaceType, name, ReturnType,
3796 ParameterTypes, member.IsExplicitImpl);
3798 if (member.IsExplicitImpl)
3799 container.TypeBuilder.DefineMethodOverride (
3800 builder, implementing);
3804 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3805 Report.Error (111, Location,
3806 "Class `" + container.Name +
3807 "' already contains a definition with the " +
3808 "same return value and parameter types as the " +
3809 "'get' method of property `" + member.Name + "'");
3813 TypeManager.AddMethod (builder, this);
3821 public virtual void Emit (TypeContainer container, Block block, object kind)
3826 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3827 ig = builder.GetILGenerator ();
3831 ec = new EmitContext (container, ds, Location, ig, ReturnType, modifiers, false);
3833 if (OptAttributes != null)
3834 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes);
3836 if (member is MethodCore)
3837 MethodCore.LabelParameters (ec, MethodBuilder,
3838 ((MethodCore) member).Parameters,
3842 SymbolWriter sw = CodeGen.SymbolWriter;
3845 // abstract or extern methods have no bodies
3847 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3848 if (block == null) {
3849 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0) &&
3850 !Location.IsNull (Location) &&
3851 (Location.SymbolDocument != null)) {
3852 sw.OpenMethod (container, MethodBuilder, Location, Location);
3860 // abstract or extern methods have no bodies.
3862 if ((modifiers & Modifiers.ABSTRACT) != 0)
3864 500, Location, "Abstract method `" +
3865 TypeManager.CSharpSignature (builder) +
3866 "' can not have a body");
3868 if ((modifiers & Modifiers.EXTERN) != 0)
3870 179, Location, "External method `" +
3871 TypeManager.CSharpSignature (builder) +
3872 "' can not have a body");
3878 // Methods must have a body unless they're extern or abstract
3880 if (block == null) {
3882 501, Location, "Method `" +
3883 TypeManager.CSharpSignature (builder) +
3884 "' must declare a body since it is not marked " +
3885 "abstract or extern");
3890 // Handle destructors specially
3892 // FIXME: This code generates buggy code
3894 if ((sw != null) && !Location.IsNull (Location) &&
3895 !Location.IsNull (block.EndLocation) &&
3896 (Location.SymbolDocument != null)) {
3897 sw.OpenMethod (container, MethodBuilder, Location, block.EndLocation);
3899 if (member is Destructor)
3900 EmitDestructor (ec, block);
3902 ec.EmitTopBlock (block, ParameterInfo, Location);
3906 if (member is Destructor)
3907 EmitDestructor (ec, block);
3909 ec.EmitTopBlock (block, ParameterInfo, Location);
3913 void EmitDestructor (EmitContext ec, Block block)
3915 ILGenerator ig = ec.ig;
3917 Label finish = ig.DefineLabel ();
3919 block.SetDestructor ();
3921 ig.BeginExceptionBlock ();
3922 ec.ReturnLabel = finish;
3923 ec.HasReturnLabel = true;
3924 ec.EmitTopBlock (block, null, Location);
3926 // ig.MarkLabel (finish);
3927 ig.BeginFinallyBlock ();
3929 if (ec.ContainerType.BaseType != null) {
3930 Expression member_lookup = Expression.MemberLookup (
3931 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3932 "Finalize", 0, MemberTypes.Method, Expression.AllBindingFlags, Location);
3934 if (member_lookup != null){
3935 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3937 ig.Emit (OpCodes.Ldarg_0);
3938 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3942 ig.EndExceptionBlock ();
3943 //ig.MarkLabel (ec.ReturnLabel);
3944 ig.Emit (OpCodes.Ret);
3948 public class Destructor : Method {
3950 public Destructor (DeclSpace ds, Expression return_type, int mod, string name,
3951 Parameters parameters, Attributes attrs, Location l)
3952 : base (ds, return_type, mod, false, new MemberName (name),
3953 parameters, attrs, l)
3958 abstract public class MemberBase : MemberCore {
3959 public Expression Type;
3961 protected MethodAttributes flags;
3963 protected readonly int explicit_mod_flags;
3965 public readonly MemberName MemberName;
3968 // The "short" name of this property / indexer / event. This is the
3969 // name without the explicit interface.
3971 public string ShortName;
3974 // The type of this property / indexer / event
3976 public Type MemberType;
3979 // If true, this is an explicit interface implementation
3981 public bool IsExplicitImpl = false;
3984 // The name of the interface we are explicitly implementing
3986 public Expression ExplicitInterfaceName = null;
3989 // Whether this is an interface member.
3991 public bool IsInterface;
3994 // If true, the interface type we are explicitly implementing
3996 public Type InterfaceType = null;
3999 // The method we're overriding if this is an override method.
4001 protected MethodInfo parent_method = null;
4002 public MethodInfo ParentMethod {
4004 return parent_method;
4009 // The constructor is only exposed to our children
4011 protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod,
4012 MemberName name, Attributes attrs, Location loc)
4013 : base (name.GetMemberName (), attrs, loc)
4015 explicit_mod_flags = mod;
4018 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
4021 protected virtual bool CheckBase (TypeContainer container)
4023 if ((container is Struct) || (RootContext.WarningLevel > 3)){
4024 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
4025 if (container is Struct){
4026 Report.Error (666, Location, "Protected member in struct declaration");
4029 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
4035 protected void WarningNotHiding (TypeContainer parent)
4039 "The member " + parent.MakeName (Name) + " does not hide an " +
4040 "inherited member. The keyword new is not required");
4044 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
4048 // FIXME: report the old/new permissions?
4051 507, Location, parent.MakeName (Name) +
4052 ": can't change the access modifiers when overriding inherited " +
4053 "member `" + name + "'");
4056 protected abstract bool CheckGenericOverride (MethodInfo method, string name);
4059 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
4060 // that have been defined.
4062 // `name' is the user visible name for reporting errors (this is used to
4063 // provide the right name regarding method names and properties)
4065 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
4066 MethodInfo mb, string name)
4070 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4071 if (!(mb.IsAbstract || mb.IsVirtual)){
4073 506, Location, parent.MakeName (Name) +
4074 ": cannot override inherited member `" +
4075 name + "' because it is not " +
4076 "virtual, abstract or override");
4080 // Now we check that the overriden method is not final
4083 // This happens when implementing interface methods.
4084 if (mb.IsHideBySig && mb.IsVirtual) {
4086 506, Location, parent.MakeName (Name) +
4087 ": cannot override inherited member `" +
4088 name + "' because it is not " +
4089 "virtual, abstract or override");
4091 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
4092 "override inherited member `" + name +
4093 "' because it is sealed.");
4098 // Check that the constraints match when overriding a
4102 if (!CheckGenericOverride (mb, name))
4106 // Check that the permissions are not being changed
4108 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
4109 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
4112 // special case for "protected internal"
4115 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4117 // when overriding protected internal, the method can be declared
4118 // protected internal only within the same assembly
4121 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4122 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
4124 // assemblies differ - report an error
4127 Error_CannotChangeAccessModifiers (parent, mb, name);
4129 } else if (thisp != parentp) {
4131 // same assembly, but other attributes differ - report an error
4134 Error_CannotChangeAccessModifiers (parent, mb, name);
4137 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
4139 // if it's not "protected internal", it must be "protected"
4142 Error_CannotChangeAccessModifiers (parent, mb, name);
4144 } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
4146 // protected within the same assembly - an error
4148 Error_CannotChangeAccessModifiers (parent, mb, name);
4150 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
4151 (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
4153 // protected ok, but other attributes differ - report an error
4155 Error_CannotChangeAccessModifiers (parent, mb, name);
4159 if (thisp != parentp){
4160 Error_CannotChangeAccessModifiers (parent, mb, name);
4166 if (mb.IsVirtual || mb.IsAbstract){
4167 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4168 if (Name != "Finalize"){
4170 114, 2, Location, parent.MakeName (Name) +
4171 " hides inherited member `" + name +
4172 "'. To make the current member override that " +
4173 "implementation, add the override keyword, " +
4174 "otherwise use the new keyword");
4175 ModFlags |= Modifiers.NEW;
4179 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4180 if (Name != "Finalize"){
4182 108, 1, Location, "The keyword new is required on " +
4183 parent.MakeName (Name) + " because it hides " +
4184 "inherited member `" + name + "'");
4185 ModFlags |= Modifiers.NEW;
4193 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
4197 foreach (Type partype in parameters){
4198 if (partype.IsPointer){
4201 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
4205 if (ds.AsAccessible (partype, ModFlags))
4208 if (this is Indexer)
4209 Report.Error (55, Location,
4210 "Inconsistent accessibility: parameter type `" +
4211 TypeManager.CSharpName (partype) + "' is less " +
4212 "accessible than indexer `" + Name + "'");
4213 else if ((this is Method) && ((Method) this).IsOperator)
4214 Report.Error (57, Location,
4215 "Inconsistent accessibility: parameter type `" +
4216 TypeManager.CSharpName (partype) + "' is less " +
4217 "accessible than operator `" + Name + "'");
4219 Report.Error (51, Location,
4220 "Inconsistent accessibility: parameter type `" +
4221 TypeManager.CSharpName (partype) + "' is less " +
4222 "accessible than method `" + Name + "'");
4229 protected virtual bool DoDefine (DeclSpace decl, TypeContainer container)
4235 ModFlags = Modifiers.PUBLIC |
4236 Modifiers.ABSTRACT |
4239 flags = MethodAttributes.Public |
4240 MethodAttributes.Abstract |
4241 MethodAttributes.HideBySig |
4242 MethodAttributes.NewSlot |
4243 MethodAttributes.Virtual;
4245 if (!container.MethodModifiersValid (ModFlags, Name, Location))
4248 flags = Modifiers.MethodAttr (ModFlags);
4251 // Lookup Type, verify validity
4252 MemberType = decl.ResolveType (Type, false, Location);
4253 if (MemberType == null)
4256 if ((container.ModFlags & Modifiers.SEALED) != 0){
4257 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
4258 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
4263 // verify accessibility
4264 if (!container.AsAccessible (MemberType, ModFlags)) {
4265 if (this is Property)
4266 Report.Error (53, Location,
4267 "Inconsistent accessibility: property type `" +
4268 TypeManager.CSharpName (MemberType) + "' is less " +
4269 "accessible than property `" + Name + "'");
4270 else if (this is Indexer)
4271 Report.Error (54, Location,
4272 "Inconsistent accessibility: indexer return type `" +
4273 TypeManager.CSharpName (MemberType) + "' is less " +
4274 "accessible than indexer `" + Name + "'");
4275 else if (this is Method) {
4276 if (((Method) this).IsOperator)
4277 Report.Error (56, Location,
4278 "Inconsistent accessibility: return type `" +
4279 TypeManager.CSharpName (MemberType) + "' is less " +
4280 "accessible than operator `" + Name + "'");
4282 Report.Error (50, Location,
4283 "Inconsistent accessibility: return type `" +
4284 TypeManager.CSharpName (MemberType) + "' is less " +
4285 "accessible than method `" + Name + "'");
4287 Report.Error (52, Location,
4288 "Inconsistent accessibility: field type `" +
4289 TypeManager.CSharpName (MemberType) + "' is less " +
4290 "accessible than field `" + Name + "'");
4294 if (MemberType.IsPointer && !UnsafeOK (container))
4298 // Check for explicit interface implementation
4300 if (MemberName.Left != null) {
4301 ExplicitInterfaceName = MemberName.Left.GetTypeExpression (Location);
4302 ShortName = MemberName.Name;
4306 if (ExplicitInterfaceName != null) {
4307 InterfaceType = container.ResolveType (
4308 ExplicitInterfaceName, false, Location);
4309 if (InterfaceType == null)
4312 if (InterfaceType.IsClass) {
4313 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
4317 // Compute the full name that we need to export.
4318 Name = InterfaceType.FullName + "." + ShortName;
4320 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
4323 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
4325 IsExplicitImpl = true;
4327 IsExplicitImpl = false;
4334 // Fields and Events both generate FieldBuilders, we use this to share
4335 // their common bits. This is also used to flag usage of the field
4337 abstract public class FieldBase : MemberBase {
4338 public FieldBuilder FieldBuilder;
4339 public Status status;
4342 public enum Status : byte { ASSIGNED = 1, USED = 2 }
4345 // The constructor is only exposed to our children
4347 protected FieldBase (Expression type, int mod, int allowed_mod, MemberName name,
4348 object init, Attributes attrs, Location loc)
4349 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
4355 // Whether this field has an initializer.
4357 public bool HasInitializer {
4359 return init != null;
4363 protected readonly Object init;
4365 Expression init_expr;
4366 bool init_expr_initialized = false;
4368 protected override bool CheckGenericOverride (MethodInfo method, string name)
4374 // Resolves and returns the field initializer.
4376 public Expression GetInitializerExpression (EmitContext ec)
4378 if (init_expr_initialized)
4382 if (init is Expression)
4383 e = (Expression) init;
4385 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
4387 ec.IsFieldInitializer = true;
4388 e = e.DoResolve (ec);
4389 ec.IsFieldInitializer = false;
4392 init_expr_initialized = true;
4397 public void SetAssigned ()
4399 status |= Status.ASSIGNED;
4404 // The Field class is used to represents class/struct fields during parsing.
4406 public class Field : FieldBase {
4408 // Modifiers allowed in a class declaration
4410 const int AllowedModifiers =
4413 Modifiers.PROTECTED |
4414 Modifiers.INTERNAL |
4417 Modifiers.VOLATILE |
4421 public Field (Expression type, int mod, string name, Object expr_or_array_init,
4422 Attributes attrs, Location loc)
4423 : base (type, mod, AllowedModifiers, new MemberName (name),
4424 expr_or_array_init, attrs, loc)
4428 public override bool Define (TypeContainer container)
4430 Type t = container.ResolveType (Type, false, Location);
4435 CheckBase (container);
4437 if (!container.AsAccessible (t, ModFlags)) {
4438 Report.Error (52, Location,
4439 "Inconsistent accessibility: field type `" +
4440 TypeManager.CSharpName (t) + "' is less " +
4441 "accessible than field `" + Name + "'");
4445 if (t.IsPointer && !UnsafeOK (container))
4448 if (RootContext.WarningLevel > 1){
4449 Type ptype = container.TypeBuilder.BaseType;
4451 // ptype is only null for System.Object while compiling corlib.
4453 TypeContainer.FindMembers (
4454 ptype, MemberTypes.Method,
4455 BindingFlags.Public |
4456 BindingFlags.Static | BindingFlags.Instance,
4457 System.Type.FilterName, Name);
4461 if ((ModFlags & Modifiers.VOLATILE) != 0){
4465 if (TypeManager.IsEnumType (vt))
4466 vt = TypeManager.EnumToUnderlying (t);
4468 if (!((vt == TypeManager.bool_type) ||
4469 (vt == TypeManager.sbyte_type) ||
4470 (vt == TypeManager.byte_type) ||
4471 (vt == TypeManager.short_type) ||
4472 (vt == TypeManager.ushort_type) ||
4473 (vt == TypeManager.int32_type) ||
4474 (vt == TypeManager.uint32_type) ||
4475 (vt == TypeManager.char_type) ||
4476 (vt == TypeManager.float_type))){
4478 677, Location, container.MakeName (Name) +
4479 " A volatile field can not be of type `" +
4480 TypeManager.CSharpName (vt) + "'");
4485 if ((ModFlags & Modifiers.READONLY) != 0){
4488 "A field can not be both volatile and readonly");
4493 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
4495 if (container is Struct &&
4496 ((fa & FieldAttributes.Static) == 0) &&
4497 t == container.TypeBuilder &&
4498 !TypeManager.IsBuiltinType (t)){
4499 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name +
4500 "' causes a cycle in the structure layout");
4505 FieldBuilder = container.TypeBuilder.DefineField (
4506 Name, t, Modifiers.FieldAttr (ModFlags));
4508 TypeManager.RegisterFieldBase (FieldBuilder, this);
4510 catch (ArgumentException) {
4511 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
4518 public void Emit (TypeContainer tc)
4520 EmitContext ec = new EmitContext (tc, Location, null,
4521 FieldBuilder.FieldType, ModFlags);
4523 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes);
4528 // `set' and `get' accessors are represented with an Accessor.
4530 public class Accessor {
4532 // Null if the accessor is empty, or a Block if not
4535 public Attributes OptAttributes;
4537 public Accessor (Block b, Attributes attrs)
4540 OptAttributes = attrs;
4545 // Properties and Indexers both generate PropertyBuilders, we use this to share
4546 // their common bits.
4548 abstract public class PropertyBase : MethodCore {
4549 public Accessor Get, Set;
4550 public PropertyBuilder PropertyBuilder;
4551 public MethodBuilder GetBuilder, SetBuilder;
4552 public MethodData GetData, SetData;
4554 protected EmitContext ec;
4556 public PropertyBase (DeclSpace ds, Expression type, int mod_flags,
4557 int allowed_mod, bool is_iface, MemberName name,
4558 Parameters parameters, Attributes attrs,
4559 Accessor get_block, Accessor set_block,
4561 : base (ds, type, mod_flags, allowed_mod, is_iface, name,
4562 attrs, parameters, loc)
4568 protected override bool DoDefine (DeclSpace decl, TypeContainer container)
4570 if (!base.DoDefine (decl, container))
4573 ec = new EmitContext (container, Location, null, MemberType, ModFlags);
4579 // Checks our base implementation if any
4581 protected override bool CheckBase (TypeContainer container)
4583 base.CheckBase (container);
4585 // Check whether arguments were correct.
4586 if (!DoDefineParameters ())
4593 // Check in our class for dups
4595 ArrayList ar = container.Properties;
4597 int arLen = ar.Count;
4599 for (int i = 0; i < arLen; i++) {
4600 Property m = (Property) ar [i];
4601 if (IsDuplicateImplementation (container, m))
4610 MethodSignature ms, base_ms;
4611 if (this is Indexer) {
4612 string name, base_name;
4614 report_name = "this";
4615 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
4616 ms = new MethodSignature (name, null, ParameterTypes);
4617 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
4618 base_ms = new MethodSignature (base_name, null, ParameterTypes);
4621 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
4625 // Verify if the parent has a type with the same name, and then
4626 // check whether we have to create a new slot for it or not.
4628 Type ptype = container.TypeBuilder.BaseType;
4630 // ptype is only null for System.Object while compiling corlib.
4631 if (ptype == null) {
4632 if ((ModFlags & Modifiers.NEW) != 0)
4633 WarningNotHiding (container);
4638 PropertyInfo parent_property = null;
4641 // Explicit implementations do not have `parent' methods, however,
4642 // the member cache stores them there. Without this check, we get
4643 // an incorrect warning in corlib.
4645 if (! IsExplicitImpl) {
4646 parent_property = (PropertyInfo) ((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
4647 container.TypeBuilder, Name, ParameterTypes, true);
4650 if (parent_property != null) {
4651 string name = parent_property.DeclaringType.Name + "." +
4652 parent_property.Name;
4654 MethodInfo get, set, parent_method;
4655 get = parent_property.GetGetMethod (true);
4656 set = parent_property.GetSetMethod (true);
4659 parent_method = get;
4660 else if (set != null)
4661 parent_method = set;
4663 throw new Exception ("Internal error!");
4665 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
4668 if ((ModFlags & Modifiers.NEW) == 0) {
4669 Type parent_type = TypeManager.TypeToCoreType (
4670 parent_property.PropertyType);
4672 if (parent_type != MemberType) {
4674 508, Location, container.MakeName (Name) + ": cannot " +
4675 "change return type when overriding " +
4676 "inherited member " + name);
4681 if ((ModFlags & Modifiers.NEW) != 0)
4682 WarningNotHiding (container);
4684 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4685 if (this is Indexer)
4686 Report.Error (115, Location,
4687 container.MakeName (Name) +
4688 " no suitable indexers found to override");
4690 Report.Error (115, Location,
4691 container.MakeName (Name) +
4692 " no suitable properties found to override");
4699 public void Emit (TypeContainer tc)
4702 // The PropertyBuilder can be null for explicit implementations, in that
4703 // case, we do not actually emit the ".property", so there is nowhere to
4704 // put the attribute
4706 if (PropertyBuilder != null)
4707 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes);
4709 if (GetData != null) {
4710 GetData.Emit (tc, Get.Block, Get);
4714 if (SetData != null) {
4715 SetData.Emit (tc, Set.Block, Set);
4721 public class Property : PropertyBase, IIteratorContainer {
4722 const int AllowedModifiers =
4725 Modifiers.PROTECTED |
4726 Modifiers.INTERNAL |
4730 Modifiers.OVERRIDE |
4731 Modifiers.ABSTRACT |
4734 Modifiers.METHOD_YIELDS |
4737 const int AllowedInterfaceModifiers =
4740 public Property (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
4741 MemberName name, Attributes attrs, Accessor get_block,
4742 Accessor set_block, Location loc)
4743 : base (ds, type, mod_flags,
4744 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
4745 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
4746 get_block, set_block, loc)
4750 public override bool Define (TypeContainer container)
4752 if (!DoDefine (container, container))
4755 if (!CheckBase (container))
4758 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4761 Type [] parameters = TypeManager.NoTypes;
4763 InternalParameters ip = new InternalParameters (
4764 container, Parameters.EmptyReadOnlyParameters);
4766 GetData = new MethodData (container, this, "get", MemberType,
4767 parameters, ip, CallingConventions.Standard,
4768 Get.OptAttributes, ModFlags, flags, false);
4771 // Setup iterator if we are one
4773 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
4774 IteratorHandler ih = new IteratorHandler (
4775 "get", container, MemberType,
4776 parameters, ip, ModFlags, Location);
4778 Block new_block = ih.Setup (block);
4779 if (new_block == null)
4784 if (!GetData.Define (container))
4787 GetBuilder = GetData.MethodBuilder;
4791 Type [] parameters = new Type [1];
4792 parameters [0] = MemberType;
4794 Parameter [] parms = new Parameter [1];
4795 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4796 InternalParameters ip = new InternalParameters (
4797 container, new Parameters (parms, null, Location));
4799 SetData = new MethodData (container, this, "set", TypeManager.void_type,
4800 parameters, ip, CallingConventions.Standard,
4801 Set.OptAttributes, ModFlags, flags, false);
4803 if (!SetData.Define (container))
4806 SetBuilder = SetData.MethodBuilder;
4807 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4810 // FIXME - PropertyAttributes.HasDefault ?
4812 PropertyAttributes prop_attr = PropertyAttributes.None;
4814 prop_attr |= PropertyAttributes.RTSpecialName |
4815 PropertyAttributes.SpecialName;
4817 if (!IsExplicitImpl){
4818 PropertyBuilder = container.TypeBuilder.DefineProperty (
4819 Name, prop_attr, MemberType, null);
4822 PropertyBuilder.SetGetMethod (GetBuilder);
4825 PropertyBuilder.SetSetMethod (SetBuilder);
4828 // HACK for the reasons exposed above
4830 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4833 "Class `" + container.Name +
4834 "' already contains a definition for the property `" +
4842 public void SetYields ()
4844 ModFlags |= Modifiers.METHOD_YIELDS;
4849 /// Gigantic workaround for lameness in SRE follows :
4850 /// This class derives from EventInfo and attempts to basically
4851 /// wrap around the EventBuilder so that FindMembers can quickly
4852 /// return this in it search for members
4854 public class MyEventBuilder : EventInfo {
4857 // We use this to "point" to our Builder which is
4858 // not really a MemberInfo
4860 EventBuilder MyBuilder;
4863 // We "catch" and wrap these methods
4865 MethodInfo raise, remove, add;
4867 EventAttributes attributes;
4868 Type declaring_type, reflected_type, event_type;
4873 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4875 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4877 // And now store the values in our own fields.
4879 declaring_type = type_builder;
4881 reflected_type = type_builder;
4883 attributes = event_attr;
4886 this.event_type = event_type;
4890 // Methods that you have to override. Note that you only need
4891 // to "implement" the variants that take the argument (those are
4892 // the "abstract" methods, the others (GetAddMethod()) are
4895 public override MethodInfo GetAddMethod (bool nonPublic)
4900 public override MethodInfo GetRemoveMethod (bool nonPublic)
4905 public override MethodInfo GetRaiseMethod (bool nonPublic)
4911 // These methods make "MyEventInfo" look like a Builder
4913 public void SetRaiseMethod (MethodBuilder raiseMethod)
4915 raise = raiseMethod;
4916 MyBuilder.SetRaiseMethod (raiseMethod);
4919 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4921 remove = removeMethod;
4922 MyBuilder.SetRemoveOnMethod (removeMethod);
4925 public void SetAddOnMethod (MethodBuilder addMethod)
4928 MyBuilder.SetAddOnMethod (addMethod);
4931 public void SetCustomAttribute (CustomAttributeBuilder cb)
4933 MyBuilder.SetCustomAttribute (cb);
4936 public override object [] GetCustomAttributes (bool inherit)
4938 // FIXME : There's nothing which can be seemingly done here because
4939 // we have no way of getting at the custom attribute objects of the
4944 public override object [] GetCustomAttributes (Type t, bool inherit)
4946 // FIXME : Same here !
4950 public override bool IsDefined (Type t, bool b)
4955 public override EventAttributes Attributes {
4961 public override string Name {
4967 public override Type DeclaringType {
4969 return declaring_type;
4973 public override Type ReflectedType {
4975 return reflected_type;
4979 public Type EventType {
4985 public void SetUsed ()
4987 if (my_event != null)
4988 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
4992 public class Event : FieldBase {
4993 const int AllowedModifiers =
4996 Modifiers.PROTECTED |
4997 Modifiers.INTERNAL |
5002 Modifiers.OVERRIDE |
5006 const int AllowedInterfaceModifiers =
5009 public readonly Accessor Add;
5010 public readonly Accessor Remove;
5011 public MyEventBuilder EventBuilder;
5013 public MethodBuilder AddBuilder, RemoveBuilder;
5014 MethodData AddData, RemoveData;
5016 public Event (Expression type, int mod_flags, bool is_iface, MemberName name,
5017 Object init, Attributes attrs, Accessor add, Accessor remove,
5019 : base (type, mod_flags,
5020 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5021 name, init, attrs, loc)
5025 IsInterface = is_iface;
5028 public override bool Define (TypeContainer container)
5030 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
5031 MethodAttributes m_attr = MethodAttributes.HideBySig | MethodAttributes.SpecialName
5033 if (!DoDefine (container, container))
5036 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
5037 Report.Error (74, Location, "'" + container.Name + "." + Name +
5038 "': abstract event can not have an initializer");
5042 if (!TypeManager.IsDelegateType (MemberType)) {
5043 Report.Error (66, Location, "'" + container.Name + "." + Name +
5044 "' : event must be of a delegate type");
5048 Type [] parameter_types = new Type [1];
5049 parameter_types [0] = MemberType;
5051 Parameter [] parms = new Parameter [1];
5052 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
5053 InternalParameters ip = new InternalParameters (
5054 container, new Parameters (parms, null, Location));
5056 if (!CheckBase (container))
5060 // Now define the accessors
5062 AddData = new MethodData (container, this, "add", TypeManager.void_type,
5063 parameter_types, ip, CallingConventions.Standard,
5064 (Add != null) ? Add.OptAttributes : null,
5065 ModFlags, flags | m_attr, false);
5067 if (!AddData.Define (container))
5070 AddBuilder = AddData.MethodBuilder;
5071 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
5073 RemoveData = new MethodData (container, this, "remove", TypeManager.void_type,
5074 parameter_types, ip, CallingConventions.Standard,
5075 (Remove != null) ? Remove.OptAttributes : null,
5076 ModFlags, flags | m_attr, false);
5078 if (!RemoveData.Define (container))
5081 RemoveBuilder = RemoveData.MethodBuilder;
5082 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
5084 if (!IsExplicitImpl){
5085 EventBuilder = new MyEventBuilder (this,
5086 container.TypeBuilder, Name, e_attr, MemberType);
5088 if (Add == null && Remove == null) {
5089 FieldBuilder = container.TypeBuilder.DefineField (
5091 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
5092 TypeManager.RegisterPrivateFieldOfEvent (
5093 (EventInfo) EventBuilder, FieldBuilder);
5094 TypeManager.RegisterFieldBase (FieldBuilder, this);
5097 EventBuilder.SetAddOnMethod (AddBuilder);
5098 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
5100 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
5101 Report.Error (111, Location,
5102 "Class `" + container.Name +
5103 "' already contains a definition for the event `" +
5112 void EmitDefaultMethod (EmitContext ec, bool is_add)
5114 ILGenerator ig = ec.ig;
5115 MethodInfo method = null;
5118 method = TypeManager.delegate_combine_delegate_delegate;
5120 method = TypeManager.delegate_remove_delegate_delegate;
5122 if ((ModFlags & Modifiers.STATIC) != 0) {
5123 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
5124 ig.Emit (OpCodes.Ldarg_0);
5125 ig.Emit (OpCodes.Call, method);
5126 ig.Emit (OpCodes.Castclass, MemberType);
5127 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
5129 ig.Emit (OpCodes.Ldarg_0);
5130 ig.Emit (OpCodes.Ldarg_0);
5131 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
5132 ig.Emit (OpCodes.Ldarg_1);
5133 ig.Emit (OpCodes.Call, method);
5134 ig.Emit (OpCodes.Castclass, MemberType);
5135 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
5137 ig.Emit (OpCodes.Ret);
5140 public void Emit (TypeContainer tc)
5144 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
5145 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes);
5148 AddData.Emit (tc, Add.Block, Add);
5151 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
5152 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
5153 EmitDefaultMethod (ec, true);
5156 if (Remove != null) {
5157 RemoveData.Emit (tc, Remove.Block, Remove);
5158 Remove.Block = null;
5160 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
5161 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
5162 EmitDefaultMethod (ec, false);
5169 // FIXME: This does not handle:
5171 // int INTERFACENAME [ args ]
5176 // int this [ args ]
5178 public class Indexer : PropertyBase {
5180 const int AllowedModifiers =
5183 Modifiers.PROTECTED |
5184 Modifiers.INTERNAL |
5188 Modifiers.OVERRIDE |
5193 const int AllowedInterfaceModifiers =
5196 public string IndexerName;
5197 public string InterfaceIndexerName;
5200 // Are we implementing an interface ?
5202 public Indexer (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
5203 MemberName name, Parameters parameters, Attributes attrs,
5204 Accessor get_block, Accessor set_block, Location loc)
5205 : base (ds, type, mod_flags,
5206 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5207 is_iface, name, parameters, attrs, get_block, set_block, loc)
5211 public override bool Define (TypeContainer container)
5213 PropertyAttributes prop_attr =
5214 PropertyAttributes.RTSpecialName |
5215 PropertyAttributes.SpecialName;
5217 if (!DoDefine (container, container))
5220 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
5221 if (IndexerName == null)
5222 IndexerName = "Item";
5223 else if (IsExplicitImpl)
5224 Report.Error (592, Location,
5225 "Attribute 'IndexerName' is not valid on this declaration " +
5226 "type. It is valid on `property' declarations only.");
5228 ShortName = IndexerName;
5229 if (IsExplicitImpl) {
5230 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
5231 Name = InterfaceType.FullName + "." + IndexerName;
5233 InterfaceIndexerName = IndexerName;
5237 if (!CheckNameCollision (container))
5240 if (!CheckBase (container))
5243 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
5245 InternalParameters ip = new InternalParameters (container, Parameters);
5247 GetData = new MethodData (container, this, "get", MemberType,
5248 ParameterTypes, ip, CallingConventions.Standard,
5249 Get.OptAttributes, ModFlags, flags, false);
5251 if (!GetData.Define (container))
5254 GetBuilder = GetData.MethodBuilder;
5258 int top = ParameterTypes.Length;
5259 Type [] set_pars = new Type [top + 1];
5260 ParameterTypes.CopyTo (set_pars, 0);
5261 set_pars [top] = MemberType;
5263 Parameter [] fixed_parms = Parameters.FixedParameters;
5265 if (fixed_parms == null){
5266 throw new Exception ("We currently do not support only array arguments in an indexer at: " + Location);
5267 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5268 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5270 // Here is the problem: the `value' parameter has
5271 // to come *after* the array parameter in the declaration
5273 // X (object [] x, Type value)
5276 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5277 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5281 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
5284 fixed_parms.CopyTo (tmp, 0);
5285 tmp [fixed_parms.Length] = new Parameter (
5286 Type, "value", Parameter.Modifier.NONE, null);
5288 Parameters set_formal_params = new Parameters (tmp, null, Location);
5290 InternalParameters ip = new InternalParameters (container, set_formal_params);
5292 SetData = new MethodData (container, this, "set", TypeManager.void_type,
5293 set_pars, ip, CallingConventions.Standard,
5294 Set.OptAttributes, ModFlags, flags, false);
5296 if (!SetData.Define (container))
5299 SetBuilder = SetData.MethodBuilder;
5303 // Now name the parameters
5305 Parameter [] p = Parameters.FixedParameters;
5309 for (i = 0; i < p.Length; ++i) {
5311 GetBuilder.DefineParameter (
5312 i + 1, p [i].Attributes, p [i].Name);
5315 SetBuilder.DefineParameter (
5316 i + 1, p [i].Attributes, p [i].Name);
5320 SetBuilder.DefineParameter (
5321 i + 1, ParameterAttributes.None, "value");
5323 if (i != ParameterTypes.Length) {
5324 Parameter array_param = Parameters.ArrayParameter;
5326 SetBuilder.DefineParameter (
5327 i + 1, array_param.Attributes, array_param.Name);
5332 // Define the PropertyBuilder if one of the following conditions are met:
5333 // a) we're not implementing an interface indexer.
5334 // b) the indexer has a different IndexerName and this is no
5335 // explicit interface implementation.
5337 if (!IsExplicitImpl) {
5338 PropertyBuilder = container.TypeBuilder.DefineProperty (
5339 IndexerName, prop_attr, MemberType, ParameterTypes);
5341 if (GetData != null)
5342 PropertyBuilder.SetGetMethod (GetBuilder);
5344 if (SetData != null)
5345 PropertyBuilder.SetSetMethod (SetBuilder);
5347 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
5354 bool CheckNameCollision (TypeContainer container) {
5355 switch (VerifyName (container)){
5356 case DeclSpace.AdditionResult.NameExists:
5357 Report.Error (102, Location, "The container '{0}' already contains a definition for '{1}'", container.GetSignatureForError (), Name);
5360 case DeclSpace.AdditionResult.Success:
5363 throw new NotImplementedException ();
5366 DeclSpace.AdditionResult VerifyName (TypeContainer container) {
5367 if (!AddIndexer (container, container.Name + "." + Name))
5368 return DeclSpace.AdditionResult.NameExists;
5371 if (!AddIndexer (container, container.Name + ".get_" + Name))
5372 return DeclSpace.AdditionResult.NameExists;
5376 if (!AddIndexer (container, container.Name + ".set_" + Name))
5377 return DeclSpace.AdditionResult.NameExists;
5379 return DeclSpace.AdditionResult.Success;
5382 bool AddIndexer (TypeContainer container, string fullname)
5384 object value = container.GetDefinition (fullname);
5386 if (value != null) {
5387 return value.GetType () != GetType () ? false : true;
5390 container.DefineName (fullname, this);
5394 public override string GetSignatureForError () {
5395 return TypeManager.CSharpSignature (PropertyBuilder, true);
5399 public class Operator : MemberBase, IIteratorContainer {
5401 const int AllowedModifiers =
5407 const int RequiredModifiers =
5411 public enum OpType : byte {
5421 // Unary and Binary operators
5444 // Implicit and Explicit
5449 public readonly OpType OperatorType;
5450 public readonly Expression ReturnType;
5451 public readonly Expression FirstArgType, SecondArgType;
5452 public readonly string FirstArgName, SecondArgName;
5454 public MethodBuilder OperatorMethodBuilder;
5456 public string MethodName;
5457 public Method OperatorMethod;
5459 public Operator (OpType type, Expression ret_type, int mod_flags,
5460 Expression arg1type, string arg1name,
5461 Expression arg2type, string arg2name,
5462 Block block, Attributes attrs, Location loc)
5463 : base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC,
5464 MemberName.Null, attrs, loc)
5466 OperatorType = type;
5467 Name = "op_" + OperatorType;
5468 ReturnType = ret_type;
5469 FirstArgType = arg1type;
5470 FirstArgName = arg1name;
5471 SecondArgType = arg2type;
5472 SecondArgName = arg2name;
5476 string Prototype (TypeContainer container)
5478 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
5479 SecondArgType + ")";
5482 protected override bool CheckGenericOverride (MethodInfo method, string name)
5487 public override bool Define (TypeContainer container)
5490 MethodName = "op_" + OperatorType;
5492 if (SecondArgType != null)
5495 Parameter [] param_list = new Parameter [length];
5497 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
5500 "User defined operators `" +
5501 Prototype (container) +
5502 "' must be declared static and public");
5506 param_list[0] = new Parameter (FirstArgType, FirstArgName,
5507 Parameter.Modifier.NONE, null);
5508 if (SecondArgType != null)
5509 param_list[1] = new Parameter (SecondArgType, SecondArgName,
5510 Parameter.Modifier.NONE, null);
5512 OperatorMethod = new Method (
5513 container, ReturnType, ModFlags, false,
5514 new MemberName (MethodName),
5515 new Parameters (param_list, null, Location),
5516 OptAttributes, Location);
5518 OperatorMethod.Block = Block;
5519 OperatorMethod.IsOperator = true;
5520 OperatorMethod.Define (container);
5522 if (OperatorMethod.MethodBuilder == null)
5525 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
5527 Type [] param_types = OperatorMethod.ParameterTypes;
5528 Type declaring_type = OperatorMethod.MethodData.DeclaringType;
5529 Type return_type = OperatorMethod.GetReturnType ();
5530 Type first_arg_type = param_types [0];
5532 // Rules for conversion operators
5534 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
5535 if (first_arg_type == return_type && first_arg_type == declaring_type){
5538 "User-defined conversion cannot take an object of the " +
5539 "enclosing type and convert to an object of the enclosing" +
5544 if (first_arg_type != declaring_type && return_type != declaring_type){
5547 "User-defined conversion must convert to or from the " +
5552 if (first_arg_type == TypeManager.object_type ||
5553 return_type == TypeManager.object_type){
5556 "User-defined conversion cannot convert to or from " +
5561 if (first_arg_type.IsInterface || return_type.IsInterface){
5564 "User-defined conversion cannot convert to or from an " +
5569 if (first_arg_type.IsSubclassOf (return_type) ||
5570 return_type.IsSubclassOf (first_arg_type)){
5573 "User-defined conversion cannot convert between types " +
5574 "that derive from each other");
5577 } else if (SecondArgType == null) {
5578 // Checks for Unary operators
5580 if (first_arg_type != declaring_type){
5583 "The parameter of a unary operator must be the " +
5588 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
5589 if (return_type != declaring_type){
5592 "The parameter and return type for ++ and -- " +
5593 "must be the containing type");
5599 if (OperatorType == OpType.True || OperatorType == OpType.False) {
5600 if (return_type != TypeManager.bool_type){
5603 "The return type of operator True or False " +
5610 // Checks for Binary operators
5612 if (first_arg_type != declaring_type &&
5613 param_types [1] != declaring_type){
5616 "One of the parameters of a binary operator must " +
5617 "be the containing type");
5625 public void Emit (TypeContainer container)
5628 // abstract or extern methods have no bodies
5630 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
5633 OperatorMethod.Emit (container);
5637 public static string GetName (OpType ot)
5640 case OpType.LogicalNot:
5642 case OpType.OnesComplement:
5644 case OpType.Increment:
5646 case OpType.Decrement:
5652 case OpType.Addition:
5654 case OpType.Subtraction:
5656 case OpType.UnaryPlus:
5658 case OpType.UnaryNegation:
5660 case OpType.Multiply:
5662 case OpType.Division:
5664 case OpType.Modulus:
5666 case OpType.BitwiseAnd:
5668 case OpType.BitwiseOr:
5670 case OpType.ExclusiveOr:
5672 case OpType.LeftShift:
5674 case OpType.RightShift:
5676 case OpType.Equality:
5678 case OpType.Inequality:
5680 case OpType.GreaterThan:
5682 case OpType.LessThan:
5684 case OpType.GreaterThanOrEqual:
5686 case OpType.LessThanOrEqual:
5688 case OpType.Implicit:
5690 case OpType.Explicit:
5696 public override string ToString ()
5698 Type return_type = OperatorMethod.GetReturnType();
5699 Type [] param_types = OperatorMethod.ParameterTypes;
5701 if (SecondArgType == null)
5702 return String.Format (
5703 "{0} operator {1}({2})",
5704 TypeManager.CSharpName (return_type),
5705 GetName (OperatorType),
5708 return String.Format (
5709 "{0} operator {1}({2}, {3})",
5710 TypeManager.CSharpName (return_type),
5711 GetName (OperatorType),
5712 param_types [0], param_types [1]);
5715 public void SetYields ()
5717 ModFlags |= Modifiers.METHOD_YIELDS;
5722 // This is used to compare method signatures
5724 struct MethodSignature {
5726 public Type RetType;
5727 public Type [] Parameters;
5730 /// This delegate is used to extract methods which have the
5731 /// same signature as the argument
5733 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
5735 public MethodSignature (string name, Type ret_type, Type [] parameters)
5740 if (parameters == null)
5741 Parameters = TypeManager.NoTypes;
5743 Parameters = parameters;
5746 public override string ToString ()
5749 if (Parameters.Length != 0){
5750 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
5751 for (int i = 0; i < Parameters.Length; i++){
5752 sb.Append (Parameters [i]);
5753 if (i+1 < Parameters.Length)
5756 pars = sb.ToString ();
5759 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
5762 public override int GetHashCode ()
5764 return Name.GetHashCode ();
5767 public override bool Equals (Object o)
5769 MethodSignature other = (MethodSignature) o;
5771 if (other.Name != Name)
5774 if (other.RetType != RetType)
5777 if (Parameters == null){
5778 if (other.Parameters == null)
5783 if (other.Parameters == null)
5786 int c = Parameters.Length;
5787 if (other.Parameters.Length != c)
5790 for (int i = 0; i < c; i++)
5791 if (other.Parameters [i] != Parameters [i])
5797 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
5799 MethodSignature sig = (MethodSignature) filter_criteria;
5801 if (m.Name != sig.Name)
5805 MethodInfo mi = m as MethodInfo;
5806 PropertyInfo pi = m as PropertyInfo;
5809 ReturnType = mi.ReturnType;
5810 else if (pi != null)
5811 ReturnType = pi.PropertyType;
5816 // we use sig.RetType == null to mean `do not check the
5817 // method return value.
5819 if (sig.RetType != null)
5820 if (ReturnType != sig.RetType)
5825 args = TypeManager.GetArgumentTypes (mi);
5827 args = TypeManager.GetArgumentTypes (pi);
5828 Type [] sigp = sig.Parameters;
5830 if (args.Length != sigp.Length)
5833 for (int i = args.Length; i > 0; ){
5835 if (args [i] != sigp [i])