2 // class.cs: Class and Struct handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@gnome.org)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Licensed under the terms of the GNU GPL
10 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
13 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
15 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
16 // have fixed a remaining problem: not every AddXXXX was adding a
17 // fully qualified name.
19 // Now everyone registers a fully qualified name in the DeclSpace as
20 // being defined instead of the partial name.
22 // Downsides: we are slower than we need to be due to the excess
23 // copies and the names being registered this way.
25 // The reason for this is that we currently depend (on the corlib
26 // bootstrap for instance) that types are fully qualified, because
27 // we dump all the types in the namespace, and we should really have
28 // types inserted into the proper namespace, so we can only store the
29 // basenames in the defined_names array.
34 using System.Collections;
35 using System.Reflection;
36 using System.Reflection.Emit;
37 using System.Runtime.CompilerServices;
38 using System.Runtime.InteropServices;
40 namespace Mono.CSharp {
43 /// This is the base class for structs and classes.
45 public class TypeContainer : DeclSpace, IMemberContainer {
46 // Holds a list of classes and structures
49 // Holds the list of properties
52 // Holds the list of enumerations
55 // Holds the list of delegates
58 // Holds the list of constructors
59 ArrayList instance_constructors;
61 // Holds the list of fields
64 // Holds a list of fields that have initializers
65 ArrayList initialized_fields;
67 // Holds a list of static fields that have initializers
68 ArrayList initialized_static_fields;
70 // Holds the list of constants
76 // Holds order in which interfaces must be closed
77 ArrayList interface_order;
88 // Holds the operators
91 // The emit context for toplevel objects.
95 // Pointers to the default constructor and the default static constructor
97 Constructor default_constructor;
98 Constructor default_static_constructor;
101 // Whether we have seen a static constructor for this class or not
103 public bool UserDefinedStaticConstructor = false;
106 // Whether we have at least one non-static field
108 bool have_nonstatic_fields = false;
111 // This one is computed after we can distinguish interfaces
112 // from classes from the arraylist `type_bases'
114 string base_class_name;
115 TypeExpr parent_type;
117 ArrayList type_bases;
119 bool members_defined;
120 bool members_defined_ok;
122 // The interfaces we implement.
124 Type[] base_inteface_types;
126 // The parent member container and our member cache
127 IMemberContainer parent_container;
128 MemberCache member_cache;
131 // The indexer name for this class
133 public string IndexerName;
137 public TypeContainer ():
138 this (null, null, MemberName.Null, null, new Location (-1)) {
141 public TypeContainer (NamespaceEntry ns, TypeContainer parent,
142 MemberName name, Attributes attrs, Location l)
143 : base (ns, parent, name, attrs, l)
145 types = new ArrayList ();
147 base_class_name = null;
150 public AdditionResult AddConstant (Const constant)
153 string basename = constant.Name;
154 string fullname = Name + "." + basename;
156 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
159 if (constants == null)
160 constants = new ArrayList ();
162 constants.Add (constant);
163 DefineName (fullname, constant);
165 return AdditionResult.Success;
168 public AdditionResult AddEnum (Mono.CSharp.Enum e)
172 if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
176 enums = new ArrayList ();
179 DefineName (e.Name, e);
181 return AdditionResult.Success;
184 public AdditionResult AddClass (Class c)
187 string name = c.Basename;
189 if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
192 DefineName (c.Name, c);
195 return AdditionResult.Success;
198 public AdditionResult AddStruct (Struct s)
201 string name = s.Basename;
203 if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
206 DefineName (s.Name, s);
209 return AdditionResult.Success;
212 public AdditionResult AddDelegate (Delegate d)
215 string name = d.Basename;
217 if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
220 if (delegates == null)
221 delegates = new ArrayList ();
223 DefineName (d.Name, d);
226 return AdditionResult.Success;
229 public AdditionResult AddMethod (Method method)
231 string basename = method.Name;
232 string fullname = Name + "." + basename;
234 Object value = defined_names [fullname];
236 if (value != null && (!(value is Method)))
237 return AdditionResult.NameExists;
239 if (basename == Basename)
240 return AdditionResult.EnclosingClash;
243 methods = new ArrayList ();
245 if (method.Name.IndexOf ('.') != -1)
246 methods.Insert (0, method);
248 methods.Add (method);
251 DefineName (fullname, method);
253 return AdditionResult.Success;
256 public AdditionResult AddConstructor (Constructor c)
258 if (c.Name != Basename)
259 return AdditionResult.NotAConstructor;
261 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
264 UserDefinedStaticConstructor = true;
265 if (default_static_constructor != null)
266 return AdditionResult.MethodExists;
268 default_static_constructor = c;
271 if (default_constructor != null)
272 return AdditionResult.MethodExists;
273 default_constructor = c;
276 if (instance_constructors == null)
277 instance_constructors = new ArrayList ();
279 instance_constructors.Add (c);
282 return AdditionResult.Success;
285 public AdditionResult AddInterface (Interface iface)
288 string name = iface.Basename;
290 if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
293 if (interfaces == null)
294 interfaces = new ArrayList ();
295 interfaces.Add (iface);
296 DefineName (iface.Name, iface);
298 return AdditionResult.Success;
301 public AdditionResult AddField (Field field)
304 string basename = field.Name;
305 string fullname = Name + "." + basename;
307 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
311 fields = new ArrayList ();
315 if (field.HasInitializer){
316 if ((field.ModFlags & Modifiers.STATIC) != 0){
317 if (initialized_static_fields == null)
318 initialized_static_fields = new ArrayList ();
320 initialized_static_fields.Add (field);
323 if (initialized_fields == null)
324 initialized_fields = new ArrayList ();
326 initialized_fields.Add (field);
330 if ((field.ModFlags & Modifiers.STATIC) == 0)
331 have_nonstatic_fields = true;
333 DefineName (fullname, field);
334 return AdditionResult.Success;
337 public AdditionResult AddProperty (Property prop)
341 if ((res = AddProperty (prop, prop.Name)) != AdditionResult.Success)
344 if (prop.Get != null) {
345 if ((res = AddProperty (prop, "get_" + prop.Name)) != AdditionResult.Success)
349 if (prop.Set != null) {
350 if ((res = AddProperty (prop, "set_" + prop.Name)) != AdditionResult.Success)
354 if (properties == null)
355 properties = new ArrayList ();
357 if (prop.Name.IndexOf ('.') != -1)
358 properties.Insert (0, prop);
360 properties.Add (prop);
362 return AdditionResult.Success;
365 AdditionResult AddProperty (Property prop, string basename)
368 string fullname = Name + "." + basename;
370 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
373 DefineName (fullname, prop);
375 return AdditionResult.Success;
378 public AdditionResult AddEvent (Event e)
381 string basename = e.Name;
382 string fullname = Name + "." + basename;
384 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
388 events = new ArrayList ();
391 DefineName (fullname, e);
393 return AdditionResult.Success;
396 public void AddIndexer (Indexer i)
398 if (indexers == null)
399 indexers = new ArrayList ();
401 if (i.MemberName.TypeName != null)
402 indexers.Insert (0, i);
407 public AdditionResult AddOperator (Operator op)
409 if (operators == null)
410 operators = new ArrayList ();
414 string basename = op.Name;
415 string fullname = Name + "." + basename;
416 if (!defined_names.Contains (fullname))
418 DefineName (fullname, op);
420 return AdditionResult.Success;
423 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
425 if (a.Type == TypeManager.default_member_type) {
426 if (Indexers != null) {
427 Report.Error (646, a.Location,
428 "Cannot specify the DefaultMember attribute on" +
429 " a type containing an indexer");
434 base.ApplyAttributeBuilder (a, cb);
437 public override AttributeTargets AttributeTargets {
439 throw new NotSupportedException ();
443 public void RegisterOrder (Interface iface)
445 if (interface_order == null)
446 interface_order = new ArrayList ();
448 interface_order.Add (iface);
451 public ArrayList Types {
457 public ArrayList Methods {
463 public ArrayList Constants {
469 public ArrayList Interfaces {
477 return base_class_name;
481 public ArrayList Bases {
491 public ArrayList Fields {
501 public ArrayList InstanceConstructors {
503 return instance_constructors;
507 public ArrayList Properties {
513 public ArrayList Events {
519 public ArrayList Enums {
525 public ArrayList Indexers {
531 public ArrayList Operators {
537 public ArrayList Delegates {
543 public virtual TypeAttributes TypeAttr {
545 return Modifiers.TypeAttr (ModFlags, this);
550 // Emits the instance field initializers
552 public bool EmitFieldInitializers (EmitContext ec)
555 Expression instance_expr;
558 fields = initialized_static_fields;
559 instance_expr = null;
561 fields = initialized_fields;
562 instance_expr = new This (Location.Null).Resolve (ec);
568 foreach (Field f in fields){
569 Expression e = f.GetInitializerExpression (ec);
573 Location l = f.Location;
574 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
575 fe.InstanceExpression = instance_expr;
576 ExpressionStatement a = new Assign (fe, e, l);
578 a = a.ResolveStatement (ec);
582 a.EmitStatement (ec);
589 // Defines the default constructors
591 void DefineDefaultConstructor (bool is_static)
595 // The default constructor is public
596 // If the class is abstract, the default constructor is protected
597 // The default static constructor is private
599 int mods = Modifiers.PUBLIC;
601 mods = Modifiers.STATIC | Modifiers.PRIVATE;
602 else if ((ModFlags & Modifiers.ABSTRACT) != 0)
603 mods = Modifiers.PROTECTED;
605 c = new Constructor (this, Basename, mods, Parameters.EmptyReadOnlyParameters,
606 new ConstructorBaseInitializer (
607 null, Parameters.EmptyReadOnlyParameters,
613 c.Block = new ToplevelBlock (null, Location);
617 public void ReportStructInitializedInstanceError ()
619 string n = TypeBuilder.FullName;
621 foreach (Field f in initialized_fields){
624 "`" + n + "." + f.Name + "': can not have " +
625 "instance field initializers in structs");
630 /// The pending methods that need to be implemented (interfaces or abstract methods)
632 public PendingImplementation Pending;
635 /// This function computes the Base class and also the
636 /// list of interfaces that the class or struct @c implements.
638 /// The return value is an array (might be null) of
639 /// interfaces implemented (as Types).
641 /// The @parent argument is set to the parent object or null
642 /// if this is `System.Object'.
644 TypeExpr [] GetClassBases (bool is_class, bool is_iface, out bool error)
646 ArrayList bases = Bases;
652 if (is_class || is_iface)
655 parent_type = TypeManager.system_valuetype_expr;
659 if (RootContext.StdLib)
660 parent_type = TypeManager.system_object_expr;
661 else if (Name != "System.Object")
662 parent_type = TypeManager.system_object_expr;
665 // If we are compiling our runtime,
666 // and we are defining ValueType, then our
667 // parent is `System.Object'.
669 if (!RootContext.StdLib && Name == "System.ValueType")
670 parent_type = TypeManager.system_object_expr;
677 // Bases should be null if there are no bases at all
682 TypeExpr name = ResolveTypeExpr ((Expression) bases [0], false, Location);
689 if (name is TypeParameterExpr){
692 "Type parameter `{0}' can not be used as a " +
693 "base class or interface", name.Name);
698 if (IsGeneric && name.IsAttribute){
701 "A generic type cannot derive from `{0}' " +
702 "because it is an attribute class", name.Name);
711 parent_type = TypeManager.system_object_expr;
717 if (name.IsValueType)
718 detail = " (a class can not inherit from a struct/enum)";
720 Report.Error (509, "class `"+ Name +
721 "': Cannot inherit from sealed class `"+
722 name.Name + "'" + detail);
727 if (!parent_type.CanInheritFrom ()){
728 Report.Error (644, Location,
729 "`{0}' cannot inherit from special class `{1}'",
730 Name, parent_type.Name);
735 if (!parent_type.AsAccessible (this, ModFlags))
736 Report.Error (60, Location,
737 "Inconsistent accessibility: base class `" +
738 name.Name + "' is less accessible than class `" +
745 if (parent_type != null)
746 base_class_name = parent_type.Name;
748 TypeExpr [] ifaces = new TypeExpr [count-start];
750 for (i = start, j = 0; i < count; i++, j++){
751 Expression name = (Expression) bases [i];
752 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
754 if (resolved == null)
757 bases [i] = resolved;
759 if (is_class == false && !resolved.IsInterface){
760 Report.Error (527, "In Struct `" + Name + "', type `"+
761 name +"' is not an interface");
766 if (resolved.IsClass) {
767 if (parent_type != null){
768 Report.Error (527, "In Class `" + Name + "', type `"+
769 name+"' is not an interface");
775 for (int x = 0; x < j; x++) {
776 if (resolved.Equals (ifaces [x])) {
777 Report.Error (528, "`" + name + "' is already listed in interface list");
784 !resolved.AsAccessible (Parent, ModFlags))
785 Report.Error (61, Location,
786 "Inconsistent accessibility: base interface `" +
787 name + "' is less accessible than interface `" +
790 ifaces [j] = resolved;
793 return TypeManager.ExpandInterfaces (ifaces);
796 bool CheckGenericInterfaces (Type[] ifaces)
798 ArrayList already_checked = new ArrayList ();
800 for (int i = 0; i < ifaces.Length; i++) {
801 Type iface = ifaces [i];
802 foreach (Type t in already_checked) {
806 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t))
811 "`{0}' cannot implement both `{1}' and `{2}' " +
812 "because they may unify for some type " +
813 "parameter substitutions",
814 TypeManager.GetFullName (TypeBuilder),
819 already_checked.Add (iface);
828 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
830 public override TypeBuilder DefineType ()
833 bool is_class, is_iface;
835 if (TypeBuilder != null)
842 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
849 if (this is Interface) {
860 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
862 ifaces = GetClassBases (is_class, is_iface, out error);
868 foreach (TypeParameter type_param in TypeParameters)
869 if (!type_param.Resolve (this)) {
875 if (!is_class && TypeManager.value_type == null)
876 throw new Exception ();
878 TypeAttributes type_attributes = TypeAttr;
881 ConstructedType constructed = parent_type as ConstructedType;
882 if ((constructed == null) && (parent_type != null))
883 ptype = parent_type.ResolveType (ec);
888 if (TypeManager.NamespaceClash (Name, Location)) {
893 ModuleBuilder builder = CodeGen.Module.Builder;
894 TypeBuilder = builder.DefineType (
895 Name, type_attributes, ptype, null);
897 TypeBuilder builder = Parent.DefineType ();
898 if (builder == null) {
903 TypeBuilder = builder.DefineNestedType (
904 MemberName.Basename, type_attributes, ptype, null);
907 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
910 CurrentType = new ConstructedType (
911 Name, TypeParameters, Location);
913 string[] param_names = new string [TypeParameters.Length];
914 for (int i = 0; i < TypeParameters.Length; i++)
915 param_names [i] = TypeParameters [i].Name;
917 GenericTypeParameterBuilder[] gen_params;
919 gen_params = TypeBuilder.DefineGenericParameters (param_names);
921 for (int i = 0; i < gen_params.Length; i++)
922 TypeParameters [i].Define (gen_params [i]);
925 if (constructed != null) {
926 ptype = constructed.ResolveType (ec);
932 TypeBuilder.SetParent (ptype);
936 foreach (TypeParameter type_param in TypeParameters)
937 if (!type_param.DefineType (ec))
945 // Structs with no fields need to have at least one byte.
946 // The right thing would be to set the PackingSize in a DefineType
947 // but there are no functions that allow interfaces *and* the size to
951 if (!is_class && !is_iface && !have_nonstatic_fields){
952 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
953 FieldAttributes.Private);
956 // add interfaces that were not added at type creation
957 if (ifaces != null) {
958 Type[] itypes = new Type[ifaces.Length];
959 for (int i = 0; i < ifaces.Length; ++i) {
960 Type itype = ifaces [i].ResolveType (ec);
961 TypeBuilder.AddInterfaceImplementation (itype);
968 if (!CheckGenericInterfaces (itypes)) {
975 // Finish the setup for the EmitContext
977 ec.ContainerType = TypeBuilder;
979 if ((parent_type != null) && parent_type.IsAttribute) {
980 RootContext.RegisterAttribute (this);
982 RootContext.RegisterOrder (this);
984 if (Interfaces != null) {
985 foreach (Interface iface in Interfaces)
986 if (iface.DefineType () == null) {
993 foreach (TypeContainer tc in Types)
994 if (tc.DefineType () == null) {
1000 if (Delegates != null) {
1001 foreach (Delegate d in Delegates)
1002 if (d.DefineType () == null) {
1008 if (Enums != null) {
1009 foreach (Enum en in Enums)
1010 if (en.DefineType () == null) {
1022 /// Defines the MemberCore objects that are in the `list' Arraylist
1024 /// The `defined_names' array contains a list of members defined in
1027 static ArrayList remove_list = new ArrayList ();
1028 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
1032 remove_list.Clear ();
1034 foreach (MemberCore mc in list){
1036 if (defined_names != null)
1037 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
1042 if (RootContext.WarningLevel >= 4){
1043 if ((mc.ModFlags & Modifiers.NEW) != 0)
1044 Warning_KeywordNewNotRequired (mc.Location, mc);
1046 } else if (mc is MethodCore)
1047 ((MethodCore) mc).OverridesSomething = true;
1049 if (!mc.Define (this)){
1050 remove_list.Add (mc);
1057 MemberInfo match = defined_names [idx];
1059 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
1063 // If we are both methods, let the method resolution emit warnings
1065 if (match is MethodBase && mc is MethodCore)
1068 if ((mc.ModFlags & Modifiers.NEW) == 0) {
1070 if (!(match is EventInfo)) {
1071 Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
1075 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
1079 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
1083 foreach (object o in remove_list)
1086 remove_list.Clear ();
1090 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
1091 // class is consistent. Either it is `Item' or it is the name defined by all the
1092 // indexers with the `IndexerName' attribute.
1094 // Turns out that the IndexerNameAttribute is applied to each indexer,
1095 // but it is never emitted, instead a DefaultMember attribute is attached
1098 void DefineIndexers ()
1100 string class_indexer_name = null;
1103 // If there's both an explicit and an implicit interface implementation, the
1104 // explicit one actually implements the interface while the other one is just
1105 // a normal indexer. See bug #37714.
1108 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
1109 bool seen_normal_indexers = false;
1110 foreach (Indexer i in Indexers) {
1115 name = i.IndexerName;
1117 if (i.InterfaceType != null) {
1118 if (seen_normal_indexers)
1119 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
1123 seen_normal_indexers = true;
1125 if (class_indexer_name == null)
1126 class_indexer_name = name;
1127 else if (name != class_indexer_name)
1128 Report.Error (668, "Two indexers have different names, " +
1129 " you should use the same name for all your indexers");
1132 if (seen_normal_indexers && class_indexer_name == null)
1133 class_indexer_name = "Item";
1134 IndexerName = class_indexer_name;
1137 static void Error_KeywordNotAllowed (Location loc)
1139 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1143 /// Populates our TypeBuilder with fields and methods
1145 public override bool DefineMembers (TypeContainer container)
1147 if (members_defined)
1148 return members_defined_ok;
1150 members_defined_ok = DoDefineMembers ();
1151 members_defined = true;
1153 return members_defined_ok;
1156 bool DoDefineMembers ()
1158 MemberInfo [] defined_names = null;
1161 // We need to be able to use the member cache while we are checking/defining
1164 if (TypeBuilder.BaseType != null)
1165 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1168 if (interface_order != null){
1169 foreach (Interface iface in interface_order)
1170 if ((iface.ModFlags & Modifiers.NEW) == 0)
1171 iface.DefineMembers (this);
1173 Error_KeywordNotAllowed (iface.Location);
1176 if (RootContext.WarningLevel > 1){
1180 // This code throws an exception in the comparer
1181 // I guess the string is not an object?
1183 ptype = TypeBuilder.BaseType;
1185 defined_names = (MemberInfo []) FindMembers (
1186 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1187 BindingFlags.Public | BindingFlags.Instance |
1188 BindingFlags.Static, null, null);
1190 Array.Sort (defined_names, mif_compare);
1194 Class pclass = Parent as Class;
1195 if (pclass != null) {
1196 string pname = null;
1197 TypeExpr ptype = null;
1198 Type t = pclass.TypeBuilder.BaseType;
1199 while ((t != null) && (ptype == null)) {
1200 pname = t.FullName + "." + Basename;
1201 ptype = RootContext.LookupType (this, pname, true, Location.Null);
1205 if ((ModFlags & Modifiers.NEW) != 0) {
1207 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1208 "inherited member. The keyword new is not required.");
1209 } else if (ptype != null) {
1210 Report.Warning (108, Location, "The keyword new is required on `" +
1211 Name + "' because it hides inherited member '" +
1214 } else if ((ModFlags & Modifiers.NEW) != 0)
1215 Error_KeywordNotAllowed (Location);
1217 if (constants != null)
1218 DefineMembers (constants, defined_names);
1221 DefineMembers (fields, defined_names);
1224 if (instance_constructors == null){
1225 if (default_constructor == null)
1226 DefineDefaultConstructor (false);
1229 if (initialized_static_fields != null &&
1230 default_static_constructor == null)
1231 DefineDefaultConstructor (true);
1234 if (this is Struct){
1236 // Structs can not have initialized instance
1239 if (initialized_static_fields != null &&
1240 default_static_constructor == null)
1241 DefineDefaultConstructor (true);
1243 if (initialized_fields != null)
1244 ReportStructInitializedInstanceError ();
1247 if (!(this is Interface))
1248 Pending = PendingImplementation.GetPendingImplementations (this);
1251 // Constructors are not in the defined_names array
1253 if (instance_constructors != null)
1254 DefineMembers (instance_constructors, null);
1256 if (default_static_constructor != null)
1257 default_static_constructor.Define (this);
1259 if (methods != null)
1260 DefineMembers (methods, defined_names);
1262 if (properties != null)
1263 DefineMembers (properties, defined_names);
1266 DefineMembers (events, defined_names);
1268 if (indexers != null)
1271 if (operators != null){
1272 DefineMembers (operators, null);
1274 CheckPairedOperators ();
1278 DefineMembers (enums, defined_names);
1280 if (delegates != null)
1281 DefineMembers (delegates, defined_names);
1283 if (CurrentType != null) {
1284 GenericType = CurrentType.ResolveType (ec);
1286 ec.ContainerType = GenericType;
1291 member_cache = new MemberCache (this);
1298 public override bool Define (TypeContainer container)
1300 if (interface_order != null){
1301 foreach (Interface iface in interface_order)
1302 if ((iface.ModFlags & Modifiers.NEW) == 0)
1303 iface.Define (this);
1310 /// This function is based by a delegate to the FindMembers routine
1312 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1318 /// This filter is used by FindMembers, and we just keep
1319 /// a global for the filter to `AlwaysAccept'
1321 static MemberFilter accepting_filter;
1325 /// A member comparission method based on name only
1327 static IComparer mif_compare;
1329 static TypeContainer ()
1331 accepting_filter = new MemberFilter (AlwaysAccept);
1332 mif_compare = new MemberInfoCompare ();
1335 public MethodInfo[] GetMethods ()
1337 ArrayList members = new ArrayList ();
1339 DefineMembers (null);
1341 if (methods != null) {
1342 int len = methods.Count;
1343 for (int i = 0; i < len; i++) {
1344 Method m = (Method) methods [i];
1346 members.Add (m.MethodBuilder);
1350 if (operators != null) {
1351 int len = operators.Count;
1352 for (int i = 0; i < len; i++) {
1353 Operator o = (Operator) operators [i];
1355 members.Add (o.OperatorMethodBuilder);
1359 if (properties != null) {
1360 int len = properties.Count;
1361 for (int i = 0; i < len; i++) {
1362 Property p = (Property) properties [i];
1364 if (p.GetBuilder != null)
1365 members.Add (p.GetBuilder);
1366 if (p.SetBuilder != null)
1367 members.Add (p.SetBuilder);
1371 if (indexers != null) {
1372 int len = indexers.Count;
1373 for (int i = 0; i < len; i++) {
1374 Indexer ix = (Indexer) indexers [i];
1376 if (ix.GetBuilder != null)
1377 members.Add (ix.GetBuilder);
1378 if (ix.SetBuilder != null)
1379 members.Add (ix.SetBuilder);
1383 if (events != null) {
1384 int len = events.Count;
1385 for (int i = 0; i < len; i++) {
1386 Event e = (Event) events [i];
1388 if (e.AddBuilder != null)
1389 members.Add (e.AddBuilder);
1390 if (e.RemoveBuilder != null)
1391 members.Add (e.RemoveBuilder);
1395 MethodInfo[] retMethods = new MethodInfo [members.Count];
1396 members.CopyTo (retMethods, 0);
1401 /// This method returns the members of this type just like Type.FindMembers would
1402 /// Only, we need to use this for types which are _being_ defined because MS'
1403 /// implementation can't take care of that.
1406 // FIXME: return an empty static array instead of null, that cleans up
1407 // some code and is consistent with some coding conventions I just found
1411 // Notice that in various cases we check if our field is non-null,
1412 // something that would normally mean that there was a bug elsewhere.
1414 // The problem happens while we are defining p-invoke methods, as those
1415 // will trigger a FindMembers, but this happens before things are defined
1417 // Since the whole process is a no-op, it is fine to check for null here.
1419 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1420 MemberFilter filter, object criteria)
1422 ArrayList members = null;
1425 if ((bf & BindingFlags.Public) != 0)
1426 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1428 if ((bf & BindingFlags.NonPublic) != 0)
1429 modflags |= Modifiers.PRIVATE;
1431 int static_mask = 0, static_flags = 0;
1432 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1433 case BindingFlags.Static:
1434 static_mask = static_flags = Modifiers.STATIC;
1437 case BindingFlags.Instance:
1438 static_mask = Modifiers.STATIC;
1443 static_mask = static_flags = 0;
1447 Timer.StartTimer (TimerType.TcFindMembers);
1450 filter = accepting_filter;
1452 if ((mt & MemberTypes.Field) != 0) {
1453 if (fields != null) {
1454 int len = fields.Count;
1455 for (int i = 0; i < len; i++) {
1456 Field f = (Field) fields [i];
1458 if ((f.ModFlags & modflags) == 0)
1460 if ((f.ModFlags & static_mask) != static_flags)
1463 FieldBuilder fb = f.FieldBuilder;
1464 if (fb != null && filter (fb, criteria) == true) {
1465 if (members == null)
1466 members = new ArrayList ();
1473 if (constants != null) {
1474 int len = constants.Count;
1475 for (int i = 0; i < len; i++) {
1476 Const con = (Const) constants [i];
1478 if ((con.ModFlags & modflags) == 0)
1480 if ((con.ModFlags & static_mask) != static_flags)
1483 FieldBuilder fb = con.FieldBuilder;
1484 if (fb != null && filter (fb, criteria) == true) {
1485 if (members == null)
1486 members = new ArrayList ();
1494 if ((mt & MemberTypes.Method) != 0) {
1495 if (methods != null) {
1496 int len = methods.Count;
1497 for (int i = 0; i < len; i++) {
1498 Method m = (Method) methods [i];
1500 if ((m.ModFlags & modflags) == 0)
1502 if ((m.ModFlags & static_mask) != static_flags)
1505 MethodBuilder mb = m.MethodBuilder;
1507 if (mb != null && filter (mb, criteria) == true) {
1508 if (members == null)
1509 members = new ArrayList ();
1516 if (operators != null) {
1517 int len = operators.Count;
1518 for (int i = 0; i < len; i++) {
1519 Operator o = (Operator) operators [i];
1521 if ((o.ModFlags & modflags) == 0)
1523 if ((o.ModFlags & static_mask) != static_flags)
1526 MethodBuilder ob = o.OperatorMethodBuilder;
1527 if (ob != null && filter (ob, criteria) == true) {
1528 if (members == null)
1529 members = new ArrayList ();
1536 if (properties != null) {
1537 int len = properties.Count;
1538 for (int i = 0; i < len; i++) {
1539 Property p = (Property) properties [i];
1541 if ((p.ModFlags & modflags) == 0)
1543 if ((p.ModFlags & static_mask) != static_flags)
1549 if (b != null && filter (b, criteria) == true) {
1550 if (members == null)
1551 members = new ArrayList ();
1557 if (b != null && filter (b, criteria) == true) {
1558 if (members == null)
1559 members = new ArrayList ();
1566 if (indexers != null) {
1567 int len = indexers.Count;
1568 for (int i = 0; i < len; i++) {
1569 Indexer ix = (Indexer) indexers [i];
1571 if ((ix.ModFlags & modflags) == 0)
1573 if ((ix.ModFlags & static_mask) != static_flags)
1579 if (b != null && filter (b, criteria) == true) {
1580 if (members == null)
1581 members = new ArrayList ();
1587 if (b != null && filter (b, criteria) == true) {
1588 if (members == null)
1589 members = new ArrayList ();
1597 if ((mt & MemberTypes.Event) != 0) {
1598 if (events != null) {
1599 int len = events.Count;
1600 for (int i = 0; i < len; i++) {
1601 Event e = (Event) events [i];
1603 if ((e.ModFlags & modflags) == 0)
1605 if ((e.ModFlags & static_mask) != static_flags)
1608 MemberInfo eb = e.EventBuilder;
1609 if (eb != null && filter (eb, criteria) == true) {
1610 if (members == null)
1611 members = new ArrayList ();
1613 members.Add (e.EventBuilder);
1619 if ((mt & MemberTypes.Property) != 0){
1620 if (properties != null) {
1621 int len = properties.Count;
1622 for (int i = 0; i < len; i++) {
1623 Property p = (Property) properties [i];
1625 if ((p.ModFlags & modflags) == 0)
1627 if ((p.ModFlags & static_mask) != static_flags)
1630 MemberInfo pb = p.PropertyBuilder;
1631 if (pb != null && filter (pb, criteria) == true) {
1632 if (members == null)
1633 members = new ArrayList ();
1635 members.Add (p.PropertyBuilder);
1640 if (indexers != null) {
1641 int len = indexers.Count;
1642 for (int i = 0; i < len; i++) {
1643 Indexer ix = (Indexer) indexers [i];
1645 if ((ix.ModFlags & modflags) == 0)
1647 if ((ix.ModFlags & static_mask) != static_flags)
1650 MemberInfo ib = ix.PropertyBuilder;
1651 if (ib != null && filter (ib, criteria) == true) {
1652 if (members == null)
1653 members = new ArrayList ();
1655 members.Add (ix.PropertyBuilder);
1661 if ((mt & MemberTypes.NestedType) != 0) {
1662 if (types != null) {
1663 int len = types.Count;
1664 for (int i = 0; i < len; i++) {
1665 TypeContainer t = (TypeContainer) types [i];
1667 if ((t.ModFlags & modflags) == 0)
1670 TypeBuilder tb = t.TypeBuilder;
1671 if (tb != null && (filter (tb, criteria) == true)) {
1672 if (members == null)
1673 members = new ArrayList ();
1680 if (enums != null) {
1681 int len = enums.Count;
1682 for (int i = 0; i < len; i++) {
1683 Enum en = (Enum) enums [i];
1685 if ((en.ModFlags & modflags) == 0)
1688 TypeBuilder tb = en.TypeBuilder;
1689 if (tb != null && (filter (tb, criteria) == true)) {
1690 if (members == null)
1691 members = new ArrayList ();
1698 if (delegates != null) {
1699 int len = delegates.Count;
1700 for (int i = 0; i < len; i++) {
1701 Delegate d = (Delegate) delegates [i];
1703 if ((d.ModFlags & modflags) == 0)
1706 TypeBuilder tb = d.TypeBuilder;
1707 if (tb != null && (filter (tb, criteria) == true)) {
1708 if (members == null)
1709 members = new ArrayList ();
1716 if (interfaces != null) {
1717 int len = interfaces.Count;
1718 for (int i = 0; i < len; i++) {
1719 Interface iface = (Interface) interfaces [i];
1721 if ((iface.ModFlags & modflags) == 0)
1724 TypeBuilder tb = iface.TypeBuilder;
1725 if (tb != null && (filter (tb, criteria) == true)) {
1726 if (members == null)
1727 members = new ArrayList ();
1735 if ((mt & MemberTypes.Constructor) != 0){
1736 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1737 int len = instance_constructors.Count;
1738 for (int i = 0; i < len; i++) {
1739 Constructor c = (Constructor) instance_constructors [i];
1741 ConstructorBuilder cb = c.ConstructorBuilder;
1742 if (cb != null && filter (cb, criteria) == true) {
1743 if (members == null)
1744 members = new ArrayList ();
1751 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1752 ConstructorBuilder cb =
1753 default_static_constructor.ConstructorBuilder;
1755 if (cb != null && filter (cb, criteria) == true) {
1756 if (members == null)
1757 members = new ArrayList ();
1765 // Lookup members in parent if requested.
1767 if ((bf & BindingFlags.DeclaredOnly) == 0) {
1768 if (TypeBuilder.BaseType != null) {
1769 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1770 if (list.Count > 0) {
1771 if (members == null)
1772 members = new ArrayList ();
1774 members.AddRange (list);
1778 if (base_inteface_types != null) {
1779 foreach (Type base_type in base_inteface_types) {
1780 MemberList list = TypeContainer.FindMembers (base_type, mt, bf, filter, criteria);
1782 if (list.Count > 0) {
1783 if (members == null)
1784 members = new ArrayList ();
1785 members.AddRange (list);
1791 Timer.StopTimer (TimerType.TcFindMembers);
1793 if (members == null)
1794 return MemberList.Empty;
1796 return new MemberList (members);
1799 public override MemberCache MemberCache {
1801 return member_cache;
1805 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1806 MemberFilter filter, object criteria)
1808 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1811 return ds.FindMembers (mt, bf, filter, criteria);
1813 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1817 // FindMethods will look for methods not only in the type `t', but in
1818 // any interfaces implemented by the type.
1820 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1821 MemberFilter filter, object criteria)
1827 /// Emits the values for the constants
1829 public void EmitConstants ()
1831 if (constants != null)
1832 foreach (Const con in constants)
1837 protected virtual void VerifyMembers (EmitContext ec)
1840 // Check for internal or private fields that were never assigned
1842 if (RootContext.WarningLevel >= 3) {
1843 if (fields != null){
1844 foreach (Field f in fields) {
1845 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
1848 if ((f.status & Field.Status.USED) == 0){
1850 169, f.Location, "Private field " +
1851 MakeName (f.Name) + " is never used");
1856 // Only report 649 on level 4
1858 if (RootContext.WarningLevel < 4)
1861 if ((f.status & Field.Status.ASSIGNED) != 0)
1866 "Field " + MakeName (f.Name) + " is never assigned " +
1867 " to and will always have its default value");
1871 if (events != null){
1872 foreach (Event e in events){
1874 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1881 /// Emits the code, this step is performed after all
1882 /// the types, enumerations, constructors
1886 if (OptAttributes != null)
1887 OptAttributes.Emit (ec, this);
1891 if (instance_constructors != null) {
1892 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && IsClsCompliaceRequired (this)) {
1893 bool has_compliant_args = false;
1895 foreach (Constructor c in instance_constructors) {
1898 if (has_compliant_args)
1901 has_compliant_args = c.HasCompliantArgs;
1903 if (!has_compliant_args)
1904 Report.Error_T (3015, Location, GetSignatureForError ());
1906 foreach (Constructor c in instance_constructors)
1911 if (default_static_constructor != null)
1912 default_static_constructor.Emit (this);
1914 if (methods != null)
1915 foreach (Method m in methods)
1918 if (operators != null)
1919 foreach (Operator o in operators)
1922 if (properties != null)
1923 foreach (Property p in properties)
1926 if (indexers != null){
1927 foreach (Indexer ix in indexers)
1929 if (IndexerName != null) {
1930 CustomAttributeBuilder cb = EmitDefaultMemberAttr ();
1931 TypeBuilder.SetCustomAttribute (cb);
1936 foreach (Field f in fields)
1939 if (events != null){
1940 foreach (Event e in Events)
1944 if (delegates != null) {
1945 foreach (Delegate d in Delegates) {
1950 if (Pending != null)
1951 if (Pending.VerifyPendingMethods ())
1956 // if (types != null)
1957 // foreach (TypeContainer tc in types)
1961 CustomAttributeBuilder EmitDefaultMemberAttr ()
1963 EmitContext ec = new EmitContext (this, Location, null, null, ModFlags);
1965 Expression ml = Expression.MemberLookup (ec, TypeManager.default_member_type,
1966 ".ctor", MemberTypes.Constructor,
1967 BindingFlags.Public | BindingFlags.Instance,
1970 MethodGroupExpr mg = (MethodGroupExpr) ml;
1972 MethodBase constructor = mg.Methods [0];
1974 string [] vals = { IndexerName };
1976 CustomAttributeBuilder cb = null;
1978 cb = new CustomAttributeBuilder ((ConstructorInfo) constructor, vals);
1980 Report.Warning (-100, "Can not set the indexer default member attribute");
1986 public override void CloseType ()
1988 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1992 caching_flags |= Flags.CloseTypeCreated;
1993 TypeBuilder.CreateType ();
1994 } catch (TypeLoadException){
1996 // This is fine, the code still created the type
1998 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1999 // Console.WriteLine (e.Message);
2001 Console.WriteLine ("In type: " + Name);
2006 foreach (Enum en in Enums)
2009 if (interface_order != null){
2010 foreach (Interface iface in interface_order)
2015 foreach (TypeContainer tc in Types)
2019 foreach (TypeContainer tc in Types)
2020 if (!(tc is Struct))
2024 if (Delegates != null)
2025 foreach (Delegate d in Delegates)
2033 initialized_fields = null;
2034 initialized_static_fields = null;
2037 interface_order = null;
2043 default_constructor = null;
2044 default_static_constructor = null;
2046 OptAttributes = null;
2048 parent_container = null;
2049 member_cache = null;
2052 public string MakeName (string n)
2054 return "`" + Name + "." + n + "'";
2057 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
2060 108, l, "The keyword new is required on " +
2061 MakeName (mi.Name) + " because it hides `" +
2062 mi.ReflectedType.Name + "." + mi.Name + "'");
2065 public void Warning_KeywordNewNotRequired (Location l, MemberCore mc)
2068 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
2069 "inherited member, the keyword new is not required");
2072 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
2075 72, l, MakeName (mi.Name) + " : cannot override; `" +
2076 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
2079 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
2085 // Performs the validation on a Method's modifiers (properties have
2086 // the same properties).
2088 public bool MethodModifiersValid (int flags, string n, Location loc)
2090 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2091 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2092 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2096 // At most one of static, virtual or override
2098 if ((flags & Modifiers.STATIC) != 0){
2099 if ((flags & vao) != 0){
2101 112, loc, "static method " + MakeName (n) + "can not be marked " +
2102 "as virtual, abstract or override");
2107 if (this is Struct){
2108 if ((flags & va) != 0){
2109 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
2114 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2116 113, loc, MakeName (n) +
2117 " marked as override cannot be marked as new or virtual");
2122 // If the declaration includes the abstract modifier, then the
2123 // declaration does not include static, virtual or extern
2125 if ((flags & Modifiers.ABSTRACT) != 0){
2126 if ((flags & Modifiers.EXTERN) != 0){
2128 180, loc, MakeName (n) + " can not be both abstract and extern");
2132 if ((flags & Modifiers.VIRTUAL) != 0){
2134 503, loc, MakeName (n) + " can not be both abstract and virtual");
2138 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2140 513, loc, MakeName (n) +
2141 " is abstract but its container class is not");
2147 if ((flags & Modifiers.PRIVATE) != 0){
2148 if ((flags & vao) != 0){
2150 621, loc, MakeName (n) +
2151 " virtual or abstract members can not be private");
2156 if ((flags & Modifiers.SEALED) != 0){
2157 if ((flags & Modifiers.OVERRIDE) == 0){
2159 238, loc, MakeName (n) +
2160 " cannot be sealed because it is not an override");
2168 Hashtable builder_and_args;
2170 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
2172 if (builder_and_args == null)
2173 builder_and_args = new Hashtable ();
2177 protected override bool VerifyClsCompliance (DeclSpace ds)
2179 if (!base.VerifyClsCompliance (ds))
2182 // parent_container is null for System.Object
2183 if (parent_container != null && !AttributeTester.IsClsCompliant (parent_container.Type)) {
2184 Report.Error_T (3009, Location, GetSignatureForError (), TypeManager.CSharpName (parent_container.Type));
2191 /// Performs checks for an explicit interface implementation. First it
2192 /// checks whether the `interface_type' is a base inteface implementation.
2193 /// Then it checks whether `name' exists in the interface type.
2195 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
2199 if (ifaces != null){
2200 foreach (TypeExpr t in ifaces){
2201 if (t.Type == interface_type){
2209 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
2216 protected override void VerifyObsoleteAttribute()
2218 CheckUsageOfObsoleteAttribute (TypeBuilder.BaseType);
2223 foreach (TypeExpr expr in ifaces) {
2224 CheckUsageOfObsoleteAttribute (expr.Type);
2232 string IMemberContainer.Name {
2238 Type IMemberContainer.Type {
2244 IMemberContainer IMemberContainer.Parent {
2246 return parent_container;
2250 MemberCache IMemberContainer.MemberCache {
2252 return member_cache;
2256 bool IMemberContainer.IsInterface {
2258 return this is Interface;
2262 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2264 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2266 if (GenericType != null)
2267 return TypeManager.FindMembers (GenericType, mt, new_bf,
2270 return FindMembers (mt, new_bf, null, null);
2274 // Operator pair checking
2277 class OperatorEntry {
2279 public Type ret_type;
2280 public Type type1, type2;
2282 public Operator.OpType ot;
2284 public OperatorEntry (int f, Operator o)
2288 ret_type = o.OperatorMethod.GetReturnType ();
2289 Type [] pt = o.OperatorMethod.ParameterTypes;
2293 ot = o.OperatorType;
2296 public override int GetHashCode ()
2298 return ret_type.GetHashCode ();
2301 public override bool Equals (object o)
2303 OperatorEntry other = (OperatorEntry) o;
2305 if (other.ret_type != ret_type)
2307 if (other.type1 != type1)
2309 if (other.type2 != type2)
2316 // Checks that some operators come in pairs:
2322 // They are matched based on the return type and the argument types
2324 void CheckPairedOperators ()
2326 Hashtable pairs = new Hashtable (null, null);
2327 Operator true_op = null;
2328 Operator false_op = null;
2329 bool has_equality_or_inequality = false;
2331 // Register all the operators we care about.
2332 foreach (Operator op in operators){
2335 switch (op.OperatorType){
2336 case Operator.OpType.Equality:
2338 has_equality_or_inequality = true;
2340 case Operator.OpType.Inequality:
2342 has_equality_or_inequality = true;
2345 case Operator.OpType.True:
2348 case Operator.OpType.False:
2352 case Operator.OpType.GreaterThan:
2354 case Operator.OpType.LessThan:
2357 case Operator.OpType.GreaterThanOrEqual:
2359 case Operator.OpType.LessThanOrEqual:
2365 OperatorEntry oe = new OperatorEntry (reg, op);
2367 object o = pairs [oe];
2371 oe = (OperatorEntry) o;
2376 if (true_op != null){
2377 if (false_op == null)
2378 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2379 } else if (false_op != null)
2380 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2383 // Look for the mistakes.
2385 foreach (DictionaryEntry de in pairs){
2386 OperatorEntry oe = (OperatorEntry) de.Key;
2393 case Operator.OpType.Equality:
2396 case Operator.OpType.Inequality:
2399 case Operator.OpType.GreaterThan:
2402 case Operator.OpType.LessThan:
2405 case Operator.OpType.GreaterThanOrEqual:
2408 case Operator.OpType.LessThanOrEqual:
2412 Report.Error (216, oe.op.Location,
2413 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2416 if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2417 MethodSignature equals_ms = new MethodSignature (
2418 "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2419 MethodSignature hash_ms = new MethodSignature (
2420 "GetHashCode", TypeManager.int32_type, new Type [0]);
2422 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2423 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2425 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2426 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2429 bool equals_ok = false;
2430 if ((equals_ml != null) && (equals_ml.Count == 1))
2431 equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2432 bool hash_ok = false;
2433 if ((hash_ml != null) && (hash_ml.Count == 1))
2434 hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2437 Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2438 "not override Object.Equals (object o)");
2440 Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2441 "not override Object.GetHashCode ()");
2447 public class ClassOrStruct : TypeContainer {
2448 bool hasExplicitLayout = false;
2449 public ClassOrStruct (NamespaceEntry ns, TypeContainer parent, MemberName name,
2450 Attributes attrs, Location l)
2451 : base (ns, parent, name, attrs, l)
2455 protected override void VerifyMembers (EmitContext ec)
2457 if (Fields != null) {
2458 foreach (Field f in Fields) {
2459 if ((f.ModFlags & Modifiers.STATIC) != 0)
2461 if (hasExplicitLayout) {
2462 if (f.OptAttributes == null
2463 || !f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
2464 Report.Error (625, f.Location,
2465 "Instance field of type marked with"
2466 + " StructLayout(LayoutKind.Explicit) must have a"
2467 + " FieldOffset attribute.");
2471 if (f.OptAttributes != null
2472 && f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
2473 Report.Error (636, f.Location,
2474 "The FieldOffset attribute can only be placed on members of "
2475 + "types marked with the StructLayout(LayoutKind.Explicit)");
2480 base.VerifyMembers (ec);
2483 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2485 if (a.Type == TypeManager.struct_layout_attribute_type
2486 && (LayoutKind) a.GetPositionalValue (0) == LayoutKind.Explicit)
2487 hasExplicitLayout = true;
2489 base.ApplyAttributeBuilder (a, cb);
2493 public class Class : ClassOrStruct {
2495 // Modifiers allowed in a class declaration
2497 public const int AllowedModifiers =
2500 Modifiers.PROTECTED |
2501 Modifiers.INTERNAL |
2503 Modifiers.ABSTRACT |
2507 // Information in the case we are an attribute type
2508 AttributeUsageAttribute attribute_usage;
2510 public Class (NamespaceEntry ns, TypeContainer parent, MemberName name,
2511 int mod, Attributes attrs, Location l)
2512 : base (ns, parent, name, attrs, l)
2516 if (parent.Parent == null)
2517 accmods = Modifiers.INTERNAL;
2519 accmods = Modifiers.PRIVATE;
2521 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2522 attribute_usage = new AttributeUsageAttribute (AttributeTargets.All);
2525 public override AttributeTargets AttributeTargets {
2527 return AttributeTargets.Class;
2531 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
2533 if (a.UsageAttribute != null)
2534 attribute_usage = a.UsageAttribute;
2536 base.ApplyAttributeBuilder (a, cb);
2539 public AttributeUsageAttribute AttributeUsage {
2541 return attribute_usage;
2546 // FIXME: How do we deal with the user specifying a different
2549 public override TypeAttributes TypeAttr {
2551 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2556 public class Struct : ClassOrStruct {
2558 // Modifiers allowed in a struct declaration
2560 public const int AllowedModifiers =
2563 Modifiers.PROTECTED |
2564 Modifiers.INTERNAL |
2568 public Struct (NamespaceEntry ns, TypeContainer parent, MemberName name,
2569 int mod, Attributes attrs, Location l)
2570 : base (ns, parent, name, attrs, l)
2574 if (parent.Parent == null)
2575 accmods = Modifiers.INTERNAL;
2577 accmods = Modifiers.PRIVATE;
2579 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2581 this.ModFlags |= Modifiers.SEALED;
2584 public override AttributeTargets AttributeTargets {
2586 return AttributeTargets.Struct;
2592 // FIXME: Allow the user to specify a different set of attributes
2593 // in some cases (Sealed for example is mandatory for a class,
2594 // but what SequentialLayout can be changed
2596 public override TypeAttributes TypeAttr {
2598 return base.TypeAttr |
2599 TypeAttributes.SequentialLayout |
2600 TypeAttributes.Sealed |
2601 TypeAttributes.BeforeFieldInit;
2609 public class Interface : TypeContainer, IMemberContainer {
2611 /// Modifiers allowed in a class declaration
2613 public const int AllowedModifiers =
2616 Modifiers.PROTECTED |
2617 Modifiers.INTERNAL |
2621 public Interface (NamespaceEntry ns, TypeContainer parent, MemberName name,
2622 int mod, Attributes attrs, Location l)
2623 : base (ns, parent, name, attrs, l)
2627 if (parent.Parent == null)
2628 accmods = Modifiers.INTERNAL;
2630 accmods = Modifiers.PRIVATE;
2632 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2635 public override AttributeTargets AttributeTargets {
2637 return AttributeTargets.Interface;
2641 public override TypeAttributes TypeAttr {
2643 return base.TypeAttr |
2644 TypeAttributes.AutoLayout |
2645 TypeAttributes.Abstract |
2646 TypeAttributes.Interface;
2651 public abstract class MethodCore : MemberBase {
2652 public readonly Parameters Parameters;
2653 public readonly GenericMethod GenericMethod;
2654 protected Block block;
2655 public DeclSpace ds;
2658 // Parameters, cached for semantic analysis.
2660 protected InternalParameters parameter_info;
2661 protected Type [] parameter_types;
2664 // This is set from TypeContainer.DefineMembers if this method overrides something.
2666 public bool OverridesSomething;
2668 // Whether this is an operator method.
2669 public bool IsOperator;
2671 static string[] attribute_targets = new string [] { "method", "return" };
2673 public MethodCore (DeclSpace ds, Expression type, int mod, int allowed_mod,
2674 bool is_interface, MemberName name, Attributes attrs,
2675 Parameters parameters, Location loc)
2676 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
2678 Parameters = parameters;
2679 IsInterface = is_interface;
2681 this.GenericMethod = ds as GenericMethod;
2685 // Returns the System.Type array for the parameters of this method
2687 public Type [] ParameterTypes {
2689 return parameter_types;
2693 public InternalParameters ParameterInfo
2696 return parameter_info;
2700 public Block Block {
2710 protected virtual bool DoDefineParameters ()
2712 // Check if arguments were correct
2713 parameter_types = Parameters.GetParameterInfo (ds);
2714 if ((parameter_types == null) || !CheckParameters (ds, parameter_types))
2717 parameter_info = new InternalParameters (ds, Parameters);
2719 Parameter array_param = Parameters.ArrayParameter;
2720 if ((array_param != null) &&
2721 (!array_param.ParameterType.IsArray ||
2722 (array_param.ParameterType.GetArrayRank () != 1))) {
2723 Report.Error (225, Location, "params parameter has to be a single dimensional array");
2730 void error_425 (Type old, Type t, string name)
2732 Report.Error (425, Location,
2733 "The constraints of type parameter `{0}' " +
2734 "of method `{1}' must match the constraints for " +
2735 "type parameter `{2}' of method `{3}'",
2736 TypeManager.CSharpName (old), Name,
2737 TypeManager.CSharpName (t), name);
2740 protected override bool CheckGenericOverride (MethodInfo method, string name)
2742 ParameterData pd = Invocation.GetParameterData (method);
2744 for (int i = 0; i < ParameterTypes.Length; i++) {
2745 GenericConstraints ogc = pd.GenericConstraints (i);
2746 GenericConstraints gc = ParameterInfo.GenericConstraints (i);
2748 if ((gc == null) && (ogc == null))
2751 Type ot = pd.ParameterType (i);
2752 Type t = ParameterTypes [i];
2754 if (!((gc != null) && (ogc != null))) {
2755 error_425 (ot, t, name);
2759 if (gc.HasConstructor != ogc.HasConstructor) {
2760 error_425 (ot, t, name);
2764 if (ogc.HasClassConstraint != gc.HasClassConstraint) {
2765 error_425 (ot, t, name);
2769 if (ogc.HasClassConstraint &&
2770 !ogc.ClassConstraint.Equals (gc.ClassConstraint)) {
2771 error_425 (ot, t, name);
2775 Type[] oct = ogc.InterfaceConstraints;
2776 Type[] ct = gc.InterfaceConstraints;
2778 if (oct.Length != ct.Length) {
2779 error_425 (ot, t, name);
2783 for (int j = 0; j < oct.Length; j++)
2784 if (!oct [j].Equals (ct [j])) {
2785 error_425 (ot, t, name);
2793 protected override string[] ValidAttributeTargets {
2795 return attribute_targets;
2799 protected override bool VerifyClsCompliance (DeclSpace ds)
2801 if (!base.VerifyClsCompliance (ds)) {
2802 if ((ModFlags & Modifiers.ABSTRACT) != 0 && IsExposedFromAssembly (ds) && ds.IsClsCompliaceRequired (ds)) {
2803 Report.Error_T (3011, Location, GetSignatureForError ());
2808 AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);
2810 if (!AttributeTester.IsClsCompliant (MemberType)) {
2811 Report.Error_T (3002, Location, GetSignatureForError ());
2817 protected bool IsDuplicateImplementation (TypeContainer tc, MethodCore method)
2819 if ((method == this) || (method.Name != Name))
2822 Type[] param_types = method.ParameterTypes;
2823 if (param_types == null)
2826 if (param_types.Length != ParameterTypes.Length)
2829 int type_params = 0;
2830 if (GenericMethod != null)
2831 type_params = GenericMethod.CountTypeParameters;
2833 int m_type_params = 0;
2834 if (method.GenericMethod != null)
2835 m_type_params = method.GenericMethod.CountTypeParameters;
2837 if (type_params != m_type_params)
2843 Type[] infered_types = new Type [param_types.Length];
2844 may_unify = Invocation.InferTypeArguments (
2845 param_types, ParameterTypes, ref infered_types);
2848 infered_types = new Type [param_types.Length];
2849 may_unify = Invocation.InferTypeArguments (
2850 ParameterTypes, param_types, ref infered_types);
2853 for (int i = 0; i < param_types.Length; i++) {
2854 Type a = param_types [i];
2855 Type b = ParameterTypes [i];
2863 // Try to report 663: method only differs on out/ref
2865 ParameterData info = ParameterInfo;
2866 ParameterData other_info = method.ParameterInfo;
2867 for (int i = 0; i < info.Count; i++){
2868 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
2869 Report.Error (663, Location,
2870 "Overload method only differs " +
2871 "in parameter modifier");
2876 Report.Error (111, Location,
2877 "Class `{0}' already defines a member called " +
2878 "`{1}' with the same parameter types",
2881 } else if (may_unify) {
2882 Report.Error (408, Location,
2883 "`{0}' cannot define overload members that " +
2884 "may unify for some type parameter substitutions",
2892 public CallingConventions GetCallingConvention (bool is_class)
2894 CallingConventions cc = 0;
2896 cc = Parameters.GetCallingConvention ();
2899 if ((ModFlags & Modifiers.STATIC) == 0)
2900 cc |= CallingConventions.HasThis;
2902 // FIXME: How is `ExplicitThis' used in C#?
2907 protected override void VerifyObsoleteAttribute()
2909 base.VerifyObsoleteAttribute ();
2911 if (parameter_types == null)
2914 foreach (Type type in parameter_types) {
2915 CheckUsageOfObsoleteAttribute (type);
2920 public class Method : MethodCore, IIteratorContainer, IMethodData {
2921 public MethodBuilder MethodBuilder;
2922 public MethodData MethodData;
2923 ReturnParameter return_attributes;
2926 /// Modifiers allowed in a class declaration
2928 const int AllowedModifiers =
2931 Modifiers.PROTECTED |
2932 Modifiers.INTERNAL |
2937 Modifiers.OVERRIDE |
2938 Modifiers.ABSTRACT |
2940 Modifiers.METHOD_YIELDS |
2943 const int AllowedInterfaceModifiers =
2944 Modifiers.NEW | Modifiers.UNSAFE;
2947 // return_type can be "null" for VOID values.
2949 public Method (DeclSpace ds, Expression return_type, int mod, bool is_iface,
2950 MemberName name, Parameters parameters, Attributes attrs,
2952 : base (ds, return_type, mod,
2953 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
2954 is_iface, name, attrs, parameters, l)
2958 public override AttributeTargets AttributeTargets {
2960 return AttributeTargets.Method | AttributeTargets.ReturnValue;
2965 // Returns the `System.Type' for the ReturnType of this
2966 // function. Provides a nice cache. (used between semantic analysis
2967 // and actual code generation
2969 public Type GetReturnType ()
2974 public override string GetSignatureForError()
2976 return TypeManager.CSharpSignature (MethodBuilder);
2980 /// Use this method when MethodBuilder is null
2982 public override string GetSignatureForError (TypeContainer tc)
2984 // TODO: move to parameters
2985 System.Text.StringBuilder args = new System.Text.StringBuilder ();
2986 if (parameter_info.Parameters.FixedParameters != null) {
2987 for (int i = 0; i < parameter_info.Parameters.FixedParameters.Length; ++i) {
2988 Parameter p = parameter_info.Parameters.FixedParameters [i];
2989 args.Append (p.GetSignatureForError ());
2991 if (i < parameter_info.Parameters.FixedParameters.Length - 1)
2996 return String.Concat (base.GetSignatureForError (tc), "(", args.ToString (), ")");
2999 void DuplicateEntryPoint (MethodInfo b, Location location)
3003 "Program `" + CodeGen.FileName +
3004 "' has more than one entry point defined: `" +
3005 TypeManager.CSharpSignature(b) + "'");
3008 void Report28 (MethodInfo b)
3012 "`" + TypeManager.CSharpSignature(b) +
3013 "' has the wrong signature to be an entry point");
3016 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
3018 if (b.ReturnType != TypeManager.void_type &&
3019 b.ReturnType != TypeManager.int32_type)
3022 if (pinfo.Count == 0)
3025 if (pinfo.Count > 1)
3028 Type t = pinfo.ParameterType(0);
3030 (t.GetArrayRank() == 1) &&
3031 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
3032 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
3038 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3040 if (a.Target == "return") {
3041 if (return_attributes == null)
3042 return_attributes = new ReturnParameter (MethodBuilder, Location);
3044 return_attributes.ApplyAttributeBuilder (a, cb);
3048 if (a.Type == TypeManager.methodimpl_attr_type && a.IsInternalCall) {
3049 MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
3052 if (a.Type == TypeManager.dllimport_type) {
3053 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3054 if ((ModFlags & extern_static) != extern_static) {
3055 //"The DllImport attribute must be specified on a method marked `static' and `extern'"
3056 Report.Error_T (601, a.Location);
3062 MethodBuilder.SetCustomAttribute (cb);
3066 // Checks our base implementation if any
3068 protected override bool CheckBase (TypeContainer container)
3070 base.CheckBase (container);
3072 // Check whether arguments were correct.
3073 if (!DoDefineParameters ())
3076 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
3078 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
3081 // Check in our class for dups
3083 ArrayList ar = container.Methods;
3085 int arLen = ar.Count;
3087 for (int i = 0; i < arLen; i++) {
3088 Method m = (Method) ar [i];
3089 if (IsDuplicateImplementation (container, m))
3097 // Verify if the parent has a type with the same name, and then
3098 // check whether we have to create a new slot for it or not.
3100 Type ptype = container.TypeBuilder.BaseType;
3102 // ptype is only null for System.Object while compiling corlib.
3103 if (ptype != null) {
3106 // Explicit implementations do not have `parent' methods, however,
3107 // the member cache stores them there. Without this check, we get
3108 // an incorrect warning in corlib.
3110 if (! IsExplicitImpl) {
3111 parent_method = (MethodInfo)((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
3112 container.TypeBuilder, Name, ParameterTypes, false);
3115 if (parent_method != null) {
3116 string name = parent_method.DeclaringType.Name + "." +
3119 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
3122 if ((ModFlags & Modifiers.NEW) == 0) {
3123 Type parent_ret = TypeManager.TypeToCoreType (
3124 parent_method.ReturnType);
3126 if (!parent_ret.Equals (MemberType)) {
3128 508, Location, container.MakeName (Name) + ": cannot " +
3129 "change return type when overriding " +
3130 "inherited member " + name);
3135 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (parent_method);
3137 Report.SymbolRelatedToPreviousError (parent_method);
3138 Report.Warning_T (672, Location, GetSignatureForError (container));
3141 if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
3142 WarningNotHiding (container);
3144 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3145 Report.Error (115, Location,
3146 container.MakeName (Name) +
3147 " no suitable methods found to override");
3150 } else if ((ModFlags & Modifiers.NEW) != 0)
3151 WarningNotHiding (container);
3159 public override bool Define (TypeContainer container)
3162 MethodBuilder mb = null;
3163 if (GenericMethod != null) {
3164 mb = container.TypeBuilder.DefineGenericMethod (Name, flags);
3165 if (!GenericMethod.Define (container, mb))
3167 decl = GenericMethod;
3171 if (!DoDefine (decl, container))
3174 if (!CheckBase (container))
3177 MethodData = new MethodData (this, ParameterInfo, ModFlags, flags,
3178 true, this, mb, GenericMethod);
3180 if (!MethodData.Define (container))
3184 // Setup iterator if we are one
3186 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
3187 IteratorHandler ih = new IteratorHandler (
3188 Name, container, MemberType,
3189 ParameterTypes, ParameterInfo,
3190 ModFlags, Location);
3192 Block new_block = ih.Setup (block);
3193 if (new_block == null)
3198 MethodBuilder = MethodData.MethodBuilder;
3201 // This is used to track the Entry Point,
3203 if (Name == "Main" &&
3204 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
3205 (RootContext.MainClass == null ||
3206 RootContext.MainClass == container.TypeBuilder.FullName)){
3207 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
3208 if (RootContext.EntryPoint == null) {
3209 if (container.IsGeneric){
3210 Report.Error (-201, Location,
3211 "Entry point can not be defined in a generic class");
3214 RootContext.EntryPoint = MethodBuilder;
3215 RootContext.EntryPointLocation = Location;
3217 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
3218 DuplicateEntryPoint (MethodBuilder, Location);
3221 Report28(MethodBuilder);
3230 public override void Emit (TypeContainer container)
3232 MethodData.Emit (container, this);
3233 base.Emit (container);
3238 void IIteratorContainer.SetYields ()
3240 ModFlags |= Modifiers.METHOD_YIELDS;
3243 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
3245 return IsIdentifierAndParamClsCompliant (ds, Name, MethodBuilder, parameter_types);
3248 #region IMethodData Members
3250 public CallingConventions CallingConventions {
3252 CallingConventions cc = Parameters.GetCallingConvention ();
3255 if ((ModFlags & Modifiers.STATIC) == 0)
3256 cc |= CallingConventions.HasThis;
3258 // FIXME: How is `ExplicitThis' used in C#?
3264 public Type ReturnType {
3270 public string MethodName {
3276 public new Location Location {
3278 return base.Location;
3282 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
3284 return new EmitContext (tc, ds, Location, ig, ReturnType, ModFlags, false);
3287 public ObsoleteAttribute GetObsoleteAttribute ()
3289 return GetObsoleteAttribute (ds);
3293 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
3295 public bool IsExcluded (EmitContext ec)
3297 if ((caching_flags & Flags.Excluded_Undetected) == 0)
3298 return (caching_flags & Flags.Excluded) != 0;
3300 caching_flags &= ~Flags.Excluded_Undetected;
3302 if (parent_method == null) {
3303 if (OptAttributes == null)
3306 Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type, ec);
3311 foreach (Attribute a in attrs) {
3312 string condition = a.GetConditionalAttributeValue (ds);
3313 if (RootContext.AllDefines.Contains (condition))
3317 caching_flags |= Flags.Excluded;
3321 IMethodData md = TypeManager.GetMethod (parent_method);
3323 if (AttributeTester.IsConditionalMethodExcluded (parent_method)) {
3324 caching_flags |= Flags.Excluded;
3330 if (md.IsExcluded (ec)) {
3331 caching_flags |= Flags.Excluded;
3337 GenericMethod IMethodData.GenericMethod {
3339 return GenericMethod;
3345 public abstract class ConstructorInitializer {
3346 ArrayList argument_list;
3347 protected ConstructorInfo parent_constructor;
3348 Parameters parameters;
3351 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
3354 this.argument_list = argument_list;
3355 this.parameters = parameters;
3359 public ArrayList Arguments {
3361 return argument_list;
3365 public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
3367 Expression parent_constructor_group;
3370 ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
3372 if (argument_list != null){
3373 foreach (Argument a in argument_list){
3374 if (!a.Resolve (ec, loc))
3378 ec.CurrentBlock = null;
3380 if (this is ConstructorBaseInitializer) {
3381 if (ec.ContainerType.BaseType == null)
3384 t = ec.ContainerType.BaseType;
3385 if (ec.ContainerType.IsValueType) {
3386 Report.Error (522, loc,
3387 "structs cannot call base class constructors");
3391 t = ec.ContainerType;
3393 parent_constructor_group = Expression.MemberLookup (
3394 ec, t, ".ctor", MemberTypes.Constructor,
3395 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3398 if (parent_constructor_group == null){
3399 parent_constructor_group = Expression.MemberLookup (
3400 ec, t, ".ctor", MemberTypes.Constructor,
3401 BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3404 if (parent_constructor_group != null)
3406 112, loc, "`{0}.{1}' is inaccessible due to " +
3407 "its protection level", t.FullName, t.Name);
3410 1501, loc, "Can not find a constructor for " +
3411 "this argument list");
3415 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (
3416 ec, (MethodGroupExpr) parent_constructor_group, argument_list,
3419 if (parent_constructor == null){
3420 Report.Error (1501, loc,
3421 "Can not find a constructor for this argument list");
3425 if (parent_constructor == caller_builder){
3426 Report.Error (515, String.Format ("Constructor `{0}' can not call itself", TypeManager.CSharpSignature (caller_builder)));
3433 public void Emit (EmitContext ec)
3435 if (parent_constructor != null){
3436 ec.Mark (loc, false);
3438 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
3440 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
3445 /// Method search for base ctor. (We do not cache it).
3447 Constructor GetOverloadedConstructor (TypeContainer tc)
3449 if (tc.InstanceConstructors == null)
3452 foreach (Constructor c in tc.InstanceConstructors) {
3453 if (Arguments == null) {
3454 if (c.ParameterTypes.Length == 0)
3462 int count = c.ParameterInfo.Count;
3464 c.ParameterInfo.ParameterModifier (count - 1) == Parameter.Modifier.PARAMS) {
3465 for (int i = 0; i < count-1; i++)
3466 if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
3471 if (c.ParameterTypes.Length != Arguments.Count)
3474 for (int i = 0; i < Arguments.Count; ++i)
3475 if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
3487 throw new InternalErrorException ();
3490 //TODO: implement caching when it will be necessary
3491 public virtual void CheckObsoleteAttribute (TypeContainer tc, Location loc)
3493 Constructor ctor = GetOverloadedConstructor (tc);
3497 ObsoleteAttribute oa = ctor.GetObsoleteAttribute (tc);
3501 AttributeTester.Report_ObsoleteMessage (oa, ctor.GetSignatureForError (), loc);
3505 public class ConstructorBaseInitializer : ConstructorInitializer {
3506 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
3507 base (argument_list, pars, l)
3511 public override void CheckObsoleteAttribute(TypeContainer tc, Location loc) {
3512 if (parent_constructor == null)
3515 TypeContainer type_ds = TypeManager.LookupTypeContainer (tc.TypeBuilder.BaseType);
3516 if (type_ds == null) {
3517 ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (parent_constructor);
3520 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (parent_constructor), loc);
3525 base.CheckObsoleteAttribute (type_ds, loc);
3530 public class ConstructorThisInitializer : ConstructorInitializer {
3531 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
3532 base (argument_list, pars, l)
3537 public class Constructor : MethodCore {
3538 public ConstructorBuilder ConstructorBuilder;
3539 public ConstructorInitializer Initializer;
3542 // Modifiers allowed for a constructor.
3544 public const int AllowedModifiers =
3546 Modifiers.PROTECTED |
3547 Modifiers.INTERNAL |
3553 bool has_compliant_args = false;
3555 // The spec claims that static is not permitted, but
3556 // my very own code has static constructors.
3558 public Constructor (DeclSpace ds, string name, int mod, Parameters args,
3559 ConstructorInitializer init, Location l)
3560 : base (ds, null, mod, AllowedModifiers, false,
3561 new MemberName (name), null, args, l)
3566 public override string GetSignatureForError()
3568 return TypeManager.CSharpSignature (ConstructorBuilder);
3571 public bool HasCompliantArgs {
3573 return has_compliant_args;
3577 public override AttributeTargets AttributeTargets {
3579 return AttributeTargets.Constructor;
3585 // Returns true if this is a default constructor
3587 public bool IsDefault ()
3589 if ((ModFlags & Modifiers.STATIC) != 0)
3590 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3591 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
3594 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3595 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
3596 (Initializer is ConstructorBaseInitializer) &&
3597 (Initializer.Arguments == null);
3600 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3602 ConstructorBuilder.SetCustomAttribute (cb);
3605 protected override bool CheckBase (TypeContainer container)
3607 base.CheckBase (container);
3609 // Check whether arguments were correct.
3610 if (!DoDefineParameters ())
3613 if ((ModFlags & Modifiers.STATIC) != 0)
3616 if (container is Struct && ParameterTypes.Length == 0) {
3617 Report.Error (568, Location,
3618 "Structs can not contain explicit parameterless " +
3624 // Check in our class for dups
3626 ArrayList ar = container.InstanceConstructors;
3628 int arLen = ar.Count;
3630 for (int i = 0; i < arLen; i++) {
3631 Constructor m = (Constructor) ar [i];
3632 if (IsDuplicateImplementation (container, m))
3641 // Creates the ConstructorBuilder
3643 public override bool Define (TypeContainer container)
3645 MethodAttributes ca = (MethodAttributes.RTSpecialName |
3646 MethodAttributes.SpecialName);
3648 if ((ModFlags & Modifiers.STATIC) != 0){
3649 ca |= MethodAttributes.Static | MethodAttributes.Private;
3651 ca |= MethodAttributes.HideBySig;
3653 if ((ModFlags & Modifiers.PUBLIC) != 0)
3654 ca |= MethodAttributes.Public;
3655 else if ((ModFlags & Modifiers.PROTECTED) != 0){
3656 if ((ModFlags & Modifiers.INTERNAL) != 0)
3657 ca |= MethodAttributes.FamORAssem;
3659 ca |= MethodAttributes.Family;
3660 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
3661 ca |= MethodAttributes.Assembly;
3662 else if (IsDefault ())
3663 ca |= MethodAttributes.Public;
3665 ca |= MethodAttributes.Private;
3668 // Check if arguments were correct.
3669 if (!CheckBase (container))
3672 ConstructorBuilder = container.TypeBuilder.DefineConstructor (
3673 ca, GetCallingConvention (container is Class), ParameterTypes);
3675 if ((ModFlags & Modifiers.UNSAFE) != 0)
3676 ConstructorBuilder.InitLocals = false;
3679 // HACK because System.Reflection.Emit is lame
3681 TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
3689 public override void Emit (TypeContainer container)
3691 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
3692 EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
3695 // extern methods have no bodies
3697 if ((ModFlags & Modifiers.EXTERN) != 0) {
3698 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
3700 179, Location, "External constructor `" +
3701 TypeManager.CSharpSignature (ConstructorBuilder) +
3702 "' can not have a body");
3705 } else if (block == null) {
3707 501, Location, "Constructor `" +
3708 TypeManager.CSharpSignature (ConstructorBuilder) +
3709 "' must declare a body since it is not marked extern");
3713 if ((ModFlags & Modifiers.STATIC) == 0){
3714 if (container is Class && Initializer == null)
3715 Initializer = new ConstructorBaseInitializer (
3716 null, Parameters.EmptyReadOnlyParameters, Location);
3720 // Spec mandates that Initializers will not have
3724 if (Initializer != null && !Initializer.Resolve (ConstructorBuilder, ec))
3726 ec.IsStatic = false;
3729 Parameters.LabelParameters (ec, ConstructorBuilder, Location);
3731 SymbolWriter sw = CodeGen.SymbolWriter;
3732 bool generate_debugging = false;
3734 if ((sw != null) && (block != null) &&
3735 !Location.IsNull (Location) &&
3736 !Location.IsNull (block.EndLocation) &&
3737 (Location.SymbolDocument != null)) {
3738 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
3740 generate_debugging = true;
3744 // Classes can have base initializers and instance field initializers.
3746 if (container is Class){
3747 if ((ModFlags & Modifiers.STATIC) == 0){
3750 // If we use a "this (...)" constructor initializer, then
3751 // do not emit field initializers, they are initialized in the other constructor
3753 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
3754 container.EmitFieldInitializers (ec);
3757 if (Initializer != null) {
3758 Initializer.CheckObsoleteAttribute (container, Location);
3759 Initializer.Emit (ec);
3762 if ((ModFlags & Modifiers.STATIC) != 0)
3763 container.EmitFieldInitializers (ec);
3765 if (OptAttributes != null)
3766 OptAttributes.Emit (ec, this);
3768 // If this is a non-static `struct' constructor and doesn't have any
3769 // initializer, it must initialize all of the struct's fields.
3770 if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
3771 Block.AddThisVariable (container, Location);
3773 ec.EmitTopBlock (block, ParameterInfo, Location);
3775 if (generate_debugging)
3778 base.Emit (container);
3783 // For constructors is needed to test only parameters
3784 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
3786 if (parameter_types == null || parameter_types.Length == 0)
3789 TypeContainer tc = ds as TypeContainer;
3791 for (int i = 0; i < tc.InstanceConstructors.Count; i++) {
3792 Constructor c = (Constructor) tc.InstanceConstructors [i];
3794 if (c == this || c.ParameterTypes.Length == 0)
3797 if (!c.IsClsCompliaceRequired (ds))
3800 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, c.ParameterTypes)) {
3801 Report.Error_T (3006, Location, GetSignatureForError ());
3806 if (tc.TypeBuilder.BaseType == null)
3809 DeclSpace temp_ds = TypeManager.LookupDeclSpace (tc.TypeBuilder.BaseType);
3810 if (temp_ds != null)
3811 return IsIdentifierClsCompliant (temp_ds);
3813 MemberInfo[] ml = tc.TypeBuilder.BaseType.FindMembers (MemberTypes.Constructor, BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance, null, null);
3814 // Skip parameter-less ctor
3818 foreach (ConstructorInfo ci in ml) {
3819 object[] cls_attribute = ci.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
3820 if (cls_attribute.Length == 1 && (!((CLSCompliantAttribute)cls_attribute[0]).IsCompliant))
3823 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, TypeManager.GetArgumentTypes (ci))) {
3824 Report.Error_T (3006, Location, GetSignatureForError ());
3832 protected override bool VerifyClsCompliance (DeclSpace ds)
3834 if (!base.VerifyClsCompliance (ds) || !IsExposedFromAssembly (ds)) {
3838 if (ds.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
3839 foreach (Type param in parameter_types) {
3840 if (param.IsArray) {
3845 has_compliant_args = true;
3852 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
3854 public interface IMethodData
3856 CallingConventions CallingConventions { get; }
3857 Location Location { get; }
3858 string MethodName { get; }
3859 Type[] ParameterTypes { get; }
3860 Type ReturnType { get; }
3861 GenericMethod GenericMethod { get; }
3863 Attributes OptAttributes { get; }
3864 Block Block { get; }
3866 EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig);
3867 ObsoleteAttribute GetObsoleteAttribute ();
3868 string GetSignatureForError (TypeContainer tc);
3869 bool IsExcluded (EmitContext ec);
3873 // Encapsulates most of the Method's state
3875 public class MethodData {
3877 readonly IMethodData method;
3880 // The return type of this method
3882 public readonly GenericMethod GenericMethod;
3883 public readonly InternalParameters ParameterInfo;
3886 // Are we implementing an interface ?
3888 public bool IsImplementing = false;
3893 protected MemberBase member;
3894 protected int modifiers;
3895 protected MethodAttributes flags;
3896 protected bool is_method;
3897 protected Type declaring_type;
3901 MethodBuilder builder = null;
3902 public MethodBuilder MethodBuilder {
3908 public Type DeclaringType {
3910 return declaring_type;
3914 public MethodData (MemberBase member, InternalParameters parameters,
3915 int modifiers, MethodAttributes flags, bool is_method,
3918 this.member = member;
3919 this.ParameterInfo = parameters;
3920 this.modifiers = modifiers;
3922 this.is_method = is_method;
3924 this.method = method;
3927 public MethodData (MemberBase member, InternalParameters parameters,
3928 int modifiers, MethodAttributes flags, bool is_method,
3929 IMethodData method, MethodBuilder builder,
3930 GenericMethod generic)
3931 : this (member, parameters, modifiers, flags, is_method, method)
3933 this.builder = builder;
3934 this.GenericMethod = generic;
3940 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method,
3943 if ((opt_attrs == null) || (opt_attrs.Attrs == null))
3946 foreach (Attribute a in opt_attrs.Attrs) {
3947 Type attr_type = a.ResolveType (ec, true);
3948 if (attr_type == TypeManager.conditional_attribute_type) {
3949 if (!ApplyConditionalAttribute (a))
3958 // Applies the `Conditional' attribute to the method.
3960 protected virtual bool ApplyConditionalAttribute (Attribute a)
3962 // The Conditional attribute is only valid on methods.
3964 Attribute.Error_AttributeNotValidForElement (a, method.Location);
3968 string condition = a.Conditional_GetConditionName ();
3970 if (condition == null)
3973 if (method.ReturnType != TypeManager.void_type) {
3974 Report.Error (578, method.Location,
3975 "Conditional not valid on `" + member.Name + "' " +
3976 "because its return type is not void");
3980 if ((modifiers & Modifiers.OVERRIDE) != 0) {
3981 Report.Error (243, method.Location,
3982 "Conditional not valid on `" + member.Name + "' " +
3983 "because it is an override method");
3987 if (member.IsExplicitImpl) {
3988 Report.Error (577, method.Location,
3989 "Conditional not valid on `" + member.Name + "' " +
3990 "because it is an explicit interface implementation");
3994 if (IsImplementing) {
3995 Report.Error (623, method.Location,
3996 "Conditional not valid on `" + member.Name + "' " +
3997 "because it is an interface method");
4004 public bool Define (TypeContainer container)
4006 MethodInfo implementing = null;
4009 ec = method.CreateEmitContext (container, null);
4011 if (method.OptAttributes != null)
4012 if (!ApplyAttributes (method.OptAttributes, is_method, ec))
4015 if (member.IsExplicitImpl)
4016 prefix = member.InterfaceType.FullName + ".";
4020 string name = method.MethodName;
4021 string method_name = prefix + name;
4022 Type[] ParameterTypes = method.ParameterTypes;
4024 if (container.Pending != null){
4025 if (member is Indexer)
4026 implementing = container.Pending.IsInterfaceIndexer (
4027 member.InterfaceType, method.ReturnType, ParameterTypes);
4029 implementing = container.Pending.IsInterfaceMethod (
4030 member.InterfaceType, name, method.ReturnType, ParameterTypes);
4032 if (member.InterfaceType != null && implementing == null){
4033 Report.Error (539, method.Location, "'{0}' in explicit interface declaration is not an interface", method_name);
4039 // For implicit implementations, make sure we are public, for
4040 // explicit implementations, make sure we are private.
4042 if (implementing != null){
4044 // Setting null inside this block will trigger a more
4045 // verbose error reporting for missing interface implementations
4047 // The "candidate" function has been flagged already
4048 // but it wont get cleared
4050 if (member.IsExplicitImpl){
4051 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
4052 Modifiers.Error_InvalidModifier (method.Location, "public, virtual or abstract");
4053 implementing = null;
4055 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
4056 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
4058 // If this is an interface method implementation,
4059 // check for public accessibility
4061 implementing = null;
4062 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
4063 // We may never be private.
4064 implementing = null;
4065 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
4067 // We may be protected if we're overriding something.
4069 implementing = null;
4074 // Static is not allowed
4076 if ((modifiers & Modifiers.STATIC) != 0){
4077 implementing = null;
4078 Modifiers.Error_InvalidModifier (method.Location, "static");
4083 // If implementing is still valid, set flags
4085 if (implementing != null){
4087 // When implementing interface methods, set NewSlot
4088 // unless, we are overwriting a method.
4090 if (implementing.DeclaringType.IsInterface){
4091 if ((modifiers & Modifiers.OVERRIDE) == 0)
4092 flags |= MethodAttributes.NewSlot;
4095 MethodAttributes.Virtual |
4096 MethodAttributes.HideBySig;
4098 // Set Final unless we're virtual, abstract or already overriding a method.
4099 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
4100 flags |= MethodAttributes.Final;
4102 // Get the method name from the explicit interface.
4103 if (member.InterfaceType != null) {
4104 name = implementing.Name;
4105 method_name = prefix + name;
4108 IsImplementing = true;
4111 DefineMethodBuilder (ec, container, method_name, ParameterTypes);
4113 if (builder == null)
4116 if (GenericMethod != null) {
4117 if (!GenericMethod.DefineType (ec, builder))
4121 if (container.CurrentType != null)
4122 declaring_type = container.CurrentType.ResolveType (ec);
4124 declaring_type = container.TypeBuilder;
4126 if ((modifiers & Modifiers.UNSAFE) != 0)
4127 builder.InitLocals = false;
4129 if (IsImplementing){
4131 // clear the pending implemntation flag
4133 if (member is Indexer) {
4134 container.Pending.ImplementIndexer (
4135 member.InterfaceType, builder, method.ReturnType,
4136 ParameterTypes, true);
4138 container.Pending.ImplementMethod (
4139 member.InterfaceType, name, method.ReturnType,
4140 ParameterTypes, member.IsExplicitImpl);
4142 if (member.IsExplicitImpl)
4143 container.TypeBuilder.DefineMethodOverride (
4144 builder, implementing);
4148 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
4149 Report.Error (111, method.Location,
4150 "Class `" + container.Name +
4151 "' already contains a definition with the " +
4152 "same return value and parameter types as the " +
4153 "'get' method of property `" + member.Name + "'");
4157 TypeManager.AddMethod (builder, method);
4163 /// Create the MethodBuilder for the method
4165 void DefineMethodBuilder (EmitContext ec, TypeContainer container, string method_name, Type[] ParameterTypes)
4167 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
4169 if ((modifiers & extern_static) == extern_static) {
4171 if (method.OptAttributes != null) {
4172 Attribute dllimport_attribute = method.OptAttributes.Search (TypeManager.dllimport_type, ec);
4173 if (dllimport_attribute != null) {
4174 flags |= MethodAttributes.PinvokeImpl;
4175 builder = dllimport_attribute.DefinePInvokeMethod (
4176 ec, container.TypeBuilder, method_name, flags,
4177 method.ReturnType, ParameterTypes);
4183 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
4184 // We are more strict than Microsoft and report CS0626 like error
4185 if (method.OptAttributes == null ||
4186 !method.OptAttributes.Contains (TypeManager.methodimpl_attr_type, ec)) {
4187 //"Method, operator, or accessor '{0}' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation"
4188 Report.Error_T (626, method.Location, method.GetSignatureForError (container));
4193 if (builder == null)
4194 builder = container.TypeBuilder.DefineMethod (
4195 method_name, flags, method.CallingConventions,
4196 method.ReturnType, ParameterTypes);
4198 builder.SetGenericMethodSignature (
4199 flags, method.CallingConventions,
4200 method.ReturnType, ParameterTypes);
4206 public void Emit (TypeContainer container, Attributable kind)
4210 if ((flags & MethodAttributes.PinvokeImpl) == 0)
4211 ec = method.CreateEmitContext (container, builder.GetILGenerator ());
4213 ec = method.CreateEmitContext (container, null);
4215 Location loc = method.Location;
4216 Attributes OptAttributes = method.OptAttributes;
4218 if (OptAttributes != null)
4219 OptAttributes.Emit (ec, kind);
4221 if (member is MethodCore)
4222 ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, loc);
4224 SymbolWriter sw = CodeGen.SymbolWriter;
4225 Block block = method.Block;
4228 // abstract or extern methods have no bodies
4230 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
4231 if (block == null) {
4232 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0) &&
4233 !Location.IsNull (loc) &&
4234 (method.Location.SymbolDocument != null)) {
4235 sw.OpenMethod (container, MethodBuilder, loc, loc);
4243 // abstract or extern methods have no bodies.
4245 if ((modifiers & Modifiers.ABSTRACT) != 0)
4247 500, method.Location, "Abstract method `" +
4248 TypeManager.CSharpSignature (builder) +
4249 "' can not have a body");
4251 if ((modifiers & Modifiers.EXTERN) != 0)
4253 179, method.Location, "External method `" +
4254 TypeManager.CSharpSignature (builder) +
4255 "' can not have a body");
4261 // Methods must have a body unless they're extern or abstract
4263 if (block == null) {
4265 501, method.Location, "Method `" +
4266 TypeManager.CSharpSignature (builder) +
4267 "' must declare a body since it is not marked " +
4268 "abstract or extern");
4273 // Handle destructors specially
4275 // FIXME: This code generates buggy code
4277 if ((sw != null) && !Location.IsNull (loc) &&
4278 !Location.IsNull (block.EndLocation) &&
4279 (loc.SymbolDocument != null)) {
4280 sw.OpenMethod (container, MethodBuilder, loc, block.EndLocation);
4282 if (member is Destructor)
4283 EmitDestructor (ec, block);
4285 ec.EmitTopBlock (block, ParameterInfo, loc);
4289 if (member is Destructor)
4290 EmitDestructor (ec, block);
4292 ec.EmitTopBlock (block, ParameterInfo, loc);
4296 void EmitDestructor (EmitContext ec, Block block)
4298 ILGenerator ig = ec.ig;
4300 Label finish = ig.DefineLabel ();
4302 block.SetDestructor ();
4304 ig.BeginExceptionBlock ();
4305 ec.ReturnLabel = finish;
4306 ec.HasReturnLabel = true;
4307 ec.EmitTopBlock (block, null, method.Location);
4309 // ig.MarkLabel (finish);
4310 ig.BeginFinallyBlock ();
4312 if (ec.ContainerType.BaseType != null) {
4313 Expression member_lookup = Expression.MemberLookup (
4314 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
4315 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
4317 if (member_lookup != null){
4318 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
4320 ig.Emit (OpCodes.Ldarg_0);
4321 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
4325 ig.EndExceptionBlock ();
4326 //ig.MarkLabel (ec.ReturnLabel);
4327 ig.Emit (OpCodes.Ret);
4331 public class Destructor : Method {
4333 public Destructor (DeclSpace ds, Expression return_type, int mod, string name,
4334 Parameters parameters, Attributes attrs, Location l)
4335 : base (ds, return_type, mod, false, new MemberName (name),
4336 parameters, attrs, l)
4341 abstract public class MemberBase : MemberCore {
4342 public Expression Type;
4344 public MethodAttributes flags;
4346 protected readonly int explicit_mod_flags;
4349 // The "short" name of this property / indexer / event. This is the
4350 // name without the explicit interface.
4352 public string ShortName;
4355 // The type of this property / indexer / event
4357 public Type MemberType;
4360 // If true, this is an explicit interface implementation
4362 public bool IsExplicitImpl = false;
4365 // The name of the interface we are explicitly implementing
4367 public Expression ExplicitInterfaceName = null;
4370 // Whether this is an interface member.
4372 public bool IsInterface;
4375 // If true, the interface type we are explicitly implementing
4377 public Type InterfaceType = null;
4380 // The method we're overriding if this is an override method.
4382 protected MethodInfo parent_method = null;
4383 public MethodInfo ParentMethod {
4385 return parent_method;
4390 // The constructor is only exposed to our children
4392 protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod,
4393 MemberName name, Attributes attrs, Location loc)
4394 : base (name, attrs, loc)
4396 explicit_mod_flags = mod;
4398 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
4401 protected virtual bool CheckBase (TypeContainer container)
4403 if ((container is Struct) || (RootContext.WarningLevel > 3)){
4404 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
4405 if (container is Struct){
4406 Report.Error (666, Location, "Protected member in struct declaration");
4409 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
4415 protected void WarningNotHiding (TypeContainer parent)
4419 "The member " + parent.MakeName (Name) + " does not hide an " +
4420 "inherited member. The keyword new is not required");
4424 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
4428 // FIXME: report the old/new permissions?
4431 507, Location, parent.MakeName (Name) +
4432 ": can't change the access modifiers when overriding inherited " +
4433 "member `" + name + "'");
4436 protected abstract bool CheckGenericOverride (MethodInfo method, string name);
4439 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
4440 // that have been defined.
4442 // `name' is the user visible name for reporting errors (this is used to
4443 // provide the right name regarding method names and properties)
4445 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
4446 MethodInfo mb, string name)
4450 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4451 if (!(mb.IsAbstract || mb.IsVirtual)){
4453 506, Location, parent.MakeName (Name) +
4454 ": cannot override inherited member `" +
4455 name + "' because it is not " +
4456 "virtual, abstract or override");
4460 // Now we check that the overriden method is not final
4463 // This happens when implementing interface methods.
4464 if (mb.IsHideBySig && mb.IsVirtual) {
4466 506, Location, parent.MakeName (Name) +
4467 ": cannot override inherited member `" +
4468 name + "' because it is not " +
4469 "virtual, abstract or override");
4471 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
4472 "override inherited member `" + name +
4473 "' because it is sealed.");
4478 // Check that the constraints match when overriding a
4482 if (!CheckGenericOverride (mb, name))
4486 // Check that the permissions are not being changed
4488 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
4489 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
4492 // special case for "protected internal"
4495 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4497 // when overriding protected internal, the method can be declared
4498 // protected internal only within the same assembly
4501 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4502 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
4504 // assemblies differ - report an error
4507 Error_CannotChangeAccessModifiers (parent, mb, name);
4509 } else if (thisp != parentp) {
4511 // same assembly, but other attributes differ - report an error
4514 Error_CannotChangeAccessModifiers (parent, mb, name);
4517 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
4519 // if it's not "protected internal", it must be "protected"
4522 Error_CannotChangeAccessModifiers (parent, mb, name);
4524 } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
4526 // protected within the same assembly - an error
4528 Error_CannotChangeAccessModifiers (parent, mb, name);
4530 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
4531 (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
4533 // protected ok, but other attributes differ - report an error
4535 Error_CannotChangeAccessModifiers (parent, mb, name);
4539 if (thisp != parentp){
4540 Error_CannotChangeAccessModifiers (parent, mb, name);
4546 if (mb.IsVirtual || mb.IsAbstract){
4547 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4548 if (Name != "Finalize"){
4550 114, 2, Location, parent.MakeName (Name) +
4551 " hides inherited member `" + name +
4552 "'. To make the current member override that " +
4553 "implementation, add the override keyword, " +
4554 "otherwise use the new keyword");
4555 ModFlags |= Modifiers.NEW;
4559 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4560 if (Name != "Finalize"){
4562 108, 1, Location, "The keyword new is required on " +
4563 parent.MakeName (Name) + " because it hides " +
4564 "inherited member `" + name + "'");
4565 ModFlags |= Modifiers.NEW;
4573 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
4577 foreach (Type partype in parameters){
4578 if (partype == TypeManager.void_type) {
4580 1547, Location, "Keyword 'void' cannot " +
4581 "be used in this context");
4585 if (partype.IsPointer){
4588 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
4592 if (ds.AsAccessible (partype, ModFlags))
4595 if (this is Indexer)
4596 Report.Error (55, Location,
4597 "Inconsistent accessibility: parameter type `" +
4598 TypeManager.CSharpName (partype) + "' is less " +
4599 "accessible than indexer `" + Name + "'");
4600 else if ((this is Method) && ((Method) this).IsOperator)
4601 Report.Error (57, Location,
4602 "Inconsistent accessibility: parameter type `" +
4603 TypeManager.CSharpName (partype) + "' is less " +
4604 "accessible than operator `" + Name + "'");
4606 Report.Error (51, Location,
4607 "Inconsistent accessibility: parameter type `" +
4608 TypeManager.CSharpName (partype) + "' is less " +
4609 "accessible than method `" + Name + "'");
4616 protected virtual bool DoDefine (DeclSpace decl, TypeContainer container)
4622 ModFlags = Modifiers.PUBLIC |
4623 Modifiers.ABSTRACT |
4624 Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE);
4626 flags = MethodAttributes.Public |
4627 MethodAttributes.Abstract |
4628 MethodAttributes.HideBySig |
4629 MethodAttributes.NewSlot |
4630 MethodAttributes.Virtual;
4632 if (!container.MethodModifiersValid (ModFlags, Name, Location))
4635 flags = Modifiers.MethodAttr (ModFlags);
4638 // Lookup Type, verify validity
4639 MemberType = decl.ResolveType (Type, false, Location);
4640 if (MemberType == null)
4643 if ((container.ModFlags & Modifiers.SEALED) != 0){
4644 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
4645 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
4650 // verify accessibility
4651 if (!container.AsAccessible (MemberType, ModFlags)) {
4652 if (this is Property)
4653 Report.Error (53, Location,
4654 "Inconsistent accessibility: property type `" +
4655 TypeManager.CSharpName (MemberType) + "' is less " +
4656 "accessible than property `" + Name + "'");
4657 else if (this is Indexer)
4658 Report.Error (54, Location,
4659 "Inconsistent accessibility: indexer return type `" +
4660 TypeManager.CSharpName (MemberType) + "' is less " +
4661 "accessible than indexer `" + Name + "'");
4662 else if (this is Method) {
4663 if (((Method) this).IsOperator)
4664 Report.Error (56, Location,
4665 "Inconsistent accessibility: return type `" +
4666 TypeManager.CSharpName (MemberType) + "' is less " +
4667 "accessible than operator `" + Name + "'");
4669 Report.Error (50, Location,
4670 "Inconsistent accessibility: return type `" +
4671 TypeManager.CSharpName (MemberType) + "' is less " +
4672 "accessible than method `" + Name + "'");
4674 Report.Error (52, Location,
4675 "Inconsistent accessibility: field type `" +
4676 TypeManager.CSharpName (MemberType) + "' is less " +
4677 "accessible than field `" + Name + "'");
4681 if (MemberType.IsPointer && !UnsafeOK (container))
4685 // Check for explicit interface implementation
4687 if (MemberName.TypeName != null) {
4688 ExplicitInterfaceName = MemberName.TypeName.GetTypeExpression (Location);
4689 ShortName = MemberName.Name;
4693 if (ExplicitInterfaceName != null) {
4694 InterfaceType = container.ResolveType (
4695 ExplicitInterfaceName, false, Location);
4696 if (InterfaceType == null)
4699 if (InterfaceType.IsClass) {
4700 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
4704 // Compute the full name that we need to export.
4705 Name = InterfaceType.FullName + "." + ShortName;
4707 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
4710 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
4712 IsExplicitImpl = true;
4714 IsExplicitImpl = false;
4720 /// Use this method when MethodBuilder is null
4722 public virtual string GetSignatureForError (TypeContainer tc)
4724 return String.Concat (tc.Name, '.', Name);
4727 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
4729 return IsIdentifierAndParamClsCompliant (ds, Name, null, null);
4732 protected override bool VerifyClsCompliance(DeclSpace ds)
4734 if (base.VerifyClsCompliance (ds)) {
4738 if (IsInterface && HasClsCompliantAttribute && ds.IsClsCompliaceRequired (ds)) {
4739 Report.Error_T (3010, Location, GetSignatureForError ());
4744 protected override void VerifyObsoleteAttribute()
4746 CheckUsageOfObsoleteAttribute (MemberType);
4751 // Fields and Events both generate FieldBuilders, we use this to share
4752 // their common bits. This is also used to flag usage of the field
4754 abstract public class FieldBase : MemberBase {
4755 public FieldBuilder FieldBuilder;
4756 public Status status;
4759 public enum Status : byte { ASSIGNED = 1, USED = 2 }
4761 static string[] attribute_targets = new string [] { "field" };
4764 // The constructor is only exposed to our children
4766 protected FieldBase (Expression type, int mod, int allowed_mod, MemberName name,
4767 object init, Attributes attrs, Location loc)
4768 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
4773 public override AttributeTargets AttributeTargets {
4775 return AttributeTargets.Field;
4779 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4781 if (a.Type == TypeManager.marshal_as_attr_type) {
4782 UnmanagedMarshal marshal = a.GetMarshal ();
4783 if (marshal != null) {
4784 FieldBuilder.SetMarshal (marshal);
4787 Report.Warning_T (-24, a.Location);
4792 FieldBuilder.SetCustomAttribute (cb);
4796 // Whether this field has an initializer.
4798 public bool HasInitializer {
4800 return init != null;
4804 protected readonly Object init;
4806 Expression init_expr;
4807 bool init_expr_initialized = false;
4809 protected override bool CheckGenericOverride (MethodInfo method, string name)
4815 // Resolves and returns the field initializer.
4817 public Expression GetInitializerExpression (EmitContext ec)
4819 if (init_expr_initialized)
4823 if (init is Expression)
4824 e = (Expression) init;
4826 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
4828 ec.IsFieldInitializer = true;
4829 e = e.DoResolve (ec);
4830 ec.IsFieldInitializer = false;
4833 init_expr_initialized = true;
4838 protected override bool DoDefine (DeclSpace ds, TypeContainer container)
4840 if (!base.DoDefine (ds, container))
4843 if (MemberType == TypeManager.void_type) {
4844 Report.Error (1547, Location,
4845 "Keyword 'void' cannot be used in this context");
4852 public override string GetSignatureForError ()
4854 return TypeManager.GetFullNameSignature (FieldBuilder);
4857 protected override string[] ValidAttributeTargets {
4859 return attribute_targets;
4863 protected override bool VerifyClsCompliance (DeclSpace ds)
4865 if (!base.VerifyClsCompliance (ds))
4868 if (FieldBuilder == null) {
4872 if (!AttributeTester.IsClsCompliant (FieldBuilder.FieldType)) {
4873 Report.Error_T (3003, Location, GetSignatureForError ());
4879 public void SetAssigned ()
4881 status |= Status.ASSIGNED;
4886 // The Field class is used to represents class/struct fields during parsing.
4888 public class Field : FieldBase {
4890 // Modifiers allowed in a class declaration
4892 const int AllowedModifiers =
4895 Modifiers.PROTECTED |
4896 Modifiers.INTERNAL |
4899 Modifiers.VOLATILE |
4903 public Field (Expression type, int mod, string name, Object expr_or_array_init,
4904 Attributes attrs, Location loc)
4905 : base (type, mod, AllowedModifiers, new MemberName (name),
4906 expr_or_array_init, attrs, loc)
4910 public override bool Define (TypeContainer container)
4912 MemberType = container.ResolveType (Type, false, Location);
4914 if (MemberType == null)
4917 CheckBase (container);
4919 if (!container.AsAccessible (MemberType, ModFlags)) {
4920 Report.Error (52, Location,
4921 "Inconsistent accessibility: field type `" +
4922 TypeManager.CSharpName (MemberType) + "' is less " +
4923 "accessible than field `" + Name + "'");
4927 if (MemberType.IsPointer && !UnsafeOK (container))
4930 if (RootContext.WarningLevel > 1){
4931 Type ptype = container.TypeBuilder.BaseType;
4933 // ptype is only null for System.Object while compiling corlib.
4935 TypeContainer.FindMembers (
4936 ptype, MemberTypes.Method,
4937 BindingFlags.Public |
4938 BindingFlags.Static | BindingFlags.Instance,
4939 System.Type.FilterName, Name);
4943 if ((ModFlags & Modifiers.VOLATILE) != 0){
4944 if (!MemberType.IsClass){
4945 Type vt = MemberType;
4947 if (TypeManager.IsEnumType (vt))
4948 vt = TypeManager.EnumToUnderlying (MemberType);
4950 if (!((vt == TypeManager.bool_type) ||
4951 (vt == TypeManager.sbyte_type) ||
4952 (vt == TypeManager.byte_type) ||
4953 (vt == TypeManager.short_type) ||
4954 (vt == TypeManager.ushort_type) ||
4955 (vt == TypeManager.int32_type) ||
4956 (vt == TypeManager.uint32_type) ||
4957 (vt == TypeManager.char_type) ||
4958 (vt == TypeManager.float_type) ||
4959 (!vt.IsValueType))){
4961 677, Location, container.MakeName (Name) +
4962 " A volatile field can not be of type `" +
4963 TypeManager.CSharpName (vt) + "'");
4968 if ((ModFlags & Modifiers.READONLY) != 0){
4971 "A field can not be both volatile and readonly");
4976 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
4978 if (container is Struct &&
4979 ((fa & FieldAttributes.Static) == 0) &&
4980 MemberType == container.TypeBuilder &&
4981 !TypeManager.IsBuiltinType (MemberType)){
4982 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name +
4983 "' causes a cycle in the structure layout");
4988 FieldBuilder = container.TypeBuilder.DefineField (
4989 Name, MemberType, Modifiers.FieldAttr (ModFlags));
4991 TypeManager.RegisterFieldBase (FieldBuilder, this);
4993 catch (ArgumentException) {
4994 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
5001 public override void Emit (TypeContainer tc)
5003 if (OptAttributes != null) {
5004 EmitContext ec = new EmitContext (tc, Location, null, FieldBuilder.FieldType, ModFlags);
5005 OptAttributes.Emit (ec, this);
5013 // `set' and `get' accessors are represented with an Accessor.
5015 public class Accessor {
5017 // Null if the accessor is empty, or a Block if not
5020 public Attributes Attributes;
5022 public Accessor (Block b, Attributes attrs)
5030 // Properties and Indexers both generate PropertyBuilders, we use this to share
5031 // their common bits.
5033 abstract public class PropertyBase : MethodCore {
5035 public class GetMethod: PropertyMethod
5037 static string[] attribute_targets = new string [] { "method", "return" };
5039 public GetMethod (MethodCore method, Accessor accessor):
5040 base (method, accessor)
5044 public override MethodBuilder Define(TypeContainer container)
5046 method_data = new MethodData (method, method.ParameterInfo, method.ModFlags, method.flags, false, this);
5048 if (!method_data.Define (container))
5051 return method_data.MethodBuilder;
5054 public override string GetSignatureForError (TypeContainer tc)
5056 return String.Concat (base.GetSignatureForError (tc), ".get");
5059 public override string MethodName
5062 return "get_" + method.ShortName;
5066 public override Type ReturnType {
5068 return method.MemberType;
5072 protected override string[] ValidAttributeTargets {
5074 return attribute_targets;
5079 public class SetMethod: PropertyMethod {
5081 static string[] attribute_targets = new string [] { "method", "param", "return" };
5082 ImplicitParameter param_attr;
5084 public SetMethod (MethodCore method, Accessor accessor):
5085 base (method, accessor)
5089 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5091 if (a.Target == "param") {
5092 if (param_attr == null)
5093 param_attr = new ImplicitParameter (method_data.MethodBuilder);
5095 param_attr.ApplyAttributeBuilder (a, cb);
5099 base.ApplyAttributeBuilder (a, cb);
5102 protected virtual InternalParameters GetParameterInfo (TypeContainer container)
5104 Parameter [] parms = new Parameter [1];
5105 parms [0] = new Parameter (method.Type, "value", Parameter.Modifier.NONE, null);
5106 return new InternalParameters (
5107 container, new Parameters (parms, null, method.Location));
5110 public override MethodBuilder Define(TypeContainer container)
5112 method_data = new MethodData (method, GetParameterInfo (container), method.ModFlags, method.flags, false, this);
5114 if (!method_data.Define (container))
5117 return method_data.MethodBuilder;
5120 public override string GetSignatureForError (TypeContainer tc)
5122 return String.Concat (base.GetSignatureForError (tc), ".set");
5125 public override string MethodName {
5127 return "set_" + method.ShortName;
5131 public override Type[] ParameterTypes {
5133 return new Type[] { method.MemberType };
5137 public override Type ReturnType {
5139 return TypeManager.void_type;
5143 protected override string[] ValidAttributeTargets {
5145 return attribute_targets;
5150 static string[] attribute_targets = new string [] { "property" };
5152 public abstract class PropertyMethod: Attributable, IMethodData {
5153 protected readonly MethodCore method;
5154 protected MethodData method_data;
5157 ReturnParameter return_attributes;
5159 public PropertyMethod (MethodCore method, Accessor accessor):
5160 base (accessor.Attributes)
5162 this.method = method;
5163 this.block = accessor.Block;
5166 public override AttributeTargets AttributeTargets {
5168 return AttributeTargets.Method | AttributeTargets.ReturnValue;
5172 public override bool IsClsCompliaceRequired(DeclSpace ds)
5174 return method.IsClsCompliaceRequired (ds);
5177 public InternalParameters ParameterInfo
5180 return method_data.ParameterInfo;
5184 #region IMethodData Members
5186 public Block Block {
5192 public CallingConventions CallingConventions {
5194 return CallingConventions.Standard;
5198 public abstract MethodBuilder Define (TypeContainer container);
5200 public void Emit (TypeContainer container)
5202 method_data.Emit (container, this);
5206 public virtual string GetSignatureForError (TypeContainer tc)
5208 return String.Concat (tc.Name, '.', method.Name);
5211 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5213 if (a.Target == "return") {
5214 if (return_attributes == null)
5215 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
5217 return_attributes.ApplyAttributeBuilder (a, cb);
5221 method_data.MethodBuilder.SetCustomAttribute (cb);
5224 public virtual Type[] ParameterTypes {
5226 return TypeManager.NoTypes;
5230 public abstract Type ReturnType { get; }
5232 public Location Location {
5234 return method.Location;
5238 public abstract string MethodName { get; }
5240 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
5242 return new EmitContext (tc, method.ds, method.Location, ig, ReturnType, method.ModFlags, false);
5245 public ObsoleteAttribute GetObsoleteAttribute ()
5247 return method.GetObsoleteAttribute (method.ds);
5250 public bool IsExcluded (EmitContext ec)
5255 GenericMethod IMethodData.GenericMethod {
5263 public PropertyMethod Get, Set;
5264 public PropertyBuilder PropertyBuilder;
5265 public MethodBuilder GetBuilder, SetBuilder;
5267 protected EmitContext ec;
5269 public PropertyBase (DeclSpace ds, Expression type, int mod_flags,
5270 int allowed_mod, bool is_iface, MemberName name,
5271 Parameters parameters, Attributes attrs,
5273 : base (ds, type, mod_flags, allowed_mod, is_iface, name,
5274 attrs, parameters, loc)
5278 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5280 PropertyBuilder.SetCustomAttribute (cb);
5283 public override AttributeTargets AttributeTargets {
5285 return AttributeTargets.Property;
5289 protected override bool DoDefine (DeclSpace decl, TypeContainer container)
5291 if (!base.DoDefine (decl, container))
5294 ec = new EmitContext (container, Location, null, MemberType, ModFlags);
5299 public override string GetSignatureForError()
5301 return TypeManager.CSharpSignature (PropertyBuilder, false);
5304 protected virtual string RealMethodName {
5310 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
5312 if (!IsIdentifierAndParamClsCompliant (ds, RealMethodName, null, null))
5315 if (Get != null && !IsIdentifierAndParamClsCompliant (ds, "get_" + RealMethodName, null, null))
5318 if (Set != null && !IsIdentifierAndParamClsCompliant (ds, "set_" + RealMethodName, null, null))
5326 // Checks our base implementation if any
5328 protected override bool CheckBase (TypeContainer container)
5330 base.CheckBase (container);
5332 // Check whether arguments were correct.
5333 if (!DoDefineParameters ())
5340 // Check in our class for dups
5342 ArrayList ar = container.Properties;
5344 int arLen = ar.Count;
5346 for (int i = 0; i < arLen; i++) {
5347 Property m = (Property) ar [i];
5348 if (IsDuplicateImplementation (container, m))
5357 MethodSignature ms, base_ms;
5358 if (this is Indexer) {
5359 string name, base_name;
5361 report_name = "this";
5362 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
5363 ms = new MethodSignature (name, null, ParameterTypes);
5364 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
5365 base_ms = new MethodSignature (base_name, null, ParameterTypes);
5368 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
5372 // Verify if the parent has a type with the same name, and then
5373 // check whether we have to create a new slot for it or not.
5375 Type ptype = container.TypeBuilder.BaseType;
5377 // ptype is only null for System.Object while compiling corlib.
5378 if (ptype == null) {
5379 if ((ModFlags & Modifiers.NEW) != 0)
5380 WarningNotHiding (container);
5385 MemberInfo parent_member = null;
5388 // Explicit implementations do not have `parent' methods, however,
5389 // the member cache stores them there. Without this check, we get
5390 // an incorrect warning in corlib.
5392 if (! IsExplicitImpl) {
5393 parent_member = ((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
5394 container.TypeBuilder, Name, ParameterTypes, true);
5397 if (parent_member is PropertyInfo) {
5398 PropertyInfo parent_property = (PropertyInfo)parent_member;
5400 string name = parent_property.DeclaringType.Name + "." +
5401 parent_property.Name;
5403 MethodInfo get, set, parent_method;
5404 get = parent_property.GetGetMethod (true);
5405 set = parent_property.GetSetMethod (true);
5408 parent_method = get;
5409 else if (set != null)
5410 parent_method = set;
5412 throw new Exception ("Internal error!");
5414 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
5417 if ((ModFlags & Modifiers.NEW) == 0) {
5418 Type parent_type = TypeManager.TypeToCoreType (
5419 parent_property.PropertyType);
5421 if (parent_type != MemberType) {
5423 508, Location, container.MakeName (Name) + ": cannot " +
5424 "change return type when overriding " +
5425 "inherited member " + name);
5429 } else if (parent_member == null){
5430 if ((ModFlags & Modifiers.NEW) != 0)
5431 WarningNotHiding (container);
5433 if ((ModFlags & Modifiers.OVERRIDE) != 0){
5434 if (this is Indexer)
5435 Report.Error (115, Location,
5436 container.MakeName (Name) +
5437 " no suitable indexers found to override");
5439 Report.Error (115, Location,
5440 container.MakeName (Name) +
5441 " no suitable properties found to override");
5448 public override void Emit (TypeContainer tc)
5451 // The PropertyBuilder can be null for explicit implementations, in that
5452 // case, we do not actually emit the ".property", so there is nowhere to
5453 // put the attribute
5455 if (PropertyBuilder != null && OptAttributes != null)
5456 OptAttributes.Emit (ec, this);
5467 protected override string[] ValidAttributeTargets {
5469 return attribute_targets;
5474 public class Property : PropertyBase, IIteratorContainer {
5475 const int AllowedModifiers =
5478 Modifiers.PROTECTED |
5479 Modifiers.INTERNAL |
5483 Modifiers.OVERRIDE |
5484 Modifiers.ABSTRACT |
5487 Modifiers.METHOD_YIELDS |
5490 const int AllowedInterfaceModifiers =
5493 public Property (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
5494 MemberName name, Attributes attrs, Accessor get_block,
5495 Accessor set_block, Location loc)
5496 : base (ds, type, mod_flags,
5497 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5498 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
5501 if (get_block != null)
5502 Get = new GetMethod (this, get_block);
5504 if (set_block != null)
5505 Set = new SetMethod (this, set_block);
5508 public override bool Define (TypeContainer container)
5510 if (!DoDefine (container, container))
5513 if (!CheckBase (container))
5516 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
5520 GetBuilder = Get.Define (container);
5521 if (GetBuilder == null)
5525 // Setup iterator if we are one
5527 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
5528 IteratorHandler ih = new IteratorHandler (
5529 "get", container, MemberType,
5530 TypeManager.NoTypes, Get.ParameterInfo, ModFlags, Location);
5532 Block new_block = ih.Setup (block);
5533 if (new_block == null)
5540 SetBuilder = Set.Define (container);
5541 if (SetBuilder == null)
5544 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
5547 // FIXME - PropertyAttributes.HasDefault ?
5549 PropertyAttributes prop_attr = PropertyAttributes.None;
5551 prop_attr |= PropertyAttributes.RTSpecialName |
5552 PropertyAttributes.SpecialName;
5554 if (!IsExplicitImpl){
5555 PropertyBuilder = container.TypeBuilder.DefineProperty (
5556 Name, prop_attr, MemberType, null);
5559 PropertyBuilder.SetGetMethod (GetBuilder);
5562 PropertyBuilder.SetSetMethod (SetBuilder);
5565 // HACK for the reasons exposed above
5567 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
5570 "Class `" + container.Name +
5571 "' already contains a definition for the property `" +
5579 public void SetYields ()
5581 ModFlags |= Modifiers.METHOD_YIELDS;
5586 /// Gigantic workaround for lameness in SRE follows :
5587 /// This class derives from EventInfo and attempts to basically
5588 /// wrap around the EventBuilder so that FindMembers can quickly
5589 /// return this in it search for members
5591 public class MyEventBuilder : EventInfo {
5594 // We use this to "point" to our Builder which is
5595 // not really a MemberInfo
5597 EventBuilder MyBuilder;
5600 // We "catch" and wrap these methods
5602 MethodInfo raise, remove, add;
5604 EventAttributes attributes;
5605 Type declaring_type, reflected_type, event_type;
5610 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
5612 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
5614 // And now store the values in our own fields.
5616 declaring_type = type_builder;
5618 reflected_type = type_builder;
5620 attributes = event_attr;
5623 this.event_type = event_type;
5627 // Methods that you have to override. Note that you only need
5628 // to "implement" the variants that take the argument (those are
5629 // the "abstract" methods, the others (GetAddMethod()) are
5632 public override MethodInfo GetAddMethod (bool nonPublic)
5637 public override MethodInfo GetRemoveMethod (bool nonPublic)
5642 public override MethodInfo GetRaiseMethod (bool nonPublic)
5648 // These methods make "MyEventInfo" look like a Builder
5650 public void SetRaiseMethod (MethodBuilder raiseMethod)
5652 raise = raiseMethod;
5653 MyBuilder.SetRaiseMethod (raiseMethod);
5656 public void SetRemoveOnMethod (MethodBuilder removeMethod)
5658 remove = removeMethod;
5659 MyBuilder.SetRemoveOnMethod (removeMethod);
5662 public void SetAddOnMethod (MethodBuilder addMethod)
5665 MyBuilder.SetAddOnMethod (addMethod);
5668 public void SetCustomAttribute (CustomAttributeBuilder cb)
5670 MyBuilder.SetCustomAttribute (cb);
5673 public override object [] GetCustomAttributes (bool inherit)
5675 // FIXME : There's nothing which can be seemingly done here because
5676 // we have no way of getting at the custom attribute objects of the
5681 public override object [] GetCustomAttributes (Type t, bool inherit)
5683 // FIXME : Same here !
5687 public override bool IsDefined (Type t, bool b)
5692 public override EventAttributes Attributes {
5698 public override string Name {
5704 public override Type DeclaringType {
5706 return declaring_type;
5710 public override Type ReflectedType {
5712 return reflected_type;
5716 public Type EventType {
5722 public void SetUsed ()
5724 if (my_event != null)
5725 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
5730 /// For case when event is declared like property (with add and remove accessors).
5732 public class EventProperty: Event {
5734 static string[] attribute_targets = new string [] { "event", "property" };
5736 public EventProperty (DeclSpace ds, Expression type, int mod_flags,
5737 bool is_iface, MemberName name, Object init,
5738 Attributes attrs, Accessor add, Accessor remove,
5740 : base (ds, type, mod_flags, is_iface, name, init, attrs, loc)
5742 Add = new AddDelegateMethod (this, add);
5743 Remove = new RemoveDelegateMethod (this, remove);
5746 protected override string[] ValidAttributeTargets {
5748 return attribute_targets;
5754 /// Event is declared like field.
5756 public class EventField: Event {
5758 static string[] attribute_targets = new string [] { "method", "field", "event" };
5760 public EventField (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
5761 MemberName name, Object init, Attributes attrs, Location loc)
5762 : base (ds, type, mod_flags, is_iface, name, init, attrs, loc)
5764 Add = new AddDelegateMethod (this);
5765 Remove = new RemoveDelegateMethod (this);
5768 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5770 if (a.Target == "field") {
5771 FieldBuilder.SetCustomAttribute (cb);
5775 if (a.Target == "method") {
5776 AddBuilder.SetCustomAttribute (cb);
5777 RemoveBuilder.SetCustomAttribute (cb);
5781 base.ApplyAttributeBuilder (a, cb);
5784 protected override string[] ValidAttributeTargets {
5786 return attribute_targets;
5791 public abstract class Event : FieldBase {
5793 protected sealed class AddDelegateMethod: DelegateMethod
5795 public AddDelegateMethod (Event method):
5800 public AddDelegateMethod (Event method, Accessor accessor):
5801 base (method, accessor)
5805 public override string MethodName {
5807 return "add_" + method.ShortName;
5811 protected override MethodInfo DelegateMethodInfo {
5813 return TypeManager.delegate_remove_delegate_delegate;
5819 protected sealed class RemoveDelegateMethod: DelegateMethod
5821 public RemoveDelegateMethod (Event method):
5826 public RemoveDelegateMethod (Event method, Accessor accessor):
5827 base (method, accessor)
5831 public override string MethodName {
5833 return "remove_" + method.ShortName;
5837 protected override MethodInfo DelegateMethodInfo {
5839 return TypeManager.delegate_combine_delegate_delegate;
5845 public abstract class DelegateMethod: Attributable, IMethodData
5847 protected readonly Event method;
5848 protected MethodData method_data;
5850 ReturnParameter return_attributes;
5851 ImplicitParameter param_attr;
5853 static string[] attribute_targets = new string [] { "method", "param", "return" };
5855 public DelegateMethod (Event method):
5858 this.method = method;
5861 public DelegateMethod (Event method, Accessor accessor):
5862 base (accessor.Attributes)
5864 this.method = method;
5865 this.block = accessor.Block;
5868 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5870 if (a.Target == "return") {
5871 if (return_attributes == null)
5872 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
5874 return_attributes.ApplyAttributeBuilder (a, cb);
5878 if (a.Target == "param") {
5879 if (param_attr == null)
5880 param_attr = new ImplicitParameter (method_data.MethodBuilder);
5882 param_attr.ApplyAttributeBuilder (a, cb);
5886 method_data.MethodBuilder.SetCustomAttribute (cb);
5889 public override AttributeTargets AttributeTargets {
5891 return AttributeTargets.Method;
5895 public override bool IsClsCompliaceRequired(DeclSpace ds)
5897 return method.IsClsCompliaceRequired (ds);
5900 public MethodBuilder Define (TypeContainer container, InternalParameters ip)
5902 method_data = new MethodData (method, ip, method.ModFlags,
5903 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, false, this);
5905 if (!method_data.Define (container))
5908 MethodBuilder mb = method_data.MethodBuilder;
5909 mb.DefineParameter (1, ParameterAttributes.None, "value");
5913 #region IMethodData Members
5915 public Block Block {
5921 public CallingConventions CallingConventions {
5923 return CallingConventions.Standard;
5927 public void Emit (TypeContainer tc)
5929 if (block != null) {
5930 method_data.Emit (tc, this);
5935 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
5936 EmitContext ec = CreateEmitContext (tc, ig);
5937 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
5939 if ((method.ModFlags & Modifiers.STATIC) != 0) {
5940 ig.Emit (OpCodes.Ldsfld, field_info);
5941 ig.Emit (OpCodes.Ldarg_0);
5942 ig.Emit (OpCodes.Call, DelegateMethodInfo);
5943 ig.Emit (OpCodes.Castclass, method.MemberType);
5944 ig.Emit (OpCodes.Stsfld, field_info);
5946 ig.Emit (OpCodes.Ldarg_0);
5947 ig.Emit (OpCodes.Ldarg_0);
5948 ig.Emit (OpCodes.Ldfld, field_info);
5949 ig.Emit (OpCodes.Ldarg_1);
5950 ig.Emit (OpCodes.Call, DelegateMethodInfo);
5951 ig.Emit (OpCodes.Castclass, method.MemberType);
5952 ig.Emit (OpCodes.Stfld, field_info);
5954 ig.Emit (OpCodes.Ret);
5957 public string GetSignatureForError (TypeContainer tc)
5959 return String.Concat (tc.Name, '.', method.Name);
5962 protected abstract MethodInfo DelegateMethodInfo { get; }
5964 public Type[] ParameterTypes {
5966 return new Type[] { method.MemberType };
5970 public Type ReturnType {
5972 return TypeManager.void_type;
5976 public Location Location {
5978 return method.Location;
5982 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
5984 return new EmitContext (tc, method.ds, Location, ig, ReturnType, method.ModFlags, false);
5987 public ObsoleteAttribute GetObsoleteAttribute ()
5989 return method.GetObsoleteAttribute (method.ds);
5992 public bool IsExcluded (EmitContext ec)
5997 GenericMethod IMethodData.GenericMethod {
6003 public abstract string MethodName { get; }
6007 protected override string[] ValidAttributeTargets {
6009 return attribute_targets;
6015 const int AllowedModifiers =
6018 Modifiers.PROTECTED |
6019 Modifiers.INTERNAL |
6024 Modifiers.OVERRIDE |
6028 const int AllowedInterfaceModifiers =
6031 protected DelegateMethod Add, Remove;
6032 public MyEventBuilder EventBuilder;
6033 public MethodBuilder AddBuilder, RemoveBuilder;
6034 public DeclSpace ds;
6036 MethodData AddData, RemoveData;
6038 public Event (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
6039 MemberName name, Object init, Attributes attrs, Location loc)
6040 : base (type, mod_flags,
6041 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6042 name, init, attrs, loc)
6044 IsInterface = is_iface;
6048 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6050 EventBuilder.SetCustomAttribute (cb);
6053 public override AttributeTargets AttributeTargets {
6055 return AttributeTargets.Event;
6059 public override bool Define (TypeContainer container)
6061 EventAttributes e_attr;
6063 e_attr = EventAttributes.None;
6065 e_attr = EventAttributes.RTSpecialName |
6066 EventAttributes.SpecialName;
6068 if (!DoDefine (container, container))
6071 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
6072 Report.Error (74, Location, "'" + container.Name + "." + Name +
6073 "': abstract event can not have an initializer");
6077 if (!TypeManager.IsDelegateType (MemberType)) {
6078 Report.Error (66, Location, "'" + container.Name + "." + Name +
6079 "' : event must be of a delegate type");
6083 Parameter [] parms = new Parameter [1];
6084 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
6085 InternalParameters ip = new InternalParameters (
6086 container, new Parameters (parms, null, Location));
6088 if (!CheckBase (container))
6092 // Now define the accessors
6095 AddBuilder = Add.Define (container, ip);
6096 if (AddBuilder == null)
6099 RemoveBuilder = Remove.Define (container, ip);
6100 if (RemoveBuilder == null)
6103 if (!IsExplicitImpl){
6104 EventBuilder = new MyEventBuilder (this,
6105 container.TypeBuilder, Name, e_attr, MemberType);
6107 if (Add.Block == null && Remove.Block == null &&
6109 FieldBuilder = container.TypeBuilder.DefineField (
6111 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
6112 TypeManager.RegisterPrivateFieldOfEvent (
6113 (EventInfo) EventBuilder, FieldBuilder);
6114 TypeManager.RegisterFieldBase (FieldBuilder, this);
6117 EventBuilder.SetAddOnMethod (AddBuilder);
6118 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
6120 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
6121 Report.Error (111, Location,
6122 "Class `" + container.Name +
6123 "' already contains a definition for the event `" +
6132 public override void Emit (TypeContainer tc)
6134 if (OptAttributes != null) {
6135 EmitContext ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
6136 OptAttributes.Emit (ec, this);
6149 // FIXME: This does not handle:
6151 // int INTERFACENAME [ args ]
6156 // int this [ args ]
6158 public class Indexer : PropertyBase {
6160 class GetIndexerMethod: GetMethod
6162 public GetIndexerMethod (MethodCore method, Accessor accessor):
6163 base (method, accessor)
6167 public override Type[] ParameterTypes {
6169 return method.ParameterTypes;
6174 class SetIndexerMethod: SetMethod
6176 readonly Parameters parameters;
6178 public SetIndexerMethod (MethodCore method, Parameters parameters, Accessor accessor):
6179 base (method, accessor)
6181 this.parameters = parameters;
6184 public override Type[] ParameterTypes {
6186 int top = method.ParameterTypes.Length;
6187 Type [] set_pars = new Type [top + 1];
6188 method.ParameterTypes.CopyTo (set_pars, 0);
6189 set_pars [top] = method.MemberType;
6194 protected override InternalParameters GetParameterInfo (TypeContainer container)
6196 Parameter [] fixed_parms = parameters.FixedParameters;
6198 if (fixed_parms == null){
6199 throw new Exception ("We currently do not support only array arguments in an indexer at: " + method.Location);
6200 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6201 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6203 // Here is the problem: the `value' parameter has
6204 // to come *after* the array parameter in the declaration
6206 // X (object [] x, Type value)
6209 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6210 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6214 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
6216 fixed_parms.CopyTo (tmp, 0);
6217 tmp [fixed_parms.Length] = new Parameter (
6218 method.Type, "value", Parameter.Modifier.NONE, null);
6220 Parameters set_formal_params = new Parameters (tmp, null, method.Location);
6222 return new InternalParameters (container, set_formal_params);
6228 const int AllowedModifiers =
6231 Modifiers.PROTECTED |
6232 Modifiers.INTERNAL |
6236 Modifiers.OVERRIDE |
6241 const int AllowedInterfaceModifiers =
6244 public string IndexerName;
6245 public string InterfaceIndexerName;
6248 // Are we implementing an interface ?
6250 public Indexer (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
6251 MemberName name, Parameters parameters, Attributes attrs,
6252 Accessor get_block, Accessor set_block, Location loc)
6253 : base (ds, type, mod_flags,
6254 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6255 is_iface, name, parameters, attrs, loc)
6257 if (get_block != null)
6258 Get = new GetIndexerMethod (this, get_block);
6260 if (set_block != null)
6261 Set = new SetIndexerMethod (this, parameters, set_block);
6264 public override bool Define (TypeContainer container)
6266 PropertyAttributes prop_attr =
6267 PropertyAttributes.RTSpecialName |
6268 PropertyAttributes.SpecialName;
6270 if (!DoDefine (container, container))
6273 if (OptAttributes != null)
6274 IndexerName = OptAttributes.ScanForIndexerName (ec);
6276 if (IndexerName == null)
6277 IndexerName = "Item";
6279 if (! Tokenizer.IsValidIdentifier (IndexerName)) {
6280 Report.Error (633, Location, "The IndexerName specified is an invalid identifier");
6284 if (IsExplicitImpl) {
6285 Report.Error (592, Location,
6286 "Attribute 'IndexerName' is not valid on explicit implementations.");
6291 ShortName = IndexerName;
6292 if (IsExplicitImpl) {
6293 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
6294 Name = InterfaceType.FullName + "." + IndexerName;
6296 InterfaceIndexerName = IndexerName;
6300 if (!CheckNameCollision (container))
6303 if (!CheckBase (container))
6306 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6308 GetBuilder = Get.Define (container);
6309 if (GetBuilder == null)
6314 SetBuilder = Set.Define (container);
6315 if (SetBuilder == null)
6320 // Now name the parameters
6322 Parameter [] p = Parameters.FixedParameters;
6326 for (i = 0; i < p.Length; ++i) {
6328 GetBuilder.DefineParameter (
6329 i + 1, p [i].Attributes, p [i].Name);
6332 SetBuilder.DefineParameter (
6333 i + 1, p [i].Attributes, p [i].Name);
6337 SetBuilder.DefineParameter (
6338 i + 1, ParameterAttributes.None, "value");
6340 if (i != ParameterTypes.Length) {
6341 Parameter array_param = Parameters.ArrayParameter;
6343 SetBuilder.DefineParameter (
6344 i + 1, array_param.Attributes, array_param.Name);
6349 // Define the PropertyBuilder if one of the following conditions are met:
6350 // a) we're not implementing an interface indexer.
6351 // b) the indexer has a different IndexerName and this is no
6352 // explicit interface implementation.
6354 if (!IsExplicitImpl) {
6355 PropertyBuilder = container.TypeBuilder.DefineProperty (
6356 IndexerName, prop_attr, MemberType, ParameterTypes);
6359 PropertyBuilder.SetGetMethod (GetBuilder);
6362 PropertyBuilder.SetSetMethod (SetBuilder);
6364 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
6371 bool CheckNameCollision (TypeContainer container) {
6372 switch (VerifyName (container)){
6373 case DeclSpace.AdditionResult.NameExists:
6374 Report.Error (102, Location, "The container '{0}' already contains a definition for '{1}'", container.GetSignatureForError (), Name);
6377 case DeclSpace.AdditionResult.Success:
6380 throw new NotImplementedException ();
6383 DeclSpace.AdditionResult VerifyName (TypeContainer container) {
6384 if (!AddIndexer (container, container.Name + "." + Name))
6385 return DeclSpace.AdditionResult.NameExists;
6388 if (!AddIndexer (container, container.Name + ".get_" + Name))
6389 return DeclSpace.AdditionResult.NameExists;
6393 if (!AddIndexer (container, container.Name + ".set_" + Name))
6394 return DeclSpace.AdditionResult.NameExists;
6396 return DeclSpace.AdditionResult.Success;
6399 bool AddIndexer (TypeContainer container, string fullname)
6401 object value = container.GetDefinition (fullname);
6403 if (value != null) {
6404 return value.GetType () != GetType () ? false : true;
6407 container.DefineName (fullname, this);
6411 public override string GetSignatureForError ()
6413 return TypeManager.CSharpSignature (PropertyBuilder, true);
6416 protected override string RealMethodName {
6423 public class Operator : MemberBase, IIteratorContainer {
6425 const int AllowedModifiers =
6431 const int RequiredModifiers =
6435 public enum OpType : byte {
6445 // Unary and Binary operators
6468 // Implicit and Explicit
6473 public readonly OpType OperatorType;
6474 public readonly Expression ReturnType;
6475 public readonly Expression FirstArgType, SecondArgType;
6476 public readonly string FirstArgName, SecondArgName;
6478 public MethodBuilder OperatorMethodBuilder;
6480 public string MethodName;
6481 public Method OperatorMethod;
6483 static string[] attribute_targets = new string [] { "method", "return" };
6485 public Operator (OpType type, Expression ret_type, int mod_flags,
6486 Expression arg1type, string arg1name,
6487 Expression arg2type, string arg2name,
6488 Block block, Attributes attrs, Location loc)
6489 : base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC,
6490 MemberName.Null, attrs, loc)
6492 OperatorType = type;
6493 Name = "op_" + OperatorType;
6494 ReturnType = ret_type;
6495 FirstArgType = arg1type;
6496 FirstArgName = arg1name;
6497 SecondArgType = arg2type;
6498 SecondArgName = arg2name;
6502 string Prototype (TypeContainer container)
6504 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
6505 SecondArgType + ")";
6508 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6510 OperatorMethod.ApplyAttributeBuilder (a, cb);
6513 public override AttributeTargets AttributeTargets {
6515 return AttributeTargets.Method;
6519 protected override bool CheckGenericOverride (MethodInfo method, string name)
6524 public override bool Define (TypeContainer container)
6527 MethodName = "op_" + OperatorType;
6529 if (SecondArgType != null)
6532 Parameter [] param_list = new Parameter [length];
6534 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
6537 "User defined operators `" +
6538 Prototype (container) +
6539 "' must be declared static and public");
6543 param_list[0] = new Parameter (FirstArgType, FirstArgName,
6544 Parameter.Modifier.NONE, null);
6545 if (SecondArgType != null)
6546 param_list[1] = new Parameter (SecondArgType, SecondArgName,
6547 Parameter.Modifier.NONE, null);
6549 OperatorMethod = new Method (
6550 container, ReturnType, ModFlags, false,
6551 new MemberName (MethodName),
6552 new Parameters (param_list, null, Location),
6553 OptAttributes, Location);
6555 OperatorMethod.Block = Block;
6556 OperatorMethod.IsOperator = true;
6557 OperatorMethod.Define (container);
6559 if (OperatorMethod.MethodBuilder == null)
6562 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
6564 Type [] param_types = OperatorMethod.ParameterTypes;
6565 Type declaring_type = OperatorMethod.MethodData.DeclaringType;
6566 Type return_type = OperatorMethod.GetReturnType ();
6567 Type first_arg_type = param_types [0];
6569 // Rules for conversion operators
6571 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
6572 if (first_arg_type == return_type && first_arg_type == declaring_type){
6575 "User-defined conversion cannot take an object of the " +
6576 "enclosing type and convert to an object of the enclosing" +
6581 if (first_arg_type != declaring_type && return_type != declaring_type){
6584 "User-defined conversion must convert to or from the " +
6589 if (first_arg_type == TypeManager.object_type ||
6590 return_type == TypeManager.object_type){
6593 "User-defined conversion cannot convert to or from " +
6598 if (first_arg_type.IsInterface || return_type.IsInterface){
6601 "User-defined conversion cannot convert to or from an " +
6606 if (first_arg_type.IsSubclassOf (return_type) ||
6607 return_type.IsSubclassOf (first_arg_type)){
6610 "User-defined conversion cannot convert between types " +
6611 "that derive from each other");
6614 } else if (SecondArgType == null) {
6615 // Checks for Unary operators
6617 if (first_arg_type != declaring_type){
6620 "The parameter of a unary operator must be the " +
6625 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
6626 if (return_type != declaring_type){
6629 "The parameter and return type for ++ and -- " +
6630 "must be the containing type");
6636 if (OperatorType == OpType.True || OperatorType == OpType.False) {
6637 if (return_type != TypeManager.bool_type){
6640 "The return type of operator True or False " +
6647 // Checks for Binary operators
6649 if (first_arg_type != declaring_type &&
6650 param_types [1] != declaring_type){
6653 "One of the parameters of a binary operator must " +
6654 "be the containing type");
6662 public override void Emit (TypeContainer container)
6665 // abstract or extern methods have no bodies
6667 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
6670 OperatorMethod.Emit (container);
6674 public static string GetName (OpType ot)
6677 case OpType.LogicalNot:
6679 case OpType.OnesComplement:
6681 case OpType.Increment:
6683 case OpType.Decrement:
6689 case OpType.Addition:
6691 case OpType.Subtraction:
6693 case OpType.UnaryPlus:
6695 case OpType.UnaryNegation:
6697 case OpType.Multiply:
6699 case OpType.Division:
6701 case OpType.Modulus:
6703 case OpType.BitwiseAnd:
6705 case OpType.BitwiseOr:
6707 case OpType.ExclusiveOr:
6709 case OpType.LeftShift:
6711 case OpType.RightShift:
6713 case OpType.Equality:
6715 case OpType.Inequality:
6717 case OpType.GreaterThan:
6719 case OpType.LessThan:
6721 case OpType.GreaterThanOrEqual:
6723 case OpType.LessThanOrEqual:
6725 case OpType.Implicit:
6727 case OpType.Explicit:
6733 public override string GetSignatureForError(TypeContainer tc)
6735 return Prototype (tc);
6738 public override string ToString ()
6740 Type return_type = OperatorMethod.GetReturnType();
6741 Type [] param_types = OperatorMethod.ParameterTypes;
6743 if (SecondArgType == null)
6744 return String.Format (
6745 "{0} operator {1}({2})",
6746 TypeManager.CSharpName (return_type),
6747 GetName (OperatorType),
6750 return String.Format (
6751 "{0} operator {1}({2}, {3})",
6752 TypeManager.CSharpName (return_type),
6753 GetName (OperatorType),
6754 param_types [0], param_types [1]);
6757 protected override string[] ValidAttributeTargets {
6759 return attribute_targets;
6763 public void SetYields ()
6765 ModFlags |= Modifiers.METHOD_YIELDS;
6770 // This is used to compare method signatures
6772 struct MethodSignature {
6774 public Type RetType;
6775 public Type [] Parameters;
6778 /// This delegate is used to extract methods which have the
6779 /// same signature as the argument
6781 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
6783 public MethodSignature (string name, Type ret_type, Type [] parameters)
6788 if (parameters == null)
6789 Parameters = TypeManager.NoTypes;
6791 Parameters = parameters;
6794 public override string ToString ()
6797 if (Parameters.Length != 0){
6798 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
6799 for (int i = 0; i < Parameters.Length; i++){
6800 sb.Append (Parameters [i]);
6801 if (i+1 < Parameters.Length)
6804 pars = sb.ToString ();
6807 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
6810 public override int GetHashCode ()
6812 return Name.GetHashCode ();
6815 public override bool Equals (Object o)
6817 MethodSignature other = (MethodSignature) o;
6819 if (other.Name != Name)
6822 if (other.RetType != RetType)
6825 if (Parameters == null){
6826 if (other.Parameters == null)
6831 if (other.Parameters == null)
6834 int c = Parameters.Length;
6835 if (other.Parameters.Length != c)
6838 for (int i = 0; i < c; i++)
6839 if (other.Parameters [i] != Parameters [i])
6845 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
6847 MethodSignature sig = (MethodSignature) filter_criteria;
6849 if (m.Name != sig.Name)
6853 MethodInfo mi = m as MethodInfo;
6854 PropertyInfo pi = m as PropertyInfo;
6857 ReturnType = mi.ReturnType;
6858 else if (pi != null)
6859 ReturnType = pi.PropertyType;
6864 // we use sig.RetType == null to mean `do not check the
6865 // method return value.
6867 if (sig.RetType != null)
6868 if (ReturnType != sig.RetType)
6873 args = TypeManager.GetArgumentTypes (mi);
6875 args = TypeManager.GetArgumentTypes (pi);
6876 Type [] sigp = sig.Parameters;
6878 if (args.Length != sigp.Length)
6881 for (int i = args.Length; i > 0; ){
6883 if (args [i] != sigp [i])