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 public Type base_classs_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;
135 public TypeContainer ():
136 this (null, null, "", null, new Location (-1)) {
139 public TypeContainer (NamespaceEntry ns, TypeContainer parent, string name, Attributes attrs, Location l)
140 : base (ns, parent, name, attrs, l)
142 types = new ArrayList ();
144 base_class_name = null;
147 public AdditionResult AddConstant (Const constant)
150 string basename = constant.Name;
151 string fullname = Name + "." + basename;
153 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
156 if (constants == null)
157 constants = new ArrayList ();
159 constants.Add (constant);
160 DefineName (fullname, constant);
162 return AdditionResult.Success;
165 public AdditionResult AddEnum (Mono.CSharp.Enum e)
169 if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
173 enums = new ArrayList ();
176 DefineName (e.Name, e);
178 return AdditionResult.Success;
181 public AdditionResult AddClass (Class c)
184 string name = c.Basename;
186 if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
189 DefineName (c.Name, c);
192 return AdditionResult.Success;
195 public AdditionResult AddStruct (Struct s)
198 string name = s.Basename;
200 if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
203 DefineName (s.Name, s);
206 return AdditionResult.Success;
209 public AdditionResult AddDelegate (Delegate d)
212 string name = d.Basename;
214 if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
217 if (delegates == null)
218 delegates = new ArrayList ();
220 DefineName (d.Name, d);
223 return AdditionResult.Success;
226 public AdditionResult AddMethod (Method method)
228 string basename = method.Name;
229 string fullname = Name + "." + basename;
231 Object value = defined_names [fullname];
233 if (value != null && (!(value is Method)))
234 return AdditionResult.NameExists;
236 if (basename == Basename)
237 return AdditionResult.EnclosingClash;
240 methods = new ArrayList ();
242 if (method.Name.IndexOf ('.') != -1)
243 methods.Insert (0, method);
245 methods.Add (method);
248 DefineName (fullname, method);
250 return AdditionResult.Success;
253 public AdditionResult AddConstructor (Constructor c)
255 if (c.Name != Basename)
256 return AdditionResult.NotAConstructor;
258 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
261 UserDefinedStaticConstructor = true;
262 if (default_static_constructor != null)
263 return AdditionResult.MethodExists;
265 default_static_constructor = c;
268 if (default_constructor != null)
269 return AdditionResult.MethodExists;
270 default_constructor = c;
273 if (instance_constructors == null)
274 instance_constructors = new ArrayList ();
276 instance_constructors.Add (c);
279 return AdditionResult.Success;
282 public AdditionResult AddInterface (Interface iface)
285 string name = iface.Basename;
287 if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
290 if (interfaces == null)
291 interfaces = new ArrayList ();
292 interfaces.Add (iface);
293 DefineName (iface.Name, iface);
295 return AdditionResult.Success;
298 public AdditionResult AddField (Field field)
301 string basename = field.Name;
302 string fullname = Name + "." + basename;
304 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
308 fields = new ArrayList ();
312 if (field.HasInitializer){
313 if ((field.ModFlags & Modifiers.STATIC) != 0){
314 if (initialized_static_fields == null)
315 initialized_static_fields = new ArrayList ();
317 initialized_static_fields.Add (field);
320 if (initialized_fields == null)
321 initialized_fields = new ArrayList ();
323 initialized_fields.Add (field);
327 if ((field.ModFlags & Modifiers.STATIC) == 0)
328 have_nonstatic_fields = true;
330 DefineName (fullname, field);
331 return AdditionResult.Success;
334 public AdditionResult AddProperty (Property prop)
338 if ((res = AddProperty (prop, prop.Name)) != AdditionResult.Success)
341 if (prop.Get != null) {
342 if ((res = AddProperty (prop, "get_" + prop.Name)) != AdditionResult.Success)
346 if (prop.Set != null) {
347 if ((res = AddProperty (prop, "set_" + prop.Name)) != AdditionResult.Success)
351 if (properties == null)
352 properties = new ArrayList ();
354 if (prop.Name.IndexOf ('.') != -1)
355 properties.Insert (0, prop);
357 properties.Add (prop);
359 return AdditionResult.Success;
362 AdditionResult AddProperty (Property prop, string basename)
365 string fullname = Name + "." + basename;
367 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
370 DefineName (fullname, prop);
372 return AdditionResult.Success;
375 public AdditionResult AddEvent (Event e)
378 string basename = e.Name;
379 string fullname = Name + "." + basename;
381 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
385 events = new ArrayList ();
388 DefineName (fullname, e);
390 return AdditionResult.Success;
393 public void AddIndexer (Indexer i)
395 if (indexers == null)
396 indexers = new ArrayList ();
398 if (i.ExplicitInterfaceName != null)
399 indexers.Insert (0, i);
404 public AdditionResult AddOperator (Operator op)
406 if (operators == null)
407 operators = new ArrayList ();
411 string basename = op.Name;
412 string fullname = Name + "." + basename;
413 if (!defined_names.Contains (fullname))
415 DefineName (fullname, op);
417 return AdditionResult.Success;
420 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
422 if (a.Type == TypeManager.default_member_type) {
423 if (Indexers != null) {
424 Report.Error (646, a.Location,
425 "Cannot specify the DefaultMember attribute on" +
426 " a type containing an indexer");
431 base.ApplyAttributeBuilder (a, cb);
434 public override AttributeTargets AttributeTargets {
436 throw new NotSupportedException ();
440 public void RegisterOrder (Interface iface)
442 if (interface_order == null)
443 interface_order = new ArrayList ();
445 interface_order.Add (iface);
448 public ArrayList Types {
454 public ArrayList Methods {
460 public ArrayList Constants {
466 public ArrayList Interfaces {
474 return base_class_name;
478 public ArrayList Bases {
488 public ArrayList Fields {
498 public ArrayList InstanceConstructors {
500 return instance_constructors;
504 public ArrayList Properties {
510 public ArrayList Events {
516 public ArrayList Enums {
522 public ArrayList Indexers {
528 public ArrayList Operators {
534 public ArrayList Delegates {
540 public virtual TypeAttributes TypeAttr {
542 return Modifiers.TypeAttr (ModFlags, this);
547 // Emits the instance field initializers
549 public bool EmitFieldInitializers (EmitContext ec)
552 Expression instance_expr;
555 fields = initialized_static_fields;
556 instance_expr = null;
558 fields = initialized_fields;
559 instance_expr = new This (Location.Null).Resolve (ec);
565 foreach (Field f in fields){
566 Expression e = f.GetInitializerExpression (ec);
570 Location l = f.Location;
571 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
572 fe.InstanceExpression = instance_expr;
573 ExpressionStatement a = new Assign (fe, e, l);
575 a = a.ResolveStatement (ec);
579 a.EmitStatement (ec);
586 // Defines the default constructors
588 void DefineDefaultConstructor (bool is_static)
592 // The default constructor is public
593 // If the class is abstract, the default constructor is protected
594 // The default static constructor is private
596 int mods = Modifiers.PUBLIC;
598 mods = Modifiers.STATIC | Modifiers.PRIVATE;
599 else if ((ModFlags & Modifiers.ABSTRACT) != 0)
600 mods = Modifiers.PROTECTED;
602 c = new Constructor (this, Basename, mods, Parameters.EmptyReadOnlyParameters,
603 new ConstructorBaseInitializer (
604 null, Parameters.EmptyReadOnlyParameters,
610 c.Block = new ToplevelBlock (null, Location);
614 public void ReportStructInitializedInstanceError ()
616 string n = TypeBuilder.FullName;
618 foreach (Field f in initialized_fields){
621 "`" + n + "." + f.Name + "': can not have " +
622 "instance field initializers in structs");
627 /// The pending methods that need to be implemented (interfaces or abstract methods)
629 public PendingImplementation Pending;
632 /// This function computes the Base class and also the
633 /// list of interfaces that the class or struct @c implements.
635 /// The return value is an array (might be null) of
636 /// interfaces implemented (as Types).
638 /// The @parent argument is set to the parent object or null
639 /// if this is `System.Object'.
641 TypeExpr [] GetClassBases (bool is_class, bool is_iface,
642 out TypeExpr parent, out bool error)
644 ArrayList bases = Bases;
650 if (is_class || is_iface)
653 parent = TypeManager.system_valuetype_expr;
657 if (RootContext.StdLib)
658 parent = TypeManager.system_object_expr;
659 else if (Name != "System.Object")
660 parent = TypeManager.system_object_expr;
663 // If we are compiling our runtime,
664 // and we are defining ValueType, then our
665 // parent is `System.Object'.
667 if (!RootContext.StdLib && Name == "System.ValueType")
668 parent = TypeManager.system_object_expr;
675 // Bases should be null if there are no bases at all
680 TypeExpr name = ResolveTypeExpr ((Expression) bases [0], false, Location);
691 parent = TypeManager.system_object_expr;
697 if (name.IsValueType)
698 detail = " (a class can not inherit from a struct/enum)";
700 Report.Error (509, "class `"+ Name +
701 "': Cannot inherit from sealed class `"+
702 name.Name + "'" + detail);
707 if (!parent.CanInheritFrom ()){
708 Report.Error (644, Location,
709 "`{0}' cannot inherit from special class `{1}'",
715 if (!parent.AsAccessible (this, ModFlags))
716 Report.Error (60, Location,
717 "Inconsistent accessibility: base class `" +
718 name.Name + "' is less accessible than class `" +
726 base_class_name = parent.Name;
728 TypeExpr [] ifaces = new TypeExpr [count-start];
730 for (i = start, j = 0; i < count; i++, j++){
731 Expression name = (Expression) bases [i];
732 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
733 if (resolved == null)
736 bases [i] = resolved;
738 if (is_class == false && !resolved.IsInterface){
739 Report.Error (527, "In Struct `" + Name + "', type `"+
740 name +"' is not an interface");
745 if (resolved.IsClass) {
747 Report.Error (527, "In Class `" + Name + "', type `"+
748 name+"' is not an interface");
754 for (int x = 0; x < j; x++) {
755 if (resolved.Equals (ifaces [x])) {
756 Report.Error (528, "`" + name + "' is already listed in interface list");
763 !resolved.AsAccessible (Parent, ModFlags))
764 Report.Error (61, Location,
765 "Inconsistent accessibility: base interface `" +
766 name + "' is less accessible than interface `" +
769 ifaces [j] = resolved;
772 return TypeManager.ExpandInterfaces (ifaces);
778 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
780 public override TypeBuilder DefineType ()
783 bool is_class, is_iface;
785 if (TypeBuilder != null)
792 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
799 if (this is Interface) {
810 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
812 ifaces = GetClassBases (is_class, is_iface, out parent, out error);
817 if (!is_class && TypeManager.value_type == null)
818 throw new Exception ();
820 TypeAttributes type_attributes = TypeAttr;
823 base_classs_type = parent.ResolveType (ec);
826 if (TypeManager.NamespaceClash (Name, Location)) {
831 ModuleBuilder builder = CodeGen.Module.Builder;
832 TypeBuilder = builder.DefineType (
833 Name, type_attributes, base_classs_type, null);
836 TypeBuilder builder = Parent.DefineType ();
840 TypeBuilder = builder.DefineNestedType (
841 Basename, type_attributes, base_classs_type, null);
845 // Structs with no fields need to have at least one byte.
846 // The right thing would be to set the PackingSize in a DefineType
847 // but there are no functions that allow interfaces *and* the size to
851 if (!is_class && !is_iface && !have_nonstatic_fields){
852 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
853 FieldAttributes.Private);
856 // add interfaces that were not added at type creation
857 if (ifaces != null) {
858 base_inteface_types = new Type[ifaces.Length];
859 for (int i = 0; i < ifaces.Length; ++i) {
860 Type itype = ifaces [i].ResolveType (ec);
861 TypeBuilder.AddInterfaceImplementation (itype);
862 base_inteface_types [i] = itype;
867 // Finish the setup for the EmitContext
869 ec.ContainerType = TypeBuilder;
871 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
873 if ((parent != null) && parent.IsAttribute) {
874 RootContext.RegisterAttribute (this);
876 RootContext.RegisterOrder (this);
878 if (Interfaces != null) {
879 foreach (Interface iface in Interfaces)
880 if (iface.DefineType () == null) {
887 foreach (TypeContainer tc in Types)
888 if (tc.DefineType () == null) {
894 if (Delegates != null) {
895 foreach (Delegate d in Delegates)
896 if (d.DefineType () == null) {
903 foreach (Enum en in Enums)
904 if (en.DefineType () == null) {
916 /// Defines the MemberCore objects that are in the `list' Arraylist
918 /// The `defined_names' array contains a list of members defined in
921 static ArrayList remove_list = new ArrayList ();
922 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
926 remove_list.Clear ();
928 foreach (MemberCore mc in list){
930 if (defined_names != null)
931 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
936 if (RootContext.WarningLevel >= 4){
937 if ((mc.ModFlags & Modifiers.NEW) != 0)
938 Warning_KeywordNewNotRequired (mc.Location, mc);
940 } else if (mc is MethodCore)
941 ((MethodCore) mc).OverridesSomething = true;
943 if (!mc.Define (this)){
944 remove_list.Add (mc);
951 MemberInfo match = defined_names [idx];
953 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
957 // If we are both methods, let the method resolution emit warnings
959 if (match is MethodBase && mc is MethodCore)
962 if ((mc.ModFlags & Modifiers.NEW) == 0) {
964 if (!(match is EventInfo)) {
965 Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
969 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
973 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
977 foreach (object o in remove_list)
980 remove_list.Clear ();
984 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
985 // class is consistent. Either it is `Item' or it is the name defined by all the
986 // indexers with the `IndexerName' attribute.
988 // Turns out that the IndexerNameAttribute is applied to each indexer,
989 // but it is never emitted, instead a DefaultMember attribute is attached
992 void DefineIndexers ()
994 string class_indexer_name = null;
997 // If there's both an explicit and an implicit interface implementation, the
998 // explicit one actually implements the interface while the other one is just
999 // a normal indexer. See bug #37714.
1002 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
1003 bool seen_normal_indexers = false;
1005 foreach (Indexer i in Indexers) {
1010 name = i.IndexerName;
1012 if (i.InterfaceType != null) {
1013 if (seen_normal_indexers)
1014 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
1018 seen_normal_indexers = true;
1020 if (class_indexer_name == null)
1021 class_indexer_name = name;
1022 else if (name != class_indexer_name)
1023 Report.Error (668, i.Location, "Two indexers have different names, " +
1024 " you should use the same name for all your indexers");
1027 if (seen_normal_indexers && class_indexer_name == null)
1028 class_indexer_name = "Item";
1029 IndexerName = class_indexer_name;
1032 static void Error_KeywordNotAllowed (Location loc)
1034 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1038 /// Populates our TypeBuilder with fields and methods
1040 public override bool DefineMembers (TypeContainer container)
1042 if (members_defined)
1043 return members_defined_ok;
1045 members_defined_ok = DoDefineMembers ();
1046 members_defined = true;
1048 return members_defined_ok;
1051 bool DoDefineMembers ()
1053 MemberInfo [] defined_names = null;
1056 // We need to be able to use the member cache while we are checking/defining
1059 if (TypeBuilder.BaseType != null)
1060 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1063 if (interface_order != null){
1064 foreach (Interface iface in interface_order)
1065 if ((iface.ModFlags & Modifiers.NEW) == 0)
1066 iface.DefineMembers (this);
1068 Error_KeywordNotAllowed (iface.Location);
1071 if (RootContext.WarningLevel > 1){
1075 // This code throws an exception in the comparer
1076 // I guess the string is not an object?
1078 ptype = TypeBuilder.BaseType;
1080 defined_names = (MemberInfo []) FindMembers (
1081 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1082 BindingFlags.Public | BindingFlags.Instance |
1083 BindingFlags.Static, null, null);
1085 Array.Sort (defined_names, mif_compare);
1089 Class pclass = Parent as Class;
1090 if (pclass != null) {
1091 string pname = null;
1093 Type t = pclass.TypeBuilder.BaseType;
1094 while ((t != null) && (ptype == null)) {
1095 pname = t.FullName + "." + Basename;
1096 ptype = RootContext.LookupType (this, pname, true, Location.Null);
1100 if ((ModFlags & Modifiers.NEW) != 0) {
1102 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1103 "inherited member. The keyword new is not required.");
1104 } else if (ptype != null) {
1105 Report.Warning (108, Location, "The keyword new is required on `" +
1106 Name + "' because it hides inherited member '" +
1109 } else if ((ModFlags & Modifiers.NEW) != 0)
1110 Error_KeywordNotAllowed (Location);
1112 if (constants != null)
1113 DefineMembers (constants, defined_names);
1116 DefineMembers (fields, defined_names);
1119 if (instance_constructors == null){
1120 if (default_constructor == null)
1121 DefineDefaultConstructor (false);
1124 if (initialized_static_fields != null &&
1125 default_static_constructor == null)
1126 DefineDefaultConstructor (true);
1129 if (this is Struct){
1131 // Structs can not have initialized instance
1134 if (initialized_static_fields != null &&
1135 default_static_constructor == null)
1136 DefineDefaultConstructor (true);
1138 if (initialized_fields != null)
1139 ReportStructInitializedInstanceError ();
1142 if (!(this is Interface))
1143 Pending = PendingImplementation.GetPendingImplementations (this);
1146 // Constructors are not in the defined_names array
1148 if (instance_constructors != null)
1149 DefineMembers (instance_constructors, null);
1151 if (default_static_constructor != null)
1152 default_static_constructor.Define (this);
1154 if (methods != null)
1155 DefineMembers (methods, defined_names);
1157 if (properties != null)
1158 DefineMembers (properties, defined_names);
1161 DefineMembers (events, defined_names);
1163 if (indexers != null)
1166 if (operators != null){
1167 DefineMembers (operators, null);
1169 CheckPairedOperators ();
1173 DefineMembers (enums, defined_names);
1175 if (delegates != null)
1176 DefineMembers (delegates, defined_names);
1179 member_cache = new MemberCache (this);
1186 public override bool Define (TypeContainer container)
1188 if (interface_order != null){
1189 foreach (Interface iface in interface_order)
1190 if ((iface.ModFlags & Modifiers.NEW) == 0)
1191 iface.Define (this);
1198 /// This function is based by a delegate to the FindMembers routine
1200 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1206 /// This filter is used by FindMembers, and we just keep
1207 /// a global for the filter to `AlwaysAccept'
1209 static MemberFilter accepting_filter;
1213 /// A member comparission method based on name only
1215 static IComparer mif_compare;
1217 static TypeContainer ()
1219 accepting_filter = new MemberFilter (AlwaysAccept);
1220 mif_compare = new MemberInfoCompare ();
1223 public MethodInfo[] GetMethods ()
1225 ArrayList members = new ArrayList ();
1227 DefineMembers (null);
1229 if (methods != null) {
1230 int len = methods.Count;
1231 for (int i = 0; i < len; i++) {
1232 Method m = (Method) methods [i];
1234 members.Add (m.MethodBuilder);
1238 if (operators != null) {
1239 int len = operators.Count;
1240 for (int i = 0; i < len; i++) {
1241 Operator o = (Operator) operators [i];
1243 members.Add (o.OperatorMethodBuilder);
1247 if (properties != null) {
1248 int len = properties.Count;
1249 for (int i = 0; i < len; i++) {
1250 Property p = (Property) properties [i];
1252 if (p.GetBuilder != null)
1253 members.Add (p.GetBuilder);
1254 if (p.SetBuilder != null)
1255 members.Add (p.SetBuilder);
1259 if (indexers != null) {
1260 int len = indexers.Count;
1261 for (int i = 0; i < len; i++) {
1262 Indexer ix = (Indexer) indexers [i];
1264 if (ix.GetBuilder != null)
1265 members.Add (ix.GetBuilder);
1266 if (ix.SetBuilder != null)
1267 members.Add (ix.SetBuilder);
1271 if (events != null) {
1272 int len = events.Count;
1273 for (int i = 0; i < len; i++) {
1274 Event e = (Event) events [i];
1276 if (e.AddBuilder != null)
1277 members.Add (e.AddBuilder);
1278 if (e.RemoveBuilder != null)
1279 members.Add (e.RemoveBuilder);
1283 MethodInfo[] retMethods = new MethodInfo [members.Count];
1284 members.CopyTo (retMethods, 0);
1289 /// This method returns the members of this type just like Type.FindMembers would
1290 /// Only, we need to use this for types which are _being_ defined because MS'
1291 /// implementation can't take care of that.
1294 // FIXME: return an empty static array instead of null, that cleans up
1295 // some code and is consistent with some coding conventions I just found
1299 // Notice that in various cases we check if our field is non-null,
1300 // something that would normally mean that there was a bug elsewhere.
1302 // The problem happens while we are defining p-invoke methods, as those
1303 // will trigger a FindMembers, but this happens before things are defined
1305 // Since the whole process is a no-op, it is fine to check for null here.
1307 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1308 MemberFilter filter, object criteria)
1310 ArrayList members = null;
1313 if ((bf & BindingFlags.Public) != 0)
1314 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1316 if ((bf & BindingFlags.NonPublic) != 0)
1317 modflags |= Modifiers.PRIVATE;
1319 int static_mask = 0, static_flags = 0;
1320 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1321 case BindingFlags.Static:
1322 static_mask = static_flags = Modifiers.STATIC;
1325 case BindingFlags.Instance:
1326 static_mask = Modifiers.STATIC;
1331 static_mask = static_flags = 0;
1335 Timer.StartTimer (TimerType.TcFindMembers);
1338 filter = accepting_filter;
1340 if ((mt & MemberTypes.Field) != 0) {
1341 if (fields != null) {
1342 int len = fields.Count;
1343 for (int i = 0; i < len; i++) {
1344 Field f = (Field) fields [i];
1346 if ((f.ModFlags & modflags) == 0)
1348 if ((f.ModFlags & static_mask) != static_flags)
1351 FieldBuilder fb = f.FieldBuilder;
1352 if (fb != null && filter (fb, criteria) == true) {
1353 if (members == null)
1354 members = new ArrayList ();
1361 if (constants != null) {
1362 int len = constants.Count;
1363 for (int i = 0; i < len; i++) {
1364 Const con = (Const) constants [i];
1366 if ((con.ModFlags & modflags) == 0)
1368 if ((con.ModFlags & static_mask) != static_flags)
1371 FieldBuilder fb = con.FieldBuilder;
1372 if (fb != null && filter (fb, criteria) == true) {
1373 if (members == null)
1374 members = new ArrayList ();
1382 if ((mt & MemberTypes.Method) != 0) {
1383 if (methods != null) {
1384 int len = methods.Count;
1385 for (int i = 0; i < len; i++) {
1386 Method m = (Method) methods [i];
1388 if ((m.ModFlags & modflags) == 0)
1390 if ((m.ModFlags & static_mask) != static_flags)
1393 MethodBuilder mb = m.MethodBuilder;
1395 if (mb != null && filter (mb, criteria) == true) {
1396 if (members == null)
1397 members = new ArrayList ();
1404 if (operators != null) {
1405 int len = operators.Count;
1406 for (int i = 0; i < len; i++) {
1407 Operator o = (Operator) operators [i];
1409 if ((o.ModFlags & modflags) == 0)
1411 if ((o.ModFlags & static_mask) != static_flags)
1414 MethodBuilder ob = o.OperatorMethodBuilder;
1415 if (ob != null && filter (ob, criteria) == true) {
1416 if (members == null)
1417 members = new ArrayList ();
1424 if (properties != null) {
1425 int len = properties.Count;
1426 for (int i = 0; i < len; i++) {
1427 Property p = (Property) properties [i];
1429 if ((p.ModFlags & modflags) == 0)
1431 if ((p.ModFlags & static_mask) != static_flags)
1437 if (b != null && filter (b, criteria) == true) {
1438 if (members == null)
1439 members = new ArrayList ();
1445 if (b != null && filter (b, criteria) == true) {
1446 if (members == null)
1447 members = new ArrayList ();
1454 if (indexers != null) {
1455 int len = indexers.Count;
1456 for (int i = 0; i < len; i++) {
1457 Indexer ix = (Indexer) indexers [i];
1459 if ((ix.ModFlags & modflags) == 0)
1461 if ((ix.ModFlags & static_mask) != static_flags)
1467 if (b != null && filter (b, criteria) == true) {
1468 if (members == null)
1469 members = new ArrayList ();
1475 if (b != null && filter (b, criteria) == true) {
1476 if (members == null)
1477 members = new ArrayList ();
1485 if ((mt & MemberTypes.Event) != 0) {
1486 if (events != null) {
1487 int len = events.Count;
1488 for (int i = 0; i < len; i++) {
1489 Event e = (Event) events [i];
1491 if ((e.ModFlags & modflags) == 0)
1493 if ((e.ModFlags & static_mask) != static_flags)
1496 MemberInfo eb = e.EventBuilder;
1497 if (eb != null && filter (eb, criteria) == true) {
1498 if (members == null)
1499 members = new ArrayList ();
1501 members.Add (e.EventBuilder);
1507 if ((mt & MemberTypes.Property) != 0){
1508 if (properties != null) {
1509 int len = properties.Count;
1510 for (int i = 0; i < len; i++) {
1511 Property p = (Property) properties [i];
1513 if ((p.ModFlags & modflags) == 0)
1515 if ((p.ModFlags & static_mask) != static_flags)
1518 MemberInfo pb = p.PropertyBuilder;
1519 if (pb != null && filter (pb, criteria) == true) {
1520 if (members == null)
1521 members = new ArrayList ();
1523 members.Add (p.PropertyBuilder);
1528 if (indexers != null) {
1529 int len = indexers.Count;
1530 for (int i = 0; i < len; i++) {
1531 Indexer ix = (Indexer) indexers [i];
1533 if ((ix.ModFlags & modflags) == 0)
1535 if ((ix.ModFlags & static_mask) != static_flags)
1538 MemberInfo ib = ix.PropertyBuilder;
1539 if (ib != null && filter (ib, criteria) == true) {
1540 if (members == null)
1541 members = new ArrayList ();
1543 members.Add (ix.PropertyBuilder);
1549 if ((mt & MemberTypes.NestedType) != 0) {
1550 if (types != null) {
1551 int len = types.Count;
1552 for (int i = 0; i < len; i++) {
1553 TypeContainer t = (TypeContainer) types [i];
1555 if ((t.ModFlags & modflags) == 0)
1558 TypeBuilder tb = t.TypeBuilder;
1559 if (tb != null && (filter (tb, criteria) == true)) {
1560 if (members == null)
1561 members = new ArrayList ();
1568 if (enums != null) {
1569 int len = enums.Count;
1570 for (int i = 0; i < len; i++) {
1571 Enum en = (Enum) enums [i];
1573 if ((en.ModFlags & modflags) == 0)
1576 TypeBuilder tb = en.TypeBuilder;
1577 if (tb != null && (filter (tb, criteria) == true)) {
1578 if (members == null)
1579 members = new ArrayList ();
1586 if (delegates != null) {
1587 int len = delegates.Count;
1588 for (int i = 0; i < len; i++) {
1589 Delegate d = (Delegate) delegates [i];
1591 if ((d.ModFlags & modflags) == 0)
1594 TypeBuilder tb = d.TypeBuilder;
1595 if (tb != null && (filter (tb, criteria) == true)) {
1596 if (members == null)
1597 members = new ArrayList ();
1604 if (interfaces != null) {
1605 int len = interfaces.Count;
1606 for (int i = 0; i < len; i++) {
1607 Interface iface = (Interface) interfaces [i];
1609 if ((iface.ModFlags & modflags) == 0)
1612 TypeBuilder tb = iface.TypeBuilder;
1613 if (tb != null && (filter (tb, criteria) == true)) {
1614 if (members == null)
1615 members = new ArrayList ();
1623 if ((mt & MemberTypes.Constructor) != 0){
1624 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1625 int len = instance_constructors.Count;
1626 for (int i = 0; i < len; i++) {
1627 Constructor c = (Constructor) instance_constructors [i];
1629 ConstructorBuilder cb = c.ConstructorBuilder;
1630 if (cb != null && filter (cb, criteria) == true) {
1631 if (members == null)
1632 members = new ArrayList ();
1639 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1640 ConstructorBuilder cb =
1641 default_static_constructor.ConstructorBuilder;
1643 if (cb != null && filter (cb, criteria) == true) {
1644 if (members == null)
1645 members = new ArrayList ();
1653 // Lookup members in parent if requested.
1655 if ((bf & BindingFlags.DeclaredOnly) == 0) {
1656 if (TypeBuilder.BaseType != null) {
1657 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1658 if (list.Count > 0) {
1659 if (members == null)
1660 members = new ArrayList ();
1662 members.AddRange (list);
1665 if (base_inteface_types != null) {
1666 foreach (Type base_type in base_inteface_types) {
1667 MemberList list = TypeContainer.FindMembers (base_type, mt, bf, filter, criteria);
1669 if (list.Count > 0) {
1670 if (members == null)
1671 members = new ArrayList ();
1672 members.AddRange (list);
1678 Timer.StopTimer (TimerType.TcFindMembers);
1680 if (members == null)
1681 return MemberList.Empty;
1683 return new MemberList (members);
1686 public override MemberCache MemberCache {
1688 return member_cache;
1692 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1693 MemberFilter filter, object criteria)
1695 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1698 return ds.FindMembers (mt, bf, filter, criteria);
1700 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1705 // FindMethods will look for methods not only in the type `t', but in
1706 // any interfaces implemented by the type.
1708 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1709 MemberFilter filter, object criteria)
1715 /// Emits the values for the constants
1717 public void EmitConstants ()
1719 if (constants != null)
1720 foreach (Const con in constants)
1725 protected virtual void VerifyMembers (EmitContext ec)
1728 // Check for internal or private fields that were never assigned
1730 if (RootContext.WarningLevel >= 3) {
1731 if (fields != null){
1732 foreach (Field f in fields) {
1733 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
1736 if ((f.status & Field.Status.USED) == 0){
1738 169, f.Location, "Private field " +
1739 MakeName (f.Name) + " is never used");
1744 // Only report 649 on level 4
1746 if (RootContext.WarningLevel < 4)
1749 if ((f.status & Field.Status.ASSIGNED) != 0)
1754 "Field " + MakeName (f.Name) + " is never assigned " +
1755 " to and will always have its default value");
1759 if (events != null){
1760 foreach (Event e in events){
1762 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1769 /// Emits the code, this step is performed after all
1770 /// the types, enumerations, constructors
1774 if (OptAttributes != null)
1775 OptAttributes.Emit (ec, this);
1779 if (instance_constructors != null) {
1780 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && IsClsCompliaceRequired (this)) {
1781 bool has_compliant_args = false;
1783 foreach (Constructor c in instance_constructors) {
1786 if (has_compliant_args)
1789 has_compliant_args = c.HasCompliantArgs;
1791 if (!has_compliant_args)
1792 Report.Error_T (3015, Location, GetSignatureForError ());
1794 foreach (Constructor c in instance_constructors)
1799 if (default_static_constructor != null)
1800 default_static_constructor.Emit (this);
1802 if (methods != null)
1803 foreach (Method m in methods)
1806 if (operators != null)
1807 foreach (Operator o in operators)
1810 if (properties != null)
1811 foreach (Property p in properties)
1814 if (indexers != null){
1815 foreach (Indexer ix in indexers)
1817 if (IndexerName != null) {
1818 CustomAttributeBuilder cb = EmitDefaultMemberAttr ();
1819 TypeBuilder.SetCustomAttribute (cb);
1824 foreach (Field f in fields)
1827 if (events != null){
1828 foreach (Event e in Events)
1832 if (delegates != null) {
1833 foreach (Delegate d in Delegates) {
1838 if (enums != null) {
1839 foreach (Enum e in enums) {
1844 if (Pending != null)
1845 if (Pending.VerifyPendingMethods ())
1850 // if (types != null)
1851 // foreach (TypeContainer tc in types)
1855 CustomAttributeBuilder EmitDefaultMemberAttr ()
1857 EmitContext ec = new EmitContext (this, Location, null, null, ModFlags);
1859 Expression ml = Expression.MemberLookup (ec, TypeManager.default_member_type,
1860 ".ctor", MemberTypes.Constructor,
1861 BindingFlags.Public | BindingFlags.Instance,
1864 MethodGroupExpr mg = (MethodGroupExpr) ml;
1866 MethodBase constructor = mg.Methods [0];
1868 string [] vals = { IndexerName };
1870 CustomAttributeBuilder cb = null;
1872 cb = new CustomAttributeBuilder ((ConstructorInfo) constructor, vals);
1874 Report.Warning (-100, "Can not set the indexer default member attribute");
1880 public override void CloseType ()
1882 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1886 caching_flags |= Flags.CloseTypeCreated;
1887 TypeBuilder.CreateType ();
1888 } catch (TypeLoadException){
1890 // This is fine, the code still created the type
1892 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1893 // Console.WriteLine (e.Message);
1895 Console.WriteLine ("In type: " + Name);
1900 foreach (Enum en in Enums)
1903 if (interface_order != null){
1904 foreach (Interface iface in interface_order)
1909 foreach (TypeContainer tc in Types)
1913 foreach (TypeContainer tc in Types)
1914 if (!(tc is Struct))
1918 if (Delegates != null)
1919 foreach (Delegate d in Delegates)
1927 initialized_fields = null;
1928 initialized_static_fields = null;
1931 interface_order = null;
1937 default_constructor = null;
1938 default_static_constructor = null;
1940 OptAttributes = null;
1942 parent_container = null;
1943 member_cache = null;
1946 public string MakeName (string n)
1948 return "`" + Name + "." + n + "'";
1951 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1954 108, l, "The keyword new is required on " +
1955 MakeName (mi.Name) + " because it hides `" +
1956 mi.ReflectedType.Name + "." + mi.Name + "'");
1959 public void Warning_KeywordNewNotRequired (Location l, MemberCore mc)
1962 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1963 "inherited member, the keyword new is not required");
1966 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
1969 72, l, MakeName (mi.Name) + " : cannot override; `" +
1970 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
1973 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1979 // Performs the validation on a Method's modifiers (properties have
1980 // the same properties).
1982 public bool MethodModifiersValid (int flags, string n, Location loc)
1984 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1985 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1986 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1990 // At most one of static, virtual or override
1992 if ((flags & Modifiers.STATIC) != 0){
1993 if ((flags & vao) != 0){
1995 112, loc, "static method " + MakeName (n) + "can not be marked " +
1996 "as virtual, abstract or override");
2001 if (this is Struct){
2002 if ((flags & va) != 0){
2003 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
2008 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2010 113, loc, MakeName (n) +
2011 " marked as override cannot be marked as new or virtual");
2016 // If the declaration includes the abstract modifier, then the
2017 // declaration does not include static, virtual or extern
2019 if ((flags & Modifiers.ABSTRACT) != 0){
2020 if ((flags & Modifiers.EXTERN) != 0){
2022 180, loc, MakeName (n) + " can not be both abstract and extern");
2026 if ((flags & Modifiers.VIRTUAL) != 0){
2028 503, loc, MakeName (n) + " can not be both abstract and virtual");
2032 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2034 513, loc, MakeName (n) +
2035 " is abstract but its container class is not");
2041 if ((flags & Modifiers.PRIVATE) != 0){
2042 if ((flags & vao) != 0){
2044 621, loc, MakeName (n) +
2045 " virtual or abstract members can not be private");
2050 if ((flags & Modifiers.SEALED) != 0){
2051 if ((flags & Modifiers.OVERRIDE) == 0){
2053 238, loc, MakeName (n) +
2054 " cannot be sealed because it is not an override");
2062 Hashtable builder_and_args;
2064 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
2066 if (builder_and_args == null)
2067 builder_and_args = new Hashtable ();
2071 protected override bool VerifyClsCompliance (DeclSpace ds)
2073 if (!base.VerifyClsCompliance (ds))
2076 // parent_container is null for System.Object
2077 if (parent_container != null && !AttributeTester.IsClsCompliant (parent_container.Type)) {
2078 Report.Error_T (3009, Location, GetSignatureForError (), TypeManager.CSharpName (parent_container.Type));
2085 /// Performs checks for an explicit interface implementation. First it
2086 /// checks whether the `interface_type' is a base inteface implementation.
2087 /// Then it checks whether `name' exists in the interface type.
2089 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
2093 if (ifaces != null){
2094 foreach (TypeExpr t in ifaces){
2095 if (t.Type == interface_type){
2103 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
2110 protected override void VerifyObsoleteAttribute()
2112 CheckUsageOfObsoleteAttribute (base_classs_type);
2117 foreach (TypeExpr expr in ifaces) {
2118 CheckUsageOfObsoleteAttribute (expr.Type);
2127 string IMemberContainer.Name {
2133 Type IMemberContainer.Type {
2139 IMemberContainer IMemberContainer.Parent {
2141 return parent_container;
2145 MemberCache IMemberContainer.MemberCache {
2147 return member_cache;
2151 bool IMemberContainer.IsInterface {
2153 return this is Interface;
2157 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2159 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
2163 // Operator pair checking
2166 class OperatorEntry {
2168 public Type ret_type;
2169 public Type type1, type2;
2171 public Operator.OpType ot;
2173 public OperatorEntry (int f, Operator o)
2177 ret_type = o.OperatorMethod.GetReturnType ();
2178 Type [] pt = o.OperatorMethod.ParameterTypes;
2182 ot = o.OperatorType;
2185 public override int GetHashCode ()
2187 return ret_type.GetHashCode ();
2190 public override bool Equals (object o)
2192 OperatorEntry other = (OperatorEntry) o;
2194 if (other.ret_type != ret_type)
2196 if (other.type1 != type1)
2198 if (other.type2 != type2)
2205 // Checks that some operators come in pairs:
2211 // They are matched based on the return type and the argument types
2213 void CheckPairedOperators ()
2215 Hashtable pairs = new Hashtable (null, null);
2216 Operator true_op = null;
2217 Operator false_op = null;
2218 bool has_equality_or_inequality = false;
2220 // Register all the operators we care about.
2221 foreach (Operator op in operators){
2224 switch (op.OperatorType){
2225 case Operator.OpType.Equality:
2227 has_equality_or_inequality = true;
2229 case Operator.OpType.Inequality:
2231 has_equality_or_inequality = true;
2234 case Operator.OpType.True:
2237 case Operator.OpType.False:
2241 case Operator.OpType.GreaterThan:
2243 case Operator.OpType.LessThan:
2246 case Operator.OpType.GreaterThanOrEqual:
2248 case Operator.OpType.LessThanOrEqual:
2254 OperatorEntry oe = new OperatorEntry (reg, op);
2256 object o = pairs [oe];
2260 oe = (OperatorEntry) o;
2265 if (true_op != null){
2266 if (false_op == null)
2267 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2268 } else if (false_op != null)
2269 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2272 // Look for the mistakes.
2274 foreach (DictionaryEntry de in pairs){
2275 OperatorEntry oe = (OperatorEntry) de.Key;
2282 case Operator.OpType.Equality:
2285 case Operator.OpType.Inequality:
2288 case Operator.OpType.GreaterThan:
2291 case Operator.OpType.LessThan:
2294 case Operator.OpType.GreaterThanOrEqual:
2297 case Operator.OpType.LessThanOrEqual:
2301 Report.Error (216, oe.op.Location,
2302 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2305 if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2306 MethodSignature equals_ms = new MethodSignature (
2307 "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2308 MethodSignature hash_ms = new MethodSignature (
2309 "GetHashCode", TypeManager.int32_type, new Type [0]);
2311 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2312 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2314 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2315 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2318 bool equals_ok = false;
2319 if ((equals_ml != null) && (equals_ml.Count == 1))
2320 equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2321 bool hash_ok = false;
2322 if ((hash_ml != null) && (hash_ml.Count == 1))
2323 hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2326 Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2327 "not override Object.Equals (object o)");
2329 Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2330 "not override Object.GetHashCode ()");
2337 public class ClassOrStruct : TypeContainer {
2338 bool hasExplicitLayout = false;
2339 public ClassOrStruct (NamespaceEntry ns, TypeContainer parent, string name, Attributes attrs, Location l)
2340 : base (ns, parent, name, attrs, l)
2344 protected override void VerifyMembers (EmitContext ec)
2346 if (Fields != null) {
2347 foreach (Field f in Fields) {
2348 if ((f.ModFlags & Modifiers.STATIC) != 0)
2350 if (hasExplicitLayout) {
2351 if (f.OptAttributes == null
2352 || !f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
2353 Report.Error (625, f.Location,
2354 "Instance field of type marked with"
2355 + " StructLayout(LayoutKind.Explicit) must have a"
2356 + " FieldOffset attribute.");
2360 if (f.OptAttributes != null
2361 && f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
2362 Report.Error (636, f.Location,
2363 "The FieldOffset attribute can only be placed on members of "
2364 + "types marked with the StructLayout(LayoutKind.Explicit)");
2369 base.VerifyMembers (ec);
2372 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2374 if (a.Type == TypeManager.struct_layout_attribute_type
2375 && (LayoutKind) a.GetPositionalValue (0) == LayoutKind.Explicit)
2376 hasExplicitLayout = true;
2378 base.ApplyAttributeBuilder (a, cb);
2382 public class Class : ClassOrStruct {
2384 // Modifiers allowed in a class declaration
2386 public const int AllowedModifiers =
2389 Modifiers.PROTECTED |
2390 Modifiers.INTERNAL |
2392 Modifiers.ABSTRACT |
2397 // Information in the case we are an attribute type
2398 AttributeUsageAttribute attribute_usage;
2400 public Class (NamespaceEntry ns, TypeContainer parent, string name, int mod,
2401 Attributes attrs, Location l)
2402 : base (ns, parent, name, attrs, l)
2406 if (parent.Parent == null)
2407 accmods = Modifiers.INTERNAL;
2409 accmods = Modifiers.PRIVATE;
2411 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2412 attribute_usage = new AttributeUsageAttribute (AttributeTargets.All);
2415 public override AttributeTargets AttributeTargets {
2417 return AttributeTargets.Class;
2421 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
2423 if (a.UsageAttribute != null)
2424 attribute_usage = a.UsageAttribute;
2426 base.ApplyAttributeBuilder (a, cb);
2429 public AttributeUsageAttribute AttributeUsage {
2431 return attribute_usage;
2436 // FIXME: How do we deal with the user specifying a different
2439 public override TypeAttributes TypeAttr {
2441 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2446 public class Struct : ClassOrStruct {
2448 // Modifiers allowed in a struct declaration
2450 public const int AllowedModifiers =
2453 Modifiers.PROTECTED |
2454 Modifiers.INTERNAL |
2458 public Struct (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2459 : base (ns, parent, name, attrs, l)
2463 if (parent.Parent == null)
2464 accmods = Modifiers.INTERNAL;
2466 accmods = Modifiers.PRIVATE;
2468 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2470 this.ModFlags |= Modifiers.SEALED;
2473 public override AttributeTargets AttributeTargets {
2475 return AttributeTargets.Struct;
2481 // FIXME: Allow the user to specify a different set of attributes
2482 // in some cases (Sealed for example is mandatory for a class,
2483 // but what SequentialLayout can be changed
2485 public override TypeAttributes TypeAttr {
2487 return base.TypeAttr |
2488 TypeAttributes.SequentialLayout |
2489 TypeAttributes.Sealed |
2490 TypeAttributes.BeforeFieldInit;
2498 public class Interface : TypeContainer, IMemberContainer {
2500 /// Modifiers allowed in a class declaration
2502 public const int AllowedModifiers =
2505 Modifiers.PROTECTED |
2506 Modifiers.INTERNAL |
2510 public Interface (NamespaceEntry ns, TypeContainer parent, string name, int mod,
2511 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);
2524 public override AttributeTargets AttributeTargets {
2526 return AttributeTargets.Interface;
2530 public override TypeAttributes TypeAttr {
2532 return base.TypeAttr |
2533 TypeAttributes.AutoLayout |
2534 TypeAttributes.Abstract |
2535 TypeAttributes.Interface;
2540 public abstract class MethodCore : MemberBase {
2541 public readonly Parameters Parameters;
2542 protected Block block;
2543 public DeclSpace ds;
2546 // Parameters, cached for semantic analysis.
2548 protected InternalParameters parameter_info;
2549 protected Type [] parameter_types;
2552 // This is set from TypeContainer.DefineMembers if this method overrides something.
2554 public bool OverridesSomething;
2556 // Whether this is an operator method.
2557 public bool IsOperator;
2559 static string[] attribute_targets = new string [] { "method", "return" };
2561 public MethodCore (DeclSpace ds, Expression type, int mod, int allowed_mod,
2562 bool is_interface, string name, Attributes attrs,
2563 Parameters parameters, Location loc)
2564 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
2566 Parameters = parameters;
2567 IsInterface = is_interface;
2572 // Returns the System.Type array for the parameters of this method
2574 public Type [] ParameterTypes {
2576 return parameter_types;
2580 public InternalParameters ParameterInfo
2583 return parameter_info;
2587 public Block Block {
2597 protected virtual bool DoDefineParameters ()
2599 // Check if arguments were correct
2600 parameter_types = Parameters.GetParameterInfo (ds);
2601 if ((parameter_types == null) || !CheckParameters (ds, parameter_types))
2604 parameter_info = new InternalParameters (ds, Parameters);
2606 Parameter array_param = Parameters.ArrayParameter;
2607 if ((array_param != null) &&
2608 (!array_param.ParameterType.IsArray ||
2609 (array_param.ParameterType.GetArrayRank () != 1))) {
2610 Report.Error (225, Location, "params parameter has to be a single dimensional array");
2617 protected override string[] ValidAttributeTargets {
2619 return attribute_targets;
2623 protected override bool VerifyClsCompliance (DeclSpace ds)
2625 if (!base.VerifyClsCompliance (ds)) {
2626 if ((ModFlags & Modifiers.ABSTRACT) != 0 && IsExposedFromAssembly (ds) && ds.IsClsCompliaceRequired (ds)) {
2627 Report.Error_T (3011, Location, GetSignatureForError ());
2632 if (Parameters.HasArglist) {
2633 // "Methods with variable arguments are not CLS-compliant"
2634 Report.Error_T (3000, Location);
2637 AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);
2639 if (!AttributeTester.IsClsCompliant (MemberType)) {
2640 Report.Error_T (3002, Location, GetSignatureForError ());
2646 protected bool IsDuplicateImplementation (TypeContainer tc, MethodCore method)
2648 if ((method == this) || (method.Name != Name))
2651 Type[] param_types = method.ParameterTypes;
2652 if (param_types == null)
2655 if (param_types.Length != ParameterTypes.Length)
2658 for (int i = 0; i < param_types.Length; i++)
2659 if (param_types [i] != ParameterTypes [i])
2663 // Try to report 663: method only differs on out/ref
2665 ParameterData info = ParameterInfo;
2666 ParameterData other_info = method.ParameterInfo;
2667 for (int i = 0; i < info.Count; i++){
2668 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
2669 Report.Error (663, Location, "Overload method only differs in parameter modifier");
2674 Report.Error (111, Location, "Class `{0}' already defines a " +
2675 "member called `{1}' with the same parameter types",
2680 public CallingConventions GetCallingConvention (bool is_class)
2682 CallingConventions cc = 0;
2684 cc = Parameters.GetCallingConvention ();
2687 if ((ModFlags & Modifiers.STATIC) == 0)
2688 cc |= CallingConventions.HasThis;
2690 // FIXME: How is `ExplicitThis' used in C#?
2695 protected override void VerifyObsoleteAttribute()
2697 base.VerifyObsoleteAttribute ();
2699 if (parameter_types == null)
2702 foreach (Type type in parameter_types) {
2703 CheckUsageOfObsoleteAttribute (type);
2708 public class Method : MethodCore, IIteratorContainer, IMethodData {
2709 public MethodBuilder MethodBuilder;
2710 public MethodData MethodData;
2711 ReturnParameter return_attributes;
2714 /// Modifiers allowed in a class declaration
2716 const int AllowedModifiers =
2719 Modifiers.PROTECTED |
2720 Modifiers.INTERNAL |
2725 Modifiers.OVERRIDE |
2726 Modifiers.ABSTRACT |
2728 Modifiers.METHOD_YIELDS |
2731 const int AllowedInterfaceModifiers =
2732 Modifiers.NEW | Modifiers.UNSAFE;
2735 // return_type can be "null" for VOID values.
2737 public Method (DeclSpace ds, Expression return_type, int mod, bool is_iface,
2738 string name, Parameters parameters, Attributes attrs, Location l)
2739 : base (ds, return_type, mod,
2740 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
2741 is_iface, name, attrs, parameters, l)
2745 public override AttributeTargets AttributeTargets {
2747 return AttributeTargets.Method | AttributeTargets.ReturnValue;
2752 // Returns the `System.Type' for the ReturnType of this
2753 // function. Provides a nice cache. (used between semantic analysis
2754 // and actual code generation
2756 public Type GetReturnType ()
2761 public override string GetSignatureForError()
2763 return TypeManager.CSharpSignature (MethodBuilder);
2767 /// Use this method when MethodBuilder is null
2769 public override string GetSignatureForError (TypeContainer tc)
2771 // TODO: move to parameters
2772 System.Text.StringBuilder args = new System.Text.StringBuilder ();
2773 if (parameter_info.Parameters.FixedParameters != null) {
2774 for (int i = 0; i < parameter_info.Parameters.FixedParameters.Length; ++i) {
2775 Parameter p = parameter_info.Parameters.FixedParameters [i];
2776 args.Append (p.GetSignatureForError ());
2778 if (i < parameter_info.Parameters.FixedParameters.Length - 1)
2783 return String.Concat (base.GetSignatureForError (tc), "(", args.ToString (), ")");
2786 void DuplicateEntryPoint (MethodInfo b, Location location)
2790 "Program `" + CodeGen.FileName +
2791 "' has more than one entry point defined: `" +
2792 TypeManager.CSharpSignature(b) + "'");
2795 void Report28 (MethodInfo b)
2799 "`" + TypeManager.CSharpSignature(b) +
2800 "' has the wrong signature to be an entry point");
2803 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2805 if (b.ReturnType != TypeManager.void_type &&
2806 b.ReturnType != TypeManager.int32_type)
2809 if (pinfo.Count == 0)
2812 if (pinfo.Count > 1)
2815 Type t = pinfo.ParameterType(0);
2817 (t.GetArrayRank() == 1) &&
2818 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
2819 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2825 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2827 if (a.Target == "return") {
2828 if (return_attributes == null)
2829 return_attributes = new ReturnParameter (MethodBuilder, Location);
2831 return_attributes.ApplyAttributeBuilder (a, cb);
2835 if (a.Type == TypeManager.methodimpl_attr_type && a.IsInternalCall) {
2836 MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
2839 if (a.Type == TypeManager.dllimport_type) {
2840 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2841 if ((ModFlags & extern_static) != extern_static) {
2842 //"The DllImport attribute must be specified on a method marked `static' and `extern'"
2843 Report.Error_T (601, a.Location);
2849 if (a.Type == TypeManager.conditional_attribute_type) {
2850 if (IsOperator || IsExplicitImpl) {
2851 // Conditional not valid on '{0}' because it is a destructor, operator, or explicit interface implementation
2852 Report.Error_T (577, Location, GetSignatureForError ());
2856 if (ReturnType != TypeManager.void_type) {
2857 // Conditional not valid on '{0}' because its return type is not void
2858 Report.Error_T (578, Location, GetSignatureForError ());
2862 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
2863 // Conditional not valid on '{0}' because it is an override method
2864 Report.Error_T (243, Location, GetSignatureForError ());
2869 // Conditional not valid on interface members
2870 Report.Error_T (582, Location);
2874 if (MethodData.IsImplementing) {
2875 // Conditional member '{0}' cannot implement interface member
2876 Report.Error_T (629, Location, GetSignatureForError ());
2881 MethodBuilder.SetCustomAttribute (cb);
2885 // Checks our base implementation if any
2887 protected override bool CheckBase (TypeContainer container)
2889 base.CheckBase (container);
2891 // Check whether arguments were correct.
2892 if (!DoDefineParameters ())
2895 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2897 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2900 // Check in our class for dups
2902 ArrayList ar = container.Methods;
2904 int arLen = ar.Count;
2906 for (int i = 0; i < arLen; i++) {
2907 Method m = (Method) ar [i];
2908 if (IsDuplicateImplementation (container, m))
2916 // Verify if the parent has a type with the same name, and then
2917 // check whether we have to create a new slot for it or not.
2919 Type ptype = container.TypeBuilder.BaseType;
2921 // ptype is only null for System.Object while compiling corlib.
2922 if (ptype != null) {
2925 // Explicit implementations do not have `parent' methods, however,
2926 // the member cache stores them there. Without this check, we get
2927 // an incorrect warning in corlib.
2929 if (! IsExplicitImpl) {
2930 parent_method = (MethodInfo)((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
2931 container.TypeBuilder, Name, ParameterTypes, false);
2934 if (parent_method != null) {
2935 string name = parent_method.DeclaringType.Name + "." +
2938 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
2941 if ((ModFlags & Modifiers.NEW) == 0) {
2942 Type parent_ret = TypeManager.TypeToCoreType (
2943 parent_method.ReturnType);
2945 if (parent_ret != MemberType) {
2947 508, Location, container.MakeName (Name) + ": cannot " +
2948 "change return type when overriding " +
2949 "inherited member " + name);
2954 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (parent_method);
2956 Report.SymbolRelatedToPreviousError (parent_method);
2957 Report.Warning_T (672, Location, GetSignatureForError (container));
2960 if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
2961 WarningNotHiding (container);
2963 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2964 Report.Error (115, Location,
2965 container.MakeName (Name) +
2966 " no suitable methods found to override");
2969 } else if ((ModFlags & Modifiers.NEW) != 0)
2970 WarningNotHiding (container);
2978 public override bool Define (TypeContainer container)
2980 if (!DoDefine (container))
2983 if (!CheckBase (container))
2986 MethodData = new MethodData (this, ParameterInfo, ModFlags, flags, this);
2988 if (!MethodData.Define (container))
2992 // Setup iterator if we are one
2994 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
2995 IteratorHandler ih = new IteratorHandler (
2996 Name, container, MemberType,
2997 ParameterTypes, ParameterInfo,
2998 ModFlags, Location);
3000 Block new_block = ih.Setup (block);
3001 if (new_block == null)
3006 MethodBuilder = MethodData.MethodBuilder;
3009 // This is used to track the Entry Point,
3011 if (Name == "Main" &&
3012 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
3013 (RootContext.MainClass == null ||
3014 RootContext.MainClass == container.TypeBuilder.FullName)){
3015 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
3016 if (RootContext.EntryPoint == null) {
3017 RootContext.EntryPoint = MethodBuilder;
3018 RootContext.EntryPointLocation = Location;
3020 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
3021 DuplicateEntryPoint (MethodBuilder, Location);
3024 Report28(MethodBuilder);
3033 public override void Emit (TypeContainer container)
3035 MethodData.Emit (container, this);
3036 base.Emit (container);
3041 void IIteratorContainer.SetYields ()
3043 ModFlags |= Modifiers.METHOD_YIELDS;
3046 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
3048 return IsIdentifierAndParamClsCompliant (ds, Name, MethodBuilder, parameter_types);
3051 #region IMethodData Members
3053 public CallingConventions CallingConventions {
3055 CallingConventions cc = Parameters.GetCallingConvention ();
3056 if (Parameters.HasArglist)
3057 block.HasVarargs = true;
3060 if ((ModFlags & Modifiers.STATIC) == 0)
3061 cc |= CallingConventions.HasThis;
3063 // FIXME: How is `ExplicitThis' used in C#?
3069 public Type ReturnType {
3075 public string MethodName {
3081 public new Location Location {
3083 return base.Location;
3087 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
3089 return new EmitContext (tc, ds, Location, ig, ReturnType, ModFlags, false);
3092 public ObsoleteAttribute GetObsoleteAttribute ()
3094 return GetObsoleteAttribute (ds);
3098 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
3100 public bool IsExcluded (EmitContext ec)
3102 if ((caching_flags & Flags.Excluded_Undetected) == 0)
3103 return (caching_flags & Flags.Excluded) != 0;
3105 caching_flags &= ~Flags.Excluded_Undetected;
3107 if (parent_method == null) {
3108 if (OptAttributes == null)
3111 Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type, ec);
3116 foreach (Attribute a in attrs) {
3117 string condition = a.GetConditionalAttributeValue (ds);
3118 if (RootContext.AllDefines.Contains (condition))
3122 caching_flags |= Flags.Excluded;
3126 IMethodData md = TypeManager.GetMethod (parent_method);
3128 if (AttributeTester.IsConditionalMethodExcluded (parent_method)) {
3129 caching_flags |= Flags.Excluded;
3135 if (md.IsExcluded (ec)) {
3136 caching_flags |= Flags.Excluded;
3145 public abstract class ConstructorInitializer {
3146 ArrayList argument_list;
3147 protected ConstructorInfo parent_constructor;
3148 Parameters parameters;
3151 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
3154 this.argument_list = argument_list;
3155 this.parameters = parameters;
3159 public ArrayList Arguments {
3161 return argument_list;
3165 public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
3167 Expression parent_constructor_group;
3170 ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
3172 if (argument_list != null){
3173 foreach (Argument a in argument_list){
3174 if (!a.Resolve (ec, loc))
3178 ec.CurrentBlock = null;
3180 if (this is ConstructorBaseInitializer) {
3181 if (ec.ContainerType.BaseType == null)
3184 t = ec.ContainerType.BaseType;
3185 if (ec.ContainerType.IsValueType) {
3186 Report.Error (522, loc,
3187 "structs cannot call base class constructors");
3191 t = ec.ContainerType;
3193 parent_constructor_group = Expression.MemberLookup (
3194 ec, t, ".ctor", MemberTypes.Constructor,
3195 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3198 if (parent_constructor_group == null){
3199 parent_constructor_group = Expression.MemberLookup (
3200 ec, t, ".ctor", MemberTypes.Constructor,
3201 BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3204 if (parent_constructor_group != null)
3206 112, loc, "`{0}.{1}' is inaccessible due to " +
3207 "its protection level", t.FullName, t.Name);
3210 1501, loc, "Can not find a constructor for " +
3211 "this argument list");
3215 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
3216 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
3218 if (parent_constructor == null){
3219 Report.Error (1501, loc,
3220 "Can not find a constructor for this argument list");
3224 if (parent_constructor == caller_builder){
3225 Report.Error (515, String.Format ("Constructor `{0}' can not call itself", TypeManager.CSharpSignature (caller_builder)));
3232 public void Emit (EmitContext ec)
3234 if (parent_constructor != null){
3235 ec.Mark (loc, false);
3237 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
3239 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
3244 /// Method search for base ctor. (We do not cache it).
3246 Constructor GetOverloadedConstructor (TypeContainer tc)
3248 if (tc.InstanceConstructors == null)
3251 foreach (Constructor c in tc.InstanceConstructors) {
3252 if (Arguments == null) {
3253 if (c.ParameterTypes.Length == 0)
3261 int count = c.ParameterInfo.Count;
3263 c.ParameterInfo.ParameterModifier (count - 1) == Parameter.Modifier.PARAMS) {
3264 for (int i = 0; i < count-1; i++)
3265 if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
3270 if (c.ParameterTypes.Length != Arguments.Count)
3273 for (int i = 0; i < Arguments.Count; ++i)
3274 if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
3289 //TODO: implement caching when it will be necessary
3290 public virtual void CheckObsoleteAttribute (TypeContainer tc, Location loc)
3292 Constructor ctor = GetOverloadedConstructor (tc);
3296 ObsoleteAttribute oa = ctor.GetObsoleteAttribute (tc);
3300 AttributeTester.Report_ObsoleteMessage (oa, ctor.GetSignatureForError (), loc);
3304 public class ConstructorBaseInitializer : ConstructorInitializer {
3305 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
3306 base (argument_list, pars, l)
3310 public override void CheckObsoleteAttribute(TypeContainer tc, Location loc) {
3311 if (parent_constructor == null)
3314 TypeContainer type_ds = TypeManager.LookupTypeContainer (tc.base_classs_type);
3315 if (type_ds == null) {
3316 ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (parent_constructor);
3319 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (parent_constructor), loc);
3324 base.CheckObsoleteAttribute (type_ds, loc);
3329 public class ConstructorThisInitializer : ConstructorInitializer {
3330 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
3331 base (argument_list, pars, l)
3336 public class Constructor : MethodCore {
3337 public ConstructorBuilder ConstructorBuilder;
3338 public ConstructorInitializer Initializer;
3341 // Modifiers allowed for a constructor.
3343 public const int AllowedModifiers =
3345 Modifiers.PROTECTED |
3346 Modifiers.INTERNAL |
3352 bool has_compliant_args = false;
3354 // The spec claims that static is not permitted, but
3355 // my very own code has static constructors.
3357 public Constructor (DeclSpace ds, string name, int mod, Parameters args,
3358 ConstructorInitializer init, Location l)
3359 : base (ds, null, mod, AllowedModifiers, false, name, null, args, l)
3364 public override string GetSignatureForError()
3366 return TypeManager.CSharpSignature (ConstructorBuilder);
3369 public bool HasCompliantArgs {
3371 return has_compliant_args;
3375 public override AttributeTargets AttributeTargets {
3377 return AttributeTargets.Constructor;
3383 // Returns true if this is a default constructor
3385 public bool IsDefault ()
3387 if ((ModFlags & Modifiers.STATIC) != 0)
3388 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3389 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
3392 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3393 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
3394 (Initializer is ConstructorBaseInitializer) &&
3395 (Initializer.Arguments == null);
3398 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3400 ConstructorBuilder.SetCustomAttribute (cb);
3403 protected override bool CheckBase (TypeContainer container)
3405 base.CheckBase (container);
3407 // Check whether arguments were correct.
3408 if (!DoDefineParameters ())
3411 if ((ModFlags & Modifiers.STATIC) != 0)
3414 if (container is Struct && ParameterTypes.Length == 0) {
3415 Report.Error (568, Location,
3416 "Structs can not contain explicit parameterless " +
3422 // Check in our class for dups
3424 ArrayList ar = container.InstanceConstructors;
3426 int arLen = ar.Count;
3428 for (int i = 0; i < arLen; i++) {
3429 Constructor m = (Constructor) ar [i];
3430 if (IsDuplicateImplementation (container, m))
3439 // Creates the ConstructorBuilder
3441 public override bool Define (TypeContainer container)
3443 MethodAttributes ca = (MethodAttributes.RTSpecialName |
3444 MethodAttributes.SpecialName);
3446 if ((ModFlags & Modifiers.STATIC) != 0) {
3447 ca |= MethodAttributes.Static | MethodAttributes.Private;
3449 ca |= MethodAttributes.HideBySig;
3451 if ((ModFlags & Modifiers.PUBLIC) != 0)
3452 ca |= MethodAttributes.Public;
3453 else if ((ModFlags & Modifiers.PROTECTED) != 0){
3454 if ((ModFlags & Modifiers.INTERNAL) != 0)
3455 ca |= MethodAttributes.FamORAssem;
3457 ca |= MethodAttributes.Family;
3458 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
3459 ca |= MethodAttributes.Assembly;
3460 else if (IsDefault ())
3461 ca |= MethodAttributes.Public;
3463 ca |= MethodAttributes.Private;
3466 // Check if arguments were correct.
3467 if (!CheckBase (container))
3470 ConstructorBuilder = container.TypeBuilder.DefineConstructor (
3471 ca, GetCallingConvention (container is Class), ParameterTypes);
3473 if ((ModFlags & Modifiers.UNSAFE) != 0)
3474 ConstructorBuilder.InitLocals = false;
3477 // HACK because System.Reflection.Emit is lame
3479 TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
3487 public override void Emit (TypeContainer container)
3489 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
3490 EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
3493 // extern methods have no bodies
3495 if ((ModFlags & Modifiers.EXTERN) != 0) {
3496 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
3498 179, Location, "External constructor `" +
3499 TypeManager.CSharpSignature (ConstructorBuilder) +
3500 "' can not have a body");
3503 } else if (block == null) {
3505 501, Location, "Constructor `" +
3506 TypeManager.CSharpSignature (ConstructorBuilder) +
3507 "' must declare a body since it is not marked extern");
3511 if ((ModFlags & Modifiers.STATIC) == 0){
3512 if (container is Class && Initializer == null)
3513 Initializer = new ConstructorBaseInitializer (
3514 null, Parameters.EmptyReadOnlyParameters, Location);
3518 // Spec mandates that Initializers will not have
3522 if (Initializer != null && !Initializer.Resolve (ConstructorBuilder, ec))
3524 ec.IsStatic = false;
3527 Parameters.LabelParameters (ec, ConstructorBuilder, Location);
3529 SymbolWriter sw = CodeGen.SymbolWriter;
3530 bool generate_debugging = false;
3532 if ((sw != null) && (block != null) &&
3533 !Location.IsNull (Location) &&
3534 !Location.IsNull (block.EndLocation) &&
3535 (Location.SymbolDocument != null)) {
3536 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
3538 generate_debugging = true;
3542 // Classes can have base initializers and instance field initializers.
3544 if (container is Class){
3545 if ((ModFlags & Modifiers.STATIC) == 0){
3548 // If we use a "this (...)" constructor initializer, then
3549 // do not emit field initializers, they are initialized in the other constructor
3551 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
3552 container.EmitFieldInitializers (ec);
3555 if (Initializer != null) {
3556 Initializer.CheckObsoleteAttribute (container, Location);
3557 Initializer.Emit (ec);
3560 if ((ModFlags & Modifiers.STATIC) != 0)
3561 container.EmitFieldInitializers (ec);
3563 if (OptAttributes != null)
3564 OptAttributes.Emit (ec, this);
3566 // If this is a non-static `struct' constructor and doesn't have any
3567 // initializer, it must initialize all of the struct's fields.
3568 if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
3569 Block.AddThisVariable (container, Location);
3571 ec.EmitTopBlock (block, ParameterInfo, Location);
3573 if (generate_debugging)
3576 base.Emit (container);
3581 // For constructors is needed to test only parameters
3582 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
3584 if (parameter_types == null || parameter_types.Length == 0)
3587 TypeContainer tc = ds as TypeContainer;
3589 for (int i = 0; i < tc.InstanceConstructors.Count; i++) {
3590 Constructor c = (Constructor) tc.InstanceConstructors [i];
3592 if (c == this || c.ParameterTypes.Length == 0)
3595 if (!c.IsClsCompliaceRequired (ds))
3598 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, c.ParameterTypes)) {
3599 Report.Error_T (3006, Location, GetSignatureForError ());
3604 if (tc.TypeBuilder.BaseType == null)
3607 DeclSpace temp_ds = TypeManager.LookupDeclSpace (tc.TypeBuilder.BaseType);
3608 if (temp_ds != null)
3609 return IsIdentifierClsCompliant (temp_ds);
3611 MemberInfo[] ml = tc.TypeBuilder.BaseType.FindMembers (MemberTypes.Constructor, BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance, null, null);
3612 // Skip parameter-less ctor
3616 foreach (ConstructorInfo ci in ml) {
3617 object[] cls_attribute = ci.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
3618 if (cls_attribute.Length == 1 && (!((CLSCompliantAttribute)cls_attribute[0]).IsCompliant))
3621 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, TypeManager.GetArgumentTypes (ci))) {
3622 Report.Error_T (3006, Location, GetSignatureForError ());
3630 protected override bool VerifyClsCompliance (DeclSpace ds)
3632 if (!base.VerifyClsCompliance (ds) || !IsExposedFromAssembly (ds)) {
3636 if (ds.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
3637 foreach (Type param in parameter_types) {
3638 if (param.IsArray) {
3643 has_compliant_args = true;
3650 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
3652 public interface IMethodData
3654 CallingConventions CallingConventions { get; }
3655 Location Location { get; }
3656 string MethodName { get; }
3657 Type[] ParameterTypes { get; }
3658 Type ReturnType { get; }
3660 Attributes OptAttributes { get; }
3661 Block Block { get; }
3663 EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig);
3664 ObsoleteAttribute GetObsoleteAttribute ();
3665 string GetSignatureForError (TypeContainer tc);
3666 bool IsExcluded (EmitContext ec);
3670 // Encapsulates most of the Method's state
3672 public class MethodData {
3674 readonly IMethodData method;
3677 // The return type of this method
3679 public readonly InternalParameters ParameterInfo;
3682 // Are we implementing an interface ?
3684 public bool IsImplementing = false;
3689 protected MemberBase member;
3690 protected int modifiers;
3691 protected MethodAttributes flags;
3693 MethodBuilder builder = null;
3694 public MethodBuilder MethodBuilder {
3700 public MethodData (MemberBase member, InternalParameters parameters,
3701 int modifiers, MethodAttributes flags, IMethodData method)
3703 this.member = member;
3704 this.ParameterInfo = parameters;
3705 this.modifiers = modifiers;
3708 this.method = method;
3711 public bool Define (TypeContainer container)
3713 MethodInfo implementing = null;
3716 if (member.IsExplicitImpl)
3717 prefix = member.InterfaceType.FullName + ".";
3721 string name = method.MethodName;
3722 string method_name = prefix + name;
3723 Type[] ParameterTypes = method.ParameterTypes;
3725 if (container.Pending != null){
3726 if (member is Indexer)
3727 implementing = container.Pending.IsInterfaceIndexer (
3728 member.InterfaceType, method.ReturnType, ParameterTypes);
3730 implementing = container.Pending.IsInterfaceMethod (
3731 member.InterfaceType, name, method.ReturnType, ParameterTypes);
3733 if (member.InterfaceType != null && implementing == null){
3734 Report.Error (539, method.Location, "'{0}' in explicit interface declaration is not an interface", method_name);
3740 // For implicit implementations, make sure we are public, for
3741 // explicit implementations, make sure we are private.
3743 if (implementing != null){
3745 // Setting null inside this block will trigger a more
3746 // verbose error reporting for missing interface implementations
3748 // The "candidate" function has been flagged already
3749 // but it wont get cleared
3751 if (member.IsExplicitImpl){
3752 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3753 Modifiers.Error_InvalidModifier (method.Location, "public, virtual or abstract");
3754 implementing = null;
3756 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
3757 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
3759 // If this is an interface method implementation,
3760 // check for public accessibility
3762 implementing = null;
3763 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
3764 // We may never be private.
3765 implementing = null;
3766 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
3768 // We may be protected if we're overriding something.
3770 implementing = null;
3775 // Static is not allowed
3777 if ((modifiers & Modifiers.STATIC) != 0){
3778 implementing = null;
3779 Modifiers.Error_InvalidModifier (method.Location, "static");
3784 // If implementing is still valid, set flags
3786 if (implementing != null){
3788 // When implementing interface methods, set NewSlot
3789 // unless, we are overwriting a method.
3791 if (implementing.DeclaringType.IsInterface){
3792 if ((modifiers & Modifiers.OVERRIDE) == 0)
3793 flags |= MethodAttributes.NewSlot;
3796 MethodAttributes.Virtual |
3797 MethodAttributes.HideBySig;
3799 // Set Final unless we're virtual, abstract or already overriding a method.
3800 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
3801 flags |= MethodAttributes.Final;
3803 // Get the method name from the explicit interface.
3804 if (member.InterfaceType != null) {
3805 name = implementing.Name;
3806 method_name = prefix + name;
3809 IsImplementing = true;
3812 EmitContext ec = method.CreateEmitContext (container, null);
3814 DefineMethodBuilder (ec, container, method_name, ParameterTypes);
3816 if (builder == null)
3819 if ((modifiers & Modifiers.UNSAFE) != 0)
3820 builder.InitLocals = false;
3822 if (IsImplementing){
3824 // clear the pending implemntation flag
3826 if (member is Indexer) {
3827 container.Pending.ImplementIndexer (
3828 member.InterfaceType, builder, method.ReturnType,
3829 ParameterTypes, true);
3831 container.Pending.ImplementMethod (
3832 member.InterfaceType, name, method.ReturnType,
3833 ParameterTypes, member.IsExplicitImpl);
3835 if (member.IsExplicitImpl)
3836 container.TypeBuilder.DefineMethodOverride (
3837 builder, implementing);
3841 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3842 Report.Error (111, method.Location,
3843 "Class `" + container.Name +
3844 "' already contains a definition with the " +
3845 "same return value and parameter types as the " +
3846 "'get' method of property `" + member.Name + "'");
3850 TypeManager.AddMethod (builder, method);
3857 /// Create the MethodBuilder for the method
3859 void DefineMethodBuilder (EmitContext ec, TypeContainer container, string method_name, Type[] ParameterTypes)
3861 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3863 if ((modifiers & extern_static) == extern_static) {
3865 if (method.OptAttributes != null) {
3866 Attribute dllimport_attribute = method.OptAttributes.Search (TypeManager.dllimport_type, ec);
3867 if (dllimport_attribute != null) {
3868 flags |= MethodAttributes.PinvokeImpl;
3869 builder = dllimport_attribute.DefinePInvokeMethod (
3870 ec, container.TypeBuilder, method_name, flags,
3871 method.ReturnType, ParameterTypes);
3877 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3878 // We are more strict than Microsoft and report CS0626 like error
3879 if (method.OptAttributes == null ||
3880 !method.OptAttributes.Contains (TypeManager.methodimpl_attr_type, ec)) {
3881 //"Method, operator, or accessor '{0}' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation"
3882 Report.Error_T (626, method.Location, method.GetSignatureForError (container));
3887 builder = container.TypeBuilder.DefineMethod (
3888 method_name, flags, method.CallingConventions,
3889 method.ReturnType, ParameterTypes);
3895 public void Emit (TypeContainer container, Attributable kind)
3899 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3900 ec = method.CreateEmitContext (container, builder.GetILGenerator ());
3902 ec = method.CreateEmitContext (container, null);
3904 Location loc = method.Location;
3905 Attributes OptAttributes = method.OptAttributes;
3907 if (OptAttributes != null)
3908 OptAttributes.Emit (ec, kind);
3910 if (member is MethodCore)
3911 ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, loc);
3913 SymbolWriter sw = CodeGen.SymbolWriter;
3914 Block block = method.Block;
3917 // abstract or extern methods have no bodies
3919 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3920 if (block == null) {
3921 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0) &&
3922 !Location.IsNull (loc) &&
3923 (method.Location.SymbolDocument != null)) {
3924 sw.OpenMethod (container, MethodBuilder, loc, loc);
3932 // abstract or extern methods have no bodies.
3934 if ((modifiers & Modifiers.ABSTRACT) != 0)
3936 500, method.Location, "Abstract method `" +
3937 TypeManager.CSharpSignature (builder) +
3938 "' can not have a body");
3940 if ((modifiers & Modifiers.EXTERN) != 0)
3942 179, method.Location, "External method `" +
3943 TypeManager.CSharpSignature (builder) +
3944 "' can not have a body");
3950 // Methods must have a body unless they're extern or abstract
3952 if (block == null) {
3954 501, method.Location, "Method `" +
3955 TypeManager.CSharpSignature (builder) +
3956 "' must declare a body since it is not marked " +
3957 "abstract or extern");
3962 // Handle destructors specially
3964 // FIXME: This code generates buggy code
3966 if ((sw != null) && !Location.IsNull (loc) &&
3967 !Location.IsNull (block.EndLocation) &&
3968 (loc.SymbolDocument != null)) {
3969 sw.OpenMethod (container, MethodBuilder, loc, block.EndLocation);
3971 if (member is Destructor)
3972 EmitDestructor (ec, block);
3974 ec.EmitTopBlock (block, ParameterInfo, loc);
3978 if (member is Destructor)
3979 EmitDestructor (ec, block);
3981 ec.EmitTopBlock (block, ParameterInfo, loc);
3985 void EmitDestructor (EmitContext ec, Block block)
3987 ILGenerator ig = ec.ig;
3989 Label finish = ig.DefineLabel ();
3991 block.SetDestructor ();
3993 ig.BeginExceptionBlock ();
3994 ec.ReturnLabel = finish;
3995 ec.HasReturnLabel = true;
3996 ec.EmitTopBlock (block, null, method.Location);
3998 // ig.MarkLabel (finish);
3999 ig.BeginFinallyBlock ();
4001 if (ec.ContainerType.BaseType != null) {
4002 Expression member_lookup = Expression.MemberLookup (
4003 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
4004 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
4006 if (member_lookup != null){
4007 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
4009 ig.Emit (OpCodes.Ldarg_0);
4010 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
4014 ig.EndExceptionBlock ();
4015 //ig.MarkLabel (ec.ReturnLabel);
4016 ig.Emit (OpCodes.Ret);
4020 public class Destructor : Method {
4022 public Destructor (DeclSpace ds, Expression return_type, int mod, string name,
4023 Parameters parameters, Attributes attrs, Location l)
4024 : base (ds, return_type, mod, false, name, parameters, attrs, l)
4027 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
4029 if (a.Type == TypeManager.conditional_attribute_type) {
4030 // Conditional not valid on '{0}' because it is a destructor, operator, or explicit interface implementation
4031 Report.Error_T (577, Location, GetSignatureForError ());
4035 base.ApplyAttributeBuilder (a, cb);
4039 abstract public class MemberBase : MemberCore {
4040 public Expression Type;
4042 public MethodAttributes flags;
4044 protected readonly int explicit_mod_flags;
4047 // The "short" name of this property / indexer / event. This is the
4048 // name without the explicit interface.
4050 public string ShortName;
4053 // The type of this property / indexer / event
4055 public Type MemberType;
4058 // If true, this is an explicit interface implementation
4060 public bool IsExplicitImpl = false;
4063 // The name of the interface we are explicitly implementing
4065 public string ExplicitInterfaceName = null;
4068 // Whether this is an interface member.
4070 public bool IsInterface;
4073 // If true, the interface type we are explicitly implementing
4075 public Type InterfaceType = null;
4078 // The method we're overriding if this is an override method.
4080 protected MethodInfo parent_method = null;
4081 public MethodInfo ParentMethod {
4083 return parent_method;
4088 // The constructor is only exposed to our children
4090 protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod, string name,
4091 Attributes attrs, Location loc)
4092 : base (name, attrs, loc)
4094 explicit_mod_flags = mod;
4096 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
4099 protected virtual bool CheckBase (TypeContainer container)
4101 if ((container is Struct) || (RootContext.WarningLevel > 3)){
4102 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
4103 if (container is Struct){
4104 Report.Error (666, Location, "Protected member in struct declaration");
4107 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
4113 protected void WarningNotHiding (TypeContainer parent)
4117 "The member " + parent.MakeName (Name) + " does not hide an " +
4118 "inherited member. The keyword new is not required");
4122 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
4126 // FIXME: report the old/new permissions?
4129 507, Location, parent.MakeName (Name) +
4130 ": can't change the access modifiers when overriding inherited " +
4131 "member `" + name + "'");
4135 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
4136 // that have been defined.
4138 // `name' is the user visible name for reporting errors (this is used to
4139 // provide the right name regarding method names and properties)
4141 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
4142 MethodInfo mb, string name)
4146 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4147 if (!(mb.IsAbstract || mb.IsVirtual)){
4149 506, Location, parent.MakeName (Name) +
4150 ": cannot override inherited member `" +
4151 name + "' because it is not " +
4152 "virtual, abstract or override");
4156 // Now we check that the overriden method is not final
4159 // This happens when implementing interface methods.
4160 if (mb.IsHideBySig && mb.IsVirtual) {
4162 506, Location, parent.MakeName (Name) +
4163 ": cannot override inherited member `" +
4164 name + "' because it is not " +
4165 "virtual, abstract or override");
4167 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
4168 "override inherited member `" + name +
4169 "' because it is sealed.");
4173 // Check that the permissions are not being changed
4175 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
4176 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
4179 // special case for "protected internal"
4182 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4184 // when overriding protected internal, the method can be declared
4185 // protected internal only within the same assembly
4188 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4189 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
4191 // assemblies differ - report an error
4194 Error_CannotChangeAccessModifiers (parent, mb, name);
4196 } else if (thisp != parentp) {
4198 // same assembly, but other attributes differ - report an error
4201 Error_CannotChangeAccessModifiers (parent, mb, name);
4204 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
4206 // if it's not "protected internal", it must be "protected"
4209 Error_CannotChangeAccessModifiers (parent, mb, name);
4211 } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
4213 // protected within the same assembly - an error
4215 Error_CannotChangeAccessModifiers (parent, mb, name);
4217 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
4218 (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
4220 // protected ok, but other attributes differ - report an error
4222 Error_CannotChangeAccessModifiers (parent, mb, name);
4226 if (thisp != parentp){
4227 Error_CannotChangeAccessModifiers (parent, mb, name);
4233 if (mb.IsVirtual || mb.IsAbstract){
4234 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4235 if (Name != "Finalize"){
4237 114, 2, Location, parent.MakeName (Name) +
4238 " hides inherited member `" + name +
4239 "'. To make the current member override that " +
4240 "implementation, add the override keyword, " +
4241 "otherwise use the new keyword");
4242 ModFlags |= Modifiers.NEW;
4246 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4247 if (Name != "Finalize"){
4249 108, 1, Location, "The keyword new is required on " +
4250 parent.MakeName (Name) + " because it hides " +
4251 "inherited member `" + name + "'");
4252 ModFlags |= Modifiers.NEW;
4260 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
4264 foreach (Type partype in parameters){
4265 if (partype == TypeManager.void_type) {
4267 1547, Location, "Keyword 'void' cannot " +
4268 "be used in this context");
4272 if (partype.IsPointer){
4275 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
4279 if (ds.AsAccessible (partype, ModFlags))
4282 if (this is Indexer)
4283 Report.Error (55, Location,
4284 "Inconsistent accessibility: parameter type `" +
4285 TypeManager.CSharpName (partype) + "' is less " +
4286 "accessible than indexer `" + Name + "'");
4287 else if ((this is Method) && ((Method) this).IsOperator)
4288 Report.Error (57, Location,
4289 "Inconsistent accessibility: parameter type `" +
4290 TypeManager.CSharpName (partype) + "' is less " +
4291 "accessible than operator `" + Name + "'");
4293 Report.Error (51, Location,
4294 "Inconsistent accessibility: parameter type `" +
4295 TypeManager.CSharpName (partype) + "' is less " +
4296 "accessible than method `" + Name + "'");
4303 protected virtual bool DoDefine (TypeContainer container)
4309 ModFlags = Modifiers.PUBLIC |
4310 Modifiers.ABSTRACT |
4311 Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE);
4313 flags = MethodAttributes.Public |
4314 MethodAttributes.Abstract |
4315 MethodAttributes.HideBySig |
4316 MethodAttributes.NewSlot |
4317 MethodAttributes.Virtual;
4319 if (!container.MethodModifiersValid (ModFlags, Name, Location))
4322 flags = Modifiers.MethodAttr (ModFlags);
4325 // Lookup Type, verify validity
4326 MemberType = container.ResolveType (Type, false, Location);
4327 if (MemberType == null)
4330 if ((container.ModFlags & Modifiers.SEALED) != 0){
4331 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
4332 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
4337 // verify accessibility
4338 if (!container.AsAccessible (MemberType, ModFlags)) {
4339 if (this is Property)
4340 Report.Error (53, Location,
4341 "Inconsistent accessibility: property type `" +
4342 TypeManager.CSharpName (MemberType) + "' is less " +
4343 "accessible than property `" + Name + "'");
4344 else if (this is Indexer)
4345 Report.Error (54, Location,
4346 "Inconsistent accessibility: indexer return type `" +
4347 TypeManager.CSharpName (MemberType) + "' is less " +
4348 "accessible than indexer `" + Name + "'");
4349 else if (this is Method) {
4350 if (((Method) this).IsOperator)
4351 Report.Error (56, Location,
4352 "Inconsistent accessibility: return type `" +
4353 TypeManager.CSharpName (MemberType) + "' is less " +
4354 "accessible than operator `" + Name + "'");
4356 Report.Error (50, Location,
4357 "Inconsistent accessibility: return type `" +
4358 TypeManager.CSharpName (MemberType) + "' is less " +
4359 "accessible than method `" + Name + "'");
4361 Report.Error (52, Location,
4362 "Inconsistent accessibility: field type `" +
4363 TypeManager.CSharpName (MemberType) + "' is less " +
4364 "accessible than field `" + Name + "'");
4368 if (MemberType.IsPointer && !UnsafeOK (container))
4372 // Check for explicit interface implementation
4374 if ((ExplicitInterfaceName == null) && (Name.IndexOf ('.') != -1)){
4375 int pos = Name.LastIndexOf ('.');
4377 ExplicitInterfaceName = Name.Substring (0, pos);
4378 ShortName = Name.Substring (pos + 1);
4382 if (ExplicitInterfaceName != null) {
4383 InterfaceType = container.FindType (
4384 Location, ExplicitInterfaceName);
4385 if (InterfaceType == null)
4388 if (InterfaceType.IsClass) {
4389 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
4393 // Compute the full name that we need to export.
4394 Name = InterfaceType.FullName + "." + ShortName;
4396 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
4399 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
4401 IsExplicitImpl = true;
4403 IsExplicitImpl = false;
4409 /// Use this method when MethodBuilder is null
4411 public virtual string GetSignatureForError (TypeContainer tc)
4413 return String.Concat (tc.Name, '.', Name);
4416 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
4418 return IsIdentifierAndParamClsCompliant (ds, Name, null, null);
4421 protected override bool VerifyClsCompliance(DeclSpace ds)
4423 if (base.VerifyClsCompliance (ds)) {
4427 if (IsInterface && HasClsCompliantAttribute && ds.IsClsCompliaceRequired (ds)) {
4428 Report.Error_T (3010, Location, GetSignatureForError ());
4433 protected override void VerifyObsoleteAttribute()
4435 CheckUsageOfObsoleteAttribute (MemberType);
4440 // Fields and Events both generate FieldBuilders, we use this to share
4441 // their common bits. This is also used to flag usage of the field
4443 abstract public class FieldBase : MemberBase {
4444 public FieldBuilder FieldBuilder;
4445 public Status status;
4448 public enum Status : byte { ASSIGNED = 1, USED = 2 }
4450 static string[] attribute_targets = new string [] { "field" };
4453 // The constructor is only exposed to our children
4455 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
4456 object init, Attributes attrs, Location loc)
4457 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
4462 public override AttributeTargets AttributeTargets {
4464 return AttributeTargets.Field;
4468 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4470 if (a.Type == TypeManager.marshal_as_attr_type) {
4471 UnmanagedMarshal marshal = a.GetMarshal ();
4472 if (marshal != null) {
4473 FieldBuilder.SetMarshal (marshal);
4476 Report.Warning_T (-24, a.Location);
4481 FieldBuilder.SetCustomAttribute (cb);
4485 // Whether this field has an initializer.
4487 public bool HasInitializer {
4489 return init != null;
4493 protected readonly Object init;
4495 Expression init_expr;
4496 bool init_expr_initialized = false;
4499 // Resolves and returns the field initializer.
4501 public Expression GetInitializerExpression (EmitContext ec)
4503 if (init_expr_initialized)
4507 if (init is Expression)
4508 e = (Expression) init;
4510 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
4512 ec.IsFieldInitializer = true;
4513 e = e.DoResolve (ec);
4514 ec.IsFieldInitializer = false;
4517 init_expr_initialized = true;
4522 protected override bool DoDefine (TypeContainer container)
4524 if (!base.DoDefine (container))
4527 if (MemberType == TypeManager.void_type) {
4528 Report.Error (1547, Location,
4529 "Keyword 'void' cannot be used in this context");
4533 if (MemberType == TypeManager.arg_iterator_type || MemberType == TypeManager.typed_reference_type) {
4534 // "Field or property cannot be of type '{0}'";
4535 Report.Error_T (610, Location, TypeManager.CSharpName (MemberType));
4542 public override string GetSignatureForError ()
4544 return TypeManager.GetFullNameSignature (FieldBuilder);
4547 protected override string[] ValidAttributeTargets {
4549 return attribute_targets;
4553 protected override bool VerifyClsCompliance (DeclSpace ds)
4555 if (!base.VerifyClsCompliance (ds))
4558 if (FieldBuilder == null) {
4562 if (!AttributeTester.IsClsCompliant (FieldBuilder.FieldType)) {
4563 Report.Error_T (3003, Location, GetSignatureForError ());
4569 public void SetAssigned ()
4571 status |= Status.ASSIGNED;
4576 // The Field class is used to represents class/struct fields during parsing.
4578 public class Field : FieldBase {
4580 // Modifiers allowed in a class declaration
4582 const int AllowedModifiers =
4585 Modifiers.PROTECTED |
4586 Modifiers.INTERNAL |
4589 Modifiers.VOLATILE |
4593 public Field (Expression type, int mod, string name, Object expr_or_array_init,
4594 Attributes attrs, Location loc)
4595 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
4599 public override bool Define (TypeContainer container)
4601 MemberType = container.ResolveType (Type, false, Location);
4603 if (MemberType == null)
4606 CheckBase (container);
4608 if (!container.AsAccessible (MemberType, ModFlags)) {
4609 Report.Error (52, Location,
4610 "Inconsistent accessibility: field type `" +
4611 TypeManager.CSharpName (MemberType) + "' is less " +
4612 "accessible than field `" + Name + "'");
4616 if (MemberType.IsPointer && !UnsafeOK (container))
4619 if (RootContext.WarningLevel > 1){
4620 Type ptype = container.TypeBuilder.BaseType;
4622 // ptype is only null for System.Object while compiling corlib.
4624 TypeContainer.FindMembers (
4625 ptype, MemberTypes.Method,
4626 BindingFlags.Public |
4627 BindingFlags.Static | BindingFlags.Instance,
4628 System.Type.FilterName, Name);
4632 if ((ModFlags & Modifiers.VOLATILE) != 0){
4633 if (!MemberType.IsClass){
4634 Type vt = MemberType;
4636 if (TypeManager.IsEnumType (vt))
4637 vt = TypeManager.EnumToUnderlying (MemberType);
4639 if (!((vt == TypeManager.bool_type) ||
4640 (vt == TypeManager.sbyte_type) ||
4641 (vt == TypeManager.byte_type) ||
4642 (vt == TypeManager.short_type) ||
4643 (vt == TypeManager.ushort_type) ||
4644 (vt == TypeManager.int32_type) ||
4645 (vt == TypeManager.uint32_type) ||
4646 (vt == TypeManager.char_type) ||
4647 (vt == TypeManager.float_type) ||
4648 (!vt.IsValueType))){
4650 677, Location, container.MakeName (Name) +
4651 " A volatile field can not be of type `" +
4652 TypeManager.CSharpName (vt) + "'");
4657 if ((ModFlags & Modifiers.READONLY) != 0){
4660 "A field can not be both volatile and readonly");
4665 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
4667 if (container is Struct &&
4668 ((fa & FieldAttributes.Static) == 0) &&
4669 MemberType == container.TypeBuilder &&
4670 !TypeManager.IsBuiltinType (MemberType)){
4671 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name +
4672 "' causes a cycle in the structure layout");
4677 FieldBuilder = container.TypeBuilder.DefineField (
4678 Name, MemberType, Modifiers.FieldAttr (ModFlags));
4680 TypeManager.RegisterFieldBase (FieldBuilder, this);
4682 catch (ArgumentException) {
4683 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
4690 public override void Emit (TypeContainer tc)
4692 if (OptAttributes != null) {
4693 EmitContext ec = new EmitContext (tc, Location, null, FieldBuilder.FieldType, ModFlags);
4694 OptAttributes.Emit (ec, this);
4702 // `set' and `get' accessors are represented with an Accessor.
4704 public class Accessor {
4706 // Null if the accessor is empty, or a Block if not
4709 public Attributes Attributes;
4711 public Accessor (Block b, Attributes attrs)
4719 // Ooouh Martin, templates are missing here.
4720 // When it will be possible move here a lot of child code and template method type.
4721 public abstract class AbstractPropertyEventMethod: Attributable, IMethodData
4723 protected MethodData method_data;
4724 protected Block block;
4726 ReturnParameter return_attributes;
4728 public AbstractPropertyEventMethod ():
4733 public AbstractPropertyEventMethod (Accessor accessor):
4734 base (accessor.Attributes)
4736 this.block = accessor.Block;
4739 #region IMethodData Members
4741 public Block Block {
4747 public CallingConventions CallingConventions {
4749 return CallingConventions.Standard;
4753 public bool IsExcluded (EmitContext ec)
4758 public abstract ObsoleteAttribute GetObsoleteAttribute ();
4759 public abstract string GetSignatureForError (TypeContainer tc);
4760 public abstract Location Location { get; }
4761 public abstract string MethodName { get; }
4762 public abstract Type[] ParameterTypes { get; }
4763 public abstract Type ReturnType { get; }
4764 public abstract EmitContext CreateEmitContext(TypeContainer tc, ILGenerator ig);
4768 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
4770 if (a.Type == TypeManager.cls_compliant_attribute_type || a.Type == TypeManager.obsolete_attribute_type ||
4771 a.Type == TypeManager.conditional_attribute_type) {
4772 //"'{0}' is not valid on property or event accessors. It is valid on '{1}' declarations only"
4773 Report.Error_T (1667, a.Location, TypeManager.CSharpName (a.Type), a.GetValidTargets ());
4777 if (a.Target == "method") {
4778 method_data.MethodBuilder.SetCustomAttribute (cb);
4782 if (a.Target == "return") {
4783 if (return_attributes == null)
4784 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
4786 return_attributes.ApplyAttributeBuilder (a, cb);
4790 ApplyToExtraTarget (a, cb);
4793 virtual protected void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb)
4795 System.Diagnostics.Debug.Fail ("You forgot to define special attribute target handling");
4798 public virtual void Emit (TypeContainer container)
4800 method_data.Emit (container, this);
4806 // Properties and Indexers both generate PropertyBuilders, we use this to share
4807 // their common bits.
4809 abstract public class PropertyBase : MethodCore {
4811 public class GetMethod: PropertyMethod
4813 static string[] attribute_targets = new string [] { "method", "return" };
4815 public GetMethod (MethodCore method, Accessor accessor):
4816 base (method, accessor)
4820 public override MethodBuilder Define(TypeContainer container)
4822 method_data = new MethodData (method, method.ParameterInfo, method.ModFlags, method.flags, this);
4824 if (!method_data.Define (container))
4827 return method_data.MethodBuilder;
4830 public override string GetSignatureForError (TypeContainer tc)
4832 return String.Concat (base.GetSignatureForError (tc), ".get");
4835 public override string MethodName
4838 return "get_" + method.ShortName;
4842 public override Type ReturnType {
4844 return method.MemberType;
4848 protected override string[] ValidAttributeTargets {
4850 return attribute_targets;
4855 public class SetMethod: PropertyMethod {
4857 static string[] attribute_targets = new string [] { "method", "param", "return" };
4858 ImplicitParameter param_attr;
4860 public SetMethod (MethodCore method, Accessor accessor):
4861 base (method, accessor)
4865 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
4867 if (a.Target == "param") {
4868 if (param_attr == null)
4869 param_attr = new ImplicitParameter (method_data.MethodBuilder);
4871 param_attr.ApplyAttributeBuilder (a, cb);
4875 base.ApplyAttributeBuilder (a, cb);
4878 protected virtual InternalParameters GetParameterInfo (TypeContainer container)
4880 Parameter [] parms = new Parameter [1];
4881 parms [0] = new Parameter (method.Type, "value", Parameter.Modifier.NONE, null);
4882 return new InternalParameters (
4883 container, new Parameters (parms, null, method.Location));
4886 public override MethodBuilder Define(TypeContainer container)
4888 method_data = new MethodData (method, GetParameterInfo (container), method.ModFlags, method.flags, this);
4890 if (!method_data.Define (container))
4893 return method_data.MethodBuilder;
4896 public override string GetSignatureForError (TypeContainer tc)
4898 return String.Concat (base.GetSignatureForError (tc), ".set");
4901 public override string MethodName {
4903 return "set_" + method.ShortName;
4907 public override Type[] ParameterTypes {
4909 return new Type[] { method.MemberType };
4913 public override Type ReturnType {
4915 return TypeManager.void_type;
4919 protected override string[] ValidAttributeTargets {
4921 return attribute_targets;
4926 static string[] attribute_targets = new string [] { "property" };
4928 public abstract class PropertyMethod: AbstractPropertyEventMethod
4930 protected readonly MethodCore method;
4932 public PropertyMethod (MethodCore method, Accessor accessor):
4935 this.method = method;
4938 public override AttributeTargets AttributeTargets {
4940 return AttributeTargets.Method | AttributeTargets.ReturnValue;
4944 public override bool IsClsCompliaceRequired(DeclSpace ds)
4946 return method.IsClsCompliaceRequired (ds);
4949 public InternalParameters ParameterInfo
4952 return method_data.ParameterInfo;
4956 public abstract MethodBuilder Define (TypeContainer container);
4958 public override Type[] ParameterTypes {
4960 return TypeManager.NoTypes;
4964 public override Location Location {
4966 return method.Location;
4970 public override EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
4972 return new EmitContext (tc, method.ds, method.Location, ig, ReturnType, method.ModFlags, false);
4975 public override ObsoleteAttribute GetObsoleteAttribute ()
4977 return method.GetObsoleteAttribute (method.ds);
4980 public override string GetSignatureForError (TypeContainer tc)
4982 return String.Concat (tc.Name, '.', method.Name);
4987 public PropertyMethod Get, Set;
4988 public PropertyBuilder PropertyBuilder;
4989 public MethodBuilder GetBuilder, SetBuilder;
4991 protected EmitContext ec;
4993 public PropertyBase (DeclSpace ds, Expression type, int mod_flags,
4994 int allowed_mod, bool is_iface, string name,
4995 Parameters parameters, Attributes attrs,
4997 : base (ds, type, mod_flags, allowed_mod, is_iface, name,
4998 attrs, parameters, loc)
5002 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5004 PropertyBuilder.SetCustomAttribute (cb);
5007 public override AttributeTargets AttributeTargets {
5009 return AttributeTargets.Property;
5013 protected override bool DoDefine (TypeContainer container)
5015 if (!base.DoDefine (container))
5018 if (MemberType == TypeManager.arg_iterator_type || MemberType == TypeManager.typed_reference_type) {
5019 // "Field or property cannot be of type '{0}'";
5020 Report.Error_T (610, Location, TypeManager.CSharpName (MemberType));
5024 ec = new EmitContext (container, Location, null, MemberType, ModFlags);
5029 public override string GetSignatureForError()
5031 return TypeManager.CSharpSignature (PropertyBuilder, false);
5034 protected virtual string RealMethodName {
5040 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
5042 if (!IsIdentifierAndParamClsCompliant (ds, RealMethodName, null, null))
5045 if (Get != null && !IsIdentifierAndParamClsCompliant (ds, "get_" + RealMethodName, null, null))
5048 if (Set != null && !IsIdentifierAndParamClsCompliant (ds, "set_" + RealMethodName, null, null))
5056 // Checks our base implementation if any
5058 protected override bool CheckBase (TypeContainer container)
5060 base.CheckBase (container);
5062 // Check whether arguments were correct.
5063 if (!DoDefineParameters ())
5070 // Check in our class for dups
5072 ArrayList ar = container.Properties;
5074 int arLen = ar.Count;
5076 for (int i = 0; i < arLen; i++) {
5077 Property m = (Property) ar [i];
5078 if (IsDuplicateImplementation (container, m))
5087 MethodSignature ms, base_ms;
5088 if (this is Indexer) {
5089 string name, base_name;
5091 report_name = "this";
5092 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
5093 ms = new MethodSignature (name, null, ParameterTypes);
5094 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
5095 base_ms = new MethodSignature (base_name, null, ParameterTypes);
5098 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
5102 // Verify if the parent has a type with the same name, and then
5103 // check whether we have to create a new slot for it or not.
5105 Type ptype = container.TypeBuilder.BaseType;
5107 // ptype is only null for System.Object while compiling corlib.
5108 if (ptype == null) {
5109 if ((ModFlags & Modifiers.NEW) != 0)
5110 WarningNotHiding (container);
5115 MemberInfo parent_member = null;
5118 // Explicit implementations do not have `parent' methods, however,
5119 // the member cache stores them there. Without this check, we get
5120 // an incorrect warning in corlib.
5122 if (! IsExplicitImpl) {
5123 parent_member = ((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
5124 container.TypeBuilder, Name, ParameterTypes, true);
5127 if (parent_member is PropertyInfo) {
5128 PropertyInfo parent_property = (PropertyInfo)parent_member;
5130 string name = parent_property.DeclaringType.Name + "." +
5131 parent_property.Name;
5133 MethodInfo get, set, parent_method;
5134 get = parent_property.GetGetMethod (true);
5135 set = parent_property.GetSetMethod (true);
5138 parent_method = get;
5139 else if (set != null)
5140 parent_method = set;
5142 throw new Exception ("Internal error!");
5144 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
5147 if ((ModFlags & Modifiers.NEW) == 0) {
5148 Type parent_type = TypeManager.TypeToCoreType (
5149 parent_property.PropertyType);
5151 if (parent_type != MemberType) {
5153 508, Location, container.MakeName (Name) + ": cannot " +
5154 "change return type when overriding " +
5155 "inherited member " + name);
5159 } else if (parent_member == null){
5160 if ((ModFlags & Modifiers.NEW) != 0)
5161 WarningNotHiding (container);
5163 if ((ModFlags & Modifiers.OVERRIDE) != 0){
5164 if (this is Indexer)
5165 Report.Error (115, Location,
5166 container.MakeName (Name) +
5167 " no suitable indexers found to override");
5169 Report.Error (115, Location,
5170 container.MakeName (Name) +
5171 " no suitable properties found to override");
5178 public override void Emit (TypeContainer tc)
5181 // The PropertyBuilder can be null for explicit implementations, in that
5182 // case, we do not actually emit the ".property", so there is nowhere to
5183 // put the attribute
5185 if (PropertyBuilder != null && OptAttributes != null)
5186 OptAttributes.Emit (ec, this);
5197 protected override string[] ValidAttributeTargets {
5199 return attribute_targets;
5204 public class Property : PropertyBase, IIteratorContainer {
5205 const int AllowedModifiers =
5208 Modifiers.PROTECTED |
5209 Modifiers.INTERNAL |
5213 Modifiers.OVERRIDE |
5214 Modifiers.ABSTRACT |
5217 Modifiers.METHOD_YIELDS |
5220 const int AllowedInterfaceModifiers =
5223 public Property (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
5224 string name, Attributes attrs, Accessor get_block,
5225 Accessor set_block, Location loc)
5226 : base (ds, type, mod_flags,
5227 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5228 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
5231 if (get_block != null)
5232 Get = new GetMethod (this, get_block);
5234 if (set_block != null)
5235 Set = new SetMethod (this, set_block);
5238 public override bool Define (TypeContainer container)
5240 if (!DoDefine (container))
5243 if (!CheckBase (container))
5246 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
5250 GetBuilder = Get.Define (container);
5251 if (GetBuilder == null)
5255 // Setup iterator if we are one
5257 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
5258 IteratorHandler ih = new IteratorHandler (
5259 "get", container, MemberType,
5260 TypeManager.NoTypes, Get.ParameterInfo, ModFlags, Location);
5262 Block new_block = ih.Setup (block);
5263 if (new_block == null)
5270 SetBuilder = Set.Define (container);
5271 if (SetBuilder == null)
5274 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
5277 // FIXME - PropertyAttributes.HasDefault ?
5279 PropertyAttributes prop_attr = PropertyAttributes.None;
5281 prop_attr |= PropertyAttributes.RTSpecialName |
5282 PropertyAttributes.SpecialName;
5284 if (!IsExplicitImpl){
5285 PropertyBuilder = container.TypeBuilder.DefineProperty (
5286 Name, prop_attr, MemberType, null);
5289 PropertyBuilder.SetGetMethod (GetBuilder);
5292 PropertyBuilder.SetSetMethod (SetBuilder);
5295 // HACK for the reasons exposed above
5297 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
5300 "Class `" + container.Name +
5301 "' already contains a definition for the property `" +
5309 public void SetYields ()
5311 ModFlags |= Modifiers.METHOD_YIELDS;
5316 /// Gigantic workaround for lameness in SRE follows :
5317 /// This class derives from EventInfo and attempts to basically
5318 /// wrap around the EventBuilder so that FindMembers can quickly
5319 /// return this in it search for members
5321 public class MyEventBuilder : EventInfo {
5324 // We use this to "point" to our Builder which is
5325 // not really a MemberInfo
5327 EventBuilder MyBuilder;
5330 // We "catch" and wrap these methods
5332 MethodInfo raise, remove, add;
5334 EventAttributes attributes;
5335 Type declaring_type, reflected_type, event_type;
5340 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
5342 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
5344 // And now store the values in our own fields.
5346 declaring_type = type_builder;
5348 reflected_type = type_builder;
5350 attributes = event_attr;
5353 this.event_type = event_type;
5357 // Methods that you have to override. Note that you only need
5358 // to "implement" the variants that take the argument (those are
5359 // the "abstract" methods, the others (GetAddMethod()) are
5362 public override MethodInfo GetAddMethod (bool nonPublic)
5367 public override MethodInfo GetRemoveMethod (bool nonPublic)
5372 public override MethodInfo GetRaiseMethod (bool nonPublic)
5378 // These methods make "MyEventInfo" look like a Builder
5380 public void SetRaiseMethod (MethodBuilder raiseMethod)
5382 raise = raiseMethod;
5383 MyBuilder.SetRaiseMethod (raiseMethod);
5386 public void SetRemoveOnMethod (MethodBuilder removeMethod)
5388 remove = removeMethod;
5389 MyBuilder.SetRemoveOnMethod (removeMethod);
5392 public void SetAddOnMethod (MethodBuilder addMethod)
5395 MyBuilder.SetAddOnMethod (addMethod);
5398 public void SetCustomAttribute (CustomAttributeBuilder cb)
5400 MyBuilder.SetCustomAttribute (cb);
5403 public override object [] GetCustomAttributes (bool inherit)
5405 // FIXME : There's nothing which can be seemingly done here because
5406 // we have no way of getting at the custom attribute objects of the
5411 public override object [] GetCustomAttributes (Type t, bool inherit)
5413 // FIXME : Same here !
5417 public override bool IsDefined (Type t, bool b)
5422 public override EventAttributes Attributes {
5428 public override string Name {
5434 public override Type DeclaringType {
5436 return declaring_type;
5440 public override Type ReflectedType {
5442 return reflected_type;
5446 public Type EventType {
5452 public void SetUsed ()
5454 if (my_event != null)
5455 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
5460 /// For case when event is declared like property (with add and remove accessors).
5462 public class EventProperty: Event {
5464 static string[] attribute_targets = new string [] { "event", "property" };
5466 public EventProperty (DeclSpace ds, Expression type, int mod_flags, bool is_iface, string name,
5467 Object init, Attributes attrs, Accessor add, Accessor remove, Location loc)
5468 : base (ds, type, mod_flags, is_iface, name, init, attrs, loc)
5470 Add = new AddDelegateMethod (this, add);
5471 Remove = new RemoveDelegateMethod (this, remove);
5474 protected override string[] ValidAttributeTargets {
5476 return attribute_targets;
5482 /// Event is declared like field.
5484 public class EventField: Event {
5486 static string[] attribute_targets = new string [] { "event", "field", "method" };
5488 public EventField (DeclSpace ds, Expression type, int mod_flags, bool is_iface, string name,
5489 Object init, Attributes attrs, Location loc)
5490 : base (ds, type, mod_flags, is_iface, name, init, attrs, loc)
5492 Add = new AddDelegateMethod (this);
5493 Remove = new RemoveDelegateMethod (this);
5496 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5498 if (a.Target == "field") {
5499 FieldBuilder.SetCustomAttribute (cb);
5503 if (a.Target == "method") {
5504 AddBuilder.SetCustomAttribute (cb);
5505 RemoveBuilder.SetCustomAttribute (cb);
5509 base.ApplyAttributeBuilder (a, cb);
5512 protected override string[] ValidAttributeTargets {
5514 return attribute_targets;
5519 public abstract class Event : FieldBase {
5521 protected sealed class AddDelegateMethod: DelegateMethod
5523 public AddDelegateMethod (Event method):
5528 public AddDelegateMethod (Event method, Accessor accessor):
5529 base (method, accessor)
5533 public override string MethodName {
5535 return "add_" + method.ShortName;
5539 protected override MethodInfo DelegateMethodInfo {
5541 return TypeManager.delegate_combine_delegate_delegate;
5547 protected sealed class RemoveDelegateMethod: DelegateMethod
5549 public RemoveDelegateMethod (Event method):
5554 public RemoveDelegateMethod (Event method, Accessor accessor):
5555 base (method, accessor)
5559 public override string MethodName {
5561 return "remove_" + method.ShortName;
5565 protected override MethodInfo DelegateMethodInfo {
5567 return TypeManager.delegate_remove_delegate_delegate;
5573 public abstract class DelegateMethod: AbstractPropertyEventMethod
5575 protected readonly Event method;
5576 ImplicitParameter param_attr;
5578 static string[] attribute_targets = new string [] { "method", "param", "return" };
5580 public DelegateMethod (Event method)
5582 this.method = method;
5585 public DelegateMethod (Event method, Accessor accessor):
5588 this.method = method;
5591 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
5593 if (a.Target == "param") {
5594 if (param_attr == null)
5595 param_attr = new ImplicitParameter (method_data.MethodBuilder);
5597 param_attr.ApplyAttributeBuilder (a, cb);
5601 base.ApplyAttributeBuilder (a, cb);
5604 public override AttributeTargets AttributeTargets {
5606 return AttributeTargets.Method;
5610 public override bool IsClsCompliaceRequired(DeclSpace ds)
5612 return method.IsClsCompliaceRequired (ds);
5615 public MethodBuilder Define (TypeContainer container, InternalParameters ip)
5617 method_data = new MethodData (method, ip, method.ModFlags,
5618 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
5620 if (!method_data.Define (container))
5623 MethodBuilder mb = method_data.MethodBuilder;
5624 mb.DefineParameter (1, ParameterAttributes.None, "value");
5629 public override void Emit (TypeContainer tc)
5631 if (block != null) {
5636 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
5637 EmitContext ec = CreateEmitContext (tc, ig);
5638 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
5640 method_data.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Synchronized);
5641 if ((method.ModFlags & Modifiers.STATIC) != 0) {
5642 ig.Emit (OpCodes.Ldsfld, field_info);
5643 ig.Emit (OpCodes.Ldarg_0);
5644 ig.Emit (OpCodes.Call, DelegateMethodInfo);
5645 ig.Emit (OpCodes.Castclass, method.MemberType);
5646 ig.Emit (OpCodes.Stsfld, field_info);
5648 ig.Emit (OpCodes.Ldarg_0);
5649 ig.Emit (OpCodes.Ldarg_0);
5650 ig.Emit (OpCodes.Ldfld, field_info);
5651 ig.Emit (OpCodes.Ldarg_1);
5652 ig.Emit (OpCodes.Call, DelegateMethodInfo);
5653 ig.Emit (OpCodes.Castclass, method.MemberType);
5654 ig.Emit (OpCodes.Stfld, field_info);
5656 ig.Emit (OpCodes.Ret);
5659 protected abstract MethodInfo DelegateMethodInfo { get; }
5661 public override Type[] ParameterTypes {
5663 return new Type[] { method.MemberType };
5667 public override Type ReturnType {
5669 return TypeManager.void_type;
5673 public override Location Location {
5675 return method.Location;
5679 public override EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
5681 return new EmitContext (tc, method.ds, Location, ig, ReturnType, method.ModFlags, false);
5684 public override string GetSignatureForError (TypeContainer tc)
5686 return String.Concat (tc.Name, '.', method.Name);
5689 public override ObsoleteAttribute GetObsoleteAttribute ()
5691 return method.GetObsoleteAttribute (method.ds);
5694 protected override string[] ValidAttributeTargets {
5696 return attribute_targets;
5702 const int AllowedModifiers =
5705 Modifiers.PROTECTED |
5706 Modifiers.INTERNAL |
5711 Modifiers.OVERRIDE |
5715 const int AllowedInterfaceModifiers =
5718 protected DelegateMethod Add, Remove;
5719 public MyEventBuilder EventBuilder;
5720 public MethodBuilder AddBuilder, RemoveBuilder;
5721 public DeclSpace ds;
5723 public Event (DeclSpace ds, Expression type, int mod_flags, bool is_iface, string name,
5724 Object init, Attributes attrs, Location loc)
5725 : base (type, mod_flags, is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5726 name, init, attrs, loc)
5728 IsInterface = is_iface;
5732 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5734 EventBuilder.SetCustomAttribute (cb);
5737 public override AttributeTargets AttributeTargets {
5739 return AttributeTargets.Event;
5743 public override bool Define (TypeContainer container)
5745 EventAttributes e_attr;
5746 e_attr = EventAttributes.None;
5748 if (!DoDefine (container))
5751 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
5752 Report.Error (74, Location, "'" + container.Name + "." + Name +
5753 "': abstract event can not have an initializer");
5757 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
5758 Report.Error (66, Location, "'" + container.Name + "." + Name +
5759 "' : event must be of a delegate type");
5763 Parameter [] parms = new Parameter [1];
5764 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
5765 InternalParameters ip = new InternalParameters (
5766 container, new Parameters (parms, null, Location));
5768 if (!CheckBase (container))
5772 // Now define the accessors
5775 AddBuilder = Add.Define (container, ip);
5776 if (AddBuilder == null)
5779 RemoveBuilder = Remove.Define (container, ip);
5780 if (RemoveBuilder == null)
5783 if (!IsExplicitImpl){
5784 EventBuilder = new MyEventBuilder (this,
5785 container.TypeBuilder, Name, e_attr, MemberType);
5787 if (Add.Block == null && Remove.Block == null &&
5789 FieldBuilder = container.TypeBuilder.DefineField (
5791 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
5792 TypeManager.RegisterPrivateFieldOfEvent (
5793 (EventInfo) EventBuilder, FieldBuilder);
5794 TypeManager.RegisterFieldBase (FieldBuilder, this);
5797 EventBuilder.SetAddOnMethod (AddBuilder);
5798 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
5800 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
5801 Report.Error (111, Location,
5802 "Class `" + container.Name +
5803 "' already contains a definition for the event `" +
5812 public override void Emit (TypeContainer tc)
5814 if (OptAttributes != null) {
5815 EmitContext ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
5816 OptAttributes.Emit (ec, this);
5827 public override string GetSignatureForError ()
5829 return TypeManager.GetFullNameSignature (EventBuilder);
5834 // FIXME: This does not handle:
5836 // int INTERFACENAME [ args ]
5841 // int this [ args ]
5843 public class Indexer : PropertyBase {
5845 class GetIndexerMethod: GetMethod
5847 public GetIndexerMethod (MethodCore method, Accessor accessor):
5848 base (method, accessor)
5852 public override Type[] ParameterTypes {
5854 return method.ParameterTypes;
5859 class SetIndexerMethod: SetMethod
5861 readonly Parameters parameters;
5863 public SetIndexerMethod (MethodCore method, Parameters parameters, Accessor accessor):
5864 base (method, accessor)
5866 this.parameters = parameters;
5869 public override Type[] ParameterTypes {
5871 int top = method.ParameterTypes.Length;
5872 Type [] set_pars = new Type [top + 1];
5873 method.ParameterTypes.CopyTo (set_pars, 0);
5874 set_pars [top] = method.MemberType;
5879 protected override InternalParameters GetParameterInfo (TypeContainer container)
5881 Parameter [] fixed_parms = parameters.FixedParameters;
5883 if (fixed_parms == null){
5884 throw new Exception ("We currently do not support only array arguments in an indexer at: " + method.Location);
5885 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5886 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5888 // Here is the problem: the `value' parameter has
5889 // to come *after* the array parameter in the declaration
5891 // X (object [] x, Type value)
5894 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5895 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5899 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
5901 fixed_parms.CopyTo (tmp, 0);
5902 tmp [fixed_parms.Length] = new Parameter (
5903 method.Type, "value", Parameter.Modifier.NONE, null);
5905 Parameters set_formal_params = new Parameters (tmp, null, method.Location);
5907 return new InternalParameters (container, set_formal_params);
5913 const int AllowedModifiers =
5916 Modifiers.PROTECTED |
5917 Modifiers.INTERNAL |
5921 Modifiers.OVERRIDE |
5926 const int AllowedInterfaceModifiers =
5929 public string IndexerName = "Item";
5930 public string InterfaceIndexerName;
5933 // Are we implementing an interface ?
5935 public Indexer (DeclSpace ds, Expression type, string int_type, int mod_flags,
5936 bool is_iface, Parameters parameters, Attributes attrs,
5937 Accessor get_block, Accessor set_block, Location loc)
5938 : base (ds, type, mod_flags,
5939 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5940 is_iface, "", parameters, attrs, loc)
5942 ExplicitInterfaceName = int_type;
5944 if (get_block != null)
5945 Get = new GetIndexerMethod (this, get_block);
5947 if (set_block != null)
5948 Set = new SetIndexerMethod (this, parameters, set_block);
5951 public override bool Define (TypeContainer container)
5953 PropertyAttributes prop_attr =
5954 PropertyAttributes.RTSpecialName |
5955 PropertyAttributes.SpecialName;
5957 if (!DoDefine (container))
5960 if (OptAttributes != null) {
5961 Attribute indexer_attr = OptAttributes.GetIndexerNameAttribute (ec);
5962 if (indexer_attr != null) {
5963 IndexerName = indexer_attr.GetIndexerAttributeValue (ec);
5965 if (IsExplicitImpl) {
5966 // The 'IndexerName' attribute is valid only on an indexer that is not an explicit interface member declaration
5967 Report.Error_T (415, indexer_attr.Location);
5971 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
5972 // Cannot set the 'IndexerName' attribute on an indexer marked override
5973 Report.Error_T (609, indexer_attr.Location);
5977 if (!Tokenizer.IsValidIdentifier (IndexerName)) {
5978 // The argument to the 'IndexerName' attribute must be a valid identifier
5979 Report.Error_T (633, indexer_attr.Location);
5985 ShortName = IndexerName;
5986 if (IsExplicitImpl) {
5987 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
5988 Name = InterfaceType.FullName + "." + IndexerName;
5990 InterfaceIndexerName = IndexerName;
5994 if (!CheckNameCollision (container))
5997 if (!CheckBase (container))
6000 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6002 GetBuilder = Get.Define (container);
6003 if (GetBuilder == null)
6008 SetBuilder = Set.Define (container);
6009 if (SetBuilder == null)
6014 // Now name the parameters
6016 Parameter [] p = Parameters.FixedParameters;
6020 for (i = 0; i < p.Length; ++i) {
6022 GetBuilder.DefineParameter (
6023 i + 1, p [i].Attributes, p [i].Name);
6026 SetBuilder.DefineParameter (
6027 i + 1, p [i].Attributes, p [i].Name);
6031 SetBuilder.DefineParameter (
6032 i + 1, ParameterAttributes.None, "value");
6034 if (i != ParameterTypes.Length) {
6035 Parameter array_param = Parameters.ArrayParameter;
6037 SetBuilder.DefineParameter (
6038 i + 1, array_param.Attributes, array_param.Name);
6043 // Define the PropertyBuilder if one of the following conditions are met:
6044 // a) we're not implementing an interface indexer.
6045 // b) the indexer has a different IndexerName and this is no
6046 // explicit interface implementation.
6048 if (!IsExplicitImpl) {
6049 PropertyBuilder = container.TypeBuilder.DefineProperty (
6050 IndexerName, prop_attr, MemberType, ParameterTypes);
6053 PropertyBuilder.SetGetMethod (GetBuilder);
6056 PropertyBuilder.SetSetMethod (SetBuilder);
6058 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
6065 bool CheckNameCollision (TypeContainer container) {
6066 switch (VerifyName (container)){
6067 case DeclSpace.AdditionResult.NameExists:
6068 Report.Error (102, Location, "The container '{0}' already contains a definition for '{1}'", container.GetSignatureForError (), Name);
6071 case DeclSpace.AdditionResult.Success:
6074 throw new NotImplementedException ();
6077 DeclSpace.AdditionResult VerifyName (TypeContainer container) {
6078 if (!AddIndexer (container, container.Name + "." + Name))
6079 return DeclSpace.AdditionResult.NameExists;
6082 if (!AddIndexer (container, container.Name + ".get_" + Name))
6083 return DeclSpace.AdditionResult.NameExists;
6087 if (!AddIndexer (container, container.Name + ".set_" + Name))
6088 return DeclSpace.AdditionResult.NameExists;
6090 return DeclSpace.AdditionResult.Success;
6093 bool AddIndexer (TypeContainer container, string fullname)
6095 object value = container.GetDefinition (fullname);
6097 if (value != null) {
6098 return value.GetType () != GetType () ? false : true;
6101 container.DefineName (fullname, this);
6105 public override string GetSignatureForError ()
6107 return TypeManager.CSharpSignature (PropertyBuilder, true);
6110 protected override string RealMethodName {
6117 public class Operator : MemberBase, IIteratorContainer {
6119 const int AllowedModifiers =
6125 const int RequiredModifiers =
6129 public enum OpType : byte {
6139 // Unary and Binary operators
6162 // Implicit and Explicit
6167 public readonly OpType OperatorType;
6168 public readonly Expression ReturnType;
6169 public readonly Expression FirstArgType, SecondArgType;
6170 public readonly string FirstArgName, SecondArgName;
6172 public MethodBuilder OperatorMethodBuilder;
6174 public string MethodName;
6175 public Method OperatorMethod;
6177 static string[] attribute_targets = new string [] { "method", "return" };
6179 public Operator (OpType type, Expression ret_type, int mod_flags,
6180 Expression arg1type, string arg1name,
6181 Expression arg2type, string arg2name,
6182 Block block, Attributes attrs, Location loc)
6183 : base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC, "", attrs, loc)
6185 OperatorType = type;
6186 Name = "op_" + OperatorType;
6187 ReturnType = ret_type;
6188 FirstArgType = arg1type;
6189 FirstArgName = arg1name;
6190 SecondArgType = arg2type;
6191 SecondArgName = arg2name;
6195 string Prototype (TypeContainer container)
6197 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
6198 SecondArgType + ")";
6201 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6203 OperatorMethod.ApplyAttributeBuilder (a, cb);
6206 public override AttributeTargets AttributeTargets {
6208 return AttributeTargets.Method;
6212 public override bool Define (TypeContainer container)
6215 MethodName = "op_" + OperatorType;
6217 if (SecondArgType != null)
6220 Parameter [] param_list = new Parameter [length];
6222 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
6225 "User defined operators `" +
6226 Prototype (container) +
6227 "' must be declared static and public");
6231 param_list[0] = new Parameter (FirstArgType, FirstArgName,
6232 Parameter.Modifier.NONE, null);
6233 if (SecondArgType != null)
6234 param_list[1] = new Parameter (SecondArgType, SecondArgName,
6235 Parameter.Modifier.NONE, null);
6237 OperatorMethod = new Method (
6238 container, ReturnType, ModFlags, false, MethodName,
6239 new Parameters (param_list, null, Location),
6240 OptAttributes, Location);
6242 OperatorMethod.Block = Block;
6243 OperatorMethod.IsOperator = true;
6244 OperatorMethod.Define (container);
6246 if (OperatorMethod.MethodBuilder == null)
6249 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
6251 Type [] param_types = OperatorMethod.ParameterTypes;
6252 Type declaring_type = OperatorMethodBuilder.DeclaringType;
6253 Type return_type = OperatorMethod.GetReturnType ();
6254 Type first_arg_type = param_types [0];
6256 // Rules for conversion operators
6258 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
6259 if (first_arg_type == return_type && first_arg_type == declaring_type){
6262 "User-defined conversion cannot take an object of the " +
6263 "enclosing type and convert to an object of the enclosing" +
6268 if (first_arg_type != declaring_type && return_type != declaring_type){
6271 "User-defined conversion must convert to or from the " +
6276 if (first_arg_type == TypeManager.object_type ||
6277 return_type == TypeManager.object_type){
6280 "User-defined conversion cannot convert to or from " +
6285 if (first_arg_type.IsInterface || return_type.IsInterface){
6288 "User-defined conversion cannot convert to or from an " +
6293 if (first_arg_type.IsSubclassOf (return_type)
6294 || return_type.IsSubclassOf (first_arg_type)){
6295 if (declaring_type.IsSubclassOf (return_type)) {
6296 // '{0}' : user defined conversion to/from base class
6297 Report.Error_T (553, Location, GetSignatureForError ());
6300 // '{0}' : user defined conversion to/from derived class
6301 Report.Error_T (554, Location, GetSignatureForError ());
6304 } else if (SecondArgType == null) {
6305 // Checks for Unary operators
6307 if (first_arg_type != declaring_type){
6310 "The parameter of a unary operator must be the " +
6315 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
6316 if (return_type != declaring_type){
6319 "The parameter and return type for ++ and -- " +
6320 "must be the containing type");
6326 if (OperatorType == OpType.True || OperatorType == OpType.False) {
6327 if (return_type != TypeManager.bool_type){
6330 "The return type of operator True or False " +
6337 // Checks for Binary operators
6339 if (first_arg_type != declaring_type &&
6340 param_types [1] != declaring_type){
6343 "One of the parameters of a binary operator must " +
6344 "be the containing type");
6352 public override void Emit (TypeContainer container)
6355 // abstract or extern methods have no bodies
6357 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
6360 OperatorMethod.Emit (container);
6364 public static string GetName (OpType ot)
6367 case OpType.LogicalNot:
6369 case OpType.OnesComplement:
6371 case OpType.Increment:
6373 case OpType.Decrement:
6379 case OpType.Addition:
6381 case OpType.Subtraction:
6383 case OpType.UnaryPlus:
6385 case OpType.UnaryNegation:
6387 case OpType.Multiply:
6389 case OpType.Division:
6391 case OpType.Modulus:
6393 case OpType.BitwiseAnd:
6395 case OpType.BitwiseOr:
6397 case OpType.ExclusiveOr:
6399 case OpType.LeftShift:
6401 case OpType.RightShift:
6403 case OpType.Equality:
6405 case OpType.Inequality:
6407 case OpType.GreaterThan:
6409 case OpType.LessThan:
6411 case OpType.GreaterThanOrEqual:
6413 case OpType.LessThanOrEqual:
6415 case OpType.Implicit:
6417 case OpType.Explicit:
6423 public override string GetSignatureForError(TypeContainer tc)
6428 public override string GetSignatureForError()
6433 public override string ToString ()
6435 Type return_type = OperatorMethod.GetReturnType();
6436 Type [] param_types = OperatorMethod.ParameterTypes;
6438 if (SecondArgType == null)
6439 return String.Format (
6440 "{0} operator {1}({2})",
6441 TypeManager.CSharpName (return_type),
6442 GetName (OperatorType),
6445 return String.Format (
6446 "{0} operator {1}({2}, {3})",
6447 TypeManager.CSharpName (return_type),
6448 GetName (OperatorType),
6449 param_types [0], param_types [1]);
6452 protected override string[] ValidAttributeTargets {
6454 return attribute_targets;
6458 public void SetYields ()
6460 ModFlags |= Modifiers.METHOD_YIELDS;
6465 // This is used to compare method signatures
6467 struct MethodSignature {
6469 public Type RetType;
6470 public Type [] Parameters;
6473 /// This delegate is used to extract methods which have the
6474 /// same signature as the argument
6476 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
6478 public MethodSignature (string name, Type ret_type, Type [] parameters)
6483 if (parameters == null)
6484 Parameters = TypeManager.NoTypes;
6486 Parameters = parameters;
6489 public override string ToString ()
6492 if (Parameters.Length != 0){
6493 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
6494 for (int i = 0; i < Parameters.Length; i++){
6495 sb.Append (Parameters [i]);
6496 if (i+1 < Parameters.Length)
6499 pars = sb.ToString ();
6502 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
6505 public override int GetHashCode ()
6507 return Name.GetHashCode ();
6510 public override bool Equals (Object o)
6512 MethodSignature other = (MethodSignature) o;
6514 if (other.Name != Name)
6517 if (other.RetType != RetType)
6520 if (Parameters == null){
6521 if (other.Parameters == null)
6526 if (other.Parameters == null)
6529 int c = Parameters.Length;
6530 if (other.Parameters.Length != c)
6533 for (int i = 0; i < c; i++)
6534 if (other.Parameters [i] != Parameters [i])
6540 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
6542 MethodSignature sig = (MethodSignature) filter_criteria;
6544 if (m.Name != sig.Name)
6548 MethodInfo mi = m as MethodInfo;
6549 PropertyInfo pi = m as PropertyInfo;
6552 ReturnType = mi.ReturnType;
6553 else if (pi != null)
6554 ReturnType = pi.PropertyType;
6559 // we use sig.RetType == null to mean `do not check the
6560 // method return value.
6562 if (sig.RetType != null)
6563 if (ReturnType != sig.RetType)
6568 args = TypeManager.GetArgumentTypes (mi);
6570 args = TypeManager.GetArgumentTypes (pi);
6571 Type [] sigp = sig.Parameters;
6573 if (args.Length != sigp.Length)
6576 for (int i = args.Length; i > 0; ){
6578 if (args [i] != sigp [i])