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 using Mono.CompilerServices.SymbolWriter;
42 namespace Mono.CSharp {
52 /// This is the base class for structs and classes.
54 public abstract class TypeContainer : DeclSpace, IMemberContainer {
56 // Whether this is a struct, class or interface
57 public readonly Kind Kind;
59 // Holds a list of classes and structures
62 // Holds the list of properties
65 // Holds the list of enumerations
68 // Holds the list of delegates
71 // Holds the list of constructors
72 ArrayList instance_constructors;
74 // Holds the list of fields
77 // Holds a list of fields that have initializers
78 ArrayList initialized_fields;
80 // Holds a list of static fields that have initializers
81 ArrayList initialized_static_fields;
83 // Holds the list of constants
98 // Holds the operators
101 // Holds the iterators
104 // Holds the parts of a partial class;
107 // The emit context for toplevel objects.
111 // Pointers to the default constructor and the default static constructor
113 Constructor default_constructor;
114 Constructor default_static_constructor;
117 // Whether we have seen a static constructor for this class or not
119 public bool UserDefinedStaticConstructor = false;
122 // Whether we have at least one non-static field
124 bool have_nonstatic_fields = false;
127 // This one is computed after we can distinguish interfaces
128 // from classes from the arraylist `type_bases'
130 string base_class_name;
131 public Type base_class_type;
133 ArrayList type_bases;
135 bool members_defined;
136 bool members_defined_ok;
138 // The interfaces we implement.
140 Type[] base_inteface_types;
142 // The parent member container and our member cache
143 IMemberContainer parent_container;
144 MemberCache member_cache;
147 // The indexer name for this class
149 public string IndexerName;
151 public TypeContainer (NamespaceEntry ns, TypeContainer parent, string name,
152 Attributes attrs, Kind kind, Location l)
153 : base (ns, parent, name, attrs, l)
157 types = new ArrayList ();
159 base_class_name = null;
163 // Used to report back to the user the result of a declaration
164 // in the current declaration space
166 public void CheckDef (AdditionResult result, string name, Location loc)
168 if (result == AdditionResult.Success)
172 case AdditionResult.NameExists:
173 Report.Error (102, loc, "The container `{0}' already " +
174 "contains a definition for `{1}'",
179 // This is handled only for static Constructors, because
180 // in reality we handle these by the semantic analysis later
182 case AdditionResult.MethodExists:
183 Report.Error (111, loc, "Class `{0}' already defines a " +
184 "member called '{1}' with the same parameter " +
185 "types (more than one default constructor)",
189 case AdditionResult.EnclosingClash:
190 Report.Error (542, loc, "Member names cannot be the same " +
191 "as their enclosing type");
194 case AdditionResult.NotAConstructor:
195 Report.Error (1520, loc, "Class, struct, or interface method " +
196 "must have a return type");
199 case AdditionResult.Error:
200 // Error has already been reported.
205 public AdditionResult AddConstant (Const constant)
208 string basename = constant.Name;
209 string fullname = Name + "." + basename;
211 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
214 if (constants == null)
215 constants = new ArrayList ();
217 constants.Add (constant);
218 DefineName (fullname, constant);
220 return AdditionResult.Success;
223 public AdditionResult AddEnum (Mono.CSharp.Enum e)
227 if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
231 enums = new ArrayList ();
234 DefineName (e.Name, e);
236 return AdditionResult.Success;
239 public AdditionResult AddClass (TypeContainer c)
242 string name = c.Basename;
244 if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
247 DefineName (c.Name, c);
250 return AdditionResult.Success;
253 public AdditionResult AddStruct (TypeContainer s)
256 string name = s.Basename;
258 if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
261 DefineName (s.Name, s);
264 return AdditionResult.Success;
267 public AdditionResult AddDelegate (Delegate d)
270 string name = d.Basename;
272 if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
275 if (delegates == null)
276 delegates = new ArrayList ();
278 DefineName (d.Name, d);
281 return AdditionResult.Success;
284 public AdditionResult AddMethod (Method method)
286 string basename = method.Name;
287 string fullname = Name + "." + basename;
289 Object value = defined_names [fullname];
291 if (value != null && (!(value is Method)))
292 return AdditionResult.NameExists;
294 if (basename == Basename)
295 return AdditionResult.EnclosingClash;
298 methods = new ArrayList ();
300 if (method.Name.IndexOf ('.') != -1)
301 methods.Insert (0, method);
303 methods.Add (method);
306 DefineName (fullname, method);
308 return AdditionResult.Success;
311 public AdditionResult AddConstructor (Constructor c)
313 if (c.Name != Basename)
314 return AdditionResult.NotAConstructor;
316 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
319 UserDefinedStaticConstructor = true;
320 if (default_static_constructor != null)
321 return AdditionResult.MethodExists;
323 default_static_constructor = c;
326 if (default_constructor != null)
327 return AdditionResult.MethodExists;
328 default_constructor = c;
331 if (instance_constructors == null)
332 instance_constructors = new ArrayList ();
334 instance_constructors.Add (c);
337 return AdditionResult.Success;
340 public AdditionResult AddInterface (TypeContainer iface)
343 string name = iface.Basename;
345 if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
348 if (interfaces == null)
349 interfaces = new ArrayList ();
350 interfaces.Add (iface);
351 DefineName (iface.Name, iface);
353 return AdditionResult.Success;
356 public AdditionResult AddField (Field field)
359 string basename = field.Name;
360 string fullname = Name + "." + basename;
362 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
366 fields = new ArrayList ();
370 if (field.HasInitializer){
371 if ((field.ModFlags & Modifiers.STATIC) != 0){
372 if (initialized_static_fields == null)
373 initialized_static_fields = new ArrayList ();
375 initialized_static_fields.Add (field);
378 if (initialized_fields == null)
379 initialized_fields = new ArrayList ();
381 initialized_fields.Add (field);
385 if ((field.ModFlags & Modifiers.STATIC) == 0)
386 have_nonstatic_fields = true;
388 DefineName (fullname, field);
389 return AdditionResult.Success;
392 public AdditionResult AddProperty (Property prop)
396 if ((res = AddProperty (prop, prop.Name)) != AdditionResult.Success)
399 if (prop.Get != null) {
400 if ((res = AddProperty (prop, "get_" + prop.Name)) != AdditionResult.Success)
404 if (prop.Set != null) {
405 if ((res = AddProperty (prop, "set_" + prop.Name)) != AdditionResult.Success)
409 if (properties == null)
410 properties = new ArrayList ();
412 if (prop.Name.IndexOf ('.') != -1)
413 properties.Insert (0, prop);
415 properties.Add (prop);
417 return AdditionResult.Success;
420 AdditionResult AddProperty (Property prop, string basename)
423 string fullname = Name + "." + basename;
425 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
428 DefineName (fullname, prop);
430 return AdditionResult.Success;
433 public AdditionResult AddEvent (Event e)
436 string basename = e.Name;
437 string fullname = Name + "." + basename;
439 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
443 events = new ArrayList ();
446 DefineName (fullname, e);
448 return AdditionResult.Success;
451 public void AddIndexer (Indexer i)
453 if (indexers == null)
454 indexers = new ArrayList ();
456 if (i.ExplicitInterfaceName != null)
457 indexers.Insert (0, i);
462 public AdditionResult AddOperator (Operator op)
464 if (operators == null)
465 operators = new ArrayList ();
469 string basename = op.Name;
470 string fullname = Name + "." + basename;
471 if (!defined_names.Contains (fullname))
473 DefineName (fullname, op);
475 return AdditionResult.Success;
478 public void AddIterator (Iterator i)
480 if (iterators == null)
481 iterators = new ArrayList ();
486 public void AddType (TypeContainer tc)
491 public void AddPart (ClassPart part)
494 parts = new ArrayList ();
499 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
501 if (a.Type == TypeManager.default_member_type) {
502 if (Indexers != null) {
503 Report.Error (646, a.Location,
504 "Cannot specify the DefaultMember attribute on" +
505 " a type containing an indexer");
510 base.ApplyAttributeBuilder (a, cb);
513 public override AttributeTargets AttributeTargets {
515 throw new NotSupportedException ();
519 public ArrayList Types {
525 public ArrayList Methods {
531 public ArrayList Constants {
537 public ArrayList Interfaces {
543 public ArrayList Iterators {
551 return base_class_name;
555 public ArrayList Bases {
565 public ArrayList Fields {
575 public ArrayList InstanceConstructors {
577 return instance_constructors;
581 public ArrayList Properties {
587 public ArrayList Events {
593 public ArrayList Enums {
599 public ArrayList Indexers {
605 public ArrayList Operators {
611 public ArrayList Delegates {
617 public ArrayList Parts {
623 public virtual TypeAttributes TypeAttr {
625 return Modifiers.TypeAttr (ModFlags, this);
630 // Emits the instance field initializers
632 public bool EmitFieldInitializers (EmitContext ec)
635 Expression instance_expr;
638 fields = initialized_static_fields;
639 instance_expr = null;
641 fields = initialized_fields;
642 instance_expr = new This (Location.Null).Resolve (ec);
648 foreach (Field f in fields){
649 Expression e = f.GetInitializerExpression (ec);
653 Location l = f.Location;
654 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
655 fe.InstanceExpression = instance_expr;
656 ExpressionStatement a = new Assign (fe, e, l);
658 a = a.ResolveStatement (ec);
662 a.EmitStatement (ec);
669 // Defines the default constructors
671 void DefineDefaultConstructor (bool is_static)
675 // The default constructor is public
676 // If the class is abstract, the default constructor is protected
677 // The default static constructor is private
679 int mods = Modifiers.PUBLIC;
681 mods = Modifiers.STATIC | Modifiers.PRIVATE;
682 else if ((ModFlags & Modifiers.ABSTRACT) != 0)
683 mods = Modifiers.PROTECTED;
685 c = new Constructor (this, Basename, mods, Parameters.EmptyReadOnlyParameters,
686 new ConstructorBaseInitializer (
687 null, Parameters.EmptyReadOnlyParameters,
693 c.Block = new ToplevelBlock (null, Location);
697 public void ReportStructInitializedInstanceError ()
699 string n = TypeBuilder.FullName;
701 foreach (Field f in initialized_fields){
704 "`" + n + "." + f.Name + "': can not have " +
705 "instance field initializers in structs");
710 /// The pending methods that need to be implemented
711 // (interfaces or abstract methods)
713 public PendingImplementation Pending;
715 public abstract void Register ();
717 public abstract PendingImplementation GetPendingImplementations ();
719 TypeExpr[] GetPartialBases (out TypeExpr parent, out bool error)
721 ArrayList ifaces = new ArrayList ();
724 Location parent_loc = Location.Null;
726 foreach (ClassPart part in parts) {
728 TypeExpr[] new_ifaces;
730 new_ifaces = part.GetClassBases (out new_parent, out error);
734 if ((parent != null) && (new_parent != null) &&
735 !parent.Equals (new_parent)) {
736 Report.Error (263, part.Location,
737 "Partial declarations of `{0}' must " +
738 "not specify different base classes",
741 if (!Location.IsNull (parent_loc))
742 Report.LocationOfPreviousError (parent_loc);
748 if ((parent == null) && (new_parent != null)) {
750 parent_loc = part.Location;
753 if (new_ifaces == null)
756 foreach (TypeExpr iface in new_ifaces) {
758 foreach (TypeExpr old_iface in ifaces) {
759 if (old_iface.Equals (iface)) {
772 TypeExpr[] retval = new TypeExpr [ifaces.Count];
773 ifaces.CopyTo (retval, 0);
777 TypeExpr[] GetNormalBases (out TypeExpr parent, out bool error)
781 int count = Bases.Count;
784 if (Kind == Kind.Class){
785 TypeExpr name = ResolveTypeExpr (
786 (Expression) Bases [0], false, Location);
803 TypeExpr [] ifaces = new TypeExpr [count-start];
805 for (i = start, j = 0; i < count; i++, j++){
806 Expression name = (Expression) Bases [i];
807 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
808 if (resolved == null) {
813 ifaces [j] = resolved;
821 /// This function computes the Base class and also the
822 /// list of interfaces that the class or struct @c implements.
824 /// The return value is an array (might be null) of
825 /// interfaces implemented (as Types).
827 /// The @parent argument is set to the parent object or null
828 /// if this is `System.Object'.
830 TypeExpr [] GetClassBases (out TypeExpr parent, out bool error)
832 ArrayList bases = Bases;
840 ifaces = GetPartialBases (out parent, out error);
841 else if (Bases == null){
845 ifaces = GetNormalBases (out parent, out error);
850 if ((parent != null) && (Kind == Kind.Class)){
851 if (parent.IsSealed){
854 if (parent.IsValueType)
855 detail = " (a class can not inherit from a struct/enum)";
857 Report.Error (509, "class `"+ Name +
858 "': Cannot inherit from sealed class `"+
859 parent.Name + "'" + detail);
864 if (!parent.CanInheritFrom ()){
865 Report.Error (644, Location,
866 "`{0}' cannot inherit from special class `{1}'",
872 if (!parent.AsAccessible (this, ModFlags))
873 Report.Error (60, Location,
874 "Inconsistent accessibility: base class `" +
875 parent.Name + "' is less accessible than class `" +
880 base_class_name = parent.Name;
885 int count = ifaces != null ? ifaces.Length : 0;
887 for (i = 0; i < count; i++) {
888 TypeExpr iface = (TypeExpr) ifaces [i];
890 if ((Kind != Kind.Class) && !iface.IsInterface){
891 string what = Kind == Kind.Struct ?
892 "Struct" : "Interface";
894 Report.Error (527, Location,
895 "In {0} `{1}', type `{2}' is not "+
896 "an interface", what, Name, iface.Name);
903 Report.Error (527, Location,
904 "In Class `{0}', `{1}' is not " +
905 "an interface", Name, iface.Name);
911 for (int x = 0; x < i; x++) {
912 if (iface.Equals (ifaces [x])) {
913 Report.Error (528, Location,
914 "`{0}' is already listed in " +
915 "interface list", iface.Name);
921 if ((Kind == Kind.Interface) &&
922 !iface.AsAccessible (Parent, ModFlags))
923 Report.Error (61, Location,
924 "Inconsistent accessibility: base " +
925 "interface `{0}' is less accessible " +
926 "than interface `{1}'", iface.Name,
930 return TypeManager.ExpandInterfaces (ifaces);
936 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
938 public override TypeBuilder DefineType ()
942 if (TypeBuilder != null)
949 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
956 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
958 ifaces = GetClassBases (out parent, out error);
962 if (parent == null) {
963 if (Kind == Kind.Class){
964 if (RootContext.StdLib)
965 parent = TypeManager.system_object_expr;
966 else if (Name != "System.Object")
967 parent = TypeManager.system_object_expr;
968 } else if (Kind == Kind.Struct) {
970 // If we are compiling our runtime,
971 // and we are defining ValueType, then our
972 // parent is `System.Object'.
974 if (!RootContext.StdLib && Name == "System.ValueType")
975 parent = TypeManager.system_object_expr;
977 parent = TypeManager.system_valuetype_expr;
981 if ((Kind == Kind.Struct) && TypeManager.value_type == null)
982 throw new Exception ();
984 TypeAttributes type_attributes = TypeAttr;
987 base_class_type = parent.ResolveType (ec);
990 if (TypeManager.NamespaceClash (Name, Location)) {
995 ModuleBuilder builder = CodeGen.Module.Builder;
996 TypeBuilder = builder.DefineType (
997 Name, type_attributes, base_class_type, null);
1000 TypeBuilder builder = Parent.DefineType ();
1001 if (builder == null)
1004 TypeBuilder = builder.DefineNestedType (
1005 Basename, type_attributes, base_class_type, null);
1009 // Structs with no fields need to have at least one byte.
1010 // The right thing would be to set the PackingSize in a DefineType
1011 // but there are no functions that allow interfaces *and* the size to
1015 if ((Kind == Kind.Struct) && !have_nonstatic_fields){
1016 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
1017 FieldAttributes.Private);
1020 // add interfaces that were not added at type creation
1021 if (ifaces != null) {
1022 base_inteface_types = new Type[ifaces.Length];
1023 for (int i = 0; i < ifaces.Length; ++i) {
1024 Type itype = ifaces [i].ResolveType (ec);
1025 TypeBuilder.AddInterfaceImplementation (itype);
1026 base_inteface_types [i] = itype;
1031 // Finish the setup for the EmitContext
1033 ec.ContainerType = TypeBuilder;
1035 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
1037 if ((parent != null) && parent.IsAttribute) {
1038 RootContext.RegisterAttribute (this);
1039 } else if (!(this is Iterator))
1040 RootContext.RegisterOrder (this);
1042 if (!DefineNestedTypes ()) {
1051 protected virtual bool DefineNestedTypes ()
1053 if (Interfaces != null) {
1054 foreach (TypeContainer iface in Interfaces)
1055 if (iface.DefineType () == null)
1059 if (Types != null) {
1060 foreach (TypeContainer tc in Types)
1061 if (tc.DefineType () == null)
1065 if (Delegates != null) {
1066 foreach (Delegate d in Delegates)
1067 if (d.DefineType () == null)
1071 if (Enums != null) {
1072 foreach (Enum en in Enums)
1073 if (en.DefineType () == null)
1077 if (Parts != null) {
1078 foreach (ClassPart part in Parts) {
1079 part.TypeBuilder = TypeBuilder;
1080 part.base_class_type = base_class_type;
1088 /// Defines the MemberCore objects that are in the `list' Arraylist
1090 /// The `defined_names' array contains a list of members defined in
1093 static ArrayList remove_list = new ArrayList ();
1094 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
1098 remove_list.Clear ();
1100 foreach (MemberCore mc in list){
1102 if (defined_names != null)
1103 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
1108 if (RootContext.WarningLevel >= 4){
1109 if ((mc.ModFlags & Modifiers.NEW) != 0)
1110 Warning_KeywordNewNotRequired (mc.Location, mc);
1112 } else if (mc is MethodCore)
1113 ((MethodCore) mc).OverridesSomething = true;
1116 remove_list.Add (mc);
1123 MemberInfo match = defined_names [idx];
1125 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
1129 // If we are both methods, let the method resolution emit warnings
1131 if (match is MethodBase && mc is MethodCore)
1134 if ((mc.ModFlags & Modifiers.NEW) == 0) {
1136 if (!(match is EventInfo)) {
1137 Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
1141 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
1145 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
1149 foreach (object o in remove_list)
1152 remove_list.Clear ();
1156 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
1157 // class is consistent. Either it is `Item' or it is the name defined by all the
1158 // indexers with the `IndexerName' attribute.
1160 // Turns out that the IndexerNameAttribute is applied to each indexer,
1161 // but it is never emitted, instead a DefaultMember attribute is attached
1164 void DefineIndexers ()
1166 string class_indexer_name = null;
1169 // If there's both an explicit and an implicit interface implementation, the
1170 // explicit one actually implements the interface while the other one is just
1171 // a normal indexer. See bug #37714.
1174 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
1175 bool seen_normal_indexers = false;
1177 foreach (Indexer i in Indexers) {
1182 name = i.IndexerName;
1184 if (i.InterfaceType != null) {
1185 if (seen_normal_indexers)
1186 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
1190 seen_normal_indexers = true;
1192 if (class_indexer_name == null)
1193 class_indexer_name = name;
1194 else if (name != class_indexer_name)
1195 Report.Error (668, i.Location, "Two indexers have different names, " +
1196 " you should use the same name for all your indexers");
1199 if (seen_normal_indexers && class_indexer_name == null)
1200 class_indexer_name = "Item";
1201 IndexerName = class_indexer_name;
1204 static void Error_KeywordNotAllowed (Location loc)
1206 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1210 /// Populates our TypeBuilder with fields and methods
1212 public override bool DefineMembers (TypeContainer container)
1214 if (members_defined)
1215 return members_defined_ok;
1217 members_defined_ok = DoDefineMembers ();
1218 members_defined = true;
1220 return members_defined_ok;
1223 bool DoDefineMembers ()
1225 MemberInfo [] defined_names = null;
1228 // We need to be able to use the member cache while we are checking/defining
1231 if (TypeBuilder.BaseType != null)
1232 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1235 if (RootContext.WarningLevel > 1){
1239 // This code throws an exception in the comparer
1240 // I guess the string is not an object?
1242 ptype = TypeBuilder.BaseType;
1244 defined_names = (MemberInfo []) FindMembers (
1245 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1246 BindingFlags.Public | BindingFlags.Instance |
1247 BindingFlags.Static, null, null);
1249 Array.Sort (defined_names, mif_compare);
1253 Class pclass = Parent as Class;
1254 if (pclass != null) {
1255 string pname = null;
1257 Type t = pclass.TypeBuilder.BaseType;
1258 while ((t != null) && (ptype == null)) {
1259 pname = t.FullName + "." + Basename;
1260 ptype = RootContext.LookupType (this, pname, true, Location.Null);
1264 if ((ModFlags & Modifiers.NEW) != 0) {
1266 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1267 "inherited member. The keyword new is not required.");
1268 } else if (ptype != null) {
1269 Report.Warning (108, Location, "The keyword new is required on `" +
1270 Name + "' because it hides inherited member '" +
1273 } else if ((ModFlags & Modifiers.NEW) != 0)
1274 Error_KeywordNotAllowed (Location);
1276 if (constants != null)
1277 DefineMembers (constants, defined_names);
1280 DefineMembers (fields, defined_names);
1282 if ((Kind == Kind.Class) && !(this is ClassPart)){
1283 if (instance_constructors == null){
1284 if (default_constructor == null)
1285 DefineDefaultConstructor (false);
1288 if (initialized_static_fields != null &&
1289 default_static_constructor == null)
1290 DefineDefaultConstructor (true);
1293 if (Kind == Kind.Struct){
1295 // Structs can not have initialized instance
1298 if (initialized_static_fields != null &&
1299 default_static_constructor == null)
1300 DefineDefaultConstructor (true);
1302 if (initialized_fields != null)
1303 ReportStructInitializedInstanceError ();
1306 Pending = GetPendingImplementations ();
1308 if (parts != null) {
1309 foreach (ClassPart part in parts) {
1310 if (!part.DefineMembers (this))
1316 // Constructors are not in the defined_names array
1318 if (instance_constructors != null)
1319 DefineMembers (instance_constructors, null);
1321 if (default_static_constructor != null)
1322 default_static_constructor.Define ();
1324 if (methods != null)
1325 DefineMembers (methods, defined_names);
1327 if (properties != null)
1328 DefineMembers (properties, defined_names);
1331 DefineMembers (events, defined_names);
1333 if (indexers != null)
1336 if (operators != null){
1337 DefineMembers (operators, null);
1339 CheckPairedOperators ();
1343 DefineMembers (enums, defined_names);
1345 if (delegates != null)
1346 DefineMembers (delegates, defined_names);
1349 if (!(this is ClassPart))
1350 member_cache = new MemberCache (this);
1353 if (parts != null) {
1354 foreach (ClassPart part in parts)
1355 part.member_cache = member_cache;
1358 if (iterators != null) {
1359 foreach (Iterator iterator in iterators) {
1360 if (iterator.DefineType () == null)
1364 foreach (Iterator iterator in iterators) {
1365 if (!iterator.DefineMembers (this))
1373 public override bool Define ()
1375 if (parts != null) {
1376 foreach (ClassPart part in parts) {
1377 if (!part.Define ())
1386 /// This function is based by a delegate to the FindMembers routine
1388 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1394 /// This filter is used by FindMembers, and we just keep
1395 /// a global for the filter to `AlwaysAccept'
1397 static MemberFilter accepting_filter;
1401 /// A member comparission method based on name only
1403 static IComparer mif_compare;
1405 static TypeContainer ()
1407 accepting_filter = new MemberFilter (AlwaysAccept);
1408 mif_compare = new MemberInfoCompare ();
1411 public MethodInfo[] GetMethods ()
1413 ArrayList members = new ArrayList ();
1415 DefineMembers (null);
1417 if (methods != null) {
1418 int len = methods.Count;
1419 for (int i = 0; i < len; i++) {
1420 Method m = (Method) methods [i];
1422 members.Add (m.MethodBuilder);
1426 if (operators != null) {
1427 int len = operators.Count;
1428 for (int i = 0; i < len; i++) {
1429 Operator o = (Operator) operators [i];
1431 members.Add (o.OperatorMethodBuilder);
1435 if (properties != null) {
1436 int len = properties.Count;
1437 for (int i = 0; i < len; i++) {
1438 Property p = (Property) properties [i];
1440 if (p.GetBuilder != null)
1441 members.Add (p.GetBuilder);
1442 if (p.SetBuilder != null)
1443 members.Add (p.SetBuilder);
1447 if (indexers != null) {
1448 int len = indexers.Count;
1449 for (int i = 0; i < len; i++) {
1450 Indexer ix = (Indexer) indexers [i];
1452 if (ix.GetBuilder != null)
1453 members.Add (ix.GetBuilder);
1454 if (ix.SetBuilder != null)
1455 members.Add (ix.SetBuilder);
1459 if (events != null) {
1460 int len = events.Count;
1461 for (int i = 0; i < len; i++) {
1462 Event e = (Event) events [i];
1464 if (e.AddBuilder != null)
1465 members.Add (e.AddBuilder);
1466 if (e.RemoveBuilder != null)
1467 members.Add (e.RemoveBuilder);
1471 MethodInfo[] retMethods = new MethodInfo [members.Count];
1472 members.CopyTo (retMethods, 0);
1477 /// This method returns the members of this type just like Type.FindMembers would
1478 /// Only, we need to use this for types which are _being_ defined because MS'
1479 /// implementation can't take care of that.
1482 // FIXME: return an empty static array instead of null, that cleans up
1483 // some code and is consistent with some coding conventions I just found
1487 // Notice that in various cases we check if our field is non-null,
1488 // something that would normally mean that there was a bug elsewhere.
1490 // The problem happens while we are defining p-invoke methods, as those
1491 // will trigger a FindMembers, but this happens before things are defined
1493 // Since the whole process is a no-op, it is fine to check for null here.
1495 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1496 MemberFilter filter, object criteria)
1498 ArrayList members = null;
1501 if ((bf & BindingFlags.Public) != 0)
1502 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1504 if ((bf & BindingFlags.NonPublic) != 0)
1505 modflags |= Modifiers.PRIVATE;
1507 int static_mask = 0, static_flags = 0;
1508 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1509 case BindingFlags.Static:
1510 static_mask = static_flags = Modifiers.STATIC;
1513 case BindingFlags.Instance:
1514 static_mask = Modifiers.STATIC;
1519 static_mask = static_flags = 0;
1523 Timer.StartTimer (TimerType.TcFindMembers);
1526 filter = accepting_filter;
1528 if ((mt & MemberTypes.Field) != 0) {
1529 if (fields != null) {
1530 int len = fields.Count;
1531 for (int i = 0; i < len; i++) {
1532 Field f = (Field) fields [i];
1534 if ((f.ModFlags & modflags) == 0)
1536 if ((f.ModFlags & static_mask) != static_flags)
1539 FieldBuilder fb = f.FieldBuilder;
1540 if (fb != null && filter (fb, criteria) == true) {
1541 if (members == null)
1542 members = new ArrayList ();
1549 if (constants != null) {
1550 int len = constants.Count;
1551 for (int i = 0; i < len; i++) {
1552 Const con = (Const) constants [i];
1554 if ((con.ModFlags & modflags) == 0)
1556 if ((con.ModFlags & static_mask) != static_flags)
1559 FieldBuilder fb = con.FieldBuilder;
1560 if (fb != null && filter (fb, criteria) == true) {
1561 if (members == null)
1562 members = new ArrayList ();
1570 if ((mt & MemberTypes.Method) != 0) {
1571 if (methods != null) {
1572 int len = methods.Count;
1573 for (int i = 0; i < len; i++) {
1574 Method m = (Method) methods [i];
1576 if ((m.ModFlags & modflags) == 0)
1578 if ((m.ModFlags & static_mask) != static_flags)
1581 MethodBuilder mb = m.MethodBuilder;
1583 if (mb != null && filter (mb, criteria) == true) {
1584 if (members == null)
1585 members = new ArrayList ();
1592 if (operators != null) {
1593 int len = operators.Count;
1594 for (int i = 0; i < len; i++) {
1595 Operator o = (Operator) operators [i];
1597 if ((o.ModFlags & modflags) == 0)
1599 if ((o.ModFlags & static_mask) != static_flags)
1602 MethodBuilder ob = o.OperatorMethodBuilder;
1603 if (ob != null && filter (ob, criteria) == true) {
1604 if (members == null)
1605 members = new ArrayList ();
1612 if (properties != null) {
1613 int len = properties.Count;
1614 for (int i = 0; i < len; i++) {
1615 Property p = (Property) properties [i];
1617 if ((p.ModFlags & modflags) == 0)
1619 if ((p.ModFlags & static_mask) != static_flags)
1625 if (b != null && filter (b, criteria) == true) {
1626 if (members == null)
1627 members = new ArrayList ();
1633 if (b != null && filter (b, criteria) == true) {
1634 if (members == null)
1635 members = new ArrayList ();
1642 if (indexers != null) {
1643 int len = indexers.Count;
1644 for (int i = 0; i < len; i++) {
1645 Indexer ix = (Indexer) indexers [i];
1647 if ((ix.ModFlags & modflags) == 0)
1649 if ((ix.ModFlags & static_mask) != static_flags)
1655 if (b != null && filter (b, criteria) == true) {
1656 if (members == null)
1657 members = new ArrayList ();
1663 if (b != null && filter (b, criteria) == true) {
1664 if (members == null)
1665 members = new ArrayList ();
1673 if ((mt & MemberTypes.Event) != 0) {
1674 if (events != null) {
1675 int len = events.Count;
1676 for (int i = 0; i < len; i++) {
1677 Event e = (Event) events [i];
1679 if ((e.ModFlags & modflags) == 0)
1681 if ((e.ModFlags & static_mask) != static_flags)
1684 MemberInfo eb = e.EventBuilder;
1685 if (eb != null && filter (eb, criteria) == true) {
1686 if (members == null)
1687 members = new ArrayList ();
1689 members.Add (e.EventBuilder);
1695 if ((mt & MemberTypes.Property) != 0){
1696 if (properties != null) {
1697 int len = properties.Count;
1698 for (int i = 0; i < len; i++) {
1699 Property p = (Property) properties [i];
1701 if ((p.ModFlags & modflags) == 0)
1703 if ((p.ModFlags & static_mask) != static_flags)
1706 MemberInfo pb = p.PropertyBuilder;
1707 if (pb != null && filter (pb, criteria) == true) {
1708 if (members == null)
1709 members = new ArrayList ();
1711 members.Add (p.PropertyBuilder);
1716 if (indexers != null) {
1717 int len = indexers.Count;
1718 for (int i = 0; i < len; i++) {
1719 Indexer ix = (Indexer) indexers [i];
1721 if ((ix.ModFlags & modflags) == 0)
1723 if ((ix.ModFlags & static_mask) != static_flags)
1726 MemberInfo ib = ix.PropertyBuilder;
1727 if (ib != null && filter (ib, criteria) == true) {
1728 if (members == null)
1729 members = new ArrayList ();
1731 members.Add (ix.PropertyBuilder);
1737 if ((mt & MemberTypes.NestedType) != 0) {
1738 if (types != null) {
1739 int len = types.Count;
1740 for (int i = 0; i < len; i++) {
1741 TypeContainer t = (TypeContainer) types [i];
1743 if ((t.ModFlags & modflags) == 0)
1746 TypeBuilder tb = t.TypeBuilder;
1747 if (tb != null && (filter (tb, criteria) == true)) {
1748 if (members == null)
1749 members = new ArrayList ();
1756 if (enums != null) {
1757 int len = enums.Count;
1758 for (int i = 0; i < len; i++) {
1759 Enum en = (Enum) enums [i];
1761 if ((en.ModFlags & modflags) == 0)
1764 TypeBuilder tb = en.TypeBuilder;
1765 if (tb != null && (filter (tb, criteria) == true)) {
1766 if (members == null)
1767 members = new ArrayList ();
1774 if (delegates != null) {
1775 int len = delegates.Count;
1776 for (int i = 0; i < len; i++) {
1777 Delegate d = (Delegate) delegates [i];
1779 if ((d.ModFlags & modflags) == 0)
1782 TypeBuilder tb = d.TypeBuilder;
1783 if (tb != null && (filter (tb, criteria) == true)) {
1784 if (members == null)
1785 members = new ArrayList ();
1792 if (interfaces != null) {
1793 int len = interfaces.Count;
1794 for (int i = 0; i < len; i++) {
1795 TypeContainer iface = (TypeContainer) interfaces [i];
1797 if ((iface.ModFlags & modflags) == 0)
1800 TypeBuilder tb = iface.TypeBuilder;
1801 if (tb != null && (filter (tb, criteria) == true)) {
1802 if (members == null)
1803 members = new ArrayList ();
1811 if ((mt & MemberTypes.Constructor) != 0){
1812 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1813 int len = instance_constructors.Count;
1814 for (int i = 0; i < len; i++) {
1815 Constructor c = (Constructor) instance_constructors [i];
1817 ConstructorBuilder cb = c.ConstructorBuilder;
1818 if (cb != null && filter (cb, criteria) == true) {
1819 if (members == null)
1820 members = new ArrayList ();
1827 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1828 ConstructorBuilder cb =
1829 default_static_constructor.ConstructorBuilder;
1831 if (cb != null && filter (cb, criteria) == true) {
1832 if (members == null)
1833 members = new ArrayList ();
1841 // Lookup members in parent if requested.
1843 if ((bf & BindingFlags.DeclaredOnly) == 0) {
1844 if (TypeBuilder.BaseType != null) {
1845 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1846 if (list.Count > 0) {
1847 if (members == null)
1848 members = new ArrayList ();
1850 members.AddRange (list);
1853 if (base_inteface_types != null) {
1854 foreach (Type base_type in base_inteface_types) {
1855 MemberList list = TypeContainer.FindMembers (base_type, mt, bf, filter, criteria);
1857 if (list.Count > 0) {
1858 if (members == null)
1859 members = new ArrayList ();
1860 members.AddRange (list);
1866 Timer.StopTimer (TimerType.TcFindMembers);
1868 if (members == null)
1869 return MemberList.Empty;
1871 return new MemberList (members);
1874 public override MemberCache MemberCache {
1876 return member_cache;
1880 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1881 MemberFilter filter, object criteria)
1883 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1886 return ds.FindMembers (mt, bf, filter, criteria);
1888 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1893 // FindMethods will look for methods not only in the type `t', but in
1894 // any interfaces implemented by the type.
1896 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1897 MemberFilter filter, object criteria)
1903 /// Emits the values for the constants
1905 public void EmitConstants ()
1907 if (constants != null)
1908 foreach (Const con in constants)
1913 protected virtual void VerifyMembers (EmitContext ec)
1916 // Check for internal or private fields that were never assigned
1918 if (RootContext.WarningLevel >= 3) {
1919 if (fields != null){
1920 foreach (Field f in fields) {
1921 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
1924 if ((f.status & Field.Status.USED) == 0){
1925 Report.Warning (Message.CS0169_The_private_field_is_never_used, f.Location, f.GetSignatureForError ());
1930 // Only report 649 on level 4
1932 if (RootContext.WarningLevel < 4)
1935 if ((f.status & Field.Status.ASSIGNED) != 0)
1938 Report.Warning (Message.CS0649_Field_is_never_assigned_to_and_will_always_have_its_default_value, f.Location, f.GetSignatureForError (), "");
1942 if (events != null){
1943 foreach (Event e in events){
1945 Report.Warning (Message.CS0067_The_event_is_never_used, e.Location, e.GetSignatureForError ());
1952 /// Emits the code, this step is performed after all
1953 /// the types, enumerations, constructors
1955 public void EmitType ()
1957 if (OptAttributes != null)
1958 OptAttributes.Emit (ec, this);
1962 if (instance_constructors != null) {
1963 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && IsClsCompliaceRequired (this)) {
1964 bool has_compliant_args = false;
1966 foreach (Constructor c in instance_constructors) {
1969 if (has_compliant_args)
1972 has_compliant_args = c.HasCompliantArgs;
1974 if (!has_compliant_args)
1975 Report.Error_T (Message.CS3015_has_no_accessible_constructors_which_use_only_CLS_compliant_types, Location, GetSignatureForError ());
1977 foreach (Constructor c in instance_constructors)
1982 if (default_static_constructor != null)
1983 default_static_constructor.Emit ();
1985 if (methods != null)
1986 foreach (Method m in methods)
1989 if (operators != null)
1990 foreach (Operator o in operators)
1993 if (properties != null)
1994 foreach (Property p in properties)
1997 if (indexers != null){
1998 foreach (Indexer ix in indexers)
2000 if (IndexerName != null) {
2001 CustomAttributeBuilder cb = EmitDefaultMemberAttr ();
2002 TypeBuilder.SetCustomAttribute (cb);
2007 foreach (Field f in fields)
2010 if (events != null){
2011 foreach (Event e in Events)
2015 if (delegates != null) {
2016 foreach (Delegate d in Delegates) {
2021 if (enums != null) {
2022 foreach (Enum e in enums) {
2027 if (parts != null) {
2028 foreach (ClassPart part in parts)
2032 if ((Pending != null) && !(this is ClassPart))
2033 if (Pending.VerifyPendingMethods ())
2038 if (iterators != null)
2039 foreach (Iterator iterator in iterators)
2040 iterator.EmitType ();
2042 // if (types != null)
2043 // foreach (TypeContainer tc in types)
2047 CustomAttributeBuilder EmitDefaultMemberAttr ()
2049 EmitContext ec = new EmitContext (this, Location, null, null, ModFlags);
2051 Expression ml = Expression.MemberLookup (ec, TypeManager.default_member_type,
2052 ".ctor", MemberTypes.Constructor,
2053 BindingFlags.Public | BindingFlags.Instance,
2056 MethodGroupExpr mg = (MethodGroupExpr) ml;
2058 MethodBase constructor = mg.Methods [0];
2060 string [] vals = { IndexerName };
2062 CustomAttributeBuilder cb = null;
2064 cb = new CustomAttributeBuilder ((ConstructorInfo) constructor, vals);
2066 Report.Warning (-100, "Can not set the indexer default member attribute");
2072 public override void CloseType ()
2074 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2078 caching_flags |= Flags.CloseTypeCreated;
2079 TypeBuilder.CreateType ();
2080 } catch (TypeLoadException){
2082 // This is fine, the code still created the type
2084 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2085 // Console.WriteLine (e.Message);
2087 Console.WriteLine ("In type: " + Name);
2092 foreach (Enum en in Enums)
2096 foreach (TypeContainer tc in Types)
2097 if (tc.Kind == Kind.Struct)
2100 foreach (TypeContainer tc in Types)
2101 if (tc.Kind != Kind.Struct)
2105 if (Delegates != null)
2106 foreach (Delegate d in Delegates)
2109 if (Iterators != null)
2110 foreach (Iterator i in Iterators)
2118 initialized_fields = null;
2119 initialized_static_fields = null;
2128 default_constructor = null;
2129 default_static_constructor = null;
2131 OptAttributes = null;
2133 parent_container = null;
2134 member_cache = null;
2137 public string MakeName (string n)
2139 return "`" + Name + "." + n + "'";
2142 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
2145 108, l, "The keyword new is required on " +
2146 MakeName (mi.Name) + " because it hides `" +
2147 mi.ReflectedType.Name + "." + mi.Name + "'");
2150 public void Warning_KeywordNewNotRequired (Location l, MemberCore mc)
2153 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
2154 "inherited member, the keyword new is not required");
2157 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
2160 72, l, MakeName (mi.Name) + " : cannot override; `" +
2161 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
2164 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
2170 // Performs the validation on a Method's modifiers (properties have
2171 // the same properties).
2173 public bool MethodModifiersValid (int flags, string n, Location loc)
2175 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2176 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2177 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2181 // At most one of static, virtual or override
2183 if ((flags & Modifiers.STATIC) != 0){
2184 if ((flags & vao) != 0){
2186 112, loc, "static method " + MakeName (n) + "can not be marked " +
2187 "as virtual, abstract or override");
2192 if (Kind == Kind.Struct){
2193 if ((flags & va) != 0){
2194 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
2199 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2201 113, loc, MakeName (n) +
2202 " marked as override cannot be marked as new or virtual");
2207 // If the declaration includes the abstract modifier, then the
2208 // declaration does not include static, virtual or extern
2210 if ((flags & Modifiers.ABSTRACT) != 0){
2211 if ((flags & Modifiers.EXTERN) != 0){
2213 180, loc, MakeName (n) + " can not be both abstract and extern");
2217 if ((flags & Modifiers.VIRTUAL) != 0){
2219 503, loc, MakeName (n) + " can not be both abstract and virtual");
2223 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2225 513, loc, MakeName (n) +
2226 " is abstract but its container class is not");
2232 if ((flags & Modifiers.PRIVATE) != 0){
2233 if ((flags & vao) != 0){
2235 621, loc, MakeName (n) +
2236 " virtual or abstract members can not be private");
2241 if ((flags & Modifiers.SEALED) != 0){
2242 if ((flags & Modifiers.OVERRIDE) == 0){
2244 238, loc, MakeName (n) +
2245 " cannot be sealed because it is not an override");
2253 Hashtable builder_and_args;
2255 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
2257 if (builder_and_args == null)
2258 builder_and_args = new Hashtable ();
2262 protected override bool VerifyClsCompliance (DeclSpace ds)
2264 if (!base.VerifyClsCompliance (ds))
2267 // parent_container is null for System.Object
2268 if (parent_container != null && !AttributeTester.IsClsCompliant (parent_container.Type)) {
2269 Report.Error_T (Message.CS3009_base_type_is_not_CLS_compliant, Location, GetSignatureForError (), TypeManager.CSharpName (parent_container.Type));
2276 /// Performs checks for an explicit interface implementation. First it
2277 /// checks whether the `interface_type' is a base inteface implementation.
2278 /// Then it checks whether `name' exists in the interface type.
2280 public virtual bool VerifyImplements (Type interface_type, string full,
2281 string name, Location loc)
2285 if (ifaces != null){
2286 foreach (TypeExpr t in ifaces){
2287 if (t.Type == interface_type){
2295 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
2302 protected override void VerifyObsoleteAttribute()
2304 CheckUsageOfObsoleteAttribute (base_class_type);
2309 foreach (TypeExpr expr in ifaces) {
2310 CheckUsageOfObsoleteAttribute (expr.Type);
2319 string IMemberContainer.Name {
2325 Type IMemberContainer.Type {
2331 IMemberContainer IMemberContainer.Parent {
2333 return parent_container;
2337 MemberCache IMemberContainer.MemberCache {
2339 return member_cache;
2343 bool IMemberContainer.IsInterface {
2345 return Kind == Kind.Interface;
2349 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2351 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
2355 // Operator pair checking
2358 class OperatorEntry {
2360 public Type ret_type;
2361 public Type type1, type2;
2363 public Operator.OpType ot;
2365 public OperatorEntry (int f, Operator o)
2369 ret_type = o.OperatorMethod.GetReturnType ();
2370 Type [] pt = o.OperatorMethod.ParameterTypes;
2374 ot = o.OperatorType;
2377 public override int GetHashCode ()
2379 return ret_type.GetHashCode ();
2382 public override bool Equals (object o)
2384 OperatorEntry other = (OperatorEntry) o;
2386 if (other.ret_type != ret_type)
2388 if (other.type1 != type1)
2390 if (other.type2 != type2)
2397 // Checks that some operators come in pairs:
2403 // They are matched based on the return type and the argument types
2405 void CheckPairedOperators ()
2407 Hashtable pairs = new Hashtable (null, null);
2408 Operator true_op = null;
2409 Operator false_op = null;
2410 bool has_equality_or_inequality = false;
2412 // Register all the operators we care about.
2413 foreach (Operator op in operators){
2416 switch (op.OperatorType){
2417 case Operator.OpType.Equality:
2419 has_equality_or_inequality = true;
2421 case Operator.OpType.Inequality:
2423 has_equality_or_inequality = true;
2426 case Operator.OpType.True:
2429 case Operator.OpType.False:
2433 case Operator.OpType.GreaterThan:
2435 case Operator.OpType.LessThan:
2438 case Operator.OpType.GreaterThanOrEqual:
2440 case Operator.OpType.LessThanOrEqual:
2446 OperatorEntry oe = new OperatorEntry (reg, op);
2448 object o = pairs [oe];
2452 oe = (OperatorEntry) o;
2457 if (true_op != null){
2458 if (false_op == null)
2459 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2460 } else if (false_op != null)
2461 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2464 // Look for the mistakes.
2466 foreach (DictionaryEntry de in pairs){
2467 OperatorEntry oe = (OperatorEntry) de.Key;
2474 case Operator.OpType.Equality:
2477 case Operator.OpType.Inequality:
2480 case Operator.OpType.GreaterThan:
2483 case Operator.OpType.LessThan:
2486 case Operator.OpType.GreaterThanOrEqual:
2489 case Operator.OpType.LessThanOrEqual:
2493 Report.Error (216, oe.op.Location,
2494 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2497 if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2498 MethodSignature equals_ms = new MethodSignature (
2499 "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2500 MethodSignature hash_ms = new MethodSignature (
2501 "GetHashCode", TypeManager.int32_type, new Type [0]);
2503 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2504 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2506 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2507 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2510 bool equals_ok = false;
2511 if ((equals_ml != null) && (equals_ml.Count == 1))
2512 equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2513 bool hash_ok = false;
2514 if ((hash_ml != null) && (hash_ml.Count == 1))
2515 hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2518 Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2519 "not override Object.Equals (object o)");
2521 Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2522 "not override Object.GetHashCode ()");
2527 public class PartialContainer : TypeContainer {
2529 public readonly Namespace Namespace;
2530 public readonly int OriginalModFlags;
2531 public readonly int AllowedModifiers;
2532 public readonly TypeAttributes DefaultTypeAttributes;
2534 static PartialContainer Create (NamespaceEntry ns, TypeContainer parent,
2535 string name, int mod_flags, Kind kind,
2538 PartialContainer pc;
2539 DeclSpace ds = (DeclSpace) RootContext.Tree.Decls [name];
2541 pc = ds as PartialContainer;
2545 260, ds.Location, "Missing partial modifier " +
2546 "on declaration of type `{0}'; another " +
2547 "partial implementation of this type exists",
2550 Report.LocationOfPreviousError (loc);
2554 if (pc.Kind != kind) {
2556 261, loc, "Partial declarations of `{0}' " +
2557 "must be all classes, all structs or " +
2558 "all interfaces", name);
2562 if (pc.OriginalModFlags != mod_flags) {
2564 262, loc, "Partial declarations of `{0}' " +
2565 "have conflicting accessibility modifiers",
2573 pc = new PartialContainer (ns, parent, name, mod_flags, kind, loc);
2574 RootContext.Tree.RecordDecl (name, pc);
2575 parent.AddType (pc);
2580 public static ClassPart CreatePart (NamespaceEntry ns, TypeContainer parent,
2581 string name, int mod, Attributes attrs,
2582 Kind kind, Location loc)
2584 PartialContainer pc = Create (ns, parent, name, mod, kind, loc);
2586 // An error occured; create a dummy container, but don't
2588 pc = new PartialContainer (ns, parent, name, mod, kind, loc);
2591 ClassPart part = new ClassPart (ns, pc, mod, attrs, kind, loc);
2596 protected PartialContainer (NamespaceEntry ns, TypeContainer parent,
2597 string name, int mod, Kind kind, Location l)
2598 : base (ns, parent, name, null, kind, l)
2600 this.Namespace = ns.NS;
2604 AllowedModifiers = Class.AllowedModifiers;
2605 DefaultTypeAttributes = Class.DefaultTypeAttributes;
2609 AllowedModifiers = Struct.AllowedModifiers;
2610 DefaultTypeAttributes = Struct.DefaultTypeAttributes;
2613 case Kind.Interface:
2614 AllowedModifiers = Interface.AllowedModifiers;
2615 DefaultTypeAttributes = Interface.DefaultTypeAttributes;
2619 throw new InvalidOperationException ();
2623 if (parent.Parent == null)
2624 accmods = Modifiers.INTERNAL;
2626 accmods = Modifiers.PRIVATE;
2628 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2629 this.OriginalModFlags = mod;
2632 public override void Register ()
2634 if (Kind == Kind.Interface)
2635 Parent.AddInterface (this);
2636 else if (Kind == Kind.Class)
2637 Parent.AddClass (this);
2638 else if (Kind == Kind.Struct)
2639 Parent.AddStruct (this);
2641 throw new InvalidOperationException ();
2644 public override PendingImplementation GetPendingImplementations ()
2646 return PendingImplementation.GetPendingImplementations (this);
2649 public ClassPart AddPart (NamespaceEntry ns, int mod, Attributes attrs,
2652 ClassPart part = new ClassPart (ns, this, mod, attrs, Kind, l);
2657 public override TypeAttributes TypeAttr {
2659 return base.TypeAttr | DefaultTypeAttributes;
2664 public class ClassPart : TypeContainer {
2665 public readonly PartialContainer PartialContainer;
2666 public readonly bool IsPartial;
2668 public ClassPart (NamespaceEntry ns, PartialContainer parent,
2669 int mod, Attributes attrs, Kind kind, Location l)
2670 : base (ns, parent.Parent, parent.Name, attrs, kind, l)
2672 this.PartialContainer = parent;
2673 this.IsPartial = true;
2676 if (parent.Parent == null)
2677 accmods = Modifiers.INTERNAL;
2679 accmods = Modifiers.PRIVATE;
2681 this.ModFlags = Modifiers.Check (
2682 parent.AllowedModifiers, mod, accmods, l);
2685 public override void Register ()
2689 public override PendingImplementation GetPendingImplementations ()
2691 return PartialContainer.Pending;
2694 public override bool VerifyImplements (Type interface_type, string full,
2695 string name, Location loc)
2697 return PartialContainer.VerifyImplements (
2698 interface_type, full, name, loc);
2702 public abstract class ClassOrStruct : TypeContainer {
2703 bool hasExplicitLayout = false;
2705 public ClassOrStruct (NamespaceEntry ns, TypeContainer parent,
2706 string name, Attributes attrs, Kind kind,
2708 : base (ns, parent, name, attrs, kind, l)
2712 public override PendingImplementation GetPendingImplementations ()
2714 return PendingImplementation.GetPendingImplementations (this);
2717 protected override void VerifyMembers (EmitContext ec)
2719 if (Fields != null) {
2720 foreach (Field f in Fields) {
2721 if ((f.ModFlags & Modifiers.STATIC) != 0)
2723 if (hasExplicitLayout) {
2724 if (f.OptAttributes == null
2725 || !f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
2726 Report.Error (625, f.Location,
2727 "Instance field of type marked with"
2728 + " StructLayout(LayoutKind.Explicit) must have a"
2729 + " FieldOffset attribute.");
2733 if (f.OptAttributes != null
2734 && f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
2735 Report.Error (636, f.Location,
2736 "The FieldOffset attribute can only be placed on members of "
2737 + "types marked with the StructLayout(LayoutKind.Explicit)");
2742 base.VerifyMembers (ec);
2745 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2747 if (a.Type == TypeManager.struct_layout_attribute_type
2748 && (LayoutKind) a.GetPositionalValue (0) == LayoutKind.Explicit)
2749 hasExplicitLayout = true;
2751 base.ApplyAttributeBuilder (a, cb);
2755 public class Class : ClassOrStruct {
2757 // Modifiers allowed in a class declaration
2759 public const int AllowedModifiers =
2762 Modifiers.PROTECTED |
2763 Modifiers.INTERNAL |
2765 Modifiers.ABSTRACT |
2769 // Information in the case we are an attribute type
2770 AttributeUsageAttribute attribute_usage;
2772 public Class (NamespaceEntry ns, TypeContainer parent, string name, int mod,
2773 Attributes attrs, Location l)
2774 : base (ns, parent, name, attrs, Kind.Class, l)
2778 if (parent.Parent == null)
2779 accmods = Modifiers.INTERNAL;
2781 accmods = Modifiers.PRIVATE;
2783 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2784 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.SEALED)) == (Modifiers.ABSTRACT | Modifiers.SEALED)) {
2785 Report.Error_T (Message.CS0502_cannot_be_both_abstract_and_sealed, Location, GetSignatureForError ());
2788 attribute_usage = new AttributeUsageAttribute (AttributeTargets.All);
2791 public override AttributeTargets AttributeTargets {
2793 return AttributeTargets.Class;
2797 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
2799 if (a.UsageAttribute != null)
2800 attribute_usage = a.UsageAttribute;
2802 base.ApplyAttributeBuilder (a, cb);
2805 public AttributeUsageAttribute AttributeUsage {
2807 return attribute_usage;
2811 public override void Register ()
2813 CheckDef (Parent.AddClass (this), Name, Location);
2816 public const TypeAttributes DefaultTypeAttributes =
2817 TypeAttributes.AutoLayout | TypeAttributes.Class;
2820 // FIXME: How do we deal with the user specifying a different
2823 public override TypeAttributes TypeAttr {
2825 return base.TypeAttr | DefaultTypeAttributes;
2830 public class Struct : ClassOrStruct {
2832 // Modifiers allowed in a struct declaration
2834 public const int AllowedModifiers =
2837 Modifiers.PROTECTED |
2838 Modifiers.INTERNAL |
2842 public Struct (NamespaceEntry ns, TypeContainer parent, string name,
2843 int mod, Attributes attrs, Location l)
2844 : base (ns, parent, name, attrs, Kind.Struct, l)
2848 if (parent.Parent == null)
2849 accmods = Modifiers.INTERNAL;
2851 accmods = Modifiers.PRIVATE;
2853 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2855 this.ModFlags |= Modifiers.SEALED;
2858 public override AttributeTargets AttributeTargets {
2860 return AttributeTargets.Struct;
2864 public override void Register ()
2866 CheckDef (Parent.AddStruct (this), Name, Location);
2869 public const TypeAttributes DefaultTypeAttributes =
2870 TypeAttributes.SequentialLayout |
2871 TypeAttributes.Sealed |
2872 TypeAttributes.BeforeFieldInit;
2875 // FIXME: Allow the user to specify a different set of attributes
2876 // in some cases (Sealed for example is mandatory for a class,
2877 // but what SequentialLayout can be changed
2879 public override TypeAttributes TypeAttr {
2881 return base.TypeAttr | DefaultTypeAttributes;
2889 public class Interface : TypeContainer, IMemberContainer {
2891 /// Modifiers allowed in a class declaration
2893 public const int AllowedModifiers =
2896 Modifiers.PROTECTED |
2897 Modifiers.INTERNAL |
2901 public Interface (NamespaceEntry ns, TypeContainer parent, string name, int mod,
2902 Attributes attrs, Location l)
2903 : base (ns, parent, name, attrs, Kind.Interface, l)
2907 if (parent.Parent == null)
2908 accmods = Modifiers.INTERNAL;
2910 accmods = Modifiers.PRIVATE;
2912 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2915 public override void Register ()
2917 CheckDef (Parent.AddInterface (this), Name, Location);
2920 public override PendingImplementation GetPendingImplementations ()
2925 public override AttributeTargets AttributeTargets {
2927 return AttributeTargets.Interface;
2931 public const TypeAttributes DefaultTypeAttributes =
2932 TypeAttributes.AutoLayout |
2933 TypeAttributes.Abstract |
2934 TypeAttributes.Interface;
2936 public override TypeAttributes TypeAttr {
2938 return base.TypeAttr | DefaultTypeAttributes;
2943 public abstract class MethodCore : MemberBase {
2944 public readonly Parameters Parameters;
2945 protected Block block;
2948 // Parameters, cached for semantic analysis.
2950 protected InternalParameters parameter_info;
2951 protected Type [] parameter_types;
2954 // This is set from TypeContainer.DefineMembers if this method overrides something.
2956 public bool OverridesSomething;
2958 // Whether this is an operator method.
2959 public bool IsOperator;
2961 static string[] attribute_targets = new string [] { "method", "return" };
2963 public MethodCore (TypeContainer parent, Expression type, int mod,
2964 int allowed_mod, bool is_interface, string name,
2965 Attributes attrs, Parameters parameters, Location loc)
2966 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name,
2969 Parameters = parameters;
2970 IsInterface = is_interface;
2974 // Returns the System.Type array for the parameters of this method
2976 public Type [] ParameterTypes {
2978 return parameter_types;
2982 public InternalParameters ParameterInfo
2985 return parameter_info;
2989 public Block Block {
2999 protected virtual bool DoDefineParameters ()
3001 // Check if arguments were correct
3002 parameter_types = Parameters.GetParameterInfo (Parent);
3003 if ((parameter_types == null) ||
3004 !CheckParameters (Parent, parameter_types))
3007 parameter_info = new InternalParameters (Parent, Parameters);
3009 Parameter array_param = Parameters.ArrayParameter;
3010 if ((array_param != null) &&
3011 (!array_param.ParameterType.IsArray ||
3012 (array_param.ParameterType.GetArrayRank () != 1))) {
3013 Report.Error (225, Location, "params parameter has to be a single dimensional array");
3020 public override string[] ValidAttributeTargets {
3022 return attribute_targets;
3026 protected override bool VerifyClsCompliance (DeclSpace ds)
3028 if (!base.VerifyClsCompliance (ds)) {
3029 if ((ModFlags & Modifiers.ABSTRACT) != 0 && IsExposedFromAssembly (ds) && ds.IsClsCompliaceRequired (ds)) {
3030 Report.Error_T (Message.CS3011_only_CLS_compliant_members_can_be_abstract, Location, GetSignatureForError ());
3035 if (Parameters.HasArglist) {
3036 Report.Error_T (Message.CS3000_Methods_with_variable_arguments_are_not_CLS_compliant, Location);
3039 AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);
3041 if (!AttributeTester.IsClsCompliant (MemberType)) {
3042 Report.Error_T (Message.CS3002_Return_type_of_is_not_CLS_compliant, Location, GetSignatureForError ());
3048 protected bool IsDuplicateImplementation (TypeContainer tc, MethodCore method)
3050 if ((method == this) || (method.Name != Name))
3053 Type[] param_types = method.ParameterTypes;
3054 if (param_types == null)
3057 if (param_types.Length != ParameterTypes.Length)
3060 for (int i = 0; i < param_types.Length; i++)
3061 if (param_types [i] != ParameterTypes [i])
3065 // Try to report 663: method only differs on out/ref
3067 ParameterData info = ParameterInfo;
3068 ParameterData other_info = method.ParameterInfo;
3069 for (int i = 0; i < info.Count; i++){
3070 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
3071 Report.Error (663, Location, "Overload method only differs in parameter modifier");
3076 Report.Error (111, Location, "Class `{0}' already defines a " +
3077 "member called `{1}' with the same parameter types",
3082 public CallingConventions GetCallingConvention (bool is_class)
3084 CallingConventions cc = 0;
3086 cc = Parameters.GetCallingConvention ();
3089 if ((ModFlags & Modifiers.STATIC) == 0)
3090 cc |= CallingConventions.HasThis;
3092 // FIXME: How is `ExplicitThis' used in C#?
3097 protected override void VerifyObsoleteAttribute()
3099 base.VerifyObsoleteAttribute ();
3101 if (parameter_types == null)
3104 foreach (Type type in parameter_types) {
3105 CheckUsageOfObsoleteAttribute (type);
3110 public class SourceMethod : ISourceMethod
3112 TypeContainer container;
3115 protected SourceMethod (TypeContainer container, MethodBase builder,
3116 ISourceFile file, Location start, Location end)
3118 this.container = container;
3119 this.builder = builder;
3121 CodeGen.SymbolWriter.OpenMethod (
3122 file, this, start.Row, 0, end.Row, 0);
3125 public string Name {
3126 get { return builder.Name; }
3129 public int NamespaceID {
3130 get { return container.NamespaceEntry.SymbolFileID; }
3135 if (builder is MethodBuilder)
3136 return ((MethodBuilder) builder).GetToken ().Token;
3137 else if (builder is ConstructorBuilder)
3138 return ((ConstructorBuilder) builder).GetToken ().Token;
3140 throw new NotSupportedException ();
3144 public void CloseMethod ()
3146 if (CodeGen.SymbolWriter != null)
3147 CodeGen.SymbolWriter.CloseMethod ();
3150 public static SourceMethod Create (TypeContainer parent,
3151 MethodBase builder, Block block)
3153 if (CodeGen.SymbolWriter == null)
3158 Location start_loc = block.StartLocation;
3159 if (Location.IsNull (start_loc))
3162 Location end_loc = block.EndLocation;
3163 if (Location.IsNull (end_loc))
3166 ISourceFile file = start_loc.SourceFile;
3170 return new SourceMethod (
3171 parent, builder, file, start_loc, end_loc);
3175 public class Method : MethodCore, IIteratorContainer, IMethodData {
3176 public MethodBuilder MethodBuilder;
3177 public MethodData MethodData;
3178 ReturnParameter return_attributes;
3181 /// Modifiers allowed in a class declaration
3183 const int AllowedModifiers =
3186 Modifiers.PROTECTED |
3187 Modifiers.INTERNAL |
3192 Modifiers.OVERRIDE |
3193 Modifiers.ABSTRACT |
3195 Modifiers.METHOD_YIELDS |
3198 const int AllowedInterfaceModifiers =
3199 Modifiers.NEW | Modifiers.UNSAFE;
3202 // return_type can be "null" for VOID values.
3204 public Method (TypeContainer ds, Expression return_type, int mod, bool is_iface,
3205 string name, Parameters parameters, Attributes attrs, Location l)
3206 : base (ds, return_type, mod,
3207 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
3208 is_iface, name, attrs, parameters, l)
3212 public override AttributeTargets AttributeTargets {
3214 return AttributeTargets.Method;
3219 // Returns the `System.Type' for the ReturnType of this
3220 // function. Provides a nice cache. (used between semantic analysis
3221 // and actual code generation
3223 public Type GetReturnType ()
3228 public override string GetSignatureForError()
3230 return TypeManager.CSharpSignature (MethodBuilder);
3234 /// Use this method when MethodBuilder is null
3236 public override string GetSignatureForError (TypeContainer tc)
3238 // TODO: move to parameters
3239 System.Text.StringBuilder args = new System.Text.StringBuilder ();
3240 if (parameter_info.Parameters.FixedParameters != null) {
3241 for (int i = 0; i < parameter_info.Parameters.FixedParameters.Length; ++i) {
3242 Parameter p = parameter_info.Parameters.FixedParameters [i];
3243 args.Append (p.GetSignatureForError ());
3245 if (i < parameter_info.Parameters.FixedParameters.Length - 1)
3250 return String.Concat (base.GetSignatureForError (tc), "(", args.ToString (), ")");
3253 void DuplicateEntryPoint (MethodInfo b, Location location)
3257 "Program `" + CodeGen.FileName +
3258 "' has more than one entry point defined: `" +
3259 TypeManager.CSharpSignature(b) + "'");
3262 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
3264 if (b.ReturnType != TypeManager.void_type &&
3265 b.ReturnType != TypeManager.int32_type)
3268 if (pinfo.Count == 0)
3271 if (pinfo.Count > 1)
3274 Type t = pinfo.ParameterType(0);
3276 (t.GetArrayRank() == 1) &&
3277 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
3278 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
3284 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3286 if (a.Target == AttributeTargets.ReturnValue) {
3287 if (return_attributes == null)
3288 return_attributes = new ReturnParameter (MethodBuilder, Location);
3290 return_attributes.ApplyAttributeBuilder (a, cb);
3294 if (a.Type == TypeManager.methodimpl_attr_type && a.IsInternalCall) {
3295 MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
3298 if (a.Type == TypeManager.dllimport_type) {
3299 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3300 if ((ModFlags & extern_static) != extern_static) {
3301 Report.Error_T (Message.CS0601_The_DllImport_attribute_must_be_specified_on_a_method_marked_static_and_extern, a.Location);
3307 if (a.Type == TypeManager.conditional_attribute_type) {
3308 if (IsOperator || IsExplicitImpl) {
3309 Report.Error_T (Message.CS0577_Conditional_not_valid_on_because_it_is_a_destructor, Location, GetSignatureForError ());
3313 if (ReturnType != TypeManager.void_type) {
3314 Report.Error_T (Message.CS0578_Conditional_not_valid_on_because_its_return_type_is_not_void, Location, GetSignatureForError ());
3318 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3319 Report.Error_T (Message.CS0243_Conditional_not_valid_on_because_it_is_an_override_method, Location, GetSignatureForError ());
3324 Report.Error_T (Message.CS0582_Conditional_not_valid_on_interface_members, Location);
3328 if (MethodData.IsImplementing) {
3329 Report.Error_T (Message.CS0629_Conditional_member_cannot_implement_interface_member, Location, GetSignatureForError ());
3334 MethodBuilder.SetCustomAttribute (cb);
3338 // Checks our base implementation if any
3340 protected override bool CheckBase ()
3344 // Check whether arguments were correct.
3345 if (!DoDefineParameters ())
3348 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
3350 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
3353 // Check in our class for dups
3355 ArrayList ar = Parent.Methods;
3357 int arLen = ar.Count;
3359 for (int i = 0; i < arLen; i++) {
3360 Method m = (Method) ar [i];
3361 if (IsDuplicateImplementation (Parent, m))
3369 // Verify if the parent has a type with the same name, and then
3370 // check whether we have to create a new slot for it or not.
3372 Type ptype = Parent.TypeBuilder.BaseType;
3374 // ptype is only null for System.Object while compiling corlib.
3375 if (ptype != null) {
3378 // Explicit implementations do not have `parent' methods, however,
3379 // the member cache stores them there. Without this check, we get
3380 // an incorrect warning in corlib.
3382 if (! IsExplicitImpl) {
3383 parent_method = (MethodInfo)((IMemberContainer)Parent).Parent.MemberCache.FindMemberToOverride (
3384 Parent.TypeBuilder, Name, ParameterTypes, false);
3387 if (parent_method != null) {
3388 string name = parent_method.DeclaringType.Name + "." +
3391 if (!CheckMethodAgainstBase (Parent, flags, parent_method, name))
3394 if ((ModFlags & Modifiers.NEW) == 0) {
3395 Type parent_ret = TypeManager.TypeToCoreType (
3396 parent_method.ReturnType);
3398 if (parent_ret != MemberType) {
3400 508, Location, Parent.MakeName (Name) + ": cannot " +
3401 "change return type when overriding " +
3402 "inherited member " + name);
3407 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (parent_method);
3409 Report.SymbolRelatedToPreviousError (parent_method);
3410 Report.Warning (Message.CS0672_Member_overrides_obsolete_member, Location, GetSignatureForError (Parent));
3413 if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
3414 WarningNotHiding (Parent);
3416 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3417 Report.Error (115, Location,
3418 Parent.MakeName (Name) +
3419 " no suitable methods found to override");
3422 } else if ((ModFlags & Modifiers.NEW) != 0)
3423 WarningNotHiding (Parent);
3431 public override bool Define ()
3439 MethodData = new MethodData (this, ParameterInfo, ModFlags, flags, this);
3441 if (!MethodData.Define (Parent))
3445 // Setup iterator if we are one
3447 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
3448 Iterator iterator = new Iterator (
3449 Parent, Name, MemberType, ParameterTypes,
3450 ParameterInfo, ModFlags, block, Location);
3452 if (!iterator.DefineIterator ())
3455 block = iterator.Block;
3458 MethodBuilder = MethodData.MethodBuilder;
3461 // This is used to track the Entry Point,
3463 if (Name == "Main" &&
3464 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
3465 (RootContext.MainClass == null ||
3466 RootContext.MainClass == Parent.TypeBuilder.FullName)){
3467 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
3468 if (RootContext.EntryPoint == null) {
3469 RootContext.EntryPoint = MethodBuilder;
3470 RootContext.EntryPointLocation = Location;
3472 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
3473 DuplicateEntryPoint (MethodBuilder, Location);
3477 Report.Warning (Message.CS0028_The_wrong_signature_to_be_an_entry_point, Location, TypeManager.CSharpSignature(MethodBuilder) );
3487 public override void Emit ()
3489 MethodData.Emit (Parent, this);
3495 void IIteratorContainer.SetYields ()
3497 ModFlags |= Modifiers.METHOD_YIELDS;
3500 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
3502 return IsIdentifierAndParamClsCompliant (ds, Name, MethodBuilder, parameter_types);
3505 #region IMethodData Members
3507 public CallingConventions CallingConventions {
3509 CallingConventions cc = Parameters.GetCallingConvention ();
3510 if (Parameters.HasArglist)
3511 block.HasVarargs = true;
3514 if ((ModFlags & Modifiers.STATIC) == 0)
3515 cc |= CallingConventions.HasThis;
3517 // FIXME: How is `ExplicitThis' used in C#?
3523 public Type ReturnType {
3529 public string MethodName {
3535 public new Location Location {
3537 return base.Location;
3541 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
3543 return new EmitContext (
3544 tc, Parent, Location, ig, ReturnType, ModFlags, false);
3547 public ObsoleteAttribute GetObsoleteAttribute ()
3549 return GetObsoleteAttribute (Parent);
3553 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
3555 public bool IsExcluded (EmitContext ec)
3557 if ((caching_flags & Flags.Excluded_Undetected) == 0)
3558 return (caching_flags & Flags.Excluded) != 0;
3560 caching_flags &= ~Flags.Excluded_Undetected;
3562 if (parent_method == null) {
3563 if (OptAttributes == null)
3566 Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type, ec);
3571 foreach (Attribute a in attrs) {
3572 string condition = a.GetConditionalAttributeValue (
3574 if (RootContext.AllDefines.Contains (condition))
3578 caching_flags |= Flags.Excluded;
3582 IMethodData md = TypeManager.GetMethod (parent_method);
3584 if (AttributeTester.IsConditionalMethodExcluded (parent_method)) {
3585 caching_flags |= Flags.Excluded;
3591 if (md.IsExcluded (ec)) {
3592 caching_flags |= Flags.Excluded;
3601 public abstract class ConstructorInitializer {
3602 ArrayList argument_list;
3603 protected ConstructorInfo parent_constructor;
3604 Parameters parameters;
3607 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
3610 this.argument_list = argument_list;
3611 this.parameters = parameters;
3615 public ArrayList Arguments {
3617 return argument_list;
3621 public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
3623 Expression parent_constructor_group;
3626 ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
3628 if (argument_list != null){
3629 foreach (Argument a in argument_list){
3630 if (!a.Resolve (ec, loc))
3634 ec.CurrentBlock = null;
3636 if (this is ConstructorBaseInitializer) {
3637 if (ec.ContainerType.BaseType == null)
3640 t = ec.ContainerType.BaseType;
3641 if (ec.ContainerType.IsValueType) {
3642 Report.Error (522, loc,
3643 "structs cannot call base class constructors");
3647 t = ec.ContainerType;
3649 parent_constructor_group = Expression.MemberLookup (
3650 ec, t, ".ctor", MemberTypes.Constructor,
3651 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3654 if (parent_constructor_group == null){
3655 parent_constructor_group = Expression.MemberLookup (
3656 ec, t, ".ctor", MemberTypes.Constructor,
3657 BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3660 if (parent_constructor_group != null)
3662 112, loc, "`{0}.{1}' is inaccessible due to " +
3663 "its protection level", t.FullName, t.Name);
3666 1501, loc, "Can not find a constructor for " +
3667 "this argument list");
3671 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
3672 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
3674 if (parent_constructor == null){
3675 Report.Error (1501, loc,
3676 "Can not find a constructor for this argument list");
3680 if (parent_constructor == caller_builder){
3681 Report.Error (515, String.Format ("Constructor `{0}' can not call itself", TypeManager.CSharpSignature (caller_builder)));
3688 public void Emit (EmitContext ec)
3690 if (parent_constructor != null){
3691 ec.Mark (loc, false);
3693 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
3695 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
3700 /// Method search for base ctor. (We do not cache it).
3702 Constructor GetOverloadedConstructor (TypeContainer tc)
3704 if (tc.InstanceConstructors == null)
3707 foreach (Constructor c in tc.InstanceConstructors) {
3708 if (Arguments == null) {
3709 if (c.ParameterTypes.Length == 0)
3717 int count = c.ParameterInfo.Count;
3719 c.ParameterInfo.ParameterModifier (count - 1) == Parameter.Modifier.PARAMS) {
3720 for (int i = 0; i < count-1; i++)
3721 if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
3726 if (c.ParameterTypes.Length != Arguments.Count)
3729 for (int i = 0; i < Arguments.Count; ++i)
3730 if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
3745 //TODO: implement caching when it will be necessary
3746 public virtual void CheckObsoleteAttribute (TypeContainer tc, Location loc)
3748 Constructor ctor = GetOverloadedConstructor (tc);
3752 ObsoleteAttribute oa = ctor.GetObsoleteAttribute (tc);
3756 AttributeTester.Report_ObsoleteMessage (oa, ctor.GetSignatureForError (), loc);
3760 public class ConstructorBaseInitializer : ConstructorInitializer {
3761 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
3762 base (argument_list, pars, l)
3766 public override void CheckObsoleteAttribute(TypeContainer tc, Location loc) {
3767 if (parent_constructor == null)
3770 TypeContainer type_ds = TypeManager.LookupTypeContainer (tc.base_class_type);
3771 if (type_ds == null) {
3772 ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (parent_constructor);
3775 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (parent_constructor), loc);
3780 base.CheckObsoleteAttribute (type_ds, loc);
3785 public class ConstructorThisInitializer : ConstructorInitializer {
3786 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
3787 base (argument_list, pars, l)
3792 public class Constructor : MethodCore {
3793 public ConstructorBuilder ConstructorBuilder;
3794 public ConstructorInitializer Initializer;
3797 // Modifiers allowed for a constructor.
3799 public const int AllowedModifiers =
3801 Modifiers.PROTECTED |
3802 Modifiers.INTERNAL |
3808 bool has_compliant_args = false;
3810 // The spec claims that static is not permitted, but
3811 // my very own code has static constructors.
3813 public Constructor (TypeContainer ds, string name, int mod, Parameters args,
3814 ConstructorInitializer init, Location l)
3815 : base (ds, null, mod, AllowedModifiers, false, name, null, args, l)
3820 public override string GetSignatureForError()
3822 return TypeManager.CSharpSignature (ConstructorBuilder);
3825 public bool HasCompliantArgs {
3827 return has_compliant_args;
3831 public override AttributeTargets AttributeTargets {
3833 return AttributeTargets.Constructor;
3839 // Returns true if this is a default constructor
3841 public bool IsDefault ()
3843 if ((ModFlags & Modifiers.STATIC) != 0)
3844 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3845 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
3848 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3849 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
3850 (Initializer is ConstructorBaseInitializer) &&
3851 (Initializer.Arguments == null);
3854 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3856 ConstructorBuilder.SetCustomAttribute (cb);
3859 protected override bool CheckBase ()
3863 // Check whether arguments were correct.
3864 if (!DoDefineParameters ())
3867 if ((ModFlags & Modifiers.STATIC) != 0)
3870 if (Parent.Kind == Kind.Struct && ParameterTypes.Length == 0) {
3871 Report.Error (568, Location,
3872 "Structs can not contain explicit parameterless " +
3878 // Check in our class for dups
3880 ArrayList ar = Parent.InstanceConstructors;
3882 int arLen = ar.Count;
3884 for (int i = 0; i < arLen; i++) {
3885 Constructor m = (Constructor) ar [i];
3886 if (IsDuplicateImplementation (Parent, m))
3895 // Creates the ConstructorBuilder
3897 public override bool Define ()
3899 MethodAttributes ca = (MethodAttributes.RTSpecialName |
3900 MethodAttributes.SpecialName);
3902 if ((ModFlags & Modifiers.STATIC) != 0) {
3903 ca |= MethodAttributes.Static | MethodAttributes.Private;
3905 ca |= MethodAttributes.HideBySig;
3907 if ((ModFlags & Modifiers.PUBLIC) != 0)
3908 ca |= MethodAttributes.Public;
3909 else if ((ModFlags & Modifiers.PROTECTED) != 0){
3910 if ((ModFlags & Modifiers.INTERNAL) != 0)
3911 ca |= MethodAttributes.FamORAssem;
3913 ca |= MethodAttributes.Family;
3914 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
3915 ca |= MethodAttributes.Assembly;
3916 else if (IsDefault ())
3917 ca |= MethodAttributes.Public;
3919 ca |= MethodAttributes.Private;
3922 // Check if arguments were correct.
3926 ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
3927 ca, GetCallingConvention (Parent.Kind == Kind.Class),
3930 if ((ModFlags & Modifiers.UNSAFE) != 0)
3931 ConstructorBuilder.InitLocals = false;
3934 // HACK because System.Reflection.Emit is lame
3936 TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
3944 public override void Emit ()
3946 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
3947 EmitContext ec = new EmitContext (Parent, Location, ig, null, ModFlags, true);
3950 // extern methods have no bodies
3952 if ((ModFlags & Modifiers.EXTERN) != 0) {
3953 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
3955 179, Location, "External constructor `" +
3956 TypeManager.CSharpSignature (ConstructorBuilder) +
3957 "' can not have a body");
3960 } else if (block == null) {
3962 501, Location, "Constructor `" +
3963 TypeManager.CSharpSignature (ConstructorBuilder) +
3964 "' must declare a body since it is not marked extern");
3968 if ((ModFlags & Modifiers.STATIC) == 0){
3969 if (Parent.Kind == Kind.Class && Initializer == null)
3970 Initializer = new ConstructorBaseInitializer (
3971 null, Parameters.EmptyReadOnlyParameters, Location);
3975 // Spec mandates that Initializers will not have
3979 if (Initializer != null && !Initializer.Resolve (ConstructorBuilder, ec))
3981 ec.IsStatic = false;
3984 Parameters.LabelParameters (ec, ConstructorBuilder, Location);
3986 SourceMethod source = SourceMethod.Create (
3987 Parent, ConstructorBuilder, block);
3990 // Classes can have base initializers and instance field initializers.
3992 if (Parent.Kind == Kind.Class){
3993 if ((ModFlags & Modifiers.STATIC) == 0){
3996 // If we use a "this (...)" constructor initializer, then
3997 // do not emit field initializers, they are initialized in the other constructor
3999 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
4000 Parent.EmitFieldInitializers (ec);
4003 if (Initializer != null) {
4004 Initializer.CheckObsoleteAttribute (Parent, Location);
4005 Initializer.Emit (ec);
4008 if ((ModFlags & Modifiers.STATIC) != 0)
4009 Parent.EmitFieldInitializers (ec);
4011 if (OptAttributes != null)
4012 OptAttributes.Emit (ec, this);
4014 // If this is a non-static `struct' constructor and doesn't have any
4015 // initializer, it must initialize all of the struct's fields.
4016 if ((Parent.Kind == Kind.Struct) &&
4017 ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
4018 Block.AddThisVariable (Parent, Location);
4020 ec.EmitTopBlock (block, ParameterInfo, Location);
4023 source.CloseMethod ();
4030 // For constructors is needed to test only parameters
4031 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
4033 if (parameter_types == null || parameter_types.Length == 0)
4036 TypeContainer tc = ds as TypeContainer;
4038 for (int i = 0; i < tc.InstanceConstructors.Count; i++) {
4039 Constructor c = (Constructor) tc.InstanceConstructors [i];
4041 if (c == this || c.ParameterTypes.Length == 0)
4044 if (!c.IsClsCompliaceRequired (ds))
4047 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, c.ParameterTypes)) {
4048 Report.Error_T (Message.CS3006_Overloaded_method_differing_only_in_ref_or_out_or_in_array_rank_is_not_CLS_compliant, Location, GetSignatureForError ());
4053 if (tc.TypeBuilder.BaseType == null)
4056 DeclSpace temp_ds = TypeManager.LookupDeclSpace (tc.TypeBuilder.BaseType);
4057 if (temp_ds != null)
4058 return IsIdentifierClsCompliant (temp_ds);
4060 MemberInfo[] ml = tc.TypeBuilder.BaseType.FindMembers (MemberTypes.Constructor, BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance, null, null);
4061 // Skip parameter-less ctor
4065 foreach (ConstructorInfo ci in ml) {
4066 object[] cls_attribute = ci.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
4067 if (cls_attribute.Length == 1 && (!((CLSCompliantAttribute)cls_attribute[0]).IsCompliant))
4070 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, TypeManager.GetArgumentTypes (ci))) {
4071 Report.Error_T (Message.CS3006_Overloaded_method_differing_only_in_ref_or_out_or_in_array_rank_is_not_CLS_compliant, Location, GetSignatureForError ());
4079 protected override bool VerifyClsCompliance (DeclSpace ds)
4081 if (!base.VerifyClsCompliance (ds) || !IsExposedFromAssembly (ds)) {
4085 if (ds.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
4086 foreach (Type param in parameter_types) {
4087 if (param.IsArray) {
4092 has_compliant_args = true;
4099 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
4101 public interface IMethodData
4103 CallingConventions CallingConventions { get; }
4104 Location Location { get; }
4105 string MethodName { get; }
4106 Type[] ParameterTypes { get; }
4107 Type ReturnType { get; }
4109 Attributes OptAttributes { get; }
4110 Block Block { get; }
4112 EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig);
4113 ObsoleteAttribute GetObsoleteAttribute ();
4114 string GetSignatureForError (TypeContainer tc);
4115 bool IsExcluded (EmitContext ec);
4119 // Encapsulates most of the Method's state
4121 public class MethodData {
4123 readonly IMethodData method;
4126 // The return type of this method
4128 public readonly InternalParameters ParameterInfo;
4131 // Are we implementing an interface ?
4133 public bool IsImplementing = false;
4138 protected MemberBase member;
4139 protected int modifiers;
4140 protected MethodAttributes flags;
4142 MethodBuilder builder = null;
4143 public MethodBuilder MethodBuilder {
4149 public MethodData (MemberBase member, InternalParameters parameters,
4150 int modifiers, MethodAttributes flags, IMethodData method)
4152 this.member = member;
4153 this.ParameterInfo = parameters;
4154 this.modifiers = modifiers;
4157 this.method = method;
4160 public bool Define (TypeContainer container)
4162 MethodInfo implementing = null;
4165 if (member.IsExplicitImpl)
4166 prefix = member.InterfaceType.FullName + ".";
4170 string name = method.MethodName;
4171 string method_name = prefix + name;
4172 Type[] ParameterTypes = method.ParameterTypes;
4174 if (container.Pending != null){
4175 if (member is Indexer)
4176 implementing = container.Pending.IsInterfaceIndexer (
4177 member.InterfaceType, method.ReturnType, ParameterTypes);
4179 implementing = container.Pending.IsInterfaceMethod (
4180 member.InterfaceType, name, method.ReturnType, ParameterTypes);
4182 if (member.InterfaceType != null && implementing == null){
4183 Report.Error (539, method.Location, "'{0}' in explicit interface declaration is not an interface", method_name);
4189 // For implicit implementations, make sure we are public, for
4190 // explicit implementations, make sure we are private.
4192 if (implementing != null){
4194 // Setting null inside this block will trigger a more
4195 // verbose error reporting for missing interface implementations
4197 // The "candidate" function has been flagged already
4198 // but it wont get cleared
4200 if (member.IsExplicitImpl){
4201 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
4202 Modifiers.Error_InvalidModifier (method.Location, "public, virtual or abstract");
4203 implementing = null;
4205 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
4206 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
4208 // If this is an interface method implementation,
4209 // check for public accessibility
4211 implementing = null;
4212 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
4213 // We may never be private.
4214 implementing = null;
4215 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
4217 // We may be protected if we're overriding something.
4219 implementing = null;
4224 // Static is not allowed
4226 if ((modifiers & Modifiers.STATIC) != 0){
4227 implementing = null;
4228 Modifiers.Error_InvalidModifier (method.Location, "static");
4233 // If implementing is still valid, set flags
4235 if (implementing != null){
4237 // When implementing interface methods, set NewSlot
4238 // unless, we are overwriting a method.
4240 if (implementing.DeclaringType.IsInterface){
4241 if ((modifiers & Modifiers.OVERRIDE) == 0)
4242 flags |= MethodAttributes.NewSlot;
4245 MethodAttributes.Virtual |
4246 MethodAttributes.HideBySig;
4248 // Set Final unless we're virtual, abstract or already overriding a method.
4249 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
4250 flags |= MethodAttributes.Final;
4252 // Get the method name from the explicit interface.
4253 if (member.InterfaceType != null) {
4254 name = implementing.Name;
4255 method_name = prefix + name;
4258 IsImplementing = true;
4261 EmitContext ec = method.CreateEmitContext (container, null);
4263 DefineMethodBuilder (ec, container, method_name, ParameterTypes);
4265 if (builder == null)
4268 if ((modifiers & Modifiers.UNSAFE) != 0)
4269 builder.InitLocals = false;
4271 if (IsImplementing){
4273 // clear the pending implemntation flag
4275 if (member is Indexer) {
4276 container.Pending.ImplementIndexer (
4277 member.InterfaceType, builder, method.ReturnType,
4278 ParameterTypes, true);
4280 container.Pending.ImplementMethod (
4281 member.InterfaceType, name, method.ReturnType,
4282 ParameterTypes, member.IsExplicitImpl);
4284 if (member.IsExplicitImpl)
4285 container.TypeBuilder.DefineMethodOverride (
4286 builder, implementing);
4290 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
4291 Report.Error (111, method.Location,
4292 "Class `" + container.Name +
4293 "' already contains a definition with the " +
4294 "same return value and parameter types as the " +
4295 "'get' method of property `" + member.Name + "'");
4299 TypeManager.AddMethod (builder, method);
4306 /// Create the MethodBuilder for the method
4308 void DefineMethodBuilder (EmitContext ec, TypeContainer container, string method_name, Type[] ParameterTypes)
4310 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
4312 if ((modifiers & extern_static) == extern_static) {
4314 if (method.OptAttributes != null) {
4315 Attribute dllimport_attribute = method.OptAttributes.Search (TypeManager.dllimport_type, ec);
4316 if (dllimport_attribute != null) {
4317 flags |= MethodAttributes.PinvokeImpl;
4318 builder = dllimport_attribute.DefinePInvokeMethod (
4319 ec, container.TypeBuilder, method_name, flags,
4320 method.ReturnType, ParameterTypes);
4326 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
4327 // We are more strict than Microsoft and report CS0626 like error
4328 if (method.OptAttributes == null ||
4329 !method.OptAttributes.Contains (TypeManager.methodimpl_attr_type, ec)) {
4330 Report.Error_T (Message.CS0626_Method_operator_or_accessor_is_marked_external_and_has_no_attributes_on_it, method.Location, method.GetSignatureForError (container));
4335 builder = container.TypeBuilder.DefineMethod (
4336 method_name, flags, method.CallingConventions,
4337 method.ReturnType, ParameterTypes);
4343 public void Emit (TypeContainer container, Attributable kind)
4346 if ((flags & MethodAttributes.PinvokeImpl) == 0)
4347 ec = method.CreateEmitContext (container, builder.GetILGenerator ());
4349 ec = method.CreateEmitContext (container, null);
4351 Location loc = method.Location;
4352 Attributes OptAttributes = method.OptAttributes;
4354 if (OptAttributes != null)
4355 OptAttributes.Emit (ec, kind);
4357 if (member is MethodCore)
4358 ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, loc);
4360 Block block = method.Block;
4363 // abstract or extern methods have no bodies
4365 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
4370 // abstract or extern methods have no bodies.
4372 if ((modifiers & Modifiers.ABSTRACT) != 0)
4374 500, method.Location, "Abstract method `" +
4375 TypeManager.CSharpSignature (builder) +
4376 "' can not have a body");
4378 if ((modifiers & Modifiers.EXTERN) != 0)
4380 179, method.Location, "External method `" +
4381 TypeManager.CSharpSignature (builder) +
4382 "' can not have a body");
4388 // Methods must have a body unless they're extern or abstract
4390 if (block == null) {
4392 501, method.Location, "Method `" +
4393 TypeManager.CSharpSignature (builder) +
4394 "' must declare a body since it is not marked " +
4395 "abstract or extern");
4399 SourceMethod source = SourceMethod.Create (
4400 container, MethodBuilder, method.Block);
4403 // Handle destructors specially
4405 // FIXME: This code generates buggy code
4407 if (member is Destructor)
4408 EmitDestructor (ec, block);
4410 ec.EmitTopBlock (block, ParameterInfo, loc);
4413 source.CloseMethod ();
4416 void EmitDestructor (EmitContext ec, Block block)
4418 ILGenerator ig = ec.ig;
4420 Label finish = ig.DefineLabel ();
4422 block.SetDestructor ();
4424 ig.BeginExceptionBlock ();
4425 ec.ReturnLabel = finish;
4426 ec.HasReturnLabel = true;
4427 ec.EmitTopBlock (block, null, method.Location);
4429 // ig.MarkLabel (finish);
4430 ig.BeginFinallyBlock ();
4432 if (ec.ContainerType.BaseType != null) {
4433 Expression member_lookup = Expression.MemberLookup (
4434 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
4435 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
4437 if (member_lookup != null){
4438 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
4440 ig.Emit (OpCodes.Ldarg_0);
4441 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
4445 ig.EndExceptionBlock ();
4446 //ig.MarkLabel (ec.ReturnLabel);
4447 ig.Emit (OpCodes.Ret);
4451 public class Destructor : Method {
4453 public Destructor (TypeContainer ds, Expression return_type, int mod, string name,
4454 Parameters parameters, Attributes attrs, Location l)
4455 : base (ds, return_type, mod, false, name, parameters, attrs, l)
4458 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
4460 if (a.Type == TypeManager.conditional_attribute_type) {
4461 Report.Error_T (Message.CS0577_Conditional_not_valid_on_because_it_is_a_destructor, Location, GetSignatureForError ());
4465 base.ApplyAttributeBuilder (a, cb);
4469 abstract public class MemberBase : MemberCore {
4470 public Expression Type;
4472 public MethodAttributes flags;
4474 protected readonly int explicit_mod_flags;
4477 // The "short" name of this property / indexer / event. This is the
4478 // name without the explicit interface.
4480 public string ShortName;
4483 // The type of this property / indexer / event
4485 public Type MemberType;
4488 // If true, this is an explicit interface implementation
4490 public bool IsExplicitImpl = false;
4493 // The name of the interface we are explicitly implementing
4495 public string ExplicitInterfaceName = null;
4498 // Whether this is an interface member.
4500 public bool IsInterface;
4503 // If true, the interface type we are explicitly implementing
4505 public Type InterfaceType = null;
4508 // The method we're overriding if this is an override method.
4510 protected MethodInfo parent_method = null;
4511 public MethodInfo ParentMethod {
4513 return parent_method;
4518 // The constructor is only exposed to our children
4520 protected MemberBase (TypeContainer parent, Expression type, int mod,
4521 int allowed_mod, int def_mod, string name,
4522 Attributes attrs, Location loc)
4523 : base (parent, name, attrs, loc)
4525 explicit_mod_flags = mod;
4527 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
4530 protected virtual bool CheckBase ()
4532 if ((Parent.Kind == Kind.Struct) || (RootContext.WarningLevel > 3)){
4533 if ((ModFlags & Modifiers.PROTECTED) != 0 && (Parent.ModFlags & Modifiers.SEALED) != 0){
4534 if (Parent.Kind == Kind.Struct){
4535 Report.Error (666, Location, "Protected member in struct declaration");
4538 Report.Warning (Message.CS0628_New_protected_member_declared_in_sealed_class, Location, GetSignatureForError (Parent));
4544 protected void WarningNotHiding (TypeContainer parent)
4548 "The member " + parent.MakeName (Name) + " does not hide an " +
4549 "inherited member. The keyword new is not required");
4553 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
4557 // FIXME: report the old/new permissions?
4560 507, Location, parent.MakeName (Name) +
4561 ": can't change the access modifiers when overriding inherited " +
4562 "member `" + name + "'");
4566 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
4567 // that have been defined.
4569 // `name' is the user visible name for reporting errors (this is used to
4570 // provide the right name regarding method names and properties)
4572 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
4573 MethodInfo mb, string name)
4577 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4578 if (!(mb.IsAbstract || mb.IsVirtual)){
4580 506, Location, parent.MakeName (Name) +
4581 ": cannot override inherited member `" +
4582 name + "' because it is not " +
4583 "virtual, abstract or override");
4587 // Now we check that the overriden method is not final
4590 // This happens when implementing interface methods.
4591 if (mb.IsHideBySig && mb.IsVirtual) {
4593 506, Location, parent.MakeName (Name) +
4594 ": cannot override inherited member `" +
4595 name + "' because it is not " +
4596 "virtual, abstract or override");
4598 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
4599 "override inherited member `" + name +
4600 "' because it is sealed.");
4604 // Check that the permissions are not being changed
4606 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
4607 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
4610 // special case for "protected internal"
4613 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4615 // when overriding protected internal, the method can be declared
4616 // protected internal only within the same assembly
4619 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4620 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
4622 // assemblies differ - report an error
4625 Error_CannotChangeAccessModifiers (parent, mb, name);
4627 } else if (thisp != parentp) {
4629 // same assembly, but other attributes differ - report an error
4632 Error_CannotChangeAccessModifiers (parent, mb, name);
4635 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
4637 // if it's not "protected internal", it must be "protected"
4640 Error_CannotChangeAccessModifiers (parent, mb, name);
4642 } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
4644 // protected within the same assembly - an error
4646 Error_CannotChangeAccessModifiers (parent, mb, name);
4648 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
4649 (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
4651 // protected ok, but other attributes differ - report an error
4653 Error_CannotChangeAccessModifiers (parent, mb, name);
4657 if (thisp != parentp){
4658 Error_CannotChangeAccessModifiers (parent, mb, name);
4664 if (mb.IsVirtual || mb.IsAbstract){
4665 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4666 if (Name != "Finalize"){
4667 Report.SymbolRelatedToPreviousError (mb);
4668 Report.Warning (Message.CS0114_Hides_inherited_member, Location, GetSignatureForError (parent), TypeManager.CSharpSignature (mb));
4669 ModFlags |= Modifiers.NEW;
4673 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4674 if (Name != "Finalize"){
4675 Report.SymbolRelatedToPreviousError (mb);
4676 Report.Warning (Message.CS0108_The_keyword_new_is_required, Location, GetSignatureForError (parent), TypeManager.CSharpSignature (mb));
4677 ModFlags |= Modifiers.NEW;
4685 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
4689 foreach (Type partype in parameters){
4690 if (partype == TypeManager.void_type) {
4692 1547, Location, "Keyword 'void' cannot " +
4693 "be used in this context");
4697 if (partype.IsPointer){
4700 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
4704 if (ds.AsAccessible (partype, ModFlags))
4707 if (this is Indexer)
4708 Report.Error (55, Location,
4709 "Inconsistent accessibility: parameter type `" +
4710 TypeManager.CSharpName (partype) + "' is less " +
4711 "accessible than indexer `" + Name + "'");
4712 else if ((this is Method) && ((Method) this).IsOperator)
4713 Report.Error (57, Location,
4714 "Inconsistent accessibility: parameter type `" +
4715 TypeManager.CSharpName (partype) + "' is less " +
4716 "accessible than operator `" + Name + "'");
4718 Report.Error (51, Location,
4719 "Inconsistent accessibility: parameter type `" +
4720 TypeManager.CSharpName (partype) + "' is less " +
4721 "accessible than method `" + Name + "'");
4728 protected virtual bool DoDefine ()
4734 ModFlags = Modifiers.PUBLIC |
4735 Modifiers.ABSTRACT |
4736 Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE);
4738 flags = MethodAttributes.Public |
4739 MethodAttributes.Abstract |
4740 MethodAttributes.HideBySig |
4741 MethodAttributes.NewSlot |
4742 MethodAttributes.Virtual;
4744 if (!Parent.MethodModifiersValid (ModFlags, Name, Location))
4747 flags = Modifiers.MethodAttr (ModFlags);
4750 // Lookup Type, verify validity
4751 MemberType = Parent.ResolveType (Type, false, Location);
4752 if (MemberType == null)
4755 if ((Parent.ModFlags & Modifiers.SEALED) != 0){
4756 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
4757 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
4762 // verify accessibility
4763 if (!Parent.AsAccessible (MemberType, ModFlags)) {
4764 if (this is Property)
4765 Report.Error (53, Location,
4766 "Inconsistent accessibility: property type `" +
4767 TypeManager.CSharpName (MemberType) + "' is less " +
4768 "accessible than property `" + Name + "'");
4769 else if (this is Indexer)
4770 Report.Error (54, Location,
4771 "Inconsistent accessibility: indexer return type `" +
4772 TypeManager.CSharpName (MemberType) + "' is less " +
4773 "accessible than indexer `" + Name + "'");
4774 else if (this is Method) {
4775 if (((Method) this).IsOperator)
4776 Report.Error (56, Location,
4777 "Inconsistent accessibility: return type `" +
4778 TypeManager.CSharpName (MemberType) + "' is less " +
4779 "accessible than operator `" + Name + "'");
4781 Report.Error (50, Location,
4782 "Inconsistent accessibility: return type `" +
4783 TypeManager.CSharpName (MemberType) + "' is less " +
4784 "accessible than method `" + Name + "'");
4786 Report.Error (52, Location,
4787 "Inconsistent accessibility: field type `" +
4788 TypeManager.CSharpName (MemberType) + "' is less " +
4789 "accessible than field `" + Name + "'");
4793 if (MemberType.IsPointer && !UnsafeOK (Parent))
4797 // Check for explicit interface implementation
4799 if ((ExplicitInterfaceName == null) && (Name.IndexOf ('.') != -1)){
4800 int pos = Name.LastIndexOf ('.');
4802 ExplicitInterfaceName = Name.Substring (0, pos);
4803 ShortName = Name.Substring (pos + 1);
4807 if (ExplicitInterfaceName != null) {
4808 int errors = Report.Errors;
4810 InterfaceType = Parent.FindType (
4811 Location, ExplicitInterfaceName);
4813 if (Report.Errors != errors)
4815 else if (InterfaceType == null) {
4816 Report.Error (246, Location, "Can not find type `{0}'",
4817 ExplicitInterfaceName);
4821 if (InterfaceType == null)
4824 if (InterfaceType.IsClass) {
4825 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
4829 // Compute the full name that we need to export.
4830 Name = InterfaceType.FullName + "." + ShortName;
4832 if (!Parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
4835 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
4837 IsExplicitImpl = true;
4839 IsExplicitImpl = false;
4845 /// Use this method when MethodBuilder is null
4847 public virtual string GetSignatureForError (TypeContainer tc)
4849 return String.Concat (tc.Name, '.', Name);
4852 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
4854 return IsIdentifierAndParamClsCompliant (ds, Name, null, null);
4857 protected override bool VerifyClsCompliance(DeclSpace ds)
4859 if (base.VerifyClsCompliance (ds)) {
4863 if (IsInterface && HasClsCompliantAttribute && ds.IsClsCompliaceRequired (ds)) {
4864 Report.Error_T (Message.CS3010_CLS_compliant_interfaces_must_have_only_CLScompliant_members, Location, GetSignatureForError ());
4869 protected override void VerifyObsoleteAttribute()
4871 CheckUsageOfObsoleteAttribute (MemberType);
4876 // Fields and Events both generate FieldBuilders, we use this to share
4877 // their common bits. This is also used to flag usage of the field
4879 abstract public class FieldBase : MemberBase {
4880 public FieldBuilder FieldBuilder;
4881 public Status status;
4884 public enum Status : byte { ASSIGNED = 1, USED = 2 }
4886 static string[] attribute_targets = new string [] { "field" };
4889 // The constructor is only exposed to our children
4891 protected FieldBase (TypeContainer parent, Expression type, int mod,
4892 int allowed_mod, string name, object init,
4893 Attributes attrs, Location loc)
4894 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE,
4900 public override AttributeTargets AttributeTargets {
4902 return AttributeTargets.Field;
4906 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4908 if (a.Type == TypeManager.marshal_as_attr_type) {
4909 UnmanagedMarshal marshal = a.GetMarshal ();
4910 if (marshal != null) {
4911 FieldBuilder.SetMarshal (marshal);
4914 Report.Warning (Message.CS_24_The_Microsoft_Runtime_cannot_set_this_marshal_info, a.Location);
4919 FieldBuilder.SetCustomAttribute (cb);
4923 // Whether this field has an initializer.
4925 public bool HasInitializer {
4927 return init != null;
4931 protected readonly Object init;
4933 Expression init_expr;
4934 bool init_expr_initialized = false;
4937 // Resolves and returns the field initializer.
4939 public Expression GetInitializerExpression (EmitContext ec)
4941 if (init_expr_initialized)
4945 if (init is Expression)
4946 e = (Expression) init;
4948 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
4950 ec.IsFieldInitializer = true;
4951 e = e.DoResolve (ec);
4952 ec.IsFieldInitializer = false;
4955 init_expr_initialized = true;
4960 protected override bool DoDefine ()
4962 if (!base.DoDefine ())
4965 if (MemberType == TypeManager.void_type) {
4966 Report.Error (1547, Location,
4967 "Keyword 'void' cannot be used in this context");
4971 if (MemberType == TypeManager.arg_iterator_type || MemberType == TypeManager.typed_reference_type) {
4972 Report.Error_T (Message.CS0610_Field_or_property_cannot_be_of_type, Location, TypeManager.CSharpName (MemberType));
4979 public override string GetSignatureForError ()
4981 return TypeManager.GetFullNameSignature (FieldBuilder);
4984 public override string[] ValidAttributeTargets {
4986 return attribute_targets;
4990 protected override bool VerifyClsCompliance (DeclSpace ds)
4992 if (!base.VerifyClsCompliance (ds))
4995 if (FieldBuilder == null) {
4999 if (!AttributeTester.IsClsCompliant (FieldBuilder.FieldType)) {
5000 Report.Error_T (Message.CS3003_Type_is_not_CLS_compliant, Location, GetSignatureForError ());
5006 public void SetAssigned ()
5008 status |= Status.ASSIGNED;
5013 // The Field class is used to represents class/struct fields during parsing.
5015 public class Field : FieldBase {
5017 // Modifiers allowed in a class declaration
5019 const int AllowedModifiers =
5022 Modifiers.PROTECTED |
5023 Modifiers.INTERNAL |
5026 Modifiers.VOLATILE |
5030 public Field (TypeContainer parent, Expression type, int mod, string name,
5031 Object expr_or_array_init, Attributes attrs, Location loc)
5032 : base (parent, type, mod, AllowedModifiers, name, expr_or_array_init,
5037 public override bool Define ()
5039 MemberType = Parent.ResolveType (Type, false, Location);
5041 if (MemberType == null)
5046 if (!Parent.AsAccessible (MemberType, ModFlags)) {
5047 Report.Error (52, Location,
5048 "Inconsistent accessibility: field type `" +
5049 TypeManager.CSharpName (MemberType) + "' is less " +
5050 "accessible than field `" + Name + "'");
5054 if (MemberType.IsPointer && !UnsafeOK (Parent))
5057 if (RootContext.WarningLevel > 1){
5058 Type ptype = Parent.TypeBuilder.BaseType;
5060 // ptype is only null for System.Object while compiling corlib.
5062 TypeContainer.FindMembers (
5063 ptype, MemberTypes.Method,
5064 BindingFlags.Public |
5065 BindingFlags.Static | BindingFlags.Instance,
5066 System.Type.FilterName, Name);
5070 if ((ModFlags & Modifiers.VOLATILE) != 0){
5071 if (!MemberType.IsClass){
5072 Type vt = MemberType;
5074 if (TypeManager.IsEnumType (vt))
5075 vt = TypeManager.EnumToUnderlying (MemberType);
5077 if (!((vt == TypeManager.bool_type) ||
5078 (vt == TypeManager.sbyte_type) ||
5079 (vt == TypeManager.byte_type) ||
5080 (vt == TypeManager.short_type) ||
5081 (vt == TypeManager.ushort_type) ||
5082 (vt == TypeManager.int32_type) ||
5083 (vt == TypeManager.uint32_type) ||
5084 (vt == TypeManager.char_type) ||
5085 (vt == TypeManager.float_type) ||
5086 (!vt.IsValueType))){
5088 677, Location, Parent.MakeName (Name) +
5089 " A volatile field can not be of type `" +
5090 TypeManager.CSharpName (vt) + "'");
5095 if ((ModFlags & Modifiers.READONLY) != 0){
5098 "A field can not be both volatile and readonly");
5103 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
5105 if (Parent.Kind == Kind.Struct &&
5106 ((fa & FieldAttributes.Static) == 0) &&
5107 MemberType == Parent.TypeBuilder &&
5108 !TypeManager.IsBuiltinType (MemberType)){
5109 Report.Error (523, Location, "Struct member `" + Parent.Name + "." + Name +
5110 "' causes a cycle in the structure layout");
5115 FieldBuilder = Parent.TypeBuilder.DefineField (
5116 Name, MemberType, Modifiers.FieldAttr (ModFlags));
5118 TypeManager.RegisterFieldBase (FieldBuilder, this);
5120 catch (ArgumentException) {
5121 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
5128 public override void Emit ()
5130 if (OptAttributes != null) {
5131 EmitContext ec = new EmitContext (
5132 Parent, Location, null, FieldBuilder.FieldType,
5134 OptAttributes.Emit (ec, this);
5142 // `set' and `get' accessors are represented with an Accessor.
5144 public class Accessor {
5146 // Null if the accessor is empty, or a Block if not
5149 public Attributes Attributes;
5151 public Accessor (Block b, Attributes attrs)
5159 // Ooouh Martin, templates are missing here.
5160 // When it will be possible move here a lot of child code and template method type.
5161 public abstract class AbstractPropertyEventMethod: Attributable, IMethodData
5163 protected MethodData method_data;
5164 protected Block block;
5166 ReturnParameter return_attributes;
5168 public AbstractPropertyEventMethod ():
5173 public AbstractPropertyEventMethod (Accessor accessor):
5174 base (accessor.Attributes)
5176 this.block = accessor.Block;
5179 #region IMethodData Members
5181 public Block Block {
5191 public CallingConventions CallingConventions {
5193 return CallingConventions.Standard;
5197 public bool IsExcluded (EmitContext ec)
5202 public abstract ObsoleteAttribute GetObsoleteAttribute ();
5203 public abstract string GetSignatureForError (TypeContainer tc);
5204 public abstract Location Location { get; }
5205 public abstract string MethodName { get; }
5206 public abstract Type[] ParameterTypes { get; }
5207 public abstract Type ReturnType { get; }
5208 public abstract EmitContext CreateEmitContext(TypeContainer tc, ILGenerator ig);
5212 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5214 if (a.Type == TypeManager.cls_compliant_attribute_type || a.Type == TypeManager.obsolete_attribute_type ||
5215 a.Type == TypeManager.conditional_attribute_type) {
5216 Report.Error_T (Message.CS1667_is_not_valid_on_property_or_event_accessors, a.Location, TypeManager.CSharpName (a.Type), a.GetValidTargets ());
5220 if (a.Target == AttributeTargets.Method) {
5221 method_data.MethodBuilder.SetCustomAttribute (cb);
5225 if (a.Target == AttributeTargets.ReturnValue) {
5226 if (return_attributes == null)
5227 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
5229 return_attributes.ApplyAttributeBuilder (a, cb);
5233 ApplyToExtraTarget (a, cb);
5236 virtual protected void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb)
5238 System.Diagnostics.Debug.Fail ("You forgot to define special attribute target handling");
5241 public virtual void Emit (TypeContainer container)
5243 method_data.Emit (container, this);
5249 // Properties and Indexers both generate PropertyBuilders, we use this to share
5250 // their common bits.
5252 abstract public class PropertyBase : MethodCore {
5254 public class GetMethod: PropertyMethod
5256 static string[] attribute_targets = new string [] { "method", "return" };
5258 public GetMethod (MethodCore method, Accessor accessor):
5259 base (method, accessor)
5263 public override MethodBuilder Define(TypeContainer container)
5265 method_data = new MethodData (method, method.ParameterInfo, method.ModFlags, method.flags, this);
5267 if (!method_data.Define (container))
5270 return method_data.MethodBuilder;
5273 public override string GetSignatureForError (TypeContainer tc)
5275 return String.Concat (base.GetSignatureForError (tc), ".get");
5278 public override string MethodName
5281 return "get_" + method.ShortName;
5285 public override Type ReturnType {
5287 return method.MemberType;
5291 public override string[] ValidAttributeTargets {
5293 return attribute_targets;
5298 public class SetMethod: PropertyMethod {
5300 static string[] attribute_targets = new string [] { "method", "param", "return" };
5301 ImplicitParameter param_attr;
5303 public SetMethod (MethodCore method, Accessor accessor):
5304 base (method, accessor)
5308 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
5310 if (a.Target == AttributeTargets.Parameter) {
5311 if (param_attr == null)
5312 param_attr = new ImplicitParameter (method_data.MethodBuilder);
5314 param_attr.ApplyAttributeBuilder (a, cb);
5318 base.ApplyAttributeBuilder (a, cb);
5321 protected virtual InternalParameters GetParameterInfo (TypeContainer container)
5323 Parameter [] parms = new Parameter [1];
5324 parms [0] = new Parameter (method.Type, "value", Parameter.Modifier.NONE, null);
5325 return new InternalParameters (
5326 container, new Parameters (parms, null, method.Location));
5329 public override MethodBuilder Define(TypeContainer container)
5331 method_data = new MethodData (method, GetParameterInfo (container), method.ModFlags, method.flags, this);
5333 if (!method_data.Define (container))
5336 return method_data.MethodBuilder;
5339 public override string GetSignatureForError (TypeContainer tc)
5341 return String.Concat (base.GetSignatureForError (tc), ".set");
5344 public override string MethodName {
5346 return "set_" + method.ShortName;
5350 public override Type[] ParameterTypes {
5352 return new Type[] { method.MemberType };
5356 public override Type ReturnType {
5358 return TypeManager.void_type;
5362 public override string[] ValidAttributeTargets {
5364 return attribute_targets;
5369 static string[] attribute_targets = new string [] { "property" };
5371 public abstract class PropertyMethod: AbstractPropertyEventMethod
5373 protected readonly MethodCore method;
5375 public PropertyMethod (MethodCore method, Accessor accessor):
5378 this.method = method;
5381 public override AttributeTargets AttributeTargets {
5383 return AttributeTargets.Method;
5387 public override bool IsClsCompliaceRequired(DeclSpace ds)
5389 return method.IsClsCompliaceRequired (ds);
5392 public InternalParameters ParameterInfo
5395 return method_data.ParameterInfo;
5399 public abstract MethodBuilder Define (TypeContainer container);
5401 public override Type[] ParameterTypes {
5403 return TypeManager.NoTypes;
5407 public override Location Location {
5409 return method.Location;
5413 public override EmitContext CreateEmitContext (TypeContainer tc,
5416 return new EmitContext (
5417 tc, method.Parent, method.Location, ig, ReturnType,
5418 method.ModFlags, false);
5421 public override ObsoleteAttribute GetObsoleteAttribute ()
5423 return method.GetObsoleteAttribute (method.Parent);
5426 public override string GetSignatureForError (TypeContainer tc)
5428 return String.Concat (tc.Name, '.', method.Name);
5433 public PropertyMethod Get, Set;
5434 public PropertyBuilder PropertyBuilder;
5435 public MethodBuilder GetBuilder, SetBuilder;
5437 protected EmitContext ec;
5439 public PropertyBase (TypeContainer ds, Expression type, int mod_flags,
5440 int allowed_mod, bool is_iface, string name,
5441 Parameters parameters, Attributes attrs,
5443 : base (ds, type, mod_flags, allowed_mod, is_iface, name,
5444 attrs, parameters, loc)
5448 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5450 PropertyBuilder.SetCustomAttribute (cb);
5453 public override AttributeTargets AttributeTargets {
5455 return AttributeTargets.Property;
5459 protected override bool DoDefine ()
5461 if (!base.DoDefine ())
5464 if (MemberType == TypeManager.arg_iterator_type || MemberType == TypeManager.typed_reference_type) {
5465 Report.Error_T (Message.CS0610_Field_or_property_cannot_be_of_type, Location, TypeManager.CSharpName (MemberType));
5469 ec = new EmitContext (Parent, Location, null, MemberType, ModFlags);
5474 public override string GetSignatureForError()
5476 return TypeManager.CSharpSignature (PropertyBuilder, false);
5479 protected virtual string RealMethodName {
5485 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
5487 if (!IsIdentifierAndParamClsCompliant (ds, RealMethodName, null, null))
5490 if (Get != null && !IsIdentifierAndParamClsCompliant (ds, "get_" + RealMethodName, null, null))
5493 if (Set != null && !IsIdentifierAndParamClsCompliant (ds, "set_" + RealMethodName, null, null))
5501 // Checks our base implementation if any
5503 protected override bool CheckBase ()
5507 // Check whether arguments were correct.
5508 if (!DoDefineParameters ())
5515 // Check in our class for dups
5517 ArrayList ar = Parent.Properties;
5519 int arLen = ar.Count;
5521 for (int i = 0; i < arLen; i++) {
5522 Property m = (Property) ar [i];
5523 if (IsDuplicateImplementation (Parent, m))
5532 MethodSignature ms, base_ms;
5533 if (this is Indexer) {
5534 string name, base_name;
5536 report_name = "this";
5537 name = TypeManager.IndexerPropertyName (Parent.TypeBuilder);
5538 ms = new MethodSignature (name, null, ParameterTypes);
5539 base_name = TypeManager.IndexerPropertyName (Parent.TypeBuilder.BaseType);
5540 base_ms = new MethodSignature (base_name, null, ParameterTypes);
5543 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
5547 // Verify if the parent has a type with the same name, and then
5548 // check whether we have to create a new slot for it or not.
5550 Type ptype = Parent.TypeBuilder.BaseType;
5552 // ptype is only null for System.Object while compiling corlib.
5553 if (ptype == null) {
5554 if ((ModFlags & Modifiers.NEW) != 0)
5555 WarningNotHiding (Parent);
5560 MemberInfo parent_member = null;
5563 // Explicit implementations do not have `parent' methods, however,
5564 // the member cache stores them there. Without this check, we get
5565 // an incorrect warning in corlib.
5567 if (! IsExplicitImpl) {
5568 parent_member = ((IMemberContainer)Parent).Parent.MemberCache.FindMemberToOverride (
5569 Parent.TypeBuilder, Name, ParameterTypes, true);
5572 if (parent_member is PropertyInfo) {
5573 PropertyInfo parent_property = (PropertyInfo)parent_member;
5575 string name = parent_property.DeclaringType.Name + "." +
5576 parent_property.Name;
5578 MethodInfo get, set, parent_method;
5579 get = parent_property.GetGetMethod (true);
5580 set = parent_property.GetSetMethod (true);
5583 parent_method = get;
5584 else if (set != null)
5585 parent_method = set;
5587 throw new Exception ("Internal error!");
5589 if (!CheckMethodAgainstBase (Parent, flags, parent_method, name))
5592 if ((ModFlags & Modifiers.NEW) == 0) {
5593 Type parent_type = TypeManager.TypeToCoreType (
5594 parent_property.PropertyType);
5596 if (parent_type != MemberType) {
5598 508, Location, Parent.MakeName (Name) + ": cannot " +
5599 "change return type when overriding " +
5600 "inherited member " + name);
5604 } else if (parent_member == null){
5605 if ((ModFlags & Modifiers.NEW) != 0)
5606 WarningNotHiding (Parent);
5608 if ((ModFlags & Modifiers.OVERRIDE) != 0){
5609 if (this is Indexer)
5610 Report.Error (115, Location,
5611 Parent.MakeName (Name) +
5612 " no suitable indexers found to override");
5614 Report.Error (115, Location,
5615 Parent.MakeName (Name) +
5616 " no suitable properties found to override");
5623 public override void Emit ()
5626 // The PropertyBuilder can be null for explicit implementations, in that
5627 // case, we do not actually emit the ".property", so there is nowhere to
5628 // put the attribute
5630 if (PropertyBuilder != null && OptAttributes != null)
5631 OptAttributes.Emit (ec, this);
5642 public override string[] ValidAttributeTargets {
5644 return attribute_targets;
5649 public class Property : PropertyBase, IIteratorContainer {
5650 const int AllowedModifiers =
5653 Modifiers.PROTECTED |
5654 Modifiers.INTERNAL |
5658 Modifiers.OVERRIDE |
5659 Modifiers.ABSTRACT |
5662 Modifiers.METHOD_YIELDS |
5665 const int AllowedInterfaceModifiers =
5668 public Property (TypeContainer ds, Expression type, int mod, bool is_iface,
5669 string name, Attributes attrs, Accessor get_block,
5670 Accessor set_block, Location loc)
5671 : base (ds, type, mod,
5672 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5673 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
5676 if (get_block != null)
5677 Get = new GetMethod (this, get_block);
5679 if (set_block != null)
5680 Set = new SetMethod (this, set_block);
5683 public override bool Define ()
5691 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
5695 GetBuilder = Get.Define (Parent);
5696 if (GetBuilder == null)
5700 // Setup iterator if we are one
5702 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
5703 Iterator iterator = new Iterator (
5704 Parent, "get", MemberType,
5705 TypeManager.NoTypes, Get.ParameterInfo,
5706 ModFlags, Get.Block, Location);
5708 if (!iterator.DefineIterator ())
5710 Get.Block = iterator.Block;
5715 SetBuilder = Set.Define (Parent);
5716 if (SetBuilder == null)
5719 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
5722 // FIXME - PropertyAttributes.HasDefault ?
5724 PropertyAttributes prop_attr = PropertyAttributes.None;
5726 prop_attr |= PropertyAttributes.RTSpecialName |
5727 PropertyAttributes.SpecialName;
5729 if (!IsExplicitImpl){
5730 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
5731 Name, prop_attr, MemberType, null);
5734 PropertyBuilder.SetGetMethod (GetBuilder);
5737 PropertyBuilder.SetSetMethod (SetBuilder);
5740 // HACK for the reasons exposed above
5742 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
5745 "Class `" + Parent.Name +
5746 "' already contains a definition for the property `" +
5754 public void SetYields ()
5756 ModFlags |= Modifiers.METHOD_YIELDS;
5761 /// Gigantic workaround for lameness in SRE follows :
5762 /// This class derives from EventInfo and attempts to basically
5763 /// wrap around the EventBuilder so that FindMembers can quickly
5764 /// return this in it search for members
5766 public class MyEventBuilder : EventInfo {
5769 // We use this to "point" to our Builder which is
5770 // not really a MemberInfo
5772 EventBuilder MyBuilder;
5775 // We "catch" and wrap these methods
5777 MethodInfo raise, remove, add;
5779 EventAttributes attributes;
5780 Type declaring_type, reflected_type, event_type;
5785 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
5787 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
5789 // And now store the values in our own fields.
5791 declaring_type = type_builder;
5793 reflected_type = type_builder;
5795 attributes = event_attr;
5798 this.event_type = event_type;
5802 // Methods that you have to override. Note that you only need
5803 // to "implement" the variants that take the argument (those are
5804 // the "abstract" methods, the others (GetAddMethod()) are
5807 public override MethodInfo GetAddMethod (bool nonPublic)
5812 public override MethodInfo GetRemoveMethod (bool nonPublic)
5817 public override MethodInfo GetRaiseMethod (bool nonPublic)
5823 // These methods make "MyEventInfo" look like a Builder
5825 public void SetRaiseMethod (MethodBuilder raiseMethod)
5827 raise = raiseMethod;
5828 MyBuilder.SetRaiseMethod (raiseMethod);
5831 public void SetRemoveOnMethod (MethodBuilder removeMethod)
5833 remove = removeMethod;
5834 MyBuilder.SetRemoveOnMethod (removeMethod);
5837 public void SetAddOnMethod (MethodBuilder addMethod)
5840 MyBuilder.SetAddOnMethod (addMethod);
5843 public void SetCustomAttribute (CustomAttributeBuilder cb)
5845 MyBuilder.SetCustomAttribute (cb);
5848 public override object [] GetCustomAttributes (bool inherit)
5850 // FIXME : There's nothing which can be seemingly done here because
5851 // we have no way of getting at the custom attribute objects of the
5856 public override object [] GetCustomAttributes (Type t, bool inherit)
5858 // FIXME : Same here !
5862 public override bool IsDefined (Type t, bool b)
5867 public override EventAttributes Attributes {
5873 public override string Name {
5879 public override Type DeclaringType {
5881 return declaring_type;
5885 public override Type ReflectedType {
5887 return reflected_type;
5891 public Type EventType {
5897 public void SetUsed ()
5899 if (my_event != null)
5900 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
5905 /// For case when event is declared like property (with add and remove accessors).
5907 public class EventProperty: Event {
5909 static string[] attribute_targets = new string [] { "event", "property" };
5911 public EventProperty (TypeContainer parent, Expression type, int mod_flags,
5912 bool is_iface, string name, Object init,
5913 Attributes attrs, Accessor add, Accessor remove,
5915 : base (parent, type, mod_flags, is_iface, name, init, attrs, loc)
5917 Add = new AddDelegateMethod (this, add);
5918 Remove = new RemoveDelegateMethod (this, remove);
5921 public override string[] ValidAttributeTargets {
5923 return attribute_targets;
5929 /// Event is declared like field.
5931 public class EventField: Event {
5933 static string[] attribute_targets = new string [] { "event", "field", "method" };
5935 public EventField (TypeContainer parent, Expression type, int mod_flags,
5936 bool is_iface, string name, Object init,
5937 Attributes attrs, Location loc)
5938 : base (parent, type, mod_flags, is_iface, name, init, attrs, loc)
5940 Add = new AddDelegateMethod (this);
5941 Remove = new RemoveDelegateMethod (this);
5944 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5946 if (a.Target == AttributeTargets.Field) {
5947 FieldBuilder.SetCustomAttribute (cb);
5951 if (a.Target == AttributeTargets.Method) {
5952 AddBuilder.SetCustomAttribute (cb);
5953 RemoveBuilder.SetCustomAttribute (cb);
5957 base.ApplyAttributeBuilder (a, cb);
5960 public override string[] ValidAttributeTargets {
5962 return attribute_targets;
5967 public abstract class Event : FieldBase {
5969 protected sealed class AddDelegateMethod: DelegateMethod
5971 public AddDelegateMethod (Event method):
5976 public AddDelegateMethod (Event method, Accessor accessor):
5977 base (method, accessor)
5981 public override string MethodName {
5983 return "add_" + method.ShortName;
5987 protected override MethodInfo DelegateMethodInfo {
5989 return TypeManager.delegate_combine_delegate_delegate;
5995 protected sealed class RemoveDelegateMethod: DelegateMethod
5997 public RemoveDelegateMethod (Event method):
6002 public RemoveDelegateMethod (Event method, Accessor accessor):
6003 base (method, accessor)
6007 public override string MethodName {
6009 return "remove_" + method.ShortName;
6013 protected override MethodInfo DelegateMethodInfo {
6015 return TypeManager.delegate_remove_delegate_delegate;
6021 public abstract class DelegateMethod: AbstractPropertyEventMethod
6023 protected readonly Event method;
6024 ImplicitParameter param_attr;
6026 static string[] attribute_targets = new string [] { "method", "param", "return" };
6028 public DelegateMethod (Event method)
6030 this.method = method;
6033 public DelegateMethod (Event method, Accessor accessor):
6036 this.method = method;
6039 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
6041 if (a.Target == AttributeTargets.Parameter) {
6042 if (param_attr == null)
6043 param_attr = new ImplicitParameter (method_data.MethodBuilder);
6045 param_attr.ApplyAttributeBuilder (a, cb);
6049 base.ApplyAttributeBuilder (a, cb);
6052 public override AttributeTargets AttributeTargets {
6054 return AttributeTargets.Method;
6058 public override bool IsClsCompliaceRequired(DeclSpace ds)
6060 return method.IsClsCompliaceRequired (ds);
6063 public MethodBuilder Define (TypeContainer container, InternalParameters ip)
6065 method_data = new MethodData (method, ip, method.ModFlags,
6066 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
6068 if (!method_data.Define (container))
6071 MethodBuilder mb = method_data.MethodBuilder;
6072 mb.DefineParameter (1, ParameterAttributes.None, "value");
6077 public override void Emit (TypeContainer tc)
6079 if (block != null) {
6084 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
6085 EmitContext ec = CreateEmitContext (tc, ig);
6086 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
6088 method_data.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Synchronized);
6089 if ((method.ModFlags & Modifiers.STATIC) != 0) {
6090 ig.Emit (OpCodes.Ldsfld, field_info);
6091 ig.Emit (OpCodes.Ldarg_0);
6092 ig.Emit (OpCodes.Call, DelegateMethodInfo);
6093 ig.Emit (OpCodes.Castclass, method.MemberType);
6094 ig.Emit (OpCodes.Stsfld, field_info);
6096 ig.Emit (OpCodes.Ldarg_0);
6097 ig.Emit (OpCodes.Ldarg_0);
6098 ig.Emit (OpCodes.Ldfld, field_info);
6099 ig.Emit (OpCodes.Ldarg_1);
6100 ig.Emit (OpCodes.Call, DelegateMethodInfo);
6101 ig.Emit (OpCodes.Castclass, method.MemberType);
6102 ig.Emit (OpCodes.Stfld, field_info);
6104 ig.Emit (OpCodes.Ret);
6107 protected abstract MethodInfo DelegateMethodInfo { get; }
6109 public override Type[] ParameterTypes {
6111 return new Type[] { method.MemberType };
6115 public override Type ReturnType {
6117 return TypeManager.void_type;
6121 public override Location Location {
6123 return method.Location;
6127 public override EmitContext CreateEmitContext (TypeContainer tc,
6130 return new EmitContext (
6131 tc, method.Parent, Location, ig, ReturnType,
6132 method.ModFlags, false);
6135 public override string GetSignatureForError (TypeContainer tc)
6137 return String.Concat (tc.Name, '.', method.Name);
6140 public override ObsoleteAttribute GetObsoleteAttribute ()
6142 return method.GetObsoleteAttribute (method.Parent);
6145 public override string[] ValidAttributeTargets {
6147 return attribute_targets;
6153 const int AllowedModifiers =
6156 Modifiers.PROTECTED |
6157 Modifiers.INTERNAL |
6162 Modifiers.OVERRIDE |
6166 const int AllowedInterfaceModifiers =
6169 protected DelegateMethod Add, Remove;
6170 public MyEventBuilder EventBuilder;
6171 public MethodBuilder AddBuilder, RemoveBuilder;
6173 public Event (TypeContainer parent, Expression type, int mod_flags,
6174 bool is_iface, string name, Object init, Attributes attrs,
6176 : base (parent, type, mod_flags,
6177 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6178 name, init, attrs, loc)
6180 IsInterface = is_iface;
6183 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6185 EventBuilder.SetCustomAttribute (cb);
6188 public override AttributeTargets AttributeTargets {
6190 return AttributeTargets.Event;
6194 public override bool Define ()
6196 EventAttributes e_attr;
6197 e_attr = EventAttributes.None;
6202 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
6203 Report.Error (74, Location, "'" + Parent.Name + "." + Name +
6204 "': abstract event can not have an initializer");
6208 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
6209 Report.Error (66, Location, "'" + Parent.Name + "." + Name +
6210 "' : event must be of a delegate type");
6214 Parameter [] parms = new Parameter [1];
6215 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
6216 InternalParameters ip = new InternalParameters (
6217 Parent, new Parameters (parms, null, Location));
6223 // Now define the accessors
6226 AddBuilder = Add.Define (Parent, ip);
6227 if (AddBuilder == null)
6230 RemoveBuilder = Remove.Define (Parent, ip);
6231 if (RemoveBuilder == null)
6234 if (!IsExplicitImpl){
6235 EventBuilder = new MyEventBuilder (this,
6236 Parent.TypeBuilder, Name, e_attr, MemberType);
6238 if (Add.Block == null && Remove.Block == null &&
6240 FieldBuilder = Parent.TypeBuilder.DefineField (
6242 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
6243 TypeManager.RegisterPrivateFieldOfEvent (
6244 (EventInfo) EventBuilder, FieldBuilder);
6245 TypeManager.RegisterFieldBase (FieldBuilder, this);
6248 EventBuilder.SetAddOnMethod (AddBuilder);
6249 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
6251 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
6252 Report.Error (111, Location,
6253 "Class `" + Parent.Name +
6254 "' already contains a definition for the event `" +
6263 public override void Emit ()
6265 if (OptAttributes != null) {
6266 EmitContext ec = new EmitContext (
6267 Parent, Location, null, MemberType, ModFlags);
6268 OptAttributes.Emit (ec, this);
6273 Remove.Emit (Parent);
6279 public override string GetSignatureForError ()
6281 return TypeManager.GetFullNameSignature (EventBuilder);
6286 // FIXME: This does not handle:
6288 // int INTERFACENAME [ args ]
6293 // int this [ args ]
6295 public class Indexer : PropertyBase {
6297 class GetIndexerMethod: GetMethod
6299 public GetIndexerMethod (MethodCore method, Accessor accessor):
6300 base (method, accessor)
6304 public override Type[] ParameterTypes {
6306 return method.ParameterTypes;
6311 class SetIndexerMethod: SetMethod
6313 readonly Parameters parameters;
6315 public SetIndexerMethod (MethodCore method, Parameters parameters, Accessor accessor):
6316 base (method, accessor)
6318 this.parameters = parameters;
6321 public override Type[] ParameterTypes {
6323 int top = method.ParameterTypes.Length;
6324 Type [] set_pars = new Type [top + 1];
6325 method.ParameterTypes.CopyTo (set_pars, 0);
6326 set_pars [top] = method.MemberType;
6331 protected override InternalParameters GetParameterInfo (TypeContainer container)
6333 Parameter [] fixed_parms = parameters.FixedParameters;
6335 if (fixed_parms == null){
6336 throw new Exception ("We currently do not support only array arguments in an indexer at: " + method.Location);
6337 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6338 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6340 // Here is the problem: the `value' parameter has
6341 // to come *after* the array parameter in the declaration
6343 // X (object [] x, Type value)
6346 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6347 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6351 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
6353 fixed_parms.CopyTo (tmp, 0);
6354 tmp [fixed_parms.Length] = new Parameter (
6355 method.Type, "value", Parameter.Modifier.NONE, null);
6357 Parameters set_formal_params = new Parameters (tmp, null, method.Location);
6359 return new InternalParameters (container, set_formal_params);
6365 const int AllowedModifiers =
6368 Modifiers.PROTECTED |
6369 Modifiers.INTERNAL |
6373 Modifiers.OVERRIDE |
6378 const int AllowedInterfaceModifiers =
6381 public string IndexerName = "Item";
6382 public string InterfaceIndexerName;
6385 // Are we implementing an interface ?
6387 public Indexer (TypeContainer ds, Expression type, string int_type, int mod,
6388 bool is_iface, Parameters parameters, Attributes attrs,
6389 Accessor get_block, Accessor set_block, Location loc)
6390 : base (ds, type, mod,
6391 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6392 is_iface, "", parameters, attrs, loc)
6394 ExplicitInterfaceName = int_type;
6396 if (get_block != null)
6397 Get = new GetIndexerMethod (this, get_block);
6399 if (set_block != null)
6400 Set = new SetIndexerMethod (this, parameters, set_block);
6403 public override bool Define ()
6405 PropertyAttributes prop_attr =
6406 PropertyAttributes.RTSpecialName |
6407 PropertyAttributes.SpecialName;
6412 if (OptAttributes != null) {
6413 Attribute indexer_attr = OptAttributes.GetIndexerNameAttribute (ec);
6414 if (indexer_attr != null) {
6415 IndexerName = indexer_attr.GetIndexerAttributeValue (ec);
6417 if (IsExplicitImpl) {
6418 Report.Error_T (Message.CS0415_The_IndexerName_attribute_is_valid_only_on_an_indexer_that_is_not_an_explicit_interface_member_declaration, indexer_attr.Location);
6422 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
6423 Report.Error_T (Message.CS0609_Cannot_set_the_IndexerName_attribute_on_an_indexer_marked_override, indexer_attr.Location);
6427 if (!Tokenizer.IsValidIdentifier (IndexerName)) {
6428 Report.Error_T (Message.CS0633_The_argument_to_the_IndexerName_attribute_must_be_a_valid_identifier, indexer_attr.Location);
6434 ShortName = IndexerName;
6435 if (IsExplicitImpl) {
6436 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
6437 Name = InterfaceType.FullName + "." + IndexerName;
6439 InterfaceIndexerName = IndexerName;
6443 if (!CheckNameCollision (Parent))
6449 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6451 GetBuilder = Get.Define (Parent);
6452 if (GetBuilder == null)
6457 SetBuilder = Set.Define (Parent);
6458 if (SetBuilder == null)
6463 // Now name the parameters
6465 Parameter [] p = Parameters.FixedParameters;
6469 for (i = 0; i < p.Length; ++i) {
6471 GetBuilder.DefineParameter (
6472 i + 1, p [i].Attributes, p [i].Name);
6475 SetBuilder.DefineParameter (
6476 i + 1, p [i].Attributes, p [i].Name);
6480 SetBuilder.DefineParameter (
6481 i + 1, ParameterAttributes.None, "value");
6483 if (i != ParameterTypes.Length) {
6484 Parameter array_param = Parameters.ArrayParameter;
6486 SetBuilder.DefineParameter (
6487 i + 1, array_param.Attributes, array_param.Name);
6492 // Define the PropertyBuilder if one of the following conditions are met:
6493 // a) we're not implementing an interface indexer.
6494 // b) the indexer has a different IndexerName and this is no
6495 // explicit interface implementation.
6497 if (!IsExplicitImpl) {
6498 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6499 IndexerName, prop_attr, MemberType, ParameterTypes);
6502 PropertyBuilder.SetGetMethod (GetBuilder);
6505 PropertyBuilder.SetSetMethod (SetBuilder);
6507 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
6514 bool CheckNameCollision (TypeContainer container) {
6515 switch (VerifyName (container)){
6516 case DeclSpace.AdditionResult.NameExists:
6517 Report.Error (102, Location, "The container '{0}' already contains a definition for '{1}'", container.GetSignatureForError (), Name);
6520 case DeclSpace.AdditionResult.Success:
6523 throw new NotImplementedException ();
6526 DeclSpace.AdditionResult VerifyName (TypeContainer container) {
6527 if (!AddIndexer (container, container.Name + "." + Name))
6528 return DeclSpace.AdditionResult.NameExists;
6531 if (!AddIndexer (container, container.Name + ".get_" + Name))
6532 return DeclSpace.AdditionResult.NameExists;
6536 if (!AddIndexer (container, container.Name + ".set_" + Name))
6537 return DeclSpace.AdditionResult.NameExists;
6539 return DeclSpace.AdditionResult.Success;
6542 bool AddIndexer (TypeContainer container, string fullname)
6544 object value = container.GetDefinition (fullname);
6546 if (value != null) {
6547 return value.GetType () != GetType () ? false : true;
6550 container.DefineName (fullname, this);
6554 public override string GetSignatureForError ()
6556 return TypeManager.CSharpSignature (PropertyBuilder, true);
6559 protected override string RealMethodName {
6566 public class Operator : MemberBase, IIteratorContainer {
6568 const int AllowedModifiers =
6574 const int RequiredModifiers =
6578 public enum OpType : byte {
6588 // Unary and Binary operators
6611 // Implicit and Explicit
6616 public readonly OpType OperatorType;
6617 public readonly Expression ReturnType;
6618 public readonly Expression FirstArgType, SecondArgType;
6619 public readonly string FirstArgName, SecondArgName;
6621 public MethodBuilder OperatorMethodBuilder;
6623 public string MethodName;
6624 public Method OperatorMethod;
6626 static string[] attribute_targets = new string [] { "method", "return" };
6628 public Operator (TypeContainer parent, OpType type, Expression ret_type,
6629 int mod_flags, Expression arg1type, string arg1name,
6630 Expression arg2type, string arg2name,
6631 Block block, Attributes attrs, Location loc)
6632 : base (parent, ret_type, mod_flags, AllowedModifiers,
6633 Modifiers.PUBLIC, "", attrs, loc)
6635 OperatorType = type;
6636 Name = "op_" + OperatorType;
6637 ReturnType = ret_type;
6638 FirstArgType = arg1type;
6639 FirstArgName = arg1name;
6640 SecondArgType = arg2type;
6641 SecondArgName = arg2name;
6645 string Prototype (TypeContainer container)
6647 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
6648 SecondArgType + ")";
6651 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6653 OperatorMethod.ApplyAttributeBuilder (a, cb);
6656 public override AttributeTargets AttributeTargets {
6658 return AttributeTargets.Method;
6662 public override bool Define ()
6665 MethodName = "op_" + OperatorType;
6667 if (SecondArgType != null)
6670 Parameter [] param_list = new Parameter [length];
6672 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
6675 "User defined operators `" +
6676 Prototype (Parent) +
6677 "' must be declared static and public");
6681 param_list[0] = new Parameter (FirstArgType, FirstArgName,
6682 Parameter.Modifier.NONE, null);
6683 if (SecondArgType != null)
6684 param_list[1] = new Parameter (SecondArgType, SecondArgName,
6685 Parameter.Modifier.NONE, null);
6687 OperatorMethod = new Method (
6688 Parent, ReturnType, ModFlags, false, MethodName,
6689 new Parameters (param_list, null, Location),
6690 OptAttributes, Location);
6692 OperatorMethod.Block = Block;
6693 OperatorMethod.IsOperator = true;
6694 OperatorMethod.Define ();
6696 if (OperatorMethod.MethodBuilder == null)
6699 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
6701 Type [] param_types = OperatorMethod.ParameterTypes;
6702 Type declaring_type = OperatorMethodBuilder.DeclaringType;
6703 Type return_type = OperatorMethod.GetReturnType ();
6704 Type first_arg_type = param_types [0];
6706 // Rules for conversion operators
6708 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
6709 if (first_arg_type == return_type && first_arg_type == declaring_type){
6712 "User-defined conversion cannot take an object of the " +
6713 "enclosing type and convert to an object of the enclosing" +
6718 if (first_arg_type != declaring_type && return_type != declaring_type){
6721 "User-defined conversion must convert to or from the " +
6726 if (first_arg_type == TypeManager.object_type ||
6727 return_type == TypeManager.object_type){
6730 "User-defined conversion cannot convert to or from " +
6735 if (first_arg_type.IsInterface || return_type.IsInterface){
6738 "User-defined conversion cannot convert to or from an " +
6743 if (first_arg_type.IsSubclassOf (return_type)
6744 || return_type.IsSubclassOf (first_arg_type)){
6745 if (declaring_type.IsSubclassOf (return_type)) {
6746 Report.Error_T (Message.CS0553_user_defined_conversion_to_from_base_class, Location, GetSignatureForError ());
6749 Report.Error_T (Message.CS0554_user_defined_conversion_to_from_derived_class, Location, GetSignatureForError ());
6752 } else if (SecondArgType == null) {
6753 // Checks for Unary operators
6755 if (first_arg_type != declaring_type){
6758 "The parameter of a unary operator must be the " +
6763 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
6764 if (return_type != declaring_type){
6767 "The parameter and return type for ++ and -- " +
6768 "must be the containing type");
6774 if (OperatorType == OpType.True || OperatorType == OpType.False) {
6775 if (return_type != TypeManager.bool_type){
6778 "The return type of operator True or False " +
6785 // Checks for Binary operators
6787 if (first_arg_type != declaring_type &&
6788 param_types [1] != declaring_type){
6791 "One of the parameters of a binary operator must " +
6792 "be the containing type");
6800 public override void Emit ()
6803 // abstract or extern methods have no bodies
6805 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
6808 OperatorMethod.Emit ();
6812 public static string GetName (OpType ot)
6815 case OpType.LogicalNot:
6817 case OpType.OnesComplement:
6819 case OpType.Increment:
6821 case OpType.Decrement:
6827 case OpType.Addition:
6829 case OpType.Subtraction:
6831 case OpType.UnaryPlus:
6833 case OpType.UnaryNegation:
6835 case OpType.Multiply:
6837 case OpType.Division:
6839 case OpType.Modulus:
6841 case OpType.BitwiseAnd:
6843 case OpType.BitwiseOr:
6845 case OpType.ExclusiveOr:
6847 case OpType.LeftShift:
6849 case OpType.RightShift:
6851 case OpType.Equality:
6853 case OpType.Inequality:
6855 case OpType.GreaterThan:
6857 case OpType.LessThan:
6859 case OpType.GreaterThanOrEqual:
6861 case OpType.LessThanOrEqual:
6863 case OpType.Implicit:
6865 case OpType.Explicit:
6871 public override string GetSignatureForError(TypeContainer tc)
6876 public override string GetSignatureForError()
6881 public override string ToString ()
6883 Type return_type = OperatorMethod.GetReturnType();
6884 Type [] param_types = OperatorMethod.ParameterTypes;
6886 if (SecondArgType == null)
6887 return String.Format (
6888 "{0} operator {1}({2})",
6889 TypeManager.CSharpName (return_type),
6890 GetName (OperatorType),
6893 return String.Format (
6894 "{0} operator {1}({2}, {3})",
6895 TypeManager.CSharpName (return_type),
6896 GetName (OperatorType),
6897 param_types [0], param_types [1]);
6900 public override string[] ValidAttributeTargets {
6902 return attribute_targets;
6906 public void SetYields ()
6908 ModFlags |= Modifiers.METHOD_YIELDS;
6913 // This is used to compare method signatures
6915 struct MethodSignature {
6917 public Type RetType;
6918 public Type [] Parameters;
6921 /// This delegate is used to extract methods which have the
6922 /// same signature as the argument
6924 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
6926 public MethodSignature (string name, Type ret_type, Type [] parameters)
6931 if (parameters == null)
6932 Parameters = TypeManager.NoTypes;
6934 Parameters = parameters;
6937 public override string ToString ()
6940 if (Parameters.Length != 0){
6941 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
6942 for (int i = 0; i < Parameters.Length; i++){
6943 sb.Append (Parameters [i]);
6944 if (i+1 < Parameters.Length)
6947 pars = sb.ToString ();
6950 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
6953 public override int GetHashCode ()
6955 return Name.GetHashCode ();
6958 public override bool Equals (Object o)
6960 MethodSignature other = (MethodSignature) o;
6962 if (other.Name != Name)
6965 if (other.RetType != RetType)
6968 if (Parameters == null){
6969 if (other.Parameters == null)
6974 if (other.Parameters == null)
6977 int c = Parameters.Length;
6978 if (other.Parameters.Length != c)
6981 for (int i = 0; i < c; i++)
6982 if (other.Parameters [i] != Parameters [i])
6988 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
6990 MethodSignature sig = (MethodSignature) filter_criteria;
6992 if (m.Name != sig.Name)
6996 MethodInfo mi = m as MethodInfo;
6997 PropertyInfo pi = m as PropertyInfo;
7000 ReturnType = mi.ReturnType;
7001 else if (pi != null)
7002 ReturnType = pi.PropertyType;
7007 // we use sig.RetType == null to mean `do not check the
7008 // method return value.
7010 if (sig.RetType != null)
7011 if (ReturnType != sig.RetType)
7016 args = TypeManager.GetArgumentTypes (mi);
7018 args = TypeManager.GetArgumentTypes (pi);
7019 Type [] sigp = sig.Parameters;
7021 if (args.Length != sigp.Length)
7024 for (int i = args.Length; i > 0; ){
7026 if (args [i] != sigp [i])